Commit 5b899dbf authored by iordan iordanov's avatar iordan iordanov
Browse files

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.
parent 0031c57f
Pipeline #471910 passed with stage
in 4 minutes and 1 second
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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
......@@ -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
......@@ -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: 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: 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
......
......@@ -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__ */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment