Skip to content

Commit 0ce6776

Browse files
committed
refactor(usb): create usb.Controller interface for testing
1 parent ce8fca4 commit 0ce6776

File tree

14 files changed

+561
-38
lines changed

14 files changed

+561
-38
lines changed

src/machine/machine_atsamd21_usb.go

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ func handleUSBSetAddress(setup usb.Setup) bool {
336336
}
337337

338338
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
339-
func SendUSBInPacket(ep uint32, data []byte) bool {
339+
func (dev *USBDevice) SendUSBInPacket(ep uint32, data []byte) bool {
340340
sendUSBPacket(ep, data, 0)
341341

342342
// clear transfer complete flag
@@ -348,6 +348,10 @@ func SendUSBInPacket(ep uint32, data []byte) bool {
348348
return true
349349
}
350350

351+
func SendUSBInPacket(ep uint32, data []byte) bool {
352+
return USBDev.SendUSBInPacket(ep, data)
353+
}
354+
351355
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
352356
//
353357
//go:noinline
@@ -417,7 +421,7 @@ func handleEndpointRx(ep uint32) []byte {
417421
}
418422

419423
// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer.
420-
func AckUsbOutTransfer(ep uint32) {
424+
func (dev *USBDevice) AckUsbOutTransfer(ep uint32) {
421425
// set byte count to zero
422426
usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
423427

@@ -426,13 +430,20 @@ func AckUsbOutTransfer(ep uint32) {
426430

427431
// set ready for next data
428432
setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_BK0RDY)
433+
}
429434

435+
func AckUsbOutTransfer(ep uint32) {
436+
USBDev.AckUsbOutTransfer(ep)
430437
}
431438

432-
func SendZlp() {
439+
func (dev *USBDevice) SendZlp() {
433440
usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
434441
}
435442

443+
func SendZlp() {
444+
USBDev.SendZlp()
445+
}
446+
436447
func epPacketSize(size uint16) uint32 {
437448
switch size {
438449
case 8:
@@ -662,3 +673,23 @@ func setEPINTENSET(ep uint32, val uint8) {
662673
return
663674
}
664675
}
676+
677+
// Set ENDPOINT_HALT/stall status on a USB IN endpoint.
678+
func (dev *USBDevice) SetStallEPIn(ep uint32) {
679+
setEPSTATUSSET(ep, sam.USB_DEVICE_EPSTATUSSET_STALLRQ1)
680+
}
681+
682+
// Set ENDPOINT_HALT/stall status on a USB OUT endpoint.
683+
func (dev *USBDevice) SetStallEPOut(ep uint32) {
684+
setEPSTATUSSET(ep, sam.USB_DEVICE_EPSTATUSSET_STALLRQ0)
685+
}
686+
687+
// Clear the ENDPOINT_HALT/stall on a USB IN endpoint.
688+
func (dev *USBDevice) ClearStallEPIn(ep uint32) {
689+
setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_STALLRQ1)
690+
}
691+
692+
// Clear the ENDPOINT_HALT/stall on a USB OUT endpoint.
693+
func (dev *USBDevice) ClearStallEPOut(ep uint32) {
694+
setEPSTATUSCLR(ep, sam.USB_DEVICE_EPSTATUSCLR_STALLRQ0)
695+
}

src/machine/machine_atsamd51_usb.go

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ func handleUSBSetAddress(setup usb.Setup) bool {
339339
}
340340

341341
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
342-
func SendUSBInPacket(ep uint32, data []byte) bool {
342+
func (dev *USBDevice) SendUSBInPacket(ep uint32, data []byte) bool {
343343
sendUSBPacket(ep, data, 0)
344344

345345
// clear transfer complete flag
@@ -351,6 +351,10 @@ func SendUSBInPacket(ep uint32, data []byte) bool {
351351
return true
352352
}
353353

354+
func SendUSBInPacket(ep uint32, data []byte) bool {
355+
return USBDev.SendUSBInPacket(ep, data)
356+
}
357+
354358
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
355359
//
356360
//go:noinline
@@ -420,7 +424,7 @@ func handleEndpointRx(ep uint32) []byte {
420424
}
421425

422426
// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer.
423-
func AckUsbOutTransfer(ep uint32) {
427+
func (dev *USBDevice) AckUsbOutTransfer(ep uint32) {
424428
// set byte count to zero
425429
usbEndpointDescriptors[ep].DeviceDescBank[0].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
426430

@@ -431,10 +435,18 @@ func AckUsbOutTransfer(ep uint32) {
431435
setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_BK0RDY)
432436
}
433437

434-
func SendZlp() {
438+
func AckUsbOutTransfer(ep uint32) {
439+
USBDev.AckUsbOutTransfer(ep)
440+
}
441+
442+
func (dev *USBDevice) SendZlp() {
435443
usbEndpointDescriptors[0].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
436444
}
437445

446+
func SendZlp() {
447+
USBDev.SendZlp()
448+
}
449+
438450
func epPacketSize(size uint16) uint32 {
439451
switch size {
440452
case 8:
@@ -493,3 +505,23 @@ func setEPINTENCLR(ep uint32, val uint8) {
493505
func setEPINTENSET(ep uint32, val uint8) {
494506
sam.USB_DEVICE.DEVICE_ENDPOINT[ep].EPINTENSET.Set(val)
495507
}
508+
509+
// Set ENDPOINT_HALT/stall status on a USB IN endpoint.
510+
func (dev *USBDevice) SetStallEPIn(ep uint32) {
511+
setEPSTATUSSET(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_STALLRQ1)
512+
}
513+
514+
// Set ENDPOINT_HALT/stall status on a USB OUT endpoint.
515+
func (dev *USBDevice) SetStallEPOut(ep uint32) {
516+
setEPSTATUSSET(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_STALLRQ0)
517+
}
518+
519+
// Clear the ENDPOINT_HALT/stall on a USB IN endpoint.
520+
func (dev *USBDevice) ClearStallEPIn(ep uint32) {
521+
setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_STALLRQ1)
522+
}
523+
524+
// Clear the ENDPOINT_HALT/stall on a USB OUT endpoint.
525+
func (dev *USBDevice) ClearStallEPOut(ep uint32) {
526+
setEPSTATUSCLR(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSCLR_STALLRQ0)
527+
}

src/machine/machine_nrf52840_usb.go

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ func initEndpoint(ep, config uint32) {
255255
}
256256

257257
// SendUSBInPacket sends a packet for USBHID (interrupt in / bulk in).
258-
func SendUSBInPacket(ep uint32, data []byte) bool {
258+
func (dev *USBDevice) SendUSBInPacket(ep uint32, data []byte) bool {
259259
sendUSBPacket(ep, data, 0)
260260

261261
// clear transfer complete flag
@@ -264,6 +264,10 @@ func SendUSBInPacket(ep uint32, data []byte) bool {
264264
return true
265265
}
266266

267+
func SendUSBInPacket(ep uint32, data []byte) bool {
268+
return USBDev.SendUSBInPacket(ep, data)
269+
}
270+
267271
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
268272
//
269273
//go:noinline
@@ -304,15 +308,47 @@ func handleEndpointRx(ep uint32) []byte {
304308
}
305309

306310
// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer.
307-
func AckUsbOutTransfer(ep uint32) {
311+
func (dev *USBDevice) AckUsbOutTransfer(ep uint32) {
308312
// set ready for next data
309313
nrf.USBD.SIZE.EPOUT[ep].Set(0)
310314
}
311315

312-
func SendZlp() {
316+
func AckUsbOutTransfer(ep uint32) {
317+
USBDev.AckUsbOutTransfer(ep)
318+
}
319+
320+
func (dev *USBDevice) SendZlp() {
313321
nrf.USBD.TASKS_EP0STATUS.Set(1)
314322
}
315323

324+
func SendZlp() {
325+
USBDev.SendZlp()
326+
}
327+
328+
// Set ENDPOINT_HALT/stall status on a USB IN endpoint.
329+
func (dev *USBDevice) SetStallEPIn(ep uint32) {
330+
// Bit 8 is STALL, Bit 7 is IO (1 for IN), Bits 0-2 are EP number.
331+
nrf.USBD.EPSTALL.Set((1 << 8) | (1 << 7) | (ep & 0x7))
332+
}
333+
334+
// Set ENDPOINT_HALT/stall status on a USB OUT endpoint.
335+
func (dev *USBDevice) SetStallEPOut(ep uint32) {
336+
// Bit 8 is STALL, Bit 7 is IO (0 for OUT), Bits 0-2 are EP number.
337+
nrf.USBD.EPSTALL.Set((1 << 8) | (0 << 7) | (ep & 0x7))
338+
}
339+
340+
// Clear the ENDPOINT_HALT/stall on a USB IN endpoint.
341+
func (dev *USBDevice) ClearStallEPIn(ep uint32) {
342+
// Bit 8 is STALL (0 for UnStall), Bit 7 is IO (1 for IN), Bits 0-2 are EP number.
343+
nrf.USBD.EPSTALL.Set((0 << 8) | (1 << 7) | (ep & 0x7))
344+
}
345+
346+
// Clear the ENDPOINT_HALT/stall on a USB OUT endpoint.
347+
func (dev *USBDevice) ClearStallEPOut(ep uint32) {
348+
// Bit 8 is STALL (0 for UnStall), Bit 7 is IO (0 for OUT), Bits 0-2 are EP number.
349+
nrf.USBD.EPSTALL.Set((0 << 8) | (0 << 7) | (ep & 0x7))
350+
}
351+
316352
func sendViaEPIn(ep uint32, ptr *byte, count int) {
317353
nrf.USBD.EPIN[ep].PTR.Set(
318354
uint32(uintptr(unsafe.Pointer(ptr))),

src/machine/machine_rp2_usb.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,15 @@ func initEndpoint(ep, config uint32) {
7171
}
7272

7373
// SendUSBInPacket sends a packet for USB (interrupt in / bulk in).
74-
func SendUSBInPacket(ep uint32, data []byte) bool {
74+
func (dev *USBDevice) SendUSBInPacket(ep uint32, data []byte) bool {
7575
sendUSBPacket(ep, data, 0)
7676
return true
7777
}
7878

79+
func SendUSBInPacket(ep uint32, data []byte) bool {
80+
return USBDev.SendUSBInPacket(ep, data)
81+
}
82+
7983
// Prevent file size increases: https://github.com/tinygo-org/tinygo/pull/998
8084
//
8185
//go:noinline
@@ -129,11 +133,15 @@ func handleEndpointRx(ep uint32) []byte {
129133
}
130134

131135
// AckUsbOutTransfer is called to acknowledge the completion of a USB OUT transfer.
132-
func AckUsbOutTransfer(ep uint32) {
136+
func (dev *USBDevice) AckUsbOutTransfer(ep uint32) {
133137
ep = ep & 0x7F
134138
setEPDataPID(ep, !epXdata0[ep])
135139
}
136140

141+
func AckUsbOutTransfer(ep uint32) {
142+
USBDev.AckUsbOutTransfer(ep)
143+
}
144+
137145
// Set the USB endpoint Packet ID to DATA0 or DATA1.
138146
func setEPDataPID(ep uint32, dataOne bool) {
139147
epXdata0[ep] = dataOne
@@ -144,10 +152,14 @@ func setEPDataPID(ep uint32, dataOne bool) {
144152
_usbDPSRAM.EPxBufferControl[ep].Out.SetBits(usbBuf0CtrlAvail)
145153
}
146154

147-
func SendZlp() {
155+
func (dev *USBDevice) SendZlp() {
148156
sendUSBPacket(0, []byte{}, 0)
149157
}
150158

159+
func SendZlp() {
160+
USBDev.SendZlp()
161+
}
162+
151163
func sendViaEPIn(ep uint32, data []byte, count int) {
152164
// Prepare buffer control register value
153165
val := uint32(count) | usbBuf0CtrlAvail

src/machine/usb.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ var (
1919
USBCDC Serialer
2020
)
2121

22+
func init() {
23+
usb.DefaultController = USBDev
24+
}
25+
2226
type Serialer interface {
2327
WriteByte(c byte) error
2428
Write(data []byte) (n int, err error)
@@ -274,6 +278,10 @@ func handleStandardSetup(setup usb.Setup) bool {
274278
}
275279
}
276280

281+
func (d *USBDevice) IsInitEndpointComplete() bool {
282+
return d.InitEndpointComplete
283+
}
284+
277285
func EnableCDC(txHandler func(), rxHandler func([]byte), setupHandler func(usb.Setup) bool) {
278286
if len(usbDescriptor.Device) == 0 {
279287
usbDescriptor = descriptor.CDC
@@ -308,6 +316,10 @@ func EnableCDC(txHandler func(), rxHandler func([]byte), setupHandler func(usb.S
308316
}
309317

310318
func ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []usb.EndpointConfig, setup []usb.SetupConfig) {
319+
USBDev.ConfigureUSBEndpoint(desc, epSettings, setup)
320+
}
321+
322+
func (d *USBDevice) ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []usb.EndpointConfig, setup []usb.SetupConfig) {
311323
usbDescriptor = desc
312324

313325
for _, ep := range epSettings {

src/machine/usb/device.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package usb
2+
3+
import (
4+
"machine/usb/descriptor"
5+
)
6+
7+
// Controller abstracts the USB interactions to allow for testing without hardware.
8+
type Controller interface {
9+
ConfigureUSBEndpoint(desc descriptor.Descriptor, epSettings []EndpointConfig, setup []SetupConfig)
10+
SendUSBInPacket(ep uint32, data []byte) bool
11+
AckUsbOutTransfer(ep uint32)
12+
SendZlp()
13+
IsInitEndpointComplete() bool
14+
SetStallEPIn(ep uint32)
15+
SetStallEPOut(ep uint32)
16+
ClearStallEPIn(ep uint32)
17+
ClearStallEPOut(ep uint32)
18+
}
19+
20+
var DefaultController Controller

src/machine/usb/msc/disk.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/binary"
55
"errors"
66
"fmt"
7-
"machine"
87
"time"
98
)
109

@@ -13,7 +12,7 @@ var (
1312
)
1413

1514
// RegisterBlockDevice registers a BlockDevice provider with the MSC driver
16-
func (m *msc) RegisterBlockDevice(dev machine.BlockDevice) {
15+
func (m *msc) RegisterBlockDevice(dev BlockDevice) {
1716
m.dev = dev
1817

1918
if cap(m.blockCache) != int(dev.WriteBlockSize()) {
@@ -56,11 +55,11 @@ func (m *msc) RegisterBlockDevice(dev machine.BlockDevice) {
5655
}
5756
}
5857

59-
var _ machine.BlockDevice = (*RecorderDisk)(nil)
58+
var _ BlockDevice = (*RecorderDisk)(nil)
6059

6160
// RecorderDisk is a block device that records actions taken on it
6261
type RecorderDisk struct {
63-
dev machine.BlockDevice
62+
dev BlockDevice
6463
log []RecorderRecord
6564
last time.Time
6665
time time.Time
@@ -84,7 +83,7 @@ const (
8483
)
8584

8685
// NewRecorderDisk creates a new RecorderDisk instance
87-
func NewRecorderDisk(dev machine.BlockDevice, count int) *RecorderDisk {
86+
func NewRecorderDisk(dev BlockDevice, count int) *RecorderDisk {
8887
d := &RecorderDisk{
8988
dev: dev,
9089
log: make([]RecorderRecord, 0, count),

src/machine/usb/msc/interfaces.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package msc
2+
3+
import (
4+
"io"
5+
)
6+
7+
// BlockDevice is the raw device that is meant to store flash data.
8+
// It mimics the interface defined in machine/flash.go to allow for decoupling.
9+
type BlockDevice interface {
10+
// ReadAt reads the given number of bytes from the block device.
11+
io.ReaderAt
12+
13+
// WriteAt writes the given number of bytes to the block device.
14+
io.WriterAt
15+
16+
// Size returns the number of bytes in this block device.
17+
Size() int64
18+
19+
// WriteBlockSize returns the block size in which data can be written to
20+
// memory. It can be used by a client to optimize writes, non-aligned writes
21+
// should always work correctly.
22+
WriteBlockSize() int64
23+
24+
// EraseBlockSize returns the smallest erasable area on this particular chip
25+
// in bytes. This is used for the block size in EraseBlocks.
26+
// It must be a power of two, and may be as small as 1. A typical size is 4096.
27+
EraseBlockSize() int64
28+
29+
// EraseBlocks erases the given number of blocks. An implementation may
30+
// transparently coalesce ranges of blocks into larger bundles if the chip
31+
// supports this. The start and len parameters are in block numbers, use
32+
// EraseBlockSize to map addresses to blocks.
33+
EraseBlocks(start, len int64) error
34+
}

0 commit comments

Comments
 (0)