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).
---
 libwacom/libwacom-database.c | 31 +++++++++++++++++++++++--------
 libwacom/libwacom.c          | 43 +++++++++++++++++++++++++++++++------------
 libwacom/libwacom.h          |  1 +
 libwacom/libwacomint.h       |  6 +++---
 4 files changed, 58 insertions(+), 23 deletions(-)

diff --git a/libwacom/libwacom-database.c b/libwacom/libwacom-database.c
index f4cb82a..dd2b04f 100644
--- a/libwacom/libwacom-database.c
+++ b/libwacom/libwacom-database.c
@@ -124,9 +124,13 @@ 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 int
@@ -137,25 +141,35 @@ libwacom_matchstr_to_matches(WacomDevice *device, const 
char *match)
        int i, nmatches = 0;
        WacomBusType first_bus;
        int first_vendor_id, first_product_id;
+       char *first_name = NULL;
 
        if (match == NULL)
                return 0;
 
        strs = g_strsplit(match, ";", 0);
        for (i = 0; strs[i] != NULL && *strs[i] != '\0'; i++) {
-               char busstr[64];
+               char busstr[64], namestr[64];
+               char *name;
                int vendor_id, product_id;
                WacomBusType bus;
-               rc = sscanf(strs[i], "%63[^:]:%x:%x", busstr, &vendor_id, 
&product_id);
-               if (rc != 3) {
+
+               memset(namestr, 0, sizeof(namestr));
+
+               rc = sscanf(strs[i], "%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", strs[i]);
                        continue;
                }
                bus = bus_from_str (busstr);
 
-               libwacom_update_match(device, bus, vendor_id, product_id);
+               libwacom_update_match(device, name, bus, vendor_id, product_id);
 
                if (nmatches == 0) {
+                       first_name = g_strdup(name);
                        first_bus = bus;
                        first_vendor_id = vendor_id;
                        first_product_id = product_id;
@@ -165,8 +179,9 @@ libwacom_matchstr_to_matches(WacomDevice *device, const 
char *match)
 
        /* set default to first entry */
        if (nmatches > 1)
-               libwacom_update_match(device, first_bus, first_vendor_id, 
first_product_id);
+               libwacom_update_match(device, first_name, first_bus, 
first_vendor_id, first_product_id);
 
+       g_free(first_name);
        g_strfreev(strs);
        return i;
 }
@@ -399,7 +414,7 @@ libwacom_parse_tablet_keyfile(const char *datadir, const 
char *filename)
 
        match = g_key_file_get_string(keyfile, DEVICE_GROUP, "DeviceMatch", 
NULL);
        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);
        } else {
                if (libwacom_matchstr_to_matches(device, match) == 0) {
                        DBG("failed to match '%s' for product/vendor IDs in 
'%s'\n", match, path);
diff --git a/libwacom/libwacom.c b/libwacom/libwacom.c
index d100793..0415f75 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,10 +459,17 @@ 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);
 
+       /* no matches, try without the name */
+       if (!device && name) {
+               match = make_match_string(NULL, bus, vendor_id, product_id);
+               device = libwacom_get_device(db, match);
+               g_free (match);
+       }
+
        return device;
 }
 
@@ -488,7 +496,7 @@ 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);
+       device = libwacom_new (db, name, vendor_id, product_id, bus, error);
        if (device != NULL)
                ret = libwacom_copy(device);
        else if (fallback == WFALLBACK_NONE)
@@ -503,14 +511,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, name, bus, vendor_id, product_id);
+
+       g_free (name);
 
        if (device) {
                /* if unset, use the kernel flags. Could be unset as well. */
@@ -536,7 +544,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 +714,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 +726,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 +770,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 +781,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 +1114,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

Reply via email to