summaryrefslogtreecommitdiff
path: root/examples
AgeCommit message (Collapse)Author
10 daysaudio: allow stopped duplex streams to change rateHiFiPHile
Enforce a shared capture/playback sample rate only while the opposite stream is running. This lets both stopped streams be configured in either order while preventing a live shared clock from changing underneath a transfer. Signed-off-by: HiFiPHile <[email protected]>
10 daysaudio: add UAC2 host streaming supportHiFiPHile
Add protocol-selectable UAC1/UAC2 parsing, UAC2 terminal and Feature Unit topology, Clock Source discovery, sampling-frequency ranges, and protocol-specific stream controls. Cover UAC2 playback, capture, control discovery, and malformed descriptors with unit tests. Signed-off-by: HiFiPHile <[email protected]>
11 daysimplement explicit feeback supportHiFiPHile
Signed-off-by: HiFiPHile <[email protected]>
12 daysaddress copilot review findingsHiFiPHile
Signed-off-by: HiFiPHile <[email protected]>
12 daysMerge remote-tracking branch 'origin/master' into feature/tuh-audio-uac-1.0HiFiPHile
12 daysrestrict example to supported hcdHiFiPHile
Signed-off-by: HiFiPHile <[email protected]>
12 daysfeat(audio): discover stream mute and volume controlsHiFiPHile
Inspect each associated Feature Unit during mount, cache master mute support and the common MIN, MAX, and RES volume range, and ignore units with neither control. Add typed asynchronous and synchronous mute and volume APIs and demonstrate them in the host example. Signed-off-by: HiFiPHile <[email protected]>
12 daysfix(audio): discard capture data without playbackHiFiPHile
Continue draining the capture FIFO but skip channel conversion and writes when playback is unavailable or intentionally stopped. This keeps capture running safely in microphone-only phases. Signed-off-by: HiFiPHile <[email protected]>
12 daysfix(audio): keep stream state consistent on control failuresHiFiPHile
Route asynchronous activation and sampling-frequency failures through the stream error callback. Keep a running stream active when SET_INTERFACE alt 0 cannot be submitted so stop can be retried without diverging from device state. Signed-off-by: HiFiPHile <[email protected]>
12 daysfix(audio): generate a continuous high-resolution test toneHiFiPHile
Replace the six-sample waveform with a 64-entry sine table and phase accumulator. The example now generates a continuous 1 kHz tone at the selected rate and packs the configured channel count correctly. Signed-off-by: HiFiPHile <[email protected]>
12 daysfix(audio): avoid playback alt-setting glitch at startupHiFiPHile
Enter the microphone-only phase before starting playback when both directions exist. This avoids briefly selecting the playback alternate setting and immediately returning it to alt 0. Signed-off-by: HiFiPHile <[email protected]>
12 daysrefactor(audio): separate stream configuration and startHiFiPHile
Make configuration a synchronous local operation that selects and opens the endpoint. Start now activates the alternate setting and sets the sampling frequency afterward, including every restart, so devices cannot reset the selected rate with SET_INTERFACE. Signed-off-by: HiFiPHile <[email protected]>
12 daysfix(audio): drive streams from transfer completionHiFiPHile
Keep capture and playback transfers continuously armed from their completion callbacks. Capture overwrites the oldest complete frames when full, while playback sends silence on underrun without consuming partial queued audio. Signed-off-by: HiFiPHile <[email protected]>
12 daysMerge master updates into the UAC1 host branchHiFiPHile
Bring the audio work onto the current host core and build files before applying the remaining review fixes. Signed-off-by: HiFiPHile <[email protected]>
12 daysfeat(audio): demonstrate speaker volume controlHiFiPHile
Look up the playback Feature Unit in the host example and set its master volume after configuration. The output also reports when a stream has no controllable Feature Unit. Signed-off-by: HiFiPHile <[email protected]>
12 daysfix(audio): resolve Feature Units independent of orderHiFiPHile
Record terminal and Feature Unit links while parsing the AudioControl block, then resolve the stream association after all entities are known. Common capture and playback descriptor orders are both supported. Signed-off-by: HiFiPHile <[email protected]>
12 daysfix(audio): reject continuous UAC1 sample-rate rangesHiFiPHile
Collect only format descriptors with discrete sampling frequencies. The configuration API exposes concrete tuples and cannot safely represent a continuous range as one selectable rate. Signed-off-by: HiFiPHile <[email protected]>
12 daysfix(audio): honor full-speed isochronous intervalsHiFiPHile
Convert full-speed bInterval values to the scheduler microframe timebase and size transfers for the complete service interval. Endpoints with bInterval greater than one no longer run at a one-frame cadence. Signed-off-by: HiFiPHile <[email protected]>
12 daysfix(audio): configure playback-only example devicesHiFiPHile
Select capture and playback configurations independently in the example. Speaker-only devices can now start playback without a capture configuration. Signed-off-by: HiFiPHile <[email protected]>
12 daysfeat(audio): track a Feature Unit per stream directionHiFiPHile
Associate one directly connected Feature Unit with each capture and playback stream. This lets applications control microphone and speaker paths independently. Signed-off-by: HiFiPHile <[email protected]>
12 daysfix(audio): repair the host audio example buildHiFiPHile
Add the missing preset and shared declarations, remove duplicate initialization, and correct callback call sites so the new example builds through the normal CMake flow. Signed-off-by: HiFiPHile <[email protected]>
13 daysci: an empty selection must build nothing, plus selector follow-ups (#3845)Ha Thach
ci: an empty selection must build nothing, plus selector follow-ups A PR whose build axis legitimately selected nothing rebuilt everything. build.yml reads .build.families twice - as a |-joined regex, and implicitly as "is anything selected" - but tested only -z "$FAMILY_REGEX", which an empty list and a charset-rejected one both satisfy while meaning opposite things. ci_set_matrix had already returned the correct all-empty matrix; the fall-open branch discarded it. #3842 and #3840 each spent 74 cmake legs on it. Branch on the two cases instead, rename FAM_* to FAMILY_*, and cover the block with a test that extracts it from build.yml and executes it - it had no test at all, which is how this shipped through two merges. Follow-ups to the same machinery: glob.escape the repo root at five sites, so a checkout path containing [ or * stops failing closed; drop the ci-full label, read after the matrix was already computed and so never functional; delete 13 mcu:MKL25ZXX / mcu:SAME5X skip tokens matching no board; carry the rule table in the module docstring, guarded against drift; and pin six selection behaviours a mutation pass proved untested. Cut the selector's cost 1.8x (26.0s -> 14.6s) with 0 divergences over 260 paths, and stop scoping the membrowse upload by the PR example filter.
2026-08-21examples: keep CFG_TUH_VENDOR 0 in tusb_config.hhathach
Removing the obsolete host vendor driver also dropped the `#define CFG_TUH_VENDOR 0` line from the six example configs that carried it. Put it back: host vendor is coming, and the configs are where a reader looks for the set of host classes an example can turn on. Restored byte-identical to the pre-removal state, each file keeping its own column alignment. The define is inert today - nothing under src/, hw/ or tools/ reads CFG_TUH_VENDOR - and it is 0 everywhere, so ci_select still reads the vendor class as enabled by no example and a change to it still selects nothing. Note the option's default in src/tusb_option.h is still gone; implementing the driver will need that back alongside the usbh driver-table entry.
2026-08-21ci: scope the build matrix and the HIL run to what a PR affectshathach
Every PR built all 74 legs (2494 example builds on GHA cmake alone) and flashed all 30 rig boards, whatever it touched. One classifier now walks the PR diff twice and answers three questions: which families to build, which examples per family, and which boards run which tests. Fail-open throughout - anything no rule classifies, any exception, any unusable output falls back to the full matrix, and a master push always builds everything. test/hil/helper/hil_select.py moves to tools/ci_select.py: it is no longer HIL-only, and tools/ is where the build side can import it. test_hil_select.py follows it as test_ci_select.py. Rules (docs/superpowers/specs/2026-08-19-ci-build-family-filter-design.md holds the full table): a port selects the families whose family.cmake references it, and its role - a dcd change skips host examples and vice versa; a class selects only the examples whose tusb_config.h enables its CFG_TU[DH]_ macro, following cross-class includes; an example selects itself; hw/bsp selects its family or board; hw/mcu and lib select whoever references them. CMake is the reference for all of it - make follows whatever cmake decides, family.mk is never scanned. Empty means empty (maintainer ruling): a rule that classifies a path to nothing selects nothing. Ports no family references, classes no config enables, libs no example builds and hw/mcu paths that resolve nowhere are all real - nothing compiles them, so nothing can validate them, and the master-push build is the net. Structural tests pin each such case with an explicit allowlist, so the day one stops being empty it fails pre-commit instead of silently narrowing CI. Per-example builds: build.py grows a repeatable -e, resolved against the targets CMake actually registered and batched into one `cmake --build --target a b c`. build_utils mirrors CMake's family_filter (the whole FAMILY_MCUS list, ${...} and string(TOUPPER ...) resolved) for the cmake side, while the make side keeps master's algorithm verbatim - the two build systems answer differently and a shared answer breaks lpc54's make link. hil-build gains this even on a full selection: 1702 example builds become 515. Transport: the selection travels as a file, never an argv or env var - a mass-sweep diff selects 261 KB against a 128 KiB exec limit, and E2BIG would fail the step before its own fallback could run. CircleCI carries the example map inside the generated config (pipeline parameters cap at 512 chars), swapped into the parameter defaults by sentinel match, and drops the scoping wholesale if that rewrite fails. Every PR-derived value written to $GITHUB_ENV/$GITHUB_OUTPUT is character-screened. Code metrics follow the scoping: metrics.py emits per-example totals, and metrics_pair_compare compares the (board, example) pairs present on both sides instead of a scoped run against a full-matrix average. The selector's own suite gates it in both providers: a selector that exits 0 with valid-but-wrong JSON is the one failure fail-open cannot catch, so a red suite means the full matrix.
2026-08-21examples: restore host builds on samd2x_l2xhathach
Nine examples/host/*/only.txt gate on family:samd21, but 2a8811ebb merged the samd2x and saml2x BSPs into hw/bsp/samd2x_l2x. skip_example takes `family:` from the directory name, so since that rename every one of these examples has been skipped on every board of the family, under make as well as cmake - although hw/bsp/samd2x_l2x/family.cmake wires src/portable/microchip/samd/hcd_samd.c. 107 host firmware images were being compiled nowhere. The merged family is wider than the old samd21 one, so three boards need an explicit skip rather than the rename alone: atsaml21_xpro, saml22_feather, sensorwatch_m0 - not samd21, so hcd_samd.c is not compiled for them (previous commit); SAML22 has no host controller at all curiosity_nano - SAMD21 with 16 KB RAM; msc_file_explorer_freertos overflows it by 3688 bytes (ram 122.51%). Only that one example; the other eight fit. Verified across the whole family: cmake 11 boards x 9/9 examples + curiosity_nano 8/9, three boards skipped, 0 failures; make 98 OK / 0 failed (was 98/9 before). Device examples on saml21 and saml22 are unaffected.
2026-08-21vendor: remove the obsolete host vendor driverhathach
vendor_host.c/.h implemented a CFG_TUH_VENDOR class driver that no example, board or test ever enabled: usbh's driver table entry was compiled out everywhere, and the six tusb_config.h files that mentioned the macro all set it to 0. Maintainer call - dead code, not a shrinking of supported classes. Removes the sources, the usbh driver-table entry, the CFG_TUH_VENDOR default in tusb_option.h, the tusb.h include, both build-system source lists, the rp2040 family.cmake entry and the IAR project template rows.
2026-08-18examples: document and work around the i.MX RT and LPC55 USB erratahathach
ERR050101: while an isochronous IN endpoint is active, an IN token addressed to that same endpoint number on ANOTHER device sharing the host can silently unprime one of this device's OUT endpoints - control, bulk, interrupt or isochronous alike. NXP states it cannot be detected by software and raises no interrupt, so the endpoint simply stops answering and the transfer never completes. The workaround is a uniqueness requirement rather than a particular number: the isochronous IN endpoint must not share its number with any IN endpoint in use on the bus. One family-wide constant therefore defeats it, since two affected boards on the same hub then pick the same number and each becomes the other's aggressor. CFG_TUSB_MIMXRT1XXX_ERRATA_ERR050101 is set only for the parts whose errata list it - RT1015, RT1020, RT1024 and RT1050, where it is marked no fix scheduled, plus RT1060 and RT1064 rev A - so RT1010 and the RT11xx family keep the ordinary number and cannot collide with an affected board beside them. Several affected boards on one hub can still be given distinct numbers with -DEPNUM_ISO_IN. The guard covers every example that has an isochronous IN endpoint: audio_test, audio_4_channel_mic, uac2_headset, cdc_uac2, usbtest, video_capture and video_capture_2ch. The video examples move the endpoint only when streaming isochronously, since the bulk configuration is unaffected, and video_capture_2ch takes two numbers because it has two streams. The macro name follows CFG_TUSB_RP2_ERRATA_E2/E4/E15 already in tree, and its is fixed, and which cannot be told apart at compile time - a way to define it to 0. device_issues.rst records ERR050101 against every affected part with a link to each errata sheet, and adds the LPC55S2x USB.3 speed-detection and USB.5 isochronous IN entries, neither of which TinyUSB works around. The branch's design notes are included under docs/superpowers. Verified: 340 wedge-free runs on mimxrt1064_evk, which previously wedged within hours, and the macro resolving to endpoint 0x87 on mimxrt1064_evk against 0x83 on mimxrt1010_evk and stm32f407disco.
2026-08-14example(midi2): report device identity in midi2_deviceSaulo Veríssimo
2026-08-14feat(class/audio): rework TUH_AUDIO into a WASAPI/ALSA-like stream APIZhang, Zhenjiang
Provide a high-level audio streaming API over UAC 1.0 devices while keeping the USB topology private: applications select supported {format, sample_rate, channels} configurations per logical stream, and the driver owns the mapping to AS interface, alternate setting, and endpoint. - One logical stream per direction per instance; multiple AS interfaces and alternate settings in a direction are merged into the stream's configuration list (discrete tuples; continuous ranges exposed as a single configuration at the top rate) - Asynchronous tuh_audio_configure(): SET_INTERFACE to the selected alternate setting, open/reconfigure the endpoint, set the sampling frequency when supported, initialize the FIFO and packet scheduler, then invoke the completion callback - Frame-based FIFO streaming: tuh_audio_read()/tuh_audio_write() queue whole frames; the driver owns transfer replenishment and fractional packet scheduling (44.1 kHz pays back the 0.1 frame/ms remainder via an accumulator for exact average pacing) - tuh_audio_start()/tuh_audio_stop() activate/deactivate the stream interface through SET_INTERFACE (alt n / alt 0) Driver correctness fixes: - Parse only the AC header's interface collection; MIDI Streaming and other subclasses are skipped - Keep every discrete format as a separate configuration; endpoints are opened only for the alternate setting selected by tuh_audio_configure() - Check tuh_interface_set() return values and SET_INTERFACE transfer results instead of ignoring failures - Validate instance state, direction, buffers, and frame counts in every transfer API - Feature Unit requests use the control's real width (mute/AGC/loudness 1 byte, others 2 bytes) and convert multibyte values to host order - Failed/stalled/aborted isochronous transfers reach only the error callback, never the capture/playback callbacks The audio_host example uses the new API: 48 kHz stereo by default, automatic stream restart on error callbacks, a sine test tone on the playback stream, and periodic mic-only / spk-only / echo phase switching.
2026-07-25Enable APM32F0 dependency fetching and CIJie Feng
2026-07-21Refactor TUH_AUDIO API and simplify multi-AS interface supportZhang, Zhenjiang
This commit refactors the TUH_AUDIO (USB Audio Host) class driver to simplify its public API and improve multi-AS (Audio Streaming) interface support. The changes are focused on three files: the core driver (audio_host.c/h) and the example application (audio_app.c). Key changes in src/class/audio/audio_host.h: - Remove tuh_audio_descriptor_cb_t and tuh_audio_mount_cb_t structures. The mount callback no longer passes a large descriptor-info struct; applications query per-AS info via tuh_audio_as_get_info(). - Add tuh_audio_get_dev_addr() and tuh_audio_get_feature_unit_id() accessors to retrieve device address and feature-unit ID from an interface index. - Simplify control-transfer APIs by replacing (daddr, itf_num, unit_id) parameters with a single idx parameter: tuh_audio_set_sampling_freq(idx, as_idx, ...) tuh_audio_get_sampling_freq(idx, as_idx, ...) tuh_audio_feature_unit_set(idx, control_selector, channel, ...) tuh_audio_feature_unit_get(idx, control_selector, channel, ...) - Add synchronous wrapper APIs using TU_API_SYNC macro: tuh_audio_get_sampling_freq_sync() tuh_audio_set_sampling_freq_sync() tuh_audio_feature_unit_set_sync() tuh_audio_feature_unit_get_sync() - Update isochronous endpoint APIs to use (idx, as_idx) instead of (daddr, idx): tuh_audio_receive(idx, as_idx, buffer, len) tuh_audio_send(idx, as_idx, buffer, len) - Remove tuh_audio_descriptor_cb() weak callback. - Update tuh_audio_mount_cb() signature from mount_cb(param) to no param. - Update tuh_audio_rx_cb()/tuh_audio_tx_cb() first parameter from idx to dev_addr for consistency with other class drivers. Key changes in src/class/audio/audio_host.c: - Delete tuh_audio_descriptor_cb weak stub. - Refactor get_idx_by_ep_addr() to iterate all AS interfaces per device instead of relying on single ep_in/ep_out fields. - Add audioh_get_ep_addr_by_dir() helper to find an endpoint address by direction across multiple AS interfaces. - Simplify audioh_close() cleanup: remove now-removed single-endpoint fields (ep_in, ep_out) and rely on tu_memclr(p_audio->as, ...). - Update audioh_xfer_cb() to pass dev_addr (not idx) to rx/tx callbacks, matching the new callback signature. - Simplify audioh_open(): remove descriptor-callback emission and the temporary desc_cb structure; store only ac_itf_num instead of bInterfaceNumber + iInterface + as_interface_num. - Rename local descriptor pointers for clarity: desc_input_terminal (was desc_it) desc_output_terminal (was desc_ot) Key changes in examples/host/audio_host/src/audio_app.c: - Remove now-unnecessary globals: audio_ep_in, audio_ep_out, audio_ac_itf, audio_feature_unit_id. - Initialize audio_dev_addr, audio_idx, audiostream_in_idx, audiostream_out_idx to 0xFF (TUSB_INDEX_INVALID_8) instead of 0. - Update print_as_interfaces() to use tuh_audio_as_get_count() and tuh_audio_as_get_info() instead of accessing mount_cb_data. - Update all callback signatures and API calls to match the new driver API.
2026-07-19misc fixesJie Feng
2026-07-19examples now buildJie Feng
2026-07-19Merge pull request #3775 from hathach/claude/add-usb-debug-sniffHa Thach
usb-target-debug/usb-sniffer skills
2026-07-18dcd_lpc17_40: address review findings in the iso pathshathach
From a second max-effort review of the branch: - Drop the dead TUSB_XFER_ISOCHRONOUS case in dcd_edpt_open: iso endpoints are armed via dcd_edpt_iso_alloc/activate (TUP_DCD_EDPT_ISO_ALLOC is defined for this IP), never through dcd_edpt_open, so the case and its dd->isochronous assignment were unreachable and asserted a false invariant. Only bulk/interrupt reach the switch now. - Extend the iso compile gate to the classes that actually arm an iso endpoint: DCD_ISO_ENABLED now includes CFG_TUD_BTH (bth_device.c opens an iso voice endpoint). Without it a BTH build would compile the iso machinery out and fail SET_INTERFACE at runtime. - Un-skip LPC175X_6X in the usbtest example: it shares dcd_lpc17_40.c with LPC40XX verbatim, so the "DCD has no isochronous support" skip reason no longer holds. Build-verified for lpcxpresso1769 (previously blocked by the skip). - TU_ATTR_UNUSED on the ep_id_is_iso helper: every caller is under #if DCD_ISO_ENABLED, so non-iso builds don't reference it and clang's -Wunused-function (fatal in CI) rejected the build — gcc stays quiet. Verified with the full lpc17 and lpc40 example sets under arm-clang. A fifth finding — bounding control_ep_read's PACKET_READY spin with a timeout — was implemented and REVERTED: a naive 100k-iteration bound fires on legitimately-slow control reads and intermittently drops the device (hardware-proven by interleaved A/B testing against the pre-fix binary). The infinite wait is retained; the read is only reached once out_received/ out_queued signal data is present, so the theoretical IRQ-off hang is not reachable in practice. Re-verified on ea4088_quickstart: usbtest 30/30 (repeated) + HIL 14/14.
2026-07-17skill: add usb-sniffer — wire-level capture with the ataradov hardware taphathach
Fourth view in the USB debugging toolset (usbmon = host URBs, usb-debug = host reasoning, usb-target-debug = device firmware, usb-sniffer = what actually crossed D+/D-). Covers the ataradov/usb-sniffer analyzer: headless pcapng capture (--speed ls/fs/hs, --fold, --limit self-exit), Wireshark/tshark analysis recipes, and the wire realities that bite: downstream broadcast, sniffer self-capture noise, xHCI devnum != wire address, tap-point-dependent reset visibility (hub choreography anchors), FS-behind-HS-hub splits. Every recipe hardware-validated on the rig, including the capture-window floor (a 3 s window provably misses the enumeration ladder; 3M packets minimum). Two udev files with distinct audiences, not one: - examples/device/99-tinyusb-examples.rules (renamed from 99-tinyusb.rules): the user-facing rules the examples need — cafe VID access, hidraw, the ModemManager blacklist, a couple of board probes. getting_started.rst, the webusb_serial README and its source comment point here. - tools/88-tinyusb.rules: the HIL rig's private probe/analyzer allowlist, now with the sniffer (6666:6620 + blank FX2LP 04b4:8613). Installed on the rig only; the usb-sniffer skill references it.
2026-07-17migrate NXP Kinetis khci to chipidea ci_fs driver (device + host)hathach
Complete the khci -> chipidea ci_fs migration that was started for device (commit d70403f1f "host is not yet"): - device: switch kinetis_k/kl/k32l (Makefiles + k32l CMake) to dcd_ci_fs.c - host: add hcd_ci_fs.c (port of hcd_khci.c onto ci_fs_regs_t) and switch all Kinetis families to it; remove src/portable/nxp/khci entirely - enable host examples (device_info, cdc_msc_hid) for mcu:KINETIS_K - README: merge the KL and K32L2 rows into a single "KL, K32L" ci_fs row hcd_ci_fs.c also fixes two pre-existing host bugs found via HIL on frdm_k64f (present in the old hcd_khci.c too): - data toggle was flipped on a NAK in suspend_transfer; a NAK transfers no data so the toggle must be preserved, else the retried bulk packet is silently discarded by the device (MSC CBW/CSW hang). See comment in file. - prepare_packets asserted and dropped a transfer when the single shared BDT was still owned by an in-flight transfer under concurrent activity; now it returns busy and resume_transfer defers/retries on the next SOF. HIL verified on frdm_k64f: device 13/13, host cdc_msc_hid (CDC mount + echo + MSC mount, through a hub). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01ExGPLP5eU43LR7o6yYLpNi
2026-07-17dcd_lpc17_40: fix stale EP0 out_received, add isochronous supporthathach
EP0 control-OUT fix (usbtest 14/21, errno 110/-74): usbd queues the status-stage OUT ZLP of every control read with buffer=NULL, so the ISR's `if (out_buffer)` check missed it and marked the arriving ZLP as out_received instead. The stale flag poisoned the next control-OUT with data: its first chunk "completed" instantly from an empty EP0 buffer and the host's real DATA NAKed forever. Track queued transfers with an explicit out_queued flag and void half-finished control state on a new SETUP. Isochronous support (UM10562 12.15.6): 5-word DMA descriptors with per-packet size memory, buflen/present_count in packets, one packet per FRAME (no DMARSet/EpIntEn involvement), completion at EOT for both directions. Details that matter: - the iso machinery (5th DD word + packet-size memory) is compiled only when an iso-capable class is enabled (CFG_TUD_AUDIO/VIDEO/VENDOR), so non-iso builds pay nothing: _dcd stays 648 B vs 1032 B with iso - ISR dispatch keys on the hardware's fixed ep-number/type map (ep_id_is_iso), never on dd fields that thread mode rebuilds - iso OUT honors Packet_valid (bit 16) and prefills the hardware writeback slots with 0, so a missed frame counts as 0 bytes instead of reading back stale buffer contents as data - packet count is validated (tu_div_ceil <= ISO_MAX_PACKETS) before the DD is touched, so an oversized transfer is refused without leaving a serviceable half-built descriptor armed for the frame engine - dcd_edpt_iso_alloc and iso_activate both enforce the fixed iso endpoint numbers (3/6/9/12); classes ignore alloc's return value, so activate must not trust it Un-skip LPC40XX in the usbtest example; tier 4 now enumerates and passes iso cases 15/16/22/23. cdc_msc_throughput and printer_to_cdc had bulk on iso-only EP3 (SET_CONFIGURATION failed with -32); add the LPC17/40 EPNUM block (bulk on EP2/EP5) like other fixed-EP examples. Verified on ea4088_quickstart: usbtest tier-4 battery 30/30 repeatedly and the full device HIL suite 14/14 (incl. audio_test iso).
2026-07-17fix(class/audio): fix control request byte order and buffer usage in audio hostZhang, Zhenjiang
- Fix missing tu_htole16() conversions for wValue and wIndex in tuh_audio_set_sampling_freq, tuh_audio_get_sampling_freq, tuh_audio_feature_unit_set, and tuh_audio_feature_unit_get - Fix incorrect wIndex parameter order in feature unit requests (unit_id and itf_num were swapped) - Replace static freq_buf with per-endpoint ctrl buffer in tuh_audio_set_sampling_freq to avoid concurrency issues - Update audio_host README to match actual example behavior
2026-07-17fix(class/audio): handle non-audio interface in enumeration and fix async ↵Zhang, Zhenjiang
control transfer buffer - Stop parsing at first non-Audio interface in audioh_open to avoid claiming unrelated interfaces - Call usbh_driver_set_config_complete for AS and unknown interfaces to allow enumeration to continue - Add global ctrl endpoint buffer to audioh_epbuf_t to fix use-after-return in feature_unit_set - Add sampling_freq NULL check and initialize to 0 in tuh_audio_get_sampling_freq - Change BOARD_TUH_RHPORT from 1 to 0 in audio_host example - Add only.txt with supported MCU/family list for audio_host example
2026-07-16Potential fix for pull request finding代码人生
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
2026-07-16feat(audio): add USB Audio Host (UAC 1.0) supportZhang, Zhenjiang
Add TinyUSB Host Audio class driver supporting UAC 1.0 devices. Features: - Support multiple Audio Streaming (AS) interfaces with independent format storage - Support both IN (Microphone) and OUT (Speaker) endpoints - Per-AS interface format info: channels, sample rate, bit resolution - Support Feature Unit volume control - Support sampling frequency get/set - Add host/audio_host example for STM32F407 discovery board - Support mono-to-stereo conversion for loopback Changes: - Add src/class/audio/audio_host.c and audio_host.h - Register AUDIO driver in usbh.c - Add CFG_TUH_AUDIO macro in tusb_option.h - Add host/audio_host example with CMake and Makefile build support Tested with Jabra USB headset (stereo speaker + mono microphone) on STM32F407 disco.
2026-07-14test/hil: usbtest fleet enablement, shuffled scheduling, unique PIDshathach
Pool/config: - record real uids (ra8m1_ek), enable usbtest for espressif s3/p4, then park ra6m5_ek and ra8m1_ek in boards-skip (ra6m5's usbtest/MSC traffic can kill the uPD720201 host on its ROM firmware; ra8m1 USBHS bring-up pending); max32666/nrf54lm20 stay enabled - their MosChip flakiness never wedges - re-enable device/usbtest on HS boards (mimxrt1064, ch32v307) now that uPD720201 firmware 2.0.2.6 fixes the command-ring death; mimxrt1015 stays skipped - its HS battery killed the controller on both ROM and 2.0.2.6 firmware (board-specific); match the moved host-test bundles (f723 <-> rt1064); skip never-passing tests on the new nrf5340dk/nrf54lm20dk boards and the detached pico host bundle, each documented with a comment Host-controller quirk gating in usbtest.py (auto-skip, self-heals on a healthy xHCI): - MosChip MCS9990 EHCI: case 25 (int-OUT never scheduled, FRINDEX bug) and case 11 (unlinked reads complete short/EREMOTEIO) - Renesas uPD720201 xHCI: firmware-gated. The card must run firmware >= 2.0.2.6 (RAM-uploaded - it reverts to ROM on every power cycle): on older firmware the command ring dies under unlink stress (a Configure Endpoint command stops completing; the hub worker deadlocks holding the device lock; only a host power cycle recovers; three boards reproduced it). usbtest.py reads the FW version register (PCI config 0x6c) and refuses to run at all on older firmware - hil_test surfaces that as a failed test with the reason. On current firmware the full 30-case battery runs (validated FS+HS: metro_m4, f723, f723-DMA all 30/30). Scheduling (hil_test.py): - Shuffle each (board, variant)'s test order with a seeded RNG (HIL_SHUFFLE_SEED to replay) so usbtest batteries and flash churn spread across the timeline instead of convoying on one controller. - Per-controller usbtest + flash semaphores: HIL_USBTEST_PARALLEL (default 4) concurrent usbtest batteries and HIL_FLASH_PARALLEL (default 8) concurrent flashes per host controller. Profiled on uPD720201 firmware 2.0.2.6 across 8/1..12/8: wall time falls 22.2/14.3/12.5/10.8 min at usbtest width 1/2/3/4 and plateaus there; zero controller errors everywhere; first battery case failures (leaf-hub bandwidth stretch) appear at 12/8, and flash width 12 only amplifies flasher-hub contention flakes - so 8/4 is the optimum. A separate battery-window flash throttle was profiled and dropped. - Give every example a unique hardcoded USB PID (0x4001-0x4022, usbtest keeps 0x4010) instead of the PID_MAP interface bitmap: different examples now always re-enumerate back-to-back, even on boards whose CPU reset does not drop D+ (WCH CH58x), so the EXAMPLE_PID table and same-PID adjacency reordering in hil_test.py are gone; only the variant-boundary same-example repeat needs a swap. - Report matrix: stable columns with the metric-bearing tests pinned first (usbtest, cdc_msc_throughput, msc_file_explorer[_freertos]), the rest alphabetical. Fail fast: - enum wait budget 8 s on the first attempt, 4 s on retries; dfu waits are deadline-based so dfu-util's own runtime counts against the budget. A device-absent failure now costs ~3-5x a passing test (20-30 s) instead of 10-30x (47-150 s). - CI runs hil_test with --retry 1 and no in-run second pass: a broken fixture fails the job fast instead of holding the self-hosted runner for hours and blocking other PRs' HIL jobs. hil_test still writes the .skip sidecar, so a manual re-run attempt only retests what failed. Review fixes (multi-agent adversarial review of this commit): - tinyusb_win_usbser.inf: the PID rework moved five CDC examples onto even PIDs the INF's odd-only DeviceList never matched (legacy-Windows usbser binding) - appended 0x4006/4008/400a/4020/4022 to both lists. - usbtest example: USBTEST_TIER is now overridable and the descriptors and pumps are tier-conditional, so a board whose DCD cannot serve a tier lowers it instead of skipping the whole example - RA2A1 (RUSB2 with no isochronous pipe) builds at tier 3 via its BOARD_ define; the host battery follows the tier advertised in bcdDevice. Tier-4 output verified byte-identical after the refactor. - dynamic_configuration's second config derived USB_PID + 11 = 0x4018, colliding with net_lwip_webserver - now USB_PID + 0x0100, outside the per-example space. tools/check_example_pids.py (pre-commit hook) enforces PID uniqueness incl. derived and literal idProduct values. - usbtest.py firmware gate: matched by device ID (uPD720201/720202, both use the 0x6c FW register), and an unreadable version (setpci missing/denied) now refuses with its own message instead of masquerading as "firmware 0x00000000"; noted the gate is necessary but not sufficient (board-specific kills stay per-board skips). - hil_test: deadline waits use time.monotonic(); multiprocessing context pinned to fork (raw semaphores in Pool initargs); flash and usbtest permits unified into one fail-closed, exception-safe ctrl_permit (unknown controller takes every slot and logs a warning instead of silently borrowing slot 0); an all-skipped battery reports as skip, not "0/0" failure; slow-body polls (mtp, printer, disk read) go through a shared deadline-based wait_until so their bodies count against the enum budget; throughput's FS detection compares serials case-insensitively like every other walk; a missing MSC read-speed line now fails the host msc_file_explorer test instead of passing with an empty metric. Hardening: - fail fast (15 s) when a driver-registry sysfs write blocks: a wedged device otherwise turns every subsequent battery into an unkillable D-state writer and silently hangs the whole run - usb-recover skill: a VM reboot is not a reliable cure (MosChip hubs latch up across the PCIe reset); full host power cycle is Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-13rusb2: EP0 OUT reliability, HS UTMI PHY power-up, FS-only build supporthathach
- EP0 OUT: park a back-to-back data-stage packet the DCP accepted before PID could go NAK and deliver it into the next armed chunk; flow-control the single-buffer control pipe between chunks (usbtest ctrl_out corruption); discard a packet parked while an OUT pipe was halted so BOT reset recovery's fresh CBW read can't receive stale WRITE data - HS UTMI PHY power-up per the FSP sequence, shared by dcd/hcd: CLKSEL programmed from the board XTAL (EK-RA8M1 runs 20 MHz; the 24 MHz reset default never locks) while DIRPD holds the PHY down, then timed release - hw/bsp(ra8m1_ek): fix U60CK divider macro - BSP_CFG_U60CK_DIV used the generic USB_CLOCK_DIV_8 encoding (7), which USB60CKDIVCR rejects, leaving the USBHS link domain at 480 MHz; the USB60-specific BSP_CLOCKS_USB60_CLOCK_DIV_8 (4) sticks and yields the required 60 MHz from PLL1P - support FS-only builds on the high-speed port: gate SYSCFG.HSE on TUD_OPT_HIGH_SPEED (RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED was a silent no-op) and always compile both hwfifo access widths - the FIFO width belongs to the module, not the link speed (FS builds corrupted odd-length tails: 16-bit access against MBW-32) - iso activate: reset stale pipe bookkeeping so a BRDY firing before the class re-arms can't replay a pre-SET_INTERFACE transfer; write PIPEBUF after PIPESEL selects the pipe (PIPESEL-windowed register) - clear-halt: re-assert BUF on a still-armed OUT pipe (usbtest case 29) - bound the D0FIFO ready spin so an undrained double-buffered IN pipe can't freeze the stack with the IRQ masked - usbtest example: cap interrupt mps at 64 on RUSB2 high speed (pipes 6-9 have a fixed 64-byte buffer, RA6M5 UM 29.1) Verified: usbtest 30/30 on ra6m5_ek (HS), ra4m1_ek (FS) and ra8m1_ek (FS-forced build on the HS port). Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-09example(usbtest): device-side peer for the Linux kernel usbtest batteryhathach
Gadget-Zero style source/sink on a vendor interface (alt0 empty, alt1 bulk+int+iso) plus EP0 ctrl_out; tier advertised in bcdDevice. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HeF2gZ1M7GWkz6Av4BpKPg
2026-07-05Merge pull request #3738 from sauloverissimo/fix/midi2-fb-directionZixun LI
feat(midi2): derive function blocks from the GTB descriptor
2026-07-03fix HID_STACK_SIZE typoHiFiPhile
Signed-off-by: HiFiPhile <[email protected]>
2026-07-03fix: correct video stack macro typo in video capture examplescuolm
Corrects VIDEO_STACK_SZIE to VIDEO_STACK_SIZE.
2026-06-29docs: address Copilot review on the example READMEshathach
- Order CFG_TUH_DEVICE_MAX before CFG_TUH_HID in the host config snippets (cdc_msc_hid, hid_controller) so the documented snippet has no forward macro reference when copied into tusb_config.h. - Fix stale `examples.rst` references: the generator now writes per-group `docs/examples/<group>/index.rst` pages, so update the conf.py comment and the build-doc SKILL.md accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-29docs: add build-doc tooling and a README for every examplehathach
Documentation tooling: - Add the `build-doc` skill and `tools/build_doc.py` wrapper for local Sphinx builds (clean / -W / open). - Enable Markdown (MyST) in conf.py and auto-collect examples/{device,host,dual}/*/README.md into a 3-level Examples nav (Examples > Device/Host/Dual > example), noting each page's source location and normalizing headings to a single H1. - Remove the stale `.claude/commands/build-doc.md`; point the AGENTS.md Documentation section at the skill. Example docs: - Add a README.md for every device/host/dual example: what it does, USB interface table, notable tusb_config.h settings, generic CMake + Make build steps, and how to try it. - Fold each *_freertos variant into its base README, noting the FreeRTOS source path and any RTOS-specific behavior. Generated docs/examples/ output is git-ignored. Builds clean with `sphinx-build -W`. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>