Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/hid/hid

Pull HID fixes from Jiri Kosina:
 "Two fixes for the HID subsystem:

   - regression fix for i2c-hid power management (Hans de Goede)

   - signed vs unsigned API fix for Wacom driver (Jason Gerecke)"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid:
  HID: wacom: generic: Treat serial number and related fields as unsigned
  HID: i2c-hid: Send power-on command after reset
  • Loading branch information
torvalds committed Nov 7, 2019
2 parents 4dd5815 + ff47973 commit 847120f
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 4 deletions.
4 changes: 4 additions & 0 deletions drivers/hid/i2c-hid/i2c-hid-core.c
Expand Up @@ -447,8 +447,12 @@ static int i2c_hid_hwreset(struct i2c_client *client)
if (ret) {
dev_err(&client->dev, "failed to reset device.\n");
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
goto out_unlock;
}

/* At least some SIS devices need this after reset */
ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);

out_unlock:
mutex_unlock(&ihid->reset_lock);
return ret;
Expand Down
15 changes: 15 additions & 0 deletions drivers/hid/wacom.h
Expand Up @@ -202,6 +202,21 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac,
}
}

/*
* 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);
Expand Down
10 changes: 6 additions & 4 deletions drivers/hid/wacom_wac.c
Expand Up @@ -2303,7 +2303,7 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
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:
Expand All @@ -2319,15 +2319,17 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
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;
Expand All @@ -2339,7 +2341,7 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
* 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)
Expand Down

0 comments on commit 847120f

Please sign in to comment.