Work around missing EVIOCGMTSLOTS ioctl
authorPeter Hutterer <peter.hutterer@who-t.net>
Tue, 8 Oct 2013 04:21:14 +0000 (14:21 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Tue, 22 Oct 2013 23:04:41 +0000 (09:04 +1000)
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
libevdev/libevdev.c

index 29640f4..6f203e2 100644 (file)
@@ -498,11 +498,14 @@ sync_mt_state(struct libevdev *dev, int create_events)
 {
        int rc;
        int i;
+       int ioctl_success = 0;
        struct mt_state {
                int code;
                int val[MAX_SLOTS];
        } mt_state[ABS_MT_CNT];
 
+       memset(&mt_state, 0, sizeof(mt_state));
+
        for (i = ABS_MT_MIN; i <= ABS_MT_MAX; i++) {
                int idx;
                if (i == ABS_MT_SLOT)
@@ -514,8 +517,15 @@ sync_mt_state(struct libevdev *dev, int create_events)
                idx = i - ABS_MT_MIN;
                mt_state[idx].code = i;
                rc = ioctl(dev->fd, EVIOCGMTSLOTS(sizeof(struct mt_state)), &mt_state[idx]);
-               if (rc < 0)
-                       goto out;
+               if (rc < 0) {
+                       /* if the first ioctl fails with -EINVAL, chances are the kernel
+                          doesn't support the ioctl. Simply continue */
+                       if (errno == -EINVAL && !ioctl_success) {
+                               rc = 0;
+                       } else /* if the second, ... ioctl fails, really fail */
+                               goto out;
+               } else if (ioctl_success == 0)
+                       ioctl_success = 1;
        }
 
        for (i = 0; i < dev->num_slots; i++) {