Fixed bug where a Logitech wireless keyboard with built-in mouse touchpad didn't get recongized as both devices.
authorSam Lantinga <slouken@libsdl.org>
Sat, 05 Oct 2013 21:15:55 -0700
changeset 7788 25355ecf10aa
parent 7787 e6f3e8fc96ea
child 7789 a18c12b02b69
Fixed bug where a Logitech wireless keyboard with built-in mouse touchpad didn't get recongized as both devices.
src/core/linux/SDL_udev.c
src/core/linux/SDL_udev.h
src/input/evdev/SDL_evdev.c
src/input/evdev/SDL_evdev.h
src/joystick/linux/SDL_sysjoystick.c
--- a/src/core/linux/SDL_udev.c	Sat Oct 05 19:09:03 2013 -0700
+++ b/src/core/linux/SDL_udev.c	Sat Oct 05 21:15:55 2013 -0700
@@ -279,7 +279,7 @@
 {
     const char *subsystem;
     const char *val = NULL;
-    SDL_UDEV_deviceclass devclass = 0;
+    int devclass = 0;
     const char *path;
     SDL_UDEV_CallbackList *item;
     
@@ -291,32 +291,26 @@
     subsystem = _this->udev_device_get_subsystem(dev);
     if (SDL_strcmp(subsystem, "sound") == 0) {
         devclass = SDL_UDEV_DEVICE_SOUND;
-    }
-    else if (SDL_strcmp(subsystem, "input") == 0) {
+    } else if (SDL_strcmp(subsystem, "input") == 0) {
         val = _this->udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK");
         if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
-            devclass = SDL_UDEV_DEVICE_JOYSTICK;
+            devclass |= SDL_UDEV_DEVICE_JOYSTICK;
         }
         
-        if (devclass == 0) {
-            val = _this->udev_device_get_property_value(dev, "ID_INPUT_MOUSE");
-            if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
-                devclass = SDL_UDEV_DEVICE_MOUSE;
-            }
+        val = _this->udev_device_get_property_value(dev, "ID_INPUT_MOUSE");
+        if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
+            devclass |= SDL_UDEV_DEVICE_MOUSE;
         }
-        
-        if (devclass == 0) {
-            val = _this->udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");
-            if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
-                devclass = SDL_UDEV_DEVICE_KEYBOARD;
-            }
+
+        val = _this->udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");
+        if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
+            devclass |= SDL_UDEV_DEVICE_KEYBOARD;
         }
-        
+
         if (devclass == 0) {
             return;
         }
-    }
-    else {
+    } else {
         return;
     }
     
@@ -401,4 +395,4 @@
 }
 
 
-#endif /* SDL_USE_LIBUDEV */
\ No newline at end of file
+#endif /* SDL_USE_LIBUDEV */
--- a/src/core/linux/SDL_udev.h	Sat Oct 05 19:09:03 2013 -0700
+++ b/src/core/linux/SDL_udev.h	Sat Oct 05 21:15:55 2013 -0700
@@ -46,15 +46,16 @@
     SDL_UDEV_DEVICEREMOVED
 } SDL_UDEV_deviceevent;
 
+/* A device can be any combination of these classes */
 typedef enum
 {
-    SDL_UDEV_DEVICE_MOUSE = 0x0001,
-    SDL_UDEV_DEVICE_KEYBOARD,
-    SDL_UDEV_DEVICE_JOYSTICK,
-    SDL_UDEV_DEVICE_SOUND
+    SDL_UDEV_DEVICE_MOUSE       = 0x0001,
+    SDL_UDEV_DEVICE_KEYBOARD    = 0x0002,
+    SDL_UDEV_DEVICE_JOYSTICK    = 0x0004,
+    SDL_UDEV_DEVICE_SOUND       = 0x0008
 } SDL_UDEV_deviceclass;
 
