Skip to content

Commit 2614d98

Browse files
authored
Merge pull request #2695 from adafruit/usb_host_featherwing_factoryTest
Usb host featherwing factory test
2 parents b9a7ca0 + 22a1e03 commit 2614d98

File tree

4 files changed

+252
-1
lines changed

4 files changed

+252
-1
lines changed

Factory_Tests/USB_Host_FeatherWing/.feather_esp32s2_tft.test.only

Whitespace-only changes.
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
// SPDX-FileCopyrightText: 2023 Limor Fried for Adafruit Industries
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
#include "Adafruit_TinyUSB.h"
6+
#include "Adafruit_ST7789.h"
7+
8+
// USB Host using MAX3421E: SPI, CS, INT
9+
Adafruit_USBH_Host USBHost(&SPI, 10, 9);
10+
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);
11+
void display_device_descriptor(tuh_xfer_t *xfer);
12+
13+
#define LANGUAGE_ID 0x0409
14+
15+
typedef struct {
16+
tusb_desc_device_t desc_device;
17+
uint16_t manufacturer[32];
18+
uint16_t product[48];
19+
uint16_t serial[16];
20+
bool mounted;
21+
} dev_info_t;
22+
23+
// CFG_TUH_DEVICE_MAX is defined by tusb_config header
24+
dev_info_t dev_info[CFG_TUH_DEVICE_MAX] = { 0 };
25+
26+
void setup() {
27+
Serial.begin(115200);
28+
//while ( !Serial ) delay(10); // wait for native usb
29+
30+
pinMode(TFT_BACKLITE, OUTPUT);
31+
digitalWrite(TFT_BACKLITE, HIGH);
32+
33+
// turn on the TFT / I2C power supply
34+
pinMode(TFT_I2C_POWER, OUTPUT);
35+
digitalWrite(TFT_I2C_POWER, HIGH);
36+
delay(10);
37+
38+
tft.init(135, 240); // Init ST7789 240x135
39+
tft.setRotation(3);
40+
tft.fillScreen(ST77XX_BLUE);
41+
digitalWrite(TFT_BACKLITE, HIGH);
42+
43+
Serial.println("TinyUSB USB Host FeatherWing Tester");
44+
45+
USBHost.begin(1);
46+
47+
// FeatherWing USB Host use MAX3421E's GPIO0 as VBUS enable (active high)
48+
USBHost.max3421_writeIOPINS1(0x01, false);
49+
}
50+
51+
52+
void loop() {
53+
USBHost.task();
54+
Serial.flush();
55+
}
56+
57+
58+
//--------------------------------------------------------------------+
59+
// TinyUSB Host callbacks
60+
//--------------------------------------------------------------------+
61+
void print_device_descriptor(tuh_xfer_t *xfer);
62+
63+
void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len);
64+
65+
void print_lsusb(void) {
66+
bool no_device = true;
67+
for (uint8_t daddr = 1; daddr < CFG_TUH_DEVICE_MAX + 1; daddr++) {
68+
// TODO can use tuh_mounted(daddr), but tinyusb has an bug
69+
// use local connected flag instead
70+
dev_info_t *dev = &dev_info[daddr - 1];
71+
if (dev->mounted) {
72+
Serial.printf("Device %u: ID %04x:%04x %s %s\r\n", daddr,
73+
dev->desc_device.idVendor, dev->desc_device.idProduct,
74+
(char *) dev->manufacturer, (char *) dev->product);
75+
76+
no_device = false;
77+
}
78+
}
79+
80+
if (no_device) {
81+
Serial.println("No device connected (except hub)");
82+
}
83+
}
84+
85+
// Invoked when device is mounted (configured)
86+
void tuh_mount_cb(uint8_t daddr) {
87+
Serial.printf("Device attached, address = %d\r\n", daddr);
88+
89+
dev_info_t *dev = &dev_info[daddr - 1];
90+
dev->mounted = true;
91+
92+
// Get Device Descriptor
93+
tuh_descriptor_get_device(daddr, &dev->desc_device, 18, print_device_descriptor, 0);
94+
}
95+
96+
/// Invoked when device is unmounted (bus reset/unplugged)
97+
void tuh_umount_cb(uint8_t daddr) {
98+
Serial.printf("Device removed, address = %d\r\n", daddr);
99+
dev_info_t *dev = &dev_info[daddr - 1];
100+
dev->mounted = false;
101+
102+
// print device summary
103+
print_lsusb();
104+
tft.fillScreen(ST77XX_BLACK); // Clear the screen
105+
}
106+
107+
void print_device_descriptor(tuh_xfer_t *xfer) {
108+
if (XFER_RESULT_SUCCESS != xfer->result) {
109+
Serial.printf("Failed to get device descriptor\r\n");
110+
return;
111+
}
112+
113+
uint8_t const daddr = xfer->daddr;
114+
dev_info_t *dev = &dev_info[daddr - 1];
115+
tusb_desc_device_t *desc = &dev->desc_device;
116+
117+
Serial.printf("Device %u: ID %04x:%04x\r\n", daddr, desc->idVendor, desc->idProduct);
118+
Serial.printf("Device Descriptor:\r\n");
119+
Serial.printf(" bLength %u\r\n" , desc->bLength);
120+
Serial.printf(" bDescriptorType %u\r\n" , desc->bDescriptorType);
121+
Serial.printf(" bcdUSB %04x\r\n" , desc->bcdUSB);
122+
Serial.printf(" bDeviceClass %u\r\n" , desc->bDeviceClass);
123+
Serial.printf(" bDeviceSubClass %u\r\n" , desc->bDeviceSubClass);
124+
Serial.printf(" bDeviceProtocol %u\r\n" , desc->bDeviceProtocol);
125+
Serial.printf(" bMaxPacketSize0 %u\r\n" , desc->bMaxPacketSize0);
126+
Serial.printf(" idVendor 0x%04x\r\n" , desc->idVendor);
127+
Serial.printf(" idProduct 0x%04x\r\n" , desc->idProduct);
128+
Serial.printf(" bcdDevice %04x\r\n" , desc->bcdDevice);
129+
130+
// Get String descriptor using Sync API
131+
Serial.printf(" iManufacturer %u ", desc->iManufacturer);
132+
if (XFER_RESULT_SUCCESS ==
133+
tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, dev->manufacturer, sizeof(dev->manufacturer))) {
134+
utf16_to_utf8(dev->manufacturer, sizeof(dev->manufacturer));
135+
Serial.printf((char *) dev->manufacturer);
136+
}
137+
Serial.printf("\r\n");
138+
139+
Serial.printf(" iProduct %u ", desc->iProduct);
140+
if (XFER_RESULT_SUCCESS ==
141+
tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, dev->product, sizeof(dev->product))) {
142+
utf16_to_utf8(dev->product, sizeof(dev->product));
143+
Serial.printf((char *) dev->product);
144+
}
145+
Serial.printf("\r\n");
146+
147+
Serial.printf(" iSerialNumber %u ", desc->iSerialNumber);
148+
if (XFER_RESULT_SUCCESS ==
149+
tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, dev->serial, sizeof(dev->serial))) {
150+
utf16_to_utf8(dev->serial, sizeof(dev->serial));
151+
Serial.printf((char *) dev->serial);
152+
}
153+
Serial.printf("\r\n");
154+
155+
Serial.printf(" bNumConfigurations %u\r\n", desc->bNumConfigurations);
156+
157+
// print device summary
158+
print_lsusb();
159+
160+
display_device_descriptor(xfer);
161+
}
162+
163+
164+
void display_device_descriptor(tuh_xfer_t *xfer) {
165+
if (XFER_RESULT_SUCCESS != xfer->result) {
166+
tft.println("Failed to get device descriptor");
167+
return;
168+
}
169+
170+
uint8_t const daddr = xfer->daddr;
171+
dev_info_t *dev = &dev_info[daddr - 1];
172+
tusb_desc_device_t *desc = &dev->desc_device;
173+
174+
tft.fillScreen(ST77XX_BLACK); // Clear the screen
175+
tft.setCursor(0, 0);
176+
tft.setTextWrap(true);
177+
tft.setTextSize(3);
178+
179+
tft.setTextColor(ST77XX_GREEN);
180+
tft.println("USB Found:");
181+
tft.setTextColor(ST77XX_WHITE);
182+
tft.printf("ID %04x:%04x\n", desc->idVendor, desc->idProduct);
183+
184+
if (XFER_RESULT_SUCCESS ==
185+
tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, dev->manufacturer, sizeof(dev->manufacturer))) {
186+
utf16_to_utf8(dev->manufacturer, sizeof(dev->manufacturer));
187+
tft.setTextColor(ST77XX_YELLOW);
188+
tft.println((char *)dev->manufacturer);
189+
}
190+
191+
if (XFER_RESULT_SUCCESS ==
192+
tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, dev->product, sizeof(dev->product))) {
193+
utf16_to_utf8(dev->product, sizeof(dev->product));
194+
tft.setTextColor(ST77XX_BLUE);
195+
tft.println((char *)dev->product);
196+
}
197+
198+
// Additional device descriptor details can be displayed here as needed
199+
}
200+
201+
202+
//--------------------------------------------------------------------+
203+
// String Descriptor Helper
204+
//--------------------------------------------------------------------+
205+
206+
static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
207+
// TODO: Check for runover.
208+
(void) utf8_len;
209+
// Get the UTF-16 length out of the data itself.
210+
211+
for (size_t i = 0; i < utf16_len; i++) {
212+
uint16_t chr = utf16[i];
213+
if (chr < 0x80) {
214+
*utf8++ = chr & 0xff;
215+
} else if (chr < 0x800) {
216+
*utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F));
217+
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
218+
} else {
219+
// TODO: Verify surrogate.
220+
*utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F));
221+
*utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F));
222+
*utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
223+
}
224+
// TODO: Handle UTF-16 code points that take two entries.
225+
}
226+
}
227+
228+
// Count how many bytes a utf-16-le encoded string will take in utf-8.
229+
static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
230+
size_t total_bytes = 0;
231+
for (size_t i = 0; i < len; i++) {
232+
uint16_t chr = buf[i];
233+
if (chr < 0x80) {
234+
total_bytes += 1;
235+
} else if (chr < 0x800) {
236+
total_bytes += 2;
237+
} else {
238+
total_bytes += 3;
239+
}
240+
// TODO: Handle UTF-16 code points that take two entries.
241+
}
242+
return total_bytes;
243+
}
244+
245+
void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) {
246+
size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
247+
size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len);
248+
249+
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, buf_len);
250+
((uint8_t *) temp_buf)[utf8_len] = '\0';
251+
}

library.deps

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
depends=Adafruit ILI9341, Adafruit BusIO, SD, Adafruit NeoPixel, Adafruit VS1053 Library, Adafruit BluefruitLE nRF51, Adafruit seesaw Library, Ethernet, Adafruit IO Arduino, FastLED, Adafruit LiquidCrystal, Adafruit SoftServo, TinyWireM, Adafruit AM radio library, WaveHC, Adafruit LED Backpack Library, MAX31850 OneWire, Adafruit VC0706 Serial Camera Library, RTClib, Adafruit SleepyDog Library, Adafruit Thermal Printer Library, Adafruit Zero I2S Library, Adafruit EPD, Adafruit SSD1351 library, Adafruit FONA Library, Adafruit Motor Shield V2 Library, Adafruit NeoMatrix, Adafruit Soundboard library, Adafruit Circuit Playground, ArduinoJson, Adafruit TCS34725, Adafruit Pixie, Adafruit GPS Library, TinyGPS, WiFi101, Adafruit DotStar, Adafruit Si7021 Library, Adafruit WS2801 Library, Mouse, Keyboard, Time, IRremote, Adafruit LSM9DS0 Library, Adafruit Arcada Library, MIDIUSB, PubSubClient, Adafruit LIS2MDL, Adafruit NeoPXL8, Adafruit MCP23017 Arduino Library, Adafruit MLX90640, LiquidCrystal, Adafruit NeoTrellis M4 Library, RGB matrix Panel, Adafruit MLX90614 Library, Adafruit RGB LCD Shield Library, MAX6675 library, Adafruit MP3, Adafruit Keypad, Adafruit Arcada GifDecoder, Keypad, Neosegment, Encoder, Adafruit TiCoServo, Adafruit Trellis Library, FauxmoESP, Adafruit LSM303 Accel, Adafruit LSM303DLH Mag, Adafruit LSM303DLHC, CapacitiveSensor, Adafruit Zero PDM Library, Adafruit DMA neopixel library, elapsedMillis, DST RTC, Adafruit SHARP Memory Display, Adafruit SPIFlash, BSEC Software Library, WiiChuck, Adafruit DPS310, Adafruit AHTX0, RotaryEncoder, Adafruit MCP9808 Library, LSM303, Adafruit Protomatter, Adafruit IS31FL3741 Library, Sensirion I2C SCD4x, Adafruit TestBed, Bounce2, Adafruit AHRS, Adafruit DRV2605 Library, STM32duino VL53L4CD, PicoDVI - Adafruit Fork, Adafruit MMA8451 Library, Adafruit TSC2007, GFX Library for Arduino
1+
depends=Adafruit ILI9341, Adafruit BusIO, SD, Adafruit NeoPixel, Adafruit VS1053 Library, Adafruit BluefruitLE nRF51, Adafruit seesaw Library, Ethernet, Adafruit IO Arduino, FastLED, Adafruit LiquidCrystal, Adafruit SoftServo, TinyWireM, Adafruit AM radio library, WaveHC, Adafruit LED Backpack Library, MAX31850 OneWire, Adafruit VC0706 Serial Camera Library, RTClib, Adafruit SleepyDog Library, Adafruit Thermal Printer Library, Adafruit Zero I2S Library, Adafruit EPD, Adafruit SSD1351 library, Adafruit FONA Library, Adafruit Motor Shield V2 Library, Adafruit NeoMatrix, Adafruit Soundboard library, Adafruit Circuit Playground, ArduinoJson, Adafruit TCS34725, Adafruit Pixie, Adafruit GPS Library, TinyGPS, WiFi101, Adafruit DotStar, Adafruit Si7021 Library, Adafruit WS2801 Library, Mouse, Keyboard, Time, IRremote, Adafruit LSM9DS0 Library, Adafruit Arcada Library, MIDIUSB, PubSubClient, Adafruit LIS2MDL, Adafruit NeoPXL8, Adafruit MCP23017 Arduino Library, Adafruit MLX90640, LiquidCrystal, Adafruit NeoTrellis M4 Library, RGB matrix Panel, Adafruit MLX90614 Library, Adafruit RGB LCD Shield Library, MAX6675 library, Adafruit MP3, Adafruit Keypad, Adafruit Arcada GifDecoder, Keypad, Neosegment, Encoder, Adafruit TiCoServo, Adafruit Trellis Library, FauxmoESP, Adafruit LSM303 Accel, Adafruit LSM303DLH Mag, Adafruit LSM303DLHC, CapacitiveSensor, Adafruit Zero PDM Library, Adafruit DMA neopixel library, elapsedMillis, DST RTC, Adafruit SHARP Memory Display, Adafruit SPIFlash, BSEC Software Library, WiiChuck, Adafruit DPS310, Adafruit AHTX0, RotaryEncoder, Adafruit MCP9808 Library, LSM303, Adafruit Protomatter, Adafruit IS31FL3741 Library, Sensirion I2C SCD4x, Adafruit TestBed, Bounce2, Adafruit AHRS, Adafruit DRV2605 Library, STM32duino VL53L4CD, PicoDVI - Adafruit Fork, Adafruit MMA8451 Library, Adafruit TSC2007, GFX Library for Arduino, Adafruit PyCamera Library

0 commit comments

Comments
 (0)