Compare commits

..

No commits in common. 'c9' and 'cs10' have entirely different histories.
c9 ... cs10

2
.gitignore vendored

@ -1 +1,3 @@
SOURCES/usbredir-0.13.0.tar.xz SOURCES/usbredir-0.13.0.tar.xz
SOURCES/usbredir-0.13.0.tar.xz.sig
SOURCES/victortoso-E37A484F.keyring

@ -1 +1,3 @@
7a64e4d8a52527edf41bfcd60449b89db0c0f5b2 SOURCES/usbredir-0.13.0.tar.xz 7a64e4d8a52527edf41bfcd60449b89db0c0f5b2 SOURCES/usbredir-0.13.0.tar.xz
f8550b9235d4053e012c47ee239de296faa5f112 SOURCES/usbredir-0.13.0.tar.xz.sig
da7a529db1ea28a1540c5892ea9836abeb378c3e SOURCES/victortoso-E37A484F.keyring

@ -1,593 +0,0 @@
From e06a042c1c0eccefeccc63e419b9b09bef11e28f Mon Sep 17 00:00:00 2001
From: Victor Toso <victortoso@redhat.com>
Date: Wed, 30 Nov 2022 21:02:20 +0100
Subject: [PATCH] Revert "remove usbredirserver"
Content-type: text/plain
This reverts commit f4ffdce329305da2803684776f7659083a530819.
---
README.md | 4 +
meson.build | 1 +
usbredirserver/meson.build | 12 +
usbredirserver/usbredirserver.1 | 41 +++
usbredirserver/usbredirserver.c | 474 ++++++++++++++++++++++++++++++++
5 files changed, 532 insertions(+)
create mode 100644 usbredirserver/meson.build
create mode 100644 usbredirserver/usbredirserver.1
create mode 100644 usbredirserver/usbredirserver.c
diff --git a/README.md b/README.md
index ed04cca..2acb7b0 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,10 @@ The usbredirect binary is an usbredir client for exporting an USB device either
as TCP client or server, for use from another (virtual) machine through the
usbredir protocol.
+## usbredirserver
+
+A simple tcp server usb-host, using usbredirhost
+
## usbredirtestclient
A small testclient for the usbredir protocol over tcp, using usbredirparser
diff --git a/meson.build b/meson.build
index aac9909..e740778 100644
--- a/meson.build
+++ b/meson.build
@@ -103,6 +103,7 @@ if get_option('tools').enabled()
subdir('tools')
endif
if host_machine.system() != 'windows'
+ subdir('usbredirserver')
subdir('usbredirtestclient')
if get_option('fuzzing').enabled()
diff --git a/usbredirserver/meson.build b/usbredirserver/meson.build
new file mode 100644
index 0000000..de40681
--- /dev/null
+++ b/usbredirserver/meson.build
@@ -0,0 +1,12 @@
+usbredirserver_sources = [
+ 'usbredirserver.c',
+]
+
+executable('usbredirserver',
+ sources : usbredirserver_sources,
+ c_args : '-Wno-deprecated-declarations',
+ install : true,
+ install_dir: get_option('sbindir'),
+ dependencies : usbredir_host_lib_dep)
+
+install_man('usbredirserver.1')
diff --git a/usbredirserver/usbredirserver.1 b/usbredirserver/usbredirserver.1
new file mode 100644
index 0000000..d5a6793
--- /dev/null
+++ b/usbredirserver/usbredirserver.1
@@ -0,0 +1,41 @@
+.TH USBREDIRSERVER "1" "April 2012" "usbredirserver" "User Commands"
+.SH NAME
+usbredirserver \- exporting an USB device for use from another (virtual) machine
+.SH SYNOPSIS
+.B usbredirserver
+[\fI-p|--port <port>\fR] [\fI-v|--verbose <0-5>\fR] [\fI-4 <ipv4_addr|I-6 <ipv6_addr>]
+\fI<busnum-devnum|vendorid:prodid>\fR
+.SH DESCRIPTION
+usbredirserver is a small standalone server for exporting an USB device for
+use from another (virtual) machine through the usbredir protocol.
+.PP
+You can specify the USB device to export either by USB id in the form of
+\fI<vendorid>:<prodid>\fR, or by USB bus number and device address in the form
+of \fI<usbbus>-<usbaddr>\fR.
+.PP
+Notice that an instance of usbredirserver can only be used to export a
+single USB device. If you want to export multiple devices you can start
+multiple instances listening on different TCP ports.
+.SH OPTIONS
+.TP
+\fB\-p\fR, \fB\-\-port\fR=\fIPORT\fR
+Set the TCP port to listen on to \fIPORT\fR
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR=\fIVERBOSE\fR
+Set usbredirserver's verbosity level to \fIVERBOSE\fR, this mostly affects USB
+redirection related messages. Valid values are 0-5:
+.br
+0:Silent 1:Errors 2:Warnings 3:Info 4:Debug 5:Debug++
+.SH AUTHOR
+Written by Hans de Goede <hdegoede@redhat.com>
+.SH REPORTING BUGS
+You can report bugs to the spice-devel mailinglist:
+http://lists.freedesktop.org/mailman/listinfo/spice-devel
+or filing an issue at:
+https://gitlab.freedesktop.org/spice/usbredir/issues/new
+.SH COPYRIGHT
+Copyright 2010-2012 Red Hat, Inc.
+License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.
+.br
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
diff --git a/usbredirserver/usbredirserver.c b/usbredirserver/usbredirserver.c
new file mode 100644
index 0000000..badb7bc
--- /dev/null
+++ b/usbredirserver/usbredirserver.c
@@ -0,0 +1,474 @@
+/* usbredirserver.c simple usb network redirection tcp/ip server (host).
+
+ Copyright 2010-2011 Red Hat, Inc.
+
+ Red Hat Authors:
+ Hans de Goede <hdegoede@redhat.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+#include "usbredirhost.h"
+
+
+#define SERVER_VERSION "usbredirserver " PACKAGE_VERSION
+
+#if !defined(SOL_TCP) && defined(IPPROTO_TCP)
+#define SOL_TCP IPPROTO_TCP
+#endif
+#if !defined(TCP_KEEPIDLE) && defined(TCP_KEEPALIVE) && defined(__APPLE__)
+#define TCP_KEEPIDLE TCP_KEEPALIVE
+#endif
+
+static int verbose = usbredirparser_info;
+static int client_fd, running = 1;
+static libusb_context *ctx;
+static struct usbredirhost *host;
+
+static const struct option longopts[] = {
+ { "port", required_argument, NULL, 'p' },
+ { "verbose", required_argument, NULL, 'v' },
+ { "ipv4", required_argument, NULL, '4' },
+ { "ipv6", required_argument, NULL, '6' },
+ { "keepalive", required_argument, NULL, 'k' },
+ { "help", no_argument, NULL, 'h' },
+ { NULL, 0, NULL, 0 }
+};
+
+static void usbredirserver_log(void *priv, int level, const char *msg)
+{
+ if (level <= verbose)
+ fprintf(stderr, "%s\n", msg);
+}
+
+static int usbredirserver_read(void *priv, uint8_t *data, int count)
+{
+ int r = read(client_fd, data, count);
+ if (r < 0) {
+ if (errno == EAGAIN)
+ return 0;
+ return -1;
+ }
+ if (r == 0) { /* Client disconnected */
+ close(client_fd);
+ client_fd = -1;
+ }
+ return r;
+}
+
+static int usbredirserver_write(void *priv, uint8_t *data, int count)
+{
+ int r = write(client_fd, data, count);
+ if (r < 0) {
+ if (errno == EAGAIN)
+ return 0;
+ if (errno == EPIPE) { /* Client disconnected */
+ close(client_fd);
+ client_fd = -1;
+ return 0;
+ }
+ return -1;
+ }
+ return r;
+}
+
+static void usage(int exit_code, char *argv0)
+{
+ fprintf(exit_code? stderr:stdout,
+ "Usage: %s [-p|--port <port>] [-v|--verbose <0-5>] "
+ "[[-4|--ipv4 ipaddr]|[-6|--ipv6 ipaddr]] "
+ "[-k|--keepalive seconds] "
+ "<busnum-devnum|vendorid:prodid>\n",
+ argv0);
+ exit(exit_code);
+}
+
+static void invalid_usb_device_id(char *usb_device_id, char *argv0)
+{
+ fprintf(stderr, "Invalid usb device identifier: %s\n", usb_device_id);
+ usage(1, argv0);
+}
+
+static void run_main_loop(void)
+{
+ const struct libusb_pollfd **pollfds = NULL;
+ fd_set readfds, writefds;
+ int i, n, nfds;
+ struct timeval timeout, *timeout_p;
+
+ while (running && client_fd != -1) {
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+
+ FD_SET(client_fd, &readfds);
+ if (usbredirhost_has_data_to_write(host)) {
+ FD_SET(client_fd, &writefds);
+ }
+ nfds = client_fd + 1;
+
+ free(pollfds);
+ pollfds = libusb_get_pollfds(ctx);
+ for (i = 0; pollfds && pollfds[i]; i++) {
+ if (pollfds[i]->events & POLLIN) {
+ FD_SET(pollfds[i]->fd, &readfds);
+ }
+ if (pollfds[i]->events & POLLOUT) {
+ FD_SET(pollfds[i]->fd, &writefds);
+ }
+ if (pollfds[i]->fd >= nfds)
+ nfds = pollfds[i]->fd + 1;
+ }
+
+ if (libusb_get_next_timeout(ctx, &timeout) == 1) {
+ timeout_p = &timeout;
+ } else {
+ timeout_p = NULL;
+ }
+ n = select(nfds, &readfds, &writefds, NULL, timeout_p);
+ if (n == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
+ perror("select");
+ break;
+ }
+ memset(&timeout, 0, sizeof(timeout));
+ if (n == 0) {
+ libusb_handle_events_timeout(ctx, &timeout);
+ continue;
+ }
+
+ if (FD_ISSET(client_fd, &readfds)) {
+ if (usbredirhost_read_guest_data(host)) {
+ break;
+ }
+ }
+ /* usbredirhost_read_guest_data may have detected client disconnect */
+ if (client_fd == -1)
+ break;
+
+ if (FD_ISSET(client_fd, &writefds)) {
+ if (usbredirhost_write_guest_data(host)) {
+ break;
+ }
+ }
+
+ for (i = 0; pollfds && pollfds[i]; i++) {
+ if (FD_ISSET(pollfds[i]->fd, &readfds) ||
+ FD_ISSET(pollfds[i]->fd, &writefds)) {
+ libusb_handle_events_timeout(ctx, &timeout);
+ break;
+ }
+ }
+ }
+ if (client_fd != -1) { /* Broken out of the loop because of an error ? */
+ close(client_fd);
+ client_fd = -1;
+ }
+ free(pollfds);
+}
+
+static void quit_handler(int sig)
+{
+ running = 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int o, flags, server_fd = -1;
+ char *endptr, *delim;
+ int port = 4000;
+ int usbbus = -1;
+ int usbaddr = -1;
+ int usbvendor = -1;
+ int usbproduct = -1;
+ int on = 1;
+ int keepalive = -1;
+ char *ipv4_addr = NULL, *ipv6_addr = NULL;
+ union {
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ } serveraddr;
+ struct sigaction act;
+ libusb_device_handle *handle = NULL;
+
+ while ((o = getopt_long(argc, argv, "hp:v:4:6:k:", longopts, NULL)) != -1) {
+ switch (o) {
+ case 'p':
+ port = strtol(optarg, &endptr, 10);
+ if (*endptr != '\0') {
+ fprintf(stderr, "Invalid value for --port: '%s'\n", optarg);
+ usage(1, argv[0]);
+ }
+ break;
+ case 'v':
+ verbose = strtol(optarg, &endptr, 10);
+ if (*endptr != '\0') {
+ fprintf(stderr, "Invalid value for --verbose: '%s'\n", optarg);
+ usage(1, argv[0]);
+ }
+ break;
+ case '4':
+ ipv4_addr = optarg;
+ break;
+ case '6':
+ ipv6_addr = optarg;
+ break;
+ case 'k':
+ keepalive = strtol(optarg, &endptr, 10);
+ if (*endptr != '\0') {
+ fprintf(stderr, "Invalid value for -k: '%s'\n", optarg);
+ usage(1, argv[0]);
+ }
+ break;
+ case '?':
+ case 'h':
+ usage(o == '?', argv[0]);
+ break;
+ }
+ }
+ if (optind == argc) {
+ fprintf(stderr, "Missing usb device identifier argument\n");
+ usage(1, argv[0]);
+ }
+ delim = strchr(argv[optind], '-');
+ if (delim && delim[1]) {
+ usbbus = strtol(argv[optind], &endptr, 10);
+ if (*endptr != '-') {
+ invalid_usb_device_id(argv[optind], argv[0]);
+ }
+ usbaddr = strtol(delim + 1, &endptr, 10);
+ if (*endptr != '\0') {
+ invalid_usb_device_id(argv[optind], argv[0]);
+ }
+ } else {
+ delim = strchr(argv[optind], ':');
+ if (!delim || !delim[1]) {
+ invalid_usb_device_id(argv[optind], argv[0]);
+ }
+ usbvendor = strtol(argv[optind], &endptr, 16);
+ if (*endptr != ':' || usbvendor <= 0 || usbvendor > 0xffff) {
+ invalid_usb_device_id(argv[optind], argv[0]);
+ }
+ usbproduct = strtol(delim + 1, &endptr, 16);
+ /* Product ID 0000 is valid */
+ if (*endptr != '\0' || usbproduct < 0 || usbproduct > 0xffff) {
+ invalid_usb_device_id(argv[optind], argv[0]);
+ }
+ }
+ optind++;
+ if (optind != argc) {
+ fprintf(stderr, "Excess non option arguments\n");
+ usage(1, argv[0]);
+ }
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = quit_handler;
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGQUIT, &act, NULL);
+
+ if (libusb_init(&ctx)) {
+ fprintf(stderr, "Could not init libusb\n");
+ exit(1);
+ }
+
+#if LIBUSB_API_VERSION >= 0x01000106
+ libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, verbose);
+#else
+ libusb_set_debug(ctx, verbose);
+#endif
+
+ if (ipv4_addr) {
+ server_fd = socket(AF_INET, SOCK_STREAM, 0);
+ } else {
+ server_fd = socket(AF_INET6, SOCK_STREAM, 0);
+ }
+ if (server_fd == -1) {
+ perror("Error creating ip socket");
+ exit(1);
+ }
+
+ if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) {
+ perror("Error setsockopt(SO_REUSEADDR) failed");
+ exit(1);
+ }
+
+ memset(&serveraddr, 0, sizeof(serveraddr));
+
+ if (ipv4_addr) {
+ serveraddr.v4.sin_family = AF_INET;
+ serveraddr.v4.sin_port = htons(port);
+ if ((inet_pton(AF_INET, ipv4_addr,
+ &serveraddr.v4.sin_addr)) != 1) {
+ perror("Error convert ipv4 address");
+ exit(1);
+ }
+ } else {
+ serveraddr.v6.sin6_family = AF_INET6;
+ serveraddr.v6.sin6_port = htons(port);
+ if (ipv6_addr) {
+ if ((inet_pton(AF_INET6, ipv6_addr,
+ &serveraddr.v6.sin6_addr)) != 1) {
+ perror("Error convert ipv6 address");
+ exit(1);
+ }
+ } else {
+ serveraddr.v6.sin6_addr = in6addr_any;
+ }
+ }
+
+ if (bind(server_fd, (struct sockaddr *)&serveraddr,
+ sizeof(serveraddr))) {
+ perror("Error bind");
+ exit(1);
+ }
+
+ if (listen(server_fd, 1)) {
+ perror("Error listening");
+ exit(1);
+ }
+
+ while (running) {
+ client_fd = accept(server_fd, NULL, 0);
+ if (client_fd == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
+ perror("accept");
+ break;
+ }
+
+ if (keepalive > 0) {
+ int optval = 1;
+ socklen_t optlen = sizeof(optval);
+ if (setsockopt(client_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) == -1) {
+ if (errno != ENOTSUP) {
+ perror("setsockopt SO_KEEPALIVE error.");
+ break;
+ }
+ }
+ optval = keepalive; /* set default TCP_KEEPIDLE time from cmdline */
+ if (setsockopt(client_fd, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) == -1) {
+ if (errno != ENOTSUP) {
+ perror("setsockopt TCP_KEEPIDLE error.");
+ break;
+ }
+ }
+ optval = 10; /* set default TCP_KEEPINTVL time as 10s */
+ if (setsockopt(client_fd, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) == -1) {
+ if (errno != ENOTSUP) {
+ perror("setsockopt TCP_KEEPINTVL error.");
+ break;
+ }
+ }
+ optval = 3; /* set default TCP_KEEPCNT as 3 */
+ if (setsockopt(client_fd, SOL_TCP, TCP_KEEPCNT, &optval, optlen) == -1) {
+ if (errno != ENOTSUP) {
+ perror("setsockopt TCP_KEEPCNT error.");
+ break;
+ }
+ }
+ }
+
+ flags = fcntl(client_fd, F_GETFL);
+ if (flags == -1) {
+ perror("fcntl F_GETFL");
+ break;
+ }
+ flags = fcntl(client_fd, F_SETFL, flags | O_NONBLOCK);
+ if (flags == -1) {
+ perror("fcntl F_SETFL O_NONBLOCK");
+ break;
+ }
+
+ /* Try to find the specified usb device */
+ if (usbvendor != -1) {
+ handle = libusb_open_device_with_vid_pid(ctx, usbvendor,
+ usbproduct);
+ if (!handle) {
+ fprintf(stderr,
+ "Could not open an usb-device with vid:pid %04x:%04x\n",
+ usbvendor, usbproduct);
+ } else if (verbose >= usbredirparser_info) {
+ libusb_device *dev;
+ dev = libusb_get_device(handle);
+ fprintf(stderr, "Open a usb-device with vid:pid %04x:%04x on "
+ "bus %03x device %03x\n",
+ usbvendor, usbproduct,
+ libusb_get_bus_number(dev),
+ libusb_get_device_address(dev));
+ }
+ } else {
+ libusb_device **list = NULL;
+ ssize_t i, n;
+
+ n = libusb_get_device_list(ctx, &list);
+ for (i = 0; i < n; i++) {
+ if (libusb_get_bus_number(list[i]) == usbbus &&
+ libusb_get_device_address(list[i]) == usbaddr)
+ break;
+ }
+ if (i < n) {
+ if (libusb_open(list[i], &handle) != 0) {
+ fprintf(stderr,
+ "Could not open usb-device at busnum-devnum %d-%d\n",
+ usbbus, usbaddr);
+ }
+ } else {
+ fprintf(stderr,
+ "Could not find an usb-device at busnum-devnum %d-%d\n",
+ usbbus, usbaddr);
+ }
+ libusb_free_device_list(list, 1);
+ }
+ if (!handle) {
+ close(client_fd);
+ continue;
+ }
+
+ host = usbredirhost_open(ctx, handle, usbredirserver_log,
+ usbredirserver_read, usbredirserver_write,
+ NULL, SERVER_VERSION, verbose, 0);
+ if (!host)
+ exit(1);
+ run_main_loop();
+ usbredirhost_close(host);
+ handle = NULL;
+ }
+
+ close(server_fd);
+ libusb_exit(ctx);
+ exit(0);
+}
--
2.38.1

