[Spice-devel] [PATCH v2 2/2] UsbDk: Add UsbDk as a default backend
Kirill Moizik
kirill at daynix.com
Tue Jun 9 05:53:02 PDT 2015
From: Kirill Moizik <kirillm at daynix.com>
Backend is chosen dynamically, if UsbDk is not installed, then WinUsb/usbclerk
will be chosen.
Signed-off-by: Kirill Moizik <kirillm at daynix.com>
---
src/usb-device-manager.c | 297 +++++++++++++++++++++++++++++++++--------------
1 file changed, 208 insertions(+), 89 deletions(-)
diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
index 12ad4ba..3e2a679 100644
--- a/src/usb-device-manager.c
+++ b/src/usb-device-manager.c
@@ -29,6 +29,10 @@
#include <errno.h>
#include <libusb.h>
+#ifdef G_OS_WIN32
+#include "usbdk_api.h"
+#endif
+
#if defined(USE_GUDEV)
#include <gudev/gudev.h>
#elif defined(G_OS_WIN32)
@@ -121,6 +125,9 @@ struct _SpiceUsbDeviceManagerPrivate {
libusb_hotplug_callback_handle hp_handle;
#endif
#ifdef G_OS_WIN32
+ usbdk_api_wrapper *usbdk_api;
+ HANDLE usbdk_hider_handle;
+ gboolean use_usbclerk;
SpiceWinUsbDriver *installer;
#endif
#endif
@@ -185,7 +192,8 @@ static void spice_usb_device_set_state(SpiceUsbDevice *device, guint8 s);
#endif
static gboolean spice_usb_device_equal_libdev(SpiceUsbDevice *device,
- libusb_device *libdev);
+ libusb_device *libdev,
+ gboolean use_usbclerk);
static libusb_device *
spice_usb_device_manager_device_to_libdev(SpiceUsbDeviceManager *self,
SpiceUsbDevice *device);
@@ -219,6 +227,16 @@ static void spice_usb_device_manager_init(SpiceUsbDeviceManager *self)
priv = SPICE_USB_DEVICE_MANAGER_GET_PRIVATE(self);
self->priv = priv;
+#ifdef G_OS_WIN32
+ priv->use_usbclerk = !usbdk_is_driver_installed();
+ if (!priv->use_usbclerk) {
+ if (usbdk_api_load(&priv->usbdk_api) != 0) {
+ priv->use_usbclerk = TRUE;
+ usbdk_api_unload(priv->usbdk_api);
+ SPICE_DEBUG("Failed to load UsbDk API DLL");
+ }
+ }
+#endif
priv->channels = g_ptr_array_new();
#ifdef USE_USBREDIR
priv->devices = g_ptr_array_new_with_free_func((GDestroyNotify)
@@ -351,14 +369,25 @@ static void spice_usb_device_manager_finalize(GObject *gobject)
free(priv->auto_conn_filter_rules);
free(priv->redirect_on_connect_rules);
#ifdef G_OS_WIN32
- if (priv->installer)
+ if (priv->installer) {
+ g_warn_if_fail(priv->use_usbclerk);
g_object_unref(priv->installer);
+ }
#endif
#endif
g_free(priv->auto_connect_filter);
g_free(priv->redirect_on_connect);
+#ifdef G_OS_WIN32
+ if (!priv->use_usbclerk) {
+ if (priv->usbdk_hider_handle != NULL) {
+ usbdk_clear_hide_rules(priv->usbdk_api, priv->usbdk_hider_handle);
+ usbdk_close_hider_handle(priv->usbdk_api, priv->usbdk_hider_handle);
+ }
+ usbdk_api_unload(priv->usbdk_api);
+ }
+#endif
/* Chain up to the parent class */
if (G_OBJECT_CLASS(spice_usb_device_manager_parent_class)->finalize)
G_OBJECT_CLASS(spice_usb_device_manager_parent_class)->finalize(gobject);
@@ -396,6 +425,13 @@ static void spice_usb_device_manager_get_property(GObject *gobject,
}
}
+#ifdef G_OS_WIN32
+static
+void _usbdk_autoredir_enable(SpiceUsbDeviceManager *manager);
+static
+void _usbdk_autoredir_disable(SpiceUsbDeviceManager *manager);
+#endif
+
static void spice_usb_device_manager_set_property(GObject *gobject,
guint prop_id,
const GValue *value,
@@ -410,6 +446,15 @@ static void spice_usb_device_manager_set_property(GObject *gobject,
break;
case PROP_AUTO_CONNECT:
priv->auto_connect = g_value_get_boolean(value);
+#ifdef G_OS_WIN32
+ if (!priv->use_usbclerk) {
+ if (priv->auto_connect) {
+ _usbdk_autoredir_enable(self);
+ } else {
+ _usbdk_autoredir_disable(self);
+ }
+ }
+#endif
break;
case PROP_AUTO_CONNECT_FILTER: {
const gchar *filter = g_value_get_string(value);
@@ -639,19 +684,20 @@ static void spice_usb_device_manager_class_init(SpiceUsbDeviceManagerClass *klas
#ifdef USE_GUDEV
static gboolean spice_usb_device_manager_get_udev_bus_n_address(
- GUdevDevice *udev, int *bus, int *address)
+ GUdevDevice *udev, int *bus, int *address, gboolean use_usbclerk)
{
const gchar *bus_str, *address_str;
*bus = *address = 0;
-#ifndef G_OS_WIN32
- bus_str = g_udev_device_get_property(udev, "BUSNUM");
- address_str = g_udev_device_get_property(udev, "DEVNUM");
-#else /* Windows -- request vid:pid instead */
- bus_str = g_udev_device_get_property(udev, "VID");
- address_str = g_udev_device_get_property(udev, "PID");
-#endif
+ if (!use_usbclerk) {/* Linux or UsbDk backend on Windows*/
+ bus_str = g_udev_device_get_property(udev, "BUSNUM");
+ address_str = g_udev_device_get_property(udev, "DEVNUM");
+ }
+ else { /* Windows WinUsb/UsbClerk -- request vid:pid instead */
+ bus_str = g_udev_device_get_property(udev, "VID");
+ address_str = g_udev_device_get_property(udev, "PID");
+ }
if (bus_str)
*bus = atoi(bus_str);
if (address_str)
@@ -788,19 +834,26 @@ static void spice_usb_device_manager_auto_connect_cb(GObject *gobject,
spice_usb_device_unref(device);
}
-#ifndef G_OS_WIN32 /* match functions for Linux -- match by bus.addr */
static gboolean
spice_usb_device_manager_device_match(SpiceUsbDevice *device,
- const int bus, const int address)
+ const int vid, const int pid, gboolean use_usbclerk)
{
- return (spice_usb_device_get_busnum(device) == bus &&
- spice_usb_device_get_devaddr(device) == address);
+ if (use_usbclerk) {
+ return (spice_usb_device_get_vid(device) == vid &&
+ spice_usb_device_get_pid(device) == pid);
+ }
+ else {
+ return (spice_usb_device_get_busnum(device) == vid &&
+ spice_usb_device_get_devaddr(device) == pid);
+ }
+ return TRUE;
}
+#ifndef G_OS_WIN32 /* match functions for Linux -- match by bus.addr */
#ifdef USE_GUDEV
static gboolean
spice_usb_device_manager_libdev_match(libusb_device *libdev,
- const int bus, const int address)
+ const int bus, const int address, gboolean use_usbclerk)
{
return (libusb_get_bus_number(libdev) == bus &&
libusb_get_device_address(libdev) == address);
@@ -809,23 +862,22 @@ spice_usb_device_manager_libdev_match(libusb_device *libdev,
#else /* Win32 -- match functions for Windows -- match by vid:pid */
static gboolean
-spice_usb_device_manager_device_match(SpiceUsbDevice *device,
- const int vid, const int pid)
-{
- return (spice_usb_device_get_vid(device) == vid &&
- spice_usb_device_get_pid(device) == pid);
-}
-
-static gboolean
spice_usb_device_manager_libdev_match(libusb_device *libdev,
- const int vid, const int pid)
+ const int vid, const int pid, gboolean use_usbclerk)
{
- int vid2, pid2;
+ if (use_usbclerk) {
+ int vid2, pid2;
- if (!spice_usb_device_manager_get_libdev_vid_pid(libdev, &vid2, &pid2)) {
- return FALSE;
+ if (!spice_usb_device_manager_get_libdev_vid_pid(libdev, &vid2, &pid2)) {
+ return FALSE;
+ }
+ return (vid == vid2 && pid == pid2);
+ }
+ else {
+ return (libusb_get_bus_number(libdev) == vid &&
+ libusb_get_device_address(libdev) == pid);
}
- return (vid == vid2 && pid == pid2);
+ return TRUE;
}
#endif /* of Win32 -- match functions */
@@ -839,7 +891,7 @@ spice_usb_device_manager_find_device(SpiceUsbDeviceManager *self,
for (i = 0; i < priv->devices->len; i++) {
curr = g_ptr_array_index(priv->devices, i);
- if (spice_usb_device_manager_device_match(curr, bus, address)) {
+ if (spice_usb_device_manager_device_match(curr, bus, address, priv->use_usbclerk)) {
device = curr;
break;
}
@@ -903,12 +955,14 @@ static void spice_usb_device_manager_remove_dev(SpiceUsbDeviceManager *self,
}
#ifdef G_OS_WIN32
- const guint8 state = spice_usb_device_get_state(device);
- if ((state == SPICE_USB_DEVICE_STATE_INSTALLING) ||
- (state == SPICE_USB_DEVICE_STATE_UNINSTALLING)) {
- SPICE_DEBUG("skipping " DEV_ID_FMT ". It is un/installing its driver",
- bus, address);
- return;
+ if (priv->use_usbclerk) {
+ const guint8 state = spice_usb_device_get_state(device);
+ if ((state == SPICE_USB_DEVICE_STATE_INSTALLING) ||
+ (state == SPICE_USB_DEVICE_STATE_UNINSTALLING)) {
+ SPICE_DEBUG("skipping " DEV_ID_FMT ". It is un/installing its driver",
+ bus, address);
+ return;
+ }
}
#endif
@@ -936,7 +990,7 @@ static void spice_usb_device_manager_add_udev(SpiceUsbDeviceManager *self,
if (!devtype || strcmp(devtype, "usb_device"))
return;
- if (!spice_usb_device_manager_get_udev_bus_n_address(udev, &bus, &address)) {
+ if (!spice_usb_device_manager_get_udev_bus_n_address(udev, &bus, &address, self->priv->use_usbclerk)) {
g_warning("USB device without bus number or device address");
return;
}
@@ -957,7 +1011,7 @@ static void spice_usb_device_manager_add_udev(SpiceUsbDeviceManager *self,
libusb_get_device_list(priv->context, &dev_list);
for (i = 0; dev_list && dev_list[i]; i++) {
- if (spice_usb_device_manager_libdev_match(dev_list[i], bus, address)) {
+ if (spice_usb_device_manager_libdev_match(dev_list[i], bus, address, priv->use_usbclerk)) {
libdev = dev_list[i];
break;
}
@@ -978,7 +1032,7 @@ static void spice_usb_device_manager_remove_udev(SpiceUsbDeviceManager *self,
{
int bus, address;
- if (!spice_usb_device_manager_get_udev_bus_n_address(udev, &bus, &address))
+ if (!spice_usb_device_manager_get_udev_bus_n_address(udev, &bus, &address, self->priv->use_usbclerk))
return;
spice_usb_device_manager_remove_dev(self, bus, address);
@@ -1106,6 +1160,7 @@ static void spice_usb_device_manager_drv_install_cb(GObject *gobject,
g_free(cbinfo);
g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
+ g_return_if_fail(self->priv->use_usbclerk);
g_return_if_fail(SPICE_IS_WIN_USB_DRIVER(installer));
g_return_if_fail(device!= NULL);
@@ -1138,6 +1193,7 @@ static void spice_usb_device_manager_drv_uninstall_cb(GObject *gobject,
SPICE_DEBUG("Win USB driver uninstall finished");
g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
+ g_return_if_fail(self->priv->use_usbclerk);
if (!spice_win_usb_driver_uninstall_finish(cbinfo->installer, res, &err)) {
g_warning("win usb driver uninstall failed -- %s", err->message);
@@ -1281,7 +1337,7 @@ static SpiceUsbredirChannel *spice_usb_device_manager_get_channel_for_dev(
for (i = 0; i < priv->channels->len; i++) {
SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i);
libusb_device *libdev = spice_usbredir_channel_get_device(channel);
- if (spice_usb_device_equal_libdev(device, libdev))
+ if (spice_usb_device_equal_libdev(device, libdev, priv->use_usbclerk))
return channel;
}
#endif
@@ -1470,25 +1526,35 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
{
#if defined(USE_USBREDIR) && defined(G_OS_WIN32)
- SpiceWinUsbDriver *installer;
- UsbInstallCbInfo *cbinfo;
- g_return_if_fail(self->priv->installer);
+ if (self->priv->use_usbclerk) {
+ SpiceWinUsbDriver *installer;
+ UsbInstallCbInfo *cbinfo;
- spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_INSTALLING);
+ g_return_if_fail(self->priv->installer);
- installer = self->priv->installer;
- cbinfo = g_new0(UsbInstallCbInfo, 1);
- cbinfo->manager = self;
- cbinfo->device = spice_usb_device_ref(device);
- cbinfo->installer = installer;
- cbinfo->cancellable = cancellable;
- cbinfo->callback = callback;
- cbinfo->user_data = user_data;
+ spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_INSTALLING);
- spice_win_usb_driver_install_async(installer, device, cancellable,
- spice_usb_device_manager_drv_install_cb,
- cbinfo);
+ installer = self->priv->installer;
+ cbinfo = g_new0(UsbInstallCbInfo, 1);
+ cbinfo->manager = self;
+ cbinfo->device = spice_usb_device_ref(device);
+ cbinfo->installer = installer;
+ cbinfo->cancellable = cancellable;
+ cbinfo->callback = callback;
+ cbinfo->user_data = user_data;
+
+ spice_win_usb_driver_install_async(installer, device, cancellable,
+ spice_usb_device_manager_drv_install_cb,
+ cbinfo);
+ }
+ else {
+ _spice_usb_device_manager_connect_device_async(self,
+ device,
+ cancellable,
+ callback,
+ user_data);
+ }
#else
_spice_usb_device_manager_connect_device_async(self,
device,
@@ -1536,30 +1602,32 @@ void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *self,
spice_usbredir_channel_disconnect_device(channel);
#ifdef G_OS_WIN32
- SpiceWinUsbDriver *installer;
- UsbInstallCbInfo *cbinfo;
- guint8 state;
-
- g_warn_if_fail(device != NULL);
- g_return_if_fail(self->priv->installer);
-
- state = spice_usb_device_get_state(device);
- if ((state != SPICE_USB_DEVICE_STATE_INSTALLED) &&
- (state != SPICE_USB_DEVICE_STATE_CONNECTED)) {
- return;
- }
+ if (self->priv->use_usbclerk) {
+ SpiceWinUsbDriver *installer;
+ UsbInstallCbInfo *cbinfo;
+ guint8 state;
+
+ g_warn_if_fail(device != NULL);
+ g_warn_if_fail(self->priv->installer != NULL);
+
+ state = spice_usb_device_get_state(device);
+ if ((state != SPICE_USB_DEVICE_STATE_INSTALLED) &&
+ (state != SPICE_USB_DEVICE_STATE_CONNECTED)) {
+ return;
+ }
- spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_UNINSTALLING);
+ spice_usb_device_set_state(device, SPICE_USB_DEVICE_STATE_UNINSTALLING);
- installer = self->priv->installer;
- cbinfo = g_new0(UsbInstallCbInfo, 1);
- cbinfo->manager = self;
- cbinfo->device = spice_usb_device_ref(device);
- cbinfo->installer = installer;
+ installer = self->priv->installer;
+ cbinfo = g_new0(UsbInstallCbInfo, 1);
+ cbinfo->manager = self;
+ cbinfo->device = spice_usb_device_ref(device);
+ cbinfo->installer = installer;
- spice_win_usb_driver_uninstall_async(installer, device, NULL,
- spice_usb_device_manager_drv_uninstall_cb,
- cbinfo);
+ spice_win_usb_driver_uninstall_async (installer, device, NULL,
+ spice_usb_device_manager_drv_uninstall_cb,
+ cbinfo);
+ }
#endif
#endif
@@ -1792,6 +1860,36 @@ guint8 spice_usb_device_get_state(SpiceUsbDevice *device)
return info->state;
}
+static
+void _usbdk_autoredir_enable(SpiceUsbDeviceManager *manager)
+{
+ SpiceUsbDeviceManagerPrivate *priv = manager->priv;
+
+ if (priv->redirect_on_connect == NULL) {
+ SPICE_DEBUG("No autoredirect rules, no hider setup needed");
+ return;
+ }
+
+ priv->usbdk_hider_handle = usbdk_create_hider_handle(priv->usbdk_api);
+ if (priv->usbdk_hider_handle == NULL) {
+ SPICE_DEBUG("Failed to instanciate UsbDk interface");
+ return;
+ }
+ usbdk_api_set_hide_rules(priv->usbdk_api, priv->usbdk_hider_handle, priv->redirect_on_connect);
+}
+
+static
+void _usbdk_autoredir_disable(SpiceUsbDeviceManager *manager)
+{
+ SpiceUsbDeviceManagerPrivate *priv = manager->priv;
+ g_return_if_fail(!priv->use_usbclerk);
+
+ if (priv->usbdk_hider_handle != NULL) {
+ usbdk_clear_hide_rules(priv->usbdk_api, priv->usbdk_hider_handle);
+ usbdk_close_hider_handle(priv->usbdk_api, priv->usbdk_hider_handle);
+ priv->usbdk_hider_handle = NULL;
+ }
+}
#endif
static SpiceUsbDevice *spice_usb_device_ref(SpiceUsbDevice *device)
@@ -1823,7 +1921,7 @@ static void spice_usb_device_unref(SpiceUsbDevice *device)
#ifndef G_OS_WIN32 /* Linux -- directly compare libdev */
static gboolean
spice_usb_device_equal_libdev(SpiceUsbDevice *device,
- libusb_device *libdev)
+ libusb_device *libdev, gboolean use_usbclerk)
{
SpiceUsbDeviceInfo *info = (SpiceUsbDeviceInfo *)device;
@@ -1835,21 +1933,37 @@ spice_usb_device_equal_libdev(SpiceUsbDevice *device,
#else /* Windows -- compare vid:pid of device and libdev */
static gboolean
spice_usb_device_equal_libdev(SpiceUsbDevice *device,
- libusb_device *libdev)
+ libusb_device *libdev, gboolean use_usbclerk)
{
- int vid1, vid2, pid1, pid2;
+ if (use_usbclerk) {
+ int vid1, vid2, pid1, pid2;
- if ((device == NULL) || (libdev == NULL))
- return FALSE;
+ if ((device == NULL) || (libdev == NULL))
+ return FALSE;
- vid1 = spice_usb_device_get_vid(device);
- pid1 = spice_usb_device_get_pid(device);
+ vid1 = spice_usb_device_get_vid(device);
+ pid1 = spice_usb_device_get_pid(device);
- if (!spice_usb_device_manager_get_libdev_vid_pid(libdev, &vid2, &pid2)) {
- return FALSE;
+ if (!spice_usb_device_manager_get_libdev_vid_pid(libdev, &vid2, &pid2)) {
+ return FALSE;
+ }
+
+ return ((vid1 == vid2) && (pid1 == pid2));
}
+ else {
+ int busnum1, devaddr1, busnum2, devaddr2;
+
+ if ((device == NULL) || (libdev == NULL))
+ return FALSE;
+
+ busnum1 = spice_usb_device_get_busnum(device);
+ devaddr1 = spice_usb_device_get_devaddr(device);
- return ((vid1 == vid2) && (pid1 == pid2));
+ busnum2 = libusb_get_bus_number(libdev);
+ devaddr2 = libusb_get_device_address(libdev);
+
+ return ((busnum1 == busnum2) && (devaddr1 == devaddr2));
+ }
}
#endif
@@ -1879,15 +1993,20 @@ spice_usb_device_manager_device_to_libdev(SpiceUsbDeviceManager *self,
g_return_val_if_fail(self->priv->context != NULL, NULL);
/* On windows we match by vid / pid, since the address may change */
- bus = spice_usb_device_get_vid(device);
- addr = spice_usb_device_get_pid(device);
-
+ if (self->priv->use_usbclerk) {
+ bus = spice_usb_device_get_vid(device);
+ addr = spice_usb_device_get_pid(device);
+ }
+ else{
+ bus = spice_usb_device_get_busnum(device);
+ addr = spice_usb_device_get_devaddr(device);
+ }
libusb_get_device_list(self->priv->context, &devlist);
if (!devlist)
return NULL;
for (i = 0; (d = devlist[i]) != NULL; i++) {
- if (spice_usb_device_manager_libdev_match(d, bus, addr)) {
+ if (spice_usb_device_manager_libdev_match(d, bus, addr, self->priv->use_usbclerk)) {
libusb_ref_device(d);
break;
}
--
2.1.0
More information about the Spice-devel
mailing list