From 18985ac84f66ba55811c3decb1884af13e03623b Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 28 Jun 2024 20:10:16 +0200 Subject: [PATCH 1/3] provide unique sernum: https://github.com/erikkaashoek/tinySA/issues/85 create a 12 char string based on the Arduino algorithm https://github.com/limbongofficial/STM32_Core-Arduino/blob/master/cores/arduino/stm32/usb/usbd_desc.c#L326-L370 Signed-off-by: Martin --- usbcfg.c | 116 ++++++++++++++++++++++++------------------------------- 1 file changed, 51 insertions(+), 65 deletions(-) diff --git a/usbcfg.c b/usbcfg.c index 398e3cb..902421e 100644 --- a/usbcfg.c +++ b/usbcfg.c @@ -175,74 +175,15 @@ static const uint8_t vcom_string2[] = { }; #endif -#ifdef TINYSA4 /* - * Serial Number string. VERSION = 'tinySA4_v1.3-nnn-gxxxxxxx' - * 01234567890123456789012 - * skip last two 'xx' char due to 'tinySA4_v1.3-n-gxxxxxxx' + * Serial number string */ -static const uint8_t vcom_string3[] = -{ -#if 1 - USB_DESC_BYTE(8), /* bLength. */ +#define USB_SIZ_STRING_SERIAL (2 + 24) +static uint8_t vcom_string3[USB_SIZ_STRING_SERIAL] = { + USB_DESC_BYTE(USB_SIZ_STRING_SERIAL), /* bLength. */ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ - '0' + CH_KERNEL_MAJOR, 0, - '0' + CH_KERNEL_MINOR, 0, - '0' + CH_KERNEL_PATCH, 0 -#else - USB_DESC_BYTE(32), /* bLength. */ - USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ - VERSION[8], 0, /* 'v' */ - VERSION[9], 0, /* '1' */ - VERSION[10], 0, /* '.' */ - VERSION[11], 0, /* '3' */ - VERSION[12], 0, /* '-' */ - VERSION[13], 0, /* 'n' */ - VERSION[14], 0, /* 'n' */ - VERSION[15], 0, /* 'n' */ - VERSION[16], 0, /* '-' */ - VERSION[17], 0, /* 'g' */ - VERSION[18], 0, /* 'x' */ - VERSION[19], 0, /* 'x' */ - VERSION[20], 0, /* 'x' */ - VERSION[21], 0, /* 'x' */ - VERSION[22], 0, /* 'x' */ -#endif -}; -#else -/* - * Serial Number string. VERSION = 'tinySA_v1.3-nnn-gxxxxxxx' - * 0123456789012345678901 - * skip last two 'xx' char due to 'tinySA_v1.3-n-gxxxxxxx' - */ -static const uint8_t vcom_string3[] = { -#if 1 - USB_DESC_BYTE(8), /* bLength. */ - USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ - '0' + CH_KERNEL_MAJOR, 0, - '0' + CH_KERNEL_MINOR, 0, - '0' + CH_KERNEL_PATCH, 0 -#else - USB_DESC_BYTE(32), /* bLength. */ - USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ - VERSION[7], 0, /* 'v' */ - VERSION[8], 0, /* '1' */ - VERSION[9], 0, /* '.' */ - VERSION[10], 0, /* '3' */ - VERSION[11], 0, /* '-' */ - VERSION[12], 0, /* 'n' */ - VERSION[13], 0, /* 'n' */ - VERSION[14], 0, /* 'n' */ - VERSION[15], 0, /* '-' */ - VERSION[16], 0, /* 'g' */ - VERSION[17], 0, /* 'x' */ - VERSION[18], 0, /* 'x' */ - VERSION[19], 0, /* 'x' */ - VERSION[20], 0, /* 'x' */ - VERSION[21], 0, /* 'x' */ -#endif + /* here goes the 12 char string encoded as UTF-16 (one ASCII, one 0x00) */ }; -#endif /* * Strings wrappers array. @@ -254,6 +195,48 @@ static const USBDescriptor vcom_strings[] = { {sizeof vcom_string3, vcom_string3} }; + +/** + * @brief Convert Hex 32Bits value into char + * @param value: value to convert + * @param pbuf: pointer to the buffer + * @param len: buffer length + * @retval None + */ +static void int_to_unicode(uint32_t value, uint8_t *pbuf, uint8_t len) +{ + uint8_t idx = 0; + for (idx = 0 ; idx < len ; idx ++) { + if (((value >> 28)) < 0xA) { + pbuf[ 2 * idx] = (value >> 28) + '0'; + } else { + pbuf[2 * idx] = (value >> 28) + 'A' - 10; + } + value = value << 4; + pbuf[ 2 * idx + 1] = 0; + } +} + +/** + * @brief Create the serial number string descriptor + * @param None + * @retval None + * inspired by: + * https://github.com/limbongofficial/STM32_Core-Arduino/blob/master/cores/arduino/stm32/usb/usbd_desc.c#L326-L370 + */ +static void prepare_sernum_str(void) +{ + uint32_t deviceserial0, deviceserial1, deviceserial2; + deviceserial0 = *(uint32_t *)0x1FFFF7AC; + deviceserial1 = *(uint32_t *)0x1FFFF7B0; + deviceserial2 = *(uint32_t *)0x1FFFF7B4; + deviceserial0 += deviceserial2; + if (deviceserial0 != 0) { + int_to_unicode(deviceserial0, &vcom_string3[2], 8); + int_to_unicode(deviceserial1, &vcom_string3[18], 4); + } +} + /* * Handles the GET_DESCRIPTOR callback. All required descriptors must be * handled here. @@ -271,8 +254,11 @@ static const USBDescriptor *get_descriptor(USBDriver *usbp, case USB_DESCRIPTOR_CONFIGURATION: return &vcom_configuration_descriptor; case USB_DESCRIPTOR_STRING: - if (dindex < 4) + if (dindex < 4) { + if ( dindex == 3 && vcom_string3[2] == 0 ) // not yet done + prepare_sernum_str(); return &vcom_strings[dindex]; + } } return NULL; } From 51a6fc69cf385ea0959f2d8652360e375faa6198 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 29 Jun 2024 19:59:42 +0200 Subject: [PATCH 2/3] formatting Signed-off-by: Martin --- usbcfg.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/usbcfg.c b/usbcfg.c index 902421e..b6c5e06 100644 --- a/usbcfg.c +++ b/usbcfg.c @@ -176,7 +176,7 @@ static const uint8_t vcom_string2[] = { #endif /* - * Serial number string + * Serial Number string. */ #define USB_SIZ_STRING_SERIAL (2 + 24) static uint8_t vcom_string3[USB_SIZ_STRING_SERIAL] = { @@ -195,7 +195,6 @@ static const USBDescriptor vcom_strings[] = { {sizeof vcom_string3, vcom_string3} }; - /** * @brief Convert Hex 32Bits value into char * @param value: value to convert @@ -203,8 +202,7 @@ static const USBDescriptor vcom_strings[] = { * @param len: buffer length * @retval None */ -static void int_to_unicode(uint32_t value, uint8_t *pbuf, uint8_t len) -{ +static void int_to_unicode(uint32_t value, uint8_t *pbuf, uint8_t len) { uint8_t idx = 0; for (idx = 0 ; idx < len ; idx ++) { if (((value >> 28)) < 0xA) { @@ -221,11 +219,10 @@ static void int_to_unicode(uint32_t value, uint8_t *pbuf, uint8_t len) * @brief Create the serial number string descriptor * @param None * @retval None - * inspired by: + * format and algorithm inspired by: * https://github.com/limbongofficial/STM32_Core-Arduino/blob/master/cores/arduino/stm32/usb/usbd_desc.c#L326-L370 */ -static void prepare_sernum_str(void) -{ +static void prepare_sernum_str(void) { uint32_t deviceserial0, deviceserial1, deviceserial2; deviceserial0 = *(uint32_t *)0x1FFFF7AC; deviceserial1 = *(uint32_t *)0x1FFFF7B0; From e7d2c0f8d79968b14874e5ba494baf0625f069a2 Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 8 Jul 2024 23:27:41 +0200 Subject: [PATCH 3/3] Switch to DiSlord's UID algorithm with radix32 encoding [0-9,A-V] Signed-off-by: Martin --- usbcfg.c | 88 ++++++++++++++++++++++---------------------------------- 1 file changed, 35 insertions(+), 53 deletions(-) diff --git a/usbcfg.c b/usbcfg.c index b6c5e06..e6a77ef 100644 --- a/usbcfg.c +++ b/usbcfg.c @@ -15,10 +15,17 @@ */ #include "hal.h" +#include "nanovna.h" /* Virtual serial port over USB.*/ SerialUSBDriver SDU1; +enum { + STR_LANG_ID = 0, + STR_MANUFACTURER, + STR_PRODUCT, + STR_SERIAL +}; /* * Endpoints to be used for USBD1. */ @@ -175,63 +182,39 @@ static const uint8_t vcom_string2[] = { }; #endif -/* - * Serial Number string. - */ -#define USB_SIZ_STRING_SERIAL (2 + 24) -static uint8_t vcom_string3[USB_SIZ_STRING_SERIAL] = { - USB_DESC_BYTE(USB_SIZ_STRING_SERIAL), /* bLength. */ - USB_DESC_BYTE(USB_DESCRIPTOR_STRING), /* bDescriptorType. */ - /* here goes the 12 char string encoded as UTF-16 (one ASCII, one 0x00) */ -}; - /* * Strings wrappers array. */ static const USBDescriptor vcom_strings[] = { {sizeof vcom_string0, vcom_string0}, {sizeof vcom_string1, vcom_string1}, - {sizeof vcom_string2, vcom_string2}, - {sizeof vcom_string3, vcom_string3} + {sizeof vcom_string2, vcom_string2} }; -/** - * @brief Convert Hex 32Bits value into char - * @param value: value to convert - * @param pbuf: pointer to the buffer - * @param len: buffer length - * @retval None - */ -static void int_to_unicode(uint32_t value, uint8_t *pbuf, uint8_t len) { - uint8_t idx = 0; - for (idx = 0 ; idx < len ; idx ++) { - if (((value >> 28)) < 0xA) { - pbuf[ 2 * idx] = (value >> 28) + '0'; - } else { - pbuf[2 * idx] = (value >> 28) + 'A' - 10; - } - value = value << 4; - pbuf[ 2 * idx + 1] = 0; - } -} - -/** - * @brief Create the serial number string descriptor - * @param None - * @retval None - * format and algorithm inspired by: - * https://github.com/limbongofficial/STM32_Core-Arduino/blob/master/cores/arduino/stm32/usb/usbd_desc.c#L326-L370 - */ -static void prepare_sernum_str(void) { - uint32_t deviceserial0, deviceserial1, deviceserial2; - deviceserial0 = *(uint32_t *)0x1FFFF7AC; - deviceserial1 = *(uint32_t *)0x1FFFF7B0; - deviceserial2 = *(uint32_t *)0x1FFFF7B4; - deviceserial0 += deviceserial2; - if (deviceserial0 != 0) { - int_to_unicode(deviceserial0, &vcom_string3[2], 8); - int_to_unicode(deviceserial1, &vcom_string3[18], 4); +// Use unique serial string generated from MCU id +#define UID_RADIX 5 // Radix conversion constant (5 bit, use 0..9 and A..V) +#define USB_SERIAL_STRING_SIZE ((64 + UID_RADIX -1) / UID_RADIX) // Result string size +USBDescriptor *getSerialStringDescriptor(void) { + uint16_t i; + uint16_t *buf = ((uint16_t *)&spi_buffer[ARRAY_COUNT(spi_buffer)]) - ((USB_SERIAL_STRING_SIZE + 3) & ~3); // 32 bit align + USBDescriptor *d = ((USBDescriptor *)buf) - 1; + uint32_t id0 = *(uint32_t *)0x1FFFF7AC; // MCU id0 address + uint32_t id1 = *(uint32_t *)0x1FFFF7B0; // MCU id1 address + uint32_t id2 = *(uint32_t *)0x1FFFF7B4; // MCU id2 address + uint64_t uid = id1; + uid = (id0 + id2) | (uid<<32); // generate unique 64bit ID + // Prepare serial string descriptor from 64 bit ID + for(i = 1; i < USB_SERIAL_STRING_SIZE + 1; i++) { + uint16_t c = uid & ((1<>= UID_RADIX; } + uint16_t size = i * sizeof(uint16_t); + buf[0] = size | (USB_DESCRIPTOR_STRING << 8); + // Generate USBDescriptor structure + d->ud_size = size; + d->ud_string = (uint8_t *)buf; + return d; } /* @@ -242,7 +225,6 @@ static const USBDescriptor *get_descriptor(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang) { - (void)usbp; (void)lang; switch (dtype) { @@ -251,11 +233,11 @@ static const USBDescriptor *get_descriptor(USBDriver *usbp, case USB_DESCRIPTOR_CONFIGURATION: return &vcom_configuration_descriptor; case USB_DESCRIPTOR_STRING: - if (dindex < 4) { - if ( dindex == 3 && vcom_string3[2] == 0 ) // not yet done - prepare_sernum_str(); + // send unique USB serial string if need + if (dindex == STR_SERIAL) + return getSerialStringDescriptor(); + if (dindex < STR_SERIAL) return &vcom_strings[dindex]; - } } return NULL; }