[Spice-devel] [spice-gtk Win32 v3 07/12] Windows mingw: usb: implement GUdevDevice & GUdevClient for windows

Uri Lublin uril at redhat.com
Thu Jun 28 08:07:32 PDT 2012


On 06/28/2012 04:36 PM, Arnon Gilboa wrote:
> reviewed most of it before;) but added some comments for your changes 
> below.
>
> Uri Lublin wrote:
>> From: Arnon Gilboa <agilboa at redhat.com>
>>
>>
>> +struct _GUdevDevicePrivate
>> +{
>> +    /* FixMe: move above fields to this structure and access them 
>> directly */
> it will cleanup some code as well, remove the g_new0/g_free calls.

Agreed. Disclaimer: dropping GUdevDeviceInfo is Arnon's idea.

>
> you will also find it nice to merge get_usb_dev_info into 
> g_udev_device_new, so it will be
>
> static GUdevDevice *g_udev_device_new(libusb_device *dev, 
> GUdevDeviceInfo *udevinfo);

Without the udevinfo.


>>
>> +/*
>> + * devs [in,out] an empty devs list in, full devs list out
>> + * Returns: number-of-devices, or a negative value on error.
>> + */
>> +static ssize_t
>> +g_udev_client_list_devices(GUdevClient *self, GList **devs,
>> +                           GError **err, const gchar *name)
>> +{
> is it really required to have err & name params?

It's not required.

>> +    gssize rc;
>> +    libusb_device **lusb_list, **dev;
>> +    GUdevClientPrivate *priv;
>> +    GUdevDeviceInfo *udevinfo;
>> +    GUdevDevice *udevice;
>> +    ssize_t n;
>> +
>> +    g_return_val_if_fail(G_UDEV_IS_CLIENT(self), -1);
>> +    g_return_val_if_fail(devs != NULL, -2);
>> +
>> +    priv = self->priv;
>> +
>> +    g_return_val_if_fail(self->priv->ctx != NULL, -3);
>> +
>> +    rc = libusb_get_device_list(priv->ctx, &lusb_list);
>> +    if (rc < 0) {
>> +        const char *errstr = spice_usbutil_libusb_strerror(rc);
>> +        g_warning("%s: libusb_get_device_list failed", name);
>> +        g_set_error(err, G_UDEV_CLIENT_ERROR, 
>> G_UDEV_CLIENT_LIBUSB_FAILED,
>> +                    "%s: Error getting device list from libusb: %s 
>> [%i]",
>> +                    name, errstr, rc);
>> +        return -4;
>> +    }
>> +
>> +    n = rc;
>> +
>> +    for (dev = lusb_list; *dev; dev++) {
>> +        udevinfo = g_new0(GUdevDeviceInfo, 1);
>> +        get_usb_dev_info(*dev, udevinfo);
>> +        udevice = g_udev_device_new(udevinfo);
>> +        *devs = g_list_prepend(*devs, udevice);
>> +    }
>> +    libusb_free_device_list(lusb_list, 1);
>> +
>> +    return n;
>> +}
> I personally don't like these return codes.
>> +
>> +static void g_udev_client_free_device_list(GList **devs)
>> +{
>> +    g_return_if_fail(devs != NULL);
>> +    if (*devs) {
>> +        g_list_free_full(*devs, g_object_unref);
>> +        *devs = NULL;
>> +    }
>> +}
>> +
>> +

>> +
>> +static gboolean get_usb_dev_info(libusb_device *dev, GUdevDeviceInfo 
>> *udevinfo)
>> +{
>> +    struct libusb_device_descriptor desc;
>> +
>> +    g_return_val_if_fail(dev, FALSE);
>> +    g_return_val_if_fail(udevinfo, FALSE);
>> +
>> +    if (libusb_get_device_descriptor(dev, &desc) < 0) {
>> +        g_warning("cannot get device descriptor %p", dev);
>> +        return FALSE;
>> +    }
>> +
>> +    udevinfo->bus   = libusb_get_bus_number(dev);
>> +    udevinfo->addr  = libusb_get_device_address(dev);
>> +    udevinfo->class = desc.bDeviceClass;
>> +    udevinfo->vid   = desc.idVendor;
>> +    udevinfo->pid   = desc.idProduct;
>> +    snprintf(udevinfo->sclass, sizeof(udevinfo->sclass), "%d", 
>> udevinfo->class);
>> +    snprintf(udevinfo->sbus,   sizeof(udevinfo->sbus),   "%d", 
>> udevinfo->bus);
>> +    snprintf(udevinfo->saddr,  sizeof(udevinfo->saddr),  "%d", 
>> udevinfo->addr);
>> +    return TRUE;
>> +}
>> +
>> +#define INT_RETURN_IF_DIFFERENT(x, y) \
>> +    do { gint c,d; c=(x); d=(y); if(c-d) return (c-d); } while(0)
>> +
> funny macro;) I prefer removing it and simply using if (a - b) return 
> FALSE;

You mean if (a-b) return (a-b);
That's what the macro does, except it first cast  x,y  to gint type.

>> +static gint gudev_device_compare(GUdevDevice *a, GUdevDevice *b)
> gboolean return might be nicer

Compare usually returns an int (<0, =0 , >0 values).
This makes the function usable by sort.
(I thought of sorting and break out of the loop sooner, but I think it's not
worth it, as the expected list length is pretty small).

>> +{
>> +    GUdevDeviceInfo *ai, *bi;
>> +
>> +    g_return_val_if_fail(G_UDEV_DEVICE(a), 1);
>> +    g_return_val_if_fail(G_UDEV_DEVICE(b), -1);
>> +
>> +    ai = a->priv->udevinfo;
>> +    bi = b->priv->udevinfo;
>> +
>> +    INT_RETURN_IF_DIFFERENT(ai->bus, bi->bus);
>> +    INT_RETURN_IF_DIFFERENT(ai->addr, bi->addr);
>> +    INT_RETURN_IF_DIFFERENT(ai->vid, bi->vid);
>> +    INT_RETURN_IF_DIFFERENT(ai->pid, bi->pid);
>> +
>> +    return 0;
> return TRUE;

That works too, but needs to rename the function (Equal?).

>> +    if (is_dev_change > 0) {
>> +        llist  = now_devs;
>> +        slist = priv->udev_list;
>> +    } else {
>> +        llist = priv->udev_list;
>> +        slist  = now_devs;
>> +    }
>> +
>> +    g_udev_device_print_list(llist, "handle_dev_change: long list:");
>> +    g_udev_device_print_list(slist, "handle_dev_change: short list:");
> do we still need these debug lines?

Only if we want to debug the lists. In that case one would
have to define DEBUG_GUDEV_DEVICE_LISTS above.
When DEBUG_GUDEV_DEVICE_LISTS is not defined these lines are empty.

>
>> +
>> +#ifdef DEBUG_GUDEV_DEVICE_LISTS
>> +static void g_udev_device_print_list(GList *l, const gchar *msg)
>> +{
>> +    GList *it;
>> +
>> +    for (it = g_list_first(l); it != NULL; it=g_list_next(it)) {
>> +        g_udev_device_print(it->data, msg);
>> +    }
>> +}
>> +#endif
> still need it?

Answered above.

>> diff --git a/gtk/win-usb-dev.h b/gtk/win-usb-dev.h
>> +
>> +typedef struct _SpiceUsbDeviceManager SpiceUsbDeviceManager;
> any reason we need to know SpiceUsbDeviceManager here?

No. I'll remove it.


Thanks,
     Uri.



More information about the Spice-devel mailing list