+1 (for code) please correct commit message On Thu, Jul 2, 2015 at 4:41 PM, Kirill Moizik <[email protected]> wrote:
> we will spawn a separate thread to disconnect usb device, when finish we > will update widget to allow further > usb redirection operations > 1) expose spice_usbredir_channel_connect_device_async function for > asynchronous disconnect > 2) threads synchronization > > Signed-off-by: Kirill Moizik <[email protected]> > --- > src/channel-usbredir-priv.h | 8 ++++- > src/channel-usbredir.c | 77 > ++++++++++++++++++++++++++++++++++++++------- > src/map-file | 1 + > src/usb-device-manager.c | 60 ++++++++++++++++++++++++++++++++++- > src/usb-device-manager.h | 8 +++++ > src/usb-device-widget.c | 19 +++++++++-- > 6 files changed, 157 insertions(+), 16 deletions(-) > > diff --git a/src/channel-usbredir-priv.h b/src/channel-usbredir-priv.h > index 2c4c6f7..f954377 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( > @@ -47,7 +51,9 @@ gboolean spice_usbredir_channel_connect_device_finish( > GAsyncResult *res, > GError **err); > > -void spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel > *channel); > +void spice_usbredir_channel_disconnect_device(GSimpleAsyncResult *simple, > + GObject *object, > + GCancellable *cancellable); > > libusb_device *spice_usbredir_channel_get_device(SpiceUsbredirChannel > *channel); > > diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c > index 97003dc..587f9d1 100644 > --- a/src/channel-usbredir.c > +++ b/src/channel-usbredir.c > @@ -79,6 +79,7 @@ struct _SpiceUsbredirChannelPrivate { > GSimpleAsyncResult *result; > SpiceUsbAclHelper *acl_helper; > #endif > + void* redirect_mutex; > }; > > static void channel_set_handlers(SpiceChannelClass *klass); > @@ -108,23 +109,51 @@ static void > spice_usbredir_channel_init(SpiceUsbredirChannel *channel) > #ifdef USE_USBREDIR > channel->priv = SPICE_USBREDIR_CHANNEL_GET_PRIVATE(channel); > #endif > + channel->priv->redirect_mutex = usbredir_alloc_lock(); > } > > #ifdef USE_USBREDIR > +typedef struct _reset_cb_data > +{ > + gboolean migrating; > +} reset_cb_data; > + > +static void spice_usbredir_channel_reset_cb(GObject *gobject, > + GAsyncResult *result, > + gpointer user_data) > +{ > + SpiceChannel *spiceChannel = SPICE_CHANNEL(gobject); > + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(spiceChannel); > + SpiceUsbredirChannelPrivate *priv = channel->priv; > + reset_cb_data *data = user_data; > + > + usbredirhost_close(priv->host); > + priv->host = NULL; > + /* Call set_context to re-create the host */ > + spice_usbredir_channel_set_context(channel, priv->context); > + > SPICE_CHANNEL_CLASS(spice_usbredir_channel_parent_class)->channel_reset(spiceChannel, > data->migrating); > + g_object_unref(result); > + g_free(data); > +} > + > static void spice_usbredir_channel_reset(SpiceChannel *c, gboolean > migrating) > { > SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(c); > SpiceUsbredirChannelPrivate *priv = channel->priv; > > + GSimpleAsyncResult *result ; > if (priv->host) { > - if (priv->state == STATE_CONNECTED) > - spice_usbredir_channel_disconnect_device(channel); > - usbredirhost_close(priv->host); > - priv->host = NULL; > - /* Call set_context to re-create the host */ > - spice_usbredir_channel_set_context(channel, priv->context); > + if (priv->state == STATE_CONNECTED){ > + reset_cb_data *data = g_new(reset_cb_data,1); > + data->migrating = migrating; > + result = g_simple_async_result_new(G_OBJECT(c), > + spice_usbredir_channel_reset_cb, data, > + spice_usbredir_channel_reset); > + spice_usbredir_channel_disconnect_device_async(channel, > result, NULL); > + } > + } else { > + > SPICE_CHANNEL_CLASS(spice_usbredir_channel_parent_class)->channel_reset(c, > migrating); > } > - > SPICE_CHANNEL_CLASS(spice_usbredir_channel_parent_class)->channel_reset(c, > migrating); > } > #endif > > @@ -149,7 +178,7 @@ static void spice_usbredir_channel_dispose(GObject > *obj) > { > SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(obj); > > - spice_usbredir_channel_disconnect_device(channel); > + spice_usbredir_channel_disconnect_device(NULL, G_OBJECT(channel), > NULL); > > /* Chain up to the parent class */ > if (G_OBJECT_CLASS(spice_usbredir_channel_parent_class)->dispose) > @@ -182,6 +211,7 @@ static void spice_usbredir_channel_finalize(GObject > *obj) > > if (channel->priv->host) > usbredirhost_close(channel->priv->host); > + usbredir_free_lock(channel->priv->redirect_mutex); > > /* Chain up to the parent class */ > if (G_OBJECT_CLASS(spice_usbredir_channel_parent_class)->finalize) > @@ -380,6 +410,7 @@ void spice_usbredir_channel_connect_device_async( > > spice_usbredir_channel_open_device_async, > G_PRIORITY_DEFAULT, > cancellable); > + g_object_unref(result); > return; > #endif > > @@ -406,11 +437,29 @@ gboolean > spice_usbredir_channel_connect_device_finish( > return TRUE; > } > > -G_GNUC_INTERNAL > -void spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel > *channel) > + > +void spice_usbredir_channel_disconnect_device_async(SpiceUsbredirChannel > *channel, > + GSimpleAsyncResult > *simple, > + GCancellable > *cancellable) > { > - SpiceUsbredirChannelPrivate *priv = channel->priv; > + if (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_object_unref(simple); > +} > > +void spice_usbredir_channel_disconnect_device(GSimpleAsyncResult *simple, > + GObject *object, > + GCancellable *cancellable) > +{ > + > + SpiceUsbredirChannel *channel = SPICE_USBREDIR_CHANNEL(object); > + SpiceUsbredirChannelPrivate *priv = channel->priv; > CHANNEL_DEBUG(channel, "disconnecting device from usb channel %p", > channel); > > switch (priv->state) { > @@ -438,7 +487,9 @@ void > spice_usbredir_channel_disconnect_device(SpiceUsbredirChannel *channel) > spice_usb_device_manager_get(session, NULL)); > } > /* This also closes the libusb handle we passed from open_device > */ > + usbredir_lock_lock(channel->priv->redirect_mutex); > usbredirhost_set_device(priv->host, NULL); > + usbredir_unlock_lock(channel->priv->redirect_mutex); > libusb_unref_device(priv->device); > priv->device = NULL; > g_boxed_free(spice_usb_device_get_type(), priv->spice_device); > @@ -611,7 +662,7 @@ static gboolean device_error(gpointer user_data) > > /* Check that the device has not changed before we manage to run */ > if (data->spice_device == priv->spice_device) { > - spice_usbredir_channel_disconnect_device(channel); > + spice_usbredir_channel_disconnect_device(NULL, G_OBJECT(channel), > NULL); > spice_usb_device_manager_device_error( > spice_usb_device_manager_get( > spice_channel_get_session(SPICE_CHANNEL(channel)), > NULL), > @@ -650,7 +701,9 @@ static void usbredir_handle_msg(SpiceChannel *c, > SpiceMsgIn *in) > priv->read_buf = buf; > priv->read_buf_size = size; > > + usbredir_lock_lock(priv->redirect_mutex); > r = usbredirhost_read_guest_data(priv->host); > + usbredir_unlock_lock(priv->redirect_mutex); > if (r != 0) { > SpiceUsbDevice *spice_device = priv->spice_device; > gchar *desc; > diff --git a/src/map-file b/src/map-file > index f9883b2..d3b55f0 100644 > --- a/src/map-file > +++ b/src/map-file > @@ -119,6 +119,7 @@ spice_usb_device_get_libusb_device; > spice_usb_device_get_type; > spice_g_udev_set_redirecting; > spice_g_udev_handle_device_change; > +spice_usb_device_manager_disconnect_device_async; > spice_usb_device_manager_set_redirecting; > spice_usb_device_manager_get_redirecting; > spice_usb_device_manager_can_redirect_device; > diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c > index db4944f..106330f 100644 > --- a/src/usb-device-manager.c > +++ b/src/usb-device-manager.c > @@ -1597,6 +1597,64 @@ gboolean > spice_usb_device_manager_connect_device_finish( > > return TRUE; > } > +typedef struct _disconnect_cb_data > +{ > + SpiceUsbDeviceManager *self; > + GSimpleAsyncResult *result; > + SpiceUsbDevice *device; > +} disconnect_cb_data; > + > +static > +void spice_usb_device_manager_disconnect_device_async_cb(GObject *gobject, > + GAsyncResult > *channel_res, > + gpointer user_data) > +{ > + disconnect_cb_data *data = user_data; > + SpiceUsbDeviceManager *self = SPICE_USB_DEVICE_MANAGER(data->self); > + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(data->result); > + > +#ifdef G_OS_WIN32 > + if (self->priv->use_usbclerk) { > + spice_usb_device_manager_driver_uninstall_async(self, > data->device); > + } > +#endif > + g_simple_async_result_complete(result); > + g_object_unref(result); > + g_free(data); > +} > + > +void > spice_usb_device_manager_disconnect_device_async(SpiceUsbDeviceManager > *self, > + SpiceUsbDevice > *device, > + GCancellable > *cancellable, > + GAsyncReadyCallback > callback, > + gpointer user_data) > +{ > + GSimpleAsyncResult *nested; > + GSimpleAsyncResult *result; > + g_return_if_fail(SPICE_IS_USB_DEVICE_MANAGER(self)); > + > + g_return_if_fail(device != NULL); > + > + SPICE_DEBUG("disconnecting device %p", device); > + > +#ifdef USE_USBREDIR > + 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 = 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 > +} > > /** > * spice_usb_device_manager_disconnect_device: > @@ -1618,7 +1676,7 @@ void > spice_usb_device_manager_disconnect_device(SpiceUsbDeviceManager *self, > > channel = spice_usb_device_manager_get_channel_for_dev(self, device); > if (channel) > - spice_usbredir_channel_disconnect_device(channel); > + spice_usbredir_channel_disconnect_device(NULL, G_OBJECT(channel), > NULL); > > #ifdef G_OS_WIN32 > if (self->priv->use_usbclerk) { > diff --git a/src/usb-device-manager.h b/src/usb-device-manager.h > index dca374d..abe80f7 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); > > diff --git a/src/usb-device-widget.c b/src/usb-device-widget.c > index 4c466ca..c50c3b6 100644 > --- a/src/usb-device-widget.c > +++ b/src/usb-device-widget.c > @@ -450,6 +450,17 @@ static void set_redirecting(SpiceUsbDeviceWidget > *self, gboolean val) > set_sensitive_all, (gpointer) &sensitive); > } > > +static void disconnect_cb(GObject *gobject, GAsyncResult *res, gpointer > user_data) > +{ > + connect_cb_data *data = user_data; > + SpiceUsbDeviceWidget *self = data->self; > + set_redirecting (self,FALSE); > + spice_usb_device_widget_update_status(self); > + g_object_unref(data->check); > + g_object_unref(data->self); > + g_free(data); > +} > + > static void connect_cb(GObject *gobject, GAsyncResult *res, gpointer > user_data) > { > SpiceUsbDeviceManager *manager = SPICE_USB_DEVICE_MANAGER(gobject); > @@ -501,8 +512,12 @@ static void checkbox_clicked_cb(GtkWidget *check, > gpointer user_data) > connect_cb, > data); > } else { > - spice_usb_device_manager_disconnect_device(priv->manager, > - device); > + spice_usb_device_manager_disconnect_device_async(priv->manager, > + device, > + NULL, > + disconnect_cb, > + data); > + > } > spice_usb_device_widget_update_status(self); > } > -- > 2.1.0 > >
_______________________________________________ Spice-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/spice-devel
