diff --git a/udev/libinput-device-group.c b/udev/libinput-device-group.c index ba8327ec..7bc9beec 100644 --- a/udev/libinput-device-group.c +++ b/udev/libinput-device-group.c @@ -64,47 +64,57 @@ out: } #endif +static int +find_tree_distance(struct udev_device *a, struct udev_device *b) +{ + struct udev_device *ancestor_a = a; + int dist_a = 0; + + while (ancestor_a != NULL) { + const char *path_a = udev_device_get_syspath(ancestor_a); + struct udev_device *ancestor_b = b; + int dist_b = 0; + + while (ancestor_b != NULL) { + const char *path_b = udev_device_get_syspath(ancestor_b); + + if (strcmp(path_a, path_b) == 0) + return dist_a + dist_b; + + dist_b++; + ancestor_b = udev_device_get_parent(ancestor_b); + } + + dist_a++; + ancestor_a = udev_device_get_parent(ancestor_a); + } + return -1; +} + static void wacom_handle_ekr(struct udev_device *device, int *vendor_id, int *product_id) { - struct udev_device *parent; struct udev *udev; struct udev_enumerate *e; struct udev_list_entry *entry; - - /* Search for the parent that is the cintiq, then search down for the - * inputXX node on that parent. Grab the product ID from there and - * overwrite our id with that one, this puts the EKR into the same - * device group the Cintiq is it's plugged into. - */ - - parent = udev_device_get_parent_with_subsystem_devtype(device, - "usb", - "usb_device"); - if (!parent) - return; + int best_dist = -1; udev = udev_device_get_udev(device); e = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(e, "input"); udev_enumerate_add_match_sysname(e, "input*"); - udev_enumerate_add_match_parent(e, parent); udev_enumerate_scan_devices(e); udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { struct udev_device *d; const char *path; const char *pidstr, *vidstr; - int pid, vid; - - /* This list contain the two input nodes for the - * Cintiq pen and the touch, where applicable. - * We pick the first one (usually the pen), relying on - * wacom_handle_paired() to fix our ID later if needed. - * - * Note: we don't do anything if the parent we find isn't a - * Wacom device. + int pid, vid, dist; + + /* Find and use the closest Wacom device on the system, + * relying on wacom_handle_paired() to fix our ID later + * if needed. */ path = udev_list_entry_get_name(entry); d = udev_device_new_from_syspath(udev, path); @@ -117,10 +127,14 @@ wacom_handle_ekr(struct udev_device *device, if (vidstr && pidstr && safe_atoi_base(vidstr, &vid, 16) && safe_atoi_base(pidstr, &pid, 16) && - vid == VENDOR_ID_WACOM) { - *product_id = pid; - udev_device_unref(d); - break; + vid == VENDOR_ID_WACOM && + pid != PRODUCT_ID_WACOM_EKR) { + dist = find_tree_distance(device, d); + if (dist > 0 && (dist < best_dist || best_dist < 0)) { + *vendor_id = vid; + *product_id = pid; + best_dist = dist; + } } udev_device_unref(d);