Skip to content

Commit ec12be5

Browse files
author
ladyada
committed
Merge branch 'master' of github.com:adafruit/ArduinoCore-samd
2 parents 9a6ab51 + 2cc8b49 commit ec12be5

File tree

9 files changed

+224
-57
lines changed

9 files changed

+224
-57
lines changed

cores/arduino/Adafruit_TinyUSB_Core/Adafruit_TinyUSB_Core.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ uint8_t load_serial_number(uint16_t* serial_str)
9999

100100
for (int i=0; i<4; i++) {
101101
for (int k=0; k<4; k++) {
102-
raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff;
102+
raw_id[4 * i + (3 - k)] = (*(id_addresses[i]) >> k * 8) & 0xff;
103103
}
104104
}
105105

@@ -109,7 +109,7 @@ uint8_t load_serial_number(uint16_t* serial_str)
109109
for (int j = 0; j < 2; j++) {
110110
uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf;
111111
// Strings are UTF-16-LE encoded.
112-
serial_str[i * 2 + j] = nibble_to_hex[nibble];
112+
serial_str[i * 2 + (1 - j)] = nibble_to_hex[nibble];
113113
}
114114
}
115115

cores/arduino/Adafruit_TinyUSB_Core/Adafruit_USBD_Device.cpp

Lines changed: 128 additions & 19 deletions
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,14 +84,19 @@ 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));
83-
90+
memcpy(_desc_cfg_buffer, &dev_cfg, sizeof(tusb_desc_configuration_t));
91+
_desc_cfg = _desc_cfg_buffer;
92+
_desc_cfg_size = sizeof(_desc_cfg_buffer);
8493
_desc_cfglen = sizeof(tusb_desc_configuration_t);
8594
_itf_count = 0;
8695
_epin_count = _epout_count = 1;
96+
97+
_language_id = USB_LANGUAGE;
98+
_manufacturer = USB_MANUFACTURER;
99+
_product = USB_PRODUCT;
87100
}
88101

89102
// Add interface descriptor
@@ -92,7 +105,7 @@ Adafruit_USBD_Device::Adafruit_USBD_Device(void)
92105
bool Adafruit_USBD_Device::addInterface(Adafruit_USBD_Interface& itf)
93106
{
94107
uint8_t* desc = _desc_cfg+_desc_cfglen;
95-
uint16_t const len = itf.getDescriptor(_itf_count, desc, sizeof(_desc_cfg)-_desc_cfglen);
108+
uint16_t const len = itf.getDescriptor(_itf_count, desc, _desc_cfg_size-_desc_cfglen);
96109
uint8_t* desc_end = desc+len;
97110

98111
if ( !len ) return false;
@@ -123,6 +136,16 @@ bool Adafruit_USBD_Device::addInterface(Adafruit_USBD_Interface& itf)
123136
return true;
124137
}
125138

139+
void Adafruit_USBD_Device::setDescriptorBuffer(uint8_t* buf, uint32_t buflen)
140+
{
141+
if (buflen < _desc_cfg_size)
142+
return;
143+
144+
memcpy(buf, _desc_cfg, _desc_cfglen);
145+
_desc_cfg = buf;
146+
_desc_cfg_size = buflen;
147+
}
148+
126149
void Adafruit_USBD_Device::setID(uint16_t vid, uint16_t pid)
127150
{
128151
_desc_device.idVendor = vid;
@@ -134,6 +157,22 @@ void Adafruit_USBD_Device::setVersion(uint16_t bcd)
134157
_desc_device.bcdUSB = bcd;
135158
}
136159

160+
161+
void Adafruit_USBD_Device::setLanguageDescriptor (uint16_t language_id)
162+
{
163+
_language_id = language_id;
164+
}
165+
166+
void Adafruit_USBD_Device::setManufacturerDescriptor(const char *s)
167+
{
168+
_manufacturer = s;
169+
}
170+
171+
void Adafruit_USBD_Device::setProductDescriptor(const char *s)
172+
{
173+
_product = s;
174+
}
175+
137176
bool Adafruit_USBD_Device::begin(void)
138177
{
139178
return true;
@@ -157,6 +196,85 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
157196
return USBDevice._desc_cfg;
158197
}
159198

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+
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:

cores/arduino/Adafruit_TinyUSB_Core/Adafruit_USBD_Device.h

Lines changed: 17 additions & 1 deletion
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];
41+
uint8_t *_desc_cfg;
42+
uint16_t _desc_cfg_size;
4243
uint16_t _desc_cfglen;
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/arduino/Adafruit_TinyUSB_Core/tinyusb/src/device/usbd.h

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,15 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
169169
/* CDC Header */\
170170
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\
171171
/* CDC Call */\
172-
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (_itfnum) + 1,\
172+
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\
173173
/* CDC ACM: support line request */\
174174
4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\
175175
/* CDC Union */\
176-
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (_itfnum) + 1,\
176+
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\
177177
/* Endpoint Notification */\
178178
7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\
179179
/* CDC Data Interface */\
180-
9, TUSB_DESC_INTERFACE, (_itfnum)+1, 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\
180+
9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\
181181
/* Endpoint Out */\
182182
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
183183
/* Endpoint In */\
@@ -206,7 +206,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
206206
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
207207
#define TUD_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \
208208
/* Interface */\
209-
9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (_boot_protocol) ? HID_SUBCLASS_BOOT : 0, _boot_protocol, _stridx,\
209+
9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\
210210
/* HID descriptor */\
211211
9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\
212212
/* Endpoint In */\
@@ -219,7 +219,7 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
219219
// Interface number, string index, protocol, report descriptor len, EP OUT & IN address, size & polling interval
220220
#define TUD_HID_INOUT_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epout, _epin, _epsize, _ep_interval) \
221221
/* Interface */\
222-
9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (_boot_protocol) ? HID_SUBCLASS_BOOT : 0, _boot_protocol, _stridx,\
222+
9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\
223223
/* HID descriptor */\
224224
9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0111), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\
225225
/* Endpoint Out */\
@@ -229,37 +229,60 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
229229

