feat(usb): a USB keyboard -- a full one -- and no hang on a PC without PS/2

boards/BRINGUP.md A3 and S3, FABRIC-3 SXLI.  A HID boot keyboard is
configured (interrupt IN endpoint, SET_PROTOCOL boot) and its reports
become the same Linux-keycode events as PS/2 and virtio (usb_kbd.c): the
full layout -- F-keys, navigation block, arrows, Num Lock, keypad.  The
console treats Caps and Num Lock as toggles shown on the keyboard's
lights, and the keypad as digits or navigation.  While a USB keyboard
runs, its event ring is serviced every tick, not once a second.

Found on the way: with no i8042 (port 0x64 reads 0xFF) the kernel hung at
boot in an endless drain -- a legacy-free PC would stop there.  Detected
and skipped now; drains bounded.

QEMU, amd64 with the USB keyboard the only one: 1 2 + . on main keys and
keypad, Caps Lock, Num Lock all right; aarch64/riscv64 configure it too.
Acceptance on three ISAs unchanged; identities hot-plug.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-14 14:04:33 -04:00
co-authored by Claude Opus 5.5
parent 080b7012ba
commit 739cb9c163
30 changed files with 82072 additions and 14 deletions
+44
View File
@@ -0,0 +1,44 @@
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 2023–2026 Robert A. James. All rights reserved.
Licensed under the StarForth License, Version 1.0.
*/
/**
* usb_kbd.h - a USB boot-protocol keyboard's keys, as key events
* (2026-10-14, boards/BRINGUP.md A3; usb_kbd.c).
*
* The xHCI driver hands each 8-byte boot report here; the keys pressed
* and released since the report before come out as Linux input keycodes,
* the namespace every keyboard in this kernel already speaks
* (sk_key_event_poll(), keyboard_words.c).
*/
#ifndef STARKERNEL_USB_KBD_H
#define STARKERNEL_USB_KBD_H
#include <stdint.h>
/* One boot report: byte 0 the modifier bits, byte 1 reserved, bytes 2-7
* up to six keys held (HID usage IDs). `len` below 3 is ignored. */
void usb_kbd_report(const uint8_t *report, uint32_t len);
/* Forgets the keys held: the keyboard has gone. */
void usb_kbd_reset(void);
/* The next key event: 1 with *keycode (Linux) and *pressed (1/0), or 0. */
int usb_kbd_pop_event(uint16_t *keycode, int *pressed);
/* The lock lights (boot output report bits, HID 1.11 appendix B.1). The
* console says which locks are on; the xHCI driver sends them to the
* keyboard with SET_REPORT whenever they differ from what it last sent. */
#define USB_KBD_LED_NUM 0x01u
#define USB_KBD_LED_CAPS 0x02u
#define USB_KBD_LED_SCROLL 0x04u
void usb_kbd_set_leds(uint8_t leds);
/* 1 and the lights to send if they changed since last sent, else 0. */
int usb_kbd_leds_pending(uint8_t *leds);
/* The driver has sent these. */
void usb_kbd_leds_sent(uint8_t leds);
#endif /* STARKERNEL_USB_KBD_H */