mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-17 19:23:25 +00:00
machine/rp2: expose usb endpoint stall handling
This commit is contained in:
@@ -67,7 +67,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
|
|||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
// Stall endpoint?
|
// Stall endpoint?
|
||||||
sendStallViaEPIn(0)
|
USBDev.SetStallEPIn(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) {
|
|||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
// Stall endpoint?
|
// Stall endpoint?
|
||||||
sendStallViaEPIn(0)
|
USBDev.SetStallEPIn(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user