mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-19 03:54:01 +00:00
refactor USB package with device class build tags
added basic HID keyboard support for SAMx51 (not fully-functional)
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
//go:build baremetal && usb.cdc && (atsamd51 || atsame5x)
|
||||
// +build baremetal
|
||||
// +build usb.cdc
|
||||
// +build atsamd51 atsame5x
|
||||
|
||||
package usb
|
||||
|
||||
import "runtime/volatile"
|
||||
|
||||
// Constants for USB CDC-ACM device classes.
|
||||
const (
|
||||
|
||||
// USB Bus Configuration Attributes
|
||||
|
||||
descCDCMaxPowerMa = 100 // Maximum current (mA) requested from host
|
||||
|
||||
// CDC-ACM Endpoint Descriptor Buffers
|
||||
|
||||
descCDCEDCount = descMaxEndpoints
|
||||
|
||||
// Setup packet is only 8 bytes in length. However, under certain scenarios,
|
||||
// USB DMA controller may decide to overwrite/overflow the buffer with 2 extra
|
||||
// bytes of CRC. From datasheet's "Management of SETUP Transactions" section:
|
||||
// | If the number of received data bytes is the maximum data payload
|
||||
// | specified by PCKSIZE.SIZE minus one, only the first CRC data is written
|
||||
// | to the data buffer. If the number of received data is equal or less
|
||||
// | than the data payload specified by PCKSIZE.SIZE minus two, both CRC
|
||||
// | data bytes are written to the data buffer.
|
||||
// Thus, we need to allocate 2 extra bytes for control endpoint 0 Rx (OUT).
|
||||
descCDCSxSize = 8 + 2
|
||||
descCDCCxSize = descControlPacketSize
|
||||
|
||||
// CDC-ACM Data Buffers
|
||||
|
||||
descCDCRxSize = descCDCDataRxPacketSize
|
||||
descCDCTxSize = descCDCDataTxPacketSize
|
||||
|
||||
descCDCTxTimeoutMs = 120 // millisec
|
||||
descCDCTxSyncUs = 75 // microsec
|
||||
|
||||
// Default CDC-ACM Endpoint Configurations (Full-Speed)
|
||||
|
||||
descCDCStatusInterval = descCDCStatusFSInterval // Status
|
||||
descCDCStatusPacketSize = descCDCStatusFSPacketSize //
|
||||
|
||||
descCDCDataRxPacketSize = descCDCDataRxFSPacketSize // Data Rx
|
||||
descCDCDataTxPacketSize = descCDCDataTxFSPacketSize // Data Tx
|
||||
|
||||
// CDC-ACM Endpoint Configurations for Full-Speed Device
|
||||
|
||||
descCDCStatusFSInterval = 5 // Status
|
||||
descCDCStatusFSPacketSize = 64 // (full-speed)
|
||||
|
||||
descCDCDataRxFSPacketSize = 64 // Data Rx (full-speed)
|
||||
descCDCDataTxFSPacketSize = 64 // Data Tx (full-speed)
|
||||
|
||||
// CDC-ACM Endpoint Configurations for High-Speed Device
|
||||
|
||||
// - N/A, SAMx51 only has a full-speed PHY
|
||||
)
|
||||
|
||||
// descCDC0ED is an array of endpoint descriptors, which describes to the USB
|
||||
// DMA controller the buffer and transfer properties for each endpoint, for the
|
||||
// default CDC-ACM (single) device class configuration (index 1).
|
||||
//go:align 32
|
||||
var descCDC0ED [descCDCEDCount]dhwEPAddrDesc
|
||||
|
||||
// descCDC0Sx is the receive (Rx) buffer for setup packets on control endpoint
|
||||
// 0 of the default CDC-ACM (single) device class configuration (index 1).
|
||||
//go:align 32
|
||||
var descCDC0Sx [descCDCSxSize]uint8
|
||||
|
||||
// descCDC0Cx is the transmit (Tx) buffer for control/status packets on control
|
||||
// endpoint 0 of the default CDC-ACM (single) device class configuration (index 1).
|
||||
//go:align 32
|
||||
var descCDC0Cx [descCDCCxSize]uint8
|
||||
|
||||
// descCDC0Dx is the transmit (Tx) buffer of descriptor data on endpoint 0
|
||||
// for the default CDC-ACM (single) device class configuration (index 1).
|
||||
//go:align 32
|
||||
var descCDC0Dx [descCDCConfigSize]uint8
|
||||
|
||||
// descCDC0Rx is the receive (Rx) transfer buffer for the default CDC-ACM
|
||||
// (single) device class configuration (index 1).
|
||||
//go:align 32
|
||||
var descCDC0Rx [descCDCRxSize]uint8
|
||||
|
||||
// descCDC0Tx is the transmit (Tx) transfer buffer for the default CDC-ACM
|
||||
// (single) device class configuration (index 1).
|
||||
//go:align 32
|
||||
var descCDC0Tx [descCDCTxSize]uint8
|
||||
|
||||
// descCDC0Rq is the receive (Rx) transfer buffer for the default CDC-ACM
|
||||
// (single) device class configuration (index 1).
|
||||
//go:align 32
|
||||
var descCDC0Rq [descCDCRxSize]uint8
|
||||
|
||||
// descCDC0Tq is the transmit (Tx) transfer buffer for the default CDC-ACM
|
||||
// (single) device class configuration (index 1).
|
||||
//go:align 32
|
||||
var descCDC0Tq [descCDCTxSize]uint8
|
||||
|
||||
// descCDC0LC is the emulated UART's line coding configuration for the
|
||||
// default CDC-ACM (single) device class configuration (index 1).
|
||||
//go:align 32
|
||||
var descCDC0LC descCDCLineCoding
|
||||
|
||||
// descCDC0LS is the emulated UART's line state for the default CDC-ACM
|
||||
// (single) device class configuration (index 1).
|
||||
//go:align 32
|
||||
var descCDC0LS descCDCLineState
|
||||
|
||||
// descCDCState defines the state of the CDC-ACM handshake initialization.
|
||||
//
|
||||
// Many USB hosts will send a default SET_LINE_CODING prior to SET_LINE_STATE,
|
||||
// and then another SET_LINE_CODING containing the actual terminal settings.
|
||||
//
|
||||
// We do not want to start UART Rx/Tx transactions until after we have
|
||||
// received the final SET_LINE_CODING with the intended terminal settings.
|
||||
// Otherwise, the host may cancel any data transfers occurring during a change
|
||||
// in line state or line coding.
|
||||
//
|
||||
// The "set" method on type descCDCState defines this incremental state
|
||||
// machine, with the UART's current state stored in the volatile.Register8
|
||||
// field "st" of descCDCClassData.
|
||||
type descCDCState uint8
|
||||
|
||||
// set implements the state transition logic described in the godoc comment on
|
||||
// type descCDCState. Returns the value of the resulting state.
|
||||
//go:inline
|
||||
func (s *descCDCState) set(state descCDCState) descCDCState {
|
||||
if state > *s {
|
||||
// state must be incremented in-order. Otherwise, reset to initial state.
|
||||
if state == *s+1 {
|
||||
*s = state
|
||||
} else {
|
||||
var init descCDCState // Reset to zero-value of type.
|
||||
*s = init
|
||||
}
|
||||
}
|
||||
// Return a value for safely chaining the result.
|
||||
// (Not a pointer to the object we just modified.)
|
||||
return *s
|
||||
}
|
||||
|
||||
const (
|
||||
descCDCStateConfigured descCDCState = iota // Received SET_CONFIGURATION class request
|
||||
descCDCStateLineState // Received SET_LINE_STATE after Configured state
|
||||
descCDCStateLineCoding // Received SET_LINE_CODING after LineState state
|
||||
)
|
||||
|
||||
// descCDCClassData holds the buffers and control states for all CDC-ACM
|
||||
// (single) device class configurations, ordered by index (offset by -1), for
|
||||
// SAMx51 targets only.
|
||||
//
|
||||
// Instances of this type (elements of descCDCData) are embedded in elements
|
||||
// of the common/target-agnostic CDC-ACM class configurations (descCDC).
|
||||
// Methods defined on this type implement target-specific functionality, and
|
||||
// some of these methods are required by the common device controller driver.
|
||||
// Thus, this type functions as a hardware abstraction layer (HAL).
|
||||
type descCDCClassData struct {
|
||||
|
||||
// CDC-ACM Control Buffers
|
||||
|
||||
ed *[descCDCEDCount]dhwEPAddrDesc // endpoint descriptors
|
||||
|
||||
sx *[descCDCSxSize]uint8 // control endpoint 0 Rx (OUT) setup packets
|
||||
cx *[descCDCCxSize]uint8 // control endpoint 0 Tx (IN) control/status packets
|
||||
dx *[descCDCConfigSize]uint8 // control endpoint 0 Tx (IN) descriptor transfer buffer
|
||||
|
||||
// CDC-ACM Data Buffers
|
||||
|
||||
rx *[descCDCRxSize]uint8 // bulk data endpoint Rx (OUT) transfer buffer
|
||||
tx *[descCDCTxSize]uint8 // bulk data endpoint Tx (IN) transfer buffer
|
||||
|
||||
rxq *[descCDCRxSize]uint8 // CDC-ACM UART Rx FIFO
|
||||
txq *[descCDCTxSize]uint8 // CDC-ACM UART Tx FIFO
|
||||
|
||||
rq *Queue // CDC-ACM UART Rx Queue (backed by FIFO rxq)
|
||||
tq *Queue // CDC-ACM UART Tx Queue (backed by FIFO txq)
|
||||
|
||||
lc *descCDCLineCoding // UART line coding
|
||||
ls *descCDCLineState // UART line state
|
||||
|
||||
st volatile.Register8
|
||||
|
||||
sxSize uint32
|
||||
rxSize uint32
|
||||
txSize uint32
|
||||
}
|
||||
|
||||
// setState is a wrapper for converting and storing the given descCDCState
|
||||
// value as a uint8 in the receiver's volatile.Register8 field st.
|
||||
//go:inline
|
||||
func (c *descCDCClassData) setState(state descCDCState) {
|
||||
s := descCDCState(c.st.Get())
|
||||
c.st.Set(uint8(s.set(state)))
|
||||
}
|
||||
|
||||
// state is a wrapper for retrieving and converting the receiver's
|
||||
// volatile.Register8 field st from uint8 to descCDCState.
|
||||
//go:inline
|
||||
func (c *descCDCClassData) state() descCDCState {
|
||||
return descCDCState(c.st.Get())
|
||||
}
|
||||
|
||||
// descCDCData holds statically-allocated instances for each of the target-
|
||||
// specific (SAMx51) CDC-ACM (single) device class configurations' control and
|
||||
// data structures, ordered by configuration index (offset by -1). Each element
|
||||
// is embedded in a corresponding element of descCDC.
|
||||
var descCDCData = [dcdCount]descCDCClassData{
|
||||
|
||||
{ // -- CDC-ACM (single) Class Configuration Index 1 --
|
||||
|
||||
// CDC-ACM Control Buffers
|
||||
|
||||
ed: &descCDC0ED,
|
||||
|
||||
sx: &descCDC0Sx,
|
||||
cx: &descCDC0Cx,
|
||||
dx: &descCDC0Dx,
|
||||
|
||||
// CDC-ACM Data Buffers
|
||||
|
||||
rx: &descCDC0Rx,
|
||||
tx: &descCDC0Tx,
|
||||
|
||||
rxq: &descCDC0Rq,
|
||||
txq: &descCDC0Tq,
|
||||
|
||||
rq: &Queue{},
|
||||
tq: &Queue{},
|
||||
|
||||
lc: &descCDC0LC,
|
||||
ls: &descCDC0LS,
|
||||
|
||||
sxSize: descCDCStatusPacketSize,
|
||||
rxSize: descCDCDataRxPacketSize,
|
||||
txSize: descCDCDataTxPacketSize,
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user