usb: device_next: allow to limit number or digits in serial number

Add Kconfig option to limit the length requested from HWINFO to a
meaningful number of digits. Also, check the length returned by the
HWINFO driver and rename the variables to a more suitable name.

Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
This commit is contained in:
Johann Fischer 2025-06-17 10:20:46 +02:00 committed by Benjamin Cabé
commit 76579d21ab
2 changed files with 23 additions and 12 deletions

View file

@ -96,6 +96,16 @@ config USBD_MSG_WORK_DELAY
Message work may need to be delayed because the device stack is not Message work may need to be delayed because the device stack is not
yet ready to publish the message. The delay unit is milliseconds. yet ready to publish the message. The delay unit is milliseconds.
config USBD_HWINFO_DEVID_LENGTH
int "The length of the device ID requested from HWINFO in bytes"
depends on HWINFO
range 8 128
default 16
help
Each byte represents two digits in the serial number string
descriptor. This option can be used to limit the length requested
from HWINFO to a meaningful number of digits.
rsource "class/Kconfig" rsource "class/Kconfig"
rsource "app/Kconfig.cdc_acm_serial" rsource "app/Kconfig.cdc_acm_serial"

View file

@ -533,13 +533,13 @@ static int sreq_get_desc_cfg(struct usbd_context *const uds_ctx,
return 0; return 0;
} }
#define USBD_HWID_SN_MAX 32U #define USBD_SN_ASCII7_LENGTH (CONFIG_USBD_HWINFO_DEVID_LENGTH * 2)
/* Generate valid USB device serial number from hwid */ /* Generate valid USB device serial number from hwid */
static ssize_t get_sn_from_hwid(uint8_t sn[static USBD_HWID_SN_MAX]) static ssize_t get_sn_from_hwid(uint8_t sn[static USBD_SN_ASCII7_LENGTH])
{ {
static const char hex[] = "0123456789ABCDEF"; static const char hex[] = "0123456789ABCDEF";
uint8_t hwid[USBD_HWID_SN_MAX / 2U]; uint8_t hwid[USBD_SN_ASCII7_LENGTH / 2U];
ssize_t hwid_len = -ENOSYS; ssize_t hwid_len = -ENOSYS;
if (IS_ENABLED(CONFIG_HWINFO)) { if (IS_ENABLED(CONFIG_HWINFO)) {
@ -554,36 +554,37 @@ static ssize_t get_sn_from_hwid(uint8_t sn[static USBD_HWID_SN_MAX])
return hwid_len; return hwid_len;
} }
for (ssize_t i = 0; i < hwid_len; i++) { for (ssize_t i = 0; i < MIN(hwid_len, sizeof(hwid)); i++) {
sn[i * 2] = hex[hwid[i] >> 4]; sn[i * 2] = hex[hwid[i] >> 4];
sn[i * 2 + 1] = hex[hwid[i] & 0xF]; sn[i * 2 + 1] = hex[hwid[i] & 0xF];
} }
return hwid_len * 2; return MIN(hwid_len, sizeof(hwid)) * 2;
} }
/* Copy and convert ASCII-7 string descriptor to UTF16-LE */ /* Copy and convert ASCII-7 string descriptor to UTF16-LE */
static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn,
struct net_buf *const buf, const uint16_t wLength) struct net_buf *const buf, const uint16_t wLength)
{ {
uint8_t hwid_sn[USBD_HWID_SN_MAX]; uint8_t sn_ascii7_str[USBD_SN_ASCII7_LENGTH];
struct usb_desc_header head = { struct usb_desc_header head = {
.bDescriptorType = dn->bDescriptorType, .bDescriptorType = dn->bDescriptorType,
}; };
uint8_t *ascii7_str; const uint8_t *ascii7_str;
size_t len; size_t len;
size_t i; size_t i;
if (dn->str.utype == USBD_DUT_STRING_SERIAL_NUMBER && dn->str.use_hwinfo) { if (IS_ENABLED(CONFIG_HWINFO) &&
ssize_t hwid_len = get_sn_from_hwid(hwid_sn); dn->str.utype == USBD_DUT_STRING_SERIAL_NUMBER && dn->str.use_hwinfo) {
ssize_t sn_ascii7_str_len = get_sn_from_hwid(sn_ascii7_str);
if (hwid_len < 0) { if (sn_ascii7_str_len < 0) {
errno = -ENOTSUP; errno = -ENOTSUP;
return; return;
} }
head.bLength = sizeof(head) + hwid_len * 2; head.bLength = sizeof(head) + sn_ascii7_str_len * 2;
ascii7_str = hwid_sn; ascii7_str = sn_ascii7_str;
} else { } else {
head.bLength = dn->bLength; head.bLength = dn->bLength;
ascii7_str = (uint8_t *)dn->ptr; ascii7_str = (uint8_t *)dn->ptr;