From: Dmitry Fleytman <dmitry@xxxxxxxxxx> 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@xxxxxxxxxx> Signed-off-by: Dmitry Fleytman <dmitry@xxxxxxxxxx> --- 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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel