Merge branch 'master' into fork/HiFiPhile/stm32_cache
This commit is contained in:
@@ -19,13 +19,12 @@ jobs:
|
||||
echo "MATRIX_JSON=$MATRIX_JSON"
|
||||
|
||||
BUILDSYSTEM_TOOLCHAIN=(
|
||||
"cmake aarch64-gcc"
|
||||
"cmake arm-clang"
|
||||
"cmake arm-gcc"
|
||||
"cmake esp-idf"
|
||||
"make aarch64-gcc"
|
||||
"make arm-gcc"
|
||||
"make msp430-gcc"
|
||||
"make riscv-gcc"
|
||||
"make rx-gcc"
|
||||
"cmake msp430-gcc"
|
||||
"cmake riscv-gcc"
|
||||
)
|
||||
|
||||
# only build IAR if not forked PR, since IAR token is not shared
|
||||
@@ -67,7 +66,7 @@ jobs:
|
||||
FAMILY_LARGE=$(jq -n --argjson family "$FAMILY" --argjson resource "$RESOURCE_LARGE" '$family | map(select(IN($resource[])))')
|
||||
FAMILY=$(jq -n --argjson family "$FAMILY" --argjson resource "$RESOURCE_LARGE" '$family | map(select(IN($resource[]) | not))')
|
||||
|
||||
if [[ $toolchain == esp-idf ]]; then
|
||||
if [[ $toolchain == esp-idf || $toolchain == arm-iar ]]; then
|
||||
gen_build_entry "$build_system" "$toolchain" "$FAMILY" "large"
|
||||
else
|
||||
gen_build_entry "$build_system" "$toolchain" "$FAMILY" "medium+"
|
||||
|
60
.github/workflows/build.yml
vendored
60
.github/workflows/build.yml
vendored
@@ -36,11 +36,6 @@ env:
|
||||
HIL_JSON: test/hil/tinyusb.json
|
||||
|
||||
jobs:
|
||||
# ---------------------------------------
|
||||
#
|
||||
# Build
|
||||
#
|
||||
# ---------------------------------------
|
||||
set-matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
@@ -63,28 +58,31 @@ jobs:
|
||||
echo "hil_matrix=$HIL_MATRIX_JSON" >> $GITHUB_OUTPUT
|
||||
|
||||
# ---------------------------------------
|
||||
# Build CMake
|
||||
# Build CMake: only build on push with one-per-family.
|
||||
# Full built is done by CircleCI in PR
|
||||
# ---------------------------------------
|
||||
cmake:
|
||||
if: github.event_name == 'push'
|
||||
needs: set-matrix
|
||||
uses: ./.github/workflows/build_util.yml
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
toolchain:
|
||||
# - 'arm-clang' is built by circle-ci in PR
|
||||
- 'aarch64-gcc'
|
||||
#- 'arm-clang'
|
||||
- 'arm-gcc'
|
||||
- 'esp-idf'
|
||||
- 'msp430-gcc'
|
||||
- 'riscv-gcc'
|
||||
with:
|
||||
build-system: 'cmake'
|
||||
toolchain: ${{ matrix.toolchain }}
|
||||
build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }}
|
||||
one-per-family: ${{ github.event_name == 'push' }}
|
||||
one-per-family: true
|
||||
|
||||
# ---------------------------------------
|
||||
# Build Make (built by circle-ci in PR, only build on push here)
|
||||
# Build Make: only build on push with one-per-family
|
||||
# ---------------------------------------
|
||||
make:
|
||||
if: github.event_name == 'push'
|
||||
@@ -94,36 +92,18 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
toolchain:
|
||||
# 'arm-clang'
|
||||
- 'arm-gcc'
|
||||
- 'aarch64-gcc'
|
||||
#- 'arm-clang'
|
||||
- 'arm-gcc'
|
||||
- 'msp430-gcc'
|
||||
- 'riscv-gcc'
|
||||
- 'rx-gcc'
|
||||
- 'esp-idf'
|
||||
with:
|
||||
build-system: 'make'
|
||||
toolchain: ${{ matrix.toolchain }}
|
||||
build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)[matrix.toolchain]) }}
|
||||
one-per-family: true
|
||||
|
||||
# ---------------------------------------
|
||||
# Build Make on Windows/MacOS
|
||||
# ---------------------------------------
|
||||
make-os:
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/build_util.yml
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, macos-latest]
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
build-system: 'make'
|
||||
toolchain: 'arm-gcc'
|
||||
build-args: '["stm32h7"]'
|
||||
one-per-family: true
|
||||
|
||||
# ---------------------------------------
|
||||
# Build IAR
|
||||
# Since IAR Token secret is not passed to forked PR, only build non-forked PR with make.
|
||||
@@ -146,6 +126,23 @@ jobs:
|
||||
build-args: ${{ toJSON(fromJSON(needs.set-matrix.outputs.json)['arm-iar']) }}
|
||||
one-per-family: true
|
||||
|
||||
# ---------------------------------------
|
||||
# Build Make on Windows/MacOS
|
||||
# ---------------------------------------
|
||||
make-os:
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/build_util.yml
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, macos-latest]
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
build-system: 'make'
|
||||
toolchain: 'arm-gcc'
|
||||
build-args: '["stm32h7"]'
|
||||
one-per-family: true
|
||||
|
||||
# ---------------------------------------
|
||||
# Zephyr
|
||||
# ---------------------------------------
|
||||
@@ -168,14 +165,9 @@ jobs:
|
||||
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' &&
|
||||
|
@@ -31,6 +31,13 @@ Notable contributors
|
||||
- Most features development
|
||||
|
||||
|
||||
`Heiko Kuester <https://github.com/IngHK>`__
|
||||
--------------------------------------------
|
||||
|
||||
- Add CH34x and PL2303 support (CDC host)
|
||||
- Improve FTDI and CP210x support (CDC host)
|
||||
|
||||
|
||||
`Hristo Gochkov <https://github.com/me-no-dev>`__
|
||||
-------------------------------------------------
|
||||
|
||||
|
@@ -74,7 +74,7 @@ Host Stack
|
||||
- Human Interface Device (HID): Keyboard, Mouse, Generic
|
||||
- Mass Storage Class (MSC)
|
||||
- Communication Device Class: CDC-ACM
|
||||
- Vendor serial over USB: FTDI, CP210x, CH34x
|
||||
- Vendor serial over USB: FTDI, CP210x, CH34x, PL2303
|
||||
- Hub with multiple-level support
|
||||
|
||||
Similar to the Device Stack, if you have a special requirement, ``usbh_app_driver_get_cb()`` can be used to write your own class driver without modifying the stack.
|
||||
|
@@ -5,12 +5,12 @@ Getting Started
|
||||
Add TinyUSB to your project
|
||||
---------------------------
|
||||
|
||||
It is relatively simple to incorporate tinyusb to your project
|
||||
To incorporate tinyusb to your project
|
||||
|
||||
* Copy or ``git submodule`` this repo into your project in a subfolder. Let's say it is ``your_project/tinyusb``
|
||||
* Add all the ``.c`` in the ``tinyusb/src`` folder to your project
|
||||
* Add ``your_project/tinyusb/src`` to your include path. Also make sure your current include path also contains the configuration file ``tusb_config.h``.
|
||||
* Make sure all required macros are all defined properly in ``tusb_config.h`` (configure file in demo application is sufficient, but you need to add a few more such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS`` since they are passed by IDE/compiler to maintain a unique configure for all boards).
|
||||
* Make sure all required macros are all defined properly in ``tusb_config.h`` (configure file in demo application is sufficient, but you need to add a few more such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS`` since they are passed by make/cmake to maintain a unique configure for all boards).
|
||||
* If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all **tud descriptor** callbacks for the stack to work.
|
||||
* Add ``tusb_init(rhport, role)`` call to your reset initialization code.
|
||||
* Call ``tusb_int_handler(rhport, in_isr)`` in your USB IRQ Handler
|
||||
@@ -75,24 +75,36 @@ The hardware code is located in ``hw/bsp`` folder, and is organized by family/bo
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd examples/device/cdc_msc
|
||||
$ make BOARD=raspberry_pi_pico get-deps
|
||||
$ make BOARD=feather_nrf52840_express get-deps
|
||||
|
||||
You only need to do this once per family. Check out `complete list of dependencies and their designated path here <dependencies.rst>`_
|
||||
|
||||
Build
|
||||
^^^^^
|
||||
Build Examples
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
To build example, first change directory to an example folder.
|
||||
Examples support make and cmake build system for most MCUs, however some MCU families such as espressif or rp2040 only support cmake. First change directory to an example folder.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ cd examples/device/cdc_msc
|
||||
|
||||
Then compile with ``make BOARD={board_name} all`` , for example
|
||||
Then compile with make or cmake
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ make BOARD=raspberry_pi_pico all
|
||||
$ # make
|
||||
$ make BOARD=feather_nrf52840_express all
|
||||
|
||||
$ # cmake
|
||||
$ mkdir build && cd build
|
||||
$ cmake -DBOARD=raspberry_pi_pico ..
|
||||
$ make
|
||||
|
||||
To list all available targets with cmake
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ cmake --build . --target help
|
||||
|
||||
Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``99-tinyusb.rules`` and reload your udev is good to go
|
||||
|
||||
@@ -104,20 +116,24 @@ Note: some examples especially those that uses Vendor class (e.g webUSB) may req
|
||||
RootHub Port Selection
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``PORT=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use:
|
||||
If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``RHPORT_DEVICE=x`` or ``RHPORT_HOST=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ make BOARD=stm32f746disco PORT=1 all
|
||||
$ make BOARD=stm32f746disco RHPORT_DEVICE=1 all
|
||||
|
||||
$ cmake -DBOARD=stm32f746disco -DRHPORT_DEVICE=1 ..
|
||||
|
||||
Port Speed
|
||||
~~~~~~~~~~
|
||||
|
||||
A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option ``SPEED=full/high`` e.g To force F723 operate at full instead of default high speed
|
||||
A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option ``RHPORT_DEVICE_SPEED=OPT_MODE_FULL/HIGH_SPEED/`` or ``RHPORT_HOST_SPEED=OPT_MODE_FULL/HIGH_SPEED/`` e.g To force F723 operate at full instead of default high speed
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ make BOARD=stm32f746disco SPEED=full all
|
||||
$ make BOARD=stm32f746disco RHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED all
|
||||
|
||||
$ cmake -DBOARD=stm32f746disco -DRHPORT_DEVICE_SPEED=OPT_MODE_FULL_SPEED ..
|
||||
|
||||
Size Analysis
|
||||
~~~~~~~~~~~~~
|
||||
@@ -137,6 +153,8 @@ To compile for debugging add ``DEBUG=1``\ , for example
|
||||
|
||||
$ make BOARD=feather_nrf52840_express DEBUG=1 all
|
||||
|
||||
$ cmake -DBOARD=feather_nrf52840_express -DCMAKE_BUILD_TYPE=Debug ..
|
||||
|
||||
Log
|
||||
~~~
|
||||
|
||||
@@ -146,6 +164,8 @@ Should you have an issue running example and/or submitting an bug report. You co
|
||||
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 all
|
||||
|
||||
$ cmake -DBOARD=feather_nrf52840_express -DLOG=2 ..
|
||||
|
||||
Logger
|
||||
~~~~~~
|
||||
|
||||
@@ -169,6 +189,9 @@ By default log message is printed via on-board UART which is slow and take lots
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all
|
||||
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all
|
||||
|
||||
$ cmake -DBOARD=feather_nrf52840_express -DLOG=2 -DLOGGER=rtt ..
|
||||
$ cmake -DBOARD=feather_nrf52840_express -DLOG=2 -DLOGGER=swo ..
|
||||
|
||||
Flash
|
||||
^^^^^
|
||||
|
||||
@@ -179,11 +202,15 @@ Flash
|
||||
$ make BOARD=feather_nrf52840_express flash
|
||||
$ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash
|
||||
|
||||
Since jlink can be used with most of the boards, there is also ``flash-jlink`` target for your convenience.
|
||||
Since jlink/openocd can be used with most of the boards, there is also ``flash-jlink/openocd`` (make) and ``EXAMPLE-jlink/openocd`` target for your convenience. Note for stm32 board with stlink, you can use ``flash-stlink`` target as well.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ make BOARD=feather_nrf52840_express flash-jlink
|
||||
$ make BOARD=feather_nrf52840_express flash-openocd
|
||||
|
||||
$ cmake --build . --target cdc_msc-jlink
|
||||
$ cmake --build . --target cdc_msc-openocd
|
||||
|
||||
Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with ``uf2`` target
|
||||
|
||||
@@ -191,17 +218,18 @@ Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can
|
||||
|
||||
$ make BOARD=feather_nrf52840_express all uf2
|
||||
|
||||
$ cmake --build . --target cdc_msc-uf2
|
||||
|
||||
IAR Support
|
||||
-----------
|
||||
^^^^^^^^^^^
|
||||
|
||||
Use project connection
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
IAR Project Connection files are provided to import TinyUSB stack into your project.
|
||||
|
||||
* A buildable project of your MCU need to be created in advance.
|
||||
|
||||
|
||||
* Take example of STM32F0:
|
||||
|
||||
- You need ``stm32l0xx.h``, ``startup_stm32f0xx.s``, ``system_stm32f0xx.c``.
|
||||
@@ -212,15 +240,13 @@ IAR Project Connection files are provided to import TinyUSB stack into your proj
|
||||
Click ``New Group ...``, name it to ``TUSB``, Click ``Add Variable ...``, name it to ``TUSB_DIR``, change it's value to the path of your TinyUSB stack,
|
||||
for example ``C:\\tinyusb``
|
||||
|
||||
Import stack only
|
||||
~~~~~~~~~~~~~~~~~
|
||||
**Import stack only**
|
||||
|
||||
1. Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\tools\\iar_template.ipcf``.
|
||||
Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\tools\\iar_template.ipcf``.
|
||||
|
||||
Run examples
|
||||
~~~~~~~~~~~~
|
||||
**Run examples**
|
||||
|
||||
1. (Python3 is needed) Run ``iar_gen.py`` to generate .ipcf files of examples:
|
||||
1. Run ``iar_gen.py`` to generate .ipcf files of examples:
|
||||
|
||||
.. code-block::
|
||||
|
||||
@@ -230,8 +256,8 @@ Run examples
|
||||
2. Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\examples\\(.ipcf of example)``.
|
||||
For example ``C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf``
|
||||
|
||||
Native CMake support (9.50.1+)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Native CMake support
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
With 9.50.1 release, IAR added experimental native CMake support (strangely not mentioned in public release note). Now it's possible to import CMakeLists.txt then build and debug as a normal project.
|
||||
|
||||
|
@@ -123,27 +123,24 @@ endif
|
||||
ifeq (${MAX3421_HOST},1)
|
||||
SRC_C += src/portable/analog/max3421/hcd_max3421.c
|
||||
CFLAGS += -DCFG_TUH_MAX3421=1
|
||||
CMAKE_DEFSYM += -DMAX3421_HOST=1
|
||||
endif
|
||||
|
||||
# Log level is mapped to TUSB DEBUG option
|
||||
ifneq ($(LOG),)
|
||||
CMAKE_DEFSYM += -DLOG=$(LOG)
|
||||
CFLAGS += -DCFG_TUSB_DEBUG=$(LOG)
|
||||
endif
|
||||
|
||||
# Logger: default is uart, can be set to rtt or swo
|
||||
ifneq ($(LOGGER),)
|
||||
CMAKE_DEFSYM += -DLOGGER=$(LOGGER)
|
||||
endif
|
||||
|
||||
ifeq ($(LOGGER),rtt)
|
||||
CFLAGS += -DLOGGER_RTT -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
|
||||
RTT_SRC = lib/SEGGER_RTT
|
||||
INC += $(TOP)/$(RTT_SRC)/RTT
|
||||
SRC_C += $(RTT_SRC)/RTT/SEGGER_RTT.c
|
||||
else ifeq ($(LOGGER),swo)
|
||||
CFLAGS += -DLOGGER_RTT
|
||||
#CFLAGS += -DSEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL
|
||||
INC += $(TOP)/$(lib/SEGGER_RTT)/RTT
|
||||
SRC_C += $(lib/SEGGER_RTT)/RTT/SEGGER_RTT.c
|
||||
endif
|
||||
ifeq ($(LOGGER),swo)
|
||||
CFLAGS += -DLOGGER_SWO
|
||||
else
|
||||
CFLAGS += -DLOGGER_UART
|
||||
endif
|
||||
|
||||
# CPU specific flags
|
||||
|
@@ -39,7 +39,7 @@
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
// ESP-IDF need "freertos/" prefix in include path.
|
||||
// CFG_TUSB_OS_INC_PATH should be defined accordingly.
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -158,17 +158,16 @@ int main(void)
|
||||
xTaskCreate(audio_task, "audio", AUDIO_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
|
||||
#endif
|
||||
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
// only start scheduler for non-espressif mcu
|
||||
#ifndef ESP_PLATFORM
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
void app_main(void)
|
||||
{
|
||||
#ifdef ESP_PLATFORM
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
#endif
|
||||
|
@@ -59,7 +59,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
|
@@ -38,7 +38,7 @@
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
// ESP-IDF need "freertos/" prefix in include path.
|
||||
// CFG_TUSB_OS_INC_PATH should be defined accordingly.
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -132,15 +132,15 @@ int main(void)
|
||||
xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
|
||||
#endif
|
||||
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
// only start scheduler for non-espressif mcu
|
||||
#ifndef ESP_PLATFORM
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
|
@@ -49,25 +49,34 @@ int main(void) {
|
||||
while (1) {
|
||||
uint32_t interval_ms = board_button_read() ? BLINK_PRESSED : BLINK_UNPRESSED;
|
||||
|
||||
int ch = board_getchar();
|
||||
if (ch > 0) {
|
||||
board_putchar(ch);
|
||||
#ifndef LOGGER_UART
|
||||
board_uart_write(&ch, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Blink and print every interval ms
|
||||
if (!(board_millis() - start_ms < interval_ms)) {
|
||||
board_uart_write(HELLO_STR, strlen(HELLO_STR));
|
||||
|
||||
start_ms = board_millis();
|
||||
|
||||
if (ch < 0) {
|
||||
// skip if echoing
|
||||
printf(HELLO_STR);
|
||||
|
||||
#ifndef LOGGER_UART
|
||||
board_uart_write(HELLO_STR, strlen(HELLO_STR));
|
||||
#endif
|
||||
}
|
||||
|
||||
board_led_write(led_state);
|
||||
led_state = 1 - led_state; // toggle
|
||||
}
|
||||
|
||||
// echo
|
||||
uint8_t ch;
|
||||
if (board_uart_read(&ch, 1) > 0) {
|
||||
board_uart_write(&ch, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
|
@@ -44,7 +44,7 @@
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
|
@@ -98,27 +98,33 @@ void tud_umount_cb(void) {
|
||||
blink_interval_ms = BLINK_NOT_MOUNTED;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USB CDC
|
||||
//--------------------------------------------------------------------+
|
||||
static void cdc_task(void) {
|
||||
uint8_t itf;
|
||||
|
||||
for (itf = 0; itf < CFG_TUD_CDC; itf++) {
|
||||
for (uint8_t itf = 0; itf < CFG_TUD_CDC; itf++) {
|
||||
// connected() check for DTR bit
|
||||
// Most but not all terminal client set this when making connection
|
||||
// if ( tud_cdc_n_connected(itf) )
|
||||
{
|
||||
if (tud_cdc_n_available(itf)) {
|
||||
uint8_t buf[64];
|
||||
|
||||
uint32_t count = tud_cdc_n_read(itf, buf, sizeof(buf));
|
||||
|
||||
// echo back to both serial ports
|
||||
echo_serial_port(0, buf, count);
|
||||
echo_serial_port(1, buf, count);
|
||||
}
|
||||
|
||||
// Press on-board button to send Uart status notification
|
||||
static uint32_t btn_prev = 0;
|
||||
static cdc_notify_uart_state_t uart_state = { .value = 0 };
|
||||
const uint32_t btn = board_button_read();
|
||||
if (!btn_prev && btn) {
|
||||
uart_state.dsr ^= 1;
|
||||
tud_cdc_notify_uart_state(&uart_state);
|
||||
}
|
||||
btn_prev = btn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -97,6 +97,8 @@
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_VENDOR 0
|
||||
|
||||
#define CFG_TUD_CDC_NOTIFY 1 // Enable use of notification endpoint
|
||||
|
||||
// CDC FIFO size of TX and RX
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
|
@@ -42,8 +42,7 @@
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
tusb_desc_device_t const desc_device =
|
||||
{
|
||||
tusb_desc_device_t const desc_device = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = USB_BCD,
|
||||
@@ -68,16 +67,14 @@ tusb_desc_device_t const desc_device =
|
||||
|
||||
// Invoked when received GET DEVICE DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
uint8_t const * tud_descriptor_device_cb(void)
|
||||
{
|
||||
uint8_t const *tud_descriptor_device_cb(void) {
|
||||
return (uint8_t const *) &desc_device;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Configuration Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
ITF_NUM_CDC_0 = 0,
|
||||
ITF_NUM_CDC_0_DATA,
|
||||
ITF_NUM_CDC_1,
|
||||
@@ -130,36 +127,32 @@ enum
|
||||
#define EPNUM_CDC_1_IN 0x84
|
||||
#endif
|
||||
|
||||
uint8_t const desc_fs_configuration[] =
|
||||
{
|
||||
uint8_t const desc_fs_configuration[] = {
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 16, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 64),
|
||||
|
||||
// 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 16, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 64),
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
|
||||
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
uint8_t const desc_hs_configuration[] = {
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// 1st CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 8, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_0, 4, EPNUM_CDC_0_NOTIF, 16, EPNUM_CDC_0_OUT, EPNUM_CDC_0_IN, 512),
|
||||
|
||||
// 2nd CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 8, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_1, 4, EPNUM_CDC_1_NOTIF, 16, EPNUM_CDC_1_OUT, EPNUM_CDC_1_IN, 512),
|
||||
};
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier = {
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = USB_BCD,
|
||||
@@ -177,34 +170,31 @@ tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
uint8_t const *tud_descriptor_device_qualifier_cb(void) {
|
||||
return (uint8_t const *) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) {
|
||||
(void) index;// for multiple configurations
|
||||
|
||||
// if link speed is high return fullspeed config, and vice versa
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration;
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration : desc_hs_configuration;
|
||||
}
|
||||
|
||||
#endif // highspeed
|
||||
#endif// highspeed
|
||||
|
||||
// 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)
|
||||
{
|
||||
uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Although we are highspeed, host may be fullspeed.
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
|
||||
#else
|
||||
return desc_fs_configuration;
|
||||
#endif
|
||||
@@ -223,8 +213,7 @@ enum {
|
||||
};
|
||||
|
||||
// array of pointer to string descriptors
|
||||
char const *string_desc_arr[] =
|
||||
{
|
||||
char const *string_desc_arr[] = {
|
||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||
"TinyUSB", // 1: Manufacturer
|
||||
"TinyUSB Device", // 2: Product
|
||||
@@ -254,14 +243,14 @@ 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++ ) {
|
||||
@@ -272,6 +261,5 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
|
||||
|
||||
return _desc_str;
|
||||
}
|
||||
|
@@ -119,6 +119,16 @@ void cdc_task(void) {
|
||||
tud_cdc_write(buf, count);
|
||||
tud_cdc_write_flush();
|
||||
}
|
||||
|
||||
// Press on-board button to send Uart status notification
|
||||
static uint32_t btn_prev = 0;
|
||||
static cdc_notify_uart_state_t uart_state = { .value = 0 };
|
||||
const uint32_t btn = board_button_read();
|
||||
if (!btn_prev && btn) {
|
||||
uart_state.dsr ^= 1;
|
||||
tud_cdc_notify_uart_state(&uart_state);
|
||||
}
|
||||
btn_prev = btn;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -184,7 +184,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buff
|
||||
}
|
||||
|
||||
// Check for overflow of offset + bufsize
|
||||
if (offset + bufsize > DISK_BLOCK_SIZE) {
|
||||
if (lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@@ -87,7 +87,7 @@
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
|
||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||
#endif
|
||||
|
||||
//------------- CLASS -------------//
|
||||
@@ -97,6 +97,8 @@
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_VENDOR 0
|
||||
|
||||
#define CFG_TUD_CDC_NOTIFY 1 // Enable use of notification endpoint
|
||||
|
||||
// CDC FIFO size of TX and RX
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
|
@@ -52,7 +52,6 @@ tusb_desc_device_t const desc_device = {
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = USB_VID,
|
||||
@@ -131,7 +130,7 @@ uint8_t const desc_fs_configuration[] = {
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64),
|
||||
@@ -146,7 +145,7 @@ uint8_t const desc_hs_configuration[] = {
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
|
||||
@@ -197,7 +196,6 @@ uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) {
|
||||
|
||||
#endif // highspeed
|
||||
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
@@ -256,14 +254,14 @@ 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++ ) {
|
||||
@@ -274,6 +272,5 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
|
||||
|
||||
return _desc_str;
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define USBD_STACK_SIZE 4096
|
||||
#else
|
||||
// Increase stack size when debug log is enabled
|
||||
@@ -72,7 +72,7 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
|
||||
static void usb_device_task(void *param);
|
||||
void led_blinking_task(void* param);
|
||||
void cdc_task(void *params);
|
||||
|
||||
extern void msc_disk_init(void);
|
||||
//--------------------------------------------------------------------+
|
||||
// Main
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -91,15 +91,15 @@ int main(void) {
|
||||
xTaskCreate(cdc_task, "cdc", CDC_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL);
|
||||
#endif
|
||||
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#ifndef ESP_PLATFORM
|
||||
// only start scheduler for non-espressif mcu
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
@@ -123,6 +123,7 @@ static void usb_device_task(void *param) {
|
||||
board_init_after_tusb();
|
||||
}
|
||||
|
||||
msc_disk_init();
|
||||
// RTOS forever loop
|
||||
while (1) {
|
||||
// put this thread to waiting state until there is new events
|
||||
@@ -188,6 +189,16 @@ void cdc_task(void *params) {
|
||||
}
|
||||
|
||||
tud_cdc_write_flush();
|
||||
|
||||
// Press on-board button to send Uart status notification
|
||||
static uint32_t btn_prev = 0;
|
||||
static cdc_notify_uart_state_t uart_state = { .value = 0 };
|
||||
const uint32_t btn = board_button_read();
|
||||
if (!btn_prev && btn) {
|
||||
uart_state.dsr ^= 1;
|
||||
tud_cdc_notify_uart_state(&uart_state);
|
||||
}
|
||||
btn_prev = btn;
|
||||
}
|
||||
|
||||
// For ESP32-Sx this delay is essential to allow idle how to run and reset watchdog
|
||||
|
@@ -28,6 +28,37 @@
|
||||
|
||||
#if CFG_TUD_MSC
|
||||
|
||||
// Use async IO in example or not
|
||||
#define CFG_EXAMPLE_MSC_ASYNC_IO 1
|
||||
|
||||
// Simulate read/write operation delay
|
||||
#define CFG_EXAMPLE_MSC_IO_DELAY_MS 0
|
||||
|
||||
#if CFG_EXAMPLE_MSC_ASYNC_IO
|
||||
#define IO_STACK_SIZE configMINIMAL_STACK_SIZE
|
||||
|
||||
typedef struct {
|
||||
uint8_t lun;
|
||||
bool is_read;
|
||||
uint32_t lba;
|
||||
uint32_t offset;
|
||||
void* buffer;
|
||||
uint32_t bufsize;
|
||||
} io_ops_t;
|
||||
|
||||
QueueHandle_t io_queue;
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
uint8_t io_queue_buf[sizeof(io_ops_t)];
|
||||
StaticQueue_t io_queue_static;
|
||||
StackType_t io_stack[IO_STACK_SIZE];
|
||||
StaticTask_t io_taskdef;
|
||||
#endif
|
||||
|
||||
static void io_task(void *params);
|
||||
#endif
|
||||
|
||||
void msc_disk_init(void);
|
||||
|
||||
// whether host does safe-eject
|
||||
static bool ejected = false;
|
||||
|
||||
@@ -40,8 +71,7 @@ static bool ejected = false;
|
||||
If you find any bugs or get any questions, feel free to file an\r\n\
|
||||
issue at github.com/hathach/tinyusb"
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount
|
||||
DISK_BLOCK_SIZE = 512
|
||||
};
|
||||
@@ -119,16 +149,52 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
|
||||
README_CONTENTS
|
||||
};
|
||||
|
||||
#if CFG_EXAMPLE_MSC_ASYNC_IO
|
||||
void msc_disk_init() {
|
||||
|
||||
#if configSUPPORT_STATIC_ALLOCATION
|
||||
io_queue = xQueueCreateStatic(1, sizeof(io_ops_t), io_queue_buf, &io_queue_static);
|
||||
xTaskCreateStatic(io_task, "io", IO_STACK_SIZE, NULL, 2, io_stack, &io_taskdef);
|
||||
#else
|
||||
io_queue = xQueueCreate(1, sizeof(io_ops_t));
|
||||
xTaskCreate(io_task, "io", IO_STACK_SIZE, NULL, 2, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void io_task(void *params) {
|
||||
(void) params;
|
||||
io_ops_t io_ops;
|
||||
while (1) {
|
||||
if (xQueueReceive(io_queue, &io_ops, portMAX_DELAY)) {
|
||||
const uint8_t* addr = msc_disk[io_ops.lba] + io_ops.offset;
|
||||
int32_t nbytes = io_ops.bufsize;
|
||||
if (io_ops.is_read) {
|
||||
memcpy(io_ops.buffer, addr, io_ops.bufsize);
|
||||
} else {
|
||||
#ifndef CFG_EXAMPLE_MSC_READONLY
|
||||
memcpy((uint8_t*) addr, io_ops.buffer, io_ops.bufsize);
|
||||
#else
|
||||
nbytes = -1; // failed to write
|
||||
#endif
|
||||
}
|
||||
|
||||
tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS);
|
||||
tud_msc_async_io_done(nbytes, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
void msc_disk_init() {}
|
||||
#endif
|
||||
|
||||
// Invoked when received SCSI_CMD_INQUIRY
|
||||
// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
|
||||
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
|
||||
{
|
||||
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) {
|
||||
(void) lun;
|
||||
|
||||
const char vid[] = "TinyUSB";
|
||||
const char pid[] = "Mass Storage";
|
||||
const char rev[] = "1.0";
|
||||
|
||||
memcpy(vendor_id , vid, strlen(vid));
|
||||
memcpy(product_id , pid, strlen(pid));
|
||||
memcpy(product_rev, rev, strlen(rev));
|
||||
@@ -136,8 +202,7 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16
|
||||
|
||||
// Invoked when received Test Unit Ready command.
|
||||
// return true allowing host to read/write this LUN e.g SD card inserted
|
||||
bool tud_msc_test_unit_ready_cb(uint8_t lun)
|
||||
{
|
||||
bool tud_msc_test_unit_ready_cb(uint8_t lun) {
|
||||
(void) lun;
|
||||
|
||||
// RAM disk is ready until ejected
|
||||
@@ -152,10 +217,8 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun)
|
||||
|
||||
// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
|
||||
// Application update block count and block size
|
||||
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* 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;
|
||||
}
|
||||
@@ -163,18 +226,14 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz
|
||||
// Invoked when received Start Stop Unit command
|
||||
// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
|
||||
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
|
||||
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
|
||||
{
|
||||
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) {
|
||||
(void) lun;
|
||||
(void) power_condition;
|
||||
|
||||
if ( load_eject )
|
||||
{
|
||||
if (start)
|
||||
{
|
||||
if (load_eject) {
|
||||
if (start) {
|
||||
// load disk storage
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
// unload disk storage
|
||||
ejected = true;
|
||||
}
|
||||
@@ -185,90 +244,107 @@ 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 TUD_MSC_RET_ERROR;
|
||||
}
|
||||
|
||||
// Check for overflow of offset + bufsize
|
||||
if ( offset + bufsize > DISK_BLOCK_SIZE ) {
|
||||
return -1;
|
||||
if (lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE) {
|
||||
return TUD_MSC_RET_ERROR;
|
||||
}
|
||||
|
||||
uint8_t const* addr = msc_disk[lba] + offset;
|
||||
memcpy(buffer, addr, bufsize);
|
||||
#if CFG_EXAMPLE_MSC_ASYNC_IO
|
||||
io_ops_t io_ops = {.is_read = true, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize};
|
||||
|
||||
return (int32_t) bufsize;
|
||||
// Send IO operation to IO task
|
||||
TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS);
|
||||
|
||||
return TUD_MSC_RET_ASYNC;
|
||||
#else
|
||||
uint8_t const *addr = msc_disk[lba] + offset;
|
||||
memcpy(buffer, addr, bufsize);
|
||||
return bufsize;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool tud_msc_is_writable_cb (uint8_t lun)
|
||||
{
|
||||
bool tud_msc_is_writable_cb (uint8_t lun) {
|
||||
(void) lun;
|
||||
|
||||
#ifdef CFG_EXAMPLE_MSC_READONLY
|
||||
#ifdef CFG_EXAMPLE_MSC_READONLY
|
||||
return false;
|
||||
#else
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
(void) lun;
|
||||
|
||||
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) {
|
||||
// out of ramdisk
|
||||
if ( lba >= DISK_BLOCK_NUM ) return -1;
|
||||
if (lba >= DISK_BLOCK_NUM) {
|
||||
return TUD_MSC_RET_ERROR;
|
||||
}
|
||||
|
||||
#ifndef CFG_EXAMPLE_MSC_READONLY
|
||||
uint8_t* addr = msc_disk[lba] + offset;
|
||||
// Check for overflow of offset + bufsize
|
||||
if (lba * DISK_BLOCK_SIZE + offset + bufsize > DISK_BLOCK_NUM * DISK_BLOCK_SIZE) {
|
||||
return TUD_MSC_RET_ERROR;
|
||||
}
|
||||
|
||||
#ifdef CFG_EXAMPLE_MSC_READONLY
|
||||
(void) lun;
|
||||
(void) buffer;
|
||||
return bufsize;
|
||||
#endif
|
||||
|
||||
#if CFG_EXAMPLE_MSC_ASYNC_IO
|
||||
io_ops_t io_ops = {.is_read = false, .lun = lun, .lba = lba, .offset = offset, .buffer = buffer, .bufsize = bufsize};
|
||||
|
||||
// Send IO operation to IO task
|
||||
TU_ASSERT(xQueueSend(io_queue, &io_ops, 0) == pdPASS);
|
||||
|
||||
return TUD_MSC_RET_ASYNC;
|
||||
#else
|
||||
uint8_t *addr = msc_disk[lba] + offset;
|
||||
memcpy(addr, buffer, bufsize);
|
||||
#else
|
||||
(void) lba; (void) offset; (void) buffer;
|
||||
#endif
|
||||
tusb_time_delay_ms_api(CFG_EXAMPLE_MSC_IO_DELAY_MS);
|
||||
|
||||
return (int32_t) bufsize;
|
||||
return bufsize;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Callback invoked when received an SCSI command not in built-in list below
|
||||
// - 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)
|
||||
{
|
||||
int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize) {
|
||||
// read10 & write10 has their own callback and MUST not be handled here
|
||||
|
||||
void const* response = NULL;
|
||||
void const *response = NULL;
|
||||
int32_t resplen = 0;
|
||||
|
||||
// most scsi handled is input
|
||||
bool in_xfer = true;
|
||||
|
||||
switch (scsi_cmd[0])
|
||||
{
|
||||
switch (scsi_cmd[0]) {
|
||||
default:
|
||||
// Set Sense = Invalid Command Operation
|
||||
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
|
||||
|
||||
// negative means error -> tinyusb could stall and/or response with failed status
|
||||
resplen = -1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
// return resplen must not larger than bufsize
|
||||
if ( resplen > bufsize ) resplen = bufsize;
|
||||
if (resplen > bufsize) { resplen = bufsize; }
|
||||
|
||||
if ( response && (resplen > 0) )
|
||||
{
|
||||
if(in_xfer)
|
||||
{
|
||||
if (response && (resplen > 0)) {
|
||||
if (in_xfer) {
|
||||
memcpy(buffer, response, (size_t) resplen);
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
// SCSI output
|
||||
}
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
@@ -104,6 +104,8 @@
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_VENDOR 0
|
||||
|
||||
#define CFG_TUD_CDC_NOTIFY 1 // Enable use of notification endpoint
|
||||
|
||||
// CDC FIFO size of TX and RX
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
|
@@ -52,7 +52,6 @@ tusb_desc_device_t const desc_device = {
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = USB_VID,
|
||||
@@ -131,7 +130,7 @@ uint8_t const desc_fs_configuration[] =
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64),
|
||||
@@ -147,7 +146,7 @@ uint8_t const desc_hs_configuration[] =
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 16, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512),
|
||||
@@ -176,16 +175,14 @@ tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void) {
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
// Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
// Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
{
|
||||
uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) {
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
// if link speed is high return fullspeed config, and vice versa
|
||||
@@ -204,13 +201,12 @@ uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index)
|
||||
// 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)
|
||||
{
|
||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index) {
|
||||
(void) index; // for multiple configurations
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Although we are highspeed, host may be fullspeed.
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
|
||||
#else
|
||||
return desc_fs_configuration;
|
||||
#endif
|
||||
@@ -229,8 +225,7 @@ enum {
|
||||
};
|
||||
|
||||
// array of pointer to string descriptors
|
||||
char const *string_desc_arr[] =
|
||||
{
|
||||
char const *string_desc_arr[] = {
|
||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||
"TinyUSB", // 1: Manufacturer
|
||||
"TinyUSB Device", // 2: Product
|
||||
@@ -261,14 +256,14 @@ 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++ ) {
|
||||
@@ -279,6 +274,5 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
_desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
|
||||
|
||||
return _desc_str;
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@
|
||||
#include "tusb.h"
|
||||
#include "usb_descriptors.h"
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
// ESP-IDF need "freertos/" prefix in include path.
|
||||
// CFG_TUSB_OS_INC_PATH should be defined accordingly.
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -112,17 +112,16 @@ int main(void)
|
||||
|
||||
xTimerStart(blinky_tm, 0);
|
||||
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
// only start scheduler for non-espressif mcu
|
||||
#ifndef ESP_PLATFORM
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
void app_main(void)
|
||||
{
|
||||
#ifdef ESP_PLATFORM
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
#endif
|
||||
|
@@ -59,7 +59,7 @@
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
|
@@ -40,7 +40,7 @@
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define USBD_STACK_SIZE 4096
|
||||
#else
|
||||
// Increase stack size when debug log is enabled
|
||||
@@ -95,15 +95,15 @@ int main(void) {
|
||||
xTaskCreate(midi_task, "midi", MIDI_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL);
|
||||
#endif
|
||||
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#ifndef ESP_PLATFORM
|
||||
// only start scheduler for non-espressif mcu
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += lib/lwip
|
||||
|
||||
include ../../build_system/make/make.mk
|
||||
|
||||
# suppress warning caused by lwip
|
||||
|
@@ -292,7 +292,7 @@ void led_blinking_task(void* param) {
|
||||
#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE
|
||||
#define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4)
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define USBD_STACK_SIZE 4096
|
||||
int main(void);
|
||||
void app_main(void) {
|
||||
@@ -351,8 +351,8 @@ void freertos_init_task(void) {
|
||||
xTaskCreate(video_task, "video", VIDEO_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL);
|
||||
#endif
|
||||
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
// only start scheduler for non-espressif mcu
|
||||
#ifndef ESP_PLATFORM
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
|
@@ -300,7 +300,7 @@ void led_blinking_task(void* param) {
|
||||
#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE
|
||||
#define VIDEO_STACK_SIZE (configMINIMAL_STACK_SIZE*4)
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define USBD_STACK_SIZE 4096
|
||||
int main(void);
|
||||
void app_main(void) {
|
||||
@@ -359,8 +359,8 @@ void freertos_init_task(void) {
|
||||
xTaskCreate(video_task, "video", VIDEO_STACK_SZIE, NULL, configMAX_PRIORITIES - 2, NULL);
|
||||
#endif
|
||||
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
// only start scheduler for non-espressif mcu
|
||||
#ifndef ESP_PLATFORM
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
|
@@ -31,8 +31,7 @@ static size_t get_console_inputs(uint8_t* buf, size_t bufsize) {
|
||||
size_t count = 0;
|
||||
while (count < bufsize) {
|
||||
int ch = board_getchar();
|
||||
if (ch <= 0) break;
|
||||
|
||||
if (ch <= 0) { break; }
|
||||
buf[count] = (uint8_t) ch;
|
||||
count++;
|
||||
}
|
||||
@@ -69,10 +68,15 @@ void tuh_cdc_rx_cb(uint8_t idx) {
|
||||
uint32_t const bufsize = sizeof(buf) - 1;
|
||||
|
||||
// forward cdc interfaces -> console
|
||||
uint32_t count = tuh_cdc_read(idx, buf, bufsize);
|
||||
buf[count] = 0;
|
||||
const uint32_t count = tuh_cdc_read(idx, buf, bufsize);
|
||||
if (count) {
|
||||
buf[count] = 0;
|
||||
printf("%s", (char*) buf);
|
||||
|
||||
printf("%s", (char*) buf);
|
||||
#ifndef __ICCARM__ // TODO IAR doesn't support stream control ?
|
||||
fflush(stdout);// flush right away, else nanolib will wait for newline
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when a device with CDC interface is mounted
|
||||
@@ -88,7 +92,7 @@ void tuh_cdc_mount_cb(uint8_t idx) {
|
||||
// If CFG_TUH_CDC_LINE_CODING_ON_ENUM is defined, line coding will be set by tinyusb stack
|
||||
// while eneumerating new cdc device
|
||||
cdc_line_coding_t line_coding = {0};
|
||||
if (tuh_cdc_get_local_line_coding(idx, &line_coding)) {
|
||||
if (tuh_cdc_get_line_coding_local(idx, &line_coding)) {
|
||||
printf(" Baudrate: %" PRIu32 ", Stop Bits : %u\r\n", line_coding.bit_rate, line_coding.stop_bits);
|
||||
printf(" Parity : %u, Data Width: %u\r\n", line_coding.parity, line_coding.data_bits);
|
||||
}
|
||||
|
@@ -103,10 +103,11 @@
|
||||
#define CFG_TUH_ENUMERATION_BUFSIZE 256
|
||||
|
||||
#define CFG_TUH_HUB 1 // number of supported hubs
|
||||
#define CFG_TUH_CDC 1 // CDC ACM
|
||||
#define CFG_TUH_CDC 2 // number of supported CDC devices. also activates CDC ACM
|
||||
#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_CDC_PL2303 1 // PL2303 Serial. PL2303 is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
|
||||
#define CFG_TUH_MSC 1
|
||||
#define CFG_TUH_VENDOR 0
|
||||
@@ -122,7 +123,7 @@
|
||||
|
||||
// Set Line Control state on enumeration/mounted:
|
||||
// DTR ( bit 0), RTS (bit 1)
|
||||
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0x03
|
||||
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM (CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS)
|
||||
|
||||
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
|
||||
// bit rate = 115200, 1 stop bit, no parity, 8 bit data width
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#include "tusb.h"
|
||||
#include "bsp/board_api.h"
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CDC_STACK_SZIE 2048
|
||||
#else
|
||||
#define CDC_STACK_SZIE (3*configMINIMAL_STACK_SIZE/2)
|
||||
|
@@ -30,7 +30,7 @@
|
||||
#include "bsp/board_api.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define USBH_STACK_SIZE 4096
|
||||
#else
|
||||
// Increase stack size when debug log is enabled
|
||||
@@ -86,15 +86,15 @@ int main(void) {
|
||||
|
||||
xTimerStart(blinky_tm, 0);
|
||||
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
// only start scheduler for non-espressif mcu
|
||||
#ifndef ESP_PLATFORM
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
|
@@ -44,7 +44,7 @@
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
@@ -108,10 +108,11 @@
|
||||
#define CFG_TUH_ENUMERATION_BUFSIZE 256
|
||||
|
||||
#define CFG_TUH_HUB 1 // number of supported hubs
|
||||
#define CFG_TUH_CDC 1 // CDC ACM
|
||||
#define CFG_TUH_CDC 1 // number of supported CDC devices. also activates CDC ACM
|
||||
#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_CDC_PL2303 1 // PL2303 Serial. PL2303 is not part of CDC class, only to re-use CDC driver API
|
||||
#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX) // typical keyboard + mouse device can have 3-4 HID interfaces
|
||||
#define CFG_TUH_MSC 1
|
||||
#define CFG_TUH_VENDOR 0
|
||||
@@ -127,7 +128,7 @@
|
||||
|
||||
// Set Line Control state on enumeration/mounted:
|
||||
// DTR ( bit 0), RTS (bit 1)
|
||||
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0x03
|
||||
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM (CDC_CONTROL_LINE_STATE_DTR | CDC_CONTROL_LINE_STATE_RTS)
|
||||
|
||||
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
|
||||
// bit rate = 115200, 1 stop bit, no parity, 8 bit data width
|
||||
|
@@ -268,7 +268,7 @@ void led_blinking_task(void* param) {
|
||||
|
||||
#define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define USB_STACK_SIZE 4096
|
||||
#else
|
||||
// Increase stack size when debug log is enabled
|
||||
@@ -285,7 +285,7 @@ StackType_t usb_stack[USB_STACK_SIZE];
|
||||
StaticTask_t usb_taskdef;
|
||||
#endif
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
@@ -308,8 +308,8 @@ void init_freertos_task(void) {
|
||||
xTaskCreate(usb_host_task, "usbh", USB_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
|
||||
#endif
|
||||
|
||||
// skip starting scheduler (and return) for ESP32-S2 or ESP32-S3
|
||||
#if !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
// only start scheduler for non-espressif mcu
|
||||
#ifndef ESP_PLATFORM
|
||||
vTaskStartScheduler();
|
||||
#endif
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
|
@@ -40,7 +40,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
// Espressif IDF requires "freertos/" prefix in include path
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
#define CFG_TUSB_OS_INC_PATH freertos/
|
||||
#endif
|
||||
|
||||
|
@@ -71,9 +71,8 @@ int main(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
void app_main(void)
|
||||
{
|
||||
#ifdef ESP_PLATFORM
|
||||
void app_main(void) {
|
||||
main();
|
||||
}
|
||||
#endif
|
||||
|
@@ -60,13 +60,11 @@ int sys_read(int fhdl, char *buf, size_t count) {
|
||||
int rd = (int) SEGGER_RTT_Read(0, buf, count);
|
||||
return (rd > 0) ? rd : -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined(LOGGER_SWO)
|
||||
|
||||
#define ITM_BASE 0xE0000000
|
||||
|
||||
#define ITM_STIM0 (*((volatile uint8_t*)(ITM_BASE + 0)))
|
||||
#define ITM_TER *((volatile uint32_t*)(ITM_BASE + 0xE00))
|
||||
#define ITM_TCR *((volatile uint32_t*)(ITM_BASE + 0xE80))
|
||||
@@ -150,6 +148,9 @@ int board_getchar(void) {
|
||||
return (sys_read(0, &c, 1) > 0) ? (int) c : (-1);
|
||||
}
|
||||
|
||||
void board_putchar(int c) {
|
||||
sys_write(0, (const char*)&c, 1);
|
||||
}
|
||||
|
||||
uint32_t tusb_time_millis_api(void) {
|
||||
return board_millis();
|
||||
@@ -158,7 +159,7 @@ uint32_t tusb_time_millis_api(void) {
|
||||
//--------------------------------------------------------------------
|
||||
// FreeRTOS hooks
|
||||
//--------------------------------------------------------------------
|
||||
#if CFG_TUSB_OS == OPT_OS_FREERTOS && !TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#if CFG_TUSB_OS == OPT_OS_FREERTOS && !defined(ESP_PLATFORM)
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
@@ -240,5 +241,4 @@ void vApplicationSetupTimerInterrupt(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -41,7 +41,7 @@ extern "C" {
|
||||
#if CFG_TUSB_OS == OPT_OS_ZEPHYR
|
||||
#include <zephyr/kernel.h>
|
||||
#elif CFG_TUSB_OS == OPT_OS_FREERTOS
|
||||
#if TUSB_MCU_VENDOR_ESPRESSIF
|
||||
#ifdef ESP_PLATFORM
|
||||
// ESP-IDF need "freertos/" prefix in include path.
|
||||
// CFG_TUSB_OS_INC_PATH should be defined accordingly.
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -195,6 +195,7 @@ static inline void board_delay(uint32_t ms) {
|
||||
|
||||
// stdio getchar() is blocking, this is non-blocking version
|
||||
int board_getchar(void);
|
||||
void board_putchar(int c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -13,7 +13,6 @@ else
|
||||
# The submodule BRTSG-FOSS/ft90x-sdk contains header files and source
|
||||
# code for the Bridgetek SDK. This can be used instead of the prebuilt
|
||||
# library.
|
||||
DEPS_SUBMODULES += hw/mcu/bridgetek/ft9xx/ft90x-sdk
|
||||
# The SDK can be used to load specific files from the Bridgetek SDK.
|
||||
FT9XX_SDK = hw/mcu/bridgetek/ft9xx/ft90x-sdk/Source
|
||||
INC += "$(TOP)/$(FT9XX_SDK)/include"
|
||||
|
@@ -1,6 +1,5 @@
|
||||
# Submodules
|
||||
CH32F20X_SDK = hw/mcu/wch/ch32f20x
|
||||
DEPS_SUBMODULES += $(CH32F20X_SDK)
|
||||
|
||||
# WCH-SDK paths
|
||||
CH32F20X_SDK_SRC = $(CH32F20X_SDK)/EVT/EXAM/SRC
|
||||
|
@@ -156,6 +156,10 @@ int board_getchar(void) {
|
||||
return getchar();
|
||||
}
|
||||
|
||||
void board_putchar(int c) {
|
||||
putchar(c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// PHY Init
|
||||
//--------------------------------------------------------------------
|
||||
|
@@ -1,5 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# Apply board specific content i.e IDF_TARGET must be set before project.cmake is included
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake")
|
||||
string(TOUPPER ${IDF_TARGET} FAMILY_MCUS)
|
||||
|
@@ -1,34 +0,0 @@
|
||||
#DEPS_SUBMODULES +=
|
||||
|
||||
UF2_FAMILY_ID_esp32s2 = 0xbfdd4eee
|
||||
UF2_FAMILY_ID_esp32s3 = 0xc47e5767
|
||||
|
||||
BOARD_CMAKE := $(file < $(TOP)/$(BOARD_PATH)/board.cmake)
|
||||
ifneq ($(findstring esp32s2,$(BOARD_CMAKE)),)
|
||||
IDF_TARGET = esp32s2
|
||||
else
|
||||
ifneq ($(findstring esp32s3,$(BOARD_CMAKE)),)
|
||||
IDF_TARGET = esp32s3
|
||||
endif
|
||||
endif
|
||||
|
||||
.PHONY: all clean flash bootloader-flash app-flash erase monitor dfu-flash dfu
|
||||
|
||||
all:
|
||||
idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) build
|
||||
|
||||
build: all
|
||||
|
||||
fullclean:
|
||||
if test -f sdkconfig; then $(RM) -f sdkconfig ; fi
|
||||
if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi
|
||||
idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@
|
||||
|
||||
clean flash bootloader-flash app-flash erase monitor dfu-flash dfu size size-components size-files:
|
||||
idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@
|
||||
|
||||
uf2: $(BUILD)/$(PROJECT).uf2
|
||||
|
||||
$(BUILD)/$(PROJECT).uf2: $(BUILD)/$(PROJECT).bin
|
||||
@echo CREATE $@
|
||||
$(PYTHON) $(TOP)/tools/uf2/utils/uf2conv.py -f $(UF2_FAMILY_ID_$(IDF_TARGET)) -b 0x0 -c -o $@ $^
|
@@ -221,6 +221,8 @@ function(family_configure_common TARGET RTOS)
|
||||
target_include_directories(${TARGET} PUBLIC ${TOP}/lib/SEGGER_RTT/RTT)
|
||||
# target_compile_definitions(${TARGET} PUBLIC SEGGER_RTT_MODE_DEFAULT=SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL)
|
||||
endif ()
|
||||
else ()
|
||||
target_compile_definitions(${TARGET} PUBLIC LOGGER_UART)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
|
@@ -1,6 +1,5 @@
|
||||
UF2_FAMILY_ID = 0x4fb2d5bd
|
||||
SDK_DIR = hw/mcu/nxp/mcux-sdk
|
||||
DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
SDK_DIR = hw/mcu/nxp/mcux-sdk
|
||||
DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5
|
||||
|
||||
MCU_DIR = $(SDK_DIR)/devices/${MCU_VARIANT}
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
|
@@ -1,5 +1,4 @@
|
||||
SDK_DIR = hw/mcu/nxp/mcux-sdk
|
||||
DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5
|
||||
|
||||
MCU_DIR = $(SDK_DIR)/devices/$(MCU)
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nxp/lpcopen
|
||||
|
||||
CFLAGS += \
|
||||
-DCFG_TUSB_MEM_SECTION='__attribute__((section(".data.$$RAM2")))'
|
||||
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nxp/lpcopen
|
||||
|
||||
MCU_DIR = hw/mcu/nxp/lpcopen/lpc13xx/lpc_chip_13xx
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m3
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nxp/lpcopen
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m3
|
||||
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nxp/lpcopen
|
||||
|
||||
MCU_DIR = hw/mcu/nxp/lpcopen/lpc175x_6x/lpc_chip_175x_6x
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m3
|
||||
|
@@ -1,4 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nxp/lpcopen
|
||||
MCU_DIR = hw/mcu/nxp/lpcopen/lpc18xx/lpc_chip_18xx
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nxp/lpcopen
|
||||
|
||||
MCU_DIR = hw/mcu/nxp/lpcopen/lpc40xx/lpc_chip_40xx
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m4
|
||||
|
@@ -1,4 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nxp/lpcopen
|
||||
SDK_DIR = hw/mcu/nxp/lpcopen/lpc43xx/lpc_chip_43xx
|
||||
|
||||
include ${TOP}/${BOARD_PATH}/board.mk
|
||||
|
@@ -1,5 +1,4 @@
|
||||
SDK_DIR = hw/mcu/nxp/mcux-sdk
|
||||
DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m4
|
||||
|
@@ -1,6 +1,5 @@
|
||||
UF2_FAMILY_ID = 0x2abc77ec
|
||||
SDK_DIR = hw/mcu/nxp/mcux-sdk
|
||||
DEPS_SUBMODULES += lib/CMSIS_5 lib/sct_neopixel $(SDK_DIR)
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m33
|
||||
|
@@ -1,8 +1,6 @@
|
||||
UF2_FAMILY_ID = 0x2abc77ec
|
||||
SDK_DIR = hw/mcu/nxp/mcux-sdk
|
||||
|
||||
DEPS_SUBMODULES += $(SDK_DIR) lib/CMSIS_5
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
|
||||
# Default to Highspeed PORT1
|
||||
|
@@ -11,36 +11,37 @@ set(CMAKE_TOOLCHAIN_FILE ${TOP}/examples/build_system/cmake/toolchain/msp430_${T
|
||||
|
||||
set(FAMILY_MCUS MSP430x5xx CACHE INTERNAL "")
|
||||
|
||||
|
||||
#------------------------------------
|
||||
# BOARD_TARGET
|
||||
#------------------------------------
|
||||
# only need to be built ONCE for all examples
|
||||
function(add_board_target BOARD_TARGET)
|
||||
if (NOT TARGET ${BOARD_TARGET})
|
||||
add_library(${BOARD_TARGET} INTERFACE)
|
||||
target_compile_definitions(${BOARD_TARGET} INTERFACE
|
||||
CFG_TUD_ENDPOINT0_SIZE=8
|
||||
CFG_EXAMPLE_VIDEO_READONLY
|
||||
CFG_EXAMPLE_MSC_READONLY
|
||||
)
|
||||
target_include_directories(${BOARD_TARGET} INTERFACE
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
|
||||
${SDK_DIR}
|
||||
)
|
||||
if (TARGET ${BOARD_TARGET})
|
||||
return()
|
||||
endif ()
|
||||
|
||||
update_board(${BOARD_TARGET})
|
||||
add_library(${BOARD_TARGET} INTERFACE)
|
||||
target_compile_definitions(${BOARD_TARGET} INTERFACE
|
||||
CFG_TUD_ENDPOINT0_SIZE=8
|
||||
CFG_EXAMPLE_VIDEO_READONLY
|
||||
CFG_EXAMPLE_MSC_READONLY
|
||||
)
|
||||
target_include_directories(${BOARD_TARGET} INTERFACE
|
||||
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
|
||||
${SDK_DIR}
|
||||
)
|
||||
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_options(${BOARD_TARGET} INTERFACE
|
||||
"LINKER:--script=${LD_FILE_GNU}"
|
||||
-L${SDK_DIR}
|
||||
)
|
||||
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
|
||||
target_link_options(${BOARD_TARGET} INTERFACE
|
||||
"LINKER:--config=${LD_FILE_IAR}"
|
||||
)
|
||||
endif ()
|
||||
update_board(${BOARD_TARGET})
|
||||
|
||||
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
||||
target_link_options(${BOARD_TARGET} INTERFACE
|
||||
"LINKER:--script=${LD_FILE_GNU}"
|
||||
-L${SDK_DIR}
|
||||
)
|
||||
elseif (CMAKE_C_COMPILER_ID STREQUAL "IAR")
|
||||
target_link_options(${BOARD_TARGET} INTERFACE
|
||||
"LINKER:--config=${LD_FILE_IAR}"
|
||||
)
|
||||
endif ()
|
||||
endfunction()
|
||||
|
||||
@@ -75,7 +76,6 @@ function(family_configure_example TARGET RTOS)
|
||||
)
|
||||
target_link_libraries(${TARGET} PUBLIC board_${BOARD})
|
||||
|
||||
|
||||
# Flashing
|
||||
family_add_bin_hex(${TARGET})
|
||||
family_flash_msp430flasher(${TARGET})
|
||||
|
@@ -1,5 +1,4 @@
|
||||
CROSS_COMPILE = msp430-elf-
|
||||
DEPS_SUBMODULES += hw/mcu/ti
|
||||
SKIP_NANOLIB = 1
|
||||
|
||||
SDK_DIR = hw/mcu/ti/msp430/msp430-gcc-support-files/include
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nuvoton
|
||||
|
||||
CFLAGS += \
|
||||
-flto \
|
||||
-mthumb \
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nuvoton
|
||||
|
||||
CFLAGS += \
|
||||
-flto \
|
||||
-mthumb \
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nuvoton
|
||||
|
||||
CFLAGS += \
|
||||
-flto \
|
||||
-mthumb \
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nuvoton
|
||||
|
||||
CFLAGS += \
|
||||
-flto \
|
||||
-mthumb \
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/nuvoton
|
||||
|
||||
CFLAGS += \
|
||||
-flto \
|
||||
-mthumb \
|
||||
|
@@ -254,7 +254,7 @@ size_t board_get_unique_id(uint8_t id[], size_t max_len) {
|
||||
int board_uart_read(uint8_t *buf, int len) {
|
||||
#ifdef UART_DEV
|
||||
int count = 0;
|
||||
while ( (count < len) && uart_is_readable(uart_inst) ) {
|
||||
while ((count < len) && uart_is_readable(uart_inst)) {
|
||||
buf[count] = uart_getc(uart_inst);
|
||||
count++;
|
||||
}
|
||||
@@ -282,6 +282,10 @@ int board_getchar(void) {
|
||||
return getchar_timeout_us(0);
|
||||
}
|
||||
|
||||
void board_putchar(int c) {
|
||||
stdio_putchar(c);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USB Interrupt Handler
|
||||
// rp2040 implementation will install appropriate handler when initializing
|
||||
|
@@ -1,18 +0,0 @@
|
||||
JLINK_DEVICE = rp2040_m0_0
|
||||
PYOCD_TARGET = rp2040
|
||||
|
||||
DEPS_SUBMODULES += hw/mcu/raspberry_pi/Pico-PIO-USB
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CMAKE_DEFSYM += -DCMAKE_BUILD_TYPE=Debug
|
||||
endif
|
||||
|
||||
$(BUILD):
|
||||
cmake -S . -B $(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) -DPICO_BUILD_DOCS=0 $(CMAKE_DEFSYM)
|
||||
|
||||
all: $(BUILD)
|
||||
$(MAKE) -C $(BUILD)
|
||||
|
||||
flash: flash-pyocd
|
||||
flash-uf2:
|
||||
@$(CP) $(BUILD)/$(PROJECT).uf2 /media/$(USER)/RPI-RP2
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/renesas/rx
|
||||
|
||||
# Cross Compiler for RX
|
||||
CROSS_COMPILE = rx-elf-
|
||||
|
||||
|
@@ -1,4 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/microchip
|
||||
ASF_DIR = hw/mcu/microchip/same70
|
||||
|
||||
CFLAGS += \
|
||||
|
@@ -1,4 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/microchip
|
||||
ASF_DIR = hw/mcu/microchip/same70
|
||||
|
||||
CFLAGS += \
|
||||
|
@@ -16,9 +16,6 @@ CFLAGS += \
|
||||
SILABS_FAMILY = efm32gg12b
|
||||
SILABS_CMSIS = hw/mcu/silabs/cmsis-dfp-$(SILABS_FAMILY)/Device/SiliconLabs/$(shell echo $(SILABS_FAMILY) | tr a-z A-Z)
|
||||
|
||||
DEPS_SUBMODULES += hw/mcu/silabs/cmsis-dfp-$(SILABS_FAMILY)
|
||||
DEPS_SUBMODULES += lib/CMSIS_5
|
||||
|
||||
LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
|
||||
|
||||
# All source paths should be relative to the top level.
|
||||
|
@@ -1,5 +1,3 @@
|
||||
DEPS_SUBMODULES += hw/mcu/sony/cxd56/spresense-exported-sdk
|
||||
|
||||
# Platforms are: Linux, Darwin, MSYS, CYGWIN
|
||||
PLATFORM := $(firstword $(subst _, ,$(shell uname -s 2>/dev/null)))
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
ST_FAMILY = c0
|
||||
DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
||||
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
|
||||
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
||||
|
@@ -1,7 +1,5 @@
|
||||
UF2_FAMILY_ID = 0x647824b6
|
||||
ST_FAMILY = f0
|
||||
DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
||||
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
|
||||
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
ST_FAMILY = f1
|
||||
DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_${ST_FAMILY} hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver
|
||||
|
||||
ST_CMSIS = hw/mcu/st/cmsis_device_${ST_FAMILY}
|
||||
ST_HAL_DRIVER = hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver
|
||||
|
||||
|
@@ -2,11 +2,6 @@ ST_FAMILY = f2
|
||||
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
|
||||
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
||||
DEPS_SUBMODULES += \
|
||||
lib/CMSIS_5 \
|
||||
$(ST_CMSIS) \
|
||||
$(ST_HAL_DRIVER)
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m3
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
UF2_FAMILY_ID = 0x53b80f00
|
||||
ST_FAMILY = f7
|
||||
DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
||||
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
|
||||
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
@@ -1,5 +1,4 @@
|
||||
ST_FAMILY = g0
|
||||
DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
||||
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
|
||||
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
@@ -1,5 +1,4 @@
|
||||
ST_FAMILY = l4
|
||||
DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
||||
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
|
||||
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
@@ -1,5 +1,4 @@
|
||||
ST_FAMILY = u5
|
||||
DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
||||
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
|
||||
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
|
||||
|
@@ -1,8 +1,6 @@
|
||||
UF2_FAMILY_ID = 0x00
|
||||
SDK_DIR = hw/mcu/infineon/mtb-xmclib-cat3
|
||||
|
||||
DEPS_SUBMODULES += ${SDK_DIR}
|
||||
|
||||
include $(TOP)/$(BOARD_PATH)/board.mk
|
||||
CPU_CORE ?= cortex-m4
|
||||
|
||||
|
@@ -1003,20 +1003,22 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint
|
||||
ep_fb = desc_ep->bEndpointAddress;
|
||||
}
|
||||
#endif
|
||||
// Data EP
|
||||
if (desc_ep->bmAttributes.usage == 0) {
|
||||
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
|
||||
#if CFG_TUD_AUDIO_ENABLE_EP_IN
|
||||
ep_in = desc_ep->bEndpointAddress;
|
||||
ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size);
|
||||
#endif
|
||||
} else {
|
||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
|
||||
ep_out = desc_ep->bEndpointAddress;
|
||||
ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size);
|
||||
#endif
|
||||
}
|
||||
// Data or data with implicit feedback IN EP
|
||||
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN
|
||||
&& (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2)) {
|
||||
ep_in = desc_ep->bEndpointAddress;
|
||||
ep_in_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_in_size);
|
||||
}
|
||||
#endif
|
||||
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
|
||||
// Data OUT EP
|
||||
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_OUT
|
||||
&& desc_ep->bmAttributes.usage == 0) {
|
||||
ep_out = desc_ep->bEndpointAddress;
|
||||
ep_out_size = TU_MAX(tu_edpt_packet_size(desc_ep), ep_out_size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1052,10 +1054,10 @@ uint16_t audiod_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint
|
||||
if (tu_desc_type(p_desc) == TUSB_DESC_ENDPOINT) {
|
||||
tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
|
||||
if (desc_ep->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) {
|
||||
if (desc_ep->bmAttributes.usage == 0) {
|
||||
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
|
||||
_audiod_fct[i].interval_tx = desc_ep->bInterval;
|
||||
}
|
||||
// For data or data with implicit feedback IN EP
|
||||
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN
|
||||
&& (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2)) {
|
||||
_audiod_fct[i].interval_tx = desc_ep->bInterval;
|
||||
}
|
||||
}
|
||||
} else if (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_OUTPUT_TERMINAL) {
|
||||
@@ -1227,7 +1229,8 @@ static bool audiod_set_interface(uint8_t rhport, tusb_control_request_t const *p
|
||||
usbd_edpt_clear_stall(rhport, ep_addr);
|
||||
|
||||
#if CFG_TUD_AUDIO_ENABLE_EP_IN
|
||||
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && desc_ep->bmAttributes.usage == 0x00)// Check if usage is data EP
|
||||
// For data or data with implicit feedback IN EP
|
||||
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN && (desc_ep->bmAttributes.usage == 0 || desc_ep->bmAttributes.usage == 2))
|
||||
{
|
||||
// Save address
|
||||
audio->ep_in = ep_addr;
|
||||
|
@@ -192,6 +192,11 @@ typedef enum {
|
||||
CDC_LINE_CODING_STOP_BITS_2 = 2, // 2 bits
|
||||
} cdc_line_coding_stopbits_t;
|
||||
|
||||
#define CDC_LINE_CODING_STOP_BITS_TEXT(STOP_BITS) ( \
|
||||
STOP_BITS == CDC_LINE_CODING_STOP_BITS_1 ? "1" : \
|
||||
STOP_BITS == CDC_LINE_CODING_STOP_BITS_1_5 ? "1.5" : \
|
||||
STOP_BITS == CDC_LINE_CODING_STOP_BITS_2 ? "2" : "?" )
|
||||
|
||||
// TODO Backward compatible for typos. Maybe removed in the future release
|
||||
#define CDC_LINE_CONDING_STOP_BITS_1 CDC_LINE_CODING_STOP_BITS_1
|
||||
#define CDC_LINE_CONDING_STOP_BITS_1_5 CDC_LINE_CODING_STOP_BITS_1_5
|
||||
@@ -205,22 +210,31 @@ typedef enum {
|
||||
CDC_LINE_CODING_PARITY_SPACE = 4,
|
||||
} cdc_line_coding_parity_t;
|
||||
|
||||
#define CDC_LINE_CODING_PARITY_CHAR(PARITY) ( \
|
||||
PARITY == CDC_LINE_CODING_PARITY_NONE ? 'N' : \
|
||||
PARITY == CDC_LINE_CODING_PARITY_ODD ? 'O' : \
|
||||
PARITY == CDC_LINE_CODING_PARITY_EVEN ? 'E' : \
|
||||
PARITY == CDC_LINE_CODING_PARITY_MARK ? 'M' : \
|
||||
PARITY == CDC_LINE_CODING_PARITY_SPACE ? 'S' : '?' )
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Management Element Notification (Notification Endpoint)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#define CDC_REQ_TYPE_NOTIF 0xA1 ///< Direction IN; Type Class; Recipient Interface
|
||||
|
||||
/// 6.3 Notification Codes
|
||||
typedef enum {
|
||||
CDC_NOTIF_NETWORK_CONNECTION = 0x00, ///< This notification allows the device to notify the host about network connection status.
|
||||
CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, ///< This notification allows the device to notify the hostthat a response is available. This response can be retrieved with a subsequent \ref CDC_REQUEST_GET_ENCAPSULATED_RESPONSE request.
|
||||
CDC_NOTIF_NETWORK_CONNECTION = 0x00, // notify the host about network connection status.
|
||||
CDC_NOTIF_RESPONSE_AVAILABLE = 0x01, // notify the host that a response is available.
|
||||
CDC_NOTIF_AUX_JACK_HOOK_STATE = 0x08,
|
||||
CDC_NOTIF_RING_DETECT = 0x09,
|
||||
CDC_NOTIF_SERIAL_STATE = 0x20,
|
||||
CDC_NOTIF_CALL_STATE_CHANGE = 0x28,
|
||||
CDC_NOTIF_LINE_STATE_CHANGE = 0x29,
|
||||
CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, ///< This notification allows the device to inform the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred
|
||||
CDC_NOTIF_CONNECTION_SPEED_CHANGE = 0x2A, // notify the host-networking driver that a change in either the upstream or the downstream bit rate of the connection has occurred
|
||||
CDC_NOTIF_MDLM_SEMANTIC_MODEL_NOTIFICATION = 0x40,
|
||||
}cdc_notification_request_t;
|
||||
} cdc_notify_request_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Class Specific Functional Descriptor (Communication Interface)
|
||||
@@ -231,8 +245,7 @@ TU_ATTR_PACKED_BEGIN
|
||||
TU_ATTR_BIT_FIELD_ORDER_BEGIN
|
||||
|
||||
/// Header Functional Descriptor (Communication Interface)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_
|
||||
@@ -240,8 +253,7 @@ typedef struct TU_ATTR_PACKED
|
||||
}cdc_desc_func_header_t;
|
||||
|
||||
/// Union Functional Descriptor (Communication Interface)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
|
||||
@@ -259,14 +271,13 @@ typedef struct TU_ATTR_PACKED
|
||||
}
|
||||
|
||||
/// Country Selection Functional Descriptor (Communication Interface)
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
|
||||
uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes.
|
||||
uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country.
|
||||
}cdc_desc_func_country_selection_t;
|
||||
} cdc_desc_func_country_selection_t;
|
||||
|
||||
#define cdc_desc_func_country_selection_n_t(no_country) \
|
||||
struct TU_ATTR_PACKED { \
|
||||
@@ -283,8 +294,7 @@ typedef struct TU_ATTR_PACKED
|
||||
|
||||
/// \brief Call Management Functional Descriptor
|
||||
/// \details This functional descriptor describes the processing of calls for the Communications Class interface.
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
|
||||
@@ -298,8 +308,7 @@ typedef struct TU_ATTR_PACKED
|
||||
uint8_t bDataInterface;
|
||||
}cdc_desc_func_call_management_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t support_comm_request : 1; ///< Device supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature.
|
||||
uint8_t support_line_request : 1; ///< Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State.
|
||||
uint8_t support_send_break : 1; ///< Device supports the request Send_Break
|
||||
@@ -311,8 +320,7 @@ TU_VERIFY_STATIC(sizeof(cdc_acm_capability_t) == 1, "mostly problem with compile
|
||||
|
||||
/// Abstract Control Management Functional Descriptor
|
||||
/// This functional descriptor describes the commands supported by by the Communications Class interface with SubClass code of \ref CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
|
||||
@@ -321,8 +329,7 @@ typedef struct TU_ATTR_PACKED
|
||||
|
||||
/// \brief Direct Line Management Functional Descriptor
|
||||
/// \details This functional descriptor describes the commands supported by the Communications Class interface with SubClass code of \ref CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint8_t bLength ; ///< Size of this descriptor in bytes.
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
|
||||
@@ -384,16 +391,14 @@ typedef struct TU_ATTR_PACKED
|
||||
}cdc_desc_func_telephone_call_state_reporting_capabilities_t;
|
||||
|
||||
// TODO remove
|
||||
static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc)
|
||||
{
|
||||
TU_ATTR_ALWAYS_INLINE static inline uint8_t cdc_functional_desc_typeof(uint8_t const * p_desc) {
|
||||
return p_desc[2];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Requests
|
||||
//--------------------------------------------------------------------+
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t bit_rate;
|
||||
uint8_t stop_bits; ///< 0: 1 stop bit - 1: 1.5 stop bits - 2: 2 stop bits
|
||||
uint8_t parity; ///< 0: None - 1: Odd - 2: Even - 3: Mark - 4: Space
|
||||
@@ -402,15 +407,58 @@ typedef struct TU_ATTR_PACKED
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(cdc_line_coding_t) == 7, "size is not correct");
|
||||
|
||||
typedef struct TU_ATTR_PACKED
|
||||
{
|
||||
uint16_t dtr : 1;
|
||||
uint16_t rts : 1;
|
||||
uint16_t : 6;
|
||||
uint16_t : 8;
|
||||
typedef union TU_ATTR_PACKED {
|
||||
struct TU_ATTR_PACKED {
|
||||
uint8_t dtr : 1;
|
||||
uint8_t rts : 1;
|
||||
uint8_t : 6;
|
||||
};
|
||||
uint8_t value;
|
||||
} cdc_line_control_state_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 2, "size is not correct");
|
||||
TU_VERIFY_STATIC(sizeof(cdc_line_control_state_t) == 1, "size is not correct");
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Notifications
|
||||
//--------------------------------------------------------------------+
|
||||
// PSTN 1.2 section 6.5.4 table 31
|
||||
typedef union TU_ATTR_PACKED {
|
||||
struct TU_ATTR_PACKED {
|
||||
uint16_t bRxCarrier : 1; // DCD
|
||||
uint16_t bTxCarrier : 1; // DSR
|
||||
uint16_t bBreak : 1; // Break Detected
|
||||
uint16_t bRingSignal : 1;
|
||||
uint16_t bFraming : 1;
|
||||
uint16_t bParity : 1;
|
||||
uint16_t bOverRun : 1;
|
||||
uint16_t : 9;
|
||||
};
|
||||
struct TU_ATTR_PACKED {
|
||||
uint16_t dcd : 1;
|
||||
uint16_t dsr : 1;
|
||||
uint16_t brk : 1;
|
||||
uint16_t :13;
|
||||
};
|
||||
uint16_t value;
|
||||
} cdc_notify_uart_state_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(cdc_notify_uart_state_t) == 2, "size is not correct");
|
||||
|
||||
// CDC 1.2 section 6.3.3 table 21
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
uint32_t upstream_bitrate;
|
||||
uint32_t downstream_bitrate;
|
||||
} cdc_notify_conn_speed_change_t;
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
tusb_control_request_t request;
|
||||
union {
|
||||
cdc_notify_uart_state_t serial_state;
|
||||
cdc_notify_conn_speed_change_t conn_speed_change;
|
||||
};
|
||||
} cdc_notify_msg_t;
|
||||
|
||||
TU_VERIFY_STATIC(sizeof(cdc_notify_msg_t) == 16, "size is not correct");
|
||||
|
||||
TU_ATTR_PACKED_END // End of all packed definitions
|
||||
TU_ATTR_BIT_FIELD_ORDER_END
|
||||
|
@@ -46,13 +46,13 @@
|
||||
#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
|
||||
|
||||
typedef struct {
|
||||
uint8_t rhport;
|
||||
uint8_t itf_num;
|
||||
uint8_t ep_notif;
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out;
|
||||
|
||||
// Bit 0: DTR (Data Terminal Ready), Bit 1: RTS (Request to Send)
|
||||
uint8_t line_state;
|
||||
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;
|
||||
@@ -74,6 +74,10 @@ typedef struct {
|
||||
typedef struct {
|
||||
TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE);
|
||||
TUD_EPBUF_DEF(epin, CFG_TUD_CDC_EP_BUFSIZE);
|
||||
|
||||
#if CFG_TUD_CDC_NOTIFY
|
||||
TUD_EPBUF_TYPE_DEF(cdc_notify_msg_t, epnotify);
|
||||
#endif
|
||||
} cdcd_epbuf_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -101,7 +105,7 @@ static bool _prep_out_transaction(uint8_t itf) {
|
||||
TU_VERIFY(available >= CFG_TUD_CDC_EP_BUFSIZE);
|
||||
|
||||
// claim endpoint
|
||||
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out));
|
||||
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);
|
||||
@@ -110,7 +114,7 @@ static bool _prep_out_transaction(uint8_t itf) {
|
||||
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(rhport, p_cdc->ep_out);
|
||||
usbd_edpt_release(p_cdc->rhport, p_cdc->ep_out);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -118,7 +122,6 @@ static bool _prep_out_transaction(uint8_t itf) {
|
||||
//--------------------------------------------------------------------+
|
||||
// APPLICATION API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg) {
|
||||
TU_VERIFY(driver_cfg);
|
||||
_cdcd_cfg = *driver_cfg;
|
||||
@@ -142,6 +145,42 @@ void tud_cdc_n_get_line_coding(uint8_t itf, cdc_line_coding_t* coding) {
|
||||
(*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(tud_ready() && p_cdc->ep_notify != 0);
|
||||
TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify));
|
||||
|
||||
cdc_notify_msg_t* notify_msg = &p_epbuf->epnotify;
|
||||
notify_msg->request.bmRequestType = CDC_REQ_TYPE_NOTIF;
|
||||
notify_msg->request.bRequest = CDC_NOTIF_SERIAL_STATE;
|
||||
notify_msg->request.wValue = 0;
|
||||
notify_msg->request.wIndex = p_cdc->itf_num;
|
||||
notify_msg->request.wLength = sizeof(cdc_notify_uart_state_t);
|
||||
notify_msg->serial_state = *state;
|
||||
|
||||
return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_uart_state_t));
|
||||
}
|
||||
|
||||
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(tud_ready() && p_cdc->ep_notify != 0);
|
||||
TU_VERIFY(usbd_edpt_claim(p_cdc->rhport, p_cdc->ep_notify));
|
||||
|
||||
cdc_notify_msg_t* notify_msg = &p_epbuf->epnotify;
|
||||
notify_msg->request.bmRequestType = CDC_REQ_TYPE_NOTIF;
|
||||
notify_msg->request.bRequest = CDC_NOTIF_CONNECTION_SPEED_CHANGE;
|
||||
notify_msg->request.wValue = 0;
|
||||
notify_msg->request.wIndex = p_cdc->itf_num;
|
||||
notify_msg->request.wLength = sizeof(cdc_notify_conn_speed_change_t);
|
||||
notify_msg->conn_speed_change = *conn_speed_change;
|
||||
|
||||
return usbd_edpt_xfer(p_cdc->rhport, p_cdc->ep_notify, (uint8_t *)notify_msg, 8 + sizeof(cdc_notify_conn_speed_change_t));
|
||||
}
|
||||
#endif
|
||||
|
||||
void tud_cdc_n_set_wanted_char(uint8_t itf, char wanted) {
|
||||
_cdcd_itf[itf].wanted_char = wanted;
|
||||
}
|
||||
@@ -192,30 +231,25 @@ uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t 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];
|
||||
|
||||
// Skip if usb is not ready yet
|
||||
TU_VERIFY(tud_ready(), 0);
|
||||
TU_VERIFY(tud_ready(), 0); // Skip if usb is not ready yet
|
||||
|
||||
// No data to send
|
||||
if (!tu_fifo_count(&p_cdc->tx_ff)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t rhport = 0;
|
||||
|
||||
// Claim the endpoint
|
||||
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_in), 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) {
|
||||
TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, p_epbuf->epin, 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(rhport, p_cdc->ep_in);
|
||||
usbd_edpt_release(p_cdc->rhport, p_cdc->ep_in);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -319,6 +353,7 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16
|
||||
TU_ASSERT(cdc_id < CFG_TUD_CDC, 0);
|
||||
|
||||
//------------- Control Interface -------------//
|
||||
p_cdc->rhport = rhport;
|
||||
p_cdc->itf_num = itf_desc->bInterfaceNumber;
|
||||
|
||||
uint16_t drv_len = sizeof(tusb_desc_interface_t);
|
||||
@@ -333,9 +368,8 @@ uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16
|
||||
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_notif = desc_ep->bEndpointAddress;
|
||||
p_cdc->ep_notify = desc_ep->bEndpointAddress;
|
||||
|
||||
drv_len += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
@@ -455,7 +489,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
// 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)) {
|
||||
if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in) || (ep_addr == p_cdc->ep_notify)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -504,7 +538,12 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
}
|
||||
}
|
||||
|
||||
// nothing to do with notif endpoint for now
|
||||
// Sent notification to host
|
||||
if (ep_addr == p_cdc->ep_notify) {
|
||||
if (tud_cdc_notify_complete_cb) {
|
||||
tud_cdc_notify_complete_cb(itf);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -32,6 +32,10 @@
|
||||
//--------------------------------------------------------------------+
|
||||
// Class Driver Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
#ifndef CFG_TUD_CDC_NOTIFY
|
||||
#define CFG_TUD_CDC_NOTIFY 0
|
||||
#endif
|
||||
|
||||
#if !defined(CFG_TUD_CDC_EP_BUFSIZE) && defined(CFG_TUD_CDC_EPSIZE)
|
||||
#warning CFG_TUD_CDC_EPSIZE is renamed to CFG_TUD_CDC_EP_BUFSIZE, please update to use the new name
|
||||
#define CFG_TUD_CDC_EP_BUFSIZE CFG_TUD_CDC_EPSIZE
|
||||
@@ -126,6 +130,23 @@ uint32_t tud_cdc_n_write_available(uint8_t itf);
|
||||
// Clear the transmit FIFO
|
||||
bool tud_cdc_n_write_clear(uint8_t itf);
|
||||
|
||||
|
||||
#if CFG_TUD_CDC_NOTIFY
|
||||
// Send UART status notification: DCD, DSR etc ..
|
||||
bool tud_cdc_n_notify_uart_state(uint8_t itf, const cdc_notify_uart_state_t *state);
|
||||
|
||||
// Send connection speed change notification
|
||||
bool tud_cdc_n_notify_conn_speed_change(uint8_t itf, const cdc_notify_conn_speed_change_t* conn_speed_change);
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_uart_state(const cdc_notify_uart_state_t* state) {
|
||||
return tud_cdc_n_notify_uart_state(0, state);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_notify_conn_speed_change(const cdc_notify_conn_speed_change_t* conn_speed_change) {
|
||||
return tud_cdc_n_notify_conn_speed_change(0, conn_speed_change);
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application API (Single Port)
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -195,7 +216,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_cdc_write_clear(void) {
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application Callback API (weak is optional)
|
||||
// Application Callback API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when received new data
|
||||
@@ -207,6 +228,9 @@ TU_ATTR_WEAK void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char);
|
||||
// Invoked when a TX is complete and therefore space becomes available in TX buffer
|
||||
TU_ATTR_WEAK void tud_cdc_tx_complete_cb(uint8_t itf);
|
||||
|
||||
// Invoked when a notification is sent to host
|
||||
TU_ATTR_WEAK void tud_cdc_notify_complete_cb(uint8_t itf);
|
||||
|
||||
// Invoked when line state DTR & RTS are changed via SET_CONTROL_LINE_STATE
|
||||
TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -37,16 +37,6 @@
|
||||
// Class Driver Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Set Line Control state on enumeration/mounted: DTR ( bit 0), RTS (bit 1)
|
||||
#ifndef CFG_TUH_CDC_LINE_CONTROL_ON_ENUM
|
||||
#define CFG_TUH_CDC_LINE_CONTROL_ON_ENUM 0
|
||||
#endif
|
||||
|
||||
// Set Line Coding on enumeration/mounted, value for cdc_line_coding_t
|
||||
//#ifndef CFG_TUH_CDC_LINE_CODING_ON_ENUM
|
||||
//#define CFG_TUH_CDC_LINE_CODING_ON_ENUM { 115200, CDC_LINE_CODING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
|
||||
//#endif
|
||||
|
||||
// RX FIFO size
|
||||
#ifndef CFG_TUH_CDC_RX_BUFSIZE
|
||||
#define CFG_TUH_CDC_RX_BUFSIZE TUH_EPSIZE_BULK_MPS
|
||||
@@ -79,14 +69,27 @@ uint8_t tuh_cdc_itf_get_index(uint8_t daddr, uint8_t itf_num);
|
||||
// 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);
|
||||
|
||||
// Check if a interface is mounted
|
||||
// Check if an interface is mounted
|
||||
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);
|
||||
|
||||
// Get current DTR status
|
||||
bool tuh_cdc_get_dtr(uint8_t idx);
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_get_dtr(uint8_t idx) {
|
||||
uint16_t line_state;
|
||||
TU_VERIFY(tuh_cdc_get_control_line_state_local(idx, &line_state));
|
||||
return (line_state & CDC_CONTROL_LINE_STATE_DTR) != 0;
|
||||
}
|
||||
|
||||
// Get current RTS status
|
||||
bool tuh_cdc_get_rts(uint8_t idx);
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_get_rts(uint8_t idx) {
|
||||
uint16_t line_state;
|
||||
TU_VERIFY(tuh_cdc_get_control_line_state_local(idx, &line_state));
|
||||
return (line_state & CDC_CONTROL_LINE_STATE_RTS) != 0;
|
||||
}
|
||||
|
||||
// Check if interface is connected (DTR active)
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx) {
|
||||
@@ -97,7 +100,9 @@ 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_local_line_coding(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
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Write API
|
||||
@@ -132,18 +137,31 @@ bool tuh_cdc_peek(uint8_t idx, uint8_t* ch);
|
||||
bool tuh_cdc_read_clear (uint8_t idx);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Control Endpoint (Request) API
|
||||
// Control Request API
|
||||
// Each Function will make a USB control transfer request to/from device
|
||||
// - If complete_cb is provided, the function will return immediately and invoke
|
||||
// the callback when request is complete.
|
||||
// - If complete_cb is NULL, the function will block until request is complete.
|
||||
// - In this case, user_data should be pointed to xfer_result_t to hold the transfer result.
|
||||
// - The function will return true if transfer is successful, false otherwise.
|
||||
// In this case, user_data should be usb_xfer_result_t* to hold the transfer result.
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Request to Set Control Line State: DTR (bit 0), RTS (bit 1)
|
||||
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);
|
||||
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);
|
||||
return tuh_cdc_set_control_line_state(idx, line_state.value, complete_cb, user_data);
|
||||
}
|
||||
|
||||
// Request to set baudrate
|
||||
bool tuh_cdc_set_baudrate(uint8_t idx, uint32_t baudrate, tuh_xfer_cb_t complete_cb, uintptr_t user_data);
|
||||
|
||||
@@ -160,17 +178,52 @@ bool tuh_cdc_set_line_coding(uint8_t idx, cdc_line_coding_t const* line_coding,
|
||||
// bool tuh_cdc_get_line_coding(uint8_t idx, cdc_line_coding_t* 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Control Request Sync API
|
||||
// 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_API_SYNC(tuh_cdc_set_control_line_state, idx, line_state);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_dtr_sync(uint8_t idx, bool dtr_state) {
|
||||
TU_API_SYNC(tuh_cdc_set_dtr, idx, dtr_state);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_rts_sync(uint8_t idx, bool rts_state) {
|
||||
TU_API_SYNC(tuh_cdc_set_rts, idx, rts_state);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_set_baudrate_sync(uint8_t idx, uint32_t baudrate) {
|
||||
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_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_API_SYNC(tuh_cdc_set_line_coding, idx, line_coding);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_connect_sync(uint8_t idx) {
|
||||
TU_API_SYNC(tuh_cdc_connect, idx);
|
||||
}
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline tusb_xfer_result_t tuh_cdc_disconnect_sync(uint8_t idx) {
|
||||
TU_API_SYNC(tuh_cdc_disconnect, idx);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// CDC APPLICATION CALLBACKS
|
||||
//--------------------------------------------------------------------+
|
||||
|
@@ -24,8 +24,8 @@
|
||||
* This file is part of the TinyUSB stack.
|
||||
*/
|
||||
|
||||
#ifndef _CH34X_H_
|
||||
#define _CH34X_H_
|
||||
#ifndef TUSB_CH34X_H
|
||||
#define TUSB_CH34X_H
|
||||
|
||||
// There is no official documentation for the CH34x (CH340, CH341) chips. Reference can be found
|
||||
// - https://github.com/WCHSoftGroup/ch341ser_linux
|
||||
@@ -34,51 +34,51 @@
|
||||
|
||||
// set line_coding @ enumeration
|
||||
#ifdef CFG_TUH_CDC_LINE_CODING_ON_ENUM
|
||||
#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X CFG_TUH_CDC_LINE_CODING_ON_ENUM
|
||||
#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X CFG_TUH_CDC_LINE_CODING_ON_ENUM
|
||||
#else // this default is necessary to work properly
|
||||
#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X { 9600, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
|
||||
#define CFG_TUH_CDC_LINE_CODING_ON_ENUM_CH34X { 9600, CDC_LINE_CONDING_STOP_BITS_1, CDC_LINE_CODING_PARITY_NONE, 8 }
|
||||
#endif
|
||||
|
||||
// USB requests
|
||||
#define CH34X_REQ_READ_VERSION 0x5F // dec 95
|
||||
#define CH34X_REQ_WRITE_REG 0x9A // dec 154
|
||||
#define CH34X_REQ_READ_REG 0x95 // dec 149
|
||||
#define CH34X_REQ_SERIAL_INIT 0xA1 // dec 161
|
||||
#define CH34X_REQ_MODEM_CTRL 0xA4 // dev 164
|
||||
#define CH34X_REQ_READ_VERSION 0x5F // dec 95
|
||||
#define CH34X_REQ_WRITE_REG 0x9A // dec 154
|
||||
#define CH34X_REQ_READ_REG 0x95 // dec 149
|
||||
#define CH34X_REQ_SERIAL_INIT 0xA1 // dec 161
|
||||
#define CH34X_REQ_MODEM_CTRL 0xA4 // dev 164
|
||||
|
||||
// registers
|
||||
#define CH34X_REG_BREAK 0x05
|
||||
#define CH34X_REG_PRESCALER 0x12
|
||||
#define CH34X_REG_DIVISOR 0x13
|
||||
#define CH34X_REG_LCR 0x18
|
||||
#define CH34X_REG_LCR2 0x25
|
||||
#define CH34X_REG_MCR_MSR 0x06
|
||||
#define CH34X_REG_MCR_MSR2 0x07
|
||||
#define CH34X_NBREAK_BITS 0x01
|
||||
#define CH34X_REG_BREAK 0x05
|
||||
#define CH34X_REG_PRESCALER 0x12
|
||||
#define CH34X_REG_DIVISOR 0x13
|
||||
#define CH34X_REG_LCR 0x18
|
||||
#define CH34X_REG_LCR2 0x25
|
||||
#define CH34X_REG_MCR_MSR 0x06
|
||||
#define CH34X_REG_MCR_MSR2 0x07
|
||||
#define CH34X_NBREAK_BITS 0x01
|
||||
|
||||
#define CH341_REG_0x0F 0x0F // undocumented register
|
||||
#define CH341_REG_0x2C 0x2C // undocumented register
|
||||
#define CH341_REG_0x27 0x27 // hardware flow control (cts/rts)
|
||||
#define CH341_REG_0x0F 0x0F // undocumented register
|
||||
#define CH341_REG_0x2C 0x2C // undocumented register
|
||||
#define CH341_REG_0x27 0x27 // hardware flow control (cts/rts)
|
||||
|
||||
#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER)
|
||||
#define CH32X_REG16_LCR2_LCR TU_U16(CH34X_REG_LCR2, CH34X_REG_LCR)
|
||||
#define CH34X_REG16_DIVISOR_PRESCALER TU_U16(CH34X_REG_DIVISOR, CH34X_REG_PRESCALER)
|
||||
#define CH32X_REG16_LCR2_LCR TU_U16(CH34X_REG_LCR2, CH34X_REG_LCR)
|
||||
|
||||
// modem control bits
|
||||
#define CH34X_BIT_RTS ( 1 << 6 )
|
||||
#define CH34X_BIT_DTR ( 1 << 5 )
|
||||
#define CH34X_BIT_RTS (1 << 6)
|
||||
#define CH34X_BIT_DTR (1 << 5)
|
||||
|
||||
// line control bits
|
||||
#define CH34X_LCR_ENABLE_RX 0x80
|
||||
#define CH34X_LCR_ENABLE_TX 0x40
|
||||
#define CH34X_LCR_MARK_SPACE 0x20
|
||||
#define CH34X_LCR_PAR_EVEN 0x10
|
||||
#define CH34X_LCR_ENABLE_PAR 0x08
|
||||
#define CH34X_LCR_PAR_MASK 0x38 // all parity bits
|
||||
#define CH34X_LCR_STOP_BITS_2 0x04
|
||||
#define CH34X_LCR_CS8 0x03
|
||||
#define CH34X_LCR_CS7 0x02
|
||||
#define CH34X_LCR_CS6 0x01
|
||||
#define CH34X_LCR_CS5 0x00
|
||||
#define CH34X_LCR_CS_MASK 0x03 // all CSx bits
|
||||
#define CH34X_LCR_ENABLE_RX 0x80
|
||||
#define CH34X_LCR_ENABLE_TX 0x40
|
||||
#define CH34X_LCR_MARK_SPACE 0x20
|
||||
#define CH34X_LCR_PAR_EVEN 0x10
|
||||
#define CH34X_LCR_ENABLE_PAR 0x08
|
||||
#define CH34X_LCR_PAR_MASK 0x38 // all parity bits
|
||||
#define CH34X_LCR_STOP_BITS_2 0x04
|
||||
#define CH34X_LCR_CS8 0x03
|
||||
#define CH34X_LCR_CS7 0x02
|
||||
#define CH34X_LCR_CS6 0x01
|
||||
#define CH34X_LCR_CS5 0x00
|
||||
#define CH34X_LCR_CS_MASK 0x03 // all CSx bits
|
||||
|
||||
#endif /* _CH34X_H_ */
|
||||
#endif // TUSB_CH34X_H
|
||||
|
@@ -28,9 +28,10 @@
|
||||
// Protocol details can be found at AN571: CP210x Virtual COM Port Interface
|
||||
// https://www.silabs.com/documents/public/application-notes/AN571.pdf
|
||||
|
||||
#define TU_CP210X_VID 0x10C4
|
||||
// parts are overtaken from vendors driver
|
||||
// https://www.silabs.com/documents/public/software/cp210x-3.1.0.tar.gz
|
||||
|
||||
/* Config request codes */
|
||||
// Config request codes
|
||||
#define CP210X_IFC_ENABLE 0x00
|
||||
#define CP210X_SET_BAUDDIV 0x01
|
||||
#define CP210X_GET_BAUDDIV 0x02
|
||||
@@ -59,4 +60,55 @@
|
||||
#define CP210X_SET_BAUDRATE 0x1E
|
||||
#define CP210X_VENDOR_SPECIFIC 0xFF // GPIO, Recipient must be Device
|
||||
|
||||
// SILABSER_IFC_ENABLE_REQUEST_CODE
|
||||
#define CP210X_UART_ENABLE 0x0001
|
||||
#define CP210X_UART_DISABLE 0x0000
|
||||
|
||||
// SILABSER_SET_BAUDDIV_REQUEST_CODE
|
||||
#define CP210X_BAUD_RATE_GEN_FREQ 0x384000
|
||||
|
||||
// SILABSER_SET_LINE_CTL_REQUEST_CODE
|
||||
#define CP210X_BITS_DATA_MASK 0x0f00
|
||||
#define CP210X_BITS_DATA_5 0x0500
|
||||
#define CP210X_BITS_DATA_6 0x0600
|
||||
#define CP210X_BITS_DATA_7 0x0700
|
||||
#define CP210X_BITS_DATA_8 0x0800
|
||||
#define CP210X_BITS_DATA_9 0x0900
|
||||
|
||||
#define CP210X_BITS_PARITY_MASK 0x00f0
|
||||
#define CP210X_BITS_PARITY_NONE 0x0000
|
||||
#define CP210X_BITS_PARITY_ODD 0x0010
|
||||
#define CP210X_BITS_PARITY_EVEN 0x0020
|
||||
#define CP210X_BITS_PARITY_MARK 0x0030
|
||||
#define CP210X_BITS_PARITY_SPACE 0x0040
|
||||
|
||||
#define CP210X_BITS_STOP_MASK 0x000f
|
||||
#define CP210X_BITS_STOP_1 0x0000
|
||||
#define CP210X_BITS_STOP_1_5 0x0001
|
||||
#define CP210X_BITS_STOP_2 0x0002
|
||||
|
||||
// SILABSER_SET_BREAK_REQUEST_CODE
|
||||
#define CP210X_BREAK_ON 0x0001
|
||||
#define CP210X_BREAK_OFF 0x0000
|
||||
|
||||
// SILABSER_SET_MHS_REQUEST_CODE
|
||||
#define CP210X_MCR_DTR 0x0001
|
||||
#define CP210X_MCR_RTS 0x0002
|
||||
#define CP210X_MCR_ALL 0x0003
|
||||
#define CP210X_MSR_CTS 0x0010
|
||||
#define CP210X_MSR_DSR 0x0020
|
||||
#define CP210X_MSR_RING 0x0040
|
||||
#define CP210X_MSR_DCD 0x0080
|
||||
#define CP210X_MSR_ALL 0x00F0
|
||||
|
||||
#define CP210X_CONTROL_WRITE_DTR 0x0100UL
|
||||
#define CP210X_CONTROL_WRITE_RTS 0x0200UL
|
||||
|
||||
#define CP210X_LSR_BREAK 0x0001
|
||||
#define CP210X_LSR_FRAMING_ERROR 0x0002
|
||||
#define CP210X_LSR_HW_OVERRUN 0x0004
|
||||
#define CP210X_LSR_QUEUE_OVERRUN 0x0008
|
||||
#define CP210X_LSR_PARITY_ERROR 0x0010
|
||||
#define CP210X_LSR_ALL 0x001F
|
||||
|
||||
#endif //TUSB_CP210X_H
|
||||
|
@@ -25,222 +25,207 @@
|
||||
#ifndef TUSB_FTDI_SIO_H
|
||||
#define TUSB_FTDI_SIO_H
|
||||
|
||||
// VID for matching FTDI devices
|
||||
#define TU_FTDI_VID 0x0403
|
||||
#include <stdint.h>
|
||||
|
||||
// Commands
|
||||
#define FTDI_SIO_RESET 0 /* Reset the port */
|
||||
#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
|
||||
#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */
|
||||
#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */
|
||||
#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */
|
||||
#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */
|
||||
#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */
|
||||
#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */
|
||||
#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */
|
||||
#define FTDI_SIO_GET_LATENCY_TIMER 0x0a /* Get the latency timer */
|
||||
#define FTDI_SIO_SET_BITMODE 0x0b /* Set bitbang mode */
|
||||
#define FTDI_SIO_READ_PINS 0x0c /* Read immediate value of pins */
|
||||
#define FTDI_SIO_READ_EEPROM 0x90 /* Read EEPROM */
|
||||
#define FTDI_SIO_RESET 0 // Reset the port
|
||||
#define FTDI_SIO_MODEM_CTRL 1 // Set the modem control register
|
||||
#define FTDI_SIO_SET_FLOW_CTRL 2 // Set flow control register
|
||||
#define FTDI_SIO_SET_BAUD_RATE 3 // Set baud rate
|
||||
#define FTDI_SIO_SET_DATA 4 // Set the data characteristics of the port
|
||||
#define FTDI_SIO_GET_MODEM_STATUS 5 // Retrieve current value of modem status register
|
||||
#define FTDI_SIO_SET_EVENT_CHAR 6 // Set the event character
|
||||
#define FTDI_SIO_SET_ERROR_CHAR 7 // Set the error character
|
||||
#define FTDI_SIO_SET_LATENCY_TIMER 9 // Set the latency timer
|
||||
#define FTDI_SIO_GET_LATENCY_TIMER 10 // Get the latency timer
|
||||
#define FTDI_SIO_SET_BITMODE 11 // Set bitbang mode
|
||||
#define FTDI_SIO_READ_PINS 12 // Read immediate value of pins
|
||||
#define FTDI_SIO_READ_EEPROM 0x90 // Read EEPROM
|
||||
|
||||
/* FTDI_SIO_RESET */
|
||||
#define FTDI_SIO_RESET_SIO 0
|
||||
#define FTDI_SIO_RESET_PURGE_RX 1
|
||||
#define FTDI_SIO_RESET_PURGE_TX 2
|
||||
// Channel indices for FT2232, FT2232H and FT4232H devices
|
||||
#define CHANNEL_A 1
|
||||
#define CHANNEL_B 2
|
||||
#define CHANNEL_C 3
|
||||
#define CHANNEL_D 4
|
||||
|
||||
/*
|
||||
* BmRequestType: 0100 0000B
|
||||
* bRequest: FTDI_SIO_RESET
|
||||
* wValue: Control Value
|
||||
* 0 = Reset SIO
|
||||
* 1 = Purge RX buffer
|
||||
* 2 = Purge TX buffer
|
||||
* wIndex: Port
|
||||
* wLength: 0
|
||||
* Data: None
|
||||
*
|
||||
* The Reset SIO command has this effect:
|
||||
*
|
||||
* Sets flow control set to 'none'
|
||||
* Event char = $0D
|
||||
* Event trigger = disabled
|
||||
* Purge RX buffer
|
||||
* Purge TX buffer
|
||||
* Clear DTR
|
||||
* Clear RTS
|
||||
* baud and data format not reset
|
||||
*
|
||||
* The Purge RX and TX buffer commands affect nothing except the buffers
|
||||
*
|
||||
*/
|
||||
// Port Identifier Table
|
||||
#define PIT_DEFAULT 0 // SIOA
|
||||
#define PIT_SIOA 1 // SIOA
|
||||
// The device this driver is tested with one has only one port
|
||||
#define PIT_SIOB 2 // SIOB
|
||||
#define PIT_PARALLEL 3 // Parallel
|
||||
|
||||
/* FTDI_SIO_MODEM_CTRL */
|
||||
/*
|
||||
* BmRequestType: 0100 0000B
|
||||
* bRequest: FTDI_SIO_MODEM_CTRL
|
||||
* wValue: ControlValue (see below)
|
||||
* wIndex: Port
|
||||
* wLength: 0
|
||||
* Data: None
|
||||
*
|
||||
* NOTE: If the device is in RTS/CTS flow control, the RTS set by this
|
||||
* command will be IGNORED without an error being returned
|
||||
* Also - you can not set DTR and RTS with one control message
|
||||
*/
|
||||
// FTDI_SIO_RESET
|
||||
#define FTDI_SIO_RESET_REQUEST FTDI_SIO_RESET
|
||||
#define FTDI_SIO_RESET_REQUEST_TYPE 0x40
|
||||
#define FTDI_SIO_RESET_SIO 0
|
||||
#define FTDI_SIO_RESET_PURGE_RX 1
|
||||
#define FTDI_SIO_RESET_PURGE_TX 2
|
||||
|
||||
#define FTDI_SIO_SET_DTR_MASK 0x1
|
||||
#define FTDI_SIO_SET_DTR_HIGH ((FTDI_SIO_SET_DTR_MASK << 8) | 1)
|
||||
#define FTDI_SIO_SET_DTR_LOW ((FTDI_SIO_SET_DTR_MASK << 8) | 0)
|
||||
#define FTDI_SIO_SET_RTS_MASK 0x2
|
||||
#define FTDI_SIO_SET_RTS_HIGH ((FTDI_SIO_SET_RTS_MASK << 8) | 2)
|
||||
#define FTDI_SIO_SET_RTS_LOW ((FTDI_SIO_SET_RTS_MASK << 8) | 0)
|
||||
// FTDI_SIO_SET_BAUDRATE
|
||||
#define FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE 0x40
|
||||
#define FTDI_SIO_SET_BAUDRATE_REQUEST 3
|
||||
|
||||
/*
|
||||
* ControlValue
|
||||
* B0 DTR state
|
||||
* 0 = reset
|
||||
* 1 = set
|
||||
* B1 RTS state
|
||||
* 0 = reset
|
||||
* 1 = set
|
||||
* B2..7 Reserved
|
||||
* B8 DTR state enable
|
||||
* 0 = ignore
|
||||
* 1 = use DTR state
|
||||
* B9 RTS state enable
|
||||
* 0 = ignore
|
||||
* 1 = use RTS state
|
||||
* B10..15 Reserved
|
||||
*/
|
||||
enum ftdi_sio_baudrate {
|
||||
ftdi_sio_b300 = 0,
|
||||
ftdi_sio_b600 = 1,
|
||||
ftdi_sio_b1200 = 2,
|
||||
ftdi_sio_b2400 = 3,
|
||||
ftdi_sio_b4800 = 4,
|
||||
ftdi_sio_b9600 = 5,
|
||||
ftdi_sio_b19200 = 6,
|
||||
ftdi_sio_b38400 = 7,
|
||||
ftdi_sio_b57600 = 8,
|
||||
ftdi_sio_b115200 = 9
|
||||
};
|
||||
|
||||
/* FTDI_SIO_SET_FLOW_CTRL */
|
||||
#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0
|
||||
#define FTDI_SIO_RTS_CTS_HS (0x1 << 8)
|
||||
#define FTDI_SIO_DTR_DSR_HS (0x2 << 8)
|
||||
#define FTDI_SIO_XON_XOFF_HS (0x4 << 8)
|
||||
// FTDI_SIO_SET_DATA
|
||||
#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA
|
||||
#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40
|
||||
#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8)
|
||||
#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8)
|
||||
#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8)
|
||||
#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8)
|
||||
#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8)
|
||||
#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) // same coding as ACM
|
||||
#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) // 1.5 not supported, for future use?
|
||||
#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11)
|
||||
#define FTDI_SIO_SET_BREAK (0x1 << 14)
|
||||
|
||||
/*
|
||||
* BmRequestType: 0100 0000b
|
||||
* bRequest: FTDI_SIO_SET_FLOW_CTRL
|
||||
* wValue: Xoff/Xon
|
||||
* wIndex: Protocol/Port - hIndex is protocol / lIndex is port
|
||||
* wLength: 0
|
||||
* Data: None
|
||||
*
|
||||
* hIndex protocol is:
|
||||
* B0 Output handshaking using RTS/CTS
|
||||
* 0 = disabled
|
||||
* 1 = enabled
|
||||
* B1 Output handshaking using DTR/DSR
|
||||
* 0 = disabled
|
||||
* 1 = enabled
|
||||
* B2 Xon/Xoff handshaking
|
||||
* 0 = disabled
|
||||
* 1 = enabled
|
||||
*
|
||||
* A value of zero in the hIndex field disables handshaking
|
||||
*
|
||||
* If Xon/Xoff handshaking is specified, the hValue field should contain the
|
||||
* XOFF character and the lValue field contains the XON character.
|
||||
*/
|
||||
// FTDI_SIO_MODEM_CTRL
|
||||
#define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40
|
||||
#define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL
|
||||
|
||||
/* FTDI_SIO_SET_BAUD_RATE */
|
||||
/*
|
||||
* BmRequestType: 0100 0000B
|
||||
* bRequest: FTDI_SIO_SET_BAUDRATE
|
||||
* wValue: BaudDivisor value - see below
|
||||
* wIndex: Port
|
||||
* wLength: 0
|
||||
* Data: None
|
||||
* The BaudDivisor values are calculated as follows (too complicated):
|
||||
*/
|
||||
#define FTDI_SIO_SET_DTR_MASK 0x1UL
|
||||
#define FTDI_SIO_SET_DTR_HIGH ((FTDI_SIO_SET_DTR_MASK << 8) | 1UL)
|
||||
#define FTDI_SIO_SET_DTR_LOW ((FTDI_SIO_SET_DTR_MASK << 8) | 0UL)
|
||||
#define FTDI_SIO_SET_RTS_MASK 0x2UL
|
||||
#define FTDI_SIO_SET_RTS_HIGH ((FTDI_SIO_SET_RTS_MASK << 8) | 2UL)
|
||||
#define FTDI_SIO_SET_RTS_LOW ((FTDI_SIO_SET_RTS_MASK << 8) | 0UL)
|
||||
|
||||
/* FTDI_SIO_SET_DATA */
|
||||
#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8)
|
||||
#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8)
|
||||
#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8)
|
||||
#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8)
|
||||
#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8)
|
||||
#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11)
|
||||
#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11)
|
||||
#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11)
|
||||
#define FTDI_SIO_SET_BREAK (0x1 << 14)
|
||||
// FTDI_SIO_SET_FLOW_CTRL
|
||||
#define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40
|
||||
#define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL
|
||||
#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0
|
||||
#define FTDI_SIO_RTS_CTS_HS (0x1 << 8)
|
||||
#define FTDI_SIO_DTR_DSR_HS (0x2 << 8)
|
||||
#define FTDI_SIO_XON_XOFF_HS (0x4 << 8)
|
||||
|
||||
/*
|
||||
* BmRequestType: 0100 0000B
|
||||
* bRequest: FTDI_SIO_SET_DATA
|
||||
* wValue: Data characteristics (see below)
|
||||
* wIndex: Port
|
||||
* wLength: 0
|
||||
* Data: No
|
||||
*
|
||||
* Data characteristics
|
||||
*
|
||||
* B0..7 Number of data bits
|
||||
* B8..10 Parity
|
||||
* 0 = None
|
||||
* 1 = Odd
|
||||
* 2 = Even
|
||||
* 3 = Mark
|
||||
* 4 = Space
|
||||
* B11..13 Stop Bits
|
||||
* 0 = 1
|
||||
* 1 = 1.5
|
||||
* 2 = 2
|
||||
* B14
|
||||
* 1 = TX ON (break)
|
||||
* 0 = TX OFF (normal state)
|
||||
* B15 Reserved
|
||||
*
|
||||
*/
|
||||
// FTDI_SIO_GET_LATENCY_TIMER
|
||||
#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST FTDI_SIO_GET_LATENCY_TIMER
|
||||
#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE 0xC0
|
||||
|
||||
/*
|
||||
* DATA FORMAT
|
||||
*
|
||||
* IN Endpoint
|
||||
*
|
||||
* The device reserves the first two bytes of data on this endpoint to contain
|
||||
* the current values of the modem and line status registers. In the absence of
|
||||
* data, the device generates a message consisting of these two status bytes
|
||||
* every 40 ms
|
||||
*
|
||||
* Byte 0: Modem Status
|
||||
*
|
||||
* Offset Description
|
||||
* B0 Reserved - must be 1
|
||||
* B1 Reserved - must be 0
|
||||
* B2 Reserved - must be 0
|
||||
* B3 Reserved - must be 0
|
||||
* B4 Clear to Send (CTS)
|
||||
* B5 Data Set Ready (DSR)
|
||||
* B6 Ring Indicator (RI)
|
||||
* B7 Receive Line Signal Detect (RLSD)
|
||||
*
|
||||
* Byte 1: Line Status
|
||||
*
|
||||
* Offset Description
|
||||
* B0 Data Ready (DR)
|
||||
* B1 Overrun Error (OE)
|
||||
* B2 Parity Error (PE)
|
||||
* B3 Framing Error (FE)
|
||||
* B4 Break Interrupt (BI)
|
||||
* B5 Transmitter Holding Register (THRE)
|
||||
* B6 Transmitter Empty (TEMT)
|
||||
* B7 Error in RCVR FIFO
|
||||
*
|
||||
*/
|
||||
#define FTDI_RS0_CTS (1 << 4)
|
||||
#define FTDI_RS0_DSR (1 << 5)
|
||||
#define FTDI_RS0_RI (1 << 6)
|
||||
#define FTDI_RS0_RLSD (1 << 7)
|
||||
// FTDI_SIO_SET_LATENCY_TIMER
|
||||
#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER
|
||||
#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40
|
||||
|
||||
#define FTDI_RS_DR 1
|
||||
#define FTDI_RS_OE (1<<1)
|
||||
#define FTDI_RS_PE (1<<2)
|
||||
#define FTDI_RS_FE (1<<3)
|
||||
#define FTDI_RS_BI (1<<4)
|
||||
#define FTDI_RS_THRE (1<<5)
|
||||
#define FTDI_RS_TEMT (1<<6)
|
||||
#define FTDI_RS_FIFO (1<<7)
|
||||
// FTDI_SIO_SET_EVENT_CHAR
|
||||
#define FTDI_SIO_SET_EVENT_CHAR_REQUEST FTDI_SIO_SET_EVENT_CHAR
|
||||
#define FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40
|
||||
|
||||
// FTDI_SIO_GET_MODEM_STATUS
|
||||
#define FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE 0xc0
|
||||
#define FTDI_SIO_GET_MODEM_STATUS_REQUEST FTDI_SIO_GET_MODEM_STATUS
|
||||
#define FTDI_SIO_CTS_MASK 0x10
|
||||
#define FTDI_SIO_DSR_MASK 0x20
|
||||
#define FTDI_SIO_RI_MASK 0x40
|
||||
#define FTDI_SIO_RLSD_MASK 0x80
|
||||
|
||||
// FTDI_SIO_SET_BITMODE
|
||||
#define FTDI_SIO_SET_BITMODE_REQUEST_TYPE 0x40
|
||||
#define FTDI_SIO_SET_BITMODE_REQUEST FTDI_SIO_SET_BITMODE
|
||||
|
||||
// Possible bitmodes for FTDI_SIO_SET_BITMODE_REQUEST
|
||||
#define FTDI_SIO_BITMODE_RESET 0x00
|
||||
#define FTDI_SIO_BITMODE_CBUS 0x20
|
||||
|
||||
// FTDI_SIO_READ_PINS
|
||||
#define FTDI_SIO_READ_PINS_REQUEST_TYPE 0xc0
|
||||
#define FTDI_SIO_READ_PINS_REQUEST FTDI_SIO_READ_PINS
|
||||
|
||||
// FTDI_SIO_READ_EEPROM
|
||||
#define FTDI_SIO_READ_EEPROM_REQUEST_TYPE 0xc0
|
||||
#define FTDI_SIO_READ_EEPROM_REQUEST FTDI_SIO_READ_EEPROM
|
||||
|
||||
#define FTDI_FTX_CBUS_MUX_GPIO 0x8
|
||||
#define FTDI_FT232R_CBUS_MUX_GPIO 0xa
|
||||
|
||||
#define FTDI_RS0_CTS (1 << 4)
|
||||
#define FTDI_RS0_DSR (1 << 5)
|
||||
#define FTDI_RS0_RI (1 << 6)
|
||||
#define FTDI_RS0_RLSD (1 << 7)
|
||||
|
||||
#define FTDI_RS_DR 1
|
||||
#define FTDI_RS_OE (1 << 1)
|
||||
#define FTDI_RS_PE (1 << 2)
|
||||
#define FTDI_RS_FE (1 << 3)
|
||||
#define FTDI_RS_BI (1 << 4)
|
||||
#define FTDI_RS_THRE (1 << 5)
|
||||
#define FTDI_RS_TEMT (1 << 6)
|
||||
#define FTDI_RS_FIFO (1 << 7)
|
||||
|
||||
// chip types and names
|
||||
typedef enum ftdi_chip_type {
|
||||
FTDI_SIO = 0,
|
||||
// FTDI_FT232A,
|
||||
FTDI_FT232B,
|
||||
FTDI_FT2232C,
|
||||
FTDI_FT232R,
|
||||
FTDI_FT232H,
|
||||
FTDI_FT2232H,
|
||||
FTDI_FT4232H,
|
||||
FTDI_FT4232HA,
|
||||
FTDI_FT232HP,
|
||||
FTDI_FT233HP,
|
||||
FTDI_FT2232HP,
|
||||
FTDI_FT2233HP,
|
||||
FTDI_FT4232HP,
|
||||
FTDI_FT4233HP,
|
||||
FTDI_FTX,
|
||||
FTDI_UNKNOWN
|
||||
} ftdi_chip_type_t;
|
||||
|
||||
#define FTDI_CHIP_NAMES \
|
||||
[FTDI_SIO] = "SIO", /* the serial part of FT8U100AX */ \
|
||||
/* [FTDI_FT232A] = "FT232A", */ \
|
||||
[FTDI_FT232B] = "FT232B", \
|
||||
[FTDI_FT2232C] = "FT2232C/D", \
|
||||
[FTDI_FT232R] = "FT232R", \
|
||||
[FTDI_FT232H] = "FT232H", \
|
||||
[FTDI_FT2232H] = "FTDI_FT2232H", \
|
||||
[FTDI_FT4232H] = "FT4232H", \
|
||||
[FTDI_FT4232HA] = "FT4232HA", \
|
||||
[FTDI_FT232HP] = "FT232HP", \
|
||||
[FTDI_FT233HP] = "FT233HP", \
|
||||
[FTDI_FT2232HP] = "FT2232HP", \
|
||||
[FTDI_FT2233HP] = "FT2233HP", \
|
||||
[FTDI_FT4232HP] = "FT4232HP", \
|
||||
[FTDI_FT4233HP] = "FT4233HP", \
|
||||
[FTDI_FTX] = "FT-X", \
|
||||
[FTDI_UNKNOWN] = "UNKNOWN"
|
||||
|
||||
// private interface data
|
||||
typedef struct ftdi_private {
|
||||
ftdi_chip_type_t chip_type;
|
||||
uint8_t channel; // channel index, or 0 for legacy types
|
||||
} ftdi_private_t;
|
||||
|
||||
#define FTDI_OK true
|
||||
#define FTDI_FAIL false
|
||||
#define FTDI_NOT_POSSIBLE -1
|
||||
#define FTDI_REQUESTED -2
|
||||
|
||||
// division and round function overtaken from math.h
|
||||
#define DIV_ROUND_CLOSEST(x, divisor)( \
|
||||
{ \
|
||||
typeof(x) __x = x; \
|
||||
typeof(divisor) __d = divisor; \
|
||||
(((typeof(x))-1) > 0 || \
|
||||
((typeof(divisor))-1) > 0 || \
|
||||
(((__x) > 0) == ((__d) > 0))) ? \
|
||||
(((__x) + ((__d) / 2)) / (__d)) : \
|
||||
(((__x) - ((__d) / 2)) / (__d)); \
|
||||
} \
|
||||
)
|
||||
|
||||
#endif //TUSB_FTDI_SIO_H
|
||||
|
159
src/class/cdc/serial/pl2303.h
Normal file
159
src/class/cdc/serial/pl2303.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2024 Heiko Kuester
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TUSB_PL2303_H
|
||||
#define TUSB_PL2303_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// There is no official documentation for the PL2303 chips.
|
||||
// Reference can be found
|
||||
// - https://github.com/torvalds/linux/blob/master/drivers/usb/serial/pl2303.h and
|
||||
// https://github.com/torvalds/linux/blob/master/drivers/usb/serial/pl2303.c
|
||||
// - https://github.com/freebsd/freebsd-src/blob/main/sys/dev/usb/serial/uplcom.c
|
||||
|
||||
// quirks
|
||||
#define PL2303_QUIRK_UART_STATE_IDX0 1
|
||||
#define PL2303_QUIRK_LEGACY 2
|
||||
#define PL2303_QUIRK_ENDPOINT_HACK 4
|
||||
|
||||
// requests and bits
|
||||
#define PL2303_SET_LINE_REQUEST_TYPE 0x21 // class request host to device interface
|
||||
#define PL2303_SET_LINE_REQUEST 0x20 // dec 32
|
||||
|
||||
#define PL2303_SET_CONTROL_REQUEST_TYPE 0x21 // class request host to device interface
|
||||
#define PL2303_SET_CONTROL_REQUEST 0x22 // dec 34
|
||||
#define PL2303_CONTROL_DTR 0x01 // dec 1
|
||||
#define PL2303_CONTROL_RTS 0x02 // dec 2
|
||||
|
||||
#define PL2303_BREAK_REQUEST_TYPE 0x21 // class request host to device interface
|
||||
#define PL2303_BREAK_REQUEST 0x23 // dec 35
|
||||
#define PL2303_BREAK_ON 0xffff
|
||||
#define PL2303_BREAK_OFF 0x0000
|
||||
|
||||
#define PL2303_GET_LINE_REQUEST_TYPE 0xa1 // class request device to host interface
|
||||
#define PL2303_GET_LINE_REQUEST 0x21 // dec 33
|
||||
|
||||
#define PL2303_VENDOR_WRITE_REQUEST_TYPE 0x40 // vendor request host to device interface
|
||||
#define PL2303_VENDOR_WRITE_REQUEST 0x01 // dec 1
|
||||
#define PL2303_VENDOR_WRITE_NREQUEST 0x80 // dec 128
|
||||
|
||||
#define PL2303_VENDOR_READ_REQUEST_TYPE 0xc0 // vendor request device to host interface
|
||||
#define PL2303_VENDOR_READ_REQUEST 0x01 // dec 1
|
||||
#define PL2303_VENDOR_READ_NREQUEST 0x81 // dec 129
|
||||
|
||||
#define PL2303_UART_STATE_INDEX 8
|
||||
#define PL2303_UART_STATE_MSR_MASK 0x8b
|
||||
#define PL2303_UART_STATE_TRANSIENT_MASK 0x74
|
||||
#define PL2303_UART_DCD 0x01
|
||||
#define PL2303_UART_DSR 0x02
|
||||
#define PL2303_UART_BREAK_ERROR 0x04
|
||||
#define PL2303_UART_RING 0x08
|
||||
#define PL2303_UART_FRAME_ERROR 0x10
|
||||
#define PL2303_UART_PARITY_ERROR 0x20
|
||||
#define PL2303_UART_OVERRUN_ERROR 0x40
|
||||
#define PL2303_UART_CTS 0x80
|
||||
|
||||
#define PL2303_FLOWCTRL_MASK 0xf0
|
||||
|
||||
#define PL2303_CLEAR_HALT_REQUEST_TYPE 0x02 // standard request host to device endpoint
|
||||
|
||||
// registers via vendor read/write requests
|
||||
#define PL2303_READ_TYPE_HX_STATUS 0x8080
|
||||
|
||||
#define PL2303_HXN_RESET_REG 0x07
|
||||
#define PL2303_HXN_RESET_UPSTREAM_PIPE 0x02
|
||||
#define PL2303_HXN_RESET_DOWNSTREAM_PIPE 0x01
|
||||
|
||||
#define PL2303_HXN_FLOWCTRL_REG 0x0a
|
||||
#define PL2303_HXN_FLOWCTRL_MASK 0x1c
|
||||
#define PL2303_HXN_FLOWCTRL_NONE 0x1c
|
||||
#define PL2303_HXN_FLOWCTRL_RTS_CTS 0x18
|
||||
#define PL2303_HXN_FLOWCTRL_XON_XOFF 0x0c
|
||||
|
||||
// type data
|
||||
typedef enum pl2303_type {
|
||||
PL2303_TYPE_H = 0, // 0
|
||||
PL2303_TYPE_HX, // 1
|
||||
PL2303_TYPE_TA, // 2
|
||||
PL2303_TYPE_TB, // 3
|
||||
PL2303_TYPE_HXD, // 4
|
||||
PL2303_TYPE_HXN, // 5
|
||||
PL2303_TYPE_COUNT,
|
||||
PL2303_TYPE_NEED_SUPPORTS_HX_STATUS,
|
||||
PL2303_TYPE_UNKNOWN,
|
||||
} pl2303_type_t;
|
||||
|
||||
typedef struct pl2303_type_data {
|
||||
uint32_t max_baud_rate;
|
||||
uint8_t quirks;
|
||||
uint8_t no_autoxonxoff : 1;
|
||||
uint8_t no_divisors : 1;
|
||||
uint8_t alt_divisors : 1;
|
||||
} pl2303_type_data_t;
|
||||
|
||||
#define PL2303_TYPE_DATA \
|
||||
[PL2303_TYPE_H] = { \
|
||||
.max_baud_rate = 1228800, .quirks = PL2303_QUIRK_LEGACY, \
|
||||
.no_autoxonxoff = 1, .no_divisors = 0, .alt_divisors = 0 \
|
||||
}, \
|
||||
[PL2303_TYPE_HX] = { \
|
||||
.max_baud_rate = 6000000, .quirks = 0, \
|
||||
.no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 0 \
|
||||
}, \
|
||||
[PL2303_TYPE_TA] = { \
|
||||
.max_baud_rate = 6000000, .quirks = 0, \
|
||||
.no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 1 \
|
||||
}, \
|
||||
[PL2303_TYPE_TB] = { \
|
||||
.max_baud_rate = 12000000, .quirks = 0, \
|
||||
.no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 1 \
|
||||
}, \
|
||||
[PL2303_TYPE_HXD] = { \
|
||||
.max_baud_rate = 12000000, .quirks = 0, \
|
||||
.no_autoxonxoff = 0, .no_divisors = 0, .alt_divisors = 0 \
|
||||
}, \
|
||||
[PL2303_TYPE_HXN] = { \
|
||||
.max_baud_rate = 12000000, .quirks = 0, \
|
||||
.no_autoxonxoff = 0, .no_divisors = 1, .alt_divisors = 0 \
|
||||
}
|
||||
|
||||
typedef struct TU_ATTR_PACKED {
|
||||
pl2303_type_t type;
|
||||
uint8_t quirks;
|
||||
bool supports_hx_status;
|
||||
} pl2303_private_t;
|
||||
|
||||
// buffer sizes for line coding data
|
||||
#define PL2303_LINE_CODING_BUFSIZE 7
|
||||
#define PL2303_LINE_CODING_BAUDRATE_BUFSIZE 4
|
||||
|
||||
// bulk endpoints
|
||||
#define PL2303_OUT_EP 0x02
|
||||
#define PL2303_IN_EP 0x83
|
||||
|
||||
#endif // TUSB_PL2303_H
|
@@ -53,23 +53,26 @@ enum {
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
TU_ATTR_ALIGNED(4) msc_cbw_t cbw;
|
||||
TU_ATTR_ALIGNED(4) msc_csw_t csw;
|
||||
TU_ATTR_ALIGNED(4) msc_cbw_t cbw; // 31 bytes
|
||||
uint8_t rhport;
|
||||
|
||||
TU_ATTR_ALIGNED(4) msc_csw_t csw; // 13 bytes
|
||||
uint8_t itf_num;
|
||||
uint8_t ep_in;
|
||||
uint8_t ep_out;
|
||||
|
||||
// Bulk Only Transfer (BOT) Protocol
|
||||
uint8_t stage;
|
||||
|
||||
uint32_t total_len; // byte to be transferred, can be smaller than total_bytes in cbw
|
||||
uint32_t xferred_len; // numbered of bytes transferred so far in the Data Stage
|
||||
|
||||
// Sense Response Data
|
||||
// Bulk Only Transfer (BOT) Protocol
|
||||
uint8_t stage;
|
||||
|
||||
// SCSI Sense Response Data
|
||||
uint8_t sense_key;
|
||||
uint8_t add_sense_code;
|
||||
uint8_t add_sense_qualifier;
|
||||
|
||||
uint8_t pending_io; // pending async IO
|
||||
}mscd_interface_t;
|
||||
|
||||
static mscd_interface_t _mscd_itf;
|
||||
@@ -82,31 +85,36 @@ CFG_TUD_MEM_SECTION static struct {
|
||||
// INTERNAL OBJECT & FUNCTION DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize);
|
||||
static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc);
|
||||
|
||||
static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc);
|
||||
static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes);
|
||||
static void proc_read10_cmd(mscd_interface_t* p_msc);
|
||||
static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes);
|
||||
static void proc_write10_cmd(mscd_interface_t* p_msc);
|
||||
static void proc_write10_host_data(mscd_interface_t* p_msc, uint32_t xferred_bytes);
|
||||
static void proc_write_io_data(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes);
|
||||
static bool proc_stage_status(mscd_interface_t* p_msc);
|
||||
|
||||
TU_ATTR_ALWAYS_INLINE static inline bool is_data_in(uint8_t dir) {
|
||||
return tu_bit_test(dir, 7);
|
||||
}
|
||||
|
||||
static inline bool send_csw(uint8_t rhport, mscd_interface_t* p_msc) {
|
||||
static inline bool send_csw(mscd_interface_t* p_msc) {
|
||||
// Data residue is always = host expect - actual transferred
|
||||
uint8_t rhport = p_msc->rhport;
|
||||
p_msc->csw.data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len;
|
||||
p_msc->stage = MSC_STAGE_STATUS_SENT;
|
||||
memcpy(_mscd_epbuf.buf, &p_msc->csw, sizeof(msc_csw_t));
|
||||
return usbd_edpt_xfer(rhport, p_msc->ep_in , _mscd_epbuf.buf, sizeof(msc_csw_t));
|
||||
}
|
||||
|
||||
static inline bool prepare_cbw(uint8_t rhport, mscd_interface_t* p_msc) {
|
||||
static inline bool prepare_cbw(mscd_interface_t* p_msc) {
|
||||
uint8_t rhport = p_msc->rhport;
|
||||
p_msc->stage = MSC_STAGE_CMD;
|
||||
return usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, sizeof(msc_cbw_t));
|
||||
}
|
||||
|
||||
static void fail_scsi_op(uint8_t rhport, mscd_interface_t* p_msc, uint8_t status) {
|
||||
static void fail_scsi_op(mscd_interface_t* p_msc, uint8_t status) {
|
||||
msc_cbw_t const * p_cbw = &p_msc->cbw;
|
||||
msc_csw_t * p_csw = &p_msc->csw;
|
||||
uint8_t rhport = p_msc->rhport;
|
||||
|
||||
p_csw->status = status;
|
||||
p_csw->data_residue = p_msc->cbw.total_bytes - p_msc->xferred_len;
|
||||
@@ -177,6 +185,33 @@ static uint8_t rdwr10_validate_cmd(msc_cbw_t const* cbw) {
|
||||
return status;
|
||||
}
|
||||
|
||||
static bool proc_stage_status(mscd_interface_t *p_msc) {
|
||||
uint8_t rhport = p_msc->rhport;
|
||||
msc_cbw_t const *p_cbw = &p_msc->cbw;
|
||||
|
||||
// skip status if epin is currently stalled, will do it when received Clear Stall request
|
||||
if (!usbd_edpt_stalled(rhport, p_msc->ep_in)) {
|
||||
if ((p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir)) {
|
||||
// 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status
|
||||
// TU_LOG_DRV(" SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len);
|
||||
usbd_edpt_stall(rhport, p_msc->ep_in);
|
||||
} else {
|
||||
TU_ASSERT(send_csw(p_msc));
|
||||
}
|
||||
}
|
||||
|
||||
#if TU_CHECK_MCU(OPT_MCU_CXD56)
|
||||
// WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD.
|
||||
// There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and
|
||||
// hope everything will work
|
||||
if (usbd_edpt_stalled(rhport, p_msc->ep_in)) {
|
||||
usbd_edpt_clear_stall(rhport, p_msc->ep_in);
|
||||
send_csw(p_msc);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Debug
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -214,15 +249,51 @@ bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, u
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void set_sense_medium_not_present(uint8_t lun) {
|
||||
TU_ATTR_ALWAYS_INLINE static inline void set_sense_medium_not_present(uint8_t lun) {
|
||||
// default sense is NOT READY, MEDIUM NOT PRESENT
|
||||
tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00);
|
||||
}
|
||||
|
||||
static void proc_async_io_done(void *bytes_io) {
|
||||
mscd_interface_t *p_msc = &_mscd_itf;
|
||||
TU_VERIFY(p_msc->pending_io, );
|
||||
const int32_t nbytes = (int32_t) (intptr_t) bytes_io;
|
||||
const uint8_t cmd = p_msc->cbw.command[0];
|
||||
|
||||
p_msc->pending_io = 0;
|
||||
switch (cmd) {
|
||||
case SCSI_CMD_READ_10:
|
||||
proc_read_io_data(p_msc, nbytes);
|
||||
break;
|
||||
|
||||
case SCSI_CMD_WRITE_10:
|
||||
proc_write_io_data(p_msc, (uint32_t) nbytes, nbytes);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
// send status if stage is transitioned to STATUS
|
||||
if (p_msc->stage == MSC_STAGE_STATUS) {
|
||||
proc_stage_status(p_msc);
|
||||
}
|
||||
}
|
||||
|
||||
bool tud_msc_async_io_done(int32_t bytes_io, bool in_isr) {
|
||||
// Precheck to avoid queueing multiple RW done callback
|
||||
TU_VERIFY(_mscd_itf.pending_io);
|
||||
if (bytes_io == 0) {
|
||||
bytes_io = TUD_MSC_RET_ERROR; // 0 is treated as error, no reason to call this with BUSY here
|
||||
}
|
||||
usbd_defer_func(proc_async_io_done, (void *) (intptr_t) bytes_io, in_isr);
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBD Driver API
|
||||
//--------------------------------------------------------------------+
|
||||
void mscd_init(void) {
|
||||
TU_LOG_INT(CFG_TUD_MSC_LOG_LEVEL, sizeof(mscd_interface_t));
|
||||
tu_memclr(&_mscd_itf, sizeof(mscd_interface_t));
|
||||
}
|
||||
|
||||
@@ -245,12 +316,13 @@ uint16_t mscd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
|
||||
|
||||
mscd_interface_t * p_msc = &_mscd_itf;
|
||||
p_msc->itf_num = itf_desc->bInterfaceNumber;
|
||||
p_msc->rhport = rhport;
|
||||
|
||||
// Open endpoint pair
|
||||
TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(itf_desc), 2, TUSB_XFER_BULK, &p_msc->ep_out, &p_msc->ep_in), 0);
|
||||
|
||||
// Prepare for Command Block Wrapper
|
||||
TU_ASSERT(prepare_cbw(rhport, p_msc), drv_len);
|
||||
TU_ASSERT(prepare_cbw(p_msc), drv_len);
|
||||
|
||||
return drv_len;
|
||||
}
|
||||
@@ -289,14 +361,14 @@ bool mscd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
|
||||
if (ep_addr == p_msc->ep_in) {
|
||||
if (p_msc->stage == MSC_STAGE_STATUS) {
|
||||
// resume sending SCSI status if we are in this stage previously before stalled
|
||||
TU_ASSERT(send_csw(rhport, p_msc));
|
||||
TU_ASSERT(send_csw(p_msc));
|
||||
}
|
||||
} else if (ep_addr == p_msc->ep_out) {
|
||||
if (p_msc->stage == MSC_STAGE_CMD) {
|
||||
// part of reset recovery (probably due to invalid CBW) -> prepare for new command
|
||||
// Note: skip if already queued previously
|
||||
if (usbd_edpt_ready(rhport, p_msc->ep_out)) {
|
||||
TU_ASSERT(prepare_cbw(rhport, p_msc));
|
||||
TU_ASSERT(prepare_cbw(p_msc));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -382,12 +454,12 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
uint8_t const status = rdwr10_validate_cmd(p_cbw);
|
||||
|
||||
if (status != MSC_CSW_STATUS_PASSED) {
|
||||
fail_scsi_op(rhport, p_msc, status);
|
||||
fail_scsi_op(p_msc, status);
|
||||
} else if (p_cbw->total_bytes) {
|
||||
if (SCSI_CMD_READ_10 == p_cbw->command[0]) {
|
||||
proc_read10_cmd(rhport, p_msc);
|
||||
proc_read10_cmd(p_msc);
|
||||
} else {
|
||||
proc_write10_cmd(rhport, p_msc);
|
||||
proc_write10_cmd(p_msc);
|
||||
}
|
||||
} else {
|
||||
// no data transfer, only exist in complaint test suite
|
||||
@@ -400,7 +472,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
if ((p_cbw->total_bytes > 0) && !is_data_in(p_cbw->dir)) {
|
||||
if (p_cbw->total_bytes > CFG_TUD_MSC_EP_BUFSIZE) {
|
||||
TU_LOG_DRV(" SCSI reject non READ10/WRITE10 with large data\r\n");
|
||||
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
|
||||
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
|
||||
} else {
|
||||
// Didn't check for case 9 (Ho > Dn), which requires examining scsi command first
|
||||
// but it is OK to just receive data then responded with failed status
|
||||
@@ -418,12 +490,12 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
if (resplen < 0) {
|
||||
// unsupported command
|
||||
TU_LOG_DRV(" SCSI unsupported or failed command\r\n");
|
||||
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
|
||||
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
|
||||
} else if (resplen == 0) {
|
||||
if (p_cbw->total_bytes) {
|
||||
// 6.7 The 13 Cases: case 4 (Hi > Dn)
|
||||
// TU_LOG_DRV(" SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes);
|
||||
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
|
||||
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
|
||||
} else {
|
||||
// case 1 Hn = Dn: all good
|
||||
p_msc->stage = MSC_STAGE_STATUS;
|
||||
@@ -432,7 +504,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
if (p_cbw->total_bytes == 0) {
|
||||
// 6.7 The 13 Cases: case 2 (Hn < Di)
|
||||
// TU_LOG_DRV(" SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes);
|
||||
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
|
||||
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
|
||||
} else {
|
||||
// cannot return more than host expect
|
||||
p_msc->total_len = tu_min32((uint32_t)resplen, p_cbw->total_bytes);
|
||||
@@ -456,10 +528,10 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
// Data Stage is complete
|
||||
p_msc->stage = MSC_STAGE_STATUS;
|
||||
}else {
|
||||
proc_read10_cmd(rhport, p_msc);
|
||||
proc_read10_cmd(p_msc);
|
||||
}
|
||||
} else if (SCSI_CMD_WRITE_10 == p_cbw->command[0]) {
|
||||
proc_write10_new_data(rhport, p_msc, xferred_bytes);
|
||||
proc_write10_host_data(p_msc, xferred_bytes);
|
||||
} else {
|
||||
p_msc->xferred_len += xferred_bytes;
|
||||
|
||||
@@ -470,7 +542,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
if ( cb_result < 0 ) {
|
||||
// unsupported command
|
||||
TU_LOG_DRV(" SCSI unsupported command\r\n");
|
||||
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
|
||||
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
|
||||
}else {
|
||||
// TODO haven't implement this scenario any further yet
|
||||
}
|
||||
@@ -491,7 +563,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
break;
|
||||
|
||||
case MSC_STAGE_STATUS_SENT:
|
||||
// Wait for the Status phase to complete
|
||||
// Status phase is complete
|
||||
if ((ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t))) {
|
||||
TU_LOG_DRV(" SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status);
|
||||
// TU_LOG_MEM(CFG_TUD_MSC_LOG_LEVEL, p_csw, xferred_bytes, 2);
|
||||
@@ -519,9 +591,9 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
break;
|
||||
}
|
||||
|
||||
TU_ASSERT(prepare_cbw(rhport, p_msc));
|
||||
TU_ASSERT(prepare_cbw(p_msc));
|
||||
} else {
|
||||
// Any xfer ended here is consider unknown error, ignore it
|
||||
// Any xfer ended here is considered unknown error, ignore it
|
||||
TU_LOG1(" Warning expect SCSI Status but received unknown data\r\n");
|
||||
}
|
||||
break;
|
||||
@@ -530,26 +602,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
|
||||
}
|
||||
|
||||
if (p_msc->stage == MSC_STAGE_STATUS) {
|
||||
// skip status if epin is currently stalled, will do it when received Clear Stall request
|
||||
if (!usbd_edpt_stalled(rhport, p_msc->ep_in)) {
|
||||
if ((p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir)) {
|
||||
// 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status
|
||||
// TU_LOG_DRV(" SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len);
|
||||
usbd_edpt_stall(rhport, p_msc->ep_in);
|
||||
} else {
|
||||
TU_ASSERT(send_csw(rhport, p_msc));
|
||||
}
|
||||
}
|
||||
|
||||
#if TU_CHECK_MCU(OPT_MCU_CXD56)
|
||||
// WORKAROUND: cxd56 has its own nuttx usb stack which does not forward Set/ClearFeature(Endpoint) to DCD.
|
||||
// There is no way for us to know when EP is un-stall, therefore we will unconditionally un-stall here and
|
||||
// hope everything will work
|
||||
if ( usbd_edpt_stalled(rhport, p_msc->ep_in) ) {
|
||||
usbd_edpt_clear_stall(rhport, p_msc->ep_in);
|
||||
send_csw(rhport, p_msc);
|
||||
}
|
||||
#endif
|
||||
TU_ASSERT(proc_stage_status(p_msc));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -646,8 +699,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
|
||||
break;
|
||||
|
||||
case SCSI_CMD_READ_FORMAT_CAPACITY: {
|
||||
scsi_read_format_capacity_data_t read_fmt_capa =
|
||||
{
|
||||
scsi_read_format_capacity_data_t read_fmt_capa = {
|
||||
.list_length = 8,
|
||||
.block_num = 0,
|
||||
.descriptor_type = 2, // formatted media
|
||||
@@ -679,8 +731,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
|
||||
break;
|
||||
|
||||
case SCSI_CMD_INQUIRY: {
|
||||
scsi_inquiry_resp_t inquiry_rsp =
|
||||
{
|
||||
scsi_inquiry_resp_t inquiry_rsp = {
|
||||
.is_removable = 1,
|
||||
.version = 2,
|
||||
.response_data_format = 2,
|
||||
@@ -700,8 +751,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
|
||||
break;
|
||||
|
||||
case SCSI_CMD_MODE_SENSE_6: {
|
||||
scsi_mode_sense6_resp_t mode_resp =
|
||||
{
|
||||
scsi_mode_sense6_resp_t mode_resp = {
|
||||
.data_len = 3,
|
||||
.medium_type = 0,
|
||||
.write_protected = false,
|
||||
@@ -722,8 +772,7 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
|
||||
break;
|
||||
|
||||
case SCSI_CMD_REQUEST_SENSE: {
|
||||
scsi_sense_fixed_resp_t sense_rsp =
|
||||
{
|
||||
scsi_sense_fixed_resp_t sense_rsp = {
|
||||
.response_code = 0x70, // current, fixed format
|
||||
.valid = 1
|
||||
};
|
||||
@@ -753,39 +802,49 @@ static int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_
|
||||
return resplen;
|
||||
}
|
||||
|
||||
static void proc_read10_cmd(uint8_t rhport, mscd_interface_t* p_msc) {
|
||||
static void proc_read10_cmd(mscd_interface_t* p_msc) {
|
||||
msc_cbw_t const* p_cbw = &p_msc->cbw;
|
||||
|
||||
// block size already verified not zero
|
||||
uint16_t const block_sz = rdwr10_get_blocksize(p_cbw);
|
||||
|
||||
// Adjust lba with transferred bytes
|
||||
uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); // already verified non-zero
|
||||
// Adjust lba & offset with transferred bytes
|
||||
uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz);
|
||||
uint32_t const offset = p_msc->xferred_len % block_sz;
|
||||
|
||||
// remaining bytes capped at class buffer
|
||||
int32_t nbytes = (int32_t)tu_min32(CFG_TUD_MSC_EP_BUFSIZE, p_cbw->total_bytes - p_msc->xferred_len);
|
||||
|
||||
// Application can consume smaller bytes
|
||||
uint32_t const offset = p_msc->xferred_len % block_sz;
|
||||
p_msc->pending_io = 1;
|
||||
nbytes = tud_msc_read10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, (uint32_t)nbytes);
|
||||
|
||||
if (nbytes < 0) {
|
||||
// negative means error -> endpoint is stalled & status in CSW set to failed
|
||||
TU_LOG_DRV(" tud_msc_read10_cb() return -1\r\n");
|
||||
|
||||
// set sense
|
||||
set_sense_medium_not_present(p_cbw->lun);
|
||||
|
||||
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
|
||||
} else if (nbytes == 0) {
|
||||
// zero means not ready -> simulate an transfer complete so that this driver callback will fired again
|
||||
dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false);
|
||||
} else {
|
||||
TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) nbytes),);
|
||||
if (nbytes != TUD_MSC_RET_ASYNC) {
|
||||
p_msc->pending_io = 0;
|
||||
proc_read_io_data(p_msc, nbytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) {
|
||||
static void proc_read_io_data(mscd_interface_t* p_msc, int32_t nbytes) {
|
||||
const uint8_t rhport = p_msc->rhport;
|
||||
if (nbytes > 0) {
|
||||
TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in, _mscd_epbuf.buf, (uint16_t) nbytes),);
|
||||
} else {
|
||||
// nbytes is status
|
||||
switch (nbytes) {
|
||||
case TUD_MSC_RET_ERROR:
|
||||
// error -> endpoint is stalled & status in CSW set to failed
|
||||
TU_LOG_DRV(" IO read() failed\r\n");
|
||||
set_sense_medium_not_present(p_msc->cbw.lun);
|
||||
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
|
||||
break;
|
||||
|
||||
case TUD_MSC_RET_BUSY:
|
||||
// not ready yet -> fake a transfer complete so that this driver callback will fire again
|
||||
dcd_event_xfer_complete(rhport, p_msc->ep_in, 0, XFER_RESULT_SUCCESS, false);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void proc_write10_cmd(mscd_interface_t* p_msc) {
|
||||
msc_cbw_t const* p_cbw = &p_msc->cbw;
|
||||
bool writable = true;
|
||||
|
||||
@@ -797,51 +856,56 @@ static void proc_write10_cmd(uint8_t rhport, mscd_interface_t* p_msc) {
|
||||
// Not writable, complete this SCSI op with error
|
||||
// Sense = Write protected
|
||||
tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_DATA_PROTECT, 0x27, 0x00);
|
||||
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
|
||||
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
// remaining bytes capped at class buffer
|
||||
uint16_t nbytes = (uint16_t)tu_min32(CFG_TUD_MSC_EP_BUFSIZE, p_cbw->total_bytes - p_msc->xferred_len);
|
||||
|
||||
// Write10 callback will be called later when usb transfer complete
|
||||
TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_out, _mscd_epbuf.buf, nbytes),);
|
||||
TU_ASSERT(usbd_edpt_xfer(p_msc->rhport, p_msc->ep_out, _mscd_epbuf.buf, nbytes),);
|
||||
}
|
||||
|
||||
// process new data arrived from WRITE10
|
||||
static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint32_t xferred_bytes) {
|
||||
static void proc_write10_host_data(mscd_interface_t* p_msc, uint32_t xferred_bytes) {
|
||||
msc_cbw_t const* p_cbw = &p_msc->cbw;
|
||||
uint16_t const block_sz = rdwr10_get_blocksize(p_cbw); // already verified non-zero
|
||||
|
||||
// block size already verified not zero
|
||||
uint16_t const block_sz = rdwr10_get_blocksize(p_cbw);
|
||||
|
||||
// Adjust lba with transferred bytes
|
||||
// Adjust lba & offset with transferred bytes
|
||||
uint32_t const lba = rdwr10_get_lba(p_cbw->command) + (p_msc->xferred_len / block_sz);
|
||||
|
||||
// Invoke callback to consume new data
|
||||
uint32_t const offset = p_msc->xferred_len % block_sz;
|
||||
int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, xferred_bytes);
|
||||
|
||||
p_msc->pending_io = 1;
|
||||
int32_t nbytes = tud_msc_write10_cb(p_cbw->lun, lba, offset, _mscd_epbuf.buf, xferred_bytes);
|
||||
if (nbytes != TUD_MSC_RET_ASYNC) {
|
||||
p_msc->pending_io = 0;
|
||||
proc_write_io_data(p_msc, xferred_bytes, nbytes);
|
||||
}
|
||||
}
|
||||
|
||||
static void proc_write_io_data(mscd_interface_t* p_msc, uint32_t xferred_bytes, int32_t nbytes) {
|
||||
if (nbytes < 0) {
|
||||
// negative means error -> failed this scsi op
|
||||
TU_LOG_DRV(" tud_msc_write10_cb() return -1\r\n");
|
||||
// nbytes is status
|
||||
switch (nbytes) {
|
||||
case TUD_MSC_RET_ERROR:
|
||||
// IO error -> failed this scsi op
|
||||
TU_LOG_DRV(" IO write() failed\r\n");
|
||||
set_sense_medium_not_present(p_msc->cbw.lun);
|
||||
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
|
||||
break;
|
||||
|
||||
// update actual byte before failed
|
||||
p_msc->xferred_len += xferred_bytes;
|
||||
|
||||
set_sense_medium_not_present(p_cbw->lun);
|
||||
fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED);
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
if ((uint32_t)nbytes < xferred_bytes) {
|
||||
// Application consume less than what we got (including zero)
|
||||
// Application consume less than what we got including TUD_MSC_RET_BUSY (0)
|
||||
const uint32_t left_over = xferred_bytes - (uint32_t)nbytes;
|
||||
if (nbytes > 0) {
|
||||
p_msc->xferred_len += (uint16_t)nbytes;
|
||||
memmove(_mscd_epbuf.buf, _mscd_epbuf.buf + nbytes, left_over);
|
||||
}
|
||||
|
||||
// simulate a transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter
|
||||
dcd_event_xfer_complete(rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false);
|
||||
// fake a transfer complete with adjusted parameters --> callback will be invoked with adjusted parameters
|
||||
dcd_event_xfer_complete(p_msc->rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false);
|
||||
} else {
|
||||
// Application consume all bytes in our buffer
|
||||
p_msc->xferred_len += xferred_bytes;
|
||||
@@ -851,7 +915,7 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3
|
||||
p_msc->stage = MSC_STAGE_STATUS;
|
||||
} else {
|
||||
// prepare to receive more data from host
|
||||
proc_write10_cmd(rhport, p_msc);
|
||||
proc_write10_cmd(p_msc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -48,6 +48,13 @@
|
||||
#error CFG_TUD_MSC_EP_BUFSIZE must be defined, value of a block size should work well, the more the better
|
||||
#endif
|
||||
|
||||
// Return value of callback functions
|
||||
enum {
|
||||
TUD_MSC_RET_BUSY = 0, // Busy, e.g disk I/O is not ready
|
||||
TUD_MSC_RET_ERROR = -1,
|
||||
TUD_MSC_RET_ASYNC = -2, // Asynchronous IO
|
||||
};
|
||||
|
||||
TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct");
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -57,38 +64,30 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_EP_BUFSIZE < UINT16_MAX, "Size is not correct");
|
||||
// Set SCSI sense response
|
||||
bool tud_msc_set_sense(uint8_t lun, uint8_t sense_key, uint8_t add_sense_code, uint8_t add_sense_qualifier);
|
||||
|
||||
// Called by Application once asynchronous I/O operation is done
|
||||
// bytes_io is number of bytes in I/O op, typically the bufsize in read/write_cb() or
|
||||
// TUD_MSC_RET_ERROR (-1) for error. Note TUD_MSC_RET_BUSY (0) will be treated as error as well.
|
||||
bool tud_msc_async_io_done(int32_t bytes_io, bool in_isr);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Application Callbacks (WEAK is optional)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when received SCSI READ10 command
|
||||
// - Address = lba * BLOCK_SIZE + offset
|
||||
// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE.
|
||||
//
|
||||
// - Application fill the buffer (up to bufsize) with address contents and return number of read byte. If
|
||||
// - read < bufsize : These bytes are transferred first and callback invoked again for remaining data.
|
||||
//
|
||||
// - read == 0 : Indicate application is not ready yet e.g disk I/O busy.
|
||||
// Callback invoked again with the same parameters later on.
|
||||
//
|
||||
// - read < 0 : Indicate application error e.g invalid address. This request will be STALLed
|
||||
// and return failed status in command status wrapper phase.
|
||||
/*
|
||||
Invoked when received SCSI READ10/WRITE10 command
|
||||
- Address = lba * BLOCK_SIZE + offset
|
||||
- offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE.
|
||||
- Application fill the buffer (up to bufsize) with address contents and return number of bytes read or status.
|
||||
- 0 < ret < bufsize: These bytes are transferred first and callback will be invoked again for remaining data.
|
||||
- TUD_MSC_RET_BUSY
|
||||
Application is buys e.g disk I/O not ready. Callback will be invoked again with the same parameters later on.
|
||||
- TUD_MSC_RET_ERROR
|
||||
error such as invalid address. This request will be STALLed and scsi command will be failed
|
||||
- TUD_MSC_RET_ASYNC
|
||||
Data I/O will be done asynchronously in a background task. Application should return immediately.
|
||||
tud_msc_async_io_done() must be called once IO/ is done to signal completion.
|
||||
*/
|
||||
int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize);
|
||||
|
||||
// Invoked when received SCSI WRITE10 command
|
||||
// - Address = lba * BLOCK_SIZE + offset
|
||||
// - offset is only needed if CFG_TUD_MSC_EP_BUFSIZE is smaller than BLOCK_SIZE.
|
||||
//
|
||||
// - Application write data from buffer to address contents (up to bufsize) and return number of written byte. If
|
||||
// - write < bufsize : callback invoked again with remaining data later on.
|
||||
//
|
||||
// - write == 0 : Indicate application is not ready yet e.g disk I/O busy.
|
||||
// Callback invoked again with the same parameters later on.
|
||||
//
|
||||
// - write < 0 : Indicate application error e.g invalid address. This request will be STALLed
|
||||
// and return failed status in command status wrapper phase.
|
||||
//
|
||||
// TODO change buffer to const uint8_t*
|
||||
int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize);
|
||||
|
||||
// Invoked when received SCSI_CMD_INQUIRY
|
||||
|
@@ -278,6 +278,8 @@ typedef enum {
|
||||
XFER_RESULT_INVALID
|
||||
} xfer_result_t;
|
||||
|
||||
#define tusb_xfer_result_t xfer_result_t
|
||||
|
||||
// TODO remove
|
||||
enum {
|
||||
DESC_OFFSET_LEN = 0,
|
||||
@@ -345,7 +347,6 @@ typedef struct TU_ATTR_PACKED {
|
||||
uint8_t iManufacturer ; ///< Index of string descriptor describing manufacturer.
|
||||
uint8_t iProduct ; ///< Index of string descriptor describing product.
|
||||
uint8_t iSerialNumber ; ///< Index of string descriptor describing the device's serial number.
|
||||
|
||||
uint8_t bNumConfigurations ; ///< Number of possible configurations.
|
||||
} tusb_desc_device_t;
|
||||
|
||||
|
@@ -465,13 +465,30 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
||||
return true; // skip if already initialized
|
||||
}
|
||||
TU_ASSERT(rh_init);
|
||||
|
||||
TU_LOG_USBD("USBD init on controller %u, speed = %s\r\n", rhport,
|
||||
rh_init->speed == TUSB_SPEED_HIGH ? "High" : "Full");
|
||||
#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
|
||||
char const* speed_str = 0;
|
||||
switch (rh_init->speed) {
|
||||
case TUSB_SPEED_HIGH:
|
||||
speed_str = "High";
|
||||
break;
|
||||
case TUSB_SPEED_FULL:
|
||||
speed_str = "Full";
|
||||
break;
|
||||
case TUSB_SPEED_LOW:
|
||||
speed_str = "Low";
|
||||
break;
|
||||
case TUSB_SPEED_AUTO:
|
||||
speed_str = "Auto";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
TU_LOG_USBD("USBD init on controller %u, speed = %s\r\n", rhport, speed_str);
|
||||
TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(usbd_device_t));
|
||||
TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(dcd_event_t));
|
||||
TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_fifo_t));
|
||||
TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_edpt_stream_t));
|
||||
#endif
|
||||
|
||||
tu_varclr(&_usbd_dev);
|
||||
_usbd_queued_setup = 0;
|
||||
|
@@ -244,7 +244,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
|
||||
/* CDC Union */\
|
||||
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\
|
||||
/* Endpoint Notification */\
|
||||
7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\
|
||||
7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\
|
||||
/* CDC Data Interface */\
|
||||
9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\
|
||||
/* Endpoint Out */\
|
||||
|
128
src/host/usbh.c
128
src/host/usbh.c
@@ -94,6 +94,20 @@ TU_ATTR_WEAK bool hcd_dcache_clean_invalidate(const void* addr, uint32_t data_si
|
||||
typedef struct {
|
||||
tuh_bus_info_t bus_info;
|
||||
|
||||
// Device Descriptor
|
||||
uint16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize0;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t bcdDevice;
|
||||
uint8_t iManufacturer;
|
||||
uint8_t iProduct;
|
||||
uint8_t iSerialNumber;
|
||||
uint8_t bNumConfigurations;
|
||||
|
||||
// Device State
|
||||
struct TU_ATTR_PACKED {
|
||||
volatile uint8_t connected : 1; // After 1st transfer
|
||||
@@ -103,18 +117,6 @@ typedef struct {
|
||||
// volatile uint8_t removing : 1; // Physically disconnected, waiting to be processed by usbh
|
||||
};
|
||||
|
||||
// Device Descriptor
|
||||
uint8_t ep0_size;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint8_t iManufacturer;
|
||||
uint8_t iProduct;
|
||||
uint8_t iSerialNumber;
|
||||
uint8_t bNumConfigurations;
|
||||
|
||||
// Configuration Descriptor
|
||||
// uint8_t interface_count; // bNumInterfaces alias
|
||||
|
||||
// Endpoint & Interface
|
||||
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
|
||||
@@ -373,6 +375,28 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tuh_descriptor_get_device_local(uint8_t daddr, tusb_desc_device_t* desc_device) {
|
||||
usbh_device_t *dev = get_device(daddr);
|
||||
TU_VERIFY(dev && desc_device);
|
||||
|
||||
desc_device->bLength = sizeof(tusb_desc_device_t);
|
||||
desc_device->bDescriptorType = TUSB_DESC_DEVICE;
|
||||
desc_device->bcdUSB = dev->bcdUSB;
|
||||
desc_device->bDeviceClass = dev->bDeviceClass;
|
||||
desc_device->bDeviceSubClass = dev->bDeviceSubClass;
|
||||
desc_device->bDeviceProtocol = dev->bDeviceProtocol;
|
||||
desc_device->bMaxPacketSize0 = dev->bMaxPacketSize0;
|
||||
desc_device->idVendor = dev->idVendor;
|
||||
desc_device->idProduct = dev->idProduct;
|
||||
desc_device->bcdDevice = dev->bcdDevice;
|
||||
desc_device->iManufacturer = dev->iManufacturer;
|
||||
desc_device->iProduct = dev->iProduct;
|
||||
desc_device->iSerialNumber = dev->iSerialNumber;
|
||||
desc_device->bNumConfigurations = dev->bNumConfigurations;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
tusb_speed_t tuh_speed_get(uint8_t daddr) {
|
||||
tuh_bus_info_t bus_info;
|
||||
tuh_bus_info_get(daddr, &bus_info);
|
||||
@@ -414,9 +438,26 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
|
||||
if (tuh_rhport_is_active(rhport)) {
|
||||
return true; // skip if already initialized
|
||||
}
|
||||
|
||||
TU_LOG_USBH("USBH init on controller %u, speed = %s\r\n", rhport,
|
||||
rh_init->speed == TUSB_SPEED_HIGH ? "High" : "Full");
|
||||
#if CFG_TUSB_DEBUG >= CFG_TUH_LOG_LEVEL
|
||||
char const* speed_str = 0;
|
||||
switch (rh_init->speed) {
|
||||
case TUSB_SPEED_HIGH:
|
||||
speed_str = "High";
|
||||
break;
|
||||
case TUSB_SPEED_FULL:
|
||||
speed_str = "Full";
|
||||
break;
|
||||
case TUSB_SPEED_LOW:
|
||||
speed_str = "Low";
|
||||
break;
|
||||
case TUSB_SPEED_AUTO:
|
||||
speed_str = "Auto";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
TU_LOG_USBH("USBH init on controller %u, speed = %s\r\n", rhport, speed_str);
|
||||
#endif
|
||||
|
||||
// Init host stack if not already
|
||||
if (!tuh_inited()) {
|
||||
@@ -1068,8 +1109,9 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr)
|
||||
|
||||
// generic helper to get a descriptor
|
||||
// if blocking, user_data is pointed to xfer_result
|
||||
static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
|
||||
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
|
||||
TU_ATTR_ALWAYS_INLINE static inline
|
||||
bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
|
||||
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
|
||||
tusb_control_request_t const request = {
|
||||
.bmRequestType_bit = {
|
||||
.recipient = TUSB_REQ_RCPT_DEVICE,
|
||||
@@ -1110,7 +1152,6 @@ bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer
|
||||
}
|
||||
|
||||
//------------- String Descriptor -------------//
|
||||
|
||||
bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
|
||||
tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
|
||||
return _get_descriptor(daddr, TUSB_DESC_STRING, index, language_id, buffer, len, complete_cb, user_data);
|
||||
@@ -1248,47 +1289,6 @@ bool tuh_interface_set(uint8_t daddr, uint8_t itf_num, uint8_t itf_alt,
|
||||
return tuh_control_xfer(&xfer);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Descriptor Sync
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#define _CONTROL_SYNC_API(_async_func, ...) \
|
||||
xfer_result_t result = XFER_RESULT_INVALID;\
|
||||
TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \
|
||||
return (uint8_t) result
|
||||
|
||||
uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get, daddr, type, index, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_device, daddr, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_configuration, daddr, index, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_string, daddr, index, language_id, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_product_string, daddr, language_id, buffer, len);
|
||||
}
|
||||
|
||||
uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len) {
|
||||
_CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Detaching
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -1579,7 +1579,7 @@ static void process_enumeration(tuh_xfer_t* xfer) {
|
||||
usbh_device_t* new_dev = get_device(new_addr);
|
||||
new_dev->bus_info = *dev0_bus;
|
||||
new_dev->connected = 1;
|
||||
new_dev->ep0_size = desc_device->bMaxPacketSize0;
|
||||
new_dev->bMaxPacketSize0 = desc_device->bMaxPacketSize0;
|
||||
|
||||
TU_ASSERT(tuh_address_set(0, new_addr, process_enumeration, ENUM_GET_DEVICE_DESC),);
|
||||
break;
|
||||
@@ -1596,7 +1596,7 @@ static void process_enumeration(tuh_xfer_t* xfer) {
|
||||
|
||||
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
|
||||
TU_ASSERT(usbh_edpt_control_open(new_addr, new_dev->bMaxPacketSize0),); // open new control endpoint
|
||||
|
||||
TU_LOG_USBH("Get Device Descriptor\r\n");
|
||||
TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t),
|
||||
@@ -1609,8 +1609,14 @@ static void process_enumeration(tuh_xfer_t* xfer) {
|
||||
case ENUM_GET_STRING_LANGUAGE_ID_LEN: {
|
||||
// save the received device descriptor
|
||||
tusb_desc_device_t const *desc_device = (tusb_desc_device_t const *) _usbh_epbuf.ctrl;
|
||||
dev->bcdUSB = desc_device->bcdUSB;
|
||||
dev->bDeviceClass = desc_device->bDeviceClass;
|
||||
dev->bDeviceSubClass = desc_device->bDeviceSubClass;
|
||||
dev->bDeviceProtocol = desc_device->bDeviceProtocol;
|
||||
dev->bMaxPacketSize0 = desc_device->bMaxPacketSize0;
|
||||
dev->idVendor = desc_device->idVendor;
|
||||
dev->idProduct = desc_device->idProduct;
|
||||
dev->bcdDevice = desc_device->bcdDevice;
|
||||
dev->iManufacturer = desc_device->iManufacturer;
|
||||
dev->iProduct = desc_device->iProduct;
|
||||
dev->iSerialNumber = desc_device->iSerialNumber;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user