github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/usb/hid/joystick/joystick.go (about) 1 package joystick 2 3 import ( 4 "machine" 5 "machine/usb" 6 "machine/usb/descriptor" 7 "machine/usb/hid" 8 ) 9 10 var Joystick *joystick 11 12 type joystick struct { 13 State 14 buf *hid.RingBuffer 15 waitTxc bool 16 rxHandlerFunc func(b []byte) 17 setupFunc func(setup usb.Setup) bool 18 } 19 20 func init() { 21 if Joystick == nil { 22 Joystick = newDefaultJoystick() 23 } 24 } 25 26 // UseSettings overrides the Joystick settings. This function must be 27 // called from init(). 28 func UseSettings(def Definitions, rxHandlerFunc func(b []byte), setupFunc func(setup usb.Setup) bool, hidDesc []byte) *joystick { 29 js := &joystick{ 30 buf: hid.NewRingBuffer(), 31 State: def.NewState(), 32 } 33 if setupFunc == nil { 34 setupFunc = hid.DefaultSetupHandler 35 } 36 if rxHandlerFunc == nil { 37 rxHandlerFunc = js.rxHandlerFunc 38 } 39 if len(hidDesc) == 0 { 40 hidDesc = descriptor.JoystickDefaultHIDReport 41 } 42 class, err := descriptor.FindClassHIDType(descriptor.CDCJoystick.Configuration, descriptor.ClassHIDJoystick.Bytes()) 43 if err != nil { 44 // TODO: some way to notify about error 45 return nil 46 } 47 48 class.ClassLength(uint16(len(hidDesc))) 49 descriptor.CDCJoystick.HID[2] = hidDesc 50 51 machine.ConfigureUSBEndpoint(descriptor.CDCJoystick, 52 []usb.EndpointConfig{ 53 { 54 Index: usb.HID_ENDPOINT_OUT, 55 IsIn: false, 56 Type: usb.ENDPOINT_TYPE_INTERRUPT, 57 RxHandler: rxHandlerFunc, 58 }, 59 { 60 Index: usb.HID_ENDPOINT_IN, 61 IsIn: true, 62 Type: usb.ENDPOINT_TYPE_INTERRUPT, 63 TxHandler: js.handler, 64 }, 65 }, 66 []usb.SetupConfig{ 67 { 68 Index: usb.HID_INTERFACE, 69 Handler: setupFunc, 70 }, 71 }, 72 ) 73 Joystick = js 74 return js 75 } 76 77 func newDefaultJoystick() *joystick { 78 def := DefaultDefinitions() 79 js := UseSettings(def, nil, nil, nil) 80 return js 81 } 82 83 // Port returns the USB Joystick port. 84 func Port() *joystick { 85 return Joystick 86 } 87 88 func (m *joystick) handler() { 89 m.waitTxc = false 90 if b, ok := m.buf.Get(); ok { 91 m.waitTxc = true 92 hid.SendUSBPacket(b) 93 } 94 } 95 96 func (m *joystick) tx(b []byte) { 97 if machine.USBDev.InitEndpointComplete { 98 if m.waitTxc { 99 m.buf.Put(b) 100 } else { 101 m.waitTxc = true 102 hid.SendUSBPacket(b) 103 } 104 } 105 } 106 107 func (m *joystick) ready() bool { 108 return true 109 } 110 111 func (m *joystick) rxHandler(b []byte) { 112 if m.rxHandlerFunc != nil { 113 m.rxHandlerFunc(b) 114 } 115 } 116 117 // to InterruptOut 118 func (m *joystick) SendReport(reportID byte, b []byte) { 119 m.tx(append([]byte{reportID}, b...)) 120 } 121 122 func (m *joystick) SendState() { 123 b, _ := m.State.MarshalBinary() 124 m.tx(b) 125 }