diff src/haptic/linux/SDL_syshaptic.c @ 2524:1a55848ce198 gsoc2008_force_feedback

Better handling of opening haptics from joysticks. Fixed segfault when opening from joystick.
author Edgar Simo <bobbens@gmail.com>
date Thu, 17 Jul 2008 16:07:20 +0000
parents 366d84fdf8d1
children 2d88b82ce781
line wrap: on
line diff
--- a/src/haptic/linux/SDL_syshaptic.c	Thu Jul 17 11:47:48 2008 +0000
+++ b/src/haptic/linux/SDL_syshaptic.c	Thu Jul 17 16:07:20 2008 +0000
@@ -65,6 +65,7 @@
 struct haptic_hwdata
 {
    int fd;
+   char *fname; /* Points to the name in SDL_hapticlist. */
 };
 
 
@@ -205,14 +206,30 @@
 
 
 /*
+ * 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.
  */
 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 @@
 
    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 @@
 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_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 @@
 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_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 @@
 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 @@
 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; i<MAX_HAPTICS; i++) {
+      if (SDL_hapticlist[i].fname != NULL) {
+         if (SDL_strcmp(SDL_hapticlist[i].fname, joystick->hwdata->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 @@
 
       /* 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));
 }