mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-16 02:33:28 +00:00
functioning ACM device registration with host
This commit is contained in:
@@ -252,3 +252,84 @@ func enableDcache(enable bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FlushDcache flushes data from cache to memory
|
||||||
|
//
|
||||||
|
// Normally FlushDcache is used when metadata written to memory will be used by
|
||||||
|
// a DMA or a bus-controller peripheral. Any data in the cache is written to
|
||||||
|
// memory. A copy remains in the cache, so this is typically used with special
|
||||||
|
// fields you will want to quickly access in the future. For data transmission,
|
||||||
|
// use FlushDeleteDcache.
|
||||||
|
//go:inline
|
||||||
|
func FlushDcache(addr, size uintptr) {
|
||||||
|
location := addr & 0xFFFFFFE0
|
||||||
|
endAddr := addr + size
|
||||||
|
arm.AsmFull(`
|
||||||
|
dsb 0xF
|
||||||
|
`, nil)
|
||||||
|
for {
|
||||||
|
SystemControl.DCCMVAC.Set(uint32(location))
|
||||||
|
location += 32
|
||||||
|
if location >= endAddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arm.AsmFull(`
|
||||||
|
dsb 0xF
|
||||||
|
isb 0xF
|
||||||
|
`, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDcache deletes data from the cache, without touching memory.
|
||||||
|
//
|
||||||
|
// Normally DeleteDcache is used before receiving data via DMA or from
|
||||||
|
// bus-controller peripherals which write to memory. You want to delete anything
|
||||||
|
// the cache may have stored, so your next read is certain to access the
|
||||||
|
// physical memory.
|
||||||
|
//go:inline
|
||||||
|
func DeleteDcache(addr, size uintptr) {
|
||||||
|
location := addr & 0xFFFFFFE0
|
||||||
|
endAddr := addr + size
|
||||||
|
arm.AsmFull(`
|
||||||
|
dsb 0xF
|
||||||
|
`, nil)
|
||||||
|
for {
|
||||||
|
SystemControl.DCIMVAC.Set(uint32(location))
|
||||||
|
location += 32
|
||||||
|
if location >= endAddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arm.AsmFull(`
|
||||||
|
dsb 0xF
|
||||||
|
isb 0xF
|
||||||
|
`, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlushDeleteDcache flushes data from cache to memory, and delete it from the
|
||||||
|
// cache
|
||||||
|
//
|
||||||
|
// Normally FlushDeleteDcache is used when transmitting data via DMA or
|
||||||
|
// bus-controller peripherals which read from memory. You want any cached data
|
||||||
|
// written to memory, and then removed from the cache, because you no longer
|
||||||
|
// need to access the data after transmission.
|
||||||
|
//go:inline
|
||||||
|
func FlushDeleteDcache(addr, size uintptr) {
|
||||||
|
location := addr & 0xFFFFFFE0
|
||||||
|
endAddr := addr + size
|
||||||
|
arm.AsmFull(`
|
||||||
|
dsb 0xF
|
||||||
|
`, nil)
|
||||||
|
for {
|
||||||
|
SystemControl.DCCIMVAC.Set(uint32(location))
|
||||||
|
location += 32
|
||||||
|
if location >= endAddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arm.AsmFull(`
|
||||||
|
dsb 0xF
|
||||||
|
isb 0xF
|
||||||
|
`, nil)
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package usb2
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type dcd interface {
|
||||||
|
init() status
|
||||||
|
enable(enable bool) status
|
||||||
|
critical(enter bool) status
|
||||||
|
interrupt()
|
||||||
|
receive(endpoint uint8, transfer *dcdTransfer)
|
||||||
|
transmit(endpoint uint8, transfer *dcdTransfer)
|
||||||
|
control(setup dcdSetup)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
dcdEndpointSize = 64 // bytes
|
||||||
|
dcdTransferSize = 32 //
|
||||||
|
dcdSetupSize = 8 //
|
||||||
|
)
|
||||||
|
|
||||||
|
type dcdEndpoint struct {
|
||||||
|
config uint32 // 4
|
||||||
|
current *dcdTransfer // 4 *dcdTransfer
|
||||||
|
transfer dcdTransfer // 32
|
||||||
|
setup dcdSetup // 8
|
||||||
|
// Endpoints are 48-byte data structures. The remaining data extends this to
|
||||||
|
// 64-byte, and also makes it simpler for implementations to align endpoints
|
||||||
|
// allocated contiguously on 64-byte boundaries.
|
||||||
|
first *dcdTransfer // 4 *dcdTransfer
|
||||||
|
last *dcdTransfer // 4 *dcdTransfer
|
||||||
|
// After some discussion, perhaps the simplest change to support 64-bit (or
|
||||||
|
// future TinyGo versions that don't use 8 bytes to refer to a function) is to
|
||||||
|
// allocate a separate buffer of callbacks. The device controller would assign
|
||||||
|
// callbacks to unused elements in that buffer, and only the index of that
|
||||||
|
// callback would be stored here in the descriptor.
|
||||||
|
callback dcdTransferCallback // 8
|
||||||
|
}
|
||||||
|
|
||||||
|
type dcdTransferCallback func(transfer *dcdTransfer)
|
||||||
|
type dcdTransfer struct {
|
||||||
|
next *dcdTransfer // 4 *dcdTransfer
|
||||||
|
token uint32 // 4
|
||||||
|
pointer [5]uintptr // 20
|
||||||
|
param uint32 // 4
|
||||||
|
}
|
||||||
|
|
||||||
|
type dcdSetup struct {
|
||||||
|
bmRequestType uint8
|
||||||
|
bRequest uint8
|
||||||
|
wValue uint16
|
||||||
|
wIndex uint16
|
||||||
|
wLength uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s dcdSetup) pack() uint64 {
|
||||||
|
return ((uint64(s.bmRequestType) & 0xFF) << 0) | // uint8
|
||||||
|
((uint64(s.bRequest) & 0xFF) << 8) | // uint8
|
||||||
|
((uint64(s.wValue) & 0xFFFF) << 16) | // uint16
|
||||||
|
((uint64(s.wIndex) & 0xFFFF) << 32) | // uint16
|
||||||
|
((uint64(s.wLength) & 0xFFFF) << 48) // uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// dcdPointerNil is a sentinel value used to indicate a pointer to an invalid
|
||||||
|
// value. Do not attempt to dereference!
|
||||||
|
dcdPointerNil = uintptr(0)
|
||||||
|
// dcdTransferEOL is a sentinel value used to indicate the final node in a
|
||||||
|
// linked list of transfer descriptors.
|
||||||
|
dcdTransferEOL = (*dcdTransfer)(unsafe.Pointer(dcdTransferPointerEOL))
|
||||||
|
// dcdTransferPointerEOL is the notional memory address of dcdTransferEOL.
|
||||||
|
// The address does not refer to an actual dcdTransfer, so no attempt should
|
||||||
|
// be made to dereference it.
|
||||||
|
dcdTransferPointerEOL = uintptr(1)
|
||||||
|
)
|
||||||
|
|
||||||
|
// nextTransfer returns the next transfer descriptor pointed to by the receiver
|
||||||
|
// transfer descriptor, and whether or not that next descriptor is the final
|
||||||
|
// descriptor in the list.
|
||||||
|
func (t *dcdTransfer) nextTransfer() (*dcdTransfer, bool) {
|
||||||
|
return t.next, uintptr(unsafe.Pointer(t.next)) == dcdTransferPointerEOL
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,174 +0,0 @@
|
|||||||
// +build mimxrt1062
|
|
||||||
|
|
||||||
package usb2
|
|
||||||
|
|
||||||
// Implementation of USB device controller interface (dci) for NXP iMXRT1062.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"device/arm"
|
|
||||||
"device/nxp"
|
|
||||||
"runtime/interrupt"
|
|
||||||
"runtime/volatile"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// dciCount defines the number of USB cores to configure for device mode. It is
|
|
||||||
// computed as the sum of all declared device configuration descriptors.
|
|
||||||
const dciCount = descCDCACMConfigCount
|
|
||||||
|
|
||||||
// dciInterruptPriority defines the priority for all USB device interrupts.
|
|
||||||
const dciInterruptPriority = 3
|
|
||||||
|
|
||||||
// deviceController implements USB device controller interface (dci).
|
|
||||||
type deviceController struct {
|
|
||||||
core *core // Parent USB core this instance is attached to
|
|
||||||
port int // USB port index
|
|
||||||
id int // deviceControllerInstance index
|
|
||||||
|
|
||||||
bus *nxp.USB_Type
|
|
||||||
phy *nxp.USBPHY_Type
|
|
||||||
irq interrupt.Interrupt
|
|
||||||
|
|
||||||
cri volatile.Register8 // set to 1 if in critical section, else 0
|
|
||||||
ivm uintptr // interrupt state when entering critical section
|
|
||||||
}
|
|
||||||
|
|
||||||
// deviceControllerInstance provides statically-allocated instances of each USB
|
|
||||||
// device controller configured on this platform.
|
|
||||||
var deviceControllerInstance [dciCount]deviceController
|
|
||||||
|
|
||||||
// initDCI initializes and assigns a free device controller instance to the
|
|
||||||
// given USB port. Returns the initialized device controller or nil if no free
|
|
||||||
// device controller instances remain.
|
|
||||||
func initDCI(port int) (dci, status) {
|
|
||||||
if 0 == dciCount {
|
|
||||||
return nil, statusInvalidArgument // must have defined device descriptors
|
|
||||||
}
|
|
||||||
// Return the first instance whose assigned core is currently nil.
|
|
||||||
for i := range deviceControllerInstance {
|
|
||||||
if nil == deviceControllerInstance[i].core {
|
|
||||||
// Initialize device controller.
|
|
||||||
deviceControllerInstance[i].core = &coreInstance[port]
|
|
||||||
deviceControllerInstance[i].port = port
|
|
||||||
deviceControllerInstance[i].id = i
|
|
||||||
switch port {
|
|
||||||
case 0:
|
|
||||||
deviceControllerInstance[i].bus = nxp.USB1
|
|
||||||
deviceControllerInstance[i].phy = nxp.USBPHY1
|
|
||||||
deviceControllerInstance[i].irq =
|
|
||||||
interrupt.New(nxp.IRQ_USB_OTG1,
|
|
||||||
func(interrupt.Interrupt) {
|
|
||||||
coreInstance[0].dc.interrupt()
|
|
||||||
})
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
deviceControllerInstance[i].bus = nxp.USB2
|
|
||||||
deviceControllerInstance[i].phy = nxp.USBPHY2
|
|
||||||
deviceControllerInstance[i].irq =
|
|
||||||
interrupt.New(nxp.IRQ_USB_OTG2,
|
|
||||||
func(interrupt.Interrupt) {
|
|
||||||
//coreInstance[1].dc.interrupt()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return &deviceControllerInstance[i], statusOK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, statusBusy // No free device controller instances available.
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *deviceController) init() status {
|
|
||||||
|
|
||||||
// reset the controller
|
|
||||||
dc.phy.CTRL_SET.Set(nxp.USBPHY_CTRL_SFTRST)
|
|
||||||
dc.bus.USBCMD.SetBits(nxp.USB_USBCMD_RST)
|
|
||||||
for dc.bus.USBCMD.HasBits(nxp.USB_USBCMD_RST) {
|
|
||||||
}
|
|
||||||
// clear interrupts
|
|
||||||
m := arm.DisableInterrupts()
|
|
||||||
switch dc.port {
|
|
||||||
case 0:
|
|
||||||
arm.EnableInterrupts(m & ^uintptr(nxp.IRQ_USB_OTG1))
|
|
||||||
case 1:
|
|
||||||
arm.EnableInterrupts(m & ^uintptr(nxp.IRQ_USB_OTG2))
|
|
||||||
}
|
|
||||||
dc.phy.CTRL_CLR.Set(nxp.USBPHY_CTRL_CLKGATE | nxp.USBPHY_CTRL_SFTRST)
|
|
||||||
dc.phy.PWD.Set(0)
|
|
||||||
|
|
||||||
// clear the controller mode field and set to device mode:
|
|
||||||
// controller mode (CM) 0x0=idle, 0x2=device-only, 0x3=host-only
|
|
||||||
dc.bus.USBMODE.ReplaceBits(nxp.USB_USBMODE_CM_CM_2,
|
|
||||||
nxp.USB_USBMODE_CM_Msk>>nxp.USB_USBMODE_CM_Pos, nxp.USB_USBMODE_CM_Pos)
|
|
||||||
|
|
||||||
dc.bus.USBCMD.ClearBits(nxp.USB_USBCMD_ITC_Msk) // no interrupt threshold
|
|
||||||
dc.bus.USBMODE.SetBits(nxp.USB_USBMODE_SLOM_Msk) // disable setup lockout
|
|
||||||
dc.bus.USBMODE.ClearBits(nxp.USB_USBMODE_ES_Msk) // use little-endianness
|
|
||||||
|
|
||||||
// TODO: configure ENDPOINTLISTADDR
|
|
||||||
|
|
||||||
// enable interrupts
|
|
||||||
dc.bus.USBINTR.Set(
|
|
||||||
nxp.USB_USBINTR_UE_Msk | // bus enable
|
|
||||||
nxp.USB_USBINTR_UEE_Msk | // bus error
|
|
||||||
nxp.USB_USBINTR_PCE_Msk | // port change detect
|
|
||||||
nxp.USB_USBINTR_URE_Msk | // bus reset
|
|
||||||
nxp.USB_USBINTR_SLE) // sleep enable
|
|
||||||
|
|
||||||
// ensure D+ pulled down long enough for host to detect previous disconnect
|
|
||||||
dc.udelay(5000)
|
|
||||||
|
|
||||||
return statusOK
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *deviceController) enable(enable bool) status {
|
|
||||||
|
|
||||||
if enable {
|
|
||||||
dc.irq.SetPriority(dciInterruptPriority)
|
|
||||||
dc.irq.Enable()
|
|
||||||
dc.bus.USBCMD.SetBits(nxp.USB_USBCMD_RS)
|
|
||||||
} else {
|
|
||||||
dc.bus.USBCMD.ClearBits(nxp.USB_USBCMD_RS)
|
|
||||||
dc.irq.Disable()
|
|
||||||
}
|
|
||||||
return statusOK
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *deviceController) critical(enter bool) status {
|
|
||||||
if enter {
|
|
||||||
// check if critical section already locked
|
|
||||||
if dc.cri.Get() != 0 {
|
|
||||||
return statusRetry
|
|
||||||
}
|
|
||||||
// lock critical section
|
|
||||||
dc.cri.Set(1)
|
|
||||||
// disable interrupts, storing state in receiver
|
|
||||||
dc.ivm = arm.DisableInterrupts()
|
|
||||||
} else {
|
|
||||||
// ensure critical section is locked
|
|
||||||
if dc.cri.Get() != 0 {
|
|
||||||
// re-enable interrupts, using state stored in receiver
|
|
||||||
arm.EnableInterrupts(dc.ivm)
|
|
||||||
// unlock critical section
|
|
||||||
dc.cri.Set(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return statusOK
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *deviceController) interrupt() {
|
|
||||||
// read and clear the interrupts that fired
|
|
||||||
status := dc.bus.USBSTS.Get() & dc.bus.USBINTR.Get()
|
|
||||||
dc.bus.USBSTS.Set(status)
|
|
||||||
|
|
||||||
println(strconv.FormatUint(uint64(status), 16))
|
|
||||||
}
|
|
||||||
|
|
||||||
// udelay waits for the given number of microseconds before returning.
|
|
||||||
// We cannot use the sleep timer from this context (import cycle), but we need
|
|
||||||
// an approximate method to spin CPU cycles for short periods of time.
|
|
||||||
//go:inline
|
|
||||||
func (dc *deviceController) udelay(microsec uint32) {
|
|
||||||
n := cycles(microsec, descCPUFrequencyHz)
|
|
||||||
for i := uint32(0); i < n; i++ {
|
|
||||||
arm.Asm(`nop`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+390
-199
@@ -1,21 +1,29 @@
|
|||||||
package usb2
|
package usb2
|
||||||
|
|
||||||
const descUSBSpecVersion = 0x0200 // USB 2.0
|
const descUSBSpecVersion = uint16(0x0200) // USB 2.0
|
||||||
|
|
||||||
|
const descLanguageEnglish = uint16(0x0409)
|
||||||
|
|
||||||
|
type descIndexStrings [4][64]uint8
|
||||||
|
type descLocalStrings struct {
|
||||||
|
language uint16
|
||||||
|
index descIndexStrings // UTF-16, 32-character maximum length
|
||||||
|
}
|
||||||
|
|
||||||
// USB constants defined per specification.
|
// USB constants defined per specification.
|
||||||
const (
|
const (
|
||||||
|
|
||||||
// Descriptor length
|
// Descriptor length
|
||||||
descLengthDevice = 18
|
descLengthDevice = 18
|
||||||
descLengthConfigure = 9
|
descLengthConfigure = 9
|
||||||
descLengthInterface = 9
|
descLengthInterface = 9
|
||||||
descLengthEndpoint = 7
|
descLengthEndpoint = 7
|
||||||
descLengthDeviceQualitier = 10
|
descLengthQualification = 10
|
||||||
descLengthOTG = 5
|
descLengthOTG = 5
|
||||||
descLengthBOS = 5
|
descLengthBOS = 5
|
||||||
descLengthEndpointCompanion = 6
|
descLengthEndpointCompanion = 6
|
||||||
descLengthDevCapTypeUSB20Extension = 7
|
descLengthUSB20Extension = 7
|
||||||
descLengthDevCapTypeSuperspeed = 10
|
descLengthSuperspeed = 10
|
||||||
|
|
||||||
// Descriptor type
|
// Descriptor type
|
||||||
descTypeDevice = 0x01
|
descTypeDevice = 0x01
|
||||||
@@ -23,7 +31,7 @@ const (
|
|||||||
descTypeString = 0x03
|
descTypeString = 0x03
|
||||||
descTypeInterface = 0x04
|
descTypeInterface = 0x04
|
||||||
descTypeEndpoint = 0x05
|
descTypeEndpoint = 0x05
|
||||||
descTypeDeviceQualitier = 0x06
|
descTypeQualification = 0x06
|
||||||
descTypeOtherSpeedConfiguration = 0x07
|
descTypeOtherSpeedConfiguration = 0x07
|
||||||
descTypeInterfacePower = 0x08
|
descTypeInterfacePower = 0x08
|
||||||
descTypeOTG = 0x09
|
descTypeOTG = 0x09
|
||||||
@@ -37,6 +45,36 @@ const (
|
|||||||
descTypeCDCEndpoint = 0x25
|
descTypeCDCEndpoint = 0x25
|
||||||
descTypeEndpointCompanion = 0x30
|
descTypeEndpointCompanion = 0x30
|
||||||
|
|
||||||
|
// Standard request type
|
||||||
|
descRequestTypeDirMsk = 0x80
|
||||||
|
descRequestTypeDirPos = 7
|
||||||
|
descRequestTypeDirOut = 0x00
|
||||||
|
descRequestTypeDirIn = 0x80
|
||||||
|
descRequestTypeTypeMsk = 0x60
|
||||||
|
descRequestTypeTypePos = 5
|
||||||
|
descRequestTypeTypeStandard = 0
|
||||||
|
descRequestTypeTypeClass = 0x20
|
||||||
|
descRequestTypeTypeVendor = 0x40
|
||||||
|
descRequestTypeRecipientMsk = 0x1F
|
||||||
|
descRequestTypeRecipientPos = 0
|
||||||
|
descRequestTypeRecipientDevice = 0x00
|
||||||
|
descRequestTypeRecipientInterface = 0x01
|
||||||
|
descRequestTypeRecipientEndpoint = 0x02
|
||||||
|
descRequestTypeRecipientOther = 0x03
|
||||||
|
|
||||||
|
// Standard request
|
||||||
|
descRequestStandardGetStatus = 0x00
|
||||||
|
descRequestStandardClearFeature = 0x01
|
||||||
|
descRequestStandardSetFeature = 0x03
|
||||||
|
descRequestStandardSetAddress = 0x05
|
||||||
|
descRequestStandardGetDescriptor = 0x06
|
||||||
|
descRequestStandardSetDescriptor = 0x07
|
||||||
|
descRequestStandardGetConfiguration = 0x08
|
||||||
|
descRequestStandardSetConfiguration = 0x09
|
||||||
|
descRequestStandardGetInterface = 0x0A
|
||||||
|
descRequestStandardSetInterface = 0x0B
|
||||||
|
descRequestStandardSynchFrame = 0x0C
|
||||||
|
|
||||||
// Configuration attributes
|
// Configuration attributes
|
||||||
descConfigAttrD7Msk = 0x80
|
descConfigAttrD7Msk = 0x80
|
||||||
descConfigAttrD7Pos = 7
|
descConfigAttrD7Pos = 7
|
||||||
@@ -60,49 +98,55 @@ const (
|
|||||||
descEndptAddrDirectionIn = 0x80
|
descEndptAddrDirectionIn = 0x80
|
||||||
|
|
||||||
// Endpoint attributes
|
// Endpoint attributes
|
||||||
descEndptAttrTypeMsk = 0x03
|
descEndptAttrTypeMsk = 0x03
|
||||||
descEndptAttrNumberPos = 0
|
descEndptAttrNumberPos = 0
|
||||||
descEndptAttrSyncTypeMsk = 0x0C
|
descEndptAttrSyncTypeMsk = 0x0C
|
||||||
descEndptAttrSyncTypePos = 2
|
descEndptAttrSyncTypePos = 2
|
||||||
descEndptAttrSyncTypeNoSync = 0x00
|
descEndptAttrSyncTypeNoSync = 0x00
|
||||||
descEndptAttrSyncTypeAsync = 0x04
|
descEndptAttrSyncTypeAsync = 0x04
|
||||||
descEndptAttrSyncTypeAdaptive = 0x08
|
descEndptAttrSyncTypeAdaptive = 0x08
|
||||||
descEndptAttrSyncTypeSync = 0x0C
|
descEndptAttrSyncTypeSync = 0x0C
|
||||||
descEndptAttrUsageTypeMsk = 0x30
|
descEndptAttrUsageTypeMsk = 0x30
|
||||||
descEndptAttrUsageTypePos = 4
|
descEndptAttrUsageTypePos = 4
|
||||||
descEndptAttrUsageTypeDataEndpoint = 0x00
|
descEndptAttrUsageTypeData = 0x00
|
||||||
descEndptAttrUsageTypeFeedEndpoint = 0x10
|
descEndptAttrUsageTypeFeed = 0x10
|
||||||
descEndptAttrUsageTypeFeedDataEndpoint = 0x20
|
descEndptAttrUsageTypeFeedData = 0x20
|
||||||
|
|
||||||
// Endpoint max packet size
|
// Endpoint max packet size
|
||||||
descEndptMaxPktSizeSizeMsk = 0x07FF
|
descEndptMaxPktSizeMsk = 0x07FF
|
||||||
descEndptMaxPktSizeMultTransMsk = 0x1800
|
descEndptMaxPktSize = 64
|
||||||
descEndptMaxPktSizeMultTransPos = 11
|
descEndptMaxPktSizeMultMsk = 0x1800
|
||||||
descEndptMaxPktSizeMaximum = 64
|
descEndptMaxPktSizeMultPos = 11
|
||||||
|
|
||||||
// OTG attributes
|
// OTG attributes
|
||||||
descOTGAttrSRPMsk = 0x01
|
descOTGAttrSRPMsk = 0x01
|
||||||
descOTGAttrHNPMsk = 0x02
|
descOTGAttrHNPMsk = 0x02
|
||||||
descOTGAttrADPMsk = 0x04
|
descOTGAttrADPMsk = 0x04
|
||||||
|
|
||||||
|
// Device bus speed
|
||||||
|
descDeviceSpeedFull = 0x00
|
||||||
|
descDeviceSpeedLow = 0x01
|
||||||
|
descDeviceSpeedHigh = 0x02
|
||||||
|
descDeviceSpeedSuper = 0x04
|
||||||
|
|
||||||
// Device capability type
|
// Device capability type
|
||||||
descDevCapTypeWireless = 0x01
|
descDeviceCapTypeWireless = 0x01
|
||||||
descDevCapTypeUSB20Extension = 0x02
|
descDeviceCapTypeUSB20Extension = 0x02
|
||||||
descDevCapTypeSuperspeed = 0x03
|
descDeviceCapTypeSuperspeed = 0x03
|
||||||
|
|
||||||
// Device capability attributes (USB 2.0 extension)
|
// Device capability attributes (USB 2.0 extension)
|
||||||
descDevCapExtAttrLPMMsk = 0x02
|
descDeviceCapExtAttrLPMMsk = 0x02
|
||||||
descDevCapExtAttrLPMPos = 1
|
descDeviceCapExtAttrLPMPos = 1
|
||||||
descDevCapExtAttrBESLMsk = 0x04
|
descDeviceCapExtAttrBESLMsk = 0x04
|
||||||
descDevCapExtAttrBESLPos = 2
|
descDeviceCapExtAttrBESLPos = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
// USB CDC constants defined per specification.
|
// USB CDC constants defined per specification.
|
||||||
const (
|
const (
|
||||||
|
|
||||||
// Device class
|
// Device class
|
||||||
descCDCComm = 0x02 // communication/control
|
descCDCTypeComm = 0x02 // communication/control
|
||||||
descCDCData = 0x0A // data
|
descCDCTypeData = 0x0A // data
|
||||||
|
|
||||||
// Communication/control subclass
|
// Communication/control subclass
|
||||||
descCDCSubNone = 0x00
|
descCDCSubNone = 0x00
|
||||||
@@ -146,60 +190,133 @@ const (
|
|||||||
descCDCProtoUnitFunctional = 0xFE
|
descCDCProtoUnitFunctional = 0xFE
|
||||||
|
|
||||||
// Functional descriptor length
|
// Functional descriptor length
|
||||||
descCDCLengthFuncHeader = 5
|
descCDCFuncLengthHeader = 5
|
||||||
descCDCLengthFuncCallManagement = 5
|
descCDCFuncLengthCallManagement = 5
|
||||||
descCDCLengthFuncAbstractControl = 4
|
descCDCFuncLengthAbstractControl = 4
|
||||||
descCDCLengthFuncUnion = 5
|
descCDCFuncLengthUnion = 5
|
||||||
|
|
||||||
// Functional descriptor type
|
// Functional descriptor type
|
||||||
descCDCTypeFuncHeader = 0x00
|
descCDCFuncTypeHeader = 0x00
|
||||||
descCDCTypeFuncCallManagement = 0x01
|
descCDCFuncTypeCallManagement = 0x01
|
||||||
descCDCTypeFuncAbstractControl = 0x02
|
descCDCFuncTypeAbstractControl = 0x02
|
||||||
descCDCTypeFuncDirectLine = 0x03
|
descCDCFuncTypeDirectLine = 0x03
|
||||||
descCDCTypeFuncTelephoneRinger = 0x04
|
descCDCFuncTypeTelephoneRinger = 0x04
|
||||||
descCDCTypeFuncTelephoneReport = 0x05
|
descCDCFuncTypeTelephoneReport = 0x05
|
||||||
descCDCTypeFuncUnion = 0x06
|
descCDCFuncTypeUnion = 0x06
|
||||||
descCDCTypeFuncCountrySelect = 0x07
|
descCDCFuncTypeCountrySelect = 0x07
|
||||||
descCDCTypeFuncTelephoneModes = 0x08
|
descCDCFuncTypeTelephoneModes = 0x08
|
||||||
descCDCTypeFuncTerminal = 0x09
|
descCDCFuncTypeTerminal = 0x09
|
||||||
descCDCTypeFuncNetworkChannel = 0x0A
|
descCDCFuncTypeNetworkChannel = 0x0A
|
||||||
descCDCTypeFuncProtocolUnit = 0x0B
|
descCDCFuncTypeProtocolUnit = 0x0B
|
||||||
descCDCTypeFuncExtensionUnit = 0x0C
|
descCDCFuncTypeExtensionUnit = 0x0C
|
||||||
descCDCTypeFuncMultiChannel = 0x0D
|
descCDCFuncTypeMultiChannel = 0x0D
|
||||||
descCDCTypeFuncCAPIControl = 0x0E
|
descCDCFuncTypeCAPIControl = 0x0E
|
||||||
descCDCTypeFuncEthernetNetworking = 0x0F
|
descCDCFuncTypeEthernetNetworking = 0x0F
|
||||||
descCDCTypeFuncATMNetworking = 0x10
|
descCDCFuncTypeATMNetworking = 0x10
|
||||||
descCDCTypeFuncWirelessControl = 0x11
|
descCDCFuncTypeWirelessControl = 0x11
|
||||||
descCDCTypeFuncMobileDirectLine = 0x12
|
descCDCFuncTypeMobileDirectLine = 0x12
|
||||||
descCDCTypeFuncMDLMDetail = 0x13
|
descCDCFuncTypeMDLMDetail = 0x13
|
||||||
descCDCTypeFuncDeviceManagement = 0x14
|
descCDCFuncTypeDeviceManagement = 0x14
|
||||||
descCDCTypeFuncOBEX = 0x15
|
descCDCFuncTypeOBEX = 0x15
|
||||||
descCDCTypeFuncCommandSet = 0x16
|
descCDCFuncTypeCommandSet = 0x16
|
||||||
descCDCTypeFuncCommandSetDetail = 0x17
|
descCDCFuncTypeCommandSetDetail = 0x17
|
||||||
descCDCTypeFuncTelephoneControl = 0x18
|
descCDCFuncTypeTelephoneControl = 0x18
|
||||||
descCDCTypeFuncOBEXServiceID = 0x19
|
descCDCFuncTypeOBEXServiceID = 0x19
|
||||||
|
|
||||||
|
// Standard request
|
||||||
|
descCDCRequestSendEncapsulatedCommand = 0x00 // CDC request SEND_ENCAPSULATED_COMMAND
|
||||||
|
descCDCRequestGetEncapsulatedResponse = 0x01 // CDC request GET_ENCAPSULATED_RESPONSE
|
||||||
|
descCDCRequestSetCommFeature = 0x02 // CDC request SET_COMM_FEATURE
|
||||||
|
descCDCRequestGetCommFeature = 0x03 // CDC request GET_COMM_FEATURE
|
||||||
|
descCDCRequestClearCommFeature = 0x04 // CDC request CLEAR_COMM_FEATURE
|
||||||
|
descCDCRequestSetAuxLineState = 0x10 // CDC request SET_AUX_LINE_STATE
|
||||||
|
descCDCRequestSetHookState = 0x11 // CDC request SET_HOOK_STATE
|
||||||
|
descCDCRequestPulseSetup = 0x12 // CDC request PULSE_SETUP
|
||||||
|
descCDCRequestSendPulse = 0x13 // CDC request SEND_PULSE
|
||||||
|
descCDCRequestSetPulseTime = 0x14 // CDC request SET_PULSE_TIME
|
||||||
|
descCDCRequestRingAuxJack = 0x15 // CDC request RING_AUX_JACK
|
||||||
|
descCDCRequestSetLineCoding = 0x20 // CDC request SET_LINE_CODING
|
||||||
|
descCDCRequestGetLineCoding = 0x21 // CDC request GET_LINE_CODING
|
||||||
|
descCDCRequestSetControlLineState = 0x22 // CDC request SET_CONTROL_LINE_STATE
|
||||||
|
descCDCRequestSendBreak = 0x23 // CDC request SEND_BREAK
|
||||||
|
descCDCRequestSetRingerParams = 0x30 // CDC request SET_RINGER_PARAMS
|
||||||
|
descCDCRequestGetRingerParams = 0x31 // CDC request GET_RINGER_PARAMS
|
||||||
|
descCDCRequestSetOperationParam = 0x32 // CDC request SET_OPERATION_PARAM
|
||||||
|
descCDCRequestGetOperationParam = 0x33 // CDC request GET_OPERATION_PARAM
|
||||||
|
descCDCRequestSetLineParams = 0x34 // CDC request SET_LINE_PARAMS
|
||||||
|
descCDCRequestGetLineParams = 0x35 // CDC request GET_LINE_PARAMS
|
||||||
|
descCDCRequestDialDigits = 0x36 // CDC request DIAL_DIGITS
|
||||||
|
descCDCRequestSetUnitParameter = 0x37 // CDC request SET_UNIT_PARAMETER
|
||||||
|
descCDCRequestGetUnitParameter = 0x38 // CDC request GET_UNIT_PARAMETER
|
||||||
|
descCDCRequestClearUnitParameter = 0x39 // CDC request CLEAR_UNIT_PARAMETER
|
||||||
|
descCDCRequestSetEthernetMulticastFilters = 0x40 // CDC request SET_ETHERNET_MULTICAST_FILTERS
|
||||||
|
descCDCRequestSetEthernetPowPatternFilter = 0x41 // CDC request SET_ETHERNET_POW_PATTER_FILTER
|
||||||
|
descCDCRequestGetEthernetPowPatternFilter = 0x42 // CDC request GET_ETHERNET_POW_PATTER_FILTER
|
||||||
|
descCDCRequestSetEthernetPacketFilter = 0x43 // CDC request SET_ETHERNET_PACKET_FILTER
|
||||||
|
descCDCRequestGetEthernetStatistic = 0x44 // CDC request GET_ETHERNET_STATISTIC
|
||||||
|
descCDCRequestSetATMDataFormat = 0x50 // CDC request SET_ATM_DATA_FORMAT
|
||||||
|
descCDCRequestGetATMDeviceStatistics = 0x51 // CDC request GET_ATM_DEVICE_STATISTICS
|
||||||
|
descCDCRequestSetATMDefaultVC = 0x52 // CDC request SET_ATM_DEFAULT_VC
|
||||||
|
descCDCRequestGetATMVCStatistics = 0x53 // CDC request GET_ATM_VC_STATISTICS
|
||||||
|
descCDCRequestMDLMSpecificRequestsMask = 0x7F // CDC request MDLM_SPECIFIC_REQUESTS_MASK
|
||||||
|
|
||||||
|
// Notification type
|
||||||
|
descCDCNotifyNetworkConnection = 0x00 // CDC notify NETWORK_CONNECTION
|
||||||
|
descCDCNotifyResponseAvail = 0x01 // CDC notify RESPONSE_AVAIL
|
||||||
|
descCDCNotifyAuxJackHookState = 0x08 // CDC notify AUX_JACK_HOOK_STATE
|
||||||
|
descCDCNotifyRingDetect = 0x09 // CDC notify RING_DETECT
|
||||||
|
descCDCNotifySerialState = 0x20 // CDC notify SERIAL_STATE
|
||||||
|
descCDCNotifyCallStateChange = 0x28 // CDC notify CALL_STATE_CHANGE
|
||||||
|
descCDCNotifyLineStateChange = 0x29 // CDC notify LINE_STATE_CHANGE
|
||||||
|
descCDCNotifyConnectionSpeedChange = 0x2A // CDC notify CONNECTION_SPEED_CHANGE
|
||||||
|
|
||||||
|
// Feature select
|
||||||
|
descCDCFeatureAbstractState = 0x01 // CDC feature select ABSTRACT_STATE
|
||||||
|
descCDCFeatureCountrySetting = 0x02 // CDC feature select COUNTRY_SETTING
|
||||||
|
|
||||||
|
// Control signal
|
||||||
|
descCDCControlSigBitmapCarrierActivation = 0x02 // CDC control signal CARRIER_ACTIVATION
|
||||||
|
descCDCControlSigBitmapDTEPresence = 0x01 // CDC control signal DTE_PRESENCE
|
||||||
|
|
||||||
|
// UART emulated state
|
||||||
|
descCDCUARTStateRxCarrier = 0x01 // UART state RX_CARRIER
|
||||||
|
descCDCUARTStateTxCarrier = 0x02 // UART state TX_CARRIER
|
||||||
|
descCDCUARTStateBreak = 0x04 // UART state BREAK
|
||||||
|
descCDCUARTStateRingSignal = 0x08 // UART state RING_SIGNAL
|
||||||
|
descCDCUARTStateFraming = 0x10 // UART state FRAMING
|
||||||
|
descCDCUARTStateParity = 0x20 // UART state PARITY
|
||||||
|
descCDCUARTStateOverrun = 0x40 // UART state OVERRUN
|
||||||
)
|
)
|
||||||
|
|
||||||
// Common configuration constants for the USB CDC-ACM (single) device class.
|
// Common configuration constants for the USB CDC-ACM (single) device class.
|
||||||
const (
|
const (
|
||||||
// Interfaces for the first CDC-ACM device (index 1).
|
// String descriptor languages
|
||||||
descCDCACM0InterfaceCount = 2
|
descCDCACMLanguageCount = 1
|
||||||
descCDCACM0InterfaceCtrl = 0
|
// Interfaces for all CDC-ACM configurations.
|
||||||
descCDCACM0InterfaceData = 1
|
descCDCACMInterfaceCount = 2
|
||||||
// Endpoints for the first CDC-ACM device (index 1).
|
descCDCACMInterfaceCtrl = 0
|
||||||
descCDCACM0EndpointCount = 4
|
descCDCACMInterfaceData = 1
|
||||||
descCDCACM0EndpointStatus = 2 // Communication/control interrupt input
|
// Endpoints for all CDC-ACM configurations.
|
||||||
descCDCACM0EndpointDataRx = 3 // Bulk data output
|
descCDCACMEndpointCount = 4
|
||||||
descCDCACM0EndpointDataTx = 4 // Bulk data input
|
descCDCACMEndpointStatus = 2 // Communication/control interrupt input
|
||||||
|
descCDCACMEndpointDataRx = 3 // Bulk data output
|
||||||
|
descCDCACMEndpointDataTx = 4 // Bulk data input
|
||||||
|
// Endpoint configuration attributes for all CDC-ACM configurations.
|
||||||
|
descCDCACMConfigAttrStatus = (descCDCACMConfigAttrUnused << descCDCACMConfigAttrRxPos) |
|
||||||
|
(descCDCACMConfigAttrInterrupt << descCDCACMConfigAttrTxPos)
|
||||||
|
descCDCACMConfigAttrDataRx = (descCDCACMConfigAttrBulk << descCDCACMConfigAttrRxPos) |
|
||||||
|
(descCDCACMConfigAttrUnused << descCDCACMConfigAttrTxPos)
|
||||||
|
descCDCACMConfigAttrDataTx = (descCDCACMConfigAttrUnused << descCDCACMConfigAttrRxPos) |
|
||||||
|
(descCDCACMConfigAttrBulk << descCDCACMConfigAttrTxPos)
|
||||||
|
|
||||||
// Size of all CDC-ACM configuration descriptors.
|
// Size of all CDC-ACM configuration descriptors.
|
||||||
descCDCACMConfigSize = uint16(
|
descCDCACMConfigSize = uint16(
|
||||||
descLengthConfigure + // configuration
|
descLengthConfigure + // configuration
|
||||||
descLengthInterface + // communication/control interface
|
descLengthInterface + // communication/control interface
|
||||||
descCDCLengthFuncHeader + // CDC header
|
descCDCFuncLengthHeader + // CDC header
|
||||||
descCDCLengthFuncCallManagement + // CDC call management
|
descCDCFuncLengthCallManagement + // CDC call management
|
||||||
descCDCLengthFuncAbstractControl + // CDC abstract control
|
descCDCFuncLengthAbstractControl + // CDC abstract control
|
||||||
descCDCLengthFuncUnion + // CDC union
|
descCDCFuncLengthUnion + // CDC union
|
||||||
descLengthEndpoint + // communication/control input endpoint
|
descLengthEndpoint + // communication/control input endpoint
|
||||||
descLengthInterface + // data interface
|
descLengthInterface + // data interface
|
||||||
descLengthEndpoint + // data input endpoint
|
descLengthEndpoint + // data input endpoint
|
||||||
@@ -209,126 +326,200 @@ const (
|
|||||||
(1 << descConfigAttrSelfPoweredPos) | // Bit 6: self-powered
|
(1 << descConfigAttrSelfPoweredPos) | // Bit 6: self-powered
|
||||||
(0 << descConfigAttrRemoteWakeupPos) | // Bit 5: remote wakeup
|
(0 << descConfigAttrRemoteWakeupPos) | // Bit 5: remote wakeup
|
||||||
0 // Bits 0-4: reserved (0)
|
0 // Bits 0-4: reserved (0)
|
||||||
|
|
||||||
|
descCDCACMConfigAttrRxPos = 0
|
||||||
|
descCDCACMConfigAttrTxPos = 16
|
||||||
|
descCDCACMConfigAttrUnused = 0x02 // TBD: what is this?
|
||||||
|
descCDCACMConfigAttrIsochronous = descCDCACMConfigAttr | descEndptAttrSyncTypeAsync
|
||||||
|
descCDCACMConfigAttrBulk = descCDCACMConfigAttr | descEndptAttrSyncTypeAdaptive
|
||||||
|
descCDCACMConfigAttrInterrupt = descCDCACMConfigAttr | descEndptAttrSyncTypeSync
|
||||||
)
|
)
|
||||||
|
|
||||||
// Common descriptors for the USB CDC-ACM (single) device class.
|
// descCDCACM0String holds the default string descriptors for CDC-ACM[0], i.e.,
|
||||||
var (
|
// configuration index 1.
|
||||||
// descDeviceCDCACM holds the default device descriptors for CDC-ACM devices.
|
var descCDCACM0String = [descCDCACMLanguageCount]descLocalStrings{
|
||||||
descDeviceCDCACM = [descCDCACMConfigCount][descLengthDevice]uint8{
|
{
|
||||||
{
|
language: descLanguageEnglish,
|
||||||
descLengthDevice, // Size of this descriptor in bytes
|
index: descIndexStrings{
|
||||||
descTypeDevice, // DEVICE Descriptor Type
|
{ // 0: language string
|
||||||
lsU8(descUSBSpecVersion), // USB Specification Release Number in BCD (low)
|
4,
|
||||||
msU8(descUSBSpecVersion), // USB Specification Release Number in BCD (high)
|
descTypeString,
|
||||||
descCDCComm, // Class code (assigned by the USB-IF).
|
lsU8(descLanguageEnglish),
|
||||||
descCDCSubNone, // Subclass code (assigned by the USB-IF).
|
msU8(descLanguageEnglish),
|
||||||
descCDCProtoNone, // Protocol code (assigned by the USB-IF).
|
},
|
||||||
descEndptMaxPktSizeMaximum, // Maximum packet size for endpoint zero (8, 16, 32, or 64)
|
{ // 1: manufacturer
|
||||||
lsU8(descVendorID), // Vendor ID (low) (assigned by the USB-IF)
|
uint8(2 + 2*len(descManufacturer)),
|
||||||
msU8(descVendorID), // Vendor ID (high) (assigned by the USB-IF)
|
descTypeString,
|
||||||
lsU8(descProductID), // Product ID (low) (assigned by the manufacturer)
|
},
|
||||||
msU8(descProductID), // Product ID (high) (assigned by the manufacturer)
|
{ // 2: product
|
||||||
lsU8(descReleaseID), // Device release number in BCD (low)
|
uint8(2 + 2*len(descProduct)),
|
||||||
msU8(descReleaseID), // Device release number in BCD (high)
|
descTypeString,
|
||||||
1, // Index of string descriptor describing manufacturer
|
},
|
||||||
2, // Index of string descriptor describing product
|
{ // 3: serial number
|
||||||
0, // Index of string descriptor describing the device's serial number
|
uint8(2 + 2*len(descSerialNumber)),
|
||||||
descCDCACMConfigCount, // Number of possible configurations
|
descTypeString,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// descCDCACM0Device holds the default device descriptor for CDC-ACM[0], i.e.,
|
||||||
|
// configuration index 1.
|
||||||
|
var descCDCACM0Device = [descLengthDevice]uint8{
|
||||||
|
descLengthDevice, // Size of this descriptor in bytes
|
||||||
|
descTypeDevice, // Descriptor Type
|
||||||
|
lsU8(descUSBSpecVersion), // USB Specification Release Number in BCD (low)
|
||||||
|
msU8(descUSBSpecVersion), // USB Specification Release Number in BCD (high)
|
||||||
|
descCDCTypeComm, // Class code (assigned by the USB-IF).
|
||||||
|
descCDCSubNone, // Subclass code (assigned by the USB-IF).
|
||||||
|
descCDCProtoNone, // Protocol code (assigned by the USB-IF).
|
||||||
|
descEndptMaxPktSize, // Maximum packet size for endpoint zero (8, 16, 32, or 64)
|
||||||
|
lsU8(descVendorID), // Vendor ID (low) (assigned by the USB-IF)
|
||||||
|
msU8(descVendorID), // Vendor ID (high) (assigned by the USB-IF)
|
||||||
|
lsU8(descProductID), // Product ID (low) (assigned by the manufacturer)
|
||||||
|
msU8(descProductID), // Product ID (high) (assigned by the manufacturer)
|
||||||
|
lsU8(descReleaseID), // Device release number in BCD (low)
|
||||||
|
msU8(descReleaseID), // Device release number in BCD (high)
|
||||||
|
1, // Index of string descriptor describing manufacturer
|
||||||
|
2, // Index of string descriptor describing product
|
||||||
|
3, // Index of string descriptor describing the device's serial number
|
||||||
|
descCDCACMCount, // Number of possible configurations
|
||||||
|
}
|
||||||
|
|
||||||
|
// descCDCACM0Qualif holds the default device qualification descriptor for
|
||||||
|
// CDC-ACM[0], i.e., configuration index 1.
|
||||||
|
var descCDCACM0Qualif = [descLengthQualification]uint8{
|
||||||
|
descLengthQualification, // Size of this descriptor in bytes
|
||||||
|
descTypeQualification, // Descriptor Type
|
||||||
|
lsU8(descUSBSpecVersion), // USB Specification Release Number in BCD (low)
|
||||||
|
msU8(descUSBSpecVersion), // USB Specification Release Number in BCD (high)
|
||||||
|
descCDCTypeComm, // Class code (assigned by the USB-IF).
|
||||||
|
descCDCSubNone, // Subclass code (assigned by the USB-IF).
|
||||||
|
descCDCProtoNone, // Protocol code (assigned by the USB-IF).
|
||||||
|
descEndptMaxPktSize, // Maximum packet size for endpoint zero (8, 16, 32, or 64)
|
||||||
|
descCDCACMCount, // Number of possible configurations
|
||||||
|
0, // Reserved
|
||||||
|
}
|
||||||
|
|
||||||
|
// descCDCACM0Config holds the default configuration descriptors for CDC-ACM[0],
|
||||||
|
// i.e., configuration index 1.
|
||||||
|
var descCDCACM0Config = [descCDCACMConfigSize]uint8{
|
||||||
|
descLengthConfigure, // Size of this descriptor in bytes
|
||||||
|
descTypeConfigure, // Descriptor Type
|
||||||
|
lsU8(descCDCACMConfigSize), // Total length of data returned for this configuration (low)
|
||||||
|
msU8(descCDCACMConfigSize), // Total length of data returned for this configuration (high)
|
||||||
|
descCDCACMInterfaceCount, // Number of interfaces supported by this configuration
|
||||||
|
1, // Value to use to select this configuration (1 = CDC-ACM[0])
|
||||||
|
0, // Index of string descriptor describing this configuration
|
||||||
|
descCDCACMConfigAttr, // Configuration attributes
|
||||||
|
descCDCACMMaxPower, // Max power consumption when fully-operational (2 mA units)
|
||||||
|
|
||||||
|
// Communication/Control Interface Descriptor
|
||||||
|
descLengthInterface, // Descriptor length
|
||||||
|
descTypeInterface, // Descriptor type
|
||||||
|
descCDCACMInterfaceCtrl, // Interface index
|
||||||
|
0, // Alternate setting
|
||||||
|
1, // Number of endpoints
|
||||||
|
descCDCTypeComm, // Class code
|
||||||
|
descCDCSubAbstractControl, // Subclass code
|
||||||
|
descCDCProtoNone, // Protocol code (NOTE: Teensyduino defines this as 1 [AT V.250])
|
||||||
|
0, // Interface Description String Index
|
||||||
|
|
||||||
|
// CDC Header Functional Descriptor
|
||||||
|
descCDCFuncLengthHeader, // Size of this descriptor in bytes
|
||||||
|
descTypeCDCInterface, // Descriptor Type
|
||||||
|
descCDCFuncTypeHeader, // Descriptor Subtype
|
||||||
|
0x10, // USB CDC specification version 1.10 (low)
|
||||||
|
0x01, // USB CDC specification version 1.10 (high)
|
||||||
|
|
||||||
|
// CDC Call Management Functional Descriptor
|
||||||
|
descCDCFuncLengthCallManagement, // Size of this descriptor in bytes
|
||||||
|
descTypeCDCInterface, // Descriptor Type
|
||||||
|
descCDCFuncTypeCallManagement, // Descriptor Subtype
|
||||||
|
0x01, // Capabilities
|
||||||
|
descCDCACMInterfaceData, // Data Interface
|
||||||
|
|
||||||
|
// CDC Abstract Control Management Functional Descriptor
|
||||||
|
descCDCFuncLengthAbstractControl, // Size of this descriptor in bytes
|
||||||
|
descTypeCDCInterface, // Descriptor Type
|
||||||
|
descCDCFuncTypeAbstractControl, // Descriptor Subtype
|
||||||
|
0x06, // Capabilities
|
||||||
|
|
||||||
|
// CDC Union Functional Descriptor
|
||||||
|
descCDCFuncLengthUnion, // Size of this descriptor in bytes
|
||||||
|
descTypeCDCInterface, // Descriptor Type
|
||||||
|
descCDCFuncTypeUnion, // Descriptor Subtype
|
||||||
|
descCDCACMInterfaceCtrl, // Controlling interface index
|
||||||
|
descCDCACMInterfaceData, // Controlled interface index
|
||||||
|
|
||||||
|
// Communication/Control Notification Endpoint descriptor
|
||||||
|
descLengthEndpoint, // Size of this descriptor in bytes
|
||||||
|
descTypeEndpoint, // Descriptor Type
|
||||||
|
descCDCACMEndpointStatus | // Endpoint address
|
||||||
|
descEndptAddrDirectionIn,
|
||||||
|
descEndptTypeInterrupt, // Attributes
|
||||||
|
lsU8(descCDCACMStatusPacketSize), // Max packet size (low)
|
||||||
|
msU8(descCDCACMStatusPacketSize), // Max packet size (high)
|
||||||
|
16, // Polling Interval
|
||||||
|
|
||||||
|
// Data Interface Descriptor
|
||||||
|
descLengthInterface, // Interface length
|
||||||
|
descTypeInterface, // Interface type
|
||||||
|
descCDCACMInterfaceData, // Interface index
|
||||||
|
0, // Alternate setting
|
||||||
|
2, // Number of endpoints
|
||||||
|
descCDCTypeData, // Class code
|
||||||
|
descCDCSubNone, // Subclass code
|
||||||
|
descCDCProtoNone, // Protocol code
|
||||||
|
0, // Interface Description String Index
|
||||||
|
|
||||||
|
// Data Bulk Rx Endpoint descriptor
|
||||||
|
descLengthEndpoint, // Size of this descriptor in bytes
|
||||||
|
descTypeEndpoint, // Descriptor Type
|
||||||
|
descCDCACMEndpointDataRx | // Endpoint address
|
||||||
|
descEndptAddrDirectionOut,
|
||||||
|
descEndptTypeBulk, // Attributes
|
||||||
|
lsU8(descCDCACMDataRxPacketSize), // Max packet size (low)
|
||||||
|
msU8(descCDCACMDataRxPacketSize), // Max packet size (high)
|
||||||
|
0, // Polling Interval
|
||||||
|
|
||||||
|
// Data Bulk Tx Endpoint descriptor
|
||||||
|
descLengthEndpoint, // Size of this descriptor in bytes
|
||||||
|
descTypeEndpoint, // Descriptor Type
|
||||||
|
descCDCACMEndpointDataTx | // Endpoint address
|
||||||
|
descEndptAddrDirectionIn,
|
||||||
|
descEndptTypeBulk, // Attributes
|
||||||
|
lsU8(descCDCACMDataTxPacketSize), // Max packet size (low)
|
||||||
|
msU8(descCDCACMDataTxPacketSize), // Max packet size (high)
|
||||||
|
0, // Polling Interval
|
||||||
|
}
|
||||||
|
|
||||||
|
// descCDCACMCodingSize defines the length of a CDC-ACM UART line coding buffer.
|
||||||
|
const descCDCACMCodingSize = 7
|
||||||
|
|
||||||
|
// descCDCACM0Coding holds the default UART line coding for CDC-ACM[0], i.e.,
|
||||||
|
// configuration index 1.
|
||||||
|
var descCDCACM0Coding [descCDCACMCodingSize]uint8
|
||||||
|
|
||||||
|
type descCDCACMLineCoding struct {
|
||||||
|
baud uint32
|
||||||
|
stopBits uint8
|
||||||
|
parity uint8
|
||||||
|
numBits uint8
|
||||||
|
dtr bool
|
||||||
|
rts bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lc *descCDCACMLineCoding) parse(buffer []uint8) bool {
|
||||||
|
if len(buffer) < descCDCACMCodingSize {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
lc.baud = packU32(buffer)
|
||||||
// descConfigCDCACM holds the default configuration descriptors for CDC-ACM
|
lc.stopBits = buffer[4]
|
||||||
// devices.
|
if 0 == lc.stopBits {
|
||||||
descConfigCDCACM = [descCDCACMConfigCount][descCDCACMConfigSize]uint8{
|
lc.stopBits = 1
|
||||||
{
|
|
||||||
descLengthConfigure, // Size of this descriptor in bytes
|
|
||||||
descTypeConfigure, // Descriptor Type
|
|
||||||
lsU8(descCDCACMConfigSize), // Total length of data returned for this configuration (low)
|
|
||||||
msU8(descCDCACMConfigSize), // Total length of data returned for this configuration (high)
|
|
||||||
descCDCACM0InterfaceCount, // Number of interfaces supported by this configuration
|
|
||||||
1, // Value to use to select this configuration (1 = CDC-ACM[0])
|
|
||||||
0, // Index of string descriptor describing this configuration
|
|
||||||
descCDCACMConfigAttr, // Configuration attributes
|
|
||||||
descCDCACMMaxPower, // Max power consumption when fully-operational (2 mA units)
|
|
||||||
|
|
||||||
// Communication/Control Interface Descriptor
|
|
||||||
descLengthInterface, // Descriptor length
|
|
||||||
descTypeInterface, // Descriptor type
|
|
||||||
descCDCACM0InterfaceCtrl, // Interface index
|
|
||||||
0, // Alternate setting
|
|
||||||
1, // Number of endpoints
|
|
||||||
descCDCComm, // Class code
|
|
||||||
descCDCSubAbstractControl, // Subclass code
|
|
||||||
descCDCProtoNone, // Protocol code (NOTE: Teensyduino defines this as 1 [AT V.250])
|
|
||||||
0, // Interface Description String Index
|
|
||||||
|
|
||||||
// CDC Header Functional Descriptor
|
|
||||||
descCDCLengthFuncHeader, // Size of this descriptor in bytes
|
|
||||||
descTypeCDCInterface, // Descriptor Type
|
|
||||||
descCDCTypeFuncHeader, // Descriptor Subtype
|
|
||||||
0x10, // USB CDC specification version 1.10 (low)
|
|
||||||
0x01, // USB CDC specification version 1.10 (high)
|
|
||||||
|
|
||||||
// CDC Call Management Functional Descriptor
|
|
||||||
descCDCLengthFuncCallManagement, // Size of this descriptor in bytes
|
|
||||||
descTypeCDCInterface, // Descriptor Type
|
|
||||||
descCDCTypeFuncCallManagement, // Descriptor Subtype
|
|
||||||
0x01, // Capabilities
|
|
||||||
descCDCACM0InterfaceData, // Data Interface
|
|
||||||
|
|
||||||
// CDC Abstract Control Management Functional Descriptor
|
|
||||||
descCDCLengthFuncAbstractControl, // Size of this descriptor in bytes
|
|
||||||
descTypeCDCInterface, // Descriptor Type
|
|
||||||
descCDCTypeFuncAbstractControl, // Descriptor Subtype
|
|
||||||
0x06, // Capabilities
|
|
||||||
|
|
||||||
// CDC Union Functional Descriptor
|
|
||||||
descCDCLengthFuncUnion, // Size of this descriptor in bytes
|
|
||||||
descTypeCDCInterface, // Descriptor Type
|
|
||||||
descCDCTypeFuncUnion, // Descriptor Subtype
|
|
||||||
descCDCACM0InterfaceCtrl, // Controlling interface index
|
|
||||||
descCDCACM0InterfaceData, // Controlled interface index
|
|
||||||
|
|
||||||
// Communication/Control Notification Endpoint descriptor
|
|
||||||
descLengthEndpoint, // Size of this descriptor in bytes
|
|
||||||
descTypeEndpoint, // Descriptor Type
|
|
||||||
descCDCACM0EndpointStatus | // Endpoint address
|
|
||||||
descEndptAddrDirectionIn,
|
|
||||||
descEndptTypeInterrupt, // Attributes
|
|
||||||
lsU8(descCDCACMStatusPacketSize), // Max packet size (low)
|
|
||||||
msU8(descCDCACMStatusPacketSize), // Max packet size (high)
|
|
||||||
8, // Polling Interval
|
|
||||||
|
|
||||||
// Data Interface Descriptor
|
|
||||||
descLengthInterface, // Interface length
|
|
||||||
descTypeInterface, // Interface type
|
|
||||||
descCDCACM0InterfaceData, // Interface index
|
|
||||||
0, // Alternate setting
|
|
||||||
2, // Number of endpoints
|
|
||||||
descCDCData, // Class code
|
|
||||||
descCDCSubNone, // Subclass code
|
|
||||||
descCDCProtoNone, // Protocol code
|
|
||||||
0, // Interface Description String Index
|
|
||||||
|
|
||||||
// Data Bulk Rx Endpoint descriptor
|
|
||||||
descLengthEndpoint, // Size of this descriptor in bytes
|
|
||||||
descTypeEndpoint, // Descriptor Type
|
|
||||||
descCDCACM0EndpointDataRx | // Endpoint address
|
|
||||||
descEndptAddrDirectionOut,
|
|
||||||
descEndptTypeBulk, // Attributes
|
|
||||||
lsU8(descCDCACMDataRxPacketSize), // Max packet size (low)
|
|
||||||
msU8(descCDCACMDataRxPacketSize), // Max packet size (high)
|
|
||||||
0, // Polling Interval
|
|
||||||
|
|
||||||
// Data Bulk Tx Endpoint descriptor
|
|
||||||
descLengthEndpoint, // Size of this descriptor in bytes
|
|
||||||
descTypeEndpoint, // Descriptor Type
|
|
||||||
descCDCACM0EndpointDataTx | // Endpoint address
|
|
||||||
descEndptAddrDirectionIn,
|
|
||||||
descEndptTypeBulk, // Attributes
|
|
||||||
lsU8(descCDCACMDataTxPacketSize), // Max packet size (low)
|
|
||||||
msU8(descCDCACMDataTxPacketSize), // Max packet size (high)
|
|
||||||
0, // Polling Interval
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
)
|
lc.parity = buffer[5]
|
||||||
|
lc.numBits = buffer[6]
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// +build mimxrt1062
|
||||||
|
|
||||||
package usb2
|
package usb2
|
||||||
|
|
||||||
// descCPUFrequencyHz defines the target CPU frequency (Hz).
|
// descCPUFrequencyHz defines the target CPU frequency (Hz).
|
||||||
@@ -5,28 +7,183 @@ const descCPUFrequencyHz = 600000000
|
|||||||
|
|
||||||
// General USB device identification constants.
|
// General USB device identification constants.
|
||||||
const (
|
const (
|
||||||
descVendorID = 0xABCD
|
descVendorID = 0x16C0
|
||||||
descProductID = 0x1234
|
descProductID = 0x0483
|
||||||
descReleaseID = 0x0101
|
descReleaseID = 0x0101
|
||||||
|
|
||||||
descVendor = "NXP Semiconductors"
|
descManufacturer = "NXP Semiconductors"
|
||||||
descProduct = "TinyGo USB"
|
descProduct = "TinyGo USB"
|
||||||
|
descSerialNumber = "0000000000"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Constants for USB CDC-ACM device classes.
|
// Constants for USB CDC-ACM device classes.
|
||||||
const (
|
const (
|
||||||
// descCDCACMConfigCount defines the number of USB cores that will be
|
// descCDCACMCount defines the number of USB cores that will be configured as
|
||||||
// configured as CDC-ACM (single) devices.
|
// CDC-ACM (single) devices.
|
||||||
descCDCACMConfigCount = 1
|
descCDCACMCount = 1
|
||||||
|
|
||||||
|
descCDCACMQHCount = 2 * (descCDCACMEndpointCount + 1)
|
||||||
|
descCDCACMRDCount = 2 * descCDCACMEndpointCount
|
||||||
|
descCDCACMTDCount = descCDCACMEndpointCount
|
||||||
|
descCDCACMRxCount = descCDCACMRxSize * descCDCACMRDCount
|
||||||
|
descCDCACMTxCount = descCDCACMTxSize * descCDCACMTDCount
|
||||||
|
descCDCACMCxCount = 8
|
||||||
|
|
||||||
descCDCACMMaxPower = 50 // 100 mA
|
descCDCACMMaxPower = 50 // 100 mA
|
||||||
|
|
||||||
descCDCACMStatusPacketSize = 16
|
descCDCACMStatusPacketSize = 16
|
||||||
descCDCACMDataRxPacketSize = descCDCACMDataRxFSPacketSize // full-speed
|
descCDCACMDataRxPacketSize = descCDCACMDataRxHSPacketSize // high-speed
|
||||||
descCDCACMDataTxPacketSize = descCDCACMDataTxFSPacketSize // full-speed
|
descCDCACMDataTxPacketSize = descCDCACMDataTxHSPacketSize // high-speed
|
||||||
|
descCDCACMRxSize = descCDCACMDataRxPacketSize
|
||||||
|
descCDCACMTxSize = 4 * descCDCACMDataTxPacketSize
|
||||||
|
|
||||||
descCDCACMDataRxFSPacketSize = 64 // full-speed
|
descCDCACMDataRxFSPacketSize = 64 // full-speed
|
||||||
descCDCACMDataTxFSPacketSize = 64 // full-speed
|
descCDCACMDataTxFSPacketSize = 64 // full-speed
|
||||||
descCDCACMDataRxHSPacketSize = 512 // high-speed
|
descCDCACMDataRxHSPacketSize = 512 // high-speed
|
||||||
descCDCACMDataTxHSPacketSize = 512 // high-speed
|
descCDCACMDataTxHSPacketSize = 512 // high-speed
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// descCDCACM0QH is an array of endpoint queue heads, which is where all
|
||||||
|
// transfers for a given endpoint are managed, for the default CDC-ACM (single)
|
||||||
|
// device class configuration (index 1).
|
||||||
|
//
|
||||||
|
// From the iMXRT1062 Reference Manual:
|
||||||
|
//
|
||||||
|
// Software must ensure that no interface data structure reachable
|
||||||
|
// by the Device Controller spans a 4K-page boundary.
|
||||||
|
//
|
||||||
|
// The [queue head] is a 48-byte data structure, but must be aligned on
|
||||||
|
// 64-byte boundaries.
|
||||||
|
//
|
||||||
|
// Endpoint queue heads are arranged in an array in a continuous area of
|
||||||
|
// memory pointed to by the USB.ENDPOINTLISTADDR pointer. The even-numbered
|
||||||
|
// device queue heads in the list support receive endpoints (OUT/SETUP) and
|
||||||
|
// the odd-numbered queue heads in the list are used for transmit endpoints
|
||||||
|
// (IN/INTERRUPT). The device controller will index into this array based upon
|
||||||
|
// the endpoint number received from the USB bus. All information necessary to
|
||||||
|
// respond to transactions for all primed transfers is contained in this list
|
||||||
|
// so the Device Controller can readily respond to incoming requests without
|
||||||
|
// having to traverse a linked list.
|
||||||
|
//go:align 4096
|
||||||
|
var descCDCACM0QH [descCDCACMQHCount]dcdEndpoint
|
||||||
|
|
||||||
|
// descCDCACM0CD is the transfer descriptor for data messages transmitted or
|
||||||
|
// received on the status/control endpoint 0 for the default CDC-ACM (single)
|
||||||
|
// device class configuration (index 1).
|
||||||
|
//go:align 32
|
||||||
|
var descCDCACM0CD dcdTransfer
|
||||||
|
|
||||||
|
// descCDCACM0AD is the transfer descriptor for ackowledgement (ACK) messages
|
||||||
|
// transmitted or received on the status/control endpoint 0 for the default
|
||||||
|
// CDC-ACM (single) device class configuration (index 1).
|
||||||
|
//go:align 32
|
||||||
|
var descCDCACM0AD dcdTransfer
|
||||||
|
|
||||||
|
// descCDCACM0RD is an array of transfer descriptors for Rx (OUT) transfers,
|
||||||
|
// which describe to the device controller the location and quantity of data
|
||||||
|
// being received for a given transfer, for the default CDC-ACM (single) device
|
||||||
|
// class configuration (index 1).
|
||||||
|
//go:align 32
|
||||||
|
var descCDCACM0RD [descCDCACMRDCount]dcdTransfer
|
||||||
|
|
||||||
|
// descCDCACM0TD is an array of transfer descriptors for Tx (IN) transfers,
|
||||||
|
// which describe to the device controller the location and quantity of data
|
||||||
|
// being transmitted for a given transfer, for the default CDC-ACM (single)
|
||||||
|
// device class configuration (index 1).
|
||||||
|
//go:align 32
|
||||||
|
var descCDCACM0TD [descCDCACMTDCount]dcdTransfer
|
||||||
|
|
||||||
|
// descCDCACM0Cx is the buffer for control/status data received on endpoint 0 of
|
||||||
|
// the default CDC-ACM (single) device class configuration (index 1).
|
||||||
|
//go:align 32
|
||||||
|
var descCDCACM0Cx [descCDCACMCxCount]uint8
|
||||||
|
|
||||||
|
// descCDCACM0Rx is the receive (Rx) buffer of data endpoints for the default
|
||||||
|
// CDC-ACM (single) device class configuration (index 1).
|
||||||
|
//go:align 32
|
||||||
|
var descCDCACM0Rx [descCDCACMRxCount]uint8
|
||||||
|
|
||||||
|
// descCDCACM0Tx is the transmit (Tx) buffer of data endpoints for the default
|
||||||
|
// CDC-ACM (single) device class configuration (index 1).
|
||||||
|
//go:align 32
|
||||||
|
var descCDCACM0Tx [descCDCACMTxCount]uint8
|
||||||
|
|
||||||
|
// descCDCACM0Dx is the transmit (Tx) buffer of descriptor data for the default
|
||||||
|
// CDC-ACM (single) device class configuration (index 1).
|
||||||
|
var descCDCACM0Dx [descCDCACMConfigSize]uint8
|
||||||
|
|
||||||
|
var descCDCACM0RDNum [descCDCACMRDCount]uint16
|
||||||
|
var descCDCACM0RDIdx [descCDCACMRDCount]uint16
|
||||||
|
var descCDCACM0RDQue [descCDCACMRDCount + 1]uint16
|
||||||
|
|
||||||
|
type descCDCACMClass struct {
|
||||||
|
locstr *[descCDCACMLanguageCount]descLocalStrings // string descriptors
|
||||||
|
device *[descLengthDevice]uint8 // device descriptor
|
||||||
|
qualif *[descLengthQualification]uint8 // device qualification descriptor
|
||||||
|
config *[descCDCACMConfigSize]uint8 // configuration descriptor
|
||||||
|
|
||||||
|
coding *[descCDCACMCodingSize]uint8 // UART line coding
|
||||||
|
cticks int64
|
||||||
|
rtsdtr uint8
|
||||||
|
|
||||||
|
qh *[descCDCACMQHCount]dcdEndpoint // endpoint queue heads
|
||||||
|
|
||||||
|
cd *dcdTransfer // control endpoint 0 Rx/Tx data transfer descriptor
|
||||||
|
ad *dcdTransfer // control endpoint 0 Rx/Tx ACK transfer descriptor
|
||||||
|
rd *[descCDCACMRDCount]dcdTransfer // bulk data endpoint Rx (OUT) transfer descriptors
|
||||||
|
td *[descCDCACMTDCount]dcdTransfer // bulk data endpoint Tx (IN) transfer descriptors
|
||||||
|
|
||||||
|
cx *[descCDCACMCxCount]uint8 // control endpoint 0 Rx/Tx transfer buffer
|
||||||
|
rx *[descCDCACMRxCount]uint8 // bulk data endpoint Rx (OUT) transfer buffer
|
||||||
|
tx *[descCDCACMTxCount]uint8 // bulk data endpoint Tx (IN) transfer buffer
|
||||||
|
dx *[descCDCACMConfigSize]uint8 // descriptor data Tx (IN) transfer buffer
|
||||||
|
|
||||||
|
cxSize uint16
|
||||||
|
rxSize uint16
|
||||||
|
txSize uint16
|
||||||
|
|
||||||
|
txHead uint8
|
||||||
|
txFree uint16
|
||||||
|
|
||||||
|
rxHead uint8
|
||||||
|
rxTail uint8
|
||||||
|
rxFree uint16
|
||||||
|
|
||||||
|
rxCount *[descCDCACMRDCount]uint16
|
||||||
|
rxIndex *[descCDCACMRDCount]uint16
|
||||||
|
rxQueue *[descCDCACMRDCount + 1]uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// descCDCACM holds the configuration, endpoint, and transfer descriptors, along
|
||||||
|
// with the buffers and control states, for all of the CDC-ACM (single) device
|
||||||
|
// class configurations, ordered by configuration index (offset by -1).
|
||||||
|
var descCDCACM = [descCDCACMCount]descCDCACMClass{
|
||||||
|
{
|
||||||
|
locstr: &descCDCACM0String,
|
||||||
|
device: &descCDCACM0Device,
|
||||||
|
qualif: &descCDCACM0Qualif,
|
||||||
|
config: &descCDCACM0Config,
|
||||||
|
|
||||||
|
coding: &descCDCACM0Coding,
|
||||||
|
|
||||||
|
qh: &descCDCACM0QH,
|
||||||
|
|
||||||
|
cd: &descCDCACM0CD,
|
||||||
|
ad: &descCDCACM0AD,
|
||||||
|
rd: &descCDCACM0RD,
|
||||||
|
td: &descCDCACM0TD,
|
||||||
|
|
||||||
|
cx: &descCDCACM0Cx,
|
||||||
|
rx: &descCDCACM0Rx,
|
||||||
|
tx: &descCDCACM0Tx,
|
||||||
|
dx: &descCDCACM0Dx,
|
||||||
|
|
||||||
|
cxSize: descCDCACMStatusPacketSize,
|
||||||
|
rxSize: descCDCACMDataRxPacketSize,
|
||||||
|
txSize: descCDCACMDataTxPacketSize,
|
||||||
|
|
||||||
|
rxCount: &descCDCACM0RDNum,
|
||||||
|
rxIndex: &descCDCACM0RDIdx,
|
||||||
|
rxQueue: &descCDCACM0RDQue,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package usb2
|
package usb2
|
||||||
|
|
||||||
type dci interface {
|
type hcd interface {
|
||||||
init() status
|
init() status
|
||||||
enable(enable bool) status
|
enable(enable bool) status
|
||||||
critical(enter bool) status
|
critical(enter bool) status
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
package usb2
|
package usb2
|
||||||
|
|
||||||
// Implementation of USB host controller interface (hci) for NXP iMXRT1062.
|
// Implementation of USB host controller driver (hcd) for NXP iMXRT1062.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/arm"
|
"device/arm"
|
||||||
@@ -11,18 +11,19 @@ import (
|
|||||||
"runtime/volatile"
|
"runtime/volatile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// hciCount defines the number of USB cores to configure for host mode. It is
|
// hcdCount defines the number of USB cores to configure for host mode. It is
|
||||||
// computed as the sum of all declared host configuration descriptors.
|
// computed as the sum of all declared host configuration descriptors.
|
||||||
const hciCount = 0
|
const hcdCount = 0
|
||||||
|
|
||||||
// hciInterruptPriority defines the priority for all USB host interrupts.
|
// hcdInterruptPriority defines the priority for all USB host interrupts.
|
||||||
const hciInterruptPriority = 3
|
const hcdInterruptPriority = 3
|
||||||
|
|
||||||
// hostController implements USB host controller interface (hci).
|
// hostController implements USB host controller driver (hcd) interface.
|
||||||
type hostController struct {
|
type hostController struct {
|
||||||
core *core // Parent USB core this instance is attached to
|
core *core // Parent USB core this instance is attached to
|
||||||
port int // USB port index
|
port int // USB port index
|
||||||
id int // hostControllerInstance index
|
class class // USB host class
|
||||||
|
id int // hostControllerInstance index
|
||||||
|
|
||||||
bus *nxp.USB_Type
|
bus *nxp.USB_Type
|
||||||
phy *nxp.USBPHY_Type
|
phy *nxp.USBPHY_Type
|
||||||
@@ -34,14 +35,14 @@ type hostController struct {
|
|||||||
|
|
||||||
// hostControllerInstance provides statically-allocated instances of each USB
|
// hostControllerInstance provides statically-allocated instances of each USB
|
||||||
// host controller configured on this platform.
|
// host controller configured on this platform.
|
||||||
var hostControllerInstance [hciCount]hostController
|
var hostControllerInstance [hcdCount]hostController
|
||||||
|
|
||||||
// initHCI initializes and assigns a free host controller instance to the given
|
// initHCD initializes and assigns a free host controller instance to the given
|
||||||
// USB port. Returns the initialized host controller or nil if no free host
|
// USB port. Returns the initialized host controller or nil if no free host
|
||||||
// controller instances remain.
|
// controller instances remain.
|
||||||
func initHCI(port int) (hci, status) {
|
func initHCD(port int, class class) (hcd, status) {
|
||||||
if 0 == hciCount {
|
if 0 == hcdCount {
|
||||||
return nil, statusInvalidArgument // must have defined host descriptors
|
return nil, statusInvalid // must have defined host controllers
|
||||||
}
|
}
|
||||||
// Return the first instance whose assigned core is currently nil.
|
// Return the first instance whose assigned core is currently nil.
|
||||||
for i := range hostControllerInstance {
|
for i := range hostControllerInstance {
|
||||||
@@ -82,7 +83,7 @@ func (hc *hostController) init() status {
|
|||||||
|
|
||||||
func (hc *hostController) enable(enable bool) status {
|
func (hc *hostController) enable(enable bool) status {
|
||||||
|
|
||||||
hc.irq.SetPriority(hciInterruptPriority)
|
hc.irq.SetPriority(hcdInterruptPriority)
|
||||||
hc.irq.Enable()
|
hc.irq.Enable()
|
||||||
|
|
||||||
return statusOK
|
return statusOK
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package usb2
|
|
||||||
|
|
||||||
type hci interface {
|
|
||||||
init() status
|
|
||||||
enable(enable bool) status
|
|
||||||
critical(enter bool) status
|
|
||||||
interrupt()
|
|
||||||
udelay(micros uint32)
|
|
||||||
}
|
|
||||||
@@ -23,29 +23,13 @@ type (
|
|||||||
|
|
||||||
func (uart *UART) Configure(config UARTConfig) error {
|
func (uart *UART) Configure(config UARTConfig) error {
|
||||||
|
|
||||||
if uart.port >= CoreCount || uart.port >= dciCount ||
|
if uart.port >= CoreCount || uart.port >= dcdCount {
|
||||||
uart.port >= descCDCACMConfigCount {
|
|
||||||
return ErrInvalidPort
|
return ErrInvalidPort
|
||||||
}
|
}
|
||||||
|
|
||||||
// use default configuration index (1-based index; 0=invalid)
|
|
||||||
// uart.config = configDeviceCDCACMConfigurationIndex
|
|
||||||
|
|
||||||
// modify the global basic configuration struct configDeviceCDCACM for our USB
|
|
||||||
// port and configuration index.
|
|
||||||
//
|
|
||||||
// these settings are copied into the real CDC-ACM object, using interface
|
|
||||||
// deviceClassDriver, via initialization method (*deviceCDCACM).init().
|
|
||||||
|
|
||||||
// change baud rate from default, if provided
|
|
||||||
//if config.BaudRate != 0 {
|
|
||||||
// configDeviceCDCACM[uart.port][uart.config-1].lineCodingBaudRate =
|
|
||||||
// config.BaudRate
|
|
||||||
//}
|
|
||||||
|
|
||||||
// verify we have a free USB port and take ownership of it
|
// verify we have a free USB port and take ownership of it
|
||||||
var st status
|
var st status
|
||||||
uart.core, st = initCore(uart.port, modeDevice)
|
uart.core, st = initCore(uart.port, class{id: classDeviceCDCACM, config: 1})
|
||||||
if !st.ok() {
|
if !st.ok() {
|
||||||
return ErrInvalidPort
|
return ErrInvalidPort
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-16
@@ -2,12 +2,20 @@ package usb2
|
|||||||
|
|
||||||
// Hardware abstraction for USB ports configured as either host or device.
|
// Hardware abstraction for USB ports configured as either host or device.
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if unsafe.Sizeof(uintptr(0)) > 4 {
|
||||||
|
panic("USB is only supported on 32-bit systems")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// core represents the core of a USB port configured as either host or device.
|
// core represents the core of a USB port configured as either host or device.
|
||||||
type core struct {
|
type core struct {
|
||||||
port int
|
port int
|
||||||
mode int
|
mode int
|
||||||
dc dci
|
dc dcd
|
||||||
hc hci
|
hc hcd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constant definitions for USB core operating modes.
|
// Constant definitions for USB core operating modes.
|
||||||
@@ -17,9 +25,32 @@ const (
|
|||||||
modeHost = 2
|
modeHost = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// class represents the type of a host/device and its class configuration index.
|
||||||
|
// The first valid configuration index is 1. Index 0 is reserved and invalid.
|
||||||
|
type class struct {
|
||||||
|
id int
|
||||||
|
config int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constant definitions for all host/device classes.
|
||||||
|
const (
|
||||||
|
classDeviceCDCACM = 0 // The only currently-supported class (CDC-ACM)
|
||||||
|
)
|
||||||
|
|
||||||
|
// mode returns the USB core operating mode of the receiver class cl.
|
||||||
|
//go:inline
|
||||||
|
func (cl class) mode() int {
|
||||||
|
switch cl.id {
|
||||||
|
case classDeviceCDCACM:
|
||||||
|
return modeDevice
|
||||||
|
default:
|
||||||
|
return modeIdle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CoreCount defines the total number of USB cores to configure in device or
|
// CoreCount defines the total number of USB cores to configure in device or
|
||||||
// host mode.
|
// host mode.
|
||||||
const CoreCount = dciCount + hciCount
|
const CoreCount = dcdCount + hcdCount
|
||||||
|
|
||||||
// coreInstance provides statically-allocated instances of each USB core
|
// coreInstance provides statically-allocated instances of each USB core
|
||||||
// configured on this platform.
|
// configured on this platform.
|
||||||
@@ -30,30 +61,32 @@ type status uint8
|
|||||||
|
|
||||||
// Constant definitions for all status codes used within the package.
|
// Constant definitions for all status codes used within the package.
|
||||||
const (
|
const (
|
||||||
statusOK status = iota // Success
|
statusOK status = iota // Success
|
||||||
statusBusy // Busy
|
statusBusy // Busy
|
||||||
statusRetry // Retry
|
statusRetry // Retry
|
||||||
statusInvalidArgument // Invalid argument
|
statusInvalid // Invalid argument
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ok returns true if and only if the receiver st equals statusOK.
|
||||||
|
//go:inline
|
||||||
func (st status) ok() bool { return statusOK == st }
|
func (st status) ok() bool { return statusOK == st }
|
||||||
|
|
||||||
// initCore initializes a free USB core with given operating mode on the USB
|
// initCore initializes a free USB core with given operating mode on the USB
|
||||||
// port at given index, if available. Returns a reference to the initialized
|
// port at given index, if available. Returns a reference to the initialized
|
||||||
// core or nil if the core is unavailable.
|
// core or nil if the core is unavailable.
|
||||||
func initCore(port, mode int) (*core, status) {
|
func initCore(port int, class class) (*core, status) {
|
||||||
|
|
||||||
if port < 0 || port >= CoreCount {
|
if port < 0 || port >= CoreCount || 0 == class.config {
|
||||||
return nil, statusInvalidArgument
|
return nil, statusInvalid
|
||||||
}
|
}
|
||||||
if modeIdle != coreInstance[port].mode {
|
if modeIdle != coreInstance[port].mode {
|
||||||
return nil, statusBusy
|
return nil, statusBusy
|
||||||
}
|
}
|
||||||
|
|
||||||
switch mode {
|
switch class.mode() {
|
||||||
case modeDevice:
|
case modeDevice:
|
||||||
// Allocate a free device controller and install interrupts
|
// Allocate a free device controller and install interrupts
|
||||||
dc, st := initDCI(port)
|
dc, st := initDCD(port, class)
|
||||||
if !st.ok() {
|
if !st.ok() {
|
||||||
return nil, st
|
return nil, st
|
||||||
}
|
}
|
||||||
@@ -62,7 +95,7 @@ func initCore(port, mode int) (*core, status) {
|
|||||||
return nil, st
|
return nil, st
|
||||||
}
|
}
|
||||||
coreInstance[port].port = port
|
coreInstance[port].port = port
|
||||||
coreInstance[port].mode = mode
|
coreInstance[port].mode = modeDevice
|
||||||
coreInstance[port].dc = dc
|
coreInstance[port].dc = dc
|
||||||
// Enable interrupts and enter runtime
|
// Enable interrupts and enter runtime
|
||||||
if st = dc.enable(true); !st.ok() {
|
if st = dc.enable(true); !st.ok() {
|
||||||
@@ -73,7 +106,7 @@ func initCore(port, mode int) (*core, status) {
|
|||||||
|
|
||||||
case modeHost:
|
case modeHost:
|
||||||
// Allocate a free host controller and install interrupts
|
// Allocate a free host controller and install interrupts
|
||||||
hc, st := initHCI(port)
|
hc, st := initHCD(port, class)
|
||||||
if !st.ok() {
|
if !st.ok() {
|
||||||
return nil, st
|
return nil, st
|
||||||
}
|
}
|
||||||
@@ -82,7 +115,7 @@ func initCore(port, mode int) (*core, status) {
|
|||||||
return nil, st
|
return nil, st
|
||||||
}
|
}
|
||||||
coreInstance[port].port = port
|
coreInstance[port].port = port
|
||||||
coreInstance[port].mode = mode
|
coreInstance[port].mode = modeHost
|
||||||
coreInstance[port].hc = hc
|
coreInstance[port].hc = hc
|
||||||
// Enable interrupts and enter runtime
|
// Enable interrupts and enter runtime
|
||||||
if st = hc.enable(true); !st.ok() {
|
if st = hc.enable(true); !st.ok() {
|
||||||
@@ -92,7 +125,7 @@ func initCore(port, mode int) (*core, status) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, statusInvalidArgument
|
return nil, statusInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
return &coreInstance[port], statusOK
|
return &coreInstance[port], statusOK
|
||||||
|
|||||||
@@ -192,3 +192,25 @@ func lsU8(u uint16) uint8 { return uint8(u) }
|
|||||||
func cycles(microsec, cpuFreqHz uint32) uint32 {
|
func cycles(microsec, cpuFreqHz uint32) uint32 {
|
||||||
return uint32((uint64(microsec) * uint64(cpuFreqHz)) / 1000000)
|
return uint32((uint64(microsec) * uint64(cpuFreqHz)) / 1000000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func unpackEndpoint(address uint8) (number, direction uint8) {
|
||||||
|
return (address & descEndptAddrNumberMsk) >> descEndptAddrNumberPos,
|
||||||
|
(address & descEndptAddrDirectionMsk) >> descEndptAddrDirectionPos
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func rxEndpoint(number uint8) uint8 {
|
||||||
|
return (number & descEndptAddrNumberMsk) | descEndptAddrDirectionOut
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func txEndpoint(number uint8) uint8 {
|
||||||
|
return (number & descEndptAddrNumberMsk) | descEndptAddrDirectionIn
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:inline
|
||||||
|
func endpointIndex(address uint8) uint8 {
|
||||||
|
return ((address & descEndptAddrNumberMsk) << 1) |
|
||||||
|
((address & descEndptAddrDirectionMsk) >> descEndptAddrDirectionPos)
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// +build arm
|
||||||
|
|
||||||
|
package usb2
|
||||||
|
|
||||||
|
import "device/arm"
|
||||||
|
|
||||||
|
// udelay waits for the given number of microseconds before returning.
|
||||||
|
// We cannot use the sleep timer from this context (import cycle), but we need
|
||||||
|
// an approximate method to spin CPU cycles for short periods of time.
|
||||||
|
//go:inline
|
||||||
|
func udelay(microsec uint32) {
|
||||||
|
n := cycles(microsec, descCPUFrequencyHz)
|
||||||
|
for i := uint32(0); i < n; i++ {
|
||||||
|
arm.Asm(`nop`)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user