To support generic tablets, we need to extend the matching pattern of libwacom. The Huion tablets reuse the same VID:PID accross all of the products. To be able to differentiate between the models, we can somewhat rely on the name of the product. It doesn't seem very reliable (for instance, the H610 Pro and the W58 seems to share the same name), but it should allow a good amount of them to be added to the DB.
The current usb:VID:PID pattern is still working, we add a new pattern usb:VID:PID:NAME. For devices with their name in the matching pattern, the function libwacom_new_from_usbid() does not work. We encourage users to use libwacom_new_from_path() instead. (g-c-c and g-s-d already use that, and libinput just switched to it). --- changes in v3: - rebased on top of previous one changes in v2: - libwacom_new_from_path() now tries with or without name (or an extra match was appended to the device) - rebased on previous patch libwacom/libwacom-database.c | 25 ++++++++++++++++++------- libwacom/libwacom.c | 43 ++++++++++++++++++++++++++++++------------- libwacom/libwacom.h | 1 + libwacom/libwacomint.h | 6 +++--- 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/libwacom/libwacom-database.c b/libwacom/libwacom-database.c index 3b39dba..841d2b4 100644 --- a/libwacom/libwacom-database.c +++ b/libwacom/libwacom-database.c @@ -124,16 +124,21 @@ bus_to_str (WacomBusType bus) } char * -make_match_string (WacomBusType bus, int vendor_id, int product_id) +make_match_string (const char *name, WacomBusType bus, int vendor_id, int product_id) { - return g_strdup_printf("%s:%04x:%04x", bus_to_str (bus), vendor_id, product_id); + return g_strdup_printf("%s:%04x:%04x%s%s", + bus_to_str (bus), + vendor_id, product_id, + name ? ":" : "", + name ? name : ""); } static gboolean libwacom_matchstr_to_match(WacomDevice *device, const char *match) { int rc = 1; - char busstr[64]; + char busstr[64], namestr[64]; + char *name; int vendor_id, product_id; WacomBusType bus; @@ -141,18 +146,24 @@ libwacom_matchstr_to_match(WacomDevice *device, const char *match) return FALSE; if (g_strcmp0 (match, GENERIC_DEVICE_MATCH) == 0) { - libwacom_update_match(device, WBUSTYPE_UNKNOWN, 0, 0); + libwacom_update_match(device, NULL, WBUSTYPE_UNKNOWN, 0, 0); return TRUE; } - rc = sscanf(match, "%63[^:]:%x:%x", busstr, &vendor_id, &product_id); - if (rc != 3) { + memset(namestr, 0, sizeof(namestr)); + + rc = sscanf(match, "%63[^:]:%x:%x:%63c", busstr, &vendor_id, &product_id, namestr); + if (rc == 4) { + name = namestr; + } else if (rc == 3) { + name = NULL; + } else { DBG("failed to match '%s' for product/vendor IDs. Skipping.\n", match); return 0; } bus = bus_from_str (busstr); - libwacom_update_match(device, bus, vendor_id, product_id); + libwacom_update_match(device, name, bus, vendor_id, product_id); return TRUE; } diff --git a/libwacom/libwacom.c b/libwacom/libwacom.c index d100793..b389ef5 100644 --- a/libwacom/libwacom.c +++ b/libwacom/libwacom.c @@ -300,6 +300,7 @@ static WacomMatch *libwacom_copy_match(const WacomMatch *src) dst = g_new0(WacomMatch, 1); dst->match = g_strdup(src->match); + dst->name = g_strdup(src->name); dst->bus = src->bus; dst->vendor_id = src->vendor_id; dst->product_id = src->product_id; @@ -448,7 +449,7 @@ libwacom_compare(const WacomDevice *a, const WacomDevice *b, WacomCompareFlags f } static const WacomDevice * -libwacom_new (const WacomDeviceDatabase *db, int vendor_id, int product_id, WacomBusType bus, WacomError *error) +libwacom_new (const WacomDeviceDatabase *db, const char *name, int vendor_id, int product_id, WacomBusType bus, WacomError *error) { const WacomDevice *device; char *match; @@ -458,7 +459,7 @@ libwacom_new (const WacomDeviceDatabase *db, int vendor_id, int product_id, Waco return NULL; } - match = make_match_string(bus, vendor_id, product_id); + match = make_match_string(name, bus, vendor_id, product_id); device = libwacom_get_device(db, match); g_free (match); @@ -473,7 +474,7 @@ libwacom_new_from_path(const WacomDeviceDatabase *db, const char *path, WacomFal const WacomDevice *device; WacomDevice *ret; WacomIntegrationFlags integration_flags; - char *name; + char *name, *match_name; if (!db) { libwacom_error_set(error, WERROR_INVALID_DB, "db is NULL"); @@ -488,7 +489,12 @@ libwacom_new_from_path(const WacomDeviceDatabase *db, const char *path, WacomFal if (!get_device_info (path, &vendor_id, &product_id, &name, &bus, &integration_flags, error)) return NULL; - device = libwacom_new (db, vendor_id, product_id, bus, error); + match_name = name; + device = libwacom_new (db, match_name, vendor_id, product_id, bus, error); + if (device == NULL) { + match_name = NULL; + device = libwacom_new (db, match_name, vendor_id, product_id, bus, error); + } if (device != NULL) ret = libwacom_copy(device); else if (fallback == WFALLBACK_NONE) @@ -503,14 +509,14 @@ libwacom_new_from_path(const WacomDeviceDatabase *db, const char *path, WacomFal if (name != NULL) { g_free (ret->name); - ret->name = name; + ret->name = g_strdup(name); } - } else { - g_free (name); } /* for multiple-match devices, set to the one we requested */ - libwacom_update_match(ret, bus, vendor_id, product_id); + libwacom_update_match(ret, match_name, bus, vendor_id, product_id); + + g_free (name); if (device) { /* if unset, use the kernel flags. Could be unset as well. */ @@ -536,7 +542,7 @@ libwacom_new_from_usbid(const WacomDeviceDatabase *db, int vendor_id, int produc return NULL; } - device = libwacom_new(db, vendor_id, product_id, WBUSTYPE_USB, error); + device = libwacom_new(db, NULL, vendor_id, product_id, WBUSTYPE_USB, error); if (device) return libwacom_copy(device); @@ -706,6 +712,7 @@ libwacom_print_device_description(int fd, const WacomDevice *device) dprintf(fd, "Name=%s\n", libwacom_get_name(device)); dprintf(fd, "DeviceMatch="); for (match = libwacom_get_matches(device); *match; match++) { + const char *name = libwacom_match_get_name(*match); WacomBusType type = libwacom_match_get_bustype(*match); int vendor = libwacom_match_get_vendor_id(*match); int product = libwacom_match_get_product_id(*match); @@ -717,7 +724,10 @@ libwacom_print_device_description(int fd, const WacomDevice *device) case WBUSTYPE_UNKNOWN: bus_name = "unknown"; break; default: g_assert_not_reached(); break; } - dprintf(fd, "%s:%04x:%04x;", bus_name, vendor, product); + dprintf(fd, "%s:%04x:%04x", bus_name, vendor, product); + if (name) + dprintf(fd, ":%s", name); + dprintf(fd, ";"); } dprintf(fd, "\n"); @@ -758,6 +768,7 @@ libwacom_destroy(WacomDevice *device) for (i = 0; i < device->nmatches; i++) { g_free (device->matches[i]->match); + g_free (device->matches[i]->name); g_free (device->matches[i]); } g_free (device->matches); @@ -768,18 +779,19 @@ libwacom_destroy(WacomDevice *device) } void -libwacom_update_match(WacomDevice *device, WacomBusType bus, int vendor_id, int product_id) +libwacom_update_match(WacomDevice *device, const char *name, WacomBusType bus, int vendor_id, int product_id) { char *newmatch; int i; WacomMatch match; - if (bus == WBUSTYPE_UNKNOWN && vendor_id == 0 && product_id == 0) + if (name == NULL && bus == WBUSTYPE_UNKNOWN && vendor_id == 0 && product_id == 0) newmatch = g_strdup("generic"); else - newmatch = make_match_string(bus, vendor_id, product_id); + newmatch = make_match_string(name, bus, vendor_id, product_id); match.match = newmatch; + match.name = g_strdup(name); match.bus = bus; match.vendor_id = vendor_id; match.product_id = product_id; @@ -1100,6 +1112,11 @@ void libwacom_stylus_destroy(WacomStylus *stylus) } +const char *libwacom_match_get_name(const WacomMatch *match) +{ + return match->name; +} + WacomBusType libwacom_match_get_bustype(const WacomMatch *match) { return match->bus; diff --git a/libwacom/libwacom.h b/libwacom/libwacom.h index 60c873f..a0778c5 100644 --- a/libwacom/libwacom.h +++ b/libwacom/libwacom.h @@ -602,6 +602,7 @@ WacomStylusType libwacom_stylus_get_type (const WacomStylus *stylus); */ void libwacom_print_stylus_description (int fd, const WacomStylus *stylus); +const char *libwacom_match_get_name(const WacomMatch *match); WacomBusType libwacom_match_get_bustype(const WacomMatch *match); uint32_t libwacom_match_get_product_id(const WacomMatch *match); uint32_t libwacom_match_get_vendor_id(const WacomMatch *match); diff --git a/libwacom/libwacomint.h b/libwacom/libwacomint.h index 3ba54cc..825f9e9 100644 --- a/libwacom/libwacomint.h +++ b/libwacom/libwacomint.h @@ -54,6 +54,7 @@ enum WacomFeature { * make sure to update libwacom_copy_match() ! */ struct _WacomMatch { char *match; + char *name; WacomBusType bus; uint32_t vendor_id; uint32_t product_id; @@ -119,12 +120,11 @@ struct _WacomError { /* INTERNAL */ void libwacom_error_set(WacomError *error, enum WacomErrorCode code, const char *msg, ...); void libwacom_stylus_destroy(WacomStylus *stylus); -void libwacom_update_match(WacomDevice *device, WacomBusType bus, int vendor_id, int product_id); +void libwacom_update_match(WacomDevice *device, const char *name, WacomBusType bus, int vendor_id, int product_id); WacomBusType bus_from_str (const char *str); const char *bus_to_str (WacomBusType bus); -char *make_match_string(WacomBusType bus, int vendor_id, int product_id); - +char *make_match_string(const char *name, WacomBusType bus, int vendor_id, int product_id); #endif /* _LIBWACOMINT_H_ */ -- 2.3.1 ------------------------------------------------------------------------------ Dive into the World of Parallel Programming The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel