Skip to content

Commit febb390

Browse files
mikesmittydeadprogram
authored andcommitted
machine/rp2: expose usb endpoint stall handling
1 parent 0f06f59 commit febb390

File tree

5 files changed

+74
-12
lines changed

5 files changed

+74
-12
lines changed

src/machine/machine_rp2040_usb.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
6767

6868
if !ok {
6969
// Stall endpoint?
70-
sendStallViaEPIn(0)
70+
USBDev.SetStallEPIn(0)
7171
}
7272

7373
}

src/machine/machine_rp2350_usb.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
7070

7171
if !ok {
7272
// Stall endpoint?
73-
sendStallViaEPIn(0)
73+
USBDev.SetStallEPIn(0)
7474
}
7575

7676
}

src/machine/machine_rp2_usb.go

+50-5
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,33 @@ func initEndpoint(ep, config uint32) {
2121
offset := ep*2*usbBufferLen + 0x100
2222
val |= offset
2323

24+
// Bulk and interrupt endpoints must have their Packet ID reset to DATA0 when un-stalled.
25+
epXPIDReset[ep] = false // Default to false in case an endpoint is re-initialized.
26+
2427
switch config {
2528
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn:
2629
val |= usbEpControlEndpointTypeInterrupt
2730
_usbDPSRAM.EPxControl[ep].In.Set(val)
31+
epXPIDReset[ep] = true
2832

2933
case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut:
3034
val |= usbEpControlEndpointTypeBulk
3135
_usbDPSRAM.EPxControl[ep].Out.Set(val)
3236
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
3337
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
38+
epXPIDReset[ep] = true
3439

3540
case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut:
3641
val |= usbEpControlEndpointTypeInterrupt
3742
_usbDPSRAM.EPxControl[ep].Out.Set(val)
3843
_usbDPSRAM.EPxBufferControl[ep].Out.Set(usbBufferLen & usbBuf0CtrlLenMask)
3944
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
45+
epXPIDReset[ep] = true
4046

4147
case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn:
4248
val |= usbEpControlEndpointTypeBulk
4349
_usbDPSRAM.EPxControl[ep].In.Set(val)
50+
epXPIDReset[ep] = true
4451

4552
case usb.ENDPOINT_TYPE_CONTROL:
4653
val |= usbEpControlEndpointTypeControl
@@ -109,7 +116,12 @@ func handleEndpointRx(ep uint32) []byte {
109116
}
110117

111118
func handleEndpointRxComplete(ep uint32) {
112-
epXdata0[ep] = !epXdata0[ep]
119+
setEPDataPID(ep, !epXdata0[ep])
120+
}
121+
122+
// Set the USB endpoint Packet ID to DATA0 or DATA1.
123+
func setEPDataPID(ep uint32, dataOne bool) {
124+
epXdata0[ep] = dataOne
113125
if epXdata0[ep] || ep == 0 {
114126
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlData1Pid)
115127
}
@@ -138,7 +150,8 @@ func sendViaEPIn(ep uint32, data []byte, count int) {
138150
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
139151
}
140152

141-
func sendStallViaEPIn(ep uint32) {
153+
// Set ENDPOINT_HALT/stall status on a USB IN endpoint.
154+
func (dev *USBDevice) SetStallEPIn(ep uint32) {
142155
// Prepare buffer control register value
143156
if ep == 0 {
144157
armEPZeroStall()
@@ -149,6 +162,37 @@ func sendStallViaEPIn(ep uint32) {
149162
_usbDPSRAM.EPxBufferControl[ep&0x7F].In.Set(val)
150163
}
151164

165+
// Set ENDPOINT_HALT/stall status on a USB OUT endpoint.
166+
func (dev *USBDevice) SetStallEPOut(ep uint32) {
167+
if ep == 0 {
168+
panic("SetStallEPOut: EP0 OUT not valid")
169+
}
170+
val := uint32(usbBuf0CtrlStall)
171+
_usbDPSRAM.EPxBufferControl[ep&0x7F].Out.Set(val)
172+
}
173+
174+
// Clear the ENDPOINT_HALT/stall on a USB IN endpoint.
175+
func (dev *USBDevice) ClearStallEPIn(ep uint32) {
176+
ep = ep & 0x7F
177+
val := uint32(usbBuf0CtrlStall)
178+
_usbDPSRAM.EPxBufferControl[ep].In.ClearBits(val)
179+
if epXPIDReset[ep] {
180+
// Reset the PID to DATA0
181+
setEPDataPID(ep&0x7F, false)
182+
}
183+
}
184+
185+
// Clear the ENDPOINT_HALT/stall on a USB OUT endpoint.
186+
func (dev *USBDevice) ClearStallEPOut(ep uint32) {
187+
ep = ep & 0x7F
188+
val := uint32(usbBuf0CtrlStall)
189+
_usbDPSRAM.EPxBufferControl[ep].Out.ClearBits(val)
190+
if epXPIDReset[ep] {
191+
// Reset the PID to DATA0
192+
setEPDataPID(ep, false)
193+
}
194+
}
195+
152196
type usbDPSRAM struct {
153197
// Note that EPxControl[0] is not EP0Control but 8-byte setup data.
154198
EPxControl [16]usbEndpointControlRegister
@@ -173,9 +217,10 @@ type usbBuffer struct {
173217
}
174218

175219
var (
176-
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
177-
epXdata0 [16]bool
178-
setupBytes [8]byte
220+
_usbDPSRAM = (*usbDPSRAM)(unsafe.Pointer(uintptr(0x50100000)))
221+
epXdata0 [16]bool
222+
epXPIDReset [16]bool
223+
setupBytes [8]byte
179224
)
180225

181226
func (d *usbDPSRAM) setupBytes() []byte {

src/machine/usb.go

+16
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ var (
123123
usbTxHandler [usb.NumberOfEndpoints]func()
124124
usbRxHandler [usb.NumberOfEndpoints]func([]byte)
125125
usbSetupHandler [usb.NumberOfInterfaces]func(usb.Setup) bool
126+
usbStallHandler [usb.NumberOfEndpoints]func(usb.Setup) bool
126127

127128
endPoints = []uint32{
128129
usb.CONTROL_ENDPOINT: usb.ENDPOINT_TYPE_CONTROL,
@@ -212,6 +213,12 @@ func handleStandardSetup(setup usb.Setup) bool {
212213
if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP
213214
isRemoteWakeUpEnabled = false
214215
} else if setup.WValueL == 0 { // ENDPOINTHALT
216+
if idx := setup.WIndex & 0x7F; idx < usb.NumberOfEndpoints && usbStallHandler[idx] != nil {
217+
// Host has requested to clear an endpoint stall. If the request is addressed to
218+
// an endpoint with a configured StallHandler, forward the message on.
219+
// The 0x7F mask is used to clear the direction bit from the endpoint number
220+
return usbStallHandler[idx](setup)
221+
}
215222
isEndpointHalt = false
216223
}
217224
SendZlp()
@@ -221,6 +228,12 @@ func handleStandardSetup(setup usb.Setup) bool {
221228
if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP
222229
isRemoteWakeUpEnabled = true
223230
} else if setup.WValueL == 0 { // ENDPOINTHALT
231+
if idx := setup.WIndex & 0x7F; idx < usb.NumberOfEndpoints && usbStallHandler[idx] != nil {
232+
// Host has requested to stall an endpoint. If the request is addressed to
233+
// an endpoint with a configured StallHandler, forward the message on.
234+
// The 0x7F mask is used to clear the direction bit from the endpoint number
235+
return usbStallHandler[idx](setup)
236+
}
224237
isEndpointHalt = true
225238
}
226239
SendZlp()
@@ -320,6 +333,9 @@ func ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []usb.EndpointC
320333
usbRxHandler[ep.Index] = ep.RxHandler
321334
}
322335
}
336+
if ep.StallHandler != nil {
337+
usbStallHandler[ep.Index] = ep.StallHandler
338+
}
323339
}
324340

325341
for _, s := range setup {

src/machine/usb/config.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package usb
22

33
type EndpointConfig struct {
4-
Index uint8
5-
IsIn bool
6-
TxHandler func()
7-
RxHandler func([]byte)
8-
Type uint8
4+
Index uint8
5+
IsIn bool
6+
TxHandler func()
7+
RxHandler func([]byte)
8+
StallHandler func(Setup) bool
9+
Type uint8
910
}
1011

1112
type SetupConfig struct {

0 commit comments

Comments
 (0)