All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jamin Lin <jamin_lin@aspeedtech.com>
To: "Cédric Le Goater" <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 v1 00/19] hw/usb: Add a usbredir server transport and AST1030 UDC support
Date: Tue, 22 Sep 2026 09:01:55 +0000	[thread overview]
Message-ID: <20260922090154.1792077-1-jamin_lin@aspeedtech.com> (raw)

This series redirects a USB device emulated in one QEMU instance to a USB
host controller emulated in another one, over the usbredir protocol, and
uses it to bring up the ASPEED AST1030 USB Device Controller (UDC).

It is the second step of a larger plan to model USB device-side support on
ASPEED BMC/BIC SoCs, which has three goals:

1. Model the ASPEED UDC (AST2600 / AST1030). The AST2600 also has USB host
   (EHCI) controllers, so that work targets the AST2600 UDC: its gadget can
   be attached to the SoC's own EHCI bus, letting the guest enumerate its
   own gadget and exercise the UDC end-to-end.  [Done]
   https://lore.kernel.org/qemu-devel/20260902021542.3194812-1-jamin_lin@aspeedtech.com/

2. AST1030 UDC. The AST1030 has no USB host controller, so testing its UDC
   needs a second QEMU instance. The UDC gadget is redirected out of the
   guest with libusbredir and attached to another QEMU that runs a USB host
   (a VMM, or an AST2600 / AST2700 guest).  [this series]

3. ASPEED vHub, as a longer-term goal towards BMC KVM / Virtual Media
   support in QEMU.  [future]

This series implements goal 2.

The transport
=============

usb-redir-server 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.

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 series)
             |                     ^
   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

usb-redir-server 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 usb-redir-server 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.

AST1030 gadget to an AST2700 host
=================================

        QEMU #1  -M ast1030-evb              QEMU #2  -M ast2700a2-evb
  +-----------------------------+      +-----------------------------+
  | Zephyr   usb_dc_aspeed      |      | Linux    ehci-platform      |
  +--------------+--------------+      +--------------+--------------+
                 | MMIO                               | MMIO
  +--------------v--------------+      +--------------v--------------+
  | aspeed.udc                  |      | EHCI3        (usb-bus.3)    |
  +--------------+--------------+      +--------------+--------------+
                 | USBPacket                          | USBPacket
  +--------------v--------------+      +--------------v--------------+
  | aspeed.udc-gadget           |      | usb-redir                   |
  +--------------+--------------+      +--------------+--------------+
                 | USBPacket                          |
  +--------------v--------------+                     |
  | usb-redir-server            |                     |
  +--------------+--------------+                     |
                 |                                    |
                 +=========== unix socket ============+
                           usbredir protocol

Testing
=======

1. AST1030 CDC-ACM gadget, enumerated by an AST2700 host
--------------------------------------------------------

The device side owns the socket and has to be started first.

  $ qemu-system-arm -M ast1030-evb -nographic \
        -kernel zephyr.bin \
        -chardev socket,id=u,path=/tmp/usbredir.sock,server=on,wait=off \
        -device usb-redir-server,id=udcredir,chardev=u \
        -device aspeed.udc-gadget,bus=udcredir.0,udc=/machine/soc/udc

  uart:~$ usb enable
  uart:~$ usb print 1

  $ qemu-system-aarch64 -M ast2700a2-evb -nographic \
        -drive file=image-bmc,if=mtd,format=raw -snapshot \
        -net nic -net user \
        -chardev socket,id=r,path=/tmp/usbredir.sock \
        -device usb-redir,chardev=r,bus=usb-bus.3

  root@ast2700-default:~# lsusb
  Bus 001 Device 001: ID 1d6b:0002 Linux 6.18.36 ehci_hcd EHCI Host Controller
  Bus 001 Device 002: ID 2245:1030 ZEPHYR Zephyr DFU sample

