import usbredir-0.12.0-4.el8

This commit is contained in:
CentOS Sources 2023-01-27 02:16:33 +00:00 committed by root
parent 0bc205ee7e
commit 59f17083d5
7 changed files with 672 additions and 1 deletions

View File

@ -0,0 +1,135 @@
From e30b0ce5c46c0e2a75b6e38759876ba1369b2168 Mon Sep 17 00:00:00 2001
From: Frediano Ziglio <freddy77@gmail.com>
Date: Fri, 16 Sep 2022 20:14:28 +0100
Subject: [PATCH 3/8] Use typedef on redirect structure to simplify some
statements
Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
---
tools/usbredirect.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/tools/usbredirect.c b/tools/usbredirect.c
index 98e5a8c..89a42a6 100644
--- a/tools/usbredirect.c
+++ b/tools/usbredirect.c
@@ -22,7 +22,7 @@
#include <gio/gwin32outputstream.h>
#endif
-struct redirect {
+typedef struct redirect {
struct {
int vendor;
int product;
@@ -40,7 +40,7 @@ struct redirect {
int watch_server_id;
GMainLoop *main_loop;
-};
+} redirect;
static bool
parse_opt_device(const char *device, int *vendor, int *product)
@@ -124,7 +124,7 @@ parse_opt_uri(const char *uri, char **adr, int *port)
return true;
}
-static struct redirect *
+static redirect *
parse_opts(int *argc, char ***argv)
{
char *device = NULL;
@@ -132,7 +132,7 @@ parse_opts(int *argc, char ***argv)
char *localaddr = NULL;
gboolean keepalive = FALSE;
gint verbosity = 0; /* none */
- struct redirect *self = NULL;
+ redirect *self = NULL;
GOptionEntry entries[] = {
{ "device", 0, 0, G_OPTION_ARG_STRING, &device, "Local USB device to be redirected", NULL },
@@ -161,7 +161,7 @@ parse_opts(int *argc, char ***argv)
goto end;
}
- self = g_new0(struct redirect, 1);
+ self = g_new0(redirect, 1);
if (!parse_opt_device(device, &self->device.vendor, &self->device.product)) {
g_printerr("Failed to parse device: '%s' - expected: vendor:product or busnum-devnum\n", device);
g_clear_pointer(&self, g_free);
@@ -201,7 +201,7 @@ end:
static gpointer
thread_handle_libusb_events(gpointer user_data)
{
- struct redirect *self = (struct redirect *) user_data;
+ redirect *self = (redirect *) user_data;
int res = 0;
const char *desc = "";
@@ -279,7 +279,7 @@ usbredir_log_cb(void *priv, int level, const char *msg)
static int
usbredir_read_cb(void *priv, uint8_t *data, int count)
{
- struct redirect *self = (struct redirect *) priv;
+ redirect *self = (redirect *) priv;
GIOStream *iostream = G_IO_STREAM(self->connection);
GError *err = NULL;
@@ -307,7 +307,7 @@ usbredir_read_cb(void *priv, uint8_t *data, int count)
static int
usbredir_write_cb(void *priv, uint8_t *data, int count)
{
- struct redirect *self = (struct redirect *) priv;
+ redirect *self = (redirect *) priv;
GIOStream *iostream = G_IO_STREAM(self->connection);
GError *err = NULL;
@@ -335,7 +335,7 @@ usbredir_write_cb(void *priv, uint8_t *data, int count)
static void
usbredir_write_flush_cb(void *user_data)
{
- struct redirect *self = (struct redirect *) user_data;
+ redirect *self = (redirect *) user_data;
if (!self || !self->usbredirhost) {
return;
}
@@ -386,7 +386,7 @@ usbredir_unlock_lock(void *user_data)
static gboolean
connection_handle_io_cb(GIOChannel *source, GIOCondition condition, gpointer user_data)
{
- struct redirect *self = (struct redirect *) user_data;
+ redirect *self = (redirect *) user_data;
if (condition & G_IO_ERR || condition & G_IO_HUP) {
g_warning("Connection: err=%d, hup=%d - exiting", (condition & G_IO_ERR), (condition & G_IO_HUP));
@@ -418,7 +418,7 @@ end:
static gboolean
signal_handler(gpointer user_data)
{
- struct redirect *self = (struct redirect *) user_data;
+ redirect *self = (redirect *) user_data;
g_main_loop_quit(self->main_loop);
return G_SOURCE_REMOVE;
}
@@ -430,7 +430,7 @@ connection_incoming_cb(GSocketService *service,
GObject *source_object,
gpointer user_data)
{
- struct redirect *self = (struct redirect *) user_data;
+ redirect *self = (redirect *) user_data;
self->connection = g_object_ref(client_connection);
/* Add a GSource watch to handle polling for us and handle IO in the callback */
@@ -455,7 +455,7 @@ main(int argc, char *argv[])
goto err_init;
}
- struct redirect *self = parse_opts(&argc, &argv);
+ redirect *self = parse_opts(&argc, &argv);
if (!self) {
/* specific issues logged in parse_opts() */
return 1;
--
2.39.0

View File

@ -0,0 +1,74 @@
From 5399d3d5ce420891adfd4beedb023515a28ceab1 Mon Sep 17 00:00:00 2001
From: Frediano Ziglio <freddy77@gmail.com>
Date: Fri, 16 Sep 2022 20:14:28 +0100
Subject: [PATCH 4/8] Factor out a function to create watches
---
tools/usbredirect.c | 37 ++++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/tools/usbredirect.c b/tools/usbredirect.c
index 89a42a6..6a8b68b 100644
--- a/tools/usbredirect.c
+++ b/tools/usbredirect.c
@@ -414,6 +414,24 @@ end:
return G_SOURCE_REMOVE;
}
+static void
+create_watch(redirect *self)
+{
+ GSocket *socket = g_socket_connection_get_socket(self->connection);
+ int socket_fd = g_socket_get_fd(socket);
+ GIOChannel *io_channel =
+#ifdef G_OS_UNIX
+ g_io_channel_unix_new(socket_fd);
+#else
+ g_io_channel_win32_new_socket(socket_fd);
+#endif
+
+ self->watch_server_id = g_io_add_watch(io_channel,
+ G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR,
+ connection_handle_io_cb,
+ self);
+}
+
#ifdef G_OS_UNIX
static gboolean
signal_handler(gpointer user_data)
@@ -436,12 +454,7 @@ connection_incoming_cb(GSocketService *service,
/* Add a GSource watch to handle polling for us and handle IO in the callback */
GSocket *connection_socket = g_socket_connection_get_socket(self->connection);
g_socket_set_keepalive(connection_socket, self->keepalive);
- int socket_fd = g_socket_get_fd(connection_socket);
- GIOChannel *io_channel = g_io_channel_unix_new(socket_fd);
- self->watch_server_id = g_io_add_watch(io_channel,
- G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR,
- connection_handle_io_cb,
- self);
+ create_watch(self);
return G_SOURCE_REMOVE;
}
@@ -551,17 +564,7 @@ main(int argc, char *argv[])
GSocket *connection_socket = g_socket_connection_get_socket(self->connection);
g_socket_set_keepalive(connection_socket, self->keepalive);
- int socket_fd = g_socket_get_fd(connection_socket);
- GIOChannel *io_channel =
-#ifdef G_OS_UNIX
- g_io_channel_unix_new(socket_fd);
-#else
- g_io_channel_win32_new_socket(socket_fd);
-#endif
- self->watch_server_id = g_io_add_watch(io_channel,
- G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR,
- connection_handle_io_cb,
- self);
+ create_watch(self);
} else {
GSocketService *socket_service;
--
2.39.0

View File

@ -0,0 +1,106 @@
From f5e24c5cf77b92ab2737eb230db7ae0b2fb102cc Mon Sep 17 00:00:00 2001
From: Frediano Ziglio <freddy77@gmail.com>
Date: Sat, 17 Sep 2022 09:28:08 +0100
Subject: [PATCH 5/8] Recreate watch if needed
Do not always watch for output buffer.
Watching for output buffer if we don't have nothing to write
(which is the usual case) is consuming a lot of CPU.
This fixes https://gitlab.freedesktop.org/spice/usbredir/-/issues/24.
Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
---
tools/usbredirect.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/tools/usbredirect.c b/tools/usbredirect.c
index 6a8b68b..b6a30ad 100644
--- a/tools/usbredirect.c
+++ b/tools/usbredirect.c
@@ -29,6 +29,7 @@ typedef struct redirect {
} device;
bool is_client;
bool keepalive;
+ bool watch_inout;
char *addr;
int port;
int verbosity;
@@ -42,6 +43,8 @@ typedef struct redirect {
GMainLoop *main_loop;
} redirect;
+static void create_watch(redirect *self);
+
static bool
parse_opt_device(const char *device, int *vendor, int *product)
{
@@ -162,6 +165,7 @@ parse_opts(int *argc, char ***argv)
}
self = g_new0(redirect, 1);
+ self->watch_inout = true;
if (!parse_opt_device(device, &self->device.vendor, &self->device.product)) {
g_printerr("Failed to parse device: '%s' - expected: vendor:product or busnum-devnum\n", device);
g_clear_pointer(&self, g_free);
@@ -276,6 +280,20 @@ usbredir_log_cb(void *priv, int level, const char *msg)
g_log_structured(G_LOG_DOMAIN, glog_level, "MESSAGE", msg);
}
+static void
+update_watch(redirect *self)
+{
+ const bool watch_inout = usbredirhost_has_data_to_write(self->usbredirhost) != 0;
+ if (watch_inout == self->watch_inout) {
+ return;
+ }
+ g_source_remove(self->watch_server_id);
+ self->watch_server_id = 0;
+ self->watch_inout = watch_inout;
+
+ create_watch(self);
+}
+
static int
usbredir_read_cb(void *priv, uint8_t *data, int count)
{
@@ -321,6 +339,7 @@ usbredir_write_cb(void *priv, uint8_t *data, int count)
if (g_error_matches(err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
/* Try again later */
nbytes = 0;
+ update_watch(self);
} else {
if (err != NULL) {
g_warning("Failure at %s: %s", __func__, err->message);
@@ -400,13 +419,18 @@ connection_handle_io_cb(GIOChannel *source, GIOCondition condition, gpointer use
goto end;
}
}
- if (condition & G_IO_OUT) {
+ // try to write data in any case, to avoid having another iteration and
+ // creation of another watch if there is space in output buffer
+ if (usbredirhost_has_data_to_write(self->usbredirhost) != 0) {
int ret = usbredirhost_write_guest_data(self->usbredirhost);
if (ret < 0) {
g_critical("%s: Failed to write to guest", __func__);
goto end;
}
}
+
+ // update the watch if needed
+ update_watch(self);
return G_SOURCE_CONTINUE;
end:
@@ -427,7 +451,7 @@ create_watch(redirect *self)
#endif
self->watch_server_id = g_io_add_watch(io_channel,
- G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR,
+ G_IO_IN | G_IO_HUP | G_IO_ERR | (self->watch_inout ? G_IO_OUT : 0),
connection_handle_io_cb,
self);
}
--
2.39.0

View File

@ -0,0 +1,51 @@
From b3482e8d8f8970d481b9bfdb6662a8b67a973537 Mon Sep 17 00:00:00 2001
From: John Call <johnsimcall@gmail.com>
Date: Mon, 19 Dec 2022 19:01:50 +0000
Subject: [PATCH 6/8] Add documentation examples for using bus-device
identification
---
tools/usbredirect.1 | 6 ++++++
tools/usbredirect.c | 2 +-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/tools/usbredirect.1 b/tools/usbredirect.1
index d6b2a63..2be8be0 100644
--- a/tools/usbredirect.1
+++ b/tools/usbredirect.1
@@ -4,6 +4,9 @@ usbredirect \- exporting an USB device for use from another (virtual) machine
.SH SYNOPSIS
.B usbredirect
[\fI--device vendor:product\fR] [\fI--to addr:port\fR] [\fI--as addr:port\fR]
+.br
+.B usbredirect
+[\fI--device bus-device\fR] [\fI--to addr:port\fR] [\fI--as addr:port\fR]
.SH DESCRIPTION
usbredirect is an usbredir client for exporting an USB device either as TCP
client or server, for use from another (virtual) machine through the usbredir
@@ -11,6 +14,9 @@ protocol.
.PP
You can specify the USB device to export by USB id in the form of
\fI<vendorid>:<prodid>\fR.
+.br
+Or you can specify the USB device to export in the form of
+\fI<busnum>-<devnum>\fR.
.PP
Notice that an instance of usbredirect can only be used to export a single USB
device and it will close once the other side closes the connection. If you
diff --git a/tools/usbredirect.c b/tools/usbredirect.c
index b6a30ad..95f3580 100644
--- a/tools/usbredirect.c
+++ b/tools/usbredirect.c
@@ -138,7 +138,7 @@ parse_opts(int *argc, char ***argv)
redirect *self = NULL;
GOptionEntry entries[] = {
- { "device", 0, 0, G_OPTION_ARG_STRING, &device, "Local USB device to be redirected", NULL },
+ { "device", 0, 0, G_OPTION_ARG_STRING, &device, "Local USB device to be redirected identified as either VENDOR:PRODUCT \"0123:4567\" or BUS-DEVICE \"5-2\"", NULL },
{ "to", 0, 0, G_OPTION_ARG_STRING, &remoteaddr, "Client URI to connect to", NULL },
{ "as", 0, 0, G_OPTION_ARG_STRING, &localaddr, "Server URI to be run", NULL },
{ "keepalive", 'k', 0, G_OPTION_ARG_NONE, &keepalive, "If we should set SO_KEEPALIVE flag on underlying socket", NULL },
--
2.39.0

View File

@ -0,0 +1,136 @@
From 813afe206c8ff10cbbe715bf94980bf8ba6be70f Mon Sep 17 00:00:00 2001
From: Victor Toso <victortoso@redhat.com>
Date: Thu, 22 Dec 2022 16:13:08 +0100
Subject: [PATCH 7/8] usbredirect: allow multiple devices by vendor:product
Currently, if an user tries to redirect two devices with the same
vendor:product info, the second instance of usbredirect will not
succeed, leading to a segmentation fault.
The core of the problem is that usbredirect is using
libusb_open_device_with_vid_pid() which always returns the first
instance of a given vendor:product, leading the second instance of
usbredirect to give an usb device that is in use to usbredirhost.
This patch fixes the situation, making it possible to run usbredirect
with --device $vendor:$product multiple times. We do a early check
that we can claim the usb device, prior to handle it over to
usbredirhost.
Related: https://gitlab.freedesktop.org/spice/usbredir/-/issues/29
Signed-off-by: Victor Toso <victortoso@redhat.com>
---
tools/usbredirect.c | 90 ++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 85 insertions(+), 5 deletions(-)
diff --git a/tools/usbredirect.c b/tools/usbredirect.c
index 95f3580..0b04418 100644
--- a/tools/usbredirect.c
+++ b/tools/usbredirect.c
@@ -466,6 +466,90 @@ signal_handler(gpointer user_data)
}
#endif
+static bool
+can_claim_usb_device(libusb_device *dev, libusb_device_handle **handle)
+{
+ int ret = libusb_open(dev, handle);
+ if (ret != 0) {
+ g_debug("Failed to open device");
+ return false;
+ }
+
+ /* Opening is not enough. We need to check if device can be claimed
+ * for I/O operations */
+ struct libusb_config_descriptor *config = NULL;
+ ret = libusb_get_active_config_descriptor(dev, &config);
+ if (ret != 0 || config == NULL) {
+ g_debug("Failed to get active descriptor");
+ *handle = NULL;
+ return false;
+ }
+
+#if LIBUSBX_API_VERSION >= 0x01000102
+ libusb_set_auto_detach_kernel_driver(*handle, 1);
+#endif
+
+ int i;
+ for (i = 0; i < config->bNumInterfaces; i++) {
+ int interface_num = config->interface[i].altsetting[0].bInterfaceNumber;
+#if LIBUSBX_API_VERSION < 0x01000102
+ ret = libusb_detach_kernel_driver(handle, interface_num);
+ if (ret != 0 && ret != LIBUSB_ERROR_NOT_FOUND
+ && ret != LIBUSB_ERROR_NOT_SUPPORTED) {
+ g_error("failed to detach driver from interface %d: %s",
+ interface_num, libusb_error_name(ret));
+ *handle = NULL;
+ break
+ }
+#endif
+ ret = libusb_claim_interface(*handle, interface_num);
+ if (ret != 0) {
+ g_debug("Could not claim interface");
+ *handle = NULL;
+ break;
+ }
+ ret = libusb_release_interface(*handle, interface_num);
+ if (ret != 0) {
+ g_debug("Could not release interface");
+ *handle = NULL;
+ break;
+ }
+ }
+
+ libusb_free_config_descriptor(config);
+ return *handle != NULL;
+}
+
+static libusb_device_handle *
+open_usb_device(redirect *self)
+{
+ struct libusb_device **devs;
+ struct libusb_device_handle *dev_handle = NULL;
+ size_t i, ndevices;
+
+ ndevices = libusb_get_device_list(NULL, &devs);
+ for (i = 0; i < ndevices; i++) {
+ struct libusb_device_descriptor desc;
+ if (libusb_get_device_descriptor(devs[i], &desc) != 0) {
+ g_warning("Failed to get descriptor");
+ continue;
+ }
+
+ if (self->device.vendor != desc.idVendor ||
+ self->device.product != desc.idProduct) {
+ continue;
+ }
+
+ if (can_claim_usb_device(devs[i], &dev_handle)) {
+ break;
+ }
+ }
+
+ libusb_free_device_list(devs, 1);
+ return dev_handle;
+}
+
+
static gboolean
connection_incoming_cb(GSocketService *service,
GSocketConnection *client_connection,
@@ -515,11 +599,7 @@ main(int argc, char *argv[])
g_unix_signal_add(SIGTERM, signal_handler, self);
#endif
- /* This is binary is not meant to support plugins so it is safe to pass
- * NULL as libusb_context here and all subsequent calls */
- libusb_device_handle *device_handle = libusb_open_device_with_vid_pid(NULL,
- self->device.vendor,
- self->device.product);
+ libusb_device_handle *device_handle = open_usb_device(self);
if (!device_handle) {
g_printerr("Failed to open device!\n");
goto err_init;
--
2.39.0

View File

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

View File

@ -1,6 +1,6 @@
Name: usbredir
Version: 0.12.0
Release: 2%{?dist}
Release: 4%{?dist}
Summary: USB network redirection protocol libraries
Group: System Environment/Libraries
License: LGPLv2+
@ -8,6 +8,12 @@ URL: https://www.spice-space.org/usbredir.html
Source0: http://spice-space.org/download/%{name}/%{name}-%{version}.tar.xz
Patch0001: 0001-usbredirparser-Fix-unserialize-on-pristine-check.patch
Patch0002: 0002-usbredirparser-reset-parser-s-fields-on-unserialize.patch
Patch0003: 0003-Use-typedef-on-redirect-structure-to-simplify-some-s.patch
Patch0004: 0004-Factor-out-a-function-to-create-watches.patch
Patch0005: 0005-Recreate-watch-if-needed.patch
Patch0006: 0006-Add-documentation-examples-for-using-bus-device-iden.patch
Patch0007: 0007-usbredirect-allow-multiple-devices-by-vendor-product.patch
Patch0008: 0008-usbredirect-use-the-correct-bus-device.patch
BuildRequires: glib2-devel
BuildRequires: libusb1-devel >= 1.0.9
BuildRequires: git-core
@ -89,6 +95,16 @@ A simple USB host TCP server, using libusbredirhost.
%changelog
* Wed Jan 25 2023 Victor Toso <victortoso@redhat.com> - 0.12.0-4
- Rebuild to fix lack of elf sections
Related: rhbz#2157521
* Thu Jan 05 2023 Victor Toso <victortoso@redhat.com> - 0.12.0-3
- Fixes 100% CPU usage when usbredirect used as TCP server.
Related: rhbz#2157521
- Fixes USB redirection of identical devices.
Resolves: rhbz#2157521
* Wed Jul 27 2022 Victor Toso <victortoso@redhat.com> - 0.12.0-2
- Fixes unserialization on migration
Resolves: rhbz#2111351