HID: wacom: generic: Send BTN_STYLUS3 when both barrel switches are set
authorJason Gerecke <killertofu@gmail.com>
Tue, 7 Nov 2017 16:25:17 +0000 (08:25 -0800)
committerJiri Kosina <jkosina@suse.cz>
Thu, 9 Nov 2017 12:32:43 +0000 (13:32 +0100)
The Wacom Pro Pen 3D includes a third barrel switch which is intended to
be particularly useful in applications where one frequency uses pan, zoom,
and rotate to navigate around a scene or model. The pen is compatible with
the MobileStudio Pro, 2nd-gen Intuos Pro, and Cintiq Pro. When the third
button is pressed, these devices set both the HID_DG_BARRELSWITCH and
HID_DG_BARRELSWITCH2 usages since their HID descriptors do not include a
usage specific to the button.

Rather than send both BTN_STYLUS and BTN_STYLUS2 when the third button is
pressed, userspace (libinput) has requested that we detect this condition
and report a newly-defined BTN_STYLUS3 event instead. We could define a
quirk specific to devices compatible with the Pro Pen 3D, but the liklihood
of seeing both barrel switch bits set with other pens/devices is low enough
to not worry about (pens mechanically prevent accidental activation of
multiple switches).

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
drivers/hid/wacom_wac.c
drivers/hid/wacom_wac.h
include/uapi/linux/input-event-codes.h

index e3223b0..16af688 100644 (file)
@@ -2140,6 +2140,12 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
        case HID_DG_TIPSWITCH:
                wacom_wac->hid_data.tipswitch |= value;
                return;
+       case HID_DG_BARRELSWITCH:
+               wacom_wac->hid_data.barrelswitch = value;
+               return;
+       case HID_DG_BARRELSWITCH2:
+               wacom_wac->hid_data.barrelswitch2 = value;
+               return;
        case HID_DG_TOOLSERIALNUMBER:
                if (value) {
                        wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL);
@@ -2254,6 +2260,12 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
 
        if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
                int id = wacom_wac->id[0];
+               int sw_state = wacom_wac->hid_data.barrelswitch |
+                              (wacom_wac->hid_data.barrelswitch2 << 1);
+
+               input_report_key(input, BTN_STYLUS, sw_state == 1);
+               input_report_key(input, BTN_STYLUS2, sw_state == 2);
+               input_report_key(input, BTN_STYLUS3, sw_state == 3);
 
                /*
                 * Non-USI EMR tools should have their IDs mangled to
@@ -3300,9 +3312,11 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
        else
                __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
 
-       if (features->type == HID_GENERIC)
-               /* setup has already been done */
+       if (features->type == HID_GENERIC) {
+               /* setup has already been done; apply otherwise-undetectible quirks */
+               input_set_capability(input_dev, EV_KEY, BTN_STYLUS3);
                return 0;
+       }
 
        __set_bit(BTN_TOUCH, input_dev->keybit);
        __set_bit(ABS_MISC, input_dev->absbit);
index 8a03654..69dda27 100644 (file)
@@ -291,6 +291,8 @@ struct hid_data {
        bool inrange_state;
        bool invert_state;
        bool tipswitch;
+       bool barrelswitch;
+       bool barrelswitch2;
        int x;
        int y;
        int pressure;
index 1798910..9b3a522 100644 (file)
 #define BTN_TOOL_MOUSE         0x146
 #define BTN_TOOL_LENS          0x147
 #define BTN_TOOL_QUINTTAP      0x148   /* Five fingers on trackpad */
+#define BTN_STYLUS3            0x149
 #define BTN_TOUCH              0x14a
 #define BTN_STYLUS             0x14b
 #define BTN_STYLUS2            0x14c