Data was checked:

  2700 -> 1030   echo '1234567890' > /dev/ttyACM0
                 1030 console: Print Data: 0x31 0x32 ... 0x30

2. A plain usb-storage exported the same way
--------------------------------------------

Any USBDevice can be exported, not just the UDC gadget. The machine on
the exporting side is only a container for usb-redir-server, so it does
not have to run anything.

  $ qemu-system-arm -M ast2600-evb -nographic -serial null \
        -chardev socket,id=u,path=/tmp/storage.sock,server=on,wait=off \
        -device usb-redir-server,id=keyredir,chardev=u \
        -drive id=usbdisk,if=none,file=disk.img,format=raw -snapshot \
        -device usb-storage,bus=keyredir.0,id=mystorage,drive=usbdisk

  $ qemu-system-aarch64 -M ast2700a2-evb -nographic \
        -drive file=image-bmc,if=mtd,format=raw -snapshot \
        -net nic -net user \
        -chardev socket,id=r,path=/tmp/storage.sock \
        -device usb-redir,chardev=r,bus=usb-bus.3

  root@ast2700-default:~# lsusb
  Bus 001 Device 001: ID 1d6b:0002 Linux 6.18.36 ehci_hcd EHCI Host Controller
  Bus 001 Device 002: ID 46f4:0001 QEMU QEMU USB HARDDRIVE

  root@ast2700-default:~# mount /dev/sda /mnt/usb
  MOUNTED

  A 4 MiB file was written, unmounted and remounted, and the sha256
  matched.

v1
 1. Add a usbredir server transport
    1. Add a usbredir server device
    2. Announce the exported device
    3. Implement control transfers
    4. Implement bulk and interrupt transfers
    5. Stream interrupt IN endpoints
 2. ASPEED UDC
    1. Make the SETUP buffer byte addressable
    2. Support single-stage IN transfers
    3. Clear EP_POOL_ACK when no endpoint ack is left
    4. Mask the reserved bits on register writes
    5. Use the endpoint max packet size for OUT transfers
    6. Test the usbredir server transport
    7. Add the USB device controller for AST1030
    
Jamin Lin (19):
  hw/usb/bus: Let a bus opt out of automatic hub insertion
  hw/usb/redirect-server: Add a usbredir server device
  hw/usb/redirect-server: Connect usbredirparser to a chardev
  hw/usb/redirect-server: Announce the exported device
  hw/usb/redirect-server: Implement control transfers
  hw/usb/redirect-server: Implement bulk and interrupt transfers
  hw/usb/redirect-server: Stream interrupt IN endpoints
  hw/arm/aspeed: Enable the usbredir server transport
  hw/usb/aspeed-udc: Make the SETUP buffer byte addressable
  hw/usb/aspeed-udc: Mask the reserved bits on register writes
  hw/usb/aspeed-udc: Clear EP_POOL_ACK when no endpoint ack is left
  hw/usb/aspeed-udc: Rename the transfer helpers after their DMA mode
  hw/usb/aspeed-udc: Store the EP_DMA_STS write first
  hw/usb/aspeed-udc: Pick the EP_DMA_STS path by direction
  hw/usb/aspeed-udc: Support single-stage IN transfers
  hw/usb/aspeed-udc: Use the endpoint max packet size for OUT transfers
  hw/usb/aspeed-udc: Add trace events for the transfer paths
  hw/arm/aspeed_ast10x0: Add the USB device controller
  tests/functional/arm/test_aspeed_ast1030: Test the usbredir server
    transport

 include/hw/arm/aspeed_soc.h                 |    1 +
 include/hw/usb/aspeed-udc.h                 |   13 +-
 include/hw/usb/redirect-server.h            |  116 ++
 include/hw/usb/usb.h                        |    1 +
 hw/arm/aspeed.c                             |    6 +
 hw/arm/aspeed_ast10x0.c                     |   17 +-
 hw/usb/aspeed-udc.c                         |  290 +++-
 hw/usb/bus.c                                |    3 +-
 hw/usb/redirect-server.c                    | 1604 +++++++++++++++++++
 hw/usb/meson.build                          |    3 +-
 hw/usb/trace-events                         |   36 +
 tests/functional/arm/meson.build            |    1 +
 tests/functional/arm/test_aspeed_ast1030.py |   52 +
 13 files changed, 2088 insertions(+), 55 deletions(-)
 create mode 100644 include/hw/usb/redirect-server.h
 create mode 100644 hw/usb/redirect-server.c