-typedef void (*SDL_UDEV_Callback)(SDL_UDEV_deviceevent udev_type, SDL_UDEV_deviceclass udev_class, const char *devpath);
+typedef void (*SDL_UDEV_Callback)(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
 
 typedef struct SDL_UDEV_CallbackList {
     SDL_UDEV_Callback callback;
@@ -111,4 +112,4 @@
 
 #endif /* HAVE_LIBUDEV_H */
 
-#endif /* _SDL_udev_h */
\ No newline at end of file
+#endif /* _SDL_udev_h */
--- a/src/input/evdev/SDL_evdev.c	Sat Oct 05 19:09:03 2013 -0700
+++ b/src/input/evdev/SDL_evdev.c	Sat Oct 05 21:15:55 2013 -0700
@@ -62,8 +62,8 @@
 static int SDL_EVDEV_device_removed(const char *devpath);
 
 #if SDL_USE_LIBUDEV
-static int SDL_EVDEV_device_added(const SDL_UDEV_deviceclass devclass, const char *devpath);
-void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, SDL_UDEV_deviceclass udev_class, const char *devpath);
+static int SDL_EVDEV_device_added(const char *devpath);
+void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
 #endif /* SDL_USE_LIBUDEV */
 
 static SDL_Scancode EVDEV_Keycodes[] = {
@@ -403,7 +403,6 @@
         
         /* We need a physical terminal (not PTS) to be able to translate key code to symbols via the kernel tables */
         _this->console_fd = SDL_EVDEV_get_console_fd();
-
     }
     
     _this->ref_count += 1;
@@ -445,43 +444,28 @@
 }
 
 #if SDL_USE_LIBUDEV
-void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, SDL_UDEV_deviceclass udev_class, const char *devpath)
+void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
 {
-    SDL_EVDEV_deviceclass devclass;
-    
     if (devpath == NULL) {
         return;
     }
     
-    switch( udev_class )
-    {
-        case SDL_UDEV_DEVICE_MOUSE:
-            devclass = SDL_EVDEV_DEVICE_MOUSE;
-            break;
-            
-        case SDL_UDEV_DEVICE_KEYBOARD:
-            devclass = SDL_EVDEV_DEVICE_KEYBOARD;
-            break;
-            
-        default:
-            return;
+    if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE|SDL_UDEV_DEVICE_KEYBOARD))) {
+        return;
     }
-    
-    switch( udev_type )
-    {
-        case SDL_UDEV_DEVICEADDED:
-            SDL_EVDEV_device_added(devclass, devpath);
-            break;
+
+    switch( udev_type ) {
+    case SDL_UDEV_DEVICEADDED:
+        SDL_EVDEV_device_added(devpath);
+        break;
             
-        case SDL_UDEV_DEVICEREMOVED:
-            SDL_EVDEV_device_removed(devpath);
-            break;
+    case SDL_UDEV_DEVICEREMOVED:
+        SDL_EVDEV_device_removed(devpath);
+        break;
             
-        default:
-            break;
-            
+    default:
+        break;
     }
-    
 }
 
 #endif /* SDL_USE_LIBUDEV */
@@ -507,137 +491,114 @@
     SDL_UDEV_Poll();
 #endif
 
