diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-20 11:55:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-20 11:55:30 -0400 |
commit | 4d1890531413a19d63cb980fee6d9d3ff86d97ad (patch) | |
tree | 810147f704bd78acb52f8f245294381b30c73301 | |
parent | 41e3bef52e42c03cb7234f2d8419352478c92926 (diff) | |
parent | b658912cb023cd6f8e46963d29779903d3c10538 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina:
- suspend/resume handling fix for Raydium I2C-connected touchscreen
from Aaron Ma
- protocol fixup for certain BT-connected Wacoms from Aaron Armstrong
Skomra
- battery level reporting fix on BT-connected mice from Dmitry Torokhov
- hidraw race condition fix from Rodrigo Rivas Costa
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
HID: i2c-hid: fix inverted return value from i2c_hid_command()
HID: i2c-hid: Fix resume issue on Raydium touchscreen device
HID: wacom: bluetooth: send exit report for recent Bluetooth devices
HID: hidraw: Fix crash on HIDIOCGFEATURE with a destroyed device
HID: input: fix battery level reporting on BT mice
-rw-r--r-- | drivers/hid/hid-ids.h | 3 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 24 | ||||
-rw-r--r-- | drivers/hid/hidraw.c | 5 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 13 | ||||
-rw-r--r-- | drivers/hid/wacom_wac.c | 76 | ||||
-rw-r--r-- | include/linux/hid.h | 9 |
6 files changed, 92 insertions, 38 deletions
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 5a3a7ead3012..0b5cc910f62e 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -525,6 +525,9 @@ | |||
525 | #define I2C_VENDOR_ID_HANTICK 0x0911 | 525 | #define I2C_VENDOR_ID_HANTICK 0x0911 |
526 | #define I2C_PRODUCT_ID_HANTICK_5288 0x5288 | 526 | #define I2C_PRODUCT_ID_HANTICK_5288 0x5288 |
527 | 527 | ||
528 | #define I2C_VENDOR_ID_RAYD 0x2386 | ||
529 | #define I2C_PRODUCT_ID_RAYD_3118 0x3118 | ||
530 | |||
528 | #define USB_VENDOR_ID_HANWANG 0x0b57 | 531 | #define USB_VENDOR_ID_HANWANG 0x0b57 |
529 | #define USB_DEVICE_ID_HANWANG_TABLET_FIRST 0x5000 | 532 | #define USB_DEVICE_ID_HANWANG_TABLET_FIRST 0x5000 |
530 | #define USB_DEVICE_ID_HANWANG_TABLET_LAST 0x8fff | 533 | #define USB_DEVICE_ID_HANWANG_TABLET_LAST 0x8fff |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 6836a856c243..930652c25120 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -387,7 +387,8 @@ static int hidinput_get_battery_property(struct power_supply *psy, | |||
387 | break; | 387 | break; |
388 | 388 | ||
389 | case POWER_SUPPLY_PROP_CAPACITY: | 389 | case POWER_SUPPLY_PROP_CAPACITY: |
390 | if (dev->battery_report_type == HID_FEATURE_REPORT) { | 390 | if (dev->battery_status != HID_BATTERY_REPORTED && |
391 | !dev->battery_avoid_query) { | ||
391 | value = hidinput_query_battery_capacity(dev); | 392 | value = hidinput_query_battery_capacity(dev); |
392 | if (value < 0) | 393 | if (value < 0) |
393 | return value; | 394 | return value; |
@@ -403,17 +404,17 @@ static int hidinput_get_battery_property(struct power_supply *psy, | |||
403 | break; | 404 | break; |
404 | 405 | ||
405 | case POWER_SUPPLY_PROP_STATUS: | 406 | case POWER_SUPPLY_PROP_STATUS: |
406 | if (!dev->battery_reported && | 407 | if (dev->battery_status != HID_BATTERY_REPORTED && |
407 | dev->battery_report_type == HID_FEATURE_REPORT) { | 408 | !dev->battery_avoid_query) { |
408 | value = hidinput_query_battery_capacity(dev); | 409 | value = hidinput_query_battery_capacity(dev); |
409 | if (value < 0) | 410 | if (value < 0) |
410 | return value; | 411 | return value; |
411 | 412 | ||
412 | dev->battery_capacity = value; | 413 | dev->battery_capacity = value; |
413 | dev->battery_reported = true; | 414 | dev->battery_status = HID_BATTERY_QUERIED; |
414 | } | 415 | } |
415 | 416 | ||
416 | if (!dev->battery_reported) | 417 | if (dev->battery_status == HID_BATTERY_UNKNOWN) |
417 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; | 418 | val->intval = POWER_SUPPLY_STATUS_UNKNOWN; |
418 | else if (dev->battery_capacity == 100) | 419 | else if (dev->battery_capacity == 100) |
419 | val->intval = POWER_SUPPLY_STATUS_FULL; | 420 | val->intval = POWER_SUPPLY_STATUS_FULL; |
@@ -486,6 +487,14 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, | |||
486 | dev->battery_report_type = report_type; | 487 | dev->battery_report_type = report_type; |
487 | dev->battery_report_id = field->report->id; | 488 | dev->battery_report_id = field->report->id; |
488 | 489 | ||
490 | /* | ||
491 | * Stylus is normally not connected to the device and thus we | ||
492 | * can't query the device and get meaningful battery strength. | ||
493 | * We have to wait for the device to report it on its own. | ||
494 | */ | ||
495 | dev->battery_avoid_query = report_type == HID_INPUT_REPORT && | ||
496 | field->physical == HID_DG_STYLUS; | ||
497 | |||
489 | dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); | 498 | dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); |
490 | if (IS_ERR(dev->battery)) { | 499 | if (IS_ERR(dev->battery)) { |
491 | error = PTR_ERR(dev->battery); | 500 | error = PTR_ERR(dev->battery); |
@@ -530,9 +539,10 @@ static void hidinput_update_battery(struct hid_device *dev, int value) | |||
530 | 539 | ||
531 | capacity = hidinput_scale_battery_capacity(dev, value); | 540 | capacity = hidinput_scale_battery_capacity(dev, value); |
532 | 541 | ||
533 | if (!dev->battery_reported || capacity != dev->battery_capacity) { | 542 | if (dev->battery_status != HID_BATTERY_REPORTED || |
543 | capacity != dev->battery_capacity) { | ||
534 | dev->battery_capacity = capacity; | 544 | dev->battery_capacity = capacity; |
535 | dev->battery_reported = true; | 545 | dev->battery_status = HID_BATTERY_REPORTED; |
536 | power_supply_changed(dev->battery); | 546 | power_supply_changed(dev->battery); |
537 | } | 547 | } |
538 | } | 548 | } |
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index fbfcc8009432..b39844adea47 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
@@ -192,6 +192,11 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t | |||
192 | int ret = 0, len; | 192 | int ret = 0, len; |
193 | unsigned char report_number; | 193 | unsigned char report_number; |
194 | 194 | ||
195 | if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { | ||
196 | ret = -ENODEV; | ||
197 | goto out; | ||
198 | } | ||
199 | |||
195 | dev = hidraw_table[minor]->hid; | 200 | dev = hidraw_table[minor]->hid; |
196 | 201 | ||
197 | if (!dev->ll_driver->raw_request) { | 202 | if (!dev->ll_driver->raw_request) { |
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 97689e98e53f..963328674e93 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c | |||
@@ -47,6 +47,7 @@ | |||
47 | /* quirks to control the device */ | 47 | /* quirks to control the device */ |
48 | #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0) | 48 | #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0) |
49 | #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET BIT(1) | 49 | #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET BIT(1) |
50 | #define I2C_HID_QUIRK_RESEND_REPORT_DESCR BIT(2) | ||
50 | 51 | ||
51 | /* flags */ | 52 | /* flags */ |
52 | #define I2C_HID_STARTED 0 | 53 | #define I2C_HID_STARTED 0 |
@@ -171,6 +172,8 @@ static const struct i2c_hid_quirks { | |||
171 | I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV }, | 172 | I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV }, |
172 | { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288, | 173 | { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288, |
173 | I2C_HID_QUIRK_NO_IRQ_AFTER_RESET }, | 174 | I2C_HID_QUIRK_NO_IRQ_AFTER_RESET }, |
175 | { I2C_VENDOR_ID_RAYD, I2C_PRODUCT_ID_RAYD_3118, | ||
176 | I2C_HID_QUIRK_RESEND_REPORT_DESCR }, | ||
174 | { 0, 0 } | 177 | { 0, 0 } |
175 | }; | 178 | }; |
176 | 179 | ||
@@ -1220,6 +1223,16 @@ static int i2c_hid_resume(struct device *dev) | |||
1220 | if (ret) | 1223 | if (ret) |
1221 | return ret; | 1224 | return ret; |
1222 | 1225 | ||
1226 | /* RAYDIUM device (2386:3118) need to re-send report descr cmd | ||
1227 | * after resume, after this it will be back normal. | ||
1228 | * otherwise it issues too many incomplete reports. | ||
1229 | */ | ||
1230 | if (ihid->quirks & I2C_HID_QUIRK_RESEND_REPORT_DESCR) { | ||
1231 | ret = i2c_hid_command(client, &hid_report_descr_cmd, NULL, 0); | ||
1232 | if (ret) | ||
1233 | return ret; | ||
1234 | } | ||
1235 | |||
1223 | if (hid->driver && hid->driver->reset_resume) { | 1236 | if (hid->driver && hid->driver->reset_resume) { |
1224 | ret = hid->driver->reset_resume(hid); | 1237 | ret = hid->driver->reset_resume(hid); |
1225 | return ret; | 1238 | return ret; |
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 6da16a879c9f..5f947ec20dcb 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c | |||
@@ -689,6 +689,45 @@ static int wacom_intuos_get_tool_type(int tool_id) | |||
689 | return tool_type; | 689 | return tool_type; |
690 | } | 690 | } |
691 | 691 | ||
692 | static void wacom_exit_report(struct wacom_wac *wacom) | ||
693 | { | ||
694 | struct input_dev *input = wacom->pen_input; | ||
695 | struct wacom_features *features = &wacom->features; | ||
696 | unsigned char *data = wacom->data; | ||
697 | int idx = (features->type == INTUOS) ? (data[1] & 0x01) : 0; | ||
698 | |||
699 | /* | ||
700 | * Reset all states otherwise we lose the initial states | ||
701 | * when in-prox next time | ||
702 | */ | ||
703 | input_report_abs(input, ABS_X, 0); | ||
704 | input_report_abs(input, ABS_Y, 0); | ||
705 | input_report_abs(input, ABS_DISTANCE, 0); | ||
706 | input_report_abs(input, ABS_TILT_X, 0); | ||
707 | input_report_abs(input, ABS_TILT_Y, 0); | ||
708 | if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { | ||
709 | input_report_key(input, BTN_LEFT, 0); | ||
710 | input_report_key(input, BTN_MIDDLE, 0); | ||
711 | input_report_key(input, BTN_RIGHT, 0); | ||
712 | input_report_key(input, BTN_SIDE, 0); | ||
713 | input_report_key(input, BTN_EXTRA, 0); | ||
714 | input_report_abs(input, ABS_THROTTLE, 0); | ||
715 | input_report_abs(input, ABS_RZ, 0); | ||
716 | } else { | ||
717 | input_report_abs(input, ABS_PRESSURE, 0); | ||
718 | input_report_key(input, BTN_STYLUS, 0); | ||
719 | input_report_key(input, BTN_STYLUS2, 0); | ||
720 | input_report_key(input, BTN_TOUCH, 0); | ||
721 | input_report_abs(input, ABS_WHEEL, 0); | ||
722 | if (features->type >= INTUOS3S) | ||
723 | input_report_abs(input, ABS_Z, 0); | ||
724 | } | ||
725 | input_report_key(input, wacom->tool[idx], 0); | ||
726 | input_report_abs(input, ABS_MISC, 0); /* reset tool id */ | ||
727 | input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
728 | wacom->id[idx] = 0; | ||
729 | } | ||
730 | |||
692 | static int wacom_intuos_inout(struct wacom_wac *wacom) | 731 | static int wacom_intuos_inout(struct wacom_wac *wacom) |
693 | { | 732 | { |
694 | struct wacom_features *features = &wacom->features; | 733 | struct wacom_features *features = &wacom->features; |
@@ -741,36 +780,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) | |||
741 | if (!wacom->id[idx]) | 780 | if (!wacom->id[idx]) |
742 | return 1; | 781 | return 1; |
743 | 782 | ||
744 | /* | 783 | wacom_exit_report(wacom); |
745 | * Reset all states otherwise we lose the initial states | ||
746 | * when in-prox next time | ||
747 | */ | ||
748 | input_report_abs(input, ABS_X, 0); | ||
749 | input_report_abs(input, ABS_Y, 0); | ||
750 | input_report_abs(input, ABS_DISTANCE, 0); | ||
751 | input_report_abs(input, ABS_TILT_X, 0); | ||
752 | input_report_abs(input, ABS_TILT_Y, 0); | ||
753 | if (wacom->tool[idx] >= BTN_TOOL_MOUSE) { | ||
754 | input_report_key(input, BTN_LEFT, 0); | ||
755 | input_report_key(input, BTN_MIDDLE, 0); | ||
756 | input_report_key(input, BTN_RIGHT, 0); | ||
757 | input_report_key(input, BTN_SIDE, 0); | ||
758 | input_report_key(input, BTN_EXTRA, 0); | ||
759 | input_report_abs(input, ABS_THROTTLE, 0); | ||
760 | input_report_abs(input, ABS_RZ, 0); | ||
761 | } else { | ||
762 | input_report_abs(input, ABS_PRESSURE, 0); | ||
763 | input_report_key(input, BTN_STYLUS, 0); | ||
764 | input_report_key(input, BTN_STYLUS2, 0); | ||
765 | input_report_key(input, BTN_TOUCH, 0); | ||
766 | input_report_abs(input, ABS_WHEEL, 0); | ||
767 | if (features->type >= INTUOS3S) | ||
768 | input_report_abs(input, ABS_Z, 0); | ||
769 | } | ||
770 | input_report_key(input, wacom->tool[idx], 0); | ||
771 | input_report_abs(input, ABS_MISC, 0); /* reset tool id */ | ||
772 | input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | ||
773 | wacom->id[idx] = 0; | ||
774 | return 2; | 784 | return 2; |
775 | } | 785 | } |
776 | 786 | ||
@@ -1235,6 +1245,12 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) | |||
1235 | if (!valid) | 1245 | if (!valid) |
1236 | continue; | 1246 | continue; |
1237 | 1247 | ||
1248 | if (!prox) { | ||
1249 | wacom->shared->stylus_in_proximity = false; | ||
1250 | wacom_exit_report(wacom); | ||
1251 | input_sync(pen_input); | ||
1252 | return; | ||
1253 | } | ||
1238 | if (range) { | 1254 | if (range) { |
1239 | input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1])); | 1255 | input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1])); |
1240 | input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3])); | 1256 | input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3])); |
diff --git a/include/linux/hid.h b/include/linux/hid.h index 8da3e1f48195..26240a22978a 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -516,6 +516,12 @@ enum hid_type { | |||
516 | HID_TYPE_USBNONE | 516 | HID_TYPE_USBNONE |
517 | }; | 517 | }; |
518 | 518 | ||
519 | enum hid_battery_status { | ||
520 | HID_BATTERY_UNKNOWN = 0, | ||
521 | HID_BATTERY_QUERIED, /* Kernel explicitly queried battery strength */ | ||
522 | HID_BATTERY_REPORTED, /* Device sent unsolicited battery strength report */ | ||
523 | }; | ||
524 | |||
519 | struct hid_driver; | 525 | struct hid_driver; |
520 | struct hid_ll_driver; | 526 | struct hid_ll_driver; |
521 | 527 | ||
@@ -558,7 +564,8 @@ struct hid_device { /* device report descriptor */ | |||
558 | __s32 battery_max; | 564 | __s32 battery_max; |
559 | __s32 battery_report_type; | 565 | __s32 battery_report_type; |
560 | __s32 battery_report_id; | 566 | __s32 battery_report_id; |
561 | bool battery_reported; | 567 | enum hid_battery_status battery_status; |
568 | bool battery_avoid_query; | ||
562 | #endif | 569 | #endif |
563 | 570 | ||
564 | unsigned int status; /* see STAT flags above */ | 571 | unsigned int status; /* see STAT flags above */ |