On Tue, Sep 27, 2011 at 06:03:55PM -0700, Jason Gerecke wrote:
> Replaces several near-identical calls to XGetDeviceProperty with
> a single centralized function to do the same thing. The new '_get'
> function is responsible for reading the property from the server,
> verifying its format matches that which is intended, and returning
> a pointer to the requested piece.
> 
> Signed-off-by: Jason Gerecke <killert...@gmail.com>
> ---
>  tools/xsetwacom.c |  217 
> ++++++++++++++++++++++++++++++++++++-----------------
>  1 files changed, 147 insertions(+), 70 deletions(-)
> 
> diff --git a/tools/xsetwacom.c b/tools/xsetwacom.c
> index 7202b23..392b063 100644
> --- a/tools/xsetwacom.c
> +++ b/tools/xsetwacom.c
> @@ -101,6 +101,8 @@ typedef struct _param
>  
>  
>  /* get_func/set_func calls for special parameters */
> +static void* _get_property(Display *dpy, XDevice *dev, const char 
> *prop_name, int format, Atom type, unsigned long *items);
> +static void* _get(Display *dpy, XDevice *dev, const char *prop_name, int 
> prop_offset, int format, Atom type, int items);
>  static void map_actions(Display *dpy, XDevice *dev, param_t *param, int 
> argc, char **argv);
>  static void set_mode(Display *dpy, XDevice *dev, param_t *param, int argc, 
> char **argv);
>  static void get_mode(Display *dpy, XDevice *dev, param_t *param, int argc, 
> char **argv);
> @@ -1650,6 +1652,127 @@ out:
>       free(data);
>  }
>  
> +/**
> + * Obtains a property from the server. This function is a wrapper around
> + * XGetDeviceProperty which ensures that a pointer to the entire property
> + * data is returned, as well as verifying it has the expected type and
> + * format. If this function fails for any reason, *items will be zero and
> + * the function will return NULL.
> + *
> + * @param dpy        X11 display to connect to
> + * @param dev        Device to query
> + * @param prop_name  Name of device property
> + * @param format     Format of the property (8/16/32)
> + * @param type       Type of the property
> + * @param items      Number of 'format'-bit items successfully retrieved 
> from the server
> + * @return           Pointer to the requested data. Must be 'free()'-ed
> + */
> +static void* _get_property(Display *dpy, XDevice *dev, const char *prop_name,
> +                          int format, Atom type, unsigned long *items)

actually, if you want to make this really useful, you could return a union
in the form

union propdata {
        char *c;
        int *i;
        float *f;
};

and do the convertion to/fro the stupid property long format for 32-byte
properties. it would likely make the callers more clear too. see xinput's
src/property.c for an example.

Cheers,
  Peter


