samd21,samd51,nrf52840: move usbcdc to machine/usb/cdc (#2972)

* samd21,samd51,nrf52840: move usbcdc to machine/usb/cdc
This commit is contained in:
sago35
2022-07-10 18:33:52 +09:00
committed by GitHub
parent 56780c2691
commit d434058aef
15 changed files with 662 additions and 839 deletions
+65 -123
View File
@@ -14,25 +14,25 @@ type USBDevice struct {
var (
USBDev = &USBDevice{}
USBCDC Serialer
)
type Serialer interface {
WriteByte(c byte) error
Write(data []byte) (n int, err error)
Configure(config UARTConfig) error
Buffered() int
ReadByte() (byte, error)
}
var usbDescriptor = descriptorCDC
var (
errUSBCDCBufferEmpty = errors.New("USB-CDC buffer empty")
errUSBCDCWriteByteTimeout = errors.New("USB-CDC write byte timeout")
errUSBCDCReadTimeout = errors.New("USB-CDC read timeout")
errUSBCDCBytesRead = errors.New("USB-CDC invalid number of bytes read")
const (
usbDescriptorConfigCDC = 1 << iota
usbDescriptorConfigHID
)
const cdcLineInfoSize = 7
type cdcLineInfo struct {
dwDTERate uint32
bCharFormat uint8
bParityType uint8
bDataBits uint8
lineState uint8
}
var usbDescriptorConfig uint8 = usbDescriptorConfigCDC
// strToUTF16LEDescriptor converts a utf8 string into a string descriptor
// note: the following code only converts ascii characters to UTF16LE. In order
@@ -54,22 +54,25 @@ var (
usb_STRING_LANGUAGE = [2]uint16{(3 << 8) | (2 + 2), 0x0409} // English
)
var (
usbEndpointDescriptors [8]usbDeviceDescriptor
const cdcLineInfoSize = 7
udd_ep_in_cache_buffer [7][128]uint8
udd_ep_out_cache_buffer [7][128]uint8
var (
ErrUSBReadTimeout = errors.New("USB read timeout")
ErrUSBBytesRead = errors.New("USB invalid number of bytes read")
)
var (
usbEndpointDescriptors [numberOfEndpoints]usbDeviceDescriptor
udd_ep_control_cache_buffer [256]uint8
udd_ep_in_cache_buffer [7][64]uint8
udd_ep_out_cache_buffer [7][64]uint8
isEndpointHalt = false
isRemoteWakeUpEnabled = false
endPoints = []uint32{usb_ENDPOINT_TYPE_CONTROL,
(usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn),
(usb_ENDPOINT_TYPE_BULK | usbEndpointOut),
(usb_ENDPOINT_TYPE_BULK | usbEndpointIn)}
usbConfiguration uint8
usbSetInterface uint8
usbLineInfo = cdcLineInfo{115200, 0x00, 0x00, 0x08, 0x00}
)
const (
@@ -77,6 +80,7 @@ const (
usb_IPRODUCT = 2
usb_ISERIAL = 3
usb_ENDPOINT_TYPE_DISABLE = 0xFF
usb_ENDPOINT_TYPE_CONTROL = 0x00
usb_ENDPOINT_TYPE_ISOCHRONOUS = 0x01
usb_ENDPOINT_TYPE_BULK = 0x02
@@ -95,8 +99,8 @@ const (
usbEndpointOut = 0x00
usbEndpointIn = 0x80
numberOfEndpoints = 8
usbEndpointPacketSize = 64 // 64 for Full Speed, EPT size max is 1024
usb_EPT_NUM = 7
// standard requests
usb_GET_STATUS = 0
@@ -123,12 +127,15 @@ const (
usb_CONFIG_SELF_POWERED = 0xC0
usb_CONFIG_REMOTE_WAKEUP = 0x20
// CDC
// Interface
numberOfInterfaces = 3
usb_CDC_ACM_INTERFACE = 0 // CDC ACM
usb_CDC_DATA_INTERFACE = 1 // CDC Data
usb_CDC_FIRST_ENDPOINT = 1
usb_HID_INTERFACE = 2 // HID
// Endpoint
usb_CONTROL_ENDPOINT = 0
usb_CDC_ENDPOINT_ACM = 1
usb_CDC_ENDPOINT_OUT = 2
usb_CDC_ENDPOINT_IN = 3
@@ -153,27 +160,20 @@ const (
usb_REQUEST_DEVICETOHOST_CLASS_INTERFACE = (usb_REQUEST_DEVICETOHOST | usb_REQUEST_CLASS | usb_REQUEST_INTERFACE)
usb_REQUEST_HOSTTODEVICE_CLASS_INTERFACE = (usb_REQUEST_HOSTTODEVICE | usb_REQUEST_CLASS | usb_REQUEST_INTERFACE)
usb_REQUEST_DEVICETOHOST_STANDARD_INTERFACE = (usb_REQUEST_DEVICETOHOST | usb_REQUEST_STANDARD | usb_REQUEST_INTERFACE)
)
// CDC Class requests
usb_CDC_SET_LINE_CODING = 0x20
usb_CDC_GET_LINE_CODING = 0x21
usb_CDC_SET_CONTROL_LINE_STATE = 0x22
usb_CDC_SEND_BREAK = 0x23
var (
usbTxHandler [numberOfEndpoints]func()
usbRxHandler [numberOfEndpoints]func([]byte)
usbSetupHandler [numberOfInterfaces]func(USBSetup) bool
usb_CDC_V1_10 = 0x0110
usb_CDC_COMMUNICATION_INTERFACE_CLASS = 0x02
usb_CDC_CALL_MANAGEMENT = 0x01
usb_CDC_ABSTRACT_CONTROL_MODEL = 0x02
usb_CDC_HEADER = 0x00
usb_CDC_ABSTRACT_CONTROL_MANAGEMENT = 0x02
usb_CDC_UNION = 0x06
usb_CDC_CS_INTERFACE = 0x24
usb_CDC_CS_ENDPOINT = 0x25
usb_CDC_DATA_INTERFACE_CLASS = 0x0A
usb_CDC_LINESTATE_DTR = 0x01
usb_CDC_LINESTATE_RTS = 0x02
endPoints = []uint32{
usb_CONTROL_ENDPOINT: usb_ENDPOINT_TYPE_CONTROL,
usb_CDC_ENDPOINT_ACM: (usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn),
usb_CDC_ENDPOINT_OUT: (usb_ENDPOINT_TYPE_BULK | usbEndpointOut),
usb_CDC_ENDPOINT_IN: (usb_ENDPOINT_TYPE_BULK | usbEndpointIn),
usb_HID_ENDPOINT_IN: (usb_ENDPOINT_TYPE_DISABLE), // Interrupt In
}
)
// usbDeviceDescBank is the USB device endpoint descriptor.
@@ -209,73 +209,6 @@ func newUSBSetup(data []byte) USBSetup {
return u
}
// USBCDC is the serial interface that works over the USB port.
// To implement the USBCDC interface for a board, you must declare a concrete type as follows:
//
// type USBCDC struct {
// Buffer *RingBuffer
// }
//
// You can also add additional members to this struct depending on your implementation,
// but the *RingBuffer is required.
// When you are declaring the USBCDC for your board, make sure that you also declare the
// RingBuffer using the NewRingBuffer() function:
//
// USBCDC{Buffer: NewRingBuffer()}
//
// Read from the RX buffer.
func (usbcdc *USBCDC) Read(data []byte) (n int, err error) {
// check if RX buffer is empty
size := usbcdc.Buffered()
if size == 0 {
return 0, nil
}
// Make sure we do not read more from buffer than the data slice can hold.
if len(data) < size {
size = len(data)
}
// only read number of bytes used from buffer
for i := 0; i < size; i++ {
v, _ := usbcdc.ReadByte()
data[i] = v
}
return size, nil
}
// Write data to the USBCDC.
func (usbcdc *USBCDC) Write(data []byte) (n int, err error) {
for _, v := range data {
usbcdc.WriteByte(v)
}
return len(data), nil
}
// ReadByte reads a single byte from the RX buffer.
// If there is no data in the buffer, returns an error.
func (usbcdc *USBCDC) ReadByte() (byte, error) {
// check if RX buffer is empty
buf, ok := usbcdc.Buffer.Get()
if !ok {
return 0, errUSBCDCBufferEmpty
}
return buf, nil
}
// Buffered returns the number of bytes currently stored in the RX buffer.
func (usbcdc *USBCDC) Buffered() int {
return int(usbcdc.Buffer.Used())
}
// Receive handles adding data to the UART's data buffer.
// Usually called by the IRQ handler for a machine.
func (usbcdc *USBCDC) Receive(data byte) {
usbcdc.Buffer.Put(data)
}
// sendDescriptor creates and sends the various USB descriptor types that
// can be requested by the host.
func sendDescriptor(setup USBSetup) {
@@ -285,6 +218,11 @@ func sendDescriptor(setup USBSetup) {
return
case usb_DEVICE_DESCRIPTOR_TYPE:
// composite descriptor
if (usbDescriptorConfig & usbDescriptorConfigHID) > 0 {
usbDescriptor = descriptorCDCHID
} else {
usbDescriptor = descriptorCDC
}
usbDescriptor.Configure(usb_VID, usb_PID)
sendUSBPacket(0, usbDescriptor.Device, setup.WLength)
return
@@ -402,17 +340,21 @@ func handleStandardSetup(setup USBSetup) bool {
}
}
// EnableHID enables HID. This function must be executed from the init().
func EnableHID(callback func()) {
usbDescriptor = descriptorCDCHID
endPoints = []uint32{usb_ENDPOINT_TYPE_CONTROL,
(usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn),
(usb_ENDPOINT_TYPE_BULK | usbEndpointOut),
(usb_ENDPOINT_TYPE_BULK | usbEndpointIn),
(usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn)}
hidCallback = callback
func EnableCDC(txHandler func(), rxHandler func([]byte), setupHandler func(USBSetup) bool) {
usbDescriptorConfig |= usbDescriptorConfigCDC
endPoints[usb_CDC_ENDPOINT_ACM] = (usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn)
endPoints[usb_CDC_ENDPOINT_OUT] = (usb_ENDPOINT_TYPE_BULK | usbEndpointOut)
endPoints[usb_CDC_ENDPOINT_IN] = (usb_ENDPOINT_TYPE_BULK | usbEndpointIn)
usbRxHandler[usb_CDC_ENDPOINT_OUT] = rxHandler
usbTxHandler[usb_CDC_ENDPOINT_IN] = txHandler
usbSetupHandler[usb_CDC_ACM_INTERFACE] = setupHandler // 0x02 (Communications and CDC Control)
usbSetupHandler[usb_CDC_DATA_INTERFACE] = nil // 0x0A (CDC-Data)
}
// hidCallback is a variable that holds the callback when using HID.
var hidCallback func()
// EnableHID enables HID. This function must be executed from the init().
func EnableHID(txHandler func(), rxHandler func([]byte), setupHandler func(USBSetup) bool) {
usbDescriptorConfig |= usbDescriptorConfigHID
endPoints[usb_HID_ENDPOINT_IN] = (usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn)
usbTxHandler[usb_HID_ENDPOINT_IN] = txHandler
usbSetupHandler[usb_HID_INTERFACE] = setupHandler // 0x03 (HID - Human Interface Device)
}