summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2012-03-29 12:14:18 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2012-03-29 14:37:30 +1000
commit1b1a730db6fd4f989eae5cac87aa057c71af994f (patch)
tree111b470db65677ea637d04cbf0d8f5de5339efb4
parent7e1e1e4f1a4379ec2e1568caaf5b6fc4b933c11e (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.c18
-rw-r--r--libwacom/libwacom-database.c68
-rw-r--r--libwacom/libwacom.c106
-rw-r--r--libwacom/libwacom.h20
-rw-r--r--libwacom/libwacomint.h16
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 {