From 0066bb37db08635d74b27eb9c9e2e12219d8851c Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Fri, 12 Sep 2025 09:44:13 -0400 Subject: [PATCH] feat: allow bidirectional usb endpoint numbers --- builder/sizes_test.go | 2 +- src/machine/machine_atsamd21_usb.go | 78 +++++++++++++---------- src/machine/machine_atsamd51_usb.go | 44 ++++++------- src/machine/machine_nrf52840_usb.go | 20 ++---- src/machine/machine_rp2_usb.go | 87 +++++++++++++++----------- src/machine/usb.go | 33 ++++++++-- src/machine/usb/cdc/cdc.go | 4 +- src/machine/usb/descriptor/cdc.go | 6 +- src/machine/usb/descriptor/endpoint.go | 59 ++++++++++------- src/machine/usb/descriptor/hid.go | 10 +-- src/machine/usb/descriptor/joystick.go | 10 +-- src/machine/usb/descriptor/midi.go | 33 +++++----- src/machine/usb/descriptor/msc.go | 6 +- src/machine/usb/usb.go | 16 ++--- 14 files changed, 226 insertions(+), 182 deletions(-) diff --git a/builder/sizes_test.go b/builder/sizes_test.go index f4274708da..dffbcb0ade 100644 --- a/builder/sizes_test.go +++ b/builder/sizes_test.go @@ -44,7 +44,7 @@ func TestBinarySize(t *testing.T) { // microcontrollers {"hifive1b", "examples/echo", 4580, 280, 0, 2264}, {"microbit", "examples/serial", 2928, 388, 8, 2272}, - {"wioterminal", "examples/pininterrupt", 7387, 1489, 116, 6912}, + {"wioterminal", "examples/pininterrupt", 7442, 1502, 116, 6592}, // TODO: also check wasm. Right now this is difficult, because // wasm binaries are run through wasm-opt and therefore the diff --git a/src/machine/machine_atsamd21_usb.go b/src/machine/machine_atsamd21_usb.go index 7b9d2e14f8..c8c52f4d78 100644 --- a/src/machine/machine_atsamd21_usb.go +++ b/src/machine/machine_atsamd21_usb.go @@ -19,21 +19,6 @@ const ( usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Pos = 14 usb_DEVICE_PCKSIZE_MULTI_PACKET_SIZE_Mask = 0x3FFF - - NumberOfUSBEndpoints = 8 -) - -var ( - endPoints = []uint32{ - usb.CONTROL_ENDPOINT: usb.ENDPOINT_TYPE_CONTROL, - usb.CDC_ENDPOINT_ACM: (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn), - 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.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 - } ) // Configure the USB peripheral. The config is here for compatibility with the UART interface. @@ -188,7 +173,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) { // Now the actual transfer handlers, ignore endpoint number 0 (setup) var i uint32 - for i = 1; i < uint32(len(endPoints)); i++ { + for i = 1; i < uint32(NumberOfUSBEndpoints); i++ { // Check if endpoint has a pending interrupt epFlags := getEPINTFLAG(i) setEPINTFLAG(i, epFlags) @@ -197,7 +182,8 @@ func handleUSBIRQ(intr interrupt.Interrupt) { if usbRxHandler[i] == nil || usbRxHandler[i](buf) { AckUsbOutTransfer(i) } - } else if (epFlags & sam.USB_DEVICE_EPINTFLAG_TRCPT1) > 0 { + } + if (epFlags & sam.USB_DEVICE_EPINTFLAG_TRCPT1) > 0 { if usbTxHandler[i] != nil { usbTxHandler[i]() } @@ -215,8 +201,9 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_EPCFG_EPTYPE1_Pos)) + setEPCFGEPType1(ep, (usb.ENDPOINT_TYPE_INTERRUPT + 1)) + // Set interrupt enable setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT1) case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut: @@ -227,7 +214,7 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_EPCFG_EPTYPE0_Pos)) + setEPCFGEPType0(ep, (usb.ENDPOINT_TYPE_BULK + 1)) // receive interrupts when current transfer complete setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT0) @@ -246,7 +233,7 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_EPCFG_EPTYPE0_Pos)) + setEPCFGEPType0(ep, (usb.ENDPOINT_TYPE_INTERRUPT + 1)) // receive interrupts when current transfer complete setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT0) @@ -265,11 +252,12 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_EPCFG_EPTYPE1_Pos)) + setEPCFGEPType1(ep, (usb.ENDPOINT_TYPE_BULK + 1)) // NAK on endpoint IN, the bank is not yet filled in. setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK1RDY) + // Set interrupt enable setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT1) case usb.ENDPOINT_TYPE_CONTROL: @@ -281,7 +269,7 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_CONTROL+1)< 0 { + } + if (epFlags & sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1) > 0 { if usbTxHandler[i] != nil { usbTxHandler[i]() } @@ -218,8 +204,9 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos)) + setEPCFGEPType1(ep, (usb.ENDPOINT_TYPE_INTERRUPT + 1)) + // Set interrupt enable setEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT1) case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut: @@ -230,7 +217,7 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos)) + setEPCFGEPType0(ep, (usb.ENDPOINT_TYPE_BULK + 1)) // receive interrupts when current transfer complete setEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0) @@ -249,7 +236,7 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos)) + setEPCFGEPType0(ep, (usb.ENDPOINT_TYPE_INTERRUPT + 1)) // receive interrupts when current transfer complete setEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0) @@ -268,11 +255,12 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos)) + setEPCFGEPType1(ep, (usb.ENDPOINT_TYPE_BULK + 1)) // NAK on endpoint IN, the bank is not yet filled in. setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK1RDY) + // Set interrupt enable setEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT1) case usb.ENDPOINT_TYPE_CONTROL: @@ -284,7 +272,7 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_CONTROL+1)< 0 outDataDone := epDataStatus&(nrf.USBD_EPDATASTATUS_EPOUT1<<(i-1)) > 0 @@ -191,7 +178,8 @@ func handleUSBIRQ(interrupt.Interrupt) { if usbTxHandler[i] != nil { usbTxHandler[i]() } - } else if outDataDone { + } + if outDataDone { enterCriticalSection() nrf.USBD.EPOUT[i].PTR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[i])))) count := nrf.USBD.SIZE.EPOUT[i].Get() @@ -202,7 +190,7 @@ func handleUSBIRQ(interrupt.Interrupt) { } // ENDEPOUT[n] events - for i := 0; i < len(endPoints); i++ { + for i := 0; i < len(outEndpoints); i++ { if nrf.USBD.EVENTS_ENDEPOUT[i].Get() > 0 { nrf.USBD.EVENTS_ENDEPOUT[i].Set(0) buf := handleEndpointRx(uint32(i)) diff --git a/src/machine/machine_rp2_usb.go b/src/machine/machine_rp2_usb.go index 297cc9d9cf..c537e9d219 100644 --- a/src/machine/machine_rp2_usb.go +++ b/src/machine/machine_rp2_usb.go @@ -8,25 +8,12 @@ import ( "unsafe" ) -const NumberOfUSBEndpoints = 8 - var ( sendOnEP0DATADONE struct { offset int data []byte pid uint32 } - - endPoints = []uint32{ - usb.CONTROL_ENDPOINT: usb.ENDPOINT_TYPE_CONTROL, - usb.CDC_ENDPOINT_ACM: (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn), - 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.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 - } ) func initEndpoint(ep, config uint32) { @@ -35,32 +22,34 @@ func initEndpoint(ep, config uint32) { val |= offset // Bulk and interrupt endpoints must have their Packet ID reset to DATA0 when un-stalled. - epXPIDReset[ep] = false // Default to false in case an endpoint is re-initialized. + // Default to false in case an endpoint is re-initialized. + inEpXPIDReset[ep] = false + outEpXPIDReset[ep] = false switch config { case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn: val |= usbEpControlEndpointTypeInterrupt _usbDPSRAM.EPxControl[ep].In.Set(val) - epXPIDReset[ep] = true + inEpXPIDReset[ep] = true case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut: val |= usbEpControlEndpointTypeBulk _usbDPSRAM.EPxControl[ep].Out.Set(val) _usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask) _usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail) - epXPIDReset[ep] = true + outEpXPIDReset[ep] = true case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut: val |= usbEpControlEndpointTypeInterrupt _usbDPSRAM.EPxControl[ep].Out.Set(val) _usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask) _usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail) - epXPIDReset[ep] = true + outEpXPIDReset[ep] = true case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn: val |= usbEpControlEndpointTypeBulk _usbDPSRAM.EPxControl[ep].In.Set(val) - epXPIDReset[ep] = true + inEpXPIDReset[ep] = true case usb.ENDPOINT_TYPE_CONTROL: val |= usbEpControlEndpointTypeControl @@ -94,7 +83,7 @@ func sendUSBPacket(ep uint32, data []byte, maxsize uint16) { } else { sendOnEP0DATADONE.offset = 0 } - epXdata0[ep] = true + inEpXdata0[ep] = usbPIDData1 } sendViaEPIn(ep, data, count) @@ -130,14 +119,24 @@ func handleEndpointRx(ep uint32) []byte { // AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer. func AckUsbOutTransfer(ep uint32) { + setOutEPDataPID(ep, !outEpXdata0[ep]) +} + +// Set the USB endpoint Packet ID to DATA0 or DATA1. +func setInEPDataPID(ep uint32, dataOne usbPID) { ep = ep & 0x7F - setEPDataPID(ep, !epXdata0[ep]) + inEpXdata0[ep] = dataOne + if inEpXdata0[ep] || ep == 0 { + _usbDPSRAM.EPxBufferControl[ep].In.SetBits(usbBuf0CtrlData1Pid) + } + + _usbDPSRAM.EPxBufferControl[ep].In.SetBits(usbBuf0CtrlAvail) } // Set the USB endpoint Packet ID to DATA0 or DATA1. -func setEPDataPID(ep uint32, dataOne bool) { - epXdata0[ep] = dataOne - if epXdata0[ep] || ep == 0 { +func setOutEPDataPID(ep uint32, dataOne usbPID) { + outEpXdata0[ep] = dataOne + if outEpXdata0[ep] || ep == 0 { _usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid) } @@ -151,22 +150,25 @@ func SendZlp() { func sendViaEPIn(ep uint32, data []byte, count int) { // Prepare buffer control register value val := uint32(count) | usbBuf0CtrlAvail + // Drop the endpoint in bit (0x80) + ep = ep & 0x7F // DATA0 or DATA1 - epXdata0[ep&0x7F] = !epXdata0[ep&0x7F] - if !epXdata0[ep&0x7F] { + inEpXdata0[ep] = !inEpXdata0[ep] + if !inEpXdata0[ep] { val |= usbBuf0CtrlData1Pid } // Mark as full val |= usbBuf0CtrlFull - copy(_usbDPSRAM.EPxBuffer[ep&0x7F].Buffer0[:], data[:count]) - _usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val) + copy(_usbDPSRAM.EPxBuffer[ep].Buffer0[:], data[:count]) + _usbDPSRAM.EPxBufferControl[ep].In.Set(val) } // Set ENDPOINT_HALT/stall status on a USB IN endpoint. func (dev *USBDevice) SetStallEPIn(ep uint32) { + // Drop the endpoint in bit (0x80) ep = ep & 0x7F // Prepare buffer control register value if ep == 0 { @@ -180,7 +182,6 @@ func (dev *USBDevice) SetStallEPIn(ep uint32) { // Set ENDPOINT_HALT/stall status on a USB OUT endpoint. func (dev *USBDevice) SetStallEPOut(ep uint32) { - ep = ep & 0x7F if ep == 0 { panic("SetStallEPOut: EP0 OUT not valid") } @@ -190,26 +191,28 @@ func (dev *USBDevice) SetStallEPOut(ep uint32) { // Clear the ENDPOINT_HALT/stall on a USB IN endpoint. func (dev *USBDevice) ClearStallEPIn(ep uint32) { + // Drop the endpoint in bit (0x80) ep = ep & 0x7F val := uint32(usbBuf0CtrlStall) _usbDPSRAM.EPxBufferControl[ep].In.ClearBits(val) - if epXPIDReset[ep] { + if inEpXPIDReset[ep] { // Reset the PID to DATA0 - setEPDataPID(ep, false) + setInEPDataPID(ep, usbPIDData0) } } // Clear the ENDPOINT_HALT/stall on a USB OUT endpoint. func (dev *USBDevice) ClearStallEPOut(ep uint32) { - ep = ep & 0x7F val := uint32(usbBuf0CtrlStall) _usbDPSRAM.EPxBufferControl[ep].Out.ClearBits(val) - if epXPIDReset[ep] { + if outEpXPIDReset[ep] { // Reset the PID to DATA0 - setEPDataPID(ep, false) + setOutEPDataPID(ep, usbPIDData0) } } +// RP2040: See datasheet section 4.1.2.7.2 +// RP2350: See datasheet section 12.7.3.7.2 type usbDPSRAM struct { // Note that EPxControl[0] is not EP0Control but 8-byte setup data. EPxControl [16]usbEndpointControlRegister @@ -233,11 +236,21 @@ type usbBuffer struct { Buffer1 [usbBufferLen]byte } +// USB Packet ID +type usbPID bool + +const ( + usbPIDData0 usbPID = false + usbPIDData1 usbPID = true +) + var ( - _usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000))) - epXdata0 [16]bool - epXPIDReset [16]bool - setupBytes [8]byte + _usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000))) + inEpXdata0 [16]usbPID + outEpXdata0 [16]usbPID + inEpXPIDReset [16]bool + outEpXPIDReset [16]bool + setupBytes [8]byte ) func (d *usbDPSRAM) setupBytes() []byte { diff --git a/src/machine/usb.go b/src/machine/usb.go index 434ee0f1b8..021a1b7032 100644 --- a/src/machine/usb.go +++ b/src/machine/usb.go @@ -119,11 +119,29 @@ var udd_ep_out_cache_buffer [NumberOfUSBEndpoints][64]uint8 // must be revisited. var usb_trans_buffer [255]uint8 +const NumberOfUSBEndpoints = max(len(inEndpoints), len(outEndpoints)) + var ( usbTxHandler [NumberOfUSBEndpoints]func() usbRxHandler [NumberOfUSBEndpoints]func([]byte) bool usbSetupHandler [usb.NumberOfInterfaces]func(usb.Setup) bool usbStallHandler [NumberOfUSBEndpoints]func(usb.Setup) bool + + inEndpoints = [...]uint32{ + usb.CONTROL_ENDPOINT: usb.ENDPOINT_TYPE_CONTROL, + usb.CDC_ENDPOINT_ACM: (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn), + usb.CDC_ENDPOINT_IN: (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn), + usb.HID_ENDPOINT_IN: (usb.ENDPOINT_TYPE_DISABLE), // Interrupt In + usb.MIDI_ENDPOINT_IN: (usb.ENDPOINT_TYPE_DISABLE), // Bulk In + usb.MSC_ENDPOINT_IN: (usb.ENDPOINT_TYPE_DISABLE), // Bulk In + } + outEndpoints = [...]uint32{ + usb.CONTROL_ENDPOINT: usb.ENDPOINT_TYPE_CONTROL, + usb.CDC_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut), + usb.HID_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Interrupt Out + usb.MIDI_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Bulk Out + usb.MSC_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Bulk Out + } ) // sendDescriptor creates and sends the various USB descriptor types that @@ -202,7 +220,7 @@ func handleStandardSetup(setup usb.Setup) bool { if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP isRemoteWakeUpEnabled = false } else if setup.WValueL == 0 { // ENDPOINTHALT - if idx := setup.WIndex & 0x7F; idx < NumberOfUSBEndpoints && usbStallHandler[idx] != nil { + if idx := setup.WIndex & 0x7F; idx < uint16(NumberOfUSBEndpoints) && usbStallHandler[idx] != nil { // Host has requested to clear an endpoint stall. If the request is addressed to // an endpoint with a configured StallHandler, forward the message on. // The 0x7F mask is used to clear the direction bit from the endpoint number @@ -217,7 +235,7 @@ func handleStandardSetup(setup usb.Setup) bool { if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP isRemoteWakeUpEnabled = true } else if setup.WValueL == 0 { // ENDPOINTHALT - if idx := setup.WIndex & 0x7F; idx < NumberOfUSBEndpoints && usbStallHandler[idx] != nil { + if idx := setup.WIndex & 0x7F; idx < uint16(NumberOfUSBEndpoints) && usbStallHandler[idx] != nil { // Host has requested to stall an endpoint. If the request is addressed to // an endpoint with a configured StallHandler, forward the message on. // The 0x7F mask is used to clear the direction bit from the endpoint number @@ -245,8 +263,11 @@ func handleStandardSetup(setup usb.Setup) bool { case usb.SET_CONFIGURATION: if setup.BmRequestType&usb.REQUEST_RECIPIENT == usb.REQUEST_DEVICE { - for i := 1; i < len(endPoints); i++ { - initEndpoint(uint32(i), endPoints[i]) + for i := 1; i < len(inEndpoints); i++ { + initEndpoint(uint32(i), inEndpoints[i]) + } + for i := 1; i < len(outEndpoints); i++ { + initEndpoint(uint32(i), outEndpoints[i]) } usbConfiguration = setup.WValueL @@ -312,12 +333,12 @@ func ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []usb.EndpointC for _, ep := range epSettings { if ep.IsIn { - endPoints[ep.Index] = uint32(ep.Type | usb.EndpointIn) + inEndpoints[ep.Index] = uint32(ep.Type | usb.EndpointIn) if ep.TxHandler != nil { usbTxHandler[ep.Index] = ep.TxHandler } } else { - endPoints[ep.Index] = uint32(ep.Type | usb.EndpointOut) + outEndpoints[ep.Index] = uint32(ep.Type | usb.EndpointOut) if ep.RxHandler != nil { usbRxHandler[ep.Index] = func(b []byte) bool { ep.RxHandler(b) diff --git a/src/machine/usb/cdc/cdc.go b/src/machine/usb/cdc/cdc.go index f180535df1..6888fa4f67 100644 --- a/src/machine/usb/cdc/cdc.go +++ b/src/machine/usb/cdc/cdc.go @@ -2,8 +2,8 @@ package cdc const ( cdcEndpointACM = 1 - cdcEndpointOut = 2 - cdcEndpointIn = 3 + cdcEndpointOut = 1 + cdcEndpointIn = 2 ) // New returns USBCDC struct. diff --git a/src/machine/usb/descriptor/cdc.go b/src/machine/usb/descriptor/cdc.go index ec72186e3a..8b427016f2 100644 --- a/src/machine/usb/descriptor/cdc.go +++ b/src/machine/usb/descriptor/cdc.go @@ -160,9 +160,9 @@ var CDC = Descriptor{ ClassSpecificCDCCallManagement.Bytes(), ClassSpecificCDCACM.Bytes(), ClassSpecificCDCUnion.Bytes(), - EndpointEP1IN.Bytes(), + EndpointCDCACMIN.Bytes(), InterfaceCDCData.Bytes(), - EndpointEP2OUT.Bytes(), - EndpointEP3IN.Bytes(), + EndpointCDCOUT.Bytes(), + EndpointCDCIN.Bytes(), }), } diff --git a/src/machine/usb/descriptor/endpoint.go b/src/machine/usb/descriptor/endpoint.go index 57a17060c4..a9ec1d2224 100644 --- a/src/machine/usb/descriptor/endpoint.go +++ b/src/machine/usb/descriptor/endpoint.go @@ -29,92 +29,103 @@ var EndpointEP1IN = EndpointType{ data: endpointEP1IN[:], } -var endpointEP2OUT = [endpointTypeLen]byte{ +var endpointEP1OUT = [endpointTypeLen]byte{ endpointTypeLen, TypeEndpoint, - 0x02, // EndpointAddress + 0x01, // EndpointAddress 0x02, // Attributes 0x40, // MaxPacketSizeL 0x00, // MaxPacketSizeH 0x00, // Interval } -var EndpointEP2OUT = EndpointType{ - data: endpointEP2OUT[:], +var EndpointEP1OUT = EndpointType{ + data: endpointEP1OUT[:], } -var endpointEP3IN = [endpointTypeLen]byte{ +var endpointEP2IN = [endpointTypeLen]byte{ endpointTypeLen, TypeEndpoint, - 0x83, // EndpointAddress + 0x82, // EndpointAddress 0x02, // Attributes 0x40, // MaxPacketSizeL 0x00, // MaxPacketSizeH 0x00, // Interval } -var EndpointEP3IN = EndpointType{ - data: endpointEP3IN[:], +var EndpointEP2IN = EndpointType{ + data: endpointEP2IN[:], } -var endpointEP4IN = [endpointTypeLen]byte{ +var endpointEP2OUT = [endpointTypeLen]byte{ endpointTypeLen, TypeEndpoint, - 0x84, // EndpointAddress + 0x02, // EndpointAddress 0x03, // Attributes 0x40, // MaxPacketSizeL 0x00, // MaxPacketSizeH 0x01, // Interval } -var EndpointEP4IN = EndpointType{ - data: endpointEP4IN[:], +var EndpointEP2OUT = EndpointType{ + data: endpointEP2OUT[:], } -var endpointEP5OUT = [endpointTypeLen]byte{ +var endpointEP3IN = [endpointTypeLen]byte{ endpointTypeLen, TypeEndpoint, - 0x05, // EndpointAddress + 0x83, // EndpointAddress 0x03, // Attributes 0x40, // MaxPacketSizeL 0x00, // MaxPacketSizeH 0x01, // Interval } -var EndpointEP5OUT = EndpointType{ - data: endpointEP5OUT[:], +var EndpointEP3IN = EndpointType{ + data: endpointEP3IN[:], } // Mass Storage Class bulk in endpoint -var endpointMSCIN = [endpointTypeLen]byte{ +var endpointEP5IN = [endpointTypeLen]byte{ endpointTypeLen, TypeEndpoint, - 0x86, // EndpointAddress + 0x85, // EndpointAddress TransferTypeBulk, // Attributes 0x40, // MaxPacketSizeL (64 bytes) 0x00, // MaxPacketSizeH 0x00, // Interval } -var EndpointMSCIN = EndpointType{ - data: endpointMSCIN[:], +var EndpointEP5IN = EndpointType{ + data: endpointEP5IN[:], } // Mass Storage Class bulk out endpoint -var endpointMSCOUT = [endpointTypeLen]byte{ +var endpointEP4OUT = [endpointTypeLen]byte{ endpointTypeLen, TypeEndpoint, - 0x07, // EndpointAddress + 0x04, // EndpointAddress TransferTypeBulk, // Attributes 0x40, // MaxPacketSizeL (64 bytes) 0x00, // MaxPacketSizeH 0x00, // Interval } -var EndpointMSCOUT = EndpointType{ - data: endpointMSCOUT[:], +var EndpointEP4OUT = EndpointType{ + data: endpointEP4OUT[:], } +// Aliases for easier reuse +var ( + EndpointCDCACMIN = &EndpointEP1IN + EndpointCDCOUT = &EndpointEP1OUT + EndpointCDCIN = &EndpointEP2IN + EndpointHIDOUT = &EndpointEP2OUT + EndpointHIDIN = &EndpointEP3IN + EndpointMSCOUT = &EndpointEP4OUT + EndpointMSCIN = &EndpointEP5IN +) + const ( endpointTypeLen = 7 ) diff --git a/src/machine/usb/descriptor/hid.go b/src/machine/usb/descriptor/hid.go index 06b9801530..cf121605bc 100644 --- a/src/machine/usb/descriptor/hid.go +++ b/src/machine/usb/descriptor/hid.go @@ -121,14 +121,14 @@ var CDCHID = Descriptor{ ClassSpecificCDCACM.Bytes(), ClassSpecificCDCUnion.Bytes(), ClassSpecificCDCCallManagement.Bytes(), - EndpointEP1IN.Bytes(), + EndpointCDCACMIN.Bytes(), InterfaceCDCData.Bytes(), - EndpointEP2OUT.Bytes(), - EndpointEP3IN.Bytes(), + EndpointCDCOUT.Bytes(), + EndpointCDCIN.Bytes(), InterfaceHID.Bytes(), ClassHID.Bytes(), - EndpointEP4IN.Bytes(), - EndpointEP5OUT.Bytes(), + EndpointHIDIN.Bytes(), + EndpointHIDOUT.Bytes(), }), HID: map[uint16][]byte{ 2: Append([][]byte{ // Update ClassLength in classHID whenever the array length is modified! diff --git a/src/machine/usb/descriptor/joystick.go b/src/machine/usb/descriptor/joystick.go index 65756e0d63..b1d71fc2ca 100644 --- a/src/machine/usb/descriptor/joystick.go +++ b/src/machine/usb/descriptor/joystick.go @@ -131,14 +131,14 @@ var CDCJoystick = Descriptor{ ClassSpecificCDCACM.Bytes(), ClassSpecificCDCUnion.Bytes(), ClassSpecificCDCCallManagement.Bytes(), - EndpointEP1IN.Bytes(), + EndpointCDCACMIN.Bytes(), InterfaceCDCData.Bytes(), - EndpointEP2OUT.Bytes(), - EndpointEP3IN.Bytes(), + EndpointCDCOUT.Bytes(), + EndpointCDCIN.Bytes(), InterfaceHIDJoystick.Bytes(), ClassHIDJoystick.Bytes(), - EndpointEP4IN.Bytes(), - EndpointEP5OUT.Bytes(), + EndpointHIDIN.Bytes(), + EndpointHIDOUT.Bytes(), }), HID: map[uint16][]byte{}, } diff --git a/src/machine/usb/descriptor/midi.go b/src/machine/usb/descriptor/midi.go index fad81f31d5..4c4744506b 100644 --- a/src/machine/usb/descriptor/midi.go +++ b/src/machine/usb/descriptor/midi.go @@ -3,7 +3,7 @@ package descriptor var interfaceAssociationMIDI = [interfaceAssociationTypeLen]byte{ interfaceAssociationTypeLen, TypeInterfaceAssociation, - 0x02, // EndpointAddress + 0x01, // EndpointAddress 0x02, // Attributes 0x01, // MaxPacketSizeL 0x01, // MaxPacketSizeH @@ -171,10 +171,10 @@ var ClassSpecificMIDIInEndpoint = ClassSpecificType{ const endpointMIDITypeLen = 9 -var endpointEP6IN = [endpointMIDITypeLen]byte{ +var endpointEP4IN = [endpointMIDITypeLen]byte{ endpointMIDITypeLen, TypeEndpoint, - 0x86, // EndpointAddress + 0x84, // EndpointAddress 0x02, // Attributes 0x40, // MaxPacketSizeL 0x00, // MaxPacketSizeH @@ -183,14 +183,14 @@ var endpointEP6IN = [endpointMIDITypeLen]byte{ 0x00, // sync address } -var EndpointEP6IN = EndpointType{ - data: endpointEP6IN[:], +var EndpointEP4IN = EndpointType{ + data: endpointEP4IN[:], } -var endpointEP7OUT = [endpointMIDITypeLen]byte{ +var endpointEP3OUT = [endpointMIDITypeLen]byte{ endpointMIDITypeLen, TypeEndpoint, - 0x07, // EndpointAddress + 0x03, // EndpointAddress 0x02, // Attributes 0x40, // MaxPacketSizeL 0x00, // MaxPacketSizeH @@ -199,10 +199,15 @@ var endpointEP7OUT = [endpointMIDITypeLen]byte{ 0x00, // sync address } -var EndpointEP7OUT = EndpointType{ - data: endpointEP7OUT[:], +var EndpointEP3OUT = EndpointType{ + data: endpointEP3OUT[:], } +var ( + EndpointMIDIIN = &EndpointEP4IN + EndpointMIDIOUT = &EndpointEP3OUT +) + var configurationCDCMIDI = [configurationTypeLen]byte{ configurationTypeLen, TypeConfiguration, @@ -228,10 +233,10 @@ var CDCMIDI = Descriptor{ ClassSpecificCDCACM.Bytes(), ClassSpecificCDCUnion.Bytes(), ClassSpecificCDCCallManagement.Bytes(), - EndpointEP1IN.Bytes(), + EndpointCDCACMIN.Bytes(), InterfaceCDCData.Bytes(), - EndpointEP2OUT.Bytes(), - EndpointEP3IN.Bytes(), + EndpointCDCOUT.Bytes(), + EndpointCDCIN.Bytes(), InterfaceAssociationMIDI.Bytes(), InterfaceAudio.Bytes(), ClassSpecificAudioInterface.Bytes(), @@ -241,9 +246,9 @@ var CDCMIDI = Descriptor{ ClassSpecificMIDIInJack2.Bytes(), ClassSpecificMIDIOutJack1.Bytes(), ClassSpecificMIDIOutJack2.Bytes(), - EndpointEP7OUT.Bytes(), + EndpointMIDIOUT.Bytes(), ClassSpecificMIDIOutEndpoint.Bytes(), - EndpointEP6IN.Bytes(), + EndpointMIDIIN.Bytes(), ClassSpecificMIDIInEndpoint.Bytes(), }), } diff --git a/src/machine/usb/descriptor/msc.go b/src/machine/usb/descriptor/msc.go index 55c6ddd857..939fa393d2 100644 --- a/src/machine/usb/descriptor/msc.go +++ b/src/machine/usb/descriptor/msc.go @@ -63,10 +63,10 @@ var MSC = Descriptor{ ClassSpecificCDCACM.Bytes(), ClassSpecificCDCUnion.Bytes(), ClassSpecificCDCCallManagement.Bytes(), - EndpointEP1IN.Bytes(), + EndpointCDCACMIN.Bytes(), InterfaceCDCData.Bytes(), - EndpointEP2OUT.Bytes(), - EndpointEP3IN.Bytes(), + EndpointCDCOUT.Bytes(), + EndpointCDCIN.Bytes(), InterfaceAssociationMSC.Bytes(), InterfaceMSC.Bytes(), EndpointMSCIN.Bytes(), diff --git a/src/machine/usb/usb.go b/src/machine/usb/usb.go index 40983a9a3c..f45b52a018 100644 --- a/src/machine/usb/usb.go +++ b/src/machine/usb/usb.go @@ -73,14 +73,14 @@ const ( // Endpoint CONTROL_ENDPOINT = 0 CDC_ENDPOINT_ACM = 1 - CDC_ENDPOINT_OUT = 2 - CDC_ENDPOINT_IN = 3 - 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 - MSC_ENDPOINT_IN = 6 // for Bulk In - MSC_ENDPOINT_OUT = 7 // for Bulk Out + CDC_ENDPOINT_OUT = 1 + CDC_ENDPOINT_IN = 2 + HID_ENDPOINT_OUT = 2 // for Interrupt Out + HID_ENDPOINT_IN = 3 // for Interrupt In + MIDI_ENDPOINT_OUT = 3 // for Bulk Out + MIDI_ENDPOINT_IN = 4 // for Bulk In + MSC_ENDPOINT_OUT = 4 // for Bulk Out + MSC_ENDPOINT_IN = 5 // for Bulk In // bmRequestType REQUEST_HOSTTODEVICE = 0x00