Skip to content

Commit 123758c

Browse files
authored
Merge pull request #3 from adafruit/use-string-descriptor
update to work with stock TinyUSB
2 parents eebd128 + a74cd88 commit 123758c

File tree

4 files changed

+23
-203
lines changed

4 files changed

+23
-203
lines changed

examples/simple_daplink/simple_daplink.ino

+7-200
Original file line numberDiff line numberDiff line change
@@ -92,213 +92,22 @@ uint8_t const desc_hid_report[] =
9292

9393
};
9494

95-
uint16_t Serial_u16[33];
96-
97-
static inline bool isInvalidUtf8Octet(uint8_t t) {
98-
// see bullets in https://tools.ietf.org/html/rfc3629#section-1
99-
return (t == 0xc0) || (t == 0xC1) || ((t >= 0xF5) && (t <= 0xFF));
100-
}
101-
102-
// up to 32 unicode characters (header make it 33)
103-
static uint16_t _desc_str[33];
104-
105-
//
106-
// This function has an UNWRITTEN CONTRACT that the buffer is either:
107-
// 1. Pre-validated as legal UTF-8, -OR-
108-
// 2. has a trailing zero-value octet/byte/uint8_t (aka null-terminated string)
109-
//
110-
// If the above are not true, this decoder may read past the end of the allocated
111-
// buffer, by up to three bytes.
112-
//
113-
// U+1F47F == 👿 ("IMP")
114-
// == 0001_1111_0100_0111_1111 ==> requires four-byte encoding in UTF-8
115-
// AABB BBBB CCCC CCDD DDDD ==> 0xF0 0x9F 0x91 0xBF
116-
//
117-
// Example sandwich and safety variables are there to cover the
118-
// two most-common stack layouts for declared variables, in unoptimized
119-
// code, so that the bytes surrounding those allocated for 'evilUTF8'
120-
// are guaranteed to be non-zero and valid UTF8 continuation octets.
121-
// uint8_t safety1 = 0;
122-
// uint8_t sandwich1[4] = { 0x81, 0x82, 0x83, 0x84 };
123-
// uint8_t evilUTF8[5] = { 0xF0, 0x9F, 0x91, 0xBF, 0xF9 };
124-
// uint8_t sandwich2[4] = { 0x85, 0x86, 0x87, 0x88 };
125-
// uint8_t safety2 = 0;
126-
//
127-
// NOTE: evilUTF8 could just contain a single byte 0xF9 ....
128-
//
129-
// Attempting to decode evilUTF8 will progress to whatever is next to it on the stack.
130-
// The above should work when optimizations are turned
131-
//
132-
static int8_t utf8Codepoint(const uint8_t *utf8, uint32_t *codepointp)
133-
{
134-
const uint32_t CODEPOINT_LOWEST_SURROGATE_HALF = 0xD800;
135-
const uint32_t CODEPOINT_HIGHEST_SURROGATE_HALF = 0xDFFF;
136-
137-
*codepointp = 0xFFFD; // always initialize output to known value ... 0xFFFD (REPLACEMENT CHARACTER) seems the natural choice
138-
int codepoint;
139-
int len;
140-
141-
// The upper bits define both the length of additional bytes for the multi-byte encoding,
142-
// as well as defining how many bits of the first byte are included in the codepoint.
143-
// Each additional byte starts with 0b10xxxxxx, encoding six additional bits for the codepoint.
144-
//
145-
// For key summary points, see:
146-
// * https://tools.ietf.org/html/rfc3629#section-3
147-
//
148-
if (isInvalidUtf8Octet(utf8[0])) { // do not allow illegal octet sequences (e.g., 0xC0 0x80 should NOT decode to NULL)
149-
return -1;
150-
}
151-
152-
if (utf8[0] < 0x80) { // characters 0000 0000..0000 007F (up to 7 significant bits)
153-
len = 1;
154-
codepoint = utf8[0];
155-
} else if ((utf8[0] & 0xe0) == 0xc0) { // characters 0000 0080..0000 07FF (up to 11 significant bits, so first byte encodes five bits)
156-
len = 2;
157-
codepoint = utf8[0] & 0x1f;
158-
} else if ((utf8[0] & 0xf0) == 0xe0) { // characters 0000 8000..0000 FFFF (up to 16 significant bits, so first byte encodes four bits)
159-
len = 3;
160-
codepoint = utf8[0] & 0x0f;
161-
} else if ((utf8[0] & 0xf8) == 0xf0) { // characters 0001 0000..0010 FFFF (up to 21 significant bits, so first byte encodes three bits)
162-
len = 4;
163-
codepoint = utf8[0] & 0x07;
164-
} else { // UTF-8 is defined to only map to Unicode -- 0x00000000..0x0010FFFF
165-
// 5-byte and 6-byte sequences are not legal per RFC3629
166-
return -1;
167-
}
168-
169-
for (int i = 1; i < len; i++) {
170-
if ((utf8[i] & 0xc0) != 0x80) {
171-
// the additional bytes in a valid UTF-8 multi-byte encoding cannot have either of the top two bits set
172-
// This is more restrictive than isInvalidUtf8Octet()
173-
return -1;
174-
}
175-
codepoint <<= 6; // each continuation byte adds six bits to the codepoint
176-
codepoint |= utf8[i] & 0x3f; // mask off the top two continuation bits, and add the six relevant bits
177-
}
178-
179-
// explicit validation to prevent overlong encodings
180-
if ( (len == 1) && ((codepoint < 0x000000) || (codepoint > 0x00007F))) {
181-
return -1;
182-
} else if ((len == 2) && ((codepoint < 0x000080) || (codepoint > 0x0007FF))) {
183-
return -1;
184-
} else if ((len == 3) && ((codepoint < 0x000800) || (codepoint > 0x00FFFF))) {
185-
return -1;
186-
} else if ((len == 4) && ((codepoint < 0x010000) || (codepoint > 0x10FFFF))) {
187-
// "You might expect larger code points than U+10FFFF
188-
// to be expressible, but Unicode is limited in Sections 12
189-
// of RFC3629 to match the limits of UTF-16." -- Wikipedia UTF-8 note
190-
// See https://tools.ietf.org/html/rfc3629#section-12
191-
return -1;
192-
}
193-
194-
// high and low surrogate halves (U+D800 through U+DFFF) used by UTF-16 are
195-
// not legal Unicode values ... see RFC 3629.
196-
if ((codepoint >= CODEPOINT_LOWEST_SURROGATE_HALF) && (codepoint <= CODEPOINT_HIGHEST_SURROGATE_HALF)) {
197-
return -1;
198-
}
199-
200-
*codepointp = codepoint;
201-
return len;
202-
}
203-
204-
205-
static int strcpy_utf16(const char *s, uint16_t *buf, int bufsize)
206-
{
207-
int i = 0;
208-
int buflen = 0;
209-
210-
while (s[i] != 0) {
211-
uint32_t codepoint;
212-
int8_t utf8len = utf8Codepoint((const uint8_t *)s + i, &codepoint);
213-
214-
if (utf8len < 0) {
215-
// Invalid utf8 sequence, skip it
216-
i++;
217-
continue;
218-
}
219-
220-
i += utf8len;
221-
222-
if (codepoint <= 0xffff) {
223-
if (buflen == bufsize)
224-
break;
225-
226-
buf[buflen++] = codepoint;
227-
228-
} else {
229-
if (buflen + 1 >= bufsize)
230-
break;
231-
232-
// Surrogate pair
233-
codepoint -= 0x10000;
234-
buf[buflen++] = (codepoint >> 10) + 0xd800;
235-
buf[buflen++] = (codepoint & 0x3ff) + 0xdc00;
236-
}
237-
}
238-
239-
return buflen;
240-
}
241-
242-
243-
// Invoked when received GET STRING DESCRIPTOR request
244-
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
245-
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
246-
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
247-
const uint16_t * tud_descriptor_string_cb(uint8_t index, uint16_t langid)
248-
{
249-
(void) langid;
250-
251-
uint8_t chr_count;
252-
253-
switch (index)
254-
{
255-
case 0:
256-
_desc_str[1] = USBDevice.getLanguageDescriptor();
257-
chr_count = 1;
258-
break;
259-
case 1:
260-
chr_count = strcpy_utf16(USBDevice.getManufacturerDescriptor(), _desc_str + 1, 32);
261-
break;
262-
263-
case 2:
264-
chr_count = strcpy_utf16(USBDevice.getProductDescriptor(), _desc_str + 1, 32);
265-
break;
266-
267-
case 3:
268-
// serial Number
269-
chr_count = USBDevice.getSerialDescriptor(_desc_str+1);
270-
break;
271-
case 4:
272-
// interface name
273-
chr_count = strcpy_utf16("CMSIS-DAP", _desc_str + 1, 32);
274-
break;
275-
default: return NULL;
276-
}
277-
278-
// first byte is length (including header), second byte is string type
279-
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
280-
281-
return _desc_str;
282-
}
283-
284-
285-
286-
28795
void setup() {
96+
USBDevice.setProductDescriptor("CMSIS-DAP");
97+
28898
usb_hid.enableOutEndpoint(true);
28999
usb_hid.setPollInterval(2);
290100
usb_hid.setBootProtocol(0);
291-
USBDevice.setProductDescriptor("CMSIS-DAP");
101+
usb_hid.setStringDescriptor("CMSIS-DAP");
292102
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
293103
usb_hid.setReportCallback(get_report_callback, set_report_callback);
294104

295105
usb_hid.begin();
296106

297107
pinMode(LED_BUILTIN, OUTPUT);
298108

299-
Serial.begin(115200);
300-
baud = Serial.getBaud();
301-
old_baud = baud;
109+
baud = old_baud = 115200;
110+
Serial.begin(baud);
302111
SerialTTL.begin(baud);
303112

304113
// wait until device mounted
@@ -311,15 +120,12 @@ void setup() {
311120
USB_ResponseIdle = 1;
312121
free_count = FREE_COUNT_INIT;
313122
send_count = SEND_COUNT_INIT;
314-
315-
USBDevice.getSerialDescriptor(Serial_u16);
316-
317123
}
318124

319125

320126
void loop() {
321127
// put your main code here, to run repeatedly:
322-
baud = Serial.getBaud();
128+
baud = Serial.baud();
323129
if (baud != old_baud) {
324130
SerialTTL.begin(baud);
325131
while (!SerialTTL);
@@ -337,6 +143,7 @@ void loop() {
337143
Serial.write(c);
338144
}
339145
}
146+
340147
void hid_send_packet()
341148
{
342149
if (send_count) {

src/DAP.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ const char TargetDeviceVendor [] = TARGET_DEVICE_VENDOR;
8181
const char TargetDeviceName [] = TARGET_DEVICE_NAME;
8282
#endif
8383

84-
extern uint16_t Serial_u16[33];
8584
// Get DAP Information
8685
// id: info identifier
8786
// info: pointer to info data
@@ -104,8 +103,7 @@ static uint8_t DAP_Info(uint8_t id, uint8_t *info) {
104103
break;
105104
case DAP_ID_SER_NUM:
106105
#ifdef DAP_SER_NUM
107-
memcpy(info, &Serial_u16[0], 32);
108-
length = 32;
106+
length = USBDevice.getSerialDescriptor((uint16_t*) info);
109107
#endif
110108
break;
111109
case DAP_ID_FW_VER:

src/DAP_config.h

+10
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,16 @@ Provides definitions about:
183183
#define PIN_LED_CONNECTED PIN_LED_TXL
184184
#define PIN_LED_RUNNING PIN_LED_RXL
185185

186+
#else
187+
188+
#define PIN_SWDIO A0
189+
#define PIN_SWCLK A1
190+
#define PIN_TDO A3
191+
#define PIN_TDI A4
192+
#define PIN_nRESET A2
193+
#define PIN_LED_CONNECTED LED_BUILTIN
194+
#define PIN_LED_RUNNING LED_BUILTIN
195+
186196
#endif
187197
//**************************************************************************************************
188198
/**

src/board.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@
102102
#define BOARD_ID {1, 1, 1, 1}
103103
#define BOARD_SECRET {1, 1, 1, 1, 1, 1, 1, 1, 1}
104104

105+
#else // default for all other boards
106+
107+
#define BOARD_ID {1, 1, 1, 1}
108+
#define BOARD_SECRET {1, 1, 1, 1, 1, 1, 1, 1, 1}
109+
105110
#endif
106111

107112
#if !defined(BOARD_SECRET) || !defined(BOARD_ID)

0 commit comments

Comments
 (0)