Skip to content

Commit 41372d5

Browse files
jigpuJiri Kosina
authored andcommitted
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 <[email protected]> Reviewed-by: Benjamin Tissoires <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent e5bc8eb commit 41372d5

File tree

2 files changed

+72
-13
lines changed

2 files changed

+72
-13
lines changed

drivers/hid/wacom_sys.c

Lines changed: 71 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -527,36 +527,95 @@ struct wacom_hdev_data {
527527
static LIST_HEAD(wacom_udev_list);
528528
static DEFINE_MUTEX(wacom_udev_list_lock);
529529

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+
530542
static bool wacom_are_sibling(struct hid_device *hdev,
531543
struct hid_device *sibling)
532544
{
533545
struct wacom *wacom = hid_get_drvdata(hdev);
534546
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;
538551

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;
542569
}
543570

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))
545581
return false;
546582

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))
551599
return false;
552600

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;
554606
}
555607

556608
static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
557609
{
558610
struct wacom_hdev_data *data;
559611

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" */
560619
list_for_each_entry(data, &wacom_udev_list, list) {
561620
if (wacom_are_sibling(hdev, data->dev)) {
562621
kref_get(&data->kref);

drivers/hid/wacom_wac.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3531,7 +3531,7 @@ static const struct wacom_features wacom_features_0x343 =
35313531
WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
35323532

35333533
static 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 };
35353535

35363536
#define USB_DEVICE_WACOM(prod) \
35373537
HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\

0 commit comments

Comments
 (0)