Allow for get_hardware_id() to be used for serial number. (#24053)

* Allow for `get_hardware_id()` to be used for serial number.

* Length checks.

* Explain length.

* Cleanup.

* Preprocessor magic.

* Use the force, Batman.

* Swap logic; if SERIAL_NUMBER is defined use that, otherwise derive it.

* Cleanup.

* Cleanup.
This commit is contained in:
Nick Brassel 2024-10-06 21:44:36 +13:00 committed by GitHub
parent 65b5dc7e0f
commit 305e7baa71
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 82 additions and 13 deletions

View File

@ -5,3 +5,7 @@
#ifndef CORTEX_ENABLE_WFI_IDLE
# define CORTEX_ENABLE_WFI_IDLE TRUE
#endif // CORTEX_ENABLE_WFI_IDLE
#ifndef SERIAL_NUMBER_USE_HARDWARE_ID
# define SERIAL_NUMBER_USE_HARDWARE_ID TRUE
#endif // SERIAL_NUMBER_USE_HARDWARE_ID

View File

@ -49,6 +49,16 @@
# include "os_detection.h"
#endif
#if defined(SERIAL_NUMBER) || (defined(SERIAL_NUMBER_USE_HARDWARE_ID) && SERIAL_NUMBER_USE_HARDWARE_ID == TRUE)
# define HAS_SERIAL_NUMBER
# if defined(SERIAL_NUMBER_USE_HARDWARE_ID) && SERIAL_NUMBER_USE_HARDWARE_ID == TRUE
# include "hardware_id.h"
# endif
#endif // defined(SERIAL_NUMBER) || (defined(SERIAL_NUMBER_USE_HARDWARE_ID) && SERIAL_NUMBER_USE_HARDWARE_ID == TRUE)
// clang-format off
/*
@ -451,11 +461,11 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = {
.ReleaseNumber = DEVICE_VER,
.ManufacturerStrIndex = 0x01,
.ProductStrIndex = 0x02,
#if defined(SERIAL_NUMBER)
#ifdef HAS_SERIAL_NUMBER
.SerialNumStrIndex = 0x03,
#else
#else // HAS_SERIAL_NUMBER
.SerialNumStrIndex = 0x00,
#endif
#endif // HAS_SERIAL_NUMBER
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
};
@ -1037,9 +1047,13 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
/*
* String descriptors
*/
#define USB_DESCRIPTOR_SIZE_LITERAL_U16STRING(str) \
(sizeof(USB_Descriptor_Header_t) + sizeof(str) - sizeof(wchar_t)) // include header, don't count null terminator
const USB_Descriptor_String_t PROGMEM LanguageString = {
.Header = {
.Size = 4,
.Size = sizeof(USB_Descriptor_Header_t) + sizeof(uint16_t),
.Type = DTYPE_String
},
.UnicodeString = {LANGUAGE_ID_ENG}
@ -1047,7 +1061,7 @@ const USB_Descriptor_String_t PROGMEM LanguageString = {
const USB_Descriptor_String_t PROGMEM ManufacturerString = {
.Header = {
.Size = sizeof(USBSTR(MANUFACTURER)),
.Size = USB_DESCRIPTOR_SIZE_LITERAL_U16STRING(USBSTR(MANUFACTURER)),
.Type = DTYPE_String
},
.UnicodeString = USBSTR(MANUFACTURER)
@ -1055,24 +1069,70 @@ const USB_Descriptor_String_t PROGMEM ManufacturerString = {
const USB_Descriptor_String_t PROGMEM ProductString = {
.Header = {
.Size = sizeof(USBSTR(PRODUCT)),
.Size = USB_DESCRIPTOR_SIZE_LITERAL_U16STRING(USBSTR(PRODUCT)),
.Type = DTYPE_String
},
.UnicodeString = USBSTR(PRODUCT)
};
// clang-format on
#if defined(SERIAL_NUMBER)
// clang-format off
const USB_Descriptor_String_t PROGMEM SerialNumberString = {
.Header = {
.Size = sizeof(USBSTR(SERIAL_NUMBER)),
.Size = USB_DESCRIPTOR_SIZE_LITERAL_U16STRING(USBSTR(SERIAL_NUMBER)),
.Type = DTYPE_String
},
.UnicodeString = USBSTR(SERIAL_NUMBER)
};
#endif
// clang-format on
#else // defined(SERIAL_NUMBER)
# if defined(SERIAL_NUMBER_USE_HARDWARE_ID) && SERIAL_NUMBER_USE_HARDWARE_ID == TRUE
# if defined(__AVR__)
# error Dynamically setting the serial number on AVR is unsupported as LUFA requires the string to be in PROGMEM.
# endif // defined(__AVR__)
# ifndef SERIAL_NUMBER_LENGTH
# define SERIAL_NUMBER_LENGTH (sizeof(hardware_id_t) * 2)
# endif
# define SERIAL_NUMBER_DESCRIPTOR_SIZE \
(sizeof(USB_Descriptor_Header_t) /* Descriptor header */ \
+ (((SERIAL_NUMBER_LENGTH) + 1) * sizeof(wchar_t))) /* Length of serial number, with potential extra character as we're converting 2 nibbles at a time */
uint8_t SerialNumberString[SERIAL_NUMBER_DESCRIPTOR_SIZE] = {0};
void set_serial_number_descriptor(void) {
static bool is_set = false;
if (is_set) {
return;
}
is_set = true;
static const char hex_str[] = "0123456789ABCDEF";
hardware_id_t id = get_hardware_id();
USB_Descriptor_String_t* desc = (USB_Descriptor_String_t*)SerialNumberString;
// Copy across nibbles from the hardware ID as unicode hex characters
int length = MIN(sizeof(id) * 2, SERIAL_NUMBER_LENGTH);
uint8_t* p = (uint8_t*)&id;
for (int i = 0; i < length; i += 2) {
desc->UnicodeString[i + 0] = hex_str[p[i / 2] >> 4];
desc->UnicodeString[i + 1] = hex_str[p[i / 2] & 0xF];
}
desc->Header.Size = sizeof(USB_Descriptor_Header_t) + (length * sizeof(wchar_t)); // includes header, don't count null terminator
desc->Header.Type = DTYPE_String;
}
# endif // defined(SERIAL_NUMBER_USE_HARDWARE_ID) && SERIAL_NUMBER_USE_HARDWARE_ID == TRUE
#endif // defined(SERIAL_NUMBER)
/**
* This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
* documentation) by the application code so that the address and size of a requested descriptor can be given
@ -1114,13 +1174,18 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
Size = pgm_read_byte(&ProductString.Header.Size);
break;
#if defined(SERIAL_NUMBER)
#ifdef HAS_SERIAL_NUMBER
case 0x03:
Address = &SerialNumberString;
Size = pgm_read_byte(&SerialNumberString.Header.Size);
Address = (const USB_Descriptor_String_t*)&SerialNumberString;
# if defined(SERIAL_NUMBER)
Size = pgm_read_byte(&SerialNumberString.Header.Size);
# else
set_serial_number_descriptor();
Size = ((const USB_Descriptor_String_t*)SerialNumberString)->Header.Size;
# endif
break;
#endif
#endif // HAS_SERIAL_NUMBER
}
#ifdef OS_DETECTION_ENABLE
process_wlength(wLength);