Linux USB
 help / color / mirror / Atom feed
* [RFC PATCH 0/9] rust: usb: synchronous bulk/control transfers + helpers
@ 2026-06-17 14:59 Mike Lothian
  2026-06-17 14:59 ` [RFC PATCH 1/9] rust: usb: add synchronous bulk transfer support Mike Lothian
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Mike Lothian @ 2026-06-17 14:59 UTC (permalink / raw)
  To: rust-for-linux
  Cc: Mike Lothian, linux-usb, Greg Kroah-Hartman, Daniel Almeida,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Alexandre Courbot, Shankari Anand, linux-kernel

This RFC series adds the synchronous USB transfer primitives a driver
needs at bring-up to the Rust USB abstraction (rust/kernel/usb.rs), which
currently lets a driver bind a device (probe/disconnect) but provides no
way to move data, so any real driver still has to drop to C:

  1/9  bulk_send() / bulk_recv()        over usb_bulk_msg()
  2/9  control_send() / control_recv()  over usb_control_msg_send()/_recv()
  3/9  set_interface()                  over usb_set_interface()
  4/9  Interface::number()              bInterfaceNumber accessor
  5/9  clear_halt()                     over usb_clear_halt()
  6/9  interrupt_recv()                 over usb_interrupt_msg()
  7/9  reset_configuration()            over usb_reset_configuration()
  8/9  bulk_in_queue() / BulkInQueue    persistently-queued async bulk IN
  9/9  bulk_out_queue() / BulkOutQueue  pipelined async bulk OUT

usb::Device is made public; each method documents its blocking/sleeping
context, timeouts are taken as a Delta, transfer lengths are
range-checked into the C int types, and every FFI call carries a SAFETY
comment. All the transfer methods take the endpoint's bEndpointAddress as
it appears in the descriptor (e.g. 0x84) and use its low four bits as the
endpoint number, so the convention is uniform across bulk_send/bulk_recv,
interrupt_recv and clear_halt. The function-like pipe macros
(usb_sndbulkpipe(), usb_rcvbulkpipe(), usb_rcvintpipe()) are exposed via
rust_helper_* shims, matching the existing
rust_helper_interface_to_usbdev() in the same file.

clear_halt() selects an IN or OUT pipe from the USB_DIR_IN bit of the
endpoint address so it can clear a stall on either direction;
interrupt_recv() uses usb_interrupt_msg() over an interrupt pipe (built
with the new rust_helper_usb_rcvintpipe() shim) so the URB's transfer
type matches the endpoint, rather than a bulk pipe with the type bits
patched.

DMA-buffer handling: usb_bulk_msg()/usb_interrupt_msg() DMA directly
to/from the transfer buffer, which must therefore be kmalloc'd
(DMA-capable) memory. Rather than expose that as an unenforced
precondition on a safe method taking &[u8] (which would be unsound for an
arbitrary stack or .rodata slice), bulk_send/bulk_recv/interrupt_recv
copy through an internally-allocated kmalloc'd bounce buffer, so any
slice is accepted; the control path already bounces inside
usb_control_msg_send()/_recv(). This keeps the methods honestly safe at
the cost of one copy. The open question for reviewers is whether that
bounce is the right default or whether a dedicated DMA-buffer type should
be taken for a zero-copy fast path; feedback on that API shape is a main
reason this is posted as an RFC.

Patches 8 and 9 add the asynchronous URB path (usb_submit_urb) for
endpoints where the per-transfer device-ACK round-trip of the synchronous
calls is too costly. bulk_in_queue() keeps depth IN URBs perpetually
posted (the always-pending-IN behaviour of a libusb event loop) and hands
each completion to BulkInQueue::recv(); bulk_out_queue() pipelines OUT
URBs submit-and-reap so a back-to-back burst is not serialised. The URBs
are filled with usb_fill_bulk_urb() and re-armed with reinit_completion()
(both static-inline, reached through rust_helper_ shims), the completion
callback only signals a struct completion, and each queue owns its URBs in
a fixed slot pool for its whole lifetime, killing them directly on Drop.

The additions were developed for an out-of-tree in-kernel Rust
DisplayLink DL3 dock driver, but are generic and not driver-specific.
Each patch builds on its own, so the tree stays bisectable; the full
series builds in-tree on drm-next (LLVM/Rust) with no new warnings.

Mike Lothian (9):
  rust: usb: add synchronous bulk transfer support
  rust: usb: add synchronous control transfer support
  rust: usb: add usb::Device::set_interface()
  rust: usb: add usb::Interface::number()
  rust: usb: add usb::Device::clear_halt()
  rust: usb: add usb::Device::interrupt_recv()
  rust: usb: add usb::Device::reset_configuration()
  rust: usb: add an asynchronous persistently-queued bulk IN reader
  rust: usb: add an asynchronous pipelined bulk OUT queue

 rust/helpers/usb.c |  35 +++
 rust/kernel/usb.rs | 682 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 716 insertions(+), 1 deletion(-)

--
2.54.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-06-17 16:07 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-17 14:59 [RFC PATCH 0/9] rust: usb: synchronous bulk/control transfers + helpers Mike Lothian
2026-06-17 14:59 ` [RFC PATCH 1/9] rust: usb: add synchronous bulk transfer support Mike Lothian
2026-06-17 16:07   ` Danilo Krummrich
2026-06-17 14:59 ` [RFC PATCH 2/9] rust: usb: add synchronous control " Mike Lothian
2026-06-17 14:59 ` [RFC PATCH 3/9] rust: usb: add usb::Device::set_interface() Mike Lothian
2026-06-17 14:59 ` [RFC PATCH 4/9] rust: usb: add usb::Interface::number() Mike Lothian
2026-06-17 14:59 ` [RFC PATCH 5/9] rust: usb: add usb::Device::clear_halt() Mike Lothian
2026-06-17 14:59 ` [RFC PATCH 6/9] rust: usb: add usb::Device::interrupt_recv() Mike Lothian
2026-06-17 14:59 ` [RFC PATCH 7/9] rust: usb: add usb::Device::reset_configuration() Mike Lothian
2026-06-17 14:59 ` [RFC PATCH 8/9] rust: usb: add an asynchronous persistently-queued bulk IN reader Mike Lothian
2026-06-17 14:59 ` [RFC PATCH 9/9] rust: usb: add an asynchronous pipelined bulk OUT queue Mike Lothian

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox