For Windows, it's better not to keep references for libusb_devices that are not used. So instead of makeing SpiceUsbDevice a box for a libusb_device it is going to be a box for a SpiceUsbDeviceInfo. --- gtk/usb-device-manager.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 145 insertions(+), 0 deletions(-) diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c index b39c2d4..c4cbc20 100644 --- a/gtk/usb-device-manager.c +++ b/gtk/usb-device-manager.c @@ -101,6 +101,16 @@ struct _SpiceUsbDeviceManagerPrivate { GPtrArray *channels; }; +typedef struct _SpiceUsbDeviceInfo { +#ifdef USE_USBREDIR + guint8 busnum; + guint8 devaddr; + guint16 vid; + guint16 pid; + int ref; +#endif +} SpiceUsbDeviceInfo; + #ifdef USE_USBREDIR static void channel_new(SpiceSession *session, SpiceChannel *channel, gpointer user_data); @@ -113,6 +123,12 @@ static void spice_usb_device_manager_uevent_cb(GUdevClient *client, static void spice_usb_device_manager_add_dev(SpiceUsbDeviceManager *self, GUdevDevice *udev); +static SpiceUsbDeviceInfo *spice_usb_device_set_info(libusb_device *libdev); +static SpiceUsbDevice *spice_usb_device_ref(SpiceUsbDevice *device); +static void spice_usb_device_unref(SpiceUsbDevice *device); + +static gboolean spice_usb_device_equal_libdev(SpiceUsbDevice *device, + libusb_device *libdev); G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device, (GBoxedCopyFunc)libusb_ref_device, (GBoxedFreeFunc)libusb_unref_device) @@ -1052,3 +1068,132 @@ gchar *spice_usb_device_get_description(SpiceUsbDevice *_device, const gchar *fo return NULL; #endif } + + + +#ifdef USE_USBREDIR +/* + * SpiceUsbDeviceInfo + */ +#ifdef __GNUC__ /* current implementation requires gcc */ +static int atomic_inc(int *a) +{ + return __sync_add_and_fetch (a, 1); +} +static int atomic_dec(int *a) +{ + return __sync_sub_and_fetch (a, 1); +} +#else /* not __GNUC__ ( and not atomic) */ +#error "atomic_inc and a atomic dec are only implemented for GNUC" +#endif /* __GNUC__ */ + +static SpiceUsbDeviceInfo *spice_usb_device_set_info(libusb_device *libdev) +{ + SpiceUsbDeviceInfo *info; + struct libusb_device_descriptor desc; + int errcode; + const gchar *errstr; + guint8 bus, addr; + + g_return_val_if_fail(libdev != NULL, NULL); + + bus = libusb_get_bus_number(libdev); + addr = libusb_get_device_address(libdev); + + errcode = libusb_get_device_descriptor(libdev, &desc); + if (errcode < 0) { + errstr = spice_usbutil_libusb_strerror(errcode); + g_warning("cannot get device descriptor for (%p) %d.%d -- %s(%d)", + libdev, bus, addr, errstr, errcode); + return NULL; + } + + info = g_new0(SpiceUsbDeviceInfo, 1); + + info->busnum = bus; + info->devaddr = addr; + info->vid = desc.idVendor; + info->pid = desc.idProduct; + info->ref = 1; + + return info; +} + +guint8 spice_usb_device_get_busnum(SpiceUsbDevice *device) +{ + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, 0); + + return info->busnum; +} + +guint8 spice_usb_device_get_devaddr(SpiceUsbDevice *device) +{ + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, 0); + + return info->devaddr; +} + +guint16 spice_usb_device_get_vid(SpiceUsbDevice *device) +{ + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, 0); + + return info->vid; +} + +guint16 spice_usb_device_get_pid(SpiceUsbDevice *device) +{ + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, 0); + + return info->pid; +} + +static SpiceUsbDevice *spice_usb_device_ref(SpiceUsbDevice *device) +{ + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + g_return_val_if_fail(info != NULL, NULL); + atomic_inc(&info->ref); + return device; +} + +static void spice_usb_device_unref(SpiceUsbDevice *device) +{ + int ref; + + SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device; + + g_return_if_fail(info != NULL); + + ref = atomic_dec(&info->ref); + if (ref == 0) { + memset(info, 0, sizeof(*info)); + g_free(info); + } +} + +static gboolean +spice_usb_device_equal_libdev(SpiceUsbDevice *device, + libusb_device *libdev) +{ + guint8 addr1, addr2, bus1, bus2; + + if ((device == NULL) || (libdev == NULL)) + return FALSE; + + bus1 = spice_usb_device_get_busnum(device); + addr1 = spice_usb_device_get_devaddr(device); + bus2 = libusb_get_bus_number(libdev); + addr2 = libusb_get_device_address(libdev); + + return ((bus1 == bus2) && (addr1 == addr2)); +} +#endif /* USE_USBREDIR */ -- 1.7.7.6 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel