aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gerecke <killertofu@gmail.com>2016-08-08 15:06:30 -0400
committerJiri Kosina <jkosina@suse.cz>2016-08-10 05:44:28 -0400
commit41372d5d40e73ef4d8574e53a39c7faabff20260 (patch)
treee3eeba450c0b8dbff84d48aa195f7029af106b68
parente5bc8eb1b02244be4e97e9654d394275e615923a (diff)
HID: wacom: Augment 'oVid' and 'oPid' with heuristics for HID_GENERIC
The 'oVid' and 'oPid' variables used by wacom_are_sibling are a hacky solution to the problem of the driver historically having few good heuristics to use in determining if two devices should be considered siblings or not. While it works well enough for explicitly supported devices, it offers no help for HID_GENERIC devices. Now that we have a bit more information (e.g. direct/indirect) available to us though, we should make use of it it to improve the pairing of such devices. Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/wacom_sys.c83
-rw-r--r--drivers/hid/wacom_wac.c2
2 files changed, 72 insertions, 13 deletions
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index edde8819e506..5e7a5648e708 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -527,36 +527,95 @@ struct wacom_hdev_data {
527static LIST_HEAD(wacom_udev_list); 527static LIST_HEAD(wacom_udev_list);
528static DEFINE_MUTEX(wacom_udev_list_lock); 528static DEFINE_MUTEX(wacom_udev_list_lock);
529 529
530static bool compare_device_paths(struct hid_device *hdev_a,
531 struct hid_device *hdev_b, char separator)
532{
533 int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys;
534 int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys;
535
536 if (n1 != n2 || n1 <= 0 || n2 <= 0)
537 return false;
538
539 return !strncmp(hdev_a->phys, hdev_b->phys, n1);
540}
541
530static bool wacom_are_sibling(struct hid_device *hdev, 542static bool wacom_are_sibling(struct hid_device *hdev,
531 struct hid_device *sibling) 543 struct hid_device *sibling)
532{ 544{
533 struct wacom *wacom = hid_get_drvdata(hdev); 545 struct wacom *wacom = hid_get_drvdata(hdev);
534 struct wacom_features *features = &wacom->wacom_wac.features; 546 struct wacom_features *features = &wacom->wacom_wac.features;
535 int vid = features->oVid; 547 struct wacom *sibling_wacom = hid_get_drvdata(sibling);
536 int pid = features->oPid; 548 struct wacom_features *sibling_features = &sibling_wacom->wacom_wac.features;
537 int n1,n2; 549 __u32 oVid = features->oVid ? features->oVid : hdev->vendor;
550 __u32 oPid = features->oPid ? features->oPid : hdev->product;
538 551
539 if (vid == 0 && pid == 0) { 552 /* The defined oVid/oPid must match that of the sibling */
540 vid = hdev->vendor; 553 if (features->oVid != HID_ANY_ID && sibling->vendor != oVid)
541 pid = hdev->product; 554 return false;
555 if (features->oPid != HID_ANY_ID && sibling->product != oPid)
556 return false;
557
558 /*
559 * Devices with the same VID/PID must share the same physical
560 * device path, while those with different VID/PID must share
561 * the same physical parent device path.
562 */
563 if (hdev->vendor == sibling->vendor && hdev->product == sibling->product) {
564 if (!compare_device_paths(hdev, sibling, '/'))
565 return false;
566 } else {
567 if (!compare_device_paths(hdev, sibling, '.'))
568 return false;
542 } 569 }
543 570
544 if (vid != sibling->vendor || pid != sibling->product) 571 /* Skip the remaining heuristics unless you are a HID_GENERIC device */
572 if (features->type != HID_GENERIC)
573 return true;
574
575 /*
576 * Direct-input devices may not be siblings of indirect-input
577 * devices.
578 */
579 if ((features->device_type & WACOM_DEVICETYPE_DIRECT) &&
580 !(sibling_features->device_type & WACOM_DEVICETYPE_DIRECT))
545 return false; 581 return false;
546 582
547 /* Compare the physical path. */ 583 /*
548 n1 = strrchr(hdev->phys, '.') - hdev->phys; 584 * Indirect-input devices may not be siblings of direct-input
549 n2 = strrchr(sibling->phys, '.') - sibling->phys; 585 * devices.
550 if (n1 != n2 || n1 <= 0 || n2 <= 0) 586 */
587 if (!(features->device_type & WACOM_DEVICETYPE_DIRECT) &&
588 (sibling_features->device_type & WACOM_DEVICETYPE_DIRECT))
589 return false;
590
591 /* Pen devices may only be siblings of touch devices */
592 if ((features->device_type & WACOM_DEVICETYPE_PEN) &&
593 !(sibling_features->device_type & WACOM_DEVICETYPE_TOUCH))
594 return false;
595
596 /* Touch devices may only be siblings of pen devices */
597 if ((features->device_type & WACOM_DEVICETYPE_TOUCH) &&
598 !(sibling_features->device_type & WACOM_DEVICETYPE_PEN))
551 return false; 599 return false;
552 600
553 return !strncmp(hdev->phys, sibling->phys, n1); 601 /*
602 * No reason could be found for these two devices to NOT be
603 * siblings, so there's a good chance they ARE siblings
604 */
605 return true;
554} 606}
555 607
556static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev) 608static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
557{ 609{
558 struct wacom_hdev_data *data; 610 struct wacom_hdev_data *data;
559 611
612 /* Try to find an already-probed interface from the same device */
613 list_for_each_entry(data, &wacom_udev_list, list) {
614 if (compare_device_paths(hdev, data->dev, '/'))
615 return data;
616 }
617
618 /* Fallback to finding devices that appear to be "siblings" */
560 list_for_each_entry(data, &wacom_udev_list, list) { 619 list_for_each_entry(data, &wacom_udev_list, list) {
561 if (wacom_are_sibling(hdev, data->dev)) { 620 if (wacom_are_sibling(hdev, data->dev)) {
562 kref_get(&data->kref); 621 kref_get(&data->kref);
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index a545c2451156..0c4eb31c1c71 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -3531,7 +3531,7 @@ static const struct wacom_features wacom_features_0x343 =
3531 WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; 3531 WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
3532 3532
3533static const struct wacom_features wacom_features_HID_ANY_ID = 3533static const struct wacom_features wacom_features_HID_ANY_ID =
3534 { "Wacom HID", .type = HID_GENERIC }; 3534 { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID };
3535 3535
3536#define USB_DEVICE_WACOM(prod) \ 3536#define USB_DEVICE_WACOM(prod) \
3537 HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\ 3537 HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\