From 2ab7ee6a8a793f26278e67646fad5fa010bc3561 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sun, 2 Apr 2023 12:12:32 +0200 Subject: machine/usb: refactoring descriptors into subpackage for modularity Signed-off-by: deadprogram --- src/machine/usb/descriptor.go | 179 --------------- src/machine/usb/descriptor/cdc.go | 168 ++++++++++++++ src/machine/usb/descriptor/classspecific.go | 17 ++ src/machine/usb/descriptor/configuration.go | 49 ++++ src/machine/usb/descriptor/descriptor.go | 63 ++++++ src/machine/usb/descriptor/device.go | 73 ++++++ src/machine/usb/descriptor/endpoint.go | 111 +++++++++ src/machine/usb/descriptor/hid.go | 189 ++++++++++++++++ src/machine/usb/descriptor/interface.go | 49 ++++ src/machine/usb/descriptor/interfaceassociation.go | 45 ++++ src/machine/usb/descriptor/joystick.go | 145 ++++++++++++ src/machine/usb/descriptor/midi.go | 249 +++++++++++++++++++++ src/machine/usb/hid/joystick/state.go | 57 +---- src/machine/usb/usb.go | 23 +- 14 files changed, 1171 insertions(+), 246 deletions(-) delete mode 100644 src/machine/usb/descriptor.go create mode 100644 src/machine/usb/descriptor/cdc.go create mode 100644 src/machine/usb/descriptor/classspecific.go create mode 100644 src/machine/usb/descriptor/configuration.go create mode 100644 src/machine/usb/descriptor/descriptor.go create mode 100644 src/machine/usb/descriptor/device.go create mode 100644 src/machine/usb/descriptor/endpoint.go create mode 100644 src/machine/usb/descriptor/hid.go create mode 100644 src/machine/usb/descriptor/interface.go create mode 100644 src/machine/usb/descriptor/interfaceassociation.go create mode 100644 src/machine/usb/descriptor/joystick.go create mode 100644 src/machine/usb/descriptor/midi.go (limited to 'src/machine/usb') diff --git a/src/machine/usb/descriptor.go b/src/machine/usb/descriptor.go deleted file mode 100644 index d57d0bd8a..000000000 --- a/src/machine/usb/descriptor.go +++ /dev/null @@ -1,179 +0,0 @@ -package usb - -import "runtime/volatile" - -// DeviceDescBank is the USB device endpoint descriptor. -type DeviceDescBank struct { - ADDR volatile.Register32 - PCKSIZE volatile.Register32 - EXTREG volatile.Register16 - STATUS_BK volatile.Register8 - _reserved [5]volatile.Register8 -} - -type DeviceDescriptor struct { - DeviceDescBank [2]DeviceDescBank -} - -type Descriptor struct { - Device []byte - Configuration []byte - HID map[uint16][]byte -} - -func (d *Descriptor) Configure(idVendor, idProduct uint16) { - d.Device[8] = byte(idVendor) - d.Device[9] = byte(idVendor >> 8) - d.Device[10] = byte(idProduct) - d.Device[11] = byte(idProduct >> 8) - - d.Configuration[2] = byte(len(d.Configuration)) - d.Configuration[3] = byte(len(d.Configuration) >> 8) -} - -var DescriptorCDC = Descriptor{ - Device: []byte{ - 0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x86, 0x28, 0x2d, 0x80, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01, - }, - Configuration: []byte{ - 0x09, 0x02, 0x4b, 0x00, 0x02, 0x01, 0x00, 0xa0, 0x32, - 0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, - 0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, - 0x05, 0x24, 0x00, 0x10, 0x01, - 0x04, 0x24, 0x02, 0x06, - 0x05, 0x24, 0x06, 0x00, 0x01, - 0x05, 0x24, 0x01, 0x01, 0x01, - 0x07, 0x05, 0x81, 0x03, 0x10, 0x00, 0x10, - 0x09, 0x04, 0x01, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00, - 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, - 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, - }, -} - -var DescriptorCDCHID = Descriptor{ - Device: []byte{ - 0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x86, 0x28, 0x2d, 0x80, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01, - }, - Configuration: []byte{ - 0x09, 0x02, 0x64, 0x00, 0x03, 0x01, 0x00, 0xa0, 0x32, - 0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, - 0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, - 0x05, 0x24, 0x00, 0x10, 0x01, - 0x04, 0x24, 0x02, 0x06, - 0x05, 0x24, 0x06, 0x00, 0x01, - 0x05, 0x24, 0x01, 0x01, 0x01, - 0x07, 0x05, 0x81, 0x03, 0x10, 0x00, 0x10, - 0x09, 0x04, 0x01, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00, - 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, - 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, - 0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, - 0x09, 0x21, 0x01, 0x01, 0x00, 0x01, 0x22, 0x7E, 0x00, - 0x07, 0x05, 0x84, 0x03, 0x40, 0x00, 0x01, - }, - HID: map[uint16][]byte{ - 2: []byte{ - // keyboard and mouse - 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x85, 0x02, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, - 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x03, 0x95, 0x06, - 0x75, 0x08, 0x15, 0x00, 0x25, 0xFF, 0x05, 0x07, 0x19, 0x00, 0x29, 0xFF, 0x81, 0x00, 0xc0, 0x05, - 0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x85, 0x01, 0x05, 0x09, 0x19, 0x01, 0x29, - 0x03, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, - 0x03, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 0x95, - 0x03, 0x81, 0x06, 0xc0, 0xc0, - - 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 - }, - }, -} - -var DescriptorCDCMIDI = Descriptor{ - Device: []byte{ - 0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x86, 0x28, 0x2d, 0x80, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01, - }, - Configuration: []byte{ - 0x09, 0x02, 0xaf, 0x00, 0x04, 0x01, 0x00, 0xa0, 0x32, - 0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, - 0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, - 0x05, 0x24, 0x00, 0x10, 0x01, - 0x04, 0x24, 0x02, 0x06, - 0x05, 0x24, 0x06, 0x00, 0x01, - 0x05, 0x24, 0x01, 0x01, 0x01, - 0x07, 0x05, 0x81, 0x03, 0x10, 0x00, 0x10, - 0x09, 0x04, 0x01, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00, - 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, - 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, - 0x08, 0x0b, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, - 0x09, 0x04, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, - 0x09, 0x24, 0x01, 0x00, 0x01, 0x09, 0x00, 0x01, 0x03, - 0x09, 0x04, 0x03, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, - 0x07, 0x24, 0x01, 0x00, 0x01, 0x41, 0x00, - 0x06, 0x24, 0x02, 0x01, 0x01, 0x00, - 0x06, 0x24, 0x02, 0x02, 0x02, 0x00, - 0x09, 0x24, 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, - 0x09, 0x24, 0x03, 0x02, 0x04, 0x01, 0x01, 0x01, 0x00, - 0x09, 0x05, 0x07, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x25, 0x01, 0x01, 0x01, - 0x09, 0x05, 0x86, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x25, 0x01, 0x01, 0x03, - }, -} - -var DescriptorCDCJoystick = Descriptor{ - Device: []byte{ - 0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, - 0x41, 0x23, 0x36, 0x80, 0x00, 0x01, 0x01, 0x02, - 0x03, 0x01, - }, - Configuration: []byte{ - // Configuration Descriptor Header - 0x09, 0x02, - 0x6b, 0x00, // Total Length: 0x006b(107) - 0x03, 0x01, 0x00, 0xa0, 0xfa, - // InterfaceAssociation Descriptoy - 0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, - // InterfaceSescriptor(CDC-Ctrl) - 0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, - // Communication Descriptor - 0x05, 0x24, 0x00, 0x10, 0x01, - // Communication Descriptor - 0x05, 0x24, 0x01, 0x01, 0x01, - // Communication Descriptor - 0x04, 0x24, 0x02, 0x06, - // Communication Descriptor - 0x05, 0x24, 0x06, 0x00, 0x01, - // ENDPOINT Descriptor - 0x07, 0x05, 0x81, 0x03, 0x10, 0x00, 0x40, - // InterfaceSescriptor(CDC-Data) - 0x09, 0x04, 0x01, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00, - // ENDPOINT Descriptor - 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00, - // ENDPOINT Descriptor - 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, - // InterfaceSescriptor(HID) - 0x09, 0x04, 0x02, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, - // HID Descriptor - 0x09, // bLength: 9 - 0x21, // bDescriptorType: 0x21(HID) - 0x11, 0x01, // bcdHID: 0x111 - 0x00, // bCountryCode: Not Supported - 0x01, // bNumDescriptors: 1 - 0x22, // Type: HID Report - 0x00, 0x00, // Length - // ENDPOINT Descriptor - 0x07, 0x05, 0x84, 0x03, 0x40, 0x00, 0x01, - // ENDPOINT Descriptor - 0x07, 0x05, 0x05, 0x03, 0x40, 0x00, 0x01, - }, - HID: map[uint16][]byte{}, -} diff --git a/src/machine/usb/descriptor/cdc.go b/src/machine/usb/descriptor/cdc.go new file mode 100644 index 000000000..a44b94aec --- /dev/null +++ b/src/machine/usb/descriptor/cdc.go @@ -0,0 +1,168 @@ +package descriptor + +const ( + cdcFunctionalHeader = 0 + cdcFunctionalCallManagement = 0x1 + cdcFunctionalACM = 0x2 + cdcFunctionalDirect = 0x3 + cdcFunctionalRinger = 0x4 + cdcFunctionalCall = 0x5 + cdcFunctionalUnion = 0x6 + cdcFunctionalCountry = 0x7 + cdcFunctionalOperational = 0x8 + cdcFunctionalUSB = 0x9 + cdcFunctionalNetwork = 0xa + cdcFunctionalProtocol = 0xb + cdcFunctionalExtension = 0xc + cdcFunctionalMulti = 0xd + cdcFunctionalCAPI = 0xe + cdcFunctionalEthernet = 0xf + cdcFunctionalATM = 0x10 +) + +var classSpecificCDCHeader = [classSpecificTypeLen]byte{ + classSpecificTypeLen, + TypeClassSpecific, + cdcFunctionalHeader, + 0x10, // + 0x1, // +} + +var ClassSpecificCDCHeader = ClassSpecificType{ + data: classSpecificCDCHeader[:], +} + +var classSpecificCDCCallManagement = [classSpecificTypeLen]byte{ + classSpecificTypeLen, + TypeClassSpecific, + cdcFunctionalCallManagement, + 0x0, // + 0x1, // +} + +var ClassSpecificCDCCallManagement = ClassSpecificType{ + data: classSpecificCDCCallManagement[:], +} + +var classSpecificCDCACM = [classSpecificTypeLen]byte{ + 4, + TypeClassSpecific, + cdcFunctionalACM, + 0x2, // +} + +var ClassSpecificCDCACM = ClassSpecificType{ + data: classSpecificCDCACM[:], +} + +var classSpecificCDCUnion = [classSpecificTypeLen]byte{ + classSpecificTypeLen, + TypeClassSpecific, + cdcFunctionalUnion, + 0x0, // + 0x1, // +} + +var ClassSpecificCDCUnion = ClassSpecificType{ + data: classSpecificCDCUnion[:], +} + +var interfaceAssociationCDC = [interfaceAssociationTypeLen]byte{ + interfaceAssociationTypeLen, + TypeInterfaceAssociation, + 0x00, // FirstInterface + 0x02, // InterfaceCount + 0x02, // FunctionClass + 0x02, // FunctionSubClass + 0x01, // FunctionProtocol + 0x00, // Function +} + +var InterfaceAssociationCDC = InterfaceAssociationType{ + data: interfaceAssociationCDC[:], +} + +var deviceCDC = [deviceTypeLen]byte{ + deviceTypeLen, + TypeDevice, + 0x00, 0x02, // USB version + 0xef, // device class + 0x02, // device subclass + 0x01, // protocol + 0x40, // maxpacketsize + 0x86, 0x28, // vendor id + 0x2d, 0x80, // product id + 0x00, 0x01, // device + 0x01, // manufacturer + 0x02, // product + 0x03, // SerialNumber + 0x01, // NumConfigurations +} + +var DeviceCDC = DeviceType{ + data: deviceCDC[:], +} + +var configurationCDC = [configurationTypeLen]byte{ + configurationTypeLen, + TypeConfiguration, + 0x4b, 0x00, // adjust length as needed + 0x02, // number of interfaces + 0x01, // configuration value + 0x00, // index to string description + 0xa0, // attributes + 0x32, // maxpower +} + +var ConfigurationCDC = ConfigurationType{ + data: configurationCDC[:], +} + +var interfaceCDCControl = [interfaceTypeLen]byte{ + interfaceTypeLen, + TypeInterface, + 0x00, // InterfaceNumber + 0x00, // AlternateSetting + 0x01, // NumEndpoints + 0x02, // InterfaceClass + 0x02, // InterfaceSubClass + 0x01, // InterfaceProtocol + 0x00, // Interface +} + +var InterfaceCDCControl = InterfaceType{ + data: interfaceCDCControl[:], +} + +var interfaceCDCData = [interfaceTypeLen]byte{ + interfaceTypeLen, + TypeInterface, + 0x01, // InterfaceNumber + 0x00, // AlternateSetting + 0x02, // NumEndpoints + 0x0a, // InterfaceClass + 0x00, // InterfaceSubClass + 0x00, // InterfaceProtocol + 0x00, // Interface +} + +var InterfaceCDCData = InterfaceType{ + data: interfaceCDCData[:], +} + +var CDC = Descriptor{ + Device: DeviceCDC.Bytes(), + Configuration: appendSlices([][]byte{ + ConfigurationCDC.Bytes(), + InterfaceAssociationCDC.Bytes(), + InterfaceCDCControl.Bytes(), + ClassSpecificCDCHeader.Bytes(), + ClassSpecificCDCCallManagement.Bytes(), + ClassSpecificCDCACM.Bytes(), + ClassSpecificCDCUnion.Bytes(), + EndpointEP1IN.Bytes(), + InterfaceCDCData.Bytes(), + EndpointEP2OUT.Bytes(), + EndpointEP3IN.Bytes(), + }), +} diff --git a/src/machine/usb/descriptor/classspecific.go b/src/machine/usb/descriptor/classspecific.go new file mode 100644 index 000000000..d8ea937b6 --- /dev/null +++ b/src/machine/usb/descriptor/classspecific.go @@ -0,0 +1,17 @@ +package descriptor + +const ( + classSpecificTypeLen = 5 +) + +type ClassSpecificType struct { + data []byte +} + +func (d ClassSpecificType) Bytes() []byte { + return d.data[:d.data[0]] +} + +func (d ClassSpecificType) Length(v uint8) { + d.data[0] = byte(v) +} diff --git a/src/machine/usb/descriptor/configuration.go b/src/machine/usb/descriptor/configuration.go new file mode 100644 index 000000000..d9446e673 --- /dev/null +++ b/src/machine/usb/descriptor/configuration.go @@ -0,0 +1,49 @@ +package descriptor + +import ( + "encoding/binary" +) + +const ( + configurationTypeLen = 9 +) + +type ConfigurationType struct { + data []byte +} + +func (d ConfigurationType) Bytes() []byte { + return d.data +} + +func (d ConfigurationType) Length(v uint8) { + d.data[0] = byte(v) +} + +func (d ConfigurationType) Type(v uint8) { + d.data[1] = byte(v) +} + +func (d ConfigurationType) TotalLength(v uint16) { + binary.LittleEndian.PutUint16(d.data[2:4], v) +} + +func (d ConfigurationType) NumInterfaces(v uint8) { + d.data[4] = byte(v) +} + +func (d ConfigurationType) ConfigurationValue(v uint8) { + d.data[5] = byte(v) +} + +func (d ConfigurationType) Configuration(v uint8) { + d.data[6] = byte(v) +} + +func (d ConfigurationType) Attributes(v uint8) { + d.data[7] = byte(v) +} + +func (d ConfigurationType) MaxPower(v uint8) { + d.data[8] = byte(v) +} diff --git a/src/machine/usb/descriptor/descriptor.go b/src/machine/usb/descriptor/descriptor.go new file mode 100644 index 000000000..5b52edb2c --- /dev/null +++ b/src/machine/usb/descriptor/descriptor.go @@ -0,0 +1,63 @@ +package descriptor + +import ( + "runtime/volatile" +) + +const ( + TypeDevice = 0x1 + TypeConfiguration = 0x2 + TypeString = 0x3 + TypeInterface = 0x4 + TypeEndpoint = 0x5 + TypeDeviceQualifier = 0x6 + TypeInterfaceAssociation = 0xb + TypeClassHID = 0x21 + TypeHIDReport = 0x22 + TypeClassSpecific = 0x24 + TypeClassSpecificEndpoint = 0x25 +) + +// DeviceDescBank is the USB device endpoint . +type DeviceDescBank struct { + ADDR volatile.Register32 + PCKSIZE volatile.Register32 + EXTREG volatile.Register16 + STATUS_BK volatile.Register8 + _reserved [5]volatile.Register8 +} + +type Device struct { + DeviceDescBank [2]DeviceDescBank +} + +type Descriptor struct { + Device []byte + Configuration []byte + HID map[uint16][]byte +} + +func (d *Descriptor) Configure(idVendor, idProduct uint16) { + dev := DeviceType{d.Device} + dev.VendorID(idVendor) + dev.ProductID(idProduct) + + conf := ConfigurationType{d.Configuration} + conf.TotalLength(uint16(len(d.Configuration))) +} + +func appendSlices[T any](slices [][]T) []T { + var size, pos int + + for _, s := range slices { + size += len(s) + } + + result := make([]T, size) + + for _, s := range slices { + pos += copy(result[pos:], s) + } + + return result +} diff --git a/src/machine/usb/descriptor/device.go b/src/machine/usb/descriptor/device.go new file mode 100644 index 000000000..48229fbfd --- /dev/null +++ b/src/machine/usb/descriptor/device.go @@ -0,0 +1,73 @@ +package descriptor + +import ( + "encoding/binary" +) + +const ( + deviceTypeLen = 18 +) + +type DeviceType struct { + data []byte +} + +func (d DeviceType) Bytes() []byte { + return d.data +} + +func (d DeviceType) Length(v uint8) { + d.data[0] = byte(v) +} + +func (d DeviceType) Type(v uint8) { + d.data[1] = byte(v) +} + +func (d DeviceType) USB(v uint16) { + binary.LittleEndian.PutUint16(d.data[2:4], v) +} + +func (d DeviceType) DeviceClass(v uint8) { + d.data[4] = byte(v) +} + +func (d DeviceType) DeviceSubClass(v uint8) { + d.data[5] = byte(v) +} + +func (d DeviceType) DeviceProtocol(v uint8) { + d.data[6] = byte(v) +} + +func (d DeviceType) MaxPacketSize0(v uint8) { + d.data[7] = byte(v) +} + +func (d DeviceType) VendorID(v uint16) { + binary.LittleEndian.PutUint16(d.data[8:10], v) +} + +func (d DeviceType) ProductID(v uint16) { + binary.LittleEndian.PutUint16(d.data[10:12], v) +} + +func (d DeviceType) Device(v uint16) { + binary.LittleEndian.PutUint16(d.data[12:14], v) +} + +func (d DeviceType) Manufacturer(v uint8) { + d.data[14] = byte(v) +} + +func (d DeviceType) Product(v uint8) { + d.data[15] = byte(v) +} + +func (d DeviceType) SerialNumber(v uint8) { + d.data[16] = byte(v) +} + +func (d DeviceType) NumConfigurations(v uint8) { + d.data[17] = byte(v) +} diff --git a/src/machine/usb/descriptor/endpoint.go b/src/machine/usb/descriptor/endpoint.go new file mode 100644 index 000000000..affaffa0a --- /dev/null +++ b/src/machine/usb/descriptor/endpoint.go @@ -0,0 +1,111 @@ +package descriptor + +import ( + "encoding/binary" +) + +var endpointEP1IN = [endpointTypeLen]byte{ + endpointTypeLen, + TypeEndpoint, + 0x81, // EndpointAddress + 0x03, // Attributes + 0x10, // MaxPacketSizeL + 0x00, // MaxPacketSizeH + 0x10, // Interval +} + +var EndpointEP1IN = EndpointType{ + data: endpointEP1IN[:], +} + +var endpointEP2OUT = [endpointTypeLen]byte{ + endpointTypeLen, + TypeEndpoint, + 0x02, // EndpointAddress + 0x02, // Attributes + 0x40, // MaxPacketSizeL + 0x00, // MaxPacketSizeH + 0x00, // Interval +} + +var EndpointEP2OUT = EndpointType{ + data: endpointEP2OUT[:], +} + +var endpointEP3IN = [endpointTypeLen]byte{ + endpointTypeLen, + TypeEndpoint, + 0x83, // EndpointAddress + 0x02, // Attributes + 0x40, // MaxPacketSizeL + 0x00, // MaxPacketSizeH + 0x00, // Interval +} + +var EndpointEP3IN = EndpointType{ + data: endpointEP3IN[:], +} + +var endpointEP4IN = [endpointTypeLen]byte{ + endpointTypeLen, + TypeEndpoint, + 0x84, // EndpointAddress + 0x03, // Attributes + 0x40, // MaxPacketSizeL + 0x00, // MaxPacketSizeH + 0x01, // Interval +} + +var EndpointEP4IN = EndpointType{ + data: endpointEP4IN[:], +} + +var endpointEP5OUT = [endpointTypeLen]byte{ + endpointTypeLen, + TypeEndpoint, + 0x05, // EndpointAddress + 0x03, // Attributes + 0x40, // MaxPacketSizeL + 0x00, // MaxPacketSizeH + 0x01, // Interval +} + +var EndpointEP5OUT = EndpointType{ + data: endpointEP5OUT[:], +} + +const ( + endpointTypeLen = 7 +) + +type EndpointType struct { + data []byte +} + +func (d EndpointType) Bytes() []byte { + return d.data +} + +func (d EndpointType) Length(v uint8) { + d.data[0] = byte(v) +} + +func (d EndpointType) Type(v uint8) { + d.data[1] = byte(v) +} + +func (d EndpointType) EndpointAddress(v uint8) { + d.data[2] = byte(v) +} + +func (d EndpointType) Attributes(v uint8) { + d.data[3] = byte(v) +} + +func (d EndpointType) MaxPacketSize(v uint16) { + binary.LittleEndian.PutUint16(d.data[4:6], v) +} + +func (d EndpointType) Interval(v uint8) { + d.data[6] = byte(v) +} diff --git a/src/machine/usb/descriptor/hid.go b/src/machine/usb/descriptor/hid.go new file mode 100644 index 000000000..266d10065 --- /dev/null +++ b/src/machine/usb/descriptor/hid.go @@ -0,0 +1,189 @@ +package descriptor + +import ( + "bytes" + "encoding/binary" +) + +var configurationCDCHID = [configurationTypeLen]byte{ + configurationTypeLen, + TypeConfiguration, + 0x64, 0x00, // adjust length as needed + 0x03, // number of interfaces + 0x01, // configuration value + 0x00, // index to string description + 0xa0, // attributes + 0x32, // maxpower +} + +var ConfigurationCDCHID = ConfigurationType{ + data: configurationCDCHID[:], +} + +var interfaceHID = [interfaceTypeLen]byte{ + interfaceTypeLen, + TypeInterface, + 0x02, // InterfaceNumber + 0x00, // AlternateSetting + 0x01, // NumEndpoints + 0x03, // InterfaceClass + 0x00, // InterfaceSubClass + 0x00, // InterfaceProtocol + 0x00, // Interface +} + +var InterfaceHID = InterfaceType{ + data: interfaceHID[:], +} + +const ( + ClassHIDTypeLen = 9 +) + +type ClassHIDType struct { + data []byte +} + +func (d ClassHIDType) Bytes() []byte { + return d.data[:] +} + +func (d ClassHIDType) Length(v uint8) { + d.data[0] = byte(v) +} + +func (d ClassHIDType) Type(v uint8) { + d.data[1] = byte(v) +} + +func (d ClassHIDType) HID(v uint16) { + binary.LittleEndian.PutUint16(d.data[2:4], v) +} + +func (d ClassHIDType) CountryCode(v uint8) { + d.data[4] = byte(v) +} + +func (d ClassHIDType) NumDescriptors(v uint8) { + d.data[5] = byte(v) +} + +func (d ClassHIDType) ClassType(v uint8) { + d.data[6] = byte(v) +} + +func (d ClassHIDType) ClassLength(v uint16) { + binary.LittleEndian.PutUint16(d.data[7:9], v) +} + +func FindClassHIDType(data, section []byte) ClassHIDType { + idx := bytes.Index(data, section) + + return ClassHIDType{data: data[idx : idx+ClassHIDTypeLen]} +} + +var classHID = [ClassHIDTypeLen]byte{ + ClassHIDTypeLen, + TypeClassHID, + 0x11, // HID version L + 0x01, // HID version H + 0x00, // CountryCode + 0x01, // NumDescriptors + 0x22, // ClassType + 0x7E, // ClassLength L + 0x00, // ClassLength H +} + +var ClassHID = ClassHIDType{ + data: classHID[:], +} + +var CDCHID = Descriptor{ + Device: DeviceCDC.Bytes(), + Configuration: appendSlices([][]byte{ + ConfigurationCDCHID.Bytes(), + InterfaceAssociationCDC.Bytes(), + InterfaceCDCControl.Bytes(), + ClassSpecificCDCHeader.Bytes(), + ClassSpecificCDCACM.Bytes(), + ClassSpecificCDCUnion.Bytes(), + ClassSpecificCDCCallManagement.Bytes(), + EndpointEP1IN.Bytes(), + InterfaceCDCData.Bytes(), + EndpointEP2OUT.Bytes(), + EndpointEP3IN.Bytes(), + InterfaceHID.Bytes(), + ClassHID.Bytes(), + 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, 0x03, // Usage Maximun (03) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x95, 0x03, // Report Count (3) + 0x75, 0x01, // Report Size (1) + 0x81, 0x02, // Input (Data, Variable, Absolute), ;3 button bits + 0x95, 0x01, // Report Count (1) + 0x75, 0x05, // Report Size (5) + 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 + }, + }, +} diff --git a/src/machine/usb/descriptor/interface.go b/src/machine/usb/descriptor/interface.go new file mode 100644 index 000000000..52f537fea --- /dev/null +++ b/src/machine/usb/descriptor/interface.go @@ -0,0 +1,49 @@ +package descriptor + +const ( + interfaceTypeLen = 9 +) + +type InterfaceType struct { + data []byte +} + +func (d InterfaceType) Bytes() []byte { + return d.data +} + +func (d InterfaceType) Length(v uint8) { + d.data[0] = byte(v) +} + +func (d InterfaceType) Type(v uint8) { + d.data[1] = byte(v) +} + +func (d InterfaceType) InterfaceNumber(v uint8) { + d.data[2] = byte(v) +} + +func (d InterfaceType) AlternateSetting(v uint8) { + d.data[3] = byte(v) +} + +func (d InterfaceType) NumEndpoints(v uint8) { + d.data[4] = byte(v) +} + +func (d InterfaceType) InterfaceClass(v uint8) { + d.data[5] = byte(v) +} + +func (d InterfaceType) InterfaceSubClass(v uint8) { + d.data[6] = byte(v) +} + +func (d InterfaceType) InterfaceProtocol(v uint8) { + d.data[7] = byte(v) +} + +func (d InterfaceType) Interface(v uint8) { + d.data[8] = byte(v) +} diff --git a/src/machine/usb/descriptor/interfaceassociation.go b/src/machine/usb/descriptor/interfaceassociation.go new file mode 100644 index 000000000..f92808626 --- /dev/null +++ b/src/machine/usb/descriptor/interfaceassociation.go @@ -0,0 +1,45 @@ +package descriptor + +const ( + interfaceAssociationTypeLen = 8 +) + +type InterfaceAssociationType struct { + data []byte +} + +func (d InterfaceAssociationType) Bytes() []byte { + return d.data +} + +func (d InterfaceAssociationType) Length(v uint8) { + d.data[0] = byte(v) +} + +func (d InterfaceAssociationType) Type(v uint8) { + d.data[1] = byte(v) +} + +func (d InterfaceAssociationType) FirstInterface(v uint8) { + d.data[2] = byte(v) +} + +func (d InterfaceAssociationType) InterfaceCount(v uint8) { + d.data[3] = byte(v) +} + +func (d InterfaceAssociationType) FunctionClass(v uint8) { + d.data[4] = byte(v) +} + +func (d InterfaceAssociationType) FunctionSubClass(v uint8) { + d.data[5] = byte(v) +} + +func (d InterfaceAssociationType) FunctionProtocol(v uint8) { + d.data[6] = byte(v) +} + +func (d InterfaceAssociationType) Function(v uint8) { + d.data[7] = byte(v) +} diff --git a/src/machine/usb/descriptor/joystick.go b/src/machine/usb/descriptor/joystick.go new file mode 100644 index 000000000..512873b49 --- /dev/null +++ b/src/machine/usb/descriptor/joystick.go @@ -0,0 +1,145 @@ +package descriptor + +var deviceJoystick = [deviceTypeLen]byte{ + deviceTypeLen, + TypeDevice, + 0x00, 0x02, // USB version + 0xef, // device class + 0x02, // subclass + 0x01, // protocol + 0x40, // maxpacketsize + 0x41, 0x23, // vendor id + 0x36, 0x80, // product id + 0x00, 0x01, // device + 0x01, // manufacturer + 0x02, // product + 0x03, // SerialNumber + 0x01, // NumConfigurations +} + +var DeviceJoystick = DeviceType{ + data: deviceJoystick[:], +} + +var configurationCDCJoystick = [configurationTypeLen]byte{ + configurationTypeLen, + TypeConfiguration, + 0x6b, 0x00, // adjust length as needed + 0x03, // number of interfaces + 0x01, // configuration value + 0x00, // index to string description + 0xa0, // attributes + 0xfa, // maxpower +} + +var ConfigurationCDCJoystick = ConfigurationType{ + data: configurationCDCJoystick[:], +} + +var interfaceHIDJoystick = [interfaceTypeLen]byte{ + interfaceTypeLen, + TypeInterface, + 0x02, // InterfaceNumber + 0x00, // AlternateSetting + 0x02, // NumEndpoints + 0x03, // InterfaceClass + 0x00, // InterfaceSubClass + 0x00, // InterfaceProtocol + 0x00, // Interface +} + +var InterfaceHIDJoystick = InterfaceType{ + data: interfaceHIDJoystick[:], +} + +var classHIDJoystick = [ClassHIDTypeLen]byte{ + ClassHIDTypeLen, + TypeClassHID, + 0x11, // HID version L + 0x01, // HID version H + 0x00, // CountryCode + 0x01, // NumDescriptors + 0x22, // ClassType + 0x00, // ClassLength L + 0x00, // ClassLength H +} + +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 +} + +// CDCJoystick requires that you append the JoystickDescriptor +// to the Configuration before using. This is in order to support +// custom configurations. +var CDCJoystick = Descriptor{ + Device: DeviceJoystick.Bytes(), + Configuration: appendSlices([][]byte{ + ConfigurationCDCJoystick.Bytes(), + InterfaceAssociationCDC.Bytes(), + InterfaceCDCControl.Bytes(), + ClassSpecificCDCHeader.Bytes(), + ClassSpecificCDCACM.Bytes(), + ClassSpecificCDCUnion.Bytes(), + ClassSpecificCDCCallManagement.Bytes(), + EndpointEP1IN.Bytes(), + InterfaceCDCData.Bytes(), + EndpointEP2OUT.Bytes(), + EndpointEP3IN.Bytes(), + InterfaceHIDJoystick.Bytes(), + ClassHIDJoystick.Bytes(), + EndpointEP4IN.Bytes(), + EndpointEP5OUT.Bytes(), + }), + HID: map[uint16][]byte{}, +} diff --git a/src/machine/usb/descriptor/midi.go b/src/machine/usb/descriptor/midi.go new file mode 100644 index 000000000..658aec850 --- /dev/null +++ b/src/machine/usb/descriptor/midi.go @@ -0,0 +1,249 @@ +package descriptor + +var interfaceAssociationMIDI = [interfaceAssociationTypeLen]byte{ + interfaceAssociationTypeLen, + TypeInterfaceAssociation, + 0x02, // EndpointAddress + 0x02, // Attributes + 0x01, // MaxPacketSizeL + 0x01, // MaxPacketSizeH + 0x00, // Interval + 0x00, // Interval +} + +var InterfaceAssociationMIDI = InterfaceAssociationType{ + data: interfaceAssociationMIDI[:], +} + +var interfaceAudio = [interfaceTypeLen]byte{ + interfaceTypeLen, + TypeInterface, + 0x02, // InterfaceNumber + 0x00, // AlternateSetting + 0x00, // NumEndpoints + 0x01, // InterfaceClass + 0x01, // InterfaceSubClass + 0x00, // InterfaceProtocol + 0x00, // Interface +} + +var InterfaceAudio = InterfaceType{ + data: interfaceAudio[:], +} + +var interfaceMIDIStreaming = [interfaceTypeLen]byte{ + interfaceTypeLen, + TypeInterface, + 0x03, // InterfaceNumber + 0x00, // AlternateSetting + 0x02, // NumEndpoints + 0x01, // InterfaceClass + 0x03, // InterfaceSubClass + 0x00, // InterfaceProtocol + 0x00, // Interface +} + +var InterfaceMIDIStreaming = InterfaceType{ + data: interfaceMIDIStreaming[:], +} + +const classSpecificAudioTypeLen = 9 + +var classSpecificAudioInterface = [classSpecificAudioTypeLen]byte{ + classSpecificAudioTypeLen, + TypeClassSpecific, + 0x01, + 0x00, // + 0x01, // + 0x09, + 0x00, + 0x01, + 0x03, +} + +var ClassSpecificAudioInterface = ClassSpecificType{ + data: classSpecificAudioInterface[:], +} + +const classSpecificMIDIHeaderLen = 7 + +var classSpecificMIDIHeader = [classSpecificMIDIHeaderLen]byte{ + classSpecificMIDIHeaderLen, + TypeClassSpecific, + 0x01, + 0x00, // + 0x01, // + 0x41, + 0x00, +} + +var ClassSpecificMIDIHeader = ClassSpecificType{ + data: classSpecificMIDIHeader[:], +} + +const classSpecificMIDIInJackLen = 6 + +var classSpecificMIDIInJack1 = [classSpecificMIDIInJackLen]byte{ + classSpecificMIDIInJackLen, + TypeClassSpecific, + 0x02, // MIDI In jack + 0x01, // Jack type (embedded) + 0x01, // Jack ID + 0x00, // iJack +} + +var ClassSpecificMIDIInJack1 = ClassSpecificType{ + data: classSpecificMIDIInJack1[:], +} + +var classSpecificMIDIInJack2 = [classSpecificMIDIInJackLen]byte{ + classSpecificMIDIInJackLen, + TypeClassSpecific, + 0x02, // MIDI In jack + 0x02, // Jack type (external) + 0x02, // Jack ID + 0x00, // iJack +} + +var ClassSpecificMIDIInJack2 = ClassSpecificType{ + data: classSpecificMIDIInJack2[:], +} + +const classSpecificMIDIOutJackLen = 9 + +var classSpecificMIDIOutJack1 = [classSpecificMIDIOutJackLen]byte{ + classSpecificMIDIOutJackLen, + TypeClassSpecific, + 0x03, // MIDI Out jack + 0x01, // Jack type (embedded) + 0x03, // Jack ID + 0x01, // number of input pins + 0x02, // source ID + 0x01, // source pin + 0x00, // iJack +} + +var ClassSpecificMIDIOutJack1 = ClassSpecificType{ + data: classSpecificMIDIOutJack1[:], +} + +var classSpecificMIDIOutJack2 = [classSpecificMIDIOutJackLen]byte{ + classSpecificMIDIOutJackLen, + TypeClassSpecific, + 0x03, // MIDI Out jack + 0x02, // Jack type (external) + 0x04, // Jack ID + 0x01, // number of input pins + 0x01, // source ID + 0x01, // source pin + 0x00, // iJack +} + +var ClassSpecificMIDIOutJack2 = ClassSpecificType{ + data: classSpecificMIDIOutJack2[:], +} + +const classSpecificMIDIEndpointLen = 5 + +var classSpecificMIDIOutEndpoint = [classSpecificMIDIEndpointLen]byte{ + classSpecificMIDIEndpointLen, + TypeClassSpecificEndpoint, + 0x01, // CS endpoint + 0x01, // number MIDI IN jacks + 0x01, // assoc Jack ID +} + +var ClassSpecificMIDIOutEndpoint = ClassSpecificType{ + data: classSpecificMIDIOutEndpoint[:], +} + +var classSpecificMIDIInEndpoint = [classSpecificMIDIEndpointLen]byte{ + classSpecificMIDIEndpointLen, + TypeClassSpecificEndpoint, + 0x01, // CS endpoint + 0x01, // number MIDI Out jacks + 0x03, // assoc Jack ID +} + +var ClassSpecificMIDIInEndpoint = ClassSpecificType{ + data: classSpecificMIDIInEndpoint[:], +} + +const endpointMIDITypeLen = 9 + +var endpointEP6IN = [endpointMIDITypeLen]byte{ + endpointMIDITypeLen, + TypeEndpoint, + 0x86, // EndpointAddress + 0x02, // Attributes + 0x40, // MaxPacketSizeL + 0x00, // MaxPacketSizeH + 0x00, // Interval + 0x00, // refresh + 0x00, // sync address +} + +var EndpointEP6IN = EndpointType{ + data: endpointEP6IN[:], +} + +var endpointEP7OUT = [endpointMIDITypeLen]byte{ + endpointMIDITypeLen, + TypeEndpoint, + 0x07, // EndpointAddress + 0x02, // Attributes + 0x40, // MaxPacketSizeL + 0x00, // MaxPacketSizeH + 0x00, // Interval + 0x00, // refresh + 0x00, // sync address +} + +var EndpointEP7OUT = EndpointType{ + data: endpointEP7OUT[:], +} + +var configurationCDCMIDI = [configurationTypeLen]byte{ + configurationTypeLen, + TypeConfiguration, + 0xaf, 0x00, // adjust length as needed + 0x04, // number of interfaces + 0x01, // configuration value + 0x00, // index to string description + 0xa0, // attributes + 0x32, // maxpower +} + +var ConfigurationCDCMIDI = ConfigurationType{ + data: configurationCDCMIDI[:], +} + +var CDCMIDI = Descriptor{ + Device: DeviceCDC.Bytes(), + Configuration: appendSlices([][]byte{ + ConfigurationCDCMIDI.Bytes(), + InterfaceAssociationCDC.Bytes(), + InterfaceCDCControl.Bytes(), + ClassSpecificCDCHeader.Bytes(), + ClassSpecificCDCACM.Bytes(), + ClassSpecificCDCUnion.Bytes(), + ClassSpecificCDCCallManagement.Bytes(), + EndpointEP1IN.Bytes(), + InterfaceCDCData.Bytes(), + EndpointEP2OUT.Bytes(), + EndpointEP3IN.Bytes(), + InterfaceAssociationMIDI.Bytes(), + InterfaceAudio.Bytes(), + ClassSpecificAudioInterface.Bytes(), + InterfaceMIDIStreaming.Bytes(), + ClassSpecificMIDIHeader.Bytes(), + ClassSpecificMIDIInJack1.Bytes(), + ClassSpecificMIDIInJack2.Bytes(), + ClassSpecificMIDIOutJack1.Bytes(), + ClassSpecificMIDIOutJack2.Bytes(), + EndpointEP7OUT.Bytes(), + ClassSpecificMIDIOutEndpoint.Bytes(), + EndpointEP6IN.Bytes(), + ClassSpecificMIDIInEndpoint.Bytes(), + }), +} diff --git a/src/machine/usb/hid/joystick/state.go b/src/machine/usb/hid/joystick/state.go index 51b7e6c40..7cb47a77c 100644 --- a/src/machine/usb/hid/joystick/state.go +++ b/src/machine/usb/hid/joystick/state.go @@ -1,6 +1,10 @@ package joystick -import "encoding/binary" +import ( + "machine/usb/descriptor" + + "encoding/binary" +) type HatDirection uint8 @@ -159,55 +163,6 @@ func DefaultDefinitions() Definitions { {MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767}, {MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767}, }, - descriptor: []byte{ - 0x05, 0x01, - 0x09, 0x04, - 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 - }, + descriptor: descriptor.JoystickDefaultHIDReport, } } diff --git a/src/machine/usb/usb.go b/src/machine/usb/usb.go index 97efbbfa4..47a8a3456 100644 --- a/src/machine/usb/usb.go +++ b/src/machine/usb/usb.go @@ -23,16 +23,6 @@ const ( ENDPOINT_TYPE_BULK = 0x02 ENDPOINT_TYPE_INTERRUPT = 0x03 - DEVICE_DESCRIPTOR_TYPE = 1 - CONFIGURATION_DESCRIPTOR_TYPE = 2 - STRING_DESCRIPTOR_TYPE = 3 - INTERFACE_DESCRIPTOR_TYPE = 4 - ENDPOINT_DESCRIPTOR_TYPE = 5 - DEVICE_QUALIFIER = 6 - OTHER_SPEED_CONFIGURATION = 7 - SET_REPORT_TYPE = 33 - HID_REPORT_TYPE = 34 - EndpointOut = 0x00 EndpointIn = 0x80 @@ -51,12 +41,13 @@ const ( SET_INTERFACE = 11 // non standard requests - GET_REPORT = 1 - GET_IDLE = 2 - GET_PROTOCOL = 3 - SET_REPORT = 9 - SET_IDLE = 10 - SET_PROTOCOL = 11 + GET_REPORT = 1 + GET_IDLE = 2 + GET_PROTOCOL = 3 + SET_REPORT = 9 + SET_IDLE = 10 + SET_PROTOCOL = 11 + SET_REPORT_TYPE = 33 DEVICE_CLASS_COMMUNICATIONS = 0x02 DEVICE_CLASS_HUMAN_INTERFACE = 0x03 -- cgit v1.2.3