@ -1,135 +0,0 @@
From c1246d5d8332890df0dab7b29de86a42c2b7b36a Mon Sep 17 00:00:00 2001
From: Frediano Ziglio <freddy77@gmail.com>
Date: Fri, 16 Sep 2022 20:14:28 +0100
Subject: [PATCH 2/4] 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 ff910ab..a479c55 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)
@@ -125,7 +125,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;
@@ -133,7 +133,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 },
@@ -162,7 +162,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);
@@ -202,7 +202,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 = "";
@@ -280,7 +280,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;
@@ -308,7 +308,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;
@@ -336,7 +336,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;
}
@@ -387,7 +387,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));
@@ -419,7 +419,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;
}
@@ -431,7 +431,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 */
@@ -456,7 +456,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

@ -1,74 +0,0 @@
From 307747e2a73cf68a239ddd7b70333bbddf7f3e3b 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/4] 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 a479c55..afe9dee 100644
--- a/tools/usbredirect.c
+++ b/tools/usbredirect.c
@@ -415,6 +415,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)
@@ -437,12 +455,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;
}
@@ -552,17 +565,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

@ -1,106 +0,0 @@
From 3fcbd4a2569f227ae6fad6a37c8864d33271e5f4 Mon Sep 17 00:00:00 2001
From: Frediano Ziglio <freddy77@gmail.com>
Date: Sat, 17 Sep 2022 09:28:08 +0100
Subject: [PATCH 4/4] 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 afe9dee..59452aa 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)
{
@@ -163,6 +166,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);
@@ -277,6 +281,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)
{
@@ -322,6 +340,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);
@@ -401,13 +420,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:
@@ -428,7 +452,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

