diff options
Diffstat (limited to 'tmk_core/protocol/usb_descriptor.c')
-rw-r--r-- | tmk_core/protocol/usb_descriptor.c | 132 |
1 files changed, 114 insertions, 18 deletions
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 703589b054..c7fb660b65 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 /* @@ -155,20 +165,34 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { # endif HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), - // Vertical wheel (1 byte) - HID_RI_USAGE(8, 0x38), // Wheel + // Vertical wheel (1 or 2 bytes) + HID_RI_USAGE(8, 0x38), // Wheel +# ifndef WHEEL_EXTENDED_REPORT HID_RI_LOGICAL_MINIMUM(8, -127), HID_RI_LOGICAL_MAXIMUM(8, 127), HID_RI_REPORT_COUNT(8, 0x01), HID_RI_REPORT_SIZE(8, 0x08), +# else + HID_RI_LOGICAL_MINIMUM(16, -32767), + HID_RI_LOGICAL_MAXIMUM(16, 32767), + HID_RI_REPORT_COUNT(8, 0x01), + HID_RI_REPORT_SIZE(8, 0x10), +# endif HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), - // Horizontal wheel (1 byte) - HID_RI_USAGE_PAGE(8, 0x0C), // Consumer - HID_RI_USAGE(16, 0x0238), // AC Pan + // Horizontal wheel (1 or 2 bytes) + HID_RI_USAGE_PAGE(8, 0x0C),// Consumer + HID_RI_USAGE(16, 0x0238), // AC Pan +# ifndef WHEEL_EXTENDED_REPORT HID_RI_LOGICAL_MINIMUM(8, -127), HID_RI_LOGICAL_MAXIMUM(8, 127), HID_RI_REPORT_COUNT(8, 0x01), HID_RI_REPORT_SIZE(8, 0x08), +# else + HID_RI_LOGICAL_MINIMUM(16, -32767), + HID_RI_LOGICAL_MAXIMUM(16, 32767), + HID_RI_REPORT_COUNT(8, 0x01), + HID_RI_REPORT_SIZE(8, 0x10), +# endif HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE), HID_RI_END_COLLECTION(0), HID_RI_END_COLLECTION(0), @@ -223,6 +247,23 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), # endif +# ifdef JOYSTICK_HAS_HAT + // Hat Switch (4 bits) + HID_RI_USAGE(8, 0x39), // Hat Switch + HID_RI_LOGICAL_MINIMUM(8, 0x00), + HID_RI_LOGICAL_MAXIMUM(8, 0x07), + HID_RI_PHYSICAL_MINIMUM(8, 0), + HID_RI_PHYSICAL_MAXIMUM(16, 315), + HID_RI_UNIT(8, 0x14), // Degree, English Rotation + HID_RI_REPORT_COUNT(8, 1), + HID_RI_REPORT_SIZE(8, 4), + HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NULLSTATE), + // Padding (4 bits) + HID_RI_REPORT_COUNT(8, 0x04), + HID_RI_REPORT_SIZE(8, 0x01), + HID_RI_INPUT(8, HID_IOF_CONSTANT), +# endif + # if JOYSTICK_BUTTON_COUNT > 0 HID_RI_USAGE_PAGE(8, 0x09), // Button HID_RI_USAGE_MINIMUM(8, 0x01), @@ -451,11 +492,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 +1078,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 +1092,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 +1100,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 +1205,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); |