From 586a2fb850b9c2ad4c308711ea420b5ab4a526ce Mon Sep 17 00:00:00 2001 From: Edgar Simo Date: Thu, 17 Jul 2008 16:07:20 +0000 Subject: [PATCH] Better handling of opening haptics from joysticks. Fixed segfault when opening from joystick. --- src/haptic/SDL_haptic.c | 2 +- src/haptic/SDL_syshaptic.h | 1 - src/haptic/linux/SDL_syshaptic.c | 76 +++++++++++++++++++++++++------- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/haptic/SDL_haptic.c b/src/haptic/SDL_haptic.c index dcacdd6bc..5e1146099 100644 --- a/src/haptic/SDL_haptic.c +++ b/src/haptic/SDL_haptic.c @@ -274,7 +274,7 @@ SDL_HapticOpenFromJoystick(SDL_Joystick * joystick) } /* Initialize the haptic device */ - SDL_memset(haptic, 0, (sizeof *haptic)); + SDL_memset(haptic, 0, sizeof(SDL_Haptic)); if (SDL_SYS_HapticOpenFromJoystick(haptic,joystick) < 0) { SDL_free(haptic); return NULL; diff --git a/src/haptic/SDL_syshaptic.h b/src/haptic/SDL_syshaptic.h index b8919bef2..ad80408e1 100644 --- a/src/haptic/SDL_syshaptic.h +++ b/src/haptic/SDL_syshaptic.h @@ -43,7 +43,6 @@ struct haptic_effect struct _SDL_Haptic { Uint8 index; /* Stores index it is attached to */ - const char* name; /* Stores the name of the device */ struct haptic_effect *effects; /* Allocated effects */ int neffects; /* Maximum amount of effects */ diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index 33d1c3d8e..502e6adbf 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -65,6 +65,7 @@ static struct struct haptic_hwdata { int fd; + char *fname; /* Points to the name in SDL_hapticlist. */ }; @@ -204,6 +205,23 @@ SDL_SYS_HapticInit(void) } +/* + * Gets the name from a file descriptor. + */ +static const char * +SDL_SYS_HapticNameFromFD(int fd) +{ + static char namebuf[128]; + + /* We use the evdev name ioctl. */ + if (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) <= 0) { + return NULL; + } + + return namebuf; +} + + /* * Return the name of a haptic device, does not need to be opened. */ @@ -211,8 +229,7 @@ const char * SDL_SYS_HapticName(int index) { int fd; - static char namebuf[128]; - char *name; + const char *name; /* Open the haptic device. */ name = NULL; @@ -220,16 +237,11 @@ SDL_SYS_HapticName(int index) if (fd >= 0) { - /* Check for name ioctl. */ - if (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) <= 0) { - + name = SDL_SYS_HapticNameFromFD(fd); + if (name==NULL) { /* No name found, return device character device */ name = SDL_hapticlist[index].fname; } - /* Name found, return name. */ - else { - name = namebuf; - } } close(fd); @@ -243,6 +255,8 @@ SDL_SYS_HapticName(int index) static int SDL_SYS_HapticOpenFromFD(SDL_Haptic * haptic, int fd) { + const char *name; + /* Allocate the hwdata */ haptic->hwdata = (struct haptic_hwdata *) SDL_malloc(sizeof(*haptic->hwdata)); @@ -252,7 +266,7 @@ SDL_SYS_HapticOpenFromFD(SDL_Haptic * haptic, int fd) } SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata)); - /* Set the data */ + /* Set the data. */ haptic->hwdata->fd = fd; haptic->supported = EV_IsHaptic(fd); haptic->naxes = 2; /* Hardcoded for now, not sure if it's possible to find out. */ @@ -293,6 +307,7 @@ int SDL_SYS_HapticOpen(SDL_Haptic * haptic) { int fd; + int ret; /* Open the character device */ fd = open(SDL_hapticlist[haptic->index].fname, O_RDWR, 0); @@ -301,8 +316,16 @@ SDL_SYS_HapticOpen(SDL_Haptic * haptic) SDL_hapticlist[haptic->index], strerror(errno)); return -1; } - - return SDL_SYS_HapticOpenFromFD(haptic,fd); + + /* Try to create the haptic. */ + ret = SDL_SYS_HapticOpenFromFD(haptic,fd); /* Already closes on error. */ + if (ret < 0) { + return -1; + } + + /* Set the fname. */ + haptic->hwdata->fname = SDL_hapticlist[haptic->index].fname; + return 0; } @@ -353,7 +376,9 @@ SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick) int SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick) { - if (SDL_strcmp(joystick->name,haptic->name)==0) { + /* We are assuming linux is using evdev which should trump the old + * joystick methods. */ + if (SDL_strcmp(joystick->hwdata->fname,haptic->hwdata->fname)==0) { return 1; } return 0; @@ -366,9 +391,27 @@ SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick) int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick) { + int i; int fd; + int ret; + + /* Find the joystick in the haptic list. */ + for (i=0; ihwdata->fname)==0) { + haptic->index = i; + } + } + } + fd = open(joystick->hwdata->fname, O_RDWR, 0); - return SDL_SYS_HapticOpenFromFD(haptic,fd); + ret = SDL_SYS_HapticOpenFromFD(haptic,fd); /* Already closes on error. */ + if (ret < 0) { + return -1; + } + + haptic->hwdata->fname = SDL_hapticlist[haptic->index].fname; + return 0; } @@ -385,10 +428,11 @@ SDL_SYS_HapticClose(SDL_Haptic * haptic) /* Free */ SDL_free(haptic->hwdata); - haptic->hwdata = NULL; SDL_free(haptic->effects); - haptic->neffects = 0; } + + /* Clear the rest. */ + SDL_memset(haptic, 0, sizeof(SDL_Haptic)); }