mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 11:07:46 +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
|
||||
|
||||
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.
|
||||
const (
|
||||
|
||||
// Descriptor length
|
||||
descLengthDevice = 18
|
||||
descLengthConfigure = 9
|
||||
descLengthInterface = 9
|
||||
descLengthEndpoint = 7
|
||||
descLengthDeviceQualitier = 10
|
||||
descLengthOTG = 5
|
||||
descLengthBOS = 5
|
||||
descLengthEndpointCompanion = 6
|
||||
descLengthDevCapTypeUSB20Extension = 7
|
||||
descLengthDevCapTypeSuperspeed = 10
|
||||
descLengthDevice = 18
|
||||
descLengthConfigure = 9
|
||||
descLengthInterface = 9
|
||||
descLengthEndpoint = 7
|
||||
descLengthQualification = 10
|
||||
descLengthOTG = 5
|
||||
descLengthBOS = 5
|
||||
descLengthEndpointCompanion = 6
|
||||
descLengthUSB20Extension = 7
|
||||
descLengthSuperspeed = 10
|
||||
|
||||
// Descriptor type
|
||||
descTypeDevice = 0x01
|
||||
@@ -23,7 +31,7 @@ const (
|
||||
descTypeString = 0x03
|
||||
descTypeInterface = 0x04
|
||||
descTypeEndpoint = 0x05
|
||||
descTypeDeviceQualitier = 0x06
|
||||
descTypeQualification = 0x06
|
||||
descTypeOtherSpeedConfiguration = 0x07
|
||||
descTypeInterfacePower = 0x08
|
||||
descTypeOTG = 0x09
|
||||
@@ -37,6 +45,36 @@ const (
|
||||
descTypeCDCEndpoint = 0x25
|
||||
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
|
||||
descConfigAttrD7Msk = 0x80
|
||||
descConfigAttrD7Pos = 7
|
||||
@@ -60,49 +98,55 @@ const (
|
||||
descEndptAddrDirectionIn = 0x80
|
||||
|
||||
// Endpoint attributes
|
||||
descEndptAttrTypeMsk = 0x03
|
||||
descEndptAttrNumberPos = 0
|
||||
descEndptAttrSyncTypeMsk = 0x0C
|
||||
descEndptAttrSyncTypePos = 2
|
||||
descEndptAttrSyncTypeNoSync = 0x00
|
||||
descEndptAttrSyncTypeAsync = 0x04
|
||||
descEndptAttrSyncTypeAdaptive = 0x08
|
||||
descEndptAttrSyncTypeSync = 0x0C
|
||||
descEndptAttrUsageTypeMsk = 0x30
|
||||
descEndptAttrUsageTypePos = 4
|
||||
descEndptAttrUsageTypeDataEndpoint = 0x00
|
||||
descEndptAttrUsageTypeFeedEndpoint = 0x10
|
||||
descEndptAttrUsageTypeFeedDataEndpoint = 0x20
|
||||
descEndptAttrTypeMsk = 0x03
|
||||
descEndptAttrNumberPos = 0
|
||||
descEndptAttrSyncTypeMsk = 0x0C
|
||||
descEndptAttrSyncTypePos = 2
|
||||
descEndptAttrSyncTypeNoSync = 0x00
|
||||
descEndptAttrSyncTypeAsync = 0x04
|
||||
descEndptAttrSyncTypeAdaptive = 0x08
|
||||
descEndptAttrSyncTypeSync = 0x0C
|
||||
descEndptAttrUsageTypeMsk = 0x30
|
||||
descEndptAttrUsageTypePos = 4
|
||||
descEndptAttrUsageTypeData = 0x00
|
||||
descEndptAttrUsageTypeFeed = 0x10
|
||||
descEndptAttrUsageTypeFeedData = 0x20
|
||||
|
||||
// Endpoint max packet size
|
||||
descEndptMaxPktSizeSizeMsk = 0x07FF
|
||||
descEndptMaxPktSizeMultTransMsk = 0x1800
|
||||
descEndptMaxPktSizeMultTransPos = 11
|
||||
descEndptMaxPktSizeMaximum = 64
|
||||
descEndptMaxPktSizeMsk = 0x07FF
|
||||
descEndptMaxPktSize = 64
|
||||
descEndptMaxPktSizeMultMsk = 0x1800
|
||||
descEndptMaxPktSizeMultPos = 11
|
||||
|
||||
// OTG attributes
|
||||
descOTGAttrSRPMsk = 0x01
|
||||
descOTGAttrHNPMsk = 0x02
|
||||
descOTGAttrADPMsk = 0x04
|
||||
|
||||
// Device bus speed
|
||||
descDeviceSpeedFull = 0x00
|
||||
descDeviceSpeedLow = 0x01
|
||||
descDeviceSpeedHigh = 0x02
|
||||
descDeviceSpeedSuper = 0x04
|
||||
|
||||
// Device capability type
|
||||
descDevCapTypeWireless = 0x01
|
||||
descDevCapTypeUSB20Extension = 0x02
|
||||
descDevCapTypeSuperspeed = 0x03
|
||||
descDeviceCapTypeWireless = 0x01
|
||||
descDeviceCapTypeUSB20Extension = 0x02
|
||||
descDeviceCapTypeSuperspeed = 0x03
|
||||
|
||||
// Device capability attributes (USB 2.0 extension)
|
||||
descDevCapExtAttrLPMMsk = 0x02
|
||||
descDevCapExtAttrLPMPos = 1
|
||||
descDevCapExtAttrBESLMsk = 0x04
|
||||
descDevCapExtAttrBESLPos = 2
|
||||
descDeviceCapExtAttrLPMMsk = 0x02
|
||||
descDeviceCapExtAttrLPMPos = 1
|
||||
descDeviceCapExtAttrBESLMsk = 0x04
|
||||
descDeviceCapExtAttrBESLPos = 2
|
||||
)
|
||||
|
||||
// USB CDC constants defined per specification.
|
||||
const (
|
||||
|
||||
// Device class
|
||||
descCDCComm = 0x02 // communication/control
|
||||
descCDCData = 0x0A // data
|
||||
descCDCTypeComm = 0x02 // communication/control
|
||||
descCDCTypeData = 0x0A // data
|
||||
|
||||
// Communication/control subclass
|
||||
descCDCSubNone = 0x00
|
||||
@@ -146,60 +190,133 @@ const (
|
||||
descCDCProtoUnitFunctional = 0xFE
|
||||
|
||||
// Functional descriptor length
|
||||
descCDCLengthFuncHeader = 5
|
||||
descCDCLengthFuncCallManagement = 5
|
||||
descCDCLengthFuncAbstractControl = 4
|
||||
descCDCLengthFuncUnion = 5
|
||||
descCDCFuncLengthHeader = 5
|
||||
descCDCFuncLengthCallManagement = 5
|
||||
descCDCFuncLengthAbstractControl = 4
|
||||
descCDCFuncLengthUnion = 5
|
||||
|
||||
// Functional descriptor type
|
||||
descCDCTypeFuncHeader = 0x00
|
||||
descCDCTypeFuncCallManagement = 0x01
|
||||
descCDCTypeFuncAbstractControl = 0x02
|
||||
descCDCTypeFuncDirectLine = 0x03
|
||||
descCDCTypeFuncTelephoneRinger = 0x04
|
||||
descCDCTypeFuncTelephoneReport = 0x05
|
||||
descCDCTypeFuncUnion = 0x06
|
||||
descCDCTypeFuncCountrySelect = 0x07
|
||||
descCDCTypeFuncTelephoneModes = 0x08
|
||||
descCDCTypeFuncTerminal = 0x09
|
||||
descCDCTypeFuncNetworkChannel = 0x0A
|
||||
descCDCTypeFuncProtocolUnit = 0x0B
|
||||
descCDCTypeFuncExtensionUnit = 0x0C
|
||||
descCDCTypeFuncMultiChannel = 0x0D
|
||||
descCDCTypeFuncCAPIControl = 0x0E
|
||||
descCDCTypeFuncEthernetNetworking = 0x0F
|
||||
descCDCTypeFuncATMNetworking = 0x10
|
||||
descCDCTypeFuncWirelessControl = 0x11
|
||||
descCDCTypeFuncMobileDirectLine = 0x12
|
||||
descCDCTypeFuncMDLMDetail = 0x13
|
||||
descCDCTypeFuncDeviceManagement = 0x14
|
||||
descCDCTypeFuncOBEX = 0x15
|
||||
descCDCTypeFuncCommandSet = 0x16
|
||||
descCDCTypeFuncCommandSetDetail = 0x17
|
||||
descCDCTypeFuncTelephoneControl = 0x18
|
||||
descCDCTypeFuncOBEXServiceID = 0x19
|
||||
descCDCFuncTypeHeader = 0x00
|
||||
descCDCFuncTypeCallManagement = 0x01
|
||||
descCDCFuncTypeAbstractControl = 0x02
|
||||
descCDCFuncTypeDirectLine = 0x03
|
||||
descCDCFuncTypeTelephoneRinger = 0x04
|
||||
descCDCFuncTypeTelephoneReport = 0x05
|
||||
descCDCFuncTypeUnion = 0x06
|
||||
descCDCFuncTypeCountrySelect = 0x07
|
||||
descCDCFuncTypeTelephoneModes = 0x08
|
||||
descCDCFuncTypeTerminal = 0x09
|
||||
descCDCFuncTypeNetworkChannel = 0x0A
|
||||
descCDCFuncTypeProtocolUnit = 0x0B
|
||||
descCDCFuncTypeExtensionUnit = 0x0C
|
||||
descCDCFuncTypeMultiChannel = 0x0D
|
||||
descCDCFuncTypeCAPIControl = 0x0E
|
||||
descCDCFuncTypeEthernetNetworking = 0x0F
|
||||
descCDCFuncTypeATMNetworking = 0x10
|
||||
descCDCFuncTypeWirelessControl = 0x11
|
||||
descCDCFuncTypeMobileDirectLine = 0x12
|
||||
descCDCFuncTypeMDLMDetail = 0x13
|
||||
descCDCFuncTypeDeviceManagement = 0x14
|
||||
descCDCFuncTypeOBEX = 0x15
|
||||
descCDCFuncTypeCommandSet = 0x16
|
||||
descCDCFuncTypeCommandSetDetail = 0x17
|
||||
descCDCFuncTypeTelephoneControl = 0x18
|
||||
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.
|
||||
const (
|
||||
// Interfaces for the first CDC-ACM device (index 1).
|
||||
descCDCACM0InterfaceCount = 2
|
||||
descCDCACM0InterfaceCtrl = 0
|
||||
descCDCACM0InterfaceData = 1
|
||||
// Endpoints for the first CDC-ACM device (index 1).
|
||||
descCDCACM0EndpointCount = 4
|
||||
descCDCACM0EndpointStatus = 2 // Communication/control interrupt input
|
||||
descCDCACM0EndpointDataRx = 3 // Bulk data output
|
||||
descCDCACM0EndpointDataTx = 4 // Bulk data input
|
||||
// String descriptor languages
|
||||
descCDCACMLanguageCount = 1
|
||||
// Interfaces for all CDC-ACM configurations.
|
||||
descCDCACMInterfaceCount = 2
|
||||
descCDCACMInterfaceCtrl = 0
|
||||
descCDCACMInterfaceData = 1
|
||||
// Endpoints for all CDC-ACM configurations.
|
||||
descCDCACMEndpointCount = 4
|
||||
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.
|
||||
descCDCACMConfigSize = uint16(
|
||||
descLengthConfigure + // configuration
|
||||
descLengthInterface + // communication/control interface
|
||||
descCDCLengthFuncHeader + // CDC header
|
||||
descCDCLengthFuncCallManagement + // CDC call management
|
||||
descCDCLengthFuncAbstractControl + // CDC abstract control
|
||||
descCDCLengthFuncUnion + // CDC union
|
||||
descCDCFuncLengthHeader + // CDC header
|
||||
descCDCFuncLengthCallManagement + // CDC call management
|
||||
descCDCFuncLengthAbstractControl + // CDC abstract control
|
||||
descCDCFuncLengthUnion + // CDC union
|
||||
descLengthEndpoint + // communication/control input endpoint
|
||||
descLengthInterface + // data interface
|
||||
descLengthEndpoint + // data input endpoint
|
||||
@@ -209,126 +326,200 @@ const (
|
||||
(1 << descConfigAttrSelfPoweredPos) | // Bit 6: self-powered
|
||||
(0 << descConfigAttrRemoteWakeupPos) | // Bit 5: remote wakeup
|
||||
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.
|
||||
var (
|
||||
// descDeviceCDCACM holds the default device descriptors for CDC-ACM devices.
|
||||
descDeviceCDCACM = [descCDCACMConfigCount][descLengthDevice]uint8{
|
||||
{
|
||||
descLengthDevice, // Size of this descriptor in bytes
|
||||
descTypeDevice, // DEVICE Descriptor Type
|
||||
lsU8(descUSBSpecVersion), // USB Specification Release Number in BCD (low)
|
||||
msU8(descUSBSpecVersion), // USB Specification Release Number in BCD (high)
|
||||
descCDCComm, // Class code (assigned by the USB-IF).
|
||||
descCDCSubNone, // Subclass code (assigned by the USB-IF).
|
||||
descCDCProtoNone, // Protocol code (assigned by the USB-IF).
|
||||
descEndptMaxPktSizeMaximum, // 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
|
||||
0, // Index of string descriptor describing the device's serial number
|
||||
descCDCACMConfigCount, // Number of possible configurations
|
||||
// descCDCACM0String holds the default string descriptors for CDC-ACM[0], i.e.,
|
||||
// configuration index 1.
|
||||
var descCDCACM0String = [descCDCACMLanguageCount]descLocalStrings{
|
||||
{
|
||||
language: descLanguageEnglish,
|
||||
index: descIndexStrings{
|
||||
{ // 0: language string
|
||||
4,
|
||||
descTypeString,
|
||||
lsU8(descLanguageEnglish),
|
||||
msU8(descLanguageEnglish),
|
||||
},
|
||||
{ // 1: manufacturer
|
||||
uint8(2 + 2*len(descManufacturer)),
|
||||
descTypeString,
|
||||
},
|
||||
{ // 2: product
|
||||
uint8(2 + 2*len(descProduct)),
|
||||
descTypeString,
|
||||
},
|
||||
{ // 3: serial number
|
||||
uint8(2 + 2*len(descSerialNumber)),
|
||||
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
|
||||
}
|
||||
|
||||
// descConfigCDCACM holds the default configuration descriptors for CDC-ACM
|
||||
// devices.
|
||||
descConfigCDCACM = [descCDCACMConfigCount][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)
|
||||
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.baud = packU32(buffer)
|
||||
lc.stopBits = buffer[4]
|
||||
if 0 == lc.stopBits {
|
||||
lc.stopBits = 1
|
||||
}
|
||||
)
|
||||
lc.parity = buffer[5]
|
||||
lc.numBits = buffer[6]
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// +build mimxrt1062
|
||||
|
||||
package usb2
|
||||
|
||||
// descCPUFrequencyHz defines the target CPU frequency (Hz).
|
||||
@@ -5,28 +7,183 @@ const descCPUFrequencyHz = 600000000
|
||||
|
||||
// General USB device identification constants.
|
||||
const (
|
||||
descVendorID = 0xABCD
|
||||
descProductID = 0x1234
|
||||
descVendorID = 0x16C0
|
||||
descProductID = 0x0483
|
||||
descReleaseID = 0x0101
|
||||
|
||||
descVendor = "NXP Semiconductors"
|
||||
descProduct = "TinyGo USB"
|
||||
descManufacturer = "NXP Semiconductors"
|
||||
descProduct = "TinyGo USB"
|
||||
descSerialNumber = "0000000000"
|
||||
)
|
||||
|
||||
// Constants for USB CDC-ACM device classes.
|
||||
const (
|
||||
// descCDCACMConfigCount defines the number of USB cores that will be
|
||||
// configured as CDC-ACM (single) devices.
|
||||
descCDCACMConfigCount = 1
|
||||
// descCDCACMCount defines the number of USB cores that will be configured as
|
||||
// CDC-ACM (single) devices.
|
||||
descCDCACMCount = 1
|
||||
|
||||
descCDCACMQHCount = 2 * (descCDCACMEndpointCount + 1)
|
||||
descCDCACMRDCount = 2 * descCDCACMEndpointCount
|
||||
descCDCACMTDCount = descCDCACMEndpointCount
|
||||
descCDCACMRxCount = descCDCACMRxSize * descCDCACMRDCount
|
||||
descCDCACMTxCount = descCDCACMTxSize * descCDCACMTDCount
|
||||
descCDCACMCxCount = 8
|
||||
|
||||
descCDCACMMaxPower = 50 // 100 mA
|
||||
|
||||
descCDCACMStatusPacketSize = 16
|
||||
descCDCACMDataRxPacketSize = descCDCACMDataRxFSPacketSize // full-speed
|
||||
descCDCACMDataTxPacketSize = descCDCACMDataTxFSPacketSize // full-speed
|
||||
descCDCACMDataRxPacketSize = descCDCACMDataRxHSPacketSize // high-speed
|
||||
descCDCACMDataTxPacketSize = descCDCACMDataTxHSPacketSize // high-speed
|
||||
descCDCACMRxSize = descCDCACMDataRxPacketSize
|
||||
descCDCACMTxSize = 4 * descCDCACMDataTxPacketSize
|
||||
|
||||
descCDCACMDataRxFSPacketSize = 64 // full-speed
|
||||
descCDCACMDataTxFSPacketSize = 64 // full-speed
|
||||
descCDCACMDataRxHSPacketSize = 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
|
||||
|
||||
type dci interface {
|
||||
type hcd interface {
|
||||
init() status
|
||||
enable(enable bool) status
|
||||
critical(enter bool) status
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
package usb2
|
||||
|
||||
// Implementation of USB host controller interface (hci) for NXP iMXRT1062.
|
||||
// Implementation of USB host controller driver (hcd) for NXP iMXRT1062.
|
||||
|
||||
import (
|
||||
"device/arm"
|
||||
@@ -11,18 +11,19 @@ import (
|
||||
"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.
|
||||
const hciCount = 0
|
||||
const hcdCount = 0
|
||||
|
||||
// hciInterruptPriority defines the priority for all USB host interrupts.
|
||||
const hciInterruptPriority = 3
|
||||
// hcdInterruptPriority defines the priority for all USB host interrupts.
|
||||
const hcdInterruptPriority = 3
|
||||
|
||||
// hostController implements USB host controller interface (hci).
|
||||
// hostController implements USB host controller driver (hcd) interface.
|
||||
type hostController struct {
|
||||
core *core // Parent USB core this instance is attached to
|
||||
port int // USB port index
|
||||
id int // hostControllerInstance index
|
||||
core *core // Parent USB core this instance is attached to
|
||||
port int // USB port index
|
||||
class class // USB host class
|
||||
id int // hostControllerInstance index
|
||||
|
||||
bus *nxp.USB_Type
|
||||
phy *nxp.USBPHY_Type
|
||||
@@ -34,14 +35,14 @@ type hostController struct {
|
||||
|
||||
// hostControllerInstance provides statically-allocated instances of each USB
|
||||
// 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
|
||||
// controller instances remain.
|
||||
func initHCI(port int) (hci, status) {
|
||||
if 0 == hciCount {
|
||||
return nil, statusInvalidArgument // must have defined host descriptors
|
||||
func initHCD(port int, class class) (hcd, status) {
|
||||
if 0 == hcdCount {
|
||||
return nil, statusInvalid // must have defined host controllers
|
||||
}
|
||||
// Return the first instance whose assigned core is currently nil.
|
||||
for i := range hostControllerInstance {
|
||||
@@ -82,7 +83,7 @@ func (hc *hostController) init() status {
|
||||
|
||||
func (hc *hostController) enable(enable bool) status {
|
||||
|
||||
hc.irq.SetPriority(hciInterruptPriority)
|
||||
hc.irq.SetPriority(hcdInterruptPriority)
|
||||
hc.irq.Enable()
|
||||
|
||||
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 {
|
||||
|
||||
if uart.port >= CoreCount || uart.port >= dciCount ||
|
||||
uart.port >= descCDCACMConfigCount {
|
||||
if uart.port >= CoreCount || uart.port >= dcdCount {
|
||||
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
|
||||
var st status
|
||||
uart.core, st = initCore(uart.port, modeDevice)
|
||||
uart.core, st = initCore(uart.port, class{id: classDeviceCDCACM, config: 1})
|
||||
if !st.ok() {
|
||||
return ErrInvalidPort
|
||||
}
|
||||
|
||||
+49
-16
@@ -2,12 +2,20 @@ package usb2
|
||||
|
||||
// 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.
|
||||
type core struct {
|
||||
port int
|
||||
mode int
|
||||
dc dci
|
||||
hc hci
|
||||
dc dcd
|
||||
hc hcd
|
||||
}
|
||||
|
||||
// Constant definitions for USB core operating modes.
|
||||
@@ -17,9 +25,32 @@ const (
|
||||
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
|
||||
// host mode.
|
||||
const CoreCount = dciCount + hciCount
|
||||
const CoreCount = dcdCount + hcdCount
|
||||
|
||||
// coreInstance provides statically-allocated instances of each USB core
|
||||
// configured on this platform.
|
||||
@@ -30,30 +61,32 @@ type status uint8
|
||||
|
||||
// Constant definitions for all status codes used within the package.
|
||||
const (
|
||||
statusOK status = iota // Success
|
||||
statusBusy // Busy
|
||||
statusRetry // Retry
|
||||
statusInvalidArgument // Invalid argument
|
||||
statusOK status = iota // Success
|
||||
statusBusy // Busy
|
||||
statusRetry // Retry
|
||||
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 }
|
||||
|
||||
// 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
|
||||
// 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 {
|
||||
return nil, statusInvalidArgument
|
||||
if port < 0 || port >= CoreCount || 0 == class.config {
|
||||
return nil, statusInvalid
|
||||
}
|
||||
if modeIdle != coreInstance[port].mode {
|
||||
return nil, statusBusy
|
||||
}
|
||||
|
||||
switch mode {
|
||||
switch class.mode() {
|
||||
case modeDevice:
|
||||
// Allocate a free device controller and install interrupts
|
||||
dc, st := initDCI(port)
|
||||
dc, st := initDCD(port, class)
|
||||
if !st.ok() {
|
||||
return nil, st
|
||||
}
|
||||
@@ -62,7 +95,7 @@ func initCore(port, mode int) (*core, status) {
|
||||
return nil, st
|
||||
}
|
||||
coreInstance[port].port = port
|
||||
coreInstance[port].mode = mode
|
||||
coreInstance[port].mode = modeDevice
|
||||
coreInstance[port].dc = dc
|
||||
// Enable interrupts and enter runtime
|
||||
if st = dc.enable(true); !st.ok() {
|
||||
@@ -73,7 +106,7 @@ func initCore(port, mode int) (*core, status) {
|
||||
|
||||
case modeHost:
|
||||
// Allocate a free host controller and install interrupts
|
||||
hc, st := initHCI(port)
|
||||
hc, st := initHCD(port, class)
|
||||
if !st.ok() {
|
||||
return nil, st
|
||||
}
|
||||
@@ -82,7 +115,7 @@ func initCore(port, mode int) (*core, status) {
|
||||
return nil, st
|
||||
}
|
||||
coreInstance[port].port = port
|
||||
coreInstance[port].mode = mode
|
||||
coreInstance[port].mode = modeHost
|
||||
coreInstance[port].hc = hc
|
||||
// Enable interrupts and enter runtime
|
||||
if st = hc.enable(true); !st.ok() {
|
||||
@@ -92,7 +125,7 @@ func initCore(port, mode int) (*core, status) {
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, statusInvalidArgument
|
||||
return nil, statusInvalid
|
||||
}
|
||||
|
||||
return &coreInstance[port], statusOK
|
||||
|
||||
@@ -192,3 +192,25 @@ func lsU8(u uint16) uint8 { return uint8(u) }
|
||||
func cycles(microsec, cpuFreqHz uint32) uint32 {
|
||||
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