diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2012-03-29 12:14:18 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2012-03-29 14:37:30 +1000 |
commit | 1b1a730db6fd4f989eae5cac87aa057c71af994f (patch) | |
tree | 111b470db65677ea637d04cbf0d8f5de5339efb4 | |
parent | 7e1e1e4f1a4379ec2e1568caaf5b6fc4b933c11e (diff) |
lib: update to take multiple match types in the struct
Add a new type WacomMatch that holds device matching information.
A WacomDevice in libwacom now has a bunch of possible matches that can be
queried. The first possible match is the default match unless the device was
updated otherwise (e.g. libwacom_device_new_from_path will set the correct
match).
Previous calls to get bustype, vendor_id, product_id now return the set
match's values.
Basic refcounting was added to the WacomDevice to allow for the device to be
stored multiple times in the device hashtable.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r-- | data/list.c | 18 | ||||
-rw-r--r-- | libwacom/libwacom-database.c | 68 | ||||
-rw-r--r-- | libwacom/libwacom.c | 106 | ||||
-rw-r--r-- | libwacom/libwacom.h | 20 | ||||
-rw-r--r-- | libwacom/libwacomint.h | 16 |
5 files changed, 185 insertions, 43 deletions
diff --git a/data/list.c b/data/list.c index 4c70fce..93f7bba 100644 --- a/data/list.c +++ b/data/list.c @@ -41,11 +41,11 @@ static void print_udev_header (void) printf ("\n"); } -static void print_udev_entry (WacomDevice *device) +static void print_udev_entry_for_match (WacomDevice *device, const WacomMatch *match) { - WacomBusType type = libwacom_get_bustype (device); - int vendor = libwacom_get_vendor_id (device); - int product = libwacom_get_product_id (device); + WacomBusType type = libwacom_match_get_bustype (match); + int vendor = libwacom_match_get_vendor_id (match); + int product = libwacom_match_get_product_id (match); int has_touch = libwacom_has_touch (device); static char *touchpad; @@ -67,6 +67,16 @@ static void print_udev_entry (WacomDevice *device) } } +static void print_udev_entry (WacomDevice *device) +{ + WacomMatch **matches; + int nmatches; + + matches = libwacom_get_matches(device, &nmatches); + while(nmatches--) + print_udev_entry_for_match(device, matches[nmatches]); +} + static void print_udev_trailer (void) { printf ("\n"); diff --git a/libwacom/libwacom-database.c b/libwacom/libwacom-database.c index ff87d54..719f747 100644 --- a/libwacom/libwacom-database.c +++ b/libwacom/libwacom-database.c @@ -121,21 +121,45 @@ make_match_string (WacomBusType bus, int vendor_id, int product_id) } static int -libwacom_matchstr_to_ints(const char *match, uint32_t *vendor_id, uint32_t *product_id, WacomBusType *bus) +libwacom_matchstr_to_matches(WacomDevice *device, const char *match) { - char busstr[64]; - int rc; + int rc = 1; + char **strs; + int i, nmatches = 0; + WacomBusType first_bus; + int first_vendor_id, first_product_id; if (match == NULL) return 0; - rc = sscanf(match, "%63[^:]:%x:%x", busstr, vendor_id, product_id); - if (rc != 3) - return 0; + strs = g_strsplit(match, ";", 0); + for (i = 0; i < g_strv_length(strs); i++) { + char busstr[64]; + int vendor_id, product_id; + WacomBusType bus; + rc = sscanf(strs[i], "%63[^:]:%x:%x", busstr, &vendor_id, &product_id); + if (rc != 3) { + DBG("failed to match '%s' for product/vendor IDs. Skipping.\n", strs[i]); + continue; + } + bus = bus_from_str (busstr); - *bus = bus_from_str (busstr); + libwacom_update_match(device, bus, vendor_id, product_id); - return 1; + if (nmatches == 0) { + first_bus = bus; + first_vendor_id = vendor_id; + first_product_id = product_id; + } + nmatches++; + } + + /* set default to first entry */ + if (nmatches > 1) + libwacom_update_match(device, first_bus, first_vendor_id, first_product_id); + + g_strfreev(strs); + return i; } static void @@ -297,18 +321,17 @@ libwacom_parse_tablet_keyfile(const char *path) match = g_key_file_get_string(keyfile, DEVICE_GROUP, "DeviceMatch", NULL); if (g_strcmp0 (match, GENERIC_DEVICE_MATCH) == 0) { - device->match = match; + libwacom_update_match(device, WBUSTYPE_UNKNOWN, 0, 0); } else { - if (!libwacom_matchstr_to_ints(match, &device->vendor_id, &device->product_id, &device->bus)) { + if (libwacom_matchstr_to_matches(device, match) == 0) { DBG("failed to match '%s' for product/vendor IDs in '%s'\n", match, path); g_free (match); g_free (device); device = NULL; goto out; } - device->match = make_match_string(device->bus, device->vendor_id, device->product_id); - g_free (match); } + g_free (match); device->name = g_key_file_get_string(keyfile, DEVICE_GROUP, "Name", NULL); device->width = g_key_file_get_integer(keyfile, DEVICE_GROUP, "Width", NULL); @@ -357,17 +380,17 @@ libwacom_parse_tablet_keyfile(const char *path) if (device->features & FEATURE_BUILTIN && device->features & FEATURE_REVERSIBLE) - g_warning ("Tablet '%s' is both reversible and builtin. This is impossible", device->match); + g_warning ("Tablet '%s' is both reversible and builtin. This is impossible", libwacom_get_match(device)); if (!(device->features & FEATURE_RING) && (device->features & FEATURE_RING2)) - g_warning ("Table '%s' has Ring2 but no Ring. This is impossible", device->match); + g_warning ("Table '%s' has Ring2 but no Ring. This is impossible", libwacom_get_match(device)); device->num_strips = g_key_file_get_integer(keyfile, FEATURES_GROUP, "NumStrips", NULL); device->num_buttons = g_key_file_get_integer(keyfile, FEATURES_GROUP, "Buttons", &error); if (device->num_buttons == 0 && g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { - g_warning ("Tablet '%s' has no buttons defined, do something!", device->match); + g_warning ("Tablet '%s' has no buttons defined, do something!", libwacom_get_match(device)); g_clear_error (&error); } if (device->num_buttons > 0) { @@ -426,13 +449,24 @@ libwacom_database_new_for_path (const char *datadir) nfiles = n; while(n--) { WacomDevice *d; + WacomMatch **matches; + int nmatches; path = g_build_filename (datadir, files[n]->d_name, NULL); d = libwacom_parse_tablet_keyfile(path); g_free(path); - if (d) - g_hash_table_insert (db->device_ht, g_strdup (d->match), d); + if (!d) + continue; + + matches = libwacom_get_matches(d, &nmatches); + while (nmatches--) { + const char *matchstr; + + matchstr = libwacom_match_get_match_string(matches[nmatches]); + g_hash_table_insert (db->device_ht, g_strdup (matchstr), d); + d->refcnt++; + } } while(nfiles--) diff --git a/libwacom/libwacom.c b/libwacom/libwacom.c index ad9cc3f..6eb0221 100644 --- a/libwacom/libwacom.c +++ b/libwacom/libwacom.c @@ -170,20 +170,34 @@ bail: return retval; } +static WacomMatch *libwacom_copy_match(const WacomMatch *src) +{ + WacomMatch *dst; + + dst = g_new0(WacomMatch, 1); + *dst = *src; + dst->match = g_strdup(src->match); + + return dst; +} + static WacomDevice * libwacom_copy(const WacomDevice *device) { WacomDevice *d; + int i; d = g_new0 (WacomDevice, 1); + d->refcnt = 1; d->name = g_strdup (device->name); d->width = device->width; d->height = device->height; - d->match = g_strdup (device->match); - d->vendor_id = device->vendor_id; - d->product_id = device->product_id; + d->nmatches = device->nmatches; + d->matches = g_malloc(d->nmatches * sizeof(WacomMatch*)); + for (i = 0; i < d->nmatches; i++) + d->matches[i] = libwacom_copy_match(device->matches[i]); + d->match = device->match; d->cls = device->cls; - d->bus = device->bus; d->num_strips = device->num_strips; d->features = device->features; d->strips_num_modes = device->strips_num_modes; @@ -193,6 +207,7 @@ libwacom_copy(const WacomDevice *device) d->supported_styli = g_memdup (device->supported_styli, sizeof(int) * device->num_styli); d->num_buttons = device->num_buttons; d->buttons = g_memdup (device->buttons, sizeof(WacomButtonFlags) * device->num_buttons); + d->refcnt = 1; return d; } @@ -254,11 +269,13 @@ libwacom_new_from_path(WacomDeviceDatabase *db, const char *path, int fallback, g_free (ret->name); ret->name = name; } - libwacom_update_match(ret, bus, vendor_id, product_id); } else { g_free (name); } + /* for multiple-match devices, set to the one we requested */ + libwacom_update_match(ret, bus, vendor_id, product_id); + if (device) { if (builtin == IS_BUILTIN_TRUE) ret->features |= FEATURE_BUILTIN; @@ -326,9 +343,18 @@ libwacom_new_from_name(WacomDeviceDatabase *db, const char *name, WacomError *er void libwacom_destroy(WacomDevice *device) { + int i; + + if (--device->refcnt) + return; + g_free (device->name); - g_free (device->match); + for (i = 0; i < device->nmatches; i++) { + g_free (device->matches[i]->match); + g_free (device->matches[i]); + } + g_free (device->matches); g_free (device->supported_styli); g_free (device->buttons); g_free (device); @@ -337,16 +363,37 @@ libwacom_destroy(WacomDevice *device) void libwacom_update_match(WacomDevice *device, WacomBusType bus, int vendor_id, int product_id) { - device->vendor_id = vendor_id; - device->product_id = product_id; - device->bus = bus; - g_free(device->match); - device->match = make_match_string(device->bus, device->vendor_id, device->product_id); + char *newmatch; + int i; + WacomMatch match; + + if (bus == WBUSTYPE_UNKNOWN && vendor_id == 0 && product_id == 0) + newmatch = g_strdup("generic"); + else + newmatch = make_match_string(bus, vendor_id, product_id); + + match.match = newmatch; + match.bus = bus; + match.vendor_id = vendor_id; + match.product_id = product_id; + + for (i = 0; i < device->nmatches; i++) { + if (g_strcmp0(libwacom_match_get_match_string(device->matches[i]), newmatch) == 0) { + device->match = i; + g_free(newmatch); + return; + } + } + + device->matches = realloc(device->matches, ++device->nmatches * sizeof(WacomMatch)); + device->matches[device->nmatches-1] = libwacom_copy_match(&match); + device->match = device->nmatches - 1; + g_free(newmatch); } int libwacom_get_vendor_id(WacomDevice *device) { - return device->vendor_id; + return device->matches[device->match]->vendor_id; } const char* libwacom_get_name(WacomDevice *device) @@ -356,14 +403,18 @@ const char* libwacom_get_name(WacomDevice *device) int libwacom_get_product_id(WacomDevice *device) { - return device->product_id; + return device->matches[device->match]->product_id; } const char* libwacom_get_match(WacomDevice *device) { - /* FIXME make sure this only returns the first match - * when we implement multiple matching */ - return device->match; + return device->matches[device->match]->match; +} + +WacomMatch** libwacom_get_matches(WacomDevice *device, int *nmatches) +{ + *nmatches = device->nmatches; + return device->matches; } int libwacom_get_width(WacomDevice *device) @@ -445,7 +496,7 @@ int libwacom_is_reversible(WacomDevice *device) WacomBusType libwacom_get_bustype(WacomDevice *device) { - return device->bus; + return device->matches[device->match]->bus; } WacomButtonFlags @@ -517,4 +568,25 @@ void libwacom_stylus_destroy(WacomStylus *stylus) g_free (stylus); } + +WacomBusType libwacom_match_get_bustype(const WacomMatch *match) +{ + return match->bus; +} + +uint32_t libwacom_match_get_product_id(const WacomMatch *match) +{ + return match->product_id; +} + +uint32_t libwacom_match_get_vendor_id(const WacomMatch *match) +{ + return match->vendor_id; +} + +const char* libwacom_match_get_match_string(const WacomMatch *match) +{ + return match->match; +} + /* vim: set noexpandtab tabstop=8 shiftwidth=8: */ diff --git a/libwacom/libwacom.h b/libwacom/libwacom.h index 7591f64..a07a8e8 100644 --- a/libwacom/libwacom.h +++ b/libwacom/libwacom.h @@ -34,6 +34,7 @@ #define _LIBWACOM_H_ /** @endcond */ +#include <stdint.h> /** @mainpage @@ -74,6 +75,8 @@ typedef struct _WacomDevice WacomDevice; +typedef struct _WacomMatch WacomMatch; + typedef struct _WacomStylus WacomStylus; typedef struct _WacomError WacomError; @@ -286,12 +289,21 @@ int libwacom_get_vendor_id(WacomDevice *device); /** * @param device The tablet to query - * @return The first match for the device in question + * @return The current match string used for this device (if set) or the first + * match string in the tablet definition. */ const char* libwacom_get_match(WacomDevice *device); /** * @param device The tablet to query + * @param nmatches The number of matches possible on this device. + * @return A pointer to the list of possible matches for this device. Do not + * modify this pointer or any content! + */ +WacomMatch** libwacom_get_matches(WacomDevice *device, int *nmatches); + +/** + * @param device The tablet to query * @return The numeric product ID for this device */ int libwacom_get_product_id(WacomDevice *device); @@ -457,6 +469,12 @@ int libwacom_stylus_has_lens (const WacomStylus *stylus); */ WacomStylusType libwacom_stylus_get_type (const WacomStylus *stylus); + +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); +const char* libwacom_match_get_match_string(const WacomMatch *match); + #endif /* _LIBWACOM_H_ */ /* vim: set noexpandtab tabstop=8 shiftwidth=8: */ diff --git a/libwacom/libwacomint.h b/libwacom/libwacomint.h index 6bdb6df..b910338 100644 --- a/libwacom/libwacomint.h +++ b/libwacom/libwacomint.h @@ -56,6 +56,13 @@ enum WacomFeature { FEATURE_REVERSIBLE = (1 << 5) }; +struct _WacomMatch { + char *match; + WacomBusType bus; + uint32_t vendor_id; + uint32_t product_id; +}; + /* WARNING: When adding new members to this struct * make sure to update libwacom_copy() ! */ struct _WacomDevice { @@ -63,12 +70,11 @@ struct _WacomDevice { int width; int height; - char *match; - uint32_t vendor_id; - uint32_t product_id; + int match; /* used match or first match by default */ + WacomMatch **matches; + int nmatches; WacomClass cls; - WacomBusType bus; int num_strips; uint32_t features; @@ -81,6 +87,8 @@ struct _WacomDevice { int num_buttons; WacomButtonFlags *buttons; + + int refcnt; /* for the db hashtable */ }; struct _WacomStylus { |