| Age | Commit message (Collapse) | Author |
|
- rp2040 dcd_edpt_clear_stall: the toggle-reset re-issue rewound remaining_len
only for IN, but bufctrl_prepare16() pre-subtracts it for OUT too, so an OUT
re-issue was short by the still-armed buffers. Rewind both directions (user_buf
only for IN, which advances at DPRAM-copy time). Validated: pico usbtest 30/30.
- usb_recover.sh: refuse pci-rebind/reset/bind on a BDF that is not a USB
controller (class 0x0c03xx), so a stray/mistyped address can't disturb storage
or NICs on the shared HIL host. Guard tested against real BDFs.
- ip3511 dcd_edpt_open: make it tolerant of reopening a still-armed endpoint
instead of asserting it disabled -- retire via EPSKIP (UM11126 41.7.6/41.8.3)
then force disabled. This is the correct ISO_ALLOC reopen contract, since
usbd_edpt_close() is a no-op there. NOTE: audio/video streaming EPs already use
usbd_edpt_iso_activate() on ISO_ALLOC, so there is no in-tree trigger; this is
defensive hardening for a class that reopens a non-iso EP via usbd_edpt_open
(e.g. a UVC device with a notification EP + VC SET_INTERFACE). Verified on HW:
lpc11u37 usbtest 30/30 and video_capture SET_INTERFACE cycling both fine.
- vendor_device set_alt: abort the outgoing altsetting's bulk/interrupt endpoints
before dropping them, so an endpoint absent from the target altsetting can't
stay armed and hold its usbd claim. (No in-tree trigger: usbtest uses a single
non-zero altsetting; defensive robustness for multi-alt vendor devices.)
- vendor_device tud_vendor_n_mounted(): count iso endpoints too, so an iso-only
altsetting reports mounted. (No in-tree trigger: usbtest alt1 always has bulk.)
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
|
|
- dcd(nrf5x): dcd_edpt_iso_activate drops a stale armed transfer (started/
data_received/iso_in_transfer_ready) — there is no dcd close on this port, so
a transfer armed before SET_INTERFACE would trip TU_ASSERT(!xfer->started) on
the class's next arm after usbd reset the endpoint's claim state.
- class(vendor): tud_vendor_n_mounted() counts the interrupt endpoints, so an
interrupt-only vendor interface (bulk absent) reports mounted.
- example(usbtest): int/iso write lengths follow the negotiated speed
(tud_speed_get), not the compile-time capability — a high-speed build
enumerated at full speed serves the FS descriptor (mps 64/128) and must not
submit HS-sized packets.
- test/hil: test_example() return annotation matches the (err, status, metric)
3-tuple it returns.
Verified: feather_nrf52840_express and raspberry_pi_pico 30/30 through the HIL
battery; pico/feather/ch32v307-usbhs builds clean.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
|
|
- dcd(rp2040): rewind IN staging before the clear-halt re-issue. Staging advances
user_buf/remaining_len when packets are copied into DPRAM, before the host has
consumed them; aborting and re-issuing from the advanced pointer silently
skipped the staged-but-unsent bytes.
- dcd(ip3511): dcd_edpt_iso_activate aborts a transfer still armed from the
previous altsetting (clear Active on both buffer slots) so the hardware can't
keep servicing the old descriptor against the class's fresh queueing.
- dcd(rusb2): reuse an endpoint's existing pipe in dcd_edpt_open. usbd_edpt_close
is a no-op on ISO_ALLOC ports, so a class's close/open across SET_INTERFACE
would allocate a second pipe with the same EPNUM and leak pipes.
- class(vendor): the buffered-mode free-slot check also tests the interrupt
endpoints, so an interrupt-only vendor interface isn't clobbered as "free".
- bsp(ch32v30x): board_get_unique_id respects max_len and copies bytes
(alignment-safe) instead of writing 12 bytes through a uint32_t cast.
- test/hil/usbtest.py: treat same-serial multi-matches as ambiguous and retry
until the dual-port stale node drops (nanoch32v203/ch32v307 variants); reprobe
a binding that predates the dynamic-id re-registration so a stale capability
profile can't survive; skip the remove_id/unbind cleanup after an unrecovered
kernel-side hang (it would join the D-state convoy and deadlock the bus).
- usbtest skip.txt: add the families whose DCD refuses dcd_edpt_iso_alloc
(CXD56, FT90X, LPC175X_6X, LPC40XX, NUC100/120/505, PIC32MZ, SAMG, SAMX7X,
VALENTYUSB_EPTRI) — tier 4 cannot enumerate there.
- test/hil/tinyusb-sudoer: note that '#1000' is a sudoers UID specifier, not a
comment (the review misread the grants as commented out).
Refuted in review threads: nrf5x ISOSPLIT keeps reserve-max per-configuration
allocation semantics (iso_alloc is per-config, not per-alt); the LPC EP-number
claim (default descriptor uses EP1-3; lpcxpresso11u37 passes 30/30 on HW); the
vendor alt-0 "abort" concern (host cannot address endpoints outside the active
altsetting; usbd_edpt_iso_activate resets state on re-entry).
Verified on hardware: raspberry_pi_pico, lpcxpresso11u37, ra4m1_ek all 30/30
through the HIL battery after the changes; builds clean incl. buffered-mode
vendor (webusb_serial).
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
|
|
overflow
Four PR-CI failures, each with a distinct root cause:
- class/vendor: mark the shared non-buffered transfer helpers TU_ATTR_UNUSED.
In buffered mode with the int/iso endpoint gates off none is referenced, and
clang (-Wunused-function -Werror) and IAR (Error[Pe177]) reject an unused
static — gcc does not, which is why only the clang/IAR matrix failed.
- bsp/ch32v20x: keep dcd_int_handler alive under LTO. The `call` sits inside
naked asm where LTO cannot see it, so -flto make builds internalized the
symbol and every ch32v20x device example failed to link (cmake has no LTO,
which masked it). A TU_ATTR_USED function-pointer reference pins it.
- usbtest: LPC11/13 (ip3511 FS) keep endpoint buffers in a dedicated 2 KB USB
RAM; the 2048 B bulk epbuf overflowed it (RamUsb2 150%) in make builds. Use
512 B (= 8 FS packets) on those parts; lpcxpresso11u37 still passes 30/30.
- test/hil: skip device/usbtest on lpcxpresso43s67 (hfp rig) — its ip3511 HS
port wedges from the first control case (1/30) and needs on-rig debugging.
Verified: make builds link for nanoch32v203 (dfu_runtime + usbtest),
lpcxpresso11u37 and lpcxpresso1347 (RamUsb2 75%); buffered-mode webusb_serial
builds; 61/61 unit tests; lpcxpresso11u37 usbtest 30/30 on hardware with the
smaller epbuf.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
|
|
# Conflicts:
# lib/rt-thread/port/msc_device_port.c
# src/device/usbd.c
|
|
#12 dcd(rusb2): key the bulk-OUT clear-stall re-arm on a new per-pipe `queued`
flag instead of `pipe.buf != NULL`. A zero-length OUT read leaves buf==NULL
while still armed, so the old test skipped the re-assert and the endpoint
NAKed forever after CLEAR_FEATURE(HALT). `queued` is set at submit and
cleared at completion (and on pipe teardown).
#11 dcd(rusb2): retry a zero-length IN packet that couldn't be queued at submit
(double-buffered pipe full, host not draining). Previously the ZLP was
dropped and the next BRDY reported a phantom completion for a packet the host
never received; now it's deferred to BRDY via `zlp_pending` and only
completes once actually queued and sent.
#15 vendor: collapse the byte-identical bulk/interrupt/isochronous non-buffered
write / write_available / read_xfer triples into three shared static-inline
helpers keyed on (endpoint, epbuf, bufsize).
Verified on ra4m1_ek: usbtest tier-4 30/30 (rusb2 + vendor refactor); pre-commit
(format/codespell/unit) clean. The nRF54LM20 DK also passes 30/30 at high speed.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
|
|
Cross-checking the branch against the MCU datasheets surfaced a regression and
several latent defects. Fixes (finding # from the review):
#1 dcd_ch32_usbfs: restore EP3's enlarged iso buffer. CH32V20x/V30x/F20x USBFS
give endpoint 3 a 1023-byte iso packet (CH32FV2x_V3xRM ch23; 16-bit
R16_UEP3_T_LEN), unlike every other 64 B endpoint. Commit c05e9313e removed
that buffer and capped iso at 64 B, breaking >64 B FS iso (UVC/UAC) on EP3.
Re-add it via CFG_TUD_WCH_USBFS_EP3_BUFSIZE, defaulted to 1023 on those parts
(CH32_USBFS_EP3_1023_BUFSIZE in ch32_usbfs_reg.h) and 64 elsewhere.
#3 dcd_ch32_usbfs: make data.isochronous[] per-direction and clear it on
endpoint (re)open, so a reused ep number can't inherit a stale iso response.
#7 dcd_ch32_usbfs: exempt iso from the PID_OUT data-toggle handling too (was
only done for PID_IN); iso is DATA0-only in both directions.
#13 dcd_ch32_usbfs: bounds-assert ep < EP_MAX in dcd_edpt_iso_alloc.
#2/#6 usbtest descriptors: TUD_OPT_HIGH_SPEED is a compile-time capability, not
the live speed, so the full-speed config (and OTHER_SPEED) advertised int/iso
mps 512 on HS boards — illegal at FS / over the 1023 B/frame iso budget. Split
into FS-legal / HS descriptor sizes; the plain macro tracks operating speed.
#10 vendor: non-alt free-slot detection also checks the int endpoints (a vendor
interface may now be interrupt-only, no bulk ep).
#14 vendor: replace the order-coupled ITF_MEM_RESET_SIZE ladder (2 unreachable
branches) with offsetof(vendord_interface_t, tx_stream).
#5 rp2040: clear_stall re-issue preserves the already-transferred count so a
mid-transfer clear-halt reports the full length, not just the remainder.
#8 rp2040: force single-buffering for iso (only BULK gets a double DPRAM buffer),
so a multi-packet iso xfer can't spill buffer 1 into the next ep's DPRAM.
Verified: CH32V203 usbfs and CH583 still pass usbtest tier-4 30/30; all board
families build; pre-commit (format/codespell/unit) clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
|
|
usbd:
- usbd_edpt_clear_stall keeps the long-standing unconditional STALLED|BUSY
clear (audio's set-interface relies on it to drop a leftover BUSY bit)
and only gates the new CLAIMED release on the endpoint having been
stalled — fixes the halt-test starvation without the double-arm race and
without regressing audio on ports where nothing else zeros ep_status.
- GET_STATUS direction guard + checked return factored into a shared
process_get_status() and applied to all three recipients (device,
interface, endpoint); previously only the interface case was hardened,
leaving the endpoint/device siblings able to hand usbd a stack buffer for
a malformed OUT request.
vendor:
- vendord_open commits p_itf_desc only after the descriptor parse succeeds,
so a mid-parse failure no longer marks the interface slot permanently
occupied (find_vendor_itf keys on p_itf_desc under ALT_SETTINGS).
- vendord_set_alt is a single pass again: the current endpoints are dropped
only once the target altsetting is confirmed present, dropping the
redundant vendord_has_alt pre-scan while keeping the invalid-alt rollback.
- CLOSE_API iso re-activation now closes+reopens the endpoint (zeroing
ep_status) instead of a no-op, so a re-selected altsetting on ip3511/rusb2
can't starve on stale BUSY/CLAIMED.
test/hil/usbtest.py:
- re-resolve on the concrete serial (never retarget a different device),
best-effort cleanup that can't mask the original error, set_pattern
catches PermissionError too, --tier choices derive from TIER_CASES,
--tests uses isdecimal.
Full 30-case battery passes on all four dwc2 boards; all three GET_STATUS
recipients + invalid SET_INTERFACE + EP0 halt verified via raw usbfs
control transfers; usbtest builds for ip3511/rusb2 (CLOSE_API iso path).
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
|
|
- Isochronous endpoints are reserved through TUP_DCD_EDPT_ISO_ALLOC-guarded
helpers with a usbd_edpt_open fallback (mirrors audio), so ports without
the iso alloc API (lpc_ip3511, rusb2) enumerate instead of failing open.
- #error when EP_ISO_* is set without ALT_SETTINGS (iso must live in a
non-zero altsetting per USB 2.0 5.6.3); the non-alt open path no longer
silently treats an iso endpoint as bulk.
- Non-buffered bulk read/write gain the 'ep > 0' guard the int/iso APIs
have, so they cannot claim EP0 while an altsetting without a bulk ep is
selected.
- find_vendor_itf uses p_itf_desc (not the ep fields) to detect a free
slot under ALT_SETTINGS, where an interface parked in the empty alt 0
has all ep fields 0; fixes slot aliasing with CFG_TUD_VENDOR > 1.
- vendord_set_alt validates the altsetting exists before mutating state
(rollback safety) and stall/clears interrupt endpoints only for the
enabled direction.
- vendord_open rejects an endpoint address reused across altsettings with
a different type/MPS (opened once), closing a misconfig + buffer overflow.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
|
|
CFG_TUD_VENDOR_EP_ISO_OUT/IN (default 0) add an isochronous endpoint per
direction with the same non-buffered API shape as the interrupt pair
(tud_vendor_n_iso_read_xfer / tud_vendor_n_iso_write + weak iso_rx/tx_cb),
buffers sized by CFG_TUD_VENDOR_EP_ISO_OUT/IN_BUFSIZE.
CFG_TUD_VENDOR_ALT_SETTINGS (default 0, non-buffered mode only) lets the
vendor interface carry multiple altsettings: vendord consumes them all,
answers GET_INTERFACE and performs SET_INTERFACE via a new internal
vendord_control_xfer_cb (registered in usbd's driver table; everything
else still delegates to the app's tud_vendor_control_xfer_cb).
Endpoints are hardware-opened exactly once at vendord_open: dcds with a
linear FIFO allocator (dwc2: TUP_DCD_EDPT_ISO_ALLOC, where
usbd_edpt_close is a no-op and every re-open leaks FIFO space) cannot
close/re-open endpoints dynamically. Selecting an altsetting only
re-targets the API: bulk/interrupt endpoints get a stall+clear-stall
cycle, which portably aborts any in-flight transfer and resets the data
toggle to DATA0 as SET_INTERFACE requires; isochronous endpoints are
FIFO-allocated at open and (re)activated on selection.
Motivated by the usbtest example (Linux usbtest iso cases 15/16/22/23,
which also drives 256 consecutive SET_INTERFACE cycles in its ch9 case);
alt 0 without endpoints satisfies USB 2.0 5.6.3 for iso devices.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
|
|
The vendor interface may carry an interrupt OUT and/or interrupt IN
endpoint alongside the bulk pair, each direction gated separately by
CFG_TUD_VENDOR_EP_INT_OUT / CFG_TUD_VENDOR_EP_INT_IN (default 0, no cost
when disabled) with CFG_TUD_VENDOR_EP_INT_OUT_BUFSIZE /
CFG_TUD_VENDOR_EP_INT_IN_BUFSIZE (default 64) sizing the dedicated
endpoint buffers; endpoint max packet size is checked at open.
Interrupt endpoints are non-buffered: tud_vendor_n_int_read_xfer() arms
the OUT endpoint one packet at a time (delivered via the new weak
tud_vendor_int_rx_cb, no automatic re-arm), tud_vendor_n_int_write() is
a direct transfer completing into tud_vendor_int_tx_cb.
Motivated by the usbtest example (Linux usbtest interrupt cases 25/26)
but generally useful for vendor protocols with a side channel.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
|
|
* license: use SPDX identifiers for src/ headers
Replace the full ~20-line MIT license boilerplate on every src/ file with a
two-line SPDX tag (SPDX-FileCopyrightText + SPDX-License-Identifier), following
the REUSE convention used by CircuitPython and the Linux kernel. Removes ~3500
lines of duplicated boilerplate.
|
|
|
|
|
|
for clarity and flexibility
|
|
|
|
Signed-off-by: HiFiPhile <[email protected]>
|
|
update vendor_device.c for direct usbd xfer when either RX/TX BUFSIZE is 0 i.e CFG_TUD_VENDOR_TXRX_BUFFERED = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor_write_flush() and write_available() only available when CFG_TUD_VENDOR_TX_BUFSIZE > 0
|
|
CFG_TUD_VENDOR_RX_BUFSIZE = 0
update vendor device to omit ep buf when dedicated hwfifo is supported
|
|
example for more robust
|
|
|
|
|
|
tu_edpt_stream_open() does not clear fifo, allow for persistent stream when disconnect/reconnect
|
|
also add tud_midi_n_packet_write/read_n()
|
|
fix compiling with nuc family
|
|
Signed-off-by: HiFiPhile <[email protected]>
|
|
|
|
|
|
tud_vendor_n_write_flush argument should be 0,1,2,..., but
p_vendor - _vendord_itf is 0, sizeof(vendord_interface_t), 2*sizeof(vendord_interface_t), ...
|
|
|
|
Signed-off-by: HiFiPhile <[email protected]>
|
|
|
|
|
|
|
|
minor fix on calculation of desc_end in vendord_open( ) for descriptor prasing
|
|
|
|
|
|
|
|
fifo) mode
|
|
|
|
|
|
|
|
|