summaryrefslogtreecommitdiff
path: root/examples/device/usbtest/src
AgeCommit message (Collapse)Author
2026-07-09usbtest: skip silicon-impossible cases via bcdDevice quirk flagshathach
The CH569 USBSS ctrl_out flakiness (cases 14/21, host -EPROTO) is a silicon erratum, not a driver bug: EP0 OUT data stages whose wLength % 4 == 1 are intermittently dropped at 5 Gbps. Proven by A/B against WCH's own binary USB3 stack (SimulateCDC EVT demo patched to accept the gadget-zero 0x5b/0x5c requests), which fails identically on the same board — independent of host LPM (persists with U1/U2 disabled) and sysclk (80 vs 120 MHz). Bulk OUT at the same lengths is clean. Document the erratum in the dcd and drop the ineffective zeroed-BOS workaround. Rather than letting known-impossible cases flake the battery, the firmware now advertises quirk flags in bcdDevice bits 4-7 (tier stays in bits 0-3): 0x10 skips ctrl_out 14/21, 0x20 skips ep-halt 13 (the previously proven single-STALL limitation). usbtest.py skips flagged cases visibly at SuperSpeed only (explicit --tests still runs them) and reports them in the summary/JSON. Also fix the CH56x USB3 dcd leaving an endpoint halted across reconfiguration: clear the stalled flag in dcd_edpt_open/close/ close_all (USB 2.0 9.4.5) so a SET_CONFIGURATION recovery of a halted-then-reopened endpoint does not STALL forever. Validated on hydrausb3_v1 at 5000M: tier-4 battery x3 = 27/27 passed + 3 skipped, full HIL device suite 12/12 green (MSC 160/134 MB/s). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019MRGjBT2NBkCoWwyDT4LaE
2026-07-08Add SuperSpeed isochronous support to the CH56x USB3 dcdhathach
The register model comes from disassembling WCH's official USB30 device blob (libCH56x_USB30_device_lib.a): USB30_ISO_Setendp reveals per- endpoint isochronous mode bits in UEP_CFG (bit 16+ep for OUT, bit 24+ep for IN); arming and completion then use the normal endpoint flow. The usbtest example moves back to tier 4 at SuperSpeed with an iso pair in the SS descriptor set - all four kernel usbtest iso cases (15/16/22/23) pass on hardware at 5000M. The endpoint-halt latch from the previous commit is kept (it fixes usbtest case 29); case 13 is now documented as a silicon limitation after exhaustive on-hardware experiments: a halted endpoint answers exactly one probe with a STALL TP and no re-arm strategy (any NUMP, ERDY, 30 us timer re-assertion, endpoint enable bounce) revives it - no event fires per stall TP. The CH32H417's reworked endpoint engine adds a persistent RB_EP_TX_HALT mode, evidently addressing exactly this. Battery results: 30/30 at high speed, 28/30 at SuperSpeed (case 13 = silicon halt limitation; case 14 ctrl_out is intermittent - pre-existing EP0 OUT flakiness under investigation). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019MRGjBT2NBkCoWwyDT4LaE
2026-07-08Pass the usbtest battery on CH569 at high and SuperSpeedhathach
Running the Linux kernel usbtest/testusb battery against the CH569 for the first time. Results: 30/30 at high speed (4 consecutive reflash cycles), 25/26 at SuperSpeed. DCD fixes found by the battery: - dcd_ch56x_usbhs: clear-halt on an armed bulk-OUT pipe reset the toggle but dropped the queued receive, NAKing forever (usbtest case 29 - the same defect previously found on rp2040/fsdev/ch32_usbhs/rusb2) - dcd_ch56x_usb30: endpoint halt is now latched; the endpoint event handler used to clear the response field on every completion, wiping a just-set STALL while the peer streamed, and clear-halt now re-arms a still-armed transfer with the fresh packet sequence (cases 13/29) usbtest example gains SuperSpeed support: tier 3 on SS builds, a 4-endpoint SS descriptor set with companions, EP0 512 config and 1024-byte receive buffers. test/hil/usbtest.py gains SuperSpeed-aware case parameters: bulk sizes and vary steps must be 1024-multiples at SS or the device's whole-packet source overruns the host request (case 4 EOVERFLOW). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019MRGjBT2NBkCoWwyDT4LaE
2026-07-07usbtest: negotiated-speed int/iso refill + harden HIL sudoershathach
Copilot review: - tud_vendor_int_tx_cb/iso_tx_cb submitted sizeof(chunk) (the HS-capacity buffer) instead of the negotiated-speed mps, diverging from usbtest_pump() on an HS-capable build enumerated at full speed. Factor the length into shared usbtest_int_len()/usbtest_iso_len() helpers used by the pump and both callbacks. - Reword the usb_descriptors.h comment that still called the plain mps macro 'live operating speed' — it is the compile-time capability maximum. Claude review (test/hil/tinyusb-sudoer): drop the two grants that bypassed the file's root-owned-helper boundary and gave uid 1000 passwordless root: - /sbin/debugfs (unused; permits '!/bin/sh' shell escape + raw root-disk write). - /home/*/actions-runner/svc.sh (user-writable script). Replace with a root-owned, argument-restricted 'systemctl stop/start actions.runner.*' grant. Also tighten the dmesg/uhubctl runas from (ALL) to (root). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-07usbtest: correct the capability-vs-runtime comment on the mps macroshathach
The plain USBTEST_*_EP_MPS macros are the compile-time capability maximum that sizes the buffers; runtime write lengths follow tud_speed_get() in main.c. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-07address review round 2 (4 fixed, 1 answered)hathach
- 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
2026-07-06usbtest: single-pass pump for the non-FreeRTOS task (SonarCloud ↵hathach
loop-executes-once) Extract the endpoint pump into usbtest_pump(); the FreeRTOS task loops it, the bare-metal path calls it once per main-loop tick instead of a while(1){...return;} whose body can only execute once. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-06fix CI: clang/IAR unused helpers, LTO-dropped ISR symbol, LPC11/13 USB RAM ↵hathach
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
2026-07-06usbtest: support CH32V307 on both USB ports (usbfs + usbhs), 30/30 eachhathach
The CH32V307 exposes two device controllers: the full-speed USBFS (dcd_ch32_usbfs, selected with -DSPEED=full) and the high-speed USBHS (dcd_ch32_usbhs, the default). Both now pass the Linux testusb tier-4 battery 30/30 (3 reflash cycles each) on ch32v307v_r1_1v0. - dcd(ch32_usbhs): fix clear-stall on an armed OUT endpoint. It set the pipe to NAK unconditionally, so a receive the class still considers submitted NAKed forever after CLEAR_FEATURE(HALT) and usbtest toggle test 29 timed out. Re-queue the pending receive (ACK/NYET) instead. This is the first usbtest coverage of the ch32_usbhs driver. - bsp(ch32v30x): implement board_get_unique_id from the ESIG UID (0x1FFFF7E8); the port previously fell back to the placeholder serial. - usbtest: the CH32V307 usbfs port caps iso at 64 B like the other WCH USBFS parts, so add it to the FS iso-64 descriptor branch (its usbhs port uses the HS sizes). - test/hil: register ch32v307v_r1_1v0 (usbhs + usbfs variants, WCH-Link BC5DA47360D0) and move nrf54lm20dk to boards-skip. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-06usbtest: address code-review findings (EP3 iso regression + 9 more)hathach
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
2026-07-06usbtest: support CH583 — its USBFS does isochronous (30/30)hathach
The CH582/CH583 USBFS DCD refused isochronous outright, but the datasheet (CH582-CH583 DS1, USB controller chapter) lists synchronous/real-time (isochronous) alongside control/bulk/interrupt, with 64 B packets. Accept iso like the other WCH USBFS parts (iso mps 64, capped to the 64 B endpoint buffer; drop the CH583-only refusals in dcd_edpt_iso_alloc/activate). That alone left iso IN dropping a deterministic ~1/8 of packets. Root cause: CH58x drives the data toggle manually in the ISR (its hardware AUTO_TOG is unreliable) and flipped the TX toggle after every IN packet — including isochronous, which is DATA0-only and must never toggle. Skip the manual toggle flip for iso endpoints. This path is CH58x-only (CH32_USBFS_EP_MANUAL_TOG), so CH32V103/V20x/V307 (hardware AUTO_TOG) are unaffected. Verified on ch582m_evt: Linux testusb tier-4 (30 cases) = 30/30 across 4 reflash cycles; CH32V103 and the CH32V203 usbfs port still pass. Drop CH583 from the usbtest skip list — all WCH USBFS parts now run the full battery. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-05usbtest: support CH32V203 (fsdev + usbfs ports), both pass tier-4 30/30hathach
Neither of the CH32V203's two USB device IPs could run the usbtest tier-4 battery. usbfs (port 1): - 128 B iso doesn't fit its fixed 64 B/ep buffers -> drop iso mps to 64 on CH32 (usb_descriptors.h). - dcd_ch32_usbfs.c: clear-halt on an armed OUT endpoint forced it to NAK, so a submitted read NAK'd forever and the host timed out. Re-assert ACK when a receive is still armed (usbtest toggle test 29). fsdev (port 0, the shared stm32_fsdev driver): - The descriptor hard-coded the interrupt mps, so USBTEST_INT_EP_MPS never took effect; all six tier-4 endpoints then overflowed the 512 B PMA and SET_CONFIG timed out. Wire the interrupt mps to the macro and use 16 on the fsdev port. - The USBD raises three IRQ lines (LP/HP/WakeUp) into one non-reentrant handler and they nest (HP preempts LP) with QingKe HWSTK enabled. The mainline toolchain's plain __attribute__((interrupt)) emits a software prologue that fights the hardware context stack and corrupts the return on nesting -> wild jump / illegal-instruction crash. Emit naked handlers that rely on HWSTK for context save/restore -- the equivalent of WCH's "WCH-Interrupt-fast", which mainline riscv-none-elf-gcc ignores -- so nesting is safe. - Single-buffered iso IN can't stay fed under load; double-buffer it (CFG_TUD_FSDEV_DOUBLE_BUFFERED_ISO_EP in the example tusb_config.h). iso mps 32 x2 = 64 B/ep keeps the same PMA budget. Left single for other fsdev parts (audio's larger iso would overflow their PMA too). Verified on nanoch32v203 (CH32V203D6): Linux testusb tier-4 (30 cases across bulk/control/interrupt/isochronous) = 30/30 on both the fsdev and usbfs variant, each across 5 reflash cycles. Full CH32V20X example set builds; cdc_msc still enumerates CDC+MSC on the fsdev port (naked-handler regression check). Drop CH32V20X from the usbtest skip list. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-04feat(usbtest): add FreeRTOS/espressif supporthathach
Mirror the video_capture #if pattern: dual-mode tasks that vTaskDelay under FreeRTOS and return under OS_NONE, a usb_device_task + freertos_init (xTaskCreate blinky/usbd/app), and an ESP_PLATFORM app_main. Add the ESP-IDF src/CMakeLists.txt and CFG_TUSB_OS_INC_PATH; replace the family:espressif skip with per-MCU skips for parts that can't fit the tier-4 descriptor. Verified: esp32s3 (FS) and esp32p4 (HS) both 30/30 on the usbtest battery. Co-Authored-By: Claude Opus 4.8 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-03usbtest: put iso endpoints on EP8 for nRF5xhathach
nRF5x fixes the isochronous endpoint number to 8 (EP_ISO_NUM) in hardware for both ISOOUT and ISOIN. The default tier-4 descriptor used EP3 for iso, so dcd_edpt_open() rejected it and SET_CONFIGURATION failed (can't set config, -EPIPE) - the device enumerated but never configured, so usbtest couldn't bind. Add an OPT_MCU_NRF5X case to the per-MCU endpoint-number block placing iso on EP8. usbtest on feather_nrf52840_express then configures and passes 29/30 (all bulk/int/iso/ctrl_out/halt/toggle); test 10 (queued control) hangs - a separate nRF EP0 issue tracked for follow-up. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-03usbtest: FS-sized ep buffers + host runner hardeninghathach
- example: interrupt/iso endpoint buffers track the per-speed max packet size instead of a fixed 512, saving ~1.6 KB of USB DMA RAM on FS builds. - test/hil/usbtest.py: re-resolve the device node after a mid-battery re-enumeration (stale node was misreported as NOTRUN); reject an out-of-range tier (a tier-0 device would run an empty battery and read green); validate --tests case numbers; run cleanup in a try/finally so a crash can't leave the dynamic id registered to hijack the next device; guard set_pattern and the pci-reset placeholder; report a sudo-password failure on the testusb fallback instead of a misleading NOTRUN. - tinyusb-sudoer: allow the foreign-driver unbind path and the testusb fallback used by the runner. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-02example(usbtest): tier 4 - isochronous source/sink (cases 15/16/22/23)hathach
Gadget-Zero parity: alt 0 carries no endpoints, alt 1 the full set (bulk + interrupt + iso IN/OUT, iso FS 128B / HS 512B). The host usbtest driver skips pipe-less altsettings and selects alt 1 itself, so no usbtest module parameters are needed. The complete 30-case battery (all four tiers) passes on stm32f407disco, stm32f723disco, stm32h743nucleo and stm32l476disco, including the ch9 case which now exercises 256 consecutive SET_INTERFACE cycles. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-02example(usbtest): tier 3 - interrupt source/sink (cases 25/26)hathach
The host usbtest driver collects interrupt pipes from the same altsetting as the bulk pair, so the interface grows to 4 endpoints (hand-rolled descriptor: bulk IN/OUT + interrupt IN/OUT, FS 64B interval 1 / HS 512B interval 4) using the vendor class with CFG_TUD_VENDOR_EP_INT_OUT/IN. The interrupt pumps mirror the bulk ones: poll + re-arm from callbacks, self-healing across the halt tests. Full tier-3 battery (26 cases, now incl. 25/26 interrupt write/read) passes on stm32f407disco, stm32f723disco, stm32h743nucleo and stm32l476disco. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-02example(usbtest): tier 2 - vendor control 0x5b/0x5c write/read-backhathach
Gadget-Zero ctrl_out protocol: 0x5b stores the host's wLength bytes in a 1 KiB buffer (multi-packet EP0 data stage), 0x5c returns them for comparison. bcdDevice now advertises tier 2 so the runner adds usbtest cases 14/21. No descriptor change needed: ctrl_out is unlocked by the Gadget Zero capability profile of the dynamic-id binding, not by endpoints (interrupt/iso endpoints come with tiers 3/4). Full tier-2 battery (24 cases) passes on stm32f407disco, stm32f723disco, stm32h743nucleo and stm32l476disco. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-02example(usbtest): add device-side peer for Linux usbtest/testusb (tier 1: ↵hathach
bulk source/sink) Vendor interface with bulk IN source / bulk OUT sink implementing the Gadget-Zero style protocol expected by the kernel usbtest driver. Non-buffered vendor mode keeps every transfer an exact packet multiple so the data-integrity cases never see an unexpected short packet, and polling pumps self-heal after the endpoint-halt cases. Tier (bulk-only for now) is advertised in bcdDevice for the host-side runner. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg