lkml.org 
[lkml]   [2019]   [Nov]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 022/105] HID: wacom: generic: Treat serial number and related fields as unsigned
    Date
    From: Jason Gerecke <killertofu@gmail.com>

    commit ff479731c3859609530416a18ddb3db5db019b66 upstream.

    The HID descriptors for most Wacom devices oddly declare the serial
    number and other related fields as signed integers. When these numbers
    are ingested by the HID subsystem, they are automatically sign-extended
    into 32-bit integers. We treat the fields as unsigned elsewhere in the
    kernel and userspace, however, so this sign-extension causes problems.
    In particular, the sign-extended tool ID sent to userspace as ABS_MISC
    does not properly match unsigned IDs used by xf86-input-wacom and libwacom.

    We introduce a function 'wacom_s32tou' that can undo the automatic sign
    extension performed by 'hid_snto32'. We call this function when processing
    the serial number and related fields to ensure that we are dealing with
    and reporting the unsigned form. We opt to use this method rather than
    adding a descriptor fixup in 'wacom_hid_usage_quirk' since it should be
    more robust in the face of future devices.

    Ref: https://github.com/linuxwacom/input-wacom/issues/134
    Fixes: f85c9dc678 ("HID: wacom: generic: Support tool ID and additional tool types")
    CC: <stable@vger.kernel.org> # v4.10+
    Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
    Reviewed-by: Aaron Armstrong Skomra <aaron.skomra@wacom.com>
    Signed-off-by: Jiri Kosina <jkosina@suse.cz>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/hid/wacom.h | 15 +++++++++++++++
    drivers/hid/wacom_wac.c | 10 ++++++----
    2 files changed, 21 insertions(+), 4 deletions(-)

    --- a/drivers/hid/wacom.h
    +++ b/drivers/hid/wacom.h
    @@ -205,6 +205,21 @@ static inline void wacom_schedule_work(s
    }
    }

    +/*
    + * Convert a signed 32-bit integer to an unsigned n-bit integer. Undoes
    + * the normally-helpful work of 'hid_snto32' for fields that use signed
    + * ranges for questionable reasons.
    + */
    +static inline __u32 wacom_s32tou(s32 value, __u8 n)
    +{
    + switch (n) {
    + case 8: return ((__u8)value);
    + case 16: return ((__u16)value);
    + case 32: return ((__u32)value);
    + }
    + return value & (1 << (n - 1)) ? value & (~(~0U << n)) : value;
    +}
    +
    extern const struct hid_device_id wacom_ids[];

    void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
    --- a/drivers/hid/wacom_wac.c
    +++ b/drivers/hid/wacom_wac.c
    @@ -2182,7 +2182,7 @@ static void wacom_wac_pen_event(struct h
    case HID_DG_TOOLSERIALNUMBER:
    if (value) {
    wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL);
    - wacom_wac->serial[0] |= (__u32)value;
    + wacom_wac->serial[0] |= wacom_s32tou(value, field->report_size);
    }
    return;
    case HID_DG_TWIST:
    @@ -2198,15 +2198,17 @@ static void wacom_wac_pen_event(struct h
    return;
    case WACOM_HID_WD_SERIALHI:
    if (value) {
    + __u32 raw_value = wacom_s32tou(value, field->report_size);
    +
    wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF);
    - wacom_wac->serial[0] |= ((__u64)value) << 32;
    + wacom_wac->serial[0] |= ((__u64)raw_value) << 32;
    /*
    * Non-USI EMR devices may contain additional tool type
    * information here. See WACOM_HID_WD_TOOLTYPE case for
    * more details.
    */
    if (value >> 20 == 1) {
    - wacom_wac->id[0] |= value & 0xFFFFF;
    + wacom_wac->id[0] |= raw_value & 0xFFFFF;
    }
    }
    return;
    @@ -2218,7 +2220,7 @@ static void wacom_wac_pen_event(struct h
    * bitwise OR so the complete value can be built
    * up over time :(
    */
    - wacom_wac->id[0] |= value;
    + wacom_wac->id[0] |= wacom_s32tou(value, field->report_size);
    return;
    case WACOM_HID_WD_OFFSETLEFT:
    if (features->offset_left && value != features->offset_left)

    \
     
     \ /
      Last update: 2019-11-11 19:35    [W:4.166 / U:0.116 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site