Skip to content

Commit 041f510

Browse files
committed
add board_get_unique_id() for serial number
implemented board_get_unique_id() for rp2040 and L4
1 parent 1324c28 commit 041f510

File tree

6 files changed

+124
-62
lines changed

6 files changed

+124
-62
lines changed

examples/device/cdc_msc/src/usb_descriptors.c

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*
2424
*/
2525

26+
#include "bsp/board_api.h"
2627
#include "tusb.h"
2728

2829
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
@@ -236,6 +237,14 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
236237
// String Descriptors
237238
//--------------------------------------------------------------------+
238239

240+
// String Descriptor Index
241+
enum {
242+
STRID_LANGID = 0,
243+
STRID_MANUFACTURER,
244+
STRID_PRODUCT,
245+
STRID_SERIAL,
246+
};
247+
239248
// array of pointer to string descriptors
240249
char const* string_desc_arr [] =
241250
{
@@ -247,38 +256,43 @@ char const* string_desc_arr [] =
247256
"TinyUSB MSC", // 5: MSC Interface
248257
};
249258

250-
static uint16_t _desc_str[32];
259+
static uint16_t _desc_str[32+1];
251260

252261
// Invoked when received GET STRING DESCRIPTOR request
253262
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
254263
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
255264
{
256265
(void) langid;
257266

258-
uint8_t chr_count;
267+
size_t chr_count;
268+
269+
switch(index) {
270+
case STRID_LANGID:
271+
memcpy(&_desc_str[1], string_desc_arr[0], 2);
272+
chr_count = 1;
273+
break;
274+
275+
case STRID_SERIAL:
276+
chr_count = board_usb_get_serial(_desc_str+1, 32);
277+
break;
259278

260-
if ( index == 0)
261-
{
262-
memcpy(&_desc_str[1], string_desc_arr[0], 2);
263-
chr_count = 1;
264-
}else
265-
{
266-
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
267-
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
279+
default:
280+
// Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
281+
// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
268282

269-
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
283+
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
270284

271-
const char* str = string_desc_arr[index];
285+
const char* str = string_desc_arr[index];
272286

273-
// Cap at max char
274-
chr_count = (uint8_t) strlen(str);
275-
if ( chr_count > 31 ) chr_count = 31;
287+
// Cap at max char
288+
chr_count = strlen(str);
289+
if ( chr_count > 31 ) chr_count = 31;
276290

277-
// Convert ASCII string into UTF-16
278-
for(uint8_t i=0; i<chr_count; i++)
279-
{
280-
_desc_str[1+i] = str[i];
281-
}
291+
// Convert ASCII string into UTF-16
292+
for(size_t i=0; i<chr_count; i++) {
293+
_desc_str[1+i] = str[i];
294+
}
295+
break;
282296
}
283297

284298
// first byte is length (including header), second byte is string type

hw/bsp/board_api.h

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,13 @@ void board_led_write(bool state);
6060
// a '1' means active (pressed), a '0' means inactive.
6161
uint32_t board_button_read(void);
6262

63-
// Get characters from UART
64-
// Return number of read bytes
63+
// Get board unique ID for USB serial number. Return number of bytes. Note max_len is typically 16
64+
TU_ATTR_WEAK size_t board_get_unique_id(uint8_t id[], size_t max_len);
65+
66+
// Get characters from UART. Return number of read bytes
6567
int board_uart_read(uint8_t *buf, int len);
6668

67-
// Send characters to UART
68-
// Return number of sent bytes
69+
// Send characters to UART. Return number of sent bytes
6970
int board_uart_write(void const *buf, int len);
7071

7172
#if CFG_TUSB_OS == OPT_OS_NONE
@@ -108,6 +109,37 @@ static inline void board_led_off(void) {
108109
board_led_write(false);
109110
}
110111

112+
// Get USB Serial number string from unique ID if available. Return number of character.
113+
// Input is string descriptor from index 1 (index 0 is type + len)
114+
static inline size_t board_usb_get_serial(uint16_t desc_str1[], size_t max_chars) {
115+
uint8_t serial_id[16] TU_ATTR_ALIGNED(4);
116+
size_t serial_len;
117+
118+
if ( board_get_unique_id ) {
119+
serial_len = board_get_unique_id(serial_id, sizeof(serial_id));
120+
}else {
121+
// fixed serial string is 01234567889ABCDEF
122+
*((uint32_t*)(uintptr_t) serial_id) = 0x67452301;
123+
*((uint32_t*)(uintptr_t) (serial_id+4)) = 0xEFCDAB89;
124+
serial_len = 8;
125+
}
126+
127+
if ( serial_len > max_chars / 2 ) serial_len = max_chars / 2;
128+
129+
for ( size_t i = 0; i < serial_len; i++ ) {
130+
for ( size_t j = 0; j < 2; j++ ) {
131+
const char nibble_to_hex[16] = {
132+
'0', '1', '2', '3', '4', '5', '6', '7',
133+
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
134+
};
135+
uint8_t const nibble = (serial_id[i] >> (j * 4)) & 0xf;
136+
desc_str1[i * 2 + (1 - j)] = nibble_to_hex[nibble]; // UTF-16-LE
137+
}
138+
}
139+
140+
return 2*serial_len;
141+
}
142+
111143
// TODO remove
112144
static inline void board_delay(uint32_t ms) {
113145
uint32_t start_ms = board_millis();

hw/bsp/family_support.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,8 @@ function(family_add_default_example_warnings TARGET)
289289
-Wfatal-errors
290290
-Wdouble-promotion
291291
-Wfloat-equal
292-
-Wshadow
292+
# FIXME commented out because of https://github.com/raspberrypi/pico-sdk/issues/1468
293+
#-Wshadow
293294
-Wwrite-strings
294295
-Wsign-compare
295296
-Wmissing-format-attribute

hw/bsp/rp2040/family.c

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "pico/stdlib.h"
2929
#include "pico/binary_info.h"
30+
#include "pico/unique_id.h"
3031
#include "hardware/gpio.h"
3132
#include "hardware/sync.h"
3233
#include "hardware/structs/ioqspi.h"
@@ -171,30 +172,37 @@ void board_init(void)
171172
// Board porting API
172173
//--------------------------------------------------------------------+
173174

174-
void board_led_write(bool state)
175-
{
175+
void board_led_write(bool state) {
176176
(void) state;
177177

178178
#ifdef LED_PIN
179-
gpio_put(LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
179+
gpio_put(LED_PIN, state ? LED_STATE_ON : (1 - LED_STATE_ON));
180180
#endif
181181
}
182182

183-
uint32_t board_button_read(void)
184-
{
183+
uint32_t board_button_read(void) {
185184
#ifdef BUTTON_BOOTSEL
186185
return BUTTON_STATE_ACTIVE == get_bootsel_button();
187186
#else
188187
return 0;
189188
#endif
190189
}
191190

192-
int board_uart_read(uint8_t* buf, int len)
193-
{
191+
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
192+
pico_unique_board_id_t pico_id;
193+
pico_get_unique_board_id(&pico_id);
194+
195+
size_t len = PICO_UNIQUE_BOARD_ID_SIZE_BYTES;
196+
if (len > max_len) len = max_len;
197+
198+
memcpy(id, pico_id.id, len);
199+
return len;
200+
}
201+
202+
int board_uart_read(uint8_t *buf, int len) {
194203
#ifdef UART_DEV
195204
int count = 0;
196-
while ( (count < len) && uart_is_readable(uart_inst) )
197-
{
205+
while ( (count < len) && uart_is_readable(uart_inst) ) {
198206
buf[count] = uart_getc(uart_inst);
199207
count++;
200208
}
@@ -205,11 +213,10 @@ int board_uart_read(uint8_t* buf, int len)
205213
#endif
206214
}
207215

208-
int board_uart_write(void const * buf, int len)
209-
{
216+
int board_uart_write(void const *buf, int len) {
210217
#ifdef UART_DEV
211-
char const* bufch = (char const*) buf;
212-
for(int i=0;i<len;i++) {
218+
char const *bufch = (char const *) buf;
219+
for ( int i = 0; i < len; i++ ) {
213220
uart_putc(uart_inst, bufch[i]);
214221
}
215222
return len;
@@ -219,8 +226,7 @@ int board_uart_write(void const * buf, int len)
219226
#endif
220227
}
221228

222-
int board_getchar(void)
223-
{
229+
int board_getchar(void) {
224230
return getchar_timeout_us(0);
225231
}
226232

hw/bsp/rp2040/family.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ target_sources(tinyusb_bsp INTERFACE
112112
target_include_directories(tinyusb_bsp INTERFACE
113113
${TOP}/hw
114114
)
115+
target_link_libraries(tinyusb_bsp INTERFACE pico_unique_id)
115116

116117
# tinyusb_additions will hold our extra settings for examples
117118
add_library(tinyusb_additions INTERFACE)

hw/bsp/stm32l4/family.c

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ void USB_IRQHandler(void)
4848

4949
UART_HandleTypeDef UartHandle;
5050

51-
void board_init(void)
52-
{
51+
void board_init(void) {
5352
board_clock_init();
5453

5554
// Enable All GPIOs clocks
@@ -177,51 +176,60 @@ void board_init(void)
177176
// Board porting API
178177
//--------------------------------------------------------------------+
179178

180-
void board_led_write(bool state)
181-
{
182-
GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1-LED_STATE_ON));
179+
void board_led_write(bool state) {
180+
GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON));
183181
HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state);
184182
}
185183

186-
uint32_t board_button_read(void)
187-
{
184+
uint32_t board_button_read(void) {
188185
return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);
189186
}
190187

191-
int board_uart_read(uint8_t* buf, int len)
192-
{
193-
(void) buf; (void) len;
188+
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
189+
(void) max_len;
190+
volatile uint32_t * stm32_uuid = (volatile uint32_t *) UID_BASE;
191+
192+
uint8_t const len = 12;
193+
uint32_t* id32 = (uint32_t*) (uintptr_t) id;
194+
195+
id32[0] = stm32_uuid[0];
196+
id32[1] = stm32_uuid[1];
197+
id32[2] = stm32_uuid[2];
198+
199+
return len;
200+
}
201+
202+
int board_uart_read(uint8_t *buf, int len) {
203+
(void) buf;
204+
(void) len;
194205
return 0;
195206
}
196207

197-
int board_uart_write(void const * buf, int len)
198-
{
199-
HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff);
208+
int board_uart_write(void const *buf, int len) {
209+
HAL_UART_Transmit(&UartHandle, (uint8_t *) (uintptr_t) buf, len, 0xffff);
200210
return len;
201211
}
202212

203-
#if CFG_TUSB_OS == OPT_OS_NONE
213+
#if CFG_TUSB_OS == OPT_OS_NONE
204214
volatile uint32_t system_ticks = 0;
205-
void SysTick_Handler (void)
206-
{
215+
216+
void SysTick_Handler(void) {
207217
HAL_IncTick();
208218
system_ticks++;
209219
}
210220

211-
uint32_t board_millis(void)
212-
{
221+
uint32_t board_millis(void) {
213222
return system_ticks;
214223
}
224+
215225
#endif
216226

217-
void HardFault_Handler (void)
218-
{
227+
void HardFault_Handler(void) {
219228
__asm("BKPT #0\n");
220229
}
221230

222231
// Required by __libc_init_array in startup code if we are compiling using
223232
// -nostdlib/-nostartfiles.
224-
void _init(void)
225-
{
233+
void _init(void) {
226234

227235
}

0 commit comments

Comments
 (0)