machine/atsamd21,atsamd51,nrf52840: refactor USB CDC device descriptor to reduce code duplication and heap allocations
Signed-off-by: Ron Evans <ron@hybridgroup.com>
Этот коммит содержится в:
родитель
06797b6d1a
коммит
03fa9dd9b7
4 изменённых файлов: 120 добавлений и 324 удалений
|
@ -1478,7 +1478,7 @@ func handleUSB(intr interrupt.Interrupt) {
|
||||||
setEPINTENCLR(0, sam.USB_DEVICE_EPINTENCLR_STALL1)
|
setEPINTENCLR(0, sam.USB_DEVICE_EPINTENCLR_STALL1)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now the actual transfer handlers, ignore endpoint number 0 (setup)
|
// Now the actual transfer handlers, ignore endpoint number 0 (setup)
|
||||||
|
@ -1601,7 +1601,7 @@ func handleStandardSetup(setup usbSetup) bool {
|
||||||
} else if setup.wValueL == 0 { // ENDPOINTHALT
|
} else if setup.wValueL == 0 { // ENDPOINTHALT
|
||||||
isEndpointHalt = false
|
isEndpointHalt = false
|
||||||
}
|
}
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case usb_SET_FEATURE:
|
case usb_SET_FEATURE:
|
||||||
|
@ -1610,7 +1610,7 @@ func handleStandardSetup(setup usbSetup) bool {
|
||||||
} else if setup.wValueL == 0 { // ENDPOINTHALT
|
} else if setup.wValueL == 0 { // ENDPOINTHALT
|
||||||
isEndpointHalt = true
|
isEndpointHalt = true
|
||||||
}
|
}
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case usb_SET_ADDRESS:
|
case usb_SET_ADDRESS:
|
||||||
|
@ -1665,7 +1665,7 @@ func handleStandardSetup(setup usbSetup) bool {
|
||||||
// Enable interrupt for CDC data messages from host
|
// Enable interrupt for CDC data messages from host
|
||||||
setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_EPINTENSET_TRCPT0)
|
setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_EPINTENSET_TRCPT0)
|
||||||
|
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
|
@ -1679,7 +1679,7 @@ func handleStandardSetup(setup usbSetup) bool {
|
||||||
case usb_SET_INTERFACE:
|
case usb_SET_INTERFACE:
|
||||||
usbSetInterface = setup.wValueL
|
usbSetInterface = setup.wValueL
|
||||||
|
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1724,14 +1724,14 @@ func cdcSetup(setup usbSetup) bool {
|
||||||
} else {
|
} else {
|
||||||
// TODO: cancel any reset
|
// TODO: cancel any reset
|
||||||
}
|
}
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
}
|
}
|
||||||
|
|
||||||
if setup.bRequest == usb_CDC_SEND_BREAK {
|
if setup.bRequest == usb_CDC_SEND_BREAK {
|
||||||
// TODO: something with this value?
|
// TODO: something with this value?
|
||||||
// breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;
|
// breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;
|
||||||
// return false;
|
// return false;
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -1790,104 +1790,6 @@ func receiveUSBControlPacket() []byte {
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendDescriptor creates and sends the various USB descriptor types that
|
|
||||||
// can be requested by the host.
|
|
||||||
func sendDescriptor(setup usbSetup) {
|
|
||||||
switch setup.wValueH {
|
|
||||||
case usb_CONFIGURATION_DESCRIPTOR_TYPE:
|
|
||||||
sendConfiguration(setup)
|
|
||||||
return
|
|
||||||
case usb_DEVICE_DESCRIPTOR_TYPE:
|
|
||||||
// composite descriptor
|
|
||||||
dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1)
|
|
||||||
l := deviceDescriptorSize
|
|
||||||
if setup.wLength < deviceDescriptorSize {
|
|
||||||
l = int(setup.wLength)
|
|
||||||
}
|
|
||||||
sendUSBPacket(0, dd.Bytes()[:l])
|
|
||||||
return
|
|
||||||
|
|
||||||
case usb_STRING_DESCRIPTOR_TYPE:
|
|
||||||
switch setup.wValueL {
|
|
||||||
case 0:
|
|
||||||
b := []byte{0x04, 0x03, 0x09, 0x04}
|
|
||||||
sendUSBPacket(0, b)
|
|
||||||
return
|
|
||||||
|
|
||||||
case usb_IPRODUCT:
|
|
||||||
b := strToUTF16LEDescriptor(usb_STRING_PRODUCT)
|
|
||||||
sendUSBPacket(0, b)
|
|
||||||
return
|
|
||||||
|
|
||||||
case usb_IMANUFACTURER:
|
|
||||||
b := strToUTF16LEDescriptor(usb_STRING_MANUFACTURER)
|
|
||||||
sendUSBPacket(0, b)
|
|
||||||
return
|
|
||||||
|
|
||||||
case usb_ISERIAL:
|
|
||||||
// TODO: allow returning a product serial number
|
|
||||||
sendZlp(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// send final zero length packet and return
|
|
||||||
sendZlp(0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not know how to handle this message, so return zero
|
|
||||||
sendZlp(0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendConfiguration creates and sends the configuration packet to the host.
|
|
||||||
func sendConfiguration(setup usbSetup) {
|
|
||||||
if setup.wLength == 9 {
|
|
||||||
sz := uint16(configDescriptorSize + cdcSize)
|
|
||||||
config := NewConfigDescriptor(sz, 2)
|
|
||||||
sendUSBPacket(0, config.Bytes())
|
|
||||||
} else {
|
|
||||||
iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0)
|
|
||||||
|
|
||||||
cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0)
|
|
||||||
|
|
||||||
header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF)
|
|
||||||
|
|
||||||
controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6)
|
|
||||||
|
|
||||||
functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE)
|
|
||||||
|
|
||||||
callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1)
|
|
||||||
|
|
||||||
cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10)
|
|
||||||
|
|
||||||
dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0)
|
|
||||||
|
|
||||||
out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0)
|
|
||||||
|
|
||||||
in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0)
|
|
||||||
|
|
||||||
cdc := NewCDCDescriptor(iad,
|
|
||||||
cif,
|
|
||||||
header,
|
|
||||||
controlManagement,
|
|
||||||
functionalDescriptor,
|
|
||||||
callManagement,
|
|
||||||
cifin,
|
|
||||||
dif,
|
|
||||||
out,
|
|
||||||
in)
|
|
||||||
|
|
||||||
sz := uint16(configDescriptorSize + cdcSize)
|
|
||||||
config := NewConfigDescriptor(sz, 2)
|
|
||||||
|
|
||||||
buf := make([]byte, 0, sz)
|
|
||||||
buf = append(buf, config.Bytes()...)
|
|
||||||
buf = append(buf, cdc.Bytes()...)
|
|
||||||
|
|
||||||
sendUSBPacket(0, buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleEndpoint(ep uint32) {
|
func handleEndpoint(ep uint32) {
|
||||||
// get data
|
// get data
|
||||||
count := int((usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >>
|
count := int((usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >>
|
||||||
|
@ -1908,8 +1810,8 @@ func handleEndpoint(ep uint32) {
|
||||||
setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY)
|
setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendZlp(ep uint32) {
|
func sendZlp() {
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
func epPacketSize(size uint16) uint32 {
|
func epPacketSize(size uint16) uint32 {
|
||||||
|
|
|
@ -1649,7 +1649,7 @@ func handleUSBIRQ(interrupt.Interrupt) {
|
||||||
setEPINTENCLR(0, sam.USB_DEVICE_ENDPOINT_EPINTENCLR_STALL1)
|
setEPINTENCLR(0, sam.USB_DEVICE_ENDPOINT_EPINTENCLR_STALL1)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now the actual transfer handlers, ignore endpoint number 0 (setup)
|
// Now the actual transfer handlers, ignore endpoint number 0 (setup)
|
||||||
|
@ -1772,7 +1772,7 @@ func handleStandardSetup(setup usbSetup) bool {
|
||||||
} else if setup.wValueL == 0 { // ENDPOINTHALT
|
} else if setup.wValueL == 0 { // ENDPOINTHALT
|
||||||
isEndpointHalt = false
|
isEndpointHalt = false
|
||||||
}
|
}
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case usb_SET_FEATURE:
|
case usb_SET_FEATURE:
|
||||||
|
@ -1781,7 +1781,7 @@ func handleStandardSetup(setup usbSetup) bool {
|
||||||
} else if setup.wValueL == 0 { // ENDPOINTHALT
|
} else if setup.wValueL == 0 { // ENDPOINTHALT
|
||||||
isEndpointHalt = true
|
isEndpointHalt = true
|
||||||
}
|
}
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case usb_SET_ADDRESS:
|
case usb_SET_ADDRESS:
|
||||||
|
@ -1836,7 +1836,7 @@ func handleStandardSetup(setup usbSetup) bool {
|
||||||
// Enable interrupt for CDC data messages from host
|
// Enable interrupt for CDC data messages from host
|
||||||
setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0)
|
setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0)
|
||||||
|
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
|
@ -1850,7 +1850,7 @@ func handleStandardSetup(setup usbSetup) bool {
|
||||||
case usb_SET_INTERFACE:
|
case usb_SET_INTERFACE:
|
||||||
usbSetInterface = setup.wValueL
|
usbSetInterface = setup.wValueL
|
||||||
|
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1895,14 +1895,14 @@ func cdcSetup(setup usbSetup) bool {
|
||||||
} else {
|
} else {
|
||||||
// TODO: cancel any reset
|
// TODO: cancel any reset
|
||||||
}
|
}
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
}
|
}
|
||||||
|
|
||||||
if setup.bRequest == usb_CDC_SEND_BREAK {
|
if setup.bRequest == usb_CDC_SEND_BREAK {
|
||||||
// TODO: something with this value?
|
// TODO: something with this value?
|
||||||
// breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;
|
// breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;
|
||||||
// return false;
|
// return false;
|
||||||
sendZlp(0)
|
sendZlp()
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -1961,104 +1961,6 @@ func receiveUSBControlPacket() []byte {
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendDescriptor creates and sends the various USB descriptor types that
|
|
||||||
// can be requested by the host.
|
|
||||||
func sendDescriptor(setup usbSetup) {
|
|
||||||
switch setup.wValueH {
|
|
||||||
case usb_CONFIGURATION_DESCRIPTOR_TYPE:
|
|
||||||
sendConfiguration(setup)
|
|
||||||
return
|
|
||||||
case usb_DEVICE_DESCRIPTOR_TYPE:
|
|
||||||
// composite descriptor
|
|
||||||
dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1)
|
|
||||||
l := deviceDescriptorSize
|
|
||||||
if setup.wLength < deviceDescriptorSize {
|
|
||||||
l = int(setup.wLength)
|
|
||||||
}
|
|
||||||
sendUSBPacket(0, dd.Bytes()[:l])
|
|
||||||
return
|
|
||||||
|
|
||||||
case usb_STRING_DESCRIPTOR_TYPE:
|
|
||||||
switch setup.wValueL {
|
|
||||||
case 0:
|
|
||||||
b := []byte{0x04, 0x03, 0x09, 0x04}
|
|
||||||
sendUSBPacket(0, b)
|
|
||||||
return
|
|
||||||
|
|
||||||
case usb_IPRODUCT:
|
|
||||||
b := strToUTF16LEDescriptor(usb_STRING_PRODUCT)
|
|
||||||
sendUSBPacket(0, b)
|
|
||||||
return
|
|
||||||
|
|
||||||
case usb_IMANUFACTURER:
|
|
||||||
b := strToUTF16LEDescriptor(usb_STRING_MANUFACTURER)
|
|
||||||
sendUSBPacket(0, b)
|
|
||||||
return
|
|
||||||
|
|
||||||
case usb_ISERIAL:
|
|
||||||
// TODO: allow returning a product serial number
|
|
||||||
sendZlp(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// send final zero length packet and return
|
|
||||||
sendZlp(0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not know how to handle this message, so return zero
|
|
||||||
sendZlp(0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendConfiguration creates and sends the configuration packet to the host.
|
|
||||||
func sendConfiguration(setup usbSetup) {
|
|
||||||
if setup.wLength == 9 {
|
|
||||||
sz := uint16(configDescriptorSize + cdcSize)
|
|
||||||
config := NewConfigDescriptor(sz, 2)
|
|
||||||
sendUSBPacket(0, config.Bytes())
|
|
||||||
} else {
|
|
||||||
iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0)
|
|
||||||
|
|
||||||
cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0)
|
|
||||||
|
|
||||||
header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF)
|
|
||||||
|
|
||||||
controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6)
|
|
||||||
|
|
||||||
functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE)
|
|
||||||
|
|
||||||
callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1)
|
|
||||||
|
|
||||||
cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10)
|
|
||||||
|
|
||||||
dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0)
|
|
||||||
|
|
||||||
out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0)
|
|
||||||
|
|
||||||
in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0)
|
|
||||||
|
|
||||||
cdc := NewCDCDescriptor(iad,
|
|
||||||
cif,
|
|
||||||
header,
|
|
||||||
controlManagement,
|
|
||||||
functionalDescriptor,
|
|
||||||
callManagement,
|
|
||||||
cifin,
|
|
||||||
dif,
|
|
||||||
out,
|
|
||||||
in)
|
|
||||||
|
|
||||||
sz := uint16(configDescriptorSize + cdcSize)
|
|
||||||
config := NewConfigDescriptor(sz, 2)
|
|
||||||
|
|
||||||
buf := make([]byte, 0)
|
|
||||||
buf = append(buf, config.Bytes()...)
|
|
||||||
buf = append(buf, cdc.Bytes()...)
|
|
||||||
|
|
||||||
sendUSBPacket(0, buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleEndpoint(ep uint32) {
|
func handleEndpoint(ep uint32) {
|
||||||
// get data
|
// get data
|
||||||
count := int((usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >>
|
count := int((usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.Get() >>
|
||||||
|
@ -2079,8 +1981,8 @@ func handleEndpoint(ep uint32) {
|
||||||
setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY)
|
setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendZlp(ep uint32) {
|
func sendZlp() {
|
||||||
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
func epPacketSize(size uint16) uint32 {
|
func epPacketSize(size uint16) uint32 {
|
||||||
|
|
|
@ -381,16 +381,14 @@ type cdcLineInfo struct {
|
||||||
// to do a "proper" conversion, we would need to pull in the 'unicode/utf16'
|
// to do a "proper" conversion, we would need to pull in the 'unicode/utf16'
|
||||||
// package, which at the time this was written added 512 bytes to the compiled
|
// package, which at the time this was written added 512 bytes to the compiled
|
||||||
// binary.
|
// binary.
|
||||||
func strToUTF16LEDescriptor(in string) []byte {
|
func strToUTF16LEDescriptor(in string, out []byte) {
|
||||||
size := (len(in) << 1) + 2
|
out[0] = byte(len(out))
|
||||||
out := make([]byte, size)
|
out[1] = usb_STRING_DESCRIPTOR_TYPE
|
||||||
out[0] = byte(size)
|
|
||||||
out[1] = 0x03
|
|
||||||
for i, rune := range in {
|
for i, rune := range in {
|
||||||
out[(i<<1)+2] = byte(rune)
|
out[(i<<1)+2] = byte(rune)
|
||||||
out[(i<<1)+3] = 0
|
out[(i<<1)+3] = 0
|
||||||
}
|
}
|
||||||
return out
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -615,3 +613,97 @@ func (usbcdc USBCDC) Buffered() int {
|
||||||
func (usbcdc USBCDC) Receive(data byte) {
|
func (usbcdc USBCDC) Receive(data byte) {
|
||||||
usbcdc.Buffer.Put(data)
|
usbcdc.Buffer.Put(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sendDescriptor creates and sends the various USB descriptor types that
|
||||||
|
// can be requested by the host.
|
||||||
|
func sendDescriptor(setup usbSetup) {
|
||||||
|
switch setup.wValueH {
|
||||||
|
case usb_CONFIGURATION_DESCRIPTOR_TYPE:
|
||||||
|
sendConfiguration(setup)
|
||||||
|
return
|
||||||
|
case usb_DEVICE_DESCRIPTOR_TYPE:
|
||||||
|
// composite descriptor
|
||||||
|
dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1)
|
||||||
|
l := deviceDescriptorSize
|
||||||
|
if setup.wLength < deviceDescriptorSize {
|
||||||
|
l = int(setup.wLength)
|
||||||
|
}
|
||||||
|
sendUSBPacket(0, dd.Bytes()[:l])
|
||||||
|
return
|
||||||
|
|
||||||
|
case usb_STRING_DESCRIPTOR_TYPE:
|
||||||
|
switch setup.wValueL {
|
||||||
|
case 0:
|
||||||
|
b := []byte{0x04, 0x03, 0x09, 0x04}
|
||||||
|
sendUSBPacket(0, b)
|
||||||
|
|
||||||
|
case usb_IPRODUCT:
|
||||||
|
b := make([]byte, (len(usb_STRING_PRODUCT)<<1)+2)
|
||||||
|
strToUTF16LEDescriptor(usb_STRING_PRODUCT, b)
|
||||||
|
sendUSBPacket(0, b)
|
||||||
|
|
||||||
|
case usb_IMANUFACTURER:
|
||||||
|
b := make([]byte, (len(usb_STRING_MANUFACTURER)<<1)+2)
|
||||||
|
strToUTF16LEDescriptor(usb_STRING_MANUFACTURER, b)
|
||||||
|
sendUSBPacket(0, b)
|
||||||
|
|
||||||
|
case usb_ISERIAL:
|
||||||
|
// TODO: allow returning a product serial number
|
||||||
|
sendZlp()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// do not know how to handle this message, so return zero
|
||||||
|
sendZlp()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendConfiguration creates and sends the configuration packet to the host.
|
||||||
|
func sendConfiguration(setup usbSetup) {
|
||||||
|
if setup.wLength == 9 {
|
||||||
|
sz := uint16(configDescriptorSize + cdcSize)
|
||||||
|
config := NewConfigDescriptor(sz, 2)
|
||||||
|
sendUSBPacket(0, config.Bytes())
|
||||||
|
} else {
|
||||||
|
iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0)
|
||||||
|
|
||||||
|
cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0)
|
||||||
|
|
||||||
|
header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF)
|
||||||
|
|
||||||
|
controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6)
|
||||||
|
|
||||||
|
functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE)
|
||||||
|
|
||||||
|
callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1)
|
||||||
|
|
||||||
|
cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10)
|
||||||
|
|
||||||
|
dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0)
|
||||||
|
|
||||||
|
out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0)
|
||||||
|
|
||||||
|
in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0)
|
||||||
|
|
||||||
|
cdc := NewCDCDescriptor(iad,
|
||||||
|
cif,
|
||||||
|
header,
|
||||||
|
controlManagement,
|
||||||
|
functionalDescriptor,
|
||||||
|
callManagement,
|
||||||
|
cifin,
|
||||||
|
dif,
|
||||||
|
out,
|
||||||
|
in)
|
||||||
|
|
||||||
|
sz := uint16(configDescriptorSize + cdcSize)
|
||||||
|
config := NewConfigDescriptor(sz, 2)
|
||||||
|
|
||||||
|
buf := make([]byte, 0, sz)
|
||||||
|
buf = append(buf, config.Bytes()...)
|
||||||
|
buf = append(buf, cdc.Bytes()...)
|
||||||
|
|
||||||
|
sendUSBPacket(0, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -400,110 +400,6 @@ func sendUSBPacket(ep uint32, data []byte) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendDescriptor creates and sends the various USB descriptor types that
|
|
||||||
// can be requested by the host.
|
|
||||||
func sendDescriptor(setup usbSetup) {
|
|
||||||
switch setup.wValueH {
|
|
||||||
case usb_CONFIGURATION_DESCRIPTOR_TYPE:
|
|
||||||
sendConfiguration(setup)
|
|
||||||
return
|
|
||||||
case usb_DEVICE_DESCRIPTOR_TYPE:
|
|
||||||
// composite descriptor
|
|
||||||
dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1)
|
|
||||||
l := deviceDescriptorSize
|
|
||||||
if setup.wLength < deviceDescriptorSize {
|
|
||||||
l = int(setup.wLength)
|
|
||||||
}
|
|
||||||
sendUSBPacket(0, dd.Bytes()[:l])
|
|
||||||
return
|
|
||||||
|
|
||||||
case usb_STRING_DESCRIPTOR_TYPE:
|
|
||||||
switch setup.wValueL {
|
|
||||||
case 0:
|
|
||||||
b := make([]byte, 4)
|
|
||||||
b[0] = 0x04
|
|
||||||
b[1] = 0x03
|
|
||||||
b[2] = 0x09
|
|
||||||
b[3] = 0x04
|
|
||||||
sendUSBPacket(0, b)
|
|
||||||
|
|
||||||
case usb_IPRODUCT:
|
|
||||||
b := strToUTF16LEDescriptor(usb_STRING_PRODUCT)
|
|
||||||
if setup.wLength == 2 {
|
|
||||||
sendUSBPacket(0, b[:2])
|
|
||||||
} else {
|
|
||||||
sendUSBPacket(0, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
case usb_IMANUFACTURER:
|
|
||||||
b := strToUTF16LEDescriptor(usb_STRING_MANUFACTURER)
|
|
||||||
if setup.wLength == 2 {
|
|
||||||
sendUSBPacket(0, b[:2])
|
|
||||||
} else {
|
|
||||||
sendUSBPacket(0, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
case usb_ISERIAL:
|
|
||||||
// TODO: allow returning a product serial number
|
|
||||||
nrf.USBD.TASKS_EP0STATUS.Set(1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not know how to handle this message, so return zero
|
|
||||||
nrf.USBD.TASKS_EP0STATUS.Set(1)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendConfiguration creates and sends the configuration packet to the host.
|
|
||||||
func sendConfiguration(setup usbSetup) {
|
|
||||||
if setup.wLength == 9 {
|
|
||||||
sz := uint16(configDescriptorSize + cdcSize)
|
|
||||||
config := NewConfigDescriptor(sz, 2)
|
|
||||||
|
|
||||||
sendUSBPacket(0, config.Bytes())
|
|
||||||
} else {
|
|
||||||
iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0)
|
|
||||||
|
|
||||||
cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0)
|
|
||||||
|
|
||||||
header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF)
|
|
||||||
|
|
||||||
controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6)
|
|
||||||
|
|
||||||
functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE)
|
|
||||||
|
|
||||||
callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1)
|
|
||||||
|
|
||||||
cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10)
|
|
||||||
|
|
||||||
dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0)
|
|
||||||
|
|
||||||
out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0)
|
|
||||||
|
|
||||||
in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0)
|
|
||||||
|
|
||||||
cdc := NewCDCDescriptor(iad,
|
|
||||||
cif,
|
|
||||||
header,
|
|
||||||
controlManagement,
|
|
||||||
functionalDescriptor,
|
|
||||||
callManagement,
|
|
||||||
cifin,
|
|
||||||
dif,
|
|
||||||
out,
|
|
||||||
in)
|
|
||||||
|
|
||||||
sz := uint16(configDescriptorSize + cdcSize)
|
|
||||||
config := NewConfigDescriptor(sz, 2)
|
|
||||||
|
|
||||||
buf := make([]byte, 0)
|
|
||||||
buf = append(buf, config.Bytes()...)
|
|
||||||
buf = append(buf, cdc.Bytes()...)
|
|
||||||
sendUSBPacket(0, buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (usbcdc USBCDC) handleEndpoint(ep uint32) {
|
func (usbcdc USBCDC) handleEndpoint(ep uint32) {
|
||||||
// get data
|
// get data
|
||||||
count := int(nrf.USBD.EPOUT[ep].AMOUNT.Get())
|
count := int(nrf.USBD.EPOUT[ep].AMOUNT.Get())
|
||||||
|
@ -517,6 +413,10 @@ func (usbcdc USBCDC) handleEndpoint(ep uint32) {
|
||||||
nrf.USBD.SIZE.EPOUT[ep].Set(0)
|
nrf.USBD.SIZE.EPOUT[ep].Set(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sendZlp() {
|
||||||
|
nrf.USBD.TASKS_EP0STATUS.Set(1)
|
||||||
|
}
|
||||||
|
|
||||||
func sendViaEPIn(ep uint32, ptr *byte, count int) {
|
func sendViaEPIn(ep uint32, ptr *byte, count int) {
|
||||||
nrf.USBD.EPIN[ep].PTR.Set(
|
nrf.USBD.EPIN[ep].PTR.Set(
|
||||||
uint32(uintptr(unsafe.Pointer(ptr))),
|
uint32(uintptr(unsafe.Pointer(ptr))),
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче