From: Kirill Moizik <kmoizik@xxxxxxxxxx> --- src/channel-usbredir-priv.h | 4 +++ src/channel-usbredir.c | 20 ++++++++++++- src/map-file | 1 + src/usb-device-manager.c | 73 +++++++++++++++++++++++++++++++++++++++++++++ src/usb-device-manager.h | 8 +++++ 5 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/channel-usbredir-priv.h b/src/channel-usbredir-priv.h index f2e17e3..6e6d58b 100644 --- a/src/channel-usbredir-priv.h +++ b/src/channel-usbredir-priv.h @@ -33,6 +33,10 @@ G_BEGIN_DECLS void spice_usbredir_channel_set_context(SpiceUsbredirChannel *channel, libusb_context *context); +void spice_usbredir_channel_disconnect_device_async(SpiceUsbredirChannel *channel, + GSimpleAsyncResult *simple, + GCancellable *cancellable); + /* Note the context must be set, and the channel must be brought up (through spice_channel_connect()), before calling this. */ void spice_usbredir_channel_connect_device_async( diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c index f1bd815..4cf1173 100644 --- a/src/channel-usbredir.c +++ b/src/channel-usbredir.c @@ -428,10 +428,12 @@ void spice_usbredir_channel_disconnect_device(GSimpleAsyncResult *simple, GObject *object, GCancellable *cancellable) { - SpiceUsbredirChannelPrivate *priv = channel->priv; + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(object); + SpiceUsbredirChannelPrivate *priv = channel->priv; CHANNEL_DEBUG(channel, "disconnecting device from usb channel %p", channel); + g_mutex_lock(priv->flows_mutex); switch (priv->state) { case STATE_DISCONNECTED: case STATE_DISCONNECTING: @@ -465,6 +467,22 @@ void spice_usbredir_channel_disconnect_device(GSimpleAsyncResult *simple, priv->state = STATE_DISCONNECTED; break; } + g_mutex_unlock(priv->flows_mutex); +} + +void spice_usbredir_channel_disconnect_device_async(SpiceUsbredirChannel *channel, + GSimpleAsyncResult *simple, + GCancellable *cancellable) +{ + if (channel) { + g_object_ref(channel); + g_simple_async_result_run_in_thread(simple, + spice_usbredir_channel_disconnect_device, + G_PRIORITY_DEFAULT, + cancellable); + } else { + g_simple_async_result_complete_in_idle(simple); + } } G_GNUC_INTERNAL diff --git a/src/map-file b/src/map-file index 6d5a5ef..042889f 100644 --- a/src/map-file +++ b/src/map-file @@ -120,6 +120,7 @@ spice_usb_device_get_type; spice_g_udev_set_redirecting; spice_usb_device_manager_can_redirect_device; spice_usb_device_manager_connect_device_async; +spice_usb_device_manager_disconnect_device_async; spice_usb_device_manager_connect_device_finish; spice_usb_device_manager_disconnect_device; spice_usb_device_manager_get; diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c index 901a1b9..ebd9307 100644 --- a/src/usb-device-manager.c +++ b/src/usb-device-manager.c @@ -1697,6 +1697,79 @@ void spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *self, #endif } +typedef struct _disconnect_cb_data +{ + SpiceUsbDeviceManager *self; + GSimpleAsyncResult *result; + SpiceUsbDevice *device; +} disconnect_cb_data; + +#ifdef USE_USBREDIR +static +void spice_usb_device_manager_disconnect_device_async_cb(GObject *gobject, + GAsyncResult *channel_res, + gpointer user_data) +{ + disconnect_cb_data *data = user_data; + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(data->result); + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(data->self); + +#ifdef G_OS_WIN32 + if (self->priv->use_usbclerk) { + spice_usb_device_manager_driver_uninstall_async(self, data->device); + } +#endif + + g_object_set(self, "redirecting", FALSE, NULL); + +#ifndef USE_LIBUSB_HOTPLUG + spice_g_udev_set_redirecting(FALSE); +#endif + g_simple_async_result_complete(result); + g_object_unref(result); + g_object_unref(gobject); + g_free(data); +} +#endif + +void spice_usb_device_manager_disconnect_device_async(SpiceUsbDeviceManager *self, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ +#ifdef USE_USBREDIR + GSimpleAsyncResult *nested; + GSimpleAsyncResult *result; + g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self)); + + g_return_if_fail(device != NULL); + g_return_if_fail(self->priv->redirecting == FALSE); + + SPICE_DEBUG("disconnecting device %p", device); + + SpiceUsbredirChannel *channel; + + g_object_set(self,"redirecting", TRUE, NULL); +#ifndef USE_LIBUSB_HOTPLUG + spice_g_udev_set_redirecting(TRUE); +#endif + channel = spice_usb_device_manager_get_channel_for_dev(self, device); + nested = g_simple_async_result_new(G_OBJECT(self), callback, user_data, + spice_usb_device_manager_disconnect_device_async); + disconnect_cb_data *data = g_new(disconnect_cb_data,1); + data->self = self; + data->result = nested; + data->device = device; + + result = g_simple_async_result_new(G_OBJECT(channel), + spice_usb_device_manager_disconnect_device_async_cb, data, + spice_usb_device_manager_disconnect_device_async); + + spice_usbredir_channel_disconnect_device_async(channel,result,cancellable); +#endif +} + gboolean spice_usb_device_manager_can_redirect_device(SpiceUsbDeviceManager *self, SpiceUsbDevice *device, diff --git a/src/usb-device-manager.h b/src/usb-device-manager.h index 5b4cfbe..025262a 100644 --- a/src/usb-device-manager.h +++ b/src/usb-device-manager.h @@ -106,6 +106,14 @@ void spice_usb_device_manager_connect_device_async( GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); + +void spice_usb_device_manager_disconnect_device_async( + SpiceUsbDeviceManager *manager, + SpiceUsbDevice *device, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean spice_usb_device_manager_connect_device_finish( SpiceUsbDeviceManager *self, GAsyncResult *res, GError **err); -- 2.4.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel