All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jamin Lin <jamin_lin@aspeedtech.com>
To: "clg@kaod.org" <clg@kaod.org>,
	Peter Maydell <peter.maydell@linaro.org>,
	Steven Lee <steven_lee@aspeedtech.com>,
	Troy Lee <leetroy@gmail.com>,
	Kane Chen <kane_chen@aspeedtech.com>,
	Andrew Jeffery <andrew@codeconstruct.com.au>,
	Joel Stanley <joel@jms.id.au>,
	"open list:ASPEED BMCs" <qemu-arm@nongnu.org>,
	"open list:All patches CC here" <qemu-devel@nongnu.org>
Cc: Jamin Lin <jamin_lin@aspeedtech.com>, Troy Lee <troy_lee@aspeedtech.com>
Subject: [PATCH v2 2/8] hw/usb/redirect-server: Add a usbredir server device
Date: Mon, 5 Oct 2026 03:20:26 +0000	[thread overview]
Message-ID: <20261005032022.3980903-3-jamin_lin@aspeedtech.com> (raw)
In-Reply-To: <20261005032022.3980903-1-jamin_lin@aspeedtech.com>

Add "usb-redir-server". It exports a USB device from this QEMU to a USB
host in another QEMU, using the usbredir protocol. The other side is the
existing "usb-redir" device.

The exported device is plugged in with "-device <dev>,bus=<id>.0". So we
have to provide a USB bus. To find that bus, qdev starts at the main
system bus and walks down the tree. A device that is not on a bus is not
in the tree, so the bus it provides cannot be found. We have to sit on
the main system bus. That makes this a sysbus device, even though it has
no MMIO and no IRQ.

usbredir carries one device, not a bus. A hub cannot be exported because
the protocol has no device address field, so only the device on the
first port is redirected. To export several devices, run one
usb-redir-server per device, each with its own chardev.

The link to the remote host is a chardev, so this device cannot be
migrated. Its VMStateDescription says so with unmigratable.

Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
 include/hw/usb/redirect-server.h |  27 +++++++
 hw/usb/redirect-server.c         | 130 +++++++++++++++++++++++++++++++
 hw/usb/meson.build               |   3 +-
 3 files changed, 159 insertions(+), 1 deletion(-)
 create mode 100644 include/hw/usb/redirect-server.h
 create mode 100644 hw/usb/redirect-server.c

diff --git a/include/hw/usb/redirect-server.h b/include/hw/usb/redirect-server.h
new file mode 100644
index 0000000000..e81d4e0608
--- /dev/null
+++ b/include/hw/usb/redirect-server.h
@@ -0,0 +1,27 @@
+/*
+ * USB redirector, server side
+ *
+ * Copyright (c) 2026 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_USB_REDIRECT_SERVER_H
+#define HW_USB_REDIRECT_SERVER_H
+
+#include "hw/core/sysbus.h"
+#include "hw/usb/usb.h"
+#include "qom/object.h"
+
+#define TYPE_USB_REDIR_SERVER "usb-redir-server"
+OBJECT_DECLARE_SIMPLE_TYPE(USBRedirServer, USB_REDIR_SERVER)
+
+struct USBRedirServer {
+    SysBusDevice parent_obj;
+
+    /* USB bus */
+    USBBus bus;
+    USBPort port;
+};
+
+#endif /* HW_USB_REDIRECT_SERVER_H */
diff --git a/hw/usb/redirect-server.c b/hw/usb/redirect-server.c
new file mode 100644
index 0000000000..5f365f0a35
--- /dev/null
+++ b/hw/usb/redirect-server.c
@@ -0,0 +1,130 @@
+/*
+ * USB redirector, server side
+ *
+ * Copyright (c) 2026 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Exports a locally emulated USB device to a remote USB host over the
+ * usbredir protocol, so a device emulated in one QEMU instance can be
+ * enumerated by a host controller emulated in another one.
+ *
+ * Architecture. The left column is a request going to the device. The
+ * right column is the answer coming back. The middle hop carries
+ * usbredir messages over a socket. The top and bottom hops carry
+ * USBPackets inside QEMU.
+ *
+ *     remote QEMU: guest driver -> EHCI/XHCI
+ *              |                     ^
+ *    USBPacket |                     | USBPacket
+ *              v                     |
+ *     "usb-redir" (the client)
+ *              |                     ^
+ *     usbredir |   chardev socket    | usbredir
+ *              v                     |
+ *     usb-redir-server (the server, this file)
+ *              |                     ^
+ *    USBPacket |                     | USBPacket
+ *              v                     |
+ *     any USBDevice, "-device <dev>,bus=<id>.0"
+ *
+ * "usb-redir" (hw/usb/redirect.c) is the client:
+ *   - it takes a USBPacket from the remote guest and writes it to the
+ *     socket as a usbredir message
+ *   - it reads the answer from the socket and completes the USBPacket
+ *
+ * This file is the server. It does the same thing, but backwards:
+ *   - it reads a usbredir message from the socket and runs it as a
+ *     USBPacket on the bus below
+ *   - it takes the result of that USBPacket and writes it back to the
+ *     same socket as a usbredir message, for the client to read
+ *
+ * A USB device has to sit on a USB bus, and in QEMU a USB bus is always
+ * made by a host controller. So this file makes one and acts as the
+ * host controller on this side. It models no real chip: its cable is
+ * the chardev socket. The real host is in the other QEMU.
+ *
+ * usbredir carries one device, not a bus. A hub cannot be exported:
+ * the protocol has no device address field. To export several devices,
+ * run one usb-redir-server per device, each with its own chardev.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "migration/vmstate.h"
+#include "hw/usb/redirect-server.h"
+
+/*
+ * USB port ops
+ */
+
+static void usbredir_server_port_child_detach(USBPort *port, USBDevice *child)
+{
+    /* We only export the device on our own port. Nothing to do. */
+}
+
+static void usbredir_server_port_wakeup(USBPort *port)
+{
+    /* We do not pass remote wakeup to the host. Nothing to do. */
+}
+
+static USBPortOps usbredir_server_port_ops = {
+    .child_detach = usbredir_server_port_child_detach,
+    .wakeup = usbredir_server_port_wakeup,
+};
+
+/*
+ * USB bus ops
+ */
+
+static USBBusOps usbredir_server_bus_ops = {
+};
+
+/*
+ * Device registration
+ */
+
+static void usbredir_server_realize(DeviceState *dev, Error **errp)
+{
+    USBRedirServer *s = USB_REDIR_SERVER(dev);
+
+    /* One port: usbredir carries a single device. */
+    usb_bus_new(&s->bus, sizeof(s->bus), &usbredir_server_bus_ops, dev);
+    s->bus.no_auto_hub = true;
+    usb_register_port(&s->bus, &s->port, s, 0, &usbredir_server_port_ops,
+                      USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL |
+                      USB_SPEED_MASK_HIGH);
+}
+
+/*
+ * The link to the remote host is a chardev, and we cannot migrate
+ * that. So this device cannot be migrated either.
+ */
+static const VMStateDescription vmstate_usbredir_server = {
+    .name = TYPE_USB_REDIR_SERVER,
+    .unmigratable = 1,
+};
+
+static void usbredir_server_class_init(ObjectClass *klass, const void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->desc = "USB Redirection Server";
+    dc->realize = usbredir_server_realize;
+    dc->vmsd = &vmstate_usbredir_server;
+    set_bit(DEVICE_CATEGORY_USB, dc->categories);
+}
+
+static const TypeInfo usbredir_server_types[] = {
+    {
+        .name = TYPE_USB_REDIR_SERVER,
+        .parent = TYPE_DYNAMIC_SYS_BUS_DEVICE,
+        .instance_size = sizeof(USBRedirServer),
+        .class_init = usbredir_server_class_init,
+    },
+};
+module_obj(TYPE_USB_REDIR_SERVER);
+module_kconfig(USB);
+
+DEFINE_TYPES(usbredir_server_types)
diff --git a/hw/usb/meson.build b/hw/usb/meson.build
index 429dcd6a24..0061b935e6 100644
--- a/hw/usb/meson.build
+++ b/hw/usb/meson.build
@@ -78,7 +78,8 @@ endif
 if usbredir.found()
   usbredir_ss = ss.source_set()
   usbredir_ss.add(when: 'CONFIG_USB',
-                  if_true: [usbredir, files('redirect.c', 'quirks.c')])
+                  if_true: [usbredir, files('redirect.c', 'quirks.c',
+                                            'redirect-server.c')])
   hw_usb_modules += {'redirect': usbredir_ss}
 endif
 
