Browse Source

machine/usb: refactoring descriptors into subpackage for modularity

Signed-off-by: deadprogram <ron@hybridgroup.com>
pull/3690/head
deadprogram 2 years ago
committed by Ron Evans
parent
commit
2ab7ee6a8a
  1. 39
      src/machine/usb.go
  2. 179
      src/machine/usb/descriptor.go
  3. 168
      src/machine/usb/descriptor/cdc.go
  4. 17
      src/machine/usb/descriptor/classspecific.go
  5. 49
      src/machine/usb/descriptor/configuration.go
  6. 63
      src/machine/usb/descriptor/descriptor.go
  7. 73
      src/machine/usb/descriptor/device.go
  8. 111
      src/machine/usb/descriptor/endpoint.go
  9. 189
      src/machine/usb/descriptor/hid.go
  10. 49
      src/machine/usb/descriptor/interface.go
  11. 45
      src/machine/usb/descriptor/interfaceassociation.go
  12. 145
      src/machine/usb/descriptor/joystick.go
  13. 249
      src/machine/usb/descriptor/midi.go
  14. 57
      src/machine/usb/hid/joystick/state.go
  15. 23
      src/machine/usb/usb.go

39
src/machine/usb.go

@ -3,10 +3,10 @@
package machine
import (
"bytes"
"encoding/binary"
"errors"
"machine/usb"
"machine/usb/descriptor"
"errors"
)
type USBDevice struct {
@ -29,7 +29,7 @@ type Serialer interface {
RTS() bool
}
var usbDescriptor = usb.DescriptorCDC
var usbDescriptor = descriptor.CDC
var usbDescriptorConfig uint8 = usb.DescriptorConfigCDC
@ -72,7 +72,7 @@ func usbProduct() string {
// binary.
func strToUTF16LEDescriptor(in string, out []byte) {
out[0] = byte(len(out))
out[1] = usb.STRING_DESCRIPTOR_TYPE
out[1] = descriptor.TypeString
for i, rune := range in {
out[(i<<1)+2] = byte(rune)
out[(i<<1)+3] = 0
@ -88,7 +88,7 @@ var (
)
var (
usbEndpointDescriptors [usb.NumberOfEndpoints]usb.DeviceDescriptor
usbEndpointDescriptors [usb.NumberOfEndpoints]descriptor.Device
isEndpointHalt = false
isRemoteWakeUpEnabled = false
@ -134,27 +134,27 @@ var (
// can be requested by the host.
func sendDescriptor(setup usb.Setup) {
switch setup.WValueH {
case usb.CONFIGURATION_DESCRIPTOR_TYPE:
case descriptor.TypeConfiguration:
sendUSBPacket(0, usbDescriptor.Configuration, setup.WLength)
return
case usb.DEVICE_DESCRIPTOR_TYPE:
case descriptor.TypeDevice:
// composite descriptor
switch {
case (usbDescriptorConfig & usb.DescriptorConfigHID) > 0:
usbDescriptor = usb.DescriptorCDCHID
usbDescriptor = descriptor.CDCHID
case (usbDescriptorConfig & usb.DescriptorConfigMIDI) > 0:
usbDescriptor = usb.DescriptorCDCMIDI
usbDescriptor = descriptor.CDCMIDI
case (usbDescriptorConfig & usb.DescriptorConfigJoystick) > 0:
usbDescriptor = usb.DescriptorCDCJoystick
usbDescriptor = descriptor.CDCJoystick
default:
usbDescriptor = usb.DescriptorCDC
usbDescriptor = descriptor.CDC
}
usbDescriptor.Configure(usbVendorID(), usbProductID())
sendUSBPacket(0, usbDescriptor.Device, setup.WLength)
return
case usb.STRING_DESCRIPTOR_TYPE:
case descriptor.TypeString:
switch setup.WValueL {
case 0:
usb_trans_buffer[0] = 0x04
@ -178,12 +178,12 @@ func sendDescriptor(setup usb.Setup) {
SendZlp()
}
return
case usb.HID_REPORT_TYPE:
case descriptor.TypeHIDReport:
if h, ok := usbDescriptor.HID[setup.WIndex]; ok {
sendUSBPacket(0, h, setup.WLength)
return
}
case usb.DEVICE_QUALIFIER:
case descriptor.TypeDeviceQualifier:
// skip
default:
}
@ -302,11 +302,10 @@ func EnableMIDI(txHandler func(), rxHandler func([]byte), setupHandler func(usb.
// EnableJoystick enables HID. This function must be executed from the init().
func EnableJoystick(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool, hidDesc []byte) {
idx := bytes.Index(usb.DescriptorCDCJoystick.Configuration, []byte{
0x09, 0x21, 0x11, 0x01, 0x00, 0x01, 0x22,
})
binary.LittleEndian.PutUint16(usb.DescriptorCDCJoystick.Configuration[idx+7:idx+9], uint16(len(hidDesc)))
usb.DescriptorCDCJoystick.HID[2] = hidDesc
class := descriptor.FindClassHIDType(descriptor.CDCJoystick.Configuration, descriptor.ClassHIDJoystick.Bytes())
class.ClassLength(uint16(len(hidDesc)))
descriptor.CDCJoystick.HID[2] = hidDesc
usbDescriptorConfig |= usb.DescriptorConfigJoystick
endPoints[usb.HID_ENDPOINT_OUT] = (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut)
usbRxHandler[usb.HID_ENDPOINT_OUT] = rxHandler

179
src/machine/usb/descriptor.go

@ -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{},
}

168
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(),
}),
}

17
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)
}

49
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)
}

63
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
}

73
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)
}

111
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)
}

189
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
},
},
}

49
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)
}

45
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)
}

145
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{},
}

249
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(),
}),
}

57
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,
}
}

23
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

Loading…
Cancel
Save