machine/rp2: expose usb endpoint stall handling

This commit is contained in:
Michael Smith
2025-04-16 21:16:51 -04:00
committed by Ron Evans
parent 0f06f59c6e
commit febb3906db
5 changed files with 74 additions and 12 deletions
+1 -1
View File
@@ -67,7 +67,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
if !ok { if !ok {
// Stall endpoint? // Stall endpoint?
sendStallViaEPIn(0) USBDev.SetStallEPIn(0)
} }
} }
+1 -1
View File
@@ -70,7 +70,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
if !ok { if !ok {
// Stall endpoint? // Stall endpoint?
sendStallViaEPIn(0) USBDev.SetStallEPIn(0)
} }
} }
+50 -5
View File
@@ -21,26 +21,33 @@ func initEndpoint(ep, config uint32) {
offset := ep*2*usbBufferLen + 0x100 offset := ep*2*usbBufferLen + 0x100
val |= offset 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.
switch config { switch config {
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn: case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
val |= usbEpControlEndpointTypeInterrupt val |= usbEpControlEndpointTypeInterrupt
_usbDPSRAM.EPxControl[ep].In.Set(val) _usbDPSRAM.EPxControl[ep].In.Set(val)
epXPIDReset[ep] = true
case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut: case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:
val |= usbEpControlEndpointTypeBulk val |= usbEpControlEndpointTypeBulk
_usbDPSRAM.EPxControl[ep].Out.Set(val) _usbDPSRAM.EPxControl[ep].Out.Set(val)
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask) _usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail) _usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
epXPIDReset[ep] = true
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut: case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
val |= usbEpControlEndpointTypeInterrupt val |= usbEpControlEndpointTypeInterrupt
_usbDPSRAM.EPxControl[ep].Out.Set(val) _usbDPSRAM.EPxControl[ep].Out.Set(val)
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask) _usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail) _usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
epXPIDReset[ep] = true
case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn: case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
val |= usbEpControlEndpointTypeBulk val |= usbEpControlEndpointTypeBulk
_usbDPSRAM.EPxControl[ep].In.Set(val) _usbDPSRAM.EPxControl[ep].In.Set(val)
epXPIDReset[ep] = true
case usb.ENDPOINT_TYPE_CONTROL: case usb.ENDPOINT_TYPE_CONTROL:
val |= usbEpControlEndpointTypeControl val |= usbEpControlEndpointTypeControl
@@ -109,7 +116,12 @@ func handleEndpointRx(ep uint32) []byte {
} }
func handleEndpointRxComplete(ep uint32) { func handleEndpointRxComplete(ep uint32) {
epXdata0[ep] = !epXdata0[ep] setEPDataPID(ep, !epXdata0[ep])
}
// Set the USB endpoint Packet ID to DATA0 or DATA1.
func setEPDataPID(ep uint32, dataOne bool) {
epXdata0[ep] = dataOne
if epXdata0[ep] || ep == 0 { if epXdata0[ep] || ep == 0 {
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid) _usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
} }
@@ -138,7 +150,8 @@ func sendViaEPIn(ep uint32, data []byte, count int) {
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val) _usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
} }
func sendStallViaEPIn(ep uint32) { // Set ENDPOINT_HALT/stall status on a USB IN endpoint.
func (dev *USBDevice) SetStallEPIn(ep uint32) {
// Prepare buffer control register value // Prepare buffer control register value
if ep == 0 { if ep == 0 {
armEPZeroStall() armEPZeroStall()
@@ -149,6 +162,37 @@ func sendStallViaEPIn(ep uint32) {
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val) _usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
} }
// Set ENDPOINT_HALT/stall status on a USB OUT endpoint.
func (dev *USBDevice) SetStallEPOut(ep uint32) {
if ep == 0 {
panic("SetStallEPOut: EP0 OUT not valid")
}
val := uint32(usbBuf0CtrlStall)
_usbDPSRAM.EPxBufferControl[ep&0x7F].Out.Set(val)
}
// Clear the ENDPOINT_HALT/stall on a USB IN endpoint.
func (dev *USBDevice) ClearStallEPIn(ep uint32) {
ep = ep & 0x7F
val := uint32(usbBuf0CtrlStall)
_usbDPSRAM.EPxBufferControl[ep].In.ClearBits(val)
if epXPIDReset[ep] {
// Reset the PID to DATA0
setEPDataPID(ep&0x7F, false)
}
}
// 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] {
// Reset the PID to DATA0
setEPDataPID(ep, false)
}
}
type usbDPSRAM struct { type usbDPSRAM struct {
// Note that EPxControl[0] is not EP0Control but 8-byte setup data. // Note that EPxControl[0] is not EP0Control but 8-byte setup data.
EPxControl [16]usbEndpointControlRegister EPxControl [16]usbEndpointControlRegister
@@ -173,9 +217,10 @@ type usbBuffer struct {
} }
var ( var (
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000))) _usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
epXdata0 [16]bool epXdata0 [16]bool
setupBytes [8]byte epXPIDReset [16]bool
setupBytes [8]byte
) )
func (d *usbDPSRAM) setupBytes() []byte { func (d *usbDPSRAM) setupBytes() []byte {
+16
View File
@@ -123,6 +123,7 @@ var (
usbTxHandler [usb.NumberOfEndpoints]func() usbTxHandler [usb.NumberOfEndpoints]func()
usbRxHandler [usb.NumberOfEndpoints]func([]byte) usbRxHandler [usb.NumberOfEndpoints]func([]byte)
usbSetupHandler [usb.NumberOfInterfaces]func(usb.Setup) bool usbSetupHandler [usb.NumberOfInterfaces]func(usb.Setup) bool
usbStallHandler [usb.NumberOfEndpoints]func(usb.Setup) bool
endPoints = []uint32{ endPoints = []uint32{
usb.CONTROL_ENDPOINT: usb.ENDPOINT_TYPE_CONTROL, usb.CONTROL_ENDPOINT: usb.ENDPOINT_TYPE_CONTROL,
@@ -212,6 +213,12 @@ func handleStandardSetup(setup usb.Setup) bool {
if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP
isRemoteWakeUpEnabled = false isRemoteWakeUpEnabled = false
} else if setup.WValueL == 0 { // ENDPOINTHALT } else if setup.WValueL == 0 { // ENDPOINTHALT
if idx := setup.WIndex & 0x7F; idx < usb.NumberOfEndpoints && 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
return usbStallHandler[idx](setup)
}
isEndpointHalt = false isEndpointHalt = false
} }
SendZlp() SendZlp()
@@ -221,6 +228,12 @@ func handleStandardSetup(setup usb.Setup) bool {
if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP
isRemoteWakeUpEnabled = true isRemoteWakeUpEnabled = true
} else if setup.WValueL == 0 { // ENDPOINTHALT } else if setup.WValueL == 0 { // ENDPOINTHALT
if idx := setup.WIndex & 0x7F; idx < usb.NumberOfEndpoints && 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
return usbStallHandler[idx](setup)
}
isEndpointHalt = true isEndpointHalt = true
} }
SendZlp() SendZlp()
@@ -320,6 +333,9 @@ func ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []usb.EndpointC
usbRxHandler[ep.Index] = ep.RxHandler usbRxHandler[ep.Index] = ep.RxHandler
} }
} }
if ep.StallHandler != nil {
usbStallHandler[ep.Index] = ep.StallHandler
}
} }
for _, s := range setup { for _, s := range setup {
+6 -5
View File
@@ -1,11 +1,12 @@
package usb package usb
type EndpointConfig struct { type EndpointConfig struct {
Index uint8 Index uint8
IsIn bool IsIn bool
TxHandler func() TxHandler func()
RxHandler func([]byte) RxHandler func([]byte)
Type uint8 StallHandler func(Setup) bool
Type uint8
} }
type SetupConfig struct { type SetupConfig struct {