summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIordan Iordanov <iiordanov@gmail.com>2021-12-23 21:17:45 -0500
committerFrediano Ziglio <freddy77@gmail.com>2022-01-28 12:20:46 +0000
commit9a0cec4b2f818d30eb2aa1dca8f635ece7650fa2 (patch)
tree026480060bd9d7077724a03bfed11c968ff03cb5
parentd5c01a322f488856f96325f281b59e5ec5d30ba4 (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.txt1
-rw-r--r--src/map-file1
-rw-r--r--src/spice-glib-sym-file1
-rw-r--r--src/usb-backend.c53
-rw-r--r--src/usb-backend.h3
-rw-r--r--src/usb-device-manager.c35
-rw-r--r--src/usb-device-manager.h5
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__ */