34
34
#define USB_PRODUCT " Unknown"
35
35
#endif
36
36
37
+ #ifndef USB_LANGUAGE
38
+ #define USB_LANGUAGE 0x0409 // default is English
39
+ #endif
40
+
41
+ #ifndef USB_CONFIG_POWER
42
+ #define USB_CONFIG_POWER 100
43
+ #endif
44
+
37
45
extern uint8_t load_serial_number (uint16_t * serial_str);
38
46
39
47
Adafruit_USBD_Device USBDevice;
@@ -76,23 +84,29 @@ Adafruit_USBD_Device::Adafruit_USBD_Device(void)
76
84
.bConfigurationValue = 1 ,
77
85
.iConfiguration = 0x00 ,
78
86
.bmAttributes = TU_BIT (7 ) | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP,
79
- .bMaxPower = TUSB_DESC_CONFIG_POWER_MA (100 )
87
+ .bMaxPower = TUSB_DESC_CONFIG_POWER_MA (USB_CONFIG_POWER )
80
88
};
81
89
82
- memcpy (_desc_cfg, &dev_cfg, sizeof (tusb_desc_configuration_t ));
90
+ memcpy (_desc_cfg_buffer, &dev_cfg, sizeof (tusb_desc_configuration_t ));
91
+ _desc_cfg = _desc_cfg_buffer;
92
+ _desc_cfg_maxlen = sizeof (_desc_cfg_buffer);
93
+ _desc_cfg_len = sizeof (tusb_desc_configuration_t );
94
+
95
+ _itf_count = 0 ;
96
+ _epin_count = _epout_count = 1 ;
83
97
84
- _desc_cfglen = sizeof ( tusb_desc_configuration_t ) ;
85
- _itf_count = 0 ;
86
- _epin_count = _epout_count = 1 ;
98
+ _language_id = USB_LANGUAGE ;
99
+ _manufacturer = USB_MANUFACTURER ;
100
+ _product = USB_PRODUCT ;
87
101
}
88
102
89
103
// Add interface descriptor
90
104
// - Interface number will be updated to match current count
91
105
// - Endpoint number is updated to be unique
92
106
bool Adafruit_USBD_Device::addInterface (Adafruit_USBD_Interface& itf)
93
107
{
94
- uint8_t * desc = _desc_cfg+_desc_cfglen ;
95
- uint16_t const len = itf.getDescriptor (_itf_count, desc, sizeof (_desc_cfg)-_desc_cfglen );
108
+ uint8_t * desc = _desc_cfg+_desc_cfg_len ;
109
+ uint16_t const len = itf.getDescriptor (_itf_count, desc, _desc_cfg_maxlen-_desc_cfg_len );
96
110
uint8_t * desc_end = desc+len;
97
111
98
112
if ( !len ) return false ;
@@ -113,19 +127,29 @@ bool Adafruit_USBD_Device::addInterface(Adafruit_USBD_Interface& itf)
113
127
desc += desc[0 ]; // next
114
128
}
115
129
116
- _desc_cfglen += len;
130
+ _desc_cfg_len += len;
117
131
118
132
// Update configuration descriptor
119
133
tusb_desc_configuration_t * config = (tusb_desc_configuration_t *)_desc_cfg;
120
- config->wTotalLength = _desc_cfglen ;
134
+ config->wTotalLength = _desc_cfg_len ;
121
135
config->bNumInterfaces = _itf_count;
122
136
123
137
return true ;
124
138
}
125
139
140
+ void Adafruit_USBD_Device::setDescriptorBuffer (uint8_t * buf, uint32_t buflen)
141
+ {
142
+ if (buflen < _desc_cfg_maxlen)
143
+ return ;
144
+
145
+ memcpy (buf, _desc_cfg, _desc_cfg_len);
146
+ _desc_cfg = buf;
147
+ _desc_cfg_maxlen = buflen;
148
+ }
149
+
126
150
void Adafruit_USBD_Device::setID (uint16_t vid, uint16_t pid)
127
151
{
128
- _desc_device.idVendor = vid;
152
+ _desc_device.idVendor = vid;
129
153
_desc_device.idProduct = pid;
130
154
}
131
155
@@ -134,6 +158,22 @@ void Adafruit_USBD_Device::setVersion(uint16_t bcd)
134
158
_desc_device.bcdUSB = bcd;
135
159
}
136
160
161
+
162
+ void Adafruit_USBD_Device::setLanguageDescriptor (uint16_t language_id)
163
+ {
164
+ _language_id = language_id;
165
+ }
166
+
167
+ void Adafruit_USBD_Device::setManufacturerDescriptor (const char *s)
168
+ {
169
+ _manufacturer = s;
170
+ }
171
+
172
+ void Adafruit_USBD_Device::setProductDescriptor (const char *s)
173
+ {
174
+ _product = s;
175
+ }
176
+
137
177
bool Adafruit_USBD_Device::begin (void )
138
178
{
139
179
return true ;
@@ -157,6 +197,84 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
157
197
return USBDevice._desc_cfg ;
158
198
}
159
199
200
+ static int utf8_to_unichar (const char *str8, int *unicharp)
201
+ {
202
+ int unichar;
203
+ int len;
204
+
205
+ if (str8[0 ] < 0x80 )
206
+ len = 1 ;
207
+ else if ((str8[0 ] & 0xe0 ) == 0xc0 )
208
+ len = 2 ;
209
+ else if ((str8[0 ] & 0xf0 ) == 0xe0 )
210
+ len = 3 ;
211
+ else if ((str8[0 ] & 0xf8 ) == 0xf0 )
212
+ len = 4 ;
213
+ else if ((str8[0 ] & 0xfc ) == 0xf8 )
214
+ len = 5 ;
215
+ else if ((str8[0 ] & 0xfe ) == 0xfc )
216
+ len = 6 ;
217
+ else
218
+ return -1 ;
219
+
220
+ switch (len) {
221
+ case 1 :
222
+ unichar = str8[0 ];
223
+ break ;
224
+ case 2 :
225
+ unichar = str8[0 ] & 0x1f ;
226
+ break ;
227
+ case 3 :
228
+ unichar = str8[0 ] & 0x0f ;
229
+ break ;
230
+ case 4 :
231
+ unichar = str8[0 ] & 0x07 ;
232
+ break ;
233
+ case 5 :
234
+ unichar = str8[0 ] & 0x03 ;
235
+ break ;
236
+ case 6 :
237
+ unichar = str8[0 ] & 0x01 ;
238
+ break ;
239
+ }
240
+
241
+ for (int i = 1 ; i < len; i++) {
242
+ if ((str8[i] & 0xc0 ) != 0x80 )
243
+ return -1 ;
244
+ unichar <<= 6 ;
245
+ unichar |= str8[i] & 0x3f ;
246
+ }
247
+
248
+ *unicharp = unichar;
249
+ return len;
250
+ }
251
+
252
+ // Simple UCS-2/16-bit coversion, which handles the Basic Multilingual Plane
253
+ static int strcpy_uni16 (const char *s, uint16_t *buf, int bufsize) {
254
+ int i = 0 ;
255
+ int buflen = 0 ;
256
+
257
+ while (i < bufsize) {
258
+ int unichar;
259
+ int utf8len = utf8_to_unichar (s + i, &unichar);
260
+
261
+ if (utf8len < 0 ) {
262
+ // Invalid utf8 sequence, skip it
263
+ i++;
264
+ continue ;
265
+ }
266
+
267
+ i += utf8len;
268
+
269
+ // If the codepoint is larger than 16 bit, skip it
270
+ if (unichar <= 0xffff )
271
+ buf[buflen++] = unichar;
272
+ }
273
+
274
+ buf[buflen] = ' \0 ' ;
275
+ return buflen;
276
+ }
277
+
160
278
// up to 32 unicode characters (header make it 33)
161
279
static uint16_t _desc_str[33 ];
162
280
@@ -169,25 +287,16 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index)
169
287
switch (index )
170
288
{
171
289
case 0 :
172
- // language = English
173
- _desc_str[1 ] = 0x0409 ;
290
+ _desc_str[1 ] = USBDevice.getLanguageDescriptor ();
174
291
chr_count = 1 ;
175
292
break ;
176
293
177
- case 1 : // Manufacturer
178
- case 2 : // Product
179
- {
180
- char const * str = (index == 1 ) ? USB_MANUFACTURER : USB_PRODUCT;
181
-
182
- // cap at max char
183
- chr_count = strlen (str);
184
- if ( chr_count > 32 ) chr_count = 32 ;
294
+ case 1 :
295
+ chr_count = strcpy_uni16 (USBDevice.getManufacturerDescriptor (), _desc_str + 1 , 32 );
296
+ break ;
185
297
186
- for (uint8_t i=0 ; i<chr_count; i++)
187
- {
188
- _desc_str[1 +i] = str[i];
189
- }
190
- }
298
+ case 2 :
299
+ chr_count = strcpy_uni16 (USBDevice.getProductDescriptor (), _desc_str + 1 , 32 );
191
300
break ;
192
301
193
302
case 3 :
@@ -198,8 +307,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index)
198
307
default : return NULL ;
199
308
}
200
309
201
- // first byte is len , second byte is string type
202
- _desc_str[0 ] = TUD_DESC_STR_HEADER ( chr_count);
310
+ // first byte is length (including header) , second byte is string type
311
+ _desc_str[0 ] = (TUSB_DESC_STRING << 8 ) | ( 2 * chr_count + 2 );
203
312
204
313
return _desc_str;
205
314
}
0 commit comments