@ -1,51 +0,0 @@
From 79c3214ef403a801762a79702be20cf8a829e37b Mon Sep 17 00:00:00 2001
From: John Call <johnsimcall@gmail.com>
Date: Mon, 19 Dec 2022 19:01:50 +0000
Subject: [PATCH 5/7] 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 59452aa..88c553b 100644
--- a/tools/usbredirect.c
+++ b/tools/usbredirect.c
@@ -139,7 +139,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

@ -1,136 +0,0 @@
From ebfcffbee055ef5ddf981b77240223790dcc0140 Mon Sep 17 00:00:00 2001
From: Victor Toso <victortoso@redhat.com>
Date: Thu, 22 Dec 2022 16:13:08 +0100
Subject: [PATCH 6/7] 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 88c553b..78fe5c2 100644
--- a/tools/usbredirect.c
+++ b/tools/usbredirect.c
@@ -467,6 +467,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,
@@ -516,11 +600,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

@ -1,145 +0,0 @@
From c2fc30ec2b424ac6e45e45f756a2559848bd3116 Mon Sep 17 00:00:00 2001
From: Victor Toso <victortoso@redhat.com>
Date: Thu, 22 Dec 2022 16:58:43 +0100
Subject: [PATCH 7/7] 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 | 61 +++++++++++++++++++--------------------------
1 file changed, 26 insertions(+), 35 deletions(-)
diff --git a/tools/usbredirect.c b/tools/usbredirect.c
index 78fe5c2..0451dda 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,38 +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);
+ self->device.bus = g_ascii_strtoll(usbid[0], NULL, 10);
+ self->device.device_number = g_ascii_strtoll(usbid[1], NULL, 10);
g_strfreev(usbid);
-
- 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);
return true;
}
@@ -95,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;
}
@@ -167,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;
@@ -536,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)) {
--
2.39.0

@ -1,18 +1,14 @@
Name: usbredir Name: usbredir
Version: 0.13.0 Version: 0.13.0
Release: 2%{?dist} Release: 6%{?dist}
Summary: USB network redirection protocol libraries Summary: USB network redirection protocol libraries
License: LGPLv2+ License: LGPL-2.1-or-later
URL: https://spice-space.org/usbredir.html URL: https://www.spice-space.org/usbredir.html
Source0: http://spice-space.org/download/%{name}/%{name}-%{version}.tar.xz Source0: http://spice-space.org/download/%{name}/%{name}-%{version}.tar.xz
Patch0001: 0001-Revert-remove-usbredirserver.patch Source1: http://spice-space.org/download/%{name}/%{name}-%{version}.tar.xz.sig
Patch0002: 0002-Use-typedef-on-redirect-structure-to-simplify-some-s.patch Source2: victortoso-E37A484F.keyring
Patch0003: 0003-Factor-out-a-function-to-create-watches.patch BuildRequires: gnupg2
Patch0004: 0004-Recreate-watch-if-needed.patch BuildRequires: gcc g++
Patch0005: 0005-Add-documentation-examples-for-using-bus-device-iden.patch
Patch0006: 0006-usbredirect-allow-multiple-devices-by-vendor-product.patch
Patch0007: 0007-usbredirect-use-the-correct-bus-device.patch
BuildRequires: gcc
BuildRequires: glib2-devel BuildRequires: glib2-devel
BuildRequires: libusb1-devel >= 1.0.9 BuildRequires: libusb1-devel >= 1.0.9
BuildRequires: git-core BuildRequires: git-core
@ -42,16 +38,17 @@ The %{name}-devel package contains libraries and header files for
developing applications that use %{name}. developing applications that use %{name}.
%package server %package tools
Summary: Simple USB host TCP server Summary: usbredir utility tools
License: GPLv2+ License: GPLv2+
Requires: %{name}%{?_isa} = %{version}-%{release} Requires: %{name}%{?_isa} = %{version}-%{release}
%description server %description tools
A simple USB host TCP server, using libusbredirhost. Includes usbredirect that uses libusbredirhost to export an USB device for use
in another (virtual) machine
%prep %prep
gpgv2 --quiet --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0}
%autosetup -S git_am %autosetup -S git_am
@ -63,6 +60,7 @@ A simple USB host TCP server, using libusbredirhost.
%meson_build %meson_build
%install %install
%meson_install %meson_install
@ -81,49 +79,61 @@ A simple USB host TCP server, using libusbredirhost.
%{_libdir}/libusbredir*.so %{_libdir}/libusbredir*.so
%{_libdir}/pkgconfig/libusbredir*.pc %{_libdir}/pkgconfig/libusbredir*.pc
%files server %files tools
%{!?_licensedir:%global license %%doc} %{!?_licensedir:%global license %%doc}
%license COPYING %license COPYING
%{_bindir}/usbredirect %{_bindir}/usbredirect
%{_sbindir}/usbredirserver
%{_mandir}/man1/usbredirect.1* %{_mandir}/man1/usbredirect.1*
%{_mandir}/man1/usbredirserver.1*
%changelog %changelog
* Thu Jan 05 2023 Victor Toso <victortoso@redhat.com> - 0.13.0-2 * Tue Oct 29 2024 Troy Dawson <tdawson@redhat.com> - 0.13.0-6
- Fixes 100% CPU usage when usbredirect used as TCP server - Bump release for October 2024 mass rebuild:
Related: rhbz#2157520 Resolves: RHEL-64018
- Fixes USB redirection of identical devices
Resolves: rhbz#2157520 * Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 0.13.0-5
- Bump release for June 2024 mass rebuild
* Wed Nov 30 2022 Victor Toso <victortoso@redhat.com> - 0.13.0-1
- Rebase to latest upstream: 0.13.0 * Sat Jan 27 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.13.0-4
- Keeps usbredirserver binary (removed upstream) - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
Related: rhbz#2135760
* Sat Jul 22 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.13.0-3
* Thu Jul 28 2022 Victor Toso <victortoso@redhat.com> - 0.12.0-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
- Fix unserialization (migration regression)
Related: rhbz#2111368 * Sat Jan 21 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.13.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Wed Jan 19 2022 Victor Toso <victortoso@redhat.com> - 0.12.0-2
- Fix gating process * Wed Aug 03 2022 Victor Toso <victortoso@redhat.com> - 0.13.0-1
Related: rhbz#2020215 - Update to 0.13.0
Release 0.13.0 drops usbredirserver binary so we now have renamed
* Mon Nov 15 2021 Victor Toso <victortoso@redhat.com> - 0.12.0-1 usbredir-server pacakge to usbredir-tools which is more befitting what it
- Rebase to latest upstream: 0.12.0 contains
Related: rhbz#2020215
* Wed Jul 27 2022 Victor Toso <victortoso@redhat.com> - 0.12.0-4
* Wed Sep 15 2021 Victor Toso <victortoso@redhat.com> - 0.8.0-9 - Fixes unserialization (migration bug)
- Avoid use-after-free in serialization Resolves: rhbz#2096008
Related: rhbz#1992873
* Sat Jul 23 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.12.0-3
* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 0.8.0-8 - Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688 * Sat Jan 22 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.12.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 0.8.0-7
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 * Fri Nov 12 2021 Victor Toso <victortoso@redhat.com> - 0.12.0-1
- Update to 0.12.0
* Tue Aug 10 2021 Victor Toso <victortoso@redhat.com> - 0.11.0-1
- Update to 0.11.0
* Fri Jul 23 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.10.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Thu May 27 2021 Victor Toso <victortoso@redhat.com> - 0.10.0-1
- Update to 0.10.0
- Now uses meson to build
* Fri Apr 02 2021 Victor Toso <victortoso@redhat.com> - 0.9.0-1
- Update to 0.9.0
* Wed Jan 27 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.0-6 * Wed Jan 27 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.8.0-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild

Loading…
Cancel
Save