QEMU-Arm Archive on 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:22 UTC|newest]

Thread overview: 20+ 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
2026-10-12  1:28     ` 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox