Skip to content

Commit d82401e

Browse files

File tree

4 files changed

+200
-66
lines changed

4 files changed

+200
-66
lines changed

cores/nRF5/Adafruit_TinyUSB_Core/Adafruit_USBD_Device.cpp

+136-27
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@
3434
#define USB_PRODUCT "Unknown"
3535
#endif
3636

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+
3745
extern uint8_t load_serial_number(uint16_t* serial_str);
3846

3947
Adafruit_USBD_Device USBDevice;
@@ -76,23 +84,29 @@ Adafruit_USBD_Device::Adafruit_USBD_Device(void)
7684
.bConfigurationValue = 1,
7785
.iConfiguration = 0x00,
7886
.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)
8088
};
8189

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;
8397

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;
87101
}
88102

89103
// Add interface descriptor
90104
// - Interface number will be updated to match current count
91105
// - Endpoint number is updated to be unique
92106
bool Adafruit_USBD_Device::addInterface(Adafruit_USBD_Interface& itf)
93107
{
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);
96110
uint8_t* desc_end = desc+len;
97111

98112
if ( !len ) return false;
@@ -113,19 +127,29 @@ bool Adafruit_USBD_Device::addInterface(Adafruit_USBD_Interface& itf)
113127
desc += desc[0]; // next
114128
}
115129

116-
_desc_cfglen += len;
130+
_desc_cfg_len += len;
117131

118132
// Update configuration descriptor
119133
tusb_desc_configuration_t* config = (tusb_desc_configuration_t*)_desc_cfg;
120-
config->wTotalLength = _desc_cfglen;
134+
config->wTotalLength = _desc_cfg_len;
121135
config->bNumInterfaces = _itf_count;
122136

123137
return true;
124138
}
125139

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+
126150
void Adafruit_USBD_Device::setID(uint16_t vid, uint16_t pid)
127151
{
128-
_desc_device.idVendor = vid;
152+
_desc_device.idVendor = vid;
129153
_desc_device.idProduct = pid;
130154
}
131155

@@ -134,6 +158,22 @@ void Adafruit_USBD_Device::setVersion(uint16_t bcd)
134158
_desc_device.bcdUSB = bcd;
135159
}
136160

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+
137177
bool Adafruit_USBD_Device::begin(void)
138178
{
139179
return true;
@@ -157,6 +197,84 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
157197
return USBDevice._desc_cfg;
158198
}
159199

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+
160278
// up to 32 unicode characters (header make it 33)
161279
static uint16_t _desc_str[33];
162280

@@ -169,25 +287,16 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index)
169287
switch (index)
170288
{
171289
case 0:
172-
// language = English
173-
_desc_str[1] = 0x0409;
290+
_desc_str[1] = USBDevice.getLanguageDescriptor();
174291
chr_count = 1;
175292
break;
176293

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;
185297

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);
191300
break;
192301

193302
case 3:
@@ -198,8 +307,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index)
198307
default: return NULL;
199308
}
200309

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);
203312

204313
return _desc_str;
205314
}

cores/nRF5/Adafruit_TinyUSB_Core/Adafruit_USBD_Device.h

+18-2
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,37 @@ class Adafruit_USBD_Device
3838
private:
3939
tusb_desc_device_t _desc_device;
4040

41-
uint8_t _desc_cfg[256];
42-
uint16_t _desc_cfglen;
41+
uint8_t *_desc_cfg;
42+
uint16_t _desc_cfg_maxlen;
43+
uint16_t _desc_cfg_len;
44+
uint8_t _desc_cfg_buffer[256];
4345

4446
uint8_t _itf_count;
4547

4648
uint8_t _epin_count;
4749
uint8_t _epout_count;
4850

51+
uint16_t _language_id;
52+
const char *_manufacturer;
53+
const char *_product;
54+
4955
public:
5056
Adafruit_USBD_Device(void);
5157

5258
bool addInterface(Adafruit_USBD_Interface& itf);
59+
void setDescriptorBuffer(uint8_t* buf, uint32_t buflen);
5360

5461
void setID(uint16_t vid, uint16_t pid);
5562
void setVersion(uint16_t bcd);
63+
64+
void setLanguageDescriptor(uint16_t language_id);
65+
void setManufacturerDescriptor(const char *s);
66+
void setProductDescriptor(const char *s);
67+
68+
uint16_t getLanguageDescriptor (void) { return _language_id; }
69+
const char *getManufacturerDescriptor (void) { return _manufacturer; }
70+
const char *getProductDescriptor (void) { return _product; }
71+
5672
bool begin(void);
5773

5874
bool mounted (void) { return tud_mounted(); }

cores/nRF5/Adafruit_TinyUSB_Core/tinyusb/src/common/tusb_types.h

-9
Original file line numberDiff line numberDiff line change
@@ -469,15 +469,6 @@ static inline uint8_t tu_desc_len(void const* desc)
469469
return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
470470
}
471471

472-
// Length of the string descriptors in bytes with slen characters
473-
#define TUD_DESC_STRLEN(_chr_count) (2*(_chr_count) + 2)
474-
475-
// Header of string descriptors with len + string type
476-
#define TUD_DESC_STR_HEADER(_chr_count) ( (uint16_t) ( (TUSB_DESC_STRING << 8 ) | TUD_DESC_STRLEN(_chr_count)) )
477-
478-
// Convert comma-separated string to descriptor unicode format
479-
#define TUD_DESC_STRCONV( ... ) (const uint16_t[]) { TUD_DESC_STR_HEADER(TU_ARGS_NUM(__VA_ARGS__)), __VA_ARGS__ }
480-
481472
#ifdef __cplusplus
482473
}
483474
#endif

0 commit comments

Comments
 (0)