Fix for dropped joystick events contributed by Simon <simon@mungewell.org>
authorSam Lantinga <slouken@libsdl.org>
Mon, 11 Feb 2013 16:45:24 -0800
changeset 6844 e09997fb33cc
parent 6843 a52016007a7e
child 6845 e14535915e3e
Fix for dropped joystick events contributed by Simon <simon@mungewell.org> In my system SDL2 is dropping a chunk of joystick events, which result in a 'stuck brake/accelerator' whilst playing a racing simulator. This basically means SDL2 is unsuitable for use at this point... The patch below detects this situation and forces a re-read of all attached joystick axis - thus resync to the correct/current pedal positions.
src/joystick/linux/SDL_sysjoystick.c
src/joystick/linux/SDL_sysjoystick_c.h
--- a/src/joystick/linux/SDL_sysjoystick.c	Mon Feb 11 11:21:54 2013 -0800
+++ b/src/joystick/linux/SDL_sysjoystick.c	Mon Feb 11 16:45:24 2013 -0800
@@ -763,6 +763,9 @@
     /* Get the number of buttons and axes on the joystick */
     ConfigJoystick(joystick, fd);
 
+    // mark joystick as fresh and ready
+    joystick->hwdata->fresh = 1;
+
     return (0);
 }
 
@@ -834,12 +837,55 @@
 }
 
 static __inline__ void
+PollAllValues(SDL_Joystick * joystick)
+{
+    struct input_absinfo absinfo;
+    int a, b = 0;
+
+    // Poll all axis
+    for (a = ABS_X; b < ABS_MAX; a++) {
+        switch (a) {
+        case ABS_HAT0X:
+        case ABS_HAT0Y:
+        case ABS_HAT1X:
+        case ABS_HAT1Y:
+        case ABS_HAT2X:
+        case ABS_HAT2Y:
+        case ABS_HAT3X:
+        case ABS_HAT3Y:
+            // ingore hats
+            break;
+        default:
+            if (joystick->hwdata->abs_correct[b].used) {
+                if (ioctl(joystick->hwdata->fd, EVIOCGABS(a), &absinfo) >= 0) {
+                    absinfo.value = AxisCorrect(joystick, b, absinfo.value);
+
+#ifdef DEBUG_INPUT_EVENTS
+                    printf("Joystick : Re-read Axis %d (%d) val= %d\n",
+                        joystick->hwdata->abs_map[b], a, absinfo.value);
+#endif
+                    SDL_PrivateJoystickAxis(joystick,
+                            joystick->hwdata->abs_map[b],
+                            absinfo.value);
+                }
+            }
+            b++;
+        }
+    }
+}
+
+static __inline__ void
 HandleInputEvents(SDL_Joystick * joystick)
 {
     struct input_event events[32];
     int i, len;
     int code;
 
+    if (joystick->hwdata->fresh) {
+        PollAllValues(joystick);
+        joystick->hwdata->fresh = 0;
+    }
+
     while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
         len /= sizeof(events[0]);
         for (i = 0; i < len; ++i) {
@@ -890,6 +936,17 @@
                     break;
                 }
                 break;
+            case EV_SYN:
+                switch (code) {
+                case SYN_DROPPED :
+#ifdef DEBUG_INPUT_EVENTS
+                    printf("Event SYN_DROPPED dectected\n");
+#endif
+                    PollAllValues(joystick);
+                    break;
+                default:
+                    break;
+                }
             default:
                 break;
             }
--- a/src/joystick/linux/SDL_sysjoystick_c.h	Mon Feb 11 11:21:54 2013 -0800
+++ b/src/joystick/linux/SDL_sysjoystick_c.h	Mon Feb 11 16:45:24 2013 -0800
@@ -50,4 +50,8 @@
         int used;
         int coef[3];
     } abs_correct[ABS_MAX];
+
+    int fresh;
 };
+
+/* vi: set ts=4 sw=4 expandtab: */