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

Reply via email to