evdev: Add support for device quirks and implement axes swapping
authorRob Bradford <rob@linux.intel.com>
Mon, 17 Sep 2012 17:02:22 +0000 (18:02 +0100)
committerOssama Othman <ossama.othman@intel.com>
Fri, 19 Apr 2013 22:59:49 +0000 (15:59 -0700)
This quirk is designed for hardware that has the X and Y axes swapped for
absolute events.

src/evdev.c
src/evdev.h

index ccadf92..157264b 100644 (file)
@@ -131,21 +131,41 @@ evdev_process_absolute_motion(struct evdev_device *device,
        const int screen_width = device->output->current->width;
        const int screen_height = device->output->current->height;
 
-       switch (e->code) {
-       case ABS_X:
-               device->abs.x =
-                       (e->value - device->abs.min_x) * screen_width /
-                       (device->abs.max_x - device->abs.min_x) +
-                       device->output->x;
-               device->pending_events |= EVDEV_ABSOLUTE_MOTION;
-               break;
-       case ABS_Y:
-               device->abs.y =
-                       (e->value - device->abs.min_y) * screen_height /
-                       (device->abs.max_y - device->abs.min_y) +
-                       device->output->y;
-               device->pending_events |= EVDEV_ABSOLUTE_MOTION;
-               break;
+       if (device->quirks & EVDEV_QUIRK_SWAP_AXES) {
+               switch (e->code) {
+               case ABS_X:
+                       device->abs.y =
+                               (e->value - device->abs.min_y) * screen_height /
+                               (device->abs.max_y - device->abs.min_y) +
+                               device->output->y;
+                       device->pending_events |= EVDEV_ABSOLUTE_MOTION;
+                       break;
+               case ABS_Y:
+                       device->abs.x =
+                               (e->value - device->abs.min_x) * screen_width /
+                               (device->abs.max_x - device->abs.min_x) +
+                               device->output->x;
+                       device->pending_events |= EVDEV_ABSOLUTE_MOTION;
+                       break;
+               }
+
+       } else {
+               switch (e->code) {
+               case ABS_X:
+                       device->abs.x =
+                               (e->value - device->abs.min_x) * screen_width /
+                               (device->abs.max_x - device->abs.min_x) +
+                               device->output->x;
+                       device->pending_events |= EVDEV_ABSOLUTE_MOTION;
+                       break;
+               case ABS_Y:
+                       device->abs.y =
+                               (e->value - device->abs.min_y) * screen_height /
+                               (device->abs.max_y - device->abs.min_y) +
+                               device->output->y;
+                       device->pending_events |= EVDEV_ABSOLUTE_MOTION;
+                       break;
+               }
        }
 }
 
@@ -420,12 +440,22 @@ evdev_handle_device(struct evdev_device *device)
                if (TEST_BIT(abs_bits, ABS_MT_SLOT)) {
                        ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_X),
                              &absinfo);
-                       device->abs.min_x = absinfo.minimum;
-                       device->abs.max_x = absinfo.maximum;
+                       if (device->quirks & EVDEV_QUIRK_SWAP_AXES) {
+                               device->abs.min_y = absinfo.minimum;
+                               device->abs.max_y = absinfo.maximum;
+                       } else {
+                               device->abs.min_x = absinfo.minimum;
+                               device->abs.max_x = absinfo.maximum;
+                       }
                        ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_Y),
                              &absinfo);
-                       device->abs.min_y = absinfo.minimum;
-                       device->abs.max_y = absinfo.maximum;
+                       if (device->quirks & EVDEV_QUIRK_SWAP_AXES) {
+                               device->abs.min_x = absinfo.minimum;
+                               device->abs.max_x = absinfo.maximum;
+                       } else {
+                               device->abs.min_y = absinfo.minimum;
+                               device->abs.max_y = absinfo.maximum;
+                       }
                        device->is_mt = 1;
                        device->mt.slot = 0;
                        device->caps |= EVDEV_TOUCH;
index bb931f3..cc14597 100644 (file)
@@ -45,6 +45,11 @@ enum evdev_device_capability {
        EVDEV_TOUCH = (1 << 4),
 };
 
+enum evdev_device_quirks {
+       EVDEV_QUIRK_NONE = 0,
+       EVDEV_QUIRK_SWAP_AXES = (1 << 0),
+};
+
 struct evdev_device {
        struct weston_seat *seat;
        struct wl_list link;
@@ -72,6 +77,7 @@ struct evdev_device {
 
        enum evdev_event_type pending_events;
        enum evdev_device_capability caps;
+       uint32_t quirks;
 
        int is_mt;
 };