diff --git a/keyboards/lotus/dyn_serial.c b/keyboards/lotus/dyn_serial.c new file mode 100644 index 0000000000..94fc8e52b8 --- /dev/null +++ b/keyboards/lotus/dyn_serial.c @@ -0,0 +1,51 @@ +// Copyright 2022 Framework Computer +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "quantum.h" +#include "dyn_serial.h" +#include "usb_descriptor.h" +#include "usb_descriptor_common.h" + +// Prefix string literal with L for descriptors +#ifdef SERIAL_NUMBER +USB_Descriptor_String_t PROGMEM SerialNumberString = { + .Header = { + .Size = sizeof(FALLBACK_SERIAL_NUMBER), + .Type = DTYPE_String + }, + .UnicodeString = FALLBACK_SERIAL_NUMBER +}; + +char ascii_serialnum[SERIALNUM_LEN+1]; + +void *dyn_serial_number_string(void) { + // Exit early, if it was previously read and converted + if (ascii_serialnum[0] != '\0' || ascii_serialnum[0] == 0xFF) { + return &SerialNumberString; + } + + // Read ASCII serial number from memory-mapped flash + char *serialnum_ptr = (char*) (FLASH_OFFSET + LAST_4K_BLOCK); + memcpy(ascii_serialnum, serialnum_ptr, SERIALNUM_LEN); + + // Just keep fallback serialnumber if the flash is erased + if (ascii_serialnum[0] == 0xFF) { + return &SerialNumberString; + } + + // Convert to UCS-2, which is equivalent to UTF-16, if the input is ASCII + for (int i = 0; i < SERIALNUM_LEN; i++) { + if (ascii_serialnum[i] > 128) { + dprintf("Serial number character %d is not valid ASCII.", ascii_serialnum[i]); + SerialNumberString.Header.Size = i * 2; + break; + } + SerialNumberString.UnicodeString[i] = ascii_serialnum[i]; + } + + return &SerialNumberString; +} +uint16_t dyn_serial_number_string_len(void) { + return pgm_read_byte(&SerialNumberString.Header.Size); +} +#endif diff --git a/keyboards/lotus/dyn_serial.h b/keyboards/lotus/dyn_serial.h new file mode 100644 index 0000000000..dcd2f3b4fb --- /dev/null +++ b/keyboards/lotus/dyn_serial.h @@ -0,0 +1,21 @@ +// Copyright 2022 Framework Computer +// SPDX-License-Identifier: GPL-2.0-or-later + +//#include "quantum.h" + +void *dyn_serial_number_string(void); +uint16_t dyn_serial_number_string_len(void); +// The serial number is written to the last 4K block in the first 1M of flash +#define FLASH_OFFSET 0x10000000 +#define LAST_4K_BLOCK 0xff000 +#define SERIALNUM_LEN 18 + +// 18-digit serial number. Must be programmed at factory +// TODO: Figure out how to do that. Probably a script to compile qmk +// Must be wide-string (UTF-16) +// KDK = Keyboard RGB Backlight +// KDW = Keyboard White Backlight +// KDN = Keyboard RGB Gridpad +// KDM = Keyboard White Numpad +#define FALLBACK_SERIAL_NUMBER L"FRAKDKEN0100000000" +_Static_assert(sizeof(FALLBACK_SERIAL_NUMBER) == (SERIALNUM_LEN+1)*2, "Fallback serial number must be same length"); diff --git a/keyboards/lotus/factory.c b/keyboards/lotus/factory.c index 425d330d0c..2a6a9c7ebd 100644 --- a/keyboards/lotus/factory.c +++ b/keyboards/lotus/factory.c @@ -8,6 +8,9 @@ #if defined(RGB_MATRIX_ENABLE) #include "rgb_matrix.h" #endif +#ifdef SERIAL_NUMBER +#include "dyn_serial.h" +#endif enum factory_commands { f_emu_keypress = 0x01, // Next byte is keycode diff --git a/keyboards/lotus/lotus.c b/keyboards/lotus/lotus.c index 817424184c..95d935c199 100644 --- a/keyboards/lotus/lotus.c +++ b/keyboards/lotus/lotus.c @@ -4,53 +4,6 @@ #include "quantum.h" #include "lotus.h" -#include "usb_descriptor.h" -#include "usb_descriptor_common.h" - -// Prefix string literal with L for descriptors -#ifdef SERIAL_NUMBER -USB_Descriptor_String_t PROGMEM SerialNumberString = { - .Header = { - .Size = sizeof(FALLBACK_SERIAL_NUMBER), - .Type = DTYPE_String - }, - .UnicodeString = FALLBACK_SERIAL_NUMBER -}; - -char ascii_serialnum[SERIALNUM_LEN+1]; - -void *lotus_serial_number_string(void) { - // Exit early, if it was previously read and converted - if (ascii_serialnum[0] != '\0' || ascii_serialnum[0] == 0xFF) { - return &SerialNumberString; - } - - // Read ASCII serial number from memory-mapped flash - char *serialnum_ptr = (char*) (FLASH_OFFSET + LAST_4K_BLOCK); - memcpy(ascii_serialnum, serialnum_ptr, SERIALNUM_LEN); - - // Just keep fallback serialnumber if the flash is erased - if (ascii_serialnum[0] == 0xFF) { - return &SerialNumberString; - } - - // Convert to UCS-2, which is equivalent to UTF-16, if the input is ASCII - for (int i = 0; i < SERIALNUM_LEN; i++) { - if (ascii_serialnum[i] > 128) { - dprintf("Serial number character %d is not valid ASCII.", ascii_serialnum[i]); - SerialNumberString.Header.Size = i * 2; - break; - } - SerialNumberString.UnicodeString[i] = ascii_serialnum[i]; - } - - return &SerialNumberString; -} -uint16_t lotus_serial_number_string_len(void) { - return pgm_read_byte(&SerialNumberString.Header.Size); -} -#endif - void keyboard_post_init_kb(void) { keyboard_post_init_user(); diff --git a/keyboards/lotus/lotus.h b/keyboards/lotus/lotus.h index 22a551d8b3..5ff87a8b61 100644 --- a/keyboards/lotus/lotus.h +++ b/keyboards/lotus/lotus.h @@ -32,20 +32,3 @@ enum lotus_keycodes { #else #define IS31FL3743A_ENABLE_GPIO GP29 #endif - -void *lotus_serial_number_string(void); -uint16_t lotus_serial_number_string_len(void); -// The serial number is written to the last 4K block in the first 1M of flash -#define FLASH_OFFSET 0x10000000 -#define LAST_4K_BLOCK 0xff000 -#define SERIALNUM_LEN 18 - -// 18-digit serial number. Must be programmed at factory -// TODO: Figure out how to do that. Probably a script to compile qmk -// Must be wide-string (UTF-16) -// KDK = Keyboard RGB Backlight -// KDW = Keyboard White Backlight -// KDN = Keyboard RGB Gridpad -// KDM = Keyboard White Numpad -#define FALLBACK_SERIAL_NUMBER L"FRAKDKEN0100000000" -_Static_assert(sizeof(FALLBACK_SERIAL_NUMBER) == (SERIALNUM_LEN+1)*2, "Fallback serial number must be same length"); diff --git a/keyboards/lotus/rules.mk b/keyboards/lotus/rules.mk index 70dac84cc9..9944a70ab0 100644 --- a/keyboards/lotus/rules.mk +++ b/keyboards/lotus/rules.mk @@ -16,6 +16,6 @@ BACKLIGHT_DRIVER = pwm CUSTOM_MATRIX = lite SRC += matrix.c analog.c -SRC += factory.c +SRC += dyn_serial.c factory.c DEFAULT_FOLDER = lotus/ansi diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 6a6bc25673..6e710f659e 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -41,7 +41,7 @@ #include "usb_descriptor.h" #include "usb_descriptor_common.h" -#include "lotus.h" +#include "dyn_serial.h" #ifdef JOYSTICK_ENABLE # include "joystick.h" @@ -1139,8 +1139,9 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const #if defined(SERIAL_NUMBER) case 0x03: // TODO: Give these functions a generic name and let anyone override it - Address = lotus_serial_number_string(); - Size = lotus_serial_number_string_len(); + // Framework 16 uses this + Address = dyn_serial_number_string(); + Size = dyn_serial_number_string_len(); break; #endif diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 65db49b043..a523843980 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -30,6 +30,7 @@ along with this program. If not, see . #include "debug.h" #include "wait.h" #include "usb_descriptor_common.h" +#include "dyn_serial.h" #ifdef RAW_ENABLE # include "raw_hid.h" @@ -761,7 +762,7 @@ const PROGMEM usbStringDescriptor_t usbStringDescriptorProduct = { .bString = USBSTR(PRODUCT) }; -// THIS IS NOT USED by Lotus. TODO: Implement flexible serial number here +// THIS IS NOT USED by Framework 16. TODO: Implement dynamic serial number here #if defined(SERIAL_NUMBER) const PROGMEM usbStringDescriptor_t usbStringDescriptorSerial = .header = { @@ -1035,8 +1036,9 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) { break; #if defined(SERIAL_NUMBER) case 3: // iSerialNumber - usbMsgPtr = (usbMsgPtr_t)lotus_serial_number_string(); - len = lotus_serial_number_string_len(); + // Not using this on Framework 16 + usbMsgPtr = (usbMsgPtr_t)dynamic_serial_number_string(); + len = dynamic_serial_number_string_len(); break; #endif }