From 27415e6114cb6e23ca085b21161eb79278f6b97b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Oct 2025 06:12:08 +0000 Subject: Add is_isr parameter to usbd_edpt_xfer and usbd_edpt_xfer_fifo - Added bool is_isr parameter to usbd_edpt_xfer() and usbd_edpt_xfer_fifo() wrapper functions - These are called by class drivers to queue USB transfers - Updated all callers to pass false by default (non-ISR context) - Updated audiod_rx_xfer_isr() and audiod_tx_xfer_isr() to pass true (ISR context) - All 21 unit tests pass Co-authored-by: HiFiPhile <4375114+HiFiPhile@users.noreply.github.com> --- src/tusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tusb.c') diff --git a/src/tusb.c b/src/tusb.c index 083e6d861..7f451ee70 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -378,7 +378,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_xfer(uint8_t hwid, tu_edpt_strea #endif } else { #if CFG_TUD_ENABLED - return usbd_edpt_xfer(hwid, s->ep_addr, count ? s->ep_buf : NULL, count); + return usbd_edpt_xfer(hwid, s->ep_addr, count ? s->ep_buf : NULL, count, false); #endif } return false; -- cgit v1.3.1 From 55c6d07af314627c55d595cc74d0d7694ce6f091 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 24 Oct 2025 14:28:59 +0700 Subject: fix more warnings --- hw/bsp/board_api.h | 6 ++++-- hw/bsp/samd5x_e5x/family.c | 2 +- hw/bsp/stm32f4/family.c | 2 +- hw/bsp/stm32f7/family.c | 2 +- hw/bsp/stm32h7/family.c | 4 ++-- hw/bsp/stm32h7rs/family.c | 2 +- hw/bsp/stm32n6/family.c | 2 +- src/common/tusb_types.h | 8 ++++---- src/device/dcd.h | 2 +- src/osal/osal.h | 2 +- src/osal/osal_none.h | 4 ++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 6 +++--- src/tusb.c | 8 ++++++-- src/tusb_option.h | 10 +++++----- 14 files changed, 33 insertions(+), 27 deletions(-) (limited to 'src/tusb.c') diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 5ecd7797a..80d86a4aa 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -154,11 +154,13 @@ static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars // TODO work with make, but not working with esp32s3 cmake uid_len = board_get_unique_id(uid, sizeof(uid)); - if ( uid_len > max_chars / 2 ) uid_len = max_chars / 2; + if ( uid_len > max_chars / 2u ) { + uid_len = max_chars / 2u; + } for ( size_t i = 0; i < uid_len; i++ ) { for ( size_t j = 0; j < 2; j++ ) { - const char nibble_to_hex[16] = { + const unsigned char nibble_to_hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; diff --git a/hw/bsp/samd5x_e5x/family.c b/hw/bsp/samd5x_e5x/family.c index d53aa00d6..df6f19d0f 100644 --- a/hw/bsp/samd5x_e5x/family.c +++ b/hw/bsp/samd5x_e5x/family.c @@ -179,7 +179,7 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { for (int i = 0; i < 4; i++) { uint32_t did = *((uint32_t const*) did_addr[i]); did = TU_BSWAP32(did); // swap endian to match samd51 uf2 bootloader - memcpy(id + i * 4, &did, 4); + memcpy(id + i * 4, &did, sizeof(uint32_t)); } return 16; diff --git a/hw/bsp/stm32f4/family.c b/hw/bsp/stm32f4/family.c index 260927903..6e02b0575 100644 --- a/hw/bsp/stm32f4/family.c +++ b/hw/bsp/stm32f4/family.c @@ -54,7 +54,7 @@ void OTG_HS_IRQHandler(void) { // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index bf2d28e42..38dfaa3bc 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -46,7 +46,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c index 4f80b15ff..7b618b2e4 100644 --- a/hw/bsp/stm32h7/family.c +++ b/hw/bsp/stm32h7/family.c @@ -49,7 +49,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, @@ -127,7 +127,7 @@ void board_init(void) { #if CFG_TUSB_OS == OPT_OS_NONE // 1ms tick timer - SysTick_Config(SystemCoreClock / 1000); + SysTick_Config(SystemCoreClock / 1000u); #elif CFG_TUSB_OS == OPT_OS_FREERTOS // Explicitly disable systick to prevent its ISR runs before scheduler start diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c index 80ac81125..6192f7a40 100644 --- a/hw/bsp/stm32h7rs/family.c +++ b/hw/bsp/stm32h7rs/family.c @@ -49,7 +49,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/hw/bsp/stm32n6/family.c b/hw/bsp/stm32n6/family.c index 1d0616d8e..58be4867d 100644 --- a/hw/bsp/stm32n6/family.c +++ b/hw/bsp/stm32n6/family.c @@ -62,7 +62,7 @@ typedef struct { //--------------------------------------------------------------------+ #ifdef UART_DEV -UART_HandleTypeDef UartHandle = { +static UART_HandleTypeDef UartHandle = { .Instance = UART_DEV, .Init = { .BaudRate = CFG_BOARD_UART_BAUDRATE, diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index ec01bbf0f..c0b7469ed 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -77,9 +77,9 @@ *------------------------------------------------------------------*/ typedef enum { - TUSB_ROLE_INVALID = 0, - TUSB_ROLE_DEVICE = 0x1, - TUSB_ROLE_HOST = 0x2, + TUSB_ROLE_INVALID = 0u, + TUSB_ROLE_DEVICE = 0x1u, + TUSB_ROLE_HOST = 0x2u, } tusb_role_t; /// defined base on EHCI specs value for Endpoint Speed @@ -178,7 +178,7 @@ typedef enum { } tusb_request_feature_selector_t; typedef enum { - TUSB_REQ_TYPE_STANDARD = 0, + TUSB_REQ_TYPE_STANDARD = 0u, TUSB_REQ_TYPE_CLASS, TUSB_REQ_TYPE_VENDOR, TUSB_REQ_TYPE_INVALID diff --git a/src/device/dcd.h b/src/device/dcd.h index 400f62bff..436c4555f 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -79,7 +79,7 @@ typedef struct TU_ATTR_ALIGNED(4) { // FUNC_CALL struct { - void (*func) (void*); + void (*func) (void* param); void* param; }func_call; }; diff --git a/src/osal/osal.h b/src/osal/osal.h index 8faa81b07..658b18584 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -33,7 +33,7 @@ #include "common/tusb_common.h" -typedef void (*osal_task_func_t)( void * ); +typedef void (*osal_task_func_t)(void* param); // Timeout #define OSAL_TIMEOUT_NOTIMEOUT (0) // Return immediately diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 3e397ef35..6f9b8b0dc 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -35,7 +35,7 @@ extern "C" { // Spinlock API //--------------------------------------------------------------------+ typedef struct { - void (* interrupt_set)(bool); + void (* interrupt_set)(bool enabled); } osal_spinlock_t; // For SMP, spinlock must be locked by hardware, cannot just use interrupt @@ -141,7 +141,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd #include "common/tusb_fifo.h" typedef struct { - void (* interrupt_set)(bool); + void (* interrupt_set)(bool enabled); tu_fifo_t ff; } osal_queue_def_t; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index f1e4dbd77..8560b2109 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -379,7 +379,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin // Enable tx fifo empty interrupt only if there is data. Note must after depctl enable if (dir == TUSB_DIR_IN && total_bytes != 0) { - dwc2->diepempmsk |= (1 << epnum); + dwc2->diepempmsk |= (1u << epnum); } } } @@ -402,7 +402,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { // Set device max speed uint32_t dcfg = dwc2->dcfg & ~DCFG_DSPD_Msk; if (is_highspeed) { - dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos; + // dcfg Highspeed's mask is 0 // XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required // when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347) @@ -914,7 +914,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep // Turn off TXFE if all bytes are written. tsiz.value = epin->tsiz; if (tsiz.xfer_size == 0) { - dwc2->diepempmsk &= ~(1 << epnum); + dwc2->diepempmsk &= ~(1u << epnum); } } } diff --git a/src/tusb.c b/src/tusb.c index 083e6d861..d52c156ab 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -576,8 +576,12 @@ void tu_print_mem(void const* buf, uint32_t count, uint8_t indent) { if (i % item_per_line == 0) { // Print Ascii - if (i != 0) dump_str_line(buf8 - 16, 16); - for (uint8_t s = 0; s < indent; s++) tu_printf(" "); + if (i != 0) { + dump_str_line(buf8 - 16, 16); + } + for (uint8_t s = 0; s < indent; s++) { + tu_printf(" "); + } // print offset or absolute address tu_printf("%04X: ", 16 * i / item_per_line); } diff --git a/src/tusb_option.h b/src/tusb_option.h index 9d5aed252..14404c59c 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -244,11 +244,11 @@ #define OPT_MODE_HOST 0x0002 ///< Host Mode // High byte is max operational speed (corresponding to tusb_speed_t) -#define OPT_MODE_DEFAULT_SPEED 0x0000 ///< Default (max) speed supported by MCU -#define OPT_MODE_LOW_SPEED 0x0100 ///< Low Speed -#define OPT_MODE_FULL_SPEED 0x0200 ///< Full Speed -#define OPT_MODE_HIGH_SPEED 0x0400 ///< High Speed -#define OPT_MODE_SPEED_MASK 0xff00 +#define OPT_MODE_DEFAULT_SPEED 0x0000u ///< Default (max) speed supported by MCU +#define OPT_MODE_LOW_SPEED 0x0100u ///< Low Speed +#define OPT_MODE_FULL_SPEED 0x0200u ///< Full Speed +#define OPT_MODE_HIGH_SPEED 0x0400u ///< High Speed +#define OPT_MODE_SPEED_MASK 0xff00u //--------------------------------------------------------------------+ // Include tusb_config.h -- cgit v1.3.1 From 1f04fe7924e8777c1583323171c0e1cabcb29062 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 5 Nov 2025 15:31:02 +0700 Subject: added .clang-format fix more alerts disable IAR CStat since pvs-studio check is better integrated with clion --- .PVS-Studio/.pvsconfig | 13 +- .clang-format | 102 ++++++---- .github/workflows/static_analysis.yml | 3 +- README.rst | 6 +- examples/device/audio_4_channel_mic/src/main.c | 8 +- .../src/usb_descriptors.c | 8 +- examples/device/audio_test/src/main.c | 8 +- examples/device/audio_test/src/usb_descriptors.c | 8 +- .../audio_test_freertos/src/usb_descriptors.c | 8 +- examples/device/audio_test_multi_rate/src/main.c | 8 +- .../audio_test_multi_rate/src/usb_descriptors.c | 8 +- examples/device/cdc_dual_ports/src/main.c | 12 +- examples/device/cdc_msc/src/msc_disk.c | 28 ++- examples/device/cdc_uac2/src/uac2_app.c | 28 +-- examples/device/cdc_uac2/src/usb_descriptors.c | 8 +- examples/device/dfu/src/usb_descriptors.c | 8 +- examples/device/dfu_runtime/src/main.c | 4 +- examples/device/dfu_runtime/src/usb_descriptors.c | 8 +- examples/device/dynamic_configuration/src/main.c | 56 +++--- .../device/dynamic_configuration/src/msc_disk.c | 14 +- .../dynamic_configuration/src/usb_descriptors.c | 8 +- examples/device/hid_boot_interface/src/main.c | 147 +++++++------- .../hid_boot_interface/src/usb_descriptors.c | 124 ++++++------ examples/device/hid_composite/src/main.c | 211 ++++++++++----------- examples/device/mtp/src/mtp_fs_example.c | 90 +++++---- hw/bsp/family_support.cmake | 8 +- src/class/mtp/mtp.h | 14 +- src/class/mtp/mtp_device.h | 10 +- src/class/video/video.h | 10 +- src/common/tusb_common.h | 7 +- src/common/tusb_debug.h | 4 +- src/device/usbd_control.c | 6 +- src/device/usbd_pvt.h | 5 - src/tusb.c | 4 +- 34 files changed, 523 insertions(+), 471 deletions(-) (limited to 'src/tusb.c') diff --git a/.PVS-Studio/.pvsconfig b/.PVS-Studio/.pvsconfig index 32125c2f7..2e231c939 100644 --- a/.PVS-Studio/.pvsconfig +++ b/.PVS-Studio/.pvsconfig @@ -1,3 +1,10 @@ -//-V::2506 -//-V::2514 -//-V::2614 +//V_EXCLUDE_PATH */iar/cxarm* +//V_EXCLUDE_PATH */pico-sdk/* + +//-V::2506 MISRA. A function should have a single point of exit at the end. +//-V::2514 MISRA. Unions should not be used. +//-V:memcpy:2547 [MISRA-C-17.7] The return value of non-void function 'memcpy' should be used. +//-V:printf:2547 [MISRA-C-17.7] The return value of non-void function 'printf' should be used. +//-V::2600 [MISRA-C-21.6] The function with the 'printf' name should not be used. +//+V2614 DISABLE_LENGHT_LIMIT_CHECK:YES +//-V:memcpy:2628 Pointer arguments to the 'memcpy' function should be pointers to qualified or unqualified versions of compatible types. diff --git a/.clang-format b/.clang-format index 0fd168e5a..79a160a8d 100644 --- a/.clang-format +++ b/.clang-format @@ -1,66 +1,88 @@ -# Generated from CLion C/C++ Code Style settings +--- +Language: Cpp BasedOnStyle: LLVM -AccessModifierOffset: -2 -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: None -AlignOperands: Align +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveBitFields: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: true + AcrossComments: false +AlignConsecutiveShortCaseStatements: + Enabled: true + AcrossEmptyLines: true + AcrossComments: true + AlignCaseColons: false +AlignEscapedNewlines: LeftWithLastLine +AlignOperands: true +AlignTrailingComments: + Kind: Always + OverEmptyLines: 2 AllowAllArgumentsOnNextLine: false AllowAllConstructorInitializersOnNextLine: false AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: Always -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Always -AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: true -AlwaysBreakAfterReturnType: None +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseExpressionOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never AlwaysBreakTemplateDeclarations: Yes BreakBeforeBraces: Custom BraceWrapping: AfterCaseLabel: false AfterClass: false - AfterControlStatement: Never + AfterControlStatement: false AfterEnum: false AfterFunction: false AfterNamespace: false + AfterStruct: false AfterUnion: false - BeforeCatch: false + AfterExternBlock: false + BeforeCatch: true BeforeElse: false - IndentBraces: false - SplitEmptyFunction: false + BeforeLambdaBody: false + BeforeWhile: false + SplitEmptyFunction: true SplitEmptyRecord: true -BreakBeforeBinaryOperators: None -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeColon -BreakInheritanceList: BeforeColon -ColumnLimit: 0 -CompactNamespaces: false -ContinuationIndentWidth: 4 + SplitEmptyNamespace: true +BracedInitializerIndentWidth: 2 +BreakConstructorInitializers: AfterColon +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 120 +ConstructorInitializerAllOnOneLineOrOnePerLine: false +Cpp11BracedListStyle: true +IncludeCategories: + - Regex: '^<.*' + Priority: 1 + - Regex: '^".*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '([-_](test|unittest))?$' +InsertBraces: true IndentCaseLabels: true -IndentPPDirectives: BeforeHash -IndentWidth: 2 -KeepEmptyLinesAtTheStartOfBlocks: true +InsertNewlineAtEOF: true +MacroBlockBegin: '' +MacroBlockEnd: '' MaxEmptyLinesToKeep: 2 NamespaceIndentation: All -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PointerAlignment: Right ReflowComments: false -SpaceAfterCStyleCast: true -SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements SpaceBeforeRangeBasedForLoopColon: false SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 0 SpacesInAngles: false +SpacesInConditionalStatement: false SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: true SpacesInParentheses: false -SpacesInSquareBrackets: false TabWidth: 2 -UseTab: Never +... diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 7e74f77ce..227f5e103 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -183,7 +183,8 @@ jobs: --define sonar.cfamily.compile-commands=${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json IAR-CStat: - if: github.repository_owner == 'hathach' + #if: github.repository_owner == 'hathach' + if: false runs-on: ubuntu-latest strategy: fail-fast: false diff --git a/README.rst b/README.rst index 38ebcc8da..fcec5d613 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -|Build Status| |CircleCI Status| |Documentation Status| |Fuzzing Status| |License| +|Build Status| |CircleCI Status| |Documentation Status| |Static Analysis| |Fuzzing Status| |License| Sponsors ======== @@ -252,11 +252,13 @@ The following tools are provided freely to support the development of the TinyUS .. |Build Status| image:: https://github.com/hathach/tinyusb/actions/workflows/build.yml/badge.svg - :target: https://github.com/hathach/tinyusb/actions + :target: https://github.com/hathach/tinyusb/actions/workflows/build.yml .. |CircleCI Status| image:: https://dl.circleci.com/status-badge/img/circleci/4AYHvUhFxdnY4rA7LEsdqW/QmrpoL2AjGqetvFQNqtWyq/tree/master.svg?style=svg :target: https://dl.circleci.com/status-badge/redirect/circleci/4AYHvUhFxdnY4rA7LEsdqW/QmrpoL2AjGqetvFQNqtWyq/tree/master .. |Documentation Status| image:: https://readthedocs.org/projects/tinyusb/badge/?version=latest :target: https://docs.tinyusb.org/en/latest/?badge=latest +.. |Static Analysis| image:: https://github.com/hathach/tinyusb/actions/workflows/static_analysis.yml/badge.svg + :target: https://github.com/hathach/tinyusb/actions/workflows/static_analysis.yml .. |Fuzzing Status| image:: https://oss-fuzz-build-logs.storage.googleapis.com/badges/tinyusb.svg :target: https://oss-fuzz-build-logs.storage.googleapis.com/index.html#tinyusb .. |License| image:: https://img.shields.io/badge/license-MIT-brightgreen.svg diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index de9e8a06a..5767c7453 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -156,7 +156,9 @@ void tud_resume_cb(void) { void audio_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if (start_ms == curr_ms) return;// not enough time + if (start_ms == curr_ms) { + return; // not enough time + } start_ms = curr_ms; tud_audio_write(i2s_dummy_buffer, AUDIO_SAMPLE_RATE / 1000 * CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE_TX * CFG_TUD_AUDIO_FUNC_1_N_CHANNELS_TX); } @@ -406,7 +408,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return;// not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c index 2f5f67f66..3bb93f67d 100644 --- a/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c +++ b/examples/device/audio_4_channel_mic_freertos/src/usb_descriptors.c @@ -156,14 +156,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if ( chr_count > max_count ) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 875d0b7f0..2441eefbc 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -139,7 +139,9 @@ void tud_resume_cb(void) { void audio_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if (start_ms == curr_ms) return;// not enough time + if (start_ms == curr_ms) { + return; // not enough time + } start_ms = curr_ms; for (size_t cnt = 0; cnt < sizeof(test_buffer_audio) / 2; cnt++) { test_buffer_audio[cnt] = startVal++; @@ -400,7 +402,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return;// not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/audio_test/src/usb_descriptors.c b/examples/device/audio_test/src/usb_descriptors.c index b6c19deba..ad161939e 100644 --- a/examples/device/audio_test/src/usb_descriptors.c +++ b/examples/device/audio_test/src/usb_descriptors.c @@ -158,14 +158,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/audio_test_freertos/src/usb_descriptors.c b/examples/device/audio_test_freertos/src/usb_descriptors.c index b6c19deba..ad161939e 100644 --- a/examples/device/audio_test_freertos/src/usb_descriptors.c +++ b/examples/device/audio_test_freertos/src/usb_descriptors.c @@ -158,14 +158,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/audio_test_multi_rate/src/main.c b/examples/device/audio_test_multi_rate/src/main.c index 55a649613..baeec870f 100644 --- a/examples/device/audio_test_multi_rate/src/main.c +++ b/examples/device/audio_test_multi_rate/src/main.c @@ -147,7 +147,9 @@ void tud_resume_cb(void) { void audio_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if (start_ms == curr_ms) return;// not enough time + if (start_ms == curr_ms) { + return; // not enough time + } start_ms = curr_ms; // 16bit if (bytesPerSample == 2) { @@ -612,7 +614,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return;// not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/audio_test_multi_rate/src/usb_descriptors.c b/examples/device/audio_test_multi_rate/src/usb_descriptors.c index 1912a81e2..471eb4f2e 100644 --- a/examples/device/audio_test_multi_rate/src/usb_descriptors.c +++ b/examples/device/audio_test_multi_rate/src/usb_descriptors.c @@ -213,14 +213,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/cdc_dual_ports/src/main.c b/examples/device/cdc_dual_ports/src/main.c index 8fe003f21..5ccb06a8a 100644 --- a/examples/device/cdc_dual_ports/src/main.c +++ b/examples/device/cdc_dual_ports/src/main.c @@ -75,10 +75,14 @@ static void echo_serial_port(uint8_t itf, uint8_t buf[], uint32_t count) { for (uint32_t i = 0; i < count; i++) { if (itf == 0) { // echo back 1st port as lower case - if (isupper(buf[i])) buf[i] += case_diff; + if (isupper(buf[i])) { + buf[i] += case_diff; + } } else { // echo back 2nd port as upper case - if (islower(buf[i])) buf[i] -= case_diff; + if (islower(buf[i])) { + buf[i] -= case_diff; + } } tud_cdc_n_write_char(itf, buf[i]); @@ -153,7 +157,9 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/cdc_msc/src/msc_disk.c b/examples/device/cdc_msc/src/msc_disk.c index 1a95f7f8b..e091c2985 100644 --- a/examples/device/cdc_msc/src/msc_disk.c +++ b/examples/device/cdc_msc/src/msc_disk.c @@ -128,9 +128,9 @@ uint32_t tud_msc_inquiry2_cb(uint8_t lun, scsi_inquiry_resp_t *inquiry_resp, uin const char pid[] = "Mass Storage"; const char rev[] = "1.0"; - strncpy((char*) inquiry_resp->vendor_id, vid, 8); - strncpy((char*) inquiry_resp->product_id, pid, 16); - strncpy((char*) inquiry_resp->product_rev, rev, 4); + (void) strncpy((char*) inquiry_resp->vendor_id, vid, 8); + (void) strncpy((char*) inquiry_resp->product_id, pid, 16); + (void) strncpy((char*) inquiry_resp->product_rev, rev, 4); return sizeof(scsi_inquiry_resp_t); // 36 bytes } @@ -143,8 +143,7 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) { // RAM disk is ready until ejected if (ejected) { // Additional Sense 3A-00 is NOT_FOUND - tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00); - return false; + return tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00); } return true; @@ -154,7 +153,6 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) { // Application update block count and block size void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) { (void) lun; - *block_count = DISK_BLOCK_NUM; *block_size = DISK_BLOCK_SIZE; } @@ -194,7 +192,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buff } uint8_t const *addr = msc_disk[lba] + offset; - memcpy(buffer, addr, bufsize); + (void) memcpy(buffer, addr, bufsize); return (int32_t) bufsize; } @@ -221,7 +219,7 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t * #ifndef CFG_EXAMPLE_MSC_READONLY uint8_t *addr = msc_disk[lba] + offset; - memcpy(addr, buffer, bufsize); + (void) memcpy(addr, buffer, bufsize); #else (void) lba; (void) offset; @@ -235,19 +233,17 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t * // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 has their own callbacks int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) { + (void) lun; + (void) scsi_cmd; (void) buffer; (void) bufsize; - switch (scsi_cmd[0]) { - default: - // Set Sense = Invalid Command Operation - tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); + // currently no other commands is supported - // negative means error -> tinyusb could stall and/or response with failed status - return -1; - } + // Set Sense = Invalid Command Operation + (void) tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); - return -1; + return -1; // stall/failed command request; } #endif diff --git a/examples/device/cdc_uac2/src/uac2_app.c b/examples/device/cdc_uac2/src/uac2_app.c index cb7b716e8..73a262d0c 100644 --- a/examples/device/cdc_uac2/src/uac2_app.c +++ b/examples/device/cdc_uac2/src/uac2_app.c @@ -67,7 +67,9 @@ uint8_t current_resolution; void audio_task(void) { static uint32_t start_ms = 0; uint32_t curr_ms = board_millis(); - if (start_ms == curr_ms) return;// not enough time + if (start_ms == curr_ms) { + return; // not enough time + } start_ms = curr_ms; // When new data arrived, copy data from speaker buffer, to microphone buffer // and send it over @@ -226,16 +228,15 @@ static bool tud_audio_feature_unit_set_request(uint8_t rhport, audio20_control_r //--------------------------------------------------------------------+ // Invoked when audio class specific get request received for an entity -bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) -{ +bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request) { audio20_control_request_t const *request = (audio20_control_request_t const *)p_request; - if (request->bEntityID == UAC2_ENTITY_CLOCK) + if (request->bEntityID == UAC2_ENTITY_CLOCK) { return tud_audio_clock_get_request(rhport, request); - if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) + } + if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) { return tud_audio_feature_unit_get_request(rhport, request); - else - { + } else { TU_LOG1("Get request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); } @@ -243,14 +244,15 @@ bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p } // Invoked when audio class specific set request received for an entity -bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) -{ +bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const *p_request, uint8_t *buf) { audio20_control_request_t const *request = (audio20_control_request_t const *)p_request; - if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) + if (request->bEntityID == UAC2_ENTITY_SPK_FEATURE_UNIT) { return tud_audio_feature_unit_set_request(rhport, request, buf); - if (request->bEntityID == UAC2_ENTITY_CLOCK) + } + if (request->bEntityID == UAC2_ENTITY_CLOCK) { return tud_audio_clock_set_request(rhport, request, buf); + } TU_LOG1("Set request not handled, entity = %d, selector = %d, request = %d\r\n", request->bEntityID, request->bControlSelector, request->bRequest); @@ -301,7 +303,9 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; + if (board_millis() - start_ms < blink_interval_ms) { + return; + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/cdc_uac2/src/usb_descriptors.c b/examples/device/cdc_uac2/src/usb_descriptors.c index 252b602ac..e6caaa971 100644 --- a/examples/device/cdc_uac2/src/usb_descriptors.c +++ b/examples/device/cdc_uac2/src/usb_descriptors.c @@ -248,14 +248,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/dfu/src/usb_descriptors.c b/examples/device/dfu/src/usb_descriptors.c index 14ec315ea..48c9985f3 100644 --- a/examples/device/dfu/src/usb_descriptors.c +++ b/examples/device/dfu/src/usb_descriptors.c @@ -158,14 +158,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/dfu_runtime/src/main.c b/examples/device/dfu_runtime/src/main.c index 37cb80093..5de651bcd 100644 --- a/examples/device/dfu_runtime/src/main.c +++ b/examples/device/dfu_runtime/src/main.c @@ -132,7 +132,9 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/dfu_runtime/src/usb_descriptors.c b/examples/device/dfu_runtime/src/usb_descriptors.c index 1d46ee252..5d5cf52cd 100644 --- a/examples/device/dfu_runtime/src/usb_descriptors.c +++ b/examples/device/dfu_runtime/src/usb_descriptors.c @@ -153,14 +153,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c index 258cfcd02..dac74bb7a 100644 --- a/examples/device/dynamic_configuration/src/main.c +++ b/examples/device/dynamic_configuration/src/main.c @@ -109,23 +109,18 @@ void tud_resume_cb(void) //--------------------------------------------------------------------+ // USB CDC //--------------------------------------------------------------------+ -void cdc_task(void) -{ - if ( tud_cdc_connected() ) - { - // connected and there are data available - if ( tud_cdc_available() ) - { +void cdc_task(void) { + if (tud_cdc_connected()) { + // connected and there are data available read and echo back + if (tud_cdc_available()) { uint8_t buf[64]; - - // read and echo back uint32_t count = tud_cdc_read(buf, sizeof(buf)); - for(uint32_t i=0; i= sizeof(note_sequence)) note_pos = 0; + if (note_pos >= sizeof(note_sequence)) { + note_pos = 0; + } } //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ +void led_blinking_task(void) { static uint32_t start_ms = 0; static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return;// not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); - led_state = 1 - led_state; // toggle + led_state = 1 - led_state;// toggle } diff --git a/examples/device/dynamic_configuration/src/msc_disk.c b/examples/device/dynamic_configuration/src/msc_disk.c index ab71b02d6..e95b2e197 100644 --- a/examples/device/dynamic_configuration/src/msc_disk.c +++ b/examples/device/dynamic_configuration/src/msc_disk.c @@ -177,12 +177,13 @@ bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, boo // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. -int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) -{ +int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { (void) lun; // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) return -1; + if ( lba >= DISK_BLOCK_NUM ) { + return -1; + } uint8_t const* addr = msc_disk[lba] + offset; memcpy(buffer, addr, bufsize); @@ -192,12 +193,13 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff // Callback invoked when received WRITE10 command. // Process data in buffer to disk's storage and return number of written bytes -int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) -{ +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { (void) lun; // out of ramdisk - if ( lba >= DISK_BLOCK_NUM ) return -1; + if ( lba >= DISK_BLOCK_NUM ) { + return -1; + } #ifndef CFG_EXAMPLE_MSC_READONLY uint8_t* addr = msc_disk[lba] + offset; diff --git a/examples/device/dynamic_configuration/src/usb_descriptors.c b/examples/device/dynamic_configuration/src/usb_descriptors.c index 083279938..458b7c2a5 100644 --- a/examples/device/dynamic_configuration/src/usb_descriptors.c +++ b/examples/device/dynamic_configuration/src/usb_descriptors.c @@ -232,14 +232,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 for ( size_t i = 0; i < chr_count; i++ ) { diff --git a/examples/device/hid_boot_interface/src/main.c b/examples/device/hid_boot_interface/src/main.c index 45712cede..44a91db67 100644 --- a/examples/device/hid_boot_interface/src/main.c +++ b/examples/device/hid_boot_interface/src/main.c @@ -23,8 +23,8 @@ * */ -#include #include +#include #include #include "bsp/board_api.h" @@ -40,10 +40,10 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, }; static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; @@ -52,21 +52,16 @@ void led_blinking_task(void); void hid_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port - tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); board_init_after_tusb(); - while (1) - { + while (1) { tud_task(); // tinyusb device task led_blinking_task(); @@ -81,29 +76,25 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ - (void) remote_wakeup_en; +void tud_suspend_cb(bool remote_wakeup_en) { + (void)remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } @@ -113,59 +104,54 @@ void tud_resume_cb(void) // Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) // tud_hid_report_complete_cb() is used to send the next report after previous one is complete -void hid_task(void) -{ +void hid_task(void) { // Poll every 10ms - const uint32_t interval_ms = 10; - static uint32_t start_ms = 0; + const uint32_t interval_ms = 10; + static uint32_t start_ms = 0; - if ( board_millis() - start_ms < interval_ms) return; // not enough time + if (board_millis() - start_ms < interval_ms) { + return; // not enough time + } start_ms += interval_ms; uint32_t const btn = board_button_read(); - if ( tud_suspended() && btn ) - { + if (tud_suspended() && btn) { // Wake up host if we are in suspend mode // and REMOTE_WAKEUP feature is enabled by host tud_remote_wakeup(); - } - else - { + } else { // keyboard interface - if ( tud_hid_n_ready(ITF_NUM_KEYBOARD) ) - { + if (tud_hid_n_ready(ITF_NUM_KEYBOARD)) { // used to avoid send multiple consecutive zero report for keyboard static bool has_keyboard_key = false; uint8_t const report_id = 0; uint8_t const modifier = 0; - if ( btn ) - { - uint8_t keycode[6] = { 0 }; - keycode[0] = HID_KEY_ARROW_RIGHT; + if (btn) { + uint8_t keycode[6] = {0}; + keycode[0] = HID_KEY_ARROW_RIGHT; tud_hid_n_keyboard_report(ITF_NUM_KEYBOARD, report_id, modifier, keycode); has_keyboard_key = true; - }else - { + } else { // send empty key report if previously has key pressed - if (has_keyboard_key) tud_hid_n_keyboard_report(ITF_NUM_KEYBOARD, report_id, modifier, NULL); + if (has_keyboard_key) { + tud_hid_n_keyboard_report(ITF_NUM_KEYBOARD, report_id, modifier, NULL); + } has_keyboard_key = false; } } // mouse interface - if ( tud_hid_n_ready(ITF_NUM_MOUSE) ) - { - if ( btn ) - { + if (tud_hid_n_ready(ITF_NUM_MOUSE)) { + if (btn) { uint8_t const report_id = 0; uint8_t const button_mask = 0; - int8_t const vertical = 0; - int8_t const horizontal = 0; - int8_t const delta = 5; + int8_t const vertical = 0; + int8_t const horizontal = 0; + int8_t const delta = 5; tud_hid_n_mouse_report(ITF_NUM_MOUSE, report_id, button_mask, delta, delta, vertical, horizontal); } @@ -175,10 +161,9 @@ void hid_task(void) // Invoked when received SET_PROTOCOL request // protocol is either HID_PROTOCOL_BOOT (0) or HID_PROTOCOL_REPORT (1) -void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) -{ - (void) instance; - (void) protocol; +void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) { + (void)instance; + (void)protocol; // nothing to do since we use the same compatible boot report for both Boot and Report mode. // TODO set a indicator for user @@ -187,11 +172,10 @@ void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol) // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID -void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len) -{ - (void) instance; - (void) report; - (void) len; +void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint16_t len) { + (void)instance; + (void)report; + (void)len; // nothing to do } @@ -199,42 +183,40 @@ void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_ // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) -{ +uint16_t tud_hid_get_report_cb( + uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) { // TODO not Implemented - (void) instance; - (void) report_id; - (void) report_type; - (void) buffer; - (void) reqlen; + (void)instance; + (void)report_id; + (void)report_type; + (void)buffer; + (void)reqlen; return 0; } // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) -{ - (void) report_id; +void tud_hid_set_report_cb( + uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) { + (void)report_id; // keyboard interface - if (instance == ITF_NUM_KEYBOARD) - { + if (instance == ITF_NUM_KEYBOARD) { // Set keyboard LED e.g Capslock, Numlock etc... - if (report_type == HID_REPORT_TYPE_OUTPUT) - { + if (report_type == HID_REPORT_TYPE_OUTPUT) { // bufsize should be (at least) 1 - if ( bufsize < 1 ) return; + if (bufsize < 1) { + return; + } uint8_t const kbd_leds = buffer[0]; - if (kbd_leds & KEYBOARD_LED_CAPSLOCK) - { + if (kbd_leds & KEYBOARD_LED_CAPSLOCK) { // Capslock On: disable blink, turn led on blink_interval_ms = 0; board_led_write(true); - }else - { + } else { // Caplocks Off: back to normal blink board_led_write(false); blink_interval_ms = BLINK_MOUNTED; @@ -246,16 +228,19 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_ //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ - static uint32_t start_ms = 0; - static bool led_state = false; +void led_blinking_task(void) { + static uint32_t start_ms = 0; + static bool led_state = false; // blink is disabled - if (!blink_interval_ms) return; + if (!blink_interval_ms) { + return; + } // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/hid_boot_interface/src/usb_descriptors.c b/examples/device/hid_boot_interface/src/usb_descriptors.c index 9b4becc85..b5c31a94a 100644 --- a/examples/device/hid_boot_interface/src/usb_descriptors.c +++ b/examples/device/hid_boot_interface/src/usb_descriptors.c @@ -33,60 +33,49 @@ * Auto ProductID layout's Bitmap: * [MSB] HID | MSC | CDC [LSB] */ -#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) -#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \ - PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) ) +#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0) +#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4)) //--------------------------------------------------------------------+ // Device Descriptors //--------------------------------------------------------------------+ -static tusb_desc_device_t const desc_device = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - - .idVendor = 0xCafe, - .idProduct = USB_PID, - .bcdDevice = 0x0100, - - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - - .bNumConfigurations = 0x01 -}; +static tusb_desc_device_t const desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01}; // Invoked when received GET DEVICE DESCRIPTOR // Application return pointer to descriptor -uint8_t const * tud_descriptor_device_cb(void) -{ - return (uint8_t const *) &desc_device; +uint8_t const *tud_descriptor_device_cb(void) { + return (uint8_t const *)&desc_device; } //--------------------------------------------------------------------+ // HID Report Descriptor //--------------------------------------------------------------------+ -uint8_t const desc_hid_keyboard_report[] = -{ - TUD_HID_REPORT_DESC_KEYBOARD() -}; +uint8_t const desc_hid_keyboard_report[] = {TUD_HID_REPORT_DESC_KEYBOARD()}; -uint8_t const desc_hid_mouse_report[] = -{ - TUD_HID_REPORT_DESC_MOUSE() -}; +uint8_t const desc_hid_mouse_report[] = {TUD_HID_REPORT_DESC_MOUSE()}; // Invoked when received GET HID REPORT DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance) -{ +uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance) { return (instance == 0) ? desc_hid_keyboard_report : desc_hid_mouse_report; } @@ -94,36 +83,37 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance) // Configuration Descriptor //--------------------------------------------------------------------+ -#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2*TUD_HID_DESC_LEN) +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + 2 * TUD_HID_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 - // 1 Interrupt, 2 Bulk, 3 Iso, 4 Interrupt, 5 Bulk etc ... - #define EPNUM_KEYBOARD 0x81 - #define EPNUM_MOUSE 0x84 +// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number +// 1 Interrupt, 2 Bulk, 3 Iso, 4 Interrupt, 5 Bulk etc ... +#define EPNUM_KEYBOARD 0x81 +#define EPNUM_MOUSE 0x84 #else - #define EPNUM_KEYBOARD 0x81 - #define EPNUM_MOUSE 0x82 +#define EPNUM_KEYBOARD 0x81 +#define EPNUM_MOUSE 0x82 #endif -uint8_t const desc_configuration[] = -{ +uint8_t const desc_configuration[] = { // Config number, interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_KEYBOARD, 0, HID_ITF_PROTOCOL_KEYBOARD, sizeof(desc_hid_keyboard_report), EPNUM_KEYBOARD, CFG_TUD_HID_EP_BUFSIZE, 10), + TUD_HID_DESCRIPTOR( + ITF_NUM_KEYBOARD, 0, HID_ITF_PROTOCOL_KEYBOARD, sizeof(desc_hid_keyboard_report), EPNUM_KEYBOARD, + CFG_TUD_HID_EP_BUFSIZE, 10), // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval - TUD_HID_DESCRIPTOR(ITF_NUM_MOUSE, 0, HID_ITF_PROTOCOL_MOUSE, sizeof(desc_hid_mouse_report), EPNUM_MOUSE, CFG_TUD_HID_EP_BUFSIZE, 10) -}; + TUD_HID_DESCRIPTOR( + ITF_NUM_MOUSE, 0, HID_ITF_PROTOCOL_MOUSE, sizeof(desc_hid_mouse_report), EPNUM_MOUSE, CFG_TUD_HID_EP_BUFSIZE, + 10)}; // Invoked when received GET CONFIGURATION DESCRIPTOR // Application return pointer to descriptor // Descriptor contents must exist long enough for transfer to complete -uint8_t const * tud_descriptor_configuration_cb(uint8_t index) -{ - (void) index; // for multiple configurations +uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { + (void)index; // for multiple configurations return desc_configuration; } @@ -140,12 +130,11 @@ enum { }; // array of pointer to string descriptors -static char const *string_desc_arr[] = -{ - (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) - "TinyUSB", // 1: Manufacturer - "TinyUSB Device", // 2: Product - NULL, // 3: Serials will use unique ID if possible +static char const *string_desc_arr[] = { + (const char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + NULL, // 3: Serials will use unique ID if possible }; static uint16_t _desc_str[32 + 1]; @@ -153,41 +142,44 @@ static uint16_t _desc_str[32 + 1]; // Invoked when received GET STRING DESCRIPTOR request // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { - (void) langid; + (void)langid; size_t chr_count; - switch ( index ) { + switch (index) { case STRID_LANGID: memcpy(&_desc_str[1], string_desc_arr[0], 2); chr_count = 1; break; - case STRID_SERIAL: - chr_count = board_usb_get_serial(_desc_str + 1, 32); - break; + case STRID_SERIAL: chr_count = board_usb_get_serial(_desc_str + 1, 32); break; default: // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if ( !(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0])) ) return NULL; + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { + return NULL; + } const char *str = string_desc_arr[index]; // Cap at max char chr_count = strlen(str); + size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type - if ( chr_count > max_count ) chr_count = max_count; + if (chr_count > max_count) { + chr_count = max_count; + } // Convert ASCII string into UTF-16 - for ( size_t i = 0; i < chr_count; i++ ) { + for (size_t i = 0; i < chr_count; i++) { _desc_str[1 + i] = str[i]; } break; } // first byte is length (including header), second byte is string type - _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); + _desc_str[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * chr_count + 2)); return _desc_str; } diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 89dab0bdc..9693d564d 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -23,8 +23,8 @@ * */ -#include #include +#include #include #include "bsp/board_api.h" @@ -41,10 +41,10 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -enum { +enum { BLINK_NOT_MOUNTED = 250, - BLINK_MOUNTED = 1000, - BLINK_SUSPENDED = 2500, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, }; static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; @@ -53,24 +53,18 @@ void led_blinking_task(void); void hid_task(void); /*------------- MAIN -------------*/ -int main(void) -{ +int main(void) { board_init(); // init device stack on configured roothub port - tusb_rhport_init_t dev_init = { - .role = TUSB_ROLE_DEVICE, - .speed = TUSB_SPEED_AUTO - }; + tusb_rhport_init_t dev_init = {.role = TUSB_ROLE_DEVICE, .speed = TUSB_SPEED_AUTO}; tusb_init(BOARD_TUD_RHPORT, &dev_init); board_init_after_tusb(); - while (1) - { + while (1) { tud_task(); // tinyusb device task led_blinking_task(); - hid_task(); } } @@ -80,29 +74,25 @@ int main(void) //--------------------------------------------------------------------+ // Invoked when device is mounted -void tud_mount_cb(void) -{ +void tud_mount_cb(void) { blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted -void tud_umount_cb(void) -{ +void tud_umount_cb(void) { blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended // remote_wakeup_en : if host allow us to perform remote wakeup // Within 7ms, device must draw an average of current less than 2.5 mA from bus -void tud_suspend_cb(bool remote_wakeup_en) -{ - (void) remote_wakeup_en; +void tud_suspend_cb(bool remote_wakeup_en) { + (void)remote_wakeup_en; blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed -void tud_resume_cb(void) -{ +void tud_resume_cb(void) { blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; } @@ -110,138 +100,128 @@ void tud_resume_cb(void) // USB HID //--------------------------------------------------------------------+ -static void send_hid_report(uint8_t report_id, uint32_t btn) -{ +static void send_hid_report(uint8_t report_id, uint32_t btn) { // skip if hid is not ready yet - if ( !tud_hid_ready() ) return; + if (!tud_hid_ready()) { + return; + } - switch(report_id) - { - case REPORT_ID_KEYBOARD: - { + switch (report_id) { + case REPORT_ID_KEYBOARD: { // use to avoid send multiple consecutive zero report for keyboard static bool has_keyboard_key = false; - if ( btn ) - { - uint8_t keycode[6] = { 0 }; - keycode[0] = HID_KEY_A; + if (btn != 0u) { + uint8_t keycode[6] = {0}; + keycode[0] = HID_KEY_A; tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode); has_keyboard_key = true; - }else - { + } else { // send empty key report if previously has key pressed - if (has_keyboard_key) tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); + if (has_keyboard_key) { + tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, NULL); + } has_keyboard_key = false; } + break; } - break; - case REPORT_ID_MOUSE: - { + case REPORT_ID_MOUSE: { int8_t const delta = 5; // no button, right + down, no scroll, no pan tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0); + break; } - break; - case REPORT_ID_CONSUMER_CONTROL: - { + case REPORT_ID_CONSUMER_CONTROL: { // use to avoid send multiple consecutive zero report static bool has_consumer_key = false; - if ( btn ) - { + if (btn != 0u) { // volume down uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT; tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2); has_consumer_key = true; - }else - { + } else { // send empty key report (release key) if previously has key pressed uint16_t empty_key = 0; - if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); + if (has_consumer_key) { + tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2); + } has_consumer_key = false; } + break; } - break; - case REPORT_ID_GAMEPAD: - { + case REPORT_ID_GAMEPAD: { // use to avoid send multiple consecutive zero report for keyboard static bool has_gamepad_key = false; - hid_gamepad_report_t report = - { - .x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, - .hat = 0, .buttons = 0 - }; + hid_gamepad_report_t report = {.x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0, .hat = 0, .buttons = 0}; - if ( btn ) - { - report.hat = GAMEPAD_HAT_UP; + if (btn != 0u) { + report.hat = GAMEPAD_HAT_UP; report.buttons = GAMEPAD_BUTTON_A; tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); has_gamepad_key = true; - }else - { - report.hat = GAMEPAD_HAT_CENTERED; + } else { + report.hat = GAMEPAD_HAT_CENTERED; report.buttons = 0; - if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + if (has_gamepad_key) { + tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report)); + } has_gamepad_key = false; } + break; } - break; case REPORT_ID_STYLUS_PEN: { - static bool touch_state = false; - hid_stylus_report_t report = { - .attr = 0, - .x = 0, - .y = 0 - }; - - if (btn) { + static bool touch_state = false; + hid_stylus_report_t report = {.attr = 0, .x = 0, .y = 0}; + + if (btn != 0u) { report.attr = STYLUS_ATTR_TIP_SWITCH | STYLUS_ATTR_IN_RANGE; - report.x = 100; - report.y = 100; + report.x = 100; + report.y = 100; tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); touch_state = true; } else { report.attr = 0; - if (touch_state) tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); + if (touch_state) { + tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); + } touch_state = false; } + break; } - break; - default: break; + + default: break; // unknown report id } } // Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) // tud_hid_report_complete_cb() is used to send the next report after previous one is complete -void hid_task(void) -{ +void hid_task(void) { // Poll every 10ms - const uint32_t interval_ms = 10; - static uint32_t start_ms = 0; + const uint32_t interval_ms = 10; + static uint32_t start_ms = 0; - if ( board_millis() - start_ms < interval_ms) return; // not enough time + if (board_millis() - start_ms < interval_ms) { + return; // not enough time + } start_ms += interval_ms; uint32_t const btn = board_button_read(); // Remote wakeup - if ( tud_suspended() && btn ) - { + if (tud_suspended() && btn != 0u) { // Wake up host if we are in suspend mode // and REMOTE_WAKEUP feature is enabled by host tud_remote_wakeup(); - }else - { + } else { // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() send_hid_report(REPORT_ID_KEYBOARD, btn); } @@ -250,15 +230,13 @@ void hid_task(void) // Invoked when sent REPORT successfully to host // Application can use this to send the next report // Note: For composite reports, report[0] is report ID -void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len) -{ - (void) instance; - (void) len; +void tud_hid_report_complete_cb(uint8_t instance, uint8_t const *report, uint16_t len) { + (void)instance; + (void)len; uint8_t next_report_id = report[0] + 1u; - if (next_report_id < REPORT_ID_COUNT) - { + if (next_report_id < REPORT_ID_COUNT) { send_hid_report(next_report_id, board_button_read()); } } @@ -266,41 +244,39 @@ void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_ // Invoked when received GET_REPORT control request // Application must fill buffer report's content and return its length. // Return zero will cause the stack to STALL request -uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) -{ +uint16_t tud_hid_get_report_cb( + uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) { // TODO not Implemented - (void) instance; - (void) report_id; - (void) report_type; - (void) buffer; - (void) reqlen; + (void)instance; + (void)report_id; + (void)report_type; + (void)buffer; + (void)reqlen; return 0; } // Invoked when received SET_REPORT control request or // received data on OUT endpoint ( Report ID = 0, Type = 0 ) -void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) -{ - (void) instance; +void tud_hid_set_report_cb( + uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) { + (void)instance; - if (report_type == HID_REPORT_TYPE_OUTPUT) - { + if (report_type == HID_REPORT_TYPE_OUTPUT) { // Set keyboard LED e.g Capslock, Numlock etc... - if (report_id == REPORT_ID_KEYBOARD) - { + if (report_id == REPORT_ID_KEYBOARD) { // bufsize should be (at least) 1 - if ( bufsize < 1 ) return; + if (bufsize < 1) { + return; + } uint8_t const kbd_leds = buffer[0]; - if (kbd_leds & KEYBOARD_LED_CAPSLOCK) - { + if ((kbd_leds & KEYBOARD_LED_CAPSLOCK) != 0u) { // Capslock On: disable blink, turn led on blink_interval_ms = 0; board_led_write(true); - }else - { + } else { // Caplocks Off: back to normal blink board_led_write(false); blink_interval_ms = BLINK_MOUNTED; @@ -312,16 +288,19 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_ //--------------------------------------------------------------------+ // BLINKING TASK //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ - static uint32_t start_ms = 0; - static bool led_state = false; +void led_blinking_task(void) { + static uint32_t start_ms = 0; + static bool led_state = false; // blink is disabled - if (!blink_interval_ms) return; + if (0u == blink_interval_ms) { + return; + } // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (board_millis() - start_ms < blink_interval_ms) { + return; // not enough time + } start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/mtp/src/mtp_fs_example.c b/examples/device/mtp/src/mtp_fs_example.c index b4772f146..1c287be4d 100644 --- a/examples/device/mtp/src/mtp_fs_example.c +++ b/examples/device/mtp/src/mtp_fs_example.c @@ -39,12 +39,15 @@ #define DEV_PROP_FRIENDLY_NAME "TinyUSB MTP" //------------- storage info -------------// -#define STORAGE_DESCRIPTRION { 'd', 'i', 's', 'k', 0 } +#define STORAGE_DESCRIPTION { 'd', 'i', 's', 'k', 0 } #define VOLUME_IDENTIFIER { 'v', 'o', 'l', 0 } -typedef MTP_STORAGE_INFO_STRUCT(TU_ARRAY_SIZE((uint16_t[]) STORAGE_DESCRIPTRION), - TU_ARRAY_SIZE(((uint16_t[])VOLUME_IDENTIFIER)) -) storage_info_t; +enum { + STORAGE_DESC_LEN = TU_ARRAY_SIZE((uint16_t[]) STORAGE_DESCRIPTION), + VOLUME_ID_LEN = TU_ARRAY_SIZE((uint16_t[])VOLUME_IDENTIFIER) +}; + +typedef MTP_STORAGE_INFO_STRUCT(STORAGE_DESC_LEN, VOLUME_ID_LEN) storage_info_t; storage_info_t storage_info = { #ifdef CFG_EXAMPLE_MTP_READONLY @@ -60,7 +63,7 @@ storage_info_t storage_info = { .free_space_in_objects = 0, // calculated at runtime .storage_description = { .count = (TU_FIELD_SIZE(storage_info_t, storage_description)-1) / sizeof(uint16_t), - .utf16 = STORAGE_DESCRIPTRION + .utf16 = STORAGE_DESCRIPTION }, .volume_identifier = { .count = (TU_FIELD_SIZE(storage_info_t, volume_identifier)-1) / sizeof(uint16_t), @@ -320,9 +323,9 @@ int32_t tud_mtp_data_complete_cb(tud_mtp_cb_data_t* cb_data) { break; } // parameter is: storage id, parent handle, new handle - mtp_container_add_uint32(resp, SUPPORTED_STORAGE_ID); - mtp_container_add_uint32(resp, f->parent); - mtp_container_add_uint32(resp, send_obj_handle); + (void) mtp_container_add_uint32(resp, SUPPORTED_STORAGE_ID); + (void) mtp_container_add_uint32(resp, f->parent); + (void) mtp_container_add_uint32(resp, send_obj_handle); resp->header->code = MTP_RESP_OK; break; } @@ -346,19 +349,22 @@ int32_t tud_mtp_response_complete_cb(tud_mtp_cb_data_t* cb_data) { //--------------------------------------------------------------------+ static int32_t fs_get_device_info(tud_mtp_cb_data_t* cb_data) { // Device info is already prepared up to playback formats. Application only need to add string fields + int32_t resp_code = 0; mtp_container_info_t* io_container = &cb_data->io_container; - mtp_container_add_cstring(io_container, DEV_INFO_MANUFACTURER); - mtp_container_add_cstring(io_container, DEV_INFO_MODEL); - mtp_container_add_cstring(io_container, DEV_INFO_VERSION); + (void) mtp_container_add_cstring(io_container, DEV_INFO_MANUFACTURER); + (void) mtp_container_add_cstring(io_container, DEV_INFO_MODEL); + (void) mtp_container_add_cstring(io_container, DEV_INFO_VERSION); enum { MAX_SERIAL_NCHARS = 32 }; uint16_t serial_utf16[MAX_SERIAL_NCHARS+1]; size_t nchars = board_usb_get_serial(serial_utf16, MAX_SERIAL_NCHARS); serial_utf16[tu_min32(nchars, MAX_SERIAL_NCHARS)] = 0; // ensure null termination - mtp_container_add_string(io_container, serial_utf16); + (void) mtp_container_add_string(io_container, serial_utf16); - tud_mtp_data_send(io_container); - return 0; + if (!tud_mtp_data_send(io_container)) { + resp_code = MTP_RESP_DEVICE_BUSY; + } + return resp_code; } static int32_t fs_open_close_session(tud_mtp_cb_data_t* cb_data) { @@ -380,7 +386,7 @@ static int32_t fs_open_close_session(tud_mtp_cb_data_t* cb_data) { static int32_t fs_get_storage_ids(tud_mtp_cb_data_t* cb_data) { mtp_container_info_t* io_container = &cb_data->io_container; uint32_t storage_ids [] = { SUPPORTED_STORAGE_ID }; - mtp_container_add_auint32(io_container, 1, storage_ids); + (void) mtp_container_add_auint32(io_container, 1, storage_ids); tud_mtp_data_send(io_container); return 0; } @@ -394,7 +400,7 @@ static int32_t fs_get_storage_info(tud_mtp_cb_data_t* cb_data) { storage_info.max_capacity_in_bytes = sizeof(README_TXT_CONTENT) + LOGO_LEN + FS_MAX_CAPACITY_BYTES; storage_info.free_space_in_objects = FS_MAX_FILE_COUNT - fs_get_file_count(); storage_info.free_space_in_bytes = storage_info.free_space_in_objects ? FS_MAX_CAPACITY_BYTES : 0; - mtp_container_add_raw(io_container, &storage_info, sizeof(storage_info)); + (void) mtp_container_add_raw(io_container, &storage_info, sizeof(storage_info)); tud_mtp_data_send(io_container); return 0; } @@ -408,14 +414,14 @@ static int32_t fs_get_device_properties(tud_mtp_cb_data_t* cb_data) { // get describing dataset mtp_device_prop_desc_header_t device_prop_header; device_prop_header.device_property_code = dev_prop_code; - switch (dev_prop_code) { + switch (dev_prop_code) { //-V2520 //-V2659 case MTP_DEV_PROP_DEVICE_FRIENDLY_NAME: device_prop_header.datatype = MTP_DATA_TYPE_STR; device_prop_header.get_set = MTP_MODE_GET; - mtp_container_add_raw(io_container, &device_prop_header, sizeof(device_prop_header)); - mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); // factory - mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); // current - mtp_container_add_uint8(io_container, 0); // no form + (void) mtp_container_add_raw(io_container, &device_prop_header, sizeof(device_prop_header)); + (void) mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); // factory + (void) mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); // current + (void) mtp_container_add_uint8(io_container, 0); // no form tud_mtp_data_send(io_container); break; @@ -424,9 +430,9 @@ static int32_t fs_get_device_properties(tud_mtp_cb_data_t* cb_data) { } } else { // get value - switch (dev_prop_code) { + switch (dev_prop_code) { //-V2520 //-V2659 case MTP_DEV_PROP_DEVICE_FRIENDLY_NAME: - mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); + (void) mtp_container_add_cstring(io_container, DEV_PROP_FRIENDLY_NAME); tud_mtp_data_send(io_container); break; @@ -446,20 +452,20 @@ static int32_t fs_get_object_handles(tud_mtp_cb_data_t* cb_data) { const uint32_t parent_handle = command->params[2]; // folder handle, 0xFFFFFFFF is root (void)obj_format; - if (storage_id != 0xFFFFFFFF && storage_id != SUPPORTED_STORAGE_ID) { + if (storage_id != 0xFFFFFFFFu && storage_id != SUPPORTED_STORAGE_ID) { return MTP_RESP_INVALID_STORAGE_ID; } uint32_t handles[FS_MAX_FILE_COUNT] = { 0 }; - uint32_t count = 0; - for (uint8_t i = 0; i < FS_MAX_FILE_COUNT; i++) { + uint32_t count = 0u; + for (uint8_t i = 0u; i < FS_MAX_FILE_COUNT; i++) { fs_file_t* f = &fs_objects[i]; if (fs_file_exist(f) && - (parent_handle == f->parent || (parent_handle == 0xFFFFFFFF && f->parent == 0))) { - handles[count++] = i + 1; // handle is index + 1 + (parent_handle == f->parent || (parent_handle == 0xFFFFFFFFu && f->parent == 0u))) { + handles[count++] = (uint32_t) i + 1u; // handle is index + 1 } } - mtp_container_add_auint32(io_container, count, handles); + (void) mtp_container_add_auint32(io_container, count, handles); tud_mtp_data_send(io_container); return 0; @@ -490,11 +496,11 @@ static int32_t fs_get_object_info(tud_mtp_cb_data_t* cb_data) { .association_desc = 0, .sequence_number = 0 }; - mtp_container_add_raw(io_container, &obj_info_header, sizeof(obj_info_header)); - mtp_container_add_string(io_container, f->name); - mtp_container_add_cstring(io_container, FS_FIXED_DATETIME); - mtp_container_add_cstring(io_container, FS_FIXED_DATETIME); - mtp_container_add_cstring(io_container, ""); // keywords, not used + (void) mtp_container_add_raw(io_container, &obj_info_header, sizeof(obj_info_header)); + (void) mtp_container_add_string(io_container, f->name); + (void) mtp_container_add_cstring(io_container, FS_FIXED_DATETIME); + (void) mtp_container_add_cstring(io_container, FS_FIXED_DATETIME); + (void) mtp_container_add_cstring(io_container, ""); // keywords, not used tud_mtp_data_send(io_container); return 0; @@ -512,7 +518,7 @@ static int32_t fs_get_object(tud_mtp_cb_data_t* cb_data) { if (cb_data->phase == MTP_PHASE_COMMAND) { // If file contents is larger than CFG_TUD_MTP_EP_BUFSIZE, data may only partially is added here // the rest will be sent in tud_mtp_data_more_cb - mtp_container_add_raw(io_container, f->data, f->size); + (void) mtp_container_add_raw(io_container, f->data, f->size); tud_mtp_data_send(io_container); } else if (cb_data->phase == MTP_PHASE_DATA) { // continue sending remaining data: file contents offset is xferred byte minus header size @@ -522,6 +528,8 @@ static int32_t fs_get_object(tud_mtp_cb_data_t* cb_data) { memcpy(io_container->payload, f->data + offset, xact_len); tud_mtp_data_send(io_container); } + } else { + // nothing to do } return 0; @@ -537,21 +545,21 @@ static int32_t fs_send_object_info(tud_mtp_cb_data_t* cb_data) { if (!is_session_opened) { return MTP_RESP_SESSION_NOT_OPEN; } - if (storage_id != 0xFFFFFFFF && storage_id != SUPPORTED_STORAGE_ID) { + if (storage_id != 0xFFFFFFFFu && storage_id != SUPPORTED_STORAGE_ID) { return MTP_RESP_INVALID_STORAGE_ID; } if (cb_data->phase == MTP_PHASE_COMMAND) { - tud_mtp_data_receive(io_container); + (void) tud_mtp_data_receive(io_container); } else if (cb_data->phase == MTP_PHASE_DATA) { mtp_object_info_header_t* obj_info = (mtp_object_info_header_t*) io_container->payload; if (obj_info->storage_id != 0 && obj_info->storage_id != SUPPORTED_STORAGE_ID) { return MTP_RESP_INVALID_STORAGE_ID; } - if (obj_info->parent_object) { + if (obj_info->parent_object != 0) { // not root fs_file_t* parent = fs_get_file(obj_info->parent_object); - if (parent == NULL || !parent->association_type) { + if (parent == NULL || 0u == parent->association_type) { return MTP_RESP_INVALID_PARENT_OBJECT; } } @@ -575,8 +583,10 @@ static int32_t fs_send_object_info(tud_mtp_cb_data_t* cb_data) { f->size = obj_info->object_compressed_size; f->data = f_buf; uint8_t* buf = io_container->payload + sizeof(mtp_object_info_header_t); - mtp_container_get_string(buf, f->name); + (void) mtp_container_get_string(buf, f->name); // ignore date created/modified/keywords + } else { + // nothing to do } return 0; diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 16c0d48d7..c2e7bf8f2 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -301,10 +301,10 @@ function(family_configure_common TARGET RTOS) COMMAND_EXPAND_LISTS ) # generate C-STAT report -# add_custom_command(TARGET ${TARGET} POST_BUILD -# COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/cstat_report -# COMMAND ireport --db=${CMAKE_BINARY_DIR}/cstat.db --full --project ${TARGET} --output ${CMAKE_CURRENT_BINARY_DIR}/cstat_report/index.html -# ) + add_custom_command(TARGET ${TARGET} POST_BUILD + COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/cstat_report + COMMAND ireport --db=${CMAKE_BINARY_DIR}/cstat.db --full --project ${TARGET} --output ${CMAKE_CURRENT_BINARY_DIR}/cstat_report/index.html + ) endif () endif () diff --git a/src/class/mtp/mtp.h b/src/class/mtp/mtp.h index 40b6dd8b0..236cf98e0 100644 --- a/src/class/mtp/mtp.h +++ b/src/class/mtp/mtp.h @@ -799,18 +799,18 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_array(mtp_contain TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_string(mtp_container_info_t* p_container, uint16_t* utf16) { uint8_t count = 0; - while (utf16[count]) { + while (utf16[count] != 0u) { count++; } - const uint32_t added_len = 1u + 2u * count; + const uint32_t added_len = 1u + (uint32_t) count * 2u; TU_ASSERT(p_container->header->len + added_len < CFG_TUD_MTP_EP_BUFSIZE, 0); uint8_t* buf = p_container->payload + p_container->header->len - sizeof(mtp_container_header_t); *buf++ = count; p_container->header->len++; - memcpy(buf, utf16, 2 * count); - p_container->header->len += 2 * count; + memcpy(buf, utf16, 2u * (uint32_t) count); + p_container->header->len += 2u * count; return added_len; } @@ -824,7 +824,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_cstring(mtp_conta // empty string (null only): single zero byte *buf = 0; p_container->header->len++; - return 1; + return 1u; } else { *buf++ = len; p_container->header->len++; @@ -875,8 +875,8 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_add_auint32(mtp_conta // //--------------------------------------------------------------------+ TU_ATTR_ALWAYS_INLINE static inline uint32_t mtp_container_get_string(uint8_t* buf, uint16_t utf16[]) { - uint8_t nchars = *buf++; - memcpy(utf16, buf, 2 * nchars); + size_t nchars = *buf++; + memcpy(utf16, buf, 2u * nchars); return 1u + 2u * nchars; } diff --git a/src/class/mtp/mtp_device.h b/src/class/mtp/mtp_device.h index 397fbbbce..a33f1dc08 100644 --- a/src/class/mtp/mtp_device.h +++ b/src/class/mtp/mtp_device.h @@ -53,12 +53,14 @@ typedef struct { typedef struct { uint8_t idx; uint8_t stage; // control stage - uint32_t session_id; - const tusb_control_request_t* request; // buffer for data stage - uint8_t* buf; uint16_t bufsize; + uint8_t* buf; + + const tusb_control_request_t* request; + + uint32_t session_id; } tud_mtp_request_cb_data_t; // Number of supported operations, events, device properties, capture formats, playback formats @@ -78,7 +80,7 @@ typedef struct { /* string fields will be added using append function */ \ } -typedef MTP_DEVICE_INFO_STRUCT( +typedef MTP_DEVICE_INFO_STRUCT( //-V2586 [MISRA-C-18.7] Flexible array members should not be declared sizeof(CFG_TUD_MTP_DEVICEINFO_EXTENSIONS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_OPERATIONS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_EVENTS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_SUPPORTED_DEVICE_PROPERTIES), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_CAPTURE_FORMATS), TU_ARGS_NUM(CFG_TUD_MTP_DEVICEINFO_PLAYBACK_FORMATS) diff --git a/src/class/video/video.h b/src/class/video/video.h index f348e187b..5bdf4b840 100644 --- a/src/class/video/video.h +++ b/src/class/video/video.h @@ -219,11 +219,11 @@ typedef enum { uint8_t baInterfaceNr[_nitf]; \ } -typedef tusb_desc_video_control_header_nitf_t() tusb_desc_video_control_header_t; -typedef tusb_desc_video_control_header_nitf_t(1) tusb_desc_video_control_header_1itf_t; -typedef tusb_desc_video_control_header_nitf_t(2) tusb_desc_video_control_header_2itf_t; -typedef tusb_desc_video_control_header_nitf_t(3) tusb_desc_video_control_header_3itf_t; -typedef tusb_desc_video_control_header_nitf_t(4) tusb_desc_video_control_header_4itf_t; +typedef tusb_desc_video_control_header_nitf_t() tusb_desc_video_control_header_t; //-V2586 incorrectly detected as flexible array +typedef tusb_desc_video_control_header_nitf_t(1) tusb_desc_video_control_header_1itf_t; //-V2586 incorrectly detected as flexible array +typedef tusb_desc_video_control_header_nitf_t(2) tusb_desc_video_control_header_2itf_t; //-V2586 incorrectly detected as flexible array +typedef tusb_desc_video_control_header_nitf_t(3) tusb_desc_video_control_header_3itf_t; //-V2586 incorrectly detected as flexible array +typedef tusb_desc_video_control_header_nitf_t(4) tusb_desc_video_control_header_4itf_t; //-V2586 incorrectly detected as flexible array typedef struct TU_ATTR_PACKED { uint8_t bLength; diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 5f659eb95..7aa42a2d7 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -236,7 +236,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_round_up(uint32_t v, uint32_t f) // TODO use clz TODO remove TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_log2(uint32_t value) { uint8_t result = 0; - while (value >>= 1) { + while ((value >>= 1u) != 0u) { result++; } return result; @@ -355,7 +355,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) { } TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_in_bounds(uint8_t const* p_desc, uint8_t const* desc_end) { - return (p_desc < desc_end) && (tu_desc_next(p_desc) <= desc_end); + if (p_desc >= desc_end) { + return false; + } + return tu_desc_next(p_desc) <= desc_end; } // find descriptor that match byte1 (type) diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index df4034098..a7bf3e959 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -119,7 +119,9 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3 // not found return the key value in hex static char not_found[11]; - snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key); + if (snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key) <= 0) { + not_found[0] = 0; + } return not_found; } diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index c9700fd9d..2c2ff76b7 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -93,7 +93,7 @@ static bool data_stage_xact(uint8_t rhport) { if (_ctrl_xfer.request.bmRequestType_bit.direction == TUSB_DIR_IN) { ep_addr = EDPT_CTRL_IN; - if (xact_len) { + if (0u != xact_len) { TU_VERIFY(0 == tu_memcpy_s(_ctrl_epbuf.buf, CFG_TUD_ENDPOINT0_SIZE, _ctrl_xfer.buffer, xact_len)); } } @@ -159,7 +159,7 @@ bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, // invoke optional dcd hook if available dcd_edpt0_status_complete(rhport, &_ctrl_xfer.request); - if (_ctrl_xfer.complete_cb) { + if (NULL != _ctrl_xfer.complete_cb) { // TODO refactor with usbd_driver_print_control_complete_name _ctrl_xfer.complete_cb(rhport, CONTROL_STAGE_ACK, &_ctrl_xfer.request); } @@ -185,7 +185,7 @@ bool usbd_control_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, // invoke complete callback if set // callback can still stall control in status phase e.g out data does not make sense - if (_ctrl_xfer.complete_cb) { + if (NULL != _ctrl_xfer.complete_cb) { #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL usbd_driver_print_control_complete_name(_ctrl_xfer.complete_cb); #endif diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 2894d3023..6e220129a 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -125,14 +125,9 @@ bool usbd_edpt_ready(uint8_t rhport, uint8_t ep_addr) { // Enable SOF interrupt void usbd_sof_enable(uint8_t rhport, sof_consumer_t consumer, bool en); -/*------------------------------------------------------------------*/ -/* Helper - *------------------------------------------------------------------*/ - bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in); void usbd_defer_func(osal_task_func_t func, void *param, bool in_isr); - #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL void usbd_driver_print_control_complete_name(usbd_control_xfer_cb_t callback); #endif diff --git a/src/tusb.c b/src/tusb.c index d52c156ab..be67eead2 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -599,7 +599,9 @@ void tu_print_mem(void const* buf, uint32_t count, uint8_t indent) { if (remain) { for (uint32_t i = 0; i < 16 - remain; i++) { tu_printf(" "); - for (int j = 0; j < 2 * size; j++) tu_printf(" "); + for (int j = 0; j < 2 * size; j++) { + tu_printf(" "); + } } } -- cgit v1.3.1 From 7f173ab5ed6a80a5fd6780779fe63fb97d2be0e9 Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 8 Nov 2025 15:54:02 +0700 Subject: fix more alerts --- .PVS-Studio/.pvsconfig | 1 + .clang-format | 1 + .github/workflows/static_analysis.yml | 3 +- examples/device/cdc_uac2/src/cdc_app.c | 2 +- examples/device/net_lwip_webserver/src/arch/cc.h | 6 +- examples/host/cdc_msc_hid/src/cdc_app.c | 2 +- src/class/audio/audio_device.c | 35 +- src/class/cdc/cdc_host.c | 81 +++-- src/class/msc/msc_host.c | 5 +- src/common/tusb_debug.h | 16 +- src/common/tusb_fifo.c | 414 ++++++++++------------- src/common/tusb_fifo.h | 25 +- src/common/tusb_private.h | 21 +- src/tusb.c | 38 ++- 14 files changed, 314 insertions(+), 336 deletions(-) (limited to 'src/tusb.c') diff --git a/.PVS-Studio/.pvsconfig b/.PVS-Studio/.pvsconfig index d8654b077..c9e60c996 100644 --- a/.PVS-Studio/.pvsconfig +++ b/.PVS-Studio/.pvsconfig @@ -10,6 +10,7 @@ //-V::2520 [MISRA-C-16.3] Every switch-clause should be terminated by an unconditional 'break' statement //-V:memcpy:2547 [MISRA-C-17.7] The return value of non-void function 'memcpy' should be used. //-V:memmove:2547 [MISRA-C-17.7] The return value of non-void function 'memmove' should be used. +//-V:printf:2547 [MISRA-C-17.7] //-V::2584::{gintsts} dwc2 //-V::2600 [MISRA-C-21.6] The function with the 'printf' name should not be used. //+V2614 DISABLE_LENGHT_LIMIT_CHECK:YES diff --git a/.clang-format b/.clang-format index c7d769172..907dd7cdd 100644 --- a/.clang-format +++ b/.clang-format @@ -87,5 +87,6 @@ SpacesInAngles: false SpacesInConditionalStatement: false SpacesInCStyleCastParentheses: false SpacesInParentheses: false +SortIncludes: false TabWidth: 2 ... diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 227f5e103..a89cdc279 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -118,13 +118,14 @@ jobs: sudo apt update sudo apt install pvs-studio pvs-studio-analyzer credentials ${{ secrets.PVS_STUDIO_CREDENTIALS }} + pvs-studio-analyzer --version - name: Analyze run: | mkdir -p build cmake examples -B build -G Ninja -DBOARD=${{ matrix.board }} -DCMAKE_BUILD_TYPE=MinSizeRel cmake --build build - pvs-studio-analyzer analyze -R .PVS-Studio/.pvsconfig -f build/compile_commands.json --exclude-path hw/mcu/ --exclude-path lib/ -j + pvs-studio-analyzer analyze -f build/compile_commands.json -R .PVS-Studio/.pvsconfig -j4 --security-related-issues --misra-cpp-version 2008 --misra-c-version 2023 --use-old-parser -e lib/ -e hw/mcu/ -e */iar/cxarm/ -e pico-sdk/ plog-converter -t sarif -o pvs-studio-${{ matrix.board }}.sarif PVS-Studio.log - name: Upload SARIF diff --git a/examples/device/cdc_uac2/src/cdc_app.c b/examples/device/cdc_uac2/src/cdc_app.c index e3ad8a9ac..6d18a0e69 100644 --- a/examples/device/cdc_uac2/src/cdc_app.c +++ b/examples/device/cdc_uac2/src/cdc_app.c @@ -48,7 +48,7 @@ void tud_cdc_rx_cb(uint8_t itf) { // connected() check for DTR bit // Most but not all terminal client set this when making connection if (tud_cdc_connected()) { - if (tud_cdc_available()) { + if (tud_cdc_available() > 0) { count = tud_cdc_n_read(itf, buf, sizeof(buf)); (void) count; diff --git a/examples/device/net_lwip_webserver/src/arch/cc.h b/examples/device/net_lwip_webserver/src/arch/cc.h index 9f30b91cb..c3fc12dda 100644 --- a/examples/device/net_lwip_webserver/src/arch/cc.h +++ b/examples/device/net_lwip_webserver/src/arch/cc.h @@ -29,8 +29,8 @@ * Author: Adam Dunkels * */ -#ifndef __CC_H__ -#define __CC_H__ +#ifndef CC_H__ +#define CC_H__ //#include "cpu.h" @@ -72,4 +72,4 @@ typedef int sys_prot_t; #define LWIP_PLATFORM_ASSERT(x) do { if(!(x)) while(1); } while(0) -#endif /* __CC_H__ */ +#endif /* CC_H__ */ diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c index d3daedffc..4c2c5e807 100644 --- a/examples/host/cdc_msc_hid/src/cdc_app.c +++ b/examples/host/cdc_msc_hid/src/cdc_app.c @@ -51,7 +51,7 @@ void cdc_app_task(void) { for (uint8_t idx = 0; idx < CFG_TUH_CDC; idx++) { if (tuh_cdc_mounted(idx)) { // console --> cdc interfaces - if (count) { + if (count > 0) { tuh_cdc_write(idx, buf, count); tuh_cdc_write_flush(idx); } diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index d47d87a69..f074b7d02 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -503,7 +503,7 @@ static bool audiod_rx_xfer_isr(uint8_t rhport, audiod_function_t* audio, uint16_ #if USE_LINEAR_BUFFER_RX // Data currently is in linear buffer, copy into EP OUT FIFO - TU_VERIFY(tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); + TU_VERIFY(0 < tu_fifo_write_n(&audio->ep_out_ff, audio->lin_buf_out, n_bytes_received)); // Schedule for next receive TU_VERIFY(usbd_edpt_xfer(rhport, audio->ep_out, audio->lin_buf_out, audio->ep_out_sz), false); @@ -672,8 +672,12 @@ uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles) { // The size of isochronous packets created by the device must be within the limits specified in FMT-2.0 section 2.3.1.1. // This means that the deviation of actual packet size from nominal size must not exceed +/- one audio slot // (audio slot = channel count samples). - if (feedback > audio->feedback.max_value) feedback = audio->feedback.max_value; - if (feedback < audio->feedback.min_value) feedback = audio->feedback.min_value; + if (feedback > audio->feedback.max_value) { + feedback = audio->feedback.max_value; + } + if (feedback < audio->feedback.min_value) { + feedback = audio->feedback.min_value; + } tud_audio_n_fb_set(func_id, feedback); @@ -714,7 +718,6 @@ void audiod_init(void) { // Initialize IN EP FIFO if required #if CFG_TUD_AUDIO_ENABLE_EP_IN - switch (i) { #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 case 0: @@ -883,9 +886,11 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint || tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) { break; } else if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE && ((tusb_desc_interface_t const *) p_desc)->bInterfaceSubClass == AUDIO_SUBCLASS_STREAMING) { - if (_audiod_fct[i].p_desc_as == 0) { + if (_audiod_fct[i].p_desc_as == NULL) { _audiod_fct[i].p_desc_as = p_desc; } + } else { + // nothing to do } total_len += p_desc[0]; p_desc = tu_desc_next(p_desc); @@ -957,19 +962,19 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint } #if CFG_TUD_AUDIO_ENABLE_EP_IN - if (ep_in) { + if (ep_in != 0) { usbd_edpt_iso_alloc(rhport, ep_in, ep_in_size); } #endif #if CFG_TUD_AUDIO_ENABLE_EP_OUT - if (ep_out) { + if (ep_out != 0) { usbd_edpt_iso_alloc(rhport, ep_out, ep_out_size); } #endif #if CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP - if (ep_fb) { + if (ep_fb != 0) { usbd_edpt_iso_alloc(rhport, ep_fb, 4); } #endif @@ -998,6 +1003,8 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint if (tu_unaligned_read16(p_desc + 4) == AUDIO_TERM_TYPE_USB_STREAMING) { _audiod_fct[i].bclock_id_tx = p_desc[8]; } + } else { + // nothing to do } p_desc = tu_desc_next(p_desc); } @@ -1458,6 +1465,8 @@ bool audiod_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_ return audiod_control_request(rhport, request); } else if (stage == CONTROL_STAGE_DATA) { return audiod_control_complete(rhport, request); + } else { + // nothing to do } return true; @@ -1633,8 +1642,12 @@ static void audiod_fb_fifo_count_update(audiod_function_t *audio, uint16_t lvl_n feedback = audio->feedback.compute.fifo_count.nom_value - (ff_lvl - ff_thr) * rate[1]; } - if (feedback > audio->feedback.max_value) feedback = audio->feedback.max_value; - if (feedback < audio->feedback.min_value) feedback = audio->feedback.min_value; + if (feedback > audio->feedback.max_value) { + feedback = audio->feedback.max_value; + } + if (feedback < audio->feedback.min_value) { + feedback = audio->feedback.min_value; + } audio->feedback.value = feedback; } @@ -1754,7 +1767,7 @@ static bool audiod_verify_entity_exists(uint8_t itf, uint8_t entityID, uint8_t * static bool audiod_verify_itf_exists(uint8_t itf, uint8_t *func_id) { uint8_t i; for (i = 0; i < CFG_TUD_AUDIO; i++) { - if (_audiod_fct[i].p_desc) { + if (_audiod_fct[i].p_desc != NULL) { // Get pointer at beginning and end uint8_t const *p_desc = _audiod_fct[i].p_desc; uint8_t const *p_desc_end = _audiod_fct[i].p_desc + _audiod_fct[i].desc_length; diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 3fc6a9adf..7fdf0a7b9 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -602,7 +602,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, p_cdc->requested_line.coding = *line_coding; p_cdc->user_complete_cb = complete_cb; - if (driver->set_line_coding) { + if (driver->set_line_coding != NULL) { // driver support set_line_coding request TU_VERIFY(driver->set_line_coding(p_cdc, complete_cb ? cdch_internal_control_complete : NULL, user_data)); @@ -611,7 +611,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, } } else { // driver does not support set_line_coding and need 2 stage to set baudrate and data format separately - if (complete_cb) { + if (complete_cb != NULL) { // non-blocking TU_VERIFY(driver->set_baudrate(p_cdc, cdch_set_line_coding_stage1_baudrate_complete, user_data)); } else { @@ -619,7 +619,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, xfer_result_t result = XFER_RESULT_INVALID; TU_VERIFY(driver->set_baudrate(p_cdc, NULL, (uintptr_t) &result)); - if (user_data) { + if (user_data != 0) { *((xfer_result_t *) user_data) = result; } TU_VERIFY(result == XFER_RESULT_SUCCESS); @@ -627,7 +627,7 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const *line_coding, result = XFER_RESULT_INVALID; TU_VERIFY(driver->set_data_format(p_cdc, NULL, (uintptr_t) &result)); - if (user_data) { + if (user_data != 0) { *((xfer_result_t *) user_data) = result; } TU_VERIFY(result == XFER_RESULT_SUCCESS); @@ -777,6 +777,8 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d } } } + } else { + // not supported class } return false; @@ -894,7 +896,7 @@ static void cdch_internal_control_complete(tuh_xfer_t *xfer) { // Invoke application callback xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { + if (xfer->complete_cb != NULL) { xfer->complete_cb(xfer); } } @@ -910,7 +912,7 @@ static void cdch_set_line_coding_stage1_baudrate_complete(tuh_xfer_t *xfer) { TU_ASSERT(driver->set_data_format(p_cdc, cdch_set_line_coding_stage2_data_format_complete, xfer->user_data),); } else { xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { + if (xfer->complete_cb != NULL) { xfer->complete_cb(xfer); } } @@ -926,7 +928,7 @@ static void cdch_set_line_coding_stage2_data_format_complete(tuh_xfer_t *xfer) { } xfer->complete_cb = p_cdc->user_complete_cb; - if (xfer->complete_cb) { + if (xfer->complete_cb != NULL) { xfer->complete_cb(xfer); } } @@ -950,12 +952,12 @@ static void acm_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *x break; default: - break; + break; // unknown request } } static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm.capability.support_line_request); + TU_VERIFY(p_cdc->acm.capability.support_line_request != 0); const tusb_control_request_t request = { .bmRequestType_bit = { @@ -982,7 +984,7 @@ static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t co } static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - TU_VERIFY(p_cdc->acm.capability.support_line_request); + TU_VERIFY(p_cdc->acm.capability.support_line_request != 0); TU_VERIFY((p_cdc->requested_line.coding.data_bits >= 5 && p_cdc->requested_line.coding.data_bits <= 8) || p_cdc->requested_line.coding.data_bits == 16); @@ -1167,10 +1169,10 @@ static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { uint32_t index_value = ftdi_get_divisor(p_cdc); - TU_VERIFY(index_value); + TU_VERIFY(index_value != 0); uint16_t value = (uint16_t) index_value; uint16_t index = (uint16_t) (index_value >> 16); - if (p_cdc->ftdi.channel) { + if (p_cdc->ftdi.channel != 0) { index = (uint16_t) ((index << 8) | p_cdc->ftdi.channel); } @@ -1372,6 +1374,8 @@ static uint32_t ftdi_232bm_baud_base_to_divisor(uint32_t baud, uint32_t base) { divisor = 0; } else if (divisor == 0x4001) /* 1.5 */ { divisor = 1; + } else { + // nothing to do } return divisor; } @@ -1395,12 +1399,13 @@ static uint32_t ftdi_2232h_baud_base_to_divisor(uint32_t baud, uint32_t base) { divisor = 0; } else if (divisor == 0x4001) /* 1.5 */ { divisor = 1; + } else { + // nothing to do } - /* - * Set this bit to turn off a divide by 2.5 on baud rate generator + + /* Set this bit to turn off a divide by 2.5 on baud rate generator * This enables baud rates up to 12Mbaud but cannot reach below 1200 - * baud with this bit set - */ + * baud with this bit set */ divisor |= 0x00020000; return divisor; } @@ -1412,7 +1417,7 @@ static inline uint32_t ftdi_2232h_baud_to_divisor(uint32_t baud) { static inline uint32_t ftdi_get_divisor(cdch_interface_t *p_cdc) { uint32_t baud = p_cdc->requested_line.coding.bit_rate; uint32_t div_value = 0; - TU_VERIFY(baud); + TU_VERIFY(baud != 0); switch (p_cdc->ftdi.chip_type) { case FTDI_UNKNOWN: @@ -1552,7 +1557,8 @@ static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t p_cdc->line.coding.bit_rate = p_cdc->requested_line.coding.bit_rate; break; - default: break; + default: + break; // unsupported request } } @@ -1713,7 +1719,8 @@ static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t p_cdc->line.coding.data_bits = p_cdc->requested_line.coding.data_bits; break; - default: break; + default: + break; // unsupported } break; @@ -1721,19 +1728,20 @@ static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t p_cdc->line.control_state = p_cdc->requested_line.control_state; break; - default: break; + default: + break; // unsupported request } } static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { const uint8_t lcr = ch34x_get_lcr(p_cdc); - TU_VERIFY(lcr); + TU_VERIFY(lcr > 0); return ch34x_write_reg(p_cdc, CH32X_REG16_LCR2_LCR, lcr, complete_cb, user_data); } static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { const uint16_t div_ps = ch34x_get_divisor_prescaler(p_cdc); - TU_VERIFY(div_ps); + TU_VERIFY(div_ps > 0); return ch34x_write_reg(p_cdc, CH34X_REG16_DIVISOR_PRESCALER, div_ps, complete_cb, user_data); } @@ -1916,7 +1924,8 @@ static uint8_t ch34x_get_lcr(cdch_interface_t *p_cdc) { lcr |= CH34X_LCR_ENABLE_PAR | CH34X_LCR_MARK_SPACE | CH34X_LCR_PAR_EVEN; break; - default: break; + default: + break; // invalid parity } // 1.5 stop bits not supported @@ -1999,13 +2008,15 @@ static inline bool pl2303_supports_hx_status(cdch_interface_t *p_cdc, tuh_xfer_c // return pl2303_set_request(p_cdc, PL2303_BREAK_REQUEST, PL2303_BREAK_REQUEST_TYPE, state, 0, NULL, 0); //} -static inline int pl2303_clear_halt(cdch_interface_t *p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +static inline bool +pl2303_clear_halt(cdch_interface_t *p_cdc, uint8_t endp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { /* we don't care if it wasn't halted first. in fact some devices * (like some ibmcam model 1 units) seem to expect hosts to make * this request for iso endpoints, which can't halt! */ - return pl2303_set_request(p_cdc, TUSB_REQ_CLEAR_FEATURE, PL2303_CLEAR_HALT_REQUEST_TYPE, TUSB_REQ_FEATURE_EDPT_HALT, endp, - NULL, 0, complete_cb, user_data); + return pl2303_set_request( + p_cdc, TUSB_REQ_CLEAR_FEATURE, PL2303_CLEAR_HALT_REQUEST_TYPE, TUSB_REQ_FEATURE_EDPT_HALT, endp, NULL, 0, + complete_cb, user_data); } //------------- Driver API -------------// @@ -2130,10 +2141,9 @@ static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) if (type == PL2303_TYPE_NEED_SUPPORTS_HX_STATUS) { TU_ASSERT(pl2303_supports_hx_status(p_cdc, cdch_process_set_config, CONFIG_PL2303_READ1)); break; - } else { - // no transfer triggered and continue with CONFIG_PL2303_READ1 - TU_ATTR_FALLTHROUGH; } + // no transfer triggered and continue with CONFIG_PL2303_READ1 + TU_ATTR_FALLTHROUGH; case CONFIG_PL2303_READ1: // get supports_hx_status, type and quirks (step 2), do special read @@ -2378,10 +2388,12 @@ static pl2303_type_t pl2303_detect_type(cdch_interface_t *p_cdc, uint8_t step) { return PL2303_TYPE_HXN; default: - break; + break; // unknown device } break; - default: break; + + default: + break; // unknown device } TU_LOG_CDC(p_cdc, "unknown device type bcdUSB = 0x%04x", desc_dev.bcdUSB); @@ -2443,8 +2455,9 @@ static uint32_t pl2303_encode_baud_rate_divisor(uint8_t buf[PL2303_LINE_CODING_B */ baseline = 12000000 * 32; mantissa = baseline / baud; - if (mantissa == 0) + if (mantissa == 0) { mantissa = 1; /* Avoid dividing by zero if baud > 32 * 12M. */ + } exponent = 0; while (mantissa >= 512) { if (exponent < 7) { @@ -2516,7 +2529,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_ * Use direct method for supported baud rates, otherwise use divisors. * Newer chip types do not support divisor encoding. */ - if (type_data->no_divisors) { + if (type_data->no_divisors != 0) { baud_sup = baud; } else { baud_sup = pl2303_get_supported_baud_rate(baud); @@ -2524,7 +2537,7 @@ static bool pl2303_encode_baud_rate(cdch_interface_t *p_cdc, uint8_t buf[PL2303_ if (baud == baud_sup) { baud = pl2303_encode_baud_rate_direct(buf, baud); - } else if (type_data->alt_divisors) { + } else if (type_data->alt_divisors != 0) { baud = pl2303_encode_baud_rate_divisor_alt(buf, baud); } else { baud = pl2303_encode_baud_rate_divisor(buf, baud); diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index ce2884f2e..daff345c5 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -123,7 +123,10 @@ bool tuh_msc_mounted(uint8_t dev_addr) { bool tuh_msc_ready(uint8_t dev_addr) { msch_interface_t* p_msc = get_itf(dev_addr); - return p_msc->mounted && !usbh_edpt_busy(dev_addr, p_msc->ep_in) && !usbh_edpt_busy(dev_addr, p_msc->ep_out); + TU_VERIFY(p_msc->mounted); + const bool epin_busy = usbh_edpt_busy(dev_addr, p_msc->ep_in); + const bool epout_busy = usbh_edpt_busy(dev_addr, p_msc->ep_out); + return !epin_busy && !epout_busy; } //--------------------------------------------------------------------+ diff --git a/src/common/tusb_debug.h b/src/common/tusb_debug.h index 08117283f..e0e09f5ce 100644 --- a/src/common/tusb_debug.h +++ b/src/common/tusb_debug.h @@ -56,14 +56,14 @@ void tu_print_mem(void const *buf, uint32_t count, uint8_t indent); #define tu_printf CFG_TUSB_DEBUG_PRINTF #else #include - #define tu_printf printf + #define tu_printf(...) (void) printf(__VA_ARGS__) #endif TU_ATTR_ALWAYS_INLINE static inline void tu_print_buf(uint8_t const* buf, uint32_t bufsize) { for(uint32_t i=0; i= 2 diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 3b8920c01..419046b8b 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -28,7 +28,7 @@ #include "osal/osal.h" #include "tusb_fifo.h" -#define TU_FIFO_DBG 0 +#define TU_FIFO_DBG 0 // Suppress IAR warning // Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement @@ -39,13 +39,13 @@ #if OSAL_MUTEX_REQUIRED TU_ATTR_ALWAYS_INLINE static inline void _ff_lock(osal_mutex_t mutex) { - if (mutex) { + if (mutex != NULL) { osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); } } TU_ATTR_ALWAYS_INLINE static inline void _ff_unlock(osal_mutex_t mutex) { - if (mutex) { + if (mutex != NULL) { osal_mutex_unlock(mutex); } } @@ -62,14 +62,13 @@ TU_ATTR_ALWAYS_INLINE static inline void _ff_unlock(osal_mutex_t mutex) { * copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others */ typedef enum { - TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode + TU_FIFO_COPY_INC, ///< Copy from/to an increasing source/destination address - default mode #ifdef TUP_MEM_CONST_ADDR TU_FIFO_COPY_CST_FULL_WORDS, ///< Copy from/to a constant source/destination address - required for e.g. STM32 to write into USB hardware FIFO #endif } tu_fifo_copy_mode_t; -bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable) -{ +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable) { // Limit index space to 2*depth - this allows for a fast "modulo" calculation // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable // only if overflow happens once (important for unsupervised DMA applications) @@ -80,9 +79,9 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si _ff_lock(f->mutex_wr); _ff_lock(f->mutex_rd); - f->buffer = (uint8_t*) buffer; + f->buffer = (uint8_t *)buffer; f->depth = depth; - f->item_size = (uint16_t) (item_size & 0x7FFF); + f->item_size = (uint16_t)(item_size & 0x7FFF); f->overwritable = overwritable; f->rd_idx = 0; f->wr_idx = 0; @@ -101,18 +100,18 @@ bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_si // Intended to be used to read from hardware USB FIFO in e.g. STM32 where all data is read from a constant address // Code adapted from dcd_synopsys.c // TODO generalize with configurable 1 byte or 4 byte each read -static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t len) { - volatile const uint32_t * reg_rx = (volatile const uint32_t *) app_buf; +static void _ff_push_const_addr(uint8_t *ff_buf, const void *app_buf, uint16_t len) { + const volatile uint32_t *reg_rx = (volatile const uint32_t *)app_buf; // Reading full available 32 bit words from const app address uint16_t full_words = len >> 2; - while(full_words--) { + while (full_words--) { tu_unaligned_write32(ff_buf, *reg_rx); ff_buf += 4; } // Read the remaining 1-3 bytes from const app address - uint8_t const bytes_rem = len & 0x03; + const uint8_t bytes_rem = len & 0x03; if (bytes_rem) { uint32_t tmp32 = *reg_rx; memcpy(ff_buf, &tmp32, bytes_rem); @@ -121,18 +120,18 @@ static void _ff_push_const_addr(uint8_t * ff_buf, const void * app_buf, uint16_t // Intended to be used to write to hardware USB FIFO in e.g. STM32 // where all data is written to a constant address in full word copies -static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t len) { - volatile uint32_t * reg_tx = (volatile uint32_t *) app_buf; +static void _ff_pull_const_addr(void *app_buf, const uint8_t *ff_buf, uint16_t len) { + volatile uint32_t *reg_tx = (volatile uint32_t *)app_buf; // Write full available 32 bit words to const address uint16_t full_words = len >> 2; - while(full_words--) { + while (full_words--) { *reg_tx = tu_unaligned_read32(ff_buf); ff_buf += 4; } // Write the remaining 1-3 bytes into const address - uint8_t const bytes_rem = len & 0x03; + const uint8_t bytes_rem = len & 0x03; if (bytes_rem) { uint32_t tmp32 = 0; memcpy(&tmp32, ff_buf, bytes_rem); @@ -143,32 +142,27 @@ static void _ff_pull_const_addr(void * app_buf, const uint8_t * ff_buf, uint16_t #endif // send one item to fifo WITHOUT updating write pointer -static inline void _ff_push(tu_fifo_t* f, void const * app_buf, uint16_t rel) { +static inline void _ff_push(tu_fifo_t *f, const void *app_buf, uint16_t rel) { memcpy(f->buffer + (rel * f->item_size), app_buf, f->item_size); } // send n items to fifo WITHOUT updating write pointer -static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t wr_ptr, tu_fifo_copy_mode_t copy_mode) -{ - uint16_t const lin_count = f->depth - wr_ptr; - uint16_t const wrap_count = n - lin_count; +static void _ff_push_n(tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, tu_fifo_copy_mode_t copy_mode) { + const uint16_t lin_count = f->depth - wr_ptr; + const uint16_t wrap_count = n - lin_count; - uint16_t lin_bytes = lin_count * f->item_size; + uint16_t lin_bytes = lin_count * f->item_size; uint16_t wrap_bytes = wrap_count * f->item_size; // current buffer of fifo - uint8_t* ff_buf = f->buffer + (wr_ptr * f->item_size); + uint8_t *ff_buf = f->buffer + (wr_ptr * f->item_size); - switch (copy_mode) - { + switch (copy_mode) { case TU_FIFO_COPY_INC: - if(n <= lin_count) - { + if (n <= lin_count) { // Linear only - memcpy(ff_buf, app_buf, n*f->item_size); - } - else - { + memcpy(ff_buf, app_buf, n * f->item_size); + } else { // Wrap around // Write data to linear part of buffer @@ -176,19 +170,17 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t // Write data wrapped around // TU_ASSERT(nWrap_bytes <= f->depth, ); - memcpy(f->buffer, ((uint8_t const*) app_buf) + lin_bytes, wrap_bytes); + memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); } break; + #ifdef TUP_MEM_CONST_ADDR case TU_FIFO_COPY_CST_FULL_WORDS: // Intended for hardware buffers from which it can be read word by word only - if(n <= lin_count) - { + if (n <= lin_count) { // Linear only - _ff_push_const_addr(ff_buf, app_buf, n*f->item_size); - } - else - { + _ff_push_const_addr(ff_buf, app_buf, n * f->item_size); + } else { // Wrap around case // Write full words to linear part of buffer @@ -198,83 +190,80 @@ static void _ff_push_n(tu_fifo_t* f, void const * app_buf, uint16_t n, uint16_t // There could be odd 1-3 bytes before the wrap-around boundary uint8_t rem = lin_bytes & 0x03; - if (rem > 0) - { - volatile const uint32_t * rx_fifo = (volatile const uint32_t *) app_buf; + if (rem > 0) { + const volatile uint32_t *rx_fifo = (volatile const uint32_t *)app_buf; - uint8_t remrem = (uint8_t) tu_min16(wrap_bytes, 4-rem); + uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, 4 - rem); wrap_bytes -= remrem; - uint32_t tmp32 = *rx_fifo; - uint8_t * src_u8 = ((uint8_t *) &tmp32); + uint32_t tmp32 = *rx_fifo; + uint8_t *src_u8 = ((uint8_t *)&tmp32); // Write 1-3 bytes before wrapped boundary - while(rem--) *ff_buf++ = *src_u8++; + while (rem--) { + *ff_buf++ = *src_u8++; + } // Read more bytes to beginning to complete a word ff_buf = f->buffer; - while(remrem--) *ff_buf++ = *src_u8++; - } - else - { + while (remrem--) { + *ff_buf++ = *src_u8++; + } + } else { ff_buf = f->buffer; // wrap around to beginning } // Write data wrapped part - if (wrap_bytes > 0) _ff_push_const_addr(ff_buf, app_buf, wrap_bytes); + if (wrap_bytes > 0) { + _ff_push_const_addr(ff_buf, app_buf, wrap_bytes); + } } break; #endif - default: break; + + default: + break; // unknown mode } } // get one item from fifo WITHOUT updating read pointer -static inline void _ff_pull(tu_fifo_t* f, void * app_buf, uint16_t rel) -{ +static inline void _ff_pull(tu_fifo_t *f, void *app_buf, uint16_t rel) { memcpy(app_buf, f->buffer + (rel * f->item_size), f->item_size); } // get n items from fifo WITHOUT updating read pointer -static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_copy_mode_t copy_mode) -{ - uint16_t const lin_count = f->depth - rd_ptr; - uint16_t const wrap_count = n - lin_count; // only used if wrapped +static void _ff_pull_n(tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_copy_mode_t copy_mode) { + const uint16_t lin_count = f->depth - rd_ptr; + const uint16_t wrap_count = n - lin_count; // only used if wrapped - uint16_t lin_bytes = lin_count * f->item_size; + uint16_t lin_bytes = lin_count * f->item_size; uint16_t wrap_bytes = wrap_count * f->item_size; // current buffer of fifo - uint8_t* ff_buf = f->buffer + (rd_ptr * f->item_size); + uint8_t *ff_buf = f->buffer + (rd_ptr * f->item_size); - switch (copy_mode) - { + switch (copy_mode) { case TU_FIFO_COPY_INC: - if ( n <= lin_count ) - { + if (n <= lin_count) { // Linear only - memcpy(app_buf, ff_buf, n*f->item_size); - } - else - { + memcpy(app_buf, ff_buf, n * f->item_size); + } else { // Wrap around // Read data from linear part of buffer memcpy(app_buf, ff_buf, lin_bytes); // Read data wrapped part - memcpy((uint8_t*) app_buf + lin_bytes, f->buffer, wrap_bytes); + memcpy((uint8_t *)app_buf + lin_bytes, f->buffer, wrap_bytes); } - break; + break; + #ifdef TUP_MEM_CONST_ADDR case TU_FIFO_COPY_CST_FULL_WORDS: - if ( n <= lin_count ) - { + if (n <= lin_count) { // Linear only - _ff_pull_const_addr(app_buf, ff_buf, n*f->item_size); - } - else - { + _ff_pull_const_addr(app_buf, ff_buf, n * f->item_size); + } else { // Wrap around case // Read full words from linear part of buffer @@ -284,36 +273,41 @@ static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rd_ptr, // There could be odd 1-3 bytes before the wrap-around boundary uint8_t rem = lin_bytes & 0x03; - if (rem > 0) - { - volatile uint32_t * reg_tx = (volatile uint32_t *) app_buf; + if (rem > 0) { + volatile uint32_t *reg_tx = (volatile uint32_t *)app_buf; - uint8_t remrem = (uint8_t) tu_min16(wrap_bytes, 4-rem); + uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, 4 - rem); wrap_bytes -= remrem; - uint32_t tmp32=0; - uint8_t * dst_u8 = (uint8_t *)&tmp32; + uint32_t tmp32 = 0; + uint8_t *dst_u8 = (uint8_t *)&tmp32; // Read 1-3 bytes before wrapped boundary - while(rem--) *dst_u8++ = *ff_buf++; + while (rem--) { + *dst_u8++ = *ff_buf++; + } // Read more bytes from beginning to complete a word ff_buf = f->buffer; - while(remrem--) *dst_u8++ = *ff_buf++; + while (remrem--) { + *dst_u8++ = *ff_buf++; + } *reg_tx = tmp32; - } - else - { + } else { ff_buf = f->buffer; // wrap around to beginning } // Read data wrapped part - if (wrap_bytes > 0) _ff_pull_const_addr(app_buf, ff_buf, wrap_bytes); + if (wrap_bytes > 0) { + _ff_pull_const_addr(app_buf, ff_buf, wrap_bytes); + } } - break; + break; #endif - default: break; + + default: + break; // unknown mode } } @@ -322,24 +316,18 @@ static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rd_ptr, //--------------------------------------------------------------------+ // return only the index difference and as such can be used to determine an overflow i.e overflowable count -TU_ATTR_ALWAYS_INLINE static inline -uint16_t _ff_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) { // In case we have non-power of two depth we need a further modification - if (wr_idx >= rd_idx) - { - return (uint16_t) (wr_idx - rd_idx); - } else - { - return (uint16_t) (2*depth - (rd_idx - wr_idx)); + if (wr_idx >= rd_idx) { + return (uint16_t)(wr_idx - rd_idx); + } else { + return (uint16_t)(2 * depth - (rd_idx - wr_idx)); } } // return remaining slot in fifo -TU_ATTR_ALWAYS_INLINE static inline -uint16_t _ff_remaining(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) -{ - uint16_t const count = _ff_count(depth, wr_idx, rd_idx); +TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_remaining(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) { + const uint16_t count = _ff_count(depth, wr_idx, rd_idx); return (depth > count) ? (depth - count) : 0; } @@ -349,16 +337,14 @@ uint16_t _ff_remaining(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) // Advance an absolute index // "absolute" index is only in the range of [0..2*depth) -static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) -{ +static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) { // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! // We are exploiting the wrap around to the correct index - uint16_t new_idx = (uint16_t) (idx + offset); - if ( (idx > new_idx) || (new_idx >= 2*depth) ) - { - uint16_t const non_used_index_space = (uint16_t) (UINT16_MAX - (2*depth-1)); - new_idx = (uint16_t) (new_idx + non_used_index_space); + uint16_t new_idx = (uint16_t)(idx + offset); + if ((idx > new_idx) || (new_idx >= 2 * depth)) { + const uint16_t non_used_index_space = (uint16_t)(UINT16_MAX - (2 * depth - 1)); + new_idx = (uint16_t)(new_idx + non_used_index_space); } return new_idx; @@ -366,14 +352,12 @@ static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) #if 0 // not used but // Backward an absolute index -static uint16_t backward_index(uint16_t depth, uint16_t idx, uint16_t offset) -{ +static uint16_t backward_index(uint16_t depth, uint16_t idx, uint16_t offset) { // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! // We are exploiting the wrap around to the correct index uint16_t new_idx = (uint16_t) (idx - offset); - if ( (idx < new_idx) || (new_idx >= 2*depth) ) - { + if ( (idx < new_idx) || (new_idx >= 2*depth) ) { uint16_t const non_used_index_space = (uint16_t) (UINT16_MAX - (2*depth-1)); new_idx = (uint16_t) (new_idx - non_used_index_space); } @@ -383,26 +367,22 @@ static uint16_t backward_index(uint16_t depth, uint16_t idx, uint16_t offset) #endif // index to pointer, simply an modulo with minus. -TU_ATTR_ALWAYS_INLINE static inline -uint16_t idx2ptr(uint16_t depth, uint16_t idx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t idx2ptr(uint16_t depth, uint16_t idx) { // Only run at most 3 times since index is limit in the range of [0..2*depth) - while ( idx >= depth ) idx -= depth; + while (idx >= depth) { + idx -= depth; + } return idx; } // Works on local copies of w // When an overwritable fifo is overflowed, rd_idx will be re-index so that it forms // an full fifo i.e _ff_count() = depth -TU_ATTR_ALWAYS_INLINE static inline -uint16_t _ff_correct_read_index(tu_fifo_t* f, uint16_t wr_idx) -{ +TU_ATTR_ALWAYS_INLINE static inline uint16_t _ff_correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { uint16_t rd_idx; - if ( wr_idx >= f->depth ) - { + if (wr_idx >= f->depth) { rd_idx = wr_idx - f->depth; - }else - { + } else { rd_idx = wr_idx + f->depth; } @@ -413,16 +393,16 @@ uint16_t _ff_correct_read_index(tu_fifo_t* f, uint16_t wr_idx) // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wr_idx, uint16_t rd_idx) -{ +static bool _tu_fifo_peek(tu_fifo_t *f, void *p_buffer, uint16_t wr_idx, uint16_t rd_idx) { uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx); // nothing to peek - if ( cnt == 0 ) return false; + if (cnt == 0) { + return false; + } // Check overflow and correct if required - if ( cnt > f->depth ) - { + if (cnt > f->depth) { rd_idx = _ff_correct_read_index(f, wr_idx); } @@ -436,22 +416,25 @@ static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wr_idx, uint16 // Works on local copies of w and r // Must be protected by mutexes since in case of an overflow read pointer gets modified -static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, tu_fifo_copy_mode_t copy_mode) -{ +static uint16_t _tu_fifo_peek_n( + tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, tu_fifo_copy_mode_t copy_mode) { uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx); // nothing to peek - if ( cnt == 0 ) return 0; + if (cnt == 0) { + return 0; + } // Check overflow and correct if required - if ( cnt > f->depth ) - { + if (cnt > f->depth) { rd_idx = _ff_correct_read_index(f, wr_idx); - cnt = f->depth; + cnt = f->depth; } // Check if we can read something at and after offset - if too less is available we read what remains - if ( cnt < n ) n = cnt; + if (cnt < n) { + n = cnt; + } uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); @@ -461,40 +444,36 @@ static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint1 return n; } -static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu_fifo_copy_mode_t copy_mode) -{ - if ( n == 0 ) return 0; +static uint16_t _tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_copy_mode_t copy_mode) { + if (n == 0) { + return 0; + } _ff_lock(f->mutex_wr); uint16_t wr_idx = f->wr_idx; uint16_t rd_idx = f->rd_idx; - uint8_t const* buf8 = (uint8_t const*) data; + const uint8_t *buf8 = (const uint8_t *)data; - TU_LOG(TU_FIFO_DBG, "rd = %3u, wr = %3u, count = %3u, remain = %3u, n = %3u: ", - rd_idx, wr_idx, _ff_count(f->depth, wr_idx, rd_idx), _ff_remaining(f->depth, wr_idx, rd_idx), n); + TU_LOG( + TU_FIFO_DBG, "rd = %3u, wr = %3u, count = %3u, remain = %3u, n = %3u: ", rd_idx, wr_idx, + _ff_count(f->depth, wr_idx, rd_idx), _ff_remaining(f->depth, wr_idx, rd_idx), n); - if ( !f->overwritable ) - { + if (!f->overwritable) { // limit up to full - uint16_t const remain = _ff_remaining(f->depth, wr_idx, rd_idx); - n = tu_min16(n, remain); - } - else - { + const uint16_t remain = _ff_remaining(f->depth, wr_idx, rd_idx); + n = tu_min16(n, remain); + } else { // In over-writable mode, fifo_write() is allowed even when fifo is full. In such case, // oldest data in fifo i.e at read pointer data will be overwritten // Note: we can modify read buffer contents but we must not modify the read index itself within a write function! // Since it would end up in a race condition with read functions! - if ( n >= f->depth ) - { + if (n >= f->depth) { // Only copy last part - if ( copy_mode == TU_FIFO_COPY_INC ) - { + if (copy_mode == TU_FIFO_COPY_INC) { buf8 += (n - f->depth) * f->item_size; - }else - { + } else { // TODO should read from hw fifo to discard data, however reading an odd number could // accidentally discard data. } @@ -503,12 +482,9 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu // We start writing at the read pointer's position since we fill the whole buffer wr_idx = rd_idx; - } - else - { - uint16_t const overflowable_count = _ff_count(f->depth, wr_idx, rd_idx); - if (overflowable_count + n >= 2*f->depth) - { + } else { + const uint16_t overflowable_count = _ff_count(f->depth, wr_idx, rd_idx); + if (overflowable_count + n >= 2 * f->depth) { // Double overflowed // Index is bigger than the allowed range [0,2*depth) // re-position write index to have a full fifo after pushed @@ -518,8 +494,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu // However memmove() is expensive due to actual copying + wrapping consideration. // Also race condition could happen anyway if read() is invoke while moving result in corrupted memory // currently deliberately not implemented --> result in incorrect data read back - }else - { + } else { // normal + single overflowed: // Index is in the range of [0,2*depth) and thus detect and recoverable. Recovering is handled in read() // Therefore we just increase write index @@ -528,16 +503,11 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu } } - if (n) - { + if (n) { uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); - TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); - // Write data _ff_push_n(f, buf8, n, wr_ptr, copy_mode); - - // Advance index f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); @@ -548,8 +518,7 @@ static uint16_t _tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n, tu return n; } -static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) -{ +static uint16_t _tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_copy_mode_t copy_mode) { _ff_lock(f->mutex_rd); // Peek the data @@ -582,8 +551,7 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n, tu_fifo @returns Number of items in FIFO */ /******************************************************************************/ -uint16_t tu_fifo_count(tu_fifo_t* f) -{ +uint16_t tu_fifo_count(tu_fifo_t *f) { return tu_min16(_ff_count(f->depth, f->wr_idx, f->rd_idx), f->depth); } @@ -600,8 +568,7 @@ uint16_t tu_fifo_count(tu_fifo_t* f) @returns Number of items in FIFO */ /******************************************************************************/ -bool tu_fifo_empty(tu_fifo_t* f) -{ +bool tu_fifo_empty(tu_fifo_t *f) { return f->wr_idx == f->rd_idx; } @@ -618,8 +585,7 @@ bool tu_fifo_empty(tu_fifo_t* f) @returns Number of items in FIFO */ /******************************************************************************/ -bool tu_fifo_full(tu_fifo_t* f) -{ +bool tu_fifo_full(tu_fifo_t *f) { return _ff_count(f->depth, f->wr_idx, f->rd_idx) >= f->depth; } @@ -636,8 +602,7 @@ bool tu_fifo_full(tu_fifo_t* f) @returns Number of items in FIFO */ /******************************************************************************/ -uint16_t tu_fifo_remaining(tu_fifo_t* f) -{ +uint16_t tu_fifo_remaining(tu_fifo_t *f) { return _ff_remaining(f->depth, f->wr_idx, f->rd_idx); } @@ -662,14 +627,12 @@ uint16_t tu_fifo_remaining(tu_fifo_t* f) @returns True if overflow happened */ /******************************************************************************/ -bool tu_fifo_overflowed(tu_fifo_t* f) -{ +bool tu_fifo_overflowed(tu_fifo_t *f) { return _ff_count(f->depth, f->wr_idx, f->rd_idx) > f->depth; } // Only use in case tu_fifo_overflow() returned true! -void tu_fifo_correct_read_pointer(tu_fifo_t* f) -{ +void tu_fifo_correct_read_pointer(tu_fifo_t *f) { _ff_lock(f->mutex_rd); _ff_correct_read_index(f, f->wr_idx); _ff_unlock(f->mutex_rd); @@ -691,8 +654,7 @@ void tu_fifo_correct_read_pointer(tu_fifo_t* f) @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_read(tu_fifo_t* f, void * buffer) -{ +bool tu_fifo_read(tu_fifo_t *f, void *buffer) { _ff_lock(f->mutex_rd); // Peek the data @@ -722,8 +684,7 @@ bool tu_fifo_read(tu_fifo_t* f, void * buffer) @returns number of items read from the FIFO */ /******************************************************************************/ -uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n) -{ +uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n) { return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_INC); } @@ -745,8 +706,7 @@ uint16_t tu_fifo_read_n(tu_fifo_t* f, void * buffer, uint16_t n) @returns number of items read from the FIFO */ /******************************************************************************/ -uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint16_t n) -{ +uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t *f, void *buffer, uint16_t n) { return _tu_fifo_read_n(f, buffer, n, TU_FIFO_COPY_CST_FULL_WORDS); } #endif @@ -764,8 +724,7 @@ uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t* f, void * buffer, uint1 @returns TRUE if the queue is not empty */ /******************************************************************************/ -bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) -{ +bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer) { _ff_lock(f->mutex_rd); bool ret = _tu_fifo_peek(f, p_buffer, f->wr_idx, f->rd_idx); _ff_unlock(f->mutex_rd); @@ -787,8 +746,7 @@ bool tu_fifo_peek(tu_fifo_t* f, void * p_buffer) @returns Number of bytes written to p_buffer */ /******************************************************************************/ -uint16_t tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n) -{ +uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { _ff_lock(f->mutex_rd); uint16_t ret = _tu_fifo_peek_n(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_COPY_INC); _ff_unlock(f->mutex_rd); @@ -811,27 +769,19 @@ uint16_t tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n) FIFO will always return TRUE) */ /******************************************************************************/ -bool tu_fifo_write(tu_fifo_t* f, const void * data) -{ +bool tu_fifo_write(tu_fifo_t *f, const void *data) { _ff_lock(f->mutex_wr); - bool ret; - uint16_t const wr_idx = f->wr_idx; + bool ret; + const uint16_t wr_idx = f->wr_idx; - if ( tu_fifo_full(f) && !f->overwritable ) - { + if (tu_fifo_full(f) && !f->overwritable) { ret = false; - }else - { + } else { uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); - - // Write data _ff_push(f, data, wr_ptr); - - // Advance pointer f->wr_idx = advance_index(f->depth, wr_idx, 1); - - ret = true; + ret = true; } _ff_unlock(f->mutex_wr); @@ -853,8 +803,7 @@ bool tu_fifo_write(tu_fifo_t* f, const void * data) @return Number of written elements */ /******************************************************************************/ -uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n) -{ +uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_INC); } @@ -874,8 +823,7 @@ uint16_t tu_fifo_write_n(tu_fifo_t* f, const void * data, uint16_t n) @return Number of written elements */ /******************************************************************************/ -uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t* f, const void * data, uint16_t n) -{ +uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t *f, const void *data, uint16_t n) { return _tu_fifo_write_n(f, data, n, TU_FIFO_COPY_CST_FULL_WORDS); } #endif @@ -888,8 +836,7 @@ uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t* f, const void * data, Pointer to the FIFO buffer to manipulate */ /******************************************************************************/ -bool tu_fifo_clear(tu_fifo_t *f) -{ +bool tu_fifo_clear(tu_fifo_t *f) { _ff_lock(f->mutex_wr); _ff_lock(f->mutex_rd); @@ -943,8 +890,7 @@ bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { Number of items the write pointer moves forward */ /******************************************************************************/ -void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) -{ +void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) { f->wr_idx = advance_index(f->depth, f->wr_idx, n); } @@ -964,8 +910,7 @@ void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) Number of items the read pointer moves forward */ /******************************************************************************/ -void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) -{ +void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) { f->rd_idx = advance_index(f->depth, f->rd_idx, n); } @@ -984,8 +929,7 @@ void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n) Pointer to struct which holds the desired infos */ /******************************************************************************/ -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) -{ +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { // Operate on temporary values in case they change in between uint16_t wr_idx = f->wr_idx; uint16_t rd_idx = f->rd_idx; @@ -993,8 +937,7 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx); // Check overflow and correct if required - may happen in case a DMA wrote too fast - if (cnt > f->depth) - { + if (cnt > f->depth) { _ff_lock(f->mutex_rd); rd_idx = _ff_correct_read_index(f, wr_idx); _ff_unlock(f->mutex_rd); @@ -1003,8 +946,7 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) } // Check if fifo is empty - if (cnt == 0) - { + if (cnt == 0) { info->len_lin = 0; info->len_wrap = 0; info->ptr_lin = NULL; @@ -1020,17 +962,14 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) info->ptr_lin = &f->buffer[rd_ptr]; // Check if there is a wrap around necessary - if (wr_ptr > rd_ptr) - { + if (wr_ptr > rd_ptr) { // Non wrapping case - info->len_lin = cnt; + info->len_lin = cnt; info->len_wrap = 0; info->ptr_wrap = NULL; - } - else - { - info->len_lin = f->depth - rd_ptr; // Also the case if FIFO was full + } else { + info->len_lin = f->depth - rd_ptr; // Also the case if FIFO was full info->len_wrap = cnt - info->len_lin; info->ptr_wrap = f->buffer; @@ -1052,14 +991,12 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) Pointer to struct which holds the desired infos */ /******************************************************************************/ -void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) -{ +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) { uint16_t wr_idx = f->wr_idx; uint16_t rd_idx = f->rd_idx; uint16_t remain = _ff_remaining(f->depth, wr_idx, rd_idx); - if (remain == 0) - { + if (remain == 0) { info->len_lin = 0; info->len_wrap = 0; info->ptr_lin = NULL; @@ -1074,15 +1011,12 @@ void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info) // Copy pointer to buffer to start writing to info->ptr_lin = &f->buffer[wr_ptr]; - if (wr_ptr < rd_ptr) - { + if (wr_ptr < rd_ptr) { // Non wrapping case - info->len_lin = rd_ptr-wr_ptr; + info->len_lin = rd_ptr - wr_ptr; info->len_wrap = 0; info->ptr_wrap = NULL; - } - else - { + } else { info->len_lin = f->depth - wr_ptr; info->len_wrap = remain - info->len_lin; // Remaining length - n already was limited to remain or FIFO depth info->ptr_wrap = f->buffer; // Always start of buffer diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index f2a6c5469..0f4ba00d8 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -104,16 +104,16 @@ extern "C" { * | R | 1 | 2 | W | 4 | 5 | */ typedef struct { - uint8_t* buffer ; // buffer pointer - uint16_t depth ; // max items + uint8_t *buffer; // buffer pointer + uint16_t depth; // max items struct TU_ATTR_PACKED { - uint16_t item_size : 15; // size of each item - bool overwritable : 1 ; // ovwerwritable when full + uint16_t item_size : 15; // size of each item + bool overwritable : 1; // ovwerwritable when full }; - volatile uint16_t wr_idx ; // write index - volatile uint16_t rd_idx ; // read index + volatile uint16_t wr_idx; // write index + volatile uint16_t rd_idx; // read index #if OSAL_MUTEX_REQUIRED osal_mutex_t mutex_wr; @@ -129,12 +129,13 @@ typedef struct { void * ptr_wrap ; ///< wrapped part start pointer } tu_fifo_buffer_info_t; -#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable){\ - .buffer = _buffer, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ -} +#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ + { \ + .buffer = _buffer, \ + .depth = _depth, \ + .item_size = sizeof(_type), \ + .overwritable = _overwritable, \ + } #define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ uint8_t _name##_buf[_depth*sizeof(_type)]; \ diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 5e1d59233..dcd5c45d6 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -40,6 +40,12 @@ extern tusb_role_t _tusb_rhport_role[TUP_USBIP_CONTROLLER_NUM]; // Endpoint //--------------------------------------------------------------------+ +enum { + TU_EDPT_STATE_BUSY = 0x01, + TU_EDPT_STATE_STALLED = 0x02, + TU_EDPT_STATE_CLAIMED = 0x04, +}; + typedef struct TU_ATTR_PACKED { volatile uint8_t busy : 1; volatile uint8_t stalled : 1; @@ -48,8 +54,8 @@ typedef struct TU_ATTR_PACKED { typedef struct { struct TU_ATTR_PACKED { - uint8_t is_host : 1; // 1: host, 0: device - uint8_t is_mps512 : 1; // 1: 512, 0: 64 since stream is used for Bulk only + bool is_host : 1; // 1: host, 0: device + bool is_mps512 : 1; // 1: 512, 0: 64 since stream is used for Bulk only }; uint8_t ep_addr; uint16_t ep_bufsize; @@ -93,21 +99,18 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove bool tu_edpt_stream_deinit(tu_edpt_stream_t* s); // Open an stream for an endpoint -TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_open(tu_edpt_stream_t* s, tusb_desc_endpoint_t const *desc_ep) { +TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t* s, tusb_desc_endpoint_t const *desc_ep) { tu_fifo_clear(&s->ff); s->ep_addr = desc_ep->bEndpointAddress; - s->is_mps512 = (tu_edpt_packet_size(desc_ep) == 512) ? 1 : 0; + s->is_mps512 = tu_edpt_packet_size(desc_ep) == 512; } -TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_close(tu_edpt_stream_t* s) { +TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_close(tu_edpt_stream_t* s) { s->ep_addr = 0; } // Clear fifo -TU_ATTR_ALWAYS_INLINE static inline -bool tu_edpt_stream_clear(tu_edpt_stream_t* s) { +TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_clear(tu_edpt_stream_t* s) { return tu_fifo_clear(&s->ff); } diff --git a/src/tusb.c b/src/tusb.c index be67eead2..7411f19df 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -117,11 +117,15 @@ bool tusb_inited(void) { bool ret = false; #if CFG_TUD_ENABLED - ret = ret || tud_inited(); + if (tud_inited()) { + ret = true; + } #endif #if CFG_TUH_ENABLED - ret = ret || tuh_inited(); + if (tuh_inited()) { + ret = true; + } #endif return ret; @@ -209,7 +213,8 @@ bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { (void) mutex; // pre-check to help reducing mutex lock - TU_VERIFY((ep_state->busy == 0) && (ep_state->claimed == 0)); + TU_VERIFY(ep_state->busy == 0); + TU_VERIFY(ep_state->claimed == 0); (void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); // can only claim the endpoint if it is not busy and not claimed yet. @@ -298,7 +303,7 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t const* p_desc = (uint8_t const*) desc_itf; uint16_t len = 0; - while (itf_count--) { + while ((itf_count--) > 0) { // Next on interface desc len += tu_desc_len(desc_itf); p_desc = tu_desc_next(p_desc); @@ -337,7 +342,7 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable); #if OSAL_MUTEX_REQUIRED - if (ff_buf && ff_bufsize) { + if (ff_buf != NULL && ff_bufsize > 0) { osal_mutex_t new_mutex = osal_mutex_create(&s->ff_mutexdef); tu_fifo_config_mutex(&s->ff, is_tx ? new_mutex : NULL, is_tx ? NULL : new_mutex); } @@ -352,9 +357,13 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove bool tu_edpt_stream_deinit(tu_edpt_stream_t* s) { (void) s; #if OSAL_MUTEX_REQUIRED - if (s->ff.mutex_wr) osal_mutex_delete(s->ff.mutex_wr); - if (s->ff.mutex_rd) osal_mutex_delete(s->ff.mutex_rd); - #endif + if (s->ff.mutex_wr) { + osal_mutex_delete(s->ff.mutex_wr); + } + if (s->ff.mutex_rd) { + osal_mutex_delete(s->ff.mutex_rd); + } +#endif return true; } @@ -403,7 +412,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_release(uint8_t hwid, tu_edpt_st bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t* s, uint32_t last_xferred_bytes) { // ZLP condition: no pending data, last transferred bytes is multiple of packet size const uint16_t mps = s->is_mps512 ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; - TU_VERIFY(!tu_fifo_count(&s->ff) && last_xferred_bytes && (0 == (last_xferred_bytes & (mps - 1)))); + TU_VERIFY(!tu_fifo_count(&s->ff) && last_xferred_bytes > 0 && (0 == (last_xferred_bytes & (mps - 1)))); TU_VERIFY(stream_claim(hwid, s)); TU_ASSERT(stream_xfer(hwid, s, 0)); return true; @@ -411,14 +420,13 @@ bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t* s, uint3 uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s) { // skip if no data - TU_VERIFY(tu_fifo_count(&s->ff), 0); - + TU_VERIFY(tu_fifo_count(&s->ff) > 0, 0); TU_VERIFY(stream_claim(hwid, s), 0); // Pull data from FIFO -> EP buf uint16_t const count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); - if (count) { + if (count > 0) { TU_ASSERT(stream_xfer(hwid, s, count), 0); return count; } else { @@ -430,7 +438,7 @@ uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s) { } uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t* s, void const* buffer, uint32_t bufsize) { - TU_VERIFY(bufsize); // TODO support ZLP + TU_VERIFY(bufsize > 0); // TODO support ZLP if (0 == tu_fifo_depth(&s->ff)) { // no fifo for buffered @@ -453,7 +461,7 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t* s, void const* buf } uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t* s) { - if (tu_fifo_depth(&s->ff)) { + if (tu_fifo_depth(&s->ff) > 0) { return (uint32_t) tu_fifo_remaining(&s->ff); } else { bool is_busy = true; @@ -596,7 +604,7 @@ void tu_print_mem(void const* buf, uint32_t count, uint8_t indent) { // fill up last row to 16 for printing ascii const uint32_t remain = count % 16; uint8_t nback = (uint8_t) (remain ? remain : 16); - if (remain) { + if (remain > 0) { for (uint32_t i = 0; i < 16 - remain; i++) { tu_printf(" "); for (int j = 0; j < 2 * size; j++) { -- cgit v1.3.1 From fc661abc18beefb57f5d1352219ed72678b59e0b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Nov 2025 10:41:58 +0700 Subject: migrate midi_device to use edpt stream API also add tud_midi_n_packet_write/read_n() --- .clang-format | 1 + src/class/midi/midi_device.c | 511 ++++++++++++++++----------------------- src/class/midi/midi_device.h | 130 ++++------ src/class/vendor/vendor_device.c | 3 +- src/common/tusb_fifo.c | 25 +- src/common/tusb_fifo.h | 38 +-- src/common/tusb_private.h | 14 +- src/tusb.c | 4 +- 8 files changed, 288 insertions(+), 438 deletions(-) (limited to 'src/tusb.c') diff --git a/.clang-format b/.clang-format index 907dd7cdd..c278fec37 100644 --- a/.clang-format +++ b/.clang-format @@ -70,6 +70,7 @@ IncludeCategories: - Regex: '.*' Priority: 3 IncludeIsMainRegex: '([-_](test|unittest))?$' +IndentPPDirectives: BeforeHash InsertBraces: true IndentCaseLabels: true InsertNewlineAtEOF: true diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 7dac7c4a5..f065e486a 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -36,13 +36,19 @@ #include "midi_device.h" +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf) { + (void)itf; +} + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ typedef struct { + uint8_t rhport; uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the @@ -51,134 +57,97 @@ typedef struct { midi_driver_stream_t stream_read; /*------------- From this point, data is not cleared by bus reset -------------*/ - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - uint8_t rx_ff_buf[CFG_TUD_MIDI_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_MIDI_TX_BUFSIZE]; - - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; - #endif + // Endpoint stream + struct { + tu_edpt_stream_t tx; + tu_edpt_stream_t rx; + + uint8_t rx_ff_buf[CFG_TUD_MIDI_RX_BUFSIZE]; + uint8_t tx_ff_buf[CFG_TUD_MIDI_TX_BUFSIZE]; + } ep_stream; } midid_interface_t; -#define ITF_MEM_RESET_SIZE offsetof(midid_interface_t, rx_ff) +#define ITF_MEM_RESET_SIZE offsetof(midid_interface_t, ep_stream) + +static midid_interface_t _midid_itf[CFG_TUD_MIDI]; // Endpoint Transfer buffer -CFG_TUD_MEM_SECTION static struct { +typedef struct { TUD_EPBUF_DEF(epin, CFG_TUD_MIDI_EP_BUFSIZE); TUD_EPBUF_DEF(epout, CFG_TUD_MIDI_EP_BUFSIZE); -} _midid_epbuf[CFG_TUD_MIDI]; +} midid_epbuf_t; + +CFG_TUD_MEM_SECTION static midid_epbuf_t _midid_epbuf[CFG_TUD_MIDI]; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ -static midid_interface_t _midid_itf[CFG_TUD_MIDI]; - bool tud_midi_n_mounted (uint8_t itf) { - midid_interface_t* midi = &_midid_itf[itf]; - return midi->ep_in && midi->ep_out; -} + midid_interface_t *p_midi = &_midid_itf[itf]; -static void _prep_out_transaction(uint8_t idx) { - const uint8_t rhport = 0; - midid_interface_t* p_midi = &_midid_itf[idx]; - uint16_t available = tu_fifo_remaining(&p_midi->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= CFG_TUD_MIDI_EP_BUFSIZE, ); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), ); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_midi->rx_ff); - - if ( available >= CFG_TUD_MIDI_EP_BUFSIZE ) { - usbd_edpt_xfer(rhport, p_midi->ep_out, _midid_epbuf[idx].epout, CFG_TUD_MIDI_EP_BUFSIZE); - }else - { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, p_midi->ep_out); - } -} - - -//--------------------------------------------------------------------+ -// Weak stubs: invoked if no strong implementation is available -//--------------------------------------------------------------------+ -TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf) { - (void) itf; + const bool tx_opened = tu_edpt_stream_is_opened(&p_midi->ep_stream.tx); + const bool rx_opened = tu_edpt_stream_is_opened(&p_midi->ep_stream.rx); + return tx_opened && rx_opened; } //--------------------------------------------------------------------+ // READ API //--------------------------------------------------------------------+ -uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) -{ +uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) { (void) cable_num; - - midid_interface_t* midi = &_midid_itf[itf]; - const midi_driver_stream_t* stream = &midi->stream_read; + const midid_interface_t *p_midi = &_midid_itf[itf]; + const midi_driver_stream_t *stream = &p_midi->stream_read; + const tu_edpt_stream_t *ep_str = &p_midi->ep_stream.rx; // when using with packet API stream total & index are both zero - return tu_fifo_count(&midi->rx_ff) + (uint8_t) (stream->total - stream->index); + return tu_edpt_stream_read_available(ep_str) + (uint8_t)(stream->total - stream->index); } -uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize) -{ +uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void *buffer, uint32_t bufsize) { (void) cable_num; - TU_VERIFY(bufsize, 0); - - uint8_t* buf8 = (uint8_t*) buffer; + TU_VERIFY(buffer != NULL && bufsize > 0, 0); - midid_interface_t* midi = &_midid_itf[itf]; - midi_driver_stream_t* stream = &midi->stream_read; + uint8_t *buf8 = (uint8_t *)buffer; + midid_interface_t *p_midi = &_midid_itf[itf]; + midi_driver_stream_t *stream = &p_midi->stream_read; uint32_t total_read = 0; - while( bufsize ) - { + while (bufsize > 0) { // Get new packet from fifo, then set packet expected bytes - if ( stream->total == 0 ) - { - // return if there is no more data from fifo - if ( !tud_midi_n_packet_read(itf, stream->buffer) ) return total_read; + if (stream->total == 0) { + if (!tud_midi_n_packet_read(itf, stream->buffer)) { + return total_read; // return if there is no more data from fifo + } - uint8_t const code_index = stream->buffer[0] & 0x0f; + const uint8_t code_index = stream->buffer[0] & 0x0f; // MIDI 1.0 Table 4-1: Code Index Number Classifications - switch(code_index) - { + switch (code_index) { case MIDI_CIN_MISC: case MIDI_CIN_CABLE_EVENT: // These are reserved and unused, possibly issue somewhere, skip this packet return 0; - break; case MIDI_CIN_SYSEX_END_1BYTE: case MIDI_CIN_1BYTE_DATA: stream->total = 1; - break; + break; case MIDI_CIN_SYSCOM_2BYTE : case MIDI_CIN_SYSEX_END_2BYTE : case MIDI_CIN_PROGRAM_CHANGE : case MIDI_CIN_CHANNEL_PRESSURE : stream->total = 2; - break; + break; default: stream->total = 3; - break; + break; } } // Copy data up to bufsize - uint8_t const count = (uint8_t) tu_min32(stream->total - stream->index, bufsize); + const uint8_t count = (uint8_t)tu_min32((uint32_t)(stream->total - stream->index), bufsize); // Skip the header (1st byte) in the buffer TU_VERIFY(0 == tu_memcpy_s(buf8, bufsize, stream->buffer + 1 + stream->index, count)); @@ -189,8 +158,7 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui bufsize -= count; // complete current event packet, reset stream - if ( stream->total == stream->index ) - { + if (stream->total == stream->index) { stream->index = 0; stream->total = 0; } @@ -199,150 +167,107 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui return total_read; } -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_out); +bool tud_midi_n_packet_read(uint8_t itf, uint8_t packet[4]) { + midid_interface_t *p_midi = &_midid_itf[itf]; + tu_edpt_stream_t *ep_str = &p_midi->ep_stream.rx; + TU_VERIFY(tu_edpt_stream_is_opened(ep_str)); + return 4 == tu_edpt_stream_read(p_midi->rhport, ep_str, packet, 4); +} + +uint32_t tud_midi_n_packet_read_n(uint8_t itf, uint8_t packets[], uint32_t max_packets) { + midid_interface_t *p_midi = &_midid_itf[itf]; + tu_edpt_stream_t *ep_str = &p_midi->ep_stream.rx; + TU_VERIFY(tu_edpt_stream_is_opened(ep_str), 0); - const uint32_t num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4); - _prep_out_transaction(itf); - return (num_read == 4); + const uint32_t num_read = tu_edpt_stream_read(p_midi->rhport, ep_str, packets, 4u * max_packets); + return num_read >> 2u; } //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ - -static uint32_t write_flush(uint8_t idx) { - midid_interface_t* midi = &_midid_itf[idx]; - - if (!tu_fifo_count(&midi->tx_ff)) { - return 0; // No data to send - } - - const uint8_t rhport = 0; - - // skip if previous transfer not complete - TU_VERIFY( usbd_edpt_claim(rhport, midi->ep_in), 0 ); - - uint16_t count = tu_fifo_read_n(&midi->tx_ff, _midid_epbuf[idx].epin, CFG_TUD_MIDI_EP_BUFSIZE); - - if (count) { - TU_ASSERT( usbd_edpt_xfer(rhport, midi->ep_in, _midid_epbuf[idx].epin, count), 0 ); - return count; - }else { - // Release endpoint since we don't make any transfer - usbd_edpt_release(rhport, midi->ep_in); - return 0; - } -} - -uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t* buffer, uint32_t bufsize) -{ - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in, 0); - - midi_driver_stream_t* stream = &midi->stream_write; +uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t *buffer, uint32_t bufsize) { + midid_interface_t *p_midi = &_midid_itf[itf]; + midi_driver_stream_t *stream = &p_midi->stream_write; + tu_edpt_stream_t *ep_str = &p_midi->ep_stream.tx; + TU_VERIFY(tu_edpt_stream_is_opened(ep_str), 0); uint32_t i = 0; - while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) - { + while (i < bufsize) { + if (tu_edpt_stream_write_available(p_midi->rhport, ep_str) < 4) { + break; + } + const uint8_t data = buffer[i]; i++; - if ( stream->index == 0 ) - { + if (stream->index == 0) { //------------- New event packet -------------// const uint8_t msg = data >> 4; - stream->index = 2; + stream->index = 2; stream->buffer[1] = data; // Check to see if we're still in a SysEx transmit. - if ( ((stream->buffer[0]) & 0xF) == MIDI_CIN_SYSEX_START ) - { - if ( data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = (uint8_t) ((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); - stream->total = 2; - } - else - { + if (((stream->buffer[0]) & 0xF) == MIDI_CIN_SYSEX_START) { + if (data == MIDI_STATUS_SYSEX_END) { + stream->buffer[0] = (uint8_t)((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); + stream->total = 2; + } else { stream->total = 4; } - } - else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) - { + } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { // Channel Voice Messages - stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); - stream->total = 4; - } - else if ( msg == 0xC || msg == 0xD) - { + stream->buffer[0] = (uint8_t)((cable_num << 4) | msg); + stream->total = 4; + } else if (msg == 0xC || msg == 0xD) { // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) - stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); - stream->total = 3; - } - else if ( msg == 0xf ) - { + stream->buffer[0] = (uint8_t)((cable_num << 4) | msg); + stream->total = 3; + } else if (msg == 0xf) { // System message - if ( data == MIDI_STATUS_SYSEX_START ) - { + if (data == MIDI_STATUS_SYSEX_START) { stream->buffer[0] = MIDI_CIN_SYSEX_START; - stream->total = 4; - } - else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) - { + stream->total = 4; + } else if (data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT) { stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - stream->total = 3; - } - else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) - { + stream->total = 3; + } else if (data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER) { stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - stream->total = 4; - } - else - { + stream->total = 4; + } else { stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; + stream->total = 2; } stream->buffer[0] |= (uint8_t)(cable_num << 4); - } - else - { + } else { // Pack individual bytes if we don't support packing them into words. - stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf); + stream->buffer[0] = (uint8_t)(cable_num << 4 | 0xf); stream->buffer[2] = 0; stream->buffer[3] = 0; - stream->index = 2; - stream->total = 2; + stream->total = 2; // index already set to 2 } - } - else - { + } else { //------------- On-going (buffering) packet -------------// - TU_ASSERT(stream->index < 4, i); stream->buffer[stream->index] = data; stream->index++; // See if this byte ends a SysEx. - if ( (stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) - { - stream->buffer[0] = (uint8_t) ((cable_num << 4) | (MIDI_CIN_SYSEX_START + (stream->index - 1))); - stream->total = stream->index; + if ((stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) { + stream->buffer[0] = (uint8_t)((cable_num << 4) | (MIDI_CIN_SYSEX_START + (stream->index - 1))); + stream->total = stream->index; } } // Send out packet - if ( stream->index == stream->total ) - { + if (stream->index == stream->total) { // zeroes unused bytes for (uint8_t idx = stream->total; idx < 4; idx++) { stream->buffer[idx] = 0; } - const uint16_t count = tu_fifo_write_n(&midi->tx_ff, stream->buffer, 4); + const uint32_t count = tu_edpt_stream_write(p_midi->rhport, ep_str, stream->buffer, 4); // complete current event packet, reset stream stream->index = stream->total = 0; @@ -352,25 +277,37 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t* } } - write_flush(itf); + (void)tu_edpt_stream_write_xfer(p_midi->rhport, ep_str); return i; } bool tud_midi_n_packet_write (uint8_t itf, const uint8_t packet[4]) { - midid_interface_t* midi = &_midid_itf[itf]; - TU_VERIFY(midi->ep_in); + midid_interface_t *p_midi = &_midid_itf[itf]; + tu_edpt_stream_t *ep_str = &p_midi->ep_stream.tx; + TU_VERIFY(tu_edpt_stream_is_opened(ep_str)); - if (tu_fifo_remaining(&midi->tx_ff) < 4) { - return false; - } - - tu_fifo_write_n(&midi->tx_ff, packet, 4); - write_flush(itf); + TU_VERIFY(tu_edpt_stream_write_available(p_midi->rhport, ep_str) >= 4); + TU_VERIFY(tu_edpt_stream_write(p_midi->rhport, ep_str, packet, 4) > 0); + (void)tu_edpt_stream_write_xfer(p_midi->rhport, ep_str); return true; } +uint32_t tud_midi_n_packet_write_n(uint8_t itf, const uint8_t packets[], uint32_t n_packets) { + midid_interface_t *p_midi = &_midid_itf[itf]; + tu_edpt_stream_t *ep_str = &p_midi->ep_stream.tx; + TU_VERIFY(tu_edpt_stream_is_opened(ep_str), 0); + + uint32_t n_bytes = tu_edpt_stream_write_available(p_midi->rhport, ep_str); + n_bytes = tu_min32(tu_align4(n_bytes), n_packets << 2u); + + const uint32_t n_write = tu_edpt_stream_write(p_midi->rhport, ep_str, packets, n_bytes); + (void)tu_edpt_stream_write_xfer(p_midi->rhport, ep_str); + + return n_write >> 2u; +} + //--------------------------------------------------------------------+ // USBD Driver API //--------------------------------------------------------------------+ @@ -378,72 +315,64 @@ void midid_init(void) { tu_memclr(_midid_itf, sizeof(_midid_itf)); for (uint8_t i = 0; i < CFG_TUD_MIDI; i++) { - midid_interface_t* midi = &_midid_itf[i]; - - // config fifo - tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); // true, true - tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS. + midid_interface_t *p_midi = &_midid_itf[i]; + midid_epbuf_t *p_epbuf = &_midid_epbuf[i]; - #if CFG_FIFO_MUTEX - osal_mutex_t mutex_rd = osal_mutex_create(&midi->rx_ff_mutex); - osal_mutex_t mutex_wr = osal_mutex_create(&midi->tx_ff_mutex); - TU_ASSERT(mutex_wr != NULL && mutex_wr != NULL, ); + tu_edpt_stream_init( + &p_midi->ep_stream.rx, false, false, false, p_midi->ep_stream.rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, + p_epbuf->epout, CFG_TUD_MIDI_EP_BUFSIZE); - tu_fifo_config_mutex(&midi->rx_ff, NULL, mutex_rd); - tu_fifo_config_mutex(&midi->tx_ff, mutex_wr, NULL); - #endif + tu_edpt_stream_init( + &p_midi->ep_stream.tx, false, true, false, p_midi->ep_stream.tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, p_epbuf->epin, + CFG_TUD_MIDI_EP_BUFSIZE); } } bool midid_deinit(void) { - #if CFG_FIFO_MUTEX - for(uint8_t i=0; irx_ff.mutex_rd; - osal_mutex_t mutex_wr = midi->tx_ff.mutex_wr; - - if (mutex_rd) { - osal_mutex_delete(mutex_rd); - tu_fifo_config_mutex(&midi->rx_ff, NULL, NULL); - } - - if (mutex_wr) { - osal_mutex_delete(mutex_wr); - tu_fifo_config_mutex(&midi->tx_ff, NULL, NULL); - } + for (uint8_t i = 0; i < CFG_TUD_MIDI; i++) { + midid_interface_t *p_midi = &_midid_itf[i]; + tu_edpt_stream_deinit(&p_midi->ep_stream.rx); + tu_edpt_stream_deinit(&p_midi->ep_stream.tx); } - #endif - return true; } -void midid_reset(uint8_t rhport) -{ - (void) rhport; +void midid_reset(uint8_t rhport) { + (void)rhport; + for (uint8_t i = 0; i < CFG_TUD_MIDI; i++) { + midid_interface_t *p_midi = &_midid_itf[i]; + tu_memclr(p_midi, ITF_MEM_RESET_SIZE); + + tu_edpt_stream_clear(&p_midi->ep_stream.rx); + tu_edpt_stream_close(&p_midi->ep_stream.rx); - for(uint8_t i=0; irx_ff); - tu_fifo_clear(&midi->tx_ff); + tu_edpt_stream_clear(&p_midi->ep_stream.tx); + tu_edpt_stream_close(&p_midi->ep_stream.tx); } } -uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) { - uint16_t drv_len = 0; - uint8_t const * p_desc = (uint8_t const *)desc_itf; +TU_ATTR_ALWAYS_INLINE static inline uint8_t find_midi_itf(uint8_t ep_addr) { + for (uint8_t idx = 0; idx < CFG_TUD_MIDI; idx++) { + const midid_interface_t *p_midi = &_midid_itf[idx]; + if (ep_addr == p_midi->ep_stream.rx.ep_addr || ep_addr == p_midi->ep_stream.tx.ep_addr) { + return idx; + } + } + return TUSB_INDEX_INVALID_8; +} + +uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uint16_t max_len) { + const uint8_t *p_desc = (const uint8_t *)desc_itf; + const uint8_t *desc_end = p_desc + max_len; // 1st Interface is Audio Control v1 (optional) if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) { - drv_len = tu_desc_len(desc_itf); p_desc = tu_desc_next(desc_itf); // Skip Class Specific descriptors - while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + while (tu_desc_in_bounds(p_desc, desc_end) && TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) { + p_desc = tu_desc_next(p_desc); } } @@ -451,59 +380,44 @@ uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint1 TU_VERIFY(TUSB_DESC_INTERFACE == tu_desc_type(p_desc), 0); const tusb_desc_interface_t* desc_midi = (const tusb_desc_interface_t*) p_desc; - TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && - AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_midi->bInterfaceClass && + AUDIO_SUBCLASS_MIDI_STREAMING == desc_midi->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_midi->bInterfaceProtocol, + 0); - // Find available interface - midid_interface_t * p_midi = NULL; - uint8_t idx; - for(idx=0; idxrhport = rhport; p_midi->itf_num = desc_midi->bInterfaceNumber; (void) p_midi->itf_num; - // next descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); // Find and open endpoint descriptors - uint8_t found_endpoints = 0; - while ( (found_endpoints < desc_midi->bNumEndpoints) && (drv_len <= max_len) ) - { - if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) ) - { - TU_ASSERT(usbd_edpt_open(rhport, (const tusb_desc_endpoint_t*) p_desc), 0); - uint8_t ep_addr = ((const tusb_desc_endpoint_t*) p_desc)->bEndpointAddress; - - if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) - { - p_midi->ep_in = ep_addr; + uint8_t found_ep = 0; + while ((found_ep < desc_midi->bNumEndpoints) && tu_desc_in_bounds(p_desc, desc_end)) { + if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc; + TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); + const uint8_t ep_addr = ((const tusb_desc_endpoint_t *)p_desc)->bEndpointAddress; + + if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { + tu_edpt_stream_open(&p_midi->ep_stream.tx, desc_ep); } else { - p_midi->ep_out = ep_addr; + tu_edpt_stream_open(&p_midi->ep_stream.rx, desc_ep); + TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_midi->ep_stream.rx) > 0, 0); // prepare to receive data } - // Class Specific MIDI Stream endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - - found_endpoints += 1; + p_desc = tu_desc_next(p_desc); // skip CS Endpoint descriptor + found_ep++; } - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + p_desc = tu_desc_next(p_desc); } - // Prepare for incoming data - _prep_out_transaction(idx); - - return drv_len; + return (uint16_t)(p_desc - (const uint8_t *)desc_itf); } // Invoked when a control transfer occurred on an interface of this class @@ -514,44 +428,31 @@ bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_req return false; // driver doesn't support any request yet } -bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void) result; - (void) rhport; - - uint8_t idx; - midid_interface_t* p_midi; +bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void)result; - // Identify which interface to use - for (idx = 0; idx < CFG_TUD_MIDI; idx++) { - p_midi = &_midid_itf[idx]; - if ((ep_addr == p_midi->ep_out) || (ep_addr == p_midi->ep_in)) { - break; - } - } + uint8_t idx = find_midi_itf(ep_addr); TU_ASSERT(idx < CFG_TUD_MIDI); + midid_interface_t *p_midi = &_midid_itf[idx]; - // receive new data - if (ep_addr == p_midi->ep_out) { - tu_fifo_write_n(&p_midi->rx_ff, _midid_epbuf[idx].epout, (uint16_t)xferred_bytes); - - // invoke receive callback if available - tud_midi_rx_cb(idx); - - // prepare for next - // TODO for now ep_out is not used by public API therefore there is no race condition, - // and does not need to claim like ep_in - _prep_out_transaction(idx); - } else if (ep_addr == p_midi->ep_in) { - if (0 == write_flush(idx)) { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - if (!tu_fifo_count(&p_midi->tx_ff) && xferred_bytes && (0 == (xferred_bytes % CFG_TUD_MIDI_EP_BUFSIZE))) { - if (usbd_edpt_claim(rhport, p_midi->ep_in)) { - usbd_edpt_xfer(rhport, p_midi->ep_in, NULL, 0); - } - } + tu_edpt_stream_t *ep_st_rx = &p_midi->ep_stream.rx; + tu_edpt_stream_t *ep_st_tx = &p_midi->ep_stream.tx; + + if (ep_addr == ep_st_rx->ep_addr) { + // Received new data: put into stream's fifo + if (result == XFER_RESULT_SUCCESS) { + tu_edpt_stream_read_xfer_complete(ep_st_rx, xferred_bytes); + tud_midi_rx_cb(idx); // invoke callback } + tu_edpt_stream_read_xfer(rhport, ep_st_rx); // prepare for next data + } else if (ep_addr == ep_st_tx->ep_addr && result == XFER_RESULT_SUCCESS) { + // sent complete: try to send more if possible + if (0 == tu_edpt_stream_write_xfer(rhport, ep_st_tx)) { + // If there is no data left, a ZLP should be sent if needed + (void)tu_edpt_stream_write_zlp_if_needed(rhport, ep_st_tx, xferred_bytes); + } + } else { + return false; } return true; diff --git a/src/class/midi/midi_device.h b/src/class/midi/midi_device.h index d23516cec..ddbc2f9f0 100644 --- a/src/class/midi/midi_device.h +++ b/src/class/midi/midi_device.h @@ -36,21 +36,21 @@ #if !defined(CFG_TUD_MIDI_EP_BUFSIZE) && defined(CFG_TUD_MIDI_EPSIZE) #warning CFG_TUD_MIDI_EPSIZE is renamed to CFG_TUD_MIDI_EP_BUFSIZE, please update to use the new name - #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE + #define CFG_TUD_MIDI_EP_BUFSIZE CFG_TUD_MIDI_EPSIZE #endif #ifndef CFG_TUD_MIDI_EP_BUFSIZE - #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) + #define CFG_TUD_MIDI_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif #ifdef __cplusplus - extern "C" { +extern "C" { #endif -/** \addtogroup MIDI_Serial Serial - * @{ - * \defgroup MIDI_Serial_Device Device - * @{ */ +//--------------------------------------------------------------------+ +// Application Callback API (optional) +//--------------------------------------------------------------------+ +void tud_midi_rx_cb(uint8_t itf); //--------------------------------------------------------------------+ // Application API (Multiple Interfaces) @@ -58,117 +58,77 @@ //--------------------------------------------------------------------+ // Check if midi interface is mounted -bool tud_midi_n_mounted (uint8_t itf); +bool tud_midi_n_mounted(uint8_t itf); // Get the number of bytes available for reading -uint32_t tud_midi_n_available (uint8_t itf, uint8_t cable_num); - -// Read byte stream (legacy) -uint32_t tud_midi_n_stream_read (uint8_t itf, uint8_t cable_num, void* buffer, uint32_t bufsize); - -// Write byte Stream (legacy) -uint32_t tud_midi_n_stream_write (uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -// Read event packet (4 bytes) -bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4]); - -// Write event packet (4 bytes) -bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4]); +uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num); -//--------------------------------------------------------------------+ -// Application API (Single Interface) -//--------------------------------------------------------------------+ -static inline bool tud_midi_mounted (void); -static inline uint32_t tud_midi_available (void); - -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize); -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize); - -static inline bool tud_midi_packet_read (uint8_t packet[4]); -static inline bool tud_midi_packet_write (uint8_t const packet[4]); - -//------------- Deprecated API name -------------// -// TODO remove after 0.10.0 release - -TU_ATTR_DEPRECATED("tud_midi_read() is renamed to tud_midi_stream_read()") -static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) -{ - return tud_midi_stream_read(buffer, bufsize); -} +// Read byte stream (legacy) +uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void *buffer, uint32_t bufsize); -TU_ATTR_DEPRECATED("tud_midi_write() is renamed to tud_midi_stream_write()") -static inline uint32_t tud_midi_write(uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ - return tud_midi_stream_write(cable_num, buffer, bufsize); -} +// Write byte Stream (legacy) +uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t *buffer, uint32_t bufsize); +// Read an event 4-byte packet +bool tud_midi_n_packet_read(uint8_t itf, uint8_t packet[4]); -TU_ATTR_DEPRECATED("tud_midi_send() is renamed to tud_midi_packet_write()") -static inline bool tud_midi_send(uint8_t packet[4]) -{ - return tud_midi_packet_write(packet); -} +// Read multiple event packets, return number of read packets +uint32_t tud_midi_n_packet_read_n(uint8_t itf, uint8_t packets[], uint32_t max_packets); -TU_ATTR_DEPRECATED("tud_midi_receive() is renamed to tud_midi_packet_read()") -static inline bool tud_midi_receive(uint8_t packet[4]) -{ - return tud_midi_packet_read(packet); -} +// Write an event 4-byte packet +bool tud_midi_n_packet_write(uint8_t itf, const uint8_t packet[4]); -//--------------------------------------------------------------------+ -// Application Callback API (optional) -//--------------------------------------------------------------------+ -void tud_midi_rx_cb(uint8_t itf); +// Write multiple event packets, return number of written packets +uint32_t tud_midi_n_packet_write_n(uint8_t itf, const uint8_t packets[], uint32_t n_packets); //--------------------------------------------------------------------+ -// Inline Functions +// Application API (Single Interface) //--------------------------------------------------------------------+ - -static inline bool tud_midi_mounted (void) -{ +TU_ATTR_ALWAYS_INLINE static inline bool tud_midi_mounted(void) { return tud_midi_n_mounted(0); } -static inline uint32_t tud_midi_available (void) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_midi_available(void) { return tud_midi_n_available(0, 0); } -static inline uint32_t tud_midi_stream_read (void* buffer, uint32_t bufsize) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_midi_stream_read(void *buffer, uint32_t bufsize) { return tud_midi_n_stream_read(0, 0, buffer, bufsize); } -static inline uint32_t tud_midi_stream_write (uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t +tud_midi_stream_write(uint8_t cable_num, const uint8_t *buffer, uint32_t bufsize) { return tud_midi_n_stream_write(0, cable_num, buffer, bufsize); } -static inline bool tud_midi_packet_read (uint8_t packet[4]) -{ +TU_ATTR_ALWAYS_INLINE static inline bool tud_midi_packet_read(uint8_t packet[4]) { return tud_midi_n_packet_read(0, packet); } -static inline bool tud_midi_packet_write (uint8_t const packet[4]) -{ +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_midi_packet_read_n(uint8_t packets[], uint32_t max_packets) { + return tud_midi_n_packet_read_n(0, packets, max_packets); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_midi_packet_write(const uint8_t packet[4]) { return tud_midi_n_packet_write(0, packet); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_midi_packet_write_n(const uint8_t packets[], uint32_t n_packets) { + return tud_midi_n_packet_write_n(0, packets, n_packets); +} + //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void midid_init (void); -bool midid_deinit (void); -void midid_reset (uint8_t rhport); -uint16_t midid_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -bool midid_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); -bool midid_xfer_cb (uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); +void midid_init(void); +bool midid_deinit(void); +void midid_reset(uint8_t rhport); +uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t *request); +bool midid_xfer_cb(uint8_t rhport, uint8_t edpt_addr, xfer_result_t result, uint32_t xferred_bytes); #ifdef __cplusplus - } +} #endif -#endif /* TUSB_MIDI_DEVICE_H_ */ - -/** @} */ -/** @} */ +#endif diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 27724b194..c916ebe47 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -202,8 +202,9 @@ void vendord_reset(uint8_t rhport) { vendord_interface_t* p_itf = &_vendord_itf[i]; tu_memclr(p_itf, ITF_MEM_RESET_SIZE); tu_edpt_stream_clear(&p_itf->rx.stream); - tu_edpt_stream_clear(&p_itf->tx.stream); tu_edpt_stream_close(&p_itf->rx.stream); + + tu_edpt_stream_clear(&p_itf->tx.stream); tu_edpt_stream_close(&p_itf->tx.stream); } } diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 419046b8b..5c9e586fb 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -551,27 +551,10 @@ static uint16_t _tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_ @returns Number of items in FIFO */ /******************************************************************************/ -uint16_t tu_fifo_count(tu_fifo_t *f) { +uint16_t tu_fifo_count(const tu_fifo_t *f) { return tu_min16(_ff_count(f->depth, f->wr_idx, f->rd_idx), f->depth); } -/******************************************************************************/ -/*! - @brief Check if FIFO is empty. - - As this function only reads the read and write pointers once, this function is - reentrant and thus thread and ISR save without any mutexes. - - @param[in] f - Pointer to the FIFO buffer to manipulate - - @returns Number of items in FIFO - */ -/******************************************************************************/ -bool tu_fifo_empty(tu_fifo_t *f) { - return f->wr_idx == f->rd_idx; -} - /******************************************************************************/ /*! @brief Check if FIFO is full. @@ -585,7 +568,7 @@ bool tu_fifo_empty(tu_fifo_t *f) { @returns Number of items in FIFO */ /******************************************************************************/ -bool tu_fifo_full(tu_fifo_t *f) { +bool tu_fifo_full(const tu_fifo_t *f) { return _ff_count(f->depth, f->wr_idx, f->rd_idx) >= f->depth; } @@ -602,7 +585,7 @@ bool tu_fifo_full(tu_fifo_t *f) { @returns Number of items in FIFO */ /******************************************************************************/ -uint16_t tu_fifo_remaining(tu_fifo_t *f) { +uint16_t tu_fifo_remaining(const tu_fifo_t *f) { return _ff_remaining(f->depth, f->wr_idx, f->rd_idx); } @@ -627,7 +610,7 @@ uint16_t tu_fifo_remaining(tu_fifo_t *f) { @returns True if overflow happened */ /******************************************************************************/ -bool tu_fifo_overflowed(tu_fifo_t *f) { +bool tu_fifo_overflowed(const tu_fifo_t *f) { return _ff_count(f->depth, f->wr_idx, f->rd_idx) > f->depth; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 0f4ba00d8..9d8b864e9 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -155,33 +155,35 @@ void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_m #define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex) #endif -bool tu_fifo_write (tu_fifo_t* f, void const * data); -uint16_t tu_fifo_write_n (tu_fifo_t* f, void const * data, uint16_t n); -#ifdef TUP_MEM_CONST_ADDR -uint16_t tu_fifo_write_n_const_addr_full_words (tu_fifo_t* f, const void * data, uint16_t n); -#endif +bool tu_fifo_write(tu_fifo_t *f, void const *data); +uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n); + +bool tu_fifo_read(tu_fifo_t *f, void *buffer); +uint16_t tu_fifo_read_n(tu_fifo_t *f, void *buffer, uint16_t n); -bool tu_fifo_read (tu_fifo_t* f, void * buffer); -uint16_t tu_fifo_read_n (tu_fifo_t* f, void * buffer, uint16_t n); #ifdef TUP_MEM_CONST_ADDR -uint16_t tu_fifo_read_n_const_addr_full_words (tu_fifo_t* f, void * buffer, uint16_t n); +uint16_t tu_fifo_write_n_const_addr_full_words(tu_fifo_t *f, const void *data, uint16_t n); +uint16_t tu_fifo_read_n_const_addr_full_words(tu_fifo_t *f, void *buffer, uint16_t n); #endif -bool tu_fifo_peek (tu_fifo_t* f, void * p_buffer); -uint16_t tu_fifo_peek_n (tu_fifo_t* f, void * p_buffer, uint16_t n); +bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer); +uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n); -uint16_t tu_fifo_count (tu_fifo_t* f); -uint16_t tu_fifo_remaining (tu_fifo_t* f); -bool tu_fifo_empty (tu_fifo_t* f); -bool tu_fifo_full (tu_fifo_t* f); -bool tu_fifo_overflowed (tu_fifo_t* f); -void tu_fifo_correct_read_pointer (tu_fifo_t* f); +uint16_t tu_fifo_count(const tu_fifo_t *f); +uint16_t tu_fifo_remaining(const tu_fifo_t *f); +bool tu_fifo_full(const tu_fifo_t *f); +bool tu_fifo_overflowed(const tu_fifo_t *f); -TU_ATTR_ALWAYS_INLINE static inline -uint16_t tu_fifo_depth(tu_fifo_t* f) { +TU_ATTR_ALWAYS_INLINE static inline bool tu_fifo_empty(const tu_fifo_t *f) { + return f->wr_idx == f->rd_idx; +} + +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_depth(const tu_fifo_t *f) { return f->depth; } +void tu_fifo_correct_read_pointer(tu_fifo_t *f); + // Pointer modifications intended to be used in combinations with DMAs. // USE WITH CARE - NO SAFETY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n); diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index dcd5c45d6..367209e57 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -105,6 +105,10 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t* s s->is_mps512 = tu_edpt_packet_size(desc_ep) == 512; } +TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_is_opened(const tu_edpt_stream_t *s) { + return s->ep_addr != 0; +} + TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_close(tu_edpt_stream_t* s) { s->ep_addr = 0; } @@ -121,7 +125,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_clear(tu_edpt_stream_t* // Write to stream uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize); -// Start an usb transfer if endpoint is not busy +// Start an usb transfer if endpoint is not busy. Return number of queued bytes uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s); // Start an zero-length packet if needed @@ -151,20 +155,18 @@ void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_byt // Complete read transfer with provided buffer TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_read_xfer_complete_with_buf(tu_edpt_stream_t* s, const void * buf, uint32_t xferred_bytes) { +void tu_edpt_stream_read_xfer_complete_with_buf(tu_edpt_stream_t *s, const void *buf, uint32_t xferred_bytes) { if (0u != tu_fifo_depth(&s->ff)) { tu_fifo_write_n(&s->ff, buf, (uint16_t) xferred_bytes); } } // Get the number of bytes available for reading -TU_ATTR_ALWAYS_INLINE static inline -uint32_t tu_edpt_stream_read_available(tu_edpt_stream_t* s) { +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_edpt_stream_read_available(const tu_edpt_stream_t *s) { return (uint32_t) tu_fifo_count(&s->ff); } -TU_ATTR_ALWAYS_INLINE static inline -bool tu_edpt_stream_peek(tu_edpt_stream_t* s, uint8_t* ch) { +TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_peek(tu_edpt_stream_t *s, uint8_t *ch) { return tu_fifo_peek(&s->ff, ch); } diff --git a/src/tusb.c b/src/tusb.c index 7411f19df..b308e2915 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -424,7 +424,7 @@ uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s) { TU_VERIFY(stream_claim(hwid, s), 0); // Pull data from FIFO -> EP buf - uint16_t const count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); + const uint16_t count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); if (count > 0) { TU_ASSERT(stream_xfer(hwid, s, count), 0); @@ -437,7 +437,7 @@ uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s) { } } -uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t* s, void const* buffer, uint32_t bufsize) { +uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buffer, uint32_t bufsize) { TU_VERIFY(bufsize > 0); // TODO support ZLP if (0 == tu_fifo_depth(&s->ff)) { -- cgit v1.3.1 From f11adb02ebc0c594a7114b08585b8af18c3ee6d6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Nov 2025 21:22:25 +0700 Subject: migrate cdc device to use edpt stream API tu_edpt_stream_open() does not clear fifo, allow for persistent stream when disconnect/reconnect --- .clang-format | 7 +- .../net_lwip_webserver/src/usb_descriptors.c | 2 +- src/class/cdc/cdc_device.c | 393 +++++++++------------ src/class/midi/midi_device.c | 2 + src/class/vendor/vendor_device.c | 16 +- src/common/tusb_private.h | 7 +- src/tusb.c | 8 +- 7 files changed, 194 insertions(+), 241 deletions(-) (limited to 'src/tusb.c') diff --git a/.clang-format b/.clang-format index c278fec37..40d40f7e9 100644 --- a/.clang-format +++ b/.clang-format @@ -1,7 +1,7 @@ --- Language: Cpp BasedOnStyle: LLVM -AlignAfterOpenBracket: AlwaysBreak +AlignAfterOpenBracket: Align AlignConsecutiveAssignments: Enabled: true AcrossEmptyLines: false @@ -38,6 +38,7 @@ AllowShortEnumsOnASingleLine: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: Never AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true BreakBeforeBraces: Custom BraceWrapping: AfterCaseLabel: false @@ -57,8 +58,10 @@ BraceWrapping: SplitEmptyRecord: true SplitEmptyNamespace: true BracedInitializerIndentWidth: 2 +BreakBeforeBinaryOperators: None BreakConstructorInitializers: AfterColon BreakConstructorInitializersBeforeComma: false +ContinuationIndentWidth: 2 ColumnLimit: 120 ConstructorInitializerAllOnOneLineOrOnePerLine: false Cpp11BracedListStyle: true @@ -78,6 +81,8 @@ MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 2 NamespaceIndentation: All +PenaltyBreakBeforeFirstCallParameter: 1000000 +PenaltyBreakOpenParenthesis: 1000000 QualifierAlignment: Custom QualifierOrder: ['static', 'const', 'volatile', 'restrict', 'type'] ReflowComments: false diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index b49962d65..c976cb62b 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -270,7 +270,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_contro switch (request->bmRequestType_bit.type) { case TUSB_REQ_TYPE_VENDOR: - switch (request->bRequest) { //-V2520 //-V2659 + switch (request->bRequest) { case 1: if (request->wIndex == 7) { // Get Microsoft OS 2.0 compatible descriptor diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index b3253b141..92139b14e 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -48,28 +48,23 @@ typedef struct { uint8_t rhport; uint8_t itf_num; - uint8_t ep_in; - uint8_t ep_out; - uint8_t ep_notify; uint8_t line_state; // Bit 0: DTR, Bit 1: RTS /*------------- From this point, data is not cleared by bus reset -------------*/ - char wanted_char; TU_ATTR_ALIGNED(4) cdc_line_coding_t line_coding; + char wanted_char; - // FIFO - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - - uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE]; + struct { + tu_edpt_stream_t tx; + tu_edpt_stream_t rx; - OSAL_MUTEX_DEF(rx_ff_mutex); - OSAL_MUTEX_DEF(tx_ff_mutex); + uint8_t tx_ff_buf[CFG_TUD_CDC_TX_BUFSIZE]; + uint8_t rx_ff_buf[CFG_TUD_CDC_RX_BUFSIZE]; + } stream; } cdcd_interface_t; -#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char) +#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, line_coding) typedef struct { TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE); @@ -80,111 +75,102 @@ typedef struct { #endif } cdcd_epbuf_t; -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; -CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC]; - -static tud_cdc_configure_t _cdcd_cfg = TUD_CDC_CONFIGURE_DEFAULT(); - -static bool _prep_out_transaction(uint8_t itf) { - const uint8_t rhport = 0; - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; - - // Skip if usb is not ready yet - TU_VERIFY(tud_ready() && p_cdc->ep_out); - - uint16_t available = tu_fifo_remaining(&p_cdc->rx_ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= CFG_TUD_CDC_EP_BUFSIZE); - - // claim endpoint - TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_out)); - - // fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&p_cdc->rx_ff); - - if (available >= CFG_TUD_CDC_EP_BUFSIZE) { - return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE); - } else { - // Release endpoint since we don't make any transfer - usbd_edpt_release(p_cdc->rhport, p_cdc->ep_out); - return false; - } -} - //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ TU_ATTR_WEAK void tud_cdc_rx_cb(uint8_t itf) { - (void) itf; + (void)itf; } TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { - (void) itf; - (void) wanted_char; + (void)itf; + (void)wanted_char; } TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf) { - (void) itf; + (void)itf; } TU_ATTR_WEAK void tud_cdc_notify_complete_cb(uint8_t itf) { - (void) itf; + (void)itf; } TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { - (void) itf; - (void) dtr; - (void) rts; + (void)itf; + (void)dtr; + (void)rts; } -TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding) { - (void) itf; - (void) p_line_coding; +TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, const cdc_line_coding_t *p_line_coding) { + (void)itf; + (void)p_line_coding; } TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) { - (void) itf; - (void) duration_ms; + (void)itf; + (void)duration_ms; +} + +//--------------------------------------------------------------------+ +// INTERNAL OBJECT & FUNCTION DECLARATION +//--------------------------------------------------------------------+ +static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC]; +CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC]; +static tud_cdc_configure_t _cdcd_cfg = TUD_CDC_CONFIGURE_DEFAULT(); + +TU_ATTR_ALWAYS_INLINE static inline uint8_t find_cdc_itf(uint8_t ep_addr) { + for (uint8_t idx = 0; idx < CFG_TUD_CDC; idx++) { + const cdcd_interface_t *p_cdc = &_cdcd_itf[idx]; + if (ep_addr == p_cdc->stream.rx.ep_addr || ep_addr == p_cdc->stream.tx.ep_addr || + (ep_addr == p_cdc->ep_notify && ep_addr != 0)) { + return idx; + } + } + return TUSB_INDEX_INVALID_8; } //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg) { - TU_VERIFY(driver_cfg); + TU_VERIFY(driver_cfg != NULL); _cdcd_cfg = *driver_cfg; return true; } bool tud_cdc_n_ready(uint8_t itf) { - return tud_ready() && _cdcd_itf[itf].ep_in != 0 && _cdcd_itf[itf].ep_out != 0; + TU_VERIFY(itf < CFG_TUD_CDC); + TU_VERIFY(tud_ready()); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + + const bool in_opened = tu_edpt_stream_is_opened(&p_cdc->stream.tx); + const bool out_opened = tu_edpt_stream_is_opened(&p_cdc->stream.rx); + return in_opened && out_opened; } bool tud_cdc_n_connected(uint8_t itf) { + TU_VERIFY(itf < CFG_TUD_CDC); + TU_VERIFY(tud_ready()); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; // DTR (bit 0) active is considered as connected - return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0); + return tu_bit_test(p_cdc->line_state, 0); } uint8_t tud_cdc_n_get_line_state(uint8_t itf) { + TU_VERIFY(itf < CFG_TUD_CDC, 0); return _cdcd_itf[itf].line_state; } -void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding) { +void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t *coding) { + TU_VERIFY(itf < CFG_TUD_CDC, ); (*coding) = _cdcd_itf[itf].line_coding; } #if CFG_TUD_CDC_NOTIFY bool tud_cdc_n_notify_uart_state (uint8_t itf, const cdc_notify_uart_state_t *state) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; + TU_VERIFY(itf < CFG_TUD_CDC); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[itf]; TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0); TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify)); @@ -200,8 +186,9 @@ bool tud_cdc_n_notify_uart_state (uint8_t itf, const cdc_notify_uart_state_t *st } bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; + TU_VERIFY(itf < CFG_TUD_CDC); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[itf]; TU_VERIFY(tud_ready() && p_cdc->ep_notify != 0); TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify)); @@ -218,6 +205,7 @@ bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed #endif void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) { + TU_VERIFY(itf < CFG_TUD_CDC, ); _cdcd_itf[itf].wanted_char = wanted; } @@ -225,77 +213,55 @@ void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) { // READ API //--------------------------------------------------------------------+ uint32_t tud_cdc_n_available(uint8_t itf) { - return tu_fifo_count(&_cdcd_itf[itf].rx_ff); + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_read_available(&p_cdc->stream.rx); } uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); - _prep_out_transaction(itf); - return num_read; + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_read(p_cdc->rhport, &p_cdc->stream.rx, buffer, bufsize); } -bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) { - return tu_fifo_peek(&_cdcd_itf[itf].rx_ff, chr); +bool tud_cdc_n_peek(uint8_t itf, uint8_t *chr) { + TU_VERIFY(itf < CFG_TUD_CDC); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_peek(&p_cdc->stream.rx, chr); } void tud_cdc_n_read_flush(uint8_t itf) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - tu_fifo_clear(&p_cdc->rx_ff); - _prep_out_transaction(itf); + TU_VERIFY(itf < CFG_TUD_CDC, ); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + tu_edpt_stream_clear(&p_cdc->stream.rx); + tu_edpt_stream_read_xfer(p_cdc->rhport, &p_cdc->stream.rx); } //--------------------------------------------------------------------+ // WRITE API //--------------------------------------------------------------------+ uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - uint16_t wr_count = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX)); - - // flush if queue more than packet size - if (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE - #if CFG_TUD_CDC_TX_BUFSIZE < BULK_PACKET_SIZE - || tu_fifo_full(&p_cdc->tx_ff) // check full if fifo size is less than packet size - #endif - ) { - tud_cdc_n_write_flush(itf); - } - - return wr_count; + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_write(p_cdc->rhport, &p_cdc->stream.tx, buffer, bufsize); } uint32_t tud_cdc_n_write_flush(uint8_t itf) { - cdcd_interface_t* p_cdc = &_cdcd_itf[itf]; - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; - TU_VERIFY(tud_ready(), 0); // Skip if usb is not ready yet - - // No data to send - if (0 == tu_fifo_count(&p_cdc->tx_ff)) { - return 0; - } - - TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_in), 0); // Claim the endpoint - - // Pull data from FIFO - const uint16_t count = tu_fifo_read_n(&p_cdc->tx_ff, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE); - - if (count > 0) { - TU_ASSERT(usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_in, p_epbuf->epin, count), 0); - return count; - } else { - // Release endpoint since we don't make any transfer - // Note: data is dropped if terminal is not connected - usbd_edpt_release(p_cdc->rhport, p_cdc->ep_in); - return 0; - } + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_write_xfer(p_cdc->rhport, &p_cdc->stream.tx); } uint32_t tud_cdc_n_write_available(uint8_t itf) { - return tu_fifo_remaining(&_cdcd_itf[itf].tx_ff); + TU_VERIFY(itf < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_write_available(p_cdc->rhport, &p_cdc->stream.tx); } bool tud_cdc_n_write_clear(uint8_t itf) { - return tu_fifo_clear(&_cdcd_itf[itf].tx_ff); + TU_VERIFY(itf < CFG_TUD_CDC); + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + return tu_edpt_stream_clear(&p_cdc->stream.tx); } //--------------------------------------------------------------------+ @@ -304,7 +270,8 @@ bool tud_cdc_n_write_clear(uint8_t itf) { void cdcd_init(void) { tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { - cdcd_interface_t* p_cdc = &_cdcd_itf[i]; + cdcd_interface_t *p_cdc = &_cdcd_itf[i]; + cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[i]; p_cdc->wanted_char = (char) -1; @@ -314,44 +281,23 @@ void cdcd_init(void) { p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; - // Config RX fifo - tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false); + tu_edpt_stream_init(&p_cdc->stream.rx, false, false, false, p_cdc->stream.rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, + p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE); // TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not // know if data is actually polled by terminal. This way the most current data is prioritized. // Default: is overwritable - tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, _cdcd_cfg.tx_overwritabe_if_not_connected); - - #if OSAL_MUTEX_REQUIRED - osal_mutex_t mutex_rd = osal_mutex_create(&p_cdc->rx_ff_mutex); - osal_mutex_t mutex_wr = osal_mutex_create(&p_cdc->tx_ff_mutex); - TU_ASSERT(mutex_rd != NULL && mutex_wr != NULL, ); - - tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, mutex_rd); - tu_fifo_config_mutex(&p_cdc->tx_ff, mutex_wr, NULL); - #endif + tu_edpt_stream_init(&p_cdc->stream.tx, false, true, _cdcd_cfg.tx_overwritabe_if_not_connected, + p_cdc->stream.tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE); } } bool cdcd_deinit(void) { - #if OSAL_MUTEX_REQUIRED for(uint8_t i=0; irx_ff.mutex_rd; - const osal_mutex_t mutex_wr = p_cdc->tx_ff.mutex_wr; - - if (mutex_rd != NULL) { - osal_mutex_delete(mutex_rd); - tu_fifo_config_mutex(&p_cdc->rx_ff, NULL, NULL); - } - - if (mutex_wr != NULL) { - osal_mutex_delete(mutex_wr); - tu_fifo_config_mutex(&p_cdc->tx_ff, NULL, NULL); - } + tu_edpt_stream_deinit(&p_cdc->stream.rx); + tu_edpt_stream_deinit(&p_cdc->stream.tx); } - #endif - return true; } @@ -360,74 +306,85 @@ void cdcd_reset(uint8_t rhport) { for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { cdcd_interface_t* p_cdc = &_cdcd_itf[i]; - tu_memclr(p_cdc, ITF_MEM_RESET_SIZE); - if (!_cdcd_cfg.rx_persistent) { - tu_fifo_clear(&p_cdc->rx_ff); - } - if (!_cdcd_cfg.tx_persistent) { - tu_fifo_clear(&p_cdc->tx_ff); - } - tu_fifo_set_overwritable(&p_cdc->tx_ff, _cdcd_cfg.tx_overwritabe_if_not_connected); + + tu_fifo_set_overwritable(&p_cdc->stream.tx.ff, _cdcd_cfg.tx_overwritabe_if_not_connected); // // back to default + tu_edpt_stream_close(&p_cdc->stream.rx); + tu_edpt_stream_close(&p_cdc->stream.tx); } } uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16_t max_len) { // Only support ACM subclass - TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0); + TU_VERIFY(TUSB_CLASS_CDC == itf_desc->bInterfaceClass && + CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, + 0); - // Find available interface - cdcd_interface_t* p_cdc; - uint8_t cdc_id; - for (cdc_id = 0; cdc_id < CFG_TUD_CDC; cdc_id++) { - p_cdc = &_cdcd_itf[cdc_id]; - if (p_cdc->ep_in == 0) { - break; - } - } + const uint8_t cdc_id = find_cdc_itf(0); // Find available interface TU_ASSERT(cdc_id < CFG_TUD_CDC, 0); + cdcd_interface_t *p_cdc = &_cdcd_itf[cdc_id]; //------------- Control Interface -------------// p_cdc->rhport = rhport; p_cdc->itf_num = itf_desc->bInterfaceNumber; - uint16_t drv_len = sizeof(tusb_desc_interface_t); - const uint8_t* p_desc = tu_desc_next(itf_desc); + const uint8_t *p_desc = (const uint8_t *)itf_desc; + const uint8_t *desc_end = p_desc + max_len; - // Communication Functional Descriptors - while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) { - drv_len += tu_desc_len(p_desc); + // Skip all class-specific descriptor + p_desc = tu_desc_next(itf_desc); + while (tu_desc_in_bounds(p_desc, desc_end) && TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc)) { p_desc = tu_desc_next(p_desc); } + // notification endpoint (optional) if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { - // notification endpoint const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); p_cdc->ep_notify = desc_ep->bEndpointAddress; - drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - //------------- Data Interface (if any) -------------// - if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((const tusb_desc_interface_t*) p_desc)->bInterfaceClass)) { - // next to endpoint descriptor - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + //------------- Data Interface (optional) -------------// + if (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) { + const tusb_desc_interface_t *data_itf_desc = (const tusb_desc_interface_t *)p_desc; + if (TUSB_CLASS_CDC_DATA == data_itf_desc->bInterfaceClass) { + for (uint8_t e = 0; e < data_itf_desc->bNumEndpoints; e++) { + if (!tu_desc_in_bounds(p_desc, desc_end)) { + break; + } + p_desc = tu_desc_next(p_desc); - // Open endpoint pair - TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &p_cdc->ep_out, &p_cdc->ep_in), 0); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); - drv_len += 2 * sizeof(tusb_desc_endpoint_t); - } + TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { + tu_edpt_stream_t *stream_tx = &p_cdc->stream.tx; + tu_edpt_stream_open(stream_tx, desc_ep); + + if (_cdcd_cfg.tx_persistent) { + tu_edpt_stream_write_xfer(rhport, stream_tx); // flush pending data + } else { + tu_edpt_stream_clear(stream_tx); + } + } else { + tu_edpt_stream_t *stream_rx = &p_cdc->stream.rx; - // Prepare for incoming data - _prep_out_transaction(cdc_id); + tu_edpt_stream_open(stream_rx, desc_ep); + if (!_cdcd_cfg.rx_persistent) { + tu_edpt_stream_clear(stream_rx); + } + TU_ASSERT(tu_edpt_stream_read_xfer(rhport, stream_rx) > 0, 0); // prepare for incoming data + } + } - return drv_len; + p_desc = tu_desc_next(p_desc); + } + } + + return p_desc - (const uint8_t *)itf_desc; } // Invoked when a control transfer occurred on an interface of this class @@ -449,7 +406,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ } TU_VERIFY(itf < CFG_TUD_CDC); - switch (request->bRequest) { //-V2520 //-V2659 + switch (request->bRequest) { case CDC_REQUEST_SET_LINE_CODING: if (stage == CONTROL_STAGE_SETUP) { TU_LOG_DRV(" Set Line Coding\r\n"); @@ -484,15 +441,13 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ // If enabled: fifo overwriting is disabled if DTR bit is set and vice versa if (_cdcd_cfg.tx_overwritabe_if_not_connected) { - tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr); + tu_fifo_set_overwritable(&p_cdc->stream.tx.ff, !dtr); } else { - tu_fifo_set_overwritable(&p_cdc->tx_ff, false); + tu_fifo_set_overwritable(&p_cdc->stream.tx.ff, false); } TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts); - - // Invoke callback - tud_cdc_line_state_cb(itf, dtr, rts); + tud_cdc_line_state_cb(itf, dtr, rts); // invoke callback } else { // nothing to do } @@ -507,7 +462,6 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ } else { // nothing to do } - break; default: @@ -518,58 +472,45 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ } bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) result; + (void)result; - uint8_t itf; - cdcd_interface_t* p_cdc; - - // Identify which interface to use - for (itf = 0; itf < CFG_TUD_CDC; itf++) { - p_cdc = &_cdcd_itf[itf]; - if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in) || (ep_addr == p_cdc->ep_notify)) { - break; - } - } + uint8_t itf = find_cdc_itf(ep_addr); TU_ASSERT(itf < CFG_TUD_CDC); - cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf]; + cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + tu_edpt_stream_t *stream_rx = &p_cdc->stream.rx; + tu_edpt_stream_t *stream_tx = &p_cdc->stream.tx; - // Received new data - if (ep_addr == p_cdc->ep_out) { - tu_fifo_write_n(&p_cdc->rx_ff, p_epbuf->epout, (uint16_t) xferred_bytes); + // Received new data, move to fifo + if (ep_addr == stream_rx->ep_addr) { + tu_edpt_stream_read_xfer_complete(stream_rx, xferred_bytes); - // Check for wanted char and invoke callback if needed - if (((signed char) p_cdc->wanted_char) != -1) { + // Check for wanted char and invoke wanted callback (multiple times if multiple wanted received) + if (((signed char)p_cdc->wanted_char) != -1) { for (uint32_t i = 0; i < xferred_bytes; i++) { - if ((p_cdc->wanted_char == (char) p_epbuf->epout[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) { + if ((p_cdc->wanted_char == (char)stream_rx->ep_buf[i]) && !tu_edpt_stream_empty(stream_rx)) { tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char); } } } - // invoke receive callback (if there is still data) - if (!tu_fifo_empty(&p_cdc->rx_ff)) { + // invoke receive callback if there is still data + if (!tu_edpt_stream_empty(stream_rx)) { tud_cdc_rx_cb(itf); } - // prepare for OUT transaction - _prep_out_transaction(itf); + tu_edpt_stream_read_xfer(rhport, stream_rx); // prepare for more data } // Data sent to host, we continue to fetch from tx fifo to send. // Note: This will cause incorrect baudrate set in line coding. // Though maybe the baudrate is not really important !!! - if (ep_addr == p_cdc->ep_in) { + if (ep_addr == stream_tx->ep_addr) { // invoke transmit callback to possibly refill tx fifo tud_cdc_tx_complete_cb(itf); - if (0 == tud_cdc_n_write_flush(itf)) { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP Packet size and not zero - if (0 == tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes > 0 && (0 == (xferred_bytes & (BULK_PACKET_SIZE - 1)))) { - if (usbd_edpt_claim(rhport, p_cdc->ep_in)) { - TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0)); - } - } + if (0 == tu_edpt_stream_write_xfer(rhport, stream_tx)) { + // If there is no data left, a ZLP should be sent if needed + tu_edpt_stream_write_zlp_if_needed(rhport, stream_tx, xferred_bytes); } } diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index f065e486a..79e7dfa71 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -405,8 +405,10 @@ uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uint1 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { tu_edpt_stream_open(&p_midi->ep_stream.tx, desc_ep); + tu_edpt_stream_clear(&p_midi->ep_stream.tx); } else { tu_edpt_stream_open(&p_midi->ep_stream.rx, desc_ep); + tu_edpt_stream_clear(&p_midi->ep_stream.rx); TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_midi->ep_stream.rx) > 0, 0); // prepare to receive data } diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index c916ebe47..7da4d2239 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -234,16 +234,18 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); - // open endpoint stream, skip if already opened + // open endpoint stream, skip if already opened (multiple IN/OUT endpoints) if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { - if (p_vendor->tx.stream.ep_addr == 0) { - tu_edpt_stream_open(&p_vendor->tx.stream, desc_ep); - tud_vendor_n_write_flush(itf); + tu_edpt_stream_t *stream_tx = &p_vendor->tx.stream; + if (stream_tx->ep_addr == 0) { + tu_edpt_stream_open(stream_tx, desc_ep); + tu_edpt_stream_write_xfer(rhport, stream_tx); // flush pending data } } else { - if (p_vendor->rx.stream.ep_addr == 0) { - tu_edpt_stream_open(&p_vendor->rx.stream, desc_ep); - TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_vendor->rx.stream) > 0, 0); // prepare for incoming data + tu_edpt_stream_t *stream_rx = &p_vendor->rx.stream; + if (stream_rx->ep_addr == 0) { + tu_edpt_stream_open(stream_rx, desc_ep); + TU_ASSERT(tu_edpt_stream_read_xfer(rhport, stream_rx) > 0, 0); // prepare for incoming data } } } diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 367209e57..f82f87b6f 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -100,7 +100,6 @@ bool tu_edpt_stream_deinit(tu_edpt_stream_t* s); // Open an stream for an endpoint TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t* s, tusb_desc_endpoint_t const *desc_ep) { - tu_fifo_clear(&s->ff); s->ep_addr = desc_ep->bEndpointAddress; s->is_mps512 = tu_edpt_packet_size(desc_ep) == 512; } @@ -113,11 +112,15 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_close(tu_edpt_stream_t* s->ep_addr = 0; } -// Clear fifo TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_clear(tu_edpt_stream_t* s) { return tu_fifo_clear(&s->ff); } +TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_empty(tu_edpt_stream_t *s) { + return tu_fifo_empty(&s->ff); +} + + //--------------------------------------------------------------------+ // Stream Write //--------------------------------------------------------------------+ diff --git a/src/tusb.c b/src/tusb.c index b308e2915..df33f2680 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -354,8 +354,8 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove return true; } -bool tu_edpt_stream_deinit(tu_edpt_stream_t* s) { - (void) s; +bool tu_edpt_stream_deinit(tu_edpt_stream_t *s) { + (void)s; #if OSAL_MUTEX_REQUIRED if (s->ff.mutex_wr) { osal_mutex_delete(s->ff.mutex_wr); @@ -363,7 +363,7 @@ bool tu_edpt_stream_deinit(tu_edpt_stream_t* s) { if (s->ff.mutex_rd) { osal_mutex_delete(s->ff.mutex_rd); } -#endif + #endif return true; } @@ -412,7 +412,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_release(uint8_t hwid, tu_edpt_st bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t* s, uint32_t last_xferred_bytes) { // ZLP condition: no pending data, last transferred bytes is multiple of packet size const uint16_t mps = s->is_mps512 ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; - TU_VERIFY(!tu_fifo_count(&s->ff) && last_xferred_bytes > 0 && (0 == (last_xferred_bytes & (mps - 1)))); + TU_VERIFY(tu_fifo_empty(&s->ff) && last_xferred_bytes > 0 && (0 == (last_xferred_bytes & (mps - 1)))); TU_VERIFY(stream_claim(hwid, s)); TU_ASSERT(stream_xfer(hwid, s, 0)); return true; -- cgit v1.3.1 From 397a3af8afc4bc5460572da4a40629684dfa788c Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Nov 2025 12:02:02 +0700 Subject: clear endpoint stream when open for cdc_host and midi_host --- src/class/cdc/cdc_device.c | 15 ++++++------- src/class/cdc/cdc_host.c | 50 ++++++++++++++++++-------------------------- src/class/midi/midi_device.c | 14 +++++++------ src/class/midi/midi_host.c | 48 ++++++++++++++++++++++-------------------- src/common/tusb_common.h | 2 +- src/common/tusb_private.h | 1 - src/tusb.c | 2 +- 7 files changed, 61 insertions(+), 71 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 92139b14e..80fa81d99 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -141,7 +141,7 @@ bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg) { bool tud_cdc_n_ready(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_CDC); TU_VERIFY(tud_ready()); - cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; + const cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; const bool in_opened = tu_edpt_stream_is_opened(&p_cdc->stream.tx); const bool out_opened = tu_edpt_stream_is_opened(&p_cdc->stream.rx); @@ -151,9 +151,8 @@ bool tud_cdc_n_ready(uint8_t itf) { bool tud_cdc_n_connected(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_CDC); TU_VERIFY(tud_ready()); - cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; // DTR (bit 0) active is considered as connected - return tu_bit_test(p_cdc->line_state, 0); + return tu_bit_test(_cdcd_itf[itf].line_state, 0); } uint8_t tud_cdc_n_get_line_state(uint8_t itf) { @@ -214,8 +213,7 @@ void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) { //--------------------------------------------------------------------+ uint32_t tud_cdc_n_available(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_CDC, 0); - cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; - return tu_edpt_stream_read_available(&p_cdc->stream.rx); + return tu_edpt_stream_read_available(&_cdcd_itf[itf].stream.rx); } uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { @@ -226,8 +224,7 @@ uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { bool tud_cdc_n_peek(uint8_t itf, uint8_t *chr) { TU_VERIFY(itf < CFG_TUD_CDC); - cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; - return tu_edpt_stream_peek(&p_cdc->stream.rx, chr); + return tu_edpt_stream_peek(&_cdcd_itf[itf].stream.rx, chr); } void tud_cdc_n_read_flush(uint8_t itf) { @@ -362,8 +359,8 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16 TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0); if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { tu_edpt_stream_t *stream_tx = &p_cdc->stream.tx; - tu_edpt_stream_open(stream_tx, desc_ep); + tu_edpt_stream_open(stream_tx, desc_ep); if (_cdcd_cfg.tx_persistent) { tu_edpt_stream_write_xfer(rhport, stream_tx); // flush pending data } else { @@ -384,7 +381,7 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16 } } - return p_desc - (const uint8_t *)itf_desc; + return (uint16_t)(p_desc - (const uint8_t *)itf_desc); } // Invoked when a control transfer occurred on an interface of this class diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 7fdf0a7b9..35717ddf6 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -298,6 +298,7 @@ TU_VERIFY_STATIC(TU_ARRAY_SIZE(serial_drivers) == SERIAL_DRIVER_COUNT, "Serial d //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ +static bool open_ep_stream_pair(cdch_interface_t *p_cdc, const tusb_desc_endpoint_t *desc_ep); TU_ATTR_ALWAYS_INLINE static inline cdch_interface_t * get_itf(uint8_t idx) { TU_ASSERT(idx < CFG_TUH_CDC, NULL); @@ -364,7 +365,7 @@ static cdch_interface_t* get_itf_by_xfer(const tuh_xfer_t * xfer) { #endif default: - break; + break; // unknown driver } } } @@ -389,8 +390,6 @@ static cdch_interface_t * make_new_itf(uint8_t daddr, tusb_desc_interface_t cons return NULL; } -static bool open_ep_stream_pair(cdch_interface_t * p_cdc , tusb_desc_endpoint_t const *desc_ep); - //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ @@ -519,7 +518,7 @@ bool tuh_cdc_read_clear (uint8_t idx) { TU_VERIFY(p_cdc); bool ret = tu_edpt_stream_clear(&p_cdc->stream.rx); - tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); + (void)tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); return ret; } @@ -648,13 +647,10 @@ bool cdch_init(void) { for (size_t i = 0; i < CFG_TUH_CDC; i++) { cdch_interface_t *p_cdc = &cdch_data[i]; cdch_epbuf_t *epbuf = &cdch_epbuf[i]; - tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, - p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, - epbuf->tx, CFG_TUH_CDC_TX_EPSIZE); - - tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, - p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE, - epbuf->rx, CFG_TUH_CDC_RX_EPSIZE); + TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, + epbuf->tx, CFG_TUH_CDC_TX_EPSIZE)); + TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, p_cdc->stream.rx_ff_buf, + CFG_TUH_CDC_RX_BUFSIZE, epbuf->rx, CFG_TUH_CDC_RX_EPSIZE)); } return true; @@ -663,8 +659,8 @@ bool cdch_init(void) { bool cdch_deinit(void) { for (size_t i = 0; i < CFG_TUH_CDC; i++) { cdch_interface_t *p_cdc = &cdch_data[i]; - tu_edpt_stream_deinit(&p_cdc->stream.tx); - tu_edpt_stream_deinit(&p_cdc->stream.rx); + (void)tu_edpt_stream_deinit(&p_cdc->stream.tx); + (void)tu_edpt_stream_deinit(&p_cdc->stream.rx); } return true; } @@ -674,11 +670,9 @@ void cdch_close(uint8_t daddr) { cdch_interface_t *p_cdc = &cdch_data[idx]; if (p_cdc->daddr == daddr) { TU_LOG_CDC(p_cdc, "close"); + tuh_cdc_umount_cb(idx); // invoke callback - // Invoke application callback - tuh_cdc_umount_cb(idx); - - p_cdc->daddr = 0; + p_cdc->daddr = 0; p_cdc->bInterfaceNumber = 0; p_cdc->mounted = false; tu_edpt_stream_close(&p_cdc->stream.tx); @@ -696,13 +690,12 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t TU_ASSERT(p_cdc); if (ep_addr == p_cdc->stream.tx.ep_addr) { - // invoke tx complete callback to possibly refill tx fifo - tuh_cdc_tx_complete_cb(idx); + tuh_cdc_tx_complete_cb(idx); // invoke transmit complete callback if (0 == tu_edpt_stream_write_xfer(daddr, &p_cdc->stream.tx)) { // If there is no data left, a ZLP should be sent if: // - xferred_bytes is multiple of EP Packet size and not zero - tu_edpt_stream_write_zlp_if_needed(daddr, &p_cdc->stream.tx, xferred_bytes); + (void)tu_edpt_stream_write_zlp_if_needed(daddr, &p_cdc->stream.tx, xferred_bytes); } } else if (ep_addr == p_cdc->stream.rx.ep_addr) { #if CFG_TUH_CDC_FTDI @@ -718,7 +711,6 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t #endif { tu_edpt_stream_read_xfer_complete(&p_cdc->stream.rx, xferred_bytes); - tuh_cdc_rx_cb(idx); // invoke receive callback } @@ -727,7 +719,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t } else if (ep_addr == p_cdc->ep_notif) { // TODO handle notification endpoint } else { - TU_ASSERT(false); + return false; } return true; @@ -736,20 +728,17 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t //--------------------------------------------------------------------+ // Enumeration //--------------------------------------------------------------------+ - static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t const *desc_ep) { for (size_t i = 0; i < 2; i++) { TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep)); + tu_edpt_stream_t *stream = + (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) ? &p_cdc->stream.rx : &p_cdc->stream.tx; + tu_edpt_stream_open(stream, desc_ep); + tu_edpt_stream_clear(stream); - if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { - tu_edpt_stream_open(&p_cdc->stream.rx, desc_ep); - } else { - tu_edpt_stream_open(&p_cdc->stream.tx, desc_ep); - } - - desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(desc_ep); + desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(desc_ep); } return true; @@ -832,6 +821,7 @@ static void cdch_process_set_config(tuh_xfer_t *xfer) { } } +// return false if there is no active transfer static bool set_line_state_on_enum(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { enum { ENUM_SET_LINE_CODING = 0, diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 79e7dfa71..b20903d68 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -404,15 +404,17 @@ uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uint1 const uint8_t ep_addr = ((const tusb_desc_endpoint_t *)p_desc)->bEndpointAddress; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { - tu_edpt_stream_open(&p_midi->ep_stream.tx, desc_ep); - tu_edpt_stream_clear(&p_midi->ep_stream.tx); + tu_edpt_stream_t *stream_tx = &p_midi->ep_stream.tx; + tu_edpt_stream_open(stream_tx, desc_ep); + tu_edpt_stream_clear(stream_tx); } else { - tu_edpt_stream_open(&p_midi->ep_stream.rx, desc_ep); - tu_edpt_stream_clear(&p_midi->ep_stream.rx); - TU_ASSERT(tu_edpt_stream_read_xfer(rhport, &p_midi->ep_stream.rx) > 0, 0); // prepare to receive data + tu_edpt_stream_t *stream_rx = &p_midi->ep_stream.rx; + tu_edpt_stream_open(stream_rx, desc_ep); + tu_edpt_stream_clear(stream_rx); + TU_ASSERT(tu_edpt_stream_read_xfer(rhport, stream_rx) > 0, 0); // prepare to receive data } - p_desc = tu_desc_next(p_desc); // skip CS Endpoint descriptor + p_desc = tu_desc_next(p_desc); // skip CS Endpoint descriptor found_ep++; } diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 8b78fe945..07062875c 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -59,9 +59,6 @@ typedef struct { uint8_t iInterface; uint8_t itf_count; // number of interface including Audio Control + MIDI streaming - uint8_t ep_in; // IN endpoint address - uint8_t ep_out; // OUT endpoint address - uint8_t rx_cable_count; // IN endpoint CS descriptor bNumEmbMIDIJack value uint8_t tx_cable_count; // OUT endpoint CS descriptor bNumEmbMIDIJack value @@ -147,8 +144,6 @@ void midih_close(uint8_t daddr) { TU_LOG_DRV(" MIDI close addr = %u index = %u\r\n", daddr, idx); tuh_midi_umount_cb(idx); - p_midi->ep_in = 0; - p_midi->ep_out = 0; p_midi->bInterfaceNumber = 0; p_midi->rx_cable_count = 0; p_midi->tx_cable_count = 0; @@ -169,23 +164,25 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint const uint8_t idx = get_idx_by_ep_addr(dev_addr, ep_addr); TU_VERIFY(idx < CFG_TUH_MIDI); midih_interface_t *p_midi = &_midi_host[idx]; + tu_edpt_stream_t *ep_str_rx = &p_midi->ep_stream.rx; + tu_edpt_stream_t *ep_str_tx = &p_midi->ep_stream.tx; - if (ep_addr == p_midi->ep_stream.rx.ep_addr) { + if (ep_addr == ep_str_rx->ep_addr) { // receive new data, put it into FIFO and invoke callback if available // Note: some devices send back all zero packets even if there is no data ready - if (xferred_bytes && !tu_mem_is_zero(p_midi->ep_stream.rx.ep_buf, xferred_bytes)) { - tu_edpt_stream_read_xfer_complete(&p_midi->ep_stream.rx, xferred_bytes); + if (xferred_bytes && !tu_mem_is_zero(ep_str_rx->ep_buf, xferred_bytes)) { + tu_edpt_stream_read_xfer_complete(ep_str_rx, xferred_bytes); tuh_midi_rx_cb(idx, xferred_bytes); } - tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for next transfer - } else if (ep_addr == p_midi->ep_stream.tx.ep_addr) { + tu_edpt_stream_read_xfer(dev_addr, ep_str_rx); // prepare for next transfer + } else if (ep_addr == ep_str_tx->ep_addr) { tuh_midi_tx_cb(idx, xferred_bytes); - if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi->ep_stream.tx)) { + if (0 == tu_edpt_stream_write_xfer(dev_addr, ep_str_tx)) { // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - tu_edpt_stream_write_zlp_if_needed(dev_addr, &p_midi->ep_stream.tx, xferred_bytes); + tu_edpt_stream_write_zlp_if_needed(dev_addr, ep_str_tx, xferred_bytes); } } @@ -295,21 +292,20 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d const midi_desc_cs_endpoint_t *p_csep = (const midi_desc_cs_endpoint_t *) p_desc; TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); + tu_edpt_stream_t *ep_stream; if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { - p_midi->ep_out = p_ep->bEndpointAddress; p_midi->tx_cable_count = p_csep->bNumEmbMIDIJack; desc_cb.desc_epout = p_ep; - - TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); - tu_edpt_stream_open(&p_midi->ep_stream.tx, p_ep); + ep_stream = &p_midi->ep_stream.tx; } else { - p_midi->ep_in = p_ep->bEndpointAddress; p_midi->rx_cable_count = p_csep->bNumEmbMIDIJack; - desc_cb.desc_epin = p_ep; - - TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); - tu_edpt_stream_open(&p_midi->ep_stream.rx, p_ep); + desc_cb.desc_epin = p_ep; + ep_stream = &p_midi->ep_stream.rx; } + TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); + tu_edpt_stream_open(ep_stream, p_ep); + tu_edpt_stream_clear(ep_stream); + break; } @@ -379,8 +375,14 @@ bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { desc->bDescriptorType = TUSB_DESC_INTERFACE; desc->bInterfaceNumber = p_midi->bInterfaceNumber; - desc->bAlternateSetting = 0; - desc->bNumEndpoints = (uint8_t)((p_midi->ep_in != 0 ? 1:0) + (p_midi->ep_out != 0 ? 1:0)); + desc->bAlternateSetting = 0; + desc->bNumEndpoints = 0; + if (tu_edpt_stream_is_opened(&p_midi->ep_stream.tx)) { + desc->bNumEndpoints++; + } + if (tu_edpt_stream_is_opened(&p_midi->ep_stream.rx)) { + desc->bNumEndpoints++; + } desc->bInterfaceClass = TUSB_CLASS_AUDIO; desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; desc->bInterfaceProtocol = 0; diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 7aa42a2d7..f377d5272 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -354,7 +354,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE]; } -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_in_bounds(uint8_t const* p_desc, uint8_t const* desc_end) { +TU_ATTR_ALWAYS_INLINE static inline bool tu_desc_in_bounds(const uint8_t *p_desc, const uint8_t *desc_end) { if (p_desc >= desc_end) { return false; } diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index f82f87b6f..be1264a71 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -120,7 +120,6 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_empty(tu_edpt_stream_t * return tu_fifo_empty(&s->ff); } - //--------------------------------------------------------------------+ // Stream Write //--------------------------------------------------------------------+ diff --git a/src/tusb.c b/src/tusb.c index df33f2680..6fb5309ab 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -517,7 +517,7 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) { } uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) { - uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t) bufsize); + const uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize); tu_edpt_stream_read_xfer(hwid, s); return num_read; } -- cgit v1.3.1 From c9b623aa63d24d58a7a5e55dd296afd1261b2ab8 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 21 Nov 2025 17:02:56 +0700 Subject: edpt stream support xfer_fifo for device CFG_TUD_EDPT_DEDICATED_HWFIFO cdc device omit ep buffer when hwfifo is supported --- docs/info/changelog.rst | 2 +- src/class/cdc/cdc_device.c | 18 ++++++++++++++---- src/common/tusb_fifo.h | 4 ++++ src/common/tusb_private.h | 6 +++--- src/device/usbd.c | 11 ++++++++++- src/tusb.c | 22 ++++++++++++++++------ src/tusb_option.h | 16 ++++++++++------ 7 files changed, 58 insertions(+), 21 deletions(-) (limited to 'src/tusb.c') diff --git a/docs/info/changelog.rst b/docs/info/changelog.rst index df23ce7d8..35c8515cc 100644 --- a/docs/info/changelog.rst +++ b/docs/info/changelog.rst @@ -5,7 +5,7 @@ Changelog 0.20.0 ====== -*November 19, 2024* +*November 19, 2025* General ------- diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 9e62c6509..a11de2f91 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -67,8 +67,11 @@ typedef struct { #define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, line_coding) typedef struct { + // Don't use local EP buffer if dedicated FIFO is supported + #if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE); TUD_EPBUF_DEF(epin, CFG_TUD_CDC_EP_BUFSIZE); + #endif #if CFG_TUD_CDC_NOTIFY TUD_EPBUF_TYPE_DEF(cdc_notify_msg_t, epnotify); @@ -268,8 +271,6 @@ void cdcd_init(void) { tu_memclr(_cdcd_itf, sizeof(_cdcd_itf)); for (uint8_t i = 0; i < CFG_TUD_CDC; i++) { cdcd_interface_t *p_cdc = &_cdcd_itf[i]; - cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[i]; - p_cdc->wanted_char = (char) -1; // default line coding is : stop bit = 1, parity = none, data bits = 8 @@ -278,14 +279,23 @@ void cdcd_init(void) { p_cdc->line_coding.parity = 0; p_cdc->line_coding.data_bits = 8; + #if CFG_TUD_EDPT_DEDICATED_HWFIFO + uint8_t *epout_buf = NULL; + uint8_t *epin_buf = NULL; + #else + cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[i]; + uint8_t *epout_buf = p_epbuf->epout; + uint8_t *epin_buf = p_epbuf->epin; + #endif + tu_edpt_stream_init(&p_cdc->stream.rx, false, false, false, p_cdc->stream.rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, - p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE); + epout_buf, CFG_TUD_CDC_EP_BUFSIZE); // TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not // know if data is actually polled by terminal. This way the most current data is prioritized. // Default: is overwritable tu_edpt_stream_init(&p_cdc->stream.tx, false, true, _cdcd_cfg.tx_overwritabe_if_not_connected, - p_cdc->stream.tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, p_epbuf->epin, CFG_TUD_CDC_EP_BUFSIZE); + p_cdc->stream.tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, epin_buf, CFG_TUD_CDC_EP_BUFSIZE); } } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index c16216606..0b8e83760 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -48,6 +48,10 @@ extern "C" { // for OS None, we don't get preempted #define CFG_FIFO_MUTEX OSAL_MUTEX_REQUIRED +#if CFG_TUD_EDPT_DEDICATED_HWFIFO || CFG_TUH_EDPT_DEDICATED_HWFIFO + #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32 +#endif + /* Write/Read index is always in the range of: * 0 .. 2*depth-1 * The extra window allow us to determine the fifo state of empty or full with only 2 indices diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index be1264a71..48fd1d6d2 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -60,7 +60,7 @@ typedef struct { uint8_t ep_addr; uint16_t ep_bufsize; - uint8_t* ep_buf; // TODO xfer_fifo can skip this buffer + uint8_t *ep_buf; // set to NULL to use xfer_fifo when CFG_TUD_EDPT_DEDICATED_HWFIFO = 1 tu_fifo_t ff; // mutex: read if rx, otherwise write @@ -98,7 +98,7 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove // Deinit an endpoint stream bool tu_edpt_stream_deinit(tu_edpt_stream_t* s); -// Open an stream for an endpoint +// Open an endpoint stream TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t* s, tusb_desc_endpoint_t const *desc_ep) { s->ep_addr = desc_ep->bEndpointAddress; s->is_mps512 = tu_edpt_packet_size(desc_ep) == 512; @@ -150,7 +150,7 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s); // Complete read transfer by writing EP -> FIFO. Must be called in the transfer complete callback TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) { - if (0u != tu_fifo_depth(&s->ff)) { + if (0u != tu_fifo_depth(&s->ff) && s->ep_buf != NULL) { tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes); } } diff --git a/src/device/usbd.c b/src/device/usbd.c index a65d14daf..5e7d0ffa7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1474,6 +1474,7 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t t // success message. If total_bytes is too big, the FIFO will copy only what is available // into the USB buffer! bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes, bool is_isr) { + #if CFG_TUD_EDPT_DEDICATED_HWFIFO rhport = _usbd_rhport; uint8_t const epnum = tu_edpt_number(ep_addr); @@ -1481,7 +1482,7 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_ TU_LOG_USBD(" Queue ISO EP %02X with %u bytes ... ", ep_addr, total_bytes); - // Attempt to transfer on a busy endpoint, sound like an race condition ! + // Attempt to transfer on a busy endpoint, sound like a race condition ! TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return @@ -1499,6 +1500,14 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_ TU_BREAKPOINT(); return false; } + #else + (void)rhport; + (void)ep_addr; + (void)ff; + (void)total_bytes; + (void)is_isr; + return false; + #endif } bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { diff --git a/src/tusb.c b/src/tusb.c index 3852da76b..1b8fdc460 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -387,8 +387,12 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_xfer(uint8_t hwid, tu_edpt_strea #endif } else { #if CFG_TUD_ENABLED - return usbd_edpt_xfer(hwid, s->ep_addr, count ? s->ep_buf : NULL, count, false); - #endif + if (s->ep_buf == NULL) { + return usbd_edpt_xfer_fifo(hwid, s->ep_addr, &s->ff, count, false); + } else { + return usbd_edpt_xfer(hwid, s->ep_addr, count ? s->ep_buf : NULL, count, false); + } + #endif } return false; } @@ -419,12 +423,17 @@ bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t* s, uint3 } uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s) { - // skip if no data - TU_VERIFY(tu_fifo_count(&s->ff) > 0, 0); + const uint16_t ff_count = tu_fifo_count(&s->ff); + TU_VERIFY(ff_count > 0, 0); // skip if no data TU_VERIFY(stream_claim(hwid, s), 0); // Pull data from FIFO -> EP buf - const uint16_t count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); + uint16_t count; + if (s->ep_buf == NULL) { + count = ff_count; + } else { + count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); + } if (count > 0) { TU_ASSERT(stream_xfer(hwid, s, count), 0); @@ -441,7 +450,8 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buf TU_VERIFY(bufsize > 0); // TODO support ZLP if (0 == tu_fifo_depth(&s->ff)) { - // no fifo for buffered + // no fifo for buffered, ep_buf must be valid + TU_VERIFY(s->ep_buf != NULL, 0); TU_VERIFY(stream_claim(hwid, s), 0); const uint32_t xact_len = tu_min32(bufsize, s->ep_bufsize); memcpy(s->ep_buf, buffer, xact_len); diff --git a/src/tusb_option.h b/src/tusb_option.h index e2eaecd2d..d7b61d58d 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -306,18 +306,14 @@ #if defined(TUP_USBIP_DWC2) #if CFG_TUD_DWC2_SLAVE_ENABLE - #define CFG_TUD_EDPT_DEDICATED_FIFO + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 #endif #if CFG_TUD_DWC2_SLAVE_ENABLE - #define CFG_TUH_EDPT_DEDICATED_FIFO + #define CFG_TUH_EDPT_DEDICATED_HWFIFO 1 #endif #endif -#if defined(CFG_TUD_EDPT_DEDICATED_FIFO) || defined(CFG_TUH_EDPT_DEDICATED_FIFO) - #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_RW32 -#endif - //------------- ChipIdea -------------// // Enable CI_HS VBUS Charge. Set this to 1 if the USB_VBUS pin is not connected to 5V VBUS (note: 3.3V is // insufficient). @@ -590,6 +586,10 @@ #define CFG_TUD_NCM 0 #endif +#ifndef CFG_TUD_EDPT_DEDICATED_HWFIFO + #define CFG_TUD_EDPT_DEDICATED_HWFIFO 0 +#endif + //-------------------------------------------------------------------- // Host Options (Default) //-------------------------------------------------------------------- @@ -729,6 +729,10 @@ #define CFG_TUH_API_EDPT_XFER 0 #endif +#ifndef CFG_TUH_EDPT_DEDICATED_HWFIFO + #define CFG_TUH_EDPT_DEDICATED_HWFIFO 0 +#endif + //--------------------------------------------------------------------+ // TypeC Options (Default) //--------------------------------------------------------------------+ -- cgit v1.3.1 From 07dfbadc001d669d6db6d1e0b82b65e73b67f21a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 Nov 2025 10:28:53 +0700 Subject: correct tu_edpt_stream_read() with non-fifo mode. Fix rhport with vendor device --- src/class/vendor/vendor_device.c | 25 ++++++++----------------- src/tusb.c | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index ee6cd7105..c7903375d 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -37,6 +37,7 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ typedef struct { + uint8_t rhport; uint8_t itf_num; /*------------- From this point, data is not cleared by bus reset -------------*/ @@ -97,32 +98,26 @@ bool tud_vendor_n_mounted(uint8_t itf) { uint32_t tud_vendor_n_available(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_VENDOR, 0); vendord_interface_t* p_itf = &_vendord_itf[itf]; - return tu_edpt_stream_read_available(&p_itf->rx.stream); } bool tud_vendor_n_peek(uint8_t itf, uint8_t* u8) { TU_VERIFY(itf < CFG_TUD_VENDOR); vendord_interface_t* p_itf = &_vendord_itf[itf]; - return tu_edpt_stream_peek(&p_itf->rx.stream, u8); } uint32_t tud_vendor_n_read (uint8_t itf, void* buffer, uint32_t bufsize) { TU_VERIFY(itf < CFG_TUD_VENDOR, 0); vendord_interface_t* p_itf = &_vendord_itf[itf]; - const uint8_t rhport = 0; - - return tu_edpt_stream_read(rhport, &p_itf->rx.stream, buffer, bufsize); + return tu_edpt_stream_read(p_itf->rhport, &p_itf->rx.stream, buffer, bufsize); } void tud_vendor_n_read_flush (uint8_t itf) { TU_VERIFY(itf < CFG_TUD_VENDOR, ); vendord_interface_t* p_itf = &_vendord_itf[itf]; - const uint8_t rhport = 0; - tu_edpt_stream_clear(&p_itf->rx.stream); - tu_edpt_stream_read_xfer(rhport, &p_itf->rx.stream); + tu_edpt_stream_read_xfer(p_itf->rhport, &p_itf->rx.stream); } //--------------------------------------------------------------------+ @@ -131,25 +126,19 @@ void tud_vendor_n_read_flush (uint8_t itf) { uint32_t tud_vendor_n_write (uint8_t itf, const void* buffer, uint32_t bufsize) { TU_VERIFY(itf < CFG_TUD_VENDOR, 0); vendord_interface_t* p_itf = &_vendord_itf[itf]; - const uint8_t rhport = 0; - - return tu_edpt_stream_write(rhport, &p_itf->tx.stream, buffer, (uint16_t) bufsize); + return tu_edpt_stream_write(p_itf->rhport, &p_itf->tx.stream, buffer, (uint16_t)bufsize); } uint32_t tud_vendor_n_write_flush (uint8_t itf) { TU_VERIFY(itf < CFG_TUD_VENDOR, 0); vendord_interface_t* p_itf = &_vendord_itf[itf]; - const uint8_t rhport = 0; - - return tu_edpt_stream_write_xfer(rhport, &p_itf->tx.stream); + return tu_edpt_stream_write_xfer(p_itf->rhport, &p_itf->tx.stream); } uint32_t tud_vendor_n_write_available (uint8_t itf) { TU_VERIFY(itf < CFG_TUD_VENDOR, 0); vendord_interface_t* p_itf = &_vendord_itf[itf]; - const uint8_t rhport = 0; - - return tu_edpt_stream_write_available(rhport, &p_itf->tx.stream); + return tu_edpt_stream_write_available(p_itf->rhport, &p_itf->tx.stream); } //--------------------------------------------------------------------+ @@ -223,7 +212,9 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uin } TU_VERIFY(p_vendor, 0); + p_vendor->rhport = rhport; p_vendor->itf_num = desc_itf->bInterfaceNumber; + while (tu_desc_in_bounds(p_desc, desc_end)) { const uint8_t desc_type = tu_desc_type(p_desc); if (desc_type == TUSB_DESC_INTERFACE || desc_type == TUSB_DESC_INTERFACE_ASSOCIATION) { diff --git a/src/tusb.c b/src/tusb.c index 1b8fdc460..c589e105e 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -450,7 +450,7 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buf TU_VERIFY(bufsize > 0); // TODO support ZLP if (0 == tu_fifo_depth(&s->ff)) { - // no fifo for buffered, ep_buf must be valid + // non-fifo mode, ep_buf must be valid TU_VERIFY(s->ep_buf != NULL, 0); TU_VERIFY(stream_claim(hwid, s), 0); const uint32_t xact_len = tu_min32(bufsize, s->ep_bufsize); @@ -474,6 +474,7 @@ uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t* s) { if (tu_fifo_depth(&s->ff) > 0) { return (uint32_t) tu_fifo_remaining(&s->ff); } else { + // non-fifo mode bool is_busy = true; if (s->is_host) { #if CFG_TUH_ENABLED @@ -493,7 +494,7 @@ uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t* s) { //--------------------------------------------------------------------+ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) { if (0 == tu_fifo_depth(&s->ff)) { - // no fifo for buffered + // non-fifo mode TU_VERIFY(stream_claim(hwid, s), 0); TU_ASSERT(stream_xfer(hwid, s, s->ep_bufsize), 0); return s->ep_bufsize; @@ -527,7 +528,15 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) { } uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) { - const uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize); + uint32_t num_read; + if (tu_fifo_depth(&s->ff) > 0) { + num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize); + } else { + // non-fifo mode + memcpy(buffer, s->ep_buf, bufsize); + num_read = bufsize; + } + tu_edpt_stream_read_xfer(hwid, s); return num_read; } -- cgit v1.3.1 From 4ef0f61bde446453a1ada60bbc1a319665d2e839 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 Nov 2025 16:23:00 +0700 Subject: add tu_fifo_discard_n() and tu_edpt_stream_discard() --- src/common/tusb_fifo.c | 253 ++++++++++++++++++---------------------------- src/common/tusb_fifo.h | 38 +++---- src/common/tusb_private.h | 4 + src/tusb.c | 3 +- 4 files changed, 127 insertions(+), 171 deletions(-) (limited to 'src/tusb.c') diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 27b97310a..f78167f94 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -56,6 +56,9 @@ TU_ATTR_ALWAYS_INLINE static inline void ff_unlock(osal_mutex_t mutex) { #endif +//--------------------------------------------------------------------+ +// Setup API +//--------------------------------------------------------------------+ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable) { // Limit index space to 2*depth - this allows for a fast "modulo" calculation // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable @@ -80,6 +83,36 @@ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_si return true; } +// clear fifo by resetting read and write indices +bool tu_fifo_clear(tu_fifo_t *f) { + ff_lock(f->mutex_wr); + ff_lock(f->mutex_rd); + + f->rd_idx = 0; + f->wr_idx = 0; + + ff_unlock(f->mutex_wr); + ff_unlock(f->mutex_rd); + return true; +} + +// Change the fifo overwritable mode +bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { + if (f->overwritable == overwritable) { + return true; + } + + ff_lock(f->mutex_wr); + ff_lock(f->mutex_rd); + + f->overwritable = overwritable; + + ff_unlock(f->mutex_wr); + ff_unlock(f->mutex_rd); + + return true; +} + //--------------------------------------------------------------------+ // Pull & Push // copy data to/from fifo without updating read/write pointers @@ -295,49 +328,27 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t correct_read_index(tu_fifo_t *f, ui return rd_idx; } -// peek() using local write/read index. Be careful, caller must not lock mutex, since this Will also try to lock mutex -// in case of overflowed to correct read index -static bool ff_peek_local(tu_fifo_t *f, void *buf, uint16_t wr_idx, uint16_t rd_idx) { - const uint16_t ovf_count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx); - if (ovf_count == 0) { - return false; // nothing to peek - } - - // Correct read index if overflow - if (ovf_count > f->depth) { - ff_lock(f->mutex_rd); - rd_idx = correct_read_index(f, wr_idx); - ff_unlock(f->mutex_rd); - } - - const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); - memcpy(buf, f->buffer + (rd_ptr * f->item_size), f->item_size); - - return true; -} - //--------------------------------------------------------------------+ -// Application API +// n-API //--------------------------------------------------------------------+ // Works on local copies of w and r -// Must be protected by mutexes since in case of an overflow read pointer gets modified +// Must be protected by read mutex since in case of an overflow read pointer gets modified uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, uint16_t wr_idx, uint16_t rd_idx, tu_fifo_access_mode_t access_mode) { - uint16_t ovf_cnt = tu_ff_overflow_count(f->depth, wr_idx, rd_idx); - - if (ovf_cnt == 0) { + uint16_t count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx); + if (count == 0) { return 0; // nothing to peek } // Check overflow and correct if required - if (ovf_cnt > f->depth) { + if (count > f->depth) { rd_idx = correct_read_index(f, wr_idx); - ovf_cnt = f->depth; + count = f->depth; } - if (ovf_cnt < n) { - n = ovf_cnt; // limit to available count + if (count < n) { + n = count; // limit to available count } const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); @@ -346,6 +357,27 @@ uint16_t tu_fifo_peek_n_access_mode(tu_fifo_t *f, void *p_buffer, uint16_t n, ui return n; } +// Read n items without removing it from the FIFO, correct read pointer if overflowed +uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { + ff_lock(f->mutex_rd); + const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_INC_ADDR_RW8); + ff_unlock(f->mutex_rd); + return ret; +} + +// Read n items from fifo with access mode +uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode) { + ff_lock(f->mutex_rd); + + // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable + n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, access_mode); + f->rd_idx = advance_index(f->depth, f->rd_idx, n); + + ff_unlock(f->mutex_rd); + return n; +} + +// Write n items to fifo with access mode uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode) { if (n == 0) { return 0; @@ -419,40 +451,41 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, return n; } -uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_fifo_access_mode_t access_mode) { +uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n) { + const uint16_t count = tu_min16(n, tu_fifo_count(f)); // limit to available count ff_lock(f->mutex_rd); - - // Peek the data: f->rd_idx might get modified in case of an overflow so we can not use a local variable - n = tu_fifo_peek_n_access_mode(f, buffer, n, f->wr_idx, f->rd_idx, access_mode); - f->rd_idx = advance_index(f->depth, f->rd_idx, n); - + f->rd_idx = advance_index(f->depth, f->rd_idx, count); ff_unlock(f->mutex_rd); - return n; -} -// Only use in case tu_fifo_overflow() returned true! -void tu_fifo_correct_read_pointer(tu_fifo_t *f) { - ff_lock(f->mutex_rd); - correct_read_index(f, f->wr_idx); - ff_unlock(f->mutex_rd); + return count; } -/******************************************************************************/ -/*! - @brief Read one element out of the buffer. +//--------------------------------------------------------------------+ +// One API +//--------------------------------------------------------------------+ - This function will return the element located at the array index of the - read pointer, and then increment the read pointer index. - This function checks for an overflow and corrects read pointer if required. +// peek() using local write/read index, correct read index if overflowed +// Be careful, caller must not lock mutex, since this Will also try to lock mutex +static bool ff_peek_local(tu_fifo_t *f, void *buf, uint16_t wr_idx, uint16_t rd_idx) { + const uint16_t ovf_count = tu_ff_overflow_count(f->depth, wr_idx, rd_idx); + if (ovf_count == 0) { + return false; // nothing to peek + } - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] buffer - Pointer to the place holder for data read from the buffer + // Correct read index if overflow + if (ovf_count > f->depth) { + ff_lock(f->mutex_rd); + rd_idx = correct_read_index(f, wr_idx); + ff_unlock(f->mutex_rd); + } - @returns TRUE if the queue is not empty - */ -/******************************************************************************/ + const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); + memcpy(buf, f->buffer + (rd_ptr * f->item_size), f->item_size); + + return true; +} + +// Read one element out of the buffer, correct read index if overflowed bool tu_fifo_read(tu_fifo_t *f, void *buffer) { // Peek the data // f->rd_idx might get modified in case of an overflow so we can not use a local variable @@ -466,61 +499,12 @@ bool tu_fifo_read(tu_fifo_t *f, void *buffer) { return ret; } -/******************************************************************************/ -/*! - @brief Read one item without removing it from the FIFO. - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] p_buffer - Pointer to the place holder for data read from the buffer - - @returns TRUE if the queue is not empty - */ -/******************************************************************************/ +// Read one item without removing it from the FIFO, correct rad index if overflowed bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer) { return ff_peek_local(f, p_buffer, f->wr_idx, f->rd_idx); } -/******************************************************************************/ -/*! - @brief Read n items without removing it from the FIFO - This function checks for an overflow and corrects read pointer if required. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] p_buffer - Pointer to the place holder for data read from the buffer - @param[in] n - Number of items to peek - - @returns Number of bytes written to p_buffer - */ -/******************************************************************************/ -uint16_t tu_fifo_peek_n(tu_fifo_t *f, void *p_buffer, uint16_t n) { - ff_lock(f->mutex_rd); - const uint16_t ret = tu_fifo_peek_n_access_mode(f, p_buffer, n, f->wr_idx, f->rd_idx, TU_FIFO_INC_ADDR_RW8); - ff_unlock(f->mutex_rd); - return ret; -} - -/******************************************************************************/ -/*! - @brief Write one element into the buffer. - - This function will write one element into the array index specified by - the write pointer and increment the write index. - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] data - The byte to add to the FIFO - - @returns TRUE if the data was written to the FIFO (overwrittable - FIFO will always return TRUE) - */ -/******************************************************************************/ +// Write one element into the buffer bool tu_fifo_write(tu_fifo_t *f, const void *data) { bool ret; ff_lock(f->mutex_wr); @@ -541,51 +525,9 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data) { return ret; } -/******************************************************************************/ -/*! - @brief Clear the fifo read and write pointers - - @param[in] f - Pointer to the FIFO buffer to manipulate - */ -/******************************************************************************/ -bool tu_fifo_clear(tu_fifo_t *f) { - ff_lock(f->mutex_wr); - ff_lock(f->mutex_rd); - - f->rd_idx = 0; - f->wr_idx = 0; - - ff_unlock(f->mutex_wr); - ff_unlock(f->mutex_rd); - return true; -} - -/******************************************************************************/ -/*! - @brief Change the fifo mode to overwritable or not overwritable - - @param[in] f - Pointer to the FIFO buffer to manipulate - @param[in] overwritable - Overwritable mode the fifo is set to - */ -/******************************************************************************/ -bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) { - if (f->overwritable == overwritable) { - return true; - } - - ff_lock(f->mutex_wr); - ff_lock(f->mutex_rd); - - f->overwritable = overwritable; - - ff_unlock(f->mutex_wr); - ff_unlock(f->mutex_rd); - - return true; -} +//--------------------------------------------------------------------+ +// Index API +//--------------------------------------------------------------------+ /******************************************************************************/ /*! @@ -607,6 +549,13 @@ void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n) { f->wr_idx = advance_index(f->depth, f->wr_idx, n); } +// Correct the read index in case tu_fifo_overflow() returned true! +void tu_fifo_correct_read_pointer(tu_fifo_t *f) { + ff_lock(f->mutex_rd); + correct_read_index(f, f->wr_idx); + ff_unlock(f->mutex_rd); +} + /******************************************************************************/ /*! @brief Advance read pointer - intended to be used in combination with DMA. diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 4d8448c44..42f154bca 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -156,9 +156,9 @@ typedef enum { //--------------------------------------------------------------------+ // Setup API //--------------------------------------------------------------------+ +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable); bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); bool tu_fifo_clear(tu_fifo_t *f); -bool tu_fifo_config(tu_fifo_t *f, void* buffer, uint16_t depth, uint16_t item_size, bool overwritable); #if OSAL_MUTEX_REQUIRED TU_ATTR_ALWAYS_INLINE static inline @@ -170,6 +170,22 @@ void tu_fifo_config_mutex(tu_fifo_t *f, osal_mutex_t wr_mutex, osal_mutex_t rd_m #define tu_fifo_config_mutex(_f, _wr_mutex, _rd_mutex) #endif +//--------------------------------------------------------------------+ +// Index API +//--------------------------------------------------------------------+ +void tu_fifo_correct_read_pointer(tu_fifo_t *f); + +// Pointer modifications intended to be used in combinations with DMAs. +// USE WITH CARE - NO SAFETY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! +void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n); +void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n); + +// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies +// to handle a possible wrapping part. These functions deliver a pointer to start +// reading/writing from/to and a valid linear length along which no wrap occurs. +void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); +void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); + //--------------------------------------------------------------------+ // Peek API // peek() will correct/re-index read pointer in case of an overflowed fifo to form a full fifo @@ -189,6 +205,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void * return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_INC_ADDR_RW8); } +// discard first n items from fifo i.e advance read pointer by n with mutex +// return number of discarded items +uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); + //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ @@ -198,22 +218,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_INC_ADDR_RW8); } -//--------------------------------------------------------------------+ -// Index API -//--------------------------------------------------------------------+ -void tu_fifo_correct_read_pointer(tu_fifo_t *f); - -// Pointer modifications intended to be used in combinations with DMAs. -// USE WITH CARE - NO SAFETY CHECKS CONDUCTED HERE! NOT MUTEX PROTECTED! -void tu_fifo_advance_write_pointer(tu_fifo_t *f, uint16_t n); -void tu_fifo_advance_read_pointer(tu_fifo_t *f, uint16_t n); - -// If you want to read/write from/to the FIFO by use of a DMA, you may need to conduct two copies -// to handle a possible wrapping part. These functions deliver a pointer to start -// reading/writing from/to and a valid linear length along which no wrap occurs. -void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); -void tu_fifo_get_write_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info); - //--------------------------------------------------------------------+ // Internal Helper Local // work on local copies of read/write indices in order to only access them once for re-entrancy diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 48fd1d6d2..8643bb020 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -172,6 +172,10 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_peek(tu_edpt_stream_t *s return tu_fifo_peek(&s->ff, ch); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_edpt_stream_discard(tu_edpt_stream_t *s, uint32_t len) { + return (uint32_t)tu_fifo_discard_n(&s->ff, (uint16_t)len); +} + #ifdef __cplusplus } #endif diff --git a/src/tusb.c b/src/tusb.c index c589e105e..2d122885b 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -533,8 +533,7 @@ uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, ui num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize); } else { // non-fifo mode - memcpy(buffer, s->ep_buf, bufsize); - num_read = bufsize; + num_read = 0; } tu_edpt_stream_read_xfer(hwid, s); -- cgit v1.3.1 From 9a9bf0fd7b5a005fd4701ab6cb5b1728ecc0baa2 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 Nov 2025 18:41:57 +0700 Subject: change tud_vendor_rx_cb() behavior, buffer and bufsize only available when CFG_TUD_VENDOR_RX_BUFSIZE = 0 update vendor device to omit ep buf when dedicated hwfifo is supported --- examples/device/webusb_serial/src/main.c | 15 ++++++----- src/class/cdc/cdc_device.c | 11 +++----- src/class/vendor/vendor_device.c | 45 +++++++++++++++++++++++++------- src/class/vendor/vendor_device.h | 9 ++++--- src/common/tusb_types.h | 5 ++++ src/tusb.c | 25 +++++++++++------- 6 files changed, 73 insertions(+), 37 deletions(-) (limited to 'src/tusb.c') diff --git a/examples/device/webusb_serial/src/main.c b/examples/device/webusb_serial/src/main.c index 4fcddd724..50794bdba 100644 --- a/examples/device/webusb_serial/src/main.c +++ b/examples/device/webusb_serial/src/main.c @@ -211,15 +211,16 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ return false; } -void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint16_t bufsize) { +void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint32_t bufsize) { (void)idx; + (void)buffer; + (void)bufsize; -// since we used data without pulling it from RX FIFO, we need to discard number of items used -#if CFG_TUD_VENDOR_RX_BUFSIZE > 0 - tud_vendor_read_discard(bufsize); -#endif - - echo_all(buffer, bufsize); + while (tud_vendor_available()) { + uint8_t buf[64]; + const uint32_t count = tud_vendor_read(buf, sizeof(buf)); + echo_all(buf, count); + } } //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 7ef8aa738..d7792afe4 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -266,9 +266,8 @@ void cdcd_init(void) { uint8_t *epout_buf = NULL; uint8_t *epin_buf = NULL; #else - cdcd_epbuf_t *p_epbuf = &_cdcd_epbuf[i]; - uint8_t *epout_buf = p_epbuf->epout; - uint8_t *epin_buf = p_epbuf->epin; + uint8_t *epout_buf = _cdcd_epbuf[i].epout; + uint8_t *epin_buf = _cdcd_epbuf[i].epin; #endif tu_edpt_stream_init(&p_cdc->stream.rx, false, false, false, p_cdc->stream.rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, @@ -516,11 +515,9 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ } // Data sent to host, we continue to fetch from tx fifo to send. - // Note: This will cause incorrect baudrate set in line coding. - // Though maybe the baudrate is not really important !!! + // Note: This will cause incorrect baudrate set in line coding. Though maybe the baudrate is not really important ! if (ep_addr == stream_tx->ep_addr) { - // invoke transmit callback to possibly refill tx fifo - tud_cdc_tx_complete_cb(itf); + tud_cdc_tx_complete_cb(itf); // invoke callback to possibly refill tx fifo if (0 == tu_edpt_stream_write_xfer(rhport, stream_tx)) { // If there is no data left, a ZLP should be sent if needed diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index c2393c25d..bb736aba8 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -59,20 +59,30 @@ typedef struct { static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR]; +#if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 || CFG_TUD_VENDOR_RX_BUFSIZE == 0 typedef struct { + // Skip local EP buffer if dedicated hw FIFO is supported + #if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 || CFG_TUD_VENDOR_RX_BUFSIZE == 0 TUD_EPBUF_DEF(epout, CFG_TUD_VENDOR_EPSIZE); + #endif + + // Skip local EP buffer if dedicated hw FIFO is supported + #if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 TUD_EPBUF_DEF(epin, CFG_TUD_VENDOR_EPSIZE); + #endif } vendord_epbuf_t; CFG_TUD_MEM_SECTION static vendord_epbuf_t _vendord_epbuf[CFG_TUD_VENDOR]; + #endif //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ -TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint16_t bufsize) { + +TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint32_t bufsize) { (void)idx; - (void) buffer; - (void) bufsize; + (void)buffer; + (void)bufsize; } TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t idx, uint32_t sent_bytes) { @@ -153,7 +163,19 @@ void vendord_init(void) { for(uint8_t i=0; i 0 uint8_t *rx_ff_buf = p_itf->stream.rx_ff_buf; @@ -161,7 +183,7 @@ void vendord_init(void) { uint8_t *rx_ff_buf = NULL; #endif - tu_edpt_stream_init(&p_itf->stream.rx, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, p_epbuf->epout, + tu_edpt_stream_init(&p_itf->stream.rx, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, epout_buf, CFG_TUD_VENDOR_EPSIZE); #if CFG_TUD_VENDOR_TX_BUFSIZE > 0 @@ -170,7 +192,7 @@ void vendord_init(void) { uint8_t *tx_ff_buf = NULL; #endif - tu_edpt_stream_init(&p_itf->stream.tx, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, p_epbuf->epin, + tu_edpt_stream_init(&p_itf->stream.tx, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, epin_buf, CFG_TUD_VENDOR_EPSIZE); } } @@ -264,16 +286,19 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint const uint8_t idx = find_vendor_itf(ep_addr); TU_VERIFY(idx < CFG_TUD_VENDOR); vendord_interface_t *p_vendor = &_vendord_itf[idx]; - vendord_epbuf_t *p_epbuf = &_vendord_epbuf[idx]; if (ep_addr == p_vendor->stream.rx.ep_addr) { // Received new data: put into stream's fifo tu_edpt_stream_read_xfer_complete(&p_vendor->stream.rx, xferred_bytes); - // Invoked callback if any - tud_vendor_rx_cb(idx, p_epbuf->epout, (uint16_t)xferred_bytes); + // invoke callback + #if CFG_TUD_VENDOR_RX_BUFSIZE == 0 + tud_vendor_rx_cb(idx, p_vendor->stream.rx.ep_buf, xferred_bytes); + #else + tud_vendor_rx_cb(idx, NULL, 0); + #endif - tu_edpt_stream_read_xfer(rhport, &p_vendor->stream.rx); + tu_edpt_stream_read_xfer(rhport, &p_vendor->stream.rx); // prepare next data } else if (ep_addr == p_vendor->stream.tx.ep_addr) { // Send complete tud_vendor_tx_cb(idx, (uint16_t)xferred_bytes); diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index e9dec788b..05de84f20 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -121,9 +121,12 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_available(void) { // Application Callback API (weak is optional) //--------------------------------------------------------------------+ -// Invoked when received new data -void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint16_t bufsize); -// Invoked when last rx transfer finished +// Invoked when received new data. +// - CFG_TUD_VENDOR_RX_BUFSIZE > 0; buffer and bufsize must not be used (both NULL,0) since data is in RX FIFO +// - CFG_TUD_VENDOR_RX_BUFSIZE = 0: Buffer and bufsize are valid +void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint32_t bufsize); + +// Invoked when tx transfer is finished void tud_vendor_tx_cb(uint8_t idx, uint32_t sent_bytes); //--------------------------------------------------------------------+ diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 73c816e3e..d473e53e6 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -323,6 +323,11 @@ typedef struct { tusb_speed_t speed; } tusb_rhport_init_t; +typedef struct { + uint16_t len; + uint8_t *buffer; +} tusb_buffer_t; + //--------------------------------------------------------------------+ // USB Descriptors //--------------------------------------------------------------------+ diff --git a/src/tusb.c b/src/tusb.c index 2d122885b..94121b174 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -450,12 +450,19 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buf TU_VERIFY(bufsize > 0); // TODO support ZLP if (0 == tu_fifo_depth(&s->ff)) { - // non-fifo mode, ep_buf must be valid - TU_VERIFY(s->ep_buf != NULL, 0); + // non-fifo mode TU_VERIFY(stream_claim(hwid, s), 0); - const uint32_t xact_len = tu_min32(bufsize, s->ep_bufsize); - memcpy(s->ep_buf, buffer, xact_len); + uint32_t xact_len; + if (s->ep_buf != NULL) { + // using ep buf + xact_len = tu_min32(bufsize, s->ep_bufsize); + memcpy(s->ep_buf, buffer, xact_len); + } else { + // using hwfifo + xact_len = bufsize; + } TU_ASSERT(stream_xfer(hwid, s, (uint16_t) xact_len), 0); + return xact_len; } else { const uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize); @@ -494,7 +501,8 @@ uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t* s) { //--------------------------------------------------------------------+ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) { if (0 == tu_fifo_depth(&s->ff)) { - // non-fifo mode + // non-fifo mode: RX need ep buffer + TU_VERIFY(s->ep_buf != NULL, 0); TU_VERIFY(stream_claim(hwid, s), 0); TU_ASSERT(stream_xfer(hwid, s, s->ep_bufsize), 0); return s->ep_bufsize; @@ -507,11 +515,8 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) { // and slowly move it to the FIFO when read(). // This pre-check reduces endpoint claiming TU_VERIFY(available >= mps); - TU_VERIFY(stream_claim(hwid, s), 0); - - // get available again since fifo can be changed before endpoint is claimed - available = tu_fifo_remaining(&s->ff); + available = tu_fifo_remaining(&s->ff); // re-get available since fifo can be changed if (available >= mps) { // multiple of packet size limit by ep bufsize @@ -532,7 +537,7 @@ uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, ui if (tu_fifo_depth(&s->ff) > 0) { num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize); } else { - // non-fifo mode + // non-fifo mode not support this num_read = 0; } -- cgit v1.3.1 From 1465a9b5bc64e39d9051b281ffc1f13b5cb6ad9e Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 27 Nov 2025 19:14:23 +0700 Subject: make vendor_read_* API() is only available when CFG_TUD_VENDOR_RX_BUFSIZE > 0 vendor_write_flush() and write_available() only available when CFG_TUD_VENDOR_TX_BUFSIZE > 0 --- src/class/vendor/vendor_device.c | 4 ++++ src/class/vendor/vendor_device.h | 11 +++++++++-- src/common/tusb_fifo.c | 2 +- src/tusb.c | 9 +-------- 4 files changed, 15 insertions(+), 11 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index bb736aba8..d468bd0ba 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -103,6 +103,7 @@ bool tud_vendor_n_mounted(uint8_t idx) { //--------------------------------------------------------------------+ // Read API //--------------------------------------------------------------------+ +#if CFG_TUD_VENDOR_RX_BUFSIZE > 0 uint32_t tud_vendor_n_available(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; @@ -133,6 +134,7 @@ void tud_vendor_n_read_flush(uint8_t idx) { tu_edpt_stream_clear(&p_itf->stream.rx); tu_edpt_stream_read_xfer(p_itf->rhport, &p_itf->stream.rx); } +#endif //--------------------------------------------------------------------+ // Write API @@ -143,6 +145,7 @@ uint32_t tud_vendor_n_write(uint8_t idx, const void *buffer, uint32_t bufsize) { return tu_edpt_stream_write(p_itf->rhport, &p_itf->stream.tx, buffer, (uint16_t)bufsize); } +#if CFG_TUD_VENDOR_TX_BUFSIZE > 0 uint32_t tud_vendor_n_write_flush(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; @@ -154,6 +157,7 @@ uint32_t tud_vendor_n_write_available(uint8_t idx) { vendord_interface_t *p_itf = &_vendord_itf[idx]; return tu_edpt_stream_write_available(p_itf->rhport, &p_itf->stream.tx); } +#endif //--------------------------------------------------------------------+ // USBD Driver API diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 05de84f20..daf9c19cf 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -51,16 +51,21 @@ extern "C" { // Application API (Multiple Interfaces) i.e CFG_TUD_VENDOR > 1 //--------------------------------------------------------------------+ bool tud_vendor_n_mounted(uint8_t idx); + +#if CFG_TUD_VENDOR_RX_BUFSIZE > 0 uint32_t tud_vendor_n_available(uint8_t idx); bool tud_vendor_n_peek(uint8_t idx, uint8_t *ui8); - uint32_t tud_vendor_n_read(uint8_t idx, void *buffer, uint32_t bufsize); uint32_t tud_vendor_n_read_discard(uint8_t idx, uint32_t count); void tud_vendor_n_read_flush(uint8_t idx); +#endif uint32_t tud_vendor_n_write(uint8_t idx, const void *buffer, uint32_t bufsize); + +#if CFG_TUD_VENDOR_TX_BUFSIZE > 0 uint32_t tud_vendor_n_write_flush(uint8_t idx); uint32_t tud_vendor_n_write_available(uint8_t idx); +#endif TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_n_write_str(uint8_t idx, const char *str) { return tud_vendor_n_write(idx, str, strlen(str)); @@ -76,6 +81,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_mounted(void) { return tud_vendor_n_mounted(0); } +#if CFG_TUD_VENDOR_RX_BUFSIZE > 0 TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_available(void) { return tud_vendor_n_available(0); } @@ -95,6 +101,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_read_discard(uint32_t co TU_ATTR_ALWAYS_INLINE static inline void tud_vendor_read_flush(void) { tud_vendor_n_read_flush(0); } +#endif TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write(const void *buffer, uint32_t bufsize) { return tud_vendor_n_write(0, buffer, bufsize); @@ -104,11 +111,11 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_str(const char *st return tud_vendor_n_write_str(0, str); } +#if CFG_TUD_VENDOR_TX_BUFSIZE > 0 TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_flush(void) { return tud_vendor_n_write_flush(0); } -#if CFG_TUD_VENDOR_TX_BUFSIZE > 0 TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_available(void) { return tud_vendor_n_write_available(0); } diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index f78167f94..06b0d6a58 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -499,7 +499,7 @@ bool tu_fifo_read(tu_fifo_t *f, void *buffer) { return ret; } -// Read one item without removing it from the FIFO, correct rad index if overflowed +// Read one item without removing it from the FIFO, correct read index if overflowed bool tu_fifo_peek(tu_fifo_t *f, void *p_buffer) { return ff_peek_local(f, p_buffer, f->wr_idx, f->rd_idx); } diff --git a/src/tusb.c b/src/tusb.c index 94121b174..b6cfd1260 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -533,14 +533,7 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) { } uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) { - uint32_t num_read; - if (tu_fifo_depth(&s->ff) > 0) { - num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize); - } else { - // non-fifo mode not support this - num_read = 0; - } - + const uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize); tu_edpt_stream_read_xfer(hwid, s); return num_read; } -- cgit v1.3.1 From 2c78a2dd9c4c860004ebf06c1fcf5b3dd58cb48f Mon Sep 17 00:00:00 2001 From: hathach Date: Sat, 6 Dec 2025 02:29:05 +0700 Subject: edpt stream only support non-fifo mode if needed CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED --- src/common/tusb_fifo.h | 7 ++++--- src/common/tusb_private.h | 12 ++++++++++++ src/tusb.c | 36 +++++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 14 deletions(-) (limited to 'src/tusb.c') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 42f154bca..94ab421bb 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -224,10 +224,11 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const //--------------------------------------------------------------------+ // return overflowable count (index difference), which can be used to determine both fifo count and an overflow state TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_ff_overflow_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx) { - if (wr_idx >= rd_idx) { - return (uint16_t)(wr_idx - rd_idx); + const int32_t diff = (int32_t)wr_idx - (int32_t)rd_idx; + if (diff >= 0) { + return (uint16_t)diff; } else { - return (uint16_t)(2 * depth - (rd_idx - wr_idx)); + return (uint16_t)(2 * depth + diff); } } diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 8643bb020..0e9eef732 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -33,6 +33,18 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Configuration +//--------------------------------------------------------------------+ + +#if CFG_TUD_ENABLED && CFG_TUD_VENDOR && (CFG_TUD_VENDOR_TX_BUFSIZE == 0 || CFG_TUD_VENDOR_RX_BUFSIZE == 0) + #define CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED 1 +#endif + +#ifndef CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED + #define CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED 0 +#endif + #define TUP_USBIP_CONTROLLER_NUM 2 extern tusb_role_t _tusb_rhport_role[TUP_USBIP_CONTROLLER_NUM]; diff --git a/src/tusb.c b/src/tusb.c index b6cfd1260..ecdd569c4 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -338,6 +338,10 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize) { (void) is_tx; + if (CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED == 0 && (ff_buf == NULL || ff_bufsize == 0)) { + return false; + } + s->is_host = is_host; tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable); @@ -367,7 +371,7 @@ bool tu_edpt_stream_deinit(tu_edpt_stream_t *s) { return true; } -TU_ATTR_ALWAYS_INLINE static inline bool stream_claim(uint8_t hwid, tu_edpt_stream_t* s) { +static bool stream_claim(uint8_t hwid, tu_edpt_stream_t *s) { if (s->is_host) { #if CFG_TUH_ENABLED return usbh_edpt_claim(hwid, s->ep_addr); @@ -380,7 +384,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_claim(uint8_t hwid, tu_edpt_stre return false; } -TU_ATTR_ALWAYS_INLINE static inline bool stream_xfer(uint8_t hwid, tu_edpt_stream_t* s, uint16_t count) { +static bool stream_xfer(uint8_t hwid, tu_edpt_stream_t *s, uint16_t count) { if (s->is_host) { #if CFG_TUH_ENABLED return usbh_edpt_xfer(hwid, s->ep_addr, count ? s->ep_buf : NULL, count); @@ -397,7 +401,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_xfer(uint8_t hwid, tu_edpt_strea return false; } -TU_ATTR_ALWAYS_INLINE static inline bool stream_release(uint8_t hwid, tu_edpt_stream_t* s) { +static bool stream_release(uint8_t hwid, tu_edpt_stream_t *s) { if (s->is_host) { #if CFG_TUH_ENABLED return usbh_edpt_release(hwid, s->ep_addr); @@ -447,8 +451,9 @@ uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s) { } uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buffer, uint32_t bufsize) { - TU_VERIFY(bufsize > 0); // TODO support ZLP + TU_VERIFY(bufsize > 0); + #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED if (0 == tu_fifo_depth(&s->ff)) { // non-fifo mode TU_VERIFY(stream_claim(hwid, s), 0); @@ -464,7 +469,9 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buf TU_ASSERT(stream_xfer(hwid, s, (uint16_t) xact_len), 0); return xact_len; - } else { + } else + #endif + { const uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize); // flush if fifo has more than packet size or @@ -477,10 +484,9 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buf } } -uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t* s) { - if (tu_fifo_depth(&s->ff) > 0) { - return (uint32_t) tu_fifo_remaining(&s->ff); - } else { +uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t *s) { + #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED + if (0 == tu_fifo_depth(&s->ff)) { // non-fifo mode bool is_busy = true; if (s->is_host) { @@ -493,20 +499,28 @@ uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t* s) { #endif } return is_busy ? 0 : s->ep_bufsize; + } else + #endif + { + (void)hwid; + return (uint32_t)tu_fifo_remaining(&s->ff); } } //--------------------------------------------------------------------+ // Stream Read //--------------------------------------------------------------------+ -uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) { +uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t *s) { + #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED if (0 == tu_fifo_depth(&s->ff)) { // non-fifo mode: RX need ep buffer TU_VERIFY(s->ep_buf != NULL, 0); TU_VERIFY(stream_claim(hwid, s), 0); TU_ASSERT(stream_xfer(hwid, s, s->ep_bufsize), 0); return s->ep_bufsize; - } else { + } else + #endif + { const uint16_t mps = s->is_mps512 ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; uint16_t available = tu_fifo_remaining(&s->ff); -- cgit v1.3.1 From ae53e2f9aeada83f27deaf858449a2221f32e5cd Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Mon, 8 Dec 2025 15:43:32 +0100 Subject: remove FS MPS assumption Signed-off-by: Zixun LI --- src/common/tusb_private.h | 8 +++----- src/tusb.c | 17 ++++++++--------- 2 files changed, 11 insertions(+), 14 deletions(-) (limited to 'src/tusb.c') diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 8643bb020..6dd0fc842 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -53,15 +53,13 @@ typedef struct TU_ATTR_PACKED { }tu_edpt_state_t; typedef struct { - struct TU_ATTR_PACKED { - bool is_host : 1; // 1: host, 0: device - bool is_mps512 : 1; // 1: 512, 0: 64 since stream is used for Bulk only - }; + bool is_host; // 1: host, 0: device uint8_t ep_addr; uint16_t ep_bufsize; uint8_t *ep_buf; // set to NULL to use xfer_fifo when CFG_TUD_EDPT_DEDICATED_HWFIFO = 1 tu_fifo_t ff; + uint16_t mps; // mutex: read if rx, otherwise write OSAL_MUTEX_DEF(ff_mutexdef); @@ -101,7 +99,7 @@ bool tu_edpt_stream_deinit(tu_edpt_stream_t* s); // Open an endpoint stream TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t* s, tusb_desc_endpoint_t const *desc_ep) { s->ep_addr = desc_ep->bEndpointAddress; - s->is_mps512 = tu_edpt_packet_size(desc_ep) == 512; + s->mps = tu_edpt_packet_size(desc_ep); } TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_is_opened(const tu_edpt_stream_t *s) { diff --git a/src/tusb.c b/src/tusb.c index b6cfd1260..2f34817b0 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -415,8 +415,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool stream_release(uint8_t hwid, tu_edpt_st //--------------------------------------------------------------------+ bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t* s, uint32_t last_xferred_bytes) { // ZLP condition: no pending data, last transferred bytes is multiple of packet size - const uint16_t mps = s->is_mps512 ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; - TU_VERIFY(tu_fifo_empty(&s->ff) && last_xferred_bytes > 0 && (0 == (last_xferred_bytes & (mps - 1)))); + TU_VERIFY(tu_fifo_empty(&s->ff) && last_xferred_bytes > 0 && (0 == (last_xferred_bytes & (s->mps - 1)))); TU_VERIFY(stream_claim(hwid, s)); TU_ASSERT(stream_xfer(hwid, s, 0)); return true; @@ -469,8 +468,7 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buf // flush if fifo has more than packet size or // in rare case: fifo depth is configured too small (which never reach packet size) - const uint16_t mps = s->is_mps512 ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; - if ((tu_fifo_count(&s->ff) >= mps) || (tu_fifo_depth(&s->ff) < mps)) { + if ((tu_fifo_count(&s->ff) >= s->mps) || (tu_fifo_depth(&s->ff) < s->mps)) { tu_edpt_stream_write_xfer(hwid, s); } return ret; @@ -507,21 +505,22 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s) { TU_ASSERT(stream_xfer(hwid, s, s->ep_bufsize), 0); return s->ep_bufsize; } else { - const uint16_t mps = s->is_mps512 ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS; uint16_t available = tu_fifo_remaining(&s->ff); // Prepare for incoming data but only allow what we can store in the ring buffer. // TODO Actually we can still carry out the transfer, keeping count of received bytes // and slowly move it to the FIFO when read(). // This pre-check reduces endpoint claiming - TU_VERIFY(available >= mps); + TU_VERIFY(available >= s->mps); TU_VERIFY(stream_claim(hwid, s), 0); available = tu_fifo_remaining(&s->ff); // re-get available since fifo can be changed - if (available >= mps) { + if (available >= s->mps) { // multiple of packet size limit by ep bufsize - uint16_t count = (uint16_t) (available & ~(mps - 1)); - count = tu_min16(count, s->ep_bufsize); + uint16_t count = (uint16_t) (available & ~(s->mps - 1)); + if (s->ep_buf != NULL) { + count = tu_min16(count, s->ep_bufsize); + } TU_ASSERT(stream_xfer(hwid, s, count), 0); return count; } else { -- cgit v1.3.1 From f1fc4c9c796e25111ad8249a4dab9245f5091c25 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Dec 2025 14:45:06 +0700 Subject: change tu_fifo_clear()/tu_edpt_stream_clear() from return bool to void --- .gitignore | 4 ++-- src/class/audio/audio_device.c | 6 ++++-- src/class/cdc/cdc_device.c | 3 ++- src/class/cdc/cdc_host.c | 7 ++++--- src/common/tusb_fifo.c | 3 +-- src/common/tusb_fifo.h | 2 +- src/common/tusb_private.h | 16 +++++++++++++--- src/tusb.c | 13 ------------- 8 files changed, 27 insertions(+), 27 deletions(-) (limited to 'src/tusb.c') diff --git a/.gitignore b/.gitignore index 93d13503f..162f9a019 100644 --- a/.gitignore +++ b/.gitignore @@ -30,7 +30,8 @@ settings/ /examples/*/*/build* test_old/ tests_obsolete/ -_build +_build/ +build/ /examples/*/*/ses /examples/*/*/ozone /examples/obsolete @@ -47,7 +48,6 @@ cmake-build-* sdkconfig .PVS-Studio .vscode/ -build CMakeFiles Debug RelWithDebInfo diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 1dda8af99..77ef54222 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -485,7 +485,8 @@ uint16_t tud_audio_n_read(uint8_t func_id, void *buffer, uint16_t bufsize) { bool tud_audio_n_clear_ep_out_ff(uint8_t func_id) { TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); + tu_fifo_clear(&_audiod_fct[func_id].ep_out_ff); + return true; } tu_fifo_t *tud_audio_n_get_ep_out_ff(uint8_t func_id) { @@ -536,7 +537,8 @@ uint16_t tud_audio_n_write(uint8_t func_id, const void *data, uint16_t len) { bool tud_audio_n_clear_ep_in_ff(uint8_t func_id) { TU_VERIFY(func_id < CFG_TUD_AUDIO && _audiod_fct[func_id].p_desc != NULL); - return tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); + tu_fifo_clear(&_audiod_fct[func_id].ep_in_ff); + return true; } tu_fifo_t *tud_audio_n_get_ep_in_ff(uint8_t func_id) { diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index d7792afe4..a446782e3 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -244,7 +244,8 @@ uint32_t tud_cdc_n_write_available(uint8_t itf) { bool tud_cdc_n_write_clear(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_CDC); cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; - return tu_edpt_stream_clear(&p_cdc->stream.tx); + tu_edpt_stream_clear(&p_cdc->stream.tx); + return true; } //--------------------------------------------------------------------+ diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 35717ddf6..e069d9f71 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -482,7 +482,8 @@ uint32_t tuh_cdc_write_flush(uint8_t idx) { bool tuh_cdc_write_clear(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_clear(&p_cdc->stream.tx); + tu_edpt_stream_clear(&p_cdc->stream.tx); + return true; } uint32_t tuh_cdc_write_available(uint8_t idx) { @@ -517,9 +518,9 @@ bool tuh_cdc_read_clear (uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - bool ret = tu_edpt_stream_clear(&p_cdc->stream.rx); + tu_edpt_stream_clear(&p_cdc->stream.rx); (void)tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); - return ret; + return true; } //--------------------------------------------------------------------+ diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 06b0d6a58..1313fc328 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -84,7 +84,7 @@ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_si } // clear fifo by resetting read and write indices -bool tu_fifo_clear(tu_fifo_t *f) { +void tu_fifo_clear(tu_fifo_t *f) { ff_lock(f->mutex_wr); ff_lock(f->mutex_rd); @@ -93,7 +93,6 @@ bool tu_fifo_clear(tu_fifo_t *f) { ff_unlock(f->mutex_wr); ff_unlock(f->mutex_rd); - return true; } // Change the fifo overwritable mode diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 94ab421bb..5bc05b56c 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -158,7 +158,7 @@ typedef enum { //--------------------------------------------------------------------+ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable); bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); -bool tu_fifo_clear(tu_fifo_t *f); +void tu_fifo_clear(tu_fifo_t *f); #if OSAL_MUTEX_REQUIRED TU_ATTR_ALWAYS_INLINE static inline diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 0e9eef732..df518d5ff 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -108,7 +108,17 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize); // Deinit an endpoint stream -bool tu_edpt_stream_deinit(tu_edpt_stream_t* s); +TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_deinit(tu_edpt_stream_t *s) { + (void)s; +#if OSAL_MUTEX_REQUIRED + if (s->ff.mutex_wr) { + osal_mutex_delete(s->ff.mutex_wr); + } + if (s->ff.mutex_rd) { + osal_mutex_delete(s->ff.mutex_rd); + } +#endif +} // Open an endpoint stream TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t* s, tusb_desc_endpoint_t const *desc_ep) { @@ -124,8 +134,8 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_close(tu_edpt_stream_t* s->ep_addr = 0; } -TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_clear(tu_edpt_stream_t* s) { - return tu_fifo_clear(&s->ff); +TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_clear(tu_edpt_stream_t *s) { + tu_fifo_clear(&s->ff); } TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_empty(tu_edpt_stream_t *s) { diff --git a/src/tusb.c b/src/tusb.c index ecdd569c4..fef5b1b75 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -358,19 +358,6 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove return true; } -bool tu_edpt_stream_deinit(tu_edpt_stream_t *s) { - (void)s; - #if OSAL_MUTEX_REQUIRED - if (s->ff.mutex_wr) { - osal_mutex_delete(s->ff.mutex_wr); - } - if (s->ff.mutex_rd) { - osal_mutex_delete(s->ff.mutex_rd); - } - #endif - return true; -} - static bool stream_claim(uint8_t hwid, tu_edpt_stream_t *s) { if (s->is_host) { #if CFG_TUH_ENABLED -- cgit v1.3.1 From a165cf26b269efa396667b05f5ccedace9b528ca Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Dec 2025 15:25:30 +0700 Subject: remove tu_fifo_discard_n() and its usage --- src/class/vendor/vendor_device.c | 8 ++------ src/class/vendor/vendor_device.h | 7 ------- src/common/tusb_fifo.c | 9 --------- src/common/tusb_fifo.h | 4 ---- src/common/tusb_private.h | 12 +++--------- src/tusb.c | 4 +++- 6 files changed, 8 insertions(+), 36 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 62e183465..eb78a13c4 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -122,12 +122,6 @@ uint32_t tud_vendor_n_read(uint8_t idx, void *buffer, uint32_t bufsize) { return tu_edpt_stream_read(p_itf->rhport, &p_itf->stream.rx, buffer, bufsize); } -uint32_t tud_vendor_n_read_discard(uint8_t idx, uint32_t count) { - TU_VERIFY(idx < CFG_TUD_VENDOR, 0); - vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_discard(&p_itf->stream.rx, count); -} - void tud_vendor_n_read_flush(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, ); vendord_interface_t *p_itf = &_vendord_itf[idx]; @@ -303,8 +297,10 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint vendord_interface_t *p_vendor = &_vendord_itf[idx]; if (ep_addr == p_vendor->stream.rx.ep_addr) { + #if CFG_TUD_VENDOR_RX_BUFSIZE // Received new data: put into stream's fifo tu_edpt_stream_read_xfer_complete(&p_vendor->stream.rx, xferred_bytes); + #endif // invoke callback #if CFG_TUD_VENDOR_RX_BUFSIZE == 0 diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 764d99070..d59c885d2 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -73,9 +73,6 @@ bool tud_vendor_n_peek(uint8_t idx, uint8_t *ui8); // Read from RX FIFO uint32_t tud_vendor_n_read(uint8_t idx, void *buffer, uint32_t bufsize); -// Discard count bytes in RX FIFO -uint32_t tud_vendor_n_read_discard(uint8_t idx, uint32_t count); - // Flush (clear) RX FIFO void tud_vendor_n_read_flush(uint8_t idx); #endif @@ -124,10 +121,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_read(void *buffer, uint3 return tud_vendor_n_read(0, buffer, bufsize); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_read_discard(uint32_t count) { - return tud_vendor_n_read_discard(0, count); -} - TU_ATTR_ALWAYS_INLINE static inline void tud_vendor_read_flush(void) { tud_vendor_n_read_flush(0); } diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 1313fc328..1fca1fd32 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -450,15 +450,6 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, return n; } -uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n) { - const uint16_t count = tu_min16(n, tu_fifo_count(f)); // limit to available count - ff_lock(f->mutex_rd); - f->rd_idx = advance_index(f->depth, f->rd_idx, count); - ff_unlock(f->mutex_rd); - - return count; -} - //--------------------------------------------------------------------+ // One API //--------------------------------------------------------------------+ diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 5bc05b56c..26ac38073 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -205,10 +205,6 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_read_n(tu_fifo_t *f, void * return tu_fifo_read_n_access_mode(f, buffer, n, TU_FIFO_INC_ADDR_RW8); } -// discard first n items from fifo i.e advance read pointer by n with mutex -// return number of discarded items -uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); - //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index df518d5ff..dc62ae848 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -172,17 +172,15 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s); // Complete read transfer by writing EP -> FIFO. Must be called in the transfer complete callback TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) { - if (0u != tu_fifo_depth(&s->ff) && s->ep_buf != NULL) { - tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t) xferred_bytes); + if (s->ep_buf != NULL) { + tu_fifo_write_n(&s->ff, s->ep_buf, (uint16_t)xferred_bytes); } } // Complete read transfer with provided buffer TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_read_xfer_complete_with_buf(tu_edpt_stream_t *s, const void *buf, uint32_t xferred_bytes) { - if (0u != tu_fifo_depth(&s->ff)) { - tu_fifo_write_n(&s->ff, buf, (uint16_t) xferred_bytes); - } + tu_fifo_write_n(&s->ff, buf, (uint16_t)xferred_bytes); } // Get the number of bytes available for reading @@ -194,10 +192,6 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_peek(tu_edpt_stream_t *s return tu_fifo_peek(&s->ff, ch); } -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_edpt_stream_discard(tu_edpt_stream_t *s, uint32_t len) { - return (uint32_t)tu_fifo_discard_n(&s->ff, (uint16_t)len); -} - #ifdef __cplusplus } #endif diff --git a/src/tusb.c b/src/tusb.c index fef5b1b75..8bb1ddeff 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -338,9 +338,11 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize) { (void) is_tx; - if (CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED == 0 && (ff_buf == NULL || ff_bufsize == 0)) { + #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED == 0 // FIFO is required + if (ff_buf == NULL || ff_bufsize == 0) { return false; } + #endif s->is_host = is_host; tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable); -- cgit v1.3.1 From 8d0fda879b68e0d5f905590ec1ae5124e4054e48 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Dec 2025 18:49:39 +0700 Subject: only validate endpoint tu_edpt_validate() when debug enabled --- src/common/tusb_private.h | 14 ++++++++++++-- src/tusb.c | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/tusb.c') diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index dc62ae848..cc5c7d46a 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -62,7 +62,7 @@ typedef struct TU_ATTR_PACKED { volatile uint8_t busy : 1; volatile uint8_t stalled : 1; volatile uint8_t claimed : 1; -}tu_edpt_state_t; +} tu_edpt_state_t; typedef struct { struct TU_ATTR_PACKED { @@ -84,8 +84,18 @@ typedef struct { // Endpoint //--------------------------------------------------------------------+ -// Check if endpoint descriptor is valid per USB specs +// Check if endpoint descriptor is valid per USB specs if debug is enabled +#if CFG_TUSB_DEBUG bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed, bool is_host); +#else +TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_validate(tusb_desc_endpoint_t const *desc_ep, tusb_speed_t speed, + bool is_host) { + (void)desc_ep; + (void)speed; + (void)is_host; + return true; +} +#endif // Bind all endpoint of a interface descriptor to class driver void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); diff --git a/src/tusb.c b/src/tusb.c index 8bb1ddeff..959c2ce1d 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -241,6 +241,7 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { return ret; } +#if CFG_TUSB_DEBUG bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed, bool is_host) { uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); @@ -283,6 +284,7 @@ bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed, b return true; } +#endif void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id) { -- cgit v1.3.1 From 39853dfb25c8828490e197ad4c1dd9616949110a Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 10 Dec 2025 20:47:08 +0700 Subject: move hwid into edpt stream for consistent API --- src/class/cdc/cdc_device.c | 33 ++++++++-------- src/class/cdc/cdc_host.c | 20 +++++----- src/class/midi/midi_device.c | 35 +++++++++-------- src/class/midi/midi_host.c | 32 ++++++++-------- src/class/vendor/vendor_device.c | 29 +++++++------- src/common/tusb_private.h | 28 +++++++------- src/device/usbd.c | 14 +++---- src/tusb.c | 83 ++++++++++++++++++++-------------------- 8 files changed, 139 insertions(+), 135 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index dfdee8bd4..8ea4080cc 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -203,7 +203,7 @@ uint32_t tud_cdc_n_available(uint8_t itf) { uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) { TU_VERIFY(itf < CFG_TUD_CDC, 0); cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; - return tu_edpt_stream_read(p_cdc->rhport, &p_cdc->rx_stream, buffer, bufsize); + return tu_edpt_stream_read(&p_cdc->rx_stream, buffer, bufsize); } bool tud_cdc_n_peek(uint8_t itf, uint8_t *chr) { @@ -215,7 +215,7 @@ void tud_cdc_n_read_flush(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_CDC, ); cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; tu_edpt_stream_clear(&p_cdc->rx_stream); - tu_edpt_stream_read_xfer(p_cdc->rhport, &p_cdc->rx_stream); + tu_edpt_stream_read_xfer(&p_cdc->rx_stream); } //--------------------------------------------------------------------+ @@ -224,19 +224,19 @@ void tud_cdc_n_read_flush(uint8_t itf) { uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) { TU_VERIFY(itf < CFG_TUD_CDC, 0); cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; - return tu_edpt_stream_write(p_cdc->rhport, &p_cdc->tx_stream, buffer, bufsize); + return tu_edpt_stream_write(&p_cdc->tx_stream, buffer, bufsize); } uint32_t tud_cdc_n_write_flush(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_CDC, 0); cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; - return tu_edpt_stream_write_xfer(p_cdc->rhport, &p_cdc->tx_stream); + return tu_edpt_stream_write_xfer(&p_cdc->tx_stream); } uint32_t tud_cdc_n_write_available(uint8_t itf) { TU_VERIFY(itf < CFG_TUD_CDC, 0); cdcd_interface_t *p_cdc = &_cdcd_itf[itf]; - return tu_edpt_stream_write_available(p_cdc->rhport, &p_cdc->tx_stream); + return tu_edpt_stream_write_available(&p_cdc->tx_stream); } bool tud_cdc_n_write_clear(uint8_t itf) { @@ -269,14 +269,14 @@ void cdcd_init(void) { uint8_t *epin_buf = _cdcd_epbuf[i].epin; #endif - tu_edpt_stream_init(&p_cdc->rx_stream, false, false, false, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, - epout_buf, CFG_TUD_CDC_EP_BUFSIZE); + tu_edpt_stream_init(&p_cdc->rx_stream, false, false, false, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, epout_buf, + CFG_TUD_CDC_EP_BUFSIZE); // TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not // know if data is actually polled by terminal. This way the most current data is prioritized. // Default: is overwritable - tu_edpt_stream_init(&p_cdc->tx_stream, false, true, _cdcd_cfg.tx_overwritabe_if_not_connected, - p_cdc->tx_ff_buf, CFG_TUD_CDC_TX_BUFSIZE, epin_buf, CFG_TUD_CDC_EP_BUFSIZE); + tu_edpt_stream_init(&p_cdc->tx_stream, false, true, _cdcd_cfg.tx_overwritabe_if_not_connected, p_cdc->tx_ff_buf, + CFG_TUD_CDC_TX_BUFSIZE, epin_buf, CFG_TUD_CDC_EP_BUFSIZE); } } @@ -351,20 +351,20 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16 if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { tu_edpt_stream_t *stream_tx = &p_cdc->tx_stream; - tu_edpt_stream_open(stream_tx, desc_ep); + tu_edpt_stream_open(stream_tx, rhport, desc_ep); if (_cdcd_cfg.tx_persistent) { - tu_edpt_stream_write_xfer(rhport, stream_tx); // flush pending data + tu_edpt_stream_write_xfer(stream_tx); // flush pending data } else { tu_edpt_stream_clear(stream_tx); } } else { tu_edpt_stream_t *stream_rx = &p_cdc->rx_stream; - tu_edpt_stream_open(stream_rx, desc_ep); + tu_edpt_stream_open(stream_rx, rhport, desc_ep); if (!_cdcd_cfg.rx_persistent) { tu_edpt_stream_clear(stream_rx); } - TU_ASSERT(tu_edpt_stream_read_xfer(rhport, stream_rx) > 0, 0); // prepare for incoming data + TU_ASSERT(tu_edpt_stream_read_xfer(stream_rx) > 0, 0); // prepare for incoming data } } @@ -460,6 +460,7 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ } bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void)rhport; (void)result; uint8_t itf = find_cdc_itf(ep_addr); @@ -510,7 +511,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ tud_cdc_rx_cb(itf); } - tu_edpt_stream_read_xfer(rhport, stream_rx); // prepare for more data + tu_edpt_stream_read_xfer(stream_rx); // prepare for more data } // Data sent to host, we continue to fetch from tx fifo to send. @@ -518,9 +519,9 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ if (ep_addr == stream_tx->ep_addr) { tud_cdc_tx_complete_cb(itf); // invoke callback to possibly refill tx fifo - if (0 == tu_edpt_stream_write_xfer(rhport, stream_tx)) { + if (0 == tu_edpt_stream_write_xfer(stream_tx)) { // If there is no data left, a ZLP should be sent if needed - tu_edpt_stream_write_zlp_if_needed(rhport, stream_tx, xferred_bytes); + tu_edpt_stream_write_zlp_if_needed(stream_tx, xferred_bytes); } } diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index e069d9f71..28abbf098 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -470,13 +470,13 @@ bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t * line_coding) uint32_t tuh_cdc_write(uint8_t idx, void const * buffer, uint32_t bufsize) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write(p_cdc->daddr, &p_cdc->stream.tx, buffer, bufsize); + return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize); } uint32_t tuh_cdc_write_flush(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write_xfer(p_cdc->daddr, &p_cdc->stream.tx); + return tu_edpt_stream_write_xfer(&p_cdc->stream.tx); } bool tuh_cdc_write_clear(uint8_t idx) { @@ -489,7 +489,7 @@ bool tuh_cdc_write_clear(uint8_t idx) { uint32_t tuh_cdc_write_available(uint8_t idx) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_write_available(p_cdc->daddr, &p_cdc->stream.tx); + return tu_edpt_stream_write_available(&p_cdc->stream.tx); } //--------------------------------------------------------------------+ @@ -499,7 +499,7 @@ uint32_t tuh_cdc_write_available(uint8_t idx) { uint32_t tuh_cdc_read (uint8_t idx, void * buffer, uint32_t bufsize) { cdch_interface_t * p_cdc = get_itf(idx); TU_VERIFY(p_cdc); - return tu_edpt_stream_read(p_cdc->daddr, &p_cdc->stream.rx, buffer, bufsize); + return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize); } uint32_t tuh_cdc_read_available(uint8_t idx) { @@ -519,7 +519,7 @@ bool tuh_cdc_read_clear (uint8_t idx) { TU_VERIFY(p_cdc); tu_edpt_stream_clear(&p_cdc->stream.rx); - (void)tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); + (void)tu_edpt_stream_read_xfer(&p_cdc->stream.rx); return true; } @@ -693,10 +693,10 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t if (ep_addr == p_cdc->stream.tx.ep_addr) { tuh_cdc_tx_complete_cb(idx); // invoke transmit complete callback - if (0 == tu_edpt_stream_write_xfer(daddr, &p_cdc->stream.tx)) { + if (0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx)) { // If there is no data left, a ZLP should be sent if: // - xferred_bytes is multiple of EP Packet size and not zero - (void)tu_edpt_stream_write_zlp_if_needed(daddr, &p_cdc->stream.tx, xferred_bytes); + (void)tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes); } } else if (ep_addr == p_cdc->stream.rx.ep_addr) { #if CFG_TUH_CDC_FTDI @@ -716,7 +716,7 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t } // prepare for next transfer if needed - tu_edpt_stream_read_xfer(daddr, &p_cdc->stream.rx); + tu_edpt_stream_read_xfer(&p_cdc->stream.rx); } else if (ep_addr == p_cdc->ep_notif) { // TODO handle notification endpoint } else { @@ -736,7 +736,7 @@ static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t co TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep)); tu_edpt_stream_t *stream = (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) ? &p_cdc->stream.rx : &p_cdc->stream.tx; - tu_edpt_stream_open(stream, desc_ep); + tu_edpt_stream_open(stream, p_cdc->daddr, desc_ep); tu_edpt_stream_clear(stream); desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(desc_ep); @@ -799,7 +799,7 @@ static void set_config_complete(cdch_interface_t *p_cdc, bool success) { p_cdc->mounted = true; tuh_cdc_mount_cb(idx); // Prepare for incoming data - tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx); + tu_edpt_stream_read_xfer(&p_cdc->stream.rx); } else { // clear the interface entry p_cdc->daddr = 0; diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 8d1dc7d4a..e0a5aa9c3 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -172,7 +172,7 @@ bool tud_midi_n_packet_read(uint8_t itf, uint8_t packet[4]) { midid_interface_t *p_midi = &_midid_itf[itf]; tu_edpt_stream_t *ep_str = &p_midi->ep_stream.rx; TU_VERIFY(tu_edpt_stream_is_opened(ep_str)); - return 4 == tu_edpt_stream_read(p_midi->rhport, ep_str, packet, 4); + return 4 == tu_edpt_stream_read(ep_str, packet, 4); } uint32_t tud_midi_n_packet_read_n(uint8_t itf, uint8_t packets[], uint32_t max_packets) { @@ -180,7 +180,7 @@ uint32_t tud_midi_n_packet_read_n(uint8_t itf, uint8_t packets[], uint32_t max_p tu_edpt_stream_t *ep_str = &p_midi->ep_stream.rx; TU_VERIFY(tu_edpt_stream_is_opened(ep_str), 0); - const uint32_t num_read = tu_edpt_stream_read(p_midi->rhport, ep_str, packets, 4u * max_packets); + const uint32_t num_read = tu_edpt_stream_read(ep_str, packets, 4u * max_packets); return num_read >> 2u; } @@ -195,7 +195,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t * uint32_t i = 0; while (i < bufsize) { - if (tu_edpt_stream_write_available(p_midi->rhport, ep_str) < 4) { + if (tu_edpt_stream_write_available(ep_str) < 4) { break; } @@ -268,7 +268,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t * stream->buffer[idx] = 0; } - const uint32_t count = tu_edpt_stream_write(p_midi->rhport, ep_str, stream->buffer, 4); + const uint32_t count = tu_edpt_stream_write(ep_str, stream->buffer, 4); // complete current event packet, reset stream stream->index = stream->total = 0; @@ -278,7 +278,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t * } } - (void)tu_edpt_stream_write_xfer(p_midi->rhport, ep_str); + (void)tu_edpt_stream_write_xfer(ep_str); return i; } @@ -288,9 +288,9 @@ bool tud_midi_n_packet_write (uint8_t itf, const uint8_t packet[4]) { tu_edpt_stream_t *ep_str = &p_midi->ep_stream.tx; TU_VERIFY(tu_edpt_stream_is_opened(ep_str)); - TU_VERIFY(tu_edpt_stream_write_available(p_midi->rhport, ep_str) >= 4); - TU_VERIFY(tu_edpt_stream_write(p_midi->rhport, ep_str, packet, 4) > 0); - (void)tu_edpt_stream_write_xfer(p_midi->rhport, ep_str); + TU_VERIFY(tu_edpt_stream_write_available(ep_str) >= 4); + TU_VERIFY(tu_edpt_stream_write(ep_str, packet, 4) > 0); + (void)tu_edpt_stream_write_xfer(ep_str); return true; } @@ -300,11 +300,11 @@ uint32_t tud_midi_n_packet_write_n(uint8_t itf, const uint8_t packets[], uint32_ tu_edpt_stream_t *ep_str = &p_midi->ep_stream.tx; TU_VERIFY(tu_edpt_stream_is_opened(ep_str), 0); - uint32_t n_bytes = tu_edpt_stream_write_available(p_midi->rhport, ep_str); + uint32_t n_bytes = tu_edpt_stream_write_available(ep_str); n_bytes = tu_min32(tu_align4(n_bytes), n_packets << 2u); - const uint32_t n_write = tu_edpt_stream_write(p_midi->rhport, ep_str, packets, n_bytes); - (void)tu_edpt_stream_write_xfer(p_midi->rhport, ep_str); + const uint32_t n_write = tu_edpt_stream_write(ep_str, packets, n_bytes); + (void)tu_edpt_stream_write_xfer(ep_str); return n_write >> 2u; } @@ -411,13 +411,13 @@ uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uint1 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { tu_edpt_stream_t *stream_tx = &p_midi->ep_stream.tx; - tu_edpt_stream_open(stream_tx, desc_ep); + tu_edpt_stream_open(stream_tx, rhport, desc_ep); tu_edpt_stream_clear(stream_tx); } else { tu_edpt_stream_t *stream_rx = &p_midi->ep_stream.rx; - tu_edpt_stream_open(stream_rx, desc_ep); + tu_edpt_stream_open(stream_rx, rhport, desc_ep); tu_edpt_stream_clear(stream_rx); - TU_ASSERT(tu_edpt_stream_read_xfer(rhport, stream_rx) > 0, 0); // prepare to receive data + TU_ASSERT(tu_edpt_stream_read_xfer(stream_rx) > 0, 0); // prepare to receive data } p_desc = tu_desc_next(p_desc); // skip CS Endpoint descriptor @@ -439,6 +439,7 @@ bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_req } bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void)rhport; (void)result; uint8_t idx = find_midi_itf(ep_addr); @@ -454,12 +455,12 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32 tu_edpt_stream_read_xfer_complete(ep_st_rx, xferred_bytes); tud_midi_rx_cb(idx); // invoke callback } - tu_edpt_stream_read_xfer(rhport, ep_st_rx); // prepare for next data + tu_edpt_stream_read_xfer(ep_st_rx); // prepare for next data } else if (ep_addr == ep_st_tx->ep_addr && result == XFER_RESULT_SUCCESS) { // sent complete: try to send more if possible - if (0 == tu_edpt_stream_write_xfer(rhport, ep_st_tx)) { + if (0 == tu_edpt_stream_write_xfer(ep_st_tx)) { // If there is no data left, a ZLP should be sent if needed - (void)tu_edpt_stream_write_zlp_if_needed(rhport, ep_st_tx, xferred_bytes); + (void)tu_edpt_stream_write_zlp_if_needed(ep_st_tx, xferred_bytes); } } else { return false; diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 07062875c..b4f5ac445 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -175,14 +175,14 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint tuh_midi_rx_cb(idx, xferred_bytes); } - tu_edpt_stream_read_xfer(dev_addr, ep_str_rx); // prepare for next transfer + tu_edpt_stream_read_xfer(ep_str_rx); // prepare for next transfer } else if (ep_addr == ep_str_tx->ep_addr) { tuh_midi_tx_cb(idx, xferred_bytes); - if (0 == tu_edpt_stream_write_xfer(dev_addr, ep_str_tx)) { + if (0 == tu_edpt_stream_write_xfer(ep_str_tx)) { // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - tu_edpt_stream_write_zlp_if_needed(dev_addr, ep_str_tx, xferred_bytes); + tu_edpt_stream_write_zlp_if_needed(ep_str_tx, xferred_bytes); } } @@ -303,7 +303,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d ep_stream = &p_midi->ep_stream.rx; } TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); - tu_edpt_stream_open(ep_stream, p_ep); + tu_edpt_stream_open(ep_stream, dev_addr, p_ep); tu_edpt_stream_clear(ep_stream); break; @@ -335,7 +335,7 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { }; tuh_midi_mount_cb(idx, &mount_cb_data); - tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for incoming data + tu_edpt_stream_read_xfer(&p_midi->ep_stream.rx); // prepare for incoming data // No special config things to do for MIDI usbh_driver_set_config_complete(dev_addr, p_midi->bInterfaceNumber); @@ -414,7 +414,7 @@ uint32_t tuh_midi_read_available(uint8_t idx) { uint32_t tuh_midi_write_flush(uint8_t idx) { TU_VERIFY(idx < CFG_TUH_MIDI); midih_interface_t *p_midi = &_midi_host[idx]; - return tu_edpt_stream_write_xfer(p_midi->daddr, &p_midi->ep_stream.tx); + return tu_edpt_stream_write_xfer(&p_midi->ep_stream.tx); } //--------------------------------------------------------------------+ @@ -427,7 +427,7 @@ uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t* buffer, uint32_t bufsize) uint32_t count4 = tu_min32(bufsize, tu_edpt_stream_read_available(&p_midi->ep_stream.rx)); count4 = tu_align4(count4); // round down to multiple of 4 TU_VERIFY(count4 > 0, 0); - return tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, buffer, count4); + return tu_edpt_stream_read(&p_midi->ep_stream.rx, buffer, count4); } uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bufsize) { @@ -436,7 +436,7 @@ uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bu const uint32_t bufsize4 = tu_align4(bufsize); TU_VERIFY(bufsize4 > 0, 0); - return tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, buffer, bufsize4); + return tu_edpt_stream_write(&p_midi->ep_stream.tx, buffer, bufsize4); } //--------------------------------------------------------------------+ @@ -450,8 +450,8 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu midi_driver_stream_t *stream = &p_midi->stream_write; uint32_t byte_count = 0; - while ((byte_count < bufsize) && (tu_edpt_stream_write_available(p_midi->daddr, &p_midi->ep_stream.tx) >= 4)) { - uint8_t const data = buffer[byte_count]; + while ((byte_count < bufsize) && (tu_edpt_stream_write_available(&p_midi->ep_stream.tx) >= 4)) { + const uint8_t data = buffer[byte_count]; byte_count++; if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) { // real-time messages need to be sent right away @@ -460,7 +460,7 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu streamrt.buffer[1] = data; streamrt.index = 2; streamrt.total = 2; - uint32_t const count = tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, streamrt.buffer, 4); + const uint32_t count = tu_edpt_stream_write(&p_midi->ep_stream.tx, streamrt.buffer, 4); TU_ASSERT(count == 4, byte_count); // Check FIFO overflown, since we already check fifo remaining. It is probably race condition } else if (stream->index == 0) { //------------- New event packet -------------// @@ -529,7 +529,7 @@ uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *bu } TU_LOG3_MEM(stream->buffer, 4, 2); - const uint32_t count = tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, stream->buffer, 4); + const uint32_t count = tu_edpt_stream_write(&p_midi->ep_stream.tx, stream->buffer, 4); // complete current event packet, reset stream stream->index = 0; @@ -551,7 +551,7 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff return 0; } *p_cable_num = (one_byte >> 4) & 0xf; - uint32_t nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + uint32_t nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); static uint16_t cable_sysex_in_progress;// bit i is set if received MIDI_STATUS_SYSEX_START but not MIDI_STATUS_SYSEX_END while (nread == 4 && bytes_buffered < bufsize) { *p_cable_num = (p_midi->stream_read.buffer[0] >> 4) & 0x0f; @@ -579,7 +579,7 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff } else { // bad packet discard - nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); continue; } } else if (status < MIDI_STATUS_SYSEX_START) { @@ -626,7 +626,7 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff } else { // bad packet discard - nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); continue; } @@ -639,7 +639,7 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff uint8_t new_cable = (one_byte >> 4) & 0xf; if (new_cable == *p_cable_num) { // still on the same cable. Continue reading the stream - nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); } } } diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index eb78a13c4..9972911e0 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -119,14 +119,14 @@ bool tud_vendor_n_peek(uint8_t idx, uint8_t *u8) { uint32_t tud_vendor_n_read(uint8_t idx, void *buffer, uint32_t bufsize) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_read(p_itf->rhport, &p_itf->stream.rx, buffer, bufsize); + return tu_edpt_stream_read(&p_itf->stream.rx, buffer, bufsize); } void tud_vendor_n_read_flush(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, ); vendord_interface_t *p_itf = &_vendord_itf[idx]; tu_edpt_stream_clear(&p_itf->stream.rx); - tu_edpt_stream_read_xfer(p_itf->rhport, &p_itf->stream.rx); + tu_edpt_stream_read_xfer(&p_itf->stream.rx); } #endif @@ -134,7 +134,7 @@ void tud_vendor_n_read_flush(uint8_t idx) { bool tud_vendor_n_read_xfer(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_read_xfer(p_itf->rhport, &p_itf->stream.rx); + return tu_edpt_stream_read_xfer(&p_itf->stream.rx); } #endif @@ -145,20 +145,20 @@ bool tud_vendor_n_read_xfer(uint8_t idx) { uint32_t tud_vendor_n_write(uint8_t idx, const void *buffer, uint32_t bufsize) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_write(p_itf->rhport, &p_itf->stream.tx, buffer, (uint16_t)bufsize); + return tu_edpt_stream_write(&p_itf->stream.tx, buffer, (uint16_t)bufsize); } #if CFG_TUD_VENDOR_TX_BUFSIZE > 0 uint32_t tud_vendor_n_write_flush(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_write_xfer(p_itf->rhport, &p_itf->stream.tx); + return tu_edpt_stream_write_xfer(&p_itf->stream.tx); } uint32_t tud_vendor_n_write_available(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_write_available(p_itf->rhport, &p_itf->stream.tx); + return tu_edpt_stream_write_available(&p_itf->stream.tx); } #endif @@ -270,15 +270,15 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uin if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { tu_edpt_stream_t *stream_tx = &p_vendor->stream.tx; if (stream_tx->ep_addr == 0) { - tu_edpt_stream_open(stream_tx, desc_ep); - tu_edpt_stream_write_xfer(rhport, stream_tx); // flush pending data + tu_edpt_stream_open(stream_tx, rhport, desc_ep); + tu_edpt_stream_write_xfer(stream_tx); // flush pending data } } else { tu_edpt_stream_t *stream_rx = &p_vendor->stream.rx; if (stream_rx->ep_addr == 0) { - tu_edpt_stream_open(stream_rx, desc_ep); + tu_edpt_stream_open(stream_rx, rhport, desc_ep); #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 - TU_ASSERT(tu_edpt_stream_read_xfer(rhport, stream_rx) > 0, 0); // prepare for incoming data + TU_ASSERT(tu_edpt_stream_read_xfer(stream_rx) > 0, 0); // prepare for incoming data #endif } } @@ -291,7 +291,8 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uin } bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) result; + (void)rhport; + (void)result; const uint8_t idx = find_vendor_itf(ep_addr); TU_VERIFY(idx < CFG_TUD_VENDOR); vendord_interface_t *p_vendor = &_vendord_itf[idx]; @@ -310,7 +311,7 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint #endif #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 - tu_edpt_stream_read_xfer(rhport, &p_vendor->stream.rx); // prepare next data + tu_edpt_stream_read_xfer(&p_vendor->stream.rx); // prepare next data #endif } else if (ep_addr == p_vendor->stream.tx.ep_addr) { // Send complete @@ -318,9 +319,9 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint #if CFG_TUD_VENDOR_TX_BUFSIZE > 0 // try to send more if possible - if (0 == tu_edpt_stream_write_xfer(rhport, &p_vendor->stream.tx)) { + if (0 == tu_edpt_stream_write_xfer(&p_vendor->stream.tx)) { // If there is no data left, a ZLP should be sent if xferred_bytes is multiple of EP Packet size and not zero - tu_edpt_stream_write_zlp_if_needed(rhport, &p_vendor->stream.tx, xferred_bytes); + tu_edpt_stream_write_zlp_if_needed(&p_vendor->stream.tx, xferred_bytes); } #endif } diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 69e82cda1..5cea7b5a0 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -65,17 +65,17 @@ typedef struct TU_ATTR_PACKED { } tu_edpt_state_t; typedef struct { - bool is_host; // 1: host, 0: device + uint8_t hwid; // device: rhport, host: daddr + bool is_host; // 1: host, 0: device uint8_t ep_addr; - uint16_t ep_bufsize; + uint16_t mps; + uint16_t ep_bufsize; uint8_t *ep_buf; // set to NULL to use xfer_fifo when CFG_TUD_EDPT_DEDICATED_HWFIFO = 1 tu_fifo_t ff; - uint16_t mps; // mutex: read if rx, otherwise write OSAL_MUTEX_DEF(ff_mutexdef); - }tu_edpt_stream_t; //--------------------------------------------------------------------+ @@ -112,8 +112,8 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex); //--------------------------------------------------------------------+ // Init an endpoint stream -bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable, - void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize); +bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool overwritable, void *ff_buf, + uint16_t ff_bufsize, uint8_t *ep_buf, uint16_t ep_bufsize); // Deinit an endpoint stream TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_deinit(tu_edpt_stream_t *s) { @@ -129,7 +129,9 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_deinit(tu_edpt_stream_t } // Open an endpoint stream -TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t* s, tusb_desc_endpoint_t const *desc_ep) { +TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t *s, uint8_t hwid, + const tusb_desc_endpoint_t *desc_ep) { + s->hwid = hwid; s->ep_addr = desc_ep->bEndpointAddress; s->mps = tu_edpt_packet_size(desc_ep); } @@ -155,27 +157,27 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_empty(tu_edpt_stream_t * //--------------------------------------------------------------------+ // Write to stream -uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t* s, void const *buffer, uint32_t bufsize); +uint32_t tu_edpt_stream_write(tu_edpt_stream_t *s, const void *buffer, uint32_t bufsize); // Start an usb transfer if endpoint is not busy. Return number of queued bytes -uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s); +uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t *s); // Start an zero-length packet if needed -bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t* s, uint32_t last_xferred_bytes); +bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t *s, uint32_t last_xferred_bytes); // Get the number of bytes available for writing to FIFO // Note: if no fifo, return endpoint size if not busy, 0 otherwise -uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t* s); +uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t *s); //--------------------------------------------------------------------+ // Stream Read //--------------------------------------------------------------------+ // Read from stream -uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, uint32_t bufsize); +uint32_t tu_edpt_stream_read(tu_edpt_stream_t *s, void *buffer, uint32_t bufsize); // Start an usb transfer if endpoint is not busy -uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s); +uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t *s); // Complete read transfer by writing EP -> FIFO. Must be called in the transfer complete callback TU_ATTR_ALWAYS_INLINE static inline diff --git a/src/device/usbd.c b/src/device/usbd.c index 86cbcac26..80d9fee3e 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -503,9 +503,9 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; // skip if already initialized } TU_ASSERT(rh_init); -#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL + #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL char const* speed_str = 0; - switch (rh_init->speed) { + switch (rh_init->speed) { case TUSB_SPEED_HIGH: speed_str = "High"; break; @@ -651,7 +651,9 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { } #if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL - if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG_USBD("\r\n"); // extra line for setup + if (event.event_id == DCD_EVENT_SETUP_RECEIVED) { + TU_LOG_USBD("\r\n"); // extra line for setup + } TU_LOG_USBD("USBD %s ", event.event_id < DCD_EVENT_COUNT ? _usbd_event_str[event.event_id] : "CORRUPTED"); #endif @@ -1047,7 +1049,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { while (p_desc < desc_end) { uint8_t assoc_itf_count = 1; - // Class will always starts with Interface Association (if any) and then Interface descriptor + // Class will always start with Interface Association (if any) and then Interface descriptor if (TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc)) { const tusb_desc_interface_assoc_t *desc_iad = (const tusb_desc_interface_assoc_t *)p_desc; @@ -1136,9 +1138,7 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { // bind all endpoints to found driver tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); - // next Interface - p_desc += drv_len; - + p_desc += drv_len; // next Interface break; // exit driver find loop } } diff --git a/src/tusb.c b/src/tusb.c index fc1ef7e1a..14b388d04 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -336,8 +336,8 @@ uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, // Endpoint Stream Helper for both Host and Device stack //--------------------------------------------------------------------+ -bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool overwritable, - void* ff_buf, uint16_t ff_bufsize, uint8_t* ep_buf, uint16_t ep_bufsize) { +bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool overwritable, void *ff_buf, + uint16_t ff_bufsize, uint8_t *ep_buf, uint16_t ep_bufsize) { (void) is_tx; #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED == 0 // FIFO is required @@ -362,45 +362,45 @@ bool tu_edpt_stream_init(tu_edpt_stream_t* s, bool is_host, bool is_tx, bool ove return true; } -static bool stream_claim(uint8_t hwid, tu_edpt_stream_t *s) { +static bool stream_claim(tu_edpt_stream_t *s) { if (s->is_host) { #if CFG_TUH_ENABLED - return usbh_edpt_claim(hwid, s->ep_addr); - #endif + return usbh_edpt_claim(s->hwid, s->ep_addr); + #endif } else { #if CFG_TUD_ENABLED - return usbd_edpt_claim(hwid, s->ep_addr); - #endif + return usbd_edpt_claim(s->hwid, s->ep_addr); + #endif } return false; } -static bool stream_xfer(uint8_t hwid, tu_edpt_stream_t *s, uint16_t count) { +static bool stream_xfer(tu_edpt_stream_t *s, uint16_t count) { if (s->is_host) { #if CFG_TUH_ENABLED - return usbh_edpt_xfer(hwid, s->ep_addr, count ? s->ep_buf : NULL, count); - #endif + return usbh_edpt_xfer(s->hwid, s->ep_addr, count ? s->ep_buf : NULL, count); + #endif } else { #if CFG_TUD_ENABLED if (s->ep_buf == NULL) { - return usbd_edpt_xfer_fifo(hwid, s->ep_addr, &s->ff, count, false); + return usbd_edpt_xfer_fifo(s->hwid, s->ep_addr, &s->ff, count, false); } else { - return usbd_edpt_xfer(hwid, s->ep_addr, count ? s->ep_buf : NULL, count, false); + return usbd_edpt_xfer(s->hwid, s->ep_addr, count ? s->ep_buf : NULL, count, false); } #endif } return false; } -static bool stream_release(uint8_t hwid, tu_edpt_stream_t *s) { +static bool stream_release(tu_edpt_stream_t *s) { if (s->is_host) { #if CFG_TUH_ENABLED - return usbh_edpt_release(hwid, s->ep_addr); - #endif + return usbh_edpt_release(s->hwid, s->ep_addr); + #endif } else { #if CFG_TUD_ENABLED - return usbd_edpt_release(hwid, s->ep_addr); - #endif + return usbd_edpt_release(s->hwid, s->ep_addr); + #endif } return false; } @@ -408,18 +408,18 @@ static bool stream_release(uint8_t hwid, tu_edpt_stream_t *s) { //--------------------------------------------------------------------+ // Stream Write //--------------------------------------------------------------------+ -bool tu_edpt_stream_write_zlp_if_needed(uint8_t hwid, tu_edpt_stream_t* s, uint32_t last_xferred_bytes) { +bool tu_edpt_stream_write_zlp_if_needed(tu_edpt_stream_t *s, uint32_t last_xferred_bytes) { // ZLP condition: no pending data, last transferred bytes is multiple of packet size TU_VERIFY(tu_fifo_empty(&s->ff) && last_xferred_bytes > 0 && (0 == (last_xferred_bytes & (s->mps - 1)))); - TU_VERIFY(stream_claim(hwid, s)); - TU_ASSERT(stream_xfer(hwid, s, 0)); + TU_VERIFY(stream_claim(s)); + TU_ASSERT(stream_xfer(s, 0)); return true; } -uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s) { +uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t *s) { const uint16_t ff_count = tu_fifo_count(&s->ff); TU_VERIFY(ff_count > 0, 0); // skip if no data - TU_VERIFY(stream_claim(hwid, s), 0); + TU_VERIFY(stream_claim(s), 0); // Pull data from FIFO -> EP buf uint16_t count; @@ -430,23 +430,23 @@ uint32_t tu_edpt_stream_write_xfer(uint8_t hwid, tu_edpt_stream_t* s) { } if (count > 0) { - TU_ASSERT(stream_xfer(hwid, s, count), 0); + TU_ASSERT(stream_xfer(s, count), 0); return count; } else { // Release endpoint since we don't make any transfer // Note: data is dropped if terminal is not connected - stream_release(hwid, s); + stream_release(s); return 0; } } -uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buffer, uint32_t bufsize) { +uint32_t tu_edpt_stream_write(tu_edpt_stream_t *s, const void *buffer, uint32_t bufsize) { TU_VERIFY(bufsize > 0); #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED if (0 == tu_fifo_depth(&s->ff)) { // non-fifo mode - TU_VERIFY(stream_claim(hwid, s), 0); + TU_VERIFY(stream_claim(s), 0); uint32_t xact_len; if (s->ep_buf != NULL) { // using ep buf @@ -456,7 +456,7 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buf // using hwfifo xact_len = bufsize; } - TU_ASSERT(stream_xfer(hwid, s, (uint16_t) xact_len), 0); + TU_ASSERT(stream_xfer(s, (uint16_t)xact_len), 0); return xact_len; } else @@ -467,31 +467,30 @@ uint32_t tu_edpt_stream_write(uint8_t hwid, tu_edpt_stream_t *s, const void *buf // flush if fifo has more than packet size or // in rare case: fifo depth is configured too small (which never reach packet size) if ((tu_fifo_count(&s->ff) >= s->mps) || (tu_fifo_depth(&s->ff) < s->mps)) { - tu_edpt_stream_write_xfer(hwid, s); + tu_edpt_stream_write_xfer(s); } return ret; } } -uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t *s) { +uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t *s) { #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED if (0 == tu_fifo_depth(&s->ff)) { // non-fifo mode bool is_busy = true; if (s->is_host) { #if CFG_TUH_ENABLED - is_busy = usbh_edpt_busy(hwid, s->ep_addr); - #endif + is_busy = usbh_edpt_busy(s->hwid, s->ep_addr); + #endif } else { #if CFG_TUD_ENABLED - is_busy = usbd_edpt_busy(hwid, s->ep_addr); - #endif + is_busy = usbd_edpt_busy(s->hwid, s->ep_addr); + #endif } return is_busy ? 0 : s->ep_bufsize; } else #endif { - (void)hwid; return (uint32_t)tu_fifo_remaining(&s->ff); } } @@ -499,13 +498,13 @@ uint32_t tu_edpt_stream_write_available(uint8_t hwid, tu_edpt_stream_t *s) { //--------------------------------------------------------------------+ // Stream Read //--------------------------------------------------------------------+ -uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t *s) { +uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t *s) { #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED if (0 == tu_fifo_depth(&s->ff)) { // non-fifo mode: RX need ep buffer TU_VERIFY(s->ep_buf != NULL, 0); - TU_VERIFY(stream_claim(hwid, s), 0); - TU_ASSERT(stream_xfer(hwid, s, s->ep_bufsize), 0); + TU_VERIFY(stream_claim(s), 0); + TU_ASSERT(stream_xfer(s, s->ep_bufsize), 0); return s->ep_bufsize; } else #endif @@ -517,7 +516,7 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t *s) { // and slowly move it to the FIFO when read(). // This pre-check reduces endpoint claiming TU_VERIFY(available >= s->mps); - TU_VERIFY(stream_claim(hwid, s), 0); + TU_VERIFY(stream_claim(s), 0); available = tu_fifo_remaining(&s->ff); // re-get available since fifo can be changed if (available >= s->mps) { @@ -526,19 +525,19 @@ uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t *s) { if (s->ep_buf != NULL) { count = tu_min16(count, s->ep_bufsize); } - TU_ASSERT(stream_xfer(hwid, s, count), 0); + TU_ASSERT(stream_xfer(s, count), 0); return count; } else { // Release endpoint since we don't make any transfer - stream_release(hwid, s); + stream_release(s); return 0; } } } -uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, uint32_t bufsize) { +uint32_t tu_edpt_stream_read(tu_edpt_stream_t *s, void *buffer, uint32_t bufsize) { const uint32_t num_read = tu_fifo_read_n(&s->ff, buffer, (uint16_t)bufsize); - tu_edpt_stream_read_xfer(hwid, s); + tu_edpt_stream_read_xfer(s); return num_read; } -- cgit v1.3.1 From 702be8da51d3a0c4dc481f16a0dc819b60603b51 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Dec 2025 11:49:01 +0700 Subject: refactor binding ep and interface to driver --- src/common/tusb_private.h | 5 ++-- src/device/usbd.c | 76 ++++------------------------------------------- src/tusb.c | 29 +++++++++++------- src/tusb_option.h | 2 +- 4 files changed, 28 insertions(+), 84 deletions(-) (limited to 'src/tusb.c') diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 5cea7b5a0..a94470039 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -95,8 +95,9 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_validate(tusb_desc_endpoint_t c } #endif -// Bind all endpoint of a interface descriptor to class driver -void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); +// Bind drivers to all interfaces and endpoints in the provided configuration descriptor +bool tu_bind_driver_to_ep_itf(uint8_t driver_id, uint8_t ep2drv[][2], uint8_t itf2drv[], uint8_t itf_max, + const uint8_t *p_desc, uint16_t desc_len); // Calculate total length of n interfaces (depending on IAD) uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); diff --git a/src/device/usbd.c b/src/device/usbd.c index 80d9fee3e..6fd88bf42 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1046,19 +1046,11 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { const uint8_t *p_desc = ((const uint8_t *)desc_cfg) + sizeof(tusb_desc_configuration_t); const uint8_t *desc_end = ((const uint8_t *)desc_cfg) + tu_le16toh(desc_cfg->wTotalLength); - while (p_desc < desc_end) { - uint8_t assoc_itf_count = 1; - + while (tu_desc_in_bounds(p_desc, desc_end)) { // Class will always start with Interface Association (if any) and then Interface descriptor if (TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc)) { - const tusb_desc_interface_assoc_t *desc_iad = (const tusb_desc_interface_assoc_t *)p_desc; - - assoc_itf_count = desc_iad->bInterfaceCount; p_desc = tu_desc_next(p_desc); // next to Interface - - // IAD's first interface number and class should match with opened interface - // TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && - // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); + continue; } TU_ASSERT(TUSB_DESC_INTERFACE == tu_desc_type(p_desc)); @@ -1076,67 +1068,9 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) { // Open successfully TU_LOG_USBD(" %s opened\r\n", driver->name); - // Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or - // BTH (even CDC) with class in device descriptor (single interface) - if (assoc_itf_count == 1) { - #if CFG_TUD_CDC - if (driver->open == cdcd_open) { - assoc_itf_count = 2; - } - #endif - - #if CFG_TUD_MIDI - if (driver->open == midid_open) { - // If there is a class-compliant Audio Control Class, then 2 interfaces. Otherwise, only one - if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) { - assoc_itf_count = 2; - } - } - #endif - - #if CFG_TUD_BTH && CFG_TUD_BTH_ISO_ALT_COUNT - if (driver->open == btd_open) { - assoc_itf_count = 2; - } - #endif - - #if CFG_TUD_AUDIO - if (driver->open == audiod_open) { - // UAC1 device doesn't have IAD, needs to read AS interface count from CS AC descriptor - if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) { - const uint8_t *p = tu_desc_next(p_desc); - const uint8_t *const itf_end = p_desc + remaining_len; - while (p < itf_end) { - if (TUSB_DESC_CS_INTERFACE == tu_desc_type(p) && - AUDIO10_CS_AC_INTERFACE_HEADER == - ((const audio10_desc_cs_ac_interface_1_t *)p)->bDescriptorSubType) { - const audio10_desc_cs_ac_interface_1_t *p_header = (const audio10_desc_cs_ac_interface_1_t *)p; - // AC + AS interfaces - assoc_itf_count = p_header->bInCollection + 1; - break; - } - p = tu_desc_next(p); - } - } - } - #endif - } - - // bind (associated) interfaces to found driver - for (uint8_t i = 0; i < assoc_itf_count; i++) { - const uint8_t itf_num = desc_itf->bInterfaceNumber + i; - - // Interface number must not be used already - TU_ASSERT(TUSB_INDEX_INVALID_8 == _usbd_dev.itf2drv[itf_num]); - _usbd_dev.itf2drv[itf_num] = drv_id; - } - - // bind all endpoints to found driver - tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id); + // bind found driver to all interfaces and endpoint within drv_len + TU_ASSERT(tu_bind_driver_to_ep_itf(drv_id, _usbd_dev.ep2drv, _usbd_dev.itf2drv, CFG_TUD_INTERFACE_MAX, p_desc, + drv_len)); p_desc += drv_len; // next Interface break; // exit driver find loop diff --git a/src/tusb.c b/src/tusb.c index 14b388d04..de6ec0211 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -286,19 +286,28 @@ bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed, b } #endif -void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, - uint8_t driver_id) { - uint8_t const* p_desc = (uint8_t const*) desc_itf; - uint8_t const* desc_end = p_desc + desc_len; - - while (p_desc < desc_end) { - if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) { - uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress; - TU_LOG(2, " Bind EP %02x to driver id %u\r\n", ep_addr, driver_id); - ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id; +bool tu_bind_driver_to_ep_itf(uint8_t driver_id, uint8_t ep2drv[][2], uint8_t itf2drv[], uint8_t itf_max, + const uint8_t *p_desc, uint16_t desc_len) { + const uint8_t *desc_end = p_desc + desc_len; + while (tu_desc_in_bounds(p_desc, desc_end)) { + const uint8_t desc_type = tu_desc_type(p_desc); + + if (desc_type == TUSB_DESC_ENDPOINT) { + const uint8_t ep_addr = ((const tusb_desc_endpoint_t *)p_desc)->bEndpointAddress; + const uint8_t ep_num = tu_edpt_number(ep_addr); + const uint8_t ep_dir = tu_edpt_dir(ep_addr); + ep2drv[ep_num][ep_dir] = driver_id; + } else if (desc_type == TUSB_DESC_INTERFACE) { + const tusb_desc_interface_t *desc_itf = (const tusb_desc_interface_t *)p_desc; + if (desc_itf->bAlternateSetting == 0) { + TU_ASSERT(desc_itf->bInterfaceNumber < itf_max); + itf2drv[desc_itf->bInterfaceNumber] = driver_id; + } } + p_desc = tu_desc_next(p_desc); } + return true; } uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) { diff --git a/src/tusb_option.h b/src/tusb_option.h index be954e01a..a70d7a97e 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -31,7 +31,7 @@ // Version is release as major.minor.revision eg 1.0.0 #define TUSB_VERSION_MAJOR 0 #define TUSB_VERSION_MINOR 20 -#define TUSB_VERSION_REVISION 0 +#define TUSB_VERSION_REVISION 1 #define TUSB_VERSION_NUMBER (TUSB_VERSION_MAJOR * 10000 + TUSB_VERSION_MINOR * 100 + TUSB_VERSION_REVISION) #define TUSB_VERSION_STRING TU_XSTRING(TUSB_VERSION_MAJOR) "." TU_XSTRING(TUSB_VERSION_MINOR) "." TU_XSTRING(TUSB_VERSION_REVISION) -- cgit v1.3.1 From ef018e364e886852e2789542b5758da6143af614 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Dec 2025 15:58:10 +0700 Subject: refactor usbh_class_driver_t's open() to return number of driver len instead of bool. help to simplify parsing configuration --- src/class/cdc/cdc_host.c | 250 +++++++++++++++++------------------ src/class/cdc/cdc_host.h | 73 ++++++----- src/class/cdc/cdc_rndis_host.c | 289 ----------------------------------------- src/class/cdc/cdc_rndis_host.h | 63 --------- src/class/hid/hid_host.c | 23 ++-- src/class/hid/hid_host.h | 56 ++++---- src/class/midi/midi_host.c | 41 +++--- src/class/midi/midi_host.h | 62 +++++---- src/class/msc/msc_host.c | 21 ++- src/class/msc/msc_host.h | 48 ++++--- src/common/tusb_common.h | 5 +- src/common/tusb_private.h | 3 - src/host/hub.c | 14 +- src/host/hub.h | 12 +- src/host/usbh.c | 96 +++++--------- src/host/usbh_pvt.h | 17 ++- src/tusb.c | 31 ----- 17 files changed, 349 insertions(+), 755 deletions(-) delete mode 100644 src/class/cdc/cdc_rndis_host.c delete mode 100644 src/class/cdc/cdc_rndis_host.h (limited to 'src/tusb.c') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index 28abbf098..ff1a8338d 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -41,13 +41,14 @@ #include "serial/pl2303.h" // Level where CFG_TUSB_DEBUG must be at least for this driver is logged -#ifndef CFG_TUH_CDC_LOG_LEVEL - #define CFG_TUH_CDC_LOG_LEVEL 2 -#endif + #ifndef CFG_TUH_CDC_LOG_LEVEL + #define CFG_TUH_CDC_LOG_LEVEL 2 + #endif -#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) -#define TU_LOG_CDC(_cdc, _format, ...) TU_LOG_DRV("[:%u:%u] CDCh %s " _format "\r\n", _cdc->daddr, _cdc->bInterfaceNumber, \ - serial_drivers[_cdc->serial_drid].name, ##__VA_ARGS__) + #define TU_LOG_DRV(...) TU_LOG(CFG_TUH_CDC_LOG_LEVEL, __VA_ARGS__) + #define TU_LOG_CDC(_cdc, _format, ...) \ + TU_LOG_DRV("[:%u:%u] CDCh %s " _format "\r\n", _cdc->daddr, _cdc->bInterfaceNumber, \ + serial_drivers[_cdc->serial_drid].name, ##__VA_ARGS__) //--------------------------------------------------------------------+ // Host CDC Interface @@ -113,63 +114,59 @@ static void cdch_set_line_coding_stage1_baudrate_complete(tuh_xfer_t *xfer); static void cdch_set_line_coding_stage2_data_format_complete(tuh_xfer_t *xfer); //------------- ACM prototypes -------------// -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void acm_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); - -static bool acm_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool acm_set_control_line_state(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static uint16_t acm_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void acm_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static bool acm_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool acm_set_control_line_state(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -//------------- FTDI prototypes -------------// -#if CFG_TUH_CDC_FTDI + //------------- FTDI prototypes -------------// + #if CFG_TUH_CDC_FTDI static uint16_t const ftdi_vid_pid_list[][2] = {CFG_TUH_CDC_FTDI_VID_PID_LIST}; -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); -static bool ftdi_proccess_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void ftdi_internal_control_complete(cdch_interface_t* p_cdc, tuh_xfer_t *xfer); -static bool ftdi_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ftdi_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif +static uint16_t ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static bool ftdi_proccess_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void ftdi_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static bool ftdi_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ftdi_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + #endif -//------------- CP210X prototypes -------------// -#if CFG_TUH_CDC_CP210X + //------------- CP210X prototypes -------------// + #if CFG_TUH_CDC_CP210X static uint16_t const cp210x_vid_pid_list[][2] = {CFG_TUH_CDC_CP210X_VID_PID_LIST}; -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); - -static bool cp210x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool cp210x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif +static uint16_t cp210x_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void cp210x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static bool cp210x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool cp210x_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + #endif -//------------- CH34x prototypes -------------// -#if CFG_TUH_CDC_CH34X + //------------- CH34x prototypes -------------// + #if CFG_TUH_CDC_CH34X static uint16_t const ch34x_vid_pid_list[][2] = {CFG_TUH_CDC_CH34X_VID_PID_LIST}; -static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); - -static bool ch34x_set_baudrate(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_data_format(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool ch34x_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif +static uint16_t ch34x_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void ch34x_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static bool ch34x_set_baudrate(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_data_format(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool ch34x_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + #endif -//------------- PL2303 prototypes -------------// -#if CFG_TUH_CDC_PL2303 + //------------- PL2303 prototypes -------------// + #if CFG_TUH_CDC_PL2303 static uint16_t const pl2303_vid_pid_list[][2] = {CFG_TUH_CDC_PL2303_VID_PID_LIST}; static const pl2303_type_data_t pl2303_type_data[PL2303_TYPE_COUNT] = {PL2303_TYPE_DATA}; -static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); -static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); -static void pl2303_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); - -static bool pl2303_set_line_coding(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -static bool pl2303_set_modem_ctrl(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -#endif +static uint16_t pl2303_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static void pl2303_internal_control_complete(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); +static bool pl2303_set_line_coding(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +static bool pl2303_set_modem_ctrl(cdch_interface_t *p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); + #endif //------------- Common -------------// enum { @@ -197,11 +194,12 @@ enum { typedef bool (*serial_driver_func_t)(cdch_interface_t * p_cdc, tuh_xfer_cb_t complete_cb, uintptr_t user_data); typedef struct { - uint16_t const (*vid_pid_list)[2]; - uint16_t const vid_pid_count; - bool (*const open)(uint8_t daddr, const tusb_desc_interface_t * itf_desc, uint16_t max_len); - bool (*const process_set_config)(cdch_interface_t * p_cdc, tuh_xfer_t * xfer); - void (*const request_complete)(cdch_interface_t * p_cdc, tuh_xfer_t * xfer); // internal request complete handler to update line state + const uint16_t (*vid_pid_list)[2]; + const uint16_t vid_pid_count; + uint16_t (*const open)(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); + bool (*const process_set_config)(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); + // internal request complete handler to update line state + void (*const request_complete)(cdch_interface_t *p_cdc, tuh_xfer_t *xfer); serial_driver_func_t set_control_line_state, set_baudrate, set_data_format, set_line_coding; @@ -731,11 +729,10 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t //--------------------------------------------------------------------+ static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t const *desc_ep) { for (size_t i = 0; i < 2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && - TUSB_XFER_BULK == desc_ep->bmAttributes.xfer); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0); TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep)); - tu_edpt_stream_t *stream = - (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) ? &p_cdc->stream.rx : &p_cdc->stream.tx; + const uint8_t ep_dir = tu_edpt_dir(desc_ep->bEndpointAddress); + tu_edpt_stream_t *stream = (ep_dir == TUSB_DIR_IN) ? &p_cdc->stream.rx : &p_cdc->stream.tx; tu_edpt_stream_open(stream, p_cdc->daddr, desc_ep); tu_edpt_stream_clear(stream); @@ -745,8 +742,8 @@ static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t co return true; } -bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - (void) rhport; +uint16_t cdch_open(uint8_t rhport, uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { + (void)rhport; // For CDC: only support ACM subclass // Note: Protocol 0xFF can be RNDIS device if (TUSB_CLASS_CDC == itf_desc->bInterfaceClass && @@ -755,15 +752,15 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d } else if (SERIAL_DRIVER_COUNT > 1 && TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { uint16_t vid, pid; - TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid)); + TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid), 0); - for (size_t dr = 1; dr < SERIAL_DRIVER_COUNT; dr++) { - const cdch_serial_driver_t *driver = &serial_drivers[dr]; + for (size_t drv = 1; drv < SERIAL_DRIVER_COUNT; drv++) { + const cdch_serial_driver_t *driver = &serial_drivers[drv]; for (size_t i = 0; i < driver->vid_pid_count; i++) { if (driver->vid_pid_list[i][0] == vid && driver->vid_pid_list[i][1] == pid) { - const bool ret = driver->open(daddr, itf_desc, max_len); + const uint16_t drv_len = driver->open(daddr, itf_desc, max_len); TU_LOG_DRV("[:%u:%u] CDCh %s open %s\r\n", daddr, itf_desc->bInterfaceNumber, driver->name, ret ? "OK" : "FAILED"); - return ret; + return drv_len; } } } @@ -771,7 +768,7 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d // not supported class } - return false; + return 0; } bool cdch_set_config(uint8_t daddr, uint8_t itf_num) { @@ -1012,19 +1009,19 @@ enum { CONFIG_ACM_COMPLETE = 0 }; -static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { - uint8_t const *p_desc_end = ((uint8_t const *) itf_desc) + max_len; +static uint16_t acm_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { + const uint8_t *p_desc = (const uint8_t *)itf_desc; + const uint8_t *desc_end = p_desc + max_len; cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); - + TU_VERIFY(p_cdc, 0); p_cdc->serial_drid = SERIAL_DRIVER_ACM; //------------- Control Interface -------------// - uint8_t const *p_desc = tu_desc_next(itf_desc); + p_desc = tu_desc_next(p_desc); // Communication Functional Descriptors - while ((p_desc < p_desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) { + while ((p_desc < desc_end) && (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc))) { if (CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc)) { // save ACM bmCapabilities p_cdc->acm.capability = ((cdc_desc_func_acm_t const *) p_desc)->bmCapabilities; @@ -1035,26 +1032,27 @@ static bool acm_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint1 // Open notification endpoint of control interface if any if (itf_desc->bNumEndpoints == 1) { - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)); - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc; - - TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(p_desc), 0); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc; + TU_ASSERT(tuh_edpt_open(daddr, desc_ep), 0); p_cdc->ep_notif = desc_ep->bEndpointAddress; p_desc = tu_desc_next(p_desc); } //------------- Data Interface (if any) -------------// - if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) && - (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass)) { - // next to endpoint descriptor - p_desc = tu_desc_next(p_desc); - - // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, (tusb_desc_endpoint_t const *) p_desc)); + if (TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) { + const tusb_desc_interface_t *data_itf = (const tusb_desc_interface_t *)p_desc; + if (data_itf->bInterfaceClass == TUSB_CLASS_CDC_DATA) { + p_desc = tu_desc_next(p_desc); // next to endpoint descriptor + + // data endpoints expected to be in pairs + TU_ASSERT(open_ep_stream_pair(p_cdc, (const tusb_desc_endpoint_t *)p_desc), 0); + p_desc += data_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t); + } } - return true; + return (uint16_t)((uintptr_t)p_desc - (uintptr_t)itf_desc); } static bool acm_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { @@ -1187,28 +1185,29 @@ enum { CONFIG_FTDI_COMPLETE }; -static bool ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { +static uint16_t ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // FTDI Interface includes 1 vendor interface + 2 bulk endpoints TU_VERIFY(itf_desc->bInterfaceSubClass == 0xff && itf_desc->bInterfaceProtocol == 0xff && - itf_desc->bNumEndpoints == 2); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t) <= max_len); + itf_desc->bNumEndpoints == 2, + 0); + const uint16_t drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); + TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); + TU_VERIFY(p_cdc, 0); p_cdc->serial_drid = SERIAL_DRIVER_FTDI; // endpoint pair - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(itf_desc); - /* - * NOTE: Some customers have programmed FT232R/FT245R devices - * with an endpoint size of 0 - not good. - */ - TU_ASSERT(desc_ep->wMaxPacketSize != 0); + /* NOTE: Some users have programmed FT232R/FT245R devices + * with an endpoint size of 0 !!! */ + TU_ASSERT(desc_ep->wMaxPacketSize != 0, 0); - // data endpoints expected to be in pairs - return open_ep_stream_pair(p_cdc, desc_ep); + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep), 0); + + return drv_len; } static bool ftdi_proccess_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { @@ -1579,21 +1578,22 @@ enum { CONFIG_CP210X_COMPLETE }; -static bool cp210x_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { +static uint16_t cp210x_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // CP210x Interface includes 1 vendor interface + 2 bulk endpoints - TU_VERIFY(itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0 && itf_desc->bNumEndpoints == 2); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 2 * sizeof(tusb_desc_endpoint_t) <= max_len); + TU_VERIFY(itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0 && itf_desc->bNumEndpoints == 2, 0); + const uint16_t drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); + TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); + TU_VERIFY(p_cdc, 0); p_cdc->serial_drid = SERIAL_DRIVER_CP210X; - // endpoint pair - tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - // data endpoints expected to be in pairs - return open_ep_stream_pair(p_cdc, desc_ep); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(itf_desc); + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep)); + + return drv_len; } static bool cp210x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { @@ -1753,29 +1753,29 @@ enum { CONFIG_CH34X_COMPLETE }; -static bool ch34x_open(uint8_t daddr, tusb_desc_interface_t const * itf_desc, uint16_t max_len) { +static uint16_t ch34x_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // CH34x Interface includes 1 vendor interface + 2 bulk + 1 interrupt endpoints - TU_VERIFY(itf_desc->bNumEndpoints == 3); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len); + TU_VERIFY(itf_desc->bNumEndpoints == 3, 0); + const uint16_t drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); + TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); + TU_VERIFY(p_cdc, 0); p_cdc->serial_drid = SERIAL_DRIVER_CH34X; - tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); + const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(itf_desc); // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep)); - desc_ep += 2; + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep), 0); + desc_ep = (const tusb_desc_endpoint_t *)((uintptr_t)desc_ep + 2 * sizeof(tusb_desc_endpoint_t)); // Interrupt endpoint: not used for now - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && - TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer); - TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep), 0); p_cdc->ep_notif = desc_ep->bEndpointAddress; - return true; + return drv_len; } static bool ch34x_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { @@ -2089,13 +2089,14 @@ enum { CONFIG_PL2303_COMPLETE }; -static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { +static uint16_t pl2303_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // PL2303 Interface includes 1 vendor interface + 1 interrupt endpoints + 2 bulk - TU_VERIFY(itf_desc->bNumEndpoints == 3); - TU_VERIFY(sizeof(tusb_desc_interface_t) + 3 * sizeof(tusb_desc_endpoint_t) <= max_len); + TU_VERIFY(itf_desc->bNumEndpoints == 3, 0); + const uint16_t drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); + TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); - TU_VERIFY(p_cdc); + TU_VERIFY(p_cdc, 0); p_cdc->serial_drid = SERIAL_DRIVER_PL2303; p_cdc->pl2303.quirks = 0; @@ -2104,16 +2105,15 @@ static bool pl2303_open(uint8_t daddr, tusb_desc_interface_t const *itf_desc, ui tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); // Interrupt endpoint: not used for now - TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && - TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer); - TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); + TU_ASSERT(TUSB_DESC_ENDPOINT == tu_desc_type(desc_ep) && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep), 0); p_cdc->ep_notif = desc_ep->bEndpointAddress; desc_ep += 1; // data endpoints expected to be in pairs - TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep)); + TU_ASSERT(open_ep_stream_pair(p_cdc, desc_ep), 0); - return true; + return drv_len; } static bool pl2303_process_set_config(cdch_interface_t *p_cdc, tuh_xfer_t *xfer) { diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index e8637beac..57919c7ff 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -30,7 +30,7 @@ #include "cdc.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif //--------------------------------------------------------------------+ @@ -39,22 +39,22 @@ // RX FIFO size #ifndef CFG_TUH_CDC_RX_BUFSIZE -#define CFG_TUH_CDC_RX_BUFSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_CDC_RX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif // RX Endpoint size #ifndef CFG_TUH_CDC_RX_EPSIZE -#define CFG_TUH_CDC_RX_EPSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_CDC_RX_EPSIZE TUH_EPSIZE_BULK_MPS #endif // TX FIFO size #ifndef CFG_TUH_CDC_TX_BUFSIZE -#define CFG_TUH_CDC_TX_BUFSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_CDC_TX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif // TX Endpoint size #ifndef CFG_TUH_CDC_TX_EPSIZE -#define CFG_TUH_CDC_TX_EPSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_CDC_TX_EPSIZE TUH_EPSIZE_BULK_MPS #endif //--------------------------------------------------------------------+ @@ -67,7 +67,7 @@ uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num); // Get Interface information // return true if index is correct and interface is currently mounted -bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t* info); +bool tuh_cdc_itf_get_info(uint8_t idx, tuh_itf_info_t *info); // Check if an interface is mounted bool tuh_cdc_mounted(uint8_t idx); @@ -75,7 +75,7 @@ bool tuh_cdc_mounted(uint8_t idx); // Get local (cached) line state // This function should return correct values if tuh_cdc_set_control_line_state() / tuh_cdc_get_control_line_state() // are invoked previously or CFG_TUH_CDC_LINE_STATE_ON_ENUM is defined. -bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t* line_state); +bool tuh_cdc_get_control_line_state_local(uint8_t idx, uint16_t *line_state); // Get current DTR status TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_get_dtr(uint8_t idx) { @@ -100,7 +100,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx) { // This function should return correct values if tuh_cdc_set_line_coding() / tuh_cdc_get_line_coding() // are invoked previously or CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined. // NOTE: This function does not make any USB transfer request to device. -bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t* line_coding); +bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t *line_coding); #define tuh_cdc_get_local_line_coding tuh_cdc_get_line_coding_local // backward compatibility @@ -112,7 +112,7 @@ bool tuh_cdc_get_line_coding_local(uint8_t idx, cdc_line_coding_t* line_coding); uint32_t tuh_cdc_write_available(uint8_t idx); // Write to cdc interface -uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize); +uint32_t tuh_cdc_write(uint8_t idx, const void *buffer, uint32_t bufsize); // Force sending data if possible, return number of forced bytes uint32_t tuh_cdc_write_flush(uint8_t idx); @@ -128,13 +128,13 @@ bool tuh_cdc_write_clear(uint8_t idx); uint32_t tuh_cdc_read_available(uint8_t idx); // Read from cdc interface -uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize); +uint32_t tuh_cdc_read(uint8_t idx, void *buffer, uint32_t bufsize); // Get a byte from RX FIFO without removing it -bool tuh_cdc_peek(uint8_t idx, uint8_t* ch); +bool tuh_cdc_peek(uint8_t idx, uint8_t *ch); // Clear the received FIFO -bool tuh_cdc_read_clear (uint8_t idx); +bool tuh_cdc_read_clear(uint8_t idx); //--------------------------------------------------------------------+ // Control Request API @@ -149,16 +149,18 @@ bool tuh_cdc_read_clear (uint8_t idx); bool tuh_cdc_set_control_line_state(uint8_t idx, uint16_t line_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set DTR -TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdc_line_control_state_t line_state = { .dtr = dtr_state }; - line_state.rts = tuh_cdc_get_rts(idx); +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_dtr(uint8_t idx, bool dtr_state, tuh_xfer_cb_t complete_cb, + uintptr_t user_data) { + cdc_line_control_state_t line_state = {.dtr = dtr_state}; + line_state.rts = tuh_cdc_get_rts(idx); return tuh_cdc_set_control_line_state(idx, line_state.value, complete_cb, user_data); } // Request to Set RTS -TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - cdc_line_control_state_t line_state = { .rts = rts_state }; - line_state.dtr = tuh_cdc_get_dtr(idx); +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_rts(uint8_t idx, bool rts_state, tuh_xfer_cb_t complete_cb, + uintptr_t user_data) { + cdc_line_control_state_t line_state = {.rts = rts_state}; + line_state.dtr = tuh_cdc_get_dtr(idx); return tuh_cdc_set_control_line_state(idx, line_state.value, complete_cb, user_data); } @@ -166,11 +168,13 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_set_rts(uint8_t idx, bool rts_s bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to set data format -bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +bool tuh_cdc_set_data_format(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits, + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Request to Set Line Coding = baudrate + data format // Note: only implemented by ACM and CH34x, not supported by FTDI and CP210x yet -bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +bool tuh_cdc_set_line_coding(uint8_t idx, const cdc_line_coding_t *line_coding, tuh_xfer_cb_t complete_cb, + uintptr_t user_data); // Request to Get Line Coding (ACM only) // Should only use if tuh_cdc_set_line_coding() / tuh_cdc_get_line_coding() never got invoked and @@ -179,11 +183,13 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding, // Connect by set both DTR, RTS TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return tuh_cdc_set_control_line_state(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, user_data); + return tuh_cdc_set_control_line_state(idx, CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS, complete_cb, + user_data); } // Disconnect by clear both DTR, RTS -TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { +TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_disconnect(uint8_t idx, tuh_xfer_cb_t complete_cb, + uintptr_t user_data) { return tuh_cdc_set_control_line_state(idx, 0x00, complete_cb, user_data); } @@ -192,7 +198,8 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_disconnect(uint8_t idx, tuh_xfe // Each Function will make a USB control transfer request to/from device the function will block until request is // complete. The function will return the transfer request result //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_control_line_state_sync(uint8_t idx, uint16_t line_state) { +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_control_line_state_sync(uint8_t idx, + uint16_t line_state) { TU_API_SYNC(tuh_cdc_set_control_line_state, idx, line_state); } @@ -208,11 +215,13 @@ TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_baudrate_sync TU_API_SYNC(tuh_cdc_set_baudrate, idx, baudrate); } -TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_data_format_sync(uint8_t idx, uint8_t stop_bits, uint8_t parity, uint8_t data_bits) { +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_data_format_sync(uint8_t idx, uint8_t stop_bits, + uint8_t parity, uint8_t data_bits) { TU_API_SYNC(tuh_cdc_set_data_format, idx, stop_bits, parity, data_bits); } -TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_line_coding_sync(uint8_t idx, cdc_line_coding_t const* line_coding) { +TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t +tuh_cdc_set_line_coding_sync(uint8_t idx, const cdc_line_coding_t *line_coding) { TU_API_SYNC(tuh_cdc_set_line_coding, idx, line_coding); } @@ -244,15 +253,15 @@ extern void tuh_cdc_tx_complete_cb(uint8_t idx); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -bool cdch_init (void); -bool cdch_deinit (void); -bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num); -bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void cdch_close (uint8_t dev_addr); +bool cdch_init(void); +bool cdch_deinit(void); +uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num); +bool cdch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void cdch_close(uint8_t dev_addr); #ifdef __cplusplus - } +} #endif #endif /* TUSB_CDC_HOST_H_ */ diff --git a/src/class/cdc/cdc_rndis_host.c b/src/class/cdc/cdc_rndis_host.c deleted file mode 100644 index e975ea440..000000000 --- a/src/class/cdc/cdc_rndis_host.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUH_ENABLED && CFG_TUH_CDC && CFG_TUH_CDC_RNDIS) - -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ -#include "common/tusb_common.h" -#include "cdc_host.h" -#include "cdc_rndis_host.h" - -#if 0 // TODO remove subtask related macros later -// Sub Task -#define OSAL_SUBTASK_BEGIN -#define OSAL_SUBTASK_END return TUSB_ERROR_NONE; - -#define STASK_RETURN(_error) return _error; -#define STASK_INVOKE(_subtask, _status) (_status) = _subtask -#define STASK_ASSERT(_cond) TU_VERIFY(_cond, TUSB_ERROR_OSAL_TASK_FAILED) -#endif - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ -#define RNDIS_MSG_PAYLOAD_MAX (1024*4) - -CFG_TUH_MEM_SECTION static uint8_t msg_notification[CFG_TUH_DEVICE_MAX][8]; -CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t msg_payload[RNDIS_MSG_PAYLOAD_MAX]; - -static rndish_data_t rndish_data[CFG_TUH_DEVICE_MAX]; - -// TODO Microsoft requires message length for any get command must be at least 4096 bytes - -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ -static tusb_error_t rndis_body_subtask(void); -static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, - uint8_t * p_mess, uint32_t mess_length, - uint8_t *p_response ); - -//--------------------------------------------------------------------+ -// APPLICATION API -//--------------------------------------------------------------------+ -tusb_error_t tusbh_cdc_rndis_get_mac_addr(uint8_t dev_addr, uint8_t mac_address[6]) -{ - TU_ASSERT( tusbh_cdc_rndis_is_mounted(dev_addr), TUSB_ERROR_CDCH_DEVICE_NOT_MOUNTED); - TU_VERIFY( mac_address, TUSB_ERROR_INVALID_PARA); - - memcpy(mac_address, rndish_data[dev_addr-1].mac_address, 6); - - return TUSB_ERROR_NONE; -} - -//--------------------------------------------------------------------+ -// IMPLEMENTATION -//--------------------------------------------------------------------+ - -// To enable the TASK_ASSERT style (quick return on false condition) in a real RTOS, a task must act as a wrapper -// and is used mainly to call subtasks. Within a subtask return statement can be called freely, the task with -// forever loop cannot have any return at all. -OSAL_TASK_FUNCTION(cdch_rndis_task) (void* param;) -{ - OSAL_TASK_BEGIN - rndis_body_subtask(); - OSAL_TASK_END -} - -static tusb_error_t rndis_body_subtask(void) -{ - static uint8_t relative_addr; - - OSAL_SUBTASK_BEGIN - - for (relative_addr = 0; relative_addr < CFG_TUH_DEVICE_MAX; relative_addr++) - { - - } - - tusb_time_delay_ms_api(100); - - OSAL_SUBTASK_END -} - -//--------------------------------------------------------------------+ -// RNDIS-CDC Driver API -//--------------------------------------------------------------------+ -void rndish_init(void) -{ - tu_memclr(rndish_data, sizeof(rndish_data_t)*CFG_TUH_DEVICE_MAX); - - //------------- Task creation -------------// - - //------------- semaphore creation for notification pipe -------------// - for(uint8_t i=0; itype == RNDIS_MSG_INITIALIZE_CMPLT && p_init_cmpt->status == RNDIS_STATUS_SUCCESS && - p_init_cmpt->max_packet_per_xfer == 1 && p_init_cmpt->max_xfer_size <= RNDIS_MSG_PAYLOAD_MAX); - rndish_data[dev_addr-1].max_xfer_size = p_init_cmpt->max_xfer_size; - - //------------- Message Query 802.3 Permanent Address -------------// - memcpy(msg_payload, &msg_query_permanent_addr, sizeof(rndis_msg_query_t)); - tu_memclr(msg_payload + sizeof(rndis_msg_query_t), 6); // 6 bytes for MAC address - - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_query_t) + 6, - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - rndis_msg_query_cmplt_t * const p_query_cmpt = (rndis_msg_query_cmplt_t *) msg_payload; - STASK_ASSERT(p_query_cmpt->type == RNDIS_MSG_QUERY_CMPLT && p_query_cmpt->status == RNDIS_STATUS_SUCCESS); - memcpy(rndish_data[dev_addr-1].mac_address, msg_payload + 8 + p_query_cmpt->buffer_offset, 6); - - //------------- Set OID_GEN_CURRENT_PACKET_FILTER to (DIRECTED | MULTICAST | BROADCAST) -------------// - memcpy(msg_payload, &msg_set_packet_filter, sizeof(rndis_msg_set_t)); - tu_memclr(msg_payload + sizeof(rndis_msg_set_t), 4); // 4 bytes for filter flags - ((rndis_msg_set_t*) msg_payload)->oid_buffer[0] = (RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_MULTICAST | RNDIS_PACKET_TYPE_BROADCAST); - - STASK_INVOKE( - send_message_get_response_subtask( dev_addr, p_cdc, - msg_payload, sizeof(rndis_msg_set_t) + 4, - msg_payload), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - rndis_msg_set_cmplt_t * const p_set_cmpt = (rndis_msg_set_cmplt_t *) msg_payload; - STASK_ASSERT(p_set_cmpt->type == RNDIS_MSG_SET_CMPLT && p_set_cmpt->status == RNDIS_STATUS_SUCCESS); - - tusbh_cdc_rndis_mounted_cb(dev_addr); - - OSAL_SUBTASK_END -} - -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes) -{ - if ( pipehandle_is_equal(pipe_hdl, p_cdc->pipe_notification) ) - { - osal_semaphore_post( rndish_data[pipe_hdl.dev_addr-1].sem_notification_hdl ); - } -} - -//--------------------------------------------------------------------+ -// INTERNAL & HELPER -//--------------------------------------------------------------------+ -static tusb_error_t send_message_get_response_subtask( uint8_t dev_addr, cdch_data_t *p_cdc, - uint8_t * p_mess, uint32_t mess_length, - uint8_t *p_response) -{ - tusb_error_t error; - - OSAL_SUBTASK_BEGIN - - //------------- Send RNDIS Control Message -------------// - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_OUT, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), - CDC_REQUEST_SEND_ENCAPSULATED_COMMAND, 0, p_cdc->interface_number, - mess_length, p_mess), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - //------------- waiting for Response Available notification -------------// - (void) usbh_edpt_xfer(p_cdc->pipe_notification, msg_notification[dev_addr-1], 8); - osal_semaphore_wait(rndish_data[dev_addr-1].sem_notification_hdl, OSAL_TIMEOUT_NORMAL, &error); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - STASK_ASSERT(msg_notification[dev_addr-1][0] == 1); - - //------------- Get RNDIS Message Initialize Complete -------------// - STASK_INVOKE( - usbh_control_xfer_subtask( dev_addr, bm_request_type(TUSB_DIR_IN, TUSB_REQ_TYPE_CLASS, TUSB_REQ_RCPT_INTERFACE), - CDC_REQUEST_GET_ENCAPSULATED_RESPONSE, 0, p_cdc->interface_number, - RNDIS_MSG_PAYLOAD_MAX, p_response), - error - ); - if ( TUSB_ERROR_NONE != error ) STASK_RETURN(error); - - OSAL_SUBTASK_END -} - -//static tusb_error_t send_process_msg_initialize_subtask(uint8_t dev_addr, cdch_data_t *p_cdc) -//{ -// tusb_error_t error; -// -// OSAL_SUBTASK_BEGIN -// -// *((rndis_msg_initialize_t*) msg_payload) = (rndis_msg_initialize_t) -// { -// .type = RNDIS_MSG_INITIALIZE, -// .length = sizeof(rndis_msg_initialize_t), -// .request_id = 1, // TODO should use some magic number -// .major_version = 1, -// .minor_version = 0, -// .max_xfer_size = 0x4000 // TODO mimic windows -// }; -// -// -// -// OSAL_SUBTASK_END -//} -#endif diff --git a/src/class/cdc/cdc_rndis_host.h b/src/class/cdc/cdc_rndis_host.h deleted file mode 100644 index e70d27f79..000000000 --- a/src/class/cdc/cdc_rndis_host.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -/** \ingroup CDC_RNDIS - * \defgroup CDC_RNSID_Host Host - * @{ */ - -#ifndef TUSB_CDC_RNDIS_HOST_H_ -#define TUSB_CDC_RNDIS_HOST_H_ - -#include "common/tusb_common.h" -#include "host/usbh.h" -#include "cdc_rndis.h" - -#ifdef __cplusplus - extern "C" { -#endif - -//--------------------------------------------------------------------+ -// INTERNAL RNDIS-CDC Driver API -//--------------------------------------------------------------------+ -typedef struct { - OSAL_SEM_DEF(semaphore_notification); - osal_semaphore_handle_t sem_notification_hdl; // used to wait on notification pipe - uint32_t max_xfer_size; // got from device's msg initialize complete - uint8_t mac_address[6]; -}rndish_data_t; - -void rndish_init(void); -bool rndish_open_subtask(uint8_t dev_addr, cdch_data_t *p_cdc); -void rndish_xfer_isr(cdch_data_t *p_cdc, pipe_handle_t pipe_hdl, xfer_result_t event, uint32_t xferred_bytes); -void rndish_close(uint8_t dev_addr); - -#ifdef __cplusplus - } -#endif - -#endif /* TUSB_CDC_RNDIS_HOST_H_ */ - -/** @} */ diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c index fe9a90d33..98f9bf80b 100644 --- a/src/class/hid/hid_host.c +++ b/src/class/hid/hid_host.c @@ -512,19 +512,18 @@ void hidh_close(uint8_t daddr) { //--------------------------------------------------------------------+ // Enumeration //--------------------------------------------------------------------+ - -bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const* desc_itf, uint16_t max_len) { +uint16_t hidh_open(uint8_t rhport, uint8_t daddr, const tusb_desc_interface_t *desc_itf, uint16_t max_len) { (void) rhport; (void) max_len; - TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass); + TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); TU_LOG_DRV("[%u] HID opening Interface %u\r\n", daddr, desc_itf->bInterfaceNumber); // len = interface + hid + n*endpoints - uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + - desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); - TU_ASSERT(max_len >= drv_len); - uint8_t const* p_desc = (uint8_t const*) desc_itf; + const uint16_t drv_len = (uint16_t)(sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); + TU_ASSERT(drv_len <= max_len, 0); + const uint8_t *p_desc = (const uint8_t *)desc_itf; // HID descriptor: mostly right after interface descriptor, in some rare case it might be after endpoint descriptors p_desc = tu_desc_next(p_desc); @@ -536,20 +535,20 @@ bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const* desc_ } else { // HID after endpoint desc_hid = (const tusb_hid_descriptor_hid_t *)(p_desc + sizeof(tusb_desc_endpoint_t) * desc_itf->bNumEndpoints); - TU_ASSERT(tu_desc_type(desc_hid) == HID_DESC_TYPE_HID); + TU_ASSERT(tu_desc_type(desc_hid) == HID_DESC_TYPE_HID, 0); } // Allocate new interface hidh_interface_t *p_hid = find_new_itf(); - TU_ASSERT(p_hid); // not enough interface, try to increase CFG_TUH_HID + TU_ASSERT(p_hid, 0); // not enough interface, try to increase CFG_TUH_HID p_hid->daddr = daddr; p_hid->itf_num = desc_itf->bInterfaceNumber; // Endpoint Descriptors for (uint8_t i = 0; i < desc_itf->bNumEndpoints; i++) { const tusb_desc_endpoint_t *desc_ep = (const tusb_desc_endpoint_t *)p_desc; - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - TU_ASSERT(tuh_edpt_open(daddr, desc_ep)); + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, 0); + TU_ASSERT(tuh_edpt_open(daddr, desc_ep), 0); if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { p_hid->ep_in = desc_ep->bEndpointAddress; @@ -573,7 +572,7 @@ bool hidh_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const* desc_ p_hid->itf_protocol = desc_itf->bInterfaceProtocol; } - return true; + return drv_len; } //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h index 87f0e7dc9..d7a415485 100644 --- a/src/class/hid/hid_host.h +++ b/src/class/hid/hid_host.h @@ -39,22 +39,22 @@ extern "C" { // TODO Highspeed interrupt can be up to 512 bytes #ifndef CFG_TUH_HID_EPIN_BUFSIZE -#define CFG_TUH_HID_EPIN_BUFSIZE 64 + #define CFG_TUH_HID_EPIN_BUFSIZE 64 #endif #ifndef CFG_TUH_HID_EPOUT_BUFSIZE -#define CFG_TUH_HID_EPOUT_BUFSIZE 64 + #define CFG_TUH_HID_EPOUT_BUFSIZE 64 #endif typedef struct { - uint8_t report_id; - uint8_t usage; + uint8_t report_id; + uint8_t usage; uint16_t usage_page; // TODO still use the endpoint size for now -// uint8_t in_len; // length of IN report -// uint8_t out_len; // length of OUT report + // uint8_t in_len; // length of IN report + // uint8_t out_len; // length of OUT report } tuh_hid_report_info_t; //--------------------------------------------------------------------+ @@ -68,10 +68,10 @@ uint8_t tuh_hid_itf_get_count(uint8_t dev_addr); uint8_t tuh_hid_itf_get_total_count(void); // backward compatible rename -#define tuh_hid_instance_count tuh_hid_itf_get_count +#define tuh_hid_instance_count tuh_hid_itf_get_count // Get Interface information -bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t* itf_info); +bool tuh_hid_itf_get_info(uint8_t daddr, uint8_t idx, tuh_itf_info_t *itf_info); // Get Interface index from device address + interface number // return TUSB_INDEX_INVALID_8 (0xFF) if not found @@ -85,8 +85,8 @@ bool tuh_hid_mounted(uint8_t dev_addr, uint8_t idx); // Parse report descriptor into array of report_info struct and return number of reports. // For complicated report, application should write its own parser. -TU_ATTR_UNUSED uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, - uint8_t const* desc_report, uint16_t desc_len); +TU_ATTR_UNUSED uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t *reports_info_arr, uint8_t arr_count, + const uint8_t *desc_report, uint16_t desc_len); //--------------------------------------------------------------------+ // Control Endpoint API @@ -107,12 +107,13 @@ bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t idx, uint8_t protocol); // Get Report using control endpoint // report_type is either Input, Output or Feature, (value from hid_report_type_t) -bool tuh_hid_get_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, void* report, uint16_t len); +bool tuh_hid_get_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, void *report, + uint16_t len); // Set Report using control endpoint // report_type is either Input, Output or Feature, (value from hid_report_type_t) -bool tuh_hid_set_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, - void* report, uint16_t len); +bool tuh_hid_set_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, void *report, + uint16_t len); //--------------------------------------------------------------------+ // Interrupt Endpoint API @@ -133,8 +134,9 @@ bool tuh_hid_receive_abort(uint8_t dev_addr, uint8_t idx); bool tuh_hid_send_ready(uint8_t dev_addr, uint8_t idx); // Send report using interrupt endpoint -// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent. -bool tuh_hid_send_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, const void* report, uint16_t len); +// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is +// sent. +bool tuh_hid_send_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, const void *report, uint16_t len); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) @@ -145,25 +147,27 @@ bool tuh_hid_send_report(uint8_t dev_addr, uint8_t idx, uint8_t report_id, const // can be used to parse common/simple enough descriptor. // Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped // therefore report_desc = NULL, desc_len = 0 -void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report_desc, uint16_t desc_len); +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t idx, const uint8_t *report_desc, uint16_t desc_len); // Invoked when device with hid interface is un-mounted void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t idx); // Invoked when received report from device via interrupt endpoint // Note: if there is report ID (composite), it is 1st byte of report -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report, uint16_t len); +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t idx, const uint8_t *report, uint16_t len); // Invoked when sent report to device successfully via interrupt endpoint -void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t idx, uint8_t const* report, uint16_t len); +void tuh_hid_report_sent_cb(uint8_t dev_addr, uint8_t idx, const uint8_t *report, uint16_t len); // Invoked when Get Report to device via either control endpoint // len = 0 indicate there is error in the transfer e.g stalled response -void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, uint16_t len); +void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, + uint16_t len); // Invoked when Sent Report to device via either control endpoint // len = 0 indicate there is error in the transfer e.g stalled response -void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, uint16_t len); +void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t report_id, uint8_t report_type, + uint16_t len); // Invoked when Set Protocol request is complete void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t protocol); @@ -171,12 +175,12 @@ void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t idx, uint8_t pro //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -bool hidh_init(void); -bool hidh_deinit(void); -bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len); -bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); -bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void hidh_close(uint8_t dev_addr); +bool hidh_init(void); +bool hidh_deinit(void); +uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len); +bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num); +bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void hidh_close(uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index b4f5ac445..5548a0ba8 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -192,15 +192,16 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint //--------------------------------------------------------------------+ // Enumeration //--------------------------------------------------------------------+ -bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { +uint16_t midih_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len) { (void) rhport; - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); - const uint8_t *p_end = ((const uint8_t *) desc_itf) + max_len; - const uint8_t *p_desc = (const uint8_t *) desc_itf; + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass, 0); + const uint8_t *desc_start = (const uint8_t *)desc_itf; + const uint8_t *p_desc = desc_start; + const uint8_t *desc_end = desc_start + max_len; const uint8_t idx = find_new_midi_index(); - TU_VERIFY(idx < CFG_TUH_MIDI); + TU_VERIFY(idx < CFG_TUH_MIDI, 0); midih_interface_t *p_midi = &_midi_host[idx]; p_midi->itf_count = 0; @@ -217,29 +218,30 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d // driver after parsing the audio control interface and then resume parsing // the streaming audio interface. if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { - TU_VERIFY(max_len > 2*sizeof(tusb_desc_interface_t) + sizeof(midi10_desc_cs_ac_interface_t)); - + TU_VERIFY(max_len > 2 * sizeof(tusb_desc_interface_t) + sizeof(midi10_desc_cs_ac_interface_t), 0); p_desc = tu_desc_next(p_desc); TU_VERIFY(tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && - tu_desc_subtype(p_desc) == AUDIO10_CS_AC_INTERFACE_HEADER); + tu_desc_subtype(p_desc) == AUDIO10_CS_AC_INTERFACE_HEADER, + 0); desc_cb.desc_audio_control = desc_itf; p_desc = tu_desc_next(p_desc); desc_itf = (const tusb_desc_interface_t *)p_desc; p_midi->itf_count = 1; // skip non-interface and non-midi streaming descriptors - while (tu_desc_in_bounds(p_desc, p_end) && - (desc_itf->bDescriptorType != TUSB_DESC_INTERFACE || (desc_itf->bInterfaceClass == TUSB_CLASS_AUDIO && desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING))) { + while (tu_desc_in_bounds(p_desc, desc_end) && (desc_itf->bDescriptorType != TUSB_DESC_INTERFACE || + (desc_itf->bInterfaceClass == TUSB_CLASS_AUDIO && + desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING))) { if (desc_itf->bDescriptorType == TUSB_DESC_INTERFACE && desc_itf->bAlternateSetting == 0) { p_midi->itf_count++; } p_desc = tu_desc_next(p_desc); - desc_itf = (tusb_desc_interface_t const *)p_desc; + desc_itf = (const tusb_desc_interface_t *)p_desc; } - TU_VERIFY(p_desc < p_end); // TODO: If MIDI interface comes after Audio Streaming, then max_len did not include the MIDI interface descriptor - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); + TU_VERIFY(p_desc < desc_end, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass, 0); } - TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass); + TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass, 0); TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber; @@ -250,7 +252,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d p_desc = tu_desc_next(p_desc); // next to CS Header bool found_new_interface = false; - while (tu_desc_in_bounds(p_desc, p_end) && !found_new_interface) { + while (tu_desc_in_bounds(p_desc, desc_end) && !found_new_interface) { switch (tu_desc_type(p_desc)) { case TUSB_DESC_INTERFACE: found_new_interface = true; @@ -287,8 +289,9 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d case TUSB_DESC_ENDPOINT: { const tusb_desc_endpoint_t *p_ep = (const tusb_desc_endpoint_t *) p_desc; + p_desc = tu_desc_next(p_desc); // next to CS endpoint - TU_VERIFY(p_desc < p_end && tu_desc_next(p_desc) <= p_end); + TU_VERIFY(tu_desc_in_bounds(p_desc, desc_end), 0); const midi_desc_cs_endpoint_t *p_csep = (const midi_desc_cs_endpoint_t *) p_desc; TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); @@ -302,7 +305,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d desc_cb.desc_epin = p_ep; ep_stream = &p_midi->ep_stream.rx; } - TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); + TU_ASSERT(tuh_edpt_open(dev_addr, p_ep), 0); tu_edpt_stream_open(ep_stream, dev_addr, p_ep); tu_edpt_stream_clear(ep_stream); @@ -313,12 +316,12 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d } p_desc = tu_desc_next(p_desc); } - desc_cb.desc_midi_total_len = (uint16_t) ((uintptr_t)p_desc - (uintptr_t) desc_itf); + desc_cb.desc_midi_total_len = (uint16_t)((uintptr_t)p_desc - (uintptr_t)desc_start); p_midi->daddr = dev_addr; tuh_midi_descriptor_cb(idx, &desc_cb); - return true; + return desc_cb.desc_midi_total_len; } bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 06554a03d..8a8dccab4 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -31,45 +31,45 @@ #include "midi.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ #ifndef CFG_TUH_MIDI_RX_BUFSIZE -#define CFG_TUH_MIDI_RX_BUFSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_MIDI_RX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif #ifndef CFG_TUH_MIDI_TX_BUFSIZE -#define CFG_TUH_MIDI_TX_BUFSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_MIDI_TX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif #ifndef CFG_TUH_MIDI_EP_BUFSIZE -#define CFG_TUH_MIDI_EP_BUFSIZE TUH_EPSIZE_BULK_MPS + #define CFG_TUH_MIDI_EP_BUFSIZE TUH_EPSIZE_BULK_MPS #endif // Enable the MIDI stream read/write API. Some library can work with raw USB MIDI packet // Disable this can save driver footprint. #ifndef CFG_TUH_MIDI_STREAM_API -#define CFG_TUH_MIDI_STREAM_API 1 + #define CFG_TUH_MIDI_STREAM_API 1 #endif //--------------------------------------------------------------------+ // Application Types //--------------------------------------------------------------------+ typedef struct { - const tusb_desc_interface_t* desc_audio_control; - const tusb_desc_interface_t* desc_midi; // start of whole midi interface descriptor - uint16_t desc_midi_total_len; + const tusb_desc_interface_t *desc_audio_control; + const tusb_desc_interface_t *desc_midi; // start of whole midi interface descriptor + uint16_t desc_midi_total_len; - const uint8_t* desc_header; - const uint8_t* desc_element; - const tusb_desc_endpoint_t* desc_epin; // endpoint IN descriptor, CS_ENDPOINT is right after - const tusb_desc_endpoint_t* desc_epout; // endpoint OUT descriptor, CS_ENDPOINT is right after + const uint8_t *desc_header; + const uint8_t *desc_element; + const tusb_desc_endpoint_t *desc_epin; // endpoint IN descriptor, CS_ENDPOINT is right after + const tusb_desc_endpoint_t *desc_epout; // endpoint OUT descriptor, CS_ENDPOINT is right after - uint8_t jack_num; - const uint8_t* desc_jack[32]; // list of jack descriptors (embedded + external) + uint8_t jack_num; + const uint8_t *desc_jack[32]; // list of jack descriptors (embedded + external) } tuh_midi_descriptor_cb_t; typedef struct { @@ -92,7 +92,7 @@ uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num); // Get Interface information // return true if index is correct and interface is currently mounted -bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info); +bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t *info); // return the number of virtual midi cables on the device's IN endpoint uint8_t tuh_midi_get_rx_cable_count(uint8_t idx); @@ -115,24 +115,22 @@ uint32_t tuh_midi_write_flush(uint8_t idx); // Read all available MIDI packets from the connected device // Return number of bytes read (always multiple of 4) -uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t* buffer, uint32_t bufsize); +uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t *buffer, uint32_t bufsize); // Read a raw MIDI packet from the connected device // Return true if a packet was returned -TU_ATTR_ALWAYS_INLINE static inline -bool tuh_midi_packet_read (uint8_t idx, uint8_t packet[4]) { - return 4 == tuh_midi_packet_read_n(idx, packet, 4); +TU_ATTR_ALWAYS_INLINE static inline bool tuh_midi_packet_read(uint8_t idx, uint8_t packet[4]) { + return 4 == tuh_midi_packet_read_n(idx, packet, 4); } // Write all 4-byte packets, data is locally buffered and only transferred when buffered bytes // reach the endpoint packet size or tuh_midi_write_flush() is called -uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bufsize); +uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t *buffer, uint32_t bufsize); // Write a 4-bytes packet to the device. // Returns true if the packet was successfully queued. -TU_ATTR_ALWAYS_INLINE static inline -bool tuh_midi_packet_write (uint8_t idx, uint8_t const packet[4]) { - return 4 == tuh_midi_packet_write_n(idx, packet, 4); +TU_ATTR_ALWAYS_INLINE static inline bool tuh_midi_packet_write(uint8_t idx, const uint8_t packet[4]) { + return 4 == tuh_midi_packet_write_n(idx, packet, 4); } //--------------------------------------------------------------------+ @@ -143,7 +141,7 @@ bool tuh_midi_packet_write (uint8_t idx, uint8_t const packet[4]) { // Queue a message to the device using stream API. data is locally buffered and only transferred when buffered bytes // reach the endpoint packet size or tuh_midi_write_flush() is called // Returns number of bytes was successfully queued. -uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *p_buffer, uint32_t bufsize); +uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, const uint8_t *p_buffer, uint32_t bufsize); // Get the MIDI stream from the device. Set the value pointed // to by p_cable_num to the MIDI cable number intended to receive it. @@ -162,10 +160,10 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff // Invoked when MIDI interface is detected in enumeration. Application can copy/parse descriptor if needed. // Note: may be fired before tuh_midi_mount_cb(), therefore midi interface is not mounted/ready. -void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb_data); +void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t *desc_cb_data); // Invoked when device with MIDI interface is mounted. -void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data); +void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t *mount_cb_data); // Invoked when device with MIDI interface is un-mounted void tuh_midi_umount_cb(uint8_t idx); @@ -179,12 +177,12 @@ void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -bool midih_init (void); -bool midih_deinit (void); -bool midih_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool midih_set_config (uint8_t dev_addr, uint8_t itf_num); -bool midih_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void midih_close (uint8_t daddr); +bool midih_init(void); +bool midih_deinit(void); +uint16_t midih_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len); +bool midih_set_config(uint8_t dev_addr, uint8_t itf_num); +bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void midih_close(uint8_t daddr); #ifdef __cplusplus } diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c index daff345c5..6a36c2820 100644 --- a/src/class/msc/msc_host.c +++ b/src/class/msc/msc_host.c @@ -379,22 +379,21 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, tuh_msc_complete_d static bool config_request_sense_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); static bool config_read_capacity_complete(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); -bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len) { +uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len) { (void) rhport; - TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && - MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol); + TU_VERIFY(MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass && MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol, 0); // msc driver length is fixed - uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + - desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); - TU_ASSERT(drv_len <= max_len); + const uint16_t drv_len = + (uint16_t)(sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); + TU_ASSERT(drv_len <= max_len, 0); - msch_interface_t* p_msc = get_itf(dev_addr); - tusb_desc_endpoint_t const* ep_desc = (tusb_desc_endpoint_t const*) tu_desc_next(desc_itf); + msch_interface_t *p_msc = get_itf(dev_addr); + const tusb_desc_endpoint_t *ep_desc = (const tusb_desc_endpoint_t *)tu_desc_next(desc_itf); for (uint32_t i = 0; i < 2; i++) { - TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer); - TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc)); + TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer, 0); + TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc), 0); if (TUSB_DIR_IN == tu_edpt_dir(ep_desc->bEndpointAddress)) { p_msc->ep_in = ep_desc->bEndpointAddress; @@ -407,7 +406,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* de p_msc->itf_num = desc_itf->bInterfaceNumber; - return true; + return drv_len; } bool msch_set_config(uint8_t daddr, uint8_t itf_num) { diff --git a/src/class/msc/msc_host.h b/src/class/msc/msc_host.h index b5fd55547..5dc7c0b94 100644 --- a/src/class/msc/msc_host.h +++ b/src/class/msc/msc_host.h @@ -30,7 +30,7 @@ #include "msc.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif //--------------------------------------------------------------------+ @@ -38,17 +38,17 @@ //--------------------------------------------------------------------+ #ifndef CFG_TUH_MSC_MAXLUN -#define CFG_TUH_MSC_MAXLUN 4 + #define CFG_TUH_MSC_MAXLUN 4 #endif typedef struct { - msc_cbw_t const* cbw; // SCSI command - msc_csw_t const* csw; // SCSI status - void* scsi_data; // SCSI Data - uintptr_t user_arg; // user argument -}tuh_msc_complete_data_t; + const msc_cbw_t *cbw; // SCSI command + const msc_csw_t *csw; // SCSI status + void *scsi_data; // SCSI Data + uintptr_t user_arg; // user argument +} tuh_msc_complete_data_t; -typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, tuh_msc_complete_data_t const* cb_data); +typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, const tuh_msc_complete_data_t *cb_data); //--------------------------------------------------------------------+ // Application API @@ -74,12 +74,14 @@ uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun); // Complete callback is invoked when SCSI op is complete. // return true if success, false if there is already pending operation. // NOTE: buffer must be accessible by USB/DMA controller, aligned correctly and multiple of cache line if enabled -bool tuh_msc_scsi_command(uint8_t daddr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); +bool tuh_msc_scsi_command(uint8_t daddr, const msc_cbw_t *cbw, void *data, tuh_msc_complete_cb_t complete_cb, + uintptr_t arg); // Perform SCSI Inquiry command // Complete callback is invoked when SCSI op is complete. // NOTE: response must be accessible by USB/DMA controller, aligned correctly and multiple of cache line if enabled -bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); +bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t *response, tuh_msc_complete_cb_t complete_cb, + uintptr_t arg); // Perform SCSI Test Unit Ready command // Complete callback is invoked when SCSI op is complete. @@ -88,23 +90,27 @@ bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_ // Perform SCSI Request Sense 10 command // Complete callback is invoked when SCSI op is complete. // NOTE: response must be accessible by USB/DMA controller, aligned correctly and multiple of cache line if enabled -bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); +bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *response, tuh_msc_complete_cb_t complete_cb, + uintptr_t arg); // Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer // Complete callback is invoked when SCSI op is complete. // NOTE: buffer must be accessible by USB/DMA controller, aligned correctly and multiple of cache line if enabled -bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); +bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void *buffer, uint32_t lba, uint16_t block_count, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg); // Perform SCSI Write 10 command. Write n blocks starting from LBA to device // Complete callback is invoked when SCSI op is complete. // NOTE: buffer must be accessible by USB/DMA controller, aligned correctly and multiple of cache line if enabled -bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); +bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, const void *buffer, uint32_t lba, uint16_t block_count, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg); // Perform SCSI Read Capacity 10 command // Complete callback is invoked when SCSI op is complete. // Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by // simply call tuh_msc_get_block_count() and tuh_msc_get_block_size() -bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb, uintptr_t arg); +bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t *response, + tuh_msc_complete_cb_t complete_cb, uintptr_t arg); //------------- Application Callback -------------// @@ -118,15 +124,15 @@ void tuh_msc_umount_cb(uint8_t dev_addr); // Internal Class Driver API //--------------------------------------------------------------------+ -bool msch_init (void); -bool msch_deinit (void); -bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool msch_set_config (uint8_t daddr, uint8_t itf_num); -void msch_close (uint8_t dev_addr); -bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +bool msch_init(void); +bool msch_deinit(void); +uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len); +bool msch_set_config(uint8_t daddr, uint8_t itf_num); +void msch_close(uint8_t dev_addr); +bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); #ifdef __cplusplus - } +} #endif #endif diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index b53fa5c02..d74760608 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -388,10 +388,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) { } TU_ATTR_ALWAYS_INLINE static inline bool tu_desc_in_bounds(const uint8_t *p_desc, const uint8_t *desc_end) { - if (p_desc >= desc_end) { - return false; - } - return tu_desc_next(p_desc) <= desc_end; + return p_desc < desc_end && tu_desc_next(p_desc) <= desc_end; } // find descriptor that match byte1 (type) diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index a94470039..586250163 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -99,9 +99,6 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_validate(tusb_desc_endpoint_t c bool tu_bind_driver_to_ep_itf(uint8_t driver_id, uint8_t ep2drv[][2], uint8_t itf2drv[], uint8_t itf_max, const uint8_t *p_desc, uint16_t desc_len); -// Calculate total length of n interfaces (depending on IAD) -uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len); - // Claim an endpoint with provided mutex bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex); diff --git a/src/host/hub.c b/src/host/hub.c index 0b172a596..3baaff30f 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -218,27 +218,27 @@ bool hub_deinit(void) { return true; } -bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { +uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && - 0 == itf_desc->bInterfaceSubClass); - TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); // not support multiple TT yet + 0 == itf_desc->bInterfaceSubClass, 0); + TU_VERIFY(itf_desc->bInterfaceProtocol <= 1, 0); // not support multiple TT yet - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len); + const uint16_t drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); + TU_ASSERT(drv_len <= max_len, 0); // Interrupt Status endpoint tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); + TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep), 0); hub_interface_t* p_hub = get_hub_itf(dev_addr); p_hub->itf_num = itf_desc->bInterfaceNumber; p_hub->ep_in = desc_ep->bEndpointAddress; - return true; + return drv_len; } void hub_close(uint8_t dev_addr) { diff --git a/src/host/hub.h b/src/host/hub.h index 3587f0ee3..d9750f8a5 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -206,12 +206,12 @@ bool hub_clear_feature(uint8_t hub_addr, uint8_t feature, tuh_xfer_cb_t complete //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -bool hub_init (void); -bool hub_deinit (void); -bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool hub_set_config (uint8_t daddr, uint8_t itf_num); -bool hub_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void hub_close (uint8_t dev_addr); +bool hub_init(void); +bool hub_deinit(void); +uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +bool hub_set_config(uint8_t daddr, uint8_t itf_num); +bool hub_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hub_close(uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/host/usbh.c b/src/host/usbh.c index 734024771..7c4910af1 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1815,85 +1815,51 @@ static bool enum_parse_configuration_desc(uint8_t dev_addr, tusb_desc_configurat TU_LOG_USBH("Parsing Configuration descriptor (wTotalLength = %u)\r\n", total_len); // parse each interfaces - while( p_desc < desc_end ) { - if ( 0 == tu_desc_len(p_desc) ) { + while (tu_desc_in_bounds(p_desc, desc_end)) { + if (0 == tu_desc_len(p_desc)) { // A zero length descriptor indicates that the device is off spec (e.g. wrong wTotalLength). // Parsed interfaces should still be usable TU_LOG_USBH("Encountered a zero-length descriptor after %" PRIu32 " bytes\r\n", (uint32_t)p_desc - (uint32_t)desc_cfg); break; } - uint8_t assoc_itf_count = 1; - - // Class will always starts with Interface Association (if any) and then Interface descriptor - if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; - assoc_itf_count = desc_iad->bInterfaceCount; - - p_desc = tu_desc_next(p_desc); // next to Interface - - // IAD's first interface number and class should match with opened interface - //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && - // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); - } - - TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - -#if CFG_TUH_MIDI - // MIDI has 2 interfaces (Audio Control v1 + MIDIStreaming) but does not have IAD - // manually force associated count = 2 - if (1 == assoc_itf_count && - TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) { - assoc_itf_count = 2; + // skip if not interface + if (TUSB_DESC_INTERFACE != tu_desc_type(p_desc)) { + p_desc = tu_desc_next(p_desc); + continue; } -#endif + const tusb_desc_interface_t *desc_itf = (const tusb_desc_interface_t *)p_desc; -#if CFG_TUH_CDC - // Some legacy CDC device does not use IAD but rather use device class as hint to combine 2 interfaces - // manually force associated count = 2 - if (1 == assoc_itf_count && - TUSB_CLASS_CDC == desc_itf->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == desc_itf->bInterfaceSubClass) { - assoc_itf_count = 2; - } -#endif - - uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, assoc_itf_count, (uint16_t) (desc_end-p_desc)); - TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t)); + // uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, assoc_itf_count, (uint16_t) + // (desc_end-p_desc)); TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t)); // Find driver for this interface - for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { - usbh_class_driver_t const * driver = get_driver(drv_id); - if (driver && driver->open(dev->bus_info.rhport, dev_addr, desc_itf, drv_len) ) { - // open successfully - TU_LOG_USBH(" %s opened\r\n", driver->name); - - // bind (associated) interfaces to found driver - for(uint8_t i=0; ibInterfaceNumber+i; - - // Interface number must not be used already - TU_ASSERT( TUSB_INDEX_INVALID_8 == dev->itf2drv[itf_num] ); - dev->itf2drv[itf_num] = drv_id; + const uint16_t remaining_len = (uint16_t)(desc_end - p_desc); + uint8_t drv_id; + for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { + const usbh_class_driver_t *driver = get_driver(drv_id); + if (driver) { + const uint16_t drv_len = driver->open(dev->bus_info.rhport, dev_addr, desc_itf, remaining_len); + if ((sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len)) { + // open successfully + TU_LOG_USBH(" %s opened\r\n", driver->name); + + // bind found driver to all interfaces and endpoint within drv_len + tu_bind_driver_to_ep_itf(drv_id, dev->ep2drv, dev->itf2drv, CFG_TUH_INTERFACE_MAX, p_desc, drv_len); + + p_desc += drv_len; // next Interface + break; // exit driver find loop } - - // bind all endpoints to found driver - tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); - - break; // exit driver find loop - } - - if (drv_id == TOTAL_DRIVER_COUNT - 1) { - TU_LOG_USBH("[%u:%u] Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", - dev->bus_info.rhport, dev_addr, desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); } } - // next Interface or IAD descriptor - p_desc += drv_len; + // no driver found + if (drv_id == TOTAL_DRIVER_COUNT) { + p_desc = tu_desc_next(p_desc); // skip this interface + TU_LOG_USBH("[%u:%u] Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", + dev->bus_info.rhport, dev_addr, desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, + desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); + } } return true; diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index d722bb7e8..57428e3c5 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -44,16 +44,15 @@ //--------------------------------------------------------------------+ // Class Driver API //--------------------------------------------------------------------+ - typedef struct { - char const* name; - bool (* const init )(void); - bool (* const deinit )(void); - bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); -} usbh_class_driver_t; + const char *name; + bool (*const init)(void); + bool (*const deinit)(void); + uint16_t (*const open)(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); + bool (*const set_config)(uint8_t dev_addr, uint8_t itf_num); + bool (*const xfer_cb)(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (*const close)(uint8_t dev_addr); + } usbh_class_driver_t; // Invoked when initializing host stack to get additional class drivers. // Can be implemented by application to extend/overwrite class driver support. diff --git a/src/tusb.c b/src/tusb.c index de6ec0211..c62052c97 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -310,37 +310,6 @@ bool tu_bind_driver_to_ep_itf(uint8_t driver_id, uint8_t ep2drv[][2], uint8_t it return true; } -uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len) { - uint8_t const* p_desc = (uint8_t const*) desc_itf; - uint16_t len = 0; - - while ((itf_count--) > 0) { - // Next on interface desc - len += tu_desc_len(desc_itf); - p_desc = tu_desc_next(p_desc); - - while (len < max_len) { - if (tu_desc_len(p_desc) == 0) { - // Escape infinite loop - break; - } - // return on IAD regardless of itf count - if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) { - return len; - } - if ((tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) && - ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0) { - break; - } - - len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); - } - } - - return len; -} - //--------------------------------------------------------------------+ // Endpoint Stream Helper for both Host and Device stack //--------------------------------------------------------------------+ -- cgit v1.3.1 From b73003745fb18818574baa89367fd618c36ad8b0 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 11 Dec 2025 16:22:51 +0700 Subject: move host hacked bulk mps out of tu_edpt_validate() --- src/class/cdc/cdc_host.c | 14 ++++++++++---- src/common/tusb_private.h | 6 ++---- src/device/usbd.c | 4 ++-- src/host/usbh.c | 9 ++++++++- src/tusb.c | 17 ++++------------- test/fuzz/device/cdc/src/fuzz.cc | 6 +++++- test/fuzz/device/msc/src/fuzz.cc | 7 +++++-- test/fuzz/device/net/src/fuzz.cc | 6 +++++- 8 files changed, 41 insertions(+), 28 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index ff1a8338d..0655ea1a7 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -29,6 +29,8 @@ #include "tusb_option.h" +#include + #if (CFG_TUH_ENABLED && CFG_TUH_CDC) #include "host/usbh.h" @@ -1190,7 +1192,8 @@ static uint16_t ftdi_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, TU_VERIFY(itf_desc->bInterfaceSubClass == 0xff && itf_desc->bInterfaceProtocol == 0xff && itf_desc->bNumEndpoints == 2, 0); - const uint16_t drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); + const uint16_t drv_len = + (uint16_t)(sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); @@ -1581,7 +1584,8 @@ enum { static uint16_t cp210x_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // CP210x Interface includes 1 vendor interface + 2 bulk endpoints TU_VERIFY(itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0 && itf_desc->bNumEndpoints == 2, 0); - const uint16_t drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); + const uint16_t drv_len = + (uint16_t)(sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); @@ -1756,7 +1760,8 @@ enum { static uint16_t ch34x_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // CH34x Interface includes 1 vendor interface + 2 bulk + 1 interrupt endpoints TU_VERIFY(itf_desc->bNumEndpoints == 3, 0); - const uint16_t drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); + const uint16_t drv_len = + (uint16_t)(sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t * p_cdc = make_new_itf(daddr, itf_desc); @@ -2092,7 +2097,8 @@ enum { static uint16_t pl2303_open(uint8_t daddr, const tusb_desc_interface_t *itf_desc, uint16_t max_len) { // PL2303 Interface includes 1 vendor interface + 1 interrupt endpoints + 2 bulk TU_VERIFY(itf_desc->bNumEndpoints == 3, 0); - const uint16_t drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); + const uint16_t drv_len = + (uint16_t)(sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); TU_VERIFY(drv_len <= max_len, 0); cdch_interface_t *p_cdc = make_new_itf(daddr, itf_desc); diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 586250163..10e12c2af 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -84,13 +84,11 @@ typedef struct { // Check if endpoint descriptor is valid per USB specs if debug is enabled #if CFG_TUSB_DEBUG -bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed, bool is_host); +bool tu_edpt_validate(const tusb_desc_endpoint_t *desc_ep, tusb_speed_t speed); #else -TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_validate(tusb_desc_endpoint_t const *desc_ep, tusb_speed_t speed, - bool is_host) { +TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_validate(const tusb_desc_endpoint_t *desc_ep, tusb_speed_t speed) { (void)desc_ep; (void)speed; - (void)is_host; return true; } #endif diff --git a/src/device/usbd.c b/src/device/usbd.c index 6fd88bf42..4cbba1240 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1331,7 +1331,7 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { rhport = _usbd_rhport; TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); - TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed, false)); + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t)_usbd_dev.speed)); return dcd_edpt_open(rhport, desc_ep); } @@ -1541,7 +1541,7 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress); TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX); - TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed, false)); + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t)_usbd_dev.speed)); _usbd_dev.ep_status[epnum][dir].stalled = 0; _usbd_dev.ep_status[epnum][dir].busy = 0; diff --git a/src/host/usbh.c b/src/host/usbh.c index 7c4910af1..5b14a15cb 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1066,7 +1066,14 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) { } bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const* desc_ep) { - TU_ASSERT(tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr), true)); + // HACK: some device incorrectly always report 512 bulk regardless of link speed, overwrite descriptor to force 64 + if (desc_ep->bmAttributes.xfer == TUSB_XFER_BULK && tu_edpt_packet_size(desc_ep) > 64 && + tuh_speed_get(dev_addr) == TUSB_SPEED_FULL) { + TU_LOG1(" WARN: EP max packet size is 512 in fullspeed, force to 64\r\n"); + tusb_desc_endpoint_t *hacked_ep = (tusb_desc_endpoint_t *)(uintptr_t)desc_ep; + hacked_ep->wMaxPacketSize = tu_htole16(64); + } + TU_ASSERT(tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr))); return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, desc_ep); } diff --git a/src/tusb.c b/src/tusb.c index c62052c97..f6ca3fabc 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -242,13 +242,13 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { } #if CFG_TUSB_DEBUG -bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed, bool is_host) { - uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); +bool tu_edpt_validate(const tusb_desc_endpoint_t *desc_ep, tusb_speed_t speed) { + const uint16_t max_packet_size = tu_edpt_packet_size(desc_ep); TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); switch (desc_ep->bmAttributes.xfer) { case TUSB_XFER_ISOCHRONOUS: { - uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023); + const uint16_t spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023); TU_ASSERT(max_packet_size <= spec_size); break; } @@ -259,16 +259,7 @@ bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed, b TU_ASSERT(max_packet_size == 512); } else { // Bulk fullspeed can only be 8, 16, 32, 64 - if (is_host && max_packet_size == 512) { - // HACK: while in host mode, some device incorrectly always report 512 regardless of link speed - // overwrite descriptor to force 64 - TU_LOG1(" WARN: EP max packet size is 512 in fullspeed, force to 64\r\n"); - tusb_desc_endpoint_t* hacked_ep = (tusb_desc_endpoint_t*) (uintptr_t) desc_ep; - hacked_ep->wMaxPacketSize = tu_htole16(64); - } else { - TU_ASSERT(max_packet_size == 8 || max_packet_size == 16 || - max_packet_size == 32 || max_packet_size == 64); - } + TU_ASSERT(max_packet_size == 8 || max_packet_size == 16 || max_packet_size == 32 || max_packet_size == 64); } break; diff --git a/test/fuzz/device/cdc/src/fuzz.cc b/test/fuzz/device/cdc/src/fuzz.cc index 0560e8621..ea13fce92 100644 --- a/test/fuzz/device/cdc/src/fuzz.cc +++ b/test/fuzz/device/cdc/src/fuzz.cc @@ -52,7 +52,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { provider.ConsumeIntegralInRange(0, Size)); fuzz_init(callback_data.data(), callback_data.size()); // init device stack on configured roothub port - tud_init(BOARD_TUD_RHPORT); + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUD_RHPORT, &dev_init); for (int i = 0; i < FUZZ_ITERATIONS; i++) { if (provider.remaining_bytes() == 0) { diff --git a/test/fuzz/device/msc/src/fuzz.cc b/test/fuzz/device/msc/src/fuzz.cc index 371d49882..8981e5570 100644 --- a/test/fuzz/device/msc/src/fuzz.cc +++ b/test/fuzz/device/msc/src/fuzz.cc @@ -46,8 +46,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { std::vector callback_data = provider.ConsumeBytes( provider.ConsumeIntegralInRange(0, Size)); fuzz_init(callback_data.data(), callback_data.size()); - // init device stack on configured roothub port - tud_init(BOARD_TUD_RHPORT); + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUD_RHPORT, &dev_init); for (int i = 0; i < FUZZ_ITERATIONS; i++) { if (provider.remaining_bytes() == 0) { diff --git a/test/fuzz/device/net/src/fuzz.cc b/test/fuzz/device/net/src/fuzz.cc index a6935928a..7c8c39acc 100644 --- a/test/fuzz/device/net/src/fuzz.cc +++ b/test/fuzz/device/net/src/fuzz.cc @@ -53,7 +53,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { provider.ConsumeIntegralInRange(0, Size)); fuzz_init(callback_data.data(), callback_data.size()); // init device stack on configured roothub port - tud_init(BOARD_TUD_RHPORT); + tusb_rhport_init_t dev_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUD_RHPORT, &dev_init); for (int i = 0; i < FUZZ_ITERATIONS; i++) { if (provider.remaining_bytes() == 0) { -- cgit v1.3.1 From 2f5d4dbab3a4b051eda35c7026d2568c7355decd Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 12 Dec 2025 00:51:57 +0700 Subject: fix edpt stream write/read to endpoint not yet opened --- src/class/cdc/cdc_device.c | 2 -- src/class/midi/midi_device.c | 3 --- src/common/tusb_fifo.c | 4 ++-- src/tusb.c | 2 ++ 4 files changed, 4 insertions(+), 7 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index 8ea4080cc..e2819ae4b 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -43,8 +43,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) - typedef struct { uint8_t rhport; uint8_t itf_num; diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index e0a5aa9c3..023a81595 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -171,15 +171,12 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void *buffer, ui bool tud_midi_n_packet_read(uint8_t itf, uint8_t packet[4]) { midid_interface_t *p_midi = &_midid_itf[itf]; tu_edpt_stream_t *ep_str = &p_midi->ep_stream.rx; - TU_VERIFY(tu_edpt_stream_is_opened(ep_str)); return 4 == tu_edpt_stream_read(ep_str, packet, 4); } uint32_t tud_midi_n_packet_read_n(uint8_t itf, uint8_t packets[], uint32_t max_packets) { midid_interface_t *p_midi = &_midid_itf[itf]; tu_edpt_stream_t *ep_str = &p_midi->ep_stream.rx; - TU_VERIFY(tu_edpt_stream_is_opened(ep_str), 0); - const uint32_t num_read = tu_edpt_stream_read(ep_str, packets, 4u * max_packets); return num_read >> 2u; } diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index ef787c6e6..2faf72ba8 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -289,7 +289,7 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd // Advance an absolute index // "absolute" index is only in the range of [0..2*depth) -TU_ATTR_ALWAYS_INLINE static inline uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) { +static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset) { // We limit the index space of p such that a correct wrap around happens // Check for a wrap around or if we are in unused index space - This has to be checked first!! // We are exploiting the wrap around to the correct index @@ -313,7 +313,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t idx2ptr(uint16_t depth, uint16_t id // Works on local copies of w // When an overwritable fifo is overflowed, rd_idx will be re-index so that it forms a full fifo -TU_ATTR_ALWAYS_INLINE static inline uint16_t correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { +static uint16_t correct_read_index(tu_fifo_t *f, uint16_t wr_idx) { uint16_t rd_idx; if (wr_idx >= f->depth) { rd_idx = wr_idx - f->depth; diff --git a/src/tusb.c b/src/tusb.c index f6ca3fabc..8ba9f0fff 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -332,6 +332,7 @@ bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool ove } static bool stream_claim(tu_edpt_stream_t *s) { + TU_VERIFY(s->ep_addr != 0); // must be opened if (s->is_host) { #if CFG_TUH_ENABLED return usbh_edpt_claim(s->hwid, s->ep_addr); @@ -446,6 +447,7 @@ uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t *s) { #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED if (0 == tu_fifo_depth(&s->ff)) { // non-fifo mode + TU_VERIFY(s->ep_addr > 0); // must be opened bool is_busy = true; if (s->is_host) { #if CFG_TUH_ENABLED -- cgit v1.3.1 From 8c5adcefbf64be17daa048414ba21552eab9c3a8 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 13 Dec 2025 13:54:53 +0100 Subject: tusb: fix stream write logic without fifo Signed-off-by: HiFiPhile --- src/tusb.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'src/tusb.c') diff --git a/src/tusb.c b/src/tusb.c index 8ba9f0fff..8117c3e3e 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -411,27 +411,19 @@ uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t *s) { } uint32_t tu_edpt_stream_write(tu_edpt_stream_t *s, const void *buffer, uint32_t bufsize) { - TU_VERIFY(bufsize > 0); - #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED if (0 == tu_fifo_depth(&s->ff)) { - // non-fifo mode + // non-fifo mode: TX need ep buffer + TU_VERIFY(s->ep_buf != NULL, 0); TU_VERIFY(stream_claim(s), 0); - uint32_t xact_len; - if (s->ep_buf != NULL) { - // using ep buf - xact_len = tu_min32(bufsize, s->ep_bufsize); - memcpy(s->ep_buf, buffer, xact_len); - } else { - // using hwfifo - xact_len = bufsize; - } - TU_ASSERT(stream_xfer(s, (uint16_t)xact_len), 0); - + uint32_t xact_len = tu_min32(bufsize, s->ep_bufsize); + memcpy(s->ep_buf, buffer, xact_len); + TU_ASSERT(stream_xfer(s, (uint16_t) xact_len), 0); return xact_len; } else #endif { + TU_VERIFY(bufsize > 0); const uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize); // flush if fifo has more than packet size or -- cgit v1.3.1 From aa183a50fc4bd7ca0c50f97477fe15bcd7020528 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 22 Dec 2025 21:11:32 +0100 Subject: limit fifo read size to ep_bufsize regardless ep_buf is used or not Signed-off-by: HiFiPhile --- src/tusb.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/tusb.c') diff --git a/src/tusb.c b/src/tusb.c index 8117c3e3e..9c5237d9f 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -485,9 +485,7 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t *s) { if (available >= s->mps) { // multiple of packet size limit by ep bufsize uint16_t count = (uint16_t) (available & ~(s->mps - 1)); - if (s->ep_buf != NULL) { - count = tu_min16(count, s->ep_bufsize); - } + count = tu_min16(count, s->ep_bufsize); TU_ASSERT(stream_xfer(s, count), 0); return count; } else { -- cgit v1.3.1 From 4e4398898040118969421dc236ec8f453f9b503d Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 30 Dec 2025 18:09:54 +0700 Subject: tusb_fifo remove item_size make it fifo of bytes --- src/class/audio/audio_device.c | 12 +-- src/common/tusb_fifo.c | 139 +++++++++++++++------------------- src/common/tusb_fifo.h | 39 +++++----- src/common/tusb_verify.h | 10 ++- src/osal/osal_none.h | 16 ++-- src/osal/osal_pico.h | 54 +++++++------ src/portable/synopsys/dwc2/dcd_dwc2.c | 17 ++--- src/tusb.c | 2 +- src/tusb_option.h | 1 + test/unit-test/project.yml | 1 + test/unit-test/test/test_fifo.c | 36 +-------- 11 files changed, 140 insertions(+), 187 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 55eba81dd..be0224811 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -674,17 +674,17 @@ void audiod_init(void) { switch (i) { #if CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ > 0 case 0: - tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ, true); break; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ > 0 case 1: - tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_IN_SW_BUF_SZ, true); break; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ > 0 case 2: - tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_in_ff, ep_in_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_IN_SW_BUF_SZ, true); break; #endif } @@ -716,17 +716,17 @@ void audiod_init(void) { switch (i) { #if CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ > 0 case 0: - tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_1, CFG_TUD_AUDIO_FUNC_1_EP_OUT_SW_BUF_SZ, true); break; #endif #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ > 0 case 1: - tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_2, CFG_TUD_AUDIO_FUNC_2_EP_OUT_SW_BUF_SZ, true); break; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ > 0 case 2: - tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, 1, true); + tu_fifo_config(&audio->ep_out_ff, ep_out_sw_buf.buf_3, CFG_TUD_AUDIO_FUNC_3_EP_OUT_SW_BUF_SZ, true); break; #endif } diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c index 450c31f57..7822b7aae 100644 --- a/src/common/tusb_fifo.c +++ b/src/common/tusb_fifo.c @@ -59,7 +59,7 @@ TU_ATTR_ALWAYS_INLINE static inline void ff_unlock(osal_mutex_t mutex) { //--------------------------------------------------------------------+ // Setup API //--------------------------------------------------------------------+ -bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable) { +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, bool overwritable) { // Limit index space to 2*depth - this allows for a fast "modulo" calculation // but limits the maximum depth to 2^16/2 = 2^15 and buffer overflows are detectable // only if overflow happens once (important for unsupervised DMA applications) @@ -72,7 +72,6 @@ bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_si f->buffer = (uint8_t *)buffer; f->depth = depth; - f->item_size = (uint16_t)(item_size & 0x7FFFu); f->overwritable = overwritable; f->rd_idx = 0u; f->wr_idx = 0u; @@ -130,7 +129,10 @@ enum { }; // Copy to fifo from fixed address buffer (usually a rx register) with TU_FIFO_FIXED_ADDR_RW32 mode -static void ff_push_fixed_addr(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len) { +static void ff_push_access_mode(uint8_t *ff_buf, const volatile fixed_access_item_t *reg_rx, uint16_t len, + uint8_t data_stride, uint8_t addr_stride) { + (void)data_stride; + (void)addr_stride; // Reading full available 16/32-bit data from const app address uint16_t n_items = len / sizeof(fixed_access_item_t); while (n_items--) { @@ -167,86 +169,70 @@ static void ff_pull_fixed_addr(volatile fixed_access_item_t *reg_tx, const uint8 #endif // send n items to fifo WITHOUT updating write pointer -static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, - tu_fifo_access_mode_t copy_mode) { - const uint16_t lin_count = f->depth - wr_ptr; - const uint16_t wrap_count = n - lin_count; - - uint16_t lin_bytes = lin_count * f->item_size; - uint16_t wrap_bytes = wrap_count * f->item_size; - - // current buffer of fifo - uint8_t *ff_buf = f->buffer + (wr_ptr * f->item_size); - - switch (copy_mode) { - case TU_FIFO_INC_ADDR_RW8: - if (n <= lin_count) { - // Linear only - memcpy(ff_buf, app_buf, n * f->item_size); +static void ff_push_n(const tu_fifo_t *f, const void *app_buf, uint16_t n, uint16_t wr_ptr, uint8_t data_stride, + uint8_t addr_stride) { + uint16_t lin_bytes = f->depth - wr_ptr; + uint16_t wrap_bytes = n - lin_bytes; + uint8_t *ff_buf = f->buffer + wr_ptr; + +#if CFG_TUSB_FIFO_MULTI_BYTES_ACCESS + if (data_stride > 1) { + const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf; + if (n <= lin_bytes) { + // Linear only + ff_push_access_mode(ff_buf, reg_rx, n, data_stride, addr_stride); + } else { + // Wrap around + + // Write full words to linear part of buffer + uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; + ff_push_access_mode(ff_buf, reg_rx, lin_nitems_bytes, data_stride, addr_stride); + ff_buf += lin_nitems_bytes; + + // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary + const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; + if (rem > 0) { + const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); + const fixed_access_item_t tmp = *reg_rx; + tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); + + wrap_bytes -= remrem; + ff_buf = f->buffer + remrem; // wrap around } else { - // Wrap around - memcpy(ff_buf, app_buf, lin_bytes); // linear part - memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part + ff_buf = f->buffer; // wrap around to beginning } - break; -#if CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH - case TU_FIFO_FIXED_ADDR_RW32: { - const volatile fixed_access_item_t *reg_rx = (volatile const fixed_access_item_t *)app_buf; - if (n <= lin_count) { - // Linear only - ff_push_fixed_addr(ff_buf, reg_rx, n * f->item_size); - } else { - // Wrap around - - // Write full words to linear part of buffer - uint16_t lin_nitems_bytes = lin_bytes & ~FIXED_ACCESS_REMAINDER_MASK; - ff_push_fixed_addr(ff_buf, reg_rx, lin_nitems_bytes); - ff_buf += lin_nitems_bytes; - - // There could be odd 1 byte (16bit) or 1-3 bytes (32bit) before the wrap-around boundary - const uint8_t rem = lin_bytes & FIXED_ACCESS_REMAINDER_MASK; - if (rem > 0) { - const uint8_t remrem = (uint8_t)tu_min16(wrap_bytes, sizeof(fixed_access_item_t) - rem); - const fixed_access_item_t tmp = *reg_rx; - tu_scatter_write32(tmp, ff_buf, rem, f->buffer, remrem); - - wrap_bytes -= remrem; - ff_buf = f->buffer + remrem; // wrap around - } else { - ff_buf = f->buffer; // wrap around to beginning - } - - // Write data wrapped part - if (wrap_bytes > 0) { - ff_push_fixed_addr(ff_buf, reg_rx, wrap_bytes); - } + // Write data wrapped part + if (wrap_bytes > 0) { + ff_push_access_mode(ff_buf, reg_rx, wrap_bytes, data_stride, addr_stride); } - break; } + } else #endif - - default: - break; // unknown mode + { + // single byte access + if (n <= lin_bytes) { + // Linear only + memcpy(ff_buf, app_buf, n); + } else { + // Wrap around + memcpy(ff_buf, app_buf, lin_bytes); // linear part + memcpy(f->buffer, ((const uint8_t *)app_buf) + lin_bytes, wrap_bytes); // wrapped part + } } } // get n items from fifo WITHOUT updating read pointer static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd_ptr, tu_fifo_access_mode_t copy_mode) { - const uint16_t lin_count = f->depth - rd_ptr; - const uint16_t wrap_count = n - lin_count; // only used if wrapped - - uint16_t lin_bytes = lin_count * f->item_size; - uint16_t wrap_bytes = wrap_count * f->item_size; - - // current buffer of fifo - const uint8_t *ff_buf = f->buffer + (rd_ptr * f->item_size); + uint16_t lin_bytes = f->depth - rd_ptr; + uint16_t wrap_bytes = n - lin_bytes; // only used if wrapped + const uint8_t *ff_buf = f->buffer + rd_ptr; switch (copy_mode) { case TU_FIFO_INC_ADDR_RW8: - if (n <= lin_count) { + if (n <= lin_bytes) { // Linear only - memcpy(app_buf, ff_buf, n * f->item_size); + memcpy(app_buf, ff_buf, n); } else { // Wrap around memcpy(app_buf, ff_buf, lin_bytes); // linear part @@ -258,9 +244,9 @@ static void ff_pull_n(const tu_fifo_t *f, void *app_buf, uint16_t n, uint16_t rd case TU_FIFO_FIXED_ADDR_RW32: { volatile fixed_access_item_t *reg_tx = (volatile fixed_access_item_t *)app_buf; - if (n <= lin_count) { + if (n <= lin_bytes) { // Linear only - ff_pull_fixed_addr(reg_tx, ff_buf, n * f->item_size); + ff_pull_fixed_addr(reg_tx, ff_buf, n); } else { // Wrap around case @@ -389,7 +375,8 @@ uint16_t tu_fifo_read_n_access_mode(tu_fifo_t *f, void *buffer, uint16_t n, tu_f } // Write n items to fifo with access mode -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode) { +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, + uint8_t addr_stride) { if (n == 0) { return 0; } @@ -415,8 +402,8 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, // function! Since it would end up in a race condition with read functions! if (n >= f->depth) { // Only copy last part - if (access_mode == TU_FIFO_INC_ADDR_RW8) { - buf8 += (n - f->depth) * f->item_size; + if (data_stride == TU_FIFO_INC_ADDR_RW8) { + buf8 += (n - f->depth); } else { // TODO should read from hw fifo to discard data, however reading an odd number could // accidentally discard data. @@ -451,7 +438,7 @@ uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); TU_LOG(TU_FIFO_DBG, "actual_n = %u, wr_ptr = %u", n, wr_ptr); - ff_push_n(f, buf8, n, wr_ptr, access_mode); + ff_push_n(f, buf8, n, wr_ptr, data_stride, addr_stride); f->wr_idx = advance_index(f->depth, wr_idx, n); TU_LOG(TU_FIFO_DBG, "\tnew_wr = %u\r\n", f->wr_idx); @@ -491,7 +478,7 @@ static bool ff_peek_local(tu_fifo_t *f, void *buf, uint16_t wr_idx, uint16_t rd_ } const uint16_t rd_ptr = idx2ptr(f->depth, rd_idx); - memcpy(buf, f->buffer + (rd_ptr * f->item_size), f->item_size); + memcpy(buf, f->buffer + rd_ptr, 1); return true; } @@ -526,7 +513,7 @@ bool tu_fifo_write(tu_fifo_t *f, const void *data) { ret = false; } else { const uint16_t wr_ptr = idx2ptr(f->depth, wr_idx); - memcpy(f->buffer + (wr_ptr * f->item_size), data, f->item_size); + memcpy(f->buffer + wr_ptr, data, 1); f->wr_idx = advance_index(f->depth, wr_idx, 1); ret = true; } diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index f58cc3fcb..b48cf4cea 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -58,6 +58,9 @@ extern "C" { #define CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH 0 #endif +#ifndef CFG_TUSB_FIFO_MULTI_BYTES_ACCESS + #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 0 +#endif /* Write/Read "pointer" is in the range of: 0 .. depth - 1, and is used to get the fifo data. * Write/Read "index" is always in the range of: 0 .. 2*depth-1 @@ -118,13 +121,9 @@ extern "C" { typedef struct { uint8_t *buffer; // buffer pointer uint16_t depth; // max items + bool overwritable; // ovwerwritable when full - struct TU_ATTR_PACKED { - uint16_t item_size : 15; // size of each item - bool overwritable : 1; // ovwerwritable when full - }; - - volatile uint16_t wr_idx; // write index + volatile uint16_t wr_idx; // write index TODO maybe can drop volatile volatile uint16_t rd_idx; // read index #if OSAL_MUTEX_REQUIRED @@ -141,17 +140,16 @@ typedef struct { } linear, wrapped; } tu_fifo_buffer_info_t; -#define TU_FIFO_INIT(_buffer, _depth, _type, _overwritable) \ - { \ - .buffer = _buffer, \ - .depth = _depth, \ - .item_size = sizeof(_type), \ - .overwritable = _overwritable, \ +#define TU_FIFO_INIT(_buffer, _depth, _overwritable) \ + { \ + .buffer = _buffer, \ + .depth = _depth, \ + .overwritable = _overwritable, \ } -#define TU_FIFO_DEF(_name, _depth, _type, _overwritable) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _type, _overwritable) +#define TU_FIFO_DEF(_name, _depth, _overwritable) \ + uint8_t _name##_buf[_depth]; \ + tu_fifo_t _name = TU_FIFO_INIT(_name##_buf, _depth, _overwritable) // Write modes intended to allow special read and write functions to be able to // copy data to and from USB hardware FIFOs as needed for e.g. STM32s and others @@ -163,7 +161,7 @@ typedef enum { //--------------------------------------------------------------------+ // Setup API //--------------------------------------------------------------------+ -bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, uint16_t item_size, bool overwritable); +bool tu_fifo_config(tu_fifo_t *f, void *buffer, uint16_t depth, bool overwritable); void tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable); void tu_fifo_clear(tu_fifo_t *f); @@ -223,14 +221,11 @@ uint16_t tu_fifo_discard_n(tu_fifo_t *f, uint16_t n); //--------------------------------------------------------------------+ // Write API //--------------------------------------------------------------------+ -uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, tu_fifo_access_mode_t access_mode); +uint16_t tu_fifo_write_n_access_mode(tu_fifo_t *f, const void *data, uint16_t n, uint8_t data_stride, + uint8_t addr_stride); bool tu_fifo_write(tu_fifo_t *f, const void *data); TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_INC_ADDR_RW8); -} - -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_write_n_fixed_addr(tu_fifo_t *f, const void *data, uint16_t n) { - return tu_fifo_write_n_access_mode(f, data, n, TU_FIFO_FIXED_ADDR_RW32); + return tu_fifo_write_n_access_mode(f, data, n, 1, 1); } //--------------------------------------------------------------------+ diff --git a/src/common/tusb_verify.h b/src/common/tusb_verify.h index 587554e7f..c9e06361c 100644 --- a/src/common/tusb_verify.h +++ b/src/common/tusb_verify.h @@ -96,10 +96,12 @@ * - TU_VERIFY_1ARGS : return false if failed * - TU_VERIFY_2ARGS : return provided value if failed *------------------------------------------------------------------*/ -#define TU_VERIFY_DEFINE(_cond, _ret) \ - do { \ - if (!(_cond)) { return _ret; } \ - } while(0) +#define TU_VERIFY_DEFINE(_cond, _ret) \ + do { \ + if (!(_cond)) { \ + return _ret; \ + } \ + } while (0) #define TU_VERIFY_1ARGS(_cond) TU_VERIFY_DEFINE(_cond, false) #define TU_VERIFY_2ARGS(_cond, _ret) TU_VERIFY_DEFINE(_cond, _ret) diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index aa6111a16..6ab18ace8 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -157,18 +157,18 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd typedef struct { void (* interrupt_set)(bool enabled); + uint16_t item_size; tu_fifo_t ff; } osal_queue_def_t; typedef osal_queue_def_t* osal_queue_t; // _int_set is used as mutex in OS NONE (disable/enable USB ISR) -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .interrupt_set = _int_set, \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } +#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ + uint8_t _name##_buf[_depth * sizeof(_type)]; \ + osal_queue_def_t _name = {.interrupt_set = _int_set, \ + .item_size = sizeof(_type), \ + .ff = TU_FIFO_INIT(_name##_buf, _depth * sizeof(_type), false)} TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { tu_fifo_clear(&qdef->ff); @@ -184,7 +184,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v (void) msec; // not used, always behave as msec = 0 qhdl->interrupt_set(false); - const bool success = tu_fifo_read(&qhdl->ff, data); + const bool success = tu_fifo_read_n(&qhdl->ff, data, qhdl->item_size); qhdl->interrupt_set(true); return success; @@ -195,7 +195,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void qhdl->interrupt_set(false); } - const bool success = tu_fifo_write(&qhdl->ff, data); + const bool success = tu_fifo_write_n(&qhdl->ff, data, qhdl->item_size); if (!in_isr) { qhdl->interrupt_set(true); diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index f5385071a..79b728e9a 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -47,40 +47,39 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { // Spinlock API //--------------------------------------------------------------------+ typedef critical_section_t osal_spinlock_t; // pico implement critical section with spinlock -#define OSAL_SPINLOCK_DEF(_name, _int_set) \ - osal_spinlock_t _name +#define OSAL_SPINLOCK_DEF(_name, _int_set) osal_spinlock_t _name TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { critical_section_init(ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + (void)in_isr; critical_section_enter_blocking(ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + (void)in_isr; critical_section_exit(ctx); } //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ -typedef struct semaphore osal_semaphore_def_t, * osal_semaphore_t; +typedef struct semaphore osal_semaphore_def_t, *osal_semaphore_t; -TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) { sem_init(semdef, 0, 255); return semdef; } TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) { - (void) semd_hdl; + (void)semd_hdl; return true; // nothing to do } TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - (void) in_isr; + (void)in_isr; return sem_release(sem_hdl); } @@ -96,15 +95,15 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t s // MUTEX API // Within tinyusb, mutex is never used in ISR context //--------------------------------------------------------------------+ -typedef struct mutex osal_mutex_def_t, * osal_mutex_t; +typedef struct mutex osal_mutex_def_t, *osal_mutex_t; -TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { mutex_init(mdef); return mdef; } TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) { - (void) mutex_hdl; + (void)mutex_hdl; return true; // nothing to do } @@ -123,46 +122,45 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd #include "common/tusb_fifo.h" typedef struct { - tu_fifo_t ff; + uint16_t item_size; + tu_fifo_t ff; struct critical_section critsec; // osal_queue may be used in IRQs, so need critical section } osal_queue_def_t; -typedef osal_queue_def_t* osal_queue_t; +typedef osal_queue_def_t *osal_queue_t; // role device/host is used by OS NONE for mutex (disable usb isr) only -#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ - uint8_t _name##_buf[_depth*sizeof(_type)]; \ - osal_queue_def_t _name = { \ - .ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \ - } +#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ + uint8_t _name##_buf[_depth * sizeof(_type)]; \ + osal_queue_def_t _name = {.item_size = sizeof(_type), .ff = TU_FIFO_INIT(_name##_buf, _depth * sizeof(_type), false)} -TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t *qdef) { critical_section_init(&qdef->critsec); - (void) tu_fifo_clear(&qdef->ff); - return (osal_queue_t) qdef; + tu_fifo_clear(&qdef->ff); + return (osal_queue_t)qdef; } TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) { - osal_queue_def_t* qdef = (osal_queue_def_t*) qhdl; + osal_queue_def_t *qdef = (osal_queue_def_t *)qhdl; critical_section_deinit(&qdef->critsec); return true; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { - (void) msec; // not used, always behave as msec = 0 +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void *data, uint32_t msec) { + (void)msec; // not used, always behave as msec = 0 critical_section_enter_blocking(&qhdl->critsec); - bool success = tu_fifo_read(&qhdl->ff, data); + bool success = tu_fifo_read_n(&qhdl->ff, data, qhdl->item_size); critical_section_exit(&qhdl->critsec); return success; } -TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) { - (void) in_isr; +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, const void *data, bool in_isr) { + (void)in_isr; critical_section_enter_blocking(&qhdl->critsec); - bool success = tu_fifo_write(&qhdl->ff, data); + bool success = tu_fifo_write_n(&qhdl->ff, data, qhdl->item_size); critical_section_exit(&qhdl->critsec); return success; diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index ba40498e6..aacef691f 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -345,10 +345,9 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } -static uint16_t epin_write_tx_fifo(uint8_t rhport, uint8_t epnum) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - dwc2_dep_t* const epin = &dwc2->ep[0][epnum]; - xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); +static uint16_t epin_write_tx_fifo(dwc2_regs_t *dwc2, uint8_t epnum) { + dwc2_dep_t *const epin = &dwc2->ep[0][epnum]; + xfer_ctl_t *const xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; const uint16_t remain_packets = tsiz.packet_count; @@ -438,7 +437,7 @@ static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uin dep->diepctl = depctl.value; // enable endpoint if (dir == TUSB_DIR_IN && total_bytes != 0) { - const uint16_t xferred_bytes = epin_write_tx_fifo(rhport, epnum); + const uint16_t xferred_bytes = epin_write_tx_fifo(dwc2, epnum); // Enable TXFE interrupt if there are still data to be sent // EP0 only sends one packet at a time, so no need to check for EP0 @@ -689,9 +688,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // into the USB buffer! bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes, bool is_isr) { (void) is_isr; - // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 - TU_ASSERT(ff->item_size == 1); - uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); @@ -893,7 +889,8 @@ static void handle_rxflvl_irq(uint8_t rhport) { if (byte_count != 0) { // Read packet off RxFIFO if (xfer->ff != NULL) { - tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32); + tu_fifo_write_n_access_mode(xfer->ff, (const void *)(uintptr_t)rx_fifo, byte_count, TU_FIFO_FIXED_ADDR_RW32, + 0); } else { dfifo_read_packet(dwc2, xfer->buffer, byte_count); xfer->buffer += byte_count; @@ -967,7 +964,7 @@ static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diep // - 64 bytes or // - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL) if (diepint_bm.txfifo_empty && tu_bit_test(dwc2->diepempmsk, epnum)) { - epin_write_tx_fifo(rhport, epnum); + epin_write_tx_fifo(dwc2, epnum); // Turn off TXFE if all bytes are written. dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; diff --git a/src/tusb.c b/src/tusb.c index 8117c3e3e..ed254a10b 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -316,7 +316,7 @@ bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool ove #endif s->is_host = is_host; - tu_fifo_config(&s->ff, ff_buf, ff_bufsize, 1, overwritable); + tu_fifo_config(&s->ff, ff_buf, ff_bufsize, overwritable); #if OSAL_MUTEX_REQUIRED if (ff_buf != NULL && ff_bufsize > 0) { diff --git a/src/tusb_option.h b/src/tusb_option.h index 1dc920d84..de54d33d8 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -307,6 +307,7 @@ #if defined(TUP_USBIP_DWC2) #if CFG_TUD_DWC2_SLAVE_ENABLE && !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUD_EDPT_DEDICATED_HWFIFO 1 + #define CFG_TUSB_FIFO_MULTI_BYTES_ACCESS 1 #endif #if CFG_TUH_DWC2_SLAVE_ENABLE && !CFG_TUH_DWC2_DMA_ENABLE diff --git a/test/unit-test/project.yml b/test/unit-test/project.yml index 3968faaef..d7646ca7f 100644 --- a/test/unit-test/project.yml +++ b/test/unit-test/project.yml @@ -129,6 +129,7 @@ :test: - _UNITY_TEST_ - CFG_TUSB_FIFO_ACCESS_FIXED_ADDR_WIDTH=32 + - CFG_TUSB_FIFO_MULTI_BYTES_ACCESS=1 :release: [] # Enable to inject name of a test as a unique compilation symbol into its respective executable build. diff --git a/test/unit-test/test/test_fifo.c b/test/unit-test/test/test_fifo.c index 35bbeaa62..d0e3c2d37 100644 --- a/test/unit-test/test/test_fifo.c +++ b/test/unit-test/test/test_fifo.c @@ -32,7 +32,7 @@ #define FIFO_SIZE 64 uint8_t tu_ff_buf[FIFO_SIZE * sizeof(uint8_t)]; -tu_fifo_t tu_ff = TU_FIFO_INIT(tu_ff_buf, FIFO_SIZE, uint8_t, false); +tu_fifo_t tu_ff = TU_FIFO_INIT(tu_ff_buf, FIFO_SIZE, false); tu_fifo_t *ff = &tu_ff; tu_fifo_buffer_info_t info; @@ -68,34 +68,6 @@ void test_normal(void) { } } -void test_item_size(void) { - uint8_t ff4_buf[FIFO_SIZE * sizeof(uint32_t)]; - tu_fifo_t ff4 = TU_FIFO_INIT(ff4_buf, FIFO_SIZE, uint32_t, false); - - uint32_t data4[2 * FIFO_SIZE]; - for (uint32_t i = 0; i < sizeof(data4) / 4; i++) { - data4[i] = i; - } - - // fill up fifo - tu_fifo_write_n(&ff4, data4, FIFO_SIZE); - - uint32_t rd_buf4[FIFO_SIZE]; - uint16_t rd_count; - - // read 0 -> 4 - rd_count = tu_fifo_read_n(&ff4, rd_buf4, 5); - TEST_ASSERT_EQUAL(5, rd_count); - TEST_ASSERT_EQUAL_UINT32_ARRAY(data4, rd_buf4, rd_count); // 0 -> 4 - - tu_fifo_write_n(&ff4, data4 + FIFO_SIZE, 5); - - // read all 5 -> 68 - rd_count = tu_fifo_read_n(&ff4, rd_buf4, FIFO_SIZE); - TEST_ASSERT_EQUAL(FIFO_SIZE, rd_count); - TEST_ASSERT_EQUAL_UINT32_ARRAY(data4 + 5, rd_buf4, rd_count); // 5 -> 68 -} - void test_read_n(void) { uint16_t rd_count; @@ -362,7 +334,7 @@ void test_rd_idx_wrap(void) { uint8_t buf[10]; uint8_t dst[10]; - tu_fifo_config(&ff10, buf, 10, 1, 1); + tu_fifo_config(&ff10, buf, 10, 1); uint16_t n; @@ -431,7 +403,7 @@ void test_write_n_fixed_addr_rw32_nowrap(void) { for (uint8_t n = 1; n <= 8; n++) { tu_fifo_clear(ff); - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); @@ -453,7 +425,7 @@ void test_write_n_fixed_addr_rw32_wrapped(void) { ff->wr_idx = FIFO_SIZE - 3; ff->rd_idx = FIFO_SIZE - 3; - uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, TU_FIFO_FIXED_ADDR_RW32); + uint16_t written = tu_fifo_write_n_access_mode(ff, (const void *)®, n, sizeof(uint32_t), 0); TEST_ASSERT_EQUAL(n, written); TEST_ASSERT_EQUAL(n, tu_fifo_count(ff)); -- cgit v1.3.1 From 86ca8fe717f379879298f6a723cafa897bae04de Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 14 Jan 2026 10:46:59 +0700 Subject: remove no-fifo mode in edpt stream API update vendor_device.c for direct usbd xfer when either RX/TX BUFSIZE is 0 i.e CFG_TUD_VENDOR_TXRX_BUFFERED = 0 --- src/class/vendor/vendor_device.c | 262 +++++++++++++++++++++++---------------- src/class/vendor/vendor_device.h | 44 ++++--- src/common/tusb_private.h | 8 -- src/tusb.c | 103 +++++---------- 4 files changed, 206 insertions(+), 211 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index b8e6fec6f..b917c8dc7 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -40,36 +40,33 @@ typedef struct { uint8_t rhport; uint8_t itf_num; + #if CFG_TUD_VENDOR_TXRX_BUFFERED /*------------- From this point, data is not cleared by bus reset -------------*/ - struct { - tu_edpt_stream_t tx; - tu_edpt_stream_t rx; - - #if CFG_TUD_VENDOR_TX_BUFSIZE > 0 - uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE]; - #endif - - #if CFG_TUD_VENDOR_RX_BUFSIZE > 0 - uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE]; + tu_edpt_stream_t tx_stream; + tu_edpt_stream_t rx_stream; + uint8_t tx_ff_buf[CFG_TUD_VENDOR_TX_BUFSIZE]; + uint8_t rx_ff_buf[CFG_TUD_VENDOR_RX_BUFSIZE]; + #else + uint8_t ep_in; + uint8_t ep_out; + uint16_t ep_in_mps; + uint16_t ep_out_mps; #endif - } stream; } vendord_interface_t; -#define ITF_MEM_RESET_SIZE (offsetof(vendord_interface_t, itf_num) + sizeof(((vendord_interface_t *)0)->itf_num)) + #if CFG_TUD_VENDOR_TXRX_BUFFERED + #define ITF_MEM_RESET_SIZE (offsetof(vendord_interface_t, itf_num) + TU_FIELD_SIZE(vendord_interface_t, itf_num)) + #else + #define ITF_MEM_RESET_SIZE sizeof(vendord_interface_t) + #endif static vendord_interface_t _vendord_itf[CFG_TUD_VENDOR]; -#if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 || CFG_TUD_VENDOR_RX_BUFSIZE == 0 + // Skip local EP buffer if dedicated hw FIFO is supported or no fifo mode + #if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 || !CFG_TUD_VENDOR_TXRX_BUFFERED typedef struct { - // Skip local EP buffer if dedicated hw FIFO is supported - #if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 || CFG_TUD_VENDOR_RX_BUFSIZE == 0 TUD_EPBUF_DEF(epout, CFG_TUD_VENDOR_EPSIZE); - #endif - - // Skip local EP buffer if dedicated hw FIFO is supported - #if CFG_TUD_EDPT_DEDICATED_HWFIFO == 0 TUD_EPBUF_DEF(epin, CFG_TUD_VENDOR_EPSIZE); - #endif } vendord_epbuf_t; CFG_TUD_MEM_SECTION static vendord_epbuf_t _vendord_epbuf[CFG_TUD_VENDOR]; @@ -78,7 +75,6 @@ CFG_TUD_MEM_SECTION static vendord_epbuf_t _vendord_epbuf[CFG_TUD_VENDOR]; //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ - TU_ATTR_WEAK void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint32_t bufsize) { (void)idx; (void)buffer; @@ -93,40 +89,44 @@ TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t idx, uint32_t sent_bytes) { //-------------------------------------------------------------------- // Application API //-------------------------------------------------------------------- - bool tud_vendor_n_mounted(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return p_itf->stream.rx.ep_addr || p_itf->stream.tx.ep_addr; + + #if CFG_TUD_VENDOR_TXRX_BUFFERED + return (p_itf->rx_stream.ep_addr != 0) || (p_itf->tx_stream.ep_addr != 0); + #else + return (p_itf->ep_out != 0) || (p_itf->ep_in != 0); + #endif } //--------------------------------------------------------------------+ // Read API //--------------------------------------------------------------------+ -#if CFG_TUD_VENDOR_RX_BUFSIZE > 0 + #if CFG_TUD_VENDOR_TXRX_BUFFERED uint32_t tud_vendor_n_available(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_read_available(&p_itf->stream.rx); + return tu_edpt_stream_read_available(&p_itf->rx_stream); } bool tud_vendor_n_peek(uint8_t idx, uint8_t *u8) { TU_VERIFY(idx < CFG_TUD_VENDOR); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_peek(&p_itf->stream.rx, u8); + return tu_edpt_stream_peek(&p_itf->rx_stream, u8); } uint32_t tud_vendor_n_read(uint8_t idx, void *buffer, uint32_t bufsize) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_read(&p_itf->stream.rx, buffer, bufsize); + return tu_edpt_stream_read(&p_itf->rx_stream, buffer, bufsize); } void tud_vendor_n_read_flush(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, ); vendord_interface_t *p_itf = &_vendord_itf[idx]; - tu_edpt_stream_clear(&p_itf->stream.rx); - tu_edpt_stream_read_xfer(&p_itf->stream.rx); + tu_edpt_stream_clear(&p_itf->rx_stream); + tu_edpt_stream_read_xfer(&p_itf->rx_stream); } #endif @@ -134,9 +134,17 @@ void tud_vendor_n_read_flush(uint8_t idx) { bool tud_vendor_n_read_xfer(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_read_xfer(&p_itf->stream.rx); + + #if CFG_TUD_VENDOR_TXRX_BUFFERED + return tu_edpt_stream_read_xfer(&p_itf->rx_stream); + + #else + // Non-FIFO mode + TU_VERIFY(usbd_edpt_claim(p_itf->rhport, p_itf->ep_out)); + return usbd_edpt_xfer(p_itf->rhport, p_itf->ep_out, _vendord_epbuf[idx].epout, CFG_TUD_VENDOR_EPSIZE, false); + #endif } -#endif + #endif //--------------------------------------------------------------------+ @@ -145,26 +153,45 @@ bool tud_vendor_n_read_xfer(uint8_t idx) { uint32_t tud_vendor_n_write(uint8_t idx, const void *buffer, uint32_t bufsize) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_write(&p_itf->stream.tx, buffer, (uint16_t)bufsize); + + #if CFG_TUD_VENDOR_TXRX_BUFFERED + return tu_edpt_stream_write(&p_itf->tx_stream, buffer, (uint16_t)bufsize); + + #else + // non-fifo mode: direct transfer + TU_VERIFY(usbd_edpt_claim(p_itf->rhport, p_itf->ep_in), 0); + const uint32_t xact_len = tu_min32(bufsize, CFG_TUD_VENDOR_EPSIZE); + memcpy(_vendord_epbuf[idx].epin, buffer, xact_len); + TU_ASSERT(usbd_edpt_xfer(p_itf->rhport, p_itf->ep_in, _vendord_epbuf[idx].epin, (uint16_t)xact_len, false), 0); + return xact_len; + #endif } -#if CFG_TUD_VENDOR_TX_BUFSIZE > 0 -uint32_t tud_vendor_n_write_flush(uint8_t idx) { +uint32_t tud_vendor_n_write_available(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_write_xfer(&p_itf->stream.tx); + + #if CFG_TUD_VENDOR_TXRX_BUFFERED + return tu_edpt_stream_write_available(&p_itf->tx_stream); + + #else + // Non-FIFO mode + TU_VERIFY(p_itf->ep_in > 0, 0); // must be opened + return usbd_edpt_busy(p_itf->rhport, p_itf->ep_in) ? 0 : CFG_TUD_VENDOR_EPSIZE; + #endif } -uint32_t tud_vendor_n_write_available(uint8_t idx) { + #if CFG_TUD_VENDOR_TXRX_BUFFERED +uint32_t tud_vendor_n_write_flush(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - return tu_edpt_stream_write_available(&p_itf->stream.tx); + return tu_edpt_stream_write_xfer(&p_itf->tx_stream); } bool tud_vendor_n_write_clear(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR, 0); vendord_interface_t *p_itf = &_vendord_itf[idx]; - tu_edpt_stream_clear(&p_itf->stream.tx); + tu_edpt_stream_clear(&p_itf->tx_stream); return true; } #endif @@ -175,48 +202,37 @@ bool tud_vendor_n_write_clear(uint8_t idx) { void vendord_init(void) { tu_memclr(_vendord_itf, sizeof(_vendord_itf)); - for(uint8_t i=0; i 0 - uint8_t *rx_ff_buf = p_itf->stream.rx_ff_buf; - #else - uint8_t *rx_ff_buf = NULL; - #endif + #endif - tu_edpt_stream_init(&p_itf->stream.rx, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, epout_buf, + uint8_t *rx_ff_buf = p_itf->rx_ff_buf; + tu_edpt_stream_init(&p_itf->rx_stream, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, epout_buf, CFG_TUD_VENDOR_EPSIZE); - #if CFG_TUD_VENDOR_TX_BUFSIZE > 0 - uint8_t *tx_ff_buf = p_itf->stream.tx_ff_buf; - #else - uint8_t *tx_ff_buf = NULL; - #endif - - tu_edpt_stream_init(&p_itf->stream.tx, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, epin_buf, + uint8_t *tx_ff_buf = p_itf->tx_ff_buf; + tu_edpt_stream_init(&p_itf->tx_stream, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, epin_buf, CFG_TUD_VENDOR_EPSIZE); } + #endif } bool vendord_deinit(void) { - for(uint8_t i=0; istream.rx); - tu_edpt_stream_deinit(&p_itf->stream.tx); + #if CFG_TUD_VENDOR_TXRX_BUFFERED + for (uint8_t i = 0; i < CFG_TUD_VENDOR; i++) { + vendord_interface_t *p_itf = &_vendord_itf[i]; + tu_edpt_stream_deinit(&p_itf->rx_stream); + tu_edpt_stream_deinit(&p_itf->tx_stream); } + #endif return true; } @@ -227,11 +243,12 @@ void vendord_reset(uint8_t rhport) { vendord_interface_t* p_itf = &_vendord_itf[i]; tu_memclr(p_itf, ITF_MEM_RESET_SIZE); - tu_edpt_stream_clear(&p_itf->stream.rx); - tu_edpt_stream_close(&p_itf->stream.rx); - - tu_edpt_stream_clear(&p_itf->stream.tx); - tu_edpt_stream_close(&p_itf->stream.tx); + #if CFG_TUD_VENDOR_TXRX_BUFFERED + tu_edpt_stream_clear(&p_itf->rx_stream); + tu_edpt_stream_close(&p_itf->rx_stream); + tu_edpt_stream_clear(&p_itf->tx_stream); + tu_edpt_stream_close(&p_itf->tx_stream); + #endif } } @@ -241,13 +258,25 @@ static uint8_t find_vendor_itf(uint8_t ep_addr) { const vendord_interface_t *p_vendor = &_vendord_itf[idx]; if (ep_addr == 0) { // find unused: require both ep == 0 - if (p_vendor->stream.rx.ep_addr == 0 && p_vendor->stream.tx.ep_addr == 0) { + #if CFG_TUD_VENDOR_TXRX_BUFFERED + if (p_vendor->rx_stream.ep_addr == 0 && p_vendor->tx_stream.ep_addr == 0) { return idx; } - } else if (ep_addr == p_vendor->stream.rx.ep_addr || ep_addr == p_vendor->stream.tx.ep_addr) { - return idx; + #else + if (p_vendor->ep_out == 0 && p_vendor->ep_in == 0) { + return idx; + } + #endif } else { - // nothing to do + #if CFG_TUD_VENDOR_TXRX_BUFFERED + if (ep_addr == p_vendor->rx_stream.ep_addr || ep_addr == p_vendor->tx_stream.ep_addr) { + return idx; + } + #else + if (ep_addr == p_vendor->ep_out || ep_addr == p_vendor->ep_in) { + return idx; + } + #endif } } return 0xff; @@ -273,28 +302,39 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uin const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); - // open endpoint stream, skip if already opened (multiple IN/OUT endpoints) + #if CFG_TUD_VENDOR_TXRX_BUFFERED + // open endpoint stream if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { - tu_edpt_stream_t *stream_tx = &p_vendor->stream.tx; - if (stream_tx->ep_addr == 0) { - tu_edpt_stream_open(stream_tx, rhport, desc_ep); - tu_edpt_stream_write_xfer(stream_tx); // flush pending data - } + tu_edpt_stream_t *tx_stream = &p_vendor->tx_stream; + tu_edpt_stream_open(tx_stream, rhport, desc_ep); + tu_edpt_stream_write_xfer(tx_stream); // flush pending data } else { - tu_edpt_stream_t *stream_rx = &p_vendor->stream.rx; - if (stream_rx->ep_addr == 0) { - tu_edpt_stream_open(stream_rx, rhport, desc_ep); - #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 - TU_ASSERT(tu_edpt_stream_read_xfer(stream_rx) > 0, 0); // prepare for incoming data - #endif - } + tu_edpt_stream_t *rx_stream = &p_vendor->rx_stream; + tu_edpt_stream_open(rx_stream, rhport, desc_ep); + #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 + TU_ASSERT(tu_edpt_stream_read_xfer(rx_stream) > 0, 0); // prepare for incoming data + #endif + } + #else + // Non-FIFO mode: store endpoint info + if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { + p_vendor->ep_in = desc_ep->bEndpointAddress; + p_vendor->ep_in_mps = tu_edpt_packet_size(desc_ep); + } else { + p_vendor->ep_out = desc_ep->bEndpointAddress; + p_vendor->ep_out_mps = tu_edpt_packet_size(desc_ep); + #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 + // Prepare for incoming data + TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, _vendord_epbuf[idx].epout, CFG_TUD_VENDOR_EPSIZE, false), 0); + #endif } + #endif } p_desc = tu_desc_next(p_desc); } - return (uint16_t) ((uintptr_t) p_desc - (uintptr_t) desc_itf); + return (uint16_t)((uintptr_t)p_desc - (uintptr_t)desc_itf); } bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { @@ -304,34 +344,36 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint TU_VERIFY(idx < CFG_TUD_VENDOR); vendord_interface_t *p_vendor = &_vendord_itf[idx]; - if (ep_addr == p_vendor->stream.rx.ep_addr) { - #if CFG_TUD_VENDOR_RX_BUFSIZE - // Received new data: put into stream's fifo - tu_edpt_stream_read_xfer_complete(&p_vendor->stream.rx, xferred_bytes); - #endif - - // invoke callback - #if CFG_TUD_VENDOR_RX_BUFSIZE == 0 - tud_vendor_rx_cb(idx, p_vendor->stream.rx.ep_buf, xferred_bytes); - #else +#if CFG_TUD_VENDOR_TXRX_BUFFERED + if (ep_addr == p_vendor->rx_stream.ep_addr) { + // Put received data to FIFO + tu_edpt_stream_read_xfer_complete(&p_vendor->rx_stream, xferred_bytes); tud_vendor_rx_cb(idx, NULL, 0); - #endif - - #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 - tu_edpt_stream_read_xfer(&p_vendor->stream.rx); // prepare next data - #endif - } else if (ep_addr == p_vendor->stream.tx.ep_addr) { + #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 + tu_edpt_stream_read_xfer(&p_vendor->rx_stream); // prepare next data + #endif + } else if (ep_addr == p_vendor->tx_stream.ep_addr) { // Send complete tud_vendor_tx_cb(idx, (uint16_t)xferred_bytes); - #if CFG_TUD_VENDOR_TX_BUFSIZE > 0 // try to send more if possible - if (0 == tu_edpt_stream_write_xfer(&p_vendor->stream.tx)) { + if (0 == tu_edpt_stream_write_xfer(&p_vendor->tx_stream)) { // If there is no data left, a ZLP should be sent if xferred_bytes is multiple of EP Packet size and not zero - tu_edpt_stream_write_zlp_if_needed(&p_vendor->stream.tx, xferred_bytes); + tu_edpt_stream_write_zlp_if_needed(&p_vendor->tx_stream, xferred_bytes); } - #endif } + #else + if (ep_addr == p_vendor->ep_out) { + // Non-FIFO mode: invoke callback with buffer + tud_vendor_rx_cb(idx, _vendord_epbuf[idx].epout, xferred_bytes); + #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 + usbd_edpt_xfer(rhport, p_vendor->ep_out, _vendord_epbuf[idx].epout, CFG_TUD_VENDOR_EPSIZE, false); + #endif + } else if (ep_addr == p_vendor->ep_in) { + // Send complete + tud_vendor_tx_cb(idx, (uint16_t)xferred_bytes); + } + #endif return true; } diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index c3de4c49d..101765bb1 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -50,8 +50,14 @@ extern "C" { #define CFG_TUD_VENDOR_TX_BUFSIZE 64 #endif +// Vendor is buffered (FIFO mode) if both TX and RX buffers are configured +// If either is 0, vendor operates in non-buffered (direct transfer) mode +#ifndef CFG_TUD_VENDOR_TXRX_BUFFERED + #define CFG_TUD_VENDOR_TXRX_BUFFERED ((CFG_TUD_VENDOR_RX_BUFSIZE > 0) && (CFG_TUD_VENDOR_TX_BUFSIZE > 0)) +#endif + // Application will manually schedule RX transfer. This can be useful when using with non-fifo (buffered) mode -// i.e. CFG_TUD_VENDOR_RX_BUFSIZE = 0 +// i.e. CFG_TUD_VENDOR_TXRX_BUFFERED = 0 #ifndef CFG_TUD_VENDOR_RX_MANUAL_XFER #define CFG_TUD_VENDOR_RX_MANUAL_XFER 0 #endif @@ -63,7 +69,8 @@ extern "C" { // Return whether the vendor interface is mounted bool tud_vendor_n_mounted(uint8_t idx); -#if CFG_TUD_VENDOR_RX_BUFSIZE > 0 +//------------- RX -------------// +#if CFG_TUD_VENDOR_TXRX_BUFFERED // Return number of available bytes for reading uint32_t tud_vendor_n_available(uint8_t idx); @@ -82,16 +89,17 @@ void tud_vendor_n_read_flush(uint8_t idx); bool tud_vendor_n_read_xfer(uint8_t idx); #endif +//------------- TX -------------// // Write to TX FIFO. This can be buffered and not sent immediately unless buffered bytes >= USB endpoint size uint32_t tud_vendor_n_write(uint8_t idx, const void *buffer, uint32_t bufsize); -#if CFG_TUD_VENDOR_TX_BUFSIZE > 0 +// Return number of bytes available for writing in TX FIFO (or endpoint if non-buffered) +uint32_t tud_vendor_n_write_available(uint8_t idx); + +#if CFG_TUD_VENDOR_TXRX_BUFFERED // Force sending buffered data, return number of bytes sent uint32_t tud_vendor_n_write_flush(uint8_t idx); -// Return number of bytes available for writing in TX FIFO -uint32_t tud_vendor_n_write_available(uint8_t idx); - // Clear the transmit FIFO bool tud_vendor_n_write_clear(uint8_t idx); #endif @@ -111,7 +119,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_mounted(void) { return tud_vendor_n_mounted(0); } -#if CFG_TUD_VENDOR_RX_BUFSIZE > 0 +#if CFG_TUD_VENDOR_TXRX_BUFFERED TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_available(void) { return tud_vendor_n_available(0); } @@ -127,6 +135,14 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_read(void *buffer, uint3 TU_ATTR_ALWAYS_INLINE static inline void tud_vendor_read_flush(void) { tud_vendor_n_read_flush(0); } + +TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_flush(void) { + return tud_vendor_n_write_flush(0); +} + +TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_write_clear(void) { + return tud_vendor_n_write_clear(0); +} #endif #if CFG_TUD_VENDOR_RX_MANUAL_XFER @@ -143,20 +159,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_str(const char *st return tud_vendor_n_write_str(0, str); } -#if CFG_TUD_VENDOR_TX_BUFSIZE > 0 -TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_flush(void) { - return tud_vendor_n_write_flush(0); -} - TU_ATTR_ALWAYS_INLINE static inline uint32_t tud_vendor_write_available(void) { return tud_vendor_n_write_available(0); } -TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_write_clear(void) { - return tud_vendor_n_write_clear(0); -} -#endif - // backward compatible #define tud_vendor_flush() tud_vendor_write_flush() @@ -165,8 +171,8 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_vendor_write_clear(void) { //--------------------------------------------------------------------+ // Invoked when received new data. -// - CFG_TUD_VENDOR_RX_BUFSIZE > 0; buffer and bufsize must not be used (both NULL,0) since data is in RX FIFO -// - CFG_TUD_VENDOR_RX_BUFSIZE = 0: Buffer and bufsize are valid +// - CFG_TUD_VENDOR_TXRX_BUFFERED = 1: buffer and bufsize must not be used (both NULL,0) since data is in RX FIFO +// - CFG_TUD_VENDOR_TXRX_BUFFERED = 0: Buffer and bufsize are valid void tud_vendor_rx_cb(uint8_t idx, const uint8_t *buffer, uint32_t bufsize); // Invoked when tx transfer is finished diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 10e12c2af..43ce7a1df 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -37,14 +37,6 @@ // Configuration //--------------------------------------------------------------------+ -#if CFG_TUD_ENABLED && CFG_TUD_VENDOR && (CFG_TUD_VENDOR_TX_BUFSIZE == 0 || CFG_TUD_VENDOR_RX_BUFSIZE == 0) - #define CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED 1 -#endif - -#ifndef CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED - #define CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED 0 -#endif - #define TUP_USBIP_CONTROLLER_NUM 2 extern tusb_role_t _tusb_rhport_role[TUP_USBIP_CONTROLLER_NUM]; diff --git a/src/tusb.c b/src/tusb.c index 256aa832f..bf82cdbe9 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -309,11 +309,9 @@ bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool ove uint16_t ff_bufsize, uint8_t *ep_buf, uint16_t ep_bufsize) { (void) is_tx; - #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED == 0 // FIFO is required if (ff_buf == NULL || ff_bufsize == 0) { return false; } - #endif s->is_host = is_host; tu_fifo_config(&s->ff, ff_buf, ff_bufsize, overwritable); @@ -411,88 +409,45 @@ uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t *s) { } uint32_t tu_edpt_stream_write(tu_edpt_stream_t *s, const void *buffer, uint32_t bufsize) { - #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED - if (0 == tu_fifo_depth(&s->ff)) { - // non-fifo mode: TX need ep buffer - TU_VERIFY(s->ep_buf != NULL, 0); - TU_VERIFY(stream_claim(s), 0); - uint32_t xact_len = tu_min32(bufsize, s->ep_bufsize); - memcpy(s->ep_buf, buffer, xact_len); - TU_ASSERT(stream_xfer(s, (uint16_t) xact_len), 0); - return xact_len; - } else - #endif - { - TU_VERIFY(bufsize > 0); - const uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize); - - // flush if fifo has more than packet size or - // in rare case: fifo depth is configured too small (which never reach packet size) - if ((tu_fifo_count(&s->ff) >= s->mps) || (tu_fifo_depth(&s->ff) < s->mps)) { - tu_edpt_stream_write_xfer(s); - } - return ret; + TU_VERIFY(bufsize > 0); + const uint16_t ret = tu_fifo_write_n(&s->ff, buffer, (uint16_t) bufsize); + + // flush if fifo has more than packet size or + // in rare case: fifo depth is configured too small (which never reach packet size) + if ((tu_fifo_count(&s->ff) >= s->mps) || (tu_fifo_depth(&s->ff) < s->mps)) { + tu_edpt_stream_write_xfer(s); } + return ret; } uint32_t tu_edpt_stream_write_available(tu_edpt_stream_t *s) { - #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED - if (0 == tu_fifo_depth(&s->ff)) { - // non-fifo mode - TU_VERIFY(s->ep_addr > 0); // must be opened - bool is_busy = true; - if (s->is_host) { - #if CFG_TUH_ENABLED - is_busy = usbh_edpt_busy(s->hwid, s->ep_addr); - #endif - } else { - #if CFG_TUD_ENABLED - is_busy = usbd_edpt_busy(s->hwid, s->ep_addr); - #endif - } - return is_busy ? 0 : s->ep_bufsize; - } else - #endif - { - return (uint32_t)tu_fifo_remaining(&s->ff); - } + return (uint32_t)tu_fifo_remaining(&s->ff); } //--------------------------------------------------------------------+ // Stream Read //--------------------------------------------------------------------+ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t *s) { - #if CFG_TUSB_EDPT_STREAM_NO_FIFO_ENABLED - if (0 == tu_fifo_depth(&s->ff)) { - // non-fifo mode: RX need ep buffer - TU_VERIFY(s->ep_buf != NULL, 0); - TU_VERIFY(stream_claim(s), 0); - TU_ASSERT(stream_xfer(s, s->ep_bufsize), 0); - return s->ep_bufsize; - } else - #endif - { - uint16_t available = tu_fifo_remaining(&s->ff); - - // Prepare for incoming data but only allow what we can store in the ring buffer. - // TODO Actually we can still carry out the transfer, keeping count of received bytes - // and slowly move it to the FIFO when read(). - // This pre-check reduces endpoint claiming - TU_VERIFY(available >= s->mps); - TU_VERIFY(stream_claim(s), 0); - available = tu_fifo_remaining(&s->ff); // re-get available since fifo can be changed - - if (available >= s->mps) { - // multiple of packet size limit by ep bufsize - uint16_t count = (uint16_t) (available & ~(s->mps - 1)); - count = tu_min16(count, s->ep_bufsize); - TU_ASSERT(stream_xfer(s, count), 0); - return count; - } else { - // Release endpoint since we don't make any transfer - stream_release(s); - return 0; - } + uint16_t available = tu_fifo_remaining(&s->ff); + + // Prepare for incoming data but only allow what we can store in the ring buffer. + // TODO Actually we can still carry out the transfer, keeping count of received bytes + // and slowly move it to the FIFO when read(). + // This pre-check reduces endpoint claiming + TU_VERIFY(available >= s->mps); + TU_VERIFY(stream_claim(s), 0); + available = tu_fifo_remaining(&s->ff); // re-get available since fifo can be changed + + if (available >= s->mps) { + // multiple of packet size limit by ep bufsize + uint16_t count = (uint16_t) (available & ~(s->mps - 1)); + count = tu_min16(count, s->ep_bufsize); + TU_ASSERT(stream_xfer(s, count), 0); + return count; + } else { + // Release endpoint since we don't make any transfer + stream_release(s); + return 0; } } -- cgit v1.3.1 From 042ebc04b325f95d593d337317709adc74e7b435 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 16 Jan 2026 16:17:05 +0100 Subject: fix stream write racing Signed-off-by: HiFiPhile --- src/tusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/tusb.c') diff --git a/src/tusb.c b/src/tusb.c index bf82cdbe9..6075e9db4 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -392,7 +392,7 @@ uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t *s) { // Pull data from FIFO -> EP buf uint16_t count; if (s->ep_buf == NULL) { - count = ff_count; + count = tu_fifo_count(&s->ff); // re-get count since fifo can be changed } else { count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); } -- cgit v1.3.1 From 135a130ba51d2e41b30f13fbd998f1db32a47470 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Wed, 11 Feb 2026 22:04:44 +0100 Subject: fix rx transfer length when high speed capable device/host working at full speed Signed-off-by: HiFiPhile --- src/class/cdc/cdc_device.c | 12 ++++++------ src/class/cdc/cdc_device.h | 2 ++ src/class/cdc/cdc_host.c | 8 ++++---- src/class/midi/midi_device.c | 8 ++++---- src/class/midi/midi_host.c | 6 +++--- src/class/vendor/vendor_device.c | 36 +++++++++++++++++++++--------------- src/class/vendor/vendor_device.h | 17 ++++++++++++++++- src/common/tusb_private.h | 7 ++++--- src/tusb.c | 7 +++---- 9 files changed, 63 insertions(+), 40 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c index e2819ae4b..eca4d0ad6 100644 --- a/src/class/cdc/cdc_device.c +++ b/src/class/cdc/cdc_device.c @@ -74,7 +74,7 @@ typedef struct { } cdcd_epbuf_t; CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC]; -#endif + #endif //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available @@ -267,14 +267,13 @@ void cdcd_init(void) { uint8_t *epin_buf = _cdcd_epbuf[i].epin; #endif - tu_edpt_stream_init(&p_cdc->rx_stream, false, false, false, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, epout_buf, - CFG_TUD_CDC_EP_BUFSIZE); + tu_edpt_stream_init(&p_cdc->rx_stream, false, false, false, p_cdc->rx_ff_buf, CFG_TUD_CDC_RX_BUFSIZE, epout_buf); // TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not // know if data is actually polled by terminal. This way the most current data is prioritized. // Default: is overwritable tu_edpt_stream_init(&p_cdc->tx_stream, false, true, _cdcd_cfg.tx_overwritabe_if_not_connected, p_cdc->tx_ff_buf, - CFG_TUD_CDC_TX_BUFSIZE, epin_buf, CFG_TUD_CDC_EP_BUFSIZE); + CFG_TUD_CDC_TX_BUFSIZE, epin_buf); } } @@ -349,7 +348,7 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16 if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { tu_edpt_stream_t *stream_tx = &p_cdc->tx_stream; - tu_edpt_stream_open(stream_tx, rhport, desc_ep); + tu_edpt_stream_open(stream_tx, rhport, desc_ep, CFG_TUD_CDC_EP_BUFSIZE); if (_cdcd_cfg.tx_persistent) { tu_edpt_stream_write_xfer(stream_tx); // flush pending data } else { @@ -358,7 +357,8 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16 } else { tu_edpt_stream_t *stream_rx = &p_cdc->rx_stream; - tu_edpt_stream_open(stream_rx, rhport, desc_ep); + tu_edpt_stream_open(stream_rx, rhport, desc_ep, + _cdcd_cfg.rx_multiple_packet_transfer ? CFG_TUD_CDC_EP_BUFSIZE : tu_edpt_packet_size(desc_ep)); if (!_cdcd_cfg.rx_persistent) { tu_edpt_stream_clear(stream_rx); } diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h index 0809b578f..2d3a81f60 100644 --- a/src/class/cdc/cdc_device.h +++ b/src/class/cdc/cdc_device.h @@ -64,6 +64,7 @@ typedef struct TU_ATTR_PACKED { bool rx_persistent : 1; // keep rx fifo data even with bus reset or disconnect bool tx_persistent : 1; // keep tx fifo data even with reset or disconnect bool tx_overwritabe_if_not_connected : 1; // if not connected, tx fifo can be overwritten + bool rx_multiple_packet_transfer : 1; // allow transfer more than one packet in a single transfer, increase throughput but requires host sending ZLP at the end of transfer } tud_cdc_configure_t; TU_VERIFY_STATIC(sizeof(tud_cdc_configure_t) == 1, "size is not correct"); @@ -71,6 +72,7 @@ TU_VERIFY_STATIC(sizeof(tud_cdc_configure_t) == 1, "size is not correct"); .rx_persistent = false, \ .tx_persistent = false, \ .tx_overwritabe_if_not_connected = true, \ + .rx_multiple_packet_transfer = false, \ } // Configure CDC driver behavior diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index f19c4a327..8b5667aac 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -648,10 +648,10 @@ bool cdch_init(void) { for (size_t i = 0; i < CFG_TUH_CDC; i++) { cdch_interface_t *p_cdc = &cdch_data[i]; cdch_epbuf_t *epbuf = &cdch_epbuf[i]; - TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE, - epbuf->tx, CFG_TUH_CDC_TX_EPSIZE)); + TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false, p_cdc->stream.tx_ff_buf, + CFG_TUH_CDC_TX_BUFSIZE, epbuf->tx)); TU_ASSERT(tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false, p_cdc->stream.rx_ff_buf, - CFG_TUH_CDC_RX_BUFSIZE, epbuf->rx, CFG_TUH_CDC_RX_EPSIZE)); + CFG_TUH_CDC_RX_BUFSIZE, epbuf->rx)); } return true; @@ -735,7 +735,7 @@ static bool open_ep_stream_pair(cdch_interface_t *p_cdc, tusb_desc_endpoint_t co TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep)); const uint8_t ep_dir = tu_edpt_dir(desc_ep->bEndpointAddress); tu_edpt_stream_t *stream = (ep_dir == TUSB_DIR_IN) ? &p_cdc->stream.rx : &p_cdc->stream.tx; - tu_edpt_stream_open(stream, p_cdc->daddr, desc_ep); + tu_edpt_stream_open(stream, p_cdc->daddr, desc_ep, desc_ep->wMaxPacketSize); tu_edpt_stream_clear(stream); desc_ep = (const tusb_desc_endpoint_t *)tu_desc_next(desc_ep); diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 023a81595..173baf53e 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -324,10 +324,10 @@ void midid_init(void) { #endif tu_edpt_stream_init(&p_midi->ep_stream.rx, false, false, false, p_midi->ep_stream.rx_ff_buf, - CFG_TUD_MIDI_RX_BUFSIZE, epout_buf, CFG_TUD_MIDI_EP_BUFSIZE); + CFG_TUD_MIDI_RX_BUFSIZE, epout_buf); tu_edpt_stream_init(&p_midi->ep_stream.tx, false, true, false, p_midi->ep_stream.tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, - epin_buf, CFG_TUD_MIDI_EP_BUFSIZE); + epin_buf); } } @@ -408,11 +408,11 @@ uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uint1 if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { tu_edpt_stream_t *stream_tx = &p_midi->ep_stream.tx; - tu_edpt_stream_open(stream_tx, rhport, desc_ep); + tu_edpt_stream_open(stream_tx, rhport, desc_ep, CFG_TUD_MIDI_EP_BUFSIZE); tu_edpt_stream_clear(stream_tx); } else { tu_edpt_stream_t *stream_rx = &p_midi->ep_stream.rx; - tu_edpt_stream_open(stream_rx, rhport, desc_ep); + tu_edpt_stream_open(stream_rx, rhport, desc_ep, tu_edpt_packet_size(desc_ep)); tu_edpt_stream_clear(stream_rx); TU_ASSERT(tu_edpt_stream_read_xfer(stream_rx) > 0, 0); // prepare to receive data } diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 5548a0ba8..a3d61a02f 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -121,9 +121,9 @@ bool midih_init(void) { for (int inst = 0; inst < CFG_TUH_MIDI; inst++) { midih_interface_t *p_midi_host = &_midi_host[inst]; tu_edpt_stream_init(&p_midi_host->ep_stream.rx, true, false, false, - p_midi_host->ep_stream.rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, _midi_epbuf->rx, TUH_EPSIZE_BULK_MPS); + p_midi_host->ep_stream.rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, _midi_epbuf->rx); tu_edpt_stream_init(&p_midi_host->ep_stream.tx, true, true, false, - p_midi_host->ep_stream.tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, _midi_epbuf->tx, TUH_EPSIZE_BULK_MPS); + p_midi_host->ep_stream.tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, _midi_epbuf->tx); } return true; } @@ -306,7 +306,7 @@ uint16_t midih_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_ ep_stream = &p_midi->ep_stream.rx; } TU_ASSERT(tuh_edpt_open(dev_addr, p_ep), 0); - tu_edpt_stream_open(ep_stream, dev_addr, p_ep); + tu_edpt_stream_open(ep_stream, dev_addr, p_ep, p_ep->wMaxPacketSize); tu_edpt_stream_clear(ep_stream); break; diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index b917c8dc7..b2dd8f394 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -49,8 +49,7 @@ typedef struct { #else uint8_t ep_in; uint8_t ep_out; - uint16_t ep_in_mps; - uint16_t ep_out_mps; + uint16_t rx_xfer_len; #endif } vendord_interface_t; @@ -72,6 +71,8 @@ typedef struct { CFG_TUD_MEM_SECTION static vendord_epbuf_t _vendord_epbuf[CFG_TUD_VENDOR]; #endif +static tud_vendor_configure_t _vendord_cfg = TUD_VENDOR_CONFIGURE_DEFAULT(); + //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ @@ -89,6 +90,12 @@ TU_ATTR_WEAK void tud_vendor_tx_cb(uint8_t idx, uint32_t sent_bytes) { //-------------------------------------------------------------------- // Application API //-------------------------------------------------------------------- +bool tud_vendor_configure(const tud_vendor_configure_t* driver_cfg) { + TU_VERIFY(driver_cfg != NULL); + _vendord_cfg = *driver_cfg; + return true; +} + bool tud_vendor_n_mounted(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR); vendord_interface_t *p_itf = &_vendord_itf[idx]; @@ -128,9 +135,9 @@ void tud_vendor_n_read_flush(uint8_t idx) { tu_edpt_stream_clear(&p_itf->rx_stream); tu_edpt_stream_read_xfer(&p_itf->rx_stream); } -#endif + #endif -#if CFG_TUD_VENDOR_RX_MANUAL_XFER + #if CFG_TUD_VENDOR_RX_MANUAL_XFER bool tud_vendor_n_read_xfer(uint8_t idx) { TU_VERIFY(idx < CFG_TUD_VENDOR); vendord_interface_t *p_itf = &_vendord_itf[idx]; @@ -141,7 +148,7 @@ bool tud_vendor_n_read_xfer(uint8_t idx) { #else // Non-FIFO mode TU_VERIFY(usbd_edpt_claim(p_itf->rhport, p_itf->ep_out)); - return usbd_edpt_xfer(p_itf->rhport, p_itf->ep_out, _vendord_epbuf[idx].epout, CFG_TUD_VENDOR_EPSIZE, false); + return usbd_edpt_xfer(p_itf->rhport, p_itf->ep_out, _vendord_epbuf[idx].epout, p_itf->rx_xfer_len, false); #endif } #endif @@ -215,12 +222,10 @@ void vendord_init(void) { #endif uint8_t *rx_ff_buf = p_itf->rx_ff_buf; - tu_edpt_stream_init(&p_itf->rx_stream, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, epout_buf, - CFG_TUD_VENDOR_EPSIZE); + tu_edpt_stream_init(&p_itf->rx_stream, false, false, false, rx_ff_buf, CFG_TUD_VENDOR_RX_BUFSIZE, epout_buf); uint8_t *tx_ff_buf = p_itf->tx_ff_buf; - tu_edpt_stream_init(&p_itf->tx_stream, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, epin_buf, - CFG_TUD_VENDOR_EPSIZE); + tu_edpt_stream_init(&p_itf->tx_stream, false, true, false, tx_ff_buf, CFG_TUD_VENDOR_TX_BUFSIZE, epin_buf); } #endif } @@ -302,30 +307,31 @@ uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t *desc_itf, uin const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc; TU_ASSERT(usbd_edpt_open(rhport, desc_ep)); + uint16_t rx_xfer_len = _vendord_cfg.rx_multiple_packet_transfer ? CFG_TUD_VENDOR_EPSIZE : tu_edpt_packet_size(desc_ep); + #if CFG_TUD_VENDOR_TXRX_BUFFERED // open endpoint stream if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { tu_edpt_stream_t *tx_stream = &p_vendor->tx_stream; - tu_edpt_stream_open(tx_stream, rhport, desc_ep); + tu_edpt_stream_open(tx_stream, rhport, desc_ep, CFG_TUD_VENDOR_EPSIZE); tu_edpt_stream_write_xfer(tx_stream); // flush pending data } else { tu_edpt_stream_t *rx_stream = &p_vendor->rx_stream; - tu_edpt_stream_open(rx_stream, rhport, desc_ep); + tu_edpt_stream_open(rx_stream, rhport, desc_ep, rx_xfer_len); #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 TU_ASSERT(tu_edpt_stream_read_xfer(rx_stream) > 0, 0); // prepare for incoming data #endif } #else + p_vendor->rx_xfer_len = rx_xfer_len; // Non-FIFO mode: store endpoint info if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) { p_vendor->ep_in = desc_ep->bEndpointAddress; - p_vendor->ep_in_mps = tu_edpt_packet_size(desc_ep); } else { p_vendor->ep_out = desc_ep->bEndpointAddress; - p_vendor->ep_out_mps = tu_edpt_packet_size(desc_ep); #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 // Prepare for incoming data - TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, _vendord_epbuf[idx].epout, CFG_TUD_VENDOR_EPSIZE, false), 0); + TU_ASSERT(usbd_edpt_xfer(rhport, p_vendor->ep_out, _vendord_epbuf[idx].epout, rx_xfer_len, false), 0); #endif } #endif @@ -367,7 +373,7 @@ bool vendord_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint // Non-FIFO mode: invoke callback with buffer tud_vendor_rx_cb(idx, _vendord_epbuf[idx].epout, xferred_bytes); #if CFG_TUD_VENDOR_RX_MANUAL_XFER == 0 - usbd_edpt_xfer(rhport, p_vendor->ep_out, _vendord_epbuf[idx].epout, CFG_TUD_VENDOR_EPSIZE, false); + usbd_edpt_xfer(rhport, p_vendor->ep_out, _vendord_epbuf[idx].epout, p_vendor->rx_xfer_len, false); #endif } else if (ep_addr == p_vendor->ep_in) { // Send complete diff --git a/src/class/vendor/vendor_device.h b/src/class/vendor/vendor_device.h index 101765bb1..594da19cb 100644 --- a/src/class/vendor/vendor_device.h +++ b/src/class/vendor/vendor_device.h @@ -37,7 +37,7 @@ extern "C" { // Configuration //--------------------------------------------------------------------+ #ifndef CFG_TUD_VENDOR_EPSIZE - #define CFG_TUD_VENDOR_EPSIZE 64 + #define CFG_TUD_VENDOR_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) #endif // RX FIFO can be disabled by setting this value to 0 @@ -62,6 +62,21 @@ extern "C" { #define CFG_TUD_VENDOR_RX_MANUAL_XFER 0 #endif +//--------------------------------------------------------------------+ +// Driver Configuration +//--------------------------------------------------------------------+ +typedef struct TU_ATTR_PACKED { + bool rx_multiple_packet_transfer : 1; // allow transfer more than one packet in a single transfer, increase throughput but requires host sending ZLP at the end of transfer +} tud_vendor_configure_t; +TU_VERIFY_STATIC(sizeof(tud_vendor_configure_t) == 1, "size is not correct"); + +#define TUD_VENDOR_CONFIGURE_DEFAULT() { \ + .rx_multiple_packet_transfer = false, \ +} + +// Configure CDC driver behavior +bool tud_vendor_configure(const tud_vendor_configure_t* driver_cfg); + //--------------------------------------------------------------------+ // Application API (Multiple Interfaces) i.e CFG_TUD_VENDOR > 1 //--------------------------------------------------------------------+ diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 43ce7a1df..7795d7122 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -62,7 +62,7 @@ typedef struct { uint8_t ep_addr; uint16_t mps; - uint16_t ep_bufsize; + uint16_t xfer_len; uint8_t *ep_buf; // set to NULL to use xfer_fifo when CFG_TUD_EDPT_DEDICATED_HWFIFO = 1 tu_fifo_t ff; @@ -101,7 +101,7 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex); // Init an endpoint stream bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool overwritable, void *ff_buf, - uint16_t ff_bufsize, uint8_t *ep_buf, uint16_t ep_bufsize); + uint16_t ff_bufsize, uint8_t *ep_buf); // Deinit an endpoint stream TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_deinit(tu_edpt_stream_t *s) { @@ -118,10 +118,11 @@ TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_deinit(tu_edpt_stream_t // Open an endpoint stream TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_open(tu_edpt_stream_t *s, uint8_t hwid, - const tusb_desc_endpoint_t *desc_ep) { + const tusb_desc_endpoint_t *desc_ep, uint16_t xfer_len) { s->hwid = hwid; s->ep_addr = desc_ep->bEndpointAddress; s->mps = tu_edpt_packet_size(desc_ep); + s->xfer_len = xfer_len; } TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_stream_is_opened(const tu_edpt_stream_t *s) { diff --git a/src/tusb.c b/src/tusb.c index 6075e9db4..27864cb51 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -306,7 +306,7 @@ bool tu_bind_driver_to_ep_itf(uint8_t driver_id, uint8_t ep2drv[][2], uint8_t it //--------------------------------------------------------------------+ bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool overwritable, void *ff_buf, - uint16_t ff_bufsize, uint8_t *ep_buf, uint16_t ep_bufsize) { + uint16_t ff_bufsize, uint8_t *ep_buf) { (void) is_tx; if (ff_buf == NULL || ff_bufsize == 0) { @@ -324,7 +324,6 @@ bool tu_edpt_stream_init(tu_edpt_stream_t *s, bool is_host, bool is_tx, bool ove #endif s->ep_buf = ep_buf; - s->ep_bufsize = ep_bufsize; return true; } @@ -394,7 +393,7 @@ uint32_t tu_edpt_stream_write_xfer(tu_edpt_stream_t *s) { if (s->ep_buf == NULL) { count = tu_fifo_count(&s->ff); // re-get count since fifo can be changed } else { - count = tu_fifo_read_n(&s->ff, s->ep_buf, s->ep_bufsize); + count = tu_fifo_read_n(&s->ff, s->ep_buf, s->xfer_len); } if (count > 0) { @@ -441,7 +440,7 @@ uint32_t tu_edpt_stream_read_xfer(tu_edpt_stream_t *s) { if (available >= s->mps) { // multiple of packet size limit by ep bufsize uint16_t count = (uint16_t) (available & ~(s->mps - 1)); - count = tu_min16(count, s->ep_bufsize); + count = tu_min16(count, s->xfer_len); TU_ASSERT(stream_xfer(s, count), 0); return count; } else { -- cgit v1.3.1 From a3fd3071c17bdc7392db1361f3a97019351af337 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Mon, 15 Dec 2025 23:01:36 +0100 Subject: Fix IAR warnings Signed-off-by: HiFiPhile --- src/common/tusb_fifo.h | 10 ++++++++++ src/tusb.c | 6 ++++++ 2 files changed, 16 insertions(+) (limited to 'src/tusb.c') diff --git a/src/common/tusb_fifo.h b/src/common/tusb_fifo.h index 86ba59059..a3829e38e 100644 --- a/src/common/tusb_fifo.h +++ b/src/common/tusb_fifo.h @@ -289,6 +289,12 @@ TU_ATTR_ALWAYS_INLINE static inline bool tu_fifo_empty(const tu_fifo_t *f) { return wr_idx == rd_idx; } +// Suppress IAR warning +// Warning[Pa082]: undefined behavior: the order of volatile accesses is undefined in this statement +#if defined(__ICCARM__) +#pragma diag_suppress = Pa082 +#endif + // return number of items in fifo, capped to fifo's depth TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_count(const tu_fifo_t *f) { return tu_min16(tu_ff_overflow_count(f->depth, f->wr_idx, f->rd_idx), f->depth); @@ -303,6 +309,10 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_fifo_remaining(const tu_fifo_t * return tu_ff_remaining_local(f->depth, f->wr_idx, f->rd_idx); } +#if defined(__ICCARM__) + #pragma diag_default=Pa082 +#endif + #ifdef __cplusplus } #endif diff --git a/src/tusb.c b/src/tusb.c index ed254a10b..803803ca2 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -39,6 +39,12 @@ #include "host/usbh_pvt.h" #endif +// Suppress IAR warning +// Warning[Pe111]: statement is unreachable +#if defined(__ICCARM__) +#pragma diag_suppress = Pe111 +#endif + tusb_role_t _tusb_rhport_role[TUP_USBIP_CONTROLLER_NUM] = { TUSB_ROLE_INVALID }; //-------------------------------------------------------------------- -- cgit v1.3.1 From 7ea02fd6c9e376679bc1fe025bb73e43664e17c6 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Feb 2026 23:34:48 +0700 Subject: add osal_time_millis() to osal requirement implement tusb_time_millis_api() with osal_time_millis() when OS is not NONE --- src/common/tusb_common.h | 6 ------ src/osal/osal.h | 2 ++ src/osal/osal_freertos.h | 4 ++++ src/osal/osal_mynewt.h | 4 ++++ src/osal/osal_none.h | 2 ++ src/osal/osal_pico.h | 4 ++++ src/osal/osal_rtthread.h | 4 ++++ src/osal/osal_rtx4.h | 4 ++++ src/osal/osal_zephyr.h | 4 ++++ src/tusb.c | 10 ++++++++-- src/tusb.h | 12 +++++++++++- 11 files changed, 47 insertions(+), 9 deletions(-) (limited to 'src/tusb.c') diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 6ac1405f3..9eb0a9337 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -90,12 +90,6 @@ // TODO move to a more obvious place/file //--------------------------------------------------------------------+ -// Get current milliseconds, required by some port/configuration without RTOS -extern uint32_t tusb_time_millis_api(void); - -// Delay in milliseconds, use tusb_time_millis_api() by default. required by some port/configuration with no RTOS -extern void tusb_time_delay_ms_api(uint32_t ms); - // flush data cache extern void tusb_app_dcache_flush(uintptr_t addr, uint32_t data_size); diff --git a/src/osal/osal.h b/src/osal/osal.h index 44521620f..c0292a008 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -74,6 +74,8 @@ typedef void (*osal_task_func_t)(void* param); /*-------------------------------------------------------------------- OSAL Porting API Should be implemented as static inline function in osal_port.h header + uint32_t osal_time_millis(void); + void osal_spin_init(osal_spinlock_t *ctx); void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr); diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 9aeda4d01..32ee2d55c 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -99,6 +99,10 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { vTaskDelay(pdMS_TO_TICKS(msec)); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t osal_time_millis(void) { + return pdTICKS_TO_MS(xTaskGetTickCount()); +} + //--------------------------------------------------------------------+ // Spinlock API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index 6d51f8ec3..94124ca81 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -40,6 +40,10 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { os_time_delay( os_time_ms_to_ticks32(msec) ); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t osal_time_millis(void) { + return os_time_ticks_to_ms32(os_time_get()); +} + //--------------------------------------------------------------------+ // Spinlock API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index bba42716d..7bf6029d6 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -31,6 +31,8 @@ extern "C" { #endif +// osal_time_millis() is not provided, tusb_time_millis_api() must be implemented by user application + //--------------------------------------------------------------------+ // Spinlock API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index 79b728e9a..6a0a21bb3 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -43,6 +43,10 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { sleep_ms(msec); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t osal_time_millis(void) { + return to_ms_since_boot(get_absolute_time()); +} + //--------------------------------------------------------------------+ // Spinlock API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_rtthread.h b/src/osal/osal_rtthread.h index a778f5425..f560281c5 100644 --- a/src/osal/osal_rtthread.h +++ b/src/osal/osal_rtthread.h @@ -42,6 +42,10 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { rt_thread_mdelay(msec); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t osal_time_millis(void) { + return (uint32_t)((((uint64_t)rt_tick_get()) * 1000) / RT_TICK_PER_SECOND); +} + //--------------------------------------------------------------------+ // Spinlock API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_rtx4.h b/src/osal/osal_rtx4.h index 35860ddd5..e1930c96c 100644 --- a/src/osal/osal_rtx4.h +++ b/src/osal/osal_rtx4.h @@ -46,6 +46,10 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { os_dly_wait(lo); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t osal_time_millis(void) { + return os_time_get(); +} + TU_ATTR_ALWAYS_INLINE static inline uint16_t msec2wait(uint32_t msec) { if (msec == OSAL_TIMEOUT_WAIT_FOREVER) { return 0xFFFF; diff --git a/src/osal/osal_zephyr.h b/src/osal/osal_zephyr.h index 91f225f79..900ac786c 100644 --- a/src/osal/osal_zephyr.h +++ b/src/osal/osal_zephyr.h @@ -35,6 +35,10 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { k_msleep(msec); } +TU_ATTR_ALWAYS_INLINE static inline uint32_t osal_time_millis(void) { + return k_uptime_get_32(); +} + //--------------------------------------------------------------------+ // Spinlock API //--------------------------------------------------------------------+ diff --git a/src/tusb.c b/src/tusb.c index 6075e9db4..40d0e8adf 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -45,17 +45,23 @@ tusb_role_t _tusb_rhport_role[TUP_USBIP_CONTROLLER_NUM] = { TUSB_ROLE_INVALID }; // Weak/Default API, can be overwritten by Application //-------------------------------------------------------------------- + #if CFG_TUSB_OS != OPT_OS_NONE +uint32_t tusb_time_millis_api(void) { + return osal_time_millis(); +} + #endif + TU_ATTR_WEAK void tusb_time_delay_ms_api(uint32_t ms) { #if CFG_TUSB_OS != OPT_OS_NONE osal_task_delay(ms); #else - // delay using millis() (if implemented) and/or frame number if possible + // delay using millis() const uint32_t time_ms = tusb_time_millis_api(); while ((tusb_time_millis_api() - time_ms) < ms) {} #endif } -TU_ATTR_WEAK void* tusb_app_virt_to_phys(void *virt_addr) { +TU_ATTR_WEAK void *tusb_app_virt_to_phys(void *virt_addr) { return virt_addr; } diff --git a/src/tusb.h b/src/tusb.h index 62b3b9783..742009a2e 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -135,7 +135,7 @@ //--------------------------------------------------------------------+ -// User API +// Application API //--------------------------------------------------------------------+ #if CFG_TUH_ENABLED || CFG_TUD_ENABLED @@ -174,6 +174,16 @@ bool tusb_deinit(uint8_t rhport); #endif +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ + +// Get current milliseconds, required by some port/configuration without RTOS +extern uint32_t tusb_time_millis_api(void); + +// Delay in milliseconds, use tusb_time_millis_api() by default. required by some port/configuration with no RTOS +extern void tusb_time_delay_ms_api(uint32_t ms); + #ifdef __cplusplus } #endif -- cgit v1.3.1 From 8444c25ab6bc841bad81fd04afc1e66a9d57a115 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 27 Feb 2026 23:51:36 +0700 Subject: replace board_millis() with tusb_time_millis_api() --- examples/device/audio_4_channel_mic/src/main.c | 4 +-- examples/device/audio_test/src/main.c | 4 +-- examples/device/audio_test_multi_rate/src/main.c | 4 +-- examples/device/board_test/src/main.c | 4 +-- examples/device/cdc_dual_ports/src/main.c | 2 +- examples/device/cdc_msc/src/main.c | 2 +- examples/device/cdc_uac2/src/uac2_app.c | 4 +-- examples/device/dfu/src/main.c | 2 +- examples/device/dfu_runtime/src/main.c | 2 +- examples/device/dynamic_configuration/src/main.c | 4 +-- examples/device/hid_boot_interface/src/main.c | 4 +-- examples/device/hid_composite/src/main.c | 4 +-- examples/device/hid_generic_inout/src/main.c | 2 +- examples/device/hid_multiple_interface/src/main.c | 4 +-- examples/device/midi_test/src/main.c | 4 +-- examples/device/msc_dual_lun/src/main.c | 2 +- examples/device/mtp/src/main.c | 2 +- examples/device/net_lwip_webserver/src/main.c | 2 +- examples/device/uac2_headset/src/main.c | 6 ++-- examples/device/uac2_speaker_fb/src/main.c | 6 ++-- examples/device/usbtmc/src/main.c | 6 ++-- examples/device/usbtmc/src/usbtmc_app.c | 8 ++--- examples/device/video_capture/src/main.c | 6 ++-- examples/device/video_capture_2ch/src/main.c | 6 ++-- examples/device/webusb_serial/src/main.c | 2 +- examples/dual/host_hid_to_device_cdc/src/main.c | 2 +- examples/dual/host_info_to_device_cdc/src/main.c | 6 ++-- examples/host/bare_api/src/main.c | 2 +- examples/host/cdc_msc_hid/src/main.c | 2 +- examples/host/device_info/src/main.c | 2 +- examples/host/hid_controller/src/hid_app.c | 2 +- examples/host/hid_controller/src/main.c | 2 +- examples/host/midi_rx/src/main.c | 2 +- examples/host/msc_file_explorer/src/main.c | 2 +- examples/typec/power_delivery/src/main.c | 2 +- hw/bsp/at32f402_405/family.c | 2 +- hw/bsp/at32f403a_407/family.c | 2 +- hw/bsp/at32f413/family.c | 2 +- hw/bsp/at32f415/family.c | 2 +- hw/bsp/at32f423/family.c | 2 +- hw/bsp/at32f425/family.c | 2 +- hw/bsp/at32f435_437/family.c | 2 +- hw/bsp/at32f45x/family.c | 2 +- hw/bsp/board.c | 4 --- hw/bsp/board_api.h | 41 ++--------------------- hw/bsp/broadcom_32bit/family.c | 2 +- hw/bsp/broadcom_64bit/family.c | 2 +- hw/bsp/brtmm90x/family.c | 2 +- hw/bsp/ch32f20x/family.c | 2 +- hw/bsp/ch32v10x/family.c | 2 +- hw/bsp/ch32v20x/family.c | 2 +- hw/bsp/ch32v30x/family.c | 2 +- hw/bsp/cxd56/family.c | 2 +- hw/bsp/da1469x/family.c | 2 +- hw/bsp/efm32/family.c | 2 +- hw/bsp/f1c100s/family.c | 2 +- hw/bsp/fomu/family.c | 2 +- hw/bsp/gd32vf103/family.c | 2 +- hw/bsp/hpmicro/family.c | 2 +- hw/bsp/imxrt/family.c | 2 +- hw/bsp/kinetis_k/family.c | 2 +- hw/bsp/kinetis_k32l2/family.c | 2 +- hw/bsp/kinetis_kl/family.c | 2 +- hw/bsp/lpc11/family.c | 2 +- hw/bsp/lpc13/family.c | 2 +- hw/bsp/lpc15/family.c | 2 +- hw/bsp/lpc17/family.c | 2 +- hw/bsp/lpc18/family.c | 2 +- hw/bsp/lpc40/family.c | 2 +- hw/bsp/lpc43/family.c | 2 +- hw/bsp/lpc51/family.c | 2 +- hw/bsp/lpc54/family.c | 2 +- hw/bsp/lpc55/family.c | 2 +- hw/bsp/maxim/family.c | 2 +- hw/bsp/mcx/family.c | 2 +- hw/bsp/mm32/family.c | 2 +- hw/bsp/msp430/family.c | 10 +++--- hw/bsp/msp432e4/family.c | 2 +- hw/bsp/nrf/family.c | 2 +- hw/bsp/nuc100_120/family.c | 2 +- hw/bsp/nuc121_125/family.c | 2 +- hw/bsp/nuc126/family.c | 2 +- hw/bsp/nuc505/family.c | 2 +- hw/bsp/pic32mz/family.c | 2 +- hw/bsp/ra/family.c | 2 +- hw/bsp/rw61x/family.c | 2 +- hw/bsp/rx/boards/gr_citrus/gr_citrus.c | 2 +- hw/bsp/rx/boards/rx65n_target/rx65n_target.c | 2 +- hw/bsp/samd11/family.c | 2 +- hw/bsp/samd2x_l2x/family.c | 2 +- hw/bsp/samd5x_e5x/family.c | 2 +- hw/bsp/same7x/family.c | 2 +- hw/bsp/samg/family.c | 2 +- hw/bsp/stm32c0/family.c | 2 +- hw/bsp/stm32f0/family.c | 2 +- hw/bsp/stm32f1/family.c | 2 +- hw/bsp/stm32f2/family.c | 2 +- hw/bsp/stm32f3/family.c | 2 +- hw/bsp/stm32f4/family.c | 2 +- hw/bsp/stm32f7/family.c | 2 +- hw/bsp/stm32g0/family.c | 2 +- hw/bsp/stm32g4/family.c | 2 +- hw/bsp/stm32h5/family.c | 2 +- hw/bsp/stm32h7/family.c | 2 +- hw/bsp/stm32h7rs/family.c | 2 +- hw/bsp/stm32l0/family.c | 2 +- hw/bsp/stm32l4/family.c | 2 +- hw/bsp/stm32n6/family.c | 2 +- hw/bsp/stm32u0/family.c | 2 +- hw/bsp/stm32u5/family.c | 2 +- hw/bsp/stm32wb/family.c | 2 +- hw/bsp/stm32wba/family.c | 2 +- hw/bsp/tm4c/family.c | 2 +- hw/bsp/xmc4000/family.c | 2 +- src/common/tusb_common.h | 6 ++++ src/host/usbh.c | 2 +- src/portable/sunxi/dcd_sunxi_musb.c | 3 -- src/tusb.c | 13 ++++--- src/tusb.h | 10 ------ 119 files changed, 158 insertions(+), 203 deletions(-) (limited to 'src/tusb.c') diff --git a/examples/device/audio_4_channel_mic/src/main.c b/examples/device/audio_4_channel_mic/src/main.c index 5767c7453..c9c6dd46c 100644 --- a/examples/device/audio_4_channel_mic/src/main.c +++ b/examples/device/audio_4_channel_mic/src/main.c @@ -155,7 +155,7 @@ void tud_resume_cb(void) { // In a real application, this would be replaced with actual I2S receive callback. void audio_task(void) { static uint32_t start_ms = 0; - uint32_t curr_ms = board_millis(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) { return; // not enough time } @@ -408,7 +408,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/audio_test/src/main.c b/examples/device/audio_test/src/main.c index 2441eefbc..876a41d06 100644 --- a/examples/device/audio_test/src/main.c +++ b/examples/device/audio_test/src/main.c @@ -138,7 +138,7 @@ void tud_resume_cb(void) { // In a real application, this would be replaced with actual I2S receive callback. void audio_task(void) { static uint32_t start_ms = 0; - uint32_t curr_ms = board_millis(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) { return; // not enough time } @@ -402,7 +402,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/audio_test_multi_rate/src/main.c b/examples/device/audio_test_multi_rate/src/main.c index baeec870f..952176997 100644 --- a/examples/device/audio_test_multi_rate/src/main.c +++ b/examples/device/audio_test_multi_rate/src/main.c @@ -146,7 +146,7 @@ void tud_resume_cb(void) { // In a real application, this would be replaced with actual I2S receive callback. void audio_task(void) { static uint32_t start_ms = 0; - uint32_t curr_ms = board_millis(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) { return; // not enough time } @@ -614,7 +614,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/board_test/src/main.c b/examples/device/board_test/src/main.c index ee0829e5b..757876ac8 100644 --- a/examples/device/board_test/src/main.c +++ b/examples/device/board_test/src/main.c @@ -58,8 +58,8 @@ int main(void) { } // Blink and print every interval ms - if (!(board_millis() - start_ms < interval_ms)) { - start_ms = board_millis(); + if (!(tusb_time_millis_api() - start_ms < interval_ms)) { + start_ms = tusb_time_millis_api(); if (ch < 0) { // skip if echoing diff --git a/examples/device/cdc_dual_ports/src/main.c b/examples/device/cdc_dual_ports/src/main.c index 5ccb06a8a..6f918218d 100644 --- a/examples/device/cdc_dual_ports/src/main.c +++ b/examples/device/cdc_dual_ports/src/main.c @@ -157,7 +157,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/cdc_msc/src/main.c b/examples/device/cdc_msc/src/main.c index 06a4f732f..b00a0e3a9 100644 --- a/examples/device/cdc_msc/src/main.c +++ b/examples/device/cdc_msc/src/main.c @@ -160,7 +160,7 @@ void led_blinking_task(void) { if (blink_enable) { // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/cdc_uac2/src/uac2_app.c b/examples/device/cdc_uac2/src/uac2_app.c index 73a262d0c..7760c402b 100644 --- a/examples/device/cdc_uac2/src/uac2_app.c +++ b/examples/device/cdc_uac2/src/uac2_app.c @@ -66,7 +66,7 @@ uint8_t current_resolution; // In a real application, this would be replaced with actual I2S send/receive callback. void audio_task(void) { static uint32_t start_ms = 0; - uint32_t curr_ms = board_millis(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) { return; // not enough time } @@ -303,7 +303,7 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; } start_ms += blink_interval_ms; diff --git a/examples/device/dfu/src/main.c b/examples/device/dfu/src/main.c index 77632bf1a..fb3c22630 100644 --- a/examples/device/dfu/src/main.c +++ b/examples/device/dfu/src/main.c @@ -199,7 +199,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/dfu_runtime/src/main.c b/examples/device/dfu_runtime/src/main.c index 5de651bcd..6f412e8de 100644 --- a/examples/device/dfu_runtime/src/main.c +++ b/examples/device/dfu_runtime/src/main.c @@ -132,7 +132,7 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/dynamic_configuration/src/main.c b/examples/device/dynamic_configuration/src/main.c index dac74bb7a..8ebb42f9a 100644 --- a/examples/device/dynamic_configuration/src/main.c +++ b/examples/device/dynamic_configuration/src/main.c @@ -170,7 +170,7 @@ void midi_task(void) { while( tud_midi_available() ) tud_midi_packet_read(packet); // send note every 1000 ms - if (board_millis() - start_ms < 286) { + if (tusb_time_millis_api() - start_ms < 286) { return; // not enough time } start_ms += 286; @@ -209,7 +209,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return;// not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/hid_boot_interface/src/main.c b/examples/device/hid_boot_interface/src/main.c index 44a91db67..4de319f52 100644 --- a/examples/device/hid_boot_interface/src/main.c +++ b/examples/device/hid_boot_interface/src/main.c @@ -109,7 +109,7 @@ void hid_task(void) { const uint32_t interval_ms = 10; static uint32_t start_ms = 0; - if (board_millis() - start_ms < interval_ms) { + if (tusb_time_millis_api() - start_ms < interval_ms) { return; // not enough time } start_ms += interval_ms; @@ -238,7 +238,7 @@ void led_blinking_task(void) { } // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 9693d564d..7c9d5af8d 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -209,7 +209,7 @@ void hid_task(void) { const uint32_t interval_ms = 10; static uint32_t start_ms = 0; - if (board_millis() - start_ms < interval_ms) { + if (tusb_time_millis_api() - start_ms < interval_ms) { return; // not enough time } start_ms += interval_ms; @@ -298,7 +298,7 @@ void led_blinking_task(void) { } // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/device/hid_generic_inout/src/main.c b/examples/device/hid_generic_inout/src/main.c index 9837a47d9..2a6b91a8a 100644 --- a/examples/device/hid_generic_inout/src/main.c +++ b/examples/device/hid_generic_inout/src/main.c @@ -168,7 +168,7 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/hid_multiple_interface/src/main.c b/examples/device/hid_multiple_interface/src/main.c index 0bccd13c1..c71a9cbad 100644 --- a/examples/device/hid_multiple_interface/src/main.c +++ b/examples/device/hid_multiple_interface/src/main.c @@ -120,7 +120,7 @@ void hid_task(void) const uint32_t interval_ms = 10; static uint32_t start_ms = 0; - if ( board_millis() - start_ms < interval_ms) return; // not enough time + if ( tusb_time_millis_api() - start_ms < interval_ms) return; // not enough time start_ms += interval_ms; uint32_t const btn = board_button_read(); @@ -205,7 +205,7 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/midi_test/src/main.c b/examples/device/midi_test/src/main.c index fd58e3021..1154c1d60 100644 --- a/examples/device/midi_test/src/main.c +++ b/examples/device/midi_test/src/main.c @@ -134,7 +134,7 @@ void midi_task(void) } // send note periodically - if (board_millis() - start_ms < 286) { + if (tusb_time_millis_api() - start_ms < 286) { return; // not enough time } start_ms += 286; @@ -174,7 +174,7 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/msc_dual_lun/src/main.c b/examples/device/msc_dual_lun/src/main.c index 62b1c872a..b459871f7 100644 --- a/examples/device/msc_dual_lun/src/main.c +++ b/examples/device/msc_dual_lun/src/main.c @@ -103,7 +103,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/mtp/src/main.c b/examples/device/mtp/src/main.c index 57d1535b2..6ffa435d1 100644 --- a/examples/device/mtp/src/main.c +++ b/examples/device/mtp/src/main.c @@ -102,7 +102,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c index 867cf2812..9f26da2ba 100644 --- a/examples/device/net_lwip_webserver/src/main.c +++ b/examples/device/net_lwip_webserver/src/main.c @@ -291,5 +291,5 @@ void sys_arch_unprotect(sys_prot_t pval) { /* lwip needs a millisecond time source, and the TinyUSB board support code has one available */ uint32_t sys_now(void) { - return board_millis(); + return tusb_time_millis_api(); } diff --git a/examples/device/uac2_headset/src/main.c b/examples/device/uac2_headset/src/main.c index 96fa66f1e..0ea63d8f7 100644 --- a/examples/device/uac2_headset/src/main.c +++ b/examples/device/uac2_headset/src/main.c @@ -559,7 +559,7 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const *p_reques // In a real application, this would be replaced with actual I2S send/receive callback. void audio_task(void) { static uint32_t start_ms = 0; - uint32_t curr_ms = board_millis(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) return;// not enough time start_ms = curr_ms; // When new data arrived, copy data from speaker buffer, to microphone buffer @@ -605,7 +605,7 @@ void audio_control_task(void) { static uint32_t start_ms = 0; static uint32_t btn_prev = 0; - if (board_millis() - start_ms < interval_ms) return;// not enough time + if (tusb_time_millis_api() - start_ms < interval_ms) return;// not enough time start_ms += interval_ms; uint32_t btn = board_button_read(); @@ -644,7 +644,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/uac2_speaker_fb/src/main.c b/examples/device/uac2_speaker_fb/src/main.c index 7b4e2d64c..8323d82e8 100644 --- a/examples/device/uac2_speaker_fb/src/main.c +++ b/examples/device/uac2_speaker_fb/src/main.c @@ -583,7 +583,7 @@ bool tud_audio_rx_done_isr(uint8_t rhport, uint16_t n_bytes_received, uint8_t fu // In a real application, this would be replaced with actual I2S transmit callback. void audio_task(void) { static uint32_t start_ms = 0; - uint32_t curr_ms = board_millis(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) return;// not enough time start_ms = curr_ms; @@ -610,7 +610,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; start_ms += blink_interval_ms; board_led_write(led_state); @@ -624,7 +624,7 @@ void led_blinking_task(void) { // Every 1ms, we will sent 1 debug information report void audio_debug_task(void) { static uint32_t start_ms = 0; - uint32_t curr_ms = board_millis(); + uint32_t curr_ms = tusb_time_millis_api(); if (start_ms == curr_ms) return;// not enough time start_ms = curr_ms; diff --git a/examples/device/usbtmc/src/main.c b/examples/device/usbtmc/src/main.c index 5cbbb85ef..b1269b117 100644 --- a/examples/device/usbtmc/src/main.c +++ b/examples/device/usbtmc/src/main.c @@ -124,12 +124,12 @@ void led_blinking_task(void) { led_state = true; board_led_write(true); - start_ms = board_millis(); + start_ms = tusb_time_millis_api(); doPulse = false; } else if (led_state == true) { - if ( board_millis() - start_ms < 750) //Spec says blink must be between 500 and 1000 ms. + if ( tusb_time_millis_api() - start_ms < 750) //Spec says blink must be between 500 and 1000 ms. { return; // not enough time } @@ -140,7 +140,7 @@ void led_blinking_task(void) else { // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/device/usbtmc/src/usbtmc_app.c b/examples/device/usbtmc/src/usbtmc_app.c index 4c3724ac4..35e8618f5 100644 --- a/examples/device/usbtmc/src/usbtmc_app.c +++ b/examples/device/usbtmc/src/usbtmc_app.c @@ -209,19 +209,19 @@ void usbtmc_app_task_iter(void) { case 0: break; case 1: - queryDelayStart = board_millis(); + queryDelayStart = tusb_time_millis_api(); queryState = 2; break; case 2: - if( (board_millis() - queryDelayStart) > resp_delay) { - queryDelayStart = board_millis(); + if( (tusb_time_millis_api() - queryDelayStart) > resp_delay) { + queryDelayStart = tusb_time_millis_api(); queryState=3; status |= 0x10u; // MAV status |= 0x40u; // SRQ } break; case 3: - if( (board_millis() - queryDelayStart) > resp_delay) { + if( (tusb_time_millis_api() - queryDelayStart) > resp_delay) { queryState = 4; } break; diff --git a/examples/device/video_capture/src/main.c b/examples/device/video_capture/src/main.c index ffa2a7afa..df9f77a1c 100644 --- a/examples/device/video_capture/src/main.c +++ b/examples/device/video_capture/src/main.c @@ -231,7 +231,7 @@ static void video_send_frame(void) { if (!already_sent) { already_sent = 1; tx_busy = 1; - start_ms = board_millis(); + start_ms = tusb_time_millis_api(); #if defined(CFG_EXAMPLE_VIDEO_BUFFERLESS) tud_video_n_frame_xfer(0, 0, NULL, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8); #elif defined (CFG_EXAMPLE_VIDEO_READONLY) @@ -247,7 +247,7 @@ static void video_send_frame(void) { #endif } - unsigned cur = board_millis(); + unsigned cur = tusb_time_millis_api(); if (cur - start_ms < interval_ms) { return; // not enough time } @@ -316,7 +316,7 @@ void led_blinking_task(void* param) { #if CFG_TUSB_OS == OPT_OS_FREERTOS vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } #endif diff --git a/examples/device/video_capture_2ch/src/main.c b/examples/device/video_capture_2ch/src/main.c index 79b149f2b..debd336fd 100644 --- a/examples/device/video_capture_2ch/src/main.c +++ b/examples/device/video_capture_2ch/src/main.c @@ -221,13 +221,13 @@ static void video_send_frame(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) { if (!(already_sent & (1u << idx))) { already_sent |= 1u << idx; tx_busy |= 1u << idx; - start_ms[idx] = board_millis(); + start_ms[idx] = tusb_time_millis_api(); fb_size = get_framebuf(ctl_idx, stm_idx, frame_num[idx], &fp); tud_video_n_frame_xfer(ctl_idx, stm_idx, fp, fb_size); } - unsigned cur = board_millis(); + unsigned cur = tusb_time_millis_api(); if (cur - start_ms[idx] < interval_ms[idx]) return; // not enough time if (tx_busy & (1u << idx)) return; start_ms[idx] += interval_ms[idx]; @@ -280,7 +280,7 @@ void led_blinking_task(void* param) { #if CFG_TUSB_OS == OPT_OS_FREERTOS vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time #endif start_ms += blink_interval_ms; diff --git a/examples/device/webusb_serial/src/main.c b/examples/device/webusb_serial/src/main.c index 155768b76..4be5e4db4 100644 --- a/examples/device/webusb_serial/src/main.c +++ b/examples/device/webusb_serial/src/main.c @@ -257,7 +257,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } start_ms += blink_interval_ms; diff --git a/examples/dual/host_hid_to_device_cdc/src/main.c b/examples/dual/host_hid_to_device_cdc/src/main.c index 8c53588c3..ba8ba019a 100644 --- a/examples/dual/host_hid_to_device_cdc/src/main.c +++ b/examples/dual/host_hid_to_device_cdc/src/main.c @@ -284,7 +284,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) return; // not enough time + if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/examples/dual/host_info_to_device_cdc/src/main.c b/examples/dual/host_info_to_device_cdc/src/main.c index fffb54d58..7cf43aef3 100644 --- a/examples/dual/host_info_to_device_cdc/src/main.c +++ b/examples/dual/host_info_to_device_cdc/src/main.c @@ -213,13 +213,13 @@ void cdc_task(void) { static uint32_t connected_ms = 0; if (!tud_cdc_connected()) { - connected_ms = board_millis(); + connected_ms = tusb_time_millis_api(); return; } // delay a bit otherwise we can outpace host's terminal. Linux will set LineState (DTR) then Line Coding. // If we send data before Linux's terminal set Line Coding, it can be ignored --> missing data with hardware test loop - if (board_millis() - connected_ms < 100) { + if (tusb_time_millis_api() - connected_ms < 100) { return; // wait for stable connection } @@ -309,7 +309,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return;// not enough time } start_ms += blink_interval_ms; diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c index c693d6b00..ced2eaa32 100644 --- a/examples/host/bare_api/src/main.c +++ b/examples/host/bare_api/src/main.c @@ -335,7 +335,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < interval_ms) { + if (tusb_time_millis_api() - start_ms < interval_ms) { return; // not enough time } start_ms += interval_ms; diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index c309a7cae..c27ad93fe 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -92,7 +92,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < interval_ms) { + if (tusb_time_millis_api() - start_ms < interval_ms) { return;// not enough time } start_ms += interval_ms; diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c index ab617e989..fd4e9c3ed 100644 --- a/examples/host/device_info/src/main.c +++ b/examples/host/device_info/src/main.c @@ -246,7 +246,7 @@ void led_blinking_task(void* param) { #if CFG_TUSB_OS == OPT_OS_FREERTOS vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); #else - if (board_millis() - start_ms < blink_interval_ms) { + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { return; // not enough time } #endif diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c index f8c3d029b..5417811f0 100644 --- a/examples/host/hid_controller/src/hid_app.c +++ b/examples/host/hid_controller/src/hid_app.c @@ -168,7 +168,7 @@ void hid_app_task(void) const uint32_t interval_ms = 200; static uint32_t start_ms = 0; - uint32_t current_time_ms = board_millis(); + uint32_t current_time_ms = tusb_time_millis_api(); if ( current_time_ms - start_ms >= interval_ms) { start_ms = current_time_ms; diff --git a/examples/host/hid_controller/src/main.c b/examples/host/hid_controller/src/main.c index fa70d7d1a..a9eebc90b 100644 --- a/examples/host/hid_controller/src/main.c +++ b/examples/host/hid_controller/src/main.c @@ -79,7 +79,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < interval_ms) return; // not enough time + if ( tusb_time_millis_api() - start_ms < interval_ms) return; // not enough time start_ms += interval_ms; board_led_write(led_state); diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index 78b1a11b9..f189e0864 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -72,7 +72,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < interval_ms) return;// not enough time + if (tusb_time_millis_api() - start_ms < interval_ms) return;// not enough time start_ms += interval_ms; board_led_write(led_state); diff --git a/examples/host/msc_file_explorer/src/main.c b/examples/host/msc_file_explorer/src/main.c index f9ec0ff5f..0a8967380 100644 --- a/examples/host/msc_file_explorer/src/main.c +++ b/examples/host/msc_file_explorer/src/main.c @@ -118,7 +118,7 @@ void led_blinking_task(void) { static bool led_state = false; // Blink every interval ms - if (board_millis() - start_ms < interval_ms) return; // not enough time + if (tusb_time_millis_api() - start_ms < interval_ms) return; // not enough time start_ms += interval_ms; board_led_write(led_state); diff --git a/examples/typec/power_delivery/src/main.c b/examples/typec/power_delivery/src/main.c index de0db4721..f6191bfe8 100644 --- a/examples/typec/power_delivery/src/main.c +++ b/examples/typec/power_delivery/src/main.c @@ -184,7 +184,7 @@ void led_blinking_task(void) static bool led_state = false; // Blink every interval ms - if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time + if ( tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time start_ms += blink_interval_ms; board_led_write(led_state); diff --git a/hw/bsp/at32f402_405/family.c b/hw/bsp/at32f402_405/family.c index a6c2217fe..b7dbcbd98 100644 --- a/hw/bsp/at32f402_405/family.c +++ b/hw/bsp/at32f402_405/family.c @@ -258,7 +258,7 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) { system_ticks++; } - uint32_t board_millis(void) + uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f403a_407/family.c b/hw/bsp/at32f403a_407/family.c index dd9b85dc5..d4a7e446d 100644 --- a/hw/bsp/at32f403a_407/family.c +++ b/hw/bsp/at32f403a_407/family.c @@ -250,7 +250,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f413/family.c b/hw/bsp/at32f413/family.c index bdaed523c..adf29e097 100644 --- a/hw/bsp/at32f413/family.c +++ b/hw/bsp/at32f413/family.c @@ -250,7 +250,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f415/family.c b/hw/bsp/at32f415/family.c index 2fbd4c821..b592bf6c5 100644 --- a/hw/bsp/at32f415/family.c +++ b/hw/bsp/at32f415/family.c @@ -246,7 +246,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f423/family.c b/hw/bsp/at32f423/family.c index f30c6a83f..71cb559dc 100644 --- a/hw/bsp/at32f423/family.c +++ b/hw/bsp/at32f423/family.c @@ -250,7 +250,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f425/family.c b/hw/bsp/at32f425/family.c index 4ff4c8d6a..7f443509e 100644 --- a/hw/bsp/at32f425/family.c +++ b/hw/bsp/at32f425/family.c @@ -254,7 +254,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/at32f435_437/family.c b/hw/bsp/at32f435_437/family.c index 01dd429f8..6c6bc4d72 100644 --- a/hw/bsp/at32f435_437/family.c +++ b/hw/bsp/at32f435_437/family.c @@ -320,7 +320,7 @@ volatile uint32_t system_ticks = 0; void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } void SVC_Handler(void) { diff --git a/hw/bsp/at32f45x/family.c b/hw/bsp/at32f45x/family.c index 0593e5115..fa0c1139f 100644 --- a/hw/bsp/at32f45x/family.c +++ b/hw/bsp/at32f45x/family.c @@ -227,7 +227,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 483d9dc28..91e7de9fe 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -161,10 +161,6 @@ void board_putchar(int c) { (void) sys_write(0, (const char*)&c, 1); } -uint32_t tusb_time_millis_api(void) { - return board_millis(); -} - //-------------------------------------------------------------------- // FreeRTOS hooks //-------------------------------------------------------------------- diff --git a/hw/bsp/board_api.h b/hw/bsp/board_api.h index 606ac484f..4487871eb 100644 --- a/hw/bsp/board_api.h +++ b/hw/bsp/board_api.h @@ -98,43 +98,6 @@ int board_uart_read(uint8_t *buf, int len); // Send characters to UART. Return number of sent bytes int board_uart_write(void const *buf, int len); -#if CFG_TUSB_OS == OPT_OS_NONE -// Get current milliseconds, must be implemented when no RTOS is used -uint32_t board_millis(void); - -#elif CFG_TUSB_OS == OPT_OS_FREERTOS -static inline uint32_t board_millis(void) { - return ( ( ((uint64_t) xTaskGetTickCount()) * 1000) / configTICK_RATE_HZ ); -} - -#elif CFG_TUSB_OS == OPT_OS_MYNEWT -static inline uint32_t board_millis(void) { - return os_time_ticks_to_ms32( os_time_get() ); -} - -#elif CFG_TUSB_OS == OPT_OS_PICO -#include "pico/time.h" -static inline uint32_t board_millis(void) { - return to_ms_since_boot(get_absolute_time()); -} - -#elif CFG_TUSB_OS == OPT_OS_RTTHREAD -static inline uint32_t board_millis(void) { - return (((uint64_t)rt_tick_get()) * 1000 / RT_TICK_PER_SECOND); -} - -#elif CFG_TUSB_OS == OPT_OS_CUSTOM -// Implement your own board_millis() in any of .c file -uint32_t board_millis(void); - -#elif CFG_TUSB_OS == OPT_OS_ZEPHYR -static inline uint32_t board_millis(void) { - return k_uptime_get_32(); -} -#else - #error "board_millis() is not implemented for this OS" -#endif - //--------------------------------------------------------------------+ // Helper functions //--------------------------------------------------------------------+ @@ -175,8 +138,8 @@ static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars // TODO remove static inline void board_delay(uint32_t ms) { - uint32_t start_ms = board_millis(); - while ( board_millis() - start_ms < ms ) { + uint32_t start_ms = tusb_time_millis_api(); + while ( tusb_time_millis_api() - start_ms < ms ) { // take chance to run usb background #if CFG_TUD_ENABLED tud_task(); diff --git a/hw/bsp/broadcom_32bit/family.c b/hw/bsp/broadcom_32bit/family.c index f8f3b0b70..399397bb4 100644 --- a/hw/bsp/broadcom_32bit/family.c +++ b/hw/bsp/broadcom_32bit/family.c @@ -146,7 +146,7 @@ void TIMER_1_IRQHandler(void) { SYSTMR->CS_b.M1 = 1; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/broadcom_64bit/family.c b/hw/bsp/broadcom_64bit/family.c index f8f3b0b70..399397bb4 100644 --- a/hw/bsp/broadcom_64bit/family.c +++ b/hw/bsp/broadcom_64bit/family.c @@ -146,7 +146,7 @@ void TIMER_1_IRQHandler(void) { SYSTMR->CS_b.M1 = 1; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/brtmm90x/family.c b/hw/bsp/brtmm90x/family.c index 15ff4b8ee..ff24cfe89 100644 --- a/hw/bsp/brtmm90x/family.c +++ b/hw/bsp/brtmm90x/family.c @@ -234,7 +234,7 @@ int board_uart_write(void const *buf, int len) } // Get current milliseconds -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { uint32_t safe_ms; diff --git a/hw/bsp/ch32f20x/family.c b/hw/bsp/ch32f20x/family.c index 7eae62fa4..dd84b7c77 100644 --- a/hw/bsp/ch32f20x/family.c +++ b/hw/bsp/ch32f20x/family.c @@ -101,7 +101,7 @@ void SysTick_Handler(void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/ch32v10x/family.c b/hw/bsp/ch32v10x/family.c index dfc041462..344dcaf0b 100644 --- a/hw/bsp/ch32v10x/family.c +++ b/hw/bsp/ch32v10x/family.c @@ -61,7 +61,7 @@ static uint32_t SysTick_Config(uint32_t ticks) { return 0; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c index 690acee1e..4c22450f9 100644 --- a/hw/bsp/ch32v20x/family.c +++ b/hw/bsp/ch32v20x/family.c @@ -85,7 +85,7 @@ static uint32_t SysTick_Config(uint32_t ticks) { return 0; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/ch32v30x/family.c b/hw/bsp/ch32v30x/family.c index c694f1a08..6295f7723 100644 --- a/hw/bsp/ch32v30x/family.c +++ b/hw/bsp/ch32v30x/family.c @@ -144,7 +144,7 @@ __attribute__((interrupt)) void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/cxd56/family.c b/hw/bsp/cxd56/family.c index a8e2fd52b..fd92bb9d9 100644 --- a/hw/bsp/cxd56/family.c +++ b/hw/bsp/cxd56/family.c @@ -96,7 +96,7 @@ int board_uart_write(void const *buf, int len) } // Get current milliseconds -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { struct timespec tp; diff --git a/hw/bsp/da1469x/family.c b/hw/bsp/da1469x/family.c index a64ffce67..a4f7f2e8d 100644 --- a/hw/bsp/da1469x/family.c +++ b/hw/bsp/da1469x/family.c @@ -140,7 +140,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/efm32/family.c b/hw/bsp/efm32/family.c index 39166bc4d..d318e20d6 100644 --- a/hw/bsp/efm32/family.c +++ b/hw/bsp/efm32/family.c @@ -689,7 +689,7 @@ void SysTick_Handler(void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/f1c100s/family.c b/hw/bsp/f1c100s/family.c index 9e864363f..1e71333d4 100644 --- a/hw/bsp/f1c100s/family.c +++ b/hw/bsp/f1c100s/family.c @@ -79,7 +79,7 @@ int board_uart_write(void const* buf, int len) { #if CFG_TUSB_OS == OPT_OS_NONE volatile uint32_t system_ticks = 0; -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/fomu/family.c b/hw/bsp/fomu/family.c index 9d7977bea..cf04a1f6f 100644 --- a/hw/bsp/fomu/family.c +++ b/hw/bsp/fomu/family.c @@ -117,7 +117,7 @@ int board_uart_write(void const * buf, int len) } #if CFG_TUSB_OS == OPT_OS_NONE -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/gd32vf103/family.c b/hw/bsp/gd32vf103/family.c index 9d15755fc..4c1099317 100644 --- a/hw/bsp/gd32vf103/family.c +++ b/hw/bsp/gd32vf103/family.c @@ -179,7 +179,7 @@ void eclic_mtip_handler(void) { system_ticks++; SysTick_Reload(TIMER_TICKS); } -uint32_t board_millis(void) { return system_ticks; } +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif #ifdef USE_FULL_ASSERT diff --git a/hw/bsp/hpmicro/family.c b/hw/bsp/hpmicro/family.c index ffec2523a..a80a8d913 100644 --- a/hw/bsp/hpmicro/family.c +++ b/hw/bsp/hpmicro/family.c @@ -108,7 +108,7 @@ int board_uart_write(void const *buf, int len) { #if CFG_TUSB_OS == OPT_OS_NONE // Get current milliseconds, must be implemented when no RTOS is used -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return (hpm_csr_get_core_cycle() / clock_get_core_clock_ticks_per_ms()); } diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c index d54b41bdb..c1ee34b1a 100644 --- a/hw/bsp/imxrt/family.c +++ b/hw/bsp/imxrt/family.c @@ -239,7 +239,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/kinetis_k/family.c b/hw/bsp/kinetis_k/family.c index 98ef52739..1505defe0 100644 --- a/hw/bsp/kinetis_k/family.c +++ b/hw/bsp/kinetis_k/family.c @@ -143,7 +143,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/kinetis_k32l2/family.c b/hw/bsp/kinetis_k32l2/family.c index 2062b8b18..ec8dc6ecf 100644 --- a/hw/bsp/kinetis_k32l2/family.c +++ b/hw/bsp/kinetis_k32l2/family.c @@ -148,7 +148,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/kinetis_kl/family.c b/hw/bsp/kinetis_kl/family.c index c257f4b2b..f89434d06 100644 --- a/hw/bsp/kinetis_kl/family.c +++ b/hw/bsp/kinetis_kl/family.c @@ -142,7 +142,7 @@ void SysTick_Handler(void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc11/family.c b/hw/bsp/lpc11/family.c index c9f18bd2f..76c2bd17c 100644 --- a/hw/bsp/lpc11/family.c +++ b/hw/bsp/lpc11/family.c @@ -130,7 +130,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc13/family.c b/hw/bsp/lpc13/family.c index e212c6a63..8513f4df4 100644 --- a/hw/bsp/lpc13/family.c +++ b/hw/bsp/lpc13/family.c @@ -83,7 +83,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc15/family.c b/hw/bsp/lpc15/family.c index 5f22df175..0d092d3a9 100644 --- a/hw/bsp/lpc15/family.c +++ b/hw/bsp/lpc15/family.c @@ -140,7 +140,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc17/family.c b/hw/bsp/lpc17/family.c index ba59fccca..f398f7e3c 100644 --- a/hw/bsp/lpc17/family.c +++ b/hw/bsp/lpc17/family.c @@ -145,7 +145,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc18/family.c b/hw/bsp/lpc18/family.c index 6c02c711f..2043cef99 100644 --- a/hw/bsp/lpc18/family.c +++ b/hw/bsp/lpc18/family.c @@ -143,7 +143,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc40/family.c b/hw/bsp/lpc40/family.c index 5ea95e9b8..237cd996b 100644 --- a/hw/bsp/lpc40/family.c +++ b/hw/bsp/lpc40/family.c @@ -156,7 +156,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc43/family.c b/hw/bsp/lpc43/family.c index f440fb119..bade53b07 100644 --- a/hw/bsp/lpc43/family.c +++ b/hw/bsp/lpc43/family.c @@ -257,7 +257,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/lpc51/family.c b/hw/bsp/lpc51/family.c index bec86f87f..847972350 100644 --- a/hw/bsp/lpc51/family.c +++ b/hw/bsp/lpc51/family.c @@ -122,7 +122,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/lpc54/family.c b/hw/bsp/lpc54/family.c index 7bb73afbc..945e27154 100644 --- a/hw/bsp/lpc54/family.c +++ b/hw/bsp/lpc54/family.c @@ -217,7 +217,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/lpc55/family.c b/hw/bsp/lpc55/family.c index ad0e502b5..7485ed4d5 100644 --- a/hw/bsp/lpc55/family.c +++ b/hw/bsp/lpc55/family.c @@ -350,7 +350,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/maxim/family.c b/hw/bsp/maxim/family.c index 7ad7d6ff9..6ef4c12c1 100644 --- a/hw/bsp/maxim/family.c +++ b/hw/bsp/maxim/family.c @@ -202,7 +202,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/mcx/family.c b/hw/bsp/mcx/family.c index 3b91678b1..a3969c217 100644 --- a/hw/bsp/mcx/family.c +++ b/hw/bsp/mcx/family.c @@ -219,7 +219,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/mm32/family.c b/hw/bsp/mm32/family.c index 663c30818..330b01f6d 100644 --- a/hw/bsp/mm32/family.c +++ b/hw/bsp/mm32/family.c @@ -175,7 +175,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/msp430/family.c b/hw/bsp/msp430/family.c index 390a9915e..413ad7db6 100644 --- a/hw/bsp/msp430/family.c +++ b/hw/bsp/msp430/family.c @@ -102,10 +102,10 @@ static void SystemClock_Config(void) // VUSB enabled automatically. // Wait two milliseconds to stabilize, per manual recommendation. - uint32_t ms_elapsed = board_millis(); + uint32_t ms_elapsed = tusb_time_millis_api(); do { - while((board_millis() - ms_elapsed) < 2); + while((tusb_time_millis_api() - ms_elapsed) < 2); }while(!(USBPWRCTL & USBBGVBV)); // USB uses XT2 (4 MHz) directly. Enable the PLL. @@ -113,11 +113,11 @@ static void SystemClock_Config(void) USBPLLCTL |= (UPFDEN | UPLLEN); // Wait until PLL locks. Check every 2ms, per manual. - ms_elapsed = board_millis(); + ms_elapsed = tusb_time_millis_api(); do { USBPLLIR &= ~USBOOLIFG; - while((board_millis() - ms_elapsed) < 2); + while((tusb_time_millis_api() - ms_elapsed) < 2); }while(USBPLLIR & USBOOLIFG); USBKEYPID = 0; @@ -207,7 +207,7 @@ void TIMER0_A0_ISR (void) { // TAxCCR0 CCIFG resets itself as soon as interrupt is invoked. } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { uint32_t systick_mirror; diff --git a/hw/bsp/msp432e4/family.c b/hw/bsp/msp432e4/family.c index 0e1b0528a..90eb945f4 100644 --- a/hw/bsp/msp432e4/family.c +++ b/hw/bsp/msp432e4/family.c @@ -202,7 +202,7 @@ void SysTick_Handler(void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/nrf/family.c b/hw/bsp/nrf/family.c index ee3ac61e2..04bfbf320 100644 --- a/hw/bsp/nrf/family.c +++ b/hw/bsp/nrf/family.c @@ -296,7 +296,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/nuc100_120/family.c b/hw/bsp/nuc100_120/family.c index 752af2a56..cfe60121c 100644 --- a/hw/bsp/nuc100_120/family.c +++ b/hw/bsp/nuc100_120/family.c @@ -87,7 +87,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/nuc121_125/family.c b/hw/bsp/nuc121_125/family.c index 089855207..dce5b4d62 100644 --- a/hw/bsp/nuc121_125/family.c +++ b/hw/bsp/nuc121_125/family.c @@ -86,7 +86,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/nuc126/family.c b/hw/bsp/nuc126/family.c index f992fcab4..3343064e5 100644 --- a/hw/bsp/nuc126/family.c +++ b/hw/bsp/nuc126/family.c @@ -111,7 +111,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/nuc505/family.c b/hw/bsp/nuc505/family.c index 00ed92310..f1a77e4a5 100644 --- a/hw/bsp/nuc505/family.c +++ b/hw/bsp/nuc505/family.c @@ -88,7 +88,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/pic32mz/family.c b/hw/bsp/pic32mz/family.c index da97f67a9..2bfc876e1 100644 --- a/hw/bsp/pic32mz/family.c +++ b/hw/bsp/pic32mz/family.c @@ -106,7 +106,7 @@ TU_ATTR_WEAK int board_uart_write(void const * buf, int len) } #if CFG_TUSB_OS == OPT_OS_NONE -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { // COUNTER is system clock (200MHz / 2 = 100MHz) convert to ms) return _CP0_GET_COUNT() / (100000000 / 1000); diff --git a/hw/bsp/ra/family.c b/hw/bsp/ra/family.c index 1f75b47c1..f371e694b 100644 --- a/hw/bsp/ra/family.c +++ b/hw/bsp/ra/family.c @@ -169,7 +169,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/rw61x/family.c b/hw/bsp/rw61x/family.c index 265d5fcc0..fcc7fb262 100644 --- a/hw/bsp/rw61x/family.c +++ b/hw/bsp/rw61x/family.c @@ -128,7 +128,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/rx/boards/gr_citrus/gr_citrus.c b/hw/bsp/rx/boards/gr_citrus/gr_citrus.c index 26ad4a6aa..e5b24bf69 100644 --- a/hw/bsp/rx/boards/gr_citrus/gr_citrus.c +++ b/hw/bsp/rx/boards/gr_citrus/gr_citrus.c @@ -248,7 +248,7 @@ void INT_Excep_CMT0_CMI0(void) ++system_ticks; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/rx/boards/rx65n_target/rx65n_target.c b/hw/bsp/rx/boards/rx65n_target/rx65n_target.c index 66a319541..d5c2de05a 100644 --- a/hw/bsp/rx/boards/rx65n_target/rx65n_target.c +++ b/hw/bsp/rx/boards/rx65n_target/rx65n_target.c @@ -299,7 +299,7 @@ void INT_Excep_CMT0_CMI0(void) ++system_ticks; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/samd11/family.c b/hw/bsp/samd11/family.c index 6cbf02412..bccbac8ea 100644 --- a/hw/bsp/samd11/family.c +++ b/hw/bsp/samd11/family.c @@ -155,7 +155,7 @@ void SysTick_Handler (void) system_ticks++; } -uint32_t board_millis(void) +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/samd2x_l2x/family.c b/hw/bsp/samd2x_l2x/family.c index a2dc8a8d4..737219b6c 100644 --- a/hw/bsp/samd2x_l2x/family.c +++ b/hw/bsp/samd2x_l2x/family.c @@ -361,7 +361,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/samd5x_e5x/family.c b/hw/bsp/samd5x_e5x/family.c index 5a7105894..c008b9719 100644 --- a/hw/bsp/samd5x_e5x/family.c +++ b/hw/bsp/samd5x_e5x/family.c @@ -210,7 +210,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/same7x/family.c b/hw/bsp/same7x/family.c index 6feefa3b5..ff6ecf277 100644 --- a/hw/bsp/same7x/family.c +++ b/hw/bsp/same7x/family.c @@ -192,7 +192,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/samg/family.c b/hw/bsp/samg/family.c index 5c5fc3c14..b27134305 100644 --- a/hw/bsp/samg/family.c +++ b/hw/bsp/samg/family.c @@ -148,7 +148,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32c0/family.c b/hw/bsp/stm32c0/family.c index e2ba47f45..e20c0ee15 100644 --- a/hw/bsp/stm32c0/family.c +++ b/hw/bsp/stm32c0/family.c @@ -173,7 +173,7 @@ void SysTick_Handler(void) { HAL_IncTick(); } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32f0/family.c b/hw/bsp/stm32f0/family.c index b99b0a8cc..5a35a3e50 100644 --- a/hw/bsp/stm32f0/family.c +++ b/hw/bsp/stm32f0/family.c @@ -160,7 +160,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32f1/family.c b/hw/bsp/stm32f1/family.c index 3147061cf..fae61ca9e 100644 --- a/hw/bsp/stm32f1/family.c +++ b/hw/bsp/stm32f1/family.c @@ -202,7 +202,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32f2/family.c b/hw/bsp/stm32f2/family.c index f95128040..b901bf4cc 100644 --- a/hw/bsp/stm32f2/family.c +++ b/hw/bsp/stm32f2/family.c @@ -145,7 +145,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32f3/family.c b/hw/bsp/stm32f3/family.c index 95bcc7882..fde1e9f6d 100644 --- a/hw/bsp/stm32f3/family.c +++ b/hw/bsp/stm32f3/family.c @@ -156,7 +156,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32f4/family.c b/hw/bsp/stm32f4/family.c index f0e9620f2..665ea114a 100644 --- a/hw/bsp/stm32f4/family.c +++ b/hw/bsp/stm32f4/family.c @@ -251,7 +251,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32f7/family.c b/hw/bsp/stm32f7/family.c index d8f0da201..ce9049abe 100644 --- a/hw/bsp/stm32f7/family.c +++ b/hw/bsp/stm32f7/family.c @@ -312,7 +312,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32g0/family.c b/hw/bsp/stm32g0/family.c index 4b175b0ec..b25897264 100644 --- a/hw/bsp/stm32g0/family.c +++ b/hw/bsp/stm32g0/family.c @@ -181,7 +181,7 @@ void SysTick_Handler(void) { HAL_IncTick(); } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32g4/family.c b/hw/bsp/stm32g4/family.c index d8afa0f95..2e13a1d4b 100644 --- a/hw/bsp/stm32g4/family.c +++ b/hw/bsp/stm32g4/family.c @@ -211,7 +211,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32h5/family.c b/hw/bsp/stm32h5/family.c index fdb12e44f..1e8acd502 100644 --- a/hw/bsp/stm32h5/family.c +++ b/hw/bsp/stm32h5/family.c @@ -207,7 +207,7 @@ void SysTick_Handler(void) { HAL_IncTick(); } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32h7/family.c b/hw/bsp/stm32h7/family.c index a320a7e72..2759dac63 100644 --- a/hw/bsp/stm32h7/family.c +++ b/hw/bsp/stm32h7/family.c @@ -295,7 +295,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32h7rs/family.c b/hw/bsp/stm32h7rs/family.c index 2cc39b7ac..3bf75ba97 100644 --- a/hw/bsp/stm32h7rs/family.c +++ b/hw/bsp/stm32h7rs/family.c @@ -468,7 +468,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32l0/family.c b/hw/bsp/stm32l0/family.c index 6aeab1259..192f014f4 100644 --- a/hw/bsp/stm32l0/family.c +++ b/hw/bsp/stm32l0/family.c @@ -168,7 +168,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32l4/family.c b/hw/bsp/stm32l4/family.c index 65f6b9ab3..c87b643b8 100644 --- a/hw/bsp/stm32l4/family.c +++ b/hw/bsp/stm32l4/family.c @@ -231,7 +231,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32n6/family.c b/hw/bsp/stm32n6/family.c index c839e6b3e..4354616c3 100644 --- a/hw/bsp/stm32n6/family.c +++ b/hw/bsp/stm32n6/family.c @@ -366,7 +366,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32u0/family.c b/hw/bsp/stm32u0/family.c index 50b513d8f..0f91d1f30 100644 --- a/hw/bsp/stm32u0/family.c +++ b/hw/bsp/stm32u0/family.c @@ -174,7 +174,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif diff --git a/hw/bsp/stm32u5/family.c b/hw/bsp/stm32u5/family.c index dfcf5c537..55ca25d58 100644 --- a/hw/bsp/stm32u5/family.c +++ b/hw/bsp/stm32u5/family.c @@ -270,7 +270,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32wb/family.c b/hw/bsp/stm32wb/family.c index 153d10a09..de503c072 100644 --- a/hw/bsp/stm32wb/family.c +++ b/hw/bsp/stm32wb/family.c @@ -174,7 +174,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/stm32wba/family.c b/hw/bsp/stm32wba/family.c index d05415755..e058a80a1 100644 --- a/hw/bsp/stm32wba/family.c +++ b/hw/bsp/stm32wba/family.c @@ -198,7 +198,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { return system_ticks; } +uint32_t tusb_time_millis_api(void) { return system_ticks; } #endif void HardFault_Handler(void) { asm( "bkpt 1" ); } diff --git a/hw/bsp/tm4c/family.c b/hw/bsp/tm4c/family.c index ae7f22f00..503d0a8c9 100644 --- a/hw/bsp/tm4c/family.c +++ b/hw/bsp/tm4c/family.c @@ -211,7 +211,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/hw/bsp/xmc4000/family.c b/hw/bsp/xmc4000/family.c index 6fef53025..d0acd04cb 100644 --- a/hw/bsp/xmc4000/family.c +++ b/hw/bsp/xmc4000/family.c @@ -147,7 +147,7 @@ void SysTick_Handler(void) { system_ticks++; } -uint32_t board_millis(void) { +uint32_t tusb_time_millis_api(void) { return system_ticks; } diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 9eb0a9337..6ac1405f3 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -90,6 +90,12 @@ // TODO move to a more obvious place/file //--------------------------------------------------------------------+ +// Get current milliseconds, required by some port/configuration without RTOS +extern uint32_t tusb_time_millis_api(void); + +// Delay in milliseconds, use tusb_time_millis_api() by default. required by some port/configuration with no RTOS +extern void tusb_time_delay_ms_api(uint32_t ms); + // flush data cache extern void tusb_app_dcache_flush(uintptr_t addr, uint32_t data_size); diff --git a/src/host/usbh.c b/src/host/usbh.c index 60d78605f..0da5166c2 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -685,7 +685,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { has_deferred_attach = osal_queue_receive(_usbh_daq, &event, 0); } - if (!has_deferred_attach) // skip event queue to process deferred at + if (!has_deferred_attach) // skip event queue to process deferred attach #endif { if (!osal_queue_receive(_usbh_q, &event, timeout_ms)) { diff --git a/src/portable/sunxi/dcd_sunxi_musb.c b/src/portable/sunxi/dcd_sunxi_musb.c index b413121a5..9fac0bc1c 100644 --- a/src/portable/sunxi/dcd_sunxi_musb.c +++ b/src/portable/sunxi/dcd_sunxi_musb.c @@ -36,9 +36,6 @@ #include #include "musb_def.h" -//#include "bsp/board_api.h" -extern uint32_t board_millis(void); // TODO remove - typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; diff --git a/src/tusb.c b/src/tusb.c index 40d0e8adf..37aecf693 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -45,21 +45,24 @@ tusb_role_t _tusb_rhport_role[TUP_USBIP_CONTROLLER_NUM] = { TUSB_ROLE_INVALID }; // Weak/Default API, can be overwritten by Application //-------------------------------------------------------------------- - #if CFG_TUSB_OS != OPT_OS_NONE -uint32_t tusb_time_millis_api(void) { +#if CFG_TUSB_OS != OPT_OS_NONE +TU_ATTR_WEAK uint32_t tusb_time_millis_api(void) { return osal_time_millis(); } - #endif TU_ATTR_WEAK void tusb_time_delay_ms_api(uint32_t ms) { -#if CFG_TUSB_OS != OPT_OS_NONE osal_task_delay(ms); +} + #else +// tusb_time_millis_api() must be implemented by user application. + +TU_ATTR_WEAK void tusb_time_delay_ms_api(uint32_t ms) { // delay using millis() const uint32_t time_ms = tusb_time_millis_api(); while ((tusb_time_millis_api() - time_ms) < ms) {} -#endif } +#endif TU_ATTR_WEAK void *tusb_app_virt_to_phys(void *virt_addr) { return virt_addr; diff --git a/src/tusb.h b/src/tusb.h index 742009a2e..3876bf863 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -174,16 +174,6 @@ bool tusb_deinit(uint8_t rhport); #endif -//--------------------------------------------------------------------+ -// -//--------------------------------------------------------------------+ - -// Get current milliseconds, required by some port/configuration without RTOS -extern uint32_t tusb_time_millis_api(void); - -// Delay in milliseconds, use tusb_time_millis_api() by default. required by some port/configuration with no RTOS -extern void tusb_time_delay_ms_api(uint32_t ms); - #ifdef __cplusplus } #endif -- cgit v1.3.1 From 0d4feff0eb01511d413e79109656dd76bf42e77a Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 9 Mar 2026 14:15:20 +0700 Subject: usbh device descriptor validation, also check ep size > 0 --- src/common/tusb_private.h | 3 +-- src/host/usbh.c | 30 ++++++++++++++++++++---------- src/tusb.c | 3 ++- 3 files changed, 23 insertions(+), 13 deletions(-) (limited to 'src/tusb.c') diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 5a51dfc37..17ab267c3 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -81,9 +81,8 @@ typedef struct { bool tu_edpt_validate(const tusb_desc_endpoint_t *desc_ep, tusb_speed_t speed); #else TU_ATTR_ALWAYS_INLINE static inline bool tu_edpt_validate(const tusb_desc_endpoint_t *desc_ep, tusb_speed_t speed) { - (void)desc_ep; (void)speed; - return true; + return tu_edpt_packet_size(desc_ep) > 0; } #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 33d74862f..0fa9b6646 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1150,7 +1150,7 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) { } bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const* desc_ep) { - // HACK: some device incorrectly always report 512 bulk regardless of link speed, overwrite descriptor to force 64 + // HACK: some device incorrectly always reports 512 bulk regardless of link speed, overwrite descriptor to force 64 if (desc_ep->bmAttributes.xfer == TUSB_XFER_BULK && tu_edpt_packet_size(desc_ep) > 64 && tuh_speed_get(dev_addr) == TUSB_SPEED_FULL) { TU_LOG1(" WARN: EP max packet size is 512 in fullspeed, force to 64\r\n"); @@ -1655,6 +1655,7 @@ static void process_enumeration(tuh_xfer_t *xfer) { TU_ASSERT(dev != NULL,); } uint16_t langid = 0x0409; // default is English + bool is_enum_failed = false; switch (state) { #if CFG_TUH_HUB @@ -1664,11 +1665,11 @@ static void process_enumeration(tuh_xfer_t *xfer) { if (0 == port_status.status.connection) { TU_LOG_USBH("Device unplugged from hub while debouncing\r\n"); - enum_full_complete(false); - return; + is_enum_failed = true; + } else { + TU_ASSERT(hub_port_reset(dev0_bus->hub_addr, dev0_bus->hub_port, process_enumeration, + ENUM_HUB_RESET_COMPLETE), ); } - - TU_ASSERT(hub_port_reset(dev0_bus->hub_addr, dev0_bus->hub_port, process_enumeration, ENUM_HUB_RESET_COMPLETE), ); break; } @@ -1691,7 +1692,7 @@ static void process_enumeration(tuh_xfer_t *xfer) { usbh_defer_func_ms_async(ENUM_RESET_HUB_DELAY_MS, enum_delay_async, ENUM_AFTER_RESET_HUB_DELAY_RETRY); } else { // retry but still not set --> failed - enum_full_complete(false); + is_enum_failed = true; } break; } @@ -1702,14 +1703,13 @@ static void process_enumeration(tuh_xfer_t *xfer) { if (0 == port_status.status.connection) { TU_LOG_USBH("Device unplugged from hub (not addressed yet)\r\n"); - enum_full_complete(false); - return; + is_enum_failed = true; + break; } dev0_bus->speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH : (port_status.status.low_speed) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL; - TU_ATTR_FALLTHROUGH; } #endif @@ -1720,6 +1720,12 @@ static void process_enumeration(tuh_xfer_t *xfer) { case ENUM_SET_ADDR: { const tusb_desc_device_t *desc_device = (const tusb_desc_device_t *) _usbh_epbuf.ctrl; + if (!(desc_device->bDescriptorType == TUSB_DESC_DEVICE && desc_device->bMaxPacketSize0 >= 8)) { + TU_LOG_USBH("Invalid Device descriptor\r\n"); + is_enum_failed = true; + break; + } + const uint8_t new_addr = enum_get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB); TU_ASSERT(new_addr != 0,); @@ -1910,9 +1916,13 @@ static void process_enumeration(tuh_xfer_t *xfer) { } default: - enum_full_complete(false); // stop enumeration if unknown state + is_enum_failed = true; break; } + + if (is_enum_failed) { + enum_full_complete(false); + } } static uint8_t enum_get_new_address(bool is_hub) { diff --git a/src/tusb.c b/src/tusb.c index 5241fcf3d..4ea396715 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -260,6 +260,7 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { bool tu_edpt_validate(const tusb_desc_endpoint_t *desc_ep, tusb_speed_t speed) { const uint16_t max_packet_size = tu_edpt_packet_size(desc_ep); TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); + TU_ASSERT(max_packet_size > 0); switch (desc_ep->bmAttributes.xfer) { case TUSB_XFER_ISOCHRONOUS: { @@ -279,7 +280,7 @@ bool tu_edpt_validate(const tusb_desc_endpoint_t *desc_ep, tusb_speed_t speed) { break; case TUSB_XFER_INTERRUPT: { - uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64); + const uint16_t spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64); TU_ASSERT(max_packet_size <= spec_size); break; } -- cgit v1.3.1 From 9d68ed65f7200f155f01416b332c5e9f2340a8b2 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 4 May 2026 11:19:26 +0700 Subject: refactor: replace `tu_edpt_state_t` struct with `uint8_t` and update all endpoint state handling methods and accesses --- src/class/printer/printer_device.c | 1 - src/common/tusb_private.h | 19 ++++------ src/device/usbd.c | 72 ++++++++++++++++---------------------- src/host/usbh.c | 23 ++++++------ src/tusb.c | 15 ++++---- 5 files changed, 54 insertions(+), 76 deletions(-) (limited to 'src/tusb.c') diff --git a/src/class/printer/printer_device.c b/src/class/printer/printer_device.c index d2dc9b163..158455fc9 100644 --- a/src/class/printer/printer_device.c +++ b/src/class/printer/printer_device.c @@ -41,7 +41,6 @@ typedef struct { uint8_t itf_num; /*------------- From this point, data is not cleared by bus reset -------------*/ - tu_edpt_stream_t rx_stream; tu_edpt_stream_t tx_stream; diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 91d213755..a31bf7b03 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -46,17 +46,10 @@ extern tusb_role_t _tusb_rhport_role[TUP_USBIP_CONTROLLER_NUM]; // Endpoint //--------------------------------------------------------------------+ -enum { - TU_EDPT_STATE_BUSY = 0x01, - TU_EDPT_STATE_STALLED = 0x02, - TU_EDPT_STATE_CLAIMED = 0x04, -}; - -typedef struct TU_ATTR_PACKED { - volatile uint8_t busy : 1; - volatile uint8_t stalled : 1; - volatile uint8_t claimed : 1; -} tu_edpt_state_t; +// Endpoint state bits — manipulate the bare uint8_t with these masks. +#define TU_EDPT_STATE_BUSY 0x01u +#define TU_EDPT_STATE_STALLED 0x02u +#define TU_EDPT_STATE_CLAIMED 0x04u typedef struct { uint8_t hwid; // device: rhport, host: daddr @@ -92,10 +85,10 @@ bool tu_bind_driver_to_ep_itf(uint8_t driver_id, uint8_t ep2drv[][2], uint8_t it const uint8_t *p_desc, uint16_t desc_len); // Claim an endpoint with provided mutex -bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex); +bool tu_edpt_claim(volatile uint8_t* ep_state, osal_mutex_t mutex); // Release an endpoint with provided mutex -bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex); +bool tu_edpt_release(volatile uint8_t* ep_state, osal_mutex_t mutex); //--------------------------------------------------------------------+ // Endpoint Stream diff --git a/src/device/usbd.c b/src/device/usbd.c index 291319709..f8ec51762 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -149,7 +149,7 @@ typedef struct { uint8_t itf2drv[CFG_TUD_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUD_ENDPPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each - tu_edpt_state_t ep_status[CFG_TUD_ENDPPOINT_MAX][2]; + volatile uint8_t ep_status[CFG_TUD_ENDPPOINT_MAX][2]; } usbd_device_t; static usbd_device_t _usbd_dev; @@ -711,7 +711,9 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { break; case DCD_EVENT_SETUP_RECEIVED: - TU_ASSERT(_usbd_queued_setup > 0,); + if (_usbd_queued_setup == 0) { + break; + } _usbd_queued_setup--; TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8); if (_usbd_queued_setup != 0) { @@ -723,18 +725,16 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { // But it is easier to set it every time instead of wasting time to check then set _usbd_dev.connected = 1; - // mark both in & out control as free - _usbd_dev.ep_status[0][TUSB_DIR_OUT].busy = 0; - _usbd_dev.ep_status[0][TUSB_DIR_OUT].claimed = 0; - _usbd_dev.ep_status[0][TUSB_DIR_IN].busy = 0; - _usbd_dev.ep_status[0][TUSB_DIR_IN].claimed = 0; + // reset ep state + _usbd_dev.ep_status[0][TUSB_DIR_OUT] = 0; + _usbd_dev.ep_status[0][TUSB_DIR_IN] = 0; // Process control request if (!process_setup_received(event.rhport, &event.setup_received)) { TU_LOG_USBD(" Stall EP0\r\n"); // Failed -> stall both control endpoint IN and OUT - dcd_edpt_stall(event.rhport, 0); - dcd_edpt_stall(event.rhport, 0 | TUSB_DIR_IN_MASK); + dcd_edpt_stall(event.rhport, TU_EP0_OUT); + dcd_edpt_stall(event.rhport, TU_EP0_IN); } break; @@ -746,8 +746,8 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { TU_LOG_USBD("on EP %02X with %u bytes\r\n", ep_addr, (unsigned int) event.xfer_complete.len); - _usbd_dev.ep_status[epnum][ep_dir].busy = 0; - _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; + // Clear busy + claimed + _usbd_dev.ep_status[epnum][ep_dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED); if (0 == epnum) { usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len); @@ -1202,7 +1202,7 @@ static bool process_setup_received(uint8_t rhport, tusb_control_request_t const ctrl_xfer->complete_cb = NULL; // skip ZLP status if driver already did that - if (!_usbd_dev.ep_status[0][TUSB_DIR_IN].busy) { + if (!(_usbd_dev.ep_status[0][TUSB_DIR_IN] & TU_EDPT_STATE_BUSY)) { tud_control_status(rhport, p_request); } } @@ -1441,15 +1441,15 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]); if (driver && driver->xfer_isr) { - _usbd_dev.ep_status[epnum][ep_dir].busy = 0; - _usbd_dev.ep_status[epnum][ep_dir].claimed = 0; + // Clear busy + claimed + _usbd_dev.ep_status[epnum][ep_dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED); send = !driver->xfer_isr(event->rhport, ep_addr, (xfer_result_t) event->xfer_complete.result, event->xfer_complete.len); // xfer_isr() is deferred to xfer_cb(), revert busy/claimed status if (send) { - _usbd_dev.ep_status[epnum][ep_dir].busy = 1; - _usbd_dev.ep_status[epnum][ep_dir].claimed = 1; + // set busy + claimed + _usbd_dev.ep_status[epnum][ep_dir] |= (TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED); } } } @@ -1539,9 +1539,7 @@ bool usbd_edpt_claim(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir]; - - return tu_edpt_claim(ep_state, _usbd_mutex); + return tu_edpt_claim(&_usbd_dev.ep_status[epnum][dir], _usbd_mutex); } bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) { @@ -1549,9 +1547,7 @@ bool usbd_edpt_release(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - tu_edpt_state_t* ep_state = &_usbd_dev.ep_status[epnum][dir]; - - return tu_edpt_release(ep_state, _usbd_mutex); + return tu_edpt_release(&_usbd_dev.ep_status[epnum][dir], _usbd_mutex); } bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, bool is_isr) { @@ -1571,18 +1567,17 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t t #endif // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); + TU_ASSERT((_usbd_dev.ep_status[epnum][dir] & TU_EDPT_STATE_BUSY) == 0); // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() // could return and USBD task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = 1; + _usbd_dev.ep_status[epnum][dir] |= TU_EDPT_STATE_BUSY; if (dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes, is_isr)) { return true; } else { // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = 0; - _usbd_dev.ep_status[epnum][dir].claimed = 0; + _usbd_dev.ep_status[epnum][dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED); TU_LOG_USBD("FAILED\r\n"); TU_BREAKPOINT(); return false; @@ -1603,19 +1598,18 @@ bool usbd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_ TU_LOG_USBD(" Queue FIFO EP %02X with %u bytes ... ", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like a race condition ! - TU_ASSERT(_usbd_dev.ep_status[epnum][dir].busy == 0); + TU_ASSERT((_usbd_dev.ep_status[epnum][dir] & TU_EDPT_STATE_BUSY) == 0); // Set busy first since the actual transfer can be complete before dcd_edpt_xfer() could return // and usbd task can preempt and clear the busy - _usbd_dev.ep_status[epnum][dir].busy = 1; + _usbd_dev.ep_status[epnum][dir] |= TU_EDPT_STATE_BUSY; if (dcd_edpt_xfer_fifo(rhport, ep_addr, ff, total_bytes, is_isr)) { TU_LOG_USBD("OK\r\n"); return true; } else { // DCD error, mark endpoint as ready to allow next transfer - _usbd_dev.ep_status[epnum][dir].busy = 0; - _usbd_dev.ep_status[epnum][dir].claimed = 0; + _usbd_dev.ep_status[epnum][dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED); TU_LOG_USBD("failed\r\n"); TU_BREAKPOINT(); return false; @@ -1636,7 +1630,7 @@ bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - return _usbd_dev.ep_status[epnum][dir].busy; + return (_usbd_dev.ep_status[epnum][dir] & TU_EDPT_STATE_BUSY) != 0; } void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { @@ -1648,8 +1642,7 @@ void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { // only stalled if currently cleared TU_LOG_USBD(" Stall EP %02X\r\n", ep_addr); dcd_edpt_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = 1; - _usbd_dev.ep_status[epnum][dir].busy = 1; + _usbd_dev.ep_status[epnum][dir] |= (TU_EDPT_STATE_STALLED | TU_EDPT_STATE_BUSY); } void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { @@ -1661,8 +1654,7 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { // only clear if currently stalled TU_LOG_USBD(" Clear Stall EP %02X\r\n", ep_addr); dcd_edpt_clear_stall(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = 0; - _usbd_dev.ep_status[epnum][dir].busy = 0; + _usbd_dev.ep_status[epnum][dir] &= (uint8_t) ~(TU_EDPT_STATE_STALLED | TU_EDPT_STATE_BUSY); } bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) { @@ -1671,7 +1663,7 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - return _usbd_dev.ep_status[epnum][dir].stalled; + return (_usbd_dev.ep_status[epnum][dir] & TU_EDPT_STATE_STALLED) != 0; } /** @@ -1691,9 +1683,7 @@ void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr) { uint8_t const dir = tu_edpt_dir(ep_addr); dcd_edpt_close(rhport, ep_addr); - _usbd_dev.ep_status[epnum][dir].stalled = 0; - _usbd_dev.ep_status[epnum][dir].busy = 0; - _usbd_dev.ep_status[epnum][dir].claimed = 0; + _usbd_dev.ep_status[epnum][dir] = 0; #endif return; @@ -1738,9 +1728,7 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX); TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t)_usbd_dev.speed)); - _usbd_dev.ep_status[epnum][dir].stalled = 0; - _usbd_dev.ep_status[epnum][dir].busy = 0; - _usbd_dev.ep_status[epnum][dir].claimed = 0; + _usbd_dev.ep_status[epnum][dir] = 0; return dcd_edpt_iso_activate(rhport, desc_ep); #else (void) rhport; (void) desc_ep; diff --git a/src/host/usbh.c b/src/host/usbh.c index 8f80800e9..490724b02 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -140,7 +140,7 @@ typedef struct { uint8_t itf2drv[CFG_TUH_INTERFACE_MAX]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[CFG_TUH_ENDPOINT_MAX][2]; // map endpoint to driver ( 0xff is invalid ), can use only 4-bit each - tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2]; + volatile uint8_t ep_status[CFG_TUH_ENDPOINT_MAX][2]; #if CFG_TUH_API_EDPT_XFER // TODO array can be CFG_TUH_ENDPOINT_MAX-1 @@ -744,8 +744,8 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { usbh_device_t* dev = get_device(event.dev_addr); TU_VERIFY(dev && dev->connected,); - dev->ep_status[epnum][ep_dir].busy = 0; - dev->ep_status[epnum][ep_dir].claimed = 0; + // clear busy and claimed + dev->ep_status[epnum][ep_dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED); if (0 == epnum) { usbh_control_xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len); @@ -1016,10 +1016,10 @@ bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) { usbh_device_t* dev = get_device(daddr); TU_VERIFY(dev); - TU_VERIFY(dev->ep_status[epnum][dir].busy); // non-control skip if not busy + TU_VERIFY(dev->ep_status[epnum][dir] & TU_EDPT_STATE_BUSY); // non-control skip if not busy // abort then mark as ready and release endpoint hcd_edpt_abort_xfer(dev->bus_info.rhport, daddr, ep_addr); - dev->ep_status[epnum][dir].busy = false; + dev->ep_status[epnum][dir] &= (uint8_t) ~TU_EDPT_STATE_BUSY; // clear busy tu_edpt_release(&dev->ep_status[epnum][dir], _usbh_mutex); } @@ -1110,16 +1110,16 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t* bu uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir]; + volatile uint8_t* ep_state = &dev->ep_status[epnum][dir]; TU_LOG_USBH(" Queue EP %02X with %u bytes ... \r\n", ep_addr, total_bytes); // Attempt to transfer on a busy endpoint, sound like an race condition ! - TU_ASSERT(ep_state->busy == 0); + TU_ASSERT((*ep_state & TU_EDPT_STATE_BUSY) == 0); // Set busy first since the actual transfer can be complete before hcd_edpt_xfer() // could return and USBH task can preempt and clear the busy - ep_state->busy = 1; + *ep_state |= TU_EDPT_STATE_BUSY; #if CFG_TUH_API_EDPT_XFER dev->ep_callback[epnum][dir].complete_cb = complete_cb; @@ -1130,9 +1130,8 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t* bu TU_LOG_USBH("OK\r\n"); return true; } else { - // HCD error, mark endpoint as ready to allow next transfer - ep_state->busy = 0; - ep_state->claimed = 0; + // HCD error, clear busy and claimed to allow next transfer + *ep_state &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED); TU_LOG1("Failed\r\n"); // TU_BREAKPOINT(); return false; @@ -1178,7 +1177,7 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - return dev->ep_status[epnum][dir].busy; + return (dev->ep_status[epnum][dir] & TU_EDPT_STATE_BUSY) != 0; } //--------------------------------------------------------------------+ diff --git a/src/tusb.c b/src/tusb.c index 5e4422e41..5d656fb8c 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -224,32 +224,31 @@ uint8_t const* tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t by // Endpoint Helper for both Host and Device stack //--------------------------------------------------------------------+ -bool tu_edpt_claim(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { +bool tu_edpt_claim(volatile uint8_t* ep_state, osal_mutex_t mutex) { (void) mutex; // pre-check to help reducing mutex lock - TU_VERIFY(ep_state->busy == 0); - TU_VERIFY(ep_state->claimed == 0); + TU_VERIFY((*ep_state & (TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED)) == 0); (void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); // can only claim the endpoint if it is not busy and not claimed yet. - bool const available = (ep_state->busy == 0) && (ep_state->claimed == 0); + bool const available = (*ep_state & (TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED)) == 0; if (available) { - ep_state->claimed = 1; + *ep_state |= TU_EDPT_STATE_CLAIMED; } (void) osal_mutex_unlock(mutex); return available; } -bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { +bool tu_edpt_release(volatile uint8_t* ep_state, osal_mutex_t mutex) { (void) mutex; (void) osal_mutex_lock(mutex, OSAL_TIMEOUT_WAIT_FOREVER); // can only release the endpoint if it is claimed and not busy - bool const ret = (ep_state->claimed == 1) && (ep_state->busy == 0); + bool const ret = (*ep_state & (TU_EDPT_STATE_CLAIMED | TU_EDPT_STATE_BUSY)) == TU_EDPT_STATE_CLAIMED; if (ret) { - ep_state->claimed = 0; + *ep_state &= (uint8_t) ~TU_EDPT_STATE_CLAIMED; } (void) osal_mutex_unlock(mutex); -- cgit v1.3.1 From 7e0fcaa41ee9330274808d88e5211bdbe37511a4 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 1 Jun 2026 10:05:17 +0700 Subject: ultrareview nits: keep xfer_result table in sync, hoist blinky loop - src/tusb.c: extend tu_str_xfer_result[] with "ABORTED" and "INVALID" to match the new enum size. Not reachable today (no HCD posts those values through hcd_event_xfer_complete), but keeps the enum/table invariant intact so future HCDs that surface ABORTED don't index OOB. - examples/dual/dynamic_switch/src/main.c: apply the same while(1) hoist already done for cdc_task / print_devinfo_task to led_blinking_task. On OS_NONE the loop returned mid-iteration, which on first call could fire multiple back-to-back toggles while start_ms (initially 0) caught up to uptime. Co-Authored-By: Claude Opus 4.7 --- examples/dual/dynamic_switch/src/main.c | 17 ++++++++++------- src/tusb.c | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'src/tusb.c') diff --git a/examples/dual/dynamic_switch/src/main.c b/examples/dual/dynamic_switch/src/main.c index ac5126e56..f67cd885c 100644 --- a/examples/dual/dynamic_switch/src/main.c +++ b/examples/dual/dynamic_switch/src/main.c @@ -483,16 +483,19 @@ void led_blinking_task(void *param) { (void) param; static uint32_t start_ms = 0; static bool led_state = false; - while (1) { #if CFG_TUSB_OS == OPT_OS_FREERTOS + while (1) { vTaskDelay(pdMS_TO_TICKS(blink_interval_ms)); -#else - if (tusb_time_millis_api() - start_ms < blink_interval_ms) { - return; // not enough time - } -#endif start_ms += blink_interval_ms; board_led_write(led_state); - led_state = 1 - led_state; // toggle + led_state = 1 - led_state; + } +#else + if (tusb_time_millis_api() - start_ms < blink_interval_ms) { + return; // not enough time } + start_ms += blink_interval_ms; + board_led_write(led_state); + led_state = 1 - led_state; +#endif } diff --git a/src/tusb.c b/src/tusb.c index 5d656fb8c..634cbc10b 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -497,7 +497,7 @@ char const* const tu_str_std_request[] = { }; char const* const tu_str_xfer_result[] = { - "OK", "FAILED", "STALLED", "TIMEOUT" + "OK", "FAILED", "STALLED", "TIMEOUT", "ABORTED", "INVALID" }; #endif -- cgit v1.3.1