diff options
author | Iordan Iordanov <iiordanov@gmail.com> | 2021-12-23 21:17:45 -0500 |
---|---|---|
committer | Frediano Ziglio <freddy77@gmail.com> | 2022-01-28 12:20:46 +0000 |
commit | 9a0cec4b2f818d30eb2aa1dca8f635ece7650fa2 (patch) | |
tree | 026480060bd9d7077724a03bfed11c968ff03cb5 | |
parent | d5c01a322f488856f96325f281b59e5ec5d30ba4 (diff) |
Implemented the ability to allocate SpiceUsbDevice instances
by passing an open file descriptor in order to support the modern
Android USB device permissioning scheme.
During the process, a handle obtained by a call to
libusb_wrap_sys_device() is stored in the SpiceUsbDevice instance.
A call to libusb_open() is skipped if there is already a handle
present in the SpiceUsbDevice instance.
Finally, on Android, the option LIBUSB_OPTION_NO_DEVICE_DISCOVERY
must be set prior to the call to libusb_init() as per libusb
documentation.
Acked-by: Frediano Ziglio <freddy77@gmail.com>
-rw-r--r-- | doc/reference/spice-gtk-sections.txt | 1 | ||||
-rw-r--r-- | src/map-file | 1 | ||||
-rw-r--r-- | src/spice-glib-sym-file | 1 | ||||
-rw-r--r-- | src/usb-backend.c | 53 | ||||
-rw-r--r-- | src/usb-backend.h | 3 | ||||
-rw-r--r-- | src/usb-device-manager.c | 35 | ||||
-rw-r--r-- | src/usb-device-manager.h | 5 |
7 files changed, 90 insertions, 9 deletions
diff --git a/doc/reference/spice-gtk-sections.txt b/doc/reference/spice-gtk-sections.txt index d5a7d58..5cd6686 100644 --- a/doc/reference/spice-gtk-sections.txt +++ b/doc/reference/spice-gtk-sections.txt @@ -358,6 +358,7 @@ spice_usb_device_manager_connect_device_finish spice_usb_device_manager_disconnect_device spice_usb_device_manager_disconnect_device_async spice_usb_device_manager_disconnect_device_finish +spice_usb_device_manager_allocate_device_for_file_descriptor <SUBSECTION> SpiceUsbDevice spice_usb_device_get_description diff --git a/src/map-file b/src/map-file index 2dbb0d0..c0d8ca6 100644 --- a/src/map-file +++ b/src/map-file @@ -182,6 +182,7 @@ spice_usb_device_manager_get_devices_with_filter; spice_usb_device_manager_get_type; spice_usb_device_manager_is_device_connected; spice_usb_device_manager_is_redirecting; +spice_usb_device_manager_allocate_device_for_file_descriptor; spice_usb_device_manager_create_shared_cd_device; spice_usb_device_manager_is_device_shared_cd; spice_usb_device_widget_get_type; diff --git a/src/spice-glib-sym-file b/src/spice-glib-sym-file index 2cc80aa..ccaad1a 100644 --- a/src/spice-glib-sym-file +++ b/src/spice-glib-sym-file @@ -160,6 +160,7 @@ spice_usb_device_manager_get_devices_with_filter spice_usb_device_manager_get_type spice_usb_device_manager_is_device_connected spice_usb_device_manager_is_redirecting +spice_usb_device_manager_allocate_device_for_file_descriptor spice_usbredir_channel_get_type spice_util_get_debug spice_util_get_version_string diff --git a/src/usb-backend.c b/src/usb-backend.c index c76d576..930ae4e 100644 --- a/src/usb-backend.c +++ b/src/usb-backend.c @@ -49,6 +49,7 @@ struct _SpiceUsbDevice /* Pointer to device. Either real device (libusb_device) * or emulated one (edev) */ libusb_device *libusb_device; + libusb_device_handle *handle; SpiceUsbEmulatedDevice *edev; gint ref_count; SpiceUsbBackendChannel *attached_to; @@ -436,6 +437,9 @@ SpiceUsbBackend *spice_usb_backend_new(GError **error) SpiceUsbBackend *be; SPICE_DEBUG("%s >>", __FUNCTION__); be = g_new0(SpiceUsbBackend, 1); +#ifdef __ANDROID__ + libusb_set_option(NULL, LIBUSB_OPTION_NO_DEVICE_DISCOVERY); +#endif rc = libusb_init(&be->libusb_context); if (rc < 0) { const char *desc = libusb_strerror(rc); @@ -1208,7 +1212,7 @@ gboolean spice_usb_backend_channel_attach(SpiceUsbBackendChannel *ch, SpiceUsbDevice *dev, GError **error) { - int rc; + int rc = 0; SPICE_DEBUG("%s >> ch %p, dev %p (was attached %p)", __FUNCTION__, ch, dev, ch->attached); g_return_val_if_fail(dev != NULL, FALSE); @@ -1222,20 +1226,22 @@ gboolean spice_usb_backend_channel_attach(SpiceUsbBackendChannel *ch, return FALSE; } - libusb_device_handle *handle = NULL; + libusb_device_handle *handle = dev->handle; if (ch->state != USB_CHANNEL_STATE_INITIALIZING) { ch->state = USB_CHANNEL_STATE_HOST; } - /* - Under Windows we need to avoid updating - list of devices when we are acquiring the device - */ - set_redirecting(ch->backend, TRUE); + if (!handle) { + /* + Under Windows we need to avoid updating + list of devices when we are acquiring the device + */ + set_redirecting(ch->backend, TRUE); - rc = libusb_open(dev->libusb_device, &handle); + rc = libusb_open(dev->libusb_device, &handle); - set_redirecting(ch->backend, FALSE); + set_redirecting(ch->backend, FALSE); + } if (rc) { const char *desc = libusb_strerror(rc); @@ -1522,3 +1528,32 @@ spice_usb_backend_create_emulated_device(SpiceUsbBackend *be, return TRUE; } + +SpiceUsbDevice * +spice_usb_backend_allocate_device_for_file_descriptor(SpiceUsbBackend *be, + int file_descriptor, + GError **err) +{ + libusb_device_handle *handle = NULL; + libusb_context *ctx = be->libusb_context; + if (!ctx) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("libusb backend is null")); + return NULL; + } + + if (libusb_wrap_sys_device(ctx, (intptr_t)file_descriptor, &handle) < 0) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("libusb failed to create handle for specified file descriptor")); + return NULL; + } + + SpiceUsbDevice *device = allocate_backend_device(libusb_get_device(handle)); + if (!device) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("failed to allocate SpiceUsbDevice")); + } else { + device->handle = handle; + } + return device; +}
\ No newline at end of file diff --git a/src/usb-backend.h b/src/usb-backend.h index 4dff03f..3dd7dfc 100644 --- a/src/usb-backend.h +++ b/src/usb-backend.h @@ -93,5 +93,8 @@ void spice_usb_backend_channel_get_guest_filter(SpiceUsbBackendChannel *ch, int *count); void spice_usb_backend_return_write_data(SpiceUsbBackendChannel *ch, void *data); gchar *spice_usb_backend_device_get_description(SpiceUsbDevice *dev, const gchar *format); +SpiceUsbDevice *spice_usb_backend_allocate_device_for_file_descriptor(SpiceUsbBackend *be, + int file_descriptor, + GError **err); G_END_DECLS diff --git a/src/usb-device-manager.c b/src/usb-device-manager.c index 738eba5..24b6727 100644 --- a/src/usb-device-manager.c +++ b/src/usb-device-manager.c @@ -1521,6 +1521,41 @@ spice_usb_device_manager_is_device_shared_cd(SpiceUsbDeviceManager *manager, #endif } +/** + * spice_usb_device_manager_allocate_device_for_file_descriptor: + * @manager: (type SpiceUsbDeviceManager): the #SpiceUsbDeviceManager manager. + * @file_descriptor: an open file descriptor for the USB device. + * @err: (allow-none): a return location for a #GError, or %NULL. + * + * Allocates a SpiceUsbDevice instance for the specified file descriptor. + * + * Returns: (nullable) (transfer full): an allocated SpiceUsbDevice instance or %NULL in case of failure. + * + * Since: 0.40 + */ +SpiceUsbDevice * +spice_usb_device_manager_allocate_device_for_file_descriptor(SpiceUsbDeviceManager *manager, + int file_descriptor, + GError **err) +{ +#ifdef USE_USBREDIR + SpiceUsbDeviceManagerPrivate *priv = manager->priv; + if (!priv->context) { + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("libusb backend is null")); + return NULL; + } + + return spice_usb_backend_allocate_device_for_file_descriptor(priv->context, + file_descriptor, + err); +#else + g_set_error_literal(err, SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED, + _("USB redirection support not compiled in")); + return NULL; +#endif +} + #ifdef USE_USBREDIR /* * SpiceUsbDevice diff --git a/src/usb-device-manager.h b/src/usb-device-manager.h index 4747dd4..1cebeb8 100644 --- a/src/usb-device-manager.h +++ b/src/usb-device-manager.h @@ -152,6 +152,11 @@ gboolean spice_usb_device_manager_is_device_shared_cd(SpiceUsbDeviceManager *manager, SpiceUsbDevice *device); +SpiceUsbDevice * +spice_usb_device_manager_allocate_device_for_file_descriptor(SpiceUsbDeviceManager *manager, + int file_descriptor, + GError **err); + G_END_DECLS #endif /* __SPICE_USB_DEVICE_MANAGER_H__ */ |