+    mouse = SDL_GetMouse();
+
     for (item = _this->first; item != NULL; item = item->next) {
         while ((len = read(item->fd, events, (sizeof events))) > 0) {
             len /= sizeof(events[0]);
             for (i = 0; i < len; ++i) {
-                switch(item->devclass) {
-                    case SDL_EVDEV_DEVICE_KEYBOARD:
-                        switch (events[i].type) {
-                        case EV_KEY:
-                            scan_code = SDL_EVDEV_translate_keycode(events[i].code);
-                            if (scan_code != SDL_SCANCODE_UNKNOWN) {
-                                if (events[i].value == 0) {
-                                    SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
-                                }
-                                else if (events[i].value == 1 || events[i].value == 2 /* Key repeated */ ) {
-                                    SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
+                switch (events[i].type) {
+                case EV_KEY:
+                    if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) {
+                        mouse_button = events[i].code - BTN_MOUSE;
+                        if (events[i].value == 0) {
+                            SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]);
+                        } else if (events[i].value == 1) {
+                            SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]);
+                        }
+                        break;
+                    }
+
+                    /* Probably keyboard */
+                    scan_code = SDL_EVDEV_translate_keycode(events[i].code);
+                    if (scan_code != SDL_SCANCODE_UNKNOWN) {
+                        if (events[i].value == 0) {
+                            SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
+                        } else if (events[i].value == 1 || events[i].value == 2 /* Key repeated */ ) {
+                            SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
 #ifdef SDL_INPUT_LINUXKD
-                                    if (_this->console_fd >= 0) {
-                                        kbe.kb_index = events[i].code;
-                                        /* Convert the key to an UTF-8 char */
-                                        /* Ref: http://www.linuxjournal.com/article/2783 */
-                                        modstate = SDL_GetModState();
-                                        kbe.kb_table = 0;
-                                        
-                                        /* Ref: http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching */
-                                        kbe.kb_table |= -( (modstate & KMOD_LCTRL) != 0) & (1 << KG_CTRLL | 1 << KG_CTRL);
-                                        kbe.kb_table |= -( (modstate & KMOD_RCTRL) != 0) & (1 << KG_CTRLR | 1 << KG_CTRL);
-                                        kbe.kb_table |= -( (modstate & KMOD_LSHIFT) != 0) & (1 << KG_SHIFTL | 1 << KG_SHIFT);
-                                        kbe.kb_table |= -( (modstate & KMOD_RSHIFT) != 0) & (1 << KG_SHIFTR | 1 << KG_SHIFT);
-                                        kbe.kb_table |= -( (modstate & KMOD_LALT) != 0) & (1 << KG_ALT);
-                                        kbe.kb_table |= -( (modstate & KMOD_RALT) != 0) & (1 << KG_ALTGR);
+                            if (_this->console_fd >= 0) {
+                                kbe.kb_index = events[i].code;
+                                /* Convert the key to an UTF-8 char */
+                                /* Ref: http://www.linuxjournal.com/article/2783 */
+                                modstate = SDL_GetModState();
+                                kbe.kb_table = 0;
+                                
+                                /* Ref: http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching */
+                                kbe.kb_table |= -( (modstate & KMOD_LCTRL) != 0) & (1 << KG_CTRLL | 1 << KG_CTRL);
+                                kbe.kb_table |= -( (modstate & KMOD_RCTRL) != 0) & (1 << KG_CTRLR | 1 << KG_CTRL);
+                                kbe.kb_table |= -( (modstate & KMOD_LSHIFT) != 0) & (1 << KG_SHIFTL | 1 << KG_SHIFT);
+                                kbe.kb_table |= -( (modstate & KMOD_RSHIFT) != 0) & (1 << KG_SHIFTR | 1 << KG_SHIFT);
+                                kbe.kb_table |= -( (modstate & KMOD_LALT) != 0) & (1 << KG_ALT);
+                                kbe.kb_table |= -( (modstate & KMOD_RALT) != 0) & (1 << KG_ALTGR);
 
-                                        if(ioctl(_this->console_fd, KDGKBENT, (unsigned long)&kbe) == 0 && 
-                                            ( (KTYP(kbe.kb_value) == KT_LATIN) || (KTYP(kbe.kb_value) == KT_ASCII) || (KTYP(kbe.kb_value) == KT_LETTER) )) 
-                                        {
-                                            kval = KVAL(kbe.kb_value);
-                                            
-                                            /* While there's a KG_CAPSSHIFT symbol, it's not useful to build the table index with it
-                                             * because 1 << KG_CAPSSHIFT overflows the 8 bits of kb_table 
-                                             * So, we do the CAPS LOCK logic here. Note that isalpha depends on the locale!
-                                             */
-                                            if ( modstate & KMOD_CAPS && isalpha(kval) ) {
-                                                if ( isupper(kval) ) {
-                                                    kval = tolower(kval);
-                                                }
-                                                else {
-                                                    kval = toupper(kval);
-                                                }
-                                            }
-                                             
-                                            /* Convert to UTF-8 and send */
-                                            end = SDL_UCS4ToUTF8( kval, keysym);
-                                            *end = '\0';
-                                            SDL_SendKeyboardText(keysym);
+                                if (ioctl(_this->console_fd, KDGKBENT, (unsigned long)&kbe) == 0 && 
+                                    ((KTYP(kbe.kb_value) == KT_LATIN) || (KTYP(kbe.kb_value) == KT_ASCII) || (KTYP(kbe.kb_value) == KT_LETTER))) 
+                                {
+                                    kval = KVAL(kbe.kb_value);
+                                    
+                                    /* While there's a KG_CAPSSHIFT symbol, it's not useful to build the table index with it
+                                     * because 1 << KG_CAPSSHIFT overflows the 8 bits of kb_table 
+                                     * So, we do the CAPS LOCK logic here. Note that isalpha depends on the locale!
+                                     */
+                                    if ( modstate & KMOD_CAPS && isalpha(kval) ) {
+                                        if ( isupper(kval) ) {
+                                            kval = tolower(kval);
+                                        } else {
+                                            kval = toupper(kval);
                                         }
                                     }
-#endif    
+                                     
+                                    /* Convert to UTF-8 and send */
+                                    end = SDL_UCS4ToUTF8( kval, keysym);
+                                    *end = '\0';
+                                    SDL_SendKeyboardText(keysym);
                                 }
                             }
-                                break;
-
-                            default:
-                                break;
+#endif /* SDL_INPUT_LINUXKD */
                         }
-                        break; /* SDL_EVDEV_DEVICE_KEYBOARD */
-                        
-                    case SDL_EVDEV_DEVICE_MOUSE:
-                        mouse = SDL_GetMouse();
-                        switch (events[i].type) {
-                            case EV_KEY:
-                                mouse_button = events[i].code - BTN_MOUSE;
-                                if (mouse_button >= 0 && mouse_button < SDL_arraysize(EVDEV_MouseButtons)) {
-                                    if (events[i].value == 0) {
-                                        SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]);
-                                    }
-                                    else if (events[i].value == 1) {
-                                        SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]);
-                                    } 
-                                }
-                                break;
-                            case EV_ABS:
-                                 switch(events[i].code) {
-                                    case ABS_X:
-                                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
-                                        break;
-                                    case ABS_Y:
-                                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
-                                        break;
-                                    default:
-                                        break;
-                                 }
-                                break;
-                            case EV_REL:
-                                switch(events[i].code) {
-                                    case REL_X:
-                                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0);
-                                        break;
-                                    case REL_Y:
-                                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value);
-                                        break;
-                                    case REL_WHEEL:
-                                        SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value);
-                                        break;
-                                    case REL_HWHEEL:
-                                        SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0);
-                                        break;
-                                    default:
-                                        break;
-                                }
-                                break;
-                            default:
-                                break;
-                        }
-                        break; /* SDL_EVDEV_DEVICE_MOUSE */                    
-
+                    }
+                    break;
+                case EV_ABS:
+                    switch(events[i].code) {
+                    case ABS_X:
+                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
+                        break;
+                    case ABS_Y:
+                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
+                        break;
                     default:
                         break;
+                    }
+                    break;
+                case EV_REL:
+                    switch(events[i].code) {
+                    case REL_X:
+                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0);
+                        break;
+                    case REL_Y:
+                        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value);
+                        break;
+                    case REL_WHEEL:
+                        SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value);
+                        break;
+                    case REL_HWHEEL:
+                        SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0);
+                        break;
+                    default:
+                        break;
+                    }
+                    break;
+                case EV_SYN:
+                    switch (events[i].code) {
+                    case SYN_DROPPED:
+                        SDL_EVDEV_sync_device(item);
+                        break;
+                    default:
+                        break;
+                    }
+                    break;
                 }
