From 069e4f0d987bef4699c55e84b55c7e5caa3f928c Mon Sep 17 00:00:00 2001 From: sago35 Date: Tue, 1 Aug 2023 20:22:30 +0900 Subject: [PATCH] machine/usb: allow USB Endpoint settings to be changed externally --- src/machine/usb.go | 81 +++++++++++++----------- src/machine/usb/adc/midi/midi.go | 19 +++++- src/machine/usb/config.go | 14 ++++ src/machine/usb/hid/hid.go | 17 ++++- src/machine/usb/hid/joystick/joystick.go | 45 +++++++++++-- 5 files changed, 130 insertions(+), 46 deletions(-) create mode 100644 src/machine/usb/config.go diff --git a/src/machine/usb.go b/src/machine/usb.go index 34c13a5c..823dfdb5 100644 --- a/src/machine/usb.go +++ b/src/machine/usb.go @@ -263,47 +263,52 @@ func EnableCDC(txHandler func(), rxHandler func([]byte), setupHandler func(usb.S usbDescriptor = descriptor.CDC } // Initialization of endpoints is required even for non-CDC - endPoints[usb.CDC_ENDPOINT_ACM] = (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn) - endPoints[usb.CDC_ENDPOINT_OUT] = (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut) - endPoints[usb.CDC_ENDPOINT_IN] = (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn) - usbRxHandler[usb.CDC_ENDPOINT_OUT] = rxHandler - usbTxHandler[usb.CDC_ENDPOINT_IN] = txHandler - usbSetupHandler[usb.CDC_ACM_INTERFACE] = setupHandler // 0x02 (Communications and CDC Control) - usbSetupHandler[usb.CDC_DATA_INTERFACE] = nil // 0x0A (CDC-Data) + ConfigureUSBEndpoint(usbDescriptor, + []usb.EndpointConfig{ + { + No: usb.CDC_ENDPOINT_ACM, + IsIn: true, + Type: usb.ENDPOINT_TYPE_INTERRUPT, + }, + { + 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 EnableHID(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) { - usbDescriptor = descriptor.CDCHID - 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) -} +func ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []usb.EndpointConfig, setup []usb.SetupConfig) { + usbDescriptor = desc -// EnableMIDI enables MIDI. This function must be executed from the init(). -func EnableMIDI(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) { - 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 + for _, ep := range epSettings { + if ep.IsIn { + 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 + } + } } - 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) + for _, s := range setup { + usbSetupHandler[s.No] = s.Handler + } } diff --git a/src/machine/usb/adc/midi/midi.go b/src/machine/usb/adc/midi/midi.go index 2697866f..d0ce3ee1 100644 --- a/src/machine/usb/adc/midi/midi.go +++ b/src/machine/usb/adc/midi/midi.go @@ -3,6 +3,7 @@ package midi import ( "machine" "machine/usb" + "machine/usb/descriptor" ) const ( @@ -40,7 +41,23 @@ func newMidi() *midi { m := &midi{ 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 } diff --git a/src/machine/usb/config.go b/src/machine/usb/config.go new file mode 100644 index 00000000..de620e7a --- /dev/null +++ b/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 +} diff --git a/src/machine/usb/hid/hid.go b/src/machine/usb/hid/hid.go index 67656962..4a17f953 100644 --- a/src/machine/usb/hid/hid.go +++ b/src/machine/usb/hid/hid.go @@ -4,6 +4,7 @@ import ( "errors" "machine" "machine/usb" + "machine/usb/descriptor" ) // from usb-hid.go @@ -32,7 +33,21 @@ var size int // calls machine.EnableHID for USB configuration func SetHandler(d hidDevicer) { 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 diff --git a/src/machine/usb/hid/joystick/joystick.go b/src/machine/usb/hid/joystick/joystick.go index 763b39ee..18a4d470 100644 --- a/src/machine/usb/hid/joystick/joystick.go +++ b/src/machine/usb/hid/joystick/joystick.go @@ -3,6 +3,7 @@ package joystick import ( "machine" "machine/usb" + "machine/usb/descriptor" "machine/usb/hid" ) @@ -32,18 +33,50 @@ func UseSettings(def Definitions, rxHandlerFunc func(b []byte), setupFunc func(s if setupFunc == nil { 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 return js } func newDefaultJoystick() *joystick { def := DefaultDefinitions() - js := &joystick{ - State: def.NewState(), - buf: hid.NewRingBuffer(), - } - machine.EnableJoystick(js.handler, js.rxHandler, hid.DefaultSetupHandler, def.Descriptor()) + js := UseSettings(def, nil, nil, nil) return js }