aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/machine/usb.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/machine/usb.go')
-rw-r--r--src/machine/usb.go188
1 files changed, 65 insertions, 123 deletions
diff --git a/src/machine/usb.go b/src/machine/usb.go
index ebdacfdaf..3656edc7b 100644
--- a/src/machine/usb.go
+++ b/src/machine/usb.go
@@ -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
)
+const cdcLineInfoSize = 7
+
+var (
+ ErrUSBReadTimeout = errors.New("USB read timeout")
+ ErrUSBBytesRead = errors.New("USB invalid number of bytes read")
+)
+
var (
- usbEndpointDescriptors [8]usbDeviceDescriptor
+ usbEndpointDescriptors [numberOfEndpoints]usbDeviceDescriptor
- udd_ep_in_cache_buffer [7][128]uint8
- udd_ep_out_cache_buffer [7][128]uint8
+ 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
-
- 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
+var (
+ usbTxHandler [numberOfEndpoints]func()
+ usbRxHandler [numberOfEndpoints]func([]byte)
+ usbSetupHandler [numberOfInterfaces]func(USBSetup) bool
+
+ endPoints = []uint32{
+ usb_CONTROL_ENDPOINT: usb_ENDPOINT_TYPE_CONTROL,
+ usb_CDC_ENDPOINT_ACM: (usb_ENDPOINT_TYPE_INTERRUPT | usbEndpointIn),
+ usb_CDC_ENDPOINT_OUT: (usb_ENDPOINT_TYPE_BULK | usbEndpointOut),
+ usb_CDC_ENDPOINT_IN: (usb_ENDPOINT_TYPE_BULK | usbEndpointIn),
+ usb_HID_ENDPOINT_IN: (usb_ENDPOINT_TYPE_DISABLE), // Interrupt In
+ }
)
// 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)
+}