-- 
2.43.0


  parent reply	other threads:[~2026-10-05  3:21 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-05  3:20 [PATCH v2 0/8] hw/usb: Add a usbredir server transport Jamin Lin
2026-10-05  3:20 ` [PATCH v2 1/8] hw/usb/bus: Let a bus opt out of automatic hub insertion Jamin Lin
2026-10-05  8:59   ` marcandre.lureau
2026-10-05  3:20 ` Jamin Lin [this message]
2026-10-05  8:59   ` [PATCH v2 2/8] hw/usb/redirect-server: Add a usbredir server device marcandre.lureau
2026-10-07  2:15     ` Jamin Lin
2026-10-07  6:11       ` Marc-André Lureau
2026-10-07  8:43         ` Jamin Lin
2026-10-05  3:20 ` [PATCH v2 3/8] hw/usb/redirect-server: Connect usbredirparser to a chardev Jamin Lin
2026-10-05  8:59   ` marcandre.lureau
2026-10-05  3:20 ` [PATCH v2 4/8] hw/usb/redirect-server: Announce the exported device Jamin Lin
2026-10-05  8:59   ` marcandre.lureau
2026-10-07  7:32     ` Jamin Lin
2026-10-05  3:20 ` [PATCH v2 5/8] hw/usb/redirect-server: Implement control transfers Jamin Lin
2026-10-05  3:20 ` [PATCH v2 6/8] hw/usb/redirect-server: Implement bulk and interrupt transfers Jamin Lin
2026-10-05  3:20 ` [PATCH v2 7/8] hw/usb/redirect-server: Stream interrupt IN endpoints Jamin Lin
2026-10-05  3:20 ` [PATCH v2 8/8] hw/arm/aspeed: Enable the usbredir server transport Jamin Lin
2026-10-05  8:59 ` [PATCH v2 0/8] hw/usb: Add a " marcandre.lureau
2026-10-07  8:42   ` Jamin Lin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261005032022.3980903-3-jamin_lin@aspeedtech.com \
    --to=jamin_lin@aspeedtech.com \
    --cc=andrew@codeconstruct.com.au \
    --cc=clg@kaod.org \
    --cc=joel@jms.id.au \
    --cc=kane_chen@aspeedtech.com \
    --cc=leetroy@gmail.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=steven_lee@aspeedtech.com \
    --cc=troy_lee@aspeedtech.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.