samd21,samd51,nrf52840: add support for USBHID (keyboard / mouse)

Этот коммит содержится в:
sago35 2022-06-02 08:29:13 +09:00 коммит произвёл Ron Evans
родитель 2c93a4085c
коммит 1b2e764835
13 изменённых файлов: 1510 добавлений и 479 удалений

Просмотреть файл

@ -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
@ -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

21
src/examples/hid-keyboard/main.go Обычный файл
Просмотреть файл

@ -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
src/examples/hid-mouse/main.go Обычный файл
Просмотреть файл

@ -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)
}
}
}

Просмотреть файл

@ -1746,7 +1746,8 @@ type USBCDC struct {
}
var (
USB = &USBCDC{Buffer: NewRingBuffer()}
USB = &USBCDC{Buffer: NewRingBuffer()}
waitHidTxc bool
)
const (
@ -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
@ -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
}
}
@ -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
}
}
}
@ -2156,7 +2166,7 @@ func handleStandardSetup(setup usbSetup) bool {
}
}
sendUSBPacket(0, buf)
sendUSBPacket(0, buf, setup.wLength)
return true
case usb_CLEAR_FEATURE:
@ -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:
@ -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 {
@ -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:
@ -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
}
}
@ -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]))))
@ -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) {

Просмотреть файл

@ -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 (
@ -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...
}
@ -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
}
}
@ -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
}
}
}
@ -2399,7 +2409,7 @@ func handleStandardSetup(setup usbSetup) bool {
}
}
sendUSBPacket(0, buf)
sendUSBPacket(0, buf, setup.wLength)
return true
case usb_CLEAR_FEATURE:
@ -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:
@ -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 {
@ -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:
@ -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
}
}
@ -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]))))
@ -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) {

Просмотреть файл

@ -121,8 +121,9 @@ func (usbcdc *USBCDC) RTS() bool {
}
var (
USB = &_USB
_USB = USBCDC{Buffer: NewRingBuffer()}
USB = &_USB
_USB = USBCDC{Buffer: NewRingBuffer()}
waitHidTxc bool
usbEndpointDescriptors [8]usbDeviceDescriptor
@ -201,6 +202,9 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
if nrf.USBD.EVENTS_SOF.Get() == 1 {
nrf.USBD.EVENTS_SOF.Set(0)
usbcdc.Flush()
if hidCallback != nil && !waitHidTxc {
hidCallback()
}
// if you want to blink LED showing traffic, this would be the place...
}
@ -262,6 +266,9 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
} else {
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
}
}
@ -297,6 +304,8 @@ func (usbcdc *USBCDC) handleInterrupt(interrupt.Interrupt) {
usbcdc.waitTxc = false
exitCriticalSection()
}
case usb_HID_ENDPOINT_IN:
waitHidTxc = false
}
}
}
@ -378,7 +387,7 @@ func handleStandardSetup(setup usbSetup) bool {
}
}
sendUSBPacket(0, buf)
sendUSBPacket(0, buf, setup.wLength)
return true
case usb_CLEAR_FEATURE:
@ -412,7 +421,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:
@ -422,6 +431,11 @@ func handleStandardSetup(setup usbSetup) bool {
initEndpoint(uint32(i), endPoints[i])
}
// Enable interrupt for HID messages from host
if hidCallback != nil {
nrf.USBD.INTENSET.Set(nrf.USBD_INTENSET_ENDEPOUT0 << usb_HID_ENDPOINT_IN)
}
usbConfiguration = setup.wValueL
return true
} else {
@ -430,7 +444,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:
@ -456,7 +470,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
}
}
@ -482,10 +496,29 @@ 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
nrf.USBD.INTENCLR.Set(nrf.USBD_INTENCLR_ENDEPOUT0 << 4)
waitHidTxc = true
return true
}
//go:noinline
func sendUSBPacket(ep uint32, data []byte) {
func sendUSBPacket(ep uint32, data []byte, maxsize uint16) {
count := len(data)
copy(udd_ep_in_cache_buffer[ep][:], data)
if 0 < int(maxsize) && int(maxsize) < count {
count = int(maxsize)
}
copy(udd_ep_in_cache_buffer[ep][:], data[:count])
if ep == 0 && count > usbEndpointPacketSize {
sendOnEP0DATADONE.ptr = &udd_ep_in_cache_buffer[ep][usbEndpointPacketSize]
sendOnEP0DATADONE.count = count - usbEndpointPacketSize

Просмотреть файл

@ -8,7 +8,7 @@ import (
"runtime/volatile"
)
const deviceDescriptorSize = 18
var usbDescriptor = descriptorCDC
var (
errUSBCDCBufferEmpty = errors.New("USB-CDC buffer empty")
@ -17,397 +17,6 @@ var (
errUSBCDCBytesRead = errors.New("USB-CDC invalid number of bytes read")
)
// DeviceDescriptor implements the USB standard device descriptor.
//
// Table 9-8. Standard Device Descriptor
// bLength, bDescriptorType, bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0,
// idVendor, idProduct, bcdDevice, iManufacturer, iProduct, iSerialNumber, bNumConfigurations */
//
type DeviceDescriptor struct {
bLength uint8 // 18
bDescriptorType uint8 // 1 USB_DEVICE_DESCRIPTOR_TYPE
bcdUSB uint16 // 0x200
bDeviceClass uint8
bDeviceSubClass uint8
bDeviceProtocol uint8
bMaxPacketSize0 uint8 // Packet 0
idVendor uint16
idProduct uint16
bcdDevice uint16 // 0x100
iManufacturer uint8
iProduct uint8
iSerialNumber uint8
bNumConfigurations uint8
}
// NewDeviceDescriptor returns a USB DeviceDescriptor.
func NewDeviceDescriptor(class, subClass, proto, packetSize0 uint8, vid, pid, version uint16, im, ip, is, configs uint8) DeviceDescriptor {
return DeviceDescriptor{deviceDescriptorSize, 1, 0x200, class, subClass, proto, packetSize0, vid, pid, version, im, ip, is, configs}
}
// Bytes returns DeviceDescriptor data
func (d DeviceDescriptor) Bytes() [deviceDescriptorSize]byte {
var b [deviceDescriptorSize]byte
b[0] = byte(d.bLength)
b[1] = byte(d.bDescriptorType)
b[2] = byte(d.bcdUSB)
b[3] = byte(d.bcdUSB >> 8)
b[4] = byte(d.bDeviceClass)
b[5] = byte(d.bDeviceSubClass)
b[6] = byte(d.bDeviceProtocol)
b[7] = byte(d.bMaxPacketSize0)
b[8] = byte(d.idVendor)
b[9] = byte(d.idVendor >> 8)
b[10] = byte(d.idProduct)
b[11] = byte(d.idProduct >> 8)
b[12] = byte(d.bcdDevice)
b[13] = byte(d.bcdDevice >> 8)
b[14] = byte(d.iManufacturer)
b[15] = byte(d.iProduct)
b[16] = byte(d.iSerialNumber)
b[17] = byte(d.bNumConfigurations)
return b
}
const configDescriptorSize = 9
// ConfigDescriptor implements the standard USB configuration descriptor.
//
// Table 9-10. Standard Configuration Descriptor
// bLength, bDescriptorType, wTotalLength, bNumInterfaces, bConfigurationValue, iConfiguration
// bmAttributes, bMaxPower
//
type ConfigDescriptor struct {
bLength uint8 // 9
bDescriptorType uint8 // 2
wTotalLength uint16 // total length
bNumInterfaces uint8
bConfigurationValue uint8
iConfiguration uint8
bmAttributes uint8
bMaxPower uint8
}
// NewConfigDescriptor returns a new USB ConfigDescriptor.
func NewConfigDescriptor(totalLength uint16, interfaces uint8) ConfigDescriptor {
return ConfigDescriptor{configDescriptorSize, 2, totalLength, interfaces, 1, 0, usb_CONFIG_BUS_POWERED | usb_CONFIG_REMOTE_WAKEUP, 50}
}
// Bytes returns ConfigDescriptor data.
func (d ConfigDescriptor) Bytes() [configDescriptorSize]byte {
var b [configDescriptorSize]byte
b[0] = byte(d.bLength)
b[1] = byte(d.bDescriptorType)
b[2] = byte(d.wTotalLength)
b[3] = byte(d.wTotalLength >> 8)
b[4] = byte(d.bNumInterfaces)
b[5] = byte(d.bConfigurationValue)
b[6] = byte(d.iConfiguration)
b[7] = byte(d.bmAttributes)
b[8] = byte(d.bMaxPower)
return b
}
const interfaceDescriptorSize = 9
// InterfaceDescriptor implements the standard USB interface descriptor.
//
// Table 9-12. Standard Interface Descriptor
// bLength, bDescriptorType, bInterfaceNumber, bAlternateSetting, bNumEndpoints, bInterfaceClass,
// bInterfaceSubClass, bInterfaceProtocol, iInterface
//
type InterfaceDescriptor struct {
bLength uint8 // 9
bDescriptorType uint8 // 4
bInterfaceNumber uint8
bAlternateSetting uint8
bNumEndpoints uint8
bInterfaceClass uint8
bInterfaceSubClass uint8
bInterfaceProtocol uint8
iInterface uint8
}
// NewInterfaceDescriptor returns a new USB InterfaceDescriptor.
func NewInterfaceDescriptor(n, numEndpoints, class, subClass, protocol uint8) InterfaceDescriptor {
return InterfaceDescriptor{interfaceDescriptorSize, 4, n, 0, numEndpoints, class, subClass, protocol, 0}
}
// Bytes returns InterfaceDescriptor data.
func (d InterfaceDescriptor) Bytes() [interfaceDescriptorSize]byte {
var b [interfaceDescriptorSize]byte
b[0] = byte(d.bLength)
b[1] = byte(d.bDescriptorType)
b[2] = byte(d.bInterfaceNumber)
b[3] = byte(d.bAlternateSetting)
b[4] = byte(d.bNumEndpoints)
b[5] = byte(d.bInterfaceClass)
b[6] = byte(d.bInterfaceSubClass)
b[7] = byte(d.bInterfaceProtocol)
b[8] = byte(d.iInterface)
return b
}
const endpointDescriptorSize = 7
// EndpointDescriptor implements the standard USB endpoint descriptor.
//
// Table 9-13. Standard Endpoint Descriptor
// bLength, bDescriptorType, bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval
//
type EndpointDescriptor struct {
bLength uint8 // 7
bDescriptorType uint8 // 5
bEndpointAddress uint8
bmAttributes uint8
wMaxPacketSize uint16
bInterval uint8
}
// NewEndpointDescriptor returns a new USB EndpointDescriptor.
func NewEndpointDescriptor(addr, attr uint8, packetSize uint16, interval uint8) EndpointDescriptor {
return EndpointDescriptor{endpointDescriptorSize, 5, addr, attr, packetSize, interval}
}
// Bytes returns EndpointDescriptor data.
func (d EndpointDescriptor) Bytes() [endpointDescriptorSize]byte {
var b [endpointDescriptorSize]byte
b[0] = byte(d.bLength)
b[1] = byte(d.bDescriptorType)
b[2] = byte(d.bEndpointAddress)
b[3] = byte(d.bmAttributes)
b[4] = byte(d.wMaxPacketSize)
b[5] = byte(d.wMaxPacketSize >> 8)
b[6] = byte(d.bInterval)
return b
}
const iadDescriptorSize = 8
// IADDescriptor is an Interface Association Descriptor, which is used
// to bind 2 interfaces together in CDC composite device.
//
// Standard Interface Association Descriptor:
// bLength, bDescriptorType, bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass,
// bFunctionProtocol, iFunction
//
type IADDescriptor struct {
bLength uint8 // 8
bDescriptorType uint8 // 11
bFirstInterface uint8
bInterfaceCount uint8
bFunctionClass uint8
bFunctionSubClass uint8
bFunctionProtocol uint8
iFunction uint8
}
// NewIADDescriptor returns a new USB IADDescriptor.
func NewIADDescriptor(firstInterface, count, class, subClass, protocol uint8) IADDescriptor {
return IADDescriptor{iadDescriptorSize, 11, firstInterface, count, class, subClass, protocol, 0}
}
// Bytes returns IADDescriptor data.
func (d IADDescriptor) Bytes() [iadDescriptorSize]byte {
var b [iadDescriptorSize]byte
b[0] = byte(d.bLength)
b[1] = byte(d.bDescriptorType)
b[2] = byte(d.bFirstInterface)
b[3] = byte(d.bInterfaceCount)
b[4] = byte(d.bFunctionClass)
b[5] = byte(d.bFunctionSubClass)
b[6] = byte(d.bFunctionProtocol)
b[7] = byte(d.iFunction)
return b
}
const cdcCSInterfaceDescriptorSize = 5
// CDCCSInterfaceDescriptor is a CDC CS interface descriptor.
type CDCCSInterfaceDescriptor struct {
len uint8 // 5
dtype uint8 // 0x24
subtype uint8
d0 uint8
d1 uint8
}
// NewCDCCSInterfaceDescriptor returns a new USB CDCCSInterfaceDescriptor.
func NewCDCCSInterfaceDescriptor(subtype, d0, d1 uint8) CDCCSInterfaceDescriptor {
return CDCCSInterfaceDescriptor{cdcCSInterfaceDescriptorSize, 0x24, subtype, d0, d1}
}
// Bytes returns CDCCSInterfaceDescriptor data.
func (d CDCCSInterfaceDescriptor) Bytes() [cdcCSInterfaceDescriptorSize]byte {
var b [cdcCSInterfaceDescriptorSize]byte
b[0] = byte(d.len)
b[1] = byte(d.dtype)
b[2] = byte(d.subtype)
b[3] = byte(d.d0)
b[4] = byte(d.d1)
return b
}
const cmFunctionalDescriptorSize = 5
// CMFunctionalDescriptor is the functional descriptor general format.
type CMFunctionalDescriptor struct {
bFunctionLength uint8
bDescriptorType uint8 // 0x24
bDescriptorSubtype uint8 // 1
bmCapabilities uint8
bDataInterface uint8
}
// NewCMFunctionalDescriptor returns a new USB CMFunctionalDescriptor.
func NewCMFunctionalDescriptor(subtype, d0, d1 uint8) CMFunctionalDescriptor {
return CMFunctionalDescriptor{5, 0x24, subtype, d0, d1}
}
// Bytes returns the CMFunctionalDescriptor data.
func (d CMFunctionalDescriptor) Bytes() [cmFunctionalDescriptorSize]byte {
var b [cmFunctionalDescriptorSize]byte
b[0] = byte(d.bFunctionLength)
b[1] = byte(d.bDescriptorType)
b[2] = byte(d.bDescriptorSubtype)
b[3] = byte(d.bmCapabilities)
b[4] = byte(d.bDescriptorSubtype)
return b
}
const acmFunctionalDescriptorSize = 4
// ACMFunctionalDescriptor is a Abstract Control Model (ACM) USB descriptor.
type ACMFunctionalDescriptor struct {
len uint8
dtype uint8 // 0x24
subtype uint8 // 1
bmCapabilities uint8
}
// NewACMFunctionalDescriptor returns a new USB ACMFunctionalDescriptor.
func NewACMFunctionalDescriptor(subtype, d0 uint8) ACMFunctionalDescriptor {
return ACMFunctionalDescriptor{4, 0x24, subtype, d0}
}
// Bytes returns the ACMFunctionalDescriptor data.
func (d ACMFunctionalDescriptor) Bytes() [acmFunctionalDescriptorSize]byte {
var b [acmFunctionalDescriptorSize]byte
b[0] = byte(d.len)
b[1] = byte(d.dtype)
b[2] = byte(d.subtype)
b[3] = byte(d.bmCapabilities)
return b
}
// CDCDescriptor is the Communication Device Class (CDC) descriptor.
type CDCDescriptor struct {
// IAD
iad IADDescriptor // Only needed on compound device
// Control
cif InterfaceDescriptor
header CDCCSInterfaceDescriptor
// CDC control
controlManagement ACMFunctionalDescriptor // ACM
functionalDescriptor CDCCSInterfaceDescriptor // CDC_UNION
callManagement CMFunctionalDescriptor // Call Management
cifin EndpointDescriptor
// CDC Data
dif InterfaceDescriptor
in EndpointDescriptor
out EndpointDescriptor
}
func NewCDCDescriptor(i IADDescriptor, c InterfaceDescriptor,
h CDCCSInterfaceDescriptor,
cm ACMFunctionalDescriptor,
fd CDCCSInterfaceDescriptor,
callm CMFunctionalDescriptor,
ci EndpointDescriptor,
di InterfaceDescriptor,
outp EndpointDescriptor,
inp EndpointDescriptor) CDCDescriptor {
return CDCDescriptor{iad: i,
cif: c,
header: h,
controlManagement: cm,
functionalDescriptor: fd,
callManagement: callm,
cifin: ci,
dif: di,
in: inp,
out: outp}
}
const cdcSize = iadDescriptorSize +
interfaceDescriptorSize +
cdcCSInterfaceDescriptorSize +
acmFunctionalDescriptorSize +
cdcCSInterfaceDescriptorSize +
cmFunctionalDescriptorSize +
endpointDescriptorSize +
interfaceDescriptorSize +
endpointDescriptorSize +
endpointDescriptorSize
// Bytes returns CDCDescriptor data.
func (d CDCDescriptor) Bytes() [cdcSize]byte {
var b [cdcSize]byte
offset := 0
iad := d.iad.Bytes()
copy(b[offset:], iad[:])
offset += len(iad)
cif := d.cif.Bytes()
copy(b[offset:], cif[:])
offset += len(cif)
header := d.header.Bytes()
copy(b[offset:], header[:])
offset += len(header)
controlManagement := d.controlManagement.Bytes()
copy(b[offset:], controlManagement[:])
offset += len(controlManagement)
functionalDescriptor := d.functionalDescriptor.Bytes()
copy(b[offset:], functionalDescriptor[:])
offset += len(functionalDescriptor)
callManagement := d.callManagement.Bytes()
copy(b[offset:], callManagement[:])
offset += len(callManagement)
cifin := d.cifin.Bytes()
copy(b[offset:], cifin[:])
offset += len(cifin)
dif := d.dif.Bytes()
copy(b[offset:], dif[:])
offset += len(dif)
out := d.out.Bytes()
copy(b[offset:], out[:])
offset += len(out)
in := d.in.Bytes()
copy(b[offset:], in[:])
offset += len(in)
return b
}
// MSCDescriptor is not used yet.
type MSCDescriptor struct {
msc InterfaceDescriptor
in EndpointDescriptor
out EndpointDescriptor
}
const cdcLineInfoSize = 7
type cdcLineInfo struct {
@ -455,6 +64,8 @@ const (
usb_ENDPOINT_DESCRIPTOR_TYPE = 5
usb_DEVICE_QUALIFIER = 6
usb_OTHER_SPEED_CONFIGURATION = 7
usb_SET_REPORT_TYPE = 33
usb_HID_REPORT_TYPE = 34
usbEndpointOut = 0x00
usbEndpointIn = 0x80
@ -474,6 +85,9 @@ const (
usb_GET_INTERFACE = 10
usb_SET_INTERFACE = 11
// non standard requests
usb_SET_IDLE = 10
usb_DEVICE_CLASS_COMMUNICATIONS = 0x02
usb_DEVICE_CLASS_HUMAN_INTERFACE = 0x03
usb_DEVICE_CLASS_STORAGE = 0x08
@ -488,9 +102,12 @@ const (
usb_CDC_ACM_INTERFACE = 0 // CDC ACM
usb_CDC_DATA_INTERFACE = 1 // CDC Data
usb_CDC_FIRST_ENDPOINT = 1
usb_CDC_ENDPOINT_ACM = 1
usb_CDC_ENDPOINT_OUT = 2
usb_CDC_ENDPOINT_IN = 3
// Endpoint
usb_CDC_ENDPOINT_ACM = 1
usb_CDC_ENDPOINT_OUT = 2
usb_CDC_ENDPOINT_IN = 3
usb_HID_ENDPOINT_IN = 4
// bmRequestType
usb_REQUEST_HOSTTODEVICE = 0x00
@ -661,40 +278,43 @@ func (usbcdc *USBCDC) Receive(data byte) {
func sendDescriptor(setup usbSetup) {
switch setup.wValueH {
case usb_CONFIGURATION_DESCRIPTOR_TYPE:
sendConfiguration(setup)
sendUSBPacket(0, usbDescriptor.Configuration, setup.wLength)
return
case usb_DEVICE_DESCRIPTOR_TYPE:
// composite descriptor
dd := NewDeviceDescriptor(0xef, 0x02, 0x01, 64, usb_VID, usb_PID, 0x100, usb_IMANUFACTURER, usb_IPRODUCT, usb_ISERIAL, 1)
l := deviceDescriptorSize
if setup.wLength < deviceDescriptorSize {
l = int(setup.wLength)
}
buf := dd.Bytes()
sendUSBPacket(0, buf[:l])
usbDescriptor.Configure(usb_VID, usb_PID)
sendUSBPacket(0, usbDescriptor.Device, setup.wLength)
return
case usb_STRING_DESCRIPTOR_TYPE:
switch setup.wValueL {
case 0:
b := []byte{0x04, 0x03, 0x09, 0x04}
sendUSBPacket(0, b)
sendUSBPacket(0, b, setup.wLength)
case usb_IPRODUCT:
b := make([]byte, (len(usb_STRING_PRODUCT)<<1)+2)
strToUTF16LEDescriptor(usb_STRING_PRODUCT, b)
sendUSBPacket(0, b)
sendUSBPacket(0, b, setup.wLength)
case usb_IMANUFACTURER:
b := make([]byte, (len(usb_STRING_MANUFACTURER)<<1)+2)
strToUTF16LEDescriptor(usb_STRING_MANUFACTURER, b)
sendUSBPacket(0, b)
sendUSBPacket(0, b, setup.wLength)
case usb_ISERIAL:
// TODO: allow returning a product serial number
sendZlp()
}
return
case usb_HID_REPORT_TYPE:
if h, ok := usbDescriptor.HID[setup.wIndex]; ok {
sendUSBPacket(0, h, setup.wLength)
return
}
case usb_DEVICE_QUALIFIER:
// skip
default:
}
// do not know how to handle this message, so return zero
@ -702,54 +322,17 @@ func sendDescriptor(setup usbSetup) {
return
}
// sendConfiguration creates and sends the configuration packet to the host.
func sendConfiguration(setup usbSetup) {
if setup.wLength == 9 {
sz := uint16(configDescriptorSize + cdcSize)
config := NewConfigDescriptor(sz, 2)
configBuf := config.Bytes()
sendUSBPacket(0, configBuf[:])
} else {
iad := NewIADDescriptor(0, 2, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0)
// 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)}
cif := NewInterfaceDescriptor(usb_CDC_ACM_INTERFACE, 1, usb_CDC_COMMUNICATION_INTERFACE_CLASS, usb_CDC_ABSTRACT_CONTROL_MODEL, 0)
header := NewCDCCSInterfaceDescriptor(usb_CDC_HEADER, usb_CDC_V1_10&0xFF, (usb_CDC_V1_10>>8)&0x0FF)
controlManagement := NewACMFunctionalDescriptor(usb_CDC_ABSTRACT_CONTROL_MANAGEMENT, 6)
functionalDescriptor := NewCDCCSInterfaceDescriptor(usb_CDC_UNION, usb_CDC_ACM_INTERFACE, usb_CDC_DATA_INTERFACE)
callManagement := NewCMFunctionalDescriptor(usb_CDC_CALL_MANAGEMENT, 1, 1)
cifin := NewEndpointDescriptor((usb_CDC_ENDPOINT_ACM | usbEndpointIn), usb_ENDPOINT_TYPE_INTERRUPT, 0x10, 0x10)
dif := NewInterfaceDescriptor(usb_CDC_DATA_INTERFACE, 2, usb_CDC_DATA_INTERFACE_CLASS, 0, 0)
out := NewEndpointDescriptor((usb_CDC_ENDPOINT_OUT | usbEndpointOut), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0)
in := NewEndpointDescriptor((usb_CDC_ENDPOINT_IN | usbEndpointIn), usb_ENDPOINT_TYPE_BULK, usbEndpointPacketSize, 0)
cdc := NewCDCDescriptor(iad,
cif,
header,
controlManagement,
functionalDescriptor,
callManagement,
cifin,
dif,
out,
in)
sz := uint16(configDescriptorSize + cdcSize)
config := NewConfigDescriptor(sz, 2)
configBuf := config.Bytes()
cdcBuf := cdc.Bytes()
var buf [configDescriptorSize + cdcSize]byte
copy(buf[0:], configBuf[:])
copy(buf[configDescriptorSize:], cdcBuf[:])
sendUSBPacket(0, buf[:])
}
hidCallback = callback
}
// hidCallback is a variable that holds the callback when using HID.
var hidCallback func()

52
src/machine/usb/hid/buffer.go Обычный файл
Просмотреть файл

@ -0,0 +1,52 @@
package hid
import (
"runtime/volatile"
)
const bufferSize = 128
// RingBuffer is ring buffer implementation inspired by post at
// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php
type RingBuffer struct {
rxbuffer [bufferSize][9]byte
head volatile.Register8
tail volatile.Register8
}
// NewRingBuffer returns a new ring buffer.
func NewRingBuffer() *RingBuffer {
return &RingBuffer{}
}
// Used returns how many bytes in buffer have been used.
func (rb *RingBuffer) Used() uint8 {
return uint8(rb.head.Get() - rb.tail.Get())
}
// Put stores a byte in the buffer. If the buffer is already
// full, the method will return false.
func (rb *RingBuffer) Put(val []byte) bool {
if rb.Used() != bufferSize {
rb.head.Set(rb.head.Get() + 1)
copy(rb.rxbuffer[rb.head.Get()%bufferSize][:], val)
return true
}
return false
}
// Get returns a byte from the buffer. If the buffer is empty,
// the method will return a false as the second value.
func (rb *RingBuffer) Get() ([]byte, bool) {
if rb.Used() != 0 {
rb.tail.Set(rb.tail.Get() + 1)
return rb.rxbuffer[rb.tail.Get()%bufferSize][:], true
}
return nil, false
}
// Clear resets the head and tail pointer to zero.
func (rb *RingBuffer) Clear() {
rb.head.Set(0)
rb.tail.Set(0)
}

51
src/machine/usb/hid/hid.go Обычный файл
Просмотреть файл

@ -0,0 +1,51 @@
package hid
import (
"errors"
"machine"
)
// from usb-hid.go
var (
ErrHIDInvalidPort = errors.New("invalid USB port")
ErrHIDInvalidCore = errors.New("invalid USB core")
ErrHIDReportTransfer = errors.New("failed to transfer HID report")
)
const (
hidEndpoint = 4
)
type hidDevicer interface {
Callback() bool
}
var devices [5]hidDevicer
var size int
// SetCallbackHandler sets the callback. Only the first time it is called, it
// calls machine.EnableHID for USB configuration
func SetCallbackHandler(d hidDevicer) {
if size == 0 {
machine.EnableHID(callback)
}
devices[size] = d
size++
}
func callback() {
for _, d := range devices {
if d == nil {
continue
}
if done := d.Callback(); done {
return
}
}
}
// SendUSBPacket sends a HIDPacket.
func SendUSBPacket(b []byte) {
machine.SendUSBHIDPacket(hidEndpoint, b)
}

478
src/machine/usb/hid/keyboard/keyboard.go Обычный файл
Просмотреть файл

@ -0,0 +1,478 @@
package keyboard
import (
"errors"
"machine/usb/hid"
)
// from usb-hid-keyboard.go
var (
ErrInvalidCodepoint = errors.New("invalid Unicode codepoint")
ErrInvalidKeycode = errors.New("invalid keyboard keycode")
ErrInvalidUTF8 = errors.New("invalid UTF-8 encoding")
ErrKeypressMaximum = errors.New("maximum keypresses exceeded")
)
var Keyboard *keyboard
// Keyboard represents a USB HID keyboard device with support for international
// layouts and various control, system, multimedia, and consumer keycodes.
//
// Keyboard implements the io.Writer interface that translates UTF-8 encoded
// byte strings into sequences of keypress events.
type keyboard struct {
// led holds the current state of all keyboard LEDs:
// 1=NumLock 2=CapsLock 4=ScrollLock 8=Compose 16=Kana
led uint8
// mod holds the current state of all keyboard modifier keys:
// 1=LeftCtrl 2=LeftShift 4=LeftAlt 8=LeftGUI
// 16=RightCtrl 32=RightShift 64=RightAlt 128=RightGUI
mod uint8
// key holds a list of all keyboard keys currently pressed.
key [hidKeyboardKeyCount]uint8
con [hidKeyboardConCount]uint16
sys [hidKeyboardSysCount]uint8
// decode holds the current state of the UTF-8 decoder.
decode decodeState
// wideChar holds high bits for the UTF-8 decoder.
wideChar uint16
buf *hid.RingBuffer
}
// decodeState represents a state in the UTF-8 decode state machine.
type decodeState uint8
// Constant enumerated values of type decodeState.
const (
decodeReset decodeState = iota
decodeByte1
decodeByte2
decodeByte3
)
func init() {
if Keyboard == nil {
Keyboard = newKeyboard()
hid.SetCallbackHandler(Keyboard)
}
}
// New returns hid-keybord.
func New() *keyboard {
return Keyboard
}
func newKeyboard() *keyboard {
return &keyboard{
buf: hid.NewRingBuffer(),
}
}
func (kb *keyboard) Callback() bool {
if b, ok := kb.buf.Get(); ok {
hid.SendUSBPacket(b)
return true
}
return false
}
func (kb *keyboard) ready() bool {
return true
}
// Write transmits press-and-release key sequences for each Keycode translated
// from the given UTF-8 byte string. Write implements the io.Writer interface
// and conforms to all documented conventions for arguments and return values.
func (kb *keyboard) Write(b []byte) (n int, err error) {
for _, c := range b {
if err = kb.WriteByte(c); nil != err {
break
}
n += 1
}
return
}
// WriteByte processes a single byte from a UTF-8 byte string. This method is a
// stateful method with respect to the receiver Keyboard, meaning that its exact
// behavior will depend on the current state of its UTF-8 decode state machine:
//
// (a) If the given byte is a valid ASCII encoding (0-127), then a keypress
// sequence is immediately transmitted for the respective Keycode.
//
// (b) If the given byte represents the final byte in a multi-byte codepoint,
// then a keypress sequence is immediately transmitted by translating the
// multi-byte codepoint to its respective Keycode.
//
// (c) If the given byte appears to represent high bits for a multi-byte
// codepoint, then the bits are copied to the receiver's internal state
// machine buffer for use by a subsequent call to WriteByte() (or Write())
// that completes the codepoint.
//
// (d) If the given byte is out of range, or contains illegal bits for the
// current state of the UTF-8 decoder, then the UTF-8 decode state machine
// is reset to its initial state.
//
// In cases (c) and (d), a keypress sequence is not generated and no data is
// transmitted. In case (c), additional bytes must be received via WriteByte()
// (or Write()) to complete or discard the current codepoint.
func (kb *keyboard) WriteByte(b byte) error {
switch {
case b < 0x80:
// 1-byte encoding (0x00-0x7F)
kb.decode = decodeByte1
return kb.write(uint16(b))
case b < 0xC0:
// 2nd, 3rd, or 4th byte (0x80-0xBF)
b = Keycode(b).key()
switch kb.decode {
case decodeByte2:
kb.decode = decodeByte1
return kb.write(kb.wideChar | uint16(b))
case decodeByte3:
kb.decode = decodeByte2
kb.wideChar |= uint16(b) << 6
}
case b < 0xE0:
// 2-byte encoding (0xC2-0xDF), or illegal byte 2 (0xC0-0xC1)
kb.decode = decodeByte2
kb.wideChar = uint16(b&0x1F) << 6
case b < 0xF0:
// 3-byte encoding (0xE0-0xEF)
kb.decode = decodeByte3
kb.wideChar = uint16(b&0x0F) << 12
default:
// 4-byte encoding unsupported (0xF0-0xF4), or illegal byte 4 (0xF5-0xFF)
kb.decode = decodeReset
return ErrInvalidUTF8
}
return nil
}
func (kb *keyboard) write(p uint16) error {
c := keycode(p)
if 0 == c {
return ErrInvalidCodepoint
}
if d := deadkey(c); 0 != d {
if err := kb.writeKeycode(d); nil != err {
return err
}
}
return kb.writeKeycode(c)
}
func (kb *keyboard) writeKeycode(c Keycode) error {
var b [9]byte
b[0] = 0x02
b[1] = c.mod()
b[2] = 0
b[3] = c.key()
b[4] = 0
b[5] = 0
b[6] = 0
b[7] = 0
b[8] = 0
if !kb.sendKey(false, b[:]) {
return hid.ErrHIDReportTransfer
}
b[1] = 0
b[3] = 0
if !kb.sendKey(false, b[:]) {
return hid.ErrHIDReportTransfer
}
return nil
}
// Press transmits a press-and-release sequence for the given Keycode, which
// simulates a discrete keypress event.
//
// The following values of Keycode are supported:
//
// 0x0020 - 0x007F ASCII (U+0020 to U+007F) [USES LAYOUT]
// 0x0080 - 0xC1FF Unicode (U+0080 to U+C1FF) [USES LAYOUT]
// 0xC200 - 0xDFFF UTF-8 packed (U+0080 to U+07FF) [USES LAYOUT]
// 0xE000 - 0xE0FF Modifier key (bitmap, 8 keys, Shift/Ctrl/Alt/GUI)
// 0xE200 - 0xE2FF System key (HID usage code, page 1)
// 0xE400 - 0xE7FF Media/Consumer key (HID usage code, page 12)
// 0xF000 - 0xFFFF Normal key (HID usage code, page 7)
func (kb *keyboard) Press(c Keycode) error {
if err := kb.Down(c); nil != err {
return err
}
return kb.Up(c)
}
func (kb *keyboard) sendKey(consumer bool, b []byte) bool {
kb.buf.Put(b)
return true
}
func (kb *keyboard) keyboardSendKeys(consumer bool) bool {
var b [9]byte
b[0] = 0x02
b[1] = kb.mod
b[2] = 0x02
b[3] = kb.key[0]
b[4] = kb.key[1]
b[5] = kb.key[2]
b[6] = kb.key[3]
b[7] = kb.key[4]
b[8] = kb.key[5]
return kb.sendKey(consumer, b[:])
}
// Down transmits a key-down event for the given Keycode.
//
// The host will interpret the key as being held down continuously until a
// corresponding key-up event is transmitted, e.g., via method Up().
//
// See godoc comment on method Press() for details on what input is accepted and
// how it is interpreted.
func (kb *keyboard) Down(c Keycode) error {
var res uint8
msb := c >> 8
if msb >= 0xC2 {
if msb < 0xE0 {
c = ((msb & 0x1F) << 6) | Keycode(c.key())
} else {
switch msb {
case 0xF0:
return kb.down(uint8(c), 0)
case 0xE0:
return kb.down(0, uint8(c))
case 0xE2:
return kb.downSys(uint8(c))
default:
if 0xE4 <= msb && msb <= 0xE7 {
return kb.downCon(uint16(c & 0x03FF))
}
return ErrInvalidKeycode
}
}
}
c = keycode(uint16(c))
if 0 == c {
return ErrInvalidCodepoint
}
if d := deadkey(c); 0 != d {
res = kb.mod
if 0 != res {
kb.mod = 0
kb.keyboardSendKeys(false)
}
kb.down(d.key(), d.mod())
kb.up(d.key(), d.mod())
}
return kb.down(c.key(), c.mod()|res)
}
func (kb *keyboard) down(key uint8, mod uint8) error {
send := false
if 0 != mod {
if kb.mod&mod != mod {
kb.mod |= mod
send = true
}
}
if 0 != key {
for _, k := range kb.key {
if k == key {
goto end
}
}
for i, k := range kb.key {
if 0 == k {
kb.key[i] = key
send = true
goto end
}
}
return ErrKeypressMaximum
}
end:
if send {
if !kb.keyboardSendKeys(false) {
return hid.ErrHIDReportTransfer
}
}
return nil
}
func (kb *keyboard) downCon(key uint16) error {
if 0 == key {
return ErrInvalidKeycode
}
for _, k := range kb.con {
if key == k {
return nil // already pressed
}
}
for i, k := range kb.con {
if 0 == k {
kb.con[i] = key
if !kb.keyboardSendKeys(true) {
return hid.ErrHIDReportTransfer
}
return nil
}
}
return ErrKeypressMaximum
}
func (kb *keyboard) downSys(key uint8) error {
if 0 == key {
return ErrInvalidKeycode
}
for _, k := range kb.sys {
if key == k {
return nil // already pressed
}
}
for i, k := range kb.sys {
if 0 == k {
kb.sys[i] = key
if !kb.keyboardSendKeys(true) {
return hid.ErrHIDReportTransfer
}
return nil
}
}
return ErrKeypressMaximum
}
// Up transmits a key-up event for the given Keycode.
//
// See godoc comment on method Press() for details on what input is accepted and
// how it is interpreted.
func (kb *keyboard) Up(c Keycode) error {
msb := c >> 8
if msb >= 0xC2 {
if msb < 0xE0 {
c = ((msb & 0x1F) << 6) | Keycode(c.key())
} else {
switch msb {
case 0xF0:
return kb.up(uint8(c), 0)
case 0xE0:
return kb.up(0, uint8(c))
case 0xE2:
return kb.upSys(uint8(c))
default:
if 0xE4 <= msb && msb <= 0xE7 {
return kb.upCon(uint16(c & 0x03FF))
}
return ErrInvalidKeycode
}
}
}
c = keycode(uint16(c))
if 0 == c {
return ErrInvalidCodepoint
}
return kb.up(c.key(), c.mod())
}
// Release transmits a key-up event for all keyboard keys currently pressed as
// if the user removed his/her hands from the keyboard entirely.
func (kb *keyboard) Release() error {
bits := uint16(kb.mod)
kb.mod = 0
for i, k := range kb.key {
bits |= uint16(k)
kb.key[i] = 0
}
if 0 != bits {
if !kb.keyboardSendKeys(false) {
return hid.ErrHIDReportTransfer
}
}
bits = 0
for i, k := range kb.con {
bits |= k
kb.con[i] = 0
}
for i, k := range kb.sys {
bits |= uint16(k)
kb.sys[i] = 0
}
if 0 != bits {
if !kb.keyboardSendKeys(true) {
return hid.ErrHIDReportTransfer
}
}
return nil
}
func (kb *keyboard) up(key uint8, mod uint8) error {
send := false
if 0 != mod {
if kb.mod&mod != 0 {
kb.mod &^= mod
send = true
}
}
if 0 != key {
for i, k := range kb.key {
if key == k {
kb.key[i] = 0
send = true
}
}
}
if send {
if !kb.keyboardSendKeys(false) {
return hid.ErrHIDReportTransfer
}
}
return nil
}
func (kb *keyboard) upCon(key uint16) error {
if 0 == key {
return ErrInvalidKeycode
}
for i, k := range kb.con {
if key == k {
kb.con[i] = 0
if !kb.keyboardSendKeys(true) {
return hid.ErrHIDReportTransfer
}
return nil
}
}
return nil
}
func (kb *keyboard) upSys(key uint8) error {
if 0 == key {
return ErrInvalidKeycode
}
for i, k := range kb.sys {
if key == k {
kb.sys[i] = 0
if !kb.keyboardSendKeys(true) {
return hid.ErrHIDReportTransfer
}
return nil
}
}
return nil
}

532
src/machine/usb/hid/keyboard/keycode.go Обычный файл
Просмотреть файл

@ -0,0 +1,532 @@
package keyboard
// Keycode is a package-defined bitmap used to encode the value of a given key.
type Keycode uint16
// keycode returns the given Unicode codepoint translated to a Keycode sequence.
// Unicode codepoints greater than U+FFFF are unsupported.
//go:inline
func keycode(p uint16) Keycode {
if p < 0x80 {
return ascii[p]
} else if p >= 0xA0 && p < 0x0100 {
return iso88591[p-0xA0]
} else if uint16(UNICODE20AC) == p {
return UNICODE20AC.mask()
}
return 0
}
//go:inline
func deadkey(c Keycode) Keycode {
switch c & deadkeysMask {
case acuteAccentBits:
return deadkeyAcuteAccent
case circumflexBits:
return deadkeyCircumflex
case diaeresisBits:
return deadkeyDiaeresis
case graveAccentBits:
return deadkeyGraveAccent
case tildeBits:
return deadkeyTilde
}
return 0
}
//go:inline
func (c Keycode) mask() Keycode { return c & keycodeMask }
//go:inline
func (c Keycode) key() uint8 { return uint8(c & keyMask) }
//go:inline
func (c Keycode) mod() uint8 {
var m Keycode
if 0 != c&shiftMask {
m |= KeyModifierShift
}
if 0 != c&altgrMask {
m |= KeyModifierRightAlt
}
return uint8(m)
}
//go:inline
func (c Keycode) Shift() Keycode { return c | KeyModifierShift }
const (
hidKeyboardKeyCount = 6 // Max number of simultaneous keypresses
hidKeyboardSysCount = 3
hidKeyboardConCount = 4
)
// Keycodes common to all Keyboard layouts
const (
KeyModifierCtrl Keycode = 0x01 | 0xE000
KeyModifierShift Keycode = 0x02 | 0xE000
KeyModifierAlt Keycode = 0x04 | 0xE000
KeyModifierGUI Keycode = 0x08 | 0xE000
KeyModifierLeftCtrl Keycode = 0x01 | 0xE000
KeyModifierLeftShift Keycode = 0x02 | 0xE000
KeyModifierLeftAlt Keycode = 0x04 | 0xE000
KeyModifierLeftGUI Keycode = 0x08 | 0xE000
KeyModifierRightCtrl Keycode = 0x10 | 0xE000
KeyModifierRightShift Keycode = 0x20 | 0xE000
KeyModifierRightAlt Keycode = 0x40 | 0xE000
KeyModifierRightGUI Keycode = 0x80 | 0xE000
KeySystemPowerDown Keycode = 0x81 | 0xE200
KeySystemSleep Keycode = 0x82 | 0xE200
KeySystemWakeUp Keycode = 0x83 | 0xE200
KeyMediaPlay Keycode = 0xB0 | 0xE400
KeyMediaPause Keycode = 0xB1 | 0xE400
KeyMediaRecord Keycode = 0xB2 | 0xE400
KeyMediaFastForward Keycode = 0xB3 | 0xE400
KeyMediaRewind Keycode = 0xB4 | 0xE400
KeyMediaNextTrack Keycode = 0xB5 | 0xE400
KeyMediaPrevTrack Keycode = 0xB6 | 0xE400
KeyMediaStop Keycode = 0xB7 | 0xE400
KeyMediaEject Keycode = 0xB8 | 0xE400
KeyMediaRandomPlay Keycode = 0xB9 | 0xE400
KeyMediaPlayPause Keycode = 0xCD | 0xE400
KeyMediaPlaySkip Keycode = 0xCE | 0xE400
KeyMediaMute Keycode = 0xE2 | 0xE400
KeyMediaVolumeInc Keycode = 0xE9 | 0xE400
KeyMediaVolumeDec Keycode = 0xEA | 0xE400
KeyA Keycode = 4 | 0xF000
KeyB Keycode = 5 | 0xF000
KeyC Keycode = 6 | 0xF000
KeyD Keycode = 7 | 0xF000
KeyE Keycode = 8 | 0xF000
KeyF Keycode = 9 | 0xF000
KeyG Keycode = 10 | 0xF000
KeyH Keycode = 11 | 0xF000
KeyI Keycode = 12 | 0xF000
KeyJ Keycode = 13 | 0xF000
KeyK Keycode = 14 | 0xF000
KeyL Keycode = 15 | 0xF000
KeyM Keycode = 16 | 0xF000
KeyN Keycode = 17 | 0xF000
KeyO Keycode = 18 | 0xF000
KeyP Keycode = 19 | 0xF000
KeyQ Keycode = 20 | 0xF000
KeyR Keycode = 21 | 0xF000
KeyS Keycode = 22 | 0xF000
KeyT Keycode = 23 | 0xF000
KeyU Keycode = 24 | 0xF000
KeyV Keycode = 25 | 0xF000
KeyW Keycode = 26 | 0xF000
KeyX Keycode = 27 | 0xF000
KeyY Keycode = 28 | 0xF000
KeyZ Keycode = 29 | 0xF000
Key1 Keycode = 30 | 0xF000
Key2 Keycode = 31 | 0xF000
Key3 Keycode = 32 | 0xF000
Key4 Keycode = 33 | 0xF000
Key5 Keycode = 34 | 0xF000
Key6 Keycode = 35 | 0xF000
Key7 Keycode = 36 | 0xF000
Key8 Keycode = 37 | 0xF000
Key9 Keycode = 38 | 0xF000
Key0 Keycode = 39 | 0xF000
KeyEnter Keycode = 40 | 0xF000
KeyEsc Keycode = 41 | 0xF000
KeyBackspace Keycode = 42 | 0xF000
KeyTab Keycode = 43 | 0xF000
KeySpace Keycode = 44 | 0xF000
KeyMinus Keycode = 45 | 0xF000
KeyEqual Keycode = 46 | 0xF000
KeyLeftBrace Keycode = 47 | 0xF000
KeyRightBrace Keycode = 48 | 0xF000
KeyBackslash Keycode = 49 | 0xF000
KeyNonUsNum Keycode = 50 | 0xF000
KeySemicolon Keycode = 51 | 0xF000
KeyQuote Keycode = 52 | 0xF000
KeyTilde Keycode = 53 | 0xF000
KeyComma Keycode = 54 | 0xF000
KeyPeriod Keycode = 55 | 0xF000
KeySlash Keycode = 56 | 0xF000
KeyCapsLock Keycode = 57 | 0xF000
KeyF1 Keycode = 58 | 0xF000
KeyF2 Keycode = 59 | 0xF000
KeyF3 Keycode = 60 | 0xF000
KeyF4 Keycode = 61 | 0xF000
KeyF5 Keycode = 62 | 0xF000
KeyF6 Keycode = 63 | 0xF000
KeyF7 Keycode = 64 | 0xF000
KeyF8 Keycode = 65 | 0xF000
KeyF9 Keycode = 66 | 0xF000
KeyF10 Keycode = 67 | 0xF000
KeyF11 Keycode = 68 | 0xF000
KeyF12 Keycode = 69 | 0xF000
KeyPrintscreen Keycode = 70 | 0xF000
KeyScrollLock Keycode = 71 | 0xF000
KeyPause Keycode = 72 | 0xF000
KeyInsert Keycode = 73 | 0xF000
KeyHome Keycode = 74 | 0xF000
KeyPageUp Keycode = 75 | 0xF000
KeyDelete Keycode = 76 | 0xF000
KeyEnd Keycode = 77 | 0xF000
KeyPageDown Keycode = 78 | 0xF000
KeyRight Keycode = 79 | 0xF000
KeyLeft Keycode = 80 | 0xF000
KeyDown Keycode = 81 | 0xF000
KeyUp Keycode = 82 | 0xF000
KeyNumLock Keycode = 83 | 0xF000
KeypadSlash Keycode = 84 | 0xF000
KeypadAsterisk Keycode = 85 | 0xF000
KeypadMinus Keycode = 86 | 0xF000
KeypadPlus Keycode = 87 | 0xF000
KeypadEnter Keycode = 88 | 0xF000
Keypad1 Keycode = 89 | 0xF000
Keypad2 Keycode = 90 | 0xF000
Keypad3 Keycode = 91 | 0xF000
Keypad4 Keycode = 92 | 0xF000
Keypad5 Keycode = 93 | 0xF000
Keypad6 Keycode = 94 | 0xF000
Keypad7 Keycode = 95 | 0xF000
Keypad8 Keycode = 96 | 0xF000
Keypad9 Keycode = 97 | 0xF000
Keypad0 Keycode = 98 | 0xF000
KeypadPeriod Keycode = 99 | 0xF000
KeyNonUSBS Keycode = 100 | 0xF000
KeyMenu Keycode = 101 | 0xF000
KeyF13 Keycode = 104 | 0xF000
KeyF14 Keycode = 105 | 0xF000
KeyF15 Keycode = 106 | 0xF000
KeyF16 Keycode = 107 | 0xF000
KeyF17 Keycode = 108 | 0xF000
KeyF18 Keycode = 109 | 0xF000
KeyF19 Keycode = 110 | 0xF000
KeyF20 Keycode = 111 | 0xF000
KeyF21 Keycode = 112 | 0xF000
KeyF22 Keycode = 113 | 0xF000
KeyF23 Keycode = 114 | 0xF000
KeyF24 Keycode = 115 | 0xF000
KeyUpArrow Keycode = KeyUp
KeyDownArrow Keycode = KeyDown
KeyLeftArrow Keycode = KeyLeft
KeyRightArrow Keycode = KeyRight
KeyReturn Keycode = KeyEnter
KeyLeftCtrl Keycode = KeyModifierLeftCtrl
KeyLeftShift Keycode = KeyModifierLeftShift
KeyLeftAlt Keycode = KeyModifierLeftAlt
KeyLeftGUI Keycode = KeyModifierLeftGUI
KeyRightCtrl Keycode = KeyModifierRightCtrl
KeyRightShift Keycode = KeyModifierRightShift
KeyRightAlt Keycode = KeyModifierRightAlt
KeyRightGUI Keycode = KeyModifierRightGUI
)
// Keycodes for layout US English (0x0904)
const (
keycodeMask Keycode = 0x07FF
keyMask Keycode = 0x003F
shiftMask Keycode = 0x0040
altgrMask Keycode = 0x0080
deadkeysMask Keycode = 0x0700
circumflexBits Keycode = 0x0100
acuteAccentBits Keycode = 0x0200
graveAccentBits Keycode = 0x0300
tildeBits Keycode = 0x0400
diaeresisBits Keycode = 0x0500
deadkeyCircumflex Keycode = Key6 | shiftMask
deadkeyAcuteAccent Keycode = KeyQuote
deadkeyGraveAccent Keycode = KeyTilde
deadkeyTilde Keycode = KeyTilde | shiftMask
deadkeyDiaeresis Keycode = KeyQuote | shiftMask
ASCII00 Keycode = 0 // 0 NUL
ASCII01 Keycode = 0 // 1 SOH
ASCII02 Keycode = 0 // 2 STX
ASCII03 Keycode = 0 // 3 ETX
ASCII04 Keycode = 0 // 4 EOT
ASCII05 Keycode = 0 // 5 ENQ
ASCII06 Keycode = 0 // 6 ACK
ASCII07 Keycode = 0 // 7 BEL
ASCII08 Keycode = KeyBackspace // 8 BS
ASCII09 Keycode = KeyTab // 9 TAB
ASCII0A Keycode = KeyEnter // 10 LF
ASCII0B Keycode = 0 // 11 VT
ASCII0C Keycode = 0 // 12 FF
ASCII0D Keycode = 0 // 13 CR
ASCII0E Keycode = 0 // 14 SO
ASCII0F Keycode = 0 // 15 SI
ASCII10 Keycode = 0 // 16 DEL
ASCII11 Keycode = 0 // 17 DC1
ASCII12 Keycode = 0 // 18 DC2
ASCII13 Keycode = 0 // 19 DC3
ASCII14 Keycode = 0 // 20 DC4
ASCII15 Keycode = 0 // 21 NAK
ASCII16 Keycode = 0 // 22 SYN
ASCII17 Keycode = 0 // 23 ETB
ASCII18 Keycode = 0 // 24 CAN
ASCII19 Keycode = 0 // 25 EM
ASCII1A Keycode = 0 // 26 SUB
ASCII1B Keycode = 0 // 27 ESC
ASCII1C Keycode = 0 // 28 FS
ASCII1D Keycode = 0 // 29 GS
ASCII1E Keycode = 0 // 30 RS
ASCII1F Keycode = 0 // 31 US
ASCII20 Keycode = KeySpace // 32 SPACE
ASCII21 Keycode = Key1 | shiftMask // 33 !
ASCII22 Keycode = diaeresisBits | KeySpace // 34 "
ASCII23 Keycode = Key3 | shiftMask // 35 #
ASCII24 Keycode = Key4 | shiftMask // 36 $
ASCII25 Keycode = Key5 | shiftMask // 37 %
ASCII26 Keycode = Key7 | shiftMask // 38 &
ASCII27 Keycode = acuteAccentBits | KeySpace // 39 '
ASCII28 Keycode = Key9 | shiftMask // 40 (
ASCII29 Keycode = Key0 | shiftMask // 41 )
ASCII2A Keycode = Key8 | shiftMask // 42 *
ASCII2B Keycode = KeyEqual | shiftMask // 43 +
ASCII2C Keycode = KeyComma // 44 ,
ASCII2D Keycode = KeyMinus // 45 -
ASCII2E Keycode = KeyPeriod // 46 .
ASCII2F Keycode = KeySlash // 47 /
ASCII30 Keycode = Key0 // 48 0
ASCII31 Keycode = Key1 // 49 1
ASCII32 Keycode = Key2 // 50 2
ASCII33 Keycode = Key3 // 51 3
ASCII34 Keycode = Key4 // 52 4
ASCII35 Keycode = Key5 // 53 5
ASCII36 Keycode = Key6 // 54 6
ASCII37 Keycode = Key7 // 55 7
ASCII38 Keycode = Key8 // 55 8
ASCII39 Keycode = Key9 // 57 9
ASCII3A Keycode = KeySemicolon | shiftMask // 58 :
ASCII3B Keycode = KeySemicolon // 59 ;
ASCII3C Keycode = KeyComma | shiftMask // 60 <
ASCII3D Keycode = KeyEqual // 61 =
ASCII3E Keycode = KeyPeriod | shiftMask // 62 >
ASCII3F Keycode = KeySlash | shiftMask // 63 ?
ASCII40 Keycode = Key2 | shiftMask // 64 @
ASCII41 Keycode = KeyA | shiftMask // 65 A
ASCII42 Keycode = KeyB | shiftMask // 66 B
ASCII43 Keycode = KeyC | shiftMask // 67 C
ASCII44 Keycode = KeyD | shiftMask // 68 D
ASCII45 Keycode = KeyE | shiftMask // 69 E
ASCII46 Keycode = KeyF | shiftMask // 70 F
ASCII47 Keycode = KeyG | shiftMask // 71 G
ASCII48 Keycode = KeyH | shiftMask // 72 H
ASCII49 Keycode = KeyI | shiftMask // 73 I
ASCII4A Keycode = KeyJ | shiftMask // 74 J
ASCII4B Keycode = KeyK | shiftMask // 75 K
ASCII4C Keycode = KeyL | shiftMask // 76 L
ASCII4D Keycode = KeyM | shiftMask // 77 M
ASCII4E Keycode = KeyN | shiftMask // 78 N
ASCII4F Keycode = KeyO | shiftMask // 79 O
ASCII50 Keycode = KeyP | shiftMask // 80 P
ASCII51 Keycode = KeyQ | shiftMask // 81 Q
ASCII52 Keycode = KeyR | shiftMask // 82 R
ASCII53 Keycode = KeyS | shiftMask // 83 S
ASCII54 Keycode = KeyT | shiftMask // 84 T
ASCII55 Keycode = KeyU | shiftMask // 85 U
ASCII56 Keycode = KeyV | shiftMask // 86 V
ASCII57 Keycode = KeyW | shiftMask // 87 W
ASCII58 Keycode = KeyX | shiftMask // 88 X
ASCII59 Keycode = KeyY | shiftMask // 89 Y
ASCII5A Keycode = KeyZ | shiftMask // 90 Z
ASCII5B Keycode = KeyLeftBrace // 91 [
ASCII5C Keycode = KeyBackslash // 92 \
ASCII5D Keycode = KeyRightBrace // 93 ]
ASCII5E Keycode = circumflexBits | KeySpace // 94 ^
ASCII5F Keycode = KeyMinus | shiftMask // 95
ASCII60 Keycode = graveAccentBits | KeySpace // 96 `
ASCII61 Keycode = KeyA // 97 a
ASCII62 Keycode = KeyB // 98 b
ASCII63 Keycode = KeyC // 99 c
ASCII64 Keycode = KeyD // 100 d
ASCII65 Keycode = KeyE // 101 e
ASCII66 Keycode = KeyF // 102 f
ASCII67 Keycode = KeyG // 103 g
ASCII68 Keycode = KeyH // 104 h
ASCII69 Keycode = KeyI // 105 i
ASCII6A Keycode = KeyJ // 106 j
ASCII6B Keycode = KeyK // 107 k
ASCII6C Keycode = KeyL // 108 l
ASCII6D Keycode = KeyM // 109 m
ASCII6E Keycode = KeyN // 110 n
ASCII6F Keycode = KeyO // 111 o
ASCII70 Keycode = KeyP // 112 p
ASCII71 Keycode = KeyQ // 113 q
ASCII72 Keycode = KeyR // 114 r
ASCII73 Keycode = KeyS // 115 s
ASCII74 Keycode = KeyT // 116 t
ASCII75 Keycode = KeyU // 117 u
ASCII76 Keycode = KeyV // 118 v
ASCII77 Keycode = KeyW // 119 w
ASCII78 Keycode = KeyX // 120 x
ASCII79 Keycode = KeyY // 121 y
ASCII7A Keycode = KeyZ // 122 z
ASCII7B Keycode = KeyLeftBrace | shiftMask // 123 {
ASCII7C Keycode = KeyBackslash | shiftMask // 124 |
ASCII7D Keycode = KeyRightBrace | shiftMask // 125 }
ASCII7E Keycode = tildeBits | KeySpace // 126 ~
ASCII7F Keycode = KeyBackspace // 127 DEL
ISO88591A0 Keycode = KeySpace // 160 Nonbreakng Space
ISO88591A1 Keycode = Key1 | altgrMask // 161 ¡ Inverted Exclamation
ISO88591A2 Keycode = KeyC | altgrMask | shiftMask // 162 ¢ Cent SIGN
ISO88591A3 Keycode = Key4 | altgrMask | shiftMask // 163 £ Pound Sign
ISO88591A4 Keycode = Key4 | altgrMask // 164 ¤ Currency or Euro Sign
ISO88591A5 Keycode = KeyMinus | altgrMask // 165 ¥ YEN SIGN
ISO88591A6 Keycode = KeyBackslash | altgrMask | shiftMask // 166 ¦ BROKEN BAR ??
ISO88591A7 Keycode = KeyS | altgrMask | shiftMask // 167 § SECTION SIGN
ISO88591A8 Keycode = KeyQuote | altgrMask | shiftMask // 168 ¨ DIAERESIS
ISO88591A9 Keycode = KeyC | altgrMask // 169 © COPYRIGHT SIGN
ISO88591AA Keycode = 0 // 170 ª FEMININE ORDINAL
ISO88591AB Keycode = KeyLeftBrace | altgrMask // 171 « LEFT DOUBLE ANGLE QUOTE
ISO88591AC Keycode = KeyBackslash | altgrMask // 172 ¬ NOT SIGN ??
ISO88591AD Keycode = 0 // 173 SOFT HYPHEN
ISO88591AE Keycode = KeyR | altgrMask // 174 ® REGISTERED SIGN
ISO88591AF Keycode = 0 // 175 ¯ MACRON
ISO88591B0 Keycode = KeySemicolon | altgrMask | shiftMask // 176 ° DEGREE SIGN
ISO88591B1 Keycode = 0 // 177 ± PLUS-MINUS SIGN
ISO88591B2 Keycode = Key2 | altgrMask // 178 ² SUPERSCRIPT TWO
ISO88591B3 Keycode = Key3 | altgrMask // 179 ³ SUPERSCRIPT THREE
ISO88591B4 Keycode = KeyQuote | altgrMask // 180 ´ ACUTE ACCENT
ISO88591B5 Keycode = KeyM | altgrMask // 181 µ MICRO SIGN
ISO88591B6 Keycode = KeySemicolon | altgrMask // 182 ¶ PILCROW SIGN
ISO88591B7 Keycode = 0 // 183 · MIDDLE DOT
ISO88591B8 Keycode = 0 // 184 ¸ CEDILLA
ISO88591B9 Keycode = Key1 | altgrMask | shiftMask // 185 ¹ SUPERSCRIPT ONE
ISO88591BA Keycode = 0 // 186 º MASCULINE ORDINAL
ISO88591BB Keycode = KeyRightBrace | altgrMask // 187 » RIGHT DOUBLE ANGLE QUOTE
ISO88591BC Keycode = Key6 | altgrMask // 188 ¼ FRACTION ONE QUARTER
ISO88591BD Keycode = Key7 | altgrMask // 189 ½ FRACTION ONE HALF
ISO88591BE Keycode = Key8 | altgrMask // 190 ¾ FRACTION THREE QUARTERS
ISO88591BF Keycode = KeySlash | altgrMask // 191 ¿ INVERTED QUESTION MARK
ISO88591C0 Keycode = graveAccentBits | KeyA | shiftMask // 192 À A GRAVE
ISO88591C1 Keycode = KeyA | altgrMask | shiftMask // 193 Á A ACUTE
ISO88591C2 Keycode = circumflexBits | KeyA | shiftMask // 194 Â A CIRCUMFLEX
ISO88591C3 Keycode = tildeBits | KeyA | shiftMask // 195 Ã A TILDE
ISO88591C4 Keycode = KeyQ | altgrMask | shiftMask // 196 Ä A DIAERESIS
ISO88591C5 Keycode = KeyW | altgrMask | shiftMask // 197 Å A RING ABOVE
ISO88591C6 Keycode = KeyZ | altgrMask | shiftMask // 198 Æ AE
ISO88591C7 Keycode = KeyComma | altgrMask | shiftMask // 199 Ç C CEDILLA
ISO88591C8 Keycode = graveAccentBits | KeyE | shiftMask // 200 È E GRAVE
ISO88591C9 Keycode = KeyE | altgrMask | shiftMask // 201 É E ACUTE
ISO88591CA Keycode = circumflexBits | KeyE | shiftMask // 202 Ê E CIRCUMFLEX
ISO88591CB Keycode = diaeresisBits | KeyE | shiftMask // 203 Ë E DIAERESIS
ISO88591CC Keycode = graveAccentBits | KeyI | shiftMask // 204 Ì I GRAVE
ISO88591CD Keycode = KeyI | altgrMask | shiftMask // 205 Í I ACUTE
ISO88591CE Keycode = circumflexBits | KeyI | shiftMask // 206 Î I CIRCUMFLEX
ISO88591CF Keycode = diaeresisBits | KeyI | shiftMask // 207 Ï I DIAERESIS
ISO88591D0 Keycode = KeyD | altgrMask | shiftMask // 208 Ð ETH
ISO88591D1 Keycode = KeyN | altgrMask | shiftMask // 209 Ñ N TILDE
ISO88591D2 Keycode = graveAccentBits | KeyO | shiftMask // 210 Ò O GRAVE
ISO88591D3 Keycode = KeyO | altgrMask | shiftMask // 211 Ó O ACUTE
ISO88591D4 Keycode = circumflexBits | KeyO | shiftMask // 212 Ô O CIRCUMFLEX
ISO88591D5 Keycode = tildeBits | KeyO | shiftMask // 213 Õ O TILDE
ISO88591D6 Keycode = KeyP | altgrMask | shiftMask // 214 Ö O DIAERESIS
ISO88591D7 Keycode = KeyEqual | altgrMask // 215 × MULTIPLICATION
ISO88591D8 Keycode = KeyL | altgrMask | shiftMask // 216 Ø O STROKE
ISO88591D9 Keycode = graveAccentBits | KeyU | shiftMask // 217 Ù U GRAVE
ISO88591DA Keycode = KeyU | altgrMask | shiftMask // 218 Ú U ACUTE
ISO88591DB Keycode = circumflexBits | KeyU | shiftMask // 219 Û U CIRCUMFLEX
ISO88591DC Keycode = KeyY | altgrMask | shiftMask // 220 Ü U DIAERESIS
ISO88591DD Keycode = acuteAccentBits | KeyY | shiftMask // 221 Ý Y ACUTE
ISO88591DE Keycode = KeyT | altgrMask | shiftMask // 222 Þ THORN
ISO88591DF Keycode = KeyS | altgrMask // 223 ß SHARP S
ISO88591E0 Keycode = graveAccentBits | KeyA // 224 à a GRAVE
ISO88591E1 Keycode = KeyA | altgrMask // 225 á a ACUTE
ISO88591E2 Keycode = circumflexBits | KeyA // 226 â a CIRCUMFLEX
ISO88591E3 Keycode = tildeBits | KeyA // 227 ã a TILDE
ISO88591E4 Keycode = diaeresisBits | KeyA // 228 ä a DIAERESIS
ISO88591E5 Keycode = KeyW | altgrMask // 229 å a RING ABOVE
ISO88591E6 Keycode = KeyZ | altgrMask // 230 æ ae
ISO88591E7 Keycode = KeyComma | altgrMask // 231 ç c CEDILLA
ISO88591E8 Keycode = graveAccentBits | KeyE // 232 è e GRAVE
ISO88591E9 Keycode = acuteAccentBits | KeyE // 233 é e ACUTE
ISO88591EA Keycode = circumflexBits | KeyE // 234 ê e CIRCUMFLEX
ISO88591EB Keycode = diaeresisBits | KeyE // 235 ë e DIAERESIS
ISO88591EC Keycode = graveAccentBits | KeyI // 236 ì i GRAVE
ISO88591ED Keycode = KeyI | altgrMask // 237 í i ACUTE
ISO88591EE Keycode = circumflexBits | KeyI // 238 î i CIRCUMFLEX
ISO88591EF Keycode = diaeresisBits | KeyI // 239 ï i DIAERESIS
ISO88591F0 Keycode = KeyD | altgrMask // 240 ð ETH
ISO88591F1 Keycode = KeyN | altgrMask // 241 ñ n TILDE
ISO88591F2 Keycode = graveAccentBits | KeyO // 242 ò o GRAVE
ISO88591F3 Keycode = KeyO | altgrMask // 243 ó o ACUTE
ISO88591F4 Keycode = circumflexBits | KeyO // 244 ô o CIRCUMFLEX
ISO88591F5 Keycode = tildeBits | KeyO // 245 õ o TILDE
ISO88591F6 Keycode = KeyP | altgrMask // 246 ö o DIAERESIS
ISO88591F7 Keycode = KeyEqual | altgrMask | shiftMask // 247 ÷ DIVISION
ISO88591F8 Keycode = KeyL | altgrMask // 248 ø o STROKE
ISO88591F9 Keycode = graveAccentBits | KeyU // 249 ù u GRAVE
ISO88591FA Keycode = KeyU | altgrMask // 250 ú u ACUTE
ISO88591FB Keycode = circumflexBits | KeyU // 251 û u CIRCUMFLEX
ISO88591FC Keycode = KeyY | altgrMask // 252 ü u DIAERESIS
ISO88591FD Keycode = acuteAccentBits | KeyY // 253 ý y ACUTE
ISO88591FE Keycode = KeyT | altgrMask // 254 þ THORN
ISO88591FF Keycode = diaeresisBits | KeyY // 255 ÿ y DIAERESIS
UNICODE20AC Keycode = Key5 | altgrMask // 20AC € Euro Sign
)
var ascii = [...]Keycode{
ASCII00.mask(), ASCII01.mask(), ASCII02.mask(), ASCII03.mask(),
ASCII04.mask(), ASCII05.mask(), ASCII06.mask(), ASCII07.mask(),
ASCII08.mask(), ASCII09.mask(), ASCII0A.mask(), ASCII0B.mask(),
ASCII0C.mask(), ASCII0D.mask(), ASCII0E.mask(), ASCII0F.mask(),
ASCII10.mask(), ASCII11.mask(), ASCII12.mask(), ASCII13.mask(),
ASCII14.mask(), ASCII15.mask(), ASCII16.mask(), ASCII17.mask(),
ASCII18.mask(), ASCII19.mask(), ASCII1A.mask(), ASCII1B.mask(),
ASCII1C.mask(), ASCII1D.mask(), ASCII1E.mask(), ASCII1F.mask(),
ASCII20.mask(), ASCII21.mask(), ASCII22.mask(), ASCII23.mask(),
ASCII24.mask(), ASCII25.mask(), ASCII26.mask(), ASCII27.mask(),
ASCII28.mask(), ASCII29.mask(), ASCII2A.mask(), ASCII2B.mask(),
ASCII2C.mask(), ASCII2D.mask(), ASCII2E.mask(), ASCII2F.mask(),
ASCII30.mask(), ASCII31.mask(), ASCII32.mask(), ASCII33.mask(),
ASCII34.mask(), ASCII35.mask(), ASCII36.mask(), ASCII37.mask(),
ASCII38.mask(), ASCII39.mask(), ASCII3A.mask(), ASCII3B.mask(),
ASCII3C.mask(), ASCII3D.mask(), ASCII3E.mask(), ASCII3F.mask(),
ASCII40.mask(), ASCII41.mask(), ASCII42.mask(), ASCII43.mask(),
ASCII44.mask(), ASCII45.mask(), ASCII46.mask(), ASCII47.mask(),
ASCII48.mask(), ASCII49.mask(), ASCII4A.mask(), ASCII4B.mask(),
ASCII4C.mask(), ASCII4D.mask(), ASCII4E.mask(), ASCII4F.mask(),
ASCII50.mask(), ASCII51.mask(), ASCII52.mask(), ASCII53.mask(),
ASCII54.mask(), ASCII55.mask(), ASCII56.mask(), ASCII57.mask(),
ASCII58.mask(), ASCII59.mask(), ASCII5A.mask(), ASCII5B.mask(),
ASCII5C.mask(), ASCII5D.mask(), ASCII5E.mask(), ASCII5F.mask(),
ASCII60.mask(), ASCII61.mask(), ASCII62.mask(), ASCII63.mask(),
ASCII64.mask(), ASCII65.mask(), ASCII66.mask(), ASCII67.mask(),
ASCII68.mask(), ASCII69.mask(), ASCII6A.mask(), ASCII6B.mask(),
ASCII6C.mask(), ASCII6D.mask(), ASCII6E.mask(), ASCII6F.mask(),
ASCII70.mask(), ASCII71.mask(), ASCII72.mask(), ASCII73.mask(),
ASCII74.mask(), ASCII75.mask(), ASCII76.mask(), ASCII77.mask(),
ASCII78.mask(), ASCII79.mask(), ASCII7A.mask(), ASCII7B.mask(),
ASCII7C.mask(), ASCII7D.mask(), ASCII7E.mask(), ASCII7F.mask(),
}
var iso88591 = [...]Keycode{
ISO88591A0.mask(), ISO88591A1.mask(), ISO88591A2.mask(), ISO88591A3.mask(),
ISO88591A4.mask(), ISO88591A5.mask(), ISO88591A6.mask(), ISO88591A7.mask(),
ISO88591A8.mask(), ISO88591A9.mask(), ISO88591AA.mask(), ISO88591AB.mask(),
ISO88591AC.mask(), ISO88591AD.mask(), ISO88591AE.mask(), ISO88591AF.mask(),
ISO88591B0.mask(), ISO88591B1.mask(), ISO88591B2.mask(), ISO88591B3.mask(),
ISO88591B4.mask(), ISO88591B5.mask(), ISO88591B6.mask(), ISO88591B7.mask(),
ISO88591B8.mask(), ISO88591B9.mask(), ISO88591BA.mask(), ISO88591BB.mask(),
ISO88591BC.mask(), ISO88591BD.mask(), ISO88591BE.mask(), ISO88591BF.mask(),
ISO88591C0.mask(), ISO88591C1.mask(), ISO88591C2.mask(), ISO88591C3.mask(),
ISO88591C4.mask(), ISO88591C5.mask(), ISO88591C6.mask(), ISO88591C7.mask(),
ISO88591C8.mask(), ISO88591C9.mask(), ISO88591CA.mask(), ISO88591CB.mask(),
ISO88591CC.mask(), ISO88591CD.mask(), ISO88591CE.mask(), ISO88591CF.mask(),
ISO88591D0.mask(), ISO88591D1.mask(), ISO88591D2.mask(), ISO88591D3.mask(),
ISO88591D4.mask(), ISO88591D5.mask(), ISO88591D6.mask(), ISO88591D7.mask(),
ISO88591D8.mask(), ISO88591D9.mask(), ISO88591DA.mask(), ISO88591DB.mask(),
ISO88591DC.mask(), ISO88591DD.mask(), ISO88591DE.mask(), ISO88591DF.mask(),
ISO88591E0.mask(), ISO88591E1.mask(), ISO88591E2.mask(), ISO88591E3.mask(),
ISO88591E4.mask(), ISO88591E5.mask(), ISO88591E6.mask(), ISO88591E7.mask(),
ISO88591E8.mask(), ISO88591E9.mask(), ISO88591EA.mask(), ISO88591EB.mask(),
ISO88591EC.mask(), ISO88591ED.mask(), ISO88591EE.mask(), ISO88591EF.mask(),
ISO88591F0.mask(), ISO88591F1.mask(), ISO88591F2.mask(), ISO88591F3.mask(),
ISO88591F4.mask(), ISO88591F5.mask(), ISO88591F6.mask(), ISO88591F7.mask(),
ISO88591F8.mask(), ISO88591F9.mask(), ISO88591FA.mask(), ISO88591FB.mask(),
ISO88591FC.mask(), ISO88591FD.mask(), ISO88591FE.mask(), ISO88591FF.mask(),
}

90
src/machine/usb/hid/mouse/mouse.go Обычный файл
Просмотреть файл

@ -0,0 +1,90 @@
package mouse
import (
"machine/usb/hid"
)
var Mouse *mouse
type mouse struct {
buf *hid.RingBuffer
}
func init() {
if Mouse == nil {
Mouse = newMouse()
hid.SetCallbackHandler(Mouse)
}
}
// New returns hid-mouse.
func New() *mouse {
return Mouse
}
func newMouse() *mouse {
return &mouse{
buf: hid.NewRingBuffer(),
}
}
func (m *mouse) Callback() bool {
if b, ok := m.buf.Get(); ok {
hid.SendUSBPacket(b[:5])
return true
}
return false
}
// Move is a function that moves the mouse cursor.
func (m *mouse) Move(vx, vy int) {
if vx == 0 && vy == 0 {
return
}
if vx < -128 {
vx = -128
}
if vx > 127 {
vx = 127
}
if vy < -128 {
vy = -128
}
if vy > 127 {
vy = 127
}
m.buf.Put([]byte{
0x01, 0x00, byte(vx), byte(vy), 0x00,
})
}
// WHEEL controls the mouse wheel.
func (m *mouse) Wheel(v int) {
if v == 0 {
return
}
if v < -128 {
v = -128
}
if v > 127 {
v = 127
}
m.buf.Put([]byte{
0x01, 0x00, 0x00, 0x00, byte(v),
})
}
// WheelDown turns the mouse wheel down.
func (m *mouse) WheelDown() {
m.Wheel(-1)
}
// WheelUp turns the mouse wheel up.
func (m *mouse) WheelUp() {
m.Wheel(1)
}

70
src/machine/usb_descriptor.go Обычный файл
Просмотреть файл

@ -0,0 +1,70 @@
//go:build sam || nrf52840
// +build sam nrf52840
package machine
type USBDescriptor struct {
Device []byte
Configuration []byte
HID map[uint16][]byte
}
func (d *USBDescriptor) Configure(idVendor, idProduct uint16) {
d.Device[8] = byte(idVendor)
d.Device[9] = byte(idVendor >> 8)
d.Device[10] = byte(idProduct)
d.Device[11] = byte(idProduct >> 8)
}
var descriptorCDC = USBDescriptor{
Device: []byte{
0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x86, 0x28, 0x2d, 0x80, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01,
},
Configuration: []byte{
0x09, 0x02, 0x4b, 0x00, 0x02, 0x01, 0x00, 0xa0, 0x32,
0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00,
0x05, 0x24, 0x00, 0x10, 0x01,
0x04, 0x24, 0x02, 0x06,
0x05, 0x24, 0x06, 0x00, 0x01,
0x05, 0x24, 0x01, 0x01, 0x01,
0x07, 0x05, 0x81, 0x03, 0x10, 0x00, 0x10,
0x09, 0x04, 0x01, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00,
0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00,
0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00,
},
}
var descriptorCDCHID = USBDescriptor{
Device: []byte{
0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x86, 0x28, 0x2d, 0x80, 0x00, 0x01, 0x01, 0x02, 0x03, 0x01,
},
Configuration: []byte{
0x09, 0x02, 0x64, 0x00, 0x03, 0x01, 0x00, 0xa0, 0x32,
0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00,
0x05, 0x24, 0x00, 0x10, 0x01,
0x04, 0x24, 0x02, 0x06,
0x05, 0x24, 0x06, 0x00, 0x01,
0x05, 0x24, 0x01, 0x01, 0x01,
0x07, 0x05, 0x81, 0x03, 0x10, 0x00, 0x10,
0x09, 0x04, 0x01, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00,
0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00,
0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00,
0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,
0x09, 0x21, 0x01, 0x01, 0x00, 0x01, 0x22, 0x65, 0x00,
0x07, 0x05, 0x84, 0x03, 0x40, 0x00, 0x01,
},
HID: map[uint16][]byte{
2: []byte{
// keyboard and mouse
0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x85, 0x02, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00,
0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x03, 0x95, 0x06,
0x75, 0x08, 0x15, 0x00, 0x25, 0x73, 0x05, 0x07, 0x19, 0x00, 0x29, 0x73, 0x81, 0x00, 0xc0, 0x05,
0x01, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x01, 0xa1, 0x00, 0x85, 0x01, 0x05, 0x09, 0x19, 0x01, 0x29,
0x03, 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81,
0x03, 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7f, 0x75, 0x08, 0x95,
0x03, 0x81, 0x06, 0xc0, 0xc0,
},
},
}