diff options
author | Nick Brassel <[email protected]> | 2024-10-06 21:44:36 +1300 |
---|---|---|
committer | GitHub <[email protected]> | 2024-10-06 21:44:36 +1300 |
commit | 305e7baa71ccecf8c126863a7f439361dd9cc750 (patch) | |
tree | ee3cd9148d8545bfa2daa523c93cb959fd396a6f /tmk_core | |
parent | 65b5dc7e0f73ffb9983ab1ad3f2e2494a6c090d4 (diff) | |
download | qmk_firmware-305e7baa71ccecf8c126863a7f439361dd9cc750.tar.gz qmk_firmware-305e7baa71ccecf8c126863a7f439361dd9cc750.zip |
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.
Diffstat (limited to 'tmk_core')
-rw-r--r-- | tmk_core/protocol/usb_descriptor.c | 91 |
1 files changed, 78 insertions, 13 deletions
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 7efd085ea3..7454c9a7c4 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -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); |