From 3c2d2a93d324fd7de127a7bdd09fabde90acd471 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Tue, 12 Jul 2022 22:31:23 +0200 Subject: [PATCH] machine/usb: refactorings to move functionality under machine/usb package Signed-off-by: deadprogram --- src/machine/machine_atsamd21_usb.go | 29 +- src/machine/machine_atsamd51_usb.go | 29 +- src/machine/machine_nrf52840_usb.go | 35 +-- src/machine/machine_rp2040_usb.go | 43 +-- src/machine/usb.go | 259 +++++------------- src/machine/usb/cdc/usbcdc.go | 3 +- .../{usb_descriptor.go => usb/descriptor.go} | 28 +- src/machine/usb/hid/hid.go | 3 +- src/machine/usb/usb.go | 121 ++++++++ 9 files changed, 279 insertions(+), 271 deletions(-) rename src/machine/{usb_descriptor.go => usb/descriptor.go} (87%) create mode 100644 src/machine/usb/usb.go diff --git a/src/machine/machine_atsamd21_usb.go b/src/machine/machine_atsamd21_usb.go index 1a920100..7eeb4d0c 100644 --- a/src/machine/machine_atsamd21_usb.go +++ b/src/machine/machine_atsamd21_usb.go @@ -5,6 +5,7 @@ package machine import ( "device/sam" + "machine/usb" "runtime/interrupt" "unsafe" ) @@ -117,7 +118,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) { // End of reset if (flags & sam.USB_DEVICE_INTFLAG_EORST) > 0 { // Configure control endpoint - initEndpoint(0, usb_ENDPOINT_TYPE_CONTROL) + initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL) usbConfiguration = 0 @@ -136,14 +137,14 @@ func handleUSBIRQ(intr interrupt.Interrupt) { setEPINTFLAG(0, sam.USB_DEVICE_EPINTFLAG_RXSTP) // parse setup - setup := newUSBSetup(udd_ep_out_cache_buffer[0][:]) + setup := usb.NewSetup(udd_ep_out_cache_buffer[0][:]) // Clear the Bank 0 ready flag on Control OUT setEPSTATUSCLR(0, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY) usbEndpointDescriptors[0].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) ok := false - if (setup.BmRequestType & usb_REQUEST_TYPE) == usb_REQUEST_STANDARD { + if (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD { // Standard Requests ok = handleStandardSetup(setup) } else { @@ -192,7 +193,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) { func initEndpoint(ep, config uint32) { switch config { - case usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn: + case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn: // set packet size usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) @@ -200,11 +201,11 @@ 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, ((usb.ENDPOINT_TYPE_INTERRUPT + 1) << sam.USB_DEVICE_EPCFG_EPTYPE1_Pos)) setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT1) - case usb_ENDPOINT_TYPE_BULK | usbEndpointOut: + case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut: // set packet size usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) @@ -212,7 +213,7 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, ((usb_ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_EPCFG_EPTYPE0_Pos)) + setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_EPCFG_EPTYPE0_Pos)) // receive interrupts when current transfer complete setEPINTENSET(ep, sam.USB_DEVICE_EPINTENSET_TRCPT0) @@ -223,10 +224,10 @@ func initEndpoint(ep, config uint32) { // ready for next transfer setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY) - case usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointOut: + case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut: // TODO: not really anything, seems like... - case usb_ENDPOINT_TYPE_BULK | usbEndpointIn: + case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn: // set packet size usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) @@ -234,14 +235,14 @@ 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_BULK + 1) << sam.USB_DEVICE_EPCFG_EPTYPE1_Pos)) + setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_EPCFG_EPTYPE1_Pos)) // 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: + case usb.ENDPOINT_TYPE_CONTROL: // Control OUT // set packet size usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) @@ -250,7 +251,7 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, getEPCFG(ep)|((usb_ENDPOINT_TYPE_CONTROL+1)< 0 { // Configure control endpoint - initEndpoint(0, usb_ENDPOINT_TYPE_CONTROL) + initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL) usbConfiguration = 0 @@ -139,14 +140,14 @@ func handleUSBIRQ(intr interrupt.Interrupt) { setEPINTFLAG(0, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_RXSTP) // parse setup - setup := newUSBSetup(udd_ep_out_cache_buffer[0][:]) + setup := usb.NewSetup(udd_ep_out_cache_buffer[0][:]) // Clear the Bank 0 ready flag on Control OUT setEPSTATUSCLR(0, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY) usbEndpointDescriptors[0].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos) ok := false - if (setup.BmRequestType & usb_REQUEST_TYPE) == usb_REQUEST_STANDARD { + if (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD { // Standard Requests ok = handleStandardSetup(setup) } else { @@ -195,7 +196,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) { func initEndpoint(ep, config uint32) { switch config { - case usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn: + case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn: // set packet size usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) @@ -203,11 +204,11 @@ 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_ENDPOINT_EPCFG_EPTYPE1_Pos)) + 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: + case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut: // set packet size usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) @@ -215,7 +216,7 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, ((usb_ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos)) + setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE0_Pos)) // receive interrupts when current transfer complete setEPINTENSET(ep, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0) @@ -226,10 +227,10 @@ func initEndpoint(ep, config uint32) { // ready for next transfer setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY) - case usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointOut: + case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut: // TODO: not really anything, seems like... - case usb_ENDPOINT_TYPE_BULK | usbEndpointIn: + case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn: // set packet size usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) @@ -237,14 +238,14 @@ 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_BULK + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos)) + setEPCFG(ep, ((usb.ENDPOINT_TYPE_BULK + 1) << sam.USB_DEVICE_ENDPOINT_EPCFG_EPTYPE1_Pos)) // 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: + case usb.ENDPOINT_TYPE_CONTROL: // Control OUT // set packet size usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.SetBits(epPacketSize(64) << usb_DEVICE_PCKSIZE_SIZE_Pos) @@ -253,7 +254,7 @@ func initEndpoint(ep, config uint32) { usbEndpointDescriptors[ep].DeviceDescBank[0].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_out_cache_buffer[ep])))) // set endpoint type - setEPCFG(ep, getEPCFG(ep)|((usb_ENDPOINT_TYPE_CONTROL+1)< 0 { // Configure control endpoint - initEndpoint(0, usb_ENDPOINT_TYPE_CONTROL) + initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL) nrf.USBD.USBPULLUP.Set(1) usbConfiguration = 0 @@ -115,10 +116,10 @@ func handleUSBIRQ(interrupt.Interrupt) { // previous data was too big for one packet, so send a second ptr := sendOnEP0DATADONE.ptr count := sendOnEP0DATADONE.count - if count > usbEndpointPacketSize { - sendOnEP0DATADONE.offset += usbEndpointPacketSize + if count > usb.EndpointPacketSize { + sendOnEP0DATADONE.offset += usb.EndpointPacketSize sendOnEP0DATADONE.ptr = &udd_ep_control_cache_buffer[sendOnEP0DATADONE.offset] - count = usbEndpointPacketSize + count = usb.EndpointPacketSize } sendOnEP0DATADONE.count -= count sendViaEPIn( @@ -148,7 +149,7 @@ func handleUSBIRQ(interrupt.Interrupt) { setup := parseUSBSetupRegisters() ok := false - if (setup.BmRequestType & usb_REQUEST_TYPE) == usb_REQUEST_STANDARD { + if (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD { // Standard Requests ok = handleStandardSetup(setup) } else { @@ -202,8 +203,8 @@ func handleUSBIRQ(interrupt.Interrupt) { } } -func parseUSBSetupRegisters() USBSetup { - return USBSetup{ +func parseUSBSetupRegisters() usb.Setup { + return usb.Setup{ BmRequestType: uint8(nrf.USBD.BMREQUESTTYPE.Get()), BRequest: uint8(nrf.USBD.BREQUEST.Get()), WValueL: uint8(nrf.USBD.WVALUEL.Get()), @@ -215,23 +216,23 @@ func parseUSBSetupRegisters() USBSetup { func initEndpoint(ep, config uint32) { switch config { - case usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn: + case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn: enableEPIn(ep) - case usb_ENDPOINT_TYPE_BULK | usbEndpointOut: + case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut: nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 << ep) nrf.USBD.SIZE.EPOUT[ep].Set(0) enableEPOut(ep) - case usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointOut: + case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut: nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 << ep) nrf.USBD.SIZE.EPOUT[ep].Set(0) enableEPOut(ep) - case usb_ENDPOINT_TYPE_BULK | usbEndpointIn: + case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn: enableEPIn(ep) - case usb_ENDPOINT_TYPE_CONTROL: + case usb.ENDPOINT_TYPE_CONTROL: enableEPIn(0) enableEPOut(0) nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 | @@ -261,11 +262,11 @@ func sendUSBPacket(ep uint32, data []byte, maxsize uint16) { if ep == 0 { copy(udd_ep_control_cache_buffer[:], data[:count]) - if count > usbEndpointPacketSize { - sendOnEP0DATADONE.offset = usbEndpointPacketSize + if count > usb.EndpointPacketSize { + sendOnEP0DATADONE.offset = usb.EndpointPacketSize sendOnEP0DATADONE.ptr = &udd_ep_control_cache_buffer[sendOnEP0DATADONE.offset] - sendOnEP0DATADONE.count = count - usbEndpointPacketSize - count = usbEndpointPacketSize + sendOnEP0DATADONE.count = count - usb.EndpointPacketSize + count = usb.EndpointPacketSize } sendViaEPIn( ep, @@ -316,7 +317,7 @@ func enableEPIn(ep uint32) { nrf.USBD.EPINEN.Set(epinen) } -func handleUSBSetAddress(setup USBSetup) bool { +func handleUSBSetAddress(setup usb.Setup) bool { // nrf USBD handles this return true } diff --git a/src/machine/machine_rp2040_usb.go b/src/machine/machine_rp2040_usb.go index 865b2bec..64864c44 100644 --- a/src/machine/machine_rp2040_usb.go +++ b/src/machine/machine_rp2040_usb.go @@ -6,6 +6,7 @@ package machine import ( "device/arm" "device/rp" + "machine/usb" "runtime/interrupt" "unsafe" ) @@ -58,10 +59,10 @@ func handleUSBIRQ(intr interrupt.Interrupt) { // Setup packet received if (status & rp.USBCTRL_REGS_INTS_SETUP_REQ) > 0 { rp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_SETUP_REC) - setup := newUSBSetup(usbDPSRAM.setupBytes()) + setup := usb.NewSetup(usbDPSRAM.setupBytes()) ok := false - if (setup.BmRequestType & usb_REQUEST_TYPE) == usb_REQUEST_STANDARD { + if (setup.BmRequestType & usb.REQUEST_TYPE) == usb.REQUEST_STANDARD { // Standard Requests ok = handleStandardSetup(setup) } else { @@ -84,8 +85,8 @@ func handleUSBIRQ(intr interrupt.Interrupt) { ep := uint32(0) data := sendOnEP0DATADONE.data count := len(data) - sendOnEP0DATADONE.offset - if ep == 0 && count > usbEndpointPacketSize { - count = usbEndpointPacketSize + if ep == 0 && count > usb.EndpointPacketSize { + count = usb.EndpointPacketSize } sendViaEPIn(ep, data[sendOnEP0DATADONE.offset:], count) @@ -122,7 +123,7 @@ func handleUSBIRQ(intr interrupt.Interrupt) { // Bus is reset if (status & rp.USBCTRL_REGS_INTS_BUS_RESET) > 0 { rp.USBCTRL_REGS.SIE_STATUS.Set(rp.USBCTRL_REGS_SIE_STATUS_BUS_RESET) - initEndpoint(0, usb_ENDPOINT_TYPE_CONTROL) + initEndpoint(0, usb.ENDPOINT_TYPE_CONTROL) } } @@ -132,31 +133,31 @@ func initEndpoint(ep, config uint32) { val |= offset switch config { - case usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn: + case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn: val |= usbEpControlEndpointTypeInterrupt usbDPSRAM.EPxControl[ep].In = val - case usb_ENDPOINT_TYPE_BULK | usbEndpointOut: + case usb.ENDPOINT_TYPE_BULK | usb.EndpointOut: val |= usbEpControlEndpointTypeBulk usbDPSRAM.EPxControl[ep].Out = val usbDPSRAM.EPxBufferControl[ep].Out = USBBufferLen & usbBuf0CtrlLenMask usbDPSRAM.EPxBufferControl[ep].Out |= usbBuf0CtrlAvail - case usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointOut: + case usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointOut: // TODO: not really anything, seems like... - case usb_ENDPOINT_TYPE_BULK | usbEndpointIn: + case usb.ENDPOINT_TYPE_BULK | usb.EndpointIn: val |= usbEpControlEndpointTypeBulk usbDPSRAM.EPxControl[ep].In = val - case usb_ENDPOINT_TYPE_CONTROL: + case usb.ENDPOINT_TYPE_CONTROL: val |= usbEpControlEndpointTypeControl usbDPSRAM.EPxBufferControl[ep].Out = usbBuf0CtrlAvail } } -func handleUSBSetAddress(setup USBSetup) bool { +func handleUSBSetAddress(setup usb.Setup) bool { sendUSBPacket(0, []byte{}, 0) // last, set the device address to that requested by host @@ -189,8 +190,8 @@ func sendUSBPacket(ep uint32, data []byte, maxsize uint16) { } if ep == 0 { - if count > usbEndpointPacketSize { - count = usbEndpointPacketSize + if count > usb.EndpointPacketSize { + count = usb.EndpointPacketSize sendOnEP0DATADONE.offset = count sendOnEP0DATADONE.data = data @@ -298,14 +299,14 @@ var ( func (d *USBDPSRAM) setupBytes() []byte { var buf [8]byte - buf[0] = byte(d.EPxControl[usb_CONTROL_ENDPOINT].In) - buf[1] = byte(d.EPxControl[usb_CONTROL_ENDPOINT].In >> 8) - buf[2] = byte(d.EPxControl[usb_CONTROL_ENDPOINT].In >> 16) - buf[3] = byte(d.EPxControl[usb_CONTROL_ENDPOINT].In >> 24) - buf[4] = byte(d.EPxControl[usb_CONTROL_ENDPOINT].Out) - buf[5] = byte(d.EPxControl[usb_CONTROL_ENDPOINT].Out >> 8) - buf[6] = byte(d.EPxControl[usb_CONTROL_ENDPOINT].Out >> 16) - buf[7] = byte(d.EPxControl[usb_CONTROL_ENDPOINT].Out >> 24) + buf[0] = byte(d.EPxControl[usb.CONTROL_ENDPOINT].In) + buf[1] = byte(d.EPxControl[usb.CONTROL_ENDPOINT].In >> 8) + buf[2] = byte(d.EPxControl[usb.CONTROL_ENDPOINT].In >> 16) + buf[3] = byte(d.EPxControl[usb.CONTROL_ENDPOINT].In >> 24) + buf[4] = byte(d.EPxControl[usb.CONTROL_ENDPOINT].Out) + buf[5] = byte(d.EPxControl[usb.CONTROL_ENDPOINT].Out >> 8) + buf[6] = byte(d.EPxControl[usb.CONTROL_ENDPOINT].Out >> 16) + buf[7] = byte(d.EPxControl[usb.CONTROL_ENDPOINT].Out >> 24) return buf[:] } diff --git a/src/machine/usb.go b/src/machine/usb.go index 794c4b66..7a8c4f0c 100644 --- a/src/machine/usb.go +++ b/src/machine/usb.go @@ -5,7 +5,7 @@ package machine import ( "errors" - "runtime/volatile" + "machine/usb" ) type USBDevice struct { @@ -27,15 +27,9 @@ type Serialer interface { RTS() bool } -var usbDescriptor = descriptorCDC +var usbDescriptor = usb.DescriptorCDC -const ( - usbDescriptorConfigCDC = 1 << iota - usbDescriptorConfigHID - usbDescriptorConfigMIDI -) - -var usbDescriptorConfig uint8 = usbDescriptorConfigCDC +var usbDescriptorConfig uint8 = usb.DescriptorConfigCDC // strToUTF16LEDescriptor converts a utf8 string into a string descriptor // note: the following code only converts ascii characters to UTF16LE. In order @@ -44,7 +38,7 @@ var usbDescriptorConfig uint8 = usbDescriptorConfigCDC // binary. func strToUTF16LEDescriptor(in string, out []byte) { out[0] = byte(len(out)) - out[1] = usb_STRING_DESCRIPTOR_TYPE + out[1] = usb.STRING_DESCRIPTOR_TYPE for i, rune := range in { out[(i<<1)+2] = byte(rune) out[(i<<1)+3] = 0 @@ -52,11 +46,6 @@ func strToUTF16LEDescriptor(in string, out []byte) { return } -var ( - // TODO: allow setting these - usb_STRING_LANGUAGE = [2]uint16{(3 << 8) | (2 + 2), 0x0409} // English -) - const cdcLineInfoSize = 7 var ( @@ -65,7 +54,7 @@ var ( ) var ( - usbEndpointDescriptors [numberOfEndpoints]usbDeviceDescriptor + usbEndpointDescriptors [usb.NumberOfEndpoints]usb.DeviceDescriptor udd_ep_control_cache_buffer [256]uint8 udd_ep_in_cache_buffer [7][64]uint8 @@ -78,191 +67,71 @@ var ( usbSetInterface uint8 ) -const ( - usb_IMANUFACTURER = 1 - usb_IPRODUCT = 2 - usb_ISERIAL = 3 - - usb_ENDPOINT_TYPE_DISABLE = 0xFF - usb_ENDPOINT_TYPE_CONTROL = 0x00 - usb_ENDPOINT_TYPE_ISOCHRONOUS = 0x01 - usb_ENDPOINT_TYPE_BULK = 0x02 - usb_ENDPOINT_TYPE_INTERRUPT = 0x03 - - usb_DEVICE_DESCRIPTOR_TYPE = 1 - usb_CONFIGURATION_DESCRIPTOR_TYPE = 2 - usb_STRING_DESCRIPTOR_TYPE = 3 - usb_INTERFACE_DESCRIPTOR_TYPE = 4 - usb_ENDPOINT_DESCRIPTOR_TYPE = 5 - usb_DEVICE_QUALIFIER = 6 - usb_OTHER_SPEED_CONFIGURATION = 7 - usb_SET_REPORT_TYPE = 33 - usb_HID_REPORT_TYPE = 34 - - usbEndpointOut = 0x00 - usbEndpointIn = 0x80 - - numberOfEndpoints = 8 - usbEndpointPacketSize = 64 // 64 for Full Speed, EPT size max is 1024 - - // standard requests - usb_GET_STATUS = 0 - usb_CLEAR_FEATURE = 1 - usb_SET_FEATURE = 3 - usb_SET_ADDRESS = 5 - usb_GET_DESCRIPTOR = 6 - usb_SET_DESCRIPTOR = 7 - usb_GET_CONFIGURATION = 8 - usb_SET_CONFIGURATION = 9 - usb_GET_INTERFACE = 10 - usb_SET_INTERFACE = 11 - - // non standard requests - usb_SET_IDLE = 10 - - usb_DEVICE_CLASS_COMMUNICATIONS = 0x02 - usb_DEVICE_CLASS_HUMAN_INTERFACE = 0x03 - usb_DEVICE_CLASS_STORAGE = 0x08 - usb_DEVICE_CLASS_VENDOR_SPECIFIC = 0xFF - - usb_CONFIG_POWERED_MASK = 0x40 - usb_CONFIG_BUS_POWERED = 0x80 - usb_CONFIG_SELF_POWERED = 0xC0 - usb_CONFIG_REMOTE_WAKEUP = 0x20 - - // Interface - numberOfInterfaces = 3 - usb_CDC_ACM_INTERFACE = 0 // CDC ACM - usb_CDC_DATA_INTERFACE = 1 // CDC Data - usb_CDC_FIRST_ENDPOINT = 1 - usb_HID_INTERFACE = 2 // HID - - // Endpoint - usb_CONTROL_ENDPOINT = 0 - usb_CDC_ENDPOINT_ACM = 1 - usb_CDC_ENDPOINT_OUT = 2 - usb_CDC_ENDPOINT_IN = 3 - usb_HID_ENDPOINT_IN = 4 - usb_MIDI_ENDPOINT_OUT = 5 - usb_MIDI_ENDPOINT_IN = 6 - - // bmRequestType - usb_REQUEST_HOSTTODEVICE = 0x00 - usb_REQUEST_DEVICETOHOST = 0x80 - usb_REQUEST_DIRECTION = 0x80 - - usb_REQUEST_STANDARD = 0x00 - usb_REQUEST_CLASS = 0x20 - usb_REQUEST_VENDOR = 0x40 - usb_REQUEST_TYPE = 0x60 - - usb_REQUEST_DEVICE = 0x00 - usb_REQUEST_INTERFACE = 0x01 - usb_REQUEST_ENDPOINT = 0x02 - usb_REQUEST_OTHER = 0x03 - usb_REQUEST_RECIPIENT = 0x1F - - usb_REQUEST_DEVICETOHOST_CLASS_INTERFACE = (usb_REQUEST_DEVICETOHOST | usb_REQUEST_CLASS | usb_REQUEST_INTERFACE) - usb_REQUEST_HOSTTODEVICE_CLASS_INTERFACE = (usb_REQUEST_HOSTTODEVICE | usb_REQUEST_CLASS | usb_REQUEST_INTERFACE) - usb_REQUEST_DEVICETOHOST_STANDARD_INTERFACE = (usb_REQUEST_DEVICETOHOST | usb_REQUEST_STANDARD | usb_REQUEST_INTERFACE) -) - var ( - usbTxHandler [numberOfEndpoints]func() - usbRxHandler [numberOfEndpoints]func([]byte) - usbSetupHandler [numberOfInterfaces]func(USBSetup) bool + usbTxHandler [usb.NumberOfEndpoints]func() + usbRxHandler [usb.NumberOfEndpoints]func([]byte) + usbSetupHandler [usb.NumberOfInterfaces]func(usb.Setup) bool endPoints = []uint32{ - usb_CONTROL_ENDPOINT: usb_ENDPOINT_TYPE_CONTROL, - usb_CDC_ENDPOINT_ACM: (usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn), - usb_CDC_ENDPOINT_OUT: (usb_ENDPOINT_TYPE_BULK | usbEndpointOut), - usb_CDC_ENDPOINT_IN: (usb_ENDPOINT_TYPE_BULK | usbEndpointIn), - usb_HID_ENDPOINT_IN: (usb_ENDPOINT_TYPE_DISABLE), // Interrupt In - usb_MIDI_ENDPOINT_OUT: (usb_ENDPOINT_TYPE_DISABLE), // Bulk Out - usb_MIDI_ENDPOINT_IN: (usb_ENDPOINT_TYPE_DISABLE), // Bulk In + usb.CONTROL_ENDPOINT: usb.ENDPOINT_TYPE_CONTROL, + usb.CDC_ENDPOINT_ACM: (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn), + usb.CDC_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut), + usb.CDC_ENDPOINT_IN: (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn), + usb.HID_ENDPOINT_IN: (usb.ENDPOINT_TYPE_DISABLE), // Interrupt In + usb.MIDI_ENDPOINT_OUT: (usb.ENDPOINT_TYPE_DISABLE), // Bulk Out + usb.MIDI_ENDPOINT_IN: (usb.ENDPOINT_TYPE_DISABLE), // Bulk In } ) -// usbDeviceDescBank is the USB device endpoint descriptor. -type usbDeviceDescBank struct { - ADDR volatile.Register32 - PCKSIZE volatile.Register32 - EXTREG volatile.Register16 - STATUS_BK volatile.Register8 - _reserved [5]volatile.Register8 -} - -type usbDeviceDescriptor struct { - DeviceDescBank [2]usbDeviceDescBank -} - -type USBSetup struct { - BmRequestType uint8 - BRequest uint8 - WValueL uint8 - WValueH uint8 - WIndex uint16 - WLength uint16 -} - -func newUSBSetup(data []byte) USBSetup { - u := USBSetup{} - u.BmRequestType = uint8(data[0]) - u.BRequest = uint8(data[1]) - u.WValueL = uint8(data[2]) - u.WValueH = uint8(data[3]) - u.WIndex = uint16(data[4]) | (uint16(data[5]) << 8) - u.WLength = uint16(data[6]) | (uint16(data[7]) << 8) - return u -} - // sendDescriptor creates and sends the various USB descriptor types that // can be requested by the host. -func sendDescriptor(setup USBSetup) { +func sendDescriptor(setup usb.Setup) { switch setup.WValueH { - case usb_CONFIGURATION_DESCRIPTOR_TYPE: + case usb.CONFIGURATION_DESCRIPTOR_TYPE: sendUSBPacket(0, usbDescriptor.Configuration, setup.WLength) return - case usb_DEVICE_DESCRIPTOR_TYPE: + case usb.DEVICE_DESCRIPTOR_TYPE: // composite descriptor - if (usbDescriptorConfig & usbDescriptorConfigHID) > 0 { - usbDescriptor = descriptorCDCHID - } else if (usbDescriptorConfig & usbDescriptorConfigMIDI) > 0 { - usbDescriptor = descriptorCDCMIDI - } else { - usbDescriptor = descriptorCDC + switch { + case (usbDescriptorConfig & usb.DescriptorConfigHID) > 0: + usbDescriptor = usb.DescriptorCDCHID + case (usbDescriptorConfig & usb.DescriptorConfigMIDI) > 0: + usbDescriptor = usb.DescriptorCDCMIDI + default: + usbDescriptor = usb.DescriptorCDC } + usbDescriptor.Configure(usb_VID, usb_PID) sendUSBPacket(0, usbDescriptor.Device, setup.WLength) return - case usb_STRING_DESCRIPTOR_TYPE: + case usb.STRING_DESCRIPTOR_TYPE: switch setup.WValueL { case 0: b := []byte{0x04, 0x03, 0x09, 0x04} sendUSBPacket(0, b, setup.WLength) - case usb_IPRODUCT: + case usb.IPRODUCT: b := make([]byte, (len(usb_STRING_PRODUCT)<<1)+2) strToUTF16LEDescriptor(usb_STRING_PRODUCT, b) sendUSBPacket(0, b, setup.WLength) - case usb_IMANUFACTURER: + case usb.IMANUFACTURER: b := make([]byte, (len(usb_STRING_MANUFACTURER)<<1)+2) strToUTF16LEDescriptor(usb_STRING_MANUFACTURER, b) sendUSBPacket(0, b, setup.WLength) - case usb_ISERIAL: + case usb.ISERIAL: // TODO: allow returning a product serial number SendZlp() } return - case usb_HID_REPORT_TYPE: + case usb.HID_REPORT_TYPE: if h, ok := usbDescriptor.HID[setup.WIndex]; ok { sendUSBPacket(0, h, setup.WLength) return } - case usb_DEVICE_QUALIFIER: + case usb.DEVICE_QUALIFIER: // skip default: } @@ -272,9 +141,9 @@ func sendDescriptor(setup USBSetup) { return } -func handleStandardSetup(setup USBSetup) bool { +func handleStandardSetup(setup usb.Setup) bool { switch setup.BRequest { - case usb_GET_STATUS: + case usb.GET_STATUS: buf := []byte{0, 0} if setup.BmRequestType != 0 { // endpoint @@ -286,7 +155,7 @@ func handleStandardSetup(setup USBSetup) bool { sendUSBPacket(0, buf, setup.WLength) return true - case usb_CLEAR_FEATURE: + case usb.CLEAR_FEATURE: if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP isRemoteWakeUpEnabled = false } else if setup.WValueL == 0 { // ENDPOINTHALT @@ -295,7 +164,7 @@ func handleStandardSetup(setup USBSetup) bool { SendZlp() return true - case usb_SET_FEATURE: + case usb.SET_FEATURE: if setup.WValueL == 1 { // DEVICEREMOTEWAKEUP isRemoteWakeUpEnabled = true } else if setup.WValueL == 0 { // ENDPOINTHALT @@ -304,23 +173,23 @@ func handleStandardSetup(setup USBSetup) bool { SendZlp() return true - case usb_SET_ADDRESS: + case usb.SET_ADDRESS: return handleUSBSetAddress(setup) - case usb_GET_DESCRIPTOR: + case usb.GET_DESCRIPTOR: sendDescriptor(setup) return true - case usb_SET_DESCRIPTOR: + case usb.SET_DESCRIPTOR: return false - case usb_GET_CONFIGURATION: + 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 { + 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]) } @@ -333,12 +202,12 @@ func handleStandardSetup(setup USBSetup) bool { return false } - case usb_GET_INTERFACE: + case usb.GET_INTERFACE: buff := []byte{usbSetInterface} sendUSBPacket(0, buff, setup.WLength) return true - case usb_SET_INTERFACE: + case usb.SET_INTERFACE: usbSetInterface = setup.WValueL SendZlp() @@ -349,30 +218,30 @@ func handleStandardSetup(setup USBSetup) bool { } } -func EnableCDC(txHandler func(), rxHandler func([]byte), setupHandler func(USBSetup) bool) { - usbDescriptorConfig |= usbDescriptorConfigCDC - endPoints[usb_CDC_ENDPOINT_ACM] = (usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn) - endPoints[usb_CDC_ENDPOINT_OUT] = (usb_ENDPOINT_TYPE_BULK | usbEndpointOut) - endPoints[usb_CDC_ENDPOINT_IN] = (usb_ENDPOINT_TYPE_BULK | usbEndpointIn) - usbRxHandler[usb_CDC_ENDPOINT_OUT] = rxHandler - usbTxHandler[usb_CDC_ENDPOINT_IN] = txHandler - usbSetupHandler[usb_CDC_ACM_INTERFACE] = setupHandler // 0x02 (Communications and CDC Control) - usbSetupHandler[usb_CDC_DATA_INTERFACE] = nil // 0x0A (CDC-Data) +func EnableCDC(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) { + usbDescriptorConfig |= usb.DescriptorConfigCDC + endPoints[usb.CDC_ENDPOINT_ACM] = (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn) + endPoints[usb.CDC_ENDPOINT_OUT] = (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut) + endPoints[usb.CDC_ENDPOINT_IN] = (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn) + usbRxHandler[usb.CDC_ENDPOINT_OUT] = rxHandler + usbTxHandler[usb.CDC_ENDPOINT_IN] = txHandler + usbSetupHandler[usb.CDC_ACM_INTERFACE] = setupHandler // 0x02 (Communications and CDC Control) + usbSetupHandler[usb.CDC_DATA_INTERFACE] = nil // 0x0A (CDC-Data) } // EnableHID enables HID. This function must be executed from the init(). -func EnableHID(txHandler func(), rxHandler func([]byte), setupHandler func(USBSetup) bool) { - usbDescriptorConfig |= usbDescriptorConfigHID - endPoints[usb_HID_ENDPOINT_IN] = (usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn) - usbTxHandler[usb_HID_ENDPOINT_IN] = txHandler - usbSetupHandler[usb_HID_INTERFACE] = setupHandler // 0x03 (HID - Human Interface Device) +func EnableHID(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) { + usbDescriptorConfig |= usb.DescriptorConfigHID + endPoints[usb.HID_ENDPOINT_IN] = (usb.ENDPOINT_TYPE_INTERRUPT | usb.EndpointIn) + usbTxHandler[usb.HID_ENDPOINT_IN] = txHandler + usbSetupHandler[usb.HID_INTERFACE] = setupHandler // 0x03 (HID - Human Interface Device) } // EnableMIDI enables MIDI. This function must be executed from the init(). -func EnableMIDI(txHandler func(), rxHandler func([]byte), setupHandler func(USBSetup) bool) { - usbDescriptorConfig |= usbDescriptorConfigMIDI - endPoints[usb_MIDI_ENDPOINT_OUT] = (usb_ENDPOINT_TYPE_BULK | usbEndpointOut) - endPoints[usb_MIDI_ENDPOINT_IN] = (usb_ENDPOINT_TYPE_BULK | usbEndpointIn) - usbRxHandler[usb_MIDI_ENDPOINT_OUT] = rxHandler - usbTxHandler[usb_MIDI_ENDPOINT_IN] = txHandler +func EnableMIDI(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) { + usbDescriptorConfig |= usb.DescriptorConfigMIDI + endPoints[usb.MIDI_ENDPOINT_OUT] = (usb.ENDPOINT_TYPE_BULK | usb.EndpointOut) + endPoints[usb.MIDI_ENDPOINT_IN] = (usb.ENDPOINT_TYPE_BULK | usb.EndpointIn) + usbRxHandler[usb.MIDI_ENDPOINT_OUT] = rxHandler + usbTxHandler[usb.MIDI_ENDPOINT_IN] = txHandler } diff --git a/src/machine/usb/cdc/usbcdc.go b/src/machine/usb/cdc/usbcdc.go index a2108968..b341f494 100644 --- a/src/machine/usb/cdc/usbcdc.go +++ b/src/machine/usb/cdc/usbcdc.go @@ -3,6 +3,7 @@ package cdc import ( "errors" "machine" + "machine/usb" "runtime/interrupt" ) @@ -128,7 +129,7 @@ func cdcCallbackRx(b []byte) { } } -func cdcSetup(setup machine.USBSetup) bool { +func cdcSetup(setup usb.Setup) bool { if setup.BmRequestType == usb_REQUEST_DEVICETOHOST_CLASS_INTERFACE { if setup.BRequest == usb_CDC_GET_LINE_CODING { var b [cdcLineInfoSize]byte diff --git a/src/machine/usb_descriptor.go b/src/machine/usb/descriptor.go similarity index 87% rename from src/machine/usb_descriptor.go rename to src/machine/usb/descriptor.go index 744d8703..6435c2b5 100644 --- a/src/machine/usb_descriptor.go +++ b/src/machine/usb/descriptor.go @@ -1,15 +1,27 @@ -//go:build sam || nrf52840 || rp2040 -// +build sam nrf52840 rp2040 +package usb -package machine +import "runtime/volatile" -type USBDescriptor struct { +// DeviceDescBank is the USB device endpoint descriptor. +type DeviceDescBank struct { + ADDR volatile.Register32 + PCKSIZE volatile.Register32 + EXTREG volatile.Register16 + STATUS_BK volatile.Register8 + _reserved [5]volatile.Register8 +} + +type DeviceDescriptor struct { + DeviceDescBank [2]DeviceDescBank +} + +type Descriptor struct { Device []byte Configuration []byte HID map[uint16][]byte } -func (d *USBDescriptor) Configure(idVendor, idProduct uint16) { +func (d *Descriptor) Configure(idVendor, idProduct uint16) { d.Device[8] = byte(idVendor) d.Device[9] = byte(idVendor >> 8) d.Device[10] = byte(idProduct) @@ -19,7 +31,7 @@ func (d *USBDescriptor) Configure(idVendor, idProduct uint16) { d.Configuration[3] = byte(len(d.Configuration) >> 8) } -var descriptorCDC = USBDescriptor{ +var DescriptorCDC = Descriptor{ Device: []byte{ 0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x86, 0x28, 0x2d, 0x80, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01, }, @@ -38,7 +50,7 @@ var descriptorCDC = USBDescriptor{ }, } -var descriptorCDCHID = USBDescriptor{ +var DescriptorCDCHID = Descriptor{ Device: []byte{ 0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x86, 0x28, 0x2d, 0x80, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01, }, @@ -72,7 +84,7 @@ var descriptorCDCHID = USBDescriptor{ }, } -var descriptorCDCMIDI = USBDescriptor{ +var DescriptorCDCMIDI = Descriptor{ Device: []byte{ 0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x86, 0x28, 0x2d, 0x80, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01, }, diff --git a/src/machine/usb/hid/hid.go b/src/machine/usb/hid/hid.go index dd8db204..4f407241 100644 --- a/src/machine/usb/hid/hid.go +++ b/src/machine/usb/hid/hid.go @@ -3,6 +3,7 @@ package hid import ( "errors" "machine" + "machine/usb" ) // from usb-hid.go @@ -48,7 +49,7 @@ func handler() { } } -func setupHandler(setup machine.USBSetup) bool { +func setupHandler(setup usb.Setup) bool { ok := false if setup.BmRequestType == usb_SET_REPORT_TYPE && setup.BRequest == usb_SET_IDLE { machine.SendZlp() diff --git a/src/machine/usb/usb.go b/src/machine/usb/usb.go new file mode 100644 index 00000000..592b32be --- /dev/null +++ b/src/machine/usb/usb.go @@ -0,0 +1,121 @@ +package usb + +var ( + // TODO: allow setting these + STRING_LANGUAGE = [2]uint16{(3 << 8) | (2 + 2), 0x0409} // English +) + +const ( + DescriptorConfigCDC = 1 << iota + DescriptorConfigHID + DescriptorConfigMIDI +) + +const ( + IMANUFACTURER = 1 + IPRODUCT = 2 + ISERIAL = 3 + + ENDPOINT_TYPE_DISABLE = 0xFF + ENDPOINT_TYPE_CONTROL = 0x00 + ENDPOINT_TYPE_ISOCHRONOUS = 0x01 + ENDPOINT_TYPE_BULK = 0x02 + ENDPOINT_TYPE_INTERRUPT = 0x03 + + DEVICE_DESCRIPTOR_TYPE = 1 + CONFIGURATION_DESCRIPTOR_TYPE = 2 + STRING_DESCRIPTOR_TYPE = 3 + INTERFACE_DESCRIPTOR_TYPE = 4 + ENDPOINT_DESCRIPTOR_TYPE = 5 + DEVICE_QUALIFIER = 6 + OTHER_SPEED_CONFIGURATION = 7 + SET_REPORT_TYPE = 33 + HID_REPORT_TYPE = 34 + + EndpointOut = 0x00 + EndpointIn = 0x80 + + NumberOfEndpoints = 8 + EndpointPacketSize = 64 // 64 for Full Speed, EPT size max is 1024 + + // standard requests + GET_STATUS = 0 + CLEAR_FEATURE = 1 + SET_FEATURE = 3 + SET_ADDRESS = 5 + GET_DESCRIPTOR = 6 + SET_DESCRIPTOR = 7 + GET_CONFIGURATION = 8 + SET_CONFIGURATION = 9 + GET_INTERFACE = 10 + SET_INTERFACE = 11 + + // non standard requests + SET_IDLE = 10 + + DEVICE_CLASS_COMMUNICATIONS = 0x02 + DEVICE_CLASS_HUMAN_INTERFACE = 0x03 + DEVICE_CLASS_STORAGE = 0x08 + DEVICE_CLASS_VENDOR_SPECIFIC = 0xFF + + CONFIG_POWERED_MASK = 0x40 + CONFIG_BUS_POWERED = 0x80 + CONFIG_SELF_POWERED = 0xC0 + CONFIG_REMOTE_WAKEUP = 0x20 + + // Interface + NumberOfInterfaces = 3 + CDC_ACM_INTERFACE = 0 // CDC ACM + CDC_DATA_INTERFACE = 1 // CDC Data + CDC_FIRST_ENDPOINT = 1 + HID_INTERFACE = 2 // HID + + // Endpoint + CONTROL_ENDPOINT = 0 + CDC_ENDPOINT_ACM = 1 + CDC_ENDPOINT_OUT = 2 + CDC_ENDPOINT_IN = 3 + HID_ENDPOINT_IN = 4 + MIDI_ENDPOINT_OUT = 5 + MIDI_ENDPOINT_IN = 6 + + // bmRequestType + REQUEST_HOSTTODEVICE = 0x00 + REQUEST_DEVICETOHOST = 0x80 + REQUEST_DIRECTION = 0x80 + + REQUEST_STANDARD = 0x00 + REQUEST_CLASS = 0x20 + REQUEST_VENDOR = 0x40 + REQUEST_TYPE = 0x60 + + REQUEST_DEVICE = 0x00 + REQUEST_INTERFACE = 0x01 + REQUEST_ENDPOINT = 0x02 + REQUEST_OTHER = 0x03 + REQUEST_RECIPIENT = 0x1F + + REQUEST_DEVICETOHOST_CLASS_INTERFACE = (REQUEST_DEVICETOHOST | REQUEST_CLASS | REQUEST_INTERFACE) + REQUEST_HOSTTODEVICE_CLASS_INTERFACE = (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE) + REQUEST_DEVICETOHOST_STANDARD_INTERFACE = (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) +) + +type Setup struct { + BmRequestType uint8 + BRequest uint8 + WValueL uint8 + WValueH uint8 + WIndex uint16 + WLength uint16 +} + +func NewSetup(data []byte) Setup { + u := Setup{} + u.BmRequestType = uint8(data[0]) + u.BRequest = uint8(data[1]) + u.WValueL = uint8(data[2]) + u.WValueH = uint8(data[3]) + u.WIndex = uint16(data[4]) | (uint16(data[5]) << 8) + u.WLength = uint16(data[6]) | (uint16(data[7]) << 8) + return u +}