Compare commits

...

72 commits

Author SHA1 Message Date
Tyeth Gundry
737dfb2115
Update library.json - 3.7.1 2025-07-17 11:49:41 +01:00
Tyeth Gundry
766d8cca00
Update library.properties - 3.7.1 2025-07-17 11:49:27 +01:00
Ha Thach
d3cc12070a
Merge pull request #540 from adafruit/update-bug-template
Update bug_report.yml
2025-07-15 10:37:45 +07:00
Ha Thach
86dfc05234
Merge pull request #539 from valeros/patch-1
Remove redundant USE_TINYUSB macro from PlatformIO library manifest
2025-07-15 10:30:04 +07:00
Ha Thach
8f13cb8bca
Update bug_report.yml 2025-07-15 10:19:48 +07:00
Valerii Koval
fb9763423c
Remove redundant USE_TINYUSB macro 2025-07-14 16:36:00 +03:00
Tyeth Gundry
7b30ff9e14
Update library.properties - bump version to 3.7.0 2025-06-17 19:36:00 +01:00
Tyeth Gundry
0e054b598b
Update library.json - bump version to 3.7.0 2025-06-17 19:35:40 +01:00
Ha Thach
5ab76b7931
Merge pull request #536 from adafruit/update-example
Update example
2025-06-10 17:14:19 +07:00
hathach
028629e93e
add fruitjam sdfat pinout support 2025-06-10 16:18:49 +07:00
hathach
8c615b6519
update pio-usb host requirement to only multiple of 12Mhz (previously 120Mhz) 2025-06-10 16:18:16 +07:00
Tyeth Gundry
d4071f5abe
Update library.json - bump version to 3.6.1 2025-06-03 18:53:58 +01:00
Tyeth Gundry
4daede3744
Update library.properties - bump version to 3.6.1 2025-06-03 18:53:46 +01:00
Ha Thach
44053c45df
Merge pull request #533 from adafruit/fix-metro-rp2040-msc-sdfat-macos-conflict 2025-05-31 11:03:15 +07:00
hathach
eaa9bfdaa5
update msc_sdfat.ino and msc_external_flash_sdcard.ino to
- use SDIO (pio) for rp2040/rp2350
- remove printing flash/sdcard contents to Serial since it conflict with host, which can cause conflict in spi/sdio transport and/or correupt cache,sector
2025-05-30 19:59:27 +07:00
Tyeth Gundry
9806375c60
Update library.properties - bump version to 3.6.0 2025-05-28 15:40:58 +01:00
Tyeth Gundry
e896107698
Update library.json - bump version to 3.6.0 2025-05-28 15:40:44 +01:00
Ha Thach
805aa2d41a
Merge pull request #530 from adafruit/test-metro-rp2040-sd
update msc sdcad example to work with metro rp2040
2025-05-22 22:42:50 +07:00
hathach
fee8a5e6bc
update msc sdcad example to work with metro rp2040 2025-05-22 15:58:03 +07:00
Ha Thach
59d4393012
Merge pull request #529 from adafruit/add-set-maxpower
add setConfigurationMaxPower() and setConfigurationAttribute
2025-05-22 11:48:06 +07:00
hathach
60fb663caa
add Adafruit_USBD_Device::setConfigurationMaxPower() and setConfigurationAttribute 2025-05-22 11:07:31 +07:00
Ha Thach
cdc07c1d96
Merge pull request #505 from Props3D/master
USB Device Descriptor Max Power is not configurable #504
2025-05-22 11:02:59 +07:00
Ha Thach
794ac7f34b
bump up version to 3.5.0 2025-05-21 17:29:16 +07:00
Ha Thach
9496740134
Merge pull request #528 from adafruit/fix-esp32-max3421e
fix compiling hcd max3421e with arduino-esp32 and arduino-pico due to missing atomic_flag function
2025-05-21 17:25:39 +07:00
hathach
6fa11c4d5e
bump up tinyusb to commit e41a63c60dbebd9579698e6444bc62cfa518e15c 2025-05-21 17:03:01 +07:00
Tyeth Gundry
f05bd099c3
Update library.properties - bump version to 3.4.5 2025-05-09 21:57:55 +01:00
Tyeth Gundry
951dba38f6
Update library.json - bump version to 3.4.5 2025-05-09 21:57:43 +01:00
Ha Thach
5618d9c054
Merge pull request #525 from adafruit/fix-sigma-mouse
fix sigma mouse in adafruit store cause multiple attach connection
2025-05-06 21:43:30 +07:00
hathach
46d2c6cb49
update tinyusb to commit 809af3e74ca37495d6c385acd33a488c2984a093 2025-05-06 16:14:14 +07:00
hathach
23426ed3f6
fix sigma mouse in adafruit store cause multiple attach connection 2025-05-05 23:31:59 +07:00
Ha Thach
72cd81005b
Merge pull request #523 from adafruit/update-tinyusb-commit-1a783b357343d053eb861ae783922371ce9e1b17
update tinyusb to commit 1a783b357343d053eb861ae783922371ce9e1b17
2025-05-05 17:33:24 +07:00
hathach
fafc824f6b
update tinyusb to 1a783b3573 2025-05-05 10:00:12 +07:00
Tyeth Gundry
6b772c0ac4
Update library.properties - bump version to 3.4.4 2025-03-25 17:51:36 +00:00
Tyeth Gundry
560a21bdec
Update library.json - bump version to 3.4.4 2025-03-25 17:51:21 +00:00
Ha Thach
4b9a629a55
Merge pull request #510 from adafruit/fix-esp32-max3421e
Fix esp32 max3421e
2025-03-20 20:09:29 +07:00
hathach
55a0283b48
skip more examples 2025-03-20 10:28:09 +07:00
hathach
332b0c8e31
skip device example for feather_esp32_v2 2025-03-20 09:50:31 +07:00
hathach
f83e0ce0ff
only enable CFG_TUD_ENABLED with esp wgen CONFIG_USB_OTG_SUPPORTED = 1. Add feather_esp32_v2 to ci pool 2025-03-19 16:54:45 +07:00
Props3D - Craig
d522523fd1 USB Device Descriptor Max Power is not configurable #504
Replacing hardcoded value with define macro
2025-03-07 17:32:30 -08:00
Tyeth Gundry
76a551be81
Update library.json - bump version to 3.4.3 2025-03-07 19:18:47 +00:00
Tyeth Gundry
f4e8959828
Update library.properties - bump version to 3.4.3 2025-03-07 14:30:33 +00:00
Ha Thach
7b22bd0adf
Merge pull request #503 from adafruit/support-esp32p4
support esp32p4
2025-03-07 17:08:11 +07:00
hathach
36396f4f9e
fix esp32p4 build due to lack of LED_BUILTIN 2025-03-07 16:42:10 +07:00
hathach
cfe6da84d1
fix build with host native 2025-03-07 12:48:59 +07:00
hathach
7f7ac74899
support esp32p4 2025-03-07 12:20:53 +07:00
Ha Thach
8ef30202e5
Merge pull request #498 from adafruit/update-tinyusb-1cfc88dbcb8cff6f926aef02c5609880169ec94c
Update tinyusb to commit 334ac8072650e3b18278042c2c2b402db73c7359
2025-03-07 10:58:24 +07:00
hathach
3918606fbe
update to commit 334ac8072650e3b18278042c2c2b402db73c7359 2025-03-07 10:07:41 +07:00
hathach
1d3576a40a
enable CFG_TUH_MAX3421 and skip native host dwc2 for esp32 2025-03-06 22:42:57 +07:00
hathach
605d681c81
feat(esp32) resolve conflict with latest v3.1.3. better enforce tusb_config_esp32.h within tusb_option.h
also change CFG_TUD_MIDI_RX/TX_BUFSIZE for rp2040 to 64
2025-03-06 21:18:54 +07:00
hathach
41bde22a7c
change to "SdFat_Adafruit_Fork.h" and revert to build sdfat examples 2025-03-05 22:52:39 +07:00
hathach
411821714b
update tinyusb to commit 51cfae6e97b08e9c34a4551cfa45c85a2498a943 2025-03-04 17:30:48 +07:00
hathach
aba2328b00
skip example with SdFat for rp2040 due to conflict with builtin vs Adafruit's Fork of SdFat 2025-02-26 17:10:26 +07:00
hathach
f12e3f2886
add missing files 2025-02-26 16:04:17 +07:00
hathach
a17922159b
temp patch for rp2040 lacking atomic flags test/set 2025-02-26 15:58:14 +07:00
hathach
96ac318c19
implement tusb_time_millis_api() 2025-02-26 13:10:12 +07:00
hathach
8f2d3edd77
update tinyusb to upstream 1cfc88dbcb 2025-02-26 12:48:44 +07:00
Tyeth Gundry
c92b7fde16
Update library.properties - bump version to 3.4.2 2024-12-12 18:45:22 +00:00
Ha Thach
85476dcd8f
Merge pull request #475 from OrhanYigitDurmaz/master
Bring library.json up to date
2024-12-02 15:06:31 +07:00
Orhan Yiğit Durmaz
8077b62029 Update library.json 2024-12-01 10:45:40 -08:00
Orhan Yiğit Durmaz
c976061caa fix platformio issue 2024-12-01 10:35:18 -08:00
Tyeth Gundry
f5211f4226
Update library.properties - bump version to 3.4.1 2024-11-19 19:50:14 +00:00
Ha Thach
f8ac8130c5
Merge pull request #452 from westinpigott/patch-1
Enable multiple serial over usb for rp2040
2024-11-15 12:31:23 +07:00
Ha Thach
1798428b15
Update library.properties
bump library for release
2024-10-24 17:44:30 +07:00
Ha Thach
5920d15f73
Merge pull request #466 from adafruit/update-tinyusb-fix-esp32-build
update tinyusb to fix esp32 build with v3.0.7
2024-10-24 17:43:46 +07:00
hathach
71e2c4a4bd
fix undefined reference to `__atomic_test_and_set' with rp2040 with gcc 14.2. Temporarily modify to use native semaphore 2024-10-24 16:12:17 +07:00
hathach
f13b57a01a
update tinyusb to commit 8b1e40c3e2447de5b4a86bbcdcc0344946a4793d 2024-10-23 21:20:25 +07:00
Tyeth Gundry
a529a74e4f
Update library.properties - bump version to 3.3.4 2024-09-18 19:48:04 +01:00
Ha Thach
05686e7f97
Merge pull request #454 from adafruit/force-example-re_enum
force re-enumerate for all examples.
2024-09-05 17:33:54 +07:00
hathach
59a651cca0
force re-enumerate for all examples. For some fast chip such as esp32-s3, by the time we initialize class driver enumeration process is already done. 2024-09-05 16:15:34 +07:00
Ha Thach
2df6d2905e
Merge pull request #453 from adafruit/update-tinyusb-55951b71aea46c09f27afe1640454fe43c983eec
update tinyusb to commit 55951b71aea46c09f27afe1640454fe43c983eec
2024-09-05 15:42:50 +07:00
hathach
a7c9db3f62
update tinyusb to commit 55951b71aea46c09f27afe1640454fe43c983eec 2024-09-05 14:26:59 +07:00
Westin Pigott
0a9c3fe818
Enable multiple serial over usb for rp2040 2024-09-03 14:41:27 -04:00
173 changed files with 10667 additions and 6134 deletions

View file

@ -46,7 +46,7 @@ body:
- type: input
attributes:
label: TinyUSB Library version
placeholder: "Release version or github latest"
placeholder: "Release version or commit SHA"
validations:
required: true
@ -100,3 +100,11 @@ body:
description: If applicable, add screenshots to help explain your problem.
validations:
required: false
- type: checkboxes
attributes:
label: I have checked existing issues, pr, discussion and documentation
description: You agree to check all the resources above before opening a new issue.
options:
- label: I confirm I have checked existing issues, pr, discussion and documentation.
required: true

View file

@ -38,7 +38,7 @@ jobs:
run: bash ci/doxy_gen_and_deploy.sh
# ---------------------------------------
# Main
# build
# ---------------------------------------
build:
runs-on: ubuntu-latest
@ -48,8 +48,10 @@ jobs:
matrix:
arduino-platform:
# ESP32 ci use dev json
- 'feather_esp32_v2'
- 'feather_esp32s2'
- 'feather_esp32s3'
- 'esp32p4'
# nRF52
- 'cpb'
- 'nrf52840'
@ -81,53 +83,3 @@ jobs:
- name: test platforms
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}
# ---------------------------------------
# Build ESP32 v2
# ---------------------------------------
build-esp32-v2:
if: false
runs-on: ubuntu-latest
needs: pre-commit
strategy:
fail-fast: false
matrix:
arduino-platform:
- 'feather_esp32s2'
- 'feather_esp32s3'
esp32-version:
- '2.0.17'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout adafruit/ci-arduino
uses: actions/checkout@v4
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
run: bash ci/actions_install.sh
- name: Install arduino-esp32 v2 and Libraries
env:
BSP_URLS: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
run: |
arduino-cli core install esp32:esp32@${{ matrix.esp32-version }} --additional-urls $BSP_URLS
arduino-cli lib install ${{ env.ARDUINO_LIBS }}
arduino-cli core list
arduino-cli lib list
- name: Create custom build script
working-directory: ${{ github.workspace }}/ci
run: |
echo 'import build_platform' > build_esp32_v2.py
echo 'build_platform.test_examples_in_folder("'${{ matrix.arduino-platform }}'", build_platform.BUILD_DIR)' >> build_esp32_v2.py
echo 'exit(build_platform.success)' >> build_esp32_v2.py
cat build_esp32_v2.py
- name: test platforms
run: |
python3 ci/build_esp32_v2.py

View file

@ -38,7 +38,9 @@ Following core has TinyUSB as either the primary usb stack or selectable via men
- [adafruit/Adafruit_nRF52_Arduino](https://github.com/adafruit/Adafruit_nRF52_Arduino)
- [adafruit/ArduinoCore-samd](https://github.com/adafruit/ArduinoCore-samd)
- [earlephilhower/arduino-pico](https://github.com/earlephilhower/arduino-pico)
- [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32)
- [espressif/arduino-esp32](https://github.com/espressif/arduino-esp32) Host mode using MAX3421E controller should work with all chips. Device mode only support S2/S3/P4 and additional Tools menu are needed
- `USB Mode=USB-OTG (TinyUSB)` for S3 and P4
- `USB CDC On Boot=Enabled`, `USB Firmware MSC On Boot=Disabled`, `USB DFU On Boot=Disabled`
- [openwch/arduino_core_ch32](https://github.com/openwch/arduino_core_ch32)
Note: For ESP32 port, version before v3.0 requires all descriptors must be specified in usb objects declaration i.e constructors. Therefore all descriptor-related fields must be part of object declaration and descriptor-related API have no effect afterwards. This limitation is not the case for version from v3.0.

View file

@ -1,6 +1,8 @@
feather_esp32_v2
feather_esp32s2
feather_esp32s3
funhouse
magtag
metroesp32s2
esp32p4
pico_rp2040_tinyusb_host

View file

@ -25,11 +25,9 @@
#include <Adafruit_TinyUSB.h>
#define LED LED_BUILTIN
// Create 2nd instance of CDC Ports.
#ifdef ARDUINO_ARCH_ESP32
#error "Currently multiple CDCs on ESP32-Sx is not yet supported. An PR to update core/esp32/USBCDC and/or pre-built libusb are needed."
#error "Currently multiple CDCs on ESP32 is not yet supported"
// for ESP32, we need to specify instance number when declaring object
Adafruit_USBD_CDC USBSer1(1);
#else
@ -37,13 +35,17 @@
#endif
void setup() {
pinMode(LED, OUTPUT);
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
Serial.begin(115200);
// check to see if multiple CDCs are enabled
if ( CFG_TUD_CDC < 2 ) {
digitalWrite(LED, HIGH); // LED on for error indicator
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH); // LED on for error indicator
#endif
while(1) {
Serial.printf("CFG_TUD_CDC must be at least 2, current value is %u\n", CFG_TUD_CDC);
@ -56,6 +58,13 @@ void setup() {
// initialize 2nd CDC interface
USBSer1.begin(115200);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
while (!Serial || !USBSer1) {
if (Serial) {
Serial.println("Waiting for other USB ports");
@ -89,7 +98,9 @@ void loop() {
if (delay_without_delaying(500)) {
LEDstate = !LEDstate;
digitalWrite(LED, LEDstate);
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LEDstate);
#endif
}
}

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -18,11 +18,7 @@
* Note: this will cause device to loose the touch1200 and require
* user manual interaction to put device into bootloader/DFU mode.
*/
int led = LED_BUILTIN;
void setup()
{
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
@ -31,11 +27,19 @@ void setup()
// clear configuration will remove all USB interfaces including CDC (Serial)
TinyUSBDevice.clearConfiguration();
pinMode(led, OUTPUT);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
}
void loop()
{
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
@ -46,6 +50,8 @@ void loop()
static uint8_t led_state = 0;
if (millis() - ms > 1000) {
ms = millis();
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, 1-led_state);
#endif
}
}

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -74,6 +74,8 @@ void setup() {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
usb_msc.setID("Adafruit", "Mass Storage", "1.0");
@ -97,7 +99,13 @@ void setup() {
usb_hid.setPollInterval(2);
usb_hid.begin();
Serial.begin(115200);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.println("Adafruit TinyUSB Mouse + Mass Storage (ramdisk) example");
}

View file

@ -59,14 +59,14 @@ static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
if (cpu_hz % 12000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -59,14 +59,14 @@ static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
if (cpu_hz % 12000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,2 +1,3 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -42,8 +42,7 @@ uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_MOUSE()
};
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
// USB HID object: desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_MOUSE, 2, false);
/* Adjustable parameters for the log_filter() method.

View file

@ -59,14 +59,14 @@ static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
if (cpu_hz % 12000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,2 +1,3 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -40,8 +40,7 @@ uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_MOUSE()
};
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
// USB HID object: desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_MOUSE, 2, false);
//------------- Low pass filter with Butterworth -------------//

View file

@ -59,14 +59,14 @@ static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
if (cpu_hz % 12000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,2 +1,3 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -42,11 +42,9 @@ uint8_t const desc_hid_report[] = {
TUD_HID_REPORT_DESC_KEYBOARD()
};
// USB HID object. For ESP32 these values cannot be changed after this declaration
// desc report, desc len, protocol, interval, use out endpoint
// USB HID object: desc report, desc len, protocol, interval, use out endpoint
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false);
void setup() {
Serial.begin(115200);
usb_hid.begin();

View file

@ -59,14 +59,14 @@ static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
if (cpu_hz % 12000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -38,7 +38,7 @@
#endif
// SdFat is required for using Adafruit_USBH_MSC_SdFatDevice
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// USBHost is defined in usbh_helper.h
#include "usbh_helper.h"
@ -73,7 +73,9 @@ void data_log(void) {
}
// Turn on LED when start writing
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH);
#endif
f_log = fatfs.open(LOG_FILE, O_WRITE | O_APPEND | O_CREAT);
@ -112,7 +114,9 @@ void usbhost_rtos_task(void *param) {
void setup() {
Serial.begin(115200);
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
#if defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
// init host stack on controller (rhport) 1
@ -172,10 +176,12 @@ bool write_complete_callback(uint8_t dev_addr, tuh_msc_complete_data_t const *cb
(void) dev_addr;
(void) cb_data;
#ifdef LED_BUILTIN
// turn off LED after write is complete
// Note this only marks the usb transfer is complete, device can take longer to actual
// write data to physical flash
digitalWrite(LED_BUILTIN, LOW);
#endif
return true;
}

View file

@ -59,14 +59,14 @@ static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
if (cpu_hz % 12000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -27,7 +27,7 @@
*/
// SdFat is required for using Adafruit_USBH_MSC_SdFatDevice
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// USBHost is defined in usbh_helper.h
#include "usbh_helper.h"

View file

@ -59,14 +59,14 @@ static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
if (cpu_hz % 12000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -59,14 +59,14 @@ static void rp2040_configure_pio_usb(void) {
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Core1 setup to run TinyUSB host with pio-usb");
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
// Check for CPU frequency, must be multiple of 12 Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
if (cpu_hz % 12000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 120 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n");
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be multiple of 12 Mhz\r\n", cpu_hz);
Serial.printf("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed \r\n");
while (1) {
delay(1);
}

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -66,9 +66,18 @@ void setup() {
usb_hid.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// led pin
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
#endif
// overwrite input pin with PIN_BUTTONx
#ifdef PIN_BUTTON1
@ -169,6 +178,8 @@ void hid_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8
// Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0)
uint8_t ledIndicator = buffer[0];
#ifdef LED_BUILTIN
// turn on LED if capslock is set
digitalWrite(LED_BUILTIN, ledIndicator & KEYBOARD_LED_CAPSLOCK);
#endif
}

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -59,6 +59,8 @@ void setup() {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
// Set up button, pullup opposite to active state
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
@ -67,10 +69,15 @@ void setup() {
usb_hid.setPollInterval(2);
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.setStringDescriptor("TinyUSB Mouse");
usb_hid.begin();
Serial.begin(115200);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.println("Adafruit TinyUSB HID Mouse example");
}

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -70,17 +70,24 @@ void setup() {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
// Set up HID
usb_hid.setPollInterval(2);
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.setStringDescriptor("TinyUSB HID Composite");
usb_hid.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Set up button, pullup opposite to active state
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
Serial.begin(115200);
Serial.println("Adafruit TinyUSB HID Composite example");
}

View file

@ -1,2 +1,3 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -56,13 +56,20 @@ void setup() {
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
// Notes: following commented-out functions has no affect on ESP32
// usb_hid.setPollInterval(2);
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.begin();
Serial.begin(115200);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.println("Adafruit TinyUSB HID Mouse with Joy FeatherWing example");
if (!ss.begin(0x49)) {

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -67,6 +67,8 @@ void setup() {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
// HID Keyboard
usb_keyboard.setPollInterval(2);
usb_keyboard.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD);
@ -81,10 +83,16 @@ void setup() {
usb_mouse.setStringDescriptor("TinyUSB HID Keyboard");
usb_mouse.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Set up button, pullup opposite to active state
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
Serial.begin(115200);
Serial.println("Adafruit TinyUSB HID Composite example");
}

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -47,6 +47,13 @@ void setup() {
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.println("Adafruit TinyUSB HID Gamepad example");
}

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -53,16 +53,23 @@ void setup() {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
// Notes: following commented-out functions has no affect on ESP32
usb_hid.enableOutEndpoint(true);
usb_hid.setPollInterval(2);
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.setStringDescriptor("TinyUSB HID Generic");
usb_hid.setReportCallback(get_report_callback, set_report_callback);
usb_hid.begin();
Serial.begin(115200);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
Serial.println("Adafruit TinyUSB HID Generic In Out example");
}

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -19,9 +19,10 @@
// USB MIDI object with 3 ports
Adafruit_USBD_MIDI usb_midi(3);
void setup()
{
void setup() {
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
@ -32,12 +33,17 @@ void setup()
usb_midi.setCableName(1, "Keyboard");
usb_midi.setCableName(2, "Drum Pads");
usb_midi.setCableName(3, "Lights");
usb_midi.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
}
void loop()
{
void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
@ -48,6 +54,8 @@ void loop()
static uint8_t led_state = 0;
if (millis() - ms > 1000) {
ms = millis();
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, 1-led_state);
#endif
}
}

View file

@ -0,0 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -42,7 +42,7 @@ void setup() {
TinyUSBDevice.begin(0);
}
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
usb_midi.setStringDescriptor("TinyUSB MIDI");
@ -50,14 +50,19 @@ void setup() {
// This will also call usb_midi's begin()
MIDI.begin(MIDI_CHANNEL_OMNI);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Attach the handleNoteOn function to the MIDI Library. It will
// be called whenever the Bluefruit receives MIDI Note On messages.
MIDI.setHandleNoteOn(handleNoteOn);
// Do the same for MIDI Note Off messages.
MIDI.setHandleNoteOff(handleNoteOff);
Serial.begin(115200);
}
void loop() {

View file

@ -32,7 +32,7 @@
*/
#include "SPI.h"
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
#include "Adafruit_SPIFlash.h"
#include "Adafruit_TinyUSB.h"
@ -93,14 +93,19 @@ void setupMassStorage(void)
// MSC is ready for read/write
fs_changed = false;
usb_msc.setReadyCallback(0, msc_ready_callback);
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Init file system on the flash
fs_formatted = fatfs.begin(&flash);
if ( !fs_formatted )
{
if ( !fs_formatted ) {
DBG_SERIAL.println("Failed to init files system, flash may not be formatted");
}
}

View file

@ -1,2 +1,3 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -23,7 +23,7 @@
*/
#include "SPI.h"
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
#include "Adafruit_SPIFlash.h"
#include "Adafruit_TinyUSB.h"
@ -48,9 +48,12 @@ bool fs_formatted = false;
bool fs_changed = true;;
// the setup function runs once when you press reset or power the board
void setup()
{
void setup() {
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
Serial.begin(115200);
flash.begin();
@ -68,10 +71,16 @@ void setup()
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Init file system on the flash
fs_formatted = fatfs.begin(&flash);
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage External Flash example");
@ -79,15 +88,12 @@ void setup()
Serial.print("Flash size: "); Serial.print(flash.size() / 1024); Serial.println(" KB");
}
void loop()
{
void loop() {
// check if formatted
if ( !fs_formatted )
{
if ( !fs_formatted ) {
fs_formatted = fatfs.begin(&flash);
if (!fs_formatted)
{
if (!fs_formatted) {
Serial.println("Failed to init files system, flash may not be formatted");
Serial.println("Please format it as FAT12 with your PC or using Adafruit_SPIFlash's SdFat_format example:");
Serial.println("- https://github.com/adafruit/Adafruit_SPIFlash/tree/master/examples/SdFat_format");
@ -98,14 +104,12 @@ void loop()
}
}
if ( fs_changed )
{
if ( fs_changed ) {
fs_changed = false;
Serial.println("Opening root");
if ( !root.open("/") )
{
if ( !root.open("/") ) {
Serial.println("open root failed");
return;
}
@ -115,13 +119,11 @@ void loop()
// Open next file in root.
// Warning, openNext starts at the current directory position
// so a rewind of the directory may be required.
while ( file.openNext(&root, O_RDONLY) )
{
while ( file.openNext(&root, O_RDONLY) ) {
file.printFileSize(&Serial);
Serial.write(' ');
file.printName(&Serial);
if ( file.isDir() )
{
if ( file.isDir() ) {
// Indicate a directory.
Serial.write('/');
}
@ -139,8 +141,7 @@ void loop()
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
// Note: SPIFLash Block API: readBlocks/writeBlocks/syncBlocks
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
return flash.readBlocks(lba, (uint8_t*) buffer, bufsize/512) ? bufsize : -1;
@ -149,9 +150,10 @@ int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH);
#endif
// Note: SPIFLash Block API: readBlocks/writeBlocks/syncBlocks
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
@ -160,8 +162,7 @@ int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_cb (void)
{
void msc_flush_cb (void) {
// sync with flash
flash.syncBlocks();
@ -170,5 +171,7 @@ void msc_flush_cb (void)
fs_changed = true;
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LOW);
#endif
}

View file

@ -1,2 +1,3 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -23,7 +23,7 @@
*/
#include "SPI.h"
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
#include "Adafruit_SPIFlash.h"
#include "Adafruit_TinyUSB.h"
@ -33,42 +33,67 @@
// for flashTransport definition
#include "flash_config.h"
Adafruit_SPIFlash flash(&flashTransport);
// External Flash File system
FatVolume fatfs;
//--------------------------------------------------------------------+
// SDCard Config
//--------------------------------------------------------------------+
#if defined(ARDUINO_PYPORTAL_M4) || defined(ARDUINO_PYPORTAL_M4_TITANO)
// PyPortal has on-board card reader
#define SDCARD_CS 32
#define SDCARD_DETECT 33
#define SDCARD_CS 32
#define SDCARD_DETECT 33
#define SDCARD_DETECT_ACTIVE HIGH
#elif defined(ARDUINO_ADAFRUIT_METRO_RP2040)
#define SDIO_CLK_PIN 18
#define SDIO_CMD_PIN 19 // MOSI
#define SDIO_DAT0_PIN 20 // DAT1: 21, DAT2: 22, DAT3: 23
#define SDCARD_DETECT 15
#define SDCARD_DETECT_ACTIVE LOW
#elif defined(ARDUINO_ADAFRUIT_METRO_RP2350)
// Note: not working yet (need troubleshoot later)
#define SDIO_CLK_PIN 34
#define SDIO_CMD_PIN 35 // MOSI
#define SDIO_DAT0_PIN 36 // DAT1: 37, DAT2: 38, DAT3: 39
#define SDCARD_DETECT 40
#define SDCARD_DETECT_ACTIVE LOW
#elif defined(ARDUINO_ADAFRUIT_FRUITJAM_RP2350)
#define SDIO_CLK_PIN 34
#define SDIO_CMD_PIN 35 // MOSI
#define SDIO_DAT0_PIN 36 // DAT1: 37, DAT2: 38, DAT3: 39
#define SDCARD_DETECT 33
#define SDCARD_DETECT_ACTIVE LOW
#else
// Use SPI, no detect
#define SDCARD_CS 10
// no detect
#endif
// SDCard File system
#if defined(SDIO_CLK_PIN) && defined(SDIO_CMD_PIN) && defined(SDIO_DAT0_PIN)
#define SD_CONFIG SdioConfig(SDIO_CLK_PIN, SDIO_CMD_PIN, SDIO_DAT0_PIN)
#else
#define SD_CONFIG SdSpiConfig(SDCARD_CS, SHARED_SPI, SD_SCK_MHZ(50))
#endif
// File system on SD Card
SdFat sd;
// USB Mass Storage object
Adafruit_USBD_MSC usb_msc;
// Set to true when PC write to flash
bool sd_changed = false;
bool sd_inited = false;
bool flash_formatted = false;
bool flash_changed = false;
// the setup function runs once when you press reset or power the board
void setup()
{
void setup() {
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
Serial.begin(115200);
// MSC with 2 Logical Units: LUN0: External Flash, LUN1: SDCard
@ -83,16 +108,20 @@ void setup()
// LUN readiness will always be set later on
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
//------------- Lun 0 for external flash -------------//
flash.begin();
flash_formatted = fatfs.begin(&flash);
usb_msc.setCapacity(0, flash.size()/512, 512);
usb_msc.setReadWriteCallback(0, external_flash_read_cb, external_flash_write_cb, external_flash_flush_cb);
usb_msc.setUnitReady(0, true);
flash_changed = true; // to print contents initially
//------------- Lun 1 for SD card -------------//
#ifdef SDCARD_DETECT
// DETECT pin is available, detect card present on the fly with test unit ready
@ -105,58 +134,44 @@ void setup()
usb_msc.setUnitReady(1, true);
#endif
// while ( !Serial ) delay(10); // wait for native usb
// while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage External Flash + SD Card example");
delay(1000);
}
bool init_sdcard(void)
{
bool init_sdcard(void) {
Serial.print("Init SDCard ... ");
if ( !sd.begin(SDCARD_CS, SD_SCK_MHZ(50)) )
{
Serial.print("Failed ");
sd.errorPrint("sd.begin() failed");
if (!sd.begin(SD_CONFIG)) {
Serial.println("initialization failed. Things to check:");
Serial.println("- is a card inserted?");
Serial.println("- is your wiring correct?");
Serial.println("- did you change the SDCARD_CS or SDIO pin to match your shield or module?");
return false;
}
uint32_t block_count;
#if SD_FAT_VERSION >= 20000
block_count = sd.card()->sectorCount();
#else
block_count = sd.card()->cardSize();
#endif
uint32_t block_count = sd.card()->sectorCount();
usb_msc.setCapacity(1, block_count, 512);
usb_msc.setReadWriteCallback(1, sdcard_read_cb, sdcard_write_cb, sdcard_flush_cb);
sd_changed = true; // to print contents initially
Serial.print("OK, Card size = ");
Serial.print((block_count / (1024*1024)) * 512);
Serial.print((block_count / (1024 * 1024)) * 512);
Serial.println(" MB");
return true;
}
void print_rootdir(File32* rdir)
{
void print_rootdir(File32* rdir) {
File32 file;
// Open next file in root.
// Warning, openNext starts at the current directory position
// so a rewind of the directory may be required.
while ( file.openNext(rdir, O_RDONLY) )
{
while (file.openNext(rdir, O_RDONLY)) {
file.printFileSize(&Serial);
Serial.write(' ');
file.printName(&Serial);
if ( file.isDir() )
{
if (file.isDir()) {
// Indicate a directory.
Serial.write('/');
}
@ -165,46 +180,8 @@ void print_rootdir(File32* rdir)
}
}
void loop()
{
if ( flash_changed )
{
if (!flash_formatted)
{
flash_formatted = fatfs.begin(&flash);
}
// skip if still not formatted
if (flash_formatted)
{
File32 root;
root = fatfs.open("/");
Serial.println("Flash contents:");
print_rootdir(&root);
Serial.println();
root.close();
}
flash_changed = false;
}
if ( sd_changed )
{
File32 root;
root = sd.open("/");
Serial.println("SD contents:");
print_rootdir(&root);
Serial.println();
root.close();
sd_changed = false;
}
delay(1000); // refresh every 1 second
void loop() {
// nothing to do
}
@ -212,76 +189,48 @@ void loop()
// SD Card callbacks
//--------------------------------------------------------------------+
int32_t sdcard_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
bool rc;
#if SD_FAT_VERSION >= 20000
rc = sd.card()->readSectors(lba, (uint8_t*) buffer, bufsize/512);
#else
rc = sd.card()->readBlocks(lba, (uint8_t*) buffer, bufsize/512);
#endif
int32_t sdcard_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
bool rc = sd.card()->readSectors(lba, (uint8_t*) buffer, bufsize/512);
return rc ? bufsize : -1;
}
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t sdcard_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
bool rc;
int32_t sdcard_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH);
#if SD_FAT_VERSION >= 20000
rc = sd.card()->writeSectors(lba, buffer, bufsize/512);
#else
rc = sd.card()->writeBlocks(lba, buffer, bufsize/512);
#endif
bool rc = sd.card()->writeSectors(lba, buffer, bufsize/512);
return rc ? bufsize : -1;
}
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void sdcard_flush_cb (void)
{
#if SD_FAT_VERSION >= 20000
void sdcard_flush_cb (void) {
sd.card()->syncDevice();
#else
sd.card()->syncBlocks();
#endif
// clear file system's cache to force refresh
sd.cacheClear();
sd_changed = true;
sd.cacheClear(); // clear file system's cache to force refresh
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LOW);
#endif
}
#ifdef SDCARD_DETECT
// Invoked when received Test Unit Ready command.
// return true allowing host to read/write this LUN e.g SD card inserted
bool sdcard_ready_callback(void)
{
bool sdcard_ready_callback(void) {
// Card is inserted
if ( digitalRead(SDCARD_DETECT) == HIGH )
{
if (digitalRead(SDCARD_DETECT) == SDCARD_DETECT_ACTIVE) {
// init SD card if not already
if ( !sd_inited )
{
if (!sd_inited) {
sd_inited = init_sdcard();
}
}else
{
} else {
sd_inited = false;
usb_msc.setReadWriteCallback(1, NULL, NULL, NULL);
}
Serial.println(sd_inited);
return sd_inited;
}
#endif
@ -293,8 +242,7 @@ bool sdcard_ready_callback(void)
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t external_flash_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
int32_t external_flash_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
return flash.readBlocks(lba, (uint8_t*) buffer, bufsize/512) ? bufsize : -1;
@ -303,9 +251,10 @@ int32_t external_flash_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t external_flash_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
int32_t external_flash_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH);
#endif
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
@ -314,14 +263,9 @@ int32_t external_flash_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void external_flash_flush_cb (void)
{
void external_flash_flush_cb (void) {
flash.syncBlocks();
// clear file system's cache to force refresh
fatfs.cacheClear();
flash_changed = true;
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LOW);
#endif
}

View file

@ -10,7 +10,7 @@
*********************************************************************/
#include "SPI.h"
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
#include "Adafruit_InternalFlash.h"
#include "Adafruit_TinyUSB.h"
@ -35,8 +35,9 @@ Adafruit_USBD_MSC usb_msc;
bool fs_changed;
// the setup function runs once when you press reset or power the board
void setup()
{
void setup() {
Serial.begin(115200);
// Initialize internal flash
flash.begin();
@ -46,32 +47,30 @@ void setup()
// Set callback
usb_msc.setReadWriteCallback(msc_read_callback, msc_write_callback, msc_flush_callback);
usb_msc.setWritableCallback(msc_writable_callback);
// Set disk size, block size should be 512 regardless of flash page size
usb_msc.setCapacity(flash.size()/512, 512);
// Set Lun ready
usb_msc.setUnitReady(true);
usb_msc.setCapacity(flash.size()/512, 512); // Set disk size, block size should be 512 regardless of flash page size
usb_msc.setUnitReady(true); // Set Lun ready
usb_msc.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// Init file system on the flash
fatfs.begin(&flash);
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
fs_changed = true; // to print contents initially
}
void loop()
{
if ( fs_changed )
{
void loop() {
if ( fs_changed ) {
fs_changed = false;
if ( !root.open("/") )
{
if ( !root.open("/") ) {
Serial.println("open root failed");
return;
}
@ -81,13 +80,11 @@ void loop()
// Open next file in root.
// Warning, openNext starts at the current directory position
// so a rewind of the directory may be required.
while ( file.openNext(&root, O_RDONLY) )
{
while ( file.openNext(&root, O_RDONLY) ) {
file.printFileSize(&Serial);
Serial.write(' ');
file.printName(&Serial);
if ( file.isDir() )
{
if ( file.isDir() ) {
// Indicate a directory.
Serial.write('/');
}
@ -105,8 +102,7 @@ void loop()
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_callback (uint32_t lba, void* buffer, uint32_t bufsize)
{
int32_t msc_read_callback (uint32_t lba, void* buffer, uint32_t bufsize) {
// Note: InternalFlash Block API: readBlocks/writeBlocks/syncBlocks
// already include sector caching (if needed). We don't need to cache it, yahhhh!!
return flash.readBlocks(lba, (uint8_t*) buffer, bufsize/512) ? bufsize : -1;
@ -115,8 +111,7 @@ int32_t msc_read_callback (uint32_t lba, void* buffer, uint32_t bufsize)
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_callback (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
int32_t msc_write_callback (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
// Note: InternalFlash Block API: readBlocks/writeBlocks/syncBlocks
// already include sector caching (if needed). We don't need to cache it, yahhhh!!
return flash.writeBlocks(lba, buffer, bufsize/512) ? bufsize : -1;
@ -124,8 +119,7 @@ int32_t msc_write_callback (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_callback (void)
{
void msc_flush_callback (void) {
// sync with flash
flash.syncBlocks();
@ -137,8 +131,7 @@ void msc_flush_callback (void)
// Invoked to check if device is writable as part of SCSI WRITE10
// Default mode is writable
bool msc_writable_callback(void)
{
bool msc_writable_callback(void) {
// true for writable, false for read-only
return true;
}

View file

@ -1 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -42,6 +42,8 @@ void setup() {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
#ifdef BTN_EJECT
pinMode(BTN_EJECT, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
#endif
@ -61,9 +63,14 @@ void setup() {
usb_msc.setUnitReady(true);
usb_msc.begin();
Serial.begin(115200);
// while ( !Serial ) delay(10); // wait for native usb
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage RAM Disk example");
}

View file

@ -1,2 +1,3 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -26,6 +26,8 @@ void setup() {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
usb_msc.setMaxLun(2);
// Set disk size and callback for Logical Unit 0 (LUN 0)
@ -42,9 +44,14 @@ void setup() {
usb_msc.begin();
Serial.begin(115200);
//while ( !Serial ) delay(10); // wait for native usb
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage Dual RAM Disks example");
}

View file

@ -1,8 +1,10 @@
feather_esp32_v2
feather_esp32s2
feather_esp32s3
funhouse
magtag
metroesp32s2
esp32p4
feather_rp2040_tinyusb
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -26,6 +26,8 @@ SdVolume volume;
// the setup function runs once when you press reset or power the board
void setup()
{
Serial.begin(115200);
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
usb_msc.setID("Adafruit", "SD Card", "1.0");
@ -37,15 +39,18 @@ void setup()
usb_msc.setUnitReady(false);
usb_msc.begin();
Serial.begin(115200);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage SD Card example");
Serial.println("\nInitializing SD card...");
if ( !card.init(SPI_HALF_SPEED, chipSelect) )
{
if ( !card.init(SPI_HALF_SPEED, chipSelect) ) {
Serial.println("initialization failed. Things to check:");
Serial.println("* is a card inserted?");
Serial.println("* is your wiring correct?");
@ -71,16 +76,14 @@ void setup()
usb_msc.setUnitReady(true);
}
void loop()
{
void loop() {
// nothing to do
}
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
(void) bufsize;
return card.readBlock(lba, (uint8_t*) buffer) ? 512 : -1;
}
@ -88,15 +91,13 @@ int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
(void) bufsize;
return card.writeBlock(lba, buffer) ? 512 : -1;
}
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_cb (void)
{
void msc_flush_cb (void) {
// nothing to do
}

View file

@ -1 +1,2 @@
feather_esp32_v2
pico_rp2040_tinyusb_host

View file

@ -10,31 +10,69 @@
*********************************************************************/
/* This example expose SD card as mass storage using
* SdFat Library
* - SdFat https://github.com/adafruit/SdFat
*/
#include "SPI.h"
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
#include "Adafruit_TinyUSB.h"
const int chipSelect = 10;
//--------------------------------------------------------------------+
// SDCard Config
//--------------------------------------------------------------------+
#if defined(ARDUINO_PYPORTAL_M4) || defined(ARDUINO_PYPORTAL_M4_TITANO)
// PyPortal has on-board card reader
#define SDCARD_CS 32
#define SDCARD_DETECT 33
#define SDCARD_DETECT_ACTIVE HIGH
#elif defined(ARDUINO_ADAFRUIT_METRO_RP2040)
#define SDIO_CLK_PIN 18
#define SDIO_CMD_PIN 19 // MOSI
#define SDIO_DAT0_PIN 20 // DAT1: 21, DAT2: 22, DAT3: 23
#define SDCARD_DETECT 15
#define SDCARD_DETECT_ACTIVE LOW
#elif defined(ARDUINO_ADAFRUIT_METRO_RP2350)
#define SDIO_CLK_PIN 34
#define SDIO_CMD_PIN 35 // MOSI
#define SDIO_DAT0_PIN 36 // DAT1: 37, DAT2: 38, DAT3: 39
#define SDCARD_DETECT 40
#define SDCARD_DETECT_ACTIVE LOW
#elif defined(ARDUINO_ADAFRUIT_FRUITJAM_RP2350)
#define SDIO_CLK_PIN 34
#define SDIO_CMD_PIN 35 // MOSI
#define SDIO_DAT0_PIN 36 // DAT1: 37, DAT2: 38, DAT3: 39
#define SDCARD_DETECT 33
#define SDCARD_DETECT_ACTIVE LOW
#else
// Use SPI, no detect
#define SDCARD_CS 10
#endif
#if defined(SDIO_CLK_PIN) && defined(SDIO_CMD_PIN) && defined(SDIO_DAT0_PIN)
#define SD_CONFIG SdioConfig(SDIO_CLK_PIN, SDIO_CMD_PIN, SDIO_DAT0_PIN)
#else
#define SD_CONFIG SdSpiConfig(SDCARD_CS, SHARED_SPI, SD_SCK_MHZ(50))
#endif
// File system on SD Card
SdFat sd;
SdFile root;
SdFile file;
// USB Mass Storage object
Adafruit_USBD_MSC usb_msc;
// Set to true when PC write to flash
bool fs_changed;
// the setup function runs once when you press reset or power the board
void setup()
{
void setup() {
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
#endif
Serial.begin(115200);
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
usb_msc.setID("Adafruit", "SD Card", "1.0");
@ -47,30 +85,27 @@ void setup()
usb_msc.setUnitReady(false);
usb_msc.begin();
Serial.begin(115200);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
//while ( !Serial ) delay(10); // wait for native usb
Serial.println("Adafruit TinyUSB Mass Storage SD Card example");
Serial.print("\nInitializing SD card ... ");
Serial.print("CS = "); Serial.println(chipSelect);
if ( !sd.begin(chipSelect, SD_SCK_MHZ(50)) )
{
if (!sd.begin(SD_CONFIG)) {
Serial.println("initialization failed. Things to check:");
Serial.println("* is a card inserted?");
Serial.println("* is your wiring correct?");
Serial.println("* did you change the chipSelect pin to match your shield or module?");
Serial.println("- is a card inserted?");
Serial.println("- is your wiring correct?");
Serial.println("- did you change the SDCARD_CS or SDIO pin to match your shield or module?");
while (1) delay(1);
}
// Size in blocks (512 bytes)
#if SD_FAT_VERSION >= 20000
uint32_t block_count = sd.card()->sectorCount();
#else
uint32_t block_count = sd.card()->cardSize();
#endif
Serial.print("Volume size (MB): ");
Serial.println((block_count/2) / 1024);
@ -79,91 +114,38 @@ void setup()
// MSC is ready for read/write
usb_msc.setUnitReady(true);
fs_changed = true; // to print contents initially
}
void loop()
{
if ( fs_changed )
{
root.open("/");
Serial.println("SD contents:");
// Open next file in root.
// Warning, openNext starts at the current directory position
// so a rewind of the directory may be required.
while ( file.openNext(&root, O_RDONLY) )
{
file.printFileSize(&Serial);
Serial.write(' ');
file.printName(&Serial);
if ( file.isDir() )
{
// Indicate a directory.
Serial.write('/');
}
Serial.println();
file.close();
}
root.close();
Serial.println();
fs_changed = false;
delay(1000); // refresh every 0.5 second
}
void loop() {
// noting to do
}
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
bool rc;
#if SD_FAT_VERSION >= 20000
rc = sd.card()->readSectors(lba, (uint8_t*) buffer, bufsize/512);
#else
rc = sd.card()->readBlocks(lba, (uint8_t*) buffer, bufsize/512);
#endif
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize) {
bool rc = sd.card()->readSectors(lba, (uint8_t*) buffer, bufsize/512);
return rc ? bufsize : -1;
}
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
bool rc;
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, HIGH);
#if SD_FAT_VERSION >= 20000
rc = sd.card()->writeSectors(lba, buffer, bufsize/512);
#else
rc = sd.card()->writeBlocks(lba, buffer, bufsize/512);
#endif
bool rc = sd.card()->writeSectors(lba, buffer, bufsize/512);
return rc ? bufsize : -1;
}
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_cb (void)
{
#if SD_FAT_VERSION >= 20000
void msc_flush_cb (void) {
sd.card()->syncDevice();
#else
sd.card()->syncBlocks();
#endif
// clear file system's cache to force refresh
sd.cacheClear();
fs_changed = true;
sd.cacheClear(); // clear file system's cache to force refresh
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, LOW);
#endif
}

View file

@ -1,2 +1,3 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -63,6 +63,13 @@ void setup() {
// init i2c usb with buffer and size
i2c_usb.begin(i2c_buf, sizeof(i2c_buf));
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
}
void loop() {

View file

@ -1,2 +1,3 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT

View file

@ -134,6 +134,13 @@ void setup() {
usb_video.addColorMatching(&desc_color);
usb_video.begin();
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
}
void loop() {

View file

@ -1,3 +1,4 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT
# CH32V20x_EVT is not supported due to Adafruit_Neopixel

View file

@ -59,12 +59,20 @@ void setup() {
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
//usb_web.setStringDescriptor("TinyUSB WebUSB");
usb_web.setLandingPage(&landingPage);
usb_web.setLineStateCallback(line_state_callback);
usb_web.begin();
Serial.begin(115200);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// This initializes the NeoPixel with RED
#ifdef NEOPIXEL_POWER

View file

@ -1,3 +1,4 @@
feather_esp32_v2
pico_rp2040_tinyusb_host
CH32V20x_EVT
# CH32V20x_EVT is not supported due to lacking of HardwareSerial::read(uint8_t [64], int)

View file

@ -34,24 +34,30 @@ Adafruit_USBD_WebUSB usb_web;
// Page source can be found at https://github.com/hathach/tinyusb-webusb-page/tree/main/webusb-serial
WEBUSB_URL_DEF(landingPage, 1 /*https*/, "example.tinyusb.org/webusb-serial/index.html");
int led_pin = LED_BUILTIN;
// the setup function runs once when you press reset or power the board
void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}
Serial.begin(115200);
pinMode(led_pin, OUTPUT);
digitalWrite(led_pin, LOW);
#ifdef LED_BUILTIN
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
#endif
usb_web.setLandingPage(&landingPage);
usb_web.setLineStateCallback(line_state_callback);
//usb_web.setStringDescriptor("TinyUSB WebUSB");
usb_web.begin();
Serial.begin(115200);
// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
// wait until device mounted
while (!TinyUSBDevice.mounted()) delay(1);
@ -98,7 +104,9 @@ void loop() {
}
void line_state_callback(bool connected) {
digitalWrite(led_pin, connected);
#ifdef LED_BUILTIN
digitalWrite(LED_BUILTIN, connected);
#endif
if (connected) {
usb_web.println("WebUSB interface connected !!");

View file

@ -1,7 +1,22 @@
{
"name": "Adafruit TinyUSB Library",
"keywords": "usb, arduino, tinyusb",
"description": "Arduino library for TinyUSB",
"version": "3.7.1",
"repository": {
"type": "git",
"url": "https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git"
},
"frameworks": "*",
"platforms": "*",
"build": {
"libArchive": false,
"flags": "-DUSE_TINYUSB"
}
"libArchive": false
},
"authors":
[
{
"name": "Adafruit",
"maintainer": true
}
]
}

View file

@ -1,5 +1,5 @@
name=Adafruit TinyUSB Library
version=3.3.3
version=3.7.1
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=TinyUSB library for Arduino

View file

@ -25,11 +25,6 @@
#ifndef ADAFRUIT_TINYUSB_H_
#define ADAFRUIT_TINYUSB_H_
// ESP32 out-of-sync
#ifdef ARDUINO_ARCH_ESP32
#include "arduino/ports/esp32/tusb_config_esp32.h"
#endif
#include "tusb_option.h"
// Device

View file

@ -31,6 +31,8 @@
extern "C" {
uint32_t tusb_time_millis_api(void) { return millis(); }
//--------------------------------------------------------------------+
// Device
//--------------------------------------------------------------------+

View file

@ -38,8 +38,6 @@
#define TINYUSB_API_VERSION 0
#endif
#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
// SerialTinyUSB can be macro expanding to "Serial" on supported cores
Adafruit_USBD_CDC SerialTinyUSB;
@ -71,8 +69,10 @@ uint16_t Adafruit_USBD_CDC::getInterfaceDescriptor(uint8_t itfnum_deprecated,
uint8_t _strid = 0;
#endif
uint8_t const desc[] = {TUD_CDC_DESCRIPTOR(itfnum, _strid, ep_notif, 8,
ep_out, ep_in, BULK_PACKET_SIZE)};
uint16_t const mps =
(TUD_OPT_HIGH_SPEED ? 512 : 64); // TODO actual link speed
uint8_t const desc[] = {
TUD_CDC_DESCRIPTOR(itfnum, _strid, ep_notif, 8, ep_out, ep_in, mps)};
uint16_t const len = sizeof(desc);

View file

@ -161,18 +161,6 @@ void Adafruit_USBD_Device::task(void) {
#endif
}
bool Adafruit_USBD_Device::mounted(void) { return tud_mounted(); }
bool Adafruit_USBD_Device::suspended(void) { return tud_suspended(); }
bool Adafruit_USBD_Device::ready(void) { return tud_ready(); }
bool Adafruit_USBD_Device::remoteWakeup(void) { return tud_remote_wakeup(); }
bool Adafruit_USBD_Device::detach(void) { return tud_disconnect(); }
bool Adafruit_USBD_Device::attach(void) { return tud_connect(); }
void Adafruit_USBD_Device::clearConfiguration(void) {
tusb_desc_device_t const desc_dev = {.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
@ -198,7 +186,7 @@ void Adafruit_USBD_Device::clearConfiguration(void) {
uint8_t const dev_cfg[sizeof(tusb_desc_configuration_t)] = {
TUD_CONFIG_DESCRIPTOR(1, 0, 0, sizeof(tusb_desc_configuration_t),
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP | TU_BIT(7),
100),
USB_CONFIG_POWER),
};
memcpy(_desc_cfg_buffer, dev_cfg, sizeof(tusb_desc_configuration_t));
@ -257,8 +245,10 @@ bool Adafruit_USBD_Device::begin(uint8_t rhport) {
// follow USBCDC cdc descriptor
uint8_t itfnum = allocInterface(2);
uint8_t strid = addStringDescriptor("TinyUSB Serial");
uint16_t const mps =
(TUD_OPT_HIGH_SPEED ? 512 : 64); // TODO actual link speed
uint8_t const desc_cdc[TUD_CDC_DESC_LEN] = {
TUD_CDC_DESCRIPTOR(itfnum, strid, 0x85, 64, 0x03, 0x84, 64)};
TUD_CDC_DESCRIPTOR(itfnum, strid, 0x85, 64, 0x03, 0x84, mps)};
memcpy(_desc_cfg + _desc_cfg_len, desc_cdc, sizeof(desc_cdc));
_desc_cfg_len += sizeof(desc_cdc);

View file

@ -33,6 +33,8 @@
#include "esp32-hal-tinyusb.h"
#endif
#if CFG_TUD_ENABLED
class Adafruit_USBD_Device {
private:
enum { STRING_DESCRIPTOR_MAX = 12 };
@ -78,6 +80,21 @@ public:
// Clear/Reset configuration descriptor
void clearConfiguration(void);
// Set configuration attribute
void setConfigurationAttribute(uint8_t attribute) {
_desc_cfg[offsetof(tusb_desc_configuration_t, bmAttributes)] = attribute;
}
// Set max power consumption in mA (absolute max is 510ma)
bool setConfigurationMaxPower(uint16_t power_ma) {
if (power_ma > 255 * 2u) {
return false;
}
_desc_cfg[offsetof(tusb_desc_configuration_t, bMaxPower)] =
(uint8_t)(power_ma / 2);
return true;
}
// Provide user buffer for configuration descriptor, if total length > 256
void setConfigurationBuffer(uint8_t *buf, uint32_t buflen);
@ -119,14 +136,15 @@ public:
void task(void);
// physical disable/enable pull-up
bool detach(void);
bool attach(void);
bool detach(void) { return tud_disconnect(); }
bool attach(void) { return tud_connect(); }
//------------- status -------------//
bool mounted(void);
bool suspended(void);
bool ready(void);
bool remoteWakeup(void);
bool mounted(void) { return tud_mounted(); }
bool suspended(void) { return tud_suspended(); }
bool ready(void) { return tud_ready(); }
bool remoteWakeup(void) { return tud_remote_wakeup(); }
tusb_speed_t getSpeed(void) { return tud_speed_get(); }
private:
uint16_t const *descriptor_string_cb(uint8_t index, uint16_t langid);
@ -145,4 +163,5 @@ extern Adafruit_USBD_Device TinyUSBDevice;
#define USBDevice TinyUSBDevice
#endif
#endif /* ADAFRUIT_USBD_DEVICE_H_ */
#endif /* CFG_TUD_ENABLED */
#endif /* ADAFRUIT_USBD_DEVICE_H_ */

View file

@ -28,8 +28,6 @@
#include "Adafruit_USBD_MSC.h"
#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
static Adafruit_USBD_MSC *_msc_dev = NULL;
Adafruit_USBD_MSC::Adafruit_USBD_MSC(void) {
@ -51,8 +49,10 @@ uint16_t Adafruit_USBD_MSC::getInterfaceDescriptor(uint8_t itfnum_deprecated,
uint8_t const ep_in = TinyUSBDevice.allocEndpoint(TUSB_DIR_IN);
uint8_t const ep_out = TinyUSBDevice.allocEndpoint(TUSB_DIR_OUT);
uint16_t const mps =
(TUD_OPT_HIGH_SPEED ? 512 : 64); // TODO actual link speed
uint8_t const desc[] = {
TUD_MSC_DESCRIPTOR(itfnum, _strid, ep_out, ep_in, BULK_PACKET_SIZE)};
TUD_MSC_DESCRIPTOR(itfnum, _strid, ep_out, ep_in, mps)};
uint16_t const len = sizeof(desc);
if (bufsize < len) {

View file

@ -34,7 +34,7 @@
#include "Adafruit_USBH_MSC.h"
#include "tusb.h"
#if __has_include("SdFat.h")
#if __has_include("SdFat_Adafruit_Fork.h")
Adafruit_USBH_MSC_BlockDevice::Adafruit_USBH_MSC_BlockDevice() {
_daddr = _lun = 0;

View file

@ -28,9 +28,9 @@
#include "tusb.h"
// define SdFat host helper class if SdFat library is available
#if __has_include("SdFat.h")
#if __has_include("SdFat_Adafruit_Fork.h")
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
class Adafruit_USBH_MSC_BlockDevice : public FsBlockDeviceInterface {
public:

View file

@ -38,17 +38,40 @@ extern "C" {
// libraries, this file is used to make it compatible with ESP32 Arduino core.
// This file also contains additional configuration for EPS32 in addition to
// tools/sdk/esp32xx/include/arduino_tinyusb/include/tusb_config.h
// tools/esp32-arduino-libs/esp32xx/include/arduino_tinyusb/include/tusb_config.h
//--------------------------------------------------------------------+
// ESP32 out-of-sync
//--------------------------------------------------------------------+
#include "esp_arduino_version.h"
#include "sdkconfig.h"
#if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(2, 0, 8)
#error "ESP32 Arduino core version 2.0.8 or later is required"
#endif
//--------------------------------------------------------------------
// COMMON CONFIGURATION
// Note: it is possible to use tinyusb + max3421e as host controller
// with no OTG USB MCU such as eps32, c3 etc...
//--------------------------------------------------------------------
#if CONFIG_IDF_TARGET_ESP32S2
#define CFG_TUSB_MCU OPT_MCU_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S3
#define CFG_TUSB_MCU OPT_MCU_ESP32S3
#elif CONFIG_IDF_TARGET_ESP32P4
#define CFG_TUSB_MCU OPT_MCU_ESP32P4
#else
#define CFG_TUSB_MCU OPT_MCU_ESP32
#endif
#if CONFIG_IDF_TARGET_ESP32P4
#define CFG_TUD_MAX_SPEED OPT_MODE_HIGH_SPEED
#else
#define CFG_TUD_MAX_SPEED OPT_MODE_FULL_SPEED
#endif
#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_FREERTOS
// clang-format off
@ -64,12 +87,6 @@ extern "C" {
#define CFG_TUH_LOG_LEVEL 2
#endif
//--------------------------------------------------------------------
// COMMON CONFIGURATION
// Note: it is possible to use tinyusb + max3421e as host controller
// with no OTG USB MCU such as eps32, c3 etc...
//--------------------------------------------------------------------
#ifndef CFG_TUSB_DEBUG
#define CFG_TUSB_DEBUG 0
#endif
@ -77,12 +94,48 @@ extern "C" {
// For selectively disable device log (when > CFG_TUSB_DEBUG)
// #define CFG_TUD_LOG_LEVEL 3
#define CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4)
//--------------------------------------------------------------------
// DEVICE CONFIGURATION
// only enabled if USB OTG is supported
//--------------------------------------------------------------------
#if defined(CONFIG_USB_OTG_SUPPORTED) && CONFIG_USB_OTG_SUPPORTED
#define CFG_TUD_ENABLED 1
#else
#define CFG_TUD_ENABLED 0
#endif
// device configuration is configured in BSP
// sdk/include/arduino_tinyusb/include/tusb_config.h
#define CFG_TUD_CDC 2
#define CFG_TUD_MSC 1
#define CFG_TUD_HID 2
#define CFG_TUD_MIDI 1
#define CFG_TUD_VENDOR 1
#define CFG_TUD_VIDEO 1
#define CFG_TUD_VIDEO_STREAMING 1
// video streaming endpoint buffer size
#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE \
CONFIG_TINYUSB_VIDEO_STREAMING_BUFSIZE
// CDC FIFO size of TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE
#define CFG_TUD_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE
// MSC Buffer size of Device Mass storage
#define CFG_TUD_MSC_EP_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE
// HID buffer size Should be sufficient to hold ID (if any) + Data
#define CFG_TUD_HID_BUFSIZE CONFIG_TINYUSB_HID_BUFSIZE
// MIDI FIFO size of TX and RX
#define CFG_TUD_MIDI_RX_BUFSIZE CONFIG_TINYUSB_MIDI_RX_BUFSIZE
#define CFG_TUD_MIDI_TX_BUFSIZE CONFIG_TINYUSB_MIDI_TX_BUFSIZE
// Vendor FIFO size of TX and RX
#define CFG_TUD_VENDOR_RX_BUFSIZE CONFIG_TINYUSB_VENDOR_RX_BUFSIZE
#define CFG_TUD_VENDOR_TX_BUFSIZE CONFIG_TINYUSB_VENDOR_TX_BUFSIZE
//--------------------------------------------------------------------
// Host Configuration
@ -90,8 +143,8 @@ extern "C" {
// Enable host stack with MAX3421E (host shield)
#define CFG_TUH_ENABLED 1
#define CFG_TUH_MAX_SPEED OPT_MODE_FULL_SPEED
#define CFG_TUH_MAX3421 1
#define CFG_TUH_MAX_SPEED OPT_MODE_FULL_SPEED
#ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL
#define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4 * (CFG_TUH_DEVICE_MAX - 1))

View file

@ -82,7 +82,7 @@ extern "C" {
#define CFG_TUD_ENDPOINT0_SIZE 64
#ifndef CFG_TUD_CDC
#define CFG_TUD_CDC 1
#define CFG_TUD_CDC 2
#endif
#ifndef CFG_TUD_MSC
#define CFG_TUD_MSC 1
@ -117,8 +117,8 @@ extern "C" {
#define CFG_TUD_HID_EP_BUFSIZE 64
// MIDI FIFO size of TX and RX
#define CFG_TUD_MIDI_RX_BUFSIZE 128
#define CFG_TUD_MIDI_TX_BUFSIZE 128
#define CFG_TUD_MIDI_RX_BUFSIZE 64
#define CFG_TUD_MIDI_TX_BUFSIZE 64
// Vendor FIFO size of TX and RX
#define CFG_TUD_VENDOR_RX_BUFSIZE 64

View file

@ -661,6 +661,7 @@ typedef struct TU_ATTR_PACKED
uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors.
uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t.
} audio_desc_cs_ac_interface_t;
TU_VERIFY_STATIC(sizeof(audio_desc_cs_ac_interface_t) == 9, "size is not correct");
/// AUDIO Clock Source Descriptor (4.7.2.1)
typedef struct TU_ATTR_PACKED

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,7 @@
*
* Copyright (c) 2020 Ha Thach (tinyusb.org)
* Copyright (c) 2020 Reinhard Panhuber
* Copyright (c) 2023 HiFiPhile
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -192,6 +193,7 @@
#endif
// Enable/disable conversion from 16.16 to 10.14 format on full-speed devices. See tud_audio_n_fb_set().
// Can be override by tud_audio_feedback_format_correction_cb()
#ifndef CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION 0 // 0 or 1
#endif
@ -201,6 +203,9 @@
#define CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP 0 // Feedback - 0 or 1
#endif
// Audio control interrupt EP - 6 Bytes according to UAC 2 specification (p. 74)
#define CFG_TUD_AUDIO_INTERRUPT_EP_SZ 6
// Use software encoding/decoding
// The software coding feature of the driver is not mandatory. It is useful if, for instance, you have two I2S streams which need to be interleaved
@ -242,7 +247,8 @@
// Enable encoding/decodings - for these to work, support FIFOs need to be setup in appropriate numbers and size
// The actual coding parameters of active AS alternate interface is parsed from the descriptors
// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sampe_sz) * sampe_sz)!
// The item size of the FIFO is always fixed to one i.e. bytes! Furthermore, the actively used FIFO depth is reconfigured such that the depth is a multiple
// of the current sample size in order to avoid samples to get split up in case of a wrap in the FIFO ring buffer (depth = (max_depth / sample_sz) * sample_sz)!
// This is important to remind in case you use DMAs! If the sample sizes changes, the DMA MUST BE RECONFIGURED just like the FIFOs for a different depth!!!
// For PCM encoding/decoding
@ -446,63 +452,80 @@ static inline bool tud_audio_int_write (const audio_interru
bool tud_audio_buffer_and_schedule_control_xfer(uint8_t rhport, tusb_control_request_t const * p_request, void* data, uint16_t len);
//--------------------------------------------------------------------+
// Application Callback API (weak is optional)
// Application Callback API
//--------------------------------------------------------------------+
#if CFG_TUD_AUDIO_ENABLE_EP_IN
TU_ATTR_WEAK bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting);
TU_ATTR_WEAK bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting);
bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting);
bool tud_audio_tx_done_post_load_cb(uint8_t rhport, uint16_t n_bytes_copied, uint8_t func_id, uint8_t ep_in, uint8_t cur_alt_setting);
#endif
#if CFG_TUD_AUDIO_ENABLE_EP_OUT
TU_ATTR_WEAK bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting);
TU_ATTR_WEAK bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting);
bool tud_audio_rx_done_pre_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting);
bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, uint8_t func_id, uint8_t ep_out, uint8_t cur_alt_setting);
#endif
#if CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
TU_ATTR_WEAK void tud_audio_fb_done_cb(uint8_t func_id);
void tud_audio_fb_done_cb(uint8_t func_id);
// determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer. Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 8 frames), i.e. a larger delay is introduced.
// Note about feedback calculation
//
// Option 1 - AUDIO_FEEDBACK_METHOD_FIFO_COUNT
// Feedback value is calculated within the audio driver by regulating the FIFO level to half fill.
// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load, well tested
// (Windows, Linux, OSX) with a reliable result so far.
// Disadvantage: A FIFO of minimal 4 frames is needed to compensate for jitter, an average delay of 2 frames is introduced.
//
// Option 2 - AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED / AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT
// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from
// which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter).
// See tud_audio_set_fb_params() and tud_audio_feedback_update()
// Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller and thus a smaller delay is possible.
// Disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. (The most critical point is the reading of the cycle counter value of f_m.
// It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced).
// Long-term drift could occur since error is accumulated.
//
// Option 3 - manual
// Determined by the user itself and set by use of tud_audio_n_fb_set(). The feedback value may be determined e.g. from some fill status of some FIFO buffer.
// Advantage: No ISR interrupt is enabled, hence the CPU need not to handle an ISR every 1ms or 125us and thus less CPU load.
// Disadvantage: typically a larger FIFO is needed to compensate for jitter (e.g. 6 frames), i.e. a larger delay is introduced.
// Feedback value is calculated within the audio driver by use of SOF interrupt. The driver needs information about the master clock f_m from which the audio sample frequency f_s is derived, f_s itself, and the cycle count of f_m at time of the SOF interrupt (e.g. by use of a hardware counter) - see tud_audio_set_fb_params(). Advantage: Reduced jitter in the feedback value computation, hence, the receive FIFO can be smaller (e.g. 2 frames) and thus a smaller delay is possible, disadvantage: higher CPU load due to SOF ISR handling every frame i.e. 1ms or 125us. This option is a great starting point to try the SOF ISR option but depending on your hardware setup (performance of the CPU) it might not work. If so, figure out why and use the next option. (The most critical point is the reading of the cycle counter value of f_m. It is read from within the SOF ISR - see: audiod_sof() -, hence, the ISR must has a high priority such that no software dependent "random" delay i.e. jitter is introduced).
// Feedback value is determined by the user by use of SOF interrupt. The user may use tud_audio_sof_isr() which is called every SOF (of course only invoked when an alternate interface other than zero was set). The number of frames used to determine the feedback value for the currently active alternate setting can be get by tud_audio_get_fb_n_frames(). The feedback value must be set by use of tud_audio_n_fb_set().
// This function is used to provide data rate feedback from an asynchronous sink. Feedback value will be sent at FB endpoint interval till it's changed.
//
// The feedback format is specified to be 16.16 for HS and 10.14 for FS devices (see Universal Serial Bus Specification Revision 2.0 5.12.4.2). By default,
// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set, then tinyusb
// expects 16.16 format and handles the conversion to 10.14 on FS.
// the choice of format is left to the caller and feedback argument is sent as-is. If CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION is set or tud_audio_feedback_format_correction_cb()
// return true, then tinyusb expects 16.16 format and handles the conversion to 10.14 on FS.
//
// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and it seems the
// driver can work with either format.
//
// Note that due to a bug in its USB Audio 2.0 driver, Windows currently requires 16.16 format for _all_ USB 2.0 devices. On Linux and macOS it seems the
// driver can work with either format. So a good compromise is to keep format correction disabled and stick to 16.16 format.
// Feedback value can be determined from within the SOF ISR of the audio driver. This should reduce jitter. If the feature is used, the user can not set the feedback value.
//
// Determine feedback value - The feedback method is described in 5.12.4.2 of the USB 2.0 spec
// Boiled down, the feedback value Ff = n_samples / (micro)frame.
// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13 for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s)
// Since an accuracy of less than 1 Sample / second is desired, at least n_frames = ceil(2^K * f_s / f_m) frames need to be measured, where K = 10 for full speed and K = 13
// for high speed, f_s is the sampling frequency e.g. 48 kHz and f_m is the cpu clock frequency e.g. 100 MHz (or any other master clock whose clock count is available and locked to f_s)
// The update interval in the (4.10.2.1) Feedback Endpoint Descriptor must be less or equal to 2^(K - P), where P = min( ceil(log2(f_m / f_s)), K)
// feedback = n_cycles / n_frames * f_s / f_m in 16.16 format, where n_cycles are the number of main clock cycles within fb_n_frames
bool tud_audio_n_fb_set(uint8_t func_id, uint32_t feedback);
static inline bool tud_audio_fb_set(uint32_t feedback);
// Update feedback value with passed cycles since last time this update function is called.
// Update feedback value with passed MCLK cycles since last time this update function is called.
// Typically called within tud_audio_sof_isr(). Required tud_audio_feedback_params_cb() is implemented
// This function will also call tud_audio_feedback_set()
// return feedback value in 16.16 for reference (0 for error)
// Example :
// binterval=3 (4ms); FS = 48kHz; MCLK = 12.288MHz
// In 4 SOF MCLK counted 49152 cycles
uint32_t tud_audio_feedback_update(uint8_t func_id, uint32_t cycles);
enum {
AUDIO_FEEDBACK_METHOD_DISABLED,
AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED,
AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT,
AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2,
// impelemnt later
// AUDIO_FEEDBACK_METHOD_FIFO_COUNT
AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2, // For driver internal use only
AUDIO_FEEDBACK_METHOD_FIFO_COUNT
};
typedef struct {
@ -514,52 +537,50 @@ typedef struct {
uint32_t mclk_freq; // Main clock frequency in Hz i.e. master clock to which sample clock is based on
}frequency;
#if 0 // implement later
struct {
uint32_t threshold_bytes; // minimum number of bytes received to be considered as filled/ready
}fifo_count;
#endif
};
}audio_feedback_params_t;
// Invoked when needed to set feedback parameters
TU_ATTR_WEAK void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param);
void tud_audio_feedback_params_cb(uint8_t func_id, uint8_t alt_itf, audio_feedback_params_t* feedback_param);
// Callback in ISR context, invoked periodically according to feedback endpoint bInterval.
// Could be used to compute and update feedback value, should be placed in RAM if possible
// frame_number : current SOF count
// interval_shift: number of bit shift i.e log2(interval) from Feedback endpoint descriptor
TU_ATTR_WEAK TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift);
TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t frame_number, uint8_t interval_shift);
// (Full-Speed only) Callback to set feedback format correction is applied or not,
// default to CFG_TUD_AUDIO_ENABLE_FEEDBACK_FORMAT_CORRECTION if not implemented.
bool tud_audio_feedback_format_correction_cb(uint8_t func_id);
#endif // CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP
#if CFG_TUD_AUDIO_ENABLE_INTERRUPT_EP
TU_ATTR_WEAK void tud_audio_int_done_cb(uint8_t rhport);
void tud_audio_int_done_cb(uint8_t rhport);
#endif
// Invoked when audio set interface request received
TU_ATTR_WEAK bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
// Invoked when audio set interface request received which closes an EP
TU_ATTR_WEAK bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request);
bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const * p_request);
// Invoked when audio class specific set request received for an EP
TU_ATTR_WEAK bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
bool tud_audio_set_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
// Invoked when audio class specific set request received for an interface
TU_ATTR_WEAK bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
bool tud_audio_set_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
// Invoked when audio class specific set request received for an entity
TU_ATTR_WEAK bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request, uint8_t *pBuff);
// Invoked when audio class specific get request received for an EP
TU_ATTR_WEAK bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request);
bool tud_audio_get_req_ep_cb(uint8_t rhport, tusb_control_request_t const * p_request);
// Invoked when audio class specific get request received for an interface
TU_ATTR_WEAK bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
bool tud_audio_get_req_itf_cb(uint8_t rhport, tusb_control_request_t const * p_request);
// Invoked when audio class specific get request received for an entity
TU_ATTR_WEAK bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request);
bool tud_audio_get_req_entity_cb(uint8_t rhport, tusb_control_request_t const * p_request);
//--------------------------------------------------------------------+
// Inline Functions

View file

@ -31,37 +31,35 @@
//--------------------------------------------------------------------+
// INCLUDE
//--------------------------------------------------------------------+
// ESP32 out-of-sync
#ifdef ARDUINO_ARCH_ESP32
#include "arduino/ports/esp32/tusb_config_esp32.h"
#endif
#include "bth_device.h"
#include <device/usbd_pvt.h>
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
typedef struct
{
typedef struct {
uint8_t itf_num;
uint8_t ep_ev;
uint8_t ep_acl_in;
uint16_t ep_acl_in_pkt_sz;
uint8_t ep_acl_out;
uint8_t ep_voice[2]; // Not used yet
uint8_t ep_voice_size[2][CFG_TUD_BTH_ISO_ALT_COUNT];
// Endpoint Transfer buffer
CFG_TUSB_MEM_ALIGN bt_hci_cmd_t hci_cmd;
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_BTH_DATA_EPSIZE];
// Previous amount of bytes sent when issuing ZLP
uint32_t prev_xferred_bytes;
} btd_interface_t;
typedef struct {
TUD_EPBUF_DEF(epout_buf, CFG_TUD_BTH_DATA_EPSIZE);
TUD_EPBUF_TYPE_DEF(bt_hci_cmd_t, hci_cmd);
} btd_epbuf_t;
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
CFG_TUD_MEM_SECTION btd_interface_t _btd_itf;
static btd_interface_t _btd_itf;
CFG_TUD_MEM_SECTION static btd_epbuf_t _btd_epbuf;
static bool bt_tx_data(uint8_t ep, void *data, uint16_t len)
{
@ -133,14 +131,28 @@ uint16_t btd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_
TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0);
_btd_itf.ep_ev = desc_ep->bEndpointAddress;
// Open endpoint pair
TU_ASSERT(usbd_open_edpt_pair(rhport, tu_desc_next(desc_ep), 2, TUSB_XFER_BULK, &_btd_itf.ep_acl_out,
&_btd_itf.ep_acl_in), 0);
desc_ep = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep);
itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(tu_desc_next(desc_ep)));
// Open endpoint pair
TU_ASSERT(usbd_open_edpt_pair(rhport, (uint8_t const *)desc_ep, 2,
TUSB_XFER_BULK, &_btd_itf.ep_acl_out,
&_btd_itf.ep_acl_in),
0);
// Save acl in endpoint max packet size
tusb_desc_endpoint_t const *desc_ep_acl_in = desc_ep;
for (size_t p = 0; p < 2; p++) {
if (tu_edpt_dir(desc_ep_acl_in->bEndpointAddress) == TUSB_DIR_IN) {
_btd_itf.ep_acl_in_pkt_sz = tu_edpt_packet_size(desc_ep_acl_in);
break;
}
desc_ep_acl_in = (tusb_desc_endpoint_t const *)tu_desc_next(desc_ep_acl_in);
}
itf_desc = (tusb_desc_interface_t const *)tu_desc_next(tu_desc_next(desc_ep));
// Prepare for incoming data from host
TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0);
TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_epbuf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE), 0);
drv_len = hci_itf_size;
@ -231,30 +243,30 @@ bool btd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t c
}
else return false;
return tud_control_xfer(rhport, request, &_btd_itf.hci_cmd, sizeof(_btd_itf.hci_cmd));
return tud_control_xfer(rhport, request, &_btd_epbuf.hci_cmd, sizeof(bt_hci_cmd_t));
}
else if ( stage == CONTROL_STAGE_DATA )
{
// Handle class request only
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
if (tud_bt_hci_cmd_cb) tud_bt_hci_cmd_cb(&_btd_itf.hci_cmd, tu_min16(request->wLength, sizeof(_btd_itf.hci_cmd)));
if (tud_bt_hci_cmd_cb) {
tud_bt_hci_cmd_cb(&_btd_epbuf.hci_cmd, tu_min16(request->wLength, sizeof(bt_hci_cmd_t)));
}
}
return true;
}
bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
{
(void)result;
bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result,
uint32_t xferred_bytes) {
// received new data from host
if (ep_addr == _btd_itf.ep_acl_out)
{
if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_itf.epout_buf, xferred_bytes);
if (tud_bt_acl_data_received_cb) tud_bt_acl_data_received_cb(_btd_epbuf.epout_buf, xferred_bytes);
// prepare for next data
TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_itf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE));
TU_ASSERT(usbd_edpt_xfer(rhport, _btd_itf.ep_acl_out, _btd_epbuf.epout_buf, CFG_TUD_BTH_DATA_EPSIZE));
}
else if (ep_addr == _btd_itf.ep_ev)
{
@ -262,7 +274,20 @@ bool btd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t
}
else if (ep_addr == _btd_itf.ep_acl_in)
{
if (tud_bt_acl_data_sent_cb) tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes);
if ((result == XFER_RESULT_SUCCESS) && (xferred_bytes > 0) &&
((xferred_bytes & (_btd_itf.ep_acl_in_pkt_sz - 1)) == 0)) {
// Save number of transferred bytes
_btd_itf.prev_xferred_bytes = xferred_bytes;
// Send zero-length packet
tud_bt_acl_data_send(NULL, 0);
} else if (tud_bt_acl_data_sent_cb) {
if (xferred_bytes == 0) {
xferred_bytes = _btd_itf.prev_xferred_bytes;
_btd_itf.prev_xferred_bytes = 0;
}
tud_bt_acl_data_sent_cb((uint16_t)xferred_bytes);
}
}
return true;

View file

@ -24,11 +24,6 @@
* This file is part of the TinyUSB stack.
*/
// ESP32 out-of-sync
#ifdef ARDUINO_ARCH_ESP32
#include "arduino/ports/esp32/tusb_config_esp32.h"
#endif
#include "tusb_option.h"
#if (CFG_TUD_ENABLED && CFG_TUD_CDC)
@ -72,22 +67,27 @@ typedef struct {
OSAL_MUTEX_DEF(rx_ff_mutex);
OSAL_MUTEX_DEF(tx_ff_mutex);
// Endpoint Transfer buffer
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_CDC_EP_BUFSIZE];
CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_CDC_EP_BUFSIZE];
} cdcd_interface_t;
#define ITF_MEM_RESET_SIZE offsetof(cdcd_interface_t, wanted_char)
typedef struct {
TUD_EPBUF_DEF(epout, CFG_TUD_CDC_EP_BUFSIZE);
TUD_EPBUF_DEF(epin, CFG_TUD_CDC_EP_BUFSIZE);
} cdcd_epbuf_t;
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
CFG_TUD_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
static tud_cdc_configure_fifo_t _cdcd_fifo_cfg;
static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC];
static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
uint8_t const rhport = 0;
static tud_cdc_configure_t _cdcd_cfg = TUD_CDC_CONFIGURE_DEFAULT();
static bool _prep_out_transaction(uint8_t itf) {
const uint8_t rhport = 0;
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf];
// Skip if usb is not ready yet
TU_VERIFY(tud_ready() && p_cdc->ep_out);
@ -98,7 +98,7 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
// TODO Actually we can still carry out the transfer, keeping count of received bytes
// and slowly move it to the FIFO when read().
// This pre-check reduces endpoint claiming
TU_VERIFY(available >= sizeof(p_cdc->epout_buf));
TU_VERIFY(available >= CFG_TUD_CDC_EP_BUFSIZE);
// claim endpoint
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_out));
@ -106,9 +106,9 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
// fifo can be changed before endpoint is claimed
available = tu_fifo_remaining(&p_cdc->rx_ff);
if ( available >= sizeof(p_cdc->epout_buf) ) {
return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_cdc->epout_buf, sizeof(p_cdc->epout_buf));
}else {
if (available >= CFG_TUD_CDC_EP_BUFSIZE) {
return usbd_edpt_xfer(rhport, p_cdc->ep_out, p_epbuf->epout, CFG_TUD_CDC_EP_BUFSIZE);
} else {
// Release endpoint since we don't make any transfer
usbd_edpt_release(rhport, p_cdc->ep_out);
return false;
@ -119,9 +119,9 @@ static bool _prep_out_transaction (cdcd_interface_t* p_cdc) {
// APPLICATION API
//--------------------------------------------------------------------+
bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg) {
TU_VERIFY(cfg);
_cdcd_fifo_cfg = (*cfg);
bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg) {
TU_VERIFY(driver_cfg);
_cdcd_cfg = *driver_cfg;
return true;
}
@ -156,7 +156,7 @@ uint32_t tud_cdc_n_available(uint8_t itf) {
uint32_t tud_cdc_n_read(uint8_t itf, void* buffer, uint32_t bufsize) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
uint32_t num_read = tu_fifo_read_n(&p_cdc->rx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
_prep_out_transaction(p_cdc);
_prep_out_transaction(itf);
return num_read;
}
@ -167,15 +167,15 @@ bool tud_cdc_n_peek(uint8_t itf, uint8_t* chr) {
void tud_cdc_n_read_flush(uint8_t itf) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
tu_fifo_clear(&p_cdc->rx_ff);
_prep_out_transaction(p_cdc);
_prep_out_transaction(itf);
}
//--------------------------------------------------------------------+
// WRITE API
//--------------------------------------------------------------------+
uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) {
uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
uint16_t wr_count = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
// flush if queue more than packet size
if (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE
@ -186,28 +186,31 @@ uint32_t tud_cdc_n_write(uint8_t itf, void const* buffer, uint32_t bufsize) {
tud_cdc_n_write_flush(itf);
}
return ret;
return wr_count;
}
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);
// No data to send
if (!tu_fifo_count(&p_cdc->tx_ff)) return 0;
if (!tu_fifo_count(&p_cdc->tx_ff)) {
return 0;
}
uint8_t const rhport = 0;
const uint8_t rhport = 0;
// Claim the endpoint
TU_VERIFY(usbd_edpt_claim(rhport, p_cdc->ep_in), 0);
// Pull data from FIFO
uint16_t const count = tu_fifo_read_n(&p_cdc->tx_ff, p_cdc->epin_buf, sizeof(p_cdc->epin_buf));
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_cdc->epin_buf, count), 0);
TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, p_epbuf->epin, count), 0);
return count;
} else {
// Release endpoint since we don't make any transfer
@ -230,8 +233,6 @@ bool tud_cdc_n_write_clear(uint8_t itf) {
//--------------------------------------------------------------------+
void cdcd_init(void) {
tu_memclr(_cdcd_itf, sizeof(_cdcd_itf));
tu_memclr(&_cdcd_fifo_cfg, sizeof(_cdcd_fifo_cfg));
for (uint8_t i = 0; i < CFG_TUD_CDC; i++) {
cdcd_interface_t* p_cdc = &_cdcd_itf[i];
@ -246,10 +247,10 @@ void cdcd_init(void) {
// Config RX fifo
tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false);
// Config TX fifo as overwritable at initialization and will be changed to non-overwritable
// if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal.
// In this way, the most current data is prioritized.
tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true);
// TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not
// know if data is actually polled by terminal. This way the most current data is prioritized.
// Default: is overwritable
tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, _cdcd_cfg.tx_overwritabe_if_not_connected);
#if OSAL_MUTEX_REQUIRED
osal_mutex_t mutex_rd = osal_mutex_create(&p_cdc->rx_ff_mutex);
@ -291,32 +292,37 @@ void cdcd_reset(uint8_t rhport) {
cdcd_interface_t* p_cdc = &_cdcd_itf[i];
tu_memclr(p_cdc, ITF_MEM_RESET_SIZE);
if (!_cdcd_fifo_cfg.rx_persistent) tu_fifo_clear(&p_cdc->rx_ff);
if (!_cdcd_fifo_cfg.tx_persistent) tu_fifo_clear(&p_cdc->tx_ff);
tu_fifo_set_overwritable(&p_cdc->tx_ff, true);
if (!_cdcd_cfg.rx_persistent) {
tu_fifo_clear(&p_cdc->rx_ff);
}
if (!_cdcd_cfg.tx_persistent) {
tu_fifo_clear(&p_cdc->tx_ff);
}
tu_fifo_set_overwritable(&p_cdc->tx_ff, _cdcd_cfg.tx_overwritabe_if_not_connected);
}
}
uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len) {
uint16_t cdcd_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16_t max_len) {
// Only support ACM subclass
TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass, 0);
// Find available interface
cdcd_interface_t* p_cdc = NULL;
for (uint8_t cdc_id = 0; cdc_id < CFG_TUD_CDC; cdc_id++) {
if (_cdcd_itf[cdc_id].ep_in == 0) {
p_cdc = &_cdcd_itf[cdc_id];
cdcd_interface_t* p_cdc;
uint8_t cdc_id;
for (cdc_id = 0; cdc_id < CFG_TUD_CDC; cdc_id++) {
p_cdc = &_cdcd_itf[cdc_id];
if (p_cdc->ep_in == 0) {
break;
}
}
TU_ASSERT(p_cdc, 0);
TU_ASSERT(cdc_id < CFG_TUD_CDC, 0);
//------------- Control Interface -------------//
p_cdc->itf_num = itf_desc->bInterfaceNumber;
uint16_t drv_len = sizeof(tusb_desc_interface_t);
uint8_t const* p_desc = tu_desc_next(itf_desc);
const uint8_t* p_desc = tu_desc_next(itf_desc);
// Communication Functional Descriptors
while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) {
@ -326,7 +332,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
if (TUSB_DESC_ENDPOINT == tu_desc_type(p_desc)) {
// notification endpoint
tusb_desc_endpoint_t const* desc_ep = (tusb_desc_endpoint_t const*) p_desc;
const tusb_desc_endpoint_t* desc_ep = (const tusb_desc_endpoint_t*) p_desc;
TU_ASSERT(usbd_edpt_open(rhport, desc_ep), 0);
p_cdc->ep_notif = desc_ep->bEndpointAddress;
@ -337,7 +343,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
//------------- Data Interface (if any) -------------//
if ((TUSB_DESC_INTERFACE == tu_desc_type(p_desc)) &&
(TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const*) p_desc)->bInterfaceClass)) {
(TUSB_CLASS_CDC_DATA == ((const tusb_desc_interface_t*) p_desc)->bInterfaceClass)) {
// next to endpoint descriptor
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
@ -349,7 +355,7 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
}
// Prepare for incoming data
_prep_out_transaction(p_cdc);
_prep_out_transaction(cdc_id);
return drv_len;
}
@ -357,19 +363,21 @@ uint16_t cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint1
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request) {
// Handle class request only
TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
uint8_t itf = 0;
cdcd_interface_t* p_cdc = _cdcd_itf;
uint8_t itf;
cdcd_interface_t* p_cdc;
// Identify which interface to use
for (;; itf++, p_cdc++) {
if (itf >= TU_ARRAY_SIZE(_cdcd_itf)) return false;
if (p_cdc->itf_num == request->wIndex) break;
for (itf = 0; itf < CFG_TUD_CDC; itf++) {
p_cdc = &_cdcd_itf[itf];
if (p_cdc->itf_num == request->wIndex) {
break;
}
}
TU_VERIFY(itf < CFG_TUD_CDC);
switch (request->bRequest) {
case CDC_REQUEST_SET_LINE_CODING:
@ -377,7 +385,9 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
TU_LOG_DRV(" Set Line Coding\r\n");
tud_control_xfer(rhport, request, &p_cdc->line_coding, sizeof(cdc_line_coding_t));
} else if (stage == CONTROL_STAGE_ACK) {
if (tud_cdc_line_coding_cb) tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
if (tud_cdc_line_coding_cb) {
tud_cdc_line_coding_cb(itf, &p_cdc->line_coding);
}
}
break;
@ -402,13 +412,19 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
p_cdc->line_state = (uint8_t) request->wValue;
// Disable fifo overwriting if DTR bit is set
tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr);
// If enabled: fifo overwriting is disabled if DTR bit is set and vice versa
if (_cdcd_cfg.tx_overwritabe_if_not_connected) {
tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr);
} else {
tu_fifo_set_overwritable(&p_cdc->tx_ff, false);
}
TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
// Invoke callback
if (tud_cdc_line_state_cb) tud_cdc_line_state_cb(itf, dtr, rts);
if (tud_cdc_line_state_cb) {
tud_cdc_line_state_cb(itf, dtr, rts);
}
}
break;
@ -417,7 +433,9 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
tud_control_status(rhport, request);
} else if (stage == CONTROL_STAGE_ACK) {
TU_LOG_DRV(" Send Break\r\n");
if (tud_cdc_send_break_cb) tud_cdc_send_break_cb(itf, request->wValue);
if (tud_cdc_send_break_cb) {
tud_cdc_send_break_cb(itf, request->wValue);
}
}
break;
@ -437,28 +455,33 @@ 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)) break;
if ((ep_addr == p_cdc->ep_out) || (ep_addr == p_cdc->ep_in)) {
break;
}
}
TU_ASSERT(itf < CFG_TUD_CDC);
cdcd_epbuf_t* p_epbuf = &_cdcd_epbuf[itf];
// Received new data
if (ep_addr == p_cdc->ep_out) {
tu_fifo_write_n(&p_cdc->rx_ff, p_cdc->epout_buf, (uint16_t) xferred_bytes);
tu_fifo_write_n(&p_cdc->rx_ff, p_epbuf->epout, (uint16_t) xferred_bytes);
// Check for wanted char and invoke callback if needed
if (tud_cdc_rx_wanted_cb && (((signed char) p_cdc->wanted_char) != -1)) {
for (uint32_t i = 0; i < xferred_bytes; i++) {
if ((p_cdc->wanted_char == p_cdc->epout_buf[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) {
if ((p_cdc->wanted_char == p_epbuf->epout[i]) && !tu_fifo_empty(&p_cdc->rx_ff)) {
tud_cdc_rx_wanted_cb(itf, p_cdc->wanted_char);
}
}
}
// invoke receive callback (if there is still data)
if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) tud_cdc_rx_cb(itf);
if (tud_cdc_rx_cb && !tu_fifo_empty(&p_cdc->rx_ff)) {
tud_cdc_rx_cb(itf);
}
// prepare for OUT transaction
_prep_out_transaction(p_cdc);
_prep_out_transaction(itf);
}
// Data sent to host, we continue to fetch from tx fifo to send.
@ -466,14 +489,16 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
// Though maybe the baudrate is not really important !!!
if (ep_addr == p_cdc->ep_in) {
// invoke transmit callback to possibly refill tx fifo
if (tud_cdc_tx_complete_cb) tud_cdc_tx_complete_cb(itf);
if (tud_cdc_tx_complete_cb) {
tud_cdc_tx_complete_cb(itf);
}
if (0 == tud_cdc_n_write_flush(itf)) {
// If there is no data left, a ZLP should be sent if
// xferred_bytes is multiple of EP Packet size and not zero
if (!tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE - 1)))) {
if (usbd_edpt_claim(rhport, p_cdc->ep_in)) {
usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0);
TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0));
}
}
}

View file

@ -24,8 +24,8 @@
* This file is part of the TinyUSB stack.
*/
#ifndef _TUSB_CDC_DEVICE_H_
#define _TUSB_CDC_DEVICE_H_
#ifndef TUSB_CDC_DEVICE_H_
#define TUSB_CDC_DEVICE_H_
#include "cdc.h"
@ -48,14 +48,24 @@
//--------------------------------------------------------------------+
// Driver Configuration
//--------------------------------------------------------------------+
typedef struct TU_ATTR_PACKED {
uint8_t rx_persistent : 1; // keep rx fifo on bus reset or disconnect
uint8_t tx_persistent : 1; // keep tx fifo on bus reset or disconnect
} tud_cdc_configure_fifo_t;
uint8_t rx_persistent : 1; // keep rx fifo data even with bus reset or disconnect
uint8_t tx_persistent : 1; // keep tx fifo data even with reset or disconnect
uint8_t tx_overwritabe_if_not_connected : 1; // if not connected, tx fifo can be overwritten
} tud_cdc_configure_t;
// Configure CDC FIFOs behavior
bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg);
#define TUD_CDC_CONFIGURE_DEFAULT() { \
.rx_persistent = 0, \
.tx_persistent = 0, \
.tx_overwritabe_if_not_connected = 1, \
}
// Configure CDC driver behavior
bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg);
// Backward compatible
#define tud_cdc_configure_fifo_t tud_cdc_configure_t
#define tud_cdc_configure_fifo tud_cdc_configure
//--------------------------------------------------------------------+
// Application API (Multiple Ports) i.e. CFG_TUD_CDC > 1
@ -204,6 +214,9 @@ TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts);
TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding);
// Invoked when received send break
// \param[in] itf interface for which send break was received.
// \param[in] duration_ms the length of time, in milliseconds, of the break signal. If a value of FFFFh, then the
// device will send a break until another SendBreak request is received with value 0000h.
TU_ATTR_WEAK void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms);
//--------------------------------------------------------------------+

View file

@ -27,38 +27,6 @@
* - Heiko Kuester: CH34x support
*/
// ESP32 out-of-sync
#ifdef ARDUINO_ARCH_ESP32
#include "arduino/ports/esp32/tusb_config_esp32.h"
#ifndef CFG_TUH_CDC_FTDI_VID_PID_LIST
// List of product IDs that can use the FTDI CDC driver. 0x0403 is FTDI's VID
#define CFG_TUH_CDC_FTDI_VID_PID_LIST \
{0x0403, 0x6001}, {0x0403, 0x6006}, {0x0403, 0x6010}, {0x0403, 0x6011}, \
{0x0403, 0x6014}, {0x0403, 0x6015}, {0x0403, 0x8372}, {0x0403, 0xFBFA}, \
{0x0403, 0xCD18}
#endif
#ifndef CFG_TUH_CDC_CP210X_VID_PID_LIST
// List of product IDs that can use the CP210X CDC driver. 0x10C4 is Silicon Labs' VID
#define CFG_TUH_CDC_CP210X_VID_PID_LIST \
{0x10C4, 0xEA60}, {0x10C4, 0xEA70}
#endif
#ifndef CFG_TUH_CDC_CH34X_VID_PID_LIST
// List of product IDs that can use the CH34X CDC driver
#define CFG_TUH_CDC_CH34X_VID_PID_LIST \
{ 0x1a86, 0x5523 }, /* ch341 chip */ \
{ 0x1a86, 0x7522 }, /* ch340k chip */ \
{ 0x1a86, 0x7523 }, /* ch340 chip */ \
{ 0x1a86, 0xe523 }, /* ch330 chip */ \
{ 0x4348, 0x5523 }, /* ch340 custom chip */ \
{ 0x2184, 0x0057 }, /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */ \
{ 0x9986, 0x7523 } /* overtaken from Linux Kernel driver /drivers/usb/serial/ch341.c */
#endif
#endif
#include "tusb_option.h"
#if (CFG_TUH_ENABLED && CFG_TUH_CDC)
@ -105,15 +73,17 @@ typedef struct {
tu_edpt_stream_t rx;
uint8_t tx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE];
CFG_TUH_MEM_ALIGN uint8_t tx_ep_buf[CFG_TUH_CDC_TX_EPSIZE];
uint8_t rx_ff_buf[CFG_TUH_CDC_TX_BUFSIZE];
CFG_TUH_MEM_ALIGN uint8_t rx_ep_buf[CFG_TUH_CDC_TX_EPSIZE];
} stream;
} cdch_interface_t;
CFG_TUH_MEM_SECTION
typedef struct {
TUH_EPBUF_DEF(tx, CFG_TUH_CDC_TX_EPSIZE);
TUH_EPBUF_DEF(rx, CFG_TUH_CDC_TX_EPSIZE);
} cdch_epbuf_t;
static cdch_interface_t cdch_data[CFG_TUH_CDC];
CFG_TUH_MEM_SECTION static cdch_epbuf_t cdch_epbuf[CFG_TUH_CDC];
//--------------------------------------------------------------------+
// Serial Driver
@ -373,14 +343,14 @@ uint32_t tuh_cdc_write(uint8_t idx, void const* buffer, uint32_t bufsize) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return tu_edpt_stream_write(&p_cdc->stream.tx, buffer, bufsize);
return tu_edpt_stream_write(p_cdc->daddr, &p_cdc->stream.tx, buffer, bufsize);
}
uint32_t tuh_cdc_write_flush(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return tu_edpt_stream_write_xfer(&p_cdc->stream.tx);
return tu_edpt_stream_write_xfer(p_cdc->daddr, &p_cdc->stream.tx);
}
bool tuh_cdc_write_clear(uint8_t idx) {
@ -394,7 +364,7 @@ uint32_t tuh_cdc_write_available(uint8_t idx) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return tu_edpt_stream_write_available(&p_cdc->stream.tx);
return tu_edpt_stream_write_available(p_cdc->daddr, &p_cdc->stream.tx);
}
//--------------------------------------------------------------------+
@ -405,7 +375,7 @@ uint32_t tuh_cdc_read (uint8_t idx, void* buffer, uint32_t bufsize) {
cdch_interface_t* p_cdc = get_itf(idx);
TU_VERIFY(p_cdc);
return tu_edpt_stream_read(&p_cdc->stream.rx, buffer, bufsize);
return tu_edpt_stream_read(p_cdc->daddr, &p_cdc->stream.rx, buffer, bufsize);
}
uint32_t tuh_cdc_read_available(uint8_t idx) {
@ -427,7 +397,7 @@ bool tuh_cdc_read_clear (uint8_t idx) {
TU_VERIFY(p_cdc);
bool ret = tu_edpt_stream_clear(&p_cdc->stream.rx);
tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx);
return ret;
}
@ -658,13 +628,14 @@ bool cdch_init(void) {
tu_memclr(cdch_data, sizeof(cdch_data));
for (size_t i = 0; i < CFG_TUH_CDC; i++) {
cdch_interface_t* p_cdc = &cdch_data[i];
cdch_epbuf_t* epbuf = &cdch_epbuf[i];
tu_edpt_stream_init(&p_cdc->stream.tx, true, true, false,
p_cdc->stream.tx_ff_buf, CFG_TUH_CDC_TX_BUFSIZE,
p_cdc->stream.tx_ep_buf, CFG_TUH_CDC_TX_EPSIZE);
epbuf->tx, CFG_TUH_CDC_TX_EPSIZE);
tu_edpt_stream_init(&p_cdc->stream.rx, true, false, false,
p_cdc->stream.rx_ff_buf, CFG_TUH_CDC_RX_BUFSIZE,
p_cdc->stream.rx_ep_buf, CFG_TUH_CDC_RX_EPSIZE);
epbuf->rx, CFG_TUH_CDC_RX_EPSIZE);
}
return true;
@ -686,7 +657,9 @@ void cdch_close(uint8_t daddr) {
TU_LOG_DRV(" CDCh close addr = %u index = %u\r\n", daddr, idx);
// Invoke application callback
if (tuh_cdc_umount_cb) tuh_cdc_umount_cb(idx);
if (tuh_cdc_umount_cb) {
tuh_cdc_umount_cb(idx);
}
p_cdc->daddr = 0;
p_cdc->bInterfaceNumber = 0;
@ -699,7 +672,7 @@ void cdch_close(uint8_t daddr) {
bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) {
// TODO handle stall response, retry failed transfer ...
TU_ASSERT(event == XFER_RESULT_SUCCESS);
TU_VERIFY(event == XFER_RESULT_SUCCESS);
uint8_t const idx = get_idx_by_ep_addr(daddr, ep_addr);
cdch_interface_t * p_cdc = get_itf(idx);
@ -707,19 +680,21 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t
if ( ep_addr == p_cdc->stream.tx.ep_addr ) {
// invoke tx complete callback to possibly refill tx fifo
if (tuh_cdc_tx_complete_cb) tuh_cdc_tx_complete_cb(idx);
if (tuh_cdc_tx_complete_cb) {
tuh_cdc_tx_complete_cb(idx);
}
if ( 0 == tu_edpt_stream_write_xfer(&p_cdc->stream.tx) ) {
if ( 0 == tu_edpt_stream_write_xfer(daddr, &p_cdc->stream.tx) ) {
// If there is no data left, a ZLP should be sent if:
// - xferred_bytes is multiple of EP Packet size and not zero
tu_edpt_stream_write_zlp_if_needed(&p_cdc->stream.tx, xferred_bytes);
tu_edpt_stream_write_zlp_if_needed(daddr, &p_cdc->stream.tx, xferred_bytes);
}
} else if ( ep_addr == p_cdc->stream.rx.ep_addr ) {
#if CFG_TUH_CDC_FTDI
if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) {
if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI && xferred_bytes > 2) {
// FTDI reserve 2 bytes for status
// uint8_t status[2] = {p_cdc->stream.rx.ep_buf[0], p_cdc->stream.rx.ep_buf[1]};
tu_edpt_stream_read_xfer_complete_offset(&p_cdc->stream.rx, xferred_bytes, 2);
tu_edpt_stream_read_xfer_complete_with_buf(&p_cdc->stream.rx, p_cdc->stream.rx.ep_buf+2, xferred_bytes-2);
}else
#endif
{
@ -727,10 +702,12 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t
}
// invoke receive callback
if (tuh_cdc_rx_cb) tuh_cdc_rx_cb(idx);
if (tuh_cdc_rx_cb) {
tuh_cdc_rx_cb(idx);
}
// prepare for next transfer if needed
tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
tu_edpt_stream_read_xfer(daddr, &p_cdc->stream.rx);
}else if ( ep_addr == p_cdc->ep_notif ) {
// TODO handle notification endpoint
}else {
@ -751,9 +728,9 @@ static bool open_ep_stream_pair(cdch_interface_t* p_cdc, tusb_desc_endpoint_t co
TU_ASSERT(tuh_edpt_open(p_cdc->daddr, desc_ep));
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
tu_edpt_stream_open(&p_cdc->stream.rx, p_cdc->daddr, desc_ep);
tu_edpt_stream_open(&p_cdc->stream.rx, desc_ep);
} else {
tu_edpt_stream_open(&p_cdc->stream.tx, p_cdc->daddr, desc_ep);
tu_edpt_stream_open(&p_cdc->stream.tx, desc_ep);
}
desc_ep = (tusb_desc_endpoint_t const*) tu_desc_next(desc_ep);
@ -770,9 +747,8 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d
if (TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass) {
return acm_open(daddr, itf_desc, max_len);
}
else if (SERIAL_DRIVER_COUNT > 1 &&
TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) {
} else if (SERIAL_DRIVER_COUNT > 1 &&
TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) {
uint16_t vid, pid;
TU_VERIFY(tuh_vid_pid_get(daddr, &vid, &pid));
@ -792,10 +768,12 @@ bool cdch_open(uint8_t rhport, uint8_t daddr, tusb_desc_interface_t const *itf_d
static void set_config_complete(cdch_interface_t * p_cdc, uint8_t idx, uint8_t itf_num) {
TU_LOG_DRV("CDCh Set Configure complete\r\n");
p_cdc->mounted = true;
if (tuh_cdc_mount_cb) tuh_cdc_mount_cb(idx);
if (tuh_cdc_mount_cb) {
tuh_cdc_mount_cb(idx);
}
// Prepare for incoming data
tu_edpt_stream_read_xfer(&p_cdc->stream.rx);
tu_edpt_stream_read_xfer(p_cdc->daddr, &p_cdc->stream.rx);
// notify usbh that driver enumeration is complete
usbh_driver_set_config_complete(p_cdc->daddr, itf_num);

View file

@ -49,22 +49,22 @@
// RX FIFO size
#ifndef CFG_TUH_CDC_RX_BUFSIZE
#define CFG_TUH_CDC_RX_BUFSIZE USBH_EPSIZE_BULK_MAX
#define CFG_TUH_CDC_RX_BUFSIZE TUH_EPSIZE_BULK_MPS
#endif
// RX Endpoint size
#ifndef CFG_TUH_CDC_RX_EPSIZE
#define CFG_TUH_CDC_RX_EPSIZE USBH_EPSIZE_BULK_MAX
#define CFG_TUH_CDC_RX_EPSIZE TUH_EPSIZE_BULK_MPS
#endif
// TX FIFO size
#ifndef CFG_TUH_CDC_TX_BUFSIZE
#define CFG_TUH_CDC_TX_BUFSIZE USBH_EPSIZE_BULK_MAX
#define CFG_TUH_CDC_TX_BUFSIZE TUH_EPSIZE_BULK_MPS
#endif
// TX Endpoint size
#ifndef CFG_TUH_CDC_TX_EPSIZE
#define CFG_TUH_CDC_TX_EPSIZE USBH_EPSIZE_BULK_MAX
#define CFG_TUH_CDC_TX_EPSIZE TUH_EPSIZE_BULK_MPS
#endif
//--------------------------------------------------------------------+
@ -89,8 +89,7 @@ bool tuh_cdc_get_dtr(uint8_t idx);
bool tuh_cdc_get_rts(uint8_t idx);
// Check if interface is connected (DTR active)
TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx)
{
TU_ATTR_ALWAYS_INLINE static inline bool tuh_cdc_connected(uint8_t idx) {
return tuh_cdc_get_dtr(idx);
}

View file

@ -24,11 +24,6 @@
* This file is part of the TinyUSB stack.
*/
// ESP32 out-of-sync
#ifdef ARDUINO_ARCH_ESP32
#include "arduino/ports/esp32/tusb_config_esp32.h"
#endif
#include "tusb_option.h"
#if (CFG_TUD_ENABLED && CFG_TUD_DFU)
@ -52,8 +47,7 @@
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
typedef struct
{
typedef struct {
uint8_t attrs;
uint8_t alt;
@ -63,69 +57,65 @@ typedef struct
bool flashing_in_progress;
uint16_t block;
uint16_t length;
CFG_TUSB_MEM_ALIGN uint8_t transfer_buf[CFG_TUD_DFU_XFER_BUFSIZE];
} dfu_state_ctx_t;
// Only a single dfu state is allowed
CFG_TUD_MEM_SECTION tu_static dfu_state_ctx_t _dfu_ctx;
static dfu_state_ctx_t _dfu_ctx;
static void reset_state(void)
{
CFG_TUD_MEM_SECTION static struct {
TUD_EPBUF_DEF(transfer_buf, CFG_TUD_DFU_XFER_BUFSIZE);
} _dfu_epbuf;
static void reset_state(void) {
_dfu_ctx.state = DFU_IDLE;
_dfu_ctx.status = DFU_STATUS_OK;
_dfu_ctx.flashing_in_progress = false;
}
static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout);
static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request);
static bool reply_getstatus(uint8_t rhport, const tusb_control_request_t* request, dfu_state_t state, dfu_status_t status, uint32_t timeout);
static bool process_download_get_status(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request);
static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request);
//--------------------------------------------------------------------+
// Debug
//--------------------------------------------------------------------+
#if CFG_TUSB_DEBUG >= 2
tu_static tu_lookup_entry_t const _dfu_request_lookup[] =
{
{ .key = DFU_REQUEST_DETACH , .data = "DETACH" },
{ .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" },
{ .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" },
{ .key = DFU_REQUEST_GETSTATUS , .data = "GETSTATUS" },
{ .key = DFU_REQUEST_CLRSTATUS , .data = "CLRSTATUS" },
{ .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" },
{ .key = DFU_REQUEST_ABORT , .data = "ABORT" },
tu_static tu_lookup_entry_t const _dfu_request_lookup[] = {
{ .key = DFU_REQUEST_DETACH , .data = "DETACH" },
{ .key = DFU_REQUEST_DNLOAD , .data = "DNLOAD" },
{ .key = DFU_REQUEST_UPLOAD , .data = "UPLOAD" },
{ .key = DFU_REQUEST_GETSTATUS, .data = "GETSTATUS" },
{ .key = DFU_REQUEST_CLRSTATUS, .data = "CLRSTATUS" },
{ .key = DFU_REQUEST_GETSTATE , .data = "GETSTATE" },
{ .key = DFU_REQUEST_ABORT , .data = "ABORT" },
};
tu_static tu_lookup_table_t const _dfu_request_table =
{
tu_static tu_lookup_table_t const _dfu_request_table = {
.count = TU_ARRAY_SIZE(_dfu_request_lookup),
.items = _dfu_request_lookup
};
tu_static tu_lookup_entry_t const _dfu_state_lookup[] =
{
{ .key = APP_IDLE , .data = "APP_IDLE" },
{ .key = APP_DETACH , .data = "APP_DETACH" },
{ .key = DFU_IDLE , .data = "IDLE" },
{ .key = DFU_DNLOAD_SYNC , .data = "DNLOAD_SYNC" },
{ .key = DFU_DNBUSY , .data = "DNBUSY" },
{ .key = DFU_DNLOAD_IDLE , .data = "DNLOAD_IDLE" },
{ .key = DFU_MANIFEST_SYNC , .data = "MANIFEST_SYNC" },
{ .key = DFU_MANIFEST , .data = "MANIFEST" },
{ .key = DFU_MANIFEST_WAIT_RESET , .data = "MANIFEST_WAIT_RESET" },
{ .key = DFU_UPLOAD_IDLE , .data = "UPLOAD_IDLE" },
{ .key = DFU_ERROR , .data = "ERROR" },
tu_static tu_lookup_entry_t const _dfu_state_lookup[] = {
{ .key = APP_IDLE , .data = "APP_IDLE" },
{ .key = APP_DETACH , .data = "APP_DETACH" },
{ .key = DFU_IDLE , .data = "IDLE" },
{ .key = DFU_DNLOAD_SYNC , .data = "DNLOAD_SYNC" },
{ .key = DFU_DNBUSY , .data = "DNBUSY" },
{ .key = DFU_DNLOAD_IDLE , .data = "DNLOAD_IDLE" },
{ .key = DFU_MANIFEST_SYNC , .data = "MANIFEST_SYNC" },
{ .key = DFU_MANIFEST , .data = "MANIFEST" },
{ .key = DFU_MANIFEST_WAIT_RESET, .data = "MANIFEST_WAIT_RESET" },
{ .key = DFU_UPLOAD_IDLE , .data = "UPLOAD_IDLE" },
{ .key = DFU_ERROR , .data = "ERROR" },
};
tu_static tu_lookup_table_t const _dfu_state_table =
{
tu_static tu_lookup_table_t const _dfu_state_table = {
.count = TU_ARRAY_SIZE(_dfu_state_lookup),
.items = _dfu_state_lookup
};
tu_static tu_lookup_entry_t const _dfu_status_lookup[] =
{
tu_static tu_lookup_entry_t const _dfu_status_lookup[] = {
{ .key = DFU_STATUS_OK , .data = "OK" },
{ .key = DFU_STATUS_ERR_TARGET , .data = "errTARGET" },
{ .key = DFU_STATUS_ERR_FILE , .data = "errFILE" },
@ -144,8 +134,7 @@ tu_static tu_lookup_entry_t const _dfu_status_lookup[] =
{ .key = DFU_STATUS_ERR_STALLEDPKT , .data = "errSTALLEDPKT" },
};
tu_static tu_lookup_table_t const _dfu_status_table =
{
tu_static tu_lookup_table_t const _dfu_status_table = {
.count = TU_ARRAY_SIZE(_dfu_status_lookup),
.items = _dfu_status_lookup
};
@ -155,13 +144,10 @@ tu_static tu_lookup_table_t const _dfu_status_table =
//--------------------------------------------------------------------+
// USBD Driver API
//--------------------------------------------------------------------+
void dfu_moded_reset(uint8_t rhport)
{
void dfu_moded_reset(uint8_t rhport) {
(void) rhport;
_dfu_ctx.attrs = 0;
_dfu_ctx.alt = 0;
reset_state();
}
@ -173,19 +159,17 @@ bool dfu_moded_deinit(void) {
return true;
}
uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)
{
uint16_t dfu_moded_open(uint8_t rhport, const tusb_desc_interface_t* itf_desc, uint16_t max_len) {
(void) rhport;
//------------- Interface (with Alt) descriptor -------------//
uint8_t const itf_num = itf_desc->bInterfaceNumber;
const uint8_t itf_num = itf_desc->bInterfaceNumber;
uint8_t alt_count = 0;
uint16_t drv_len = 0;
TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU, 0);
while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU)
{
while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU) {
TU_ASSERT(max_len > drv_len, 0);
// Alternate must have the same interface number
@ -196,18 +180,18 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc,
alt_count++;
drv_len += tu_desc_len(itf_desc);
itf_desc = (tusb_desc_interface_t const *) tu_desc_next(itf_desc);
itf_desc = (const tusb_desc_interface_t*) tu_desc_next(itf_desc);
}
//------------- DFU Functional descriptor -------------//
tusb_desc_dfu_functional_t const *func_desc = (tusb_desc_dfu_functional_t const *) itf_desc;
const tusb_desc_dfu_functional_t*func_desc = (const tusb_desc_dfu_functional_t*) itf_desc;
TU_ASSERT(tu_desc_type(func_desc) == TUSB_DESC_FUNCTIONAL, 0);
drv_len += sizeof(tusb_desc_dfu_functional_t);
_dfu_ctx.attrs = func_desc->bAttributes;
// CFG_TUD_DFU_XFER_BUFSIZE has to be set to the buffer size used in TUD_DFU_DESCRIPTOR
uint16_t const transfer_size = tu_le16toh( tu_unaligned_read16((uint8_t const*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) );
const uint16_t transfer_size = tu_le16toh( tu_unaligned_read16((const uint8_t*) func_desc + offsetof(tusb_desc_dfu_functional_t, wTransferSize)) );
TU_ASSERT(transfer_size <= CFG_TUD_DFU_XFER_BUFSIZE, drv_len);
return drv_len;
@ -216,99 +200,85 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc,
// Invoked when a control transfer occurred on an interface of this class
// Driver response accordingly to the request and the transfer stage (setup/data/ack)
// return false to stall control endpoint (e.g unsupported request)
bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
{
bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request) {
TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE);
TU_LOG_DRV(" DFU State : %s, Status: %s\r\n", tu_lookup_find(&_dfu_state_table, _dfu_ctx.state), tu_lookup_find(&_dfu_status_table, _dfu_ctx.status));
if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD )
{
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) {
// Standard request include GET/SET_INTERFACE
switch ( request->bRequest )
{
switch (request->bRequest) {
case TUSB_REQ_SET_INTERFACE:
if ( stage == CONTROL_STAGE_SETUP )
{
if (stage == CONTROL_STAGE_SETUP) {
// Switch Alt interface and reset state machine
_dfu_ctx.alt = (uint8_t) request->wValue;
_dfu_ctx.alt = (uint8_t)request->wValue;
reset_state();
return tud_control_status(rhport, request);
}
break;
break;
case TUSB_REQ_GET_INTERFACE:
if(stage == CONTROL_STAGE_SETUP)
{
if (stage == CONTROL_STAGE_SETUP) {
return tud_control_xfer(rhport, request, &_dfu_ctx.alt, 1);
}
break;
break;
// unsupported request
default: return false;
}
}
else if ( request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS )
{
} else if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS) {
TU_LOG_DRV(" DFU Request: %s\r\n", tu_lookup_find(&_dfu_request_table, request->bRequest));
// Class request
switch ( request->bRequest )
{
switch (request->bRequest) {
case DFU_REQUEST_DETACH:
if ( stage == CONTROL_STAGE_SETUP )
{
if (stage == CONTROL_STAGE_SETUP) {
tud_control_status(rhport, request);
} else if (stage == CONTROL_STAGE_ACK) {
if (tud_dfu_detach_cb) {
tud_dfu_detach_cb();
}
}
else if ( stage == CONTROL_STAGE_ACK )
{
if ( tud_dfu_detach_cb ) tud_dfu_detach_cb();
}
break;
break;
case DFU_REQUEST_CLRSTATUS:
if ( stage == CONTROL_STAGE_SETUP )
{
if (stage == CONTROL_STAGE_SETUP) {
reset_state();
tud_control_status(rhport, request);
}
break;
break;
case DFU_REQUEST_GETSTATE:
if ( stage == CONTROL_STAGE_SETUP )
{
if (stage == CONTROL_STAGE_SETUP) {
tud_control_xfer(rhport, request, &_dfu_ctx.state, 1);
}
break;
break;
case DFU_REQUEST_ABORT:
if ( stage == CONTROL_STAGE_SETUP )
{
if (stage == CONTROL_STAGE_SETUP) {
reset_state();
tud_control_status(rhport, request);
} else if (stage == CONTROL_STAGE_ACK) {
if (tud_dfu_abort_cb) {
tud_dfu_abort_cb(_dfu_ctx.alt);
}
}
else if ( stage == CONTROL_STAGE_ACK )
{
if ( tud_dfu_abort_cb ) tud_dfu_abort_cb(_dfu_ctx.alt);
}
break;
break;
case DFU_REQUEST_UPLOAD:
if ( stage == CONTROL_STAGE_SETUP )
{
if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_UPLOAD);
TU_VERIFY(tud_dfu_upload_cb);
TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE);
uint16_t const xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_ctx.transfer_buf, request->wLength);
const uint16_t xfer_len = tud_dfu_upload_cb(_dfu_ctx.alt, request->wValue, _dfu_epbuf.transfer_buf,
request->wLength);
return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, xfer_len);
return tud_control_xfer(rhport, request, _dfu_epbuf.transfer_buf, xfer_len);
}
break;
break;
case DFU_REQUEST_DNLOAD:
if ( stage == CONTROL_STAGE_SETUP )
{
if (stage == CONTROL_STAGE_SETUP) {
TU_VERIFY(_dfu_ctx.attrs & DFU_ATTR_CAN_DOWNLOAD);
TU_VERIFY(_dfu_ctx.state == DFU_IDLE || _dfu_ctx.state == DFU_DNLOAD_IDLE);
TU_VERIFY(request->wLength <= CFG_TUD_DFU_XFER_BUFSIZE);
@ -317,104 +287,86 @@ bool dfu_moded_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_reque
_dfu_ctx.flashing_in_progress = true;
// save block and length for flashing
_dfu_ctx.block = request->wValue;
_dfu_ctx.block = request->wValue;
_dfu_ctx.length = request->wLength;
if ( request->wLength )
{
if (request->wLength) {
// Download with payload -> transition to DOWNLOAD SYNC
_dfu_ctx.state = DFU_DNLOAD_SYNC;
return tud_control_xfer(rhport, request, _dfu_ctx.transfer_buf, request->wLength);
}
else
{
return tud_control_xfer(rhport, request, _dfu_epbuf.transfer_buf, request->wLength);
} else {
// Download is complete -> transition to MANIFEST SYNC
_dfu_ctx.state = DFU_MANIFEST_SYNC;
return tud_control_status(rhport, request);
}
}
break;
break;
case DFU_REQUEST_GETSTATUS:
switch ( _dfu_ctx.state )
{
switch (_dfu_ctx.state) {
case DFU_DNLOAD_SYNC:
return process_download_get_status(rhport, stage, request);
break;
break;
case DFU_MANIFEST_SYNC:
return process_manifest_get_status(rhport, stage, request);
break;
break;
default:
if ( stage == CONTROL_STAGE_SETUP ) return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0);
break;
if (stage == CONTROL_STAGE_SETUP) {
return reply_getstatus(rhport, request, _dfu_ctx.state, _dfu_ctx.status, 0);
}
break;
}
break;
break;
default: return false; // stall unsupported request
}
}else
{
} else {
return false; // unsupported request
}
return true;
}
void tud_dfu_finish_flashing(uint8_t status)
{
void tud_dfu_finish_flashing(uint8_t status) {
_dfu_ctx.flashing_in_progress = false;
if ( status == DFU_STATUS_OK )
{
if (_dfu_ctx.state == DFU_DNBUSY)
{
if (status == DFU_STATUS_OK) {
if (_dfu_ctx.state == DFU_DNBUSY) {
_dfu_ctx.state = DFU_DNLOAD_SYNC;
}
else if (_dfu_ctx.state == DFU_MANIFEST)
{
} else if (_dfu_ctx.state == DFU_MANIFEST) {
_dfu_ctx.state = (_dfu_ctx.attrs & DFU_ATTR_MANIFESTATION_TOLERANT)
? DFU_MANIFEST_SYNC : DFU_MANIFEST_WAIT_RESET;
? DFU_MANIFEST_SYNC
: DFU_MANIFEST_WAIT_RESET;
}
}
else
{
} else {
// failed while flashing, move to dfuError
_dfu_ctx.state = DFU_ERROR;
_dfu_ctx.status = (dfu_status_t)status;
}
}
static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
{
if ( stage == CONTROL_STAGE_SETUP )
{
static bool process_download_get_status(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request) {
if (stage == CONTROL_STAGE_SETUP) {
// only transition to next state on CONTROL_STAGE_ACK
dfu_state_t next_state;
uint32_t timeout;
if ( _dfu_ctx.flashing_in_progress )
{
if (_dfu_ctx.flashing_in_progress) {
next_state = DFU_DNBUSY;
timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t) next_state);
}
else
{
timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, (uint8_t)next_state);
} else {
next_state = DFU_DNLOAD_IDLE;
timeout = 0;
}
return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout);
}
else if ( stage == CONTROL_STAGE_ACK )
{
if ( _dfu_ctx.flashing_in_progress )
{
} else if (stage == CONTROL_STAGE_ACK) {
if (_dfu_ctx.flashing_in_progress) {
_dfu_ctx.state = DFU_DNBUSY;
tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_ctx.transfer_buf, _dfu_ctx.length);
}else
{
tud_dfu_download_cb(_dfu_ctx.alt, _dfu_ctx.block, _dfu_epbuf.transfer_buf, _dfu_ctx.length);
} else {
_dfu_ctx.state = DFU_DNLOAD_IDLE;
}
}
@ -422,36 +374,26 @@ static bool process_download_get_status(uint8_t rhport, uint8_t stage, tusb_cont
return true;
}
static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request)
{
if ( stage == CONTROL_STAGE_SETUP )
{
static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, const tusb_control_request_t* request) {
if (stage == CONTROL_STAGE_SETUP) {
// only transition to next state on CONTROL_STAGE_ACK
dfu_state_t next_state;
uint32_t timeout;
if ( _dfu_ctx.flashing_in_progress )
{
if (_dfu_ctx.flashing_in_progress) {
next_state = DFU_MANIFEST;
timeout = tud_dfu_get_timeout_cb(_dfu_ctx.alt, next_state);
}
else
{
} else {
next_state = DFU_IDLE;
timeout = 0;
}
return reply_getstatus(rhport, request, next_state, _dfu_ctx.status, timeout);
}
else if ( stage == CONTROL_STAGE_ACK )
{
if ( _dfu_ctx.flashing_in_progress )
{
} else if (stage == CONTROL_STAGE_ACK) {
if (_dfu_ctx.flashing_in_progress) {
_dfu_ctx.state = DFU_MANIFEST;
tud_dfu_manifest_cb(_dfu_ctx.alt);
}
else
{
} else {
_dfu_ctx.state = DFU_IDLE;
}
}
@ -459,15 +401,15 @@ static bool process_manifest_get_status(uint8_t rhport, uint8_t stage, tusb_cont
return true;
}
static bool reply_getstatus(uint8_t rhport, tusb_control_request_t const * request, dfu_state_t state, dfu_status_t status, uint32_t timeout)
{
static bool reply_getstatus(uint8_t rhport, const tusb_control_request_t* request, dfu_state_t state,
dfu_status_t status, uint32_t timeout) {
dfu_status_response_t resp;
resp.bStatus = (uint8_t) status;
resp.bStatus = (uint8_t)status;
resp.bwPollTimeout[0] = TU_U32_BYTE0(timeout);
resp.bwPollTimeout[1] = TU_U32_BYTE1(timeout);
resp.bwPollTimeout[2] = TU_U32_BYTE2(timeout);
resp.bState = (uint8_t) state;
resp.iString = 0;
resp.bState = (uint8_t)state;
resp.iString = 0;
return tud_control_xfer(rhport, request, &resp, sizeof(dfu_status_response_t));
}

View file

@ -24,11 +24,6 @@
* This file is part of the TinyUSB stack.
*/
// ESP32 out-of-sync
#ifdef ARDUINO_ARCH_ESP32
#include "arduino/ports/esp32/tusb_config_esp32.h"
#endif
#include "tusb_option.h"
#if (CFG_TUD_ENABLED && CFG_TUD_DFU_RUNTIME)
@ -63,9 +58,8 @@ bool dfu_rtd_deinit(void) {
return true;
}
void dfu_rtd_reset(uint8_t rhport)
{
(void) rhport;
void dfu_rtd_reset(uint8_t rhport) {
(void) rhport;
}
uint16_t dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t max_len)

View file

@ -325,6 +325,29 @@ typedef enum
/// @}
//--------------------------------------------------------------------+
// Digitizer Stylus Pen
//--------------------------------------------------------------------+
/** \addtogroup ClassDriver_HID_Stylus Stylus
* @{ */
// Standard Stylus Pen Report.
typedef struct TU_ATTR_PACKED
{
uint8_t attr; /**< Attribute mask for describing current status of the stylus pen. */
uint16_t x; /**< Current x position of the mouse. */
uint16_t y; /**< Current y position of the mouse. */
} hid_stylus_report_t;
// Standard Stylus Pen Attributes Bitmap.
typedef enum
{
STYLUS_ATTR_TIP_SWITCH = TU_BIT(0), ///< Tip switch
STYLUS_ATTR_IN_RANGE = TU_BIT(1), ///< In-range bit.
} hid_stylus_attr_bm_t;
/// @}
//--------------------------------------------------------------------+
// Keyboard
//--------------------------------------------------------------------+
@ -740,6 +763,21 @@ enum {
//--------------------------------------------------------------------+
// Usage Table
/* Usage Types Data
Sel Selector Array
SV Static Value Constant, Variable, Absolute
SF Static Flag Constant, Variable, Absolute
DV Dynamic Value Constant, Variable, Absolute
DF Dynamic Flag Constant, Variable, Absolute
*/
/* Usage Types Collection
NAry Named Array Logical
CA Collection Application Application
CL Collection Logical Logical
CP Collection Physical Physical
US Usage Switch Logical
UM Usage Modifier Logical
*/
//--------------------------------------------------------------------+
/// HID Usage Table - Table 1: Usage Page Summary
@ -759,8 +797,14 @@ enum {
HID_USAGE_PAGE_DIGITIZER = 0x0d,
HID_USAGE_PAGE_PID = 0x0f,
HID_USAGE_PAGE_UNICODE = 0x10,
HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14,
HID_USAGE_PAGE_MEDICAL = 0x40,
HID_USAGE_PAGE_SOC = 0x11,
HID_USAGE_PAGE_EYE_AND_HEAD_TRACKERS = 0x12,
// 0x13 is reserved
HID_USAGE_PAGE_AUXILIARY_DISPLAY = 0x14,
// 0x15 - 0x1f is reserved
HID_USAGE_PAGE_SENSORS = 0x20,
// 0x21 - 0x3f is reserved
HID_USAGE_PAGE_MEDICAL_INSTRUMENT = 0x40,
HID_USAGE_PAGE_LIGHTING_AND_ILLUMINATION = 0x59,
HID_USAGE_PAGE_MONITOR = 0x80, // 0x80 - 0x83
HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87
@ -846,7 +890,6 @@ enum {
HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7
};
/// HID Usage Table: Consumer Page (0x0C)
/// Only contains controls that supported by Windows (whole list is too long)
enum {
@ -905,6 +948,237 @@ enum {
HID_USAGE_CONSUMER_AC_PAN = 0x0238,
};
/// HID Usage Table: Digitizer Page (0x0D)
enum {
HID_USAGE_DIGITIZER_UNDEFINED = 0x00,
HID_USAGE_DIGITIZER_DIGITIZER = 0x01, // CA
HID_USAGE_DIGITIZER_PEN = 0x02, // CA
HID_USAGE_DIGITIZER_LIGHT_PEN = 0x03, // CA
HID_USAGE_DIGITIZER_TOUCH_SCREEN = 0x04, // CA
HID_USAGE_DIGITIZER_TOUCH_PAD = 0x05, // CA
HID_USAGE_DIGITIZER_WHITEBOARD = 0x06, // CA
HID_USAGE_DIGITIZER_COORDINATE_MEASURING_MACHINE = 0x07, // CA
HID_USAGE_DIGITIZER_3D_DIGITIZER = 0x08, // CA
HID_USAGE_DIGITIZER_STEREO_PLOTTER = 0x09, // CA
HID_USAGE_DIGITIZER_ARTICULATED_ARM = 0x0A, // CA
HID_USAGE_DIGITIZER_ARMATURE = 0x0B, // CA
HID_USAGE_DIGITIZER_MULTIPLE_POINT_DIGITIZER = 0x0C, // CA
HID_USAGE_DIGITIZER_FREE_SPACE_WAND = 0x0D, // CA
HID_USAGE_DIGITIZER_DEVICE_CONFIGURATION = 0x0E, // CA
HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_DIGITIZER = 0x0F, // CA
// Reserved (0x10 - 0x1F)
HID_USAGE_DIGITIZER_STYLUS = 0x20, // CA/CL
HID_USAGE_DIGITIZER_PUCK = 0x21, // CL
HID_USAGE_DIGITIZER_FINGER = 0x22, // CL
HID_USAGE_DIGITIZER_DEVICE_SETTINGS = 0x23, // CL
HID_USAGE_DIGITIZER_CHARACTER_GESTURE = 0x24, // CL
// Reserved (0x25 - 0x2F)
HID_USAGE_DIGITIZER_TIP_PRESSURE = 0x30, // DV
HID_USAGE_DIGITIZER_BARREL_PRESSURE = 0x31, // DV
HID_USAGE_DIGITIZER_IN_RANGE = 0x32, // MC
HID_USAGE_DIGITIZER_TOUCH = 0x33, // MC
HID_USAGE_DIGITIZER_UNTOUCH = 0x34, // OSC
HID_USAGE_DIGITIZER_TAP = 0x35, // OSC
HID_USAGE_DIGITIZER_QUALITY = 0x36, // DV
HID_USAGE_DIGITIZER_DATA_VALID = 0x37, // MC
HID_USAGE_DIGITIZER_TRANSDUCER_INDEX = 0x38, // DV
HID_USAGE_DIGITIZER_TABLET_FUNCTION_KEYS = 0x39, // CL
HID_USAGE_DIGITIZER_PROGRAM_CHANGE_KEYS = 0x3A, // CL
HID_USAGE_DIGITIZER_BATTERY_STRENGTH = 0x3B, // DV
HID_USAGE_DIGITIZER_INVERT = 0x3C, // MC
HID_USAGE_DIGITIZER_X_TILT = 0x3D, // DV
HID_USAGE_DIGITIZER_Y_TILT = 0x3E, // DV
HID_USAGE_DIGITIZER_AZIMUTH = 0x3F, // DV
HID_USAGE_DIGITIZER_ALTITUDE = 0x40, // DV
HID_USAGE_DIGITIZER_TWIST = 0x41, // DV
HID_USAGE_DIGITIZER_TIP_SWITCH = 0x42, // MC
HID_USAGE_DIGITIZER_SECONDARY_TIP_SWITCH = 0x43, // MC
HID_USAGE_DIGITIZER_BARREL_SWITCH = 0x44, // MC
HID_USAGE_DIGITIZER_ERASER = 0x45, // MC
HID_USAGE_DIGITIZER_TABLET_PICK = 0x46, // MC
HID_USAGE_DIGITIZER_TOUCH_VALID = 0x47, // MC
HID_USAGE_DIGITIZER_WIDTH = 0x48, // DV
HID_USAGE_DIGITIZER_HEIGHT = 0x49, // DV
// Reserved (0x4A - 0x50)
HID_USAGE_DIGITIZER_CONTACT_IDENTIFIER = 0x51, // DV
HID_USAGE_DIGITIZER_DEVICE_MODE = 0x52, // DV
HID_USAGE_DIGITIZER_DEVICE_IDENTIFIER = 0x53, // DV/SV
HID_USAGE_DIGITIZER_CONTACT_COUNT = 0x54, // DV
HID_USAGE_DIGITIZER_CONTACT_COUNT_MAXIMUM = 0x55, // SV
HID_USAGE_DIGITIZER_SCAN_TIME = 0x56, // DV
HID_USAGE_DIGITIZER_SURFACE_SWITCH = 0x57, // DF
HID_USAGE_DIGITIZER_BUTTON_SWITCH = 0x58, // DF
HID_USAGE_DIGITIZER_PAD_TYPE = 0x59, // SF
HID_USAGE_DIGITIZER_TRANSDUCER_SERIAL_NUMBER = 0x5B, // SV
HID_USAGE_DIGITIZER_PREFERRED_COLOR = 0x5C, // DV
HID_USAGE_DIGITIZER_PREFERRED_COLOR_LOCKED = 0x5D, // MC
HID_USAGE_DIGITIZER_PREFERRED_LINE_WIDTH = 0x5E, // DV
HID_USAGE_DIGITIZER_PREFERRED_LINE_WIDTH_LOCKED = 0x5F, // MC
HID_USAGE_DIGITIZER_LATENCY_MODE = 0x60, // DF
HID_USAGE_DIGITIZER_GESTURE_CHARACTER_QUALITY = 0x61, // DV
HID_USAGE_DIGITIZER_CHARACTER_GESTURE_DATA_LENGTH = 0x62, // DV
HID_USAGE_DIGITIZER_CHARACTER_GESTURE_DATA = 0x63, // DV
HID_USAGE_DIGITIZER_GESTURE_CHARACTER_ENCODING = 0x64, // NAry
HID_USAGE_DIGITIZER_UTF8_CHARACTER_GESTURE_ENCODING = 0x65, // Sel
HID_USAGE_DIGITIZER_UTF16_LE_CHARACTER_GESTURE_ENCODING = 0x66, // Sel
HID_USAGE_DIGITIZER_UTF16_BE_CHARACTER_GESTURE_ENCODING = 0x67, // Sel
HID_USAGE_DIGITIZER_UTF32_LE_CHARACTER_GESTURE_ENCODING = 0x68, // Sel
HID_USAGE_DIGITIZER_UTF32_BE_CHARACTER_GESTURE_ENCODING = 0x69, // Sel
HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_VENDOR_ID = 0x6A, // SV
HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_VERSION = 0x6B, // SV
HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_FRAME_DATA = 0x6C, // DV
HID_USAGE_DIGITIZER_GESTURE_CHARACTER_ENABLE = 0x6D, // DF
HID_USAGE_DIGITIZER_TRANSDUCER_SERIAL_NUMBER_PART2 = 0x6E, // SV
HID_USAGE_DIGITIZER_NO_PREFERRED_COLOR = 0x6F, // DF
HID_USAGE_DIGITIZER_PREFERRED_LINE_STYLE = 0x70, // NAry
HID_USAGE_DIGITIZER_PREFERRED_LINE_STYLE_LOCKED = 0x71, // MC
HID_USAGE_DIGITIZER_INK = 0x72, // Sel
HID_USAGE_DIGITIZER_PENCIL = 0x73, // Sel
HID_USAGE_DIGITIZER_HIGHLIGHTER = 0x74, // Sel
HID_USAGE_DIGITIZER_CHISEL_MARKER = 0x75, // Sel
HID_USAGE_DIGITIZER_BRUSH = 0x76, // Sel
HID_USAGE_DIGITIZER_NO_PREFERENCE = 0x77, // Sel
// Reserved (0x78 - 0x7F)
HID_USAGE_DIGITIZER_DIGITIZER_DIAGNOSTIC = 0x80, // CL
HID_USAGE_DIGITIZER_DIGITIZER_ERROR = 0x81, // NAry
HID_USAGE_DIGITIZER_ERR_NORMAL_STATUS = 0x82, // Sel
HID_USAGE_DIGITIZER_ERR_TRANSDUCERS_EXCEEDED = 0x83, // Sel
HID_USAGE_DIGITIZER_ERR_FULL_TRANS_FEATURES_UNAVAILABLE = 0x84, // Sel
HID_USAGE_DIGITIZER_ERR_CHARGE_LOW = 0x85, // Sel
// Reserved (0x86 - 0x8F)
HID_USAGE_DIGITIZER_TRANSDUCER_SOFTWARE_INFO = 0x90, // CL
HID_USAGE_DIGITIZER_TRANSDUCER_VENDOR_ID = 0x91, // SV
HID_USAGE_DIGITIZER_TRANSDUCER_PRODUCT_ID = 0x92, // SV
HID_USAGE_DIGITIZER_DEVICE_SUPPORTED_PROTOCOLS = 0x93, // NAry/CL
HID_USAGE_DIGITIZER_TRANSDUCER_SUPPORTED_PROTOCOLS = 0x94, // NAry/CL
HID_USAGE_DIGITIZER_NO_PROTOCOL = 0x95, // Sel
HID_USAGE_DIGITIZER_WACOM_AES_PROTOCOL = 0x96, // Sel
HID_USAGE_DIGITIZER_USI_PROTOCOL = 0x97, // Sel
HID_USAGE_DIGITIZER_MICROSOFT_PEN_PROTOCOL = 0x98, // Sel
// Reserved (0x99 - 0x9F)
HID_USAGE_DIGITIZER_SUPPORTED_REPORT_RATES = 0xA0, // SV/CL
HID_USAGE_DIGITIZER_REPORT_RATE = 0xA1, // DV
HID_USAGE_DIGITIZER_TRANSDUCER_CONNECTED = 0xA2, // SF
HID_USAGE_DIGITIZER_SWITCH_DISABLED = 0xA3, // Sel
HID_USAGE_DIGITIZER_SWITCH_UNIMPLEMENTED = 0xA4, // Sel
HID_USAGE_DIGITIZER_TRANSDUCER_SWITCHES = 0xA5, // CL
HID_USAGE_DIGITIZER_TRANSDUCER_INDEX_SELECTOR = 0xA6, // DV
// Reserved (0xA7 - 0xAF)
HID_USAGE_DIGITIZER_BUTTON_PRESS_THRESHOLD = 0xB0, // DV
// Reserved (0xB1 - 0xFFFF)
};
/// HID Usage Table: Physical Input Device Page (0x0F)
enum {
HID_USAGE_PID_UNDEFINED = 0x00,
HID_USAGE_PID_PHYSICAL_INPUT_DEVICE = 0x01,
HID_USAGE_PID_NORMAL = 0x20,
HID_USAGE_PID_SET_EFFECT_REPORT = 0x21,
HID_USAGE_PID_EFFECT_PARAMETER_BLOCK_INDEX = 0x22,
HID_USAGE_PID_PARAMETER_BLOCK_OFFSET = 0x23,
HID_USAGE_PID_ROM_FLAG = 0x24,
HID_USAGE_PID_EFFECT_TYPE = 0x25,
HID_USAGE_PID_ET_CONSTANTFORCE = 0x26,
HID_USAGE_PID_ET_RAMP = 0x27,
HID_USAGE_PID_ET_CUSTOMFORCE = 0x28,
HID_USAGE_PID_ET_SQUARE = 0x30,
HID_USAGE_PID_ET_SINE = 0x31,
HID_USAGE_PID_ET_TRIANGLE = 0x32,
HID_USAGE_PID_ET_SAWTOOTH_UP = 0x33,
HID_USAGE_PID_ET_SAWTOOTH_DOWN = 0x34,
HID_USAGE_PID_ET_SPRING = 0x40,
HID_USAGE_PID_ET_DAMPER = 0x41,
HID_USAGE_PID_ET_INERTIA = 0x42,
HID_USAGE_PID_ET_FRICTION = 0x43,
HID_USAGE_PID_DURATION = 0x50,
HID_USAGE_PID_SAMPLE_PERIOD = 0x51,
HID_USAGE_PID_GAIN = 0x52,
HID_USAGE_PID_TRIGGER_BUTTON = 0x53,
HID_USAGE_PID_TRIGGER_REPEAT_INTERVAL = 0x54,
HID_USAGE_PID_AXES_ENABLE = 0x55,
HID_USAGE_PID_DIRECTION_ENABLE = 0x56,
HID_USAGE_PID_DIRECTION = 0x57,
HID_USAGE_PID_TYPE_SPECIFIC_BLOCK_OFFSET = 0x58,
HID_USAGE_PID_BLOCK_TYPE = 0x59,
HID_USAGE_PID_SET_ENVELOPE_REPORT = 0x5a,
HID_USAGE_PID_ATTACK_LEVEL = 0x5b,
HID_USAGE_PID_ATTACK_TIME = 0x5c,
HID_USAGE_PID_FADE_LEVEL = 0x5d,
HID_USAGE_PID_FADE_TIME = 0x5e,
HID_USAGE_PID_SET_CONDITION_REPORT = 0x5f,
HID_USAGE_PID_CENTERPOINT_OFFSET = 0x60,
HID_USAGE_PID_POSITIVE_COEFFICIENT = 0x61,
HID_USAGE_PID_NEGATIVE_COEFFICIENT = 0x62,
HID_USAGE_PID_POSITIVE_SATURATION = 0x63,
HID_USAGE_PID_NEGATIVE_SATURATION = 0x64,
HID_USAGE_PID_DEAD_BAND = 0x65,
HID_USAGE_PID_DOWNLOAD_FORCE_SAMPLE = 0x66,
HID_USAGE_PID_ISOCH_CUSTOMFORCE_ENABLE = 0x67,
HID_USAGE_PID_CUSTOMFORCE_DATA_REPORT = 0x68,
HID_USAGE_PID_CUSTOMFORCE_DATA = 0x69,
HID_USAGE_PID_CUSTOMFORCE_VENDOR_DEFINED_DATA = 0x6a,
HID_USAGE_PID_SET_CUSTOMFORCE_REPORT = 0x6b,
HID_USAGE_PID_CUSTOMFORCE_DATA_OFFSET = 0x6c,
HID_USAGE_PID_SAMPLE_COUNT = 0x6d,
HID_USAGE_PID_SET_PERIODIC_REPORT = 0x6e,
HID_USAGE_PID_OFFSET = 0x6f,
HID_USAGE_PID_MAGNITUDE = 0x70,
HID_USAGE_PID_PHASE = 0x71,
HID_USAGE_PID_PERIOD = 0x72,
HID_USAGE_PID_SET_CONSTANTFORCE_REPORT = 0x73,
HID_USAGE_PID_SET_RAMPFORCE_REPORT = 0x74,
HID_USAGE_PID_RAMP_START = 0x75,
HID_USAGE_PID_RAMP_END = 0x76,
HID_USAGE_PID_EFFECT_OPERATION_REPORT = 0x77,
HID_USAGE_PID_EFFECT_OPERATION = 0x78,
HID_USAGE_PID_OP_EFFECT_START = 0x79,
HID_USAGE_PID_OP_EFFECT_START_SOLO = 0x7a,
HID_USAGE_PID_OP_EFFECT_STOP = 0x7b,
HID_USAGE_PID_LOOP_COUNT = 0x7c,
HID_USAGE_PID_DEVICE_GAIN_REPORT = 0x7d,
HID_USAGE_PID_DEVICE_GAIN = 0x7e,
HID_USAGE_PID_PARAMETER_BLOCK_POOLS_REPORT = 0x7f,
HID_USAGE_PID_RAM_POOL_SIZE = 0x80,
HID_USAGE_PID_ROM_POOL_SIZE = 0x81,
HID_USAGE_PID_ROM_EFFECT_BLOCK_COUNT = 0x82,
HID_USAGE_PID_SIMULTANEOUS_EFFECTS_MAX = 0x83,
HID_USAGE_PID_POOL_ALIGNMENT = 0x84,
HID_USAGE_PID_PARAMETER_BLOCK_MOVE_REPORT = 0x85,
HID_USAGE_PID_MOVE_SOURCE = 0x86,
HID_USAGE_PID_MOVE_DESTINATION = 0x87,
HID_USAGE_PID_MOVE_LENGTH = 0x88,
HID_USAGE_PID_EFFECT_PARAMETER_BLOCK_LOAD_REPORT = 0x89,
HID_USAGE_PID_EFFECT_PARAMETER_BLOCK_LOAD_STATUS = 0x8b,
HID_USAGE_PID_BLOCK_LOAD_SUCCESS = 0x8c,
HID_USAGE_PID_BLOCK_LOAD_FULL = 0x8d,
HID_USAGE_PID_BLOCK_LOAD_ERROR = 0x8e,
HID_USAGE_PID_BLOCK_HANDLE = 0x8f,
HID_USAGE_PID_EFFECT_PARAMETER_BLOCK_FREE_REPORT = 0x90,
HID_USAGE_PID_TYPE_SPECIFIC_BLOCK_HANDLE = 0x91,
HID_USAGE_PID_PID_STATE_REPORT = 0x92,
HID_USAGE_PID_EFFECT_PLAYING = 0x94,
HID_USAGE_PID_PID_DEVICE_CONTROL_REPORT = 0x95,
HID_USAGE_PID_PID_DEVICE_CONTROL = 0x96,
HID_USAGE_PID_DC_ENABLE_ACTUATORS = 0x97,
HID_USAGE_PID_DC_DISABLE_ACTUATORS = 0x98,
HID_USAGE_PID_DC_STOP_ALL_EFFECTS = 0x99,
HID_USAGE_PID_DC_RESET = 0x9a,
HID_USAGE_PID_DC_PAUSE = 0x9b,
HID_USAGE_PID_DC_CONTINUE = 0x9c,
HID_USAGE_PID_DEVICE_PAUSED = 0x9f,
HID_USAGE_PID_ACTUATORS_ENABLED = 0xa0,
HID_USAGE_PID_SAFETY_SWITCH = 0xa4,
HID_USAGE_PID_ACTUATOR_OVERRIDE_SWITCH = 0xa5,
HID_USAGE_PID_ACTUATOR_POWER = 0xa6,
HID_USAGE_PID_START_DELAY = 0xa7,
HID_USAGE_PID_PARAMETER_BLOCK_SIZE = 0xa8,
HID_USAGE_PID_DEVICEMANAGED_POOL = 0xa9,
HID_USAGE_PID_SHARED_PARAMETER_BLOCKS = 0xaa,
HID_USAGE_PID_CREATE_NEW_EFFECT_PARAMETER_BLOCK_REPORT = 0xab,
HID_USAGE_PID_RAM_POOL_AVAILABLE = 0xac,
};
/// HID Usage Table - Lighting And Illumination Page (0x59)
enum {
HID_USAGE_LIGHTING_LAMP_ARRAY = 0x01,

Some files were not shown because too many files have changed in this diff Show more