-                
-                
-                /* Handle events not specific to any type of device */
-                switch (events[i].type) {
-                    case EV_SYN:
-                        switch (events[i].code) {
-                        case SYN_DROPPED :
-                            SDL_EVDEV_sync_device(item);
-                            break;
-                        default:
-                            break;
-                        }
-                }
-            
             }
         }    
     }
@@ -665,7 +626,7 @@
 
 #if SDL_USE_LIBUDEV
 static int
-SDL_EVDEV_device_added(const SDL_UDEV_deviceclass devclass, const char *devpath)
+SDL_EVDEV_device_added(const char *devpath)
 {
     SDL_evdevlist_item *item;
 
@@ -681,9 +642,6 @@
         return SDL_OutOfMemory();
     }
 
-    item->devclass = devclass;
-    
-   
     item->fd = open(devpath, O_RDONLY, 0);
     if (item->fd < 0) {
         SDL_free(item);
--- a/src/input/evdev/SDL_evdev.h	Sat Oct 05 19:09:03 2013 -0700
+++ b/src/input/evdev/SDL_evdev.h	Sat Oct 05 21:15:55 2013 -0700
@@ -29,17 +29,10 @@
 #include "SDL_events.h"
 #include <sys/stat.h>
 
-typedef enum
-{
-    SDL_EVDEV_DEVICE_MOUSE = 0x0001,
-    SDL_EVDEV_DEVICE_KEYBOARD
-} SDL_EVDEV_deviceclass;
-
 typedef struct SDL_evdevlist_item
 {
     char *path;
     int fd;
-    SDL_EVDEV_deviceclass devclass;
     struct SDL_evdevlist_item *next;
 } SDL_evdevlist_item;
 
--- a/src/joystick/linux/SDL_sysjoystick.c	Sat Oct 05 19:09:03 2013 -0700
+++ b/src/joystick/linux/SDL_sysjoystick.c	Sat Oct 05 21:15:55 2013 -0700
@@ -57,7 +57,7 @@
 static int MaybeAddDevice(const char *path);
 #if SDL_USE_LIBUDEV
 static int MaybeRemoveDevice(const char *path);
-void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, SDL_UDEV_deviceclass udev_class, const char *devpath);
+void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
 #endif /* SDL_USE_LIBUDEV */
 
 
@@ -136,11 +136,11 @@
 }
 
 #if SDL_USE_LIBUDEV
-void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, SDL_UDEV_deviceclass udev_class, const char *devpath)
+void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
 {
     int instance;
     
-    if (devpath == NULL || udev_class != SDL_UDEV_DEVICE_JOYSTICK) {
+    if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
         return;
     }