aboutsummaryrefslogtreecommitdiff
path: root/tmk_core/protocol/usb_descriptor.c
diff options
context:
space:
mode:
authorNick Brassel <nick@tzarc.org>2024-11-27 21:29:12 +1100
committerNick Brassel <nick@tzarc.org>2024-11-27 21:29:12 +1100
commit9f76541b29056150cf57d69569a14a59e13995c7 (patch)
tree66c7398d873fcda88aebe3090603aefe045ff52e /tmk_core/protocol/usb_descriptor.c
parent57be4871616ee9a8fe042f6186010d436ec7d4b1 (diff)
parenteb04b94eecbb9b3e64ca9c74f937b5f762440b17 (diff)
Merge branch 'develop'
Diffstat (limited to 'tmk_core/protocol/usb_descriptor.c')
-rw-r--r--tmk_core/protocol/usb_descriptor.c132
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);