Skip to content

Commit 847120f

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/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
2 parents 4dd5815 + ff47973 commit 847120f

File tree

3 files changed

+25
-4
lines changed

3 files changed

+25
-4
lines changed

drivers/hid/i2c-hid/i2c-hid-core.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,12 @@ static int i2c_hid_hwreset(struct i2c_client *client)
447447
if (ret) {
448448
dev_err(&client->dev, "failed to reset device.\n");
449449
i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
450+
goto out_unlock;
450451
}
451452

453+
/* At least some SIS devices need this after reset */
454+
ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
455+
452456
out_unlock:
453457
mutex_unlock(&ihid->reset_lock);
454458
return ret;

drivers/hid/wacom.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,21 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac,
202202
}
203203
}
204204

205+
/*
206+
* Convert a signed 32-bit integer to an unsigned n-bit integer. Undoes
207+
* the normally-helpful work of 'hid_snto32' for fields that use signed
208+
* ranges for questionable reasons.
209+
*/
210+
static inline __u32 wacom_s32tou(s32 value, __u8 n)
211+
{
212+
switch (n) {
213+
case 8: return ((__u8)value);
214+
case 16: return ((__u16)value);
215+
case 32: return ((__u32)value);
216+
}
217+
return value & (1 << (n - 1)) ? value & (~(~0U << n)) : value;
218+
}
219+
205220
extern const struct hid_device_id wacom_ids[];
206221

207222
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);

drivers/hid/wacom_wac.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,7 +2303,7 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
23032303
case HID_DG_TOOLSERIALNUMBER:
23042304
if (value) {
23052305
wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL);
2306-
wacom_wac->serial[0] |= (__u32)value;
2306+
wacom_wac->serial[0] |= wacom_s32tou(value, field->report_size);
23072307
}
23082308
return;
23092309
case HID_DG_TWIST:
@@ -2319,15 +2319,17 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
23192319
return;
23202320
case WACOM_HID_WD_SERIALHI:
23212321
if (value) {
2322+
__u32 raw_value = wacom_s32tou(value, field->report_size);
2323+
23222324
wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF);
2323-
wacom_wac->serial[0] |= ((__u64)value) << 32;
2325+
wacom_wac->serial[0] |= ((__u64)raw_value) << 32;
23242326
/*
23252327
* Non-USI EMR devices may contain additional tool type
23262328
* information here. See WACOM_HID_WD_TOOLTYPE case for
23272329
* more details.
23282330
*/
23292331
if (value >> 20 == 1) {
2330-
wacom_wac->id[0] |= value & 0xFFFFF;
2332+
wacom_wac->id[0] |= raw_value & 0xFFFFF;
23312333
}
23322334
}
23332335
return;
@@ -2339,7 +2341,7 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
23392341
* bitwise OR so the complete value can be built
23402342
* up over time :(
23412343
*/
2342-
wacom_wac->id[0] |= value;
2344+
wacom_wac->id[0] |= wacom_s32tou(value, field->report_size);
23432345
return;
23442346
case WACOM_HID_WD_OFFSETLEFT:
23452347
if (features->offset_left && value != features->offset_left)

0 commit comments

Comments
 (0)