> +{
> +     int read_format, error;
> +     unsigned long read_items, bytes_after;
> +     Atom read_prop, read_type;
> +     unsigned char *read = NULL;
> +     void *data = NULL;
> +
> +     *items = 0;
> +
> +     read_prop = XInternAtom(dpy, prop_name, True);
> +     if (!read_prop || !test_property(dpy, dev, read_prop))
> +     {
> +             printf("Property '%s' does not exist on device.\n", prop_name);
> +             goto error;
> +     }
> +
> +     do
> +     {
> +             int offset = *items * format / 8;
> +             void *tmp;
> +
> +             error = XGetDeviceProperty(dpy, dev, read_prop, offset / 4, 1,
> +                                         False, AnyPropertyType, &read_type,
> +                                         &read_format, &read_items, 
> &bytes_after,
> +                                         &read);
> +
> +             if (error != 0)
> +             {
> +                     fprintf(stderr, "   %-23s = XGetDeviceProperty error 
> %d\n",
> +                             prop_name, error);
> +                     XFree(read);
> +                     goto error;
> +             }
> +             else if (format != read_format || type != read_type)
> +             {
> +                     fprintf(stderr, "   %-23s = property mismatch: expected 
> type %d, format %d; got type %d, format %d\n",
> +                             prop_name, format, type, read_format, 
> read_type);
> +                     XFree(read);
> +                     goto error;
> +             }
> +
> +             *items += read_items;
> +             tmp = realloc(data, *items * format / 8);
> +             if (tmp == NULL)
> +             {
> +                     fprintf(stderr, "Unable to allocate memory.\n");
> +                     XFree(read);
> +                     goto error;
> +             }
> +             else
> +             {
> +                     data = tmp;
> +                     memcpy(&data[offset], read, read_items * format / 8);
> +                     XFree(read);
> +             }
> +     }
> +     while (bytes_after > 0);
> +     return data;
> +
> +error:
> +     free(data);
> +     *items = 0;
> +     return NULL;
> +}
> +
> +/**
> + * Obtains sub-values from a specified server property. This function
> + * relies on '_get_property' to verify the type and format match what
> + * is expected. If this function fails for any reason, the function
> + * will return NULL.
> + *
> + * @param dpy          X11 display to connect to
> + * @param dev          Device to query
> + * @param prop_name    Name of device property
> + * @param prop_offset  Offset (in items) to begin reading
> + * @param format       Format of the underlying property (8/16/32)
> + * @param type         Type of the underlying property
> + * @param items        Number of items to read
> + * @return             Pointer to the requested data; must be 'free()'-ed
> + */
> +static void* _get(Display *dpy, XDevice *dev, const char *prop_name, int 
> prop_offset,
> +                  int format, Atom type, int items)
> +{
> +     unsigned long read_items;
> +     void *read, *data;
> +
> +     read = _get_property(dpy, dev, prop_name, format, type, &read_items);
> +     if (read == NULL)
> +             return NULL;
> +
> +     if (items > prop_offset + read_items)
> +     {
> +             fprintf(stderr, "   %-23s = count mismatch: expected at least 
> %d got %d\n",
> +                     prop_name, items, read_items);
> +             free(read);
> +             return NULL;
> +     }
> +
> +     data = malloc(items * format / 8);
> +     memcpy(data, read + (prop_offset * format / 8), items * format / 8);
> +     free(read);
> +     return data;
> +}
> +
>  static void get_mode(Display *dpy, XDevice *dev, param_t* param, int argc, 
> char **argv)
>  {
>       XDeviceInfo *info, *d = NULL;
> @@ -1689,10 +1812,7 @@ static void get_mode(Display *dpy, XDevice *dev, 
> param_t* param, int argc, char
>  static void get_rotate(Display *dpy, XDevice *dev, param_t* param, int argc, 
> char **argv)
>  {
>       char *rotation = NULL;
> -     Atom prop, type;
> -     int format;
> -     unsigned char* data;
> -     unsigned long nitems, bytes_after;
> +     char *data;
>  
>       if (argc != 0)
>       {
> @@ -1700,25 +1820,12 @@ static void get_rotate(Display *dpy, XDevice *dev, 
> param_t* param, int argc, cha
>               return;
>       }
>  
> -     prop = XInternAtom(dpy, param->prop_name, True);
> -     if (!prop)
> -     {
> -             fprintf(stderr, "Property for '%s' not available.\n",
> -                     param->name);
> -             return;
> -     }
> -
>       TRACE("Getting rotation for device %ld.\n", dev->device_id);
>  
> -     XGetDeviceProperty(dpy, dev, prop, 0, 1000, False, AnyPropertyType,
> -                             &type, &format, &nitems, &bytes_after, &data);
> -
> -     if (nitems == 0 || format != 8)
> -     {
> -             fprintf(stderr, "Property for '%s' has no or wrong value - this 
> is a bug.\n",
> -                     param->name);
> +     data = _get(dpy, dev, param->prop_name, param->prop_offset, 
> param->prop_format,
> +                 param->prop_type, param->arg_count);
> +     if (data == NULL)
>               return;
> -     }
>  
>       switch(*data)
>       {
> @@ -1737,7 +1844,7 @@ static void get_rotate(Display *dpy, XDevice *dev, 
> param_t* param, int argc, cha
>       }
>  
>       print_value(param, "%s", rotation);
> -
> +     free(data);
>       return;
>  }
>  
> @@ -1858,36 +1965,14 @@ static int get_actions(Display *dpy, XDevice *dev,
>   */
>  static int get_button(Display *dpy, XDevice *dev, param_t *param, int offset)
>  {
> -     Atom prop, type;
> -     int format;
> -     unsigned long nitems, bytes_after;
> -     unsigned char *data;
> -
> -     prop = XInternAtom(dpy, param->prop_name, True);
> -
> -     if (!prop)
> -             return 0;
> -
> -     XGetDeviceProperty(dpy, dev, prop, 0, 100, False,
> -                        AnyPropertyType, &type, &format, &nitems,
> -                        &bytes_after, (unsigned char**)&data);
> -
> -     if (offset >= nitems)
> -     {
> -             XFree(data);
> -             return 0;
> -     }
> +     unsigned char *data = _get(dpy, dev, param->prop_name, offset,
> +                                8, XA_INTEGER, 1);
>  
> -     prop = data[offset];
> -     XFree(data);
> -
> -     if (format != 8 || type != XA_INTEGER || !prop)
> -     {
> +     if (data == NULL)
>               return 0;
> -     }
> -
> -     print_value(param, "%d", prop);
>  
> +     print_value(param, "%d", *data);
> +     free(data);
>       return 1;
>  }
>  
> @@ -1904,6 +1989,7 @@ static int get_button(Display *dpy, XDevice *dev, 
> param_t *param, int offset)
>   */
>  static void get_map(Display *dpy, XDevice *dev, param_t *param, int argc, 
> char** argv)
>  {
> +     Atom prop;
>       int offset = param->prop_offset;
>  
>       TRACE("Getting button map for device %ld.\n", dev->device_id);
> @@ -1928,6 +2014,14 @@ static void get_map(Display *dpy, XDevice *dev, 
> param_t *param, int argc, char**
>               argv = &argv[1]; /*... ditto ...                        */
>       }
>  
> +     prop = XInternAtom(dpy, param->prop_name, True);
> +     if (!prop || !test_property(dpy, dev, prop))
> +     {
> +             printf("Property '%s' does not exist on device.\n",
> +                    param->prop_name);
> +             return;
> +     }
> +
>  
>       if (get_actions(dpy, dev, param, offset))
>               return;
> @@ -2438,24 +2532,11 @@ static void get(Display *dpy, enum printformat 
> printformat, int argc, char **arg
>  
>  static void get_param(Display *dpy, XDevice *dev, param_t *param, int argc, 
> char **argv)
>  {
> -     Atom prop = None, type;
> -     int format;
> +     Atom prop = None;
>       unsigned char* data;
> -     unsigned long nitems, bytes_after;
>       int i;
>       char str[100] = {0};
>  
> -     if (param->prop_name)
> -     {
> -             prop = XInternAtom(dpy, param->prop_name, True);
> -             if (!prop || !test_property(dpy, dev, prop))
> -             {
> -                     printf("Property '%s' does not exist on device.\n",
> -                             param->prop_name);
> -                     return;
> -             }
> -     }
> -
>       if (param->get_func)
>       {
>               TRACE("custom get func for param\n");
> @@ -2463,16 +2544,12 @@ static void get_param(Display *dpy, XDevice *dev, 
> param_t *param, int argc, char
>               return;
>       }
>  
> +     TRACE("Getting property %s, offset %d\n", param->prop_name, 
> param->prop_offset);
>  
> -     TRACE("Getting property %ld, offset %d\n", prop, param->prop_offset);
> -     XGetDeviceProperty(dpy, dev, prop, 0, 1000, False, AnyPropertyType,
> -                             &type, &format, &nitems, &bytes_after, &data);
> -
> -     if (nitems <= param->prop_offset)
> -     {
> -             fprintf(stderr, "Property offset doesn't exist.\n");
> +     data = data = _get(dpy, dev, param->prop_name, param->prop_offset, 
> param->prop_format,
> +                        param->prop_type, param->arg_count);
> +     if (data == NULL)
>               return;
> -     }
>  
>       for (i = 0; i < param->arg_count; i++)
>       {
> -- 
> 1.7.6
> 
> 
> ------------------------------------------------------------------------------
> All the data continuously generated in your IT infrastructure contains a
> definitive record of customers, application performance, security
> threats, fraudulent activity and more. Splunk takes this data and makes
> sense of it. Business sense. IT sense. Common sense.
> http://p.sf.net/sfu/splunk-d2dcopy1
> _______________________________________________
> Linuxwacom-devel mailing list
> Linuxwacom-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel
> 

------------------------------------------------------------------------------
All the data continuously generated in your IT infrastructure contains a
definitive record of customers, application performance, security
threats, fraudulent activity and more. Splunk takes this data and makes
sense of it. Business sense. IT sense. Common sense.
http://p.sf.net/sfu/splunk-d2dcopy1
_______________________________________________
Linuxwacom-devel mailing list
Linuxwacom-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxwacom-devel

Reply via email to