-- 
2.53.0


             reply	other threads:[~2026-09-22  9:04 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-22  9:01 Jamin Lin [this message]
2026-09-22  9:01 ` [PATCH v1 01/19] hw/usb/bus: Let a bus opt out of automatic hub insertion Jamin Lin
2026-09-22  9:01 ` [PATCH v1 02/19] hw/usb/redirect-server: Add a usbredir server device Jamin Lin
2026-09-22  9:01 ` [PATCH v1 03/19] hw/usb/redirect-server: Connect usbredirparser to a chardev Jamin Lin
2026-09-22  9:02 ` [PATCH v1 04/19] hw/usb/redirect-server: Announce the exported device Jamin Lin
2026-09-22  9:02 ` [PATCH v1 05/19] hw/usb/redirect-server: Implement control transfers Jamin Lin
2026-09-22  9:02 ` [PATCH v1 06/19] hw/usb/redirect-server: Implement bulk and interrupt transfers Jamin Lin
2026-09-22  9:02 ` [PATCH v1 07/19] hw/usb/redirect-server: Stream interrupt IN endpoints Jamin Lin
2026-09-22  9:02 ` [PATCH v1 08/19] hw/arm/aspeed: Enable the usbredir server transport Jamin Lin
2026-09-22  9:02 ` [PATCH v1 09/19] hw/usb/aspeed-udc: Make the SETUP buffer byte addressable Jamin Lin
2026-09-22  9:02 ` [PATCH v1 10/19] hw/usb/aspeed-udc: Mask the reserved bits on register writes Jamin Lin
2026-09-22  9:02 ` [PATCH v1 11/19] hw/usb/aspeed-udc: Clear EP_POOL_ACK when no endpoint ack is left Jamin Lin
2026-09-22  9:02 ` [PATCH v1 12/19] hw/usb/aspeed-udc: Rename the transfer helpers after their DMA mode Jamin Lin
2026-09-22  9:02 ` [PATCH v1 13/19] hw/usb/aspeed-udc: Store the EP_DMA_STS write first Jamin Lin
2026-09-22  9:02 ` [PATCH v1 14/19] hw/usb/aspeed-udc: Pick the EP_DMA_STS path by direction Jamin Lin
2026-09-22  9:02 ` [PATCH v1 15/19] hw/usb/aspeed-udc: Support single-stage IN transfers Jamin Lin
2026-09-22  9:02 ` [PATCH v1 16/19] hw/usb/aspeed-udc: Use the endpoint max packet size for OUT transfers Jamin Lin
2026-09-22  9:02 ` [PATCH v1 17/19] hw/usb/aspeed-udc: Add trace events for the transfer paths Jamin Lin
2026-09-22  9:02 ` [PATCH v1 18/19] hw/arm/aspeed_ast10x0: Add the USB device controller Jamin Lin
2026-09-22  9:02 ` [PATCH v1 19/19] tests/functional/arm/test_aspeed_ast1030: Test the usbredir server transport Jamin Lin
2026-09-30  7:48 ` [PATCH v1 00/19] hw/usb: Add a usbredir server transport and AST1030 UDC support Jamin Lin
2026-09-30  7:59   ` Cédric Le Goater
2026-09-30  8:05     ` Jamin Lin
2026-09-30  8:22       ` Cédric Le Goater

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=20260922090154.1792077-1-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.