Blame SOURCES/0008-usbredirect-use-the-correct-bus-device.patch

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