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:
Nexoniarz 2026-10-25 01:15:50 +02:00
commit c6d90e69fa
8 changed files with 387 additions and 17 deletions

View file

@ -525,19 +525,19 @@ bits(const uchar *p, int len, int bit, int size)
// A report-protocol keyboard report, rewritten as a boot one: modifiers, a
// reserved byte, six usages. Six is a limit only of the rewrite; the seventh
// key held at once is dropped, which is what a boot keyboard does too.
static void
report_keyboard(struct hid *h, const uchar *rep, int len)
// Nothing else happens here, which is what lets GMMOS call it after a panic.
static int
to_boot(struct hid *h, const uchar *rep, int len, uchar *boot)
{
uchar boot[8];
int i, n = 0;
if(h->kbd_id){
if(len < 1 || rep[0] != h->kbd_id)
return;
return 0;
rep++;
len--;
}
memset(boot, 0, sizeof(boot));
memset(boot, 0, 8);
for(i = 0; i < 8; i++)
if(h->mod_bit[i] >= 0 && bits(rep, len, h->mod_bit[i], 1))
boot[0] |= 1 << i;
@ -555,7 +555,36 @@ report_keyboard(struct hid *h, const uchar *rep, int len)
if(n < 6)
boot[2 + n++] = u;
}
keyboard_report(h, boot, sizeof(boot));
return 1;
}
static void
report_keyboard(struct hid *h, const uchar *rep, int len)
{
uchar boot[8];
if(to_boot(h, rep, len, boot))
keyboard_report(h, boot, sizeof(boot));
}
int
hid_is_keyboard(void *hv)
{
struct hid *h = hv;
return h && (h->rkbd || h->proto == USB_HID_PROTO_KEYBOARD);
}
int
hid_boot_report(void *hv, const uchar *rep, int len, uchar *boot)
{
struct hid *h = hv;
if(h->rkbd)
return to_boot(h, rep, len, boot);
if(h->proto != USB_HID_PROTO_KEYBOARD || len < 8)
return 0;
memmove(boot, rep, 8);
return 1;
}
static int