Compare commits
215 commits
suport-pic
...
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 | ||
|
|
446e0af7a9 | ||
|
|
f752bc6e05 | ||
|
|
8587060a19 | ||
|
|
0061a40530 | ||
|
|
9aaf9b56bb | ||
|
|
7a32772d52 | ||
|
|
c748ad674a | ||
|
|
4c6e9ce4e0 | ||
|
|
e92d597803 | ||
|
|
889a5d65ed | ||
|
|
51a9de832e | ||
|
|
3bd0180973 | ||
|
|
264556032f | ||
|
|
e034538570 | ||
|
|
c67266b094 | ||
|
|
c1cab3e41c | ||
|
|
1f9da4918f | ||
|
|
a56612b5a9 | ||
|
|
6cc5113f35 | ||
|
|
8cb40327f1 | ||
|
|
468f72001e | ||
|
|
1b9e433c75 | ||
|
|
f5ad52fe7f | ||
|
|
d1708bc87f | ||
|
|
f2168e439f | ||
|
|
69333be53d | ||
|
|
7ca12e3688 | ||
|
|
efa33be67c | ||
|
|
e7941194dc | ||
|
|
6f0f7e6a05 | ||
|
|
1c1a65c834 | ||
|
|
f2286b88a8 | ||
|
|
4d5e4231e2 | ||
|
|
ee005588d0 | ||
|
|
75fd754212 | ||
|
|
6d6cd1788b | ||
|
|
8f7fe509d1 | ||
|
|
2179aeb6d2 | ||
|
|
2e8f1b5c33 | ||
|
|
c0e19ef533 | ||
|
|
c953968c46 | ||
|
|
10b35388a3 | ||
|
|
28dd927214 | ||
|
|
e90e6be60f | ||
|
|
f7e7028fd6 | ||
|
|
2682fe811b | ||
|
|
93f546aa19 | ||
|
|
307e8dc52b | ||
|
|
320903f0d8 | ||
|
|
c0ba78e110 | ||
|
|
8cdf80ab42 | ||
|
|
78f060b048 | ||
|
|
a3abd887a9 | ||
|
|
e6d15a2c3f | ||
|
|
a8aae07ec5 | ||
|
|
b1eb772117 | ||
|
|
f5a27167f6 | ||
|
|
d629476752 | ||
|
|
df1a09fe48 | ||
|
|
681746cc58 | ||
|
|
040eb93e77 | ||
|
|
ebe252cd5a | ||
|
|
631d192b10 | ||
|
|
f755225450 | ||
|
|
1679e75595 | ||
|
|
2c6f60941e | ||
|
|
2ebb6ab2bf | ||
|
|
cc0babfe1b | ||
|
|
c1d2eed330 | ||
|
|
6dab54c855 | ||
|
|
2913c9cb2b | ||
|
|
16168f09dc | ||
|
|
e12a2f80f8 | ||
|
|
dac1eee654 | ||
|
|
8bd4ee67b2 | ||
|
|
e39183c0da | ||
|
|
7be2c9a613 | ||
|
|
1366ac5d50 | ||
|
|
4fb7872555 | ||
|
|
9851a7d7b0 | ||
|
|
7b257c0f86 | ||
|
|
232be2f7ab | ||
|
|
e5ae023803 | ||
|
|
fc0ecddc0d | ||
|
|
8dc1275ede | ||
|
|
99736ac1ac | ||
|
|
8ee7989e42 | ||
|
|
2e5fb959b5 | ||
|
|
756970144f | ||
|
|
56d4b611f2 | ||
|
|
29e0d60db6 | ||
|
|
5cd4063bb8 | ||
|
|
1bae99a760 | ||
|
|
6c7624fcdc | ||
|
|
2ff208bbe0 | ||
|
|
55eebb98c0 | ||
|
|
9eae19b58a | ||
|
|
10e0c41466 | ||
|
|
f0f92403f7 | ||
|
|
15111810b0 | ||
|
|
fe14079068 | ||
|
|
12a186b550 | ||
|
|
6e77d5b4a5 | ||
|
|
7dfc5ab324 | ||
|
|
185692be69 | ||
|
|
bd3fba42d4 | ||
|
|
27ae871a8b | ||
|
|
fb2bfc3e57 | ||
|
|
19814da37b | ||
|
|
5564bbd997 | ||
|
|
a93bb80c6e | ||
|
|
766a14babd | ||
|
|
a9262b4c21 | ||
|
|
cbfff996b3 | ||
|
|
d8e9044069 | ||
|
|
b5fb020216 | ||
|
|
9047e04cae | ||
|
|
0df71c015f | ||
|
|
52fca115ba | ||
|
|
7a926e8fb9 | ||
|
|
fe5a155381 | ||
|
|
208f6c8e4c | ||
|
|
70fd45a713 | ||
|
|
536c8233b5 | ||
|
|
9db1fdf435 | ||
|
|
fb97586573 | ||
|
|
693f7d4bd5 | ||
|
|
f36defbf26 | ||
|
|
8d996db507 | ||
|
|
6481d697a7 | ||
|
|
5bbad8d1eb | ||
|
|
eb09bb48d7 | ||
|
|
6de4a11a3b | ||
|
|
565619630e | ||
|
|
ac087e4bd3 | ||
|
|
541fc93a67 | ||
|
|
e4e854ea2a | ||
|
|
de5353d0ca | ||
|
|
31f1edc668 | ||
|
|
6905192954 | ||
|
|
e291865233 | ||
|
|
e7985fa52e | ||
|
|
89ffd9dca5 |
228 changed files with 24360 additions and 9803 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
|
||||
|
|
|
|||
34
.github/workflows/githubci.yml
vendored
34
.github/workflows/githubci.yml
vendored
|
|
@ -3,23 +3,21 @@ name: Build
|
|||
on: [pull_request, push, repository_dispatch]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
ARDUINO_LIBS: "\"Adafruit SPIFlash\" \"Adafruit seesaw Library\" \"Adafruit NeoPixel\" \"Adafruit Circuit Playground\" \"Adafruit InternalFlash\" \"SdFat - Adafruit Fork\" \"SD\" \"MIDI Library\" \"Pico PIO USB\""
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run pre-commit
|
||||
uses: pre-commit/action@v3.0.0
|
||||
uses: pre-commit/action@v3.0.1
|
||||
|
||||
- name: Checkout adafruit/ci-arduino
|
||||
uses: actions/checkout@v4
|
||||
|
|
@ -39,6 +37,9 @@ jobs:
|
|||
PRETTYNAME : "Adafruit TinyUSB Library"
|
||||
run: bash ci/doxy_gen_and_deploy.sh
|
||||
|
||||
# ---------------------------------------
|
||||
# build
|
||||
# ---------------------------------------
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: pre-commit
|
||||
|
|
@ -46,24 +47,23 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
arduino-platform:
|
||||
# ESP32
|
||||
# ESP32 ci use dev json
|
||||
- 'feather_esp32_v2'
|
||||
- 'feather_esp32s2'
|
||||
- 'feather_esp32s3'
|
||||
- 'esp32p4'
|
||||
# nRF52
|
||||
- 'cpb'
|
||||
- 'nrf52840'
|
||||
# RP2040
|
||||
- 'feather_rp2040_tinyusb'
|
||||
- 'pico_rp2040_tinyusb_host'
|
||||
# SAMD
|
||||
- 'metro_m0_tinyusb'
|
||||
- 'metro_m4_tinyusb'
|
||||
|
||||
# Ch32v2
|
||||
- 'CH32V20x_EVT'
|
||||
steps:
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
|
|
@ -76,8 +76,10 @@ jobs:
|
|||
- name: pre-install
|
||||
run: bash ci/actions_install.sh
|
||||
|
||||
- name: Install Libraries for building examples
|
||||
run: arduino-cli lib install "Adafruit SPIFlash" "MIDI Library" "Adafruit seesaw Library" "Adafruit NeoPixel" "SdFat - Adafruit Fork" "SD" "Adafruit Circuit Playground" "Adafruit InternalFlash" "Pico PIO USB"
|
||||
- name: Install Libraries
|
||||
run: |
|
||||
arduino-cli lib install ${{ env.ARDUINO_LIBS }}
|
||||
arduino-cli lib list
|
||||
|
||||
- name: test platforms
|
||||
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}
|
||||
|
|
|
|||
14
README.md
14
README.md
|
|
@ -15,15 +15,18 @@ Supported device class drivers are:
|
|||
- Human Interface Device (HID): Generic (In & Out), Keyboard, Mouse, Gamepad etc ...
|
||||
- Mass Storage Class (MSC): with multiple LUNs
|
||||
- Musical Instrument Digital Interface (MIDI)
|
||||
- Video (UVC): work in progress
|
||||
- WebUSB with vendor specific class
|
||||
|
||||
### Host Stack
|
||||
|
||||
Host support is still work-in-progress but currently available with rp2040 core thanks to [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB). Supported class driver are:
|
||||
Host stack is available with either addition of MAX3421E hardware (e.g [Host FeatherWing](https://www.adafruit.com/product/5858)) or rp2040 core (thanks to [Pico-PIO-USB](https://github.com/sekigon-gonnoc/Pico-PIO-USB)). Supported class driver are:
|
||||
|
||||
- Communication (CDC)
|
||||
- Communication (CDC): including vendor usb2uart such as FTDI, CP210x, CH34x
|
||||
- MassStorage class
|
||||
|
||||
Note: Host stack is still work-in-progress
|
||||
|
||||
## Supported Cores
|
||||
|
||||
There are 2 type of supported cores: with and without built-in support for TinyUSB. Built-in support provide seamless integration but requires extra code added to core's source code. Unfortunately it is not always easy or possible to make those modification.
|
||||
|
|
@ -35,9 +38,12 @@ 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)
|
||||
|
||||
ESP32 port relies on Espressif's [esp32-hal-tinyusb.c](https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp32-hal-tinyusb.c) for building usb descriptors which 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 for this port.
|
||||
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.
|
||||
|
||||
### Cores without built-in support
|
||||
|
||||
|
|
|
|||
8
examples/CDC/cdc_multi/.skip.txt
Normal file
8
examples/CDC/cdc_multi/.skip.txt
Normal file
|
|
@ -0,0 +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 "Currnetly 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,19 +18,40 @@
|
|||
* Note: this will cause device to loose the touch1200 and require
|
||||
* user manual interaction to put device into bootloader/DFU mode.
|
||||
*/
|
||||
void setup() {
|
||||
// Manual begin() is required on core without built-in support e.g. mbed rp2040
|
||||
if (!TinyUSBDevice.isInitialized()) {
|
||||
TinyUSBDevice.begin(0);
|
||||
}
|
||||
|
||||
int led = LED_BUILTIN;
|
||||
// clear configuration will remove all USB interfaces including CDC (Serial)
|
||||
TinyUSBDevice.clearConfiguration();
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.end();
|
||||
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()
|
||||
{
|
||||
digitalWrite(led, HIGH);
|
||||
delay(1000);
|
||||
digitalWrite(led, LOW);
|
||||
delay(1000);
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
// toggle LED
|
||||
static uint32_t ms = 0;
|
||||
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
|
||||
41
examples/CDC/serial_echo/serial_echo.ino
Normal file
41
examples/CDC/serial_echo/serial_echo.ino
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*********************************************************************
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
MIT license, check LICENSE for more information
|
||||
Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
All text above, and the splash screen below must be included in
|
||||
any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
|
||||
/* This sketch demonstrates USB CDC Serial echo (convert to upper case) using SerialTinyUSB which
|
||||
* is available for both core with built-in USB support and without.
|
||||
* Note: on core with built-in support Serial is alias to SerialTinyUSB
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
// Manual begin() is required on core without built-in support e.g. mbed rp2040
|
||||
if (!TinyUSBDevice.isInitialized()) {
|
||||
TinyUSBDevice.begin(0);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
uint8_t buf[64];
|
||||
uint32_t count = 0;
|
||||
while (SerialTinyUSB.available()) {
|
||||
buf[count++] = (uint8_t) toupper(SerialTinyUSB.read());
|
||||
}
|
||||
|
||||
if (count) {
|
||||
SerialTinyUSB.write(buf, count);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
/*********************************************************************
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
MIT license, check LICENSE for more information
|
||||
Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
All text above, and the splash screen below must be included in
|
||||
any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
/* This sketch demonstrates USB Mass Storage and HID mouse (and CDC)
|
||||
* - Enumerated as disk using on-board external flash
|
||||
* - Press button pin will move mouse toward bottom right of monitor
|
||||
*/
|
||||
|
||||
#include "SPI.h"
|
||||
#include "SdFat.h"
|
||||
#include "Adafruit_SPIFlash.h"
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MSC External Flash Config
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Un-comment to run example with custom SPI SPI and SS e.g with FRAM breakout
|
||||
// #define CUSTOM_CS A5
|
||||
// #define CUSTOM_SPI SPI
|
||||
|
||||
#if defined(CUSTOM_CS) && defined(CUSTOM_SPI)
|
||||
Adafruit_FlashTransport_SPI flashTransport(CUSTOM_CS, CUSTOM_SPI);
|
||||
|
||||
#elif defined(ARDUINO_ARCH_ESP32)
|
||||
// ESP32 use same flash device that store code.
|
||||
// Therefore there is no need to specify the SPI and SS
|
||||
Adafruit_FlashTransport_ESP32 flashTransport;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
// RP2040 use same flash device that store code.
|
||||
// Therefore there is no need to specify the SPI and SS
|
||||
// Use default (no-args) constructor to be compatible with CircuitPython partition scheme
|
||||
Adafruit_FlashTransport_RP2040 flashTransport;
|
||||
|
||||
// For generic usage:
|
||||
// Adafruit_FlashTransport_RP2040 flashTransport(start_address, size)
|
||||
// If start_address and size are both 0, value that match filesystem setting in
|
||||
// 'Tools->Flash Size' menu selection will be used
|
||||
|
||||
#else
|
||||
// On-board external flash (QSPI or SPI) macros should already
|
||||
// defined in your board variant if supported
|
||||
// - EXTERNAL_FLASH_USE_QSPI
|
||||
// - EXTERNAL_FLASH_USE_CS/EXTERNAL_FLASH_USE_SPI
|
||||
#if defined(EXTERNAL_FLASH_USE_QSPI)
|
||||
Adafruit_FlashTransport_QSPI flashTransport;
|
||||
|
||||
#elif defined(EXTERNAL_FLASH_USE_SPI)
|
||||
Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI);
|
||||
|
||||
#else
|
||||
#error No QSPI/SPI flash are defined on your board variant.h !
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Adafruit_SPIFlash flash(&flashTransport);
|
||||
|
||||
Adafruit_USBD_MSC usb_msc;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// HID Config
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// HID report descriptor using TinyUSB's template
|
||||
// Single Report (no ID) descriptor
|
||||
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
|
||||
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false);
|
||||
|
||||
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY)
|
||||
const int pin = 4; // Left Button
|
||||
bool activeState = true;
|
||||
|
||||
#elif defined(ARDUINO_FUNHOUSE_ESP32S2)
|
||||
const int pin = BUTTON_DOWN;
|
||||
bool activeState = true;
|
||||
|
||||
#elif defined PIN_BUTTON1
|
||||
const int pin = PIN_BUTTON1;
|
||||
bool activeState = false;
|
||||
|
||||
#else
|
||||
const int pin = 12;
|
||||
bool activeState = false;
|
||||
#endif
|
||||
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup()
|
||||
{
|
||||
flash.begin();
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
|
||||
usb_msc.setID("Adafruit", "External Flash", "1.0");
|
||||
|
||||
// Set callback
|
||||
usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb);
|
||||
|
||||
// Set disk size, block size should be 512 regardless of spi flash page size
|
||||
usb_msc.setCapacity(flash.size()/512, 512);
|
||||
|
||||
// MSC is ready for read/write
|
||||
usb_msc.setUnitReady(true);
|
||||
|
||||
usb_msc.begin();
|
||||
|
||||
// Set up button
|
||||
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
|
||||
|
||||
// Notes: following commented-out functions has no affect on ESP32
|
||||
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
|
||||
|
||||
usb_hid.begin();
|
||||
|
||||
Serial.begin(115200);
|
||||
//while ( !Serial ) delay(10); // wait for native usb
|
||||
|
||||
Serial.println("Adafruit TinyUSB Mouse + Mass Storage (external flash) example");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// poll gpio once each 10 ms
|
||||
delay(10);
|
||||
|
||||
// button is active low
|
||||
uint32_t const btn = (digitalRead(pin) == activeState);
|
||||
|
||||
// Remote wakeup
|
||||
if ( TinyUSBDevice.suspended() && btn )
|
||||
{
|
||||
// Wake up host if we are in suspend mode
|
||||
// and REMOTE_WAKEUP feature is enabled by host
|
||||
tud_remote_wakeup();
|
||||
}
|
||||
|
||||
/*------------- Mouse -------------*/
|
||||
if ( usb_hid.ready() )
|
||||
{
|
||||
if ( btn )
|
||||
{
|
||||
int8_t const delta = 5;
|
||||
usb_hid.mouseMove(0, delta, delta); // no ID: right + down
|
||||
|
||||
// delay a bit before attempt to send keyboard report
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
|
||||
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
|
||||
return flash.writeBlocks(lba, buffer, bufsize/512) ? 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)
|
||||
{
|
||||
flash.syncBlocks();
|
||||
}
|
||||
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
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
// 8KB is the smallest size that windows allow to mount
|
||||
#define DISK_BLOCK_NUM 16
|
||||
#define DISK_BLOCK_SIZE 512
|
||||
|
||||
#include "ramdisk.h"
|
||||
|
||||
Adafruit_USBD_MSC usb_msc;
|
||||
|
|
@ -33,43 +34,51 @@ Adafruit_USBD_MSC usb_msc;
|
|||
|
||||
// HID report descriptor using TinyUSB's template
|
||||
// Single Report (no ID) descriptor
|
||||
uint8_t const desc_hid_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_MOUSE()
|
||||
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
|
||||
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false);
|
||||
// USB HID object
|
||||
Adafruit_USBD_HID usb_hid;
|
||||
|
||||
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY)
|
||||
const int pin = 4; // Left Button
|
||||
bool activeState = true;
|
||||
const int pin = 4; // Left Button
|
||||
bool activeState = true;
|
||||
|
||||
#elif defined(ARDUINO_FUNHOUSE_ESP32S2)
|
||||
const int pin = BUTTON_DOWN;
|
||||
bool activeState = true;
|
||||
const int pin = BUTTON_DOWN;
|
||||
bool activeState = true;
|
||||
|
||||
#elif defined PIN_BUTTON1
|
||||
const int pin = PIN_BUTTON1;
|
||||
bool activeState = false;
|
||||
const int pin = PIN_BUTTON1;
|
||||
bool activeState = false;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_ESP32)
|
||||
const int pin = 0;
|
||||
bool activeState = false;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
const int pin = D0;
|
||||
bool activeState = false;
|
||||
|
||||
#else
|
||||
const int pin = 12;
|
||||
bool activeState = false;
|
||||
const int pin = A0;
|
||||
bool activeState = false;
|
||||
#endif
|
||||
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
#endif
|
||||
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);
|
||||
|
||||
// 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");
|
||||
|
||||
|
||||
// Set disk size
|
||||
usb_msc.setCapacity(DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
|
||||
|
||||
|
|
@ -78,44 +87,42 @@ void setup()
|
|||
|
||||
// Set Lun ready (RAM disk is always ready)
|
||||
usb_msc.setUnitReady(true);
|
||||
|
||||
|
||||
usb_msc.begin();
|
||||
|
||||
// Set up button
|
||||
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
|
||||
|
||||
// Notes: following commented-out functions has no affect on ESP32
|
||||
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
|
||||
|
||||
// Set up HID
|
||||
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
|
||||
usb_hid.setBootProtocol(HID_ITF_PROTOCOL_NONE);
|
||||
usb_hid.setPollInterval(2);
|
||||
usb_hid.begin();
|
||||
|
||||
Serial.begin(115200);
|
||||
while( !TinyUSBDevice.mounted() ) delay(1); // 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();
|
||||
}
|
||||
|
||||
Serial.println("Adafruit TinyUSB Mouse + Mass Storage (ramdisk) example");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// poll gpio once each 10 ms
|
||||
delay(10);
|
||||
|
||||
void process_hid() {
|
||||
// button is active low
|
||||
uint32_t const btn = (digitalRead(pin) == activeState);
|
||||
|
||||
// Remote wakeup
|
||||
if ( TinyUSBDevice.suspended() && btn )
|
||||
{
|
||||
if (TinyUSBDevice.suspended() && btn) {
|
||||
// Wake up host if we are in suspend mode
|
||||
// and REMOTE_WAKEUP feature is enabled by host
|
||||
tud_remote_wakeup();
|
||||
}
|
||||
|
||||
/*------------- Mouse -------------*/
|
||||
if ( usb_hid.ready() )
|
||||
{
|
||||
if ( btn )
|
||||
{
|
||||
if (usb_hid.ready()) {
|
||||
if (btn) {
|
||||
int8_t const delta = 5;
|
||||
usb_hid.mouseMove(0, delta, delta); // no ID: right + down
|
||||
|
||||
|
|
@ -125,11 +132,29 @@ void loop()
|
|||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
// not enumerated()/mounted() yet: nothing to do
|
||||
if (!TinyUSBDevice.mounted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// poll gpio once each 10 ms
|
||||
static uint32_t ms = 0;
|
||||
if (millis() - ms > 10) {
|
||||
ms = millis();
|
||||
process_hid();
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
uint8_t const* addr = msc_disk[lba];
|
||||
memcpy(buffer, addr, bufsize);
|
||||
|
||||
|
|
@ -139,8 +164,7 @@ 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) {
|
||||
uint8_t* addr = msc_disk[lba];
|
||||
memcpy(addr, buffer, bufsize);
|
||||
|
||||
|
|
@ -149,7 +173,6 @@ 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) {
|
||||
// nothing to do
|
||||
}
|
||||
|
|
|
|||
2
examples/DualRole/CDC/serial_host_bridge/.skip.txt
Normal file
2
examples/DualRole/CDC/serial_host_bridge/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
|
|
@ -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/DualRole/HID/hid_device_report/.skip.txt
Normal file
2
examples/DualRole/HID/hid_device_report/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
3
examples/DualRole/HID/hid_mouse_log_filter/.skip.txt
Normal file
3
examples/DualRole/HID/hid_mouse_log_filter/.skip.txt
Normal file
|
|
@ -0,0 +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.
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
3
examples/DualRole/HID/hid_mouse_tremor_filter/.skip.txt
Normal file
3
examples/DualRole/HID/hid_mouse_tremor_filter/.skip.txt
Normal file
|
|
@ -0,0 +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 -------------//
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
3
examples/DualRole/HID/hid_remapper/.skip.txt
Normal file
3
examples/DualRole/HID/hid_remapper/.skip.txt
Normal file
|
|
@ -0,0 +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();
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
|
|
@ -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/DualRole/MassStorage/msc_data_logger/.skip.txt
Normal file
2
examples/DualRole/MassStorage/msc_data_logger/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
|
|
@ -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
examples/DualRole/Simple/device_info/.skip.txt
Normal file
1
examples/DualRole/Simple/device_info/.skip.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
CH32V20x_EVT
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 27, 33);
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
|
|
@ -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/DualRole/Simple/device_info_max3421e/.skip.txt
Normal file
2
examples/DualRole/Simple/device_info_max3421e/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
/*********************************************************************
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
MIT license, check LICENSE for more information
|
||||
Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
All text above, and the splash screen below must be included in
|
||||
any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
/* This example demonstrates use of both device and host, where
|
||||
* - Device run on native usb controller (roothub port0)
|
||||
* - Host run on MAX3421E controller (roothub port1) tested with:
|
||||
* - SAMD21, SAMD51, nRF52840, ESP32S2, ESP32S3, ESP32
|
||||
* - RP2040: "pio_usb.h" must not be included, otherwise pio-usb will be used as host controller
|
||||
*
|
||||
* Requirements:
|
||||
* - SPI instance, CS pin, INT pin are correctly configured
|
||||
*/
|
||||
|
||||
/* Host example will get device descriptors of attached devices and print it out:
|
||||
* Device 1: ID 046d:c52f
|
||||
Device Descriptor:
|
||||
bLength 18
|
||||
bDescriptorType 1
|
||||
bcdUSB 0200
|
||||
bDeviceClass 0
|
||||
bDeviceSubClass 0
|
||||
bDeviceProtocol 0
|
||||
bMaxPacketSize0 8
|
||||
idVendor 0x046d
|
||||
idProduct 0xc52f
|
||||
bcdDevice 2200
|
||||
iManufacturer 1 Logitech
|
||||
iProduct 2 USB Receiver
|
||||
iSerialNumber 0
|
||||
bNumConfigurations 1
|
||||
*
|
||||
*/
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
#include "SPI.h"
|
||||
|
||||
// USB Host using MAX3421E: SPI, CS, INT
|
||||
#if defined(ARDUINO_METRO_ESP32S2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 15, 14);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 33, 15);
|
||||
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32C6)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 8, 7);
|
||||
#elif defined(ARDUINO_ESP32C3_DEV)
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 7);
|
||||
#else
|
||||
// Default CS and INT are pin 10, 9
|
||||
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
|
||||
#endif
|
||||
|
||||
// Language ID: English
|
||||
#define LANGUAGE_ID 0x0409
|
||||
|
||||
typedef struct {
|
||||
tusb_desc_device_t desc_device;
|
||||
uint16_t manufacturer[32];
|
||||
uint16_t product[48];
|
||||
uint16_t serial[16];
|
||||
bool mounted;
|
||||
} dev_info_t;
|
||||
|
||||
// CFG_TUH_DEVICE_MAX is defined by tusb_config header
|
||||
dev_info_t dev_info[CFG_TUH_DEVICE_MAX] = { 0 };
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// setup() & loop()
|
||||
//--------------------------------------------------------------------+
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// init host stack on controller (rhport) 1
|
||||
USBHost.begin(1);
|
||||
|
||||
// while ( !Serial ) delay(10); // wait for native usb
|
||||
Serial.println("TinyUSB Dual: Device Info Example with MAX3421E");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
USBHost.task();
|
||||
Serial.flush();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TinyUSB Host callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
void print_device_descriptor(tuh_xfer_t *xfer);
|
||||
|
||||
void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len);
|
||||
|
||||
void print_lsusb(void) {
|
||||
bool no_device = true;
|
||||
for (uint8_t daddr = 1; daddr < CFG_TUH_DEVICE_MAX + 1; daddr++) {
|
||||
// TODO can use tuh_mounted(daddr), but tinyusb has an bug
|
||||
// use local connected flag instead
|
||||
dev_info_t *dev = &dev_info[daddr - 1];
|
||||
if (dev->mounted) {
|
||||
Serial.printf("Device %u: ID %04x:%04x %s %s\r\n", daddr,
|
||||
dev->desc_device.idVendor, dev->desc_device.idProduct,
|
||||
(char *) dev->manufacturer, (char *) dev->product);
|
||||
|
||||
no_device = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (no_device) {
|
||||
Serial.println("No device connected (except hub)");
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when device is mounted (configured)
|
||||
void tuh_mount_cb(uint8_t daddr) {
|
||||
Serial.printf("Device attached, address = %d\r\n", daddr);
|
||||
|
||||
dev_info_t *dev = &dev_info[daddr - 1];
|
||||
dev->mounted = true;
|
||||
|
||||
// Get Device Descriptor
|
||||
tuh_descriptor_get_device(daddr, &dev->desc_device, 18, print_device_descriptor, 0);
|
||||
}
|
||||
|
||||
/// Invoked when device is unmounted (bus reset/unplugged)
|
||||
void tuh_umount_cb(uint8_t daddr) {
|
||||
Serial.printf("Device removed, address = %d\r\n", daddr);
|
||||
dev_info_t *dev = &dev_info[daddr - 1];
|
||||
dev->mounted = false;
|
||||
|
||||
// print device summary
|
||||
print_lsusb();
|
||||
}
|
||||
|
||||
void print_device_descriptor(tuh_xfer_t *xfer) {
|
||||
if (XFER_RESULT_SUCCESS != xfer->result) {
|
||||
Serial.printf("Failed to get device descriptor\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t const daddr = xfer->daddr;
|
||||
dev_info_t *dev = &dev_info[daddr - 1];
|
||||
tusb_desc_device_t *desc = &dev->desc_device;
|
||||
|
||||
Serial.printf("Device %u: ID %04x:%04x\r\n", daddr, desc->idVendor, desc->idProduct);
|
||||
Serial.printf("Device Descriptor:\r\n");
|
||||
Serial.printf(" bLength %u\r\n" , desc->bLength);
|
||||
Serial.printf(" bDescriptorType %u\r\n" , desc->bDescriptorType);
|
||||
Serial.printf(" bcdUSB %04x\r\n" , desc->bcdUSB);
|
||||
Serial.printf(" bDeviceClass %u\r\n" , desc->bDeviceClass);
|
||||
Serial.printf(" bDeviceSubClass %u\r\n" , desc->bDeviceSubClass);
|
||||
Serial.printf(" bDeviceProtocol %u\r\n" , desc->bDeviceProtocol);
|
||||
Serial.printf(" bMaxPacketSize0 %u\r\n" , desc->bMaxPacketSize0);
|
||||
Serial.printf(" idVendor 0x%04x\r\n" , desc->idVendor);
|
||||
Serial.printf(" idProduct 0x%04x\r\n" , desc->idProduct);
|
||||
Serial.printf(" bcdDevice %04x\r\n" , desc->bcdDevice);
|
||||
|
||||
// Get String descriptor using Sync API
|
||||
Serial.printf(" iManufacturer %u ", desc->iManufacturer);
|
||||
if (XFER_RESULT_SUCCESS ==
|
||||
tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, dev->manufacturer, sizeof(dev->manufacturer))) {
|
||||
utf16_to_utf8(dev->manufacturer, sizeof(dev->manufacturer));
|
||||
Serial.printf((char *) dev->manufacturer);
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
|
||||
Serial.printf(" iProduct %u ", desc->iProduct);
|
||||
if (XFER_RESULT_SUCCESS ==
|
||||
tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, dev->product, sizeof(dev->product))) {
|
||||
utf16_to_utf8(dev->product, sizeof(dev->product));
|
||||
Serial.printf((char *) dev->product);
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
|
||||
Serial.printf(" iSerialNumber %u ", desc->iSerialNumber);
|
||||
if (XFER_RESULT_SUCCESS ==
|
||||
tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, dev->serial, sizeof(dev->serial))) {
|
||||
utf16_to_utf8(dev->serial, sizeof(dev->serial));
|
||||
Serial.printf((char *) dev->serial);
|
||||
}
|
||||
Serial.printf("\r\n");
|
||||
|
||||
Serial.printf(" bNumConfigurations %u\r\n", desc->bNumConfigurations);
|
||||
|
||||
// print device summary
|
||||
print_lsusb();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// String Descriptor Helper
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
|
||||
// TODO: Check for runover.
|
||||
(void) utf8_len;
|
||||
// Get the UTF-16 length out of the data itself.
|
||||
|
||||
for (size_t i = 0; i < utf16_len; i++) {
|
||||
uint16_t chr = utf16[i];
|
||||
if (chr < 0x80) {
|
||||
*utf8++ = chr & 0xff;
|
||||
} else if (chr < 0x800) {
|
||||
*utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F));
|
||||
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
|
||||
} else {
|
||||
// TODO: Verify surrogate.
|
||||
*utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F));
|
||||
*utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F));
|
||||
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
|
||||
}
|
||||
// TODO: Handle UTF-16 code points that take two entries.
|
||||
}
|
||||
}
|
||||
|
||||
// Count how many bytes a utf-16-le encoded string will take in utf-8.
|
||||
static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
|
||||
size_t total_bytes = 0;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
uint16_t chr = buf[i];
|
||||
if (chr < 0x80) {
|
||||
total_bytes += 1;
|
||||
} else if (chr < 0x800) {
|
||||
total_bytes += 2;
|
||||
} else {
|
||||
total_bytes += 3;
|
||||
}
|
||||
// TODO: Handle UTF-16 code points that take two entries.
|
||||
}
|
||||
return total_bytes;
|
||||
}
|
||||
|
||||
void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) {
|
||||
size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
|
||||
size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len);
|
||||
|
||||
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, buf_len);
|
||||
((uint8_t *) temp_buf)[utf8_len] = '\0';
|
||||
}
|
||||
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
|
||||
|
|
@ -10,93 +10,73 @@
|
|||
*********************************************************************/
|
||||
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
|
||||
/* This sketch demonstrates USB HID keyboard.
|
||||
* - PIN A0-A5 is used to send digit '0' to '5' respectively
|
||||
* - PIN A0-A3 is used to send digit '0' to '3' respectively
|
||||
* (On the RP2040, pins D0-D5 used)
|
||||
* - LED and/or Neopixels will be used as Capslock indicator
|
||||
*/
|
||||
|
||||
// HID report descriptor using TinyUSB's template
|
||||
// Single Report (no ID) descriptor
|
||||
uint8_t const desc_hid_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_KEYBOARD()
|
||||
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
|
||||
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false);
|
||||
Adafruit_USBD_HID usb_hid;
|
||||
|
||||
//------------- Input Pins -------------//
|
||||
// Array of pins and its keycode.
|
||||
// Notes: these pins can be replaced by PIN_BUTTONn if defined in setup()
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
uint8_t pins[] = { D0, D1, D2, D3 };
|
||||
uint8_t pins[] = { D0, D1, D2, D3 };
|
||||
#else
|
||||
uint8_t pins[] = { A0, A1, A2, A3 };
|
||||
uint8_t pins[] = {A0, A1, A2, A3};
|
||||
#endif
|
||||
|
||||
// number of pins
|
||||
uint8_t pincount = sizeof(pins)/sizeof(pins[0]);
|
||||
uint8_t pincount = sizeof(pins) / sizeof(pins[0]);
|
||||
|
||||
// For keycode definition check out https://github.com/hathach/tinyusb/blob/master/src/class/hid/hid.h
|
||||
uint8_t hidcode[] = { HID_KEY_ARROW_RIGHT, HID_KEY_ARROW_LEFT, HID_KEY_ARROW_DOWN, HID_KEY_ARROW_UP };
|
||||
uint8_t hidcode[] = {HID_KEY_0, HID_KEY_1, HID_KEY_2, HID_KEY_3};
|
||||
|
||||
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY) || defined(ARDUINO_FUNHOUSE_ESP32S2)
|
||||
bool activeState = true;
|
||||
bool activeState = true;
|
||||
#else
|
||||
bool activeState = false;
|
||||
bool activeState = false;
|
||||
#endif
|
||||
|
||||
//------------- Neopixel -------------//
|
||||
// #define PIN_NEOPIXEL 8
|
||||
#ifdef PIN_NEOPIXEL
|
||||
|
||||
// How many NeoPixels are attached to the Arduino?
|
||||
// use on-board defined NEOPIXEL_NUM if existed
|
||||
#ifndef NEOPIXEL_NUM
|
||||
#define NEOPIXEL_NUM 10
|
||||
#endif
|
||||
|
||||
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NEOPIXEL_NUM, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
#endif
|
||||
void setup() {
|
||||
// Manual begin() is required on core without built-in support e.g. mbed rp2040
|
||||
if (!TinyUSBDevice.isInitialized()) {
|
||||
TinyUSBDevice.begin(0);
|
||||
}
|
||||
|
||||
// Notes: following commented-out functions has no affect on ESP32
|
||||
// usb_hid.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD);
|
||||
// usb_hid.setPollInterval(2);
|
||||
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
|
||||
// usb_hid.setStringDescriptor("TinyUSB Keyboard");
|
||||
// Setup HID
|
||||
usb_hid.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD);
|
||||
usb_hid.setPollInterval(2);
|
||||
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
|
||||
usb_hid.setStringDescriptor("TinyUSB Keyboard");
|
||||
|
||||
// Set up output report (on control endpoint) for Capslock indicator
|
||||
usb_hid.setReportCallback(NULL, hid_report_callback);
|
||||
|
||||
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);
|
||||
|
||||
// neopixel if existed
|
||||
#ifdef PIN_NEOPIXEL
|
||||
pixels.begin();
|
||||
pixels.setBrightness(50);
|
||||
|
||||
#ifdef NEOPIXEL_POWER
|
||||
pinMode(NEOPIXEL_POWER, OUTPUT);
|
||||
digitalWrite(NEOPIXEL_POWER, NEOPIXEL_POWER_ON);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// overwrite input pin with PIN_BUTTONx
|
||||
|
|
@ -117,32 +97,21 @@ void setup()
|
|||
#endif
|
||||
|
||||
// Set up pin as input
|
||||
for (uint8_t i=0; i<pincount; i++)
|
||||
{
|
||||
for (uint8_t i = 0; i < pincount; i++) {
|
||||
pinMode(pins[i], activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
|
||||
}
|
||||
|
||||
// wait until device mounted
|
||||
while( !TinyUSBDevice.mounted() ) delay(1);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// poll gpio once each 2 ms
|
||||
delay(2);
|
||||
|
||||
void process_hid() {
|
||||
// used to avoid send multiple consecutive zero report for keyboard
|
||||
static bool keyPressedPreviously = false;
|
||||
|
||||
uint8_t count=0;
|
||||
uint8_t keycode[6] = { 0 };
|
||||
uint8_t count = 0;
|
||||
uint8_t keycode[6] = {0};
|
||||
|
||||
// scan normal key and send report
|
||||
for(uint8_t i=0; i < pincount; i++)
|
||||
{
|
||||
if ( activeState == digitalRead(pins[i]) )
|
||||
{
|
||||
for (uint8_t i = 0; i < pincount; i++) {
|
||||
if (activeState == digitalRead(pins[i])) {
|
||||
// if pin is active (low), add its hid code to key report
|
||||
keycode[count++] = hidcode[i];
|
||||
|
||||
|
|
@ -151,55 +120,66 @@ void loop()
|
|||
}
|
||||
}
|
||||
|
||||
if ( TinyUSBDevice.suspended() && count )
|
||||
{
|
||||
if (TinyUSBDevice.suspended() && count) {
|
||||
// Wake up host if we are in suspend mode
|
||||
// and REMOTE_WAKEUP feature is enabled by host
|
||||
TinyUSBDevice.remoteWakeup();
|
||||
}
|
||||
|
||||
// skip if hid is not ready e.g still transferring previous report
|
||||
if ( !usb_hid.ready() ) return;
|
||||
if (!usb_hid.ready()) return;
|
||||
|
||||
if ( count )
|
||||
{
|
||||
if (count) {
|
||||
// Send report if there is key pressed
|
||||
uint8_t const report_id = 0;
|
||||
uint8_t const modifier = 0;
|
||||
|
||||
keyPressedPreviously = true;
|
||||
usb_hid.keyboardReport(report_id, modifier, keycode);
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
// Send All-zero report to indicate there is no keys pressed
|
||||
// Most of the time, it is, though we don't need to send zero report
|
||||
// every loop(), only a key is pressed in previous loop()
|
||||
if ( keyPressedPreviously )
|
||||
{
|
||||
if (keyPressedPreviously) {
|
||||
keyPressedPreviously = false;
|
||||
usb_hid.keyboardRelease(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
// not enumerated()/mounted() yet: nothing to do
|
||||
if (!TinyUSBDevice.mounted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// poll gpio once each 2 ms
|
||||
static uint32_t ms = 0;
|
||||
if (millis() - ms > 2) {
|
||||
ms = millis();
|
||||
process_hid();
|
||||
}
|
||||
}
|
||||
|
||||
// Output report callback for LED indicator such as Caplocks
|
||||
void hid_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
|
||||
{
|
||||
void hid_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
|
||||
(void) report_id;
|
||||
(void) bufsize;
|
||||
|
||||
// LED indicator is output report with only 1 byte length
|
||||
if ( report_type != HID_REPORT_TYPE_OUTPUT ) return;
|
||||
if (report_type != HID_REPORT_TYPE_OUTPUT) return;
|
||||
|
||||
// The LED bit map is as follows: (also defined by KEYBOARD_LED_* )
|
||||
// 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);
|
||||
|
||||
#ifdef PIN_NEOPIXEL
|
||||
pixels.fill(ledIndicator & KEYBOARD_LED_CAPSLOCK ? 0xff0000 : 0x000000);
|
||||
pixels.show();
|
||||
#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
|
||||
|
|
@ -19,66 +19,69 @@
|
|||
* and its active state (when pressed) are different
|
||||
*/
|
||||
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY)
|
||||
const int pin = 4; // Left Button
|
||||
bool activeState = true;
|
||||
const int pin = 4; // Left Button
|
||||
bool activeState = true;
|
||||
|
||||
#elif defined(ARDUINO_FUNHOUSE_ESP32S2)
|
||||
const int pin = BUTTON_DOWN;
|
||||
bool activeState = true;
|
||||
const int pin = BUTTON_DOWN;
|
||||
bool activeState = true;
|
||||
|
||||
#elif defined PIN_BUTTON1
|
||||
const int pin = PIN_BUTTON1;
|
||||
bool activeState = false;
|
||||
const int pin = PIN_BUTTON1;
|
||||
bool activeState = false;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_ESP32)
|
||||
const int pin = 0;
|
||||
bool activeState = false;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
const int pin = D0;
|
||||
bool activeState = false;
|
||||
#else
|
||||
const int pin = 12;
|
||||
bool activeState = false;
|
||||
const int pin = A0;
|
||||
bool activeState = false;
|
||||
#endif
|
||||
|
||||
|
||||
// HID report descriptor using TinyUSB's template
|
||||
// Single Report (no ID) descriptor
|
||||
uint8_t const desc_hid_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_MOUSE()
|
||||
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
|
||||
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_MOUSE, 2, false);
|
||||
// USB HID object
|
||||
Adafruit_USBD_HID usb_hid;
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
#endif
|
||||
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);
|
||||
|
||||
// Set up button, pullup opposite to active state
|
||||
pinMode(pin, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
|
||||
|
||||
// Notes: following commented-out functions has no affect on ESP32
|
||||
// usb_hid.setBootProtocol(HID_ITF_PROTOCOL_MOUSE);
|
||||
// usb_hid.setPollInterval(2);
|
||||
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
|
||||
// usb_hid.setStringDescriptor("TinyUSB Mouse");
|
||||
|
||||
// Set up HID
|
||||
usb_hid.setBootProtocol(HID_ITF_PROTOCOL_MOUSE);
|
||||
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);
|
||||
|
||||
// wait until device mounted
|
||||
while( !TinyUSBDevice.mounted() ) delay(1);
|
||||
// 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");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// poll gpio once each 10 ms
|
||||
delay(10);
|
||||
|
||||
void process_hid() {
|
||||
// Whether button is pressed
|
||||
bool btn_pressed = (digitalRead(pin) == activeState);
|
||||
|
||||
|
|
@ -86,17 +89,34 @@ void loop()
|
|||
if (!btn_pressed) return;
|
||||
|
||||
// Remote wakeup
|
||||
if ( TinyUSBDevice.suspended() )
|
||||
{
|
||||
if (TinyUSBDevice.suspended()) {
|
||||
// Wake up host if we are in suspend mode
|
||||
// and REMOTE_WAKEUP feature is enabled by host
|
||||
TinyUSBDevice.remoteWakeup();
|
||||
}
|
||||
|
||||
if ( usb_hid.ready() )
|
||||
{
|
||||
if (usb_hid.ready()) {
|
||||
uint8_t const report_id = 0; // no ID
|
||||
int8_t const delta = 5;
|
||||
usb_hid.mouseMove(report_id, delta, delta); // right + down
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
// not enumerated()/mounted() yet: nothing to do
|
||||
if (!TinyUSBDevice.mounted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// poll gpio once each 10 ms
|
||||
static uint32_t ms = 0;
|
||||
if (millis() - ms > 10) {
|
||||
ms = millis();
|
||||
process_hid();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
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
|
||||
|
|
@ -20,83 +20,90 @@
|
|||
* and its active state (when pressed) are different
|
||||
*/
|
||||
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY)
|
||||
const int pin = 4; // Left Button
|
||||
bool activeState = true;
|
||||
const int pin = 4; // Left Button
|
||||
bool activeState = true;
|
||||
|
||||
#elif defined(ARDUINO_FUNHOUSE_ESP32S2)
|
||||
const int pin = BUTTON_DOWN;
|
||||
bool activeState = true;
|
||||
const int pin = BUTTON_DOWN;
|
||||
bool activeState = true;
|
||||
|
||||
#elif defined PIN_BUTTON1
|
||||
const int pin = PIN_BUTTON1;
|
||||
bool activeState = false;
|
||||
const int pin = PIN_BUTTON1;
|
||||
bool activeState = false;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_ESP32)
|
||||
const int pin = 0;
|
||||
bool activeState = false;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
const int pin = D0;
|
||||
bool activeState = false;
|
||||
|
||||
#else
|
||||
const int pin = 12;
|
||||
bool activeState = false;
|
||||
const int pin = A0;
|
||||
bool activeState = false;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Report ID
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
RID_KEYBOARD = 1,
|
||||
RID_MOUSE,
|
||||
RID_CONSUMER_CONTROL, // Media, volume etc ..
|
||||
};
|
||||
|
||||
// HID report descriptor using TinyUSB's template
|
||||
uint8_t const desc_hid_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(RID_KEYBOARD) ),
|
||||
TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(RID_MOUSE) ),
|
||||
TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(RID_CONSUMER_CONTROL) )
|
||||
uint8_t const desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(RID_KEYBOARD)),
|
||||
TUD_HID_REPORT_DESC_MOUSE (HID_REPORT_ID(RID_MOUSE)),
|
||||
TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(RID_CONSUMER_CONTROL))
|
||||
};
|
||||
|
||||
// USB HID object. For ESP32 these values cannot be changed after this declaration
|
||||
// desc report, desc len, protocol, interval, use out endpoint
|
||||
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false);
|
||||
// USB HID object.
|
||||
Adafruit_USBD_HID usb_hid;
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup()
|
||||
{
|
||||
// Notes: following commented-out functions has no affect on ESP32
|
||||
// usb_hid.setPollInterval(2);
|
||||
// usb_hid.setReportDescriptor();
|
||||
// usb_hid.setStringDescriptor("TinyUSB HID Composite");
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
// wait until device mounted
|
||||
while( !TinyUSBDevice.mounted() ) delay(1);
|
||||
|
||||
Serial.println("Adafruit TinyUSB HID Composite example");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// poll gpio once each 10 ms
|
||||
delay(10);
|
||||
|
||||
void process_hid() {
|
||||
// Whether button is pressed
|
||||
bool btn_pressed = (digitalRead(pin) == activeState);
|
||||
|
||||
// Remote wakeup
|
||||
if ( TinyUSBDevice.suspended() && btn_pressed )
|
||||
{
|
||||
if (TinyUSBDevice.suspended() && btn_pressed) {
|
||||
// Wake up host if we are in suspend mode
|
||||
// and REMOTE_WAKEUP feature is enabled by host
|
||||
TinyUSBDevice.remoteWakeup();
|
||||
}
|
||||
|
||||
/*------------- Mouse -------------*/
|
||||
if ( usb_hid.ready() && btn_pressed )
|
||||
{
|
||||
if (usb_hid.ready() && btn_pressed) {
|
||||
int8_t const delta = 5;
|
||||
usb_hid.mouseMove(RID_MOUSE, delta, delta); // right + down
|
||||
|
||||
|
|
@ -105,21 +112,18 @@ void loop()
|
|||
}
|
||||
|
||||
/*------------- Keyboard -------------*/
|
||||
if ( usb_hid.ready() )
|
||||
{
|
||||
if (usb_hid.ready()) {
|
||||
// use to send key release report
|
||||
static bool has_key = false;
|
||||
|
||||
if ( btn_pressed )
|
||||
{
|
||||
uint8_t keycode[6] = { 0 };
|
||||
if (btn_pressed) {
|
||||
uint8_t keycode[6] = {0};
|
||||
keycode[0] = HID_KEY_A;
|
||||
|
||||
usb_hid.keyboardReport(RID_KEYBOARD, 0, keycode);
|
||||
|
||||
has_key = true;
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
// send empty key report if previously has key pressed
|
||||
if (has_key) usb_hid.keyboardRelease(RID_KEYBOARD);
|
||||
has_key = false;
|
||||
|
|
@ -130,8 +134,7 @@ void loop()
|
|||
}
|
||||
|
||||
/*------------- Consumer Control -------------*/
|
||||
if ( usb_hid.ready() )
|
||||
{
|
||||
if (usb_hid.ready()) {
|
||||
// Consumer Control is used to control Media playback, Volume, Brightness etc ...
|
||||
// Consumer report is 2-byte containing the control code of the key
|
||||
// For list of control check out https://github.com/hathach/tinyusb/blob/master/src/class/hid/hid.h
|
||||
|
|
@ -139,16 +142,33 @@ void loop()
|
|||
// use to send consumer release report
|
||||
static bool has_consumer_key = false;
|
||||
|
||||
if ( btn_pressed )
|
||||
{
|
||||
if (btn_pressed) {
|
||||
// send volume down (0x00EA)
|
||||
usb_hid.sendReport16(RID_CONSUMER_CONTROL, HID_USAGE_CONSUMER_VOLUME_DECREMENT);
|
||||
has_consumer_key = true;
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
// release the consume key by sending zero (0x0000)
|
||||
if (has_consumer_key) usb_hid.sendReport16(RID_CONSUMER_CONTROL, 0);
|
||||
has_consumer_key = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
// not enumerated()/mounted() yet: nothing to do
|
||||
if (!TinyUSBDevice.mounted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// poll gpio once each 10 ms
|
||||
static uint32_t ms = 0;
|
||||
if (millis() - ms > 10) {
|
||||
ms = millis();
|
||||
process_hid();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3
examples/HID/hid_composite_joy_featherwing/.skip.txt
Normal file
3
examples/HID/hid_composite_joy_featherwing/.skip.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
@ -33,17 +33,15 @@ uint32_t button_mask = (1 << BUTTON_A) | (1 << BUTTON_B) |
|
|||
Adafruit_seesaw ss;
|
||||
|
||||
// Report ID
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
RID_KEYBOARD = 1,
|
||||
RID_MOUSE
|
||||
};
|
||||
|
||||
// HID report descriptor using TinyUSB's template
|
||||
uint8_t const desc_hid_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(RID_KEYBOARD) ),
|
||||
TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(RID_MOUSE) )
|
||||
uint8_t const desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(RID_KEYBOARD)),
|
||||
TUD_HID_REPORT_DESC_MOUSE (HID_REPORT_ID(RID_MOUSE))
|
||||
};
|
||||
|
||||
// USB HID object. For ESP32 these values cannot be changed after this declaration
|
||||
|
|
@ -53,20 +51,30 @@ Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROT
|
|||
int last_x, last_y;
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup()
|
||||
{
|
||||
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);
|
||||
|
||||
// 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)){
|
||||
if (!ss.begin(0x49)) {
|
||||
Serial.println("ERROR! seesaw not found");
|
||||
while(1);
|
||||
while (1) {}
|
||||
} else {
|
||||
Serial.println("seesaw started");
|
||||
Serial.print("version: ");
|
||||
|
|
@ -77,16 +85,9 @@ void setup()
|
|||
|
||||
last_y = ss.analogRead(2);
|
||||
last_x = ss.analogRead(3);
|
||||
|
||||
// wait until device mounted
|
||||
while( !TinyUSBDevice.mounted() ) delay(1);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// poll gpio once each 10 ms
|
||||
delay(10);
|
||||
|
||||
void process_hid() {
|
||||
// If either analog stick or any buttons is pressed
|
||||
bool has_action = false;
|
||||
|
||||
|
|
@ -98,12 +99,10 @@ void loop()
|
|||
int dx = (x - last_x) / 2;
|
||||
int dy = (y - last_y) / 2;
|
||||
|
||||
if ( (abs(dx) > 3) || (abs(dy) > 3) )
|
||||
{
|
||||
if ((abs(dx) > 3) || (abs(dy) > 3)) {
|
||||
has_action = true;
|
||||
|
||||
if ( usb_hid.ready() )
|
||||
{
|
||||
if (usb_hid.ready()) {
|
||||
usb_hid.mouseMove(RID_MOUSE, dx, dy); // no ID: right + down
|
||||
|
||||
last_x = x;
|
||||
|
|
@ -114,31 +113,27 @@ void loop()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------- Keyboard -------------*/
|
||||
// button is active low, invert read value for convenience
|
||||
uint32_t buttons = ~ss.digitalReadBulk(button_mask);
|
||||
|
||||
if ( usb_hid.ready() )
|
||||
{
|
||||
if (usb_hid.ready()) {
|
||||
// use to prevent sending multiple consecutive zero report
|
||||
static bool has_key = false;
|
||||
|
||||
if ( buttons & button_mask )
|
||||
{
|
||||
if (buttons & button_mask) {
|
||||
has_action = true;
|
||||
has_key = true;
|
||||
|
||||
uint8_t keycode[6] = { 0 };
|
||||
|
||||
if ( buttons & (1 << BUTTON_A) ) keycode[0] = HID_KEY_A;
|
||||
if ( buttons & (1 << BUTTON_B) ) keycode[0] = HID_KEY_B;
|
||||
if ( buttons & (1 << BUTTON_X) ) keycode[0] = HID_KEY_X;
|
||||
if ( buttons & (1 << BUTTON_Y) ) keycode[0] = HID_KEY_Y;
|
||||
uint8_t keycode[6] = {0};
|
||||
|
||||
if (buttons & (1 << BUTTON_A)) keycode[0] = HID_KEY_A;
|
||||
if (buttons & (1 << BUTTON_B)) keycode[0] = HID_KEY_B;
|
||||
if (buttons & (1 << BUTTON_X)) keycode[0] = HID_KEY_X;
|
||||
if (buttons & (1 << BUTTON_Y)) keycode[0] = HID_KEY_Y;
|
||||
|
||||
usb_hid.keyboardReport(RID_KEYBOARD, 0, keycode);
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
// send empty key report if previously has key pressed
|
||||
if (has_key) usb_hid.keyboardRelease(RID_KEYBOARD);
|
||||
has_key = false;
|
||||
|
|
@ -147,10 +142,28 @@ void loop()
|
|||
|
||||
/*------------- Remote Wakeup -------------*/
|
||||
// Remote wakeup if PC is suspended and we has user interaction with joy feather wing
|
||||
if ( has_action && TinyUSBDevice.suspended() )
|
||||
{
|
||||
if (has_action && TinyUSBDevice.suspended()) {
|
||||
// Wake up only works if REMOTE_WAKEUP feature is enable by host
|
||||
// Usually this is the case with Mouse/Keyboard device
|
||||
TinyUSBDevice.remoteWakeup();
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
// not enumerated()/mounted() yet: nothing to do
|
||||
if (!TinyUSBDevice.mounted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// poll gpio once each 10 ms
|
||||
static uint32_t ms = 0;
|
||||
if (millis() - ms > 10) {
|
||||
ms = millis();
|
||||
process_hid();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
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
|
||||
|
|
@ -19,105 +19,135 @@
|
|||
* and its active state (when pressed) are different
|
||||
*/
|
||||
#if defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(ARDUINO_NRF52840_CIRCUITPLAY)
|
||||
const int pin = 4; // Left Button
|
||||
bool activeState = true;
|
||||
const int pin = 4; // Left Button
|
||||
bool activeState = true;
|
||||
|
||||
#elif defined(ARDUINO_FUNHOUSE_ESP32S2)
|
||||
const int pin = BUTTON_DOWN;
|
||||
bool activeState = true;
|
||||
const int pin = BUTTON_DOWN;
|
||||
bool activeState = true;
|
||||
|
||||
#elif defined PIN_BUTTON1
|
||||
const int pin = PIN_BUTTON1;
|
||||
bool activeState = false;
|
||||
const int pin = PIN_BUTTON1;
|
||||
bool activeState = false;
|
||||
|
||||
#elif defined PIN_BUTTON
|
||||
const int pin = PIN_BUTTON;
|
||||
bool activeState = false;
|
||||
const int pin = PIN_BUTTON;
|
||||
bool activeState = false;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_ESP32)
|
||||
const int pin = 0;
|
||||
bool activeState = false;
|
||||
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
const int pin = D0;
|
||||
bool activeState = false;
|
||||
#else
|
||||
const int pin = 12;
|
||||
bool activeState = false;
|
||||
|
||||
const int pin = A0;
|
||||
bool activeState = false;
|
||||
#endif
|
||||
|
||||
// HID report descriptor using TinyUSB's template
|
||||
uint8_t const desc_keyboard_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_KEYBOARD()
|
||||
uint8_t const desc_keyboard_report[] = {
|
||||
TUD_HID_REPORT_DESC_KEYBOARD()
|
||||
};
|
||||
|
||||
uint8_t const desc_mouse_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_MOUSE()
|
||||
uint8_t const desc_mouse_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
|
||||
Adafruit_USBD_HID usb_keyboard(desc_keyboard_report, sizeof(desc_keyboard_report), HID_ITF_PROTOCOL_KEYBOARD, 2, false);
|
||||
Adafruit_USBD_HID usb_mouse(desc_mouse_report, sizeof(desc_mouse_report), HID_ITF_PROTOCOL_MOUSE, 2, false);
|
||||
// USB HID objects
|
||||
Adafruit_USBD_HID usb_keyboard;
|
||||
Adafruit_USBD_HID usb_mouse;
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup()
|
||||
{
|
||||
// Notes: following commented-out functions has no affect on ESP32
|
||||
// usb_keyboard.setPollInterval(2);
|
||||
// usb_keyboard.setReportDescriptor();
|
||||
// usb_keyboard.setStringDescriptor("TinyUSB HID Composite");
|
||||
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);
|
||||
|
||||
// HID Keyboard
|
||||
usb_keyboard.setPollInterval(2);
|
||||
usb_keyboard.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD);
|
||||
usb_keyboard.setReportDescriptor(desc_keyboard_report, sizeof(desc_keyboard_report));
|
||||
usb_keyboard.setStringDescriptor("TinyUSB HID Keyboard");
|
||||
usb_keyboard.begin();
|
||||
|
||||
// HID Mouse
|
||||
usb_mouse.setPollInterval(2);
|
||||
usb_mouse.setBootProtocol(HID_ITF_PROTOCOL_MOUSE);
|
||||
usb_mouse.setReportDescriptor(desc_mouse_report, sizeof(desc_mouse_report));
|
||||
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);
|
||||
|
||||
// wait until device mounted
|
||||
//while( !TinyUSBDevice.mounted() ) delay(1);
|
||||
Serial.println("Adafruit TinyUSB HID Composite example");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// poll gpio once each 10 ms
|
||||
delay(10);
|
||||
|
||||
void process_hid() {
|
||||
// Whether button is pressed
|
||||
bool btn_pressed = (digitalRead(pin) == activeState);
|
||||
|
||||
// Remote wakeup
|
||||
if ( TinyUSBDevice.suspended() && btn_pressed )
|
||||
{
|
||||
if (TinyUSBDevice.suspended() && btn_pressed) {
|
||||
// Wake up host if we are in suspend mode
|
||||
// and REMOTE_WAKEUP feature is enabled by host
|
||||
TinyUSBDevice.remoteWakeup();
|
||||
}
|
||||
|
||||
/*------------- Mouse -------------*/
|
||||
if (usb_mouse.ready() && btn_pressed )
|
||||
{
|
||||
if (usb_mouse.ready() && btn_pressed) {
|
||||
int8_t const delta = 5;
|
||||
usb_mouse.mouseMove(0, delta, delta); // right + down
|
||||
}
|
||||
|
||||
/*------------- Keyboard -------------*/
|
||||
if ( usb_keyboard.ready() )
|
||||
{
|
||||
if (usb_keyboard.ready()) {
|
||||
// use to send key release report
|
||||
static bool has_key = false;
|
||||
|
||||
if ( btn_pressed )
|
||||
{
|
||||
uint8_t keycode[6] = { 0 };
|
||||
if (btn_pressed) {
|
||||
uint8_t keycode[6] = {0};
|
||||
keycode[0] = HID_KEY_A;
|
||||
|
||||
usb_keyboard.keyboardReport(0, 0, keycode);
|
||||
|
||||
has_key = true;
|
||||
}else
|
||||
{
|
||||
} else {
|
||||
// send empty key report if previously has key pressed
|
||||
if (has_key) usb_keyboard.keyboardRelease(0);
|
||||
has_key = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
// not enumerated()/mounted() yet: nothing to do
|
||||
if (!TinyUSBDevice.mounted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// poll gpio once each 10 ms
|
||||
static uint32_t ms = 0;
|
||||
if (millis() - ms > 10) {
|
||||
ms = millis();
|
||||
process_hid();
|
||||
}
|
||||
}
|
||||
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
|
||||
|
|
@ -22,43 +22,52 @@
|
|||
|
||||
// HID report descriptor using TinyUSB's template
|
||||
// Single Report (no ID) descriptor
|
||||
uint8_t const desc_hid_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_GAMEPAD()
|
||||
uint8_t const desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_GAMEPAD()
|
||||
};
|
||||
|
||||
// USB HID object. For ESP32 these values cannot be changed after this declaration
|
||||
// desc report, desc len, protocol, interval, use out endpoint
|
||||
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, false);
|
||||
// USB HID object
|
||||
Adafruit_USBD_HID usb_hid;
|
||||
|
||||
// Report payload defined in src/class/hid/hid.h
|
||||
// - For Gamepad Button Bit Mask see hid_gamepad_button_bm_t
|
||||
// - For Gamepad Hat Bit Mask see hid_gamepad_hat_t
|
||||
hid_gamepad_report_t gp;
|
||||
hid_gamepad_report_t gp;
|
||||
|
||||
void setup()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
#endif
|
||||
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);
|
||||
|
||||
// Notes: following commented-out functions has no affect on ESP32
|
||||
// usb_hid.setPollInterval(2);
|
||||
// usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
|
||||
|
||||
// Setup HID
|
||||
usb_hid.setPollInterval(2);
|
||||
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
|
||||
usb_hid.begin();
|
||||
|
||||
// wait until device mounted
|
||||
while( !TinyUSBDevice.mounted() ) delay(1);
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
// not enumerated()/mounted() yet: nothing to do
|
||||
if (!TinyUSBDevice.mounted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// // Remote wakeup
|
||||
// if ( TinyUSBDevice.suspended() && btn )
|
||||
// {
|
||||
|
|
@ -67,22 +76,22 @@ void loop()
|
|||
// TinyUSBDevice.remoteWakeup();
|
||||
// }
|
||||
|
||||
if ( !usb_hid.ready() ) return;
|
||||
if (!usb_hid.ready()) return;
|
||||
|
||||
// Reset buttons
|
||||
Serial.println("No pressing buttons");
|
||||
gp.x = 0;
|
||||
gp.y = 0;
|
||||
gp.z = 0;
|
||||
gp.rz = 0;
|
||||
gp.rx = 0;
|
||||
gp.ry = 0;
|
||||
gp.hat = 0;
|
||||
gp.x = 0;
|
||||
gp.y = 0;
|
||||
gp.z = 0;
|
||||
gp.rz = 0;
|
||||
gp.rx = 0;
|
||||
gp.ry = 0;
|
||||
gp.hat = 0;
|
||||
gp.buttons = 0;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
|
||||
|
||||
// Hat/DPAD UP
|
||||
Serial.println("Hat/DPAD UP");
|
||||
gp.hat = 1; // GAMEPAD_HAT_UP;
|
||||
|
|
@ -107,12 +116,12 @@ void loop()
|
|||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
// Hat/DPAD DOWN
|
||||
// Hat/DPAD DOWN
|
||||
Serial.println("Hat/DPAD DOWN");
|
||||
gp.hat = 5; // GAMEPAD_HAT_DOWN;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
|
||||
// Hat/DPAD DOWN LEFT
|
||||
Serial.println("Hat/DPAD DOWN LEFT");
|
||||
gp.hat = 6; // GAMEPAD_HAT_DOWN_LEFT;
|
||||
|
|
@ -137,14 +146,14 @@ void loop()
|
|||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
|
||||
|
||||
// Joystick 1 UP
|
||||
Serial.println("Joystick 1 UP");
|
||||
gp.x = 0;
|
||||
gp.y = -127;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
|
||||
// Joystick 1 DOWN
|
||||
Serial.println("Joystick 1 DOWN");
|
||||
gp.x = 0;
|
||||
|
|
@ -158,7 +167,7 @@ void loop()
|
|||
gp.y = 0;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
|
||||
// Joystick 1 LEFT
|
||||
Serial.println("Joystick 1 LEFT");
|
||||
gp.x = -127;
|
||||
|
|
@ -176,35 +185,35 @@ void loop()
|
|||
|
||||
// Joystick 2 UP
|
||||
Serial.println("Joystick 2 UP");
|
||||
gp.z = 0;
|
||||
gp.z = 0;
|
||||
gp.rz = 127;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
|
||||
// Joystick 2 DOWN
|
||||
Serial.println("Joystick 2 DOWN");
|
||||
gp.z = 0;
|
||||
gp.z = 0;
|
||||
gp.rz = -127;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
// Joystick 2 RIGHT
|
||||
Serial.println("Joystick 2 RIGHT");
|
||||
gp.z = 127;
|
||||
gp.z = 127;
|
||||
gp.rz = 0;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
|
||||
// Joystick 2 LEFT
|
||||
Serial.println("Joystick 2 LEFT");
|
||||
gp.z = -127;
|
||||
gp.z = -127;
|
||||
gp.rz = 0;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
// Joystick 2 CENTER
|
||||
Serial.println("Joystick 2 CENTER");
|
||||
gp.z = 0;
|
||||
gp.z = 0;
|
||||
gp.rz = 0;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
|
@ -215,7 +224,7 @@ void loop()
|
|||
gp.rx = 127;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
|
||||
// Analog Trigger 1 DOWN
|
||||
Serial.println("Analog Trigger 1 DOWN");
|
||||
gp.rx = -127;
|
||||
|
|
@ -234,7 +243,7 @@ void loop()
|
|||
gp.ry = 127;
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
|
||||
// Analog Trigger 2 DOWN
|
||||
Serial.println("Analog Trigger 2 DOWN");
|
||||
gp.ry = -127;
|
||||
|
|
@ -247,11 +256,11 @@ void loop()
|
|||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
||||
|
||||
|
||||
// Test buttons (up to 32 buttons)
|
||||
for (int i=0; i<32; ++i)
|
||||
{
|
||||
Serial.print("Pressing button "); Serial.println(i);
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
Serial.print("Pressing button ");
|
||||
Serial.println(i);
|
||||
gp.buttons = (1U << i);
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(1000);
|
||||
|
|
@ -260,13 +269,13 @@ void loop()
|
|||
|
||||
// Random touch
|
||||
Serial.println("Random touch");
|
||||
gp.x = random(-127, 128);
|
||||
gp.y = random(-127, 128);
|
||||
gp.z = random(-127, 128);
|
||||
gp.rz = random(-127, 128);
|
||||
gp.rx = random(-127, 128);
|
||||
gp.ry = random(-127, 128);
|
||||
gp.hat = random(0, 9);
|
||||
gp.x = random(-127, 128);
|
||||
gp.y = random(-127, 128);
|
||||
gp.z = random(-127, 128);
|
||||
gp.rz = random(-127, 128);
|
||||
gp.rx = random(-127, 128);
|
||||
gp.ry = random(-127, 128);
|
||||
gp.hat = random(0, 9);
|
||||
gp.buttons = random(0, 0xffff);
|
||||
usb_hid.sendReport(0, &gp, sizeof(gp));
|
||||
delay(2000);
|
||||
|
|
|
|||
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
|
||||
|
|
@ -39,50 +39,51 @@
|
|||
|
||||
// HID report descriptor using TinyUSB's template
|
||||
// Generic In Out with 64 bytes report (max)
|
||||
uint8_t const desc_hid_report[] =
|
||||
{
|
||||
TUD_HID_REPORT_DESC_GENERIC_INOUT(64)
|
||||
uint8_t const desc_hid_report[] = {
|
||||
TUD_HID_REPORT_DESC_GENERIC_INOUT(64)
|
||||
};
|
||||
|
||||
// USB HID object. For ESP32 these values cannot be changed after this declaration
|
||||
// desc report, desc len, protocol, interval, use out endpoint
|
||||
Adafruit_USBD_HID usb_hid(desc_hid_report, sizeof(desc_hid_report), HID_ITF_PROTOCOL_NONE, 2, true);
|
||||
// USB HID object
|
||||
Adafruit_USBD_HID usb_hid;
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
#endif
|
||||
|
||||
// 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();
|
||||
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);
|
||||
|
||||
// wait until device mounted
|
||||
while( !TinyUSBDevice.mounted() ) delay(1);
|
||||
// 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();
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// nothing to do
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Invoked when received GET_REPORT control request
|
||||
// Application must fill buffer report's content and return its length.
|
||||
// Return zero will cause the stack to STALL request
|
||||
uint16_t get_report_callback (uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
|
||||
{
|
||||
uint16_t get_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) {
|
||||
// not used in this example
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
|
|
@ -93,8 +94,7 @@ uint16_t get_report_callback (uint8_t report_id, hid_report_type_t report_type,
|
|||
|
||||
// Invoked when received SET_REPORT control request or
|
||||
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
|
||||
void set_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
|
||||
{
|
||||
void set_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) {
|
||||
// This example doesn't use multiple report and report ID
|
||||
(void) report_id;
|
||||
(void) report_type;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ dev_info_t dev_info[CFG_TUH_DEVICE_MAX] = { 0 };
|
|||
|
||||
Adafruit_USBH_Host USBHost;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// setup() & loop()
|
||||
//--------------------------------------------------------------------+
|
||||
void setup() {
|
||||
Serial1.begin(115200);
|
||||
Serial1.println("TinyUSB Host: Device Info Example");
|
||||
|
|
@ -63,7 +66,6 @@ void setup() {
|
|||
USBHost.begin(0);
|
||||
}
|
||||
|
||||
//------------- Core0 -------------//
|
||||
void loop() {
|
||||
USBHost.task();
|
||||
Serial1.flush();
|
||||
|
|
|
|||
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,28 +19,43 @@
|
|||
// USB MIDI object with 3 ports
|
||||
Adafruit_USBD_MIDI usb_midi(3);
|
||||
|
||||
void setup()
|
||||
{
|
||||
void setup() {
|
||||
#ifdef LED_BUILTIN
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
#endif
|
||||
|
||||
// Manual begin() is required on core without built-in support e.g. mbed rp2040
|
||||
if (!TinyUSBDevice.isInitialized()) {
|
||||
TinyUSBDevice.begin(0);
|
||||
}
|
||||
|
||||
// Set name for each cable, must be done before usb_midi.begin()
|
||||
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()
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
delay(1000);
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
delay(1000);
|
||||
// toggle LED
|
||||
static uint32_t ms = 0;
|
||||
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
|
||||
|
|
@ -31,65 +31,74 @@ uint32_t position = 0;
|
|||
|
||||
// Store example melody as an array of note values
|
||||
byte note_sequence[] = {
|
||||
74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78,
|
||||
74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61,
|
||||
56,61,64,68,74,78,81,86,90,93,98,102
|
||||
74, 78, 81, 86, 90, 93, 98, 102, 57, 61, 66, 69, 73, 78, 81, 85, 88, 92, 97, 100, 97, 92, 88, 85, 81, 78,
|
||||
74, 69, 66, 62, 57, 62, 66, 69, 74, 78, 81, 86, 90, 93, 97, 102, 97, 93, 90, 85, 81, 78, 73, 68, 64, 61,
|
||||
56, 61, 64, 68, 74, 78, 81, 86, 90, 93, 98, 102
|
||||
};
|
||||
|
||||
void setup()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
#endif
|
||||
void setup() {
|
||||
// Manual begin() is required on core without built-in support e.g. mbed rp2040
|
||||
if (!TinyUSBDevice.isInitialized()) {
|
||||
TinyUSBDevice.begin(0);
|
||||
}
|
||||
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
//usb_midi.setStringDescriptor("TinyUSB MIDI");
|
||||
Serial.begin(115200);
|
||||
|
||||
usb_midi.setStringDescriptor("TinyUSB MIDI");
|
||||
|
||||
// Initialize MIDI, and listen to all MIDI channels
|
||||
// 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);
|
||||
|
||||
// wait until device mounted
|
||||
while( !TinyUSBDevice.mounted() ) delay(1);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
// not enumerated()/mounted() yet: nothing to do
|
||||
if (!TinyUSBDevice.mounted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
static uint32_t start_ms = 0;
|
||||
if ( millis() - start_ms > 266 )
|
||||
{
|
||||
if (millis() - start_ms > 266) {
|
||||
start_ms += 266;
|
||||
|
||||
|
||||
// Setup variables for the current and previous
|
||||
// positions in the note sequence.
|
||||
int previous = position - 1;
|
||||
|
||||
|
||||
// If we currently are at position 0, set the
|
||||
// previous position to the last note in the sequence.
|
||||
if (previous < 0) {
|
||||
previous = sizeof(note_sequence) - 1;
|
||||
}
|
||||
|
||||
|
||||
// Send Note On for current position at full velocity (127) on channel 1.
|
||||
MIDI.sendNoteOn(note_sequence[position], 127, 1);
|
||||
|
||||
|
||||
// Send Note Off for previous note.
|
||||
MIDI.sendNoteOff(note_sequence[previous], 0, 1);
|
||||
|
||||
|
||||
// Increment position
|
||||
position++;
|
||||
|
||||
|
||||
// If we are at the end of the sequence, start over.
|
||||
if (position >= sizeof(note_sequence)) {
|
||||
position = 0;
|
||||
|
|
@ -97,11 +106,10 @@ void loop()
|
|||
}
|
||||
|
||||
// read any new MIDI messages
|
||||
MIDI.read();
|
||||
MIDI.read();
|
||||
}
|
||||
|
||||
void handleNoteOn(byte channel, byte pitch, byte velocity)
|
||||
{
|
||||
void handleNoteOn(byte channel, byte pitch, byte velocity) {
|
||||
// Log when a note is pressed.
|
||||
Serial.print("Note on: channel = ");
|
||||
Serial.print(channel);
|
||||
|
|
@ -113,8 +121,7 @@ void handleNoteOn(byte channel, byte pitch, byte velocity)
|
|||
Serial.println(velocity);
|
||||
}
|
||||
|
||||
void handleNoteOff(byte channel, byte pitch, byte velocity)
|
||||
{
|
||||
void handleNoteOff(byte channel, byte pitch, byte velocity) {
|
||||
// Log when a note is released.
|
||||
Serial.print("Note off: channel = ");
|
||||
Serial.print(channel);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3
examples/MassStorage/msc_external_flash/.skip.txt
Normal file
3
examples/MassStorage/msc_external_flash/.skip.txt
Normal file
|
|
@ -0,0 +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
|
||||
}
|
||||
|
|
|
|||
3
examples/MassStorage/msc_external_flash_sdcard/.skip.txt
Normal file
3
examples/MassStorage/msc_external_flash_sdcard/.skip.txt
Normal file
|
|
@ -0,0 +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;
|
||||
}
|
||||
|
|
|
|||
2
examples/MassStorage/msc_ramdisk/.skip.txt
Normal file
2
examples/MassStorage/msc_ramdisk/.skip.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
// 8KB is the smallest size that windows allow to mount
|
||||
#define DISK_BLOCK_NUM 16
|
||||
#define DISK_BLOCK_SIZE 512
|
||||
|
||||
#include "ramdisk.h"
|
||||
|
||||
Adafruit_USBD_MSC usb_msc;
|
||||
|
|
@ -36,10 +37,15 @@ Adafruit_USBD_MSC usb_msc;
|
|||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup() {
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as
|
||||
// - mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
// Manual begin() is required on core without built-in support e.g. mbed rp2040
|
||||
if (!TinyUSBDevice.isInitialized()) {
|
||||
TinyUSBDevice.begin(0);
|
||||
}
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
#ifdef BTN_EJECT
|
||||
pinMode(BTN_EJECT, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
|
||||
|
|
@ -50,33 +56,35 @@ void setup() {
|
|||
|
||||
// Set callback
|
||||
usb_msc.setReadWriteCallback(msc_read_callback, msc_write_callback, msc_flush_callback);
|
||||
usb_msc.setStartStopCallback(msc_start_stop_callback);
|
||||
usb_msc.setReadyCallback(msc_ready_callback);
|
||||
|
||||
// Set Lun ready (RAM disk is always ready)
|
||||
usb_msc.setUnitReady(true);
|
||||
|
||||
#ifdef BTN_EJECT
|
||||
pinMode(BTN_EJECT, activeState ? INPUT_PULLDOWN : INPUT_PULLUP);
|
||||
usb_msc.setReadyCallback(msc_ready_callback);
|
||||
#endif
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// nothing to do
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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) {
|
||||
uint8_t const* addr = msc_disk[lba];
|
||||
memcpy(buffer, addr, bufsize);
|
||||
|
||||
|
|
@ -86,8 +94,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) {
|
||||
uint8_t* addr = msc_disk[lba];
|
||||
memcpy(addr, buffer, bufsize);
|
||||
|
||||
|
|
@ -96,18 +103,22 @@ 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) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
bool msc_start_stop_callback(uint8_t power_condition, bool start, bool load_eject) {
|
||||
Serial.printf("Start/Stop callback: power condition %u, start %u, load_eject %u\n", power_condition, start, load_eject);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef BTN_EJECT
|
||||
// Invoked when received Test Unit Ready command.
|
||||
// return true allowing host to read/write this LUN e.g SD card inserted
|
||||
bool msc_ready_callback(void)
|
||||
{
|
||||
bool msc_ready_callback(void) {
|
||||
#ifdef BTN_EJECT
|
||||
// button not active --> medium ready
|
||||
return digitalRead(BTN_EJECT) != activeState;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
3
examples/MassStorage/msc_ramdisk_dual/.skip.txt
Normal file
3
examples/MassStorage/msc_ramdisk_dual/.skip.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
@ -14,20 +14,22 @@
|
|||
// 8KB is the smallest size that windows allow to mount
|
||||
#define DISK_BLOCK_NUM 16
|
||||
#define DISK_BLOCK_SIZE 512
|
||||
|
||||
#include "ramdisk.h"
|
||||
|
||||
Adafruit_USBD_MSC usb_msc;
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
#endif
|
||||
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);
|
||||
|
||||
usb_msc.setMaxLun(2);
|
||||
|
||||
|
||||
// Set disk size and callback for Logical Unit 0 (LUN 0)
|
||||
usb_msc.setID(0, "Adafruit", "Lun0", "1.0");
|
||||
usb_msc.setCapacity(0, DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
|
||||
|
|
@ -39,18 +41,25 @@ void setup()
|
|||
usb_msc.setCapacity(1, DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
|
||||
usb_msc.setReadWriteCallback(1, ram1_read_cb, ram1_write_cb, ram1_flush_cb);
|
||||
usb_msc.setUnitReady(1, 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 Dual RAM Disks example");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// nothing to do
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -61,8 +70,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 ram0_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
|
||||
{
|
||||
int32_t ram0_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
|
||||
uint8_t const* addr = msc_disk0[lba];
|
||||
memcpy(buffer, addr, bufsize);
|
||||
|
||||
|
|
@ -72,8 +80,7 @@ int32_t ram0_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 ram0_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
|
||||
{
|
||||
int32_t ram0_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
|
||||
uint8_t* addr = msc_disk0[lba];
|
||||
memcpy(addr, buffer, bufsize);
|
||||
|
||||
|
|
@ -82,8 +89,7 @@ int32_t ram0_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 ram0_flush_cb (void)
|
||||
{
|
||||
void ram0_flush_cb(void) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
|
@ -95,8 +101,7 @@ void ram0_flush_cb (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 ram1_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
|
||||
{
|
||||
int32_t ram1_read_cb(uint32_t lba, void* buffer, uint32_t bufsize) {
|
||||
uint8_t const* addr = msc_disk1[lba];
|
||||
memcpy(buffer, addr, bufsize);
|
||||
|
||||
|
|
@ -106,8 +111,7 @@ int32_t ram1_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 ram1_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
|
||||
{
|
||||
int32_t ram1_write_cb(uint32_t lba, uint8_t* buffer, uint32_t bufsize) {
|
||||
uint8_t* addr = msc_disk1[lba];
|
||||
memcpy(addr, buffer, bufsize);
|
||||
|
||||
|
|
@ -116,7 +120,6 @@ int32_t ram1_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 ram1_flush_cb (void)
|
||||
{
|
||||
void ram1_flush_cb(void) {
|
||||
// nothing to do
|
||||
}
|
||||
|
|
|
|||
10
examples/MassStorage/msc_sd/.skip.txt
Normal file
10
examples/MassStorage/msc_sd/.skip.txt
Normal file
|
|
@ -0,0 +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
|
||||
}
|
||||
|
|
|
|||
2
examples/MassStorage/msc_sdfat/.skip.txt
Normal file
2
examples/MassStorage/msc_sdfat/.skip.txt
Normal file
|
|
@ -0,0 +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
|
||||
}
|
||||
|
|
|
|||
3
examples/Vendor/i2c_tiny_usb_adapter/.skip.txt
vendored
Normal file
3
examples/Vendor/i2c_tiny_usb_adapter/.skip.txt
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
|
|
@ -64,15 +64,29 @@ Adafruit_USBD_I2C::Adafruit_USBD_I2C(TwoWire* wire) {
|
|||
setStringDescriptor("I2C Interface");
|
||||
}
|
||||
|
||||
uint16_t Adafruit_USBD_I2C::getInterfaceDescriptor(uint8_t itfnum, uint8_t* buf, uint16_t bufsize) {
|
||||
uint8_t desc[] = { TUD_VENDOR_DESCRIPTOR(itfnum, 0, 0x00, 0x80, 64) };
|
||||
uint16_t Adafruit_USBD_I2C::getInterfaceDescriptor(uint8_t itfnum_deprecated, uint8_t* buf, uint16_t bufsize) {
|
||||
uint8_t itfnum = 0;
|
||||
uint8_t ep_in = 0;
|
||||
uint8_t ep_out = 0;
|
||||
(void) itfnum_deprecated;
|
||||
|
||||
// null buffer is used to get the length of descriptor only
|
||||
if (buf) {
|
||||
itfnum = TinyUSBDevice.allocInterface(1);
|
||||
ep_in = TinyUSBDevice.allocEndpoint(TUSB_DIR_IN);
|
||||
ep_out = TinyUSBDevice.allocEndpoint(TUSB_DIR_OUT);
|
||||
}
|
||||
|
||||
uint8_t const desc[] = { TUD_VENDOR_DESCRIPTOR(itfnum, _strid, ep_out, ep_in, 64) };
|
||||
uint16_t const len = sizeof(desc);
|
||||
|
||||
if (buf) {
|
||||
if (bufsize < len) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(buf, desc, len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,11 +88,13 @@
|
|||
class Adafruit_USBD_I2C : public Adafruit_USBD_Interface {
|
||||
public:
|
||||
Adafruit_USBD_I2C(TwoWire* wire);
|
||||
uint16_t getInterfaceDescriptor(uint8_t itfnum, uint8_t* buf, uint16_t bufsize);
|
||||
bool begin(uint8_t* buffer, size_t bufsize);
|
||||
|
||||
bool handleControlTransfer(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request);
|
||||
|
||||
// from Adafruit_USBD_Interface
|
||||
virtual uint16_t getInterfaceDescriptor(uint8_t itfnum, uint8_t* buf, uint16_t bufsize);
|
||||
|
||||
private:
|
||||
TwoWire* _wire;
|
||||
uint8_t _state;
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
3
examples/Video/video_capture/.skip.txt
Normal file
3
examples/Video/video_capture/.skip.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
237
examples/Video/video_capture/video_capture.ino
Normal file
237
examples/Video/video_capture/video_capture.ino
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
/*********************************************************************
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
MIT license, check LICENSE for more information
|
||||
Copyright (c) 2019 Ha Thach for Adafruit Industries
|
||||
All text above, and the splash screen below must be included in
|
||||
any redistribution
|
||||
*********************************************************************/
|
||||
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Video descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/* Time stamp base clock. It is a deprecated parameter. */
|
||||
#define FRAME_WIDTH 128
|
||||
#define FRAME_HEIGHT 96
|
||||
#define FRAME_RATE 30
|
||||
|
||||
/* video capture path
|
||||
*
|
||||
* | Camera Terminal (0x01) | ----> | Output Terminal (0x02 Streaming) |
|
||||
* */
|
||||
#define TERMID_CAMERA 0x01
|
||||
#define TERMID_OUTPUT 0x02
|
||||
|
||||
tusb_desc_video_control_camera_terminal_t const desc_camera_terminal = {
|
||||
.bLength = sizeof(tusb_desc_video_control_camera_terminal_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VC_INPUT_TERMINAL,
|
||||
|
||||
.bTerminalID = TERMID_CAMERA,
|
||||
.wTerminalType = VIDEO_ITT_CAMERA,
|
||||
.bAssocTerminal = 0,
|
||||
.iTerminal = 0,
|
||||
.wObjectiveFocalLengthMin = 0,
|
||||
.wObjectiveFocalLengthMax = 0,
|
||||
.wOcularFocalLength = 0,
|
||||
.bControlSize = 3,
|
||||
.bmControls = { 0, 0, 0 }
|
||||
};
|
||||
|
||||
tusb_desc_video_control_output_terminal_t const desc_output_terminal = {
|
||||
.bLength = sizeof(tusb_desc_video_control_output_terminal_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VC_OUTPUT_TERMINAL,
|
||||
|
||||
.bTerminalID = TERMID_OUTPUT,
|
||||
.wTerminalType = VIDEO_TT_STREAMING,
|
||||
.bAssocTerminal = 0,
|
||||
.bSourceID = TERMID_CAMERA,
|
||||
.iTerminal = 0
|
||||
};
|
||||
|
||||
tusb_desc_video_format_uncompressed_t const desc_format = {
|
||||
.bLength = sizeof(tusb_desc_video_format_uncompressed_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VS_FORMAT_UNCOMPRESSED,
|
||||
.bFormatIndex = 1, // 1-based index
|
||||
.bNumFrameDescriptors = 1,
|
||||
.guidFormat = { TUD_VIDEO_GUID_YUY2 },
|
||||
.bBitsPerPixel = 16,
|
||||
.bDefaultFrameIndex = 1,
|
||||
.bAspectRatioX = 0,
|
||||
.bAspectRatioY = 0,
|
||||
.bmInterlaceFlags = 0,
|
||||
.bCopyProtect = 0
|
||||
};
|
||||
|
||||
tusb_desc_video_frame_uncompressed_continuous_t desc_frame = {
|
||||
.bLength = sizeof(tusb_desc_video_frame_uncompressed_continuous_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VS_FRAME_UNCOMPRESSED,
|
||||
.bFrameIndex = 1, // 1-based index
|
||||
.bmCapabilities = 0,
|
||||
.wWidth = FRAME_WIDTH,
|
||||
.wHeight = FRAME_HEIGHT,
|
||||
.dwMinBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * 1,
|
||||
.dwMaxBitRate = FRAME_WIDTH * FRAME_HEIGHT * 16 * FRAME_RATE,
|
||||
.dwMaxVideoFrameBufferSize = FRAME_WIDTH * FRAME_HEIGHT * 16 / 8,
|
||||
.dwDefaultFrameInterval = 10000000 / FRAME_RATE,
|
||||
.bFrameIntervalType = 0, // continuous
|
||||
.dwFrameInterval = {
|
||||
10000000 / FRAME_RATE, // min
|
||||
10000000, // max
|
||||
10000000 / FRAME_RATE // step
|
||||
}
|
||||
};
|
||||
|
||||
tusb_desc_video_streaming_color_matching_t desc_color = {
|
||||
.bLength = sizeof(tusb_desc_video_streaming_color_matching_t),
|
||||
.bDescriptorType = TUSB_DESC_CS_INTERFACE,
|
||||
.bDescriptorSubType = VIDEO_CS_ITF_VS_COLORFORMAT,
|
||||
|
||||
.bColorPrimaries = VIDEO_COLOR_PRIMARIES_BT709,
|
||||
.bTransferCharacteristics = VIDEO_COLOR_XFER_CH_BT709,
|
||||
.bMatrixCoefficients = VIDEO_COLOR_COEF_SMPTE170M
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Video and frame buffer
|
||||
//--------------------------------------------------------------------+
|
||||
Adafruit_USBD_Video usb_video;
|
||||
|
||||
// YUY2 frame buffer
|
||||
static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8];
|
||||
|
||||
static unsigned frame_num = 0;
|
||||
static unsigned tx_busy = 0;
|
||||
static unsigned interval_ms = 1000 / FRAME_RATE;
|
||||
static unsigned start_ms = 0;
|
||||
static unsigned already_sent = 0;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
//
|
||||
//--------------------------------------------------------------------+
|
||||
static void fill_color_bar(uint8_t* buffer, unsigned start_position);
|
||||
|
||||
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);
|
||||
|
||||
usb_video.addTerminal(&desc_camera_terminal);
|
||||
usb_video.addTerminal(&desc_output_terminal);
|
||||
usb_video.addFormat(&desc_format);
|
||||
usb_video.addFrame(&desc_frame);
|
||||
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() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
if (!tud_video_n_streaming(0, 0)) {
|
||||
already_sent = 0;
|
||||
frame_num = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!already_sent) {
|
||||
already_sent = 1;
|
||||
tx_busy = 1;
|
||||
start_ms = millis();
|
||||
fill_color_bar(frame_buffer, frame_num);
|
||||
tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
|
||||
}
|
||||
|
||||
unsigned cur = millis();
|
||||
if (cur - start_ms < interval_ms) return; // not enough time
|
||||
if (tx_busy) return;
|
||||
start_ms += interval_ms;
|
||||
tx_busy = 1;
|
||||
|
||||
fill_color_bar(frame_buffer, frame_num);
|
||||
tud_video_n_frame_xfer(0, 0, (void*) frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TinyUSB Video Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
extern "C" {
|
||||
|
||||
void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx) {
|
||||
(void) ctl_idx;
|
||||
(void) stm_idx;
|
||||
tx_busy = 0;
|
||||
/* flip buffer */
|
||||
++frame_num;
|
||||
}
|
||||
|
||||
int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx,
|
||||
video_probe_and_commit_control_t const* parameters) {
|
||||
(void) ctl_idx;
|
||||
(void) stm_idx;
|
||||
/* convert unit to ms from 100 ns */
|
||||
interval_ms = parameters->dwFrameInterval / 10000;
|
||||
return VIDEO_ERROR_NONE;
|
||||
}
|
||||
|
||||
} // extern C
|
||||
|
||||
//------------- Helper -------------//
|
||||
static void fill_color_bar(uint8_t* buffer, unsigned start_position) {
|
||||
/* EBU color bars
|
||||
* See also https://stackoverflow.com/questions/6939422 */
|
||||
static uint8_t const bar_color[8][4] = {
|
||||
/* Y, U, Y, V */
|
||||
{ 235, 128, 235, 128}, /* 100% White */
|
||||
{ 219, 16, 219, 138}, /* Yellow */
|
||||
{ 188, 154, 188, 16}, /* Cyan */
|
||||
{ 173, 42, 173, 26}, /* Green */
|
||||
{ 78, 214, 78, 230}, /* Magenta */
|
||||
{ 63, 102, 63, 240}, /* Red */
|
||||
{ 32, 240, 32, 118}, /* Blue */
|
||||
{ 16, 128, 16, 128}, /* Black */
|
||||
};
|
||||
uint8_t* p;
|
||||
|
||||
/* Generate the 1st line */
|
||||
uint8_t* end = &buffer[FRAME_WIDTH * 2];
|
||||
unsigned idx = (FRAME_WIDTH / 2 - 1) - (start_position % (FRAME_WIDTH / 2));
|
||||
p = &buffer[idx * 4];
|
||||
for (unsigned i = 0; i < 8; ++i) {
|
||||
for (int j = 0; j < FRAME_WIDTH / (2 * 8); ++j) {
|
||||
memcpy(p, &bar_color[i], 4);
|
||||
p += 4;
|
||||
if (end <= p) {
|
||||
p = buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Duplicate the 1st line to the others */
|
||||
p = &buffer[FRAME_WIDTH * 2];
|
||||
for (unsigned i = 1; i < FRAME_HEIGHT; ++i) {
|
||||
memcpy(p, buffer, FRAME_WIDTH * 2);
|
||||
p += FRAME_WIDTH * 2;
|
||||
}
|
||||
}
|
||||
4
examples/WebUSB/webusb_rgb/.skip.txt
Normal file
4
examples/WebUSB/webusb_rgb/.skip.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
feather_esp32_v2
|
||||
pico_rp2040_tinyusb_host
|
||||
CH32V20x_EVT
|
||||
# CH32V20x_EVT is not supported due to Adafruit_Neopixel
|
||||
|
|
@ -54,18 +54,25 @@ Adafruit_USBD_WebUSB usb_web;
|
|||
WEBUSB_URL_DEF(landingPage, 1 /*https*/, "example.tinyusb.org/webusb-rgb/index.html");
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
#endif
|
||||
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);
|
||||
|
||||
//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
|
||||
|
|
@ -79,21 +86,24 @@ void setup()
|
|||
pixels.show();
|
||||
|
||||
// wait until device mounted
|
||||
while( !TinyUSBDevice.mounted() ) delay(1);
|
||||
while (!TinyUSBDevice.mounted()) delay(1);
|
||||
|
||||
Serial.println("TinyUSB WebUSB RGB example");
|
||||
}
|
||||
|
||||
// convert a hex character to number
|
||||
uint8_t char2num(char c)
|
||||
{
|
||||
uint8_t char2num(char c) {
|
||||
if (c >= 'a') return c - 'a' + 10;
|
||||
if (c >= 'A') return c - 'A' + 10;
|
||||
return c - '0';
|
||||
return c - '0';
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
// Landing Page 7 characters as hex color '#RRGGBB'
|
||||
if (usb_web.available() < 7) return;
|
||||
|
||||
|
|
@ -104,17 +114,16 @@ void loop()
|
|||
Serial.write(input, 7);
|
||||
Serial.println();
|
||||
|
||||
uint8_t red = 16*char2num(input[1]) + char2num(input[2]);
|
||||
uint8_t green = 16*char2num(input[3]) + char2num(input[4]);
|
||||
uint8_t blue = 16*char2num(input[5]) + char2num(input[6]);
|
||||
uint8_t red = 16 * char2num(input[1]) + char2num(input[2]);
|
||||
uint8_t green = 16 * char2num(input[3]) + char2num(input[4]);
|
||||
uint8_t blue = 16 * char2num(input[5]) + char2num(input[6]);
|
||||
|
||||
uint32_t color = (red << 16) | (green << 8) | blue;
|
||||
pixels.fill(color);
|
||||
pixels.show();
|
||||
}
|
||||
|
||||
void line_state_callback(bool connected)
|
||||
{
|
||||
void line_state_callback(bool connected) {
|
||||
// connected = green, disconnected = red
|
||||
pixels.fill(connected ? 0x00ff00 : 0xff0000);
|
||||
pixels.show();
|
||||
|
|
|
|||
4
examples/WebUSB/webusb_serial/.skip.txt
Normal file
4
examples/WebUSB/webusb_serial/.skip.txt
Normal file
|
|
@ -0,0 +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,78 +34,81 @@ 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()
|
||||
{
|
||||
#if defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_RP2040)
|
||||
// Manual begin() is required on core without built-in support for TinyUSB such as mbed rp2040
|
||||
TinyUSB_Device_Init(0);
|
||||
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);
|
||||
|
||||
#ifdef LED_BUILTIN
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
#endif
|
||||
|
||||
pinMode(led_pin, OUTPUT);
|
||||
digitalWrite(led_pin, LOW);
|
||||
|
||||
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);
|
||||
while (!TinyUSBDevice.mounted()) delay(1);
|
||||
|
||||
Serial.println("TinyUSB WebUSB Serial example");
|
||||
}
|
||||
|
||||
// function to echo to both Serial and WebUSB
|
||||
void echo_all(uint8_t buf[], uint32_t count)
|
||||
{
|
||||
if (usb_web.connected())
|
||||
{
|
||||
void echo_all(uint8_t buf[], uint32_t count) {
|
||||
if (usb_web.connected()) {
|
||||
usb_web.write(buf, count);
|
||||
usb_web.flush();
|
||||
}
|
||||
|
||||
if ( Serial )
|
||||
{
|
||||
for(uint32_t i=0; i<count; i++)
|
||||
{
|
||||
if (Serial) {
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
Serial.write(buf[i]);
|
||||
if ( buf[i] == '\r' ) Serial.write('\n');
|
||||
if (buf[i] == '\r') Serial.write('\n');
|
||||
}
|
||||
Serial.flush();
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
void loop() {
|
||||
#ifdef TINYUSB_NEED_POLLING_TASK
|
||||
// Manual call tud_task since it isn't called by Core's background
|
||||
TinyUSBDevice.task();
|
||||
#endif
|
||||
|
||||
uint8_t buf[64];
|
||||
uint32_t count;
|
||||
|
||||
// From Serial to both Serial & webUSB
|
||||
if (Serial.available())
|
||||
{
|
||||
if (Serial.available()) {
|
||||
count = Serial.read(buf, 64);
|
||||
echo_all(buf, count);
|
||||
}
|
||||
|
||||
// from WebUSB to both Serial & webUSB
|
||||
if (usb_web.available())
|
||||
{
|
||||
if (usb_web.available()) {
|
||||
count = usb_web.read(buf, 64);
|
||||
echo_all(buf, count);
|
||||
}
|
||||
}
|
||||
|
||||
void line_state_callback(bool connected)
|
||||
{
|
||||
digitalWrite(led_pin, connected);
|
||||
void line_state_callback(bool connected) {
|
||||
#ifdef LED_BUILTIN
|
||||
digitalWrite(LED_BUILTIN, connected);
|
||||
#endif
|
||||
|
||||
if ( connected )
|
||||
{
|
||||
if (connected) {
|
||||
usb_web.println("WebUSB interface connected !!");
|
||||
usb_web.flush();
|
||||
}
|
||||
|
|
|
|||
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,9 +1,9 @@
|
|||
name=Adafruit TinyUSB Library
|
||||
version=2.2.8
|
||||
version=3.7.1
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=TinyUSB library for Arduino
|
||||
paragraph=Support nRF5x, SAMD21, SAMD51, RP2040, ESP32-S2/S3
|
||||
paragraph=Support nRF5x, SAMD21, SAMD51, RP2040, ESP32-S2/S3, CH32V
|
||||
category=Communication
|
||||
url=https://github.com/adafruit/Adafruit_TinyUSB_Arduino
|
||||
architectures=*
|
||||
|
|
|
|||
|
|
@ -25,18 +25,6 @@
|
|||
#ifndef ADAFRUIT_TINYUSB_H_
|
||||
#define ADAFRUIT_TINYUSB_H_
|
||||
|
||||
// Error message for Core that must select TinyUSB via menu
|
||||
#if !defined(USE_TINYUSB) && \
|
||||
(defined(ARDUINO_ARCH_SAMD) || \
|
||||
(defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED)))
|
||||
#error TinyUSB is not selected, please select it in "Tools->Menu->USB Stack"
|
||||
#endif
|
||||
|
||||
// ESP32 out-of-sync
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "arduino/ports/esp32/tusb_config_esp32.h"
|
||||
#endif
|
||||
|
||||
#include "tusb_option.h"
|
||||
|
||||
// Device
|
||||
|
|
@ -64,6 +52,10 @@
|
|||
#include "arduino/webusb/Adafruit_USBD_WebUSB.h"
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_VIDEO
|
||||
#include "arduino/video/Adafruit_USBD_Video.h"
|
||||
#endif
|
||||
|
||||
// Initialize device hardware, stack, also Serial as CDC
|
||||
// Wrapper for TinyUSBDevice.begin(rhport)
|
||||
void TinyUSB_Device_Init(uint8_t rhport);
|
||||
|
|
|
|||
|
|
@ -24,17 +24,19 @@
|
|||
|
||||
#include "tusb_option.h"
|
||||
|
||||
// ESP32 will use the arduino-esp32 core initialization and Serial
|
||||
#if CFG_TUD_ENABLED && !defined(ARDUINO_ARCH_ESP32)
|
||||
#if CFG_TUD_ENABLED || CFG_TUH_ENABLED
|
||||
|
||||
#include "Adafruit_TinyUSB.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
extern "C" {
|
||||
|
||||
uint32_t tusb_time_millis_api(void) { return millis(); }
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device
|
||||
//--------------------------------------------------------------------+
|
||||
#if CFG_TUD_ENABLED
|
||||
void TinyUSB_Device_Init(uint8_t rhport) {
|
||||
// Init USB Device controller and stack
|
||||
TinyUSBDevice.begin(rhport);
|
||||
|
|
@ -48,18 +50,24 @@ void TinyUSB_Device_Task(void) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
void TinyUSB_Device_FlushCDC(void) {
|
||||
uint8_t const cdc_instance = Adafruit_USBD_CDC::getInstanceCount();
|
||||
for (uint8_t instance = 0; instance < cdc_instance; instance++) {
|
||||
tud_cdc_n_write_flush(instance);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // CFG_TUD_ENABLED
|
||||
|
||||
// Debug log with Serial1
|
||||
#if CFG_TUSB_DEBUG && defined(CFG_TUSB_DEBUG_PRINTF)
|
||||
//------------- Debug log with Serial1 -------------//
|
||||
#if CFG_TUSB_DEBUG && defined(CFG_TUSB_DEBUG_PRINTF) && \
|
||||
!defined(ARDUINO_ARCH_ESP32)
|
||||
|
||||
// #define USE_SEGGER_RTT
|
||||
#ifndef SERIAL_TUSB_DEBUG
|
||||
#define SERIAL_TUSB_DEBUG Serial1
|
||||
#endif
|
||||
|
||||
#ifdef USE_SEGGER_RTT
|
||||
#include "SEGGER_RTT/RTT/SEGGER_RTT.h"
|
||||
|
|
@ -88,8 +96,8 @@ __attribute__((used)) int CFG_TUSB_DEBUG_PRINTF(const char *__restrict format,
|
|||
va_end(ap);
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
#endif // CFG_TUSB_DEBUG
|
||||
|
||||
} // extern C
|
||||
|
||||
#endif
|
||||
#endif // CFG_TUD_ENABLED || CFG_TUH_ENABLED
|
||||
|
|
|
|||
|
|
@ -30,7 +30,25 @@
|
|||
|
||||
// API Version, need to be updated when there is changes for
|
||||
// TinyUSB_API, USBD_CDC, USBD_Device, USBD_Interface,
|
||||
#define TINYUSB_API_VERSION 20000
|
||||
#define TINYUSB_API_VERSION 30000
|
||||
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_NRF52_ADAFRUIT) || \
|
||||
defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_CH32) || \
|
||||
(defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_ARCH_MBED))
|
||||
#define TINYUSB_HAS_BUITLTIN_CORE_SUPPORT
|
||||
#endif
|
||||
|
||||
// Core that has built-in support: Adafruit SAMD, Adafruit nRF, rp2040, esp32
|
||||
#if !defined(TINYUSB_HAS_BUITLTIN_CORE_SUPPORT)
|
||||
#define TINYUSB_NEED_POLLING_TASK
|
||||
#endif
|
||||
|
||||
// Error message for Core that must select TinyUSB via menu (built-in except
|
||||
// esp32)
|
||||
#if !defined(USE_TINYUSB) && (defined(TINYUSB_HAS_BUITLTIN_CORE_SUPPORT) && \
|
||||
!defined(ARDUINO_ARCH_ESP32))
|
||||
#error TinyUSB is not selected, please select it in "Tools->Menu->USB Stack"
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Core API
|
||||
|
|
|
|||
|
|
@ -46,21 +46,44 @@ Adafruit_USBD_CDC::Adafruit_USBD_CDC(void) { _instance = INVALID_INSTANCE; }
|
|||
|
||||
#if CFG_TUD_ENABLED
|
||||
|
||||
#define EPOUT 0x00
|
||||
#define EPIN 0x80
|
||||
|
||||
uint16_t Adafruit_USBD_CDC::getInterfaceDescriptor(uint8_t itfnum, uint8_t *buf,
|
||||
uint16_t Adafruit_USBD_CDC::getInterfaceDescriptor(uint8_t itfnum_deprecated,
|
||||
uint8_t *buf,
|
||||
uint16_t bufsize) {
|
||||
// CDC is mostly always existed for DFU
|
||||
// usb core will automatically update endpoint number
|
||||
uint8_t desc[] = {TUD_CDC_DESCRIPTOR(itfnum, 0, EPIN, 8, EPOUT, EPIN, 64)};
|
||||
uint16_t const len = sizeof(desc);
|
||||
(void)itfnum_deprecated;
|
||||
|
||||
if (bufsize < len) {
|
||||
return 0;
|
||||
// CDC is mostly always existed for DFU
|
||||
uint8_t itfnum = 0;
|
||||
uint8_t ep_notif = 0;
|
||||
uint8_t ep_in = 0;
|
||||
uint8_t ep_out = 0;
|
||||
|
||||
if (buf) {
|
||||
itfnum = TinyUSBDevice.allocInterface(2);
|
||||
ep_notif = TinyUSBDevice.allocEndpoint(TUSB_DIR_IN);
|
||||
ep_in = TinyUSBDevice.allocEndpoint(TUSB_DIR_IN);
|
||||
ep_out = TinyUSBDevice.allocEndpoint(TUSB_DIR_OUT);
|
||||
}
|
||||
|
||||
#if TINYUSB_API_VERSION < 20400
|
||||
// backward compatible for core that include pre-2.4.0 TinyUSB
|
||||
uint8_t _strid = 0;
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
// null buffer is used to get the length of descriptor only
|
||||
if (buf) {
|
||||
if (bufsize < len) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(buf, desc, len);
|
||||
}
|
||||
|
||||
memcpy(buf, desc, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
|
@ -266,11 +289,12 @@ void tud_cdc_line_state_cb(uint8_t instance, bool dtr, bool rts) {
|
|||
#else
|
||||
|
||||
// Device stack is not enabled (probably in host mode)
|
||||
#warning "NO_USB selected. No output to Serial will occur!"
|
||||
#warning "TinyUSB Host selected. No output to Serial will occur!"
|
||||
|
||||
uint16_t Adafruit_USBD_CDC::getInterfaceDescriptor(uint8_t itfnum, uint8_t *buf,
|
||||
uint16_t Adafruit_USBD_CDC::getInterfaceDescriptor(uint8_t itfnum_deprecated,
|
||||
uint8_t *buf,
|
||||
uint16_t bufsize) {
|
||||
(void)itfnum;
|
||||
(void)itfnum_deprecated;
|
||||
(void)buf;
|
||||
(void)bufsize;
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
// For ESP32 use USBCDC as it is compatible
|
||||
#define Adafruit_USBD_CDC USBCDC
|
||||
#define SerialTinyUSB Serial
|
||||
|
||||
#else
|
||||
|
||||
|
|
@ -45,10 +46,6 @@ public:
|
|||
|
||||
static uint8_t getInstanceCount(void) { return _instance_count; }
|
||||
|
||||
// from Adafruit_USBD_Interface
|
||||
virtual uint16_t getInterfaceDescriptor(uint8_t itfnum, uint8_t *buf,
|
||||
uint16_t bufsize);
|
||||
|
||||
void setPins(uint8_t pin_rx, uint8_t pin_tx) {
|
||||
(void)pin_rx;
|
||||
(void)pin_tx;
|
||||
|
|
@ -83,6 +80,10 @@ public:
|
|||
using Print::write; // pull in write(str) from Print
|
||||
operator bool();
|
||||
|
||||
// from Adafruit_USBD_Interface
|
||||
virtual uint16_t getInterfaceDescriptor(uint8_t itfnum_deprecated,
|
||||
uint8_t *buf, uint16_t bufsize);
|
||||
|
||||
private:
|
||||
enum { INVALID_INSTANCE = 0xffu };
|
||||
static uint8_t _instance_count;
|
||||
|
|
@ -92,16 +93,15 @@ private:
|
|||
bool isValid(void) { return _instance != INVALID_INSTANCE; }
|
||||
};
|
||||
|
||||
// "Serial" is used with TinyUSB CDC
|
||||
#if defined(USE_TINYUSB)
|
||||
extern Adafruit_USBD_CDC Serial;
|
||||
extern Adafruit_USBD_CDC SerialTinyUSB;
|
||||
|
||||
// Built-in support "Serial" is assigned to TinyUSB CDC
|
||||
// CH32 defines Serial as alias in WSerial.h
|
||||
#if defined(USE_TINYUSB) && !defined(ARDUINO_ARCH_CH32)
|
||||
#define SerialTinyUSB Serial
|
||||
#endif
|
||||
|
||||
// Serial is probably used with HW Uart
|
||||
#ifndef SerialTinyUSB
|
||||
extern Adafruit_USBD_CDC SerialTinyUSB;
|
||||
#endif
|
||||
|
||||
#endif // else of ESP32
|
||||
#endif // __cplusplus
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue