[Spice-devel] [PATCH spice-gtk] usbredir: Add support for filtering out devices from auto-redirection

Hans de Goede hdegoede at redhat.com
Wed Jan 11 08:13:26 PST 2012


Note this patch adds a default filter filtering out HID devices, since
redirecting ie a mouse plugged into a laptop is usually not what the user
wants. Also sometimes usb keyboards/mice may experience a glitch causing
them to temporarily drop of the bus. If this happens when the spice-client
has focussed it used to redirect them to the vm when they re-appeared,
not good!

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 configure.ac             |    2 +-
 gtk/spice-option.c       |    9 ++++++
 gtk/usb-device-manager.c |   70 +++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/configure.ac b/configure.ac
index 5788532..766564c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -330,7 +330,7 @@ if test "x$enable_usbredir" = "xno"; then
 else
   PKG_CHECK_MODULES(GUDEV, gudev-1.0)
   PKG_CHECK_MODULES(LIBUSB, libusb-1.0 >= 1.0.9)
-  PKG_CHECK_MODULES(LIBUSBREDIRHOST, libusbredirhost >= 0.3.2)
+  PKG_CHECK_MODULES(LIBUSBREDIRHOST, libusbredirhost >= 0.3.3)
   AC_DEFINE(USE_USBREDIR, [1], [Define if supporting usbredir proxying])
   AM_CONDITIONAL(WITH_USBREDIR, true)
   if test "x$enable_polkit" = "xno"; then
diff --git a/gtk/spice-option.c b/gtk/spice-option.c
index 9819543..394a07d 100644
--- a/gtk/spice-option.c
+++ b/gtk/spice-option.c
@@ -24,6 +24,7 @@
 #include <glib/gi18n.h>
 #include "spice-session.h"
 #include "spice-util.h"
+#include "usb-device-manager.h"
 
 static gchar *disable_effects = NULL;
 static gint color_depth = 0;
@@ -31,6 +32,7 @@ static char *ca_file = NULL;
 static char *host_subject = NULL;
 static char *smartcard_db = NULL;
 static char *smartcard_certificates = NULL;
+static char *usbredir_filter = NULL;
 static gboolean smartcard = FALSE;
 static gboolean disable_audio = FALSE;
 static gboolean disable_usbredir = FALSE;
@@ -75,6 +77,8 @@ GOptionGroup* spice_get_option_group(void)
           N_("Path to the local certificate database to use for software smartcard certificates"), N_("<certificate-db>") },
         { "spice-disable-usbredir", '\0', 0, G_OPTION_ARG_NONE, &disable_usbredir,
           N_("Disable USB redirection support"), NULL },
+        { "spice-usbredir-filter", '\0', 0, G_OPTION_ARG_STRING, &usbredir_filter,
+          N_("Filter for excluding USB devices from auto redirection"), N_("<filter-string>") },
 
         { "spice-debug", '\0', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, option_debug,
           N_("Enable Spice-GTK debugging"), NULL },
@@ -133,6 +137,11 @@ void spice_set_session_option(SpiceSession *session)
         if (smartcard_db)
             g_object_set(session, "smartcard-db", smartcard_db, NULL);
     }
+    if (usbredir_filter) {
+        SpiceUsbDeviceManager *m = spice_usb_device_manager_get(session, NULL);
+        if (m)
+            g_object_set(m, "auto-connect-filter", usbredir_filter, NULL);
+    }
     if (disable_usbredir)
         g_object_set(session, "enable-usbredir", FALSE, NULL);
     if (disable_audio)
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index fde353c..bfc5be3 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -33,9 +33,11 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #endif
+#include <errno.h>
 #include <libusb.h>
 #include <gudev/gudev.h>
 #include "channel-usbredir-priv.h"
+#include "usbredirhost.h"
 #endif
 
 #include "spice-session-priv.h"
@@ -80,6 +82,7 @@ enum {
     PROP_0,
     PROP_SESSION,
     PROP_AUTO_CONNECT,
+    PROP_AUTO_CONNECT_FILTER,
 };
 
 enum
@@ -93,6 +96,7 @@ enum
 struct _SpiceUsbDeviceManagerPrivate {
     SpiceSession *session;
     gboolean auto_connect;
+    gchar *auto_connect_filter;
 #ifdef USE_USBREDIR
     libusb_context *context;
     GUdevClient *udev;
@@ -100,6 +104,8 @@ struct _SpiceUsbDeviceManagerPrivate {
     GThread *event_thread;
     gboolean event_thread_run;
     libusb_device **coldplug_list; /* Avoid needless reprobing during init */
+    struct usbredirfilter_rule *auto_conn_filter_rules;
+    int auto_conn_filter_rules_count;
 #endif
     GPtrArray *devices;
     GPtrArray *channels;
@@ -257,6 +263,9 @@ static void spice_usb_device_manager_get_property(GObject     *gobject,
     case PROP_AUTO_CONNECT:
         g_value_set_boolean(value, priv->auto_connect);
         break;
+    case PROP_AUTO_CONNECT_FILTER:
+        g_value_set_string(value, priv->auto_connect_filter);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
         break;
@@ -278,6 +287,31 @@ static void spice_usb_device_manager_set_property(GObject       *gobject,
     case PROP_AUTO_CONNECT:
         priv->auto_connect = g_value_get_boolean(value);
         break;
+    case PROP_AUTO_CONNECT_FILTER: {
+#ifdef USE_USBREDIR
+        const gchar *filter = g_value_get_string(value);
+        struct usbredirfilter_rule *rules;
+        int r, count;
+
+        r = usbredirfilter_string_to_rules(filter, ",", "|", &rules, &count);
+        if (r) {
+            if (r == -ENOMEM)
+                g_error("Failed to allocate memory for auto-connect-filter");
+            g_warning("Error parsing auto-connect-filter string, keeping old filter\n");
+            break;
+        }
+
+        g_free(priv->auto_connect_filter);
+        free(priv->auto_conn_filter_rules);
+
+        priv->auto_connect_filter = g_strdup(filter);
+        priv->auto_conn_filter_rules = rules;
+        priv->auto_conn_filter_rules_count = count;
+#else
+        priv->auto_connect_filter = g_value_get_string(value);
+#endif
+        break;
+    }
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
         break;
@@ -318,6 +352,36 @@ static void spice_usb_device_manager_class_init(SpiceUsbDeviceManagerClass *klas
     g_object_class_install_property(gobject_class, PROP_AUTO_CONNECT, pspec);
 
     /**
+     * SpiceUsbDeviceManager:auto-connect-filter:
+     *
+     * Set a string specifying a filter to use to determine which USB devices
+     * to autoconnect when plugged in, a filter consists of one or more rules.
+     * Where each rule has the form of:
+     *
+     * @class, at vendor, at product, at version, at allow
+     *
+     * Use -1 for @class/@vendor/@product/@version to accept any value.
+     *
+     * And the rules are themselves are concatonated like this:
+     *
+     * @rule1|@rule2|@rule3
+     *
+     * The default setting filters out HID (class 0x03) USB devices from auto
+     * connect and auto connects anything else. Note the explicit allow rule at
+     * the end, this is necessary since by default all devices without a
+     * matching filter rule will not auto-connect.
+     *
+     * Filter strings in this format can be easily created with the RHEV-M
+     * USB filter editor tool.
+     */
+    pspec = g_param_spec_string("auto-connect-filter", "Auto Connect Filter ",
+               "Filter determining which USB devices to auto connect",
+               "0x03,-1,-1,-1,0|-1,-1,-1,-1,1",
+               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+    g_object_class_install_property(gobject_class, PROP_AUTO_CONNECT_FILTER,
+                                    pspec);
+
+    /**
      * SpiceUsbDeviceManager::device-added:
      * @manager: the #SpiceUsbDeviceManager that emitted the signal
      * @device: #SpiceUsbDevice boxed object corresponding to the added device
@@ -555,7 +619,11 @@ static void spice_usb_device_manager_add_dev(SpiceUsbDeviceManager  *self,
     g_ptr_array_add(priv->devices, device);
 
     if (priv->auto_connect) {
-        spice_usb_device_manager_connect_device_async(self,
+        if (usbredirhost_check_device_filter(
+                priv->auto_conn_filter_rules,
+                priv->auto_conn_filter_rules_count,
+                device, 0) == 0)
+            spice_usb_device_manager_connect_device_async(self,
                                    (SpiceUsbDevice *)device, NULL,
                                    spice_usb_device_manager_auto_connect_cb,
                                    libusb_ref_device(device));
-- 
1.7.7.4



More information about the Spice-devel mailing list