Skip to content

Commit 774aa13

Browse files
committed
adding usb host featherwing factory test
Adding USB Host FeatherWing factory test and updating memento test only to pycamera_s3
1 parent b595f4b commit 774aa13

File tree

3 files changed

+247
-0
lines changed

3 files changed

+247
-0
lines changed

Factory_Tests/USB_Host_FeatherWing/.feather_esp32s2_tft.test.only

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

0 commit comments

Comments
 (0)