aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoririeda <[email protected]>2023-01-08 06:30:40 +0900
committerGitHub <[email protected]>2023-01-07 22:30:40 +0100
commita7ff2731b91a83767a72da5f8ad196b45bc4c5de (patch)
tree158138c8c627c2e435d000edeb66a8c6be7a7ea3
parent0566bbfeb4f09adecfa1658ad7c67ac652057dce (diff)
downloadtinygo-a7ff2731b91a83767a72da5f8ad196b45bc4c5de.tar.gz
tinygo-a7ff2731b91a83767a72da5f8ad196b45bc4c5de.zip
Add USB HID joystick support (#3366)
machine/usb: add USB HID joystick support
-rw-r--r--src/examples/hid-joystick/main.go27
-rw-r--r--src/machine/machine_rp2040_usb.go5
-rw-r--r--src/machine/usb.go22
-rw-r--r--src/machine/usb/descriptor.go51
-rw-r--r--src/machine/usb/hid/hid.go9
-rw-r--r--src/machine/usb/joystick/buffer.go52
-rw-r--r--src/machine/usb/joystick/joystick.go95
-rw-r--r--src/machine/usb/joystick/state.go213
-rw-r--r--src/machine/usb/midi/midi.go5
-rw-r--r--src/machine/usb/usb.go17
10 files changed, 482 insertions, 14 deletions
diff --git a/src/examples/hid-joystick/main.go b/src/examples/hid-joystick/main.go
new file mode 100644
index 000000000..1271d997d
--- /dev/null
+++ b/src/examples/hid-joystick/main.go
@@ -0,0 +1,27 @@
+package main
+
+import (
+ "log"
+ "machine/usb/joystick"
+ "math"
+ "time"
+)
+
+var js = joystick.Port()
+
+func main() {
+ log.SetFlags(log.Lmicroseconds)
+ ticker := time.NewTicker(10 * time.Millisecond)
+ cnt := 0
+ const f = 3.0
+ for range ticker.C {
+ t := float64(cnt) * 0.01
+ x := 32767 * math.Sin(2*math.Pi*f*t)
+ button := cnt%100 > 50
+ js.SetButton(2, button)
+ js.SetButton(3, !button)
+ js.SetAxis(0, int(x))
+ js.SendState()
+ cnt++
+ }
+}
diff --git a/src/machine/machine_rp2040_usb.go b/src/machine/machine_rp2040_usb.go
index 372080eec..cb3bb789d 100644
--- a/src/machine/machine_rp2040_usb.go
+++ b/src/machine/machine_rp2040_usb.go
@@ -151,7 +151,10 @@ func initEndpoint(ep, config uint32) {
usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
- // TODO: not really anything, seems like...
+ val |= usbEpControlEndpointTypeInterrupt
+ usbDPSRAM.EPxControl[ep].Out.Set(val)
+ usbDPSRAM.EPxBufferControl[ep].Out.Set(USBBufferLen & usbBuf0CtrlLenMask)
+ usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
val |= usbEpControlEndpointTypeBulk
diff --git a/src/machine/usb.go b/src/machine/usb.go
index f49ee119e..7ed4ef35e 100644
--- a/src/machine/usb.go
+++ b/src/machine/usb.go
@@ -3,6 +3,8 @@
package machine
import (
+ "bytes"
+ "encoding/binary"
"errors"
"machine/usb"
)
@@ -89,8 +91,9 @@ var (
usb.CDC_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut),
usb.CDC_ENDPOINT_IN: (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn),
usb.HID_ENDPOINT_IN: (usb.ENDPOINT_TYPE_DISABLE), // Interrupt In
- usb.MIDI_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Bulk Out
+ usb.HID_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Interrupt Out
usb.MIDI_ENDPOINT_IN: (usb.ENDPOINT_TYPE_DISABLE), // Bulk In
+ usb.MIDI_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Bulk Out
}
)
@@ -108,6 +111,8 @@ func sendDescriptor(setup usb.Setup) {
usbDescriptor = usb.DescriptorCDCHID
case (usbDescriptorConfig & usb.DescriptorConfigMIDI) > 0:
usbDescriptor = usb.DescriptorCDCMIDI
+ case (usbDescriptorConfig & usb.DescriptorConfigJoystick) > 0:
+ usbDescriptor = usb.DescriptorCDCJoystick
default:
usbDescriptor = usb.DescriptorCDC
}
@@ -260,3 +265,18 @@ func EnableMIDI(txHandler func(), rxHandler func([]byte), setupHandler func(usb.
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) {
+ 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
+ usbDescriptorConfig |= usb.DescriptorConfigJoystick
+ 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)
+}
diff --git a/src/machine/usb/descriptor.go b/src/machine/usb/descriptor.go
index 17bf07709..3acb2e9a7 100644
--- a/src/machine/usb/descriptor.go
+++ b/src/machine/usb/descriptor.go
@@ -109,9 +109,58 @@ var DescriptorCDCMIDI = Descriptor{
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, 0x05, 0x02, 0x40, 0x00, 0x00, 0x00, 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{},
+}
diff --git a/src/machine/usb/hid/hid.go b/src/machine/usb/hid/hid.go
index 4f4072419..d0ad366f0 100644
--- a/src/machine/usb/hid/hid.go
+++ b/src/machine/usb/hid/hid.go
@@ -14,10 +14,11 @@ var (
)
const (
- hidEndpoint = 4
+ hidEndpoint = usb.HID_ENDPOINT_IN
- usb_SET_REPORT_TYPE = 33
- usb_SET_IDLE = 10
+ REPORT_TYPE_INPUT = 1
+ REPORT_TYPE_OUTPUT = 2
+ REPORT_TYPE_FEATURE = 3
)
type hidDevicer interface {
@@ -51,7 +52,7 @@ func handler() {
func setupHandler(setup usb.Setup) bool {
ok := false
- if setup.BmRequestType == usb_SET_REPORT_TYPE && setup.BRequest == usb_SET_IDLE {
+ if setup.BmRequestType == usb.SET_REPORT_TYPE && setup.BRequest == usb.SET_IDLE {
machine.SendZlp()
ok = true
}
diff --git a/src/machine/usb/joystick/buffer.go b/src/machine/usb/joystick/buffer.go
new file mode 100644
index 000000000..3610b52e3
--- /dev/null
+++ b/src/machine/usb/joystick/buffer.go
@@ -0,0 +1,52 @@
+package joystick
+
+import (
+ "runtime/volatile"
+)
+
+const bufferSize = 32
+
+// RingBuffer is ring buffer implementation inspired by post at
+// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php
+type RingBuffer struct {
+ rxbuffer [bufferSize][16]byte
+ head volatile.Register8
+ tail volatile.Register8
+}
+
+// NewRingBuffer returns a new ring buffer.
+func NewRingBuffer() *RingBuffer {
+ return &RingBuffer{}
+}
+
+// Used returns how many bytes in buffer have been used.
+func (rb *RingBuffer) Used() uint8 {
+ return uint8(rb.head.Get() - rb.tail.Get())
+}
+
+// Put stores a byte in the buffer. If the buffer is already
+// full, the method will return false.
+func (rb *RingBuffer) Put(val []byte) bool {
+ if rb.Used() != bufferSize {
+ rb.head.Set(rb.head.Get() + 1)
+ copy(rb.rxbuffer[rb.head.Get()%bufferSize][:], val)
+ return true
+ }
+ return false
+}
+
+// Get returns a byte from the buffer. If the buffer is empty,
+// the method will return a false as the second value.
+func (rb *RingBuffer) Get() ([]byte, bool) {
+ if rb.Used() != 0 {
+ rb.tail.Set(rb.tail.Get() + 1)
+ return rb.rxbuffer[rb.tail.Get()%bufferSize][:], true
+ }
+ return nil, false
+}
+
+// Clear resets the head and tail pointer to zero.
+func (rb *RingBuffer) Clear() {
+ rb.head.Set(0)
+ rb.tail.Set(0)
+}
diff --git a/src/machine/usb/joystick/joystick.go b/src/machine/usb/joystick/joystick.go
new file mode 100644
index 000000000..9c12997b9
--- /dev/null
+++ b/src/machine/usb/joystick/joystick.go
@@ -0,0 +1,95 @@
+package joystick
+
+import (
+ "machine"
+ "machine/usb"
+)
+
+const (
+ jsEndpointOut = usb.HID_ENDPOINT_OUT // from PC
+ jsEndpointIn = usb.HID_ENDPOINT_IN // to PC
+)
+
+var js *Joystick
+
+type Joystick struct {
+ State
+ buf *RingBuffer
+ waitTxc bool
+ rxHandlerFunc func(b []byte)
+ setupFunc func(setup usb.Setup) bool
+}
+
+func Enable(def Definitions, rxHandlerFunc func(b []byte),
+ setupFunc func(setup usb.Setup) bool, hidDesc []byte) *Joystick {
+ m := &Joystick{
+ buf: NewRingBuffer(),
+ State: def.NewState(),
+ }
+ m.State = def.NewState()
+ if setupFunc == nil {
+ setupFunc = m.setupFunc
+ }
+ machine.EnableJoystick(m.handler, rxHandlerFunc, setupFunc, hidDesc)
+ js = m
+ return m
+}
+
+// Port returns the USB Joystick port.
+func Port() *Joystick {
+ if js == nil {
+ def := DefaultDefinitions()
+ js = &Joystick{
+ State: def.NewState(),
+ buf: NewRingBuffer(),
+ }
+ machine.EnableJoystick(js.handler, nil, js.setupFunc, def.Descriptor())
+ }
+ return js
+}
+
+func (m *Joystick) sendUSBPacket(b []byte) {
+ machine.SendUSBInPacket(jsEndpointIn, b)
+}
+
+// from InterruptIn
+func (m *Joystick) handler() {
+ m.waitTxc = false
+ if b, ok := m.buf.Get(); ok {
+ m.waitTxc = true
+ m.sendUSBPacket(b)
+ }
+}
+
+func (m *Joystick) setup(setup usb.Setup) bool {
+ if setup.BmRequestType == usb.SET_REPORT_TYPE && setup.BRequest == usb.SET_IDLE {
+ machine.SendZlp()
+ return true
+ }
+ return false
+}
+
+func (m *Joystick) rxHandler(b []byte) {
+ if m.rxHandlerFunc != nil {
+ m.rxHandlerFunc(b)
+ }
+}
+
+func (m *Joystick) tx(b []byte) {
+ if m.waitTxc {
+ m.buf.Put(b)
+ } else {
+ m.waitTxc = true
+ m.sendUSBPacket(b)
+ }
+}
+
+// to InterruptOut
+func (m *Joystick) SendReport(reportID byte, b []byte) {
+ m.tx(append([]byte{reportID}, b...))
+}
+
+func (m *Joystick) SendState() {
+ b, _ := m.State.MarshalBinary()
+ m.tx(b)
+}
diff --git a/src/machine/usb/joystick/state.go b/src/machine/usb/joystick/state.go
new file mode 100644
index 000000000..51b7e6c40
--- /dev/null
+++ b/src/machine/usb/joystick/state.go
@@ -0,0 +1,213 @@
+package joystick
+
+import "encoding/binary"
+
+type HatDirection uint8
+
+const (
+ HatUp HatDirection = iota
+ HatRightUp
+ HatRight
+ HatRightDown
+ HatDown
+ HatLeftDown
+ HatLeft
+ HatLeftUp
+ HatCenter
+)
+
+type Constraint struct {
+ MinIn int
+ MaxIn int
+ MinOut int16
+ MaxOut int16
+}
+
+type AxisValue struct {
+ constraint Constraint
+ Value int
+}
+
+func fit(x, in_min, in_max int, out_min, out_max int16) int16 {
+ return int16((x-in_min)*(int(out_max)-int(out_min))/(in_max-in_min) + int(out_min))
+}
+
+func fitf(x, in_min, in_max, out_min, out_max float32) float32 {
+ return x - in_min*(out_max-out_min)/(in_max-in_min) + out_min
+}
+
+func limit(v, max int) int {
+ if v > max {
+ v = max
+ } else if v < -max {
+ v = -max
+ }
+ return v
+}
+
+type Definitions struct {
+ ReportID byte
+ ButtonCnt int
+ HatSwitchCnt int
+ AxisDefs []Constraint
+ descriptor []byte
+}
+
+func (c Definitions) Descriptor() []byte {
+ if len(c.descriptor) > 0 {
+ return c.descriptor
+ }
+ // TODO: build hid descriptor
+ return nil
+}
+
+func (c Definitions) NewState() State {
+ bufSize := 1
+ axises := make([]*AxisValue, 0, len(c.AxisDefs))
+ for _, v := range c.AxisDefs {
+
+ axises = append(axises, &AxisValue{
+ constraint: v,
+ Value: 0,
+ })
+ }
+ btnSize := (c.ButtonCnt + 7) / 8
+ bufSize += btnSize
+ if c.HatSwitchCnt > 0 {
+ bufSize++
+ }
+ bufSize += len(axises) * 2
+ initBuf := make([]byte, bufSize)
+ initBuf[0] = c.ReportID
+ return State{
+ buf: initBuf,
+ Buttons: make([]byte, btnSize),
+ HatSwitches: make([]HatDirection, c.HatSwitchCnt),
+ Axises: axises,
+ }
+}
+
+type State struct {
+ buf []byte
+ Buttons []byte
+ HatSwitches []HatDirection
+ Axises []*AxisValue
+}
+
+func (s State) MarshalBinary() ([]byte, error) {
+ s.buf = s.buf[0:1]
+ s.buf = append(s.buf, s.Buttons...)
+ if len(s.HatSwitches) > 0 {
+ hat := byte(0)
+ for _, v := range s.HatSwitches {
+ hat <<= 4
+ hat |= byte(v & 0xf)
+ }
+ s.buf = append(s.buf, hat)
+ }
+ for _, v := range s.Axises {
+ c := v.constraint
+ val := fit(v.Value, c.MinIn, c.MaxIn, c.MinOut, c.MaxOut)
+ s.buf = binary.LittleEndian.AppendUint16(s.buf, uint16(val))
+ }
+ return s.buf, nil
+}
+
+func (s State) Button(index int) bool {
+ idx := index / 8
+ bit := uint8(1 << (index % 8))
+ return s.Buttons[idx]&bit > 0
+}
+
+func (s State) SetButton(index int, push bool) {
+ idx := index / 8
+ bit := uint8(1 << (index % 8))
+ b := s.Buttons[idx]
+ b &= ^bit
+ if push {
+ b |= bit
+ }
+ s.Buttons[idx] = b
+}
+
+func (s State) Hat(index int) HatDirection {
+ return s.HatSwitches[index]
+}
+
+func (s State) SetHat(index int, dir HatDirection) {
+ s.HatSwitches[index] = dir
+}
+
+func (s State) Axis(index int) int {
+ return s.Axises[index].Value
+}
+
+func (s State) SetAxis(index int, v int) {
+ s.Axises[index].Value = v
+}
+
+func DefaultDefinitions() Definitions {
+ return Definitions{
+ ReportID: 1,
+ ButtonCnt: 16,
+ HatSwitchCnt: 1,
+ AxisDefs: []Constraint{
+ {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},
+ {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
+ },
+ }
+}
diff --git a/src/machine/usb/midi/midi.go b/src/machine/usb/midi/midi.go
index 58f802b51..c0796be49 100644
--- a/src/machine/usb/midi/midi.go
+++ b/src/machine/usb/midi/midi.go
@@ -2,11 +2,12 @@ package midi
import (
"machine"
+ "machine/usb"
)
const (
- midiEndpointOut = 5 // from PC
- midiEndpointIn = 6 // to PC
+ midiEndpointOut = usb.MIDI_ENDPOINT_OUT // from PC
+ midiEndpointIn = usb.MIDI_ENDPOINT_IN // to PC
)
var Midi *midi
diff --git a/src/machine/usb/usb.go b/src/machine/usb/usb.go
index 592b32beb..8363fc361 100644
--- a/src/machine/usb/usb.go
+++ b/src/machine/usb/usb.go
@@ -9,6 +9,7 @@ const (
DescriptorConfigCDC = 1 << iota
DescriptorConfigHID
DescriptorConfigMIDI
+ DescriptorConfigJoystick
)
const (
@@ -35,7 +36,6 @@ const (
EndpointOut = 0x00
EndpointIn = 0x80
- NumberOfEndpoints = 8
EndpointPacketSize = 64 // 64 for Full Speed, EPT size max is 1024
// standard requests
@@ -51,7 +51,12 @@ const (
SET_INTERFACE = 11
// non standard requests
- SET_IDLE = 10
+ GET_REPORT = 1
+ GET_IDLE = 2
+ GET_PROTOCOL = 3
+ SET_REPORT = 9
+ SET_IDLE = 10
+ SET_PROTOCOL = 11
DEVICE_CLASS_COMMUNICATIONS = 0x02
DEVICE_CLASS_HUMAN_INTERFACE = 0x03
@@ -75,9 +80,11 @@ const (
CDC_ENDPOINT_ACM = 1
CDC_ENDPOINT_OUT = 2
CDC_ENDPOINT_IN = 3
- HID_ENDPOINT_IN = 4
- MIDI_ENDPOINT_OUT = 5
- MIDI_ENDPOINT_IN = 6
+ HID_ENDPOINT_IN = 4 // for Interrupt In
+ HID_ENDPOINT_OUT = 5 // for Interrupt Out
+ MIDI_ENDPOINT_IN = 6 // for Bulk In
+ MIDI_ENDPOINT_OUT = 7 // for Bulk Out
+ NumberOfEndpoints = 8
// bmRequestType
REQUEST_HOSTTODEVICE = 0x00