Re: [PATCH v6 08/14] UsbDeviceManager: Implement asynchronous disconnect device flow

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 1 Mar 2016, at 21:14 PM, Jonathon Jongsma <jjongsma@xxxxxxxxxx> wrote:

As I mentioned in the previous patch, I'd really like this rebased on Fabiano's
GTask work. I understand that it's annoying to have to rebase this stuff, so I'm
willing to do it for you if you'd prefer.

That would be great, thanks. I don’t feel secure enough with GTask API to be sure I’m not introducing regressions during the rebase.


Another comment below


On Sun, 2016-02-28 at 11:54 +0200, Dmitry Fleytman wrote:
From: Kirill Moizik <kmoizik@xxxxxxxxxx>

This commit introduces functions for asynchronous disconnection flows.
Following commits will make use of those.

Thread safety is ensured the same way it was done for connection
flow in previous commits. Disconnect logic is protected by the same
locks that protect connect/usbredir/channel management logic.

Signed-off-by: Kirill Moizik <kmoizik@xxxxxxxxxx>
Signed-off-by: Dmitry Fleytman <dfleytma@xxxxxxxxxx>
---
src/channel-usbredir-priv.h |  9 +++++++
src/channel-usbredir.c      | 42 +++++++++++++++++++++++++++++
src/map-file                |  1 +
src/usb-device-manager.c    | 66
+++++++++++++++++++++++++++++++++++++++++++++
src/usb-device-manager.h    |  8 ++++++
5 files changed, 126 insertions(+)

diff --git a/src/channel-usbredir-priv.h b/src/channel-usbredir-priv.h
index c987474..17e9716 100644
--- a/src/channel-usbredir-priv.h
+++ b/src/channel-usbredir-priv.h
@@ -33,6 +33,15 @@ G_BEGIN_DECLS
void spice_usbredir_channel_set_context(SpiceUsbredirChannel *channel,
                                        libusb_context       *context);

+void spice_usbredir_channel_disconnect_device_async(SpiceUsbredirChannel
*channel,
+                                                    GCancellable
*cancellable,
+                                                    GAsyncReadyCallback
callback,
+                                                    gpointer user_data);
+
+gboolean spice_usbredir_channel_disconnect_device_finish(SpiceUsbredirChannel
*channel,
+                                                         GAsyncResult        
*res,
+                                                         GError             
**err);
+
/* 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 428c034..ebf9fce 100644
--- a/src/channel-usbredir.c
+++ b/src/channel-usbredir.c
@@ -431,6 +431,8 @@ void
spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel *channel)

    CHANNEL_DEBUG(channel, "disconnecting device from usb channel %p",
channel);

+    spice_usbredir_channel_lock(channel);
+
    switch (priv->state) {
    case STATE_DISCONNECTED:
    case STATE_DISCONNECTING:
@@ -464,6 +466,46 @@ void
spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel *channel)
        priv->state  = STATE_DISCONNECTED;
        break;
    }
+
+    spice_usbredir_channel_unlock(channel);
+}
+
+static void
+_disconnect_device_thread(GSimpleAsyncResult *simple,
+                          GObject *object,
+                          GCancellable *cancellable)
+{
+    spice_usbredir_channel_disconnect_device(SPICE_USBREDIR_CHANNEL(object));
+}
+
+G_GNUC_INTERNAL
+gboolean spice_usbredir_channel_disconnect_device_finish(
+                                               SpiceUsbredirChannel *channel,
+                                               GAsyncResult         *res,
+                                               GError              **err)
+{
+    return g_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(res),
err);
+}
+
+void spice_usbredir_channel_disconnect_device_async(SpiceUsbredirChannel
*channel,
+                                                    GCancellable
*cancellable,
+                                                    GAsyncReadyCallback
callback,
+                                                    gpointer user_data)
+{
+    GSimpleAsyncResult* result;
+
+    result = g_simple_async_result_new(G_OBJECT(channel),
+                                       callback, user_data,
+                                      
spice_usbredir_channel_disconnect_device_async);
+
+    if (channel) {
+        g_simple_async_result_run_in_thread(result,
+                                            _disconnect_device_thread,
+                                            G_PRIORITY_DEFAULT,
+                                            cancellable);
+    } else {
+        g_simple_async_result_complete_in_idle(result);
+    }
}

G_GNUC_INTERNAL
diff --git a/src/map-file b/src/map-file
index 92a9883..1f7755b 100644
--- a/src/map-file
+++ b/src/map-file
@@ -127,6 +127,7 @@ spice_usb_device_manager_can_redirect_device;
spice_usb_device_manager_connect_device_async;
spice_usb_device_manager_connect_device_finish;
spice_usb_device_manager_disconnect_device;
+spice_usb_device_manager_disconnect_device_async;
spice_usb_device_manager_get;
spice_usb_device_manager_get_devices;
spice_usb_device_manager_get_devices_with_filter;
diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c
index fc0f15f..93e095a 100644
--- a/src/usb-device-manager.c
+++ b/src/usb-device-manager.c
@@ -1705,6 +1705,72 @@ 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 _disconnect_device_async_cb(GObject *gobject,
+                                 GAsyncResult *channel_res,
+                                 gpointer user_data)
+{
+    SpiceUsbredirChannel  *channel = SPICE_USBREDIR_CHANNEL(gobject);
+    disconnect_cb_data    *data    = user_data;
+    GSimpleAsyncResult    *result  = G_SIMPLE_ASYNC_RESULT(data->result);
+    GError *err = NULL;
+
+#ifdef G_OS_WIN32
+    SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(data->self);
+
+    if (self->priv->use_usbclerk) {
+        _spice_usb_device_manager_uninstall_driver_async(self, data->device);
+    }
+#endif
+
+    spice_usbredir_channel_disconnect_device_finish(channel, channel_res,
&err);
+    if (err) {
+        g_simple_async_result_take_error(result, err);
+    }
+    g_simple_async_result_complete(result);
+    g_object_unref(result);
+    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;
+    g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self));
+
+    g_return_if_fail(device != NULL);
+
+    SPICE_DEBUG("disconnecting device %p", device);
+
+    SpiceUsbredirChannel *channel;
+
+    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 = "" 1);
+    data->self = self;
+    data->result = nested;
+    data->device = device;
+
+    spice_usbredir_channel_disconnect_device_async(channel, cancellable,
+                                                  
_disconnect_device_async_cb,
+                                                   data);
+#endif
+}
+
/**
 * spice_usb_device_manager_can_redirect_device:
 * @self: the #SpiceUsbDeviceManager manager
diff --git a/src/usb-device-manager.h b/src/usb-device-manager.h
index e05ebae..d705e74 100644
--- a/src/usb-device-manager.h
+++ b/src/usb-device-manager.h
@@ -116,6 +116,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);
+

In my last review, I suggested that we should have a paired _finish() function
for this operation. Your reply said you added one, but it seems you only added
spice_usbredir_channel_disconnect_device_finish() and not
spice_usb_device_manager_disconnect_device_finish()

Right, added. Thanks.



gboolean spice_usb_device_manager_connect_device_finish(
    SpiceUsbDeviceManager *self, GAsyncResult *res, GError **err);



Reviewed-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx>

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]