[Spice-devel] [PATCH spice-gtk 05/10] usbredir: Create USB event source on demand

Hans de Goede hdegoede at redhat.com
Mon Dec 19 03:24:38 PST 2011


This is a preparation patch for handling usb packet completion in a
separate thread.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 gtk/Makefile.am               |    1 +
 gtk/channel-usbredir.c        |   15 ++++++++++++
 gtk/usb-device-manager-priv.h |   36 +++++++++++++++++++++++++++++
 gtk/usb-device-manager.c      |   50 +++++++++++++++++++++++++++++++---------
 4 files changed, 90 insertions(+), 12 deletions(-)
 create mode 100644 gtk/usb-device-manager-priv.h

diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index b780882..9f208cc 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -236,6 +236,7 @@ libspice_client_glib_2_0_la_SOURCES =	\
 	smartcard-manager.c		\
 	smartcard-manager-priv.h	\
 	usb-device-manager.c		\
+	usb-device-manager-priv.h	\
 	$(GUSB_SRCS)			\
 	$(USB_ACL_HELPER_SRCS)		\
 	\
diff --git a/gtk/channel-usbredir.c b/gtk/channel-usbredir.c
index 58a4c21..26821c6 100644
--- a/gtk/channel-usbredir.c
+++ b/gtk/channel-usbredir.c
@@ -30,6 +30,7 @@
 #include "usb-acl-helper.h"
 #endif
 #include "channel-usbredir-priv.h"
+#include "usb-device-manager-priv.h"
 #endif
 
 #include "spice-client.h"
@@ -197,6 +198,16 @@ static gboolean spice_usbredir_channel_open_device(
         return FALSE;
     }
 
+    if (!spice_usb_device_manager_start_event_listening(
+            spice_usb_device_manager_get(
+                spice_channel_get_session(SPICE_CHANNEL(channel)),
+                NULL, NULL),
+            err)) {
+        usbredirhost_close(priv->host);
+        priv->host = NULL;
+        return FALSE;
+    }
+
     spice_channel_connect(SPICE_CHANNEL(channel));
     priv->state = STATE_CONNECTING;
 
@@ -335,6 +346,10 @@ void spice_usbredir_channel_disconnect(SpiceUsbredirChannel *channel)
     case STATE_CONNECTING:
     case STATE_CONNECTED:
         spice_channel_disconnect(SPICE_CHANNEL(channel), SPICE_CHANNEL_NONE);
+        spice_usb_device_manager_stop_event_listening(
+            spice_usb_device_manager_get(
+                spice_channel_get_session(SPICE_CHANNEL(channel)),
+                NULL, NULL));
         /* This also closes the libusb handle we passed to its _open */
         usbredirhost_close(priv->host);
         priv->host = NULL;
diff --git a/gtk/usb-device-manager-priv.h b/gtk/usb-device-manager-priv.h
new file mode 100644
index 0000000..841c725
--- /dev/null
+++ b/gtk/usb-device-manager-priv.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2011 Red Hat, Inc.
+
+   Red Hat Authors:
+   Hans de Goede <hdegoede at redhat.com>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __SPICE_USB_DEVICE_MANAGER_PRIV_H__
+#define __SPICE_USB_DEVICE_MANAGER_PRIV_H__
+
+#include "usb-device-manager.h"
+
+G_BEGIN_DECLS
+
+gboolean spice_usb_device_manager_start_event_listening(
+    SpiceUsbDeviceManager *manager, GError **err);
+
+void spice_usb_device_manager_stop_event_listening(
+    SpiceUsbDeviceManager *manager);
+
+G_END_DECLS
+
+#endif /* __SPICE_USB_DEVICE_MANAGER_PRIV_H__ */
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index fcd1685..6fba6f6 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -34,6 +34,7 @@
 #include "spice-session-priv.h"
 #include "spice-client.h"
 #include "spice-marshal.h"
+#include "usb-device-manager-priv.h"
 
 /**
  * SECTION:usb-device-manager
@@ -91,6 +92,7 @@ struct _SpiceUsbDeviceManagerPrivate {
     GUsbContext *context;
     GUsbDeviceList *devlist;
     GUsbSource *source;
+    int event_listeners;
 #endif
     GPtrArray *devices;
     GPtrArray *channels;
@@ -202,8 +204,6 @@ static void spice_usb_device_manager_finalize(GObject *gobject)
     SpiceUsbDeviceManagerPrivate *priv = self->priv;
 
 #ifdef USE_USBREDIR
-    if (priv->source)
-        g_usb_source_destroy(priv->source);
     if (priv->devlist) {
         g_object_unref(priv->devlist);
         g_object_unref(priv->context);
@@ -476,10 +476,45 @@ static void spice_usb_device_manager_channel_connect_cb(
     g_simple_async_result_complete(result);
     g_object_unref(result);
 }
-#endif
 
 /* ------------------------------------------------------------------ */
 /* private api                                                        */
+
+gboolean spice_usb_device_manager_start_event_listening(
+    SpiceUsbDeviceManager *self, GError **err)
+{
+    SpiceUsbDeviceManagerPrivate *priv = self->priv;
+
+    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
+
+    priv->event_listeners++;
+    if (priv->event_listeners > 1)
+        return TRUE;
+
+    g_return_val_if_fail(priv->source == NULL, FALSE);
+
+    priv->source = g_usb_source_new(priv->main_context, priv->context, err);
+    return priv->source != NULL;
+}
+
+void spice_usb_device_manager_stop_event_listening(
+    SpiceUsbDeviceManager *self)
+{
+    SpiceUsbDeviceManagerPrivate *priv = self->priv;
+
+    g_return_if_fail(priv->event_listeners > 0);
+
+    priv->event_listeners--;
+    if (priv->event_listeners != 0)
+        return;
+
+    g_return_if_fail(priv->source != NULL);
+
+    g_usb_source_destroy(priv->source);
+    priv->source = NULL;
+}
+#endif
+
 static SpiceUsbredirChannel *spice_usb_device_manager_get_channel_for_dev(
     SpiceUsbDeviceManager *manager, SpiceUsbDevice *_device)
 {
@@ -603,7 +638,6 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
 
 #ifdef USE_USBREDIR
     SpiceUsbDeviceManagerPrivate *priv = self->priv;
-    GError *e = NULL;
     guint i;
 
     if (spice_usb_device_manager_is_device_connected(self, device)) {
@@ -613,14 +647,6 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
         goto done;
     }
 
-    if (!priv->source) {
-        priv->source = g_usb_source_new(priv->main_context, priv->context, &e);
-        if (e) {
-            g_simple_async_result_take_error(result, e);
-            goto done;
-        }
-    }
-
     for (i = 0; i < priv->channels->len; i++) {
         SpiceUsbredirChannel *channel = g_ptr_array_index(priv->channels, i);
 
-- 
1.7.7.4



More information about the Spice-devel mailing list