230230
//------------- MIDI -------------//
231231

232-
// Length of template descriptor (96 bytes)
233-
#define TUD_MIDI_DESC_LEN (9 + 9 + 9 + 7 + 6 + 6 + 9 + 9 + 7 + 5 + 7 + 5)
234-
235-
// MIDI simple descriptor
236-
// - 1 Embedded Jack In connected to 1 External Jack Out
237-
// - 1 Embedded Jack out connected to 1 External Jack In
238-
#define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \
232+
#define TUD_MIDI_DESC_HEAD_LEN (9 + 9 + 9 + 7)
233+
#define TUD_MIDI_DESC_HEAD(_itfnum, _stridx, _numcables) \
239234
/* Audio Control (AC) Interface */\
240235
9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\
241236
/* AC Header */\
242-
9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, _itfnum+1,\
237+
9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, (uint8_t)((_itfnum) + 1),\
243238
/* MIDI Streaming (MS) Interface */\
244-
9, TUSB_DESC_INTERFACE, _itfnum+1, 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\
239+
9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum) + 1), 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\
245240
/* MS Header */\
246-
7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0025),\
241+
7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(7 + (_numcables) * TUD_MIDI_DESC_JACK_LEN)
242+
243+
#define TUD_MIDI_JACKID_IN_EMB(_cablenum) \
244+
(uint8_t)(((_cablenum) - 1) * 4 + 1)
245+
246+
#define TUD_MIDI_JACKID_IN_EXT(_cablenum) \
247+
(uint8_t)(((_cablenum) - 1) * 4 + 2)
248+
249+
#define TUD_MIDI_JACKID_OUT_EMB(_cablenum) \
250+
(uint8_t)(((_cablenum) - 1) * 4 + 3)
251+
252+
#define TUD_MIDI_JACKID_OUT_EXT(_cablenum) \
253+
(uint8_t)(((_cablenum) - 1) * 4 + 4)
254+
255+
#define TUD_MIDI_DESC_JACK_LEN (6 + 6 + 9 + 9)
256+
#define TUD_MIDI_DESC_JACK(_cablenum) \
247257
/* MS In Jack (Embedded) */\
248-
6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, 1, 0,\
258+
6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_IN_EMB(_cablenum), 0,\
249259
/* MS In Jack (External) */\
250-
6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, 2, 0,\
260+
6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_IN_EXT(_cablenum), 0,\
251261
/* MS Out Jack (Embedded), connected to In Jack External */\
252-
9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, 3, 1, 2, 1, 0,\
262+
9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, TUD_MIDI_JACKID_OUT_EMB(_cablenum), 1, TUD_MIDI_JACKID_IN_EXT(_cablenum), 1, 0,\
253263
/* MS Out Jack (External), connected to In Jack Embedded */\
254-
9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, 4, 1, 1, 1, 0,\
255-
/* Endpoint Out */\
264+
9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, TUD_MIDI_JACKID_OUT_EXT(_cablenum), 1, TUD_MIDI_JACKID_IN_EMB(_cablenum), 1, 0
265+
266+
#define TUD_MIDI_DESC_EP_LEN(_numcables) (7 + 4 + (_numcables))
267+
#define TUD_MIDI_DESC_EP(_epout, _epsize, _numcables) \
268+
/* Endpoint */\
256269
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
257-
/* MS Endpoint (connected to embedded jack in) */\
258-
5, TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, 1, 1,\
259-
/* Endpoint In */\
260-
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
261-
/* MS Endpoint (connected to embedded jack out) */\
262-
5, TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, 1, 3
270+
/* MS Endpoint (connected to embedded jack) */\
271+
(uint8_t)(4 + (_numcables)), TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, _numcables
272+
273+
// Length of template descriptor (88 bytes)
274+
#define TUD_MIDI_DESC_LEN (TUD_MIDI_DESC_HEAD_LEN + TUD_MIDI_DESC_JACK_LEN + TUD_MIDI_DESC_EP_LEN(1) * 2)
275+
276+
// MIDI simple descriptor
277+
// - 1 Embedded Jack In connected to 1 External Jack Out
278+
// - 1 Embedded Jack out connected to 1 External Jack In
279+
#define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \
280+
TUD_MIDI_DESC_HEAD(_itfnum, _stridx, 1),\
281+
TUD_MIDI_DESC_JACK(1),\
282+
TUD_MIDI_DESC_EP(_epout, _epsize, 1),\
283+
TUD_MIDI_JACKID_IN_EMB(1),\
284+
TUD_MIDI_DESC_EP(_epin, _epsize, 1),\
285+
TUD_MIDI_JACKID_OUT_EMB(1)
263286

264287
//------------- Vendor -------------//
265288
#define TUD_VENDOR_DESC_LEN (9+7+7)

0 commit comments

Comments
 (0)