@@ -527,36 +527,95 @@ struct wacom_hdev_data {
527
527
static LIST_HEAD (wacom_udev_list );
528
528
static DEFINE_MUTEX (wacom_udev_list_lock );
529
529
530
+ static 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
+
530
542
static bool wacom_are_sibling (struct hid_device * hdev ,
531
543
struct hid_device * sibling )
532
544
{
533
545
struct wacom * wacom = hid_get_drvdata (hdev );
534
546
struct wacom_features * features = & wacom -> wacom_wac .features ;
535
- int vid = features -> oVid ;
536
- int pid = features -> oPid ;
537
- int n1 ,n2 ;
547
+ struct wacom * sibling_wacom = hid_get_drvdata (sibling );
548
+ struct wacom_features * sibling_features = & sibling_wacom -> wacom_wac .features ;
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 ) {
540
- vid = hdev -> vendor ;
541
- pid = hdev -> product ;
552
+ /* The defined oVid/oPid must match that of the sibling */
553
+ if (features -> oVid != HID_ANY_ID && sibling -> vendor != oVid )
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
581
return false;
546
582
547
- /* Compare the physical path. */
548
- n1 = strrchr (hdev -> phys , '.' ) - hdev -> phys ;
549
- n2 = strrchr (sibling -> phys , '.' ) - sibling -> phys ;
550
- if (n1 != n2 || n1 <= 0 || n2 <= 0 )
583
+ /*
584
+ * Indirect-input devices may not be siblings of direct-input
585
+ * devices.
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
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
556
608
static struct wacom_hdev_data * wacom_get_hdev_data (struct hid_device * hdev )
557
609
{
558
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
619
list_for_each_entry (data , & wacom_udev_list , list ) {
561
620
if (wacom_are_sibling (hdev , data -> dev )) {
562
621
kref_get (& data -> kref );
0 commit comments