diff --git a/src/machine/machine_atsamd21_usb.go b/src/machine/machine_atsamd21_usb.go index 28e8c6d22..45ba18d45 100644 --- a/src/machine/machine_atsamd21_usb.go +++ b/src/machine/machine_atsamd21_usb.go @@ -175,7 +175,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 < NumberOfUSBEndpoints; i++ { // Check if endpoint has a pending interrupt epFlags := getEPINTFLAG(i) setEPINTFLAG(i, epFlags) @@ -193,6 +193,8 @@ func handleUSBIRQ(intr interrupt.Interrupt) { } func initEndpoint(ep, config uint32) { + // Note: Both IN (Bank 1) and OUT (Bank 0) configurations share the same EPCFG register. + // We must use getEPCFG(ep) | ... to avoid clearing/disabling the opposite direction. switch config { case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn: // set packet size @@ -202,7 +204,7 @@ 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)) + setEPCFG(ep, getEPCFG(ep)|((usb.ENDPOINT_TYPE_INTERRUPT+1)< m.sentBytes && m.cbw.isIn() { // 6.7.2 The Thirteen Cases - Case 5 (Hi > Di): STALL before status - m.stallEndpoint(usb.MSC_ENDPOINT_IN) + m.stallEndpointIn(usb.MSC_ENDPOINT_IN) } else if m.sendZLP { // Send a zero-length packet to force the end of the transfer before we send a CSW m.queuedBytes = 0 diff --git a/src/machine/usb/msc/scsi.go b/src/machine/usb/msc/scsi.go index 4cec23e2f..562a718ea 100644 --- a/src/machine/usb/msc/scsi.go +++ b/src/machine/usb/msc/scsi.go @@ -298,9 +298,9 @@ func (m *msc) sendScsiError(status csw.Status, key scsi.Sense, code scsi.SenseCo if expected > 0 && residue > 0 { if m.cbw.isIn() { - m.stallEndpoint(usb.MSC_ENDPOINT_IN) + m.stallEndpointIn(usb.MSC_ENDPOINT_IN) } else { - m.stallEndpoint(usb.MSC_ENDPOINT_OUT) + m.stallEndpointOut(usb.MSC_ENDPOINT_OUT) } } } diff --git a/src/machine/usb/msc/setup.go b/src/machine/usb/msc/setup.go index 00507aac6..fb4aaf2c2 100644 --- a/src/machine/usb/msc/setup.go +++ b/src/machine/usb/msc/setup.go @@ -52,32 +52,30 @@ func (m *msc) handleClearFeature(setup usb.Setup, wValue uint16) bool { // (c) a Clear Feature HALT to the Bulk-Out endpoint (clear stall OUT) // https://usb.org/sites/default/files/usbmassbulk_10.pdf if m.state == mscStateNeedReset { - wIndex := setup.WIndex & 0x7F // Clear the direction bit from the endpoint address for comparison + wIndex := uint8(setup.WIndex & 0x7F) if wIndex == usb.MSC_ENDPOINT_IN { - m.stallEndpoint(usb.MSC_ENDPOINT_IN) - } else if wIndex == usb.MSC_ENDPOINT_OUT { - m.stallEndpoint(usb.MSC_ENDPOINT_OUT) + if (setup.WIndex & 0x80) != 0 { + m.stallEndpointIn(wIndex) + } else { + m.stallEndpointOut(wIndex) + } } machine.SendZlp() return true } - // Clear the direction bit from the endpoint address for comparison - wIndex := setup.WIndex & 0x7F - - // Clear the IN/OUT stalls if addressed to the endpoint + wIndex := uint8(setup.WIndex & 0x7F) if wIndex == usb.MSC_ENDPOINT_IN { - m.clearStallEndpoint(usb.MSC_ENDPOINT_IN) - ok = true - } - if wIndex == usb.MSC_ENDPOINT_OUT { - m.clearStallEndpoint(usb.MSC_ENDPOINT_OUT) - ok = true - } - // Send a CSW if needed to resume after the IN endpoint stall is cleared - if m.state == mscStateStatus && wIndex == usb.MSC_ENDPOINT_IN { - m.sendCSW(m.respStatus) - ok = true + if (setup.WIndex & 0x80) != 0 { + m.clearStallEndpointIn(wIndex) + ok = true + if m.state == mscStateStatus { + m.sendCSW(m.respStatus) + } + } else { + m.clearStallEndpointOut(wIndex) + ok = true + } } if ok { @@ -120,26 +118,28 @@ func (m *msc) handleReset(setup usb.Setup, wValue uint16) bool { return true } -func (m *msc) stallEndpoint(ep uint8) { - if ep == usb.MSC_ENDPOINT_IN { - m.txStalled = true - machine.USBDev.SetStallEPIn(usb.MSC_ENDPOINT_IN) - } else if ep == usb.MSC_ENDPOINT_OUT { - m.rxStalled = true - machine.USBDev.SetStallEPOut(usb.MSC_ENDPOINT_OUT) - } else if ep == usb.CONTROL_ENDPOINT { +func (m *msc) stallEndpointIn(ep uint8) { + if ep == usb.CONTROL_ENDPOINT { machine.USBDev.SetStallEPIn(usb.CONTROL_ENDPOINT) + return } + m.txStalled = true + machine.USBDev.SetStallEPIn(uint32(ep)) } -func (m *msc) clearStallEndpoint(ep uint8) { - if ep == usb.MSC_ENDPOINT_IN { - machine.USBDev.ClearStallEPIn(usb.MSC_ENDPOINT_IN) - m.txStalled = false - } else if ep == usb.MSC_ENDPOINT_OUT { - machine.USBDev.ClearStallEPOut(usb.MSC_ENDPOINT_OUT) - m.rxStalled = false - } +func (m *msc) stallEndpointOut(ep uint8) { + m.rxStalled = true + machine.USBDev.SetStallEPOut(uint32(ep)) +} + +func (m *msc) clearStallEndpointIn(ep uint8) { + machine.USBDev.ClearStallEPIn(uint32(ep)) + m.txStalled = false +} + +func (m *msc) clearStallEndpointOut(ep uint8) { + machine.USBDev.ClearStallEPOut(uint32(ep)) + m.rxStalled = false } func (m *msc) setStringField(field []byte, value string) {