diff --git a/internal/usbgadget/hid_keyboard.go b/internal/usbgadget/hid_keyboard.go index 05895206..439548b5 100644 --- a/internal/usbgadget/hid_keyboard.go +++ b/internal/usbgadget/hid_keyboard.go @@ -28,61 +28,50 @@ var keyboardConfig = gadgetConfigItem{ // Source: https://www.kernel.org/doc/Documentation/usb/gadget_hid.txt var keyboardReportDesc = []byte{ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x06, /* USAGE (Keyboard) */ - 0xa1, 0x01, /* COLLECTION (Application) */ + /* boot mode descriptor */ + 0x05, 0x01, /* USAGE_PAGE-global (Generic Desktop) */ + 0x09, 0x06, /* USAGE-local (Keyboard) */ + 0xA1, 0x01, /* COLLECTION-main (Application) */ /* 8 modifier bits */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */ - 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0x05, 0x07, /* USAGE_PAGE-global (Keyboard) */ + 0x19, 0xe0, /* USAGE_MINIMUM-local 0xE0 (Keyboard LeftControl) */ + 0x29, 0xe7, /* USAGE_MAXIMUM-local 0xE7 (Keyboard Right GUI) */ + 0x15, 0x00, /* LOGICAL_MINIMUM-global (0) Modifier bit off) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM-global (1) Modifier bit on) */ + 0x75, 0x01, /* REPORT_SIZE-global (1) one bit per modifier */ + 0x95, 0x08, /* REPORT_COUNT-global (8) 8 total bits */ + 0x81, 0x02, /* INPUT-main (Data,Var,Abs) Modifier bits 0-7 */ /* 8 bits of padding */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT-global (1) one field */ + 0x75, 0x08, /* REPORT_SIZE-global (8) */ + 0x81, 0x03, /* INPUT-main (Cnst,Var,Abs) reserved byte */ /* 6 key codes for the 104 key keyboard */ - 0x95, 0x06, /* REPORT_COUNT (6) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0xE7, /* LOGICAL_MAXIMUM (104-key HID) */ - 0x05, 0x07, /* USAGE_PAGE (Keyboard) */ - 0x19, 0x00, /* USAGE_MINIMUM (Reserved) */ - 0x29, 0xE7, /* USAGE_MAXIMUM (Keyboard Right GUI) */ - 0x81, 0x00, /* INPUT (Data,Ary,Abs) */ + 0x95, 0x06, /* REPORT_COUNT-global (6) keycodes */ + 0x75, 0x08, /* REPORT_SIZE-global (8) bits each (a byte) */ + 0x15, 0x00, /* LOGICAL_MINIMUM-global (0) */ + 0x25, 0xDF, /* LOGICAL_MAXIMUM-global 0xDF (104-key HID codes) */ + 0x05, 0x07, /* USAGE_PAGE-global (Keyboard) */ + 0x19, 0x00, /* USAGE_MINIMUM-local (Reserved/0) no key */ + 0x29, 0xE7, /* USAGE_MAXIMUM-local (Keyboard Right GUI) */ + 0x81, 0x00, /* INPUT-main (Data,Ary,Abs) array of keycodes */ /* LED report 5 bits for Num Lock through Kana */ - 0x95, 0x05, /* REPORT_COUNT (5) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ - 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */ - 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ + 0x95, 0x05, /* REPORT_COUNT-global (5) 5 LED bits */ + 0x75, 0x01, /* REPORT_SIZE-global (1) each 1 bit */ + 0x05, 0x08, /* USAGE_PAGE-global (LEDs) */ + 0x19, 0x01, /* USAGE_MINIMUM-local (Num Lock) */ + 0x29, 0x05, /* USAGE_MAXIMUM-local (Kana) */ + 0x91, 0x02, /* OUTPUT-main (Data,Var,Abs) bits 0-4 */ - /* 1 bit of padding for the Power LED (ignored) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x03, /* REPORT_SIZE (3) */ - 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ + /* 3 bits of padding for the rest of the byte */ + 0x95, 0x01, /* REPORT_COUNT-global (1) one field */ + 0x75, 0x03, /* REPORT_SIZE-global (3) of three bits */ + 0x91, 0x03, /* OUTPUT-main (Cnst,Var,Abs) bit 7 pad */ - /* LED report 1 bit for Shift */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x05, 0x08, /* USAGE_PAGE (LEDs) */ - 0x19, 0x07, /* USAGE_MINIMUM (Shift) */ - 0x29, 0x07, /* USAGE_MAXIMUM (Shift) */ - 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */ - - /* 1 bit of padding for the rest of the byte */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x03, /* REPORT_SIZE (3) */ - 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */ - 0xc0, /* END_COLLECTION */ + 0xC0, /* END_COLLECTION */ } const ( @@ -96,9 +85,7 @@ const ( KeyboardLedMaskScrollLock = 1 << 2 KeyboardLedMaskCompose = 1 << 3 KeyboardLedMaskKana = 1 << 4 - // power on/off LED is 5 - KeyboardLedMaskShift = 1 << 6 - ValidKeyboardLedMasks = KeyboardLedMaskNumLock | KeyboardLedMaskCapsLock | KeyboardLedMaskScrollLock | KeyboardLedMaskCompose | KeyboardLedMaskKana | KeyboardLedMaskShift + ValidKeyboardLedMasks = KeyboardLedMaskNumLock | KeyboardLedMaskCapsLock | KeyboardLedMaskScrollLock | KeyboardLedMaskCompose | KeyboardLedMaskKana ) // Synchronization between LED states and CAPS LOCK, NUM LOCK, SCROLL LOCK, @@ -111,7 +98,6 @@ type KeyboardState struct { ScrollLock bool `json:"scroll_lock"` Compose bool `json:"compose"` Kana bool `json:"kana"` - Shift bool `json:"shift"` // This is not part of the main USB HID spec raw byte } @@ -128,7 +114,6 @@ func getKeyboardState(b byte) KeyboardState { ScrollLock: b&KeyboardLedMaskScrollLock != 0, Compose: b&KeyboardLedMaskCompose != 0, Kana: b&KeyboardLedMaskKana != 0, - Shift: b&KeyboardLedMaskShift != 0, raw: b, } } @@ -295,12 +280,13 @@ func (u *UsbGadget) listenKeyboardEvents() { time.Sleep(time.Second) continue } - // reset the counter + // reset the suppression counter u.resetLogSuppressionCounter("keyboardHidFileNil") n, err := u.keyboardHidFile.Read(buf) if err != nil { u.logWithSuppression("keyboardHidFileRead", 100, &l, err, "failed to read") + time.Sleep(100 * time.Millisecond) // Small backoff on read errors to avoid tight looping continue } u.resetLogSuppressionCounter("keyboardHidFileRead") diff --git a/ui/src/components/InfoBar.tsx b/ui/src/components/InfoBar.tsx index 2c4eb9e0..a40afbbf 100644 --- a/ui/src/components/InfoBar.tsx +++ b/ui/src/components/InfoBar.tsx @@ -166,10 +166,6 @@ export default function InfoBar() { {keyboardLedState.kana ? (
{m.info_kana()}
) : null} - - {keyboardLedState.shift ? ( -
{m.info_shift()}
- ) : null} diff --git a/ui/src/hooks/stores.ts b/ui/src/hooks/stores.ts index 06f29582..1b482658 100644 --- a/ui/src/hooks/stores.ts +++ b/ui/src/hooks/stores.ts @@ -473,7 +473,6 @@ export interface KeyboardLedState { scroll_lock: boolean; compose: boolean; kana: boolean; - shift: boolean; // Optional, as not all keyboards have a shift LED }; export const hidKeyBufferSize = 6; @@ -509,7 +508,7 @@ export interface HidState { } export const useHidStore = create(set => ({ - keyboardLedState: { num_lock: false, caps_lock: false, scroll_lock: false, compose: false, kana: false, shift: false } as KeyboardLedState, + keyboardLedState: { num_lock: false, caps_lock: false, scroll_lock: false, compose: false, kana: false } as KeyboardLedState, setKeyboardLedState: (ledState: KeyboardLedState): void => set({ keyboardLedState: ledState }), keysDownState: { modifier: 0, keys: [0, 0, 0, 0, 0, 0] } as KeysDownState, diff --git a/ui/src/keyboardMappings.ts b/ui/src/keyboardMappings.ts index 456a43c4..e35bb09d 100644 --- a/ui/src/keyboardMappings.ts +++ b/ui/src/keyboardMappings.ts @@ -3,12 +3,12 @@ // [Universal Serial Bus HID Usage Tables: Section 10](https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf) // These are all the key codes (not scan codes) that an 85/101/102 keyboard might have on it export const keys = { - Again: 0x79, + Again: 0x79, // aka Clear AlternateErase: 0x9d, AltGr: 0xe6, // aka AltRight AltLeft: 0xe2, AltRight: 0xe6, - Application: 0x65, + Application: 0x65, // aka ContextMenu ArrowDown: 0x51, ArrowLeft: 0x50, ArrowRight: 0x4f, @@ -25,11 +25,10 @@ export const keys = { ClearAgain: 0xa2, Comma: 0x36, Compose: 0xe3, - ContextMenu: 0x65, ControlLeft: 0xe0, ControlRight: 0xe4, Copy: 0x7c, - CrSel: 0xa3, + CrSel: 0xa3, // aka Props CurrencySubunit: 0xb5, CurrencyUnit: 0xb4, Cut: 0x7b, @@ -49,7 +48,7 @@ export const keys = { Enter: 0x28, Equal: 0x2e, Escape: 0x29, - Execute: 0x74, + Execute: 0x74, // aka Open ExSel: 0xa4, F1: 0x3a, F2: 0x3b, @@ -77,14 +76,14 @@ export const keys = { F24: 0x73, Find: 0x7e, Grave: 0x35, - HashTilde: 0x32, // non-US # and ~ + HashTilde: 0x32, // non-US # and ~ (typically near Enter key) Help: 0x75, Home: 0x4a, Insert: 0x49, International7: 0x8d, International8: 0x8e, International9: 0x8f, - IntlBackslash: 0x64, // non-US \ and | + IntlBackslash: 0x64, // non-US \ and | (typically near Left Shift key) KeyA: 0x04, KeyB: 0x05, KeyC: 0x06, @@ -111,17 +110,17 @@ export const keys = { KeyX: 0x1b, KeyY: 0x1c, KeyZ: 0x1d, - KeyRO: 0x87, - KatakanaHiragana: 0x88, - Yen: 0x89, - Henkan: 0x8a, - Muhenkan: 0x8b, - KPJPComma: 0x8c, - Hangeul: 0x90, - Hanja: 0x91, - Katakana: 0x92, - Hiragana: 0x93, - ZenkakuHankaku: 0x94, + RO: 0x87, // aka International1 + KatakanaHiragana: 0x88, // aka International2 + Yen: 0x89, // aka International3 + Henkan: 0x8a, // aka International4 + Muhenkan: 0x8b, // aka International5 + KPJPComma: 0x8c, // aka International6 + Hangeul: 0x90, // aka Lang1 + Hanja: 0x91, // aka Lang2 + Katakana: 0x92, // aka Lang3 + Hiragana: 0x93, // aka Lang4 + ZenkakuHankaku: 0x94, // aka Lang5 LockingCapsLock: 0x82, LockingNumLock: 0x83, LockingScrollLock: 0x84, @@ -129,9 +128,29 @@ export const keys = { Lang7: 0x96, Lang8: 0x97, Lang9: 0x98, + MediaBack: 0xF1, + MediaCalc: 0xFB, + MediaCoffee: 0xF9, + MediaEdit: 0xF7, + MediaEjectCD: 0xEC, + MediaFind: 0xF4, + MediaForward: 0xF2, + MediaMute: 0xEF, + MediaNextSong: 0xEB, + MediaPlayPause: 0xE8, + MediaPreviousSong: 0xEA, + MediaRefresh: 0xFA, + MediaScrollDown: 0xF6, + MediaScrollUp: 0xF5, + MediaSleep: 0xF8, + MediaStop: 0xF3, + MediaStopCD: 0xE9, + MediaVolumeDown: 0xEE, + MediaVolumeUp: 0xED, + MediaWWW: 0xF0, Menu: 0x76, - MetaLeft: 0xe3, - MetaRight: 0xe7, + MetaLeft: 0xe3, // aka LeftGUI + MetaRight: 0xe7, // aka RightGUI Minus: 0x2d, Mute: 0x7f, NumLock: 0x53, // and Clear @@ -157,9 +176,8 @@ export const keys = { NumpadClearEntry: 0xd9, NumpadColon: 0xcb, NumpadComma: 0x85, - NumpadDecimal: 0x63, // and Delete + NumpadDecimal: 0x63, // and NumpadDelete NumpadDecimalBase: 0xdc, - NumpadDelete: 0x63, NumpadDivide: 0x54, NumpadDownArrow: 0x5a, NumpadEnd: 0x59, @@ -211,14 +229,14 @@ export const keys = { PageUp: 0x4b, Paste: 0x7d, Pause: 0x48, - Period: 0x37, // aka Dot + Period: 0x37, // aka Dot Power: 0x66, - PrintScreen: 0x46, + PrintScreen: 0x46, // aka SysRq Prior: 0x9d, - Quote: 0x34, // aka Single Quote or Apostrophe + Quote: 0x34, // aka Single Quote or Apostrophe Return: 0x9e, - ScrollLock: 0x47, - Select: 0x77, + ScrollLock: 0x47, // aka ScrLk + Select: 0x77, // aka Front Semicolon: 0x33, Separator: 0x9f, ShiftLeft: 0xe1, @@ -240,7 +258,7 @@ export const deadKeys = { Breve: 0x02d8, Caron: 0x02c7, Cedilla: 0x00b8, - Circumflex: 0x005e, // or 0x02c6? + Circumflex: 0x02c6, Comma: 0x002c, Dot: 0x00b7, DoubleAcute: 0x02dd,