|
|
536eb0 |
From c32774c8a46aa04bf8f882ea552df8cb2d9f3a59 Mon Sep 17 00:00:00 2001
|
|
|
536eb0 |
From: Victor Toso <victortoso@redhat.com>
|
|
|
536eb0 |
Date: Thu, 22 Dec 2022 16:58:43 +0100
|
|
|
536eb0 |
Subject: [PATCH 8/8] usbredirect: use the correct bus-device
|
|
|
536eb0 |
|
|
|
536eb0 |
This patch is a continuation from:
|
|
|
536eb0 |
"usbredirect: allow multiple devices by vendor:product"
|
|
|
536eb0 |
|
|
|
536eb0 |
As we were using libusb_open_device_with_vid_pid(), if an user
|
|
|
536eb0 |
requested that device on 2-3 was redirected, we would instead get the
|
|
|
536eb0 |
vendor and product info of device on 2-3 and use that info to pick a
|
|
|
536eb0 |
usb device. This is wrong when multiple devices that shared
|
|
|
536eb0 |
vendor:product are plugged as libbusb_open_device_with_vid_pid()
|
|
|
536eb0 |
always return the same (first) device.
|
|
|
536eb0 |
|
|
|
536eb0 |
This commit now stores bus-device info and uses that to pick the usb
|
|
|
536eb0 |
device to redirect.
|
|
|
536eb0 |
|
|
|
536eb0 |
Related: https://gitlab.freedesktop.org/spice/usbredir/-/issues/29
|
|
|
536eb0 |
Signed-off-by: Victor Toso <victortoso@redhat.com>
|
|
|
536eb0 |
---
|
|
|
536eb0 |
tools/usbredirect.c | 63 ++++++++++++++++++++-------------------------
|
|
|
536eb0 |
1 file changed, 28 insertions(+), 35 deletions(-)
|
|
|
536eb0 |
|
|
|
536eb0 |
diff --git a/tools/usbredirect.c b/tools/usbredirect.c
|
|
|
536eb0 |
index 0b04418..cad9d23 100644
|
|
|
536eb0 |
--- a/tools/usbredirect.c
|
|
|
536eb0 |
+++ b/tools/usbredirect.c
|
|
|
536eb0 |
@@ -24,9 +24,14 @@
|
|
|
536eb0 |
|
|
|
536eb0 |
typedef struct redirect {
|
|
|
536eb0 |
struct {
|
|
|
536eb0 |
+ /* vendor:product */
|
|
|
536eb0 |
int vendor;
|
|
|
536eb0 |
int product;
|
|
|
536eb0 |
+ /* bus-device */
|
|
|
536eb0 |
+ int bus;
|
|
|
536eb0 |
+ int device_number;
|
|
|
536eb0 |
} device;
|
|
|
536eb0 |
+ bool by_bus;
|
|
|
536eb0 |
bool is_client;
|
|
|
536eb0 |
bool keepalive;
|
|
|
536eb0 |
bool watch_inout;
|
|
|
536eb0 |
@@ -46,7 +51,7 @@ typedef struct redirect {
|
|
|
536eb0 |
static void create_watch(redirect *self);
|
|
|
536eb0 |
|
|
|
536eb0 |
static bool
|
|
|
536eb0 |
-parse_opt_device(const char *device, int *vendor, int *product)
|
|
|
536eb0 |
+parse_opt_device(redirect *self, const char *device)
|
|
|
536eb0 |
{
|
|
|
536eb0 |
if (!device) {
|
|
|
536eb0 |
g_warning("No device to redirect. For testing only\n");
|
|
|
536eb0 |
@@ -54,37 +59,15 @@ parse_opt_device(const char *device, int *vendor, int *product)
|
|
|
536eb0 |
}
|
|
|
536eb0 |
|
|
|
536eb0 |
if (g_strrstr(device, "-") != NULL) {
|
|
|
536eb0 |
- /* Get vendor and product by bus and address number */
|
|
|
536eb0 |
+ self->by_bus = true;
|
|
|
536eb0 |
char **usbid = g_strsplit(device, "-", 2);
|
|
|
536eb0 |
if (usbid == NULL || usbid[0] == NULL || usbid[1] == NULL || usbid[2] != NULL) {
|
|
|
536eb0 |
g_strfreev(usbid);
|
|
|
536eb0 |
return false;
|
|
|
536eb0 |
}
|
|
|
536eb0 |
- gint64 bus = g_ascii_strtoll(usbid[0], NULL, 10);
|
|
|
536eb0 |
- gint64 addr = g_ascii_strtoll(usbid[1], NULL, 10);
|
|
|
536eb0 |
-
|
|
|
536eb0 |
- libusb_device **list = NULL;
|
|
|
536eb0 |
- ssize_t i, n;
|
|
|
536eb0 |
-
|
|
|
536eb0 |
- n = libusb_get_device_list(NULL, &list);
|
|
|
536eb0 |
- for (i = 0; i < n; i++) {
|
|
|
536eb0 |
- if (libusb_get_bus_number(list[i]) == bus &&
|
|
|
536eb0 |
- libusb_get_device_address(list[i]) == addr) {
|
|
|
536eb0 |
- break;
|
|
|
536eb0 |
- }
|
|
|
536eb0 |
- }
|
|
|
536eb0 |
-
|
|
|
536eb0 |
- if (i == n) {
|
|
|
536eb0 |
- libusb_free_device_list(list, true);
|
|
|
536eb0 |
- return false;
|
|
|
536eb0 |
- }
|
|
|
536eb0 |
-
|
|
|
536eb0 |
- struct libusb_device_descriptor desc;
|
|
|
536eb0 |
- libusb_get_device_descriptor(list[i], &desc);
|
|
|
536eb0 |
- *vendor = desc.idVendor;
|
|
|
536eb0 |
- *product = desc.idProduct;
|
|
|
536eb0 |
-
|
|
|
536eb0 |
- libusb_free_device_list(list, true);
|
|
|
536eb0 |
+ self->device.bus = g_ascii_strtoll(usbid[0], NULL, 10);
|
|
|
536eb0 |
+ self->device.device_number = g_ascii_strtoll(usbid[1], NULL, 10);
|
|
|
536eb0 |
+ g_strfreev(usbid);
|
|
|
536eb0 |
return true;
|
|
|
536eb0 |
}
|
|
|
536eb0 |
|
|
|
536eb0 |
@@ -94,12 +77,14 @@ parse_opt_device(const char *device, int *vendor, int *product)
|
|
|
536eb0 |
return false;
|
|
|
536eb0 |
}
|
|
|
536eb0 |
|
|
|
536eb0 |
- *vendor = g_ascii_strtoll(usbid[0], NULL, 16);
|
|
|
536eb0 |
- *product = g_ascii_strtoll(usbid[1], NULL, 16);
|
|
|
536eb0 |
+ self->device.vendor = g_ascii_strtoll(usbid[0], NULL, 16);
|
|
|
536eb0 |
+ self->device.product = g_ascii_strtoll(usbid[1], NULL, 16);
|
|
|
536eb0 |
g_strfreev(usbid);
|
|
|
536eb0 |
|
|
|
536eb0 |
- if (*vendor <= 0 || *vendor > 0xffff || *product < 0 || *product > 0xffff) {
|
|
|
536eb0 |
- g_printerr("Bad vendor:product values %04x:%04x", *vendor, *product);
|
|
|
536eb0 |
+ if (self->device.vendor <= 0 || self->device.vendor > 0xffff ||
|
|
|
536eb0 |
+ self->device.product < 0 || self->device.product > 0xffff) {
|
|
|
536eb0 |
+ g_printerr("Bad vendor:product values %04x:%04x",
|
|
|
536eb0 |
+ self->device.vendor, self->device.product);
|
|
|
536eb0 |
return false;
|
|
|
536eb0 |
}
|
|
|
536eb0 |
|
|
|
536eb0 |
@@ -166,7 +151,7 @@ parse_opts(int *argc, char ***argv)
|
|
|
536eb0 |
|
|
|
536eb0 |
self = g_new0(redirect, 1);
|
|
|
536eb0 |
self->watch_inout = true;
|
|
|
536eb0 |
- if (!parse_opt_device(device, &self->device.vendor, &self->device.product)) {
|
|
|
536eb0 |
+ if (!parse_opt_device(self, device)) {
|
|
|
536eb0 |
g_printerr("Failed to parse device: '%s' - expected: vendor:product or busnum-devnum\n", device);
|
|
|
536eb0 |
g_clear_pointer(&self, g_free);
|
|
|
536eb0 |
goto end;
|
|
|
536eb0 |
@@ -535,9 +520,16 @@ open_usb_device(redirect *self)
|
|
|
536eb0 |
continue;
|
|
|
536eb0 |
}
|
|
|
536eb0 |
|
|
|
536eb0 |
- if (self->device.vendor != desc.idVendor ||
|
|
|
536eb0 |
- self->device.product != desc.idProduct) {
|
|
|
536eb0 |
- continue;
|
|
|
536eb0 |
+ if (self->by_bus &&
|
|
|
536eb0 |
+ (self->device.bus != libusb_get_bus_number(devs[i]) ||
|
|
|
536eb0 |
+ self->device.device_number != libusb_get_device_address(devs[i]))) {
|
|
|
536eb0 |
+ continue;
|
|
|
536eb0 |
+ }
|
|
|
536eb0 |
+
|
|
|
536eb0 |
+ if (!self->by_bus &&
|
|
|
536eb0 |
+ (self->device.vendor != desc.idVendor ||
|
|
|
536eb0 |
+ self->device.product != desc.idProduct)) {
|
|
|
536eb0 |
+ continue;
|
|
|
536eb0 |
}
|
|
|
536eb0 |
|
|
|
536eb0 |
if (can_claim_usb_device(devs[i], &dev_handle)) {
|
|
|
536eb0 |
@@ -674,6 +666,7 @@ main(int argc, char *argv[])
|
|
|
536eb0 |
|
|
|
536eb0 |
socket_service = g_socket_service_new ();
|
|
|
536eb0 |
GInetAddress *iaddr = g_inet_address_new_loopback(G_SOCKET_FAMILY_IPV4);
|
|
|
536eb0 |
+
|
|
|
536eb0 |
GSocketAddress *saddr = g_inet_socket_address_new(iaddr, self->port);
|
|
|
536eb0 |
g_object_unref(iaddr);
|
|
|
536eb0 |
|
|
|
536eb0 |
--
|
|
|
536eb0 |
2.39.0
|
|
|
536eb0 |
|