15
15
16
16
#include " Adafruit_TinyUSB.h"
17
17
18
+ #define LANGUAGE_ID 0x0409 // English
19
+
18
20
// USB Host object
19
21
Adafruit_USBH_Host USBHost;
20
22
23
+ // holding device descriptor
24
+ tusb_desc_device_t desc_device;
25
+
21
26
// the setup function runs once when you press reset or power the board
22
27
void setup ()
23
28
{
@@ -27,33 +32,12 @@ void setup()
27
32
// while ( !Serial ) delay(10); // wait for native usb
28
33
29
34
Serial.println (" TinyUSB Dual Device Info Example" );
30
-
31
- // Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
32
- uint32_t cpu_hz = clock_get_hz (clk_sys);
33
- if ( cpu_hz != 120000000UL && cpu_hz != 240000000UL ) {
34
- while ( !Serial ) delay (10 ); // wait for native usb
35
- Serial.printf (" Error: CPU Clock = %u, PIO USB require CPU clock must be multiple of 120 Mhz\r\n " , cpu_hz);
36
- Serial.printf (" Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU Speed \r\n " , cpu_hz);
37
- while (1 ) delay (1 );
38
- }
39
-
40
- pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
41
- pio_cfg.pin_dp = HOST_PIN_DP;
42
- USBHost.configure_pio_usb (1 , &pio_cfg);
43
-
44
- // run host stack on controller (rhport) 1
45
- // Note: For rp2040 pico-pio-usb, calling USBHost.begin() on core1 will have most of the
46
- // host bit-banging processing works done in core1 to free up core0 for other works
47
- USBHost.begin (1 );
48
35
}
49
36
50
37
void loop ()
51
38
{
52
- USBHost.task ();
53
39
}
54
40
55
- #if 0
56
-
57
41
// core1's setup
58
42
void setup1 () {
59
43
// while ( !Serial ) delay(10); // wait for native usb
@@ -84,5 +68,127 @@ void loop1()
84
68
USBHost.task ();
85
69
}
86
70
87
- #endif
71
+ // --------------------------------------------------------------------+
72
+ // TinyUSB Host callbacks
73
+ // --------------------------------------------------------------------+
74
+
75
+ // Invoked when device is mounted (configured)
76
+ void tuh_mount_cb (uint8_t daddr)
77
+ {
78
+ Serial.printf (" Device attached, address = %d\r\n " , daddr);
79
+
80
+ // Get Device Descriptor
81
+ tuh_descriptor_get_device (daddr, &desc_device, 18 , print_device_descriptor, 0 );
82
+ }
83
+
84
+ // / Invoked when device is unmounted (bus reset/unplugged)
85
+ void tuh_umount_cb (uint8_t daddr)
86
+ {
87
+ Serial.printf (" Device removed, address = %d\r\n " , daddr);
88
+ }
89
+
90
+ void print_device_descriptor (tuh_xfer_t * xfer)
91
+ {
92
+ if ( XFER_RESULT_SUCCESS != xfer->result )
93
+ {
94
+ Serial.printf (" Failed to get device descriptor\r\n " );
95
+ return ;
96
+ }
97
+
98
+ uint8_t const daddr = xfer->daddr ;
99
+
100
+ Serial.printf (" Device %u: ID %04x:%04x\r\n " , daddr, desc_device.idVendor , desc_device.idProduct );
101
+ Serial.printf (" Device Descriptor:\r\n " );
102
+ Serial.printf (" bLength %u\r\n " , desc_device.bLength );
103
+ Serial.printf (" bDescriptorType %u\r\n " , desc_device.bDescriptorType );
104
+ Serial.printf (" bcdUSB %04x\r\n " , desc_device.bcdUSB );
105
+ Serial.printf (" bDeviceClass %u\r\n " , desc_device.bDeviceClass );
106
+ Serial.printf (" bDeviceSubClass %u\r\n " , desc_device.bDeviceSubClass );
107
+ Serial.printf (" bDeviceProtocol %u\r\n " , desc_device.bDeviceProtocol );
108
+ Serial.printf (" bMaxPacketSize0 %u\r\n " , desc_device.bMaxPacketSize0 );
109
+ Serial.printf (" idVendor 0x%04x\r\n " , desc_device.idVendor );
110
+ Serial.printf (" idProduct 0x%04x\r\n " , desc_device.idProduct );
111
+ Serial.printf (" bcdDevice %04x\r\n " , desc_device.bcdDevice );
112
+
113
+ // Get String descriptor using Sync API
114
+ uint16_t temp_buf[128 ];
115
+ uint8_t result;
116
+
117
+ Serial.printf (" iManufacturer %u " , desc_device.iManufacturer );
118
+ if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync (daddr, LANGUAGE_ID, temp_buf, sizeof (temp_buf)) )
119
+ {
120
+ TU_LOG2_ARR (temp_buf, sizeof (temp_buf));
121
+ print_utf16 (temp_buf, TU_ARRAY_SIZE (temp_buf));
122
+ }
123
+ Serial.printf (" \r\n " );
124
+
125
+ Serial.printf (" iProduct %u " , desc_device.iProduct );
126
+ if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync (daddr, LANGUAGE_ID, temp_buf, sizeof (temp_buf)))
127
+ {
128
+ print_utf16 (temp_buf, TU_ARRAY_SIZE (temp_buf));
129
+ }
130
+ Serial.printf (" \r\n " );
131
+
132
+ Serial.printf (" iSerialNumber %u " , desc_device.iSerialNumber );
133
+ if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync (daddr, LANGUAGE_ID, temp_buf, sizeof (temp_buf)))
134
+ {
135
+ print_utf16 (temp_buf, TU_ARRAY_SIZE (temp_buf));
136
+ }
137
+ Serial.printf (" \r\n " );
138
+
139
+ Serial.printf (" bNumConfigurations %u\r\n " , desc_device.bNumConfigurations );
140
+ }
141
+
142
+ // --------------------------------------------------------------------+
143
+ // String Descriptor Helper
144
+ // --------------------------------------------------------------------+
145
+
146
+ static void _convert_utf16le_to_utf8 (const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
147
+ // TODO: Check for runover.
148
+ (void )utf8_len;
149
+ // Get the UTF-16 length out of the data itself.
150
+
151
+ for (size_t i = 0 ; i < utf16_len; i++) {
152
+ uint16_t chr = utf16[i];
153
+ if (chr < 0x80 ) {
154
+ *utf8++ = chr & 0xff ;
155
+ } else if (chr < 0x800 ) {
156
+ *utf8++ = (uint8_t )(0xC0 | (chr >> 6 & 0x1F ));
157
+ *utf8++ = (uint8_t )(0x80 | (chr >> 0 & 0x3F ));
158
+ } else {
159
+ // TODO: Verify surrogate.
160
+ *utf8++ = (uint8_t )(0xE0 | (chr >> 12 & 0x0F ));
161
+ *utf8++ = (uint8_t )(0x80 | (chr >> 6 & 0x3F ));
162
+ *utf8++ = (uint8_t )(0x80 | (chr >> 0 & 0x3F ));
163
+ }
164
+ // TODO: Handle UTF-16 code points that take two entries.
165
+ }
166
+ }
167
+
168
+ // Count how many bytes a utf-16-le encoded string will take in utf-8.
169
+ static int _count_utf8_bytes (const uint16_t *buf, size_t len) {
170
+ size_t total_bytes = 0 ;
171
+ for (size_t i = 0 ; i < len; i++) {
172
+ uint16_t chr = buf[i];
173
+ if (chr < 0x80 ) {
174
+ total_bytes += 1 ;
175
+ } else if (chr < 0x800 ) {
176
+ total_bytes += 2 ;
177
+ } else {
178
+ total_bytes += 3 ;
179
+ }
180
+ // TODO: Handle UTF-16 code points that take two entries.
181
+ }
182
+ return total_bytes;
183
+ }
184
+
185
+ static void print_utf16 (uint16_t *temp_buf, size_t buf_len) {
186
+ size_t utf16_len = ((temp_buf[0 ] & 0xff ) - 2 ) / sizeof (uint16_t );
187
+ size_t utf8_len = _count_utf8_bytes (temp_buf + 1 , utf16_len);
188
+
189
+ _convert_utf16le_to_utf8 (temp_buf + 1 , utf16_len, (uint8_t *) temp_buf, sizeof (uint16_t ) * buf_len);
190
+ ((uint8_t *) temp_buf)[utf8_len] = ' \0 ' ;
191
+
192
+ Serial.printf ((char *)temp_buf);
193
+ }
88
194
0 commit comments