diff options
| author | hathach <[email protected]> | 2026-07-02 22:06:24 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-07-02 22:06:24 +0700 |
| commit | bda8f9cf9a0a2c8d7e0972c4f130fa839a1b891d (patch) | |
| tree | 36967366af56795aff92eb210835516031d30046 /examples/device/usbtest/src | |
| parent | 73b42f80992f9da5d27eed061dc7c25358bf3259 (diff) | |
example(usbtest): tier 3 - interrupt source/sink (cases 25/26)
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
Diffstat (limited to 'examples/device/usbtest/src')
| -rw-r--r-- | examples/device/usbtest/src/main.c | 44 | ||||
| -rw-r--r-- | examples/device/usbtest/src/tusb_config.h | 6 | ||||
| -rw-r--r-- | examples/device/usbtest/src/usb_descriptors.c | 55 | ||||
| -rw-r--r-- | examples/device/usbtest/src/usb_descriptors.h | 5 |
4 files changed, 79 insertions, 31 deletions
diff --git a/examples/device/usbtest/src/main.c b/examples/device/usbtest/src/main.c index 56b0128d8..ee5b53073 100644 --- a/examples/device/usbtest/src/main.c +++ b/examples/device/usbtest/src/main.c @@ -26,8 +26,8 @@ /* Device-side peer of the Linux kernel host test driver drivers/usb/misc/usbtest.c * (driven from userspace by tools/usb/testusb.c). Implements the Gadget-Zero * style source/sink protocol on a vendor interface: - * - bulk IN = infinite source (pattern 0: all zeros) - * - bulk OUT = infinite sink (data discarded) + * - bulk/interrupt IN = infinite source (pattern 0: all zeros) + * - bulk/interrupt OUT = infinite sink (data discarded) * - EP0 0x5b/0x5c = control write then read-back (ctrl_out tests) * See examples/device/usbtest/README.md and test/hil/usbtest.py for usage. */ @@ -57,9 +57,11 @@ enum { static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; -// Source data, all zeros = usbtest pattern 0. Size is a multiple of bulk MPS at -// both speeds: transfers are always whole packets, never an unintended short/ZLP. +// Source data, all zeros = usbtest pattern 0. Sizes are a multiple of the +// endpoint max packet size: transfers are always whole packets, never an +// unintended short packet or ZLP. static uint8_t const tx_chunk[CFG_TUD_VENDOR_TX_EPSIZE]; +static uint8_t const int_tx_chunk[USBTEST_INT_EP_MPS]; //------------- prototypes -------------// void led_blinking_task(void); @@ -89,19 +91,23 @@ int main(void) { // Source/sink pumps //--------------------------------------------------------------------+ -// Polling keeps both directions armed and self-heals after endpoint halt -// (set/clear feature tests): stall marks the endpoint busy so both calls fail +// Polling keeps all four endpoints armed and self-heals after endpoint halt +// (set/clear feature tests): stall marks the endpoint busy so the calls fail // quietly until the host clears the halt, then the next tick re-arms. static void usbtest_task(void) { if (!tud_vendor_mounted()) { return; } - tud_vendor_read_xfer(); // sink: arm/re-arm OUT, quiet fail if already armed or halted - - if (tud_vendor_write_available()) { // 0 while IN is busy or halted + tud_vendor_read_xfer(); // bulk sink: arm/re-arm, quiet fail if armed or halted + if (tud_vendor_write_available()) { // 0 while bulk IN is busy or halted tud_vendor_write(tx_chunk, sizeof(tx_chunk)); } + + tud_vendor_int_read_xfer(); // interrupt sink + if (tud_vendor_int_write_available()) { + tud_vendor_int_write(int_tx_chunk, sizeof(int_tx_chunk)); + } } // Invoked when received data from host: discard and immediately re-arm @@ -112,13 +118,31 @@ void tud_vendor_rx_cb(uint8_t idx, const uint8_t* buffer, uint32_t bufsize) { tud_vendor_read_xfer(); } -// Invoked when last tx transfer finished: keep the source saturated +// Invoked when last bulk tx transfer finished: keep the source saturated void tud_vendor_tx_cb(uint8_t idx, uint32_t sent_bytes) { (void) idx; (void) sent_bytes; tud_vendor_write(tx_chunk, sizeof(tx_chunk)); } +// Interrupt pair: same discard/refill pumps as bulk +void tud_vendor_int_rx_cb(uint8_t idx, const uint8_t* buffer, uint32_t bufsize) { + (void) idx; + (void) buffer; + (void) bufsize; + tud_vendor_int_read_xfer(); +} + +void tud_vendor_int_tx_cb(uint8_t idx, uint32_t sent_bytes) { + (void) idx; + (void) sent_bytes; + tud_vendor_int_write(int_tx_chunk, sizeof(int_tx_chunk)); +} + +//--------------------------------------------------------------------+ +// Vendor control requests (EP0) +//--------------------------------------------------------------------+ + // Control write/read-back for the ctrl_out tests (14/21), same protocol as // Gadget Zero: 0x5b stores the host's wLength bytes, 0x5c returns them. static uint8_t ctrl_buf[1024]; diff --git a/examples/device/usbtest/src/tusb_config.h b/examples/device/usbtest/src/tusb_config.h index 058e2362c..19729f0ca 100644 --- a/examples/device/usbtest/src/tusb_config.h +++ b/examples/device/usbtest/src/tusb_config.h @@ -110,6 +110,12 @@ // Multi-packet IN transfers; must be a multiple of bulk MPS at both speeds (64/512) #define CFG_TUD_VENDOR_TX_EPSIZE 2048 +// Interrupt IN/OUT source/sink pair (usbtest cases 25/26) +#define CFG_TUD_VENDOR_EP_INT_OUT 1 +#define CFG_TUD_VENDOR_EP_INT_IN 1 +#define CFG_TUD_VENDOR_EP_INT_OUT_BUFSIZE 512 +#define CFG_TUD_VENDOR_EP_INT_IN_BUFSIZE 512 + #ifdef __cplusplus } #endif diff --git a/examples/device/usbtest/src/usb_descriptors.c b/examples/device/usbtest/src/usb_descriptors.c index 7ef1c2ff2..e73cd7df5 100644 --- a/examples/device/usbtest/src/usb_descriptors.c +++ b/examples/device/usbtest/src/usb_descriptors.c @@ -65,43 +65,57 @@ enum { ITF_NUM_TOTAL }; -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_VENDOR_DESC_LEN) +// Vendor interface with bulk IN/OUT source/sink plus interrupt IN/OUT: the host +// usbtest driver collects all pipe types from one altsetting. No TUD_ macro +// covers this layout, hand-rolled: interface + 2 bulk + 2 interrupt endpoints. +#define USBTEST_DESC_LEN (9 + 4*7) +#define USBTEST_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _bulk_mps, _intout, _intin, _int_mps, _int_interval) \ + 9, TUSB_DESC_INTERFACE, _itfnum, 0, 4, TUSB_CLASS_VENDOR_SPECIFIC, 0x00, 0x00, _stridx,\ + 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_mps), 0,\ + 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_bulk_mps), 0,\ + 7, TUSB_DESC_ENDPOINT, _intout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_int_mps), _int_interval,\ + 7, TUSB_DESC_ENDPOINT, _intin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_int_mps), _int_interval + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + USBTEST_DESC_LEN) #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number - // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... - #define EPNUM_VENDOR_OUT 0x02 - #define EPNUM_VENDOR_IN 0x82 - -#elif CFG_TUSB_MCU == OPT_MCU_CXD56 - // CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number - // 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN) - #define EPNUM_VENDOR_OUT 0x02 - #define EPNUM_VENDOR_IN 0x81 + // 0 control, 1 Interrupt, 2 Bulk, 3 Iso, 4 Interrupt etc ... + #define EPNUM_BULK_OUT 0x02 + #define EPNUM_BULK_IN 0x85 + #define EPNUM_INT_OUT 0x01 + #define EPNUM_INT_IN 0x84 #elif CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY // MCUs that don't support a same endpoint number with different direction IN and OUT // e.g EP1 OUT & EP1 IN cannot exist together #if TU_CHECK_MCU(OPT_MCU_MAX32650, OPT_MCU_MAX32666, OPT_MCU_MAX32690, OPT_MCU_MAX78002) // Put bulk on EP>=8 so the 2048/4096-byte FIFOs can back double packet buffering - #define EPNUM_VENDOR_OUT 0x08 - #define EPNUM_VENDOR_IN 0x89 + #define EPNUM_BULK_OUT 0x08 + #define EPNUM_BULK_IN 0x89 + #define EPNUM_INT_OUT 0x02 + #define EPNUM_INT_IN 0x83 #else - #define EPNUM_VENDOR_OUT 0x01 - #define EPNUM_VENDOR_IN 0x82 + #define EPNUM_BULK_OUT 0x01 + #define EPNUM_BULK_IN 0x82 + #define EPNUM_INT_OUT 0x03 + #define EPNUM_INT_IN 0x84 #endif #else - #define EPNUM_VENDOR_OUT 0x01 - #define EPNUM_VENDOR_IN 0x81 + #define EPNUM_BULK_OUT 0x01 + #define EPNUM_BULK_IN 0x81 + #define EPNUM_INT_OUT 0x02 + #define EPNUM_INT_IN 0x82 #endif static uint8_t const desc_fs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), - // Interface number, string index, EP Out & IN address, EP size - TUD_VENDOR_DESCRIPTOR(ITF_NUM_VENDOR, 4, EPNUM_VENDOR_OUT, 0x80 | EPNUM_VENDOR_IN, 64) + // Interface number, string index, bulk EP out/in + mps, interrupt EP out/in + mps + interval + USBTEST_DESCRIPTOR(ITF_NUM_VENDOR, 4, EPNUM_BULK_OUT, 0x80 | EPNUM_BULK_IN, 64, + EPNUM_INT_OUT, 0x80 | EPNUM_INT_IN, 64, 1) }; #if TUD_OPT_HIGH_SPEED @@ -111,8 +125,9 @@ static uint8_t const desc_hs_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), - // Interface number, string index, EP Out & IN address, EP size - TUD_VENDOR_DESCRIPTOR(ITF_NUM_VENDOR, 4, EPNUM_VENDOR_OUT, 0x80 | EPNUM_VENDOR_IN, 512) + // Interface number, string index, bulk EP out/in + mps, interrupt EP out/in + mps + interval (1 ms) + USBTEST_DESCRIPTOR(ITF_NUM_VENDOR, 4, EPNUM_BULK_OUT, 0x80 | EPNUM_BULK_IN, 512, + EPNUM_INT_OUT, 0x80 | EPNUM_INT_IN, 512, 4) }; // other speed configuration diff --git a/examples/device/usbtest/src/usb_descriptors.h b/examples/device/usbtest/src/usb_descriptors.h index 6b703ed8f..02ea9ccbd 100644 --- a/examples/device/usbtest/src/usb_descriptors.h +++ b/examples/device/usbtest/src/usb_descriptors.h @@ -32,6 +32,9 @@ // 2: + vendor control 0x5b/0x5c (ctrl_out) // 3: + interrupt source/sink // 4: + isochronous source/sink -#define USBTEST_TIER 2 +#define USBTEST_TIER 3 + +// Interrupt endpoint max packet size, must match the configuration descriptor +#define USBTEST_INT_EP_MPS (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif /* USB_DESCRIPTORS_H_ */ |
