machine/usb: allow USB Endpoint settings to be changed externally

Этот коммит содержится в:
sago35 2023-08-01 20:22:30 +09:00 коммит произвёл Ron Evans
родитель d1eb642d45
коммит 069e4f0d98
5 изменённых файлов: 130 добавлений и 46 удалений

Просмотреть файл

@ -263,47 +263,52 @@ func EnableCDC(txHandler func(), rxHandler func([]byte), setupHandler func(usb.S
usbDescriptor = descriptor.CDC usbDescriptor = descriptor.CDC
} }
// Initialization of endpoints is required even for non-CDC // Initialization of endpoints is required even for non-CDC
endPoints[usb.CDC_ENDPOINT_ACM] = (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn) ConfigureUSBEndpoint(usbDescriptor,
endPoints[usb.CDC_ENDPOINT_OUT] = (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut) []usb.EndpointConfig{
endPoints[usb.CDC_ENDPOINT_IN] = (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn) {
usbRxHandler[usb.CDC_ENDPOINT_OUT] = rxHandler No: usb.CDC_ENDPOINT_ACM,
usbTxHandler[usb.CDC_ENDPOINT_IN] = txHandler IsIn: true,
usbSetupHandler[usb.CDC_ACM_INTERFACE] = setupHandler // 0x02 (Communications and CDC Control) Type: usb.ENDPOINT_TYPE_INTERRUPT,
usbSetupHandler[usb.CDC_DATA_INTERFACE] = nil // 0x0A (CDC-Data) },
{
No: usb.CDC_ENDPOINT_OUT,
IsIn: false,
Type: usb.ENDPOINT_TYPE_BULK,
RxHandler: rxHandler,
},
{
No: usb.CDC_ENDPOINT_IN,
IsIn: true,
Type: usb.ENDPOINT_TYPE_BULK,
TxHandler: txHandler,
},
},
[]usb.SetupConfig{
{
No: usb.CDC_ACM_INTERFACE,
Handler: setupHandler,
},
})
} }
// EnableHID enables HID. This function must be executed from the init(). func ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []usb.EndpointConfig, setup []usb.SetupConfig) {
func EnableHID(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) { usbDescriptor = desc
usbDescriptor = descriptor.CDCHID
endPoints[usb.HID_ENDPOINT_IN] = (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn) for _, ep := range epSettings {
usbTxHandler[usb.HID_ENDPOINT_IN] = txHandler if ep.IsIn {
usbSetupHandler[usb.HID_INTERFACE] = setupHandler // 0x03 (HID - Human Interface Device) endPoints[ep.No] = uint32(ep.Type | usb.EndpointIn)
if ep.TxHandler != nil {
usbTxHandler[ep.No] = ep.TxHandler
}
} else {
endPoints[ep.No] = uint32(ep.Type | usb.EndpointOut)
if ep.RxHandler != nil {
usbRxHandler[ep.No] = ep.RxHandler
}
}
} }
// EnableMIDI enables MIDI. This function must be executed from the init(). for _, s := range setup {
func EnableMIDI(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) { usbSetupHandler[s.No] = s.Handler
usbDescriptor = descriptor.CDCMIDI
endPoints[usb.MIDI_ENDPOINT_OUT] = (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut)
endPoints[usb.MIDI_ENDPOINT_IN] = (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn)
usbRxHandler[usb.MIDI_ENDPOINT_OUT] = rxHandler
usbTxHandler[usb.MIDI_ENDPOINT_IN] = txHandler
} }
// 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) {
class, err := descriptor.FindClassHIDType(descriptor.CDCJoystick.Configuration, descriptor.ClassHIDJoystick.Bytes())
if err != nil {
// TODO: some way to notify about error
return
}
class.ClassLength(uint16(len(hidDesc)))
descriptor.CDCJoystick.HID[2] = hidDesc
usbDescriptor = descriptor.CDCJoystick
endPoints[usb.HID_ENDPOINT_OUT] = (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut)
usbRxHandler[usb.HID_ENDPOINT_OUT] = rxHandler
endPoints[usb.HID_ENDPOINT_IN] = (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn)
usbTxHandler[usb.HID_ENDPOINT_IN] = txHandler
usbSetupHandler[usb.HID_INTERFACE] = setupHandler // 0x03 (HID - Human Interface Device)
} }

Просмотреть файл

