Compare commits
72 commits
update-tin
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
737dfb2115 | ||
|
|
766d8cca00 | ||
|
|
d3cc12070a | ||
|
|
86dfc05234 | ||
|
|
8f13cb8bca | ||
|
|
fb9763423c | ||
|
|
7b30ff9e14 | ||
|
|
0e054b598b | ||
|
|
5ab76b7931 | ||
|
|
028629e93e | ||
|
|
8c615b6519 | ||
|
|
d4071f5abe | ||
|
|
4daede3744 | ||
|
|
44053c45df | ||
|
|
eaa9bfdaa5 | ||
|
|
9806375c60 | ||
|
|
e896107698 | ||
|
|
805aa2d41a | ||
|
|
fee8a5e6bc | ||
|
|
59d4393012 | ||
|
|
60fb663caa | ||
|
|
cdc07c1d96 | ||
|
|
794ac7f34b | ||
|
|
9496740134 | ||
|
|
6fa11c4d5e | ||
|
|
f05bd099c3 | ||
|
|
951dba38f6 | ||
|
|
5618d9c054 | ||
|
|
46d2c6cb49 | ||
|
|
23426ed3f6 | ||
|
|
72cd81005b | ||
|
|
fafc824f6b | ||
|
|
6b772c0ac4 | ||
|
|
560a21bdec | ||
|
|
4b9a629a55 | ||
|
|
55a0283b48 | ||
|
|
332b0c8e31 | ||
|
|
f83e0ce0ff | ||
|
|
d522523fd1 | ||
|
|
76a551be81 | ||
|
|
f4e8959828 | ||
|
|
7b22bd0adf | ||
|
|
36396f4f9e | ||
|
|
cfe6da84d1 | ||
|
|
7f7ac74899 | ||
|
|
8ef30202e5 | ||
|
|
3918606fbe | ||
|
|
1d3576a40a | ||
|
|
605d681c81 | ||
|
|
41bde22a7c | ||
|
|
411821714b | ||
|
|
aba2328b00 | ||
|
|
f12e3f2886 | ||
|
|
a17922159b | ||
|
|
96ac318c19 | ||
|
|
8f2d3edd77 | ||
|
|
c92b7fde16 | ||
|
|
85476dcd8f | ||
|
|
8077b62029 | ||
|
|
c976061caa | ||
|
|
f5211f4226 | ||
|
|
f8ac8130c5 | ||
|
|
1798428b15 | ||
|
|
5920d15f73 | ||
|
|
71e2c4a4bd | ||
|
|
f13b57a01a | ||
|
|
a529a74e4f | ||
|
|
05686e7f97 | ||
|
|
59a651cca0 | ||
|
|
2df6d2905e | ||
|
|
a7c9db3f62 | ||
|
|
0a9c3fe818 |
173 changed files with 10667 additions and 6134 deletions
10
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
10
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
54
.github/workflows/githubci.yml
vendored
54
.github/workflows/githubci.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
feather_esp32_v2
|
||||
feather_esp32s2
|
||||
feather_esp32s3
|
||||
funhouse
|
||||
magtag
|
||||
metroesp32s2
|
||||
esp32p4
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
2
examples/CDC/no_serial/.skip.txt
Normal file
2
examples/CDC/no_serial/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
examples/CDC/serial_echo/.skip.txt
Normal file
2
examples/CDC/serial_echo/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
2
examples/Composite/mouse_ramdisk/.skip.txt
Normal file
2
examples/Composite/mouse_ramdisk/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
|
|||
|
|
@ -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 -------------//
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
2
examples/HID/hid_boot_keyboard/.skip.txt
Normal file
2
examples/HID/hid_boot_keyboard/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
2
examples/HID/hid_boot_mouse/.skip.txt
Normal file
2
examples/HID/hid_boot_mouse/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
2
examples/HID/hid_composite/.skip.txt
Normal file
2
examples/HID/hid_composite/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
2
examples/HID/hid_dual_interfaces/.skip.txt
Normal file
2
examples/HID/hid_dual_interfaces/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
2
examples/HID/hid_gamepad/.skip.txt
Normal file
2
examples/HID/hid_gamepad/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
2
examples/HID/hid_generic_inout/.skip.txt
Normal file
2
examples/HID/hid_generic_inout/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
2
examples/MIDI/midi_multi_ports/.skip.txt
Normal file
2
examples/MIDI/midi_multi_ports/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
examples/MIDI/midi_test/.skip.txt
Normal file
2
examples/MIDI/midi_test/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
feather_esp32_v2
|
||||
feather_esp32s2
|
||||
feather_esp32s3
|
||||
funhouse
|
||||
magtag
|
||||
metroesp32s2
|
||||
esp32p4
|
||||
feather_rp2040_tinyusb
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
# CH32V20x_EVT is not supported due to Adafruit_Neopixel
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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 !!");
|
||||
|
|
|
|||
21
library.json
21
library.json
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
extern "C" {
|
||||
|
||||
uint32_t tusb_time_millis_api(void) { return millis(); }
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device
|
||||
//--------------------------------------------------------------------+
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in a new issue