machine/usb: refactoring descriptors into subpackage for modularity
Signed-off-by: deadprogram <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
6a2dd35fe6
коммит
2ab7ee6a8a
15 изменённых файлов: 1190 добавлений и 266 удалений
|
@ -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
|
||||
|
|
|
@ -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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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
Обычный файл
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(),
|
||||
}),
|
||||
}
|
|
@ -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,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
|
||||
|
||||
|
@ -57,6 +47,7 @@ const (
|
|||
SET_REPORT = 9
|
||||
SET_IDLE = 10
|
||||
SET_PROTOCOL = 11
|
||||
SET_REPORT_TYPE = 33
|
||||
|
||||
DEVICE_CLASS_COMMUNICATIONS = 0x02
|
||||
DEVICE_CLASS_HUMAN_INTERFACE = 0x03
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче