// SPDX-License-Identifier: GPL-2.0-or-later // // Boot-layout keyboard reports to keys, for GMMOS's USB and I2C keyboards. // // usb_hid.c's keyboard path with the console, /dev/input, the lock and key // repeat taken out: what is left is edge detection and a table. US layout, as // the live USB path is. #include "core/types.h" #include "core/defs.h" #include "dev/kbd.h" #include "gmmos/gmmos.h" #define MOD_CTRL 0x11 #define MOD_SHIFT 0x22 static const uchar plain[0x39] = { 0, 0, 0, 0, 'a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z', '1','2','3','4','5','6','7','8','9','0', '\n', 0x1B, '\b', '\t', ' ', '-','=','[',']','\\','#',';','\'','`',',','.','/', }; static const uchar shifted[0x39] = { 0, 0, 0, 0, 'A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', '!','@','#','$','%','^','&','*','(',')', '\n', 0x1B, '\b', '\t', ' ', '_','+','{','}','|','~',':','"','~','<','>','?', }; static int special(uchar u) { switch (u) { case 0x4A: return KBD_HOME; case 0x4B: return KBD_PGUP; case 0x4C: return KBD_DEL; case 0x4D: return KBD_END; case 0x4E: return KBD_PGDN; case 0x4F: return KBD_RT; case 0x50: return KBD_LF; case 0x51: return KBD_DN; case 0x52: return KBD_UP; case 0x56: return '-'; // keypad minus and plus: the QR size keys case 0x57: return '+'; case 0x58: return '\n'; // keypad Enter } return 0; } static int was_down(const uchar *rep, uchar u) { for (int i = 2; i < 8; i++) if (rep[i] == u) return 1; return 0; } void gmmos_hid_report(struct gmmos_hidkeys *k, const uchar *boot) { uchar mods = boot[0]; for (int i = 2; i < 8; i++) { uchar u = boot[i]; int c; if (u < 4 || was_down(k->prev, u)) continue; if (u < 0x39) c = (mods & MOD_SHIFT) ? shifted[u] : plain[u]; else c = special(u); if (c == 0) continue; if ((mods & MOD_CTRL) && c < KBD_SPECIAL) { if (c >= 'a' && c <= 'z') c = c - 'a' + 1; else if (c >= 'A' && c <= 'Z') c = c - 'A' + 1; else continue; } if (k->qt - k->qh < (int)NELEM(k->q)) k->q[k->qt++ % NELEM(k->q)] = c; } memmove(k->prev, boot, 8); } int gmmos_hid_next(struct gmmos_hidkeys *k) { if (k->qh == k->qt) return 0; return k->q[k->qh++ % NELEM(k->q)]; }