@ -3,6 +3,7 @@ package midi
import ( import (
"machine" "machine"
"machine/usb" "machine/usb"
"machine/usb/descriptor"
) )
const ( const (
@ -40,7 +41,23 @@ func newMidi() *midi {
m := &midi{ m := &midi{
buf: NewRingBuffer(), buf: NewRingBuffer(),
} }
machine.EnableMIDI(m.Handler, m.RxHandler, nil) machine.ConfigureUSBEndpoint(descriptor.CDCMIDI,
[]usb.EndpointConfig{
{
No: usb.MIDI_ENDPOINT_OUT,
IsIn: false,
Type: usb.ENDPOINT_TYPE_BULK,
RxHandler: m.RxHandler,
},
{
No: usb.MIDI_ENDPOINT_IN,
IsIn: true,
Type: usb.ENDPOINT_TYPE_BULK,
TxHandler: m.Handler,
},
},
[]usb.SetupConfig{},
)
return m return m
} }

14
src/machine/usb/config.go Обычный файл
Просмотреть файл

@ -0,0 +1,14 @@
package usb
type EndpointConfig struct {
No uint8
IsIn bool
TxHandler func()
RxHandler func([]byte)
Type uint8
}
type SetupConfig struct {
No uint8
Handler func(Setup) bool
}

Просмотреть файл

@ -4,6 +4,7 @@ import (
"errors" "errors"
"machine" "machine"
"machine/usb" "machine/usb"
"machine/usb/descriptor"
) )
// from usb-hid.go // from usb-hid.go
@ -32,7 +33,21 @@ var size int
// calls machine.EnableHID for USB configuration // calls machine.EnableHID for USB configuration
func SetHandler(d hidDevicer) { func SetHandler(d hidDevicer) {
if size == 0 { if size == 0 {
machine.EnableHID(handler, nil, setupHandler) machine.ConfigureUSBEndpoint(descriptor.CDCHID,
[]usb.EndpointConfig{
{
No: usb.HID_ENDPOINT_IN,
IsIn: true,
Type: usb.ENDPOINT_TYPE_INTERRUPT,
TxHandler: handler,
},
},
[]usb.SetupConfig{
{
No: usb.HID_INTERFACE,
Handler: setupHandler,
},
})
} }
devices[size] = d devices[size] = d

Просмотреть файл

@ -3,6 +3,7 @@ package joystick
import ( import (
"machine" "machine"
"machine/usb" "machine/usb"
"machine/usb/descriptor"
"machine/usb/hid" "machine/usb/hid"
) )
@ -32,18 +33,50 @@ func UseSettings(def Definitions, rxHandlerFunc func(b []byte), setupFunc func(s
if setupFunc == nil { if setupFunc == nil {
setupFunc = hid.DefaultSetupHandler setupFunc = hid.DefaultSetupHandler
} }
machine.EnableJoystick(js.handler, rxHandlerFunc, setupFunc, hidDesc) if rxHandlerFunc == nil {
rxHandlerFunc = js.rxHandlerFunc
}
if len(hidDesc) == 0 {
hidDesc = descriptor.JoystickDefaultHIDReport
}
class, err := descriptor.FindClassHIDType(descriptor.CDCJoystick.Configuration, descriptor.ClassHIDJoystick.Bytes())
if err != nil {
// TODO: some way to notify about error
return nil
}
class.ClassLength(uint16(len(hidDesc)))
descriptor.CDCJoystick.HID[2] = hidDesc
machine.ConfigureUSBEndpoint(descriptor.CDCJoystick,
[]usb.EndpointConfig{
{
No: usb.HID_ENDPOINT_OUT,
IsIn: false,
Type: usb.ENDPOINT_TYPE_INTERRUPT,
RxHandler: rxHandlerFunc,
},
{
No: usb.HID_ENDPOINT_IN,
IsIn: true,
Type: usb.ENDPOINT_TYPE_INTERRUPT,
TxHandler: js.handler,
},
},
[]usb.SetupConfig{
{
No: usb.HID_INTERFACE,
Handler: setupFunc,
},
},
)
Joystick = js Joystick = js
return js return js
} }
func newDefaultJoystick() *joystick { func newDefaultJoystick() *joystick {
def := DefaultDefinitions() def := DefaultDefinitions()
js := &joystick{ js := UseSettings(def, nil, nil, nil)
State: def.NewState(),
buf: hid.NewRingBuffer(),
}
machine.EnableJoystick(js.handler, js.rxHandler, hid.DefaultSetupHandler, def.Descriptor())
return js return js
} }