On Thu, 2012-04-19 at 13:07 +1000, Peter Hutterer wrote: > 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.hutte...@who-t.net>
Looks good. Reviewed-By: Bastien Nocera <had...@hadess.net> > --- > Changes since v1: > - libwacom_get_matches is constified > - libwacom_get_matches returns NULL-terminated array, no nmatches > - libwacom_copy_match explicitly copies fields > - refcounting through g_atomic_int_* > - g_realloc_n instead of realloc > - g_strsplit handling improved > > data/generate-udev-rules.c | 17 +++++-- > libwacom/libwacom-database.c | 66 ++++++++++++++++++------- > libwacom/libwacom.c | 110 > +++++++++++++++++++++++++++++++++++------- > libwacom/libwacom.h | 19 +++++++- > libwacom/libwacomint.h | 18 +++++-- > 5 files changed, 187 insertions(+), 43 deletions(-) > > diff --git a/data/generate-udev-rules.c b/data/generate-udev-rules.c > index 4c70fce..17d234b 100644 > --- a/data/generate-udev-rules.c > +++ b/data/generate-udev-rules.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,15 @@ static void print_udev_entry (WacomDevice *device) > } > } > > +static void print_udev_entry (WacomDevice *device) > +{ > + const WacomMatch **matches, **match; > + > + matches = libwacom_get_matches(device); > + for (match = matches; *match; match++) > + print_udev_entry_for_match(device, *match); > +} > + > static void print_udev_trailer (void) > { > printf ("\n"); > diff --git a/libwacom/libwacom-database.c b/libwacom/libwacom-database.c > index 2a0ee19..308ba6d 100644 > --- a/libwacom/libwacom-database.c > +++ b/libwacom/libwacom-database.c > @@ -122,21 +122,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; strs[i] != NULL; 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); > + > + libwacom_update_match(device, bus, vendor_id, product_id); > > - *bus = bus_from_str (busstr); > + if (nmatches == 0) { > + first_bus = bus; > + first_vendor_id = vendor_id; > + first_product_id = product_id; > + } > + nmatches++; > + } > > - return 1; > + /* 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 > @@ -298,18 +322,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); > @@ -358,17 +381,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) { > @@ -445,13 +468,22 @@ libwacom_database_new_for_path (const char *datadir) > nfiles = n; > while(n--) { > WacomDevice *d; > + const WacomMatch **matches, **match; > > 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); > + for (match = matches; *match; match++) { > + const char *matchstr; > + matchstr = libwacom_match_get_match_string(*match); > + 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 c16e4b5..09739a4 100644 > --- a/libwacom/libwacom.c > +++ b/libwacom/libwacom.c > @@ -172,20 +172,37 @@ bail: > return retval; > } > > +static WacomMatch *libwacom_copy_match(const WacomMatch *src) > +{ > + WacomMatch *dst; > + > + dst = g_new0(WacomMatch, 1); > + dst->match = g_strdup(src->match); > + dst->bus = src->bus; > + dst->vendor_id = src->vendor_id; > + dst->product_id = src->product_id; > + > + return dst; > +} > + > static WacomDevice * > libwacom_copy(const WacomDevice *device) > { > WacomDevice *d; > + int i; > > d = g_new0 (WacomDevice, 1); > + g_atomic_int_inc(&d->refcnt); > 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 + 1) * sizeof(WacomMatch*)); > + for (i = 0; i < d->nmatches; i++) > + d->matches[i] = libwacom_copy_match(device->matches[i]); > + d->matches[d->nmatches] = NULL; > + 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; > @@ -256,11 +273,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; > @@ -328,9 +347,18 @@ libwacom_new_from_name(WacomDeviceDatabase *db, const > char *name, WacomError *er > void > libwacom_destroy(WacomDevice *device) > { > + int i; > + > + if (!g_atomic_int_dec_and_test(&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); > @@ -339,16 +367,40 @@ 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->nmatches++; > + > + device->matches = g_realloc_n(device->matches, device->nmatches + 1, > sizeof(WacomMatch)); > + device->matches[device->nmatches] = NULL; > + 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) > @@ -358,14 +410,17 @@ 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; > +} > + > +const WacomMatch** libwacom_get_matches(WacomDevice *device) > +{ > + return (const WacomMatch**)device->matches; > } > > int libwacom_get_width(WacomDevice *device) > @@ -447,7 +502,7 @@ int libwacom_is_reversible(WacomDevice *device) > > WacomBusType libwacom_get_bustype(WacomDevice *device) > { > - return device->bus; > + return device->matches[device->match]->bus; > } > > WacomButtonFlags > @@ -519,4 +574,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 bdc12b0..26df3ab 100644 > --- a/libwacom/libwacom.h > +++ b/libwacom/libwacom.h > @@ -34,6 +34,7 @@ > #define _LIBWACOM_H_ > /** @endcond */ > > +#include <stdint.h> > /** > @mainpage > > @@ -79,6 +80,8 @@ > > typedef struct _WacomDevice WacomDevice; > > +typedef struct _WacomMatch WacomMatch; > + > typedef struct _WacomStylus WacomStylus; > > typedef struct _WacomError WacomError; > @@ -291,12 +294,20 @@ 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 > + * @return A pointer to the null-terminated list of possible matches for > this device. Do not > + * modify this pointer or any content! > + */ > +const WacomMatch** libwacom_get_matches(WacomDevice *device); > + > +/** > + * @param device The tablet to query > * @return The numeric product ID for this device > */ > int libwacom_get_product_id(WacomDevice *device); > @@ -464,6 +475,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 e759a0f..1ec0a39 100644 > --- a/libwacom/libwacomint.h > +++ b/libwacom/libwacomint.h > @@ -56,18 +56,26 @@ enum WacomFeature { > }; > > /* WARNING: When adding new members to this struct > + * make sure to update libwacom_copy_match() ! */ > +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 { > char *name; > 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; /* NULL-terminated */ > + int nmatches; /* not counting NULL-terminated element */ > > WacomClass cls; > - WacomBusType bus; > int num_strips; > uint32_t features; > > @@ -80,6 +88,8 @@ struct _WacomDevice { > > int num_buttons; > WacomButtonFlags *buttons; > + > + gint refcnt; /* for the db hashtable */ > }; > > struct _WacomStylus { ------------------------------------------------------------------------------ For Developers, A Lot Can Happen In A Second. Boundary is the first to Know...and Tell You. Monitor Your Applications in Ultra-Fine Resolution. Try it FREE! http://p.sf.net/sfu/Boundary-d2dvs2 _______________________________________________ Linuxwacom-devel mailing list Linuxwacom-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel