summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/actions/setup_toolchain/action.yml2
-rw-r--r--.github/actions/setup_toolchain/toolchain.json2
-rw-r--r--.github/workflows/build.yml123
-rw-r--r--.github/workflows/codeql.yml6
-rw-r--r--.github/workflows/hil_test.yml128
-rw-r--r--.idea/debugServers/rt1064.xml2
-rw-r--r--examples/dual/host_hid_to_device_cdc/src/main.c8
-rw-r--r--examples/dual/host_info_to_device_cdc/src/main.c46
-rw-r--r--examples/host/cdc_msc_hid/src/hid_app.c100
-rw-r--r--hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld45
-rw-r--r--hw/bsp/stm32wb/family.c5
-rw-r--r--src/class/cdc/cdc_host.c2
-rw-r--r--src/class/hid/hid_host.c6
-rw-r--r--src/host/hub.c4
-rw-r--r--src/host/usbh.c261
-rwxr-xr-xtools/get_deps.py4
16 files changed, 361 insertions, 383 deletions
diff --git a/.github/actions/setup_toolchain/action.yml b/.github/actions/setup_toolchain/action.yml
index 850a3a06f..6fd5c9d4e 100644
--- a/.github/actions/setup_toolchain/action.yml
+++ b/.github/actions/setup_toolchain/action.yml
@@ -17,7 +17,7 @@ runs:
if: inputs.toolchain == 'arm-gcc'
uses: carlosperate/arm-none-eabi-gcc-action@v1
with:
- release: '13.2.Rel1'
+ release: '14.2.Rel1'
- name: Pull ESP-IDF docker
if: inputs.toolchain == 'esp-idf'
diff --git a/.github/actions/setup_toolchain/toolchain.json b/.github/actions/setup_toolchain/toolchain.json
index 4e65f1cbe..f7123ef11 100644
--- a/.github/actions/setup_toolchain/toolchain.json
+++ b/.github/actions/setup_toolchain/toolchain.json
@@ -1,7 +1,7 @@
{
"aarch64-gcc": "https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz",
"arm-clang": "https://github.com/ARM-software/LLVM-embedded-toolchain-for-Arm/releases/download/release-19.1.1/LLVM-ET-Arm-19.1.1-Linux-x86_64.tar.xz",
- "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v13.2.1-1.1/xpack-arm-none-eabi-gcc-13.2.1-1.1-linux-x64.tar.gz",
+ "arm-gcc": "https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases/download/v14.2.1-1.1/xpack-arm-none-eabi-gcc-14.2.1-1.1-linux-x64.tar.gz",
"msp430-gcc": "http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2",
"riscv-gcc": "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v13.2.0-2/xpack-riscv-none-elf-gcc-13.2.0-2-linux-x64.tar.gz",
"rx-gcc": "https://github.com/hathach/rx_device/releases/download/0.0.1/gcc-8.3.0.202411-GNURX-ELF.run",
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 17d578e4d..28447cc80 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -8,8 +8,8 @@ on:
- 'examples/**'
- 'lib/**'
- 'hw/**'
- - 'tools/get_deps.py'
- 'tools/build.py'
+ - 'tools/get_deps.py'
- '.github/actions/**'
- '.github/workflows/build.yml'
- '.github/workflows/build_util.yml'
@@ -21,8 +21,9 @@ on:
- 'examples/**'
- 'lib/**'
- 'hw/**'
- - 'tools/get_deps.py'
+ - 'test/hil/**'
- 'tools/build.py'
+ - 'tools/get_deps.py'
- '.github/actions/**'
- '.github/workflows/build.yml'
- '.github/workflows/build_util.yml'
@@ -31,11 +32,20 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
+env:
+ HIL_JSON: test/hil/tinyusb.json
+
jobs:
+ # ---------------------------------------
+ #
+ # Build
+ #
+ # ---------------------------------------
set-matrix:
runs-on: ubuntu-latest
outputs:
json: ${{ steps.set-matrix-json.outputs.matrix }}
+ hil_json: ${{ steps.set-matrix-json.outputs.hil_matrix }}
steps:
- name: Checkout TinyUSB
uses: actions/checkout@v4
@@ -43,9 +53,14 @@ jobs:
- name: Generate matrix json
id: set-matrix-json
run: |
+ # build matrix
MATRIX_JSON=$(python .github/workflows/ci_set_matrix.py)
echo "matrix=$MATRIX_JSON"
echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT
+ # hil matrix
+ HIL_MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py ${{ env.HIL_JSON }})
+ echo "hil_matrix=$HIL_MATRIX_JSON"
+ echo "hil_matrix=$HIL_MATRIX_JSON" >> $GITHUB_OUTPUT
# ---------------------------------------
# Build CMake
@@ -151,3 +166,107 @@ jobs:
run: |
west build -b pca10056 -d examples/device/cdc_msc/build examples/device/cdc_msc -- -DRTOS=zephyr
west build -b pca10056 -d examples/device/msc_dual_lun/build examples/device/msc_dual_lun -- -DRTOS=zephyr
+
+ # ---------------------------------------
+ #
+ # Hardware in the loop (HIL)
+ # Run on PR only (hil-tinyusb), hil-hfp only run on non-forked PR
+ # ---------------------------------------
+
+ # ---------------------------------------
+ # Build arm-gcc
+ # ---------------------------------------
+ hil-build:
+ if: |
+ github.repository_owner == 'hathach' &&
+ (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch')
+ needs: set-matrix
+ uses: ./.github/workflows/build_util.yml
+ strategy:
+ fail-fast: false
+ matrix:
+ toolchain:
+ - 'arm-gcc'
+ - 'esp-idf'
+ with:
+ build-system: 'cmake'
+ toolchain: ${{ matrix.toolchain }}
+ build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.hil_json)[matrix.toolchain]) }}
+ one-per-family: true
+ upload-artifacts: true
+
+ # ---------------------------------------
+ # Hardware in the loop (HIL)
+ # self-hosted on local VM, for attached hardware checkout HIL_JSON
+ # ---------------------------------------
+ hil-tinyusb:
+ if: |
+ github.repository_owner == 'hathach' &&
+ (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch')
+ needs: hil-build
+ runs-on: [self-hosted, X64, hathach, hardware-in-the-loop]
+ steps:
+ - name: Clean workspace
+ run: |
+ echo "Cleaning up previous run"
+ rm -rf "${{ github.workspace }}"
+ mkdir -p "${{ github.workspace }}"
+
+ - name: Checkout TinyUSB
+ uses: actions/checkout@v4
+ with:
+ sparse-checkout: test/hil
+
+ - name: Download Artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: cmake-build
+ merge-multiple: true
+
+ - name: Test on actual hardware
+ run: |
+ ls cmake-build/
+ python3 test/hil/hil_test.py ${{ env.HIL_JSON }}
+
+ # ---------------------------------------
+ # Hardware in the loop (HIL)
+ # self-hosted by HFP, build with IAR toolchain, for attached hardware checkout test/hil/hfp.json
+ # Since IAR Token secret is not passed to forked PR, only build non-forked PR
+ # ---------------------------------------
+ hil-hfp:
+ if: |
+ github.repository_owner == 'hathach' &&
+ github.event.pull_request.head.repo.fork == false &&
+ (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch')
+ runs-on: [self-hosted, Linux, X64, hifiphile]
+ env:
+ IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }}
+ steps:
+ - name: Clean workspace
+ run: |
+ echo "Cleaning up previous run"
+ rm -rf "${{ github.workspace }}"3
+ mkdir -p "${{ github.workspace }}"
+
+ - name: Toolchain version
+ run: |
+ iccarm --version
+
+ - name: Checkout TinyUSB
+ uses: actions/checkout@v4
+
+ - name: Get build boards
+ run: |
+ MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py test/hil/hfp.json)
+ BUILD_ARGS=$(echo $MATRIX_JSON | jq -r '.["arm-gcc"] | join(" ")')
+ echo "BUILD_ARGS=$BUILD_ARGS"
+ echo "BUILD_ARGS=$BUILD_ARGS" >> $GITHUB_ENV
+
+ - name: Get Dependencies
+ run: python3 tools/get_deps.py $BUILD_ARGS
+
+ - name: Build
+ run: python3 tools/build.py --toolchain iar $BUILD_ARGS
+
+ - name: Test on actual hardware (hardware in the loop)
+ run: python3 test/hil/hil_test.py hfp.json
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index be4c2dd87..a22c65c79 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -66,7 +66,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -93,7 +93,7 @@ jobs:
./.github/workflows/codeql-buildscript.sh
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
upload: false
@@ -129,7 +129,7 @@ jobs:
sarif_file: ${{ steps.step1.outputs.sarif-output }}
category: "/language:${{matrix.language}}"
- - name: Archive CodeQL results
+ - name: Upload CodeQL results as an artifact
uses: actions/upload-artifact@v4
with:
name: codeql-results
diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml
deleted file mode 100644
index 0ad37ffce..000000000
--- a/.github/workflows/hil_test.yml
+++ /dev/null
@@ -1,128 +0,0 @@
-name: Hardware Test
-
-on:
- workflow_dispatch:
- pull_request:
- branches: [ master ]
- paths:
- - 'src/**'
- - 'examples/**'
- - 'lib/**'
- - 'hw/**'
- - 'test/hil/**'
- - 'tools/get_deps.py'
- - '.github/actions/**'
- - '.github/workflows/hil_test.yml'
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-env:
- HIL_JSON: test/hil/tinyusb.json
-
-jobs:
- set-matrix:
- runs-on: ubuntu-latest
- outputs:
- json: ${{ steps.set-matrix-json.outputs.matrix }}
- steps:
- - name: Checkout TinyUSB
- uses: actions/checkout@v4
-
- - name: Generate matrix json
- id: set-matrix-json
- run: |
- MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py ${{ env.HIL_JSON }})
- echo "matrix=$MATRIX_JSON"
- echo "matrix=$MATRIX_JSON" >> $GITHUB_OUTPUT
-
- # ---------------------------------------
- # Build arm-gcc
- # ---------------------------------------
- build:
- if: github.repository_owner == 'hathach'
- needs: set-matrix
- uses: ./.github/workflows/build_util.yml
- strategy:
- fail-fast: false
- matrix:
- toolchain:
- - 'arm-gcc'
- - 'esp-idf'
- with:
- build-system: 'cmake'
- toolchain: ${{ matrix.toolchain }}
- build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }}
- one-per-family: true
- upload-artifacts: true
-
- # ---------------------------------------
- # Hardware in the loop (HIL)
- # self-hosted on local VM, for attached hardware checkout HIL_JSON
- # ---------------------------------------
- hil-tinyusb:
- if: github.repository_owner == 'hathach'
- needs: build
- runs-on: [self-hosted, X64, hathach, hardware-in-the-loop]
- steps:
- - name: Clean workspace
- run: |
- echo "Cleaning up previous run"
- rm -rf "${{ github.workspace }}"
- mkdir -p "${{ github.workspace }}"
-
- - name: Checkout TinyUSB
- uses: actions/checkout@v4
- with:
- sparse-checkout: test/hil
-
- - name: Download Artifacts
- uses: actions/download-artifact@v4
- with:
- path: cmake-build
- merge-multiple: true
-
- - name: Test on actual hardware
- run: |
- ls cmake-build/
- python3 test/hil/hil_test.py ${{ env.HIL_JSON }}
-
- # ---------------------------------------
- # Hardware in the loop (HIL)
- # self-hosted by HFP, build with IAR toolchain, for attached hardware checkout test/hil/hfp.json
- # Since IAR Token secret is not passed to forked PR, only build non-forked PR
- # ---------------------------------------
- hil-hfp:
- if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false
- runs-on: [self-hosted, Linux, X64, hifiphile]
- env:
- IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }}
- steps:
- - name: Clean workspace
- run: |
- echo "Cleaning up previous run"
- rm -rf "${{ github.workspace }}"
- mkdir -p "${{ github.workspace }}"
-
- - name: Toolchain version
- run: |
- iccarm --version
-
- - name: Checkout TinyUSB
- uses: actions/checkout@v4
-
- - name: Get build boards
- run: |
- MATRIX_JSON=$(python test/hil/hil_ci_set_matrix.py test/hil/hfp.json)
- BUILD_ARGS=$(echo $MATRIX_JSON | jq -r '.["arm-gcc"] | join(" ")')
- echo "BUILD_ARGS=$BUILD_ARGS"
- echo "BUILD_ARGS=$BUILD_ARGS" >> $GITHUB_ENV
-
- - name: Get Dependencies
- run: python3 tools/get_deps.py $BUILD_ARGS
-
- - name: Build
- run: python3 tools/build.py --toolchain iar $BUILD_ARGS
-
- - name: Test on actual hardware (hardware in the loop)
- run: python3 test/hil/hil_test.py hfp.json
diff --git a/.idea/debugServers/rt1064.xml b/.idea/debugServers/rt1064.xml
index b908b59e2..4fb2fdf6a 100644
--- a/.idea/debugServers/rt1064.xml
+++ b/.idea/debugServers/rt1064.xml
@@ -1,5 +1,5 @@
<component name="DebugServers">
- <jlink-debug-target name="rt1064" uniqueID="9602472b-6ce8-4a2d-9636-1c03b5fcd6da" selected="true">
+ <jlink-debug-target name="rt1064" uniqueID="9602472b-6ce8-4a2d-9636-1c03b5fcd6da">
<debugger version="1">
<debugger kind="GDB" isBundled="true" />
<env />
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 633f7a6ac..6f30ca381 100644
--- a/examples/dual/host_hid_to_device_cdc/src/main.c
+++ b/examples/dual/host_hid_to_device_cdc/src/main.c
@@ -190,7 +190,9 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
// look up new key in previous keys
static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8_t keycode) {
for (uint8_t i = 0; i < 6; i++) {
- if (report->keycode[i] == keycode) return true;
+ if (report->keycode[i] == keycode) {
+ return true;
+ }
}
return false;
@@ -230,7 +232,9 @@ static void process_kbd_report(uint8_t dev_addr, hid_keyboard_report_t const* re
// TODO example skips key released
}
- if (flush) tud_cdc_write_flush();
+ if (flush) {
+ tud_cdc_write_flush();
+ }
prev_report = *report;
}
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 7e593f234..a2a505952 100644
--- a/examples/dual/host_info_to_device_cdc/src/main.c
+++ b/examples/dual/host_info_to_device_cdc/src/main.c
@@ -78,6 +78,22 @@ static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_devi
void led_blinking_task(void);
void cdc_task(void);
+#define cdc_printf(...) \
+ do { \
+ char _tempbuf[256]; \
+ char* _bufptr = _tempbuf; \
+ uint32_t count = (uint32_t) sprintf(_tempbuf, __VA_ARGS__); \
+ while (count > 0) { \
+ uint32_t wr_count = tud_cdc_write(_bufptr, count); \
+ count -= wr_count; \
+ _bufptr += wr_count; \
+ if (count > 0){ \
+ tud_task(); \
+ tud_cdc_write_flush(); \
+ } \
+ } \
+ } while(0)
+
/*------------- MAIN -------------*/
int main(void) {
board_init();
@@ -160,22 +176,6 @@ void cdc_task(void) {
//--------------------------------------------------------------------+
// Host Get device information
//--------------------------------------------------------------------+
-#define cdc_printf(...) \
- do { \
- char _tempbuf[256]; \
- char* _bufptr = _tempbuf; \
- uint32_t count = (uint32_t) sprintf(_tempbuf, __VA_ARGS__); \
- while (count > 0) { \
- uint32_t wr_count = tud_cdc_write(_bufptr, count); \
- count -= wr_count; \
- _bufptr += wr_count; \
- if (count > 0){ \
- tud_task();\
- tud_cdc_write_flush(); \
- } \
- } \
- } while(0)
-
static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_device) {
// Get String descriptor using Sync API
uint16_t serial[64];
@@ -232,12 +232,14 @@ void tuh_enum_descriptor_device_cb(uint8_t daddr, tusb_desc_device_t const* desc
}
void tuh_mount_cb(uint8_t daddr) {
- printf("mounted device %u\r\n", daddr);
+ cdc_printf("mounted device %u\r\n", daddr);
+ tud_cdc_write_flush();
is_print[daddr] = true;
}
void tuh_umount_cb(uint8_t daddr) {
- printf("unmounted device %u\r\n", daddr);
+ cdc_printf("unmounted device %u\r\n", daddr);
+ tud_cdc_write_flush();
is_print[daddr] = false;
}
@@ -249,7 +251,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);
@@ -300,7 +304,9 @@ static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
}
static void print_utf16(uint16_t *temp_buf, size_t buf_len) {
- if ((temp_buf[0] & 0xff) == 0) return; // empty
+ if ((temp_buf[0] & 0xff) == 0) {
+ return;// empty
+ }
size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len);
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len);
diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c
index a751c9c80..6f01d6f45 100644
--- a/examples/host/cdc_msc_hid/src/hid_app.c
+++ b/examples/host/cdc_msc_hid/src/hid_app.c
@@ -29,14 +29,9 @@
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
+#define MAX_REPORT 4
-// If your host terminal support ansi escape code such as TeraTerm
-// it can be use to simulate mouse cursor movement within terminal
-#define USE_ANSI_ESCAPE 0
-
-#define MAX_REPORT 4
-
-static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
+static uint8_t const keycode2ascii[128][2] = {HID_KEYCODE_TO_ASCII};
// Each HID instance can has multiple reports
static struct {
@@ -45,8 +40,8 @@ static struct {
} hid_info[CFG_TUH_HID];
static void process_kbd_report(hid_keyboard_report_t const *report);
-static void process_mouse_report(hid_mouse_report_t const * report);
-static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
+static void process_mouse_report(hid_mouse_report_t const *report);
+static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len);
void hid_app_task(void) {
// nothing to do
@@ -70,7 +65,7 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_re
printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]);
- // By default host stack will use activate boot protocol on supported interface.
+ // By default, host stack will use boot protocol on supported interface.
// Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser)
if (itf_protocol == HID_ITF_PROTOCOL_NONE) {
hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len);
@@ -121,7 +116,7 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
//--------------------------------------------------------------------+
// look up new key in previous keys
-static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8_t keycode) {
+static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode) {
for (uint8_t i = 0; i < 6; i++) {
if (report->keycode[i] == keycode) {
return true;
@@ -130,28 +125,25 @@ static inline bool find_key_in_report(hid_keyboard_report_t const* report, uint8
return false;
}
-static void process_kbd_report(hid_keyboard_report_t const *report)
-{
- static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released
+static void process_kbd_report(hid_keyboard_report_t const *report) {
+ static hid_keyboard_report_t prev_report = {0, 0, {0}};// previous report to check key released
//------------- example code ignore control (non-printable) key affects -------------//
- for(uint8_t i=0; i<6; i++)
- {
- if ( report->keycode[i] )
- {
- if ( find_key_in_report(&prev_report, report->keycode[i]) )
- {
+ for (uint8_t i = 0; i < 6; i++) {
+ if (report->keycode[i]) {
+ if (find_key_in_report(&prev_report, report->keycode[i])) {
// exist in previous report means the current key is holding
- }else
- {
+ } else {
// not existed in previous report means the current key is pressed
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0];
putchar(ch);
- if ( ch == '\r' ) putchar('\n'); // added new line for enter key
+ if (ch == '\r') {
+ putchar('\n');
+ }
- #ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
- fflush(stdout); // flush right away, else nanolib will wait for newline
+ #ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
+ fflush(stdout);// flush right away, else nanolib will wait for newline
#endif
}
}
@@ -166,55 +158,22 @@ static void process_kbd_report(hid_keyboard_report_t const *report)
//--------------------------------------------------------------------+
static void cursor_movement(int8_t x, int8_t y, int8_t wheel) {
-#if USE_ANSI_ESCAPE
- // Move X using ansi escape
- if ( x < 0)
- {
- printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left
- }else if ( x > 0)
- {
- printf(ANSI_CURSOR_FORWARD(%d), x); // move right
- }
-
- // Move Y using ansi escape
- if ( y < 0)
- {
- printf(ANSI_CURSOR_UP(%d), (-y)); // move up
- }else if ( y > 0)
- {
- printf(ANSI_CURSOR_DOWN(%d), y); // move down
- }
-
- // Scroll using ansi escape
- if (wheel < 0)
- {
- printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up
- }else if (wheel > 0)
- {
- printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down
- }
-
- printf("\r\n");
-#else
printf("(%d %d %d)\r\n", x, y, wheel);
-#endif
}
-static void process_mouse_report(hid_mouse_report_t const * report)
-{
- static hid_mouse_report_t prev_report = { 0 };
+static void process_mouse_report(hid_mouse_report_t const *report) {
+ static hid_mouse_report_t prev_report = {0};
- //------------- button state -------------//
+ // button state
uint8_t button_changed_mask = report->buttons ^ prev_report.buttons;
- if ( button_changed_mask & report->buttons)
- {
+ if (button_changed_mask & report->buttons) {
printf(" %c%c%c ",
- report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-',
- report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-',
- report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-');
+ report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-',
+ report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-',
+ report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-');
}
- //------------- cursor movement -------------//
+ // cursor movement
cursor_movement(report->x, report->y, report->wheel);
}
@@ -263,18 +222,23 @@ static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t c
if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) {
switch (rpt_info->usage) {
case HID_USAGE_DESKTOP_KEYBOARD:
- TU_LOG1("HID receive keyboard report\r\n");
+ TU_LOG2("HID receive keyboard report\r\n");
// Assume keyboard follow boot report layout
process_kbd_report((hid_keyboard_report_t const *) report);
break;
case HID_USAGE_DESKTOP_MOUSE:
- TU_LOG1("HID receive mouse report\r\n");
+ TU_LOG2("HID receive mouse report\r\n");
// Assume mouse follow boot report layout
process_mouse_report((hid_mouse_report_t const *) report);
break;
default:
+ printf("report[%u] ", rpt_info->report_id);
+ for (uint8_t i = 0; i < len; i++) {
+ printf("%02X ", report[i]);
+ }
+ printf("\r\n");
break;
}
}
diff --git a/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld b/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld
index 916f11866..c16235586 100644
--- a/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld
+++ b/hw/bsp/stm32wb/boards/stm32wb55nucleo/stm32wb55xx_flash_cm4.ld
@@ -3,21 +3,26 @@
**
** File : stm32wb55xx_flash_cm4.ld
**
-** Abstract : System Workbench Minimal System calls file
+** Author : STM32CubeIDE
**
-** For more information about which c-functions
-** need which of these lowlevel functions
-** please consult the Newlib libc-manual
+** Abstract : Linker script for STM32WB55xx Device
+** 1024Kbytes FLASH
+** 128Kbytes RAM
**
-** Environment : System Workbench for MCU
+** Set heap size, stack size and stack location according
+** to application requirements.
**
-** Distribution: The file is distributed “as is,” without any warranty
+** Set memory bank area and size if external memory is used.
+**
+** Target : STMicroelectronics STM32
+**
+** Distribution: The file is distributed as is without any warranty
** of any kind.
**
*****************************************************************************
** @attention
**
-** Copyright (c) 2019 STMicroelectronics.
+** Copyright (c) 2019-2022 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
@@ -33,7 +38,7 @@ ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20030000; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
-_Min_Heap_Size = 0x400; /* required amount of heap */
+_Min_Heap_Size = 0x400; /* required amount of heap */
_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Specify the memory areas */
@@ -81,14 +86,17 @@ SECTIONS
. = ALIGN(4);
} >FLASH
- .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
+ .ARM.extab :
+ {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
- .preinit_array :
+ .preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
@@ -124,7 +132,6 @@ SECTIONS
_edata = .; /* define a global symbol at data end */
} >RAM1 AT> FLASH
-
/* Uninitialized data section */
. = ALIGN(4);
.bss :
@@ -152,8 +159,6 @@ SECTIONS
. = ALIGN(8);
} >RAM1
-
-
/* Remove information from the standard libraries */
/DISCARD/ :
{
@@ -163,7 +168,15 @@ SECTIONS
}
.ARM.attributes 0 : { *(.ARM.attributes) }
- MAPPING_TABLE (NOLOAD) : { *(MAPPING_TABLE) } >RAM_SHARED
- MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED
- MB_MEM2 (NOLOAD) : { _sMB_MEM2 = . ; *(MB_MEM2) ; _eMB_MEM2 = . ; } >RAM_SHARED
+ MAPPING_TABLE (NOLOAD) : { *(MAPPING_TABLE) } >RAM_SHARED
+ MB_MEM1 (NOLOAD) : { *(MB_MEM1) } >RAM_SHARED
+
+ /* used by the startup to initialize .MB_MEM2 data */
+ _siMB_MEM2 = LOADADDR(.MB_MEM2);
+ .MB_MEM2 :
+ {
+ _sMB_MEM2 = . ;
+ *(MB_MEM2) ;
+ _eMB_MEM2 = . ;
+ } >RAM_SHARED AT> FLASH
}
diff --git a/hw/bsp/stm32wb/family.c b/hw/bsp/stm32wb/family.c
index ba37b7cc3..93aba02fa 100644
--- a/hw/bsp/stm32wb/family.c
+++ b/hw/bsp/stm32wb/family.c
@@ -184,8 +184,7 @@ void HardFault_Handler(void) {
asm("bkpt 1");
}
-// Required by __libc_init_array in startup code if we are compiling using
-// -nostdlib/-nostartfiles.
+// Required by __libc_init_array in startup code if we are compiling using -nostdlib/-nostartfiles.
+void _init(void);
void _init(void) {
-
}
diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c
index 4058857c5..bf245db3f 100644
--- a/src/class/cdc/cdc_host.c
+++ b/src/class/cdc/cdc_host.c
@@ -672,7 +672,7 @@ void cdch_close(uint8_t daddr) {
bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) {
// TODO handle stall response, retry failed transfer ...
- TU_ASSERT(event == XFER_RESULT_SUCCESS);
+ TU_VERIFY(event == XFER_RESULT_SUCCESS);
uint8_t const idx = get_idx_by_ep_addr(daddr, ep_addr);
cdch_interface_t * p_cdc = get_itf(idx);
diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c
index a3cc7d6d7..57e437196 100644
--- a/src/class/hid/hid_host.c
+++ b/src/class/hid/hid_host.c
@@ -444,7 +444,7 @@ bool hidh_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t
hidh_epbuf_t* epbuf = get_hid_epbuf(idx);
if (dir == TUSB_DIR_IN) {
- TU_LOG_DRV(" Get Report callback (%u, %u)\r\n", daddr, idx);
+ TU_LOG_DRV(" [idx=%u] Get Report callback\r\n", idx);
TU_LOG3_MEM(epbuf->epin, xferred_bytes, 2);
tuh_hid_report_received_cb(daddr, idx, epbuf->epin, (uint16_t) xferred_bytes);
} else {
@@ -461,7 +461,9 @@ void hidh_close(uint8_t daddr) {
hidh_interface_t* p_hid = &_hidh_itf[i];
if (p_hid->daddr == daddr) {
TU_LOG_DRV(" HIDh close addr = %u index = %u\r\n", daddr, i);
- if (tuh_hid_umount_cb) tuh_hid_umount_cb(daddr, i);
+ if (tuh_hid_umount_cb) {
+ tuh_hid_umount_cb(daddr, i);
+ }
tu_memclr(p_hid, sizeof(hidh_interface_t));
}
}
diff --git a/src/host/hub.c b/src/host/hub.c
index c87289a14..0b172a596 100644
--- a/src/host/hub.c
+++ b/src/host/hub.c
@@ -201,7 +201,6 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
bool hub_port_get_status_local(uint8_t hub_addr, uint8_t hub_port, hub_port_status_response_t* resp) {
(void) hub_port;
- TU_VERIFY(hub_addr > CFG_TUH_DEVICE_MAX);
hub_interface_t* p_hub = get_hub_itf(hub_addr);
*resp = p_hub->port_status;
return true;
@@ -459,7 +458,8 @@ static void process_new_status(tuh_xfer_t* xfer) {
}
};
hcd_event_handler(&event, false);
- processed = true; // usbh queue status after handled this in (de)enumeration
+ // skip status for attach event, usbh will do it after handled this enumeration
+ processed = (event.event_id == HCD_EVENT_DEVICE_ATTACH);
break;
}
diff --git a/src/host/usbh.c b/src/host/usbh.c
index fbb61e10e..b7d5a05f2 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -34,7 +34,7 @@
#include "hub.h"
//--------------------------------------------------------------------+
-// USBH Configuration
+// Configuration
//--------------------------------------------------------------------+
#ifndef CFG_TUH_TASK_QUEUE_SZ
#define CFG_TUH_TASK_QUEUE_SZ 16
@@ -89,7 +89,7 @@ TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_si
}
//--------------------------------------------------------------------+
-// USBH-HCD common data structure
+// Data Structure
//--------------------------------------------------------------------+
typedef struct {
tuh_bus_info_t bus_info;
@@ -131,8 +131,60 @@ typedef struct {
} usbh_device_t;
+// sum of end device + hub
+#define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB)
+
+// all devices excluding zero-address
+// hub address start from CFG_TUH_DEVICE_MAX+1
+// TODO: hub can has its own simpler struct to save memory
+static usbh_device_t _usbh_devices[TOTAL_DEVICES];
+
+// Mutex for claiming endpoint
+#if OSAL_MUTEX_REQUIRED
+static osal_mutex_def_t _usbh_mutexdef;
+static osal_mutex_t _usbh_mutex;
+#else
+#define _usbh_mutex NULL
+#endif
+
+// Event queue: usbh_int_set() is used as mutex in OS NONE config
+OSAL_QUEUE_DEF(usbh_int_set, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t);
+static osal_queue_t _usbh_q;
+
+// Control transfers: since most controllers do not support multiple control transfers
+// on multiple devices concurrently and control transfers are not used much except for
+// enumeration, we will only execute control transfers one at a time.
+typedef struct {
+ uint8_t* buffer;
+ tuh_xfer_cb_t complete_cb;
+ uintptr_t user_data;
+
+ volatile uint8_t stage;
+ uint8_t daddr;
+ volatile uint16_t actual_len;
+ uint8_t failed_count;
+} usbh_ctrl_xfer_info_t;
+
+typedef struct {
+ uint8_t controller_id; // controller ID
+ uint8_t enumerating_daddr; // device address of the device being enumerated
+ uint8_t attach_debouncing_bm; // bitmask for roothub port attach debouncing
+ tuh_bus_info_t dev0_bus; // bus info for dev0 in enumeration
+ usbh_ctrl_xfer_info_t ctrl_xfer_info; // control transfer
+} usbh_data_t;
+
+static usbh_data_t _usbh_data = {
+ .controller_id = TUSB_INDEX_INVALID_8,
+};
+
+typedef struct {
+ TUH_EPBUF_TYPE_DEF(tusb_control_request_t, request);
+ TUH_EPBUF_DEF(ctrl, CFG_TUH_ENUMERATION_BUFSIZE);
+} usbh_epbuf_t;
+CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf;
+
//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF
+// Class Driver
//--------------------------------------------------------------------+
#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL
#define DRIVER_NAME(_name) _name
@@ -235,71 +287,21 @@ static inline usbh_class_driver_t const *get_driver(uint8_t drv_id) {
}
//--------------------------------------------------------------------+
-// INTERNAL OBJECT & FUNCTION DECLARATION
+// Function Inline and Prototypes
//--------------------------------------------------------------------+
+static bool enum_new_device(hcd_event_t* event);
+static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port);
+static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size);
+static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
-// sum of end device + hub
-#define TOTAL_DEVICES (CFG_TUH_DEVICE_MAX + CFG_TUH_HUB)
-
-// all devices excluding zero-address
-// hub address start from CFG_TUH_DEVICE_MAX+1
-// TODO: hub can has its own simpler struct to save memory
-static usbh_device_t _usbh_devices[TOTAL_DEVICES];
-
-// Mutex for claiming endpoint
-#if OSAL_MUTEX_REQUIRED
- static osal_mutex_def_t _usbh_mutexdef;
- static osal_mutex_t _usbh_mutex;
-#else
- #define _usbh_mutex NULL
-#endif
-
-// Event queue: usbh_int_set() is used as mutex in OS NONE config
-OSAL_QUEUE_DEF(usbh_int_set, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t);
-static osal_queue_t _usbh_q;
-
-// Control transfers: since most controllers do not support multiple control transfers
-// on multiple devices concurrently and control transfers are not used much except for
-// enumeration, we will only execute control transfers one at a time.
-typedef struct {
- uint8_t* buffer;
- tuh_xfer_cb_t complete_cb;
- uintptr_t user_data;
-
- volatile uint8_t stage;
- uint8_t daddr;
- volatile uint16_t actual_len;
- uint8_t failed_count;
-} usbh_ctrl_xfer_info_t;
-
-typedef struct {
- uint8_t controller_id; // controller ID
- uint8_t enumerating_daddr; // device address of the device being enumerated
- uint8_t attach_debouncing_bm; // bitmask for roothub port attach debouncing
- tuh_bus_info_t dev0_bus; // bus info for dev0 in enumeration
- usbh_ctrl_xfer_info_t ctrl_xfer_info; // control transfer
-} usbh_data_t;
-
-static usbh_data_t _usbh_data = {
- .controller_id = TUSB_INDEX_INVALID_8,
-};
-
-typedef struct {
- TUH_EPBUF_TYPE_DEF(tusb_control_request_t, request);
- TUH_EPBUF_DEF(ctrl, CFG_TUH_ENUMERATION_BUFSIZE);
-} usbh_epbuf_t;
-CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf;
-
-//------------- Helper Function -------------//
TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) {
TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL);
return &_usbh_devices[dev_addr-1];
}
-static bool enum_new_device(hcd_event_t* event);
-static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port);
-static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size);
-static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
+TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) {
+ return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX);
+}
TU_ATTR_ALWAYS_INLINE static inline bool queue_event(hcd_event_t const * event, bool in_isr) {
TU_ASSERT(osal_queue_send(_usbh_q, event, in_isr));
@@ -307,10 +309,40 @@ TU_ATTR_ALWAYS_INLINE static inline bool queue_event(hcd_event_t const * event,
return true;
}
+TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage(uint8_t stage) {
+ if (_usbh_data.ctrl_xfer_info.stage != stage) {
+ (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
+ _usbh_data.ctrl_xfer_info.stage = stage;
+ (void) osal_mutex_unlock(_usbh_mutex);
+ }
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send(uint8_t daddr, const uint8_t setup_packet[8]) {
+ const uint8_t rhport = usbh_get_rhport(daddr);
+ const bool ret = hcd_setup_send(rhport, daddr, setup_packet);
+ if (!ret) {
+ _control_set_xfer_stage(CONTROL_STAGE_IDLE);
+ }
+ return ret;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void usbh_device_close(uint8_t rhport, uint8_t daddr) {
+ hcd_device_close(rhport, daddr);
+
+ // abort any ongoing control transfer
+ if (daddr == _usbh_data.ctrl_xfer_info.daddr) {
+ _control_set_xfer_stage(CONTROL_STAGE_IDLE);
+ }
+
+ // invalidate if enumerating
+ if (daddr == _usbh_data.enumerating_daddr) {
+ _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8;
+ }
+}
+
//--------------------------------------------------------------------+
// Device API
//--------------------------------------------------------------------+
-
bool tuh_mounted(uint8_t dev_addr) {
usbh_device_t *dev = get_device(dev_addr);
TU_VERIFY(dev);
@@ -515,7 +547,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
// TODO better to have an separated queue for newly attached devices
if (_usbh_data.enumerating_daddr == TUSB_INDEX_INVALID_8) {
// New device attached and we are ready
- TU_LOG1("[%u:] USBH Device Attach\r\n", event.rhport);
+ TU_LOG_USBH("[%u:] USBH Device Attach\r\n", event.rhport);
_usbh_data.enumerating_daddr = 0; // enumerate new device with address 0
enum_new_device(&event);
} else {
@@ -531,15 +563,15 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
case HCD_EVENT_DEVICE_REMOVE:
TU_LOG_USBH("[%u:%u:%u] USBH DEVICE REMOVED\r\n", event.rhport, event.connection.hub_addr, event.connection.hub_port);
- process_removed_device(event.rhport, event.connection.hub_addr, event.connection.hub_port);
-
- #if CFG_TUH_HUB
- // TODO remove
- if (event.connection.hub_addr != 0 && event.connection.hub_port != 0) {
- // done with hub, waiting for next data on status pipe
- (void) hub_edpt_status_xfer(event.connection.hub_addr);
+ if (_usbh_data.enumerating_daddr == 0 &&
+ event.rhport == _usbh_data.dev0_bus.rhport &&
+ event.connection.hub_addr == _usbh_data.dev0_bus.hub_addr &&
+ event.connection.hub_port == _usbh_data.dev0_bus.hub_port) {
+ // dev0 is unplugged while enumerating (not yet assigned an address)
+ usbh_device_close(_usbh_data.dev0_bus.rhport, 0);
+ } else {
+ process_removed_device(event.rhport, event.connection.hub_addr, event.connection.hub_port);
}
- #endif
break;
case HCD_EVENT_XFER_COMPLETE: {
@@ -547,7 +579,8 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const ep_dir = (uint8_t) tu_edpt_dir(ep_addr);
- TU_LOG_USBH("on EP %02X with %u bytes: %s\r\n", ep_addr, (unsigned int) event.xfer_complete.len, tu_str_xfer_result[event.xfer_complete.result]);
+ TU_LOG_USBH("[:%u] on EP %02X with %u bytes: %s\r\n",
+ event.dev_addr, ep_addr, (unsigned int) event.xfer_complete.len, tu_str_xfer_result[event.xfer_complete.result]);
if (event.dev_addr == 0) {
// device 0 only has control endpoint
@@ -586,7 +619,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
uint8_t drv_id = dev->ep2drv[epnum][ep_dir];
usbh_class_driver_t const* driver = get_driver(drv_id);
if (driver) {
- TU_LOG_USBH("%s xfer callback\r\n", driver->name);
+ TU_LOG_USBH(" %s xfer callback\r\n", driver->name);
driver->xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result,
event.xfer_complete.len);
} else {
@@ -623,23 +656,6 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) {
*((xfer_result_t*) xfer->user_data) = xfer->result;
}
-TU_ATTR_ALWAYS_INLINE static inline void _control_set_xfer_stage(uint8_t stage) {
- if (_usbh_data.ctrl_xfer_info.stage != stage) {
- (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
- _usbh_data.ctrl_xfer_info.stage = stage;
- (void) osal_mutex_unlock(_usbh_mutex);
- }
-}
-
-TU_ATTR_ALWAYS_INLINE static inline bool usbh_setup_send(uint8_t daddr, const uint8_t setup_packet[8]) {
- const uint8_t rhport = usbh_get_rhport(daddr);
- const bool ret = hcd_setup_send(rhport, daddr, setup_packet);
- if (!ret) {
- _control_set_xfer_stage(CONTROL_STAGE_IDLE);
- }
- return ret;
-}
-
// TODO timeout_ms is not supported yet
bool tuh_control_xfer (tuh_xfer_t* xfer) {
TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); // EP0 with setup packet
@@ -1263,28 +1279,13 @@ uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_i
//--------------------------------------------------------------------+
// Detaching
//--------------------------------------------------------------------+
-
-TU_ATTR_ALWAYS_INLINE static inline bool is_hub_addr(uint8_t daddr) {
- return (CFG_TUH_HUB > 0) && (daddr > CFG_TUH_DEVICE_MAX);
-}
-
// a device unplugged from rhport:hub_addr:hub_port
static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port) {
- // if dev0 is unplugged while enumerating (not yet assigned an address)
- if (_usbh_data.enumerating_daddr == 0) {
- const tuh_bus_info_t* dev0_bus = &_usbh_data.dev0_bus;
- if ((rhport == dev0_bus->rhport) && (hub_addr == dev0_bus->hub_addr) && (hub_port == dev0_bus->hub_port)) {
- hcd_device_close(dev0_bus->rhport, 0);
- if (_usbh_data.ctrl_xfer_info.daddr == 0) {
- _control_set_xfer_stage(CONTROL_STAGE_IDLE);
- }
- _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8;
- return;
- }
- }
+ // Find the all devices (star-network) under port that is unplugged
+ #if CFG_TUH_HUB
+ uint8_t removing_hubs[CFG_TUH_HUB] = { 0 };
+ #endif
- //------------- find the all devices (star-network) under port that is unplugged -------------//
- uint32_t removing_hubs = 0;
do {
for (uint8_t dev_id = 0; dev_id < TOTAL_DEVICES; dev_id++) {
usbh_device_t* dev = &_usbh_devices[dev_id];
@@ -1296,10 +1297,13 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub
(hub_port == 0 || dev->bus_info.hub_port == hub_port)) {
TU_LOG_USBH("[%u:%u:%u] unplugged address = %u\r\n", rhport, hub_addr, hub_port, daddr);
+ #if CFG_TUH_HUB
if (is_hub_addr(daddr)) {
TU_LOG_USBH(" is a HUB device %u\r\n", daddr);
- removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX);
- } else {
+ removing_hubs[dev_id - CFG_TUH_DEVICE_MAX] = 1;
+ } else
+ #endif
+ {
// Invoke callback before closing driver (maybe call it later ?)
if (tuh_umount_cb) {
tuh_umount_cb(daddr);
@@ -1314,30 +1318,21 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub
}
}
- hcd_device_close(rhport, daddr);
+ usbh_device_close(rhport, daddr);
clear_device(dev);
-
- // abort ongoing control xfer on this device if any
- if (daddr == _usbh_data.ctrl_xfer_info.daddr) {
- _control_set_xfer_stage(CONTROL_STAGE_IDLE);
- }
-
- if (daddr == _usbh_data.enumerating_daddr) {
- _usbh_data.enumerating_daddr = TUSB_INDEX_INVALID_8;
- }
}
}
- // if removing a hub, we need to remove all of its downstream devices
- #if CFG_TUH_HUB
- if (removing_hubs == 0) {
+#if CFG_TUH_HUB
+ // if a hub is removed, we need to remove all of its downstream devices
+ if (tu_mem_is_zero(removing_hubs, CFG_TUH_HUB)) {
break;
}
// find a marked hub to process
for (uint8_t h_id = 0; h_id < CFG_TUH_HUB; h_id++) {
- if (tu_bit_test(removing_hubs, h_id)) {
- removing_hubs &= ~TU_BIT(h_id);
+ if (removing_hubs[h_id]) {
+ removing_hubs[h_id] = 0;
// update hub_addr and hub_port for next loop
hub_addr = h_id + 1 + CFG_TUH_DEVICE_MAX;
@@ -1345,10 +1340,10 @@ static void process_removed_device(uint8_t rhport, uint8_t hub_addr, uint8_t hub
break;
}
}
- #else
- (void) removing_hubs;
+#else
break;
- #endif
+#endif
+
} while(1);
}
@@ -1469,7 +1464,7 @@ static void process_enumeration(tuh_xfer_t* xfer) {
bool retry = (_usbh_data.enumerating_daddr != TUSB_INDEX_INVALID_8) && (failed_count < ATTEMPT_COUNT_MAX);
if (retry) {
tusb_time_delay_ms_api(ATTEMPT_DELAY_MS); // delay a bit
- TU_LOG1("Enumeration attempt %u/%u\r\n", failed_count+1, ATTEMPT_COUNT_MAX);
+ TU_LOG_USBH("Enumeration attempt %u/%u\r\n", failed_count+1, ATTEMPT_COUNT_MAX);
retry = tuh_control_xfer(xfer);
}
@@ -1560,6 +1555,10 @@ static void process_enumeration(tuh_xfer_t* xfer) {
}
case ENUM_SET_ADDR: {
+ // Due to physical debouncing, some devices can cause multiple attaches (actually reset) without detach event
+ // Force remove currently mounted with the same bus info (rhport, hub addr, hub port) if exists
+ process_removed_device(dev0_bus->rhport, dev0_bus->hub_addr, dev0_bus->hub_port);
+
const tusb_desc_device_t *desc_device = (const tusb_desc_device_t *) _usbh_epbuf.ctrl;
const uint8_t new_addr = enum_get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB);
TU_ASSERT(new_addr != 0,);
@@ -1582,7 +1581,7 @@ static void process_enumeration(tuh_xfer_t* xfer) {
new_dev->addressed = 1;
_usbh_data.enumerating_daddr = new_addr;
- hcd_device_close(dev0_bus->rhport, 0); // close dev0
+ usbh_device_close(dev0_bus->rhport, 0); // close dev0
TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->ep0_size),); // open new control endpoint
diff --git a/tools/get_deps.py b/tools/get_deps.py
index d89c1b2b1..df8dbb6e1 100755
--- a/tools/get_deps.py
+++ b/tools/get_deps.py
@@ -59,7 +59,7 @@ deps_optional = {
'144f1eb7ea8c06512e12f12b27383601c0272410',
'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'],
'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/hathach/Pico-PIO-USB.git',
- '810653f66adadba3e0e4b4b56d5167ac4f7fdbf7',
+ '032a469e79f6a4ba40760d7868e6db26e15002d7',
'rp2040'],
'hw/mcu/renesas/fsp': ['https://github.com/renesas/fsp.git',
'edcc97d684b6f716728a60d7a6fea049d9870bd6',
@@ -122,7 +122,7 @@ deps_optional = {
'5ad9797c54ec3e55eff770fc9b3cd4a1aefc1309',
'stm32u5'],
'hw/mcu/st/cmsis_device_wb': ['https://github.com/STMicroelectronics/cmsis_device_wb.git',
- '9c5d1920dd9fabbe2548e10561d63db829bb744f',
+ 'd6a7fa2e7de084f5e5e47f2ab88b022fe9b50e5a',
'stm32wb'],
'hw/mcu/st/stm32-mfxstm32l152': ['https://github.com/STMicroelectronics/stm32-mfxstm32l152.git',
'7f4389efee9c6a655b55e5df3fceef5586b35f9b',