From 4b8b4243ec79a264cbfde49aa2cbf1c75779dbf5 Mon Sep 17 00:00:00 2001 From: ardnew Date: Fri, 14 Jan 2022 16:47:31 -0600 Subject: [PATCH] cleanup and compatibility updates from STM32H7 USB implemenetation --- src/examples/usb/keyboard/keyboard.go | 8 +- src/machine/usb/dcd.go | 72 ++- src/machine/usb/desc.go | 101 ++-- src/machine/usb/desc_mimxrt1062.go | 25 +- src/machine/usb/dhw_mimxrt1062.go | 51 +- src/machine/usb/hcd.go | 8 +- src/machine/usb/hhw_mimxrt1062.go | 16 +- src/machine/usb/hid.go | 15 +- src/machine/usb/keyboard.go | 783 +++++++++++--------------- src/machine/usb/uart.go | 13 +- src/machine/usb/usb.go | 35 +- src/machine/usb/util.go | 98 +++- 12 files changed, 640 insertions(+), 585 deletions(-) diff --git a/src/examples/usb/keyboard/keyboard.go b/src/examples/usb/keyboard/keyboard.go index 7e7530067..cf2c66253 100644 --- a/src/examples/usb/keyboard/keyboard.go +++ b/src/examples/usb/keyboard/keyboard.go @@ -143,7 +143,7 @@ func main() { time.Sleep(5 * time.Second) - // Open serial connection + // Open serial connection (GNU screen) keyboard.Write([]byte("screen /dev/ttyACM0 115200")) time.Sleep(2 * time.Second) keyboard.Press(usb.KeyEnter) @@ -159,19 +159,23 @@ func main() { keyboard.Press(usb.KeyEnter) time.Sleep(2 * time.Second) - // Close serial connection + // Close serial connection (GNU screen) keyboard.Down(usb.KeyModifierCtrl) + // Ctrl-X is the prefix sequence in my GNU screen configuration keyboard.Press(usb.KeyX) keyboard.Up(usb.KeyModifierCtrl) time.Sleep(time.Second) + // Backslash (Prefix-\) is the GNU screen command to kill window keyboard.Press(usb.KeyBackslash) time.Sleep(time.Second) + // Confirm "Kill window (Y/N)?" prompt keyboard.Press(usb.KeyY) keyboard.Press(usb.KeyEnter) time.Sleep(2 * time.Second) // Close terminal keyboard.Down(usb.KeyModifierCtrl) + // Ctrl-D exits the shell (sends a resemblance of EOF, I believe?) keyboard.Press(usb.KeyD) keyboard.Up(usb.KeyModifierCtrl) diff --git a/src/machine/usb/dcd.go b/src/machine/usb/dcd.go index d4cbdfa73..85b43cdbc 100644 --- a/src/machine/usb/dcd.go +++ b/src/machine/usb/dcd.go @@ -1,15 +1,14 @@ package usb -// Implementation of 32-bit target-agnostic USB device controller driver (dcd). +// Implementation of target-agnostic USB device controller driver (dcd). +// +// The types, constants, and methods defined in this unit are applicable to all +// targets. It was designed to complement the device hardware abstraction (dhw) +// implemented for each target, providing common/shared functionality and +// defining a standard interface with which the dhw must adhere. import "unsafe" -func init() { - if unsafe.Sizeof(uintptr(0)) > 4 { - panic("USB device controller is only supported on 32-bit systems") - } -} - // dcdCount defines the number of USB cores to configure for device mode. It is // computed as the sum of all declared device configuration descriptors. const dcdCount = descCDCACMCount + descHIDCount @@ -22,8 +21,7 @@ var dcdInstance [dcdCount]dcd // abstraction for ports configured as device on this platform. var dhwInstance [dcdCount]dhw -// dcd implements a generic USB device controller driver (dcd) for 32-bit ARM -// targets. +// dcd implements a generic USB device controller driver (dcd) for all targets. type dcd struct { *dhw // USB hardware abstraction layer @@ -36,7 +34,7 @@ type dcd struct { // initDCD initializes and assigns a free device controller instance to the // given USB port. Returns the initialized device controller or nil if no free // device controller instances remain. -func initDCD(port int, class class) (*dcd, status) { +func initDCD(port int, speed Speed, class class) (*dcd, status) { if 0 == dcdCount { return nil, statusInvalid // Must have defined device controllers } @@ -51,7 +49,7 @@ func initDCD(port int, class class) (*dcd, status) { for i := range dcdInstance { if nil == dcdInstance[i].core { // Initialize device controller. - dcdInstance[i].dhw = allocDHW(port, i, &dcdInstance[i]) + dcdInstance[i].dhw = allocDHW(port, i, speed, &dcdInstance[i]) dcdInstance[i].core = &coreInstance[port] dcdInstance[i].port = port dcdInstance[i].cc = class @@ -77,6 +75,33 @@ type dcdSetup struct { wLength uint16 } +func setupFrom(addr uintptr) dcdSetup { + var u uint64 + for i := uintptr(0); i < 8; i++ { + u |= uint64(*(*uint8)(unsafe.Pointer(addr + i))) << (i << 3) + } + return dcdSetup{ + bmRequestType: uint8(u & 0xFF), + bRequest: uint8((u & 0xFF00) >> 8), + wValue: uint16((u & 0xFFFF0000) >> 16), + wIndex: uint16((u & 0xFFFF00000000) >> 32), + wLength: uint16((u & 0xFFFF000000000000) >> 48), + } +} + +func setup(b []uint8) dcdSetup { + if len(b) >= 8 { + return dcdSetup{ + bmRequestType: b[0], + bRequest: b[1], + wValue: packU16(b[2:]), + wIndex: packU16(b[4:]), + wLength: packU16(b[6:]), + } + } + return dcdSetup{} +} + // pack returns the receiver setup packet encoded as uint64. func (s dcdSetup) pack() uint64 { return ((uint64(s.bmRequestType) & 0xFF) << 0) | @@ -130,10 +155,13 @@ func (d *dcd) event(ev dcdEvent) { case dcdEventStatusError: case dcdEventControlSetup: // On control endpoint 0 setup events, the ev.setup field will be defined - switch d.controlSetup(ev.setup) { + d.stage = d.controlSetup(ev.setup) + switch d.stage { case dcdStageSetup: - case dcdStageData: - case dcdStageStatus: + case dcdStageDataIn: + case dcdStageDataOut: + case dcdStageStatusIn: + case dcdStageStatusOut: case dcdStageStall: d.controlStall() } @@ -144,15 +172,17 @@ func (d *dcd) event(ev dcdEvent) { } } -// dcdStage represents the USB transaction stage of a control request. +// dcdStage represents the stage of a USB control transfer. type dcdStage uint8 -// Enumerated constants for all possible USB transaction stages. +// Enumerated constants for all possible USB control transfer stages. const ( - dcdStageSetup dcdStage = iota // Indicates no stage transition required - dcdStageData // IN/OUT data transfer - dcdStageStatus // Setup request complete - dcdStageStall // Unhandled or invalid request + dcdStageSetup dcdStage = iota // Indicates no stage transition required + dcdStageDataIn // IN data transfer + dcdStageDataOut // OUT data transfer + dcdStageStatusIn // IN status request + dcdStageStatusOut // OUT status request + dcdStageStall // Unhandled or invalid request ) // controlSetup handles setup messages on control endpoint 0. @@ -287,7 +317,7 @@ func (d *dcd) controlSetup(sup dcdSetup) dcdStage { // Unhandled device class } - // GET DESCRIPTOR (0x06): + // GET HID REPORT (0x01): case descHIDRequestGetReport: // Respond based on our device class configuration diff --git a/src/machine/usb/desc.go b/src/machine/usb/desc.go index ae5c83d22..3cecccd17 100644 --- a/src/machine/usb/desc.go +++ b/src/machine/usb/desc.go @@ -135,10 +135,27 @@ const ( descDeviceCapExtAttrBESLPos = 2 ) +// device returns the enumerated device descriptor value, defined per USB +// specification, for the receiver Speed s. +func (s Speed) device() uint32 { + switch s { + case LowSpeed: + return descDeviceSpeedLow + case FullSpeed: + return descDeviceSpeedFull + case HighSpeed: + return descDeviceSpeedHigh + case SuperSpeed, DualSuperSpeed: + return descDeviceSpeedSuper + default: // unrecognized Speed defaults to full-speed + return descDeviceSpeedFull + } +} + const ( // Attributes of all endpoint descriptor configurations. descEndptConfigAttr = descConfigAttrD7Msk | // Bit 7: reserved (1) - (1 << descConfigAttrSelfPoweredPos) | // Bit 6: self-powered + (0 << descConfigAttrSelfPoweredPos) | // Bit 6: self-powered (0 << descConfigAttrRemoteWakeupPos) | // Bit 5: remote wakeup 0 // Bits 0-4: reserved (0) @@ -354,8 +371,8 @@ const ( descLengthEndpoint + // Mouse Endpoint Descriptor descLengthInterface + // Serial Interface Descriptor descLengthInterface + // Serial HID Interface Descriptor - descLengthEndpoint + // Serial Endpoint Descriptor - descLengthEndpoint + + descLengthEndpoint + // Serial Tx Endpoint Descriptor + descLengthEndpoint + // Serial Rx Endpoint Descriptor descLengthInterface + // Joystick Interface Descriptor descLengthInterface + // Joystick HID Interface Descriptor descLengthEndpoint + // Joystick Endpoint Descriptor @@ -420,14 +437,16 @@ const ( descCDCACMInterfaceCount = 2 // Interfaces for all CDC-ACM configurations. descCDCACMEndpointCount = 4 // Endpoints for all CDC-ACM configurations. + descCDCACMEndpointCtrl = 0 // CDC-ACM Control Endpoint 0 + descCDCACMInterfaceCtrl = 0 // CDC-ACM Control Interface - descCDCACMEndpointStatus = 2 // CDC-ACM Interrupt IN Endpoint + descCDCACMEndpointStatus = 1 // CDC-ACM Interrupt IN Endpoint descCDCACMConfigAttrStatus = descEndptConfigAttrRxUnused | descEndptConfigAttrTxInterrupt descCDCACMInterfaceData = 1 // CDC-ACM Data Interface - descCDCACMEndpointDataRx = 3 // CDC-ACM Bulk Data OUT (Rx) Endpoint + descCDCACMEndpointDataRx = 2 // CDC-ACM Bulk Data OUT (Rx) Endpoint descCDCACMConfigAttrDataRx = descEndptConfigAttrRxBulk | descEndptConfigAttrTxUnused - descCDCACMEndpointDataTx = 4 // CDC-ACM Bulk Data IN (Tx) Endpoint + descCDCACMEndpointDataTx = 3 // CDC-ACM Bulk Data IN (Tx) Endpoint descCDCACMConfigAttrDataTx = descEndptConfigAttrRxUnused | descEndptConfigAttrTxBulk ) @@ -509,7 +528,7 @@ var descCDCACM = [dcdCount]descCDCACMClass{ 1, // Value to use to select this configuration (1 = CDC-ACM[0]) 0, // Index of string descriptor describing this configuration descEndptConfigAttr, // Configuration attributes - descCDCACMMaxPower, // Max power consumption when fully-operational (2 mA units) + descCDCACMMaxPowerMa >> 1, // Max power consumption when fully-operational (2 mA units) // Communication/Control Interface Descriptor descLengthInterface, // Descriptor length @@ -519,7 +538,7 @@ var descCDCACM = [dcdCount]descCDCACMClass{ 1, // Number of endpoints descCDCTypeComm, // Class code descCDCSubAbstractControl, // Subclass code - descCDCProtoNone, // Protocol code (NOTE: Teensyduino defines this as 1 [AT V.250]) + descCDCProtoAT250, // Protocol code (NOTE: Teensyduino & Arduino-Mbed define this as 1 [AT V.250]) 0, // Interface Description String Index // CDC Header Functional Descriptor @@ -600,6 +619,8 @@ const ( descHIDInterfaceCount = 5 // Interfaces for all HID configurations. descHIDEndpointCount = 6 // Endpoints for all HID configurations. + descHIDEndpointCtrl = 0 // HID Control Endpoint 0 + descHIDInterfaceKeyboard = 0 // HID Keyboard Interface descHIDEndpointKeyboard = 3 // HID Keyboard IN Endpoint descHIDConfigAttrKeyboard = descEndptConfigAttrTxInterrupt | descEndptConfigAttrRxUnused @@ -701,7 +722,7 @@ var descHID = [dcdCount]descHIDClass{ 1, // Value to use to select this configuration (1 = CDC-ACM[0]) 0, // Index of string descriptor describing this configuration descEndptConfigAttr, // Configuration attributes - descHIDMaxPower, // Max power consumption when fully-operational (2 mA units) + descHIDMaxPowerMa >> 1, // Max power consumption when fully-operational (2 mA units) // [9+9] Keyboard Interface Descriptor descLengthInterface, // Descriptor length @@ -896,37 +917,37 @@ var descHIDReportSerial = [...]uint8{ } var descHIDReportKeyboard = [...]uint8{ - 0x05, 0x01, // Usage Page (Generic Desktop), - 0x09, 0x06, // Usage (Keyboard), - 0xA1, 0x01, // Collection (Application), - 0x75, 0x01, // Report Size (1), - 0x95, 0x08, // Report Count (8), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0xE0, // Usage Minimum (224), - 0x29, 0xE7, // Usage Maximum (231), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x01, // Logical Maximum (1), - 0x81, 0x02, // Input (Data, Variable, Absolute), ; Modifier keys - 0x95, 0x01, // Report Count (1), - 0x75, 0x08, // Report Size (8), - 0x81, 0x03, // Input (Constant), ; Reserved byte - 0x95, 0x05, // Report Count (5), - 0x75, 0x01, // Report Size (1), - 0x05, 0x08, // Usage Page (LEDs), - 0x19, 0x01, // Usage Minimum (1), - 0x29, 0x05, // Usage Maximum (5), - 0x91, 0x02, // Output (Data, Variable, Absolute), ; LED report - 0x95, 0x01, // Report Count (1), - 0x75, 0x03, // Report Size (3), - 0x91, 0x03, // Output (Constant), ; LED report padding - 0x95, 0x06, // Report Count (6), - 0x75, 0x08, // Report Size (8), - 0x15, 0x00, // Logical Minimum (0), - 0x25, 0x7F, // Logical Maximum(104), - 0x05, 0x07, // Usage Page (Key Codes), - 0x19, 0x00, // Usage Minimum (0), - 0x29, 0x7F, // Usage Maximum (104), - 0x81, 0x00, // Input (Data, Array), ; Normal keys + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x06, // Usage (Keyboard) + 0xA1, 0x01, // Collection (Application) + 0x75, 0x01, // Report Size (1) + 0x95, 0x08, // Report Count (8) + 0x05, 0x07, // Usage Page (Key Codes) + 0x19, 0xE0, // Usage Minimum (224) + 0x29, 0xE7, // Usage Maximum (231) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x81, 0x02, // Input (Data, Variable, Absolute) [Modifier keys] + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x03, // Input (Constant) [Reserved byte] + 0x95, 0x05, // Report Count (5) + 0x75, 0x01, // Report Size (1) + 0x05, 0x08, // Usage Page (LEDs) + 0x19, 0x01, // Usage Minimum (1) + 0x29, 0x05, // Usage Maximum (5) + 0x91, 0x02, // Output (Data, Variable, Absolute) [LED report] + 0x95, 0x01, // Report Count (1) + 0x75, 0x03, // Report Size (3) + 0x91, 0x03, // Output (Constant) [LED report padding] + 0x95, 0x06, // Report Count (6) + 0x75, 0x08, // Report Size (8) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x7F, // Logical Maximum(104) + 0x05, 0x07, // Usage Page (Key Codes) + 0x19, 0x00, // Usage Minimum (0) + 0x29, 0x7F, // Usage Maximum (104) + 0x81, 0x00, // Input (Data, Array) [Normal keys] 0xC0, // End Collection } diff --git a/src/machine/usb/desc_mimxrt1062.go b/src/machine/usb/desc_mimxrt1062.go index fd8e3dbd9..a5214d963 100644 --- a/src/machine/usb/desc_mimxrt1062.go +++ b/src/machine/usb/desc_mimxrt1062.go @@ -5,13 +5,18 @@ package usb // descCPUFrequencyHz defines the target CPU frequency (Hz). const descCPUFrequencyHz = 600000000 +// descCoreCount defines the number of USB PHY cores available on this platform, +// independent of the number of cores which shall be configured as TinyGo USB +// host/device controller instances. +const descCoreCount = 2 + // descCDCACMCount defines the number of USB cores that may be configured as // CDC-ACM (single) devices. -const descCDCACMCount = 0 +const descCDCACMCount = 1 // descHIDCount defines the number of USB cores that may be configured as a // composite (keyboard + mouse + joystick) human interface device (HID). -const descHIDCount = 1 +const descHIDCount = 0 // General USB device identification constants. const ( @@ -27,7 +32,10 @@ const ( // Constants for USB CDC-ACM device classes. const ( - descCDCACMMaxPower = 50 // 100 mA + + // USB bus configuration attributes + + descCDCACMMaxPowerMa = 100 // Maximum current (mA) requested from host // CDC-ACM Control Buffers @@ -77,7 +85,10 @@ const ( // Constants for USB HID (keyboard, mouse, joystick) device classes. const ( - descHIDMaxPower = 50 // 100 mA + + // USB bus configuration attributes + + descHIDMaxPowerMa = 100 // Maximum current (mA) requested from host // HID Control Buffers @@ -541,7 +552,10 @@ type descHIDClassData struct { // HID Device Instances + //serial *Serial keyboard *Keyboard + //mouse *Mouse + //joystick *Joystick } // descHIDData holds statically-allocated instances for each of the target- @@ -599,6 +613,9 @@ var descHIDData = [dcdCount]descHIDClassData{ // HID Device Instances + //serial: &descHID0Serial, keyboard: &descHID0Keyboard, + //mouse: &descHID0Mouse, + //joystick: &descHID0Joystick, }, } diff --git a/src/machine/usb/dhw_mimxrt1062.go b/src/machine/usb/dhw_mimxrt1062.go index a2700c9a7..feafffc18 100644 --- a/src/machine/usb/dhw_mimxrt1062.go +++ b/src/machine/usb/dhw_mimxrt1062.go @@ -28,12 +28,13 @@ type dhw struct { stat *dhwEndpoint // endpoint 0 Rx ("out" direction) ctrl *dhwEndpoint // endpoint 0 Tx ("in" direction) - busSpeed uint8 // 0 = full, 1 = low, 2 = high, 4 = super + speed Speed controlReply [8]uint8 controlMask uint32 endpointMask uint32 setup dcdSetup + stage dcdStage timerInterrupt [2]func() timerReboot uint8 @@ -64,7 +65,7 @@ func flushCache(addr, size uintptr) { nxp.FlushDeleteDcache(addr, size) } // allocDHW returns a reference to the USB hardware abstraction for the given // device controller driver. Should be called only one time and during device // controller initialization. -func allocDHW(port, instance int, dc *dcd) *dhw { +func allocDHW(port, instance int, speed Speed, dc *dcd) *dhw { switch port { case 0: dhwInstance[instance].dcd = dc @@ -83,16 +84,22 @@ func allocDHW(port, instance int, dc *dcd) *dhw { dhwInstance[instance].irq = interrupt.New(nxp.IRQ_USB_OTG2, func(interrupt.Interrupt) { - //coreInstance[1].dc.interrupt() + coreInstance[1].dc.interrupt() }) } + // Both ports default to high-speed (480 Mbit/sec) on Teensy 4.x + if 0 == speed { + speed = HighSpeed + } + dhwInstance[instance].speed = speed + return &dhwInstance[instance] } // init configures the USB port for device mode operation by initializing all // endpoint and transfer descriptor data structures, initializing core registers -// and interrupts, resetting the USB PHY, and enabling power on the bust. +// and interrupts, resetting the USB PHY, and enabling power on the bus. func (d *dhw) init() status { // Reset the controller @@ -315,9 +322,9 @@ func (d *dhw) interrupt() { // DCSuspend bits respectively. if 0 != status&nxp.USB_USBSTS_PCI { if d.bus.PORTSC1.HasBits(nxp.USB_PORTSC1_HSP) { - d.busSpeed = descDeviceSpeedHigh // 480 Mbit/sec + d.speed = HighSpeed // 480 Mbit/sec } else { - d.busSpeed = descDeviceSpeedFull // 12 Mbit/sec + d.speed = FullSpeed // 12 Mbit/sec } d.event(dcdEvent{id: dcdEventStatusRun}) } @@ -364,8 +371,6 @@ func (d *dhw) interrupt() { } } -func (d *dhw) speed() uint8 { return d.busSpeed } - func (d *dhw) setDeviceAddress(addr uint16) { d.bus.DEVICEADDR.Set(nxp.USB_DEVICEADDR_USBADRA | ((uint32(addr) << nxp.USB_DEVICEADDR_USBADR_Pos) & @@ -893,11 +898,13 @@ func (d *dhw) uartConfigure() { acm := &descCDCACM[d.cc.config-1] - switch d.speed() { - case descDeviceSpeedHigh: + switch d.speed { + case HighSpeed, SuperSpeed, DualSuperSpeed: acm.rxSize = descCDCACMDataRxHSPacketSize acm.txSize = descCDCACMDataTxHSPacketSize default: + fallthrough + case LowSpeed, FullSpeed: acm.rxSize = descCDCACMDataRxFSPacketSize acm.txSize = descCDCACMDataTxFSPacketSize } @@ -1151,11 +1158,13 @@ func (d *dhw) serialConfigure() { hid := &descHID[d.cc.config-1] - switch d.speed() { - case descDeviceSpeedHigh: + switch d.speed { + case HighSpeed, SuperSpeed, DualSuperSpeed: hid.rxSerialSize = descHIDSerialRxHSPacketSize hid.txSerialSize = descHIDSerialTxHSPacketSize default: + fallthrough + case LowSpeed, FullSpeed: hid.rxSerialSize = descHIDSerialRxFSPacketSize hid.txSerialSize = descHIDSerialTxFSPacketSize } @@ -1268,10 +1277,12 @@ func (d *dhw) keyboardConfigure() { // Initialize keyboard hid.keyboard.configure(d.dcd, hid) - switch d.speed() { - case descDeviceSpeedHigh: + switch d.speed { + case HighSpeed, SuperSpeed, DualSuperSpeed: hid.txKeyboardSize = descHIDKeyboardTxHSPacketSize default: + fallthrough + case LowSpeed, FullSpeed: hid.txKeyboardSize = descHIDKeyboardTxFSPacketSize } @@ -1367,10 +1378,12 @@ func (d *dhw) mouseConfigure() { hid := &descHID[d.cc.config-1] - switch d.speed() { - case descDeviceSpeedHigh: + switch d.speed { + case HighSpeed, SuperSpeed, DualSuperSpeed: hid.txMouseSize = descHIDMouseTxHSPacketSize default: + fallthrough + case LowSpeed, FullSpeed: hid.txMouseSize = descHIDMouseTxFSPacketSize } @@ -1389,10 +1402,12 @@ func (d *dhw) joystickConfigure() { hid := &descHID[d.cc.config-1] - switch d.speed() { - case descDeviceSpeedHigh: + switch d.speed { + case HighSpeed, SuperSpeed, DualSuperSpeed: hid.txJoystickSize = descHIDJoystickTxHSPacketSize default: + fallthrough + case LowSpeed, FullSpeed: hid.txJoystickSize = descHIDJoystickTxFSPacketSize } diff --git a/src/machine/usb/hcd.go b/src/machine/usb/hcd.go index 4e7f34d8d..0cf8dad46 100644 --- a/src/machine/usb/hcd.go +++ b/src/machine/usb/hcd.go @@ -1,6 +1,6 @@ package usb -// Implementation of 32-bit target-agnostic USB host controller driver (hcd). +// Implementation of target-agnostic USB host controller driver (hcd). // hcdCount defines the number of USB cores to configure for host mode. It is // computed as the sum of all declared host configuration descriptors. @@ -14,7 +14,7 @@ var hcdInstance [hcdCount]hcd // abstraction for ports configured as host on this platform. var hhwInstance [hcdCount]hhw -// hcd implements USB host controller driver (hcd) interface. +// hcd implements a generic USB host controller driver (hcd) for all targets. type hcd struct { *hhw // USB hardware abstraction layer @@ -27,7 +27,7 @@ type hcd struct { // initHCD initializes and assigns a free host controller instance to the given // USB port. Returns the initialized host controller or nil if no free host // controller instances remain. -func initHCD(port int, class class) (*hcd, status) { +func initHCD(port int, speed Speed, class class) (*hcd, status) { if 0 == hcdCount { return nil, statusInvalid // Must have defined host controllers } @@ -38,7 +38,7 @@ func initHCD(port int, class class) (*hcd, status) { for i := range hcdInstance { if nil == hcdInstance[i].core { // Initialize host controller. - hcdInstance[i].hhw = allocHHW(port, i, &hcdInstance[i]) + hcdInstance[i].hhw = allocHHW(port, i, speed, &hcdInstance[i]) hcdInstance[i].core = &coreInstance[port] hcdInstance[i].port = port hcdInstance[i].cc = class diff --git a/src/machine/usb/hhw_mimxrt1062.go b/src/machine/usb/hhw_mimxrt1062.go index 52c188437..36c04e6bc 100644 --- a/src/machine/usb/hhw_mimxrt1062.go +++ b/src/machine/usb/hhw_mimxrt1062.go @@ -9,22 +9,24 @@ import ( "runtime/interrupt" ) -// hcdInterruptPriority defines the priority for all USB host interrupts. -const hcdInterruptPriority = 3 +// hhwInterruptPriority defines the priority for all USB host interrupts. +const hhwInterruptPriority = 3 -// hcd implements USB host controller driver (hcd) interface. +// hhw implements USB host controller hardware abstraction interface. type hhw struct { *hcd // USB host controller driver bus *nxp.USB_Type // USB core register phy *nxp.USBPHY_Type // USB PHY register irq interrupt.Interrupt // USB IRQ, only a single interrupt on iMXRT1062 + + speed Speed } // allocHHW returns a reference to the USB hardware abstraction for the given // host controller driver. Should be called only one time and during host // controller initialization. -func allocHHW(port, instance int, hc *hcd) *hhw { +func allocHHW(port, instance int, speed Speed, hc *hcd) *hhw { switch port { case 0: hhwInstance[instance].hcd = hc @@ -37,6 +39,12 @@ func allocHHW(port, instance int, hc *hcd) *hhw { hhwInstance[instance].phy = nxp.USBPHY2 } + // Both ports default to high-speed (480 Mbit/sec) on Teensy 4.x + if 0 == speed { + speed = HighSpeed + } + hhwInstance[instance].speed = speed + return &hhwInstance[instance] } diff --git a/src/machine/usb/hid.go b/src/machine/usb/hid.go index 6b2dcc9ab..fdc5c73c7 100644 --- a/src/machine/usb/hid.go +++ b/src/machine/usb/hid.go @@ -10,27 +10,26 @@ var ( ErrHIDReportTransfer = errors.New("failed to transfer HID report") ) +// HID represents a virtual keyboard/mouse/joystick device (with a serial data +// Rx/Tx interface) using the USB HID device class driver. type HID struct { + // Port is the MCU's native USB core number. If in doubt, leave it + // uninitialized for default (0). Port int core *core } type HIDConfig struct { - // Port is the MCU's native USB core number. If in doubt, leave it - // uninitialized for default (0). - Port int + BusSpeed Speed } func (hid *HID) Configure(config HIDConfig) error { - if config.Port >= CoreCount || config.Port >= dcdCount { - return ErrHIDInvalidPort - } - hid.Port = config.Port + c := class{id: classDeviceHID, config: 1} // verify we have a free USB port and take ownership of it var st status - hid.core, st = initCore(hid.Port, class{id: classDeviceHID, config: 1}) + hid.core, st = initCore(hid.Port, config.BusSpeed, c) if !st.ok() { return ErrHIDInvalidPort } diff --git a/src/machine/usb/keyboard.go b/src/machine/usb/keyboard.go index b0988f78d..a67ae6c8d 100644 --- a/src/machine/usb/keyboard.go +++ b/src/machine/usb/keyboard.go @@ -181,10 +181,10 @@ func (kb *Keyboard) Press(c Keycode) error { return kb.Up(c) } -// Down transmits a press (key-down) event for the given Keycode. +// Down transmits a key-down event for the given Keycode. // // The host will interpret the key as being held down continuously until a -// corresponding release (key-up) event is transmitted, e.g., via method Up(). +// 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. @@ -303,7 +303,7 @@ func (kb *Keyboard) downSys(key uint8) error { return ErrKeypressMaximum } -// Release transmits a release (key-up) event for the given Keycode. +// 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. @@ -338,6 +338,8 @@ func (kb *Keyboard) Up(c Keycode) error { 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) @@ -435,8 +437,8 @@ func keycode(p uint16) Keycode { return ascii[p] } else if p >= 0xA0 && p < 0x0100 { return iso88591[p-0xA0] - } else if uint16(UNICODEEXTRA00) == p { - return KEYCODEEXTRA00.mask() + } else if uint16(UNICODE20AC) == p { + return UNICODE20AC.mask() } return 0 } @@ -487,149 +489,149 @@ const ( // 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) + 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) + 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) + 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) + 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 @@ -659,11 +661,11 @@ const ( graveAccentBits Keycode = 0x0300 tildeBits Keycode = 0x0400 diaeresisBits Keycode = 0x0500 - deadkeyCircumflex Keycode = Key6 + shiftMask + deadkeyCircumflex Keycode = Key6 | shiftMask deadkeyAcuteAccent Keycode = KeyQuote deadkeyGraveAccent Keycode = KeyTilde - deadkeyTilde Keycode = KeyTilde + shiftMask - deadkeyDiaeresis Keycode = KeyQuote + shiftMask + deadkeyTilde Keycode = KeyTilde | shiftMask + deadkeyDiaeresis Keycode = KeyQuote | shiftMask ASCII00 Keycode = 0 // 0 NUL ASCII01 Keycode = 0 // 1 SOH @@ -698,298 +700,199 @@ const ( 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 // € Euro Sign - UNICODEEXTRA00 Keycode = 0x20AC - KEYCODEEXTRA00 Keycode = Key5 + altgrMask // 20AC € Euro Sign - - // ASCII20 Keycode = KeySpace // 32 SPACE - // ASCII21 Keycode = Key1 + shiftMask // 33 ! - // ASCII22 Keycode = KeyQuote + shiftMask // 34 " - // ASCII23 Keycode = Key3 + shiftMask // 35 # - // ASCII24 Keycode = Key4 + shiftMask // 36 $ - // ASCII25 Keycode = Key5 + shiftMask // 37 % - // ASCII26 Keycode = Key7 + shiftMask // 38 & - // ASCII27 Keycode = KeyQuote // 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 = Key6 + shiftMask // 94 ^ - // ASCII5F Keycode = KeyMinus + shiftMask // 95 - // ASCII60 Keycode = KeyTilde // 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 = KeyTilde + shiftMask // 126 ~ - // ASCII7F Keycode = KeyBackspace // 127 DEL + 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{ diff --git a/src/machine/usb/uart.go b/src/machine/usb/uart.go index f7e8f3aef..d50966f77 100644 --- a/src/machine/usb/uart.go +++ b/src/machine/usb/uart.go @@ -14,26 +14,23 @@ var ( // UART represents a virtual serial (UART) device emulation using the USB // CDC-ACM device class driver. type UART struct { + // Port is the MCU's native USB core number. If in doubt, leave it + // uninitialized for default (0). Port int core *core } type UARTConfig struct { - // Port is the MCU's native USB core number. If in doubt, leave it - // uninitialized for default (0). - Port int + BusSpeed Speed } func (uart *UART) Configure(config UARTConfig) error { - if config.Port >= CoreCount || config.Port >= dcdCount { - return ErrUARTInvalidPort - } - uart.Port = config.Port + c := class{id: classDeviceCDCACM, config: 1} // verify we have a free USB port and take ownership of it var st status - uart.core, st = initCore(uart.Port, class{id: classDeviceCDCACM, config: 1}) + uart.core, st = initCore(uart.Port, config.BusSpeed, c) if !st.ok() { return ErrUARTInvalidPort } diff --git a/src/machine/usb/usb.go b/src/machine/usb/usb.go index 5d4c4e4ca..208401337 100644 --- a/src/machine/usb/usb.go +++ b/src/machine/usb/usb.go @@ -2,9 +2,9 @@ package usb // Hardware abstraction for USB ports configured as either host or device. -// CoreCount defines the total number of USB cores to configure in device or -// host mode. -const CoreCount = dcdCount + hcdCount +// CoreCount defines the total number of USB cores which may be configured in +// device or host mode. +const CoreCount = descCoreCount // coreInstance provides statically-allocated instances of each USB core // configured on this platform. @@ -25,13 +25,27 @@ const ( modeHost = 2 ) +// Speed represents the configured USB data transfer rate, or bus speed, for +// communication between host and device. +type Speed uint8 + +// Constant definitions for USB data transfer rates. Note that every transfer +// rate may not be supported by every target due to either hardware or software +// limitations. By far, the most commonly-supported rate is USB 1.1 Full-Speed +// (12 Mbit/sec). If unsure, either use FullSpeed or leave it undefined and let +// the driver use the default speed for your target. +const ( + LowSpeed Speed = iota + 1 // 1.5 Mbit/sec (USB 1.0) + FullSpeed // 12 Mbit/sec (USB 1.1) + HighSpeed // 480 Mbit/sec (USB 2.0) + SuperSpeed // 5 Gbit/sec (USB 3.0) + DualSuperSpeed // 10 Gbit/sec (USB 3.1, Dual-Lane SS) +) + // initCore initializes a free USB core with given operating mode on the USB // port at given index, if available. Returns a reference to the initialized // core or nil if the core is unavailable. -func initCore(port int, class class) (*core, status) { - - iv := disableInterrupts() - defer enableInterrupts(iv) +func initCore(port int, speed Speed, class class) (*core, status) { if port < 0 || port >= CoreCount || 0 == class.config { return nil, statusInvalid @@ -62,7 +76,7 @@ func initCore(port int, class class) (*core, status) { switch class.mode() { case modeDevice: // Allocate a free device controller and install interrupts - dc, st := initDCD(port, class) + dc, st := initDCD(port, speed, class) if !st.ok() { return nil, st } @@ -77,7 +91,7 @@ func initCore(port int, class class) (*core, status) { case modeHost: // Allocate a free host controller and install interrupts - hc, st := initHCD(port, class) + hc, st := initHCD(port, speed, class) if !st.ok() { return nil, st } @@ -104,7 +118,7 @@ type class struct { config int } -// Enumerated constants for all host/device class configurations. +// Enumerated constants for all supported host/device class configurations. const ( classDeviceCDCACM = 0 classDeviceHID = 1 @@ -136,6 +150,7 @@ const ( statusOK status = iota // Success statusBusy // Busy statusInvalid // Invalid argument + statusFail // Failure ) // ok returns true if and only if the receiver st equals statusOK. diff --git a/src/machine/usb/util.go b/src/machine/usb/util.go index 5b88f7a50..6d8a92c03 100644 --- a/src/machine/usb/util.go +++ b/src/machine/usb/util.go @@ -10,14 +10,20 @@ func ticks() int64 // significant byte. //go:inline func leU64(u uint64) []uint8 { + var b [8]uint8 if u == 0 { // skip all processing for the common case (u = 0) - return []uint8{0, 0, 0, 0, 0, 0, 0, 0} - } - return []uint8{ - uint8(u), uint8(u >> 8), uint8(u >> 16), uint8(u >> 24), - uint8(u >> 32), uint8(u >> 40), uint8(u >> 48), uint8(u >> 56), + return b[:] } + b[0] = uint8(u) + b[1] = uint8(u >> 8) + b[2] = uint8(u >> 16) + b[3] = uint8(u >> 24) + b[4] = uint8(u >> 32) + b[5] = uint8(u >> 40) + b[6] = uint8(u >> 48) + b[7] = uint8(u >> 56) + return b[:] } // leU32 returns a slice containing 4 bytes from the given uint32 u. @@ -27,13 +33,16 @@ func leU64(u uint64) []uint8 { // significant byte. //go:inline func leU32(u uint32) []uint8 { + var b [4]uint8 if u == 0 { // skip all processing for the common case (u = 0) - return []uint8{0, 0, 0, 0} - } - return []uint8{ - uint8(u), uint8(u >> 8), uint8(u >> 16), uint8(u >> 24), + return b[:] } + b[0] = uint8(u) + b[1] = uint8(u >> 8) + b[2] = uint8(u >> 16) + b[3] = uint8(u >> 24) + return b[:] } // leU16 returns a slice containing 2 bytes from the given uint16 u. @@ -43,13 +52,14 @@ func leU32(u uint32) []uint8 { // significant byte. //go:inline func leU16(u uint16) []uint8 { + var b [2]uint8 if u == 0 { // skip all processing for the common case (u = 0) - return []uint8{0, 0} - } - return []uint8{ - uint8(u), uint8(u >> 8), + return b[:] } + b[0] = uint8(u) + b[1] = uint8(u >> 8) + return b[:] } // beU64 returns a slice containing 8 bytes from the given uint64 u. @@ -59,14 +69,20 @@ func leU16(u uint16) []uint8 { // significant byte. //go:inline func beU64(u uint64) []uint8 { + var b [8]uint8 if u == 0 { // skip all processing for the common case (u = 0) - return []uint8{0, 0, 0, 0, 0, 0, 0, 0} - } - return []uint8{ - uint8(u >> 56), uint8(u >> 48), uint8(u >> 40), uint8(u >> 32), - uint8(u >> 24), uint8(u >> 16), uint8(u >> 8), uint8(u), + return b[:] } + b[7] = uint8(u) + b[6] = uint8(u >> 8) + b[5] = uint8(u >> 16) + b[4] = uint8(u >> 24) + b[3] = uint8(u >> 32) + b[2] = uint8(u >> 40) + b[1] = uint8(u >> 48) + b[0] = uint8(u >> 56) + return b[:] } // beU32 returns a slice containing 4 bytes from the given uint32 u. @@ -76,13 +92,16 @@ func beU64(u uint64) []uint8 { // significant byte. //go:inline func beU32(u uint32) []uint8 { + var b [4]uint8 if u == 0 { // skip all processing for the common case (u = 0) - return []uint8{0, 0, 0, 0} - } - return []uint8{ - uint8(u >> 24), uint8(u >> 16), uint8(u >> 8), uint8(u), + return b[:] } + b[3] = uint8(u) + b[2] = uint8(u >> 8) + b[1] = uint8(u >> 16) + b[0] = uint8(u >> 24) + return b[:] } // beU16 returns a slice containing 2 bytes from the given uint16 u. @@ -92,13 +111,14 @@ func beU32(u uint32) []uint8 { // significant byte. //go:inline func beU16(u uint16) []uint8 { + var b [2]uint8 if u == 0 { // skip all processing for the common case (u = 0) - return []uint8{0, 0} - } - return []uint8{ - uint8(u >> 8), uint8(u), + return b[:] } + b[1] = uint8(u) + b[0] = uint8(u >> 8) + return b[:] } // revU64 returns the given uint64 u with bytes in the reverse order. @@ -218,6 +238,32 @@ func endpointIndex(address uint8) uint8 { ((address & descEndptAddrDirectionMsk) >> descEndptAddrDirectionPos) } +//go:inline +func indexEndpoint(index uint8) uint8 { + return ((index >> 1) & descEndptAddrNumberMsk) | + ((index & 0x1) << descEndptAddrDirectionPos) +} + +// wrap computes the index into a circular buffer of length mod by walking +// forward n elements if n is positive, or reverse n elements if n is negative. +// For example, both wrap(42, 10) and wrap(-308, 10) return 2. +//go:inline +func wrap(n, mod int) int { + if mod <= 0 || n == mod { + return 0 + } + if n < 0 { + if -n < mod { + return mod + n + } + return mod - (-n % mod) + } + if n < mod { + return n + } + return n % mod +} + // The following buffLo and buffHi are helper methods for slice definitions from // potentially zero-length arrays (depending on compile-time constants). //