From d8ee520bdc020859f454308d0f0ee0fe54b26042 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Fri, 28 Apr 2023 21:22:46 +0200 Subject: [PATCH] machine/usb/descriptor: refactor HID report creation Signed-off-by: deadprogram --- src/machine/usb/descriptor/hid.go | 141 ++++++++++++------------ src/machine/usb/descriptor/hidreport.go | 130 ++++++++++++++++++++++ src/machine/usb/descriptor/joystick.go | 112 ++++++++++--------- 3 files changed, 265 insertions(+), 118 deletions(-) create mode 100644 src/machine/usb/descriptor/hidreport.go diff --git a/src/machine/usb/descriptor/hid.go b/src/machine/usb/descriptor/hid.go index 9cbf2fc2..197a45da 100644 --- a/src/machine/usb/descriptor/hid.go +++ b/src/machine/usb/descriptor/hid.go @@ -130,73 +130,78 @@ var CDCHID = Descriptor{ EndpointEP4IN.Bytes(), }), HID: map[uint16][]byte{ - 2: []byte{ - 0x05, 0x01, // Usage Page (Generic Desktop) - 0x09, 0x06, // Usage (Keyboard) - 0xa1, 0x01, // Collection (Application) - 0x85, 0x02, // Report ID (2) - 0x05, 0x07, // Usage Page (KeyCodes) - 0x19, 0xe0, // Usage Minimum (224) - 0x29, 0xe7, // Usage Maximum (231) - 0x15, 0x00, // Logical Minimum (0) - 0x25, 0x01, // Logical Maximum (1) - 0x75, 0x01, // Report Size (1) - 0x95, 0x08, // Report Count (8) - 0x81, 0x02, // Input (Data, Variable, Absolute), Modifier byte - 0x95, 0x01, // Report Count (1) - 0x75, 0x08, // Report Size (8) - 0x81, 0x03, // - 0x95, 0x06, // Report Count (6) - 0x75, 0x08, // Report Size (8) - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0xFF, // - 0x05, 0x07, // Usage Page (KeyCodes) - 0x19, 0x00, // Usage Minimum (0) - 0x29, 0xFF, // Usage Maximum (255) - 0x81, 0x00, // Input (Data, Array), Key arrays (6 bytes) - 0xc0, // End Collection - - 0x05, 0x01, // Usage Page (Generic Desktop) - 0x09, 0x02, // Usage (Mouse) - 0xa1, 0x01, // Collection (Application) - 0x09, 0x01, // Usage (Pointer) - 0xa1, 0x00, // Collection (Physical) - 0x85, 0x01, // Report ID (1) - 0x05, 0x09, // Usage Page (Buttons) - 0x19, 0x01, // Usage Minimum (01) - 0x29, 0x05, // Usage Maximun (05) - 0x15, 0x00, // Logical Minimum (0) - 0x25, 0x01, // Logical Maximum (1) - 0x95, 0x05, // Report Count (5) - 0x75, 0x01, // Report Size (1) - 0x81, 0x02, // Input (Data, Variable, Absolute), ;3 button bits - 0x95, 0x01, // Report Count (1) - 0x75, 0x03, // Report Size (3) - 0x81, 0x03, // - 0x05, 0x01, // Usage Page (Generic Desktop) - 0x09, 0x30, // Usage (X) - 0x09, 0x31, // Usage (Y) - 0x09, 0x38, // - 0x15, 0x81, // Logical Minimum (-127) - 0x25, 0x7f, // Logical Maximum (127) - 0x75, 0x08, // Report Size (8) - 0x95, 0x03, // Report Count (3) - 0x81, 0x06, // Input (Data, Variable, Relative), 2 position bytes (X & Y) - 0xc0, // End Collection - 0xc0, // End Collection - - 0x05, 0x0C, // Usage Page (Consumer) - 0x09, 0x01, // Usage (Consumer Control) - 0xA1, 0x01, // Collection (Application) - 0x85, 0x03, // Report ID (3) - 0x15, 0x00, // Logical Minimum (0) - 0x26, 0xFF, 0x1F, // Logical Maximum (8191) - 0x19, 0x00, // Usage Minimum (Unassigned) - 0x2A, 0xFF, 0x1F, // Usage Maximum (0x1FFF) - 0x75, 0x10, // Report Size (16) - 0x95, 0x01, // Report Count (1) - 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) - 0xC0, // End Collection - }, + 2: appendSlices([][]byte{ + HIDUsagePageGenericDesktop, + HIDUsageDesktopKeyboard, + HIDCollectionApplication, + HIDReportID(2), + + HIDUsagePageKeyboard, + HIDUsageMinimum(224), + HIDUsageMaximum(231), + HIDLogicalMinimum(0), + HIDLogicalMaximum(1), + HIDReportSize(1), + HIDReportCount(8), + HIDInputDataVarAbs, + HIDReportCount(1), + HIDReportSize(8), + HIDInputConstVarAbs, + HIDReportCount(6), + HIDReportSize(8), + HIDLogicalMinimum(0), + HIDLogicalMaximum(255), + + HIDUsagePageKeyboard, + HIDUsageMinimum(0), + HIDUsageMaximum(255), + HIDInputDataAryAbs, + HIDEndCollection, + + HIDUsagePageGenericDesktop, + HIDUsageDesktopMouse, + HIDCollectionApplication, + HIDUsageDesktopPointer, + HIDCollectionPhysical, + HIDReportID(1), + + HIDUsagePageButton, + HIDUsageMinimum(1), + HIDUsageMaximum(5), + HIDLogicalMinimum(0), + HIDLogicalMaximum(1), + HIDReportCount(5), + HIDReportSize(1), + HIDInputDataVarAbs, + HIDReportCount(1), + HIDReportSize(3), + HIDInputConstVarAbs, + + HIDUsagePageGenericDesktop, + HIDUsageDesktopX, + HIDUsageDesktopY, + HIDUsageDesktopWheel, + HIDLogicalMinimum(-127), + HIDLogicalMaximum(127), + HIDReportSize(8), + HIDReportCount(3), + HIDInputDataVarRel, + HIDEndCollection, + HIDEndCollection, + + HIDUsagePageConsumer, + HIDUsageConsumerControl, + HIDCollectionApplication, + HIDReportID(3), + HIDLogicalMinimum(0), + []byte{ + 0x26, 0xFF, 0x1F, // Logical Maximum (8191) + 0x19, 0x00, // Usage Minimum (Unassigned) + 0x2A, 0xFF, 0x1F, // Usage Maximum (0x1FFF) + }, + HIDReportSize(16), + HIDReportCount(1), + HIDInputDataAryAbs, + HIDEndCollection}), }, } diff --git a/src/machine/usb/descriptor/hidreport.go b/src/machine/usb/descriptor/hidreport.go new file mode 100644 index 00000000..1f16b3c9 --- /dev/null +++ b/src/machine/usb/descriptor/hidreport.go @@ -0,0 +1,130 @@ +package descriptor + +var ( + HIDUsagePageGenericDesktop = []byte{0x05, 0x01} + HIDUsagePageSimulationControls = []byte{0x05, 0x02} + HIDUsagePageVRControls = []byte{0x05, 0x03} + HIDUsagePageSportControls = []byte{0x05, 0x04} + HIDUsagePageGameControls = []byte{0x05, 0x05} + HIDUsagePageGenericControls = []byte{0x05, 0x06} + HIDUsagePageKeyboard = []byte{0x05, 0x07} + HIDUsagePageLED = []byte{0x05, 0x08} + HIDUsagePageButton = []byte{0x05, 0x09} + HIDUsagePageOrdinal = []byte{0x05, 0x0A} + HIDUsagePageTelephony = []byte{0x05, 0x0B} + HIDUsagePageConsumer = []byte{0x05, 0x0C} + HIDUsagePageDigitizers = []byte{0x05, 0x0D} + HIDUsagePageHaptics = []byte{0x05, 0x0E} + HIDUsagePagePhysicalInput = []byte{0x05, 0x0F} + HIDUsagePageUnicode = []byte{0x05, 0x10} + HIDUsagePageSoC = []byte{0x05, 0x11} + HIDUsagePageEyeHeadTrackers = []byte{0x05, 0x12} + HIDUsagePageAuxDisplay = []byte{0x05, 0x14} + HIDUsagePageSensors = []byte{0x05, 0x20} + HIDUsagePageMedicalInstrument = []byte{0x05, 0x40} + HIDUsagePageBrailleDisplay = []byte{0x05, 0x41} + HIDUsagePageLighting = []byte{0x05, 0x59} + HIDUsagePageMonitor = []byte{0x05, 0x80} + HIDUsagePageMonitorEnum = []byte{0x05, 0x81} + HIDUsagePageVESA = []byte{0x05, 0x82} + HIDUsagePagePower = []byte{0x05, 0x84} + HIDUsagePageBatterySystem = []byte{0x05, 0x85} + HIDUsagePageBarcodeScanner = []byte{0x05, 0x8C} + HIDUsagePageScales = []byte{0x05, 0x8D} + HIDUsagePageMagneticStripe = []byte{0x05, 0x8E} + HIDUsagePageCameraControl = []byte{0x05, 0x90} + HIDUsagePageArcade = []byte{0x05, 0x91} + HIDUsagePageGaming = []byte{0x05, 0x92} +) + +var ( + HIDUsageDesktopPointer = []byte{0x09, 0x01} + HIDUsageDesktopMouse = []byte{0x09, 0x02} + HIDUsageDesktopJoystick = []byte{0x09, 0x04} + HIDUsageDesktopGamepad = []byte{0x09, 0x05} + HIDUsageDesktopKeyboard = []byte{0x09, 0x06} + HIDUsageDesktopKeypad = []byte{0x09, 0x07} + HIDUsageDesktopMultiaxis = []byte{0x09, 0x08} + HIDUsageDesktopTablet = []byte{0x09, 0x09} + HIDUsageDesktopWaterCooling = []byte{0x09, 0x0A} + HIDUsageDesktopChassis = []byte{0x09, 0x0B} + HIDUsageDesktopWireless = []byte{0x09, 0x0C} + HIDUsageDesktopPortable = []byte{0x09, 0x0D} + HIDUsageDesktopSystemMultiaxis = []byte{0x09, 0x0E} + HIDUsageDesktopSpatial = []byte{0x09, 0x0F} + HIDUsageDesktopAssistive = []byte{0x09, 0x10} + HIDUsageDesktopDock = []byte{0x09, 0x11} + HIDUsageDesktopDockable = []byte{0x09, 0x12} + HIDUsageDesktopCallState = []byte{0x09, 0x13} + HIDUsageDesktopX = []byte{0x09, 0x30} + HIDUsageDesktopY = []byte{0x09, 0x31} + HIDUsageDesktopZ = []byte{0x09, 0x32} + HIDUsageDesktopRx = []byte{0x09, 0x33} + HIDUsageDesktopRy = []byte{0x09, 0x34} + HIDUsageDesktopRz = []byte{0x09, 0x35} + HIDUsageDesktopSlider = []byte{0x09, 0x36} + HIDUsageDesktopDial = []byte{0x09, 0x37} + HIDUsageDesktopWheel = []byte{0x09, 0x38} + HIDUsageDesktopHatSwitch = []byte{0x09, 0x39} + HIDUsageDesktopCountedBuffer = []byte{0x09, 0x3A} +) + +var ( + HIDUsageConsumerControl = []byte{0x09, 0x01} + HIDUsageConsumerNumericKeypad = []byte{0x09, 0x02} + HIDUsageConsumerProgrammableButtons = []byte{0x09, 0x03} + HIDUsageConsumerMicrophone = []byte{0x09, 0x04} + HIDUsageConsumerHeadphone = []byte{0x09, 0x05} + HIDUsageConsumerGraphicEqualizer = []byte{0x09, 0x06} +) + +var ( + HIDCollectionPhysical = []byte{0xa1, 0x00} + HIDCollectionApplication = []byte{0xa1, 0x01} +) + +var ( + HIDEndCollection = []byte{0xc0} +) + +var ( + // Input (Data,Ary,Abs), Key arrays (6 bytes) + HIDInputDataAryAbs = []byte{0x81, 0x00} + + // Input (Data, Variable, Absolute), Modifier byte + HIDInputDataVarAbs = []byte{0x81, 0x02} + + // Input (Const,Var,Abs), Modifier byte + HIDInputConstVarAbs = []byte{0x81, 0x03} + + // Input (Data, Variable, Relative), 2 position bytes (X & Y) + HIDInputDataVarRel = []byte{0x81, 0x06} +) + +func HIDReportSize(size int) []byte { + return []byte{0x75, byte(size)} +} + +func HIDReportCount(count int) []byte { + return []byte{0x95, byte(count)} +} + +func HIDReportID(id int) []byte { + return []byte{0x85, byte(id)} +} + +func HIDLogicalMinimum(min int) []byte { + return []byte{0x15, byte(min)} +} + +func HIDLogicalMaximum(max int) []byte { + return []byte{0x25, byte(max)} +} + +func HIDUsageMinimum(min int) []byte { + return []byte{0x19, byte(min)} +} + +func HIDUsageMaximum(max int) []byte { + return []byte{0x29, byte(max)} +} diff --git a/src/machine/usb/descriptor/joystick.go b/src/machine/usb/descriptor/joystick.go index 512873b4..068838a6 100644 --- a/src/machine/usb/descriptor/joystick.go +++ b/src/machine/usb/descriptor/joystick.go @@ -68,56 +68,68 @@ var ClassHIDJoystick = ClassHIDType{ data: classHIDJoystick[:], } -var JoystickDefaultHIDReport = []byte{ - 0x05, 0x01, // Usage page - 0x09, 0x04, // Joystick - 0xa1, 0x01, // COLLECTION (Application) - 0x85, 0x01, // REPORT_ID (1) - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x10, // USAGE_MAXIMUM (Button 16) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - 0x95, 0x10, // REPORT_COUNT (16) - 0x55, 0x00, // Unit Exponent (-16) - 0x65, 0x00, // Unit (0x00) - 0x81, 0x02, // INPUT (Data/Var/Abs) - 0x05, 0x01, // USAGE_PAGE (Generic Desktop Controls) - 0x09, 0x39, // USAGE(Hat Switch) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x07, // LOGICAL_MAXIMUM (7) - 0x35, 0x00, // PHYSICAL_MINIMUM (0) - 0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM(315) - 0x65, 0x14, // UNIT (Eng Rot:Angular Pos) - 0x75, 0x04, // REPORT_SIZE (4) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data/Var/Abs) - 0x09, 0x39, // USAGE(Hat Switch) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x07, // LOGICAL_MAXIMUM (7) - 0x35, 0x00, // PHYSICAL_MINIMUM (0) - 0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM(315) - 0x65, 0x14, // UNIT (Eng Rot:Angular Pos) - 0x75, 0x04, // REPORT_SIZE (4) - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x02, // INPUT (Data/Var/Abs) - 0x09, 0x01, // USAGE (Pointer) - 0x16, 0x01, 0x80, // LOGICAL_MINIMUM (-32767) - 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) - 0x75, 0x10, // REPORT_SIZE (16bits) - 0x95, 0x06, // REPORT_COUNT (6) - 0xa1, 0x00, // COLLECTION (Physical) - 0x09, 0x30, // USAGE(X) - 0x09, 0x31, // USAGE(Y) - 0x09, 0x32, // USAGE(Z) - 0x09, 0x33, // USAGE(RX) - 0x09, 0x34, // USAGE(RY) - 0x09, 0x35, // USAGE(RZ) - 0x81, 0x02, // INPUT (Data/Var/Abs) - 0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION -} +var JoystickDefaultHIDReport = appendSlices([][]byte{ + HIDUsagePageGenericDesktop, + HIDUsageDesktopJoystick, + HIDCollectionApplication, + HIDReportID(1), + HIDUsagePageButton, + HIDUsageMinimum(1), + HIDUsageMaximum(16), + HIDLogicalMinimum(0), + HIDLogicalMaximum(1), + HIDReportSize(1), + HIDReportCount(16), + HIDInputDataVarAbs, + HIDReportCount(1), + HIDReportSize(3), + []byte{ + 0x55, 0x00, // Unit Exponent (-16) + 0x65, 0x00, // Unit (0x00) + }, + HIDInputDataVarAbs, + + HIDUsagePageGenericDesktop, + HIDUsageDesktopHatSwitch, + HIDLogicalMinimum(0), + HIDLogicalMaximum(7), + []byte{ + 0x35, 0x00, // PHYSICAL_MINIMUM (0) + 0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM(315) + 0x65, 0x14, // UNIT (Eng Rot:Angular Pos) + }, + HIDReportCount(1), + HIDReportSize(4), + HIDInputDataVarAbs, + HIDUsageDesktopHatSwitch, + HIDLogicalMinimum(0), + HIDLogicalMaximum(7), + []byte{ + 0x35, 0x00, // PHYSICAL_MINIMUM (0) + 0x46, 0x3b, 0x01, // PHYSICAL_MAXIMUM(315) + 0x65, 0x14, // UNIT (Eng Rot:Angular Pos) + }, + HIDReportCount(1), + HIDReportSize(4), + HIDInputDataVarAbs, + HIDUsageDesktopPointer, + []byte{ + 0x16, 0x01, 0x80, // LOGICAL_MINIMUM (-32767) + 0x26, 0xff, 0x7f, // LOGICAL_MAXIMUM (32767) + }, + HIDReportCount(6), + HIDReportSize(16), + HIDCollectionPhysical, + HIDUsageDesktopX, + HIDUsageDesktopY, + HIDUsageDesktopZ, + HIDUsageDesktopRx, + HIDUsageDesktopRy, + HIDUsageDesktopRz, + HIDInputDataVarAbs, + HIDEndCollection, + HIDEndCollection, +}) // CDCJoystick requires that you append the JoystickDescriptor // to the Configuration before using. This is in order to support