lotus: Clean up serial number code

More close to upstreaming ready.

Signed-off-by: Daniel Schaefer <dhs@frame.work>
This commit is contained in:
Daniel Schaefer 2023-01-17 11:29:52 +08:00
parent 4b95cad37d
commit 924ddf3296
5 changed files with 27 additions and 33 deletions

View File

@ -13,9 +13,8 @@
// SDB is mapped to GP22
#define PICO_LOTUS
// 18-digit serial number. Must be programmed at factory
// TODO: Figure out how to do that. Probably a script to compile qmk
#define SERIAL_NUMBER "FRALDLvvccxxxxxxxx"
// Enable serial number
#define SERIAL_NUMBER
#ifdef KEYBOARD_lotus_ansi
#define LED_CAPS_LOCK_PIN GP24

View File

@ -29,7 +29,6 @@ void emulate_rgb_keycode_press(uint16_t target_keycode) {
#endif
extern char ascii_serialnum[SERIALNUM_LEN+1];
extern char utf16_serialnum[(SERIALNUM_LEN+1) * 2];
void handle_factory_command(uint8_t *data) {
uint8_t factory_command_id = data[0];

View File

@ -9,43 +9,43 @@
#define USBSTR(s) USBCONCAT(L, s)
USB_Descriptor_String_t PROGMEM SerialNumberString = {
.Header = {
.Size = sizeof(USBSTR(SERIAL_NUMBER)),
.Size = sizeof(FALLBACK_SERIAL_NUMBER),
.Type = DTYPE_String
},
.UnicodeString = USBSTR(SERIAL_NUMBER)
.UnicodeString = FALLBACK_SERIAL_NUMBER
};
char ascii_serialnum[SERIALNUM_LEN+1];
char utf16_serialnum[(SERIALNUM_LEN+1) * 2];
void *lotus_serial_number_string(void) {
if (utf16_serialnum[0] != '\0') {
return utf16_serialnum;
// Exit early, if it was previously read and converted
if (ascii_serialnum[0] != '\0' || ascii_serialnum[0] == 0xFF) {
return &SerialNumberString;
}
ascii_serialnum[SERIALNUM_LEN] = '\0';
utf16_serialnum[SERIALNUM_LEN*2] = '\0';
utf16_serialnum[SERIALNUM_LEN*2 + 1] = '\0';
char *serialnum_ptr = (char*) (FLASH_OFFSET + LAST_4K_BLOCK);
// Read ASCII serial number from memory-mapped flash
char *serialnum_ptr = (char*) (FLASH_OFFSET + LAST_4K_BLOCK);
memcpy(ascii_serialnum, serialnum_ptr, SERIALNUM_LEN);
// Replace with dummy serialnumber if the flash is erased
// Just keep fallback serialnumber if the flash is erased
if (ascii_serialnum[0] == 0xFF) {
memcpy(ascii_serialnum, SERIAL_NUMBER, sizeof(SERIAL_NUMBER));
return &SerialNumberString;
}
for (int c = 0; c < SERIALNUM_LEN; c++) {
utf16_serialnum[c*2] = ascii_serialnum[c];
// 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];
}
//SerialNumberString.UnicodeString = &utf16_serialnum[0];
memcpy(SerialNumberString.UnicodeString, utf16_serialnum, SERIALNUM_LEN*2);
SerialNumberString.Header.Size = SERIALNUM_LEN * 2;
return &SerialNumberString;
}
uint16_t lotus_serial_number_string_len(void) {
return SERIALNUM_LEN*2;
return pgm_read_byte(&SerialNumberString.Header.Size);
}
void keyboard_post_init_kb(void) {

View File

@ -38,3 +38,9 @@ uint16_t lotus_serial_number_string_len(void);
#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)
#define FALLBACK_SERIAL_NUMBER L"FRALDLvvccxxxxxxxx"
_Static_assert(sizeof(FALLBACK_SERIAL_NUMBER) == (SERIALNUM_LEN+1)*2, "Fallback serial number must be same length");

View File

@ -1078,17 +1078,6 @@ const USB_Descriptor_String_t PROGMEM ProductString = {
.UnicodeString = USBSTR(PRODUCT)
};
#if defined(SERIAL_NUMBER)
extern const USB_Descriptor_String_t PROGMEM SerialNumberString;
//const USB_Descriptor_String_t PROGMEM SerialNumberString = {
// .Header = {
// .Size = sizeof(USBSTR(SERIAL_NUMBER)),
// .Type = DTYPE_String
// },
// .UnicodeString = USBSTR(SERIAL_NUMBER)
//};
#endif
// clang-format on
/**
@ -1134,6 +1123,7 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
break;
#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();