GMMOS: I2C keyboards, and every keyboard at once
The second micro driver: i2c_hid.c with everything but reading a keyboard's input reports taken out. No ACPI -- AML cannot run on a dead kernel -- so the live driver hands over what it found at boot (i2c_hid_keyboards): the DesignWare controller, the address, the report size, the AMD GPIO pin if there is one, and the parsed report descriptor. No power commands, no reset, a read-only transfer. usb_hid.c's report-protocol rewrite is split out as hid_boot_report(), which does nothing but rewrite, and kernel/gmmos/hidkeys.c turns boot reports into keys for this and the USB micro drivers to come. GMMOS now probes every micro driver and polls all that answer. Not run: QEMU has no DesignWare I2C, and the laptops at hand have PS/2 keyboards. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
cb9b06d46f
commit
c6d90e69fa
8 changed files with 387 additions and 17 deletions
98
kernel/gmmos/hidkeys.c
Normal file
98
kernel/gmmos/hidkeys.c
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
// 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)];
|
||||
}
|
||||
Loading…
Reference in a new issue