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
|
package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"machine/usb"
|
"machine/usb"
|
||||||
|
"machine/usb/descriptor"
|
||||||
|
|
||||||
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type USBDevice struct {
|
type USBDevice struct {
|
||||||
|
@ -29,7 +29,7 @@ type Serialer interface {
|
||||||
RTS() bool
|
RTS() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var usbDescriptor = usb.DescriptorCDC
|
var usbDescriptor = descriptor.CDC
|
||||||
|
|
||||||
var usbDescriptorConfig uint8 = usb.DescriptorConfigCDC
|
var usbDescriptorConfig uint8 = usb.DescriptorConfigCDC
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ func usbProduct() string {
|
||||||
// binary.
|
// binary.
|
||||||
func strToUTF16LEDescriptor(in string, out []byte) {
|
func strToUTF16LEDescriptor(in string, out []byte) {
|
||||||
out[0] = byte(len(out))
|
out[0] = byte(len(out))
|
||||||
out[1] = usb.STRING_DESCRIPTOR_TYPE
|
out[1] = descriptor.TypeString
|
||||||
for i, rune := range in {
|
for i, rune := range in {
|
||||||
out[(i<<1)+2] = byte(rune)
|
out[(i<<1)+2] = byte(rune)
|
||||||
out[(i<<1)+3] = 0
|
out[(i<<1)+3] = 0
|
||||||
|
@ -88,7 +88,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
usbEndpointDescriptors [usb.NumberOfEndpoints]usb.DeviceDescriptor
|
usbEndpointDescriptors [usb.NumberOfEndpoints]descriptor.Device
|
||||||
|
|
||||||
isEndpointHalt = false
|
isEndpointHalt = false
|
||||||
isRemoteWakeUpEnabled = false
|
isRemoteWakeUpEnabled = false
|
||||||
|
@ -134,27 +134,27 @@ var (
|
||||||
// can be requested by the host.
|
// can be requested by the host.
|
||||||
func sendDescriptor(setup usb.Setup) {
|
func sendDescriptor(setup usb.Setup) {
|
||||||
switch setup.WValueH {
|
switch setup.WValueH {
|
||||||
case usb.CONFIGURATION_DESCRIPTOR_TYPE:
|
case descriptor.TypeConfiguration:
|
||||||
sendUSBPacket(0, usbDescriptor.Configuration, setup.WLength)
|
sendUSBPacket(0, usbDescriptor.Configuration, setup.WLength)
|
||||||
return
|
return
|
||||||
case usb.DEVICE_DESCRIPTOR_TYPE:
|
case descriptor.TypeDevice:
|
||||||
// composite descriptor
|
// composite descriptor
|
||||||
switch {
|
switch {
|
||||||
case (usbDescriptorConfig & usb.DescriptorConfigHID) > 0:
|
case (usbDescriptorConfig & usb.DescriptorConfigHID) > 0:
|
||||||
usbDescriptor = usb.DescriptorCDCHID
|
usbDescriptor = descriptor.CDCHID
|
||||||
case (usbDescriptorConfig & usb.DescriptorConfigMIDI) > 0:
|
case (usbDescriptorConfig & usb.DescriptorConfigMIDI) > 0:
|
||||||
usbDescriptor = usb.DescriptorCDCMIDI
|
usbDescriptor = descriptor.CDCMIDI
|
||||||
case (usbDescriptorConfig & usb.DescriptorConfigJoystick) > 0:
|
case (usbDescriptorConfig & usb.DescriptorConfigJoystick) > 0:
|
||||||
usbDescriptor = usb.DescriptorCDCJoystick
|
usbDescriptor = descriptor.CDCJoystick
|
||||||
default:
|
default:
|
||||||
usbDescriptor = usb.DescriptorCDC
|
usbDescriptor = descriptor.CDC
|
||||||
}
|
}
|
||||||
|
|
||||||
usbDescriptor.Configure(usbVendorID(), usbProductID())
|
usbDescriptor.Configure(usbVendorID(), usbProductID())
|
||||||
sendUSBPacket(0, usbDescriptor.Device, setup.WLength)
|
sendUSBPacket(0, usbDescriptor.Device, setup.WLength)
|
||||||
return
|
return
|
||||||
|
|
||||||
case usb.STRING_DESCRIPTOR_TYPE:
|
case descriptor.TypeString:
|
||||||
switch setup.WValueL {
|
switch setup.WValueL {
|
||||||
case 0:
|
case 0:
|
||||||
usb_trans_buffer[0] = 0x04
|
usb_trans_buffer[0] = 0x04
|
||||||
|
@ -178,12 +178,12 @@ func sendDescriptor(setup usb.Setup) {
|
||||||
SendZlp()
|
SendZlp()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
case usb.HID_REPORT_TYPE:
|
case descriptor.TypeHIDReport:
|
||||||
if h, ok := usbDescriptor.HID[setup.WIndex]; ok {
|
if h, ok := usbDescriptor.HID[setup.WIndex]; ok {
|
||||||
sendUSBPacket(0, h, setup.WLength)
|
sendUSBPacket(0, h, setup.WLength)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case usb.DEVICE_QUALIFIER:
|
case descriptor.TypeDeviceQualifier:
|
||||||
// skip
|
// skip
|
||||||
default:
|
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().
|
// 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) {
|
func EnableJoystick(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool, hidDesc []byte) {
|
||||||
idx := bytes.Index(usb.DescriptorCDCJoystick.Configuration, []byte{
|
class := descriptor.FindClassHIDType(descriptor.CDCJoystick.Configuration, descriptor.ClassHIDJoystick.Bytes())
|
||||||
0x09, 0x21, 0x11, 0x01, 0x00, 0x01, 0x22,
|
class.ClassLength(uint16(len(hidDesc)))
|
||||||
})
|
descriptor.CDCJoystick.HID[2] = hidDesc
|
||||||
binary.LittleEndian.PutUint16(usb.DescriptorCDCJoystick.Configuration[idx+7:idx+9], uint16(len(hidDesc)))
|
|
||||||
usb.DescriptorCDCJoystick.HID[2] = hidDesc
|
|
||||||
usbDescriptorConfig |= usb.DescriptorConfigJoystick
|
usbDescriptorConfig |= usb.DescriptorConfigJoystick
|
||||||
endPoints[usb.HID_ENDPOINT_OUT] = (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut)
|
endPoints[usb.HID_ENDPOINT_OUT] = (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut)
|
||||||
usbRxHandler[usb.HID_ENDPOINT_OUT] = rxHandler
|
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
|
package joystick
|
||||||
|
|
||||||
import "encoding/binary"
|
import (
|
||||||
|
"machine/usb/descriptor"
|
||||||
|
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
type HatDirection uint8
|
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},
|
||||||
{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},
|
{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},
|
||||||
},
|
},
|
||||||
descriptor: []byte{
|
descriptor: descriptor.JoystickDefaultHIDReport,
|
||||||
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
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,16 +23,6 @@ const (
|
||||||
ENDPOINT_TYPE_BULK = 0x02
|
ENDPOINT_TYPE_BULK = 0x02
|
||||||
ENDPOINT_TYPE_INTERRUPT = 0x03
|
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
|
EndpointOut = 0x00
|
||||||
EndpointIn = 0x80
|
EndpointIn = 0x80
|
||||||
|
|
||||||
|
@ -51,12 +41,13 @@ const (
|
||||||
SET_INTERFACE = 11
|
SET_INTERFACE = 11
|
||||||
|
|
||||||
// non standard requests
|
// non standard requests
|
||||||
GET_REPORT = 1
|
GET_REPORT = 1
|
||||||
GET_IDLE = 2
|
GET_IDLE = 2
|
||||||
GET_PROTOCOL = 3
|
GET_PROTOCOL = 3
|
||||||
SET_REPORT = 9
|
SET_REPORT = 9
|
||||||
SET_IDLE = 10
|
SET_IDLE = 10
|
||||||
SET_PROTOCOL = 11
|
SET_PROTOCOL = 11
|
||||||
|
SET_REPORT_TYPE = 33
|
||||||
|
|
||||||
DEVICE_CLASS_COMMUNICATIONS = 0x02
|
DEVICE_CLASS_COMMUNICATIONS = 0x02
|
||||||
DEVICE_CLASS_HUMAN_INTERFACE = 0x03
|
DEVICE_CLASS_HUMAN_INTERFACE = 0x03
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче