Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,10 @@ smoketest:
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=pca10040 examples/test
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=wioterminal examples/hid-mouse
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=wioterminal examples/hid-keyboard
@$(MD5SUM) test.hex
# test simulated boards on play.tinygo.org
ifneq ($(WASM), 0)
$(TINYGO) build -size short -o test.wasm -tags=arduino examples/blinky1
Expand Down Expand Up @@ -555,6 +559,11 @@ endif
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=feather-m4 examples/pwm
@$(MD5SUM) test.hex
# test usbhid
$(TINYGO) build -size short -o test.hex -target=feather-nrf52840 examples/hid-keyboard
@$(MD5SUM) test.hex
$(TINYGO) build -size short -o test.hex -target=circuitplay-express examples/hid-keyboard
@$(MD5SUM) test.hex
ifneq ($(STM32), 0)
$(TINYGO) build -size short -o test.hex -target=bluepill examples/blinky1
@$(MD5SUM) test.hex
Expand Down
21 changes: 21 additions & 0 deletions src/examples/hid-keyboard/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"machine"
"machine/usb/hid/keyboard"
"time"
)

func main() {
button := machine.BUTTON
button.Configure(machine.PinConfig{Mode: machine.PinInputPullup})

kb := keyboard.New()

for {
if !button.Get() {
kb.Write([]byte("tinygo"))
time.Sleep(200 * time.Millisecond)
}
}
}
37 changes: 37 additions & 0 deletions src/examples/hid-mouse/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import (
"machine"
"machine/usb/hid/mouse"
"time"
)

func main() {
button := machine.BUTTON
button.Configure(machine.PinConfig{Mode: machine.PinInputPullup})

mouse := mouse.New()

for {
if !button.Get() {
for j := 0; j < 5; j++ {
for i := 0; i < 100; i++ {
mouse.Move(1, 0)
time.Sleep(1 * time.Millisecond)
}

for i := 0; i < 100; i++ {
mouse.Move(0, 1)
time.Sleep(1 * time.Millisecond)
}

for i := 0; i < 100; i++ {
mouse.Move(-1, -1)
time.Sleep(1 * time.Millisecond)
}
}

time.Sleep(100 * time.Millisecond)
}
}
}
53 changes: 45 additions & 8 deletions src/machine/machine_atsamd21.go
Original file line number Diff line number Diff line change
Expand Up @@ -1746,7 +1746,8 @@ type USBCDC struct {
}

var (
USB = &USBCDC{Buffer: NewRingBuffer()}
USB = &USBCDC{Buffer: NewRingBuffer()}
waitHidTxc bool
)

const (
Expand Down Expand Up @@ -1999,6 +2000,9 @@ func handleUSB(intr interrupt.Interrupt) {
if (flags & sam.USB_DEVICE_INTFLAG_SOF) > 0 {
USB.Flush()
// if you want to blink LED showing traffic, this would be the place...
if hidCallback != nil && !waitHidTxc {
hidCallback()
}
}

// Endpoint 0 Setup interrupt
Expand All @@ -2021,6 +2025,9 @@ func handleUSB(intr interrupt.Interrupt) {
// Class Interface Requests
if setup.wIndex == usb_CDC_ACM_INTERFACE {
ok = cdcSetup(setup)
} else if setup.bmRequestType == usb_SET_REPORT_TYPE && setup.bRequest == usb_SET_IDLE {
sendZlp()
ok = true
}
}

Expand Down Expand Up @@ -2059,6 +2066,9 @@ func handleUSB(intr interrupt.Interrupt) {
if i == usb_CDC_ENDPOINT_IN {
USB.waitTxc = false
}
case usb_HID_ENDPOINT_IN:
setEPINTFLAG(i, sam.USB_DEVICE_EPINTFLAG_TRCPT1)
waitHidTxc = false
}
}
}
Expand Down Expand Up @@ -2156,7 +2166,7 @@ func handleStandardSetup(setup usbSetup) bool {
}
}

sendUSBPacket(0, buf)
sendUSBPacket(0, buf, setup.wLength)
return true

case usb_CLEAR_FEATURE:
Expand Down Expand Up @@ -2212,7 +2222,7 @@ func handleStandardSetup(setup usbSetup) bool {

case usb_GET_CONFIGURATION:
buff := []byte{usbConfiguration}
sendUSBPacket(0, buff)
sendUSBPacket(0, buff, setup.wLength)
return true

case usb_SET_CONFIGURATION:
Expand All @@ -2229,6 +2239,11 @@ func handleStandardSetup(setup usbSetup) bool {
// Enable interrupt for CDC data messages from host
setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_EPINTENSET_TRCPT0)

// Enable interrupt for HID messages from host
if hidCallback != nil {
setEPINTENSET(usb_HID_ENDPOINT_IN, sam.USB_DEVICE_EPINTENSET_TRCPT1)
}

sendZlp()
return true
} else {
Expand All @@ -2237,7 +2252,7 @@ func handleStandardSetup(setup usbSetup) bool {

case usb_GET_INTERFACE:
buff := []byte{usbSetInterface}
sendUSBPacket(0, buff)
sendUSBPacket(0, buff, setup.wLength)
return true

case usb_SET_INTERFACE:
Expand All @@ -2263,7 +2278,7 @@ func cdcSetup(setup usbSetup) bool {
b[5] = byte(usbLineInfo.bParityType)
b[6] = byte(usbLineInfo.bDataBits)

sendUSBPacket(0, b[:])
sendUSBPacket(0, b[:], setup.wLength)
return true
}
}
Expand Down Expand Up @@ -2306,9 +2321,31 @@ func cdcSetup(setup usbSetup) bool {
return false
}

// SendUSBHIDPacket sends a packet for USBHID (interrupt / in).
func SendUSBHIDPacket(ep uint32, data []byte) bool {
if waitHidTxc {
return false
}
sendUSBPacket(ep, data, 0)

// clear transfer complete flag
setEPINTFLAG(ep, sam.USB_DEVICE_EPINTFLAG_TRCPT1)

// send data by setting bank ready
setEPSTATUSSET(ep, sam.USB_DEVICE_EPSTATUSSET_BK1RDY)

waitHidTxc = true

return true
}

//go:noinline
func sendUSBPacket(ep uint32, data []byte) {
copy(udd_ep_in_cache_buffer[ep][:], data)
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
l := uint16(len(data))
if 0 < maxsize && maxsize < l {
l = maxsize
}
copy(udd_ep_in_cache_buffer[ep][:], data[:l])

// Set endpoint address for sending data
usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))
Expand All @@ -2318,7 +2355,7 @@ func sendUSBPacket(ep uint32, data []byte) {

// set byte count, which is total number of bytes to be sent
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(uint32((len(data) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask) << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos))
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits((uint32(l) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask) << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
}

func receiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {
Expand Down
54 changes: 46 additions & 8 deletions src/machine/machine_atsamd51.go
Original file line number Diff line number Diff line change
Expand Up @@ -1987,7 +1987,8 @@ type USBCDC struct {

var (
// USB is a USB CDC interface.
USB = &USBCDC{Buffer: NewRingBuffer()}
USB = &USBCDC{Buffer: NewRingBuffer()}
waitHidTxc bool
)

const (
Expand Down Expand Up @@ -2241,6 +2242,9 @@ func handleUSBIRQ(interrupt.Interrupt) {
// Start of frame
if (flags & sam.USB_DEVICE_INTFLAG_SOF) > 0 {
USB.Flush()
if hidCallback != nil && !waitHidTxc {
hidCallback()
}
// if you want to blink LED showing traffic, this would be the place...
}

Expand All @@ -2264,6 +2268,9 @@ func handleUSBIRQ(interrupt.Interrupt) {
// Class Interface Requests
if setup.wIndex == usb_CDC_ACM_INTERFACE {
ok = cdcSetup(setup)
} else if setup.bmRequestType == usb_SET_REPORT_TYPE && setup.bRequest == usb_SET_IDLE {
sendZlp()
ok = true
}
}

Expand Down Expand Up @@ -2302,6 +2309,9 @@ func handleUSBIRQ(interrupt.Interrupt) {
if i == usb_CDC_ENDPOINT_IN {
USB.waitTxc = false
}
case usb_HID_ENDPOINT_IN:
setEPINTFLAG(i, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1)
waitHidTxc = false
}
}
}
Expand Down Expand Up @@ -2399,7 +2409,7 @@ func handleStandardSetup(setup usbSetup) bool {
}
}

sendUSBPacket(0, buf)
sendUSBPacket(0, buf, setup.wLength)
return true

case usb_CLEAR_FEATURE:
Expand Down Expand Up @@ -2455,7 +2465,7 @@ func handleStandardSetup(setup usbSetup) bool {

case usb_GET_CONFIGURATION:
buff := []byte{usbConfiguration}
sendUSBPacket(0, buff)
sendUSBPacket(0, buff, setup.wLength)
return true

case usb_SET_CONFIGURATION:
Expand All @@ -2472,6 +2482,11 @@ func handleStandardSetup(setup usbSetup) bool {
// Enable interrupt for CDC data messages from host
setEPINTENSET(usb_CDC_ENDPOINT_OUT, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT0)

// Enable interrupt for HID messages from host
if hidCallback != nil {
setEPINTENSET(usb_HID_ENDPOINT_IN, sam.USB_DEVICE_ENDPOINT_EPINTENSET_TRCPT1)
}

sendZlp()
return true
} else {
Expand All @@ -2480,7 +2495,7 @@ func handleStandardSetup(setup usbSetup) bool {

case usb_GET_INTERFACE:
buff := []byte{usbSetInterface}
sendUSBPacket(0, buff)
sendUSBPacket(0, buff, setup.wLength)
return true

case usb_SET_INTERFACE:
Expand All @@ -2506,7 +2521,7 @@ func cdcSetup(setup usbSetup) bool {
b[5] = byte(usbLineInfo.bParityType)
b[6] = byte(usbLineInfo.bDataBits)

sendUSBPacket(0, b[:])
sendUSBPacket(0, b[:], setup.wLength)
return true
}
}
Expand Down Expand Up @@ -2549,9 +2564,32 @@ func cdcSetup(setup usbSetup) bool {
return false
}

// SendUSBHIDPacket sends a packet for USBHID (interrupt / in).
func SendUSBHIDPacket(ep uint32, data []byte) bool {
if waitHidTxc {
return false
}

sendUSBPacket(ep, data, 0)

// clear transfer complete flag
setEPINTFLAG(ep, sam.USB_DEVICE_ENDPOINT_EPINTFLAG_TRCPT1)

// send data by setting bank ready
setEPSTATUSSET(ep, sam.USB_DEVICE_ENDPOINT_EPSTATUSSET_BK1RDY)

waitHidTxc = true

return true
}

//go:noinline
func sendUSBPacket(ep uint32, data []byte) {
copy(udd_ep_in_cache_buffer[ep][:], data)
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
l := uint16(len(data))
if 0 < maxsize && maxsize < l {
l = maxsize
}
copy(udd_ep_in_cache_buffer[ep][:], data[:l])

// Set endpoint address for sending data
usbEndpointDescriptors[ep].DeviceDescBank[1].ADDR.Set(uint32(uintptr(unsafe.Pointer(&udd_ep_in_cache_buffer[ep]))))
Expand All @@ -2561,7 +2599,7 @@ func sendUSBPacket(ep uint32, data []byte) {

// set byte count, which is total number of bytes to be sent
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.ClearBits(usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits(uint32((len(data) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask) << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos))
usbEndpointDescriptors[ep].DeviceDescBank[1].PCKSIZE.SetBits((uint32(l) & usb_DEVICE_PCKSIZE_BYTE_COUNT_Mask) << usb_DEVICE_PCKSIZE_BYTE_COUNT_Pos)
}

func receiveUSBControlPacket() ([cdcLineInfoSize]byte, error) {
Expand Down
Loading