From 03fa9dd9b7f8fa150641818bff0cdec3d29df71d Mon Sep 17 00:00:00 2001 From: Ron Evans Date: Sun, 29 Mar 2020 08:18:19 +0200 Subject: [PATCH] machine/atsamd21,atsamd51,nrf52840: refactor USB CDC device descriptor to reduce code duplication and heap allocations Signed-off-by: Ron Evans --- src/machine/machine_atsamd21.go | 116 +++----------------------------- src/machine/machine_atsamd51.go | 116 +++----------------------------- src/machine/usb.go | 104 ++++++++++++++++++++++++++-- src/machine/usb_nrf52840.go | 108 ++--------------------------- 4 files changed, 120 insertions(+), 324 deletions(-) diff --git a/src/machine/machine_atsamd21.go b/src/machine/machine_atsamd21.go index c01e7416..1e1540ab 100644 --- a/src/machine/machine_atsamd21.go +++ b/src/machine/machine_atsamd21.go @@ -1478,7 +1478,7 @@ func handleUSB(intr interrupt.Interrupt) { setEPINTENCLR(0, sam.USB_DEVICE_EPINTENCLR_STALL1) } } else { - sendZlp(0) + sendZlp() } // Now the actual transfer handlers, ignore endpoint number 0 (setup) @@ -1601,7 +1601,7 @@ func handleStandardSetup(setup usbSetup) bool { } else if setup.wValueL == 0 { // ENDPOINTHALT isEndpointHalt = false } - sendZlp(0) + sendZlp() return true case usb_SET_FEATURE: @@ -1610,7 +1610,7 @@ func handleStandardSetup(setup usbSetup) bool { } else if setup.wValueL == 0 { // ENDPOINTHALT isEndpointHalt = true } - sendZlp(0) + sendZlp() return true case usb_SET_ADDRESS: @@ -1665,7 +1665,7 @@ func handleStandardSetup(setup usbSetup) bool { // Enable interrupt for CDC data messages from host setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_EPINTENSET_TRCPT0) - sendZlp(0) + sendZlp() return true } else { return false @@ -1679,7 +1679,7 @@ func handleStandardSetup(setup usbSetup) bool { case usb_SET_INTERFACE: usbSetInterface = setup.wValueL - sendZlp(0) + sendZlp() return true default: @@ -1724,14 +1724,14 @@ func cdcSetup(setup usbSetup) bool { } else { // TODO: cancel any reset } - sendZlp(0) + sendZlp() } if setup.bRequest == usb_CDC_SEND_BREAK { // TODO: something with this value? // breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; // return false; - sendZlp(0) + sendZlp() } return true } @@ -1790,104 +1790,6 @@ func receiveUSBControlPacket() []byte { return data } -// sendDescriptor creates and sends the various USB descriptor types that -// can be requested by the host. -func sendDescriptor(setup usbSetup) { - switch setup.wValueH { - case usb_CONFIGURATION_DESCRIPTOR_TYPE: - sendConfiguration(setup) - return - case usb_DEVICE_DESCRIPTOR_TYPE: - // composite descriptor - dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1) - l := deviceDescriptorSize - if setup.wLength < deviceDescriptorSize { - l = int(setup.wLength) - } - sendUSBPacket(0, dd.Bytes()[:l]) - return - - case usb_STRING_DESCRIPTOR_TYPE: - switch setup.wValueL { - case 0: - b := []byte{0x04, 0x03, 0x09, 0x04} - sendUSBPacket(0, b) - return - - case usb_IPRODUCT: - b := strToUTF16LEDescriptor(usb_STRING_PRODUCT) - sendUSBPacket(0, b) - return - - case usb_IMANUFACTURER: - b := strToUTF16LEDescriptor(usb_STRING_MANUFACTURER) - sendUSBPacket(0, b) - return - - case usb_ISERIAL: - // TODO: allow returning a product serial number - sendZlp(0) - } - - // send final zero length packet and return - sendZlp(0) - return - } - - // do not know how to handle this message, so return zero - sendZlp(0) - return -} - -// sendConfiguration creates and sends the configuration packet to the host. -func sendConfiguration(setup usbSetup) { - if setup.wLength == 9 { - sz := uint16(configDescriptorSize + cdcSize) - config := NewConfigDescriptor(sz, 2) - sendUSBPacket(0, config.Bytes()) - } else { - iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) - - cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) - - header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF) - - controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6) - - functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE) - - callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1) - - cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10) - - dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0) - - out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) - - in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) - - cdc := NewCDCDescriptor(iad, - cif, - header, - controlManagement, - functionalDescriptor, - callManagement, - cifin, - dif, - out, - in) - - sz := uint16(configDescriptorSize + cdcSize) - config := NewConfigDescriptor(sz, 2) - - buf := make([]byte, 0, sz) - buf = append(buf, config.Bytes()...) - buf = append(buf, cdc.Bytes()...) - - sendUSBPacket(0, buf) - } -} - func handleEndpoint(ep uint32) { // get data count := int((usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >> @@ -1908,8 +1810,8 @@ func handleEndpoint(ep uint32) { setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY) } -func sendZlp(ep uint32) { - usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) +func sendZlp() { + usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) } func epPacketSize(size uint16) uint32 { diff --git a/src/machine/machine_atsamd51.go b/src/machine/machine_atsamd51.go index 674ef6c8..11b3e34f 100644 --- a/src/machine/machine_atsamd51.go +++ b/src/machine/machine_atsamd51.go @@ -1649,7 +1649,7 @@ func handleUSBIRQ(interrupt.Interrupt) { setEPINTENCLR(0, sam.USB_DEVICE_ENDPOINT_EPINTENCLR_STALL1) } } else { - sendZlp(0) + sendZlp() } // Now the actual transfer handlers, ignore endpoint number 0 (setup) @@ -1772,7 +1772,7 @@ func handleStandardSetup(setup usbSetup) bool { } else if setup.wValueL == 0 { // ENDPOINTHALT isEndpointHalt = false } - sendZlp(0) + sendZlp() return true case usb_SET_FEATURE: @@ -1781,7 +1781,7 @@ func handleStandardSetup(setup usbSetup) bool { } else if setup.wValueL == 0 { // ENDPOINTHALT isEndpointHalt = true } - sendZlp(0) + sendZlp() return true case usb_SET_ADDRESS: @@ -1836,7 +1836,7 @@ func handleStandardSetup(setup usbSetup) bool { // Enable interrupt for CDC data messages from host setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0) - sendZlp(0) + sendZlp() return true } else { return false @@ -1850,7 +1850,7 @@ func handleStandardSetup(setup usbSetup) bool { case usb_SET_INTERFACE: usbSetInterface = setup.wValueL - sendZlp(0) + sendZlp() return true default: @@ -1895,14 +1895,14 @@ func cdcSetup(setup usbSetup) bool { } else { // TODO: cancel any reset } - sendZlp(0) + sendZlp() } if setup.bRequest == usb_CDC_SEND_BREAK { // TODO: something with this value? // breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; // return false; - sendZlp(0) + sendZlp() } return true } @@ -1961,104 +1961,6 @@ func receiveUSBControlPacket() []byte { return data } -// sendDescriptor creates and sends the various USB descriptor types that -// can be requested by the host. -func sendDescriptor(setup usbSetup) { - switch setup.wValueH { - case usb_CONFIGURATION_DESCRIPTOR_TYPE: - sendConfiguration(setup) - return - case usb_DEVICE_DESCRIPTOR_TYPE: - // composite descriptor - dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1) - l := deviceDescriptorSize - if setup.wLength < deviceDescriptorSize { - l = int(setup.wLength) - } - sendUSBPacket(0, dd.Bytes()[:l]) - return - - case usb_STRING_DESCRIPTOR_TYPE: - switch setup.wValueL { - case 0: - b := []byte{0x04, 0x03, 0x09, 0x04} - sendUSBPacket(0, b) - return - - case usb_IPRODUCT: - b := strToUTF16LEDescriptor(usb_STRING_PRODUCT) - sendUSBPacket(0, b) - return - - case usb_IMANUFACTURER: - b := strToUTF16LEDescriptor(usb_STRING_MANUFACTURER) - sendUSBPacket(0, b) - return - - case usb_ISERIAL: - // TODO: allow returning a product serial number - sendZlp(0) - } - - // send final zero length packet and return - sendZlp(0) - return - } - - // do not know how to handle this message, so return zero - sendZlp(0) - return -} - -// sendConfiguration creates and sends the configuration packet to the host. -func sendConfiguration(setup usbSetup) { - if setup.wLength == 9 { - sz := uint16(configDescriptorSize + cdcSize) - config := NewConfigDescriptor(sz, 2) - sendUSBPacket(0, config.Bytes()) - } else { - iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) - - cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) - - header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF) - - controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6) - - functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE) - - callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1) - - cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10) - - dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0) - - out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) - - in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) - - cdc := NewCDCDescriptor(iad, - cif, - header, - controlManagement, - functionalDescriptor, - callManagement, - cifin, - dif, - out, - in) - - sz := uint16(configDescriptorSize + cdcSize) - config := NewConfigDescriptor(sz, 2) - - buf := make([]byte, 0) - buf = append(buf, config.Bytes()...) - buf = append(buf, cdc.Bytes()...) - - sendUSBPacket(0, buf) - } -} - func handleEndpoint(ep uint32) { // get data count := int((usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >> @@ -2079,8 +1981,8 @@ func handleEndpoint(ep uint32) { setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY) } -func sendZlp(ep uint32) { - usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) +func sendZlp() { + usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) } func epPacketSize(size uint16) uint32 { diff --git a/src/machine/usb.go b/src/machine/usb.go index 979662f1..f9efe972 100644 --- a/src/machine/usb.go +++ b/src/machine/usb.go @@ -381,16 +381,14 @@ type cdcLineInfo struct { // to do a "proper" conversion, we would need to pull in the 'unicode/utf16' // package, which at the time this was written added 512 bytes to the compiled // binary. -func strToUTF16LEDescriptor(in string) []byte { - size := (len(in) << 1) + 2 - out := make([]byte, size) - out[0] = byte(size) - out[1] = 0x03 +func strToUTF16LEDescriptor(in string, out []byte) { + out[0] = byte(len(out)) + out[1] = usb_STRING_DESCRIPTOR_TYPE for i, rune := range in { out[(i<<1)+2] = byte(rune) out[(i<<1)+3] = 0 } - return out + return } var ( @@ -615,3 +613,97 @@ func (usbcdc USBCDC) Buffered() int { func (usbcdc USBCDC) Receive(data byte) { usbcdc.Buffer.Put(data) } + +// sendDescriptor creates and sends the various USB descriptor types that +// can be requested by the host. +func sendDescriptor(setup usbSetup) { + switch setup.wValueH { + case usb_CONFIGURATION_DESCRIPTOR_TYPE: + sendConfiguration(setup) + return + case usb_DEVICE_DESCRIPTOR_TYPE: + // composite descriptor + dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1) + l := deviceDescriptorSize + if setup.wLength < deviceDescriptorSize { + l = int(setup.wLength) + } + sendUSBPacket(0, dd.Bytes()[:l]) + return + + case usb_STRING_DESCRIPTOR_TYPE: + switch setup.wValueL { + case 0: + b := []byte{0x04, 0x03, 0x09, 0x04} + sendUSBPacket(0, b) + + case usb_IPRODUCT: + b := make([]byte, (len(usb_STRING_PRODUCT)<<1)+2) + strToUTF16LEDescriptor(usb_STRING_PRODUCT, b) + sendUSBPacket(0, b) + + case usb_IMANUFACTURER: + b := make([]byte, (len(usb_STRING_MANUFACTURER)<<1)+2) + strToUTF16LEDescriptor(usb_STRING_MANUFACTURER, b) + sendUSBPacket(0, b) + + case usb_ISERIAL: + // TODO: allow returning a product serial number + sendZlp() + } + return + } + + // do not know how to handle this message, so return zero + sendZlp() + return +} + +// sendConfiguration creates and sends the configuration packet to the host. +func sendConfiguration(setup usbSetup) { + if setup.wLength == 9 { + sz := uint16(configDescriptorSize + cdcSize) + config := NewConfigDescriptor(sz, 2) + sendUSBPacket(0, config.Bytes()) + } else { + iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) + + cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) + + header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF) + + controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6) + + functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE) + + callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1) + + cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10) + + dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0) + + out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) + + in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) + + cdc := NewCDCDescriptor(iad, + cif, + header, + controlManagement, + functionalDescriptor, + callManagement, + cifin, + dif, + out, + in) + + sz := uint16(configDescriptorSize + cdcSize) + config := NewConfigDescriptor(sz, 2) + + buf := make([]byte, 0, sz) + buf = append(buf, config.Bytes()...) + buf = append(buf, cdc.Bytes()...) + + sendUSBPacket(0, buf) + } +} diff --git a/src/machine/usb_nrf52840.go b/src/machine/usb_nrf52840.go index 13710789..c8375619 100644 --- a/src/machine/usb_nrf52840.go +++ b/src/machine/usb_nrf52840.go @@ -400,110 +400,6 @@ func sendUSBPacket(ep uint32, data []byte) { ) } -// sendDescriptor creates and sends the various USB descriptor types that -// can be requested by the host. -func sendDescriptor(setup usbSetup) { - switch setup.wValueH { - case usb_CONFIGURATION_DESCRIPTOR_TYPE: - sendConfiguration(setup) - return - case usb_DEVICE_DESCRIPTOR_TYPE: - // composite descriptor - dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1) - l := deviceDescriptorSize - if setup.wLength < deviceDescriptorSize { - l = int(setup.wLength) - } - sendUSBPacket(0, dd.Bytes()[:l]) - return - - case usb_STRING_DESCRIPTOR_TYPE: - switch setup.wValueL { - case 0: - b := make([]byte, 4) - b[0] = 0x04 - b[1] = 0x03 - b[2] = 0x09 - b[3] = 0x04 - sendUSBPacket(0, b) - - case usb_IPRODUCT: - b := strToUTF16LEDescriptor(usb_STRING_PRODUCT) - if setup.wLength == 2 { - sendUSBPacket(0, b[:2]) - } else { - sendUSBPacket(0, b) - } - - case usb_IMANUFACTURER: - b := strToUTF16LEDescriptor(usb_STRING_MANUFACTURER) - if setup.wLength == 2 { - sendUSBPacket(0, b[:2]) - } else { - sendUSBPacket(0, b) - } - - case usb_ISERIAL: - // TODO: allow returning a product serial number - nrf.USBD.TASKS_EP0STATUS.Set(1) - } - return - } - - // do not know how to handle this message, so return zero - nrf.USBD.TASKS_EP0STATUS.Set(1) - return -} - -// sendConfiguration creates and sends the configuration packet to the host. -func sendConfiguration(setup usbSetup) { - if setup.wLength == 9 { - sz := uint16(configDescriptorSize + cdcSize) - config := NewConfigDescriptor(sz, 2) - - sendUSBPacket(0, config.Bytes()) - } else { - iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) - - cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0) - - header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF) - - controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6) - - functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE) - - callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1) - - cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10) - - dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0) - - out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) - - in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0) - - cdc := NewCDCDescriptor(iad, - cif, - header, - controlManagement, - functionalDescriptor, - callManagement, - cifin, - dif, - out, - in) - - sz := uint16(configDescriptorSize + cdcSize) - config := NewConfigDescriptor(sz, 2) - - buf := make([]byte, 0) - buf = append(buf, config.Bytes()...) - buf = append(buf, cdc.Bytes()...) - sendUSBPacket(0, buf) - } -} - func (usbcdc USBCDC) handleEndpoint(ep uint32) { // get data count := int(nrf.USBD.EPOUT[ep].AMOUNT.Get()) @@ -517,6 +413,10 @@ func (usbcdc USBCDC) handleEndpoint(ep uint32) { nrf.USBD.SIZE.EPOUT[ep].Set(0) } +func sendZlp() { + nrf.USBD.TASKS_EP0STATUS.Set(1) +} + func sendViaEPIn(ep uint32, ptr *byte, count int) { nrf.USBD.EPIN[ep].PTR.Set( uint32(uintptr(unsafe.Pointer(ptr))),