From 335a7ad0b72aa5b5248c79bd77cc5e1ed6e1c183 Mon Sep 17 00:00:00 2001 From: sago35 Date: Thu, 7 Jul 2022 23:43:57 +0900 Subject: [PATCH] samd21,samd51,nrf52840: refactor handleStandardSetup and initEndpoint (#2968) * samd21,samd51,nrf52840: refactor handleStandardSetup and initEndpoint --- src/machine/machine_atsamd21_usb.go | 133 ++++++---------------------- src/machine/machine_atsamd51_usb.go | 133 ++++++---------------------- src/machine/machine_nrf52840_usb.go | 97 ++------------------ src/machine/usb.go | 77 ++++++++++++++++ 4 files changed, 138 insertions(+), 302 deletions(-) diff --git a/src/machine/machine_atsamd21_usb.go b/src/machine/machine_atsamd21_usb.go index f47b1ee3..2155ccf7 100644 --- a/src/machine/machine_atsamd21_usb.go +++ b/src/machine/machine_atsamd21_usb.go @@ -244,9 +244,6 @@ func handleUSBIRQ(intr interrupt.Interrupt) { // Configure control endpoint initEndpoint(0, usb_ENDPOINT_TYPE_CONTROL) - // Enable Setup-Received interrupt - setEPINTENSET(0, sam.USB_DEVICE_EPINTENSET_RXSTP) - usbConfiguration = 0 // ack the End-Of-Reset interrupt @@ -343,6 +340,8 @@ func initEndpoint(ep, config uint32) { // set endpoint type setEPCFG(ep, ((usb_ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_EPCFG_EPTYPE1_Pos)) + setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT1) + case usb_ENDPOINT_TYPE_BULK | usbEndpointOut: // set packet size usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) @@ -378,6 +377,8 @@ func initEndpoint(ep, config uint32) { // NAK on endpoint IN, the bank is not yet filled in. setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK1RDY) + setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT1) + case usb_ENDPOINT_TYPE_CONTROL: // Control OUT // set packet size @@ -408,119 +409,37 @@ func initEndpoint(ep, config uint32) { // NAK on endpoint OUT to show we are ready to receive control data setEPSTATUSSET(ep, sam.USB_DEVICE_EPSTATUSSET_BK0RDY) + + // Enable Setup-Received interrupt + setEPINTENSET(0, sam.USB_DEVICE_EPINTENSET_RXSTP) } } -func handleStandardSetup(setup USBSetup) bool { - switch setup.BRequest { - case usb_GET_STATUS: - buf := []byte{0, 0} +func handleUSBSetAddress(setup USBSetup) bool { + // set packet size 64 with auto Zlp after transfer + usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.Set((epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) | + uint32(1<<31)) // autozlp - if setup.BmRequestType != 0 { // endpoint - // TODO: actually check if the endpoint in question is currently halted - if isEndpointHalt { - buf[0] = 1 - } - } + // ack the transfer is complete from the request + setEPINTFLAG(0, sam.USB_DEVICE_EPINTFLAG_TRCPT1) - sendUSBPacket(0, buf, setup.WLength) - return true + // set bank ready for data + setEPSTATUSSET(0, sam.USB_DEVICE_EPSTATUSSET_BK1RDY) - case usb_CLEAR_FEATURE: - if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP - isRemoteWakeUpEnabled = false - } else if setup.WValueL == 0 { // ENDPOINTHALT - isEndpointHalt = false - } - SendZlp() - return true - - case usb_SET_FEATURE: - if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP - isRemoteWakeUpEnabled = true - } else if setup.WValueL == 0 { // ENDPOINTHALT - isEndpointHalt = true - } - SendZlp() - return true - - case usb_SET_ADDRESS: - // set packet size 64 with auto Zlp after transfer - usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.Set((epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) | - uint32(1<<31)) // autozlp - - // ack the transfer is complete from the request - setEPINTFLAG(0, sam.USB_DEVICE_EPINTFLAG_TRCPT1) - - // set bank ready for data - setEPSTATUSSET(0, sam.USB_DEVICE_EPSTATUSSET_BK1RDY) - - // wait for transfer to complete - timeout := 3000 - for (getEPINTFLAG(0) & sam.USB_DEVICE_EPINTFLAG_TRCPT1) == 0 { - timeout-- - if timeout == 0 { - return true - } - } - - // last, set the device address to that requested by host - sam.USB_DEVICE.DADD.SetBits(setup.WValueL) - sam.USB_DEVICE.DADD.SetBits(sam.USB_DEVICE_DADD_ADDEN) - - return true - - case usb_GET_DESCRIPTOR: - sendDescriptor(setup) - return true - - case usb_SET_DESCRIPTOR: - return false - - case usb_GET_CONFIGURATION: - buff := []byte{usbConfiguration} - sendUSBPacket(0, buff, setup.WLength) - return true - - 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]) - } - - usbConfiguration = setup.WValueL - - // Enable interrupt for CDC control messages from host (OUT packet) - setEPINTENSET(usb_CDC_ENDPOINT_ACM, sam.USB_DEVICE_EPINTENSET_TRCPT1) - - // Enable interrupt for CDC data messages from host - setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_EPINTENSET_TRCPT0) - - // Enable interrupt for HID messages from host - if hidCallback != nil { - setEPINTENSET(usb_HID_ENDPOINT_IN, sam.USB_DEVICE_EPINTENSET_TRCPT1) - } - - SendZlp() + // wait for transfer to complete + timeout := 3000 + for (getEPINTFLAG(0) & sam.USB_DEVICE_EPINTFLAG_TRCPT1) == 0 { + timeout-- + if timeout == 0 { return true - } else { - return false } - - case usb_GET_INTERFACE: - buff := []byte{usbSetInterface} - sendUSBPacket(0, buff, setup.WLength) - return true - - case usb_SET_INTERFACE: - usbSetInterface = setup.WValueL - - SendZlp() - return true - - default: - return true } + + // last, set the device address to that requested by host + sam.USB_DEVICE.DADD.SetBits(setup.WValueL) + sam.USB_DEVICE.DADD.SetBits(sam.USB_DEVICE_DADD_ADDEN) + + return true } func cdcSetup(setup USBSetup) bool { diff --git a/src/machine/machine_atsamd51_usb.go b/src/machine/machine_atsamd51_usb.go index d49a68b4..5af924a4 100644 --- a/src/machine/machine_atsamd51_usb.go +++ b/src/machine/machine_atsamd51_usb.go @@ -248,9 +248,6 @@ func handleUSBIRQ(interrupt.Interrupt) { // Configure control endpoint initEndpoint(0, usb_ENDPOINT_TYPE_CONTROL) - // Enable Setup-Received interrupt - setEPINTENSET(0, sam.USB_DEVICE_ENDPOINT_EPINTENSET_RXSTP) - usbConfiguration = 0 // ack the End-Of-Reset interrupt @@ -347,6 +344,8 @@ func initEndpoint(ep, config uint32) { // set endpoint type setEPCFG(ep, ((usb_ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos)) + setEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT1) + case usb_ENDPOINT_TYPE_BULK | usbEndpointOut: // set packet size usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) @@ -382,6 +381,8 @@ func initEndpoint(ep, config uint32) { // NAK on endpoint IN, the bank is not yet filled in. setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK1RDY) + setEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT1) + case usb_ENDPOINT_TYPE_CONTROL: // Control OUT // set packet size @@ -412,119 +413,37 @@ func initEndpoint(ep, config uint32) { // NAK on endpoint OUT to show we are ready to receive control data setEPSTATUSSET(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_BK0RDY) + + // Enable Setup-Received interrupt + setEPINTENSET(0, sam.USB_DEVICE_ENDPOINT_EPINTENSET_RXSTP) } } -func handleStandardSetup(setup USBSetup) bool { - switch setup.BRequest { - case usb_GET_STATUS: - buf := []byte{0, 0} +func handleUSBSetAddress(setup USBSetup) bool { + // set packet size 64 with auto Zlp after transfer + usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.Set((epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) | + uint32(1<<31)) // autozlp - if setup.BmRequestType != 0 { // endpoint - // TODO: actually check if the endpoint in question is currently halted - if isEndpointHalt { - buf[0] = 1 - } - } + // ack the transfer is complete from the request + setEPINTFLAG(0, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1) - sendUSBPacket(0, buf, setup.WLength) - return true + // set bank ready for data + setEPSTATUSSET(0, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_BK1RDY) - case usb_CLEAR_FEATURE: - if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP - isRemoteWakeUpEnabled = false - } else if setup.WValueL == 0 { // ENDPOINTHALT - isEndpointHalt = false - } - SendZlp() - return true - - case usb_SET_FEATURE: - if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP - isRemoteWakeUpEnabled = true - } else if setup.WValueL == 0 { // ENDPOINTHALT - isEndpointHalt = true - } - SendZlp() - return true - - case usb_SET_ADDRESS: - // set packet size 64 with auto Zlp after transfer - usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.Set((epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) | - uint32(1<<31)) // autozlp - - // ack the transfer is complete from the request - setEPINTFLAG(0, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1) - - // set bank ready for data - setEPSTATUSSET(0, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_BK1RDY) - - // wait for transfer to complete - timeout := 3000 - for (getEPINTFLAG(0) & sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1) == 0 { - timeout-- - if timeout == 0 { - return true - } - } - - // last, set the device address to that requested by host - sam.USB_DEVICE.DADD.SetBits(setup.WValueL) - sam.USB_DEVICE.DADD.SetBits(sam.USB_DEVICE_DADD_ADDEN) - - return true - - case usb_GET_DESCRIPTOR: - sendDescriptor(setup) - return true - - case usb_SET_DESCRIPTOR: - return false - - case usb_GET_CONFIGURATION: - buff := []byte{usbConfiguration} - sendUSBPacket(0, buff, setup.WLength) - return true - - 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]) - } - - usbConfiguration = setup.WValueL - - // Enable interrupt for CDC control messages from host (OUT packet) - setEPINTENSET(usb_CDC_ENDPOINT_ACM, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT1) - - // Enable interrupt for CDC data messages from host - setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0) - - // Enable interrupt for HID messages from host - if hidCallback != nil { - setEPINTENSET(usb_HID_ENDPOINT_IN, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT1) - } - - SendZlp() + // wait for transfer to complete + timeout := 3000 + for (getEPINTFLAG(0) & sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1) == 0 { + timeout-- + if timeout == 0 { return true - } else { - return false } - - case usb_GET_INTERFACE: - buff := []byte{usbSetInterface} - sendUSBPacket(0, buff, setup.WLength) - return true - - case usb_SET_INTERFACE: - usbSetInterface = setup.WValueL - - SendZlp() - return true - - default: - return true } + + // last, set the device address to that requested by host + sam.USB_DEVICE.DADD.SetBits(setup.WValueL) + sam.USB_DEVICE.DADD.SetBits(sam.USB_DEVICE_DADD_ADDEN) + + return true } func cdcSetup(setup USBSetup) bool { diff --git a/src/machine/machine_nrf52840_usb.go b/src/machine/machine_nrf52840_usb.go index a01285f3..86cbf6a5 100644 --- a/src/machine/machine_nrf52840_usb.go +++ b/src/machine/machine_nrf52840_usb.go @@ -197,9 +197,6 @@ func handleUSBIRQ(interrupt.Interrupt) { // Configure control endpoint initEndpoint(0, usb_ENDPOINT_TYPE_CONTROL) - - // Enable Setup-Received interrupt - nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_EP0SETUP) nrf.USBD.USBPULLUP.Set(1) usbConfiguration = 0 @@ -228,7 +225,7 @@ func handleUSBIRQ(interrupt.Interrupt) { sendOnEP0DATADONE.ptr = nil } else { // no more data, so set status stage - nrf.USBD.TASKS_EP0STATUS.Set(1) + SendZlp() // nrf.USBD.TASKS_EP0STATUS.Set(1) } return } @@ -353,92 +350,11 @@ func initEndpoint(ep, config uint32) { enableEPIn(ep) case usb_ENDPOINT_TYPE_CONTROL: + nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0) + nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_EP0SETUP) enableEPIn(0) enableEPOut(0) - nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0) - nrf.USBD.TASKS_EP0STATUS.Set(1) - } -} - -func handleStandardSetup(setup USBSetup) bool { - switch setup.BRequest { - case usb_GET_STATUS: - buf := []byte{0, 0} - - if setup.BmRequestType != 0 { // endpoint - if isEndpointHalt { - buf[0] = 1 - } - } - - sendUSBPacket(0, buf, setup.WLength) - return true - - case usb_CLEAR_FEATURE: - if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP - isRemoteWakeUpEnabled = false - } else if setup.WValueL == 0 { // ENDPOINTHALT - isEndpointHalt = false - } - nrf.USBD.TASKS_EP0STATUS.Set(1) - return true - - case usb_SET_FEATURE: - if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP - isRemoteWakeUpEnabled = true - } else if setup.WValueL == 0 { // ENDPOINTHALT - isEndpointHalt = true - } - nrf.USBD.TASKS_EP0STATUS.Set(1) - return true - - case usb_SET_ADDRESS: - // nrf USBD handles this - return true - - case usb_GET_DESCRIPTOR: - sendDescriptor(setup) - return true - - case usb_SET_DESCRIPTOR: - return false - - case usb_GET_CONFIGURATION: - buff := []byte{usbConfiguration} - sendUSBPacket(0, buff, setup.WLength) - return true - - case usb_SET_CONFIGURATION: - if setup.BmRequestType&usb_REQUEST_RECIPIENT == usb_REQUEST_DEVICE { - nrf.USBD.TASKS_EP0STATUS.Set(1) - for i := 1; i < len(endPoints); i++ { - initEndpoint(uint32(i), endPoints[i]) - } - - // Enable interrupt for HID messages from host - if hidCallback != nil { - nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 << usb_HID_ENDPOINT_IN) - } - - usbConfiguration = setup.WValueL - return true - } else { - return false - } - - case usb_GET_INTERFACE: - buff := []byte{usbSetInterface} - sendUSBPacket(0, buff, setup.WLength) - return true - - case usb_SET_INTERFACE: - usbSetInterface = setup.WValueL - - nrf.USBD.TASKS_EP0STATUS.Set(1) - return true - - default: - return true + SendZlp() // nrf.USBD.TASKS_EP0STATUS.Set(1) } } @@ -551,3 +467,8 @@ func enableEPIn(ep uint32) { epinen = epinen | (nrf.USBD_EPINEN_IN0 << ep) nrf.USBD.EPINEN.Set(epinen) } + +func handleUSBSetAddress(setup USBSetup) bool { + // nrf USBD handles this + return true +} diff --git a/src/machine/usb.go b/src/machine/usb.go index 2e5811b5..bff0f715 100644 --- a/src/machine/usb.go +++ b/src/machine/usb.go @@ -324,6 +324,83 @@ func sendDescriptor(setup USBSetup) { return } +func handleStandardSetup(setup USBSetup) bool { + switch setup.BRequest { + case usb_GET_STATUS: + buf := []byte{0, 0} + + if setup.BmRequestType != 0 { // endpoint + if isEndpointHalt { + buf[0] = 1 + } + } + + sendUSBPacket(0, buf, setup.WLength) + return true + + case usb_CLEAR_FEATURE: + if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP + isRemoteWakeUpEnabled = false + } else if setup.WValueL == 0 { // ENDPOINTHALT + isEndpointHalt = false + } + SendZlp() + return true + + case usb_SET_FEATURE: + if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP + isRemoteWakeUpEnabled = true + } else if setup.WValueL == 0 { // ENDPOINTHALT + isEndpointHalt = true + } + SendZlp() + return true + + case usb_SET_ADDRESS: + return handleUSBSetAddress(setup) + + case usb_GET_DESCRIPTOR: + sendDescriptor(setup) + return true + + case usb_SET_DESCRIPTOR: + return false + + case usb_GET_CONFIGURATION: + buff := []byte{usbConfiguration} + sendUSBPacket(0, buff, setup.WLength) + return true + + 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]) + } + + usbConfiguration = setup.WValueL + + SendZlp() + return true + } else { + return false + } + + case usb_GET_INTERFACE: + buff := []byte{usbSetInterface} + sendUSBPacket(0, buff, setup.WLength) + return true + + case usb_SET_INTERFACE: + usbSetInterface = setup.WValueL + + SendZlp() + return true + + default: + return true + } +} + // EnableHID enables HID. This function must be executed from the init(). func EnableHID(callback func()) { usbDescriptor = descriptorCDCHID