summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Moizik <kmoizik@redhat.com>2016-03-08 16:05:54 +0200
committerJonathon Jongsma <jjongsma@redhat.com>2016-03-24 11:00:01 -0500
commita123feddf906e961c9ee0eed5001d371f825e6d8 (patch)
tree79a8773a8ab4ed1742ffa485cc5b6664bb5b699a
parent4eea5f3afeb4ad8c5f47cc03793474602696ca29 (diff)
UsbDeviceManager: Track device redirection operations in progress
During device connection, unwanted hotplug events may happen. We need to ignore those therefore we track redirection operations in progress. See also comment to commit "Do not process USB hotplug events while redirection is in progress" that introduces corresponding filtering out logic. Signed-off-by: Kirill Moizik <kmoizik@redhat.com> Signed-off-by: Dmitry Fleytman <dfleytma@redhat.com>
-rw-r--r--src/usb-device-manager.c67
1 files changed, 54 insertions, 13 deletions
diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
index 3872bb6..0f8134f 100644
--- a/src/usb-device-manager.c
+++ b/src/usb-device-manager.c
@@ -121,6 +121,7 @@ struct _SpiceUsbDeviceManagerPrivate {
GUdevClient *udev;
libusb_device **coldplug_list; /* Avoid needless reprobing during init */
#else
+ gboolean redirecting; /* Handled by GUdevClient in the gudev case */
libusb_hotplug_callback_handle hp_handle;
#endif
#ifdef G_OS_WIN32
@@ -207,10 +208,25 @@ _spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
GAsyncReadyCallback callback,
gpointer user_data);
+static
+void _connect_device_async_cb(GObject *gobject,
+ GAsyncResult *channel_res,
+ gpointer user_data);
+
G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device,
(GBoxedCopyFunc)spice_usb_device_ref,
(GBoxedFreeFunc)spice_usb_device_unref)
+static void
+_set_redirecting(SpiceUsbDeviceManager *self, gboolean is_redirecting)
+{
+#ifdef USE_GUDEV
+ g_object_set(self->priv->udev, "redirecting", is_redirecting, NULL);
+#else
+ self->priv->redirecting = is_redirecting;
+#endif
+}
+
#else
G_DEFINE_BOXED_TYPE(SpiceUsbDevice, spice_usb_device, g_object_ref, g_object_unref)
#endif
@@ -1163,7 +1179,7 @@ static void spice_usb_device_manager_drv_install_cb(GObject *gobject,
SpiceUsbDevice *device;
UsbInstallCbInfo *cbinfo;
GCancellable *cancellable;
- GAsyncReadyCallback callback;
+ gpointer data;
g_return_if_fail(user_data != NULL);
@@ -1172,8 +1188,7 @@ static void spice_usb_device_manager_drv_install_cb(GObject *gobject,
device = cbinfo->device;
installer = cbinfo->installer;
cancellable = cbinfo->cancellable;
- callback = cbinfo->callback;
- user_data = cbinfo->user_data;
+ data = cbinfo->user_data;
g_free(cbinfo);
@@ -1195,8 +1210,8 @@ static void spice_usb_device_manager_drv_install_cb(GObject *gobject,
_spice_usb_device_manager_connect_device_async(self,
device,
cancellable,
- callback,
- user_data);
+ _connect_device_async_cb,
+ data);
spice_usb_device_unref(device);
}
@@ -1523,6 +1538,8 @@ _spice_usb_device_manager_uninstall_driver_async(SpiceUsbDeviceManager *self,
#endif
+#ifdef USE_USBREDIR
+
static void
_spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
SpiceUsbDevice *device,
@@ -1539,7 +1556,6 @@ _spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
task = g_task_new(self, cancellable, callback, user_data);
-#ifdef USE_USBREDIR
SpiceUsbDeviceManagerPrivate *priv = self->priv;
libusb_device *libdev;
guint i;
@@ -1585,17 +1601,16 @@ _spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
libusb_unref_device(libdev);
return;
}
-#endif
g_task_return_new_error(task,
SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
_("No free USB channel"));
-#ifdef USE_USBREDIR
done:
-#endif
g_object_unref(task);
}
+#endif
+
/**
* spice_usb_device_manager_connect_device_async:
* @self: a #SpiceUsbDeviceManager.
@@ -1614,11 +1629,19 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
-#if defined(USE_USBREDIR) && defined(G_OS_WIN32)
+#ifdef USE_USBREDIR
+
+ GTask *task =
+ g_task_new(G_OBJECT(self), cancellable, callback, user_data);
+
+ _set_redirecting(self, TRUE);
+
+#ifdef G_OS_WIN32
if (self->priv->use_usbclerk) {
_spice_usb_device_manager_install_driver_async(self, device, cancellable,
- callback, user_data);
+ callback, task);
return;
}
#endif
@@ -1626,8 +1649,10 @@ void spice_usb_device_manager_connect_device_async(SpiceUsbDeviceManager *self,
_spice_usb_device_manager_connect_device_async(self,
device,
cancellable,
- callback,
- user_data);
+ _connect_device_async_cb,
+ task);
+
+#endif
}
/**
@@ -1651,6 +1676,22 @@ gboolean spice_usb_device_manager_connect_device_finish(
return g_task_propagate_boolean(task, err);
}
+#ifdef USE_USBREDIR
+static
+void _connect_device_async_cb(GObject *gobject,
+ GAsyncResult *channel_res,
+ gpointer user_data)
+{
+ SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(gobject);
+ GTask *task = user_data;
+
+ _set_redirecting(self, FALSE);
+
+ g_task_return_boolean(task, TRUE);
+ g_object_unref(task);
+}
+#endif
+
/**
* spice_usb_device_manager_disconnect_device:
* @manager: the #SpiceUsbDeviceManager manager