aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-20 11:55:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-20 11:55:30 -0400
commit4d1890531413a19d63cb980fee6d9d3ff86d97ad (patch)
tree810147f704bd78acb52f8f245294381b30c73301
parent41e3bef52e42c03cb7234f2d8419352478c92926 (diff)
parentb658912cb023cd6f8e46963d29779903d3c10538 (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.h3
-rw-r--r--drivers/hid/hid-input.c24
-rw-r--r--drivers/hid/hidraw.c5
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.c13
-rw-r--r--drivers/hid/wacom_wac.c76
-rw-r--r--include/linux/hid.h9
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
692static 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
692static int wacom_intuos_inout(struct wacom_wac *wacom) 731static 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
519enum 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
519struct hid_driver; 525struct hid_driver;
520struct hid_ll_driver; 526struct 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 */