[Spice-devel] [PATCH 5/5] usb-device-manager: Configure UsbDk hiding rules on auto-redirection
Kirill Moizik
kirill at daynix.com
Thu May 28 03:24:04 PDT 2015
From: Dmitry Fleytman <dmitry at daynix.com>
When spice run with auto redirection rule, hide rule should be applied to detach device from host stack
during device plug-in to avoid "new hardware wizard" pop up (in case there is no driver for redirected device on host)
Signed-off-by: Kirill Moizik <kirill at daynix.com>
Signed-off-by: Dmitry Fleytman <dmitry at daynix.com>
---
gtk/usb-device-manager.c | 102 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 98 insertions(+), 4 deletions(-)
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index 841e3a4..9786f16 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -29,6 +29,10 @@
#include <errno.h>
#include <libusb.h>
+#ifdef USE_WINUSB
+#include "usbdk_api.h"
+#endif
+
#if defined(USE_GUDEV)
#include <gudev/gudev.h>
#elif defined(G_OS_WIN32)
@@ -124,6 +128,8 @@ struct _SpiceUsbDeviceManagerPrivate {
#endif
#ifdef USE_WINUSB
SpiceWinUsbDriver *installer;
+ usbdk_api_wrapper usbdk_api;
+ HANDLE usbdk_hider_handle;
#endif
#endif
GPtrArray *devices;
@@ -246,13 +252,19 @@ static gboolean is_usbdk_driver_installed(void)
static void spice_usb_device_manager_init(SpiceUsbDeviceManager *self)
{
+ SpiceUsbDeviceManagerPrivate *priv =
+ SPICE_USB_DEVICE_MANAGER_GET_PRIVATE(self);
+
#ifdef USE_WINUSB
use_usbdk = is_usbdk_driver_installed();
-#endif
- SpiceUsbDeviceManagerPrivate *priv;
+ if(use_usbdk) {
+ if (usbdk_api_load(&priv->usbdk_api) == -1) {
+ SPICE_DEBUG("Failed to load UsbDk API DLL");
+ }
+ }
+#endif
- priv = SPICE_USB_DEVICE_MANAGER_GET_PRIVATE(self);
self->priv = priv;
priv->channels = g_ptr_array_new();
@@ -411,6 +423,12 @@ static void spice_usb_device_manager_finalize(GObject *gobject)
g_free(priv->auto_connect_filter);
g_free(priv->redirect_on_connect);
+#ifdef USE_WINUSB
+ if (use_usbdk) {
+ 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);
@@ -428,7 +446,6 @@ static void spice_usb_device_manager_get_property(GObject *gobject,
{
SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject);
SpiceUsbDeviceManagerPrivate *priv = self->priv;
-
switch (prop_id) {
case PROP_SESSION:
g_value_set_object(value, priv->session);
@@ -448,6 +465,13 @@ static void spice_usb_device_manager_get_property(GObject *gobject,
}
}
+#ifdef USE_WINUSB
+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,
@@ -462,6 +486,13 @@ static void spice_usb_device_manager_set_property(GObject *gobject,
break;
case PROP_AUTO_CONNECT:
priv->auto_connect = g_value_get_boolean(value);
+#ifdef USE_WINUSB
+ 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);
@@ -1906,6 +1937,69 @@ guint8 spice_usb_device_get_state(SpiceUsbDevice *device)
return info->state;
}
+
+static
+void spice_usb_device_manager_set_rules(SpiceUsbDeviceManagerPrivate *priv)
+{
+ struct usbredirfilter_rule *rules;
+ int r, count;
+
+ r = usbredirfilter_string_to_rules(priv->redirect_on_connect, ",", "|", &rules, &count);
+ if (r) {
+ SPICE_DEBUG("auto-conenct rules parsing failed with error %d", r);
+ return;
+ }
+
+ for (int i = 0; i < count; i++) {
+ USB_DK_HIDE_RULE rule;
+ rule.Hide = (uint64_t)rules[i].allow;
+ rule.Class = (uint64_t)rules[i].device_class;
+ rule.VID = (uint64_t)rules[i].vendor_id;
+ rule.PID = (uint64_t)rules[i].product_id;
+ rule.BCD = (uint64_t)rules[i].device_version_bcd;
+ if(!priv->usbdk_api.AddRule(priv->usbdk_hider_handle, &rule)) {
+ SPICE_DEBUG("UsbDk set hide rule API failed");
+ }
+ }
+
+ free(rules);
+}
+
+static
+void _usbdk_autoredir_enable(SpiceUsbDeviceManager *manager)
+{
+ if(!use_usbdk)
+ return;
+
+ SpiceUsbDeviceManagerPrivate *priv = manager->priv;
+
+ if(priv->redirect_on_connect == NULL) {
+ SPICE_DEBUG("No autoredirect rules, no hider setup needed");
+ return;
+ }
+
+ priv->usbdk_hider_handle = priv->usbdk_api.CreateHandle();
+ if(priv->usbdk_hider_handle == NULL) {
+ SPICE_DEBUG("Failed to instanciate UsbDk interface");
+ return;
+ }
+
+ spice_usb_device_manager_set_rules(priv);
+}
+
+static
+void _usbdk_autoredir_disable(SpiceUsbDeviceManager *manager)
+{
+ if(!use_usbdk)
+ return;
+
+ SpiceUsbDeviceManagerPrivate *priv = manager->priv;
+ if(priv->usbdk_hider_handle != NULL) {
+ priv->usbdk_api.ClearRules(priv->usbdk_hider_handle);
+ priv->usbdk_api.CloseHiderHandle(priv->usbdk_hider_handle);
+ }
+}
+
#endif
static SpiceUsbDevice *spice_usb_device_ref(SpiceUsbDevice *device)
--
2.1.0
More information about the Spice-devel
mailing list