HID: wacom: Don’t set tool type until we’re in range [Linux 4.14.129]

HID: wacom: Don’t set tool type until we’re in range [Linux 4.14.129]

This Linux kernel change "HID: wacom: Don’t set tool type until we’re in range" is included in the Linux 4.14.129 release. This change is authored by Jason Gerecke <jason.gerecke [at] wacom.com> on Wed Apr 24 15:12:57 2019 -0700. The commit for this change in Linux stable tree is bed5114 (patch) which is from upstream commit 2cc0880. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 2cc0880.

HID: wacom: Don't set tool type until we're in range

commit 2cc08800a6b9fcda7c7afbcf2da1a6e8808da725 upstream.

The serial number and tool type information that is reported by the tablet
while a pen is merely "in prox" instead of fully "in range" can be stale
and cause us to report incorrect tool information. Serial number, tool
type, and other information is only valid once the pen comes fully in range
so we should be careful to not use this information until that point.

In particular, this issue may cause the driver to incorectly report
BTN_TOOL_RUBBER after switching from the eraser tool back to the pen.

Fixes: a48324de6d4d ("HID: wacom: Bluetooth IRQ for Intuos Pro should handle prox/range")
Cc: <[email protected]> # 4.11+
Signed-off-by: Jason Gerecke <[email protected]>
Reviewed-by: Aaron Armstrong Skomra <[email protected]>
Signed-off-by: Benjamin Tissoires <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

There are 17 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/hid/wacom_wac.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 22e8068..5336336 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1225,13 +1225,13 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
        /* Add back in missing bits of ID for non-USI pens */
        wacom->id[0] |= (wacom->serial[0] >> 32) & 0xFFFFF;
    }
-   wacom->tool[0]   = wacom_intuos_get_tool_type(wacom_intuos_id_mangle(wacom->id[0]));

    for (i = 0; i < pen_frames; i++) {
        unsigned char *frame = &data[i*pen_frame_len + 1];
        bool valid = frame[0] & 0x80;
        bool prox = frame[0] & 0x40;
        bool range = frame[0] & 0x20;
+       bool invert = frame[0] & 0x10;

        if (!valid)
            continue;
@@ -1240,8 +1240,13 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
            wacom->shared->stylus_in_proximity = false;
            wacom_exit_report(wacom);
            input_sync(pen_input);
+
+           wacom->tool[0] = 0;
+           wacom->id[0] = 0;
+           wacom->serial[0] = 0;
            return;
        }
+
        if (range) {
            /* Fix rotation alignment: userspace expects zero at left */
            int16_t rotation = (int16_t)get_unaligned_le16(&frame[9]);
@@ -1249,6 +1254,16 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
            if (rotation > 899)
                rotation -= 1800;

+           if (!wacom->tool[0]) { /* first in range */
+               /* Going into range select tool */
+               if (invert)
+                   wacom->tool[0] = BTN_TOOL_RUBBER;
+               else if (wacom->id[0])
+                   wacom->tool[0] = wacom_intuos_get_tool_type(wacom->id[0]);
+               else
+                   wacom->tool[0] = BTN_TOOL_PEN;
+           }
+
            input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1]));
            input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3]));
            input_report_abs(pen_input, ABS_TILT_X, (char)frame[7]);

Leave a Reply

Your email address will not be published. Required fields are marked *