touchpad: re-route trackpoint buttons on the *50 Lenovo series
authorPeter Hutterer <peter.hutterer@who-t.net>
Wed, 28 Jan 2015 05:38:00 +0000 (15:38 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 29 Jan 2015 04:43:57 +0000 (14:43 +1000)
The laptops on this series have the physical trackpoint buttons back but
wired them up to the touchpad instead of the trackpoint device and they appear
as BTN_0, BTN_1 and BTN_2 for left, right, middle.

The udev hwdb marks these for us with the TOUCHPAD_HAS_TRACKPOINT_BUTTONS tag
[1]. Use that tag to identify them and re-route the events through the
trackstick device after mangling the event codes to represent the actual
buttons.

[1] http://cgit.freedesktop.org/systemd/systemd/tree/hwdb/70-touchpad.hwdb

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
src/evdev-mt-touchpad.c
src/evdev.h

index 5221be60bea324bed7d56c05c506151d2e45a8a1..ae37ab17d81ce631f4433e18a9cfae8126df50f5 100644 (file)
@@ -349,6 +349,41 @@ tp_process_fake_touch(struct tp_dispatch *tp,
        }
 }
 
+static void
+tp_process_trackpoint_button(struct tp_dispatch *tp,
+                            const struct input_event *e,
+                            uint64_t time)
+{
+       struct evdev_dispatch *dispatch;
+       struct input_event event;
+
+       if (!tp->buttons.trackpoint ||
+           (tp->device->tags & EVDEV_TAG_TOUCHPAD_TRACKPOINT) == 0)
+               return;
+
+       dispatch = tp->buttons.trackpoint->dispatch;
+
+       event = *e;
+
+       switch (event.code) {
+       case BTN_0:
+               event.code = BTN_LEFT;
+               break;
+       case BTN_1:
+               event.code = BTN_RIGHT;
+               break;
+       case BTN_2:
+               event.code = BTN_MIDDLE;
+               break;
+       default:
+               return;
+       }
+
+       dispatch->interface->process(dispatch,
+                                    tp->buttons.trackpoint,
+                                    &event, time);
+}
+
 static void
 tp_process_key(struct tp_dispatch *tp,
               const struct input_event *e,
@@ -367,6 +402,11 @@ tp_process_key(struct tp_dispatch *tp,
                case BTN_TOOL_QUADTAP:
                        tp_process_fake_touch(tp, e, time);
                        break;
+               case BTN_0:
+               case BTN_1:
+               case BTN_2:
+                       tp_process_trackpoint_button(tp, e, time);
+                       break;
        }
 }
 
@@ -1063,6 +1103,10 @@ tp_tag_device(struct evdev_device *device,
                         device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
        } else if (bustype != BUS_BLUETOOTH)
                device->tags |= EVDEV_TAG_INTERNAL_TOUCHPAD;
+
+       if (udev_device_get_property_value(udev_device,
+                                          "TOUCHPAD_HAS_TRACKPOINT_BUTTONS"))
+               device->tags |= EVDEV_TAG_TOUCHPAD_TRACKPOINT;
 }
 
 static struct evdev_dispatch_interface tp_interface = {
index 0f2c5acc0ac17424e385f0980ab57fd6cdcaab1b..fc70a287fe0b8156a54c648034bf3a7043dbea84 100644 (file)
@@ -54,6 +54,7 @@ enum evdev_device_tags {
        EVDEV_TAG_EXTERNAL_MOUSE = (1 << 0),
        EVDEV_TAG_INTERNAL_TOUCHPAD = (1 << 1),
        EVDEV_TAG_TRACKPOINT = (1 << 2),
+       EVDEV_TAG_TOUCHPAD_TRACKPOINT = (1 << 3),
 };
 
 struct mt_slot {