347 headers said "Licensed under the StarForth License, Version 1.0" -- a shortening (Captain Bob, 2026-11-08: "License file SL I think I shortened accidently"); LICENSE is, and has been since the first commit, the Starship License 1.0 (SL-1.0, SPDX LicenseRef-Starship-1.0). 349 files, 566 occurrences, now "Starship License, Version 1.0 (SL-1.0)". Left as they are, pending a ruling: docs/patent/ (the patent figures), docs/formal/ (the citable volumes) and the generated reports under docs/working/experiments/ (32 files). Comments and license text only: the amd64 kernel builds, every changed script parses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
131 lines
5.8 KiB
C
131 lines
5.8 KiB
C
/*
|
||
StarForth — Steady-State Virtual Machine Runtime
|
||
Copyright (c) 2023–2026 Robert A. James. All rights reserved.
|
||
Licensed under the Starship License, Version 1.0 (SL-1.0).
|
||
*/
|
||
|
||
/**
|
||
* usb_kbd.c - a USB boot-protocol keyboard's reports, as key events
|
||
* (2026-10-14, boards/BRINGUP.md A3). See usb_kbd.h.
|
||
*
|
||
* A boot report says which keys are held now, not what changed: what was
|
||
* held in the report before and is not now has been released, and the
|
||
* other way round has been pressed. The eight modifier bits are keys too
|
||
* (left/right Ctrl, Shift, Alt, GUI). A report whose keys are all 0x01 is
|
||
* the keyboard's "too many keys" (ErrorRollOver) and changes nothing.
|
||
*
|
||
* Usage IDs (HID Usage Tables 1.12, page 7) become Linux keycodes
|
||
* (input-event-codes.h) -- the same numbers the PS/2 and virtio keyboards
|
||
* already give sk_key_event_poll(). Only the keys a console uses are
|
||
* mapped; others are dropped. The keyboard does not repeat a held key:
|
||
* held is held, and nothing here repeats it either.
|
||
*/
|
||
|
||
#include "starkernel/usb_kbd.h"
|
||
|
||
/* HID usage ID -> Linux keycode; 0 = not mapped. A full-size keyboard:
|
||
* the main block, F1-F12, the navigation block, arrows and the keypad
|
||
* (Captain Bob, 2026-10-14: "include caps lock, numlock, keypad and
|
||
* arrow"). What a key means -- Caps and Num Lock as toggles, the keypad
|
||
* as digits or navigation -- is the console's (repl.c), for every
|
||
* keyboard alike. */
|
||
static const uint8_t usage_to_key[0x66] = {
|
||
[0x04] = 30, [0x05] = 48, [0x06] = 46, [0x07] = 32, [0x08] = 18, /* a b c d e */
|
||
[0x09] = 33, [0x0A] = 34, [0x0B] = 35, [0x0C] = 23, [0x0D] = 36, /* f g h i j */
|
||
[0x0E] = 37, [0x0F] = 38, [0x10] = 50, [0x11] = 49, [0x12] = 24, /* k l m n o */
|
||
[0x13] = 25, [0x14] = 16, [0x15] = 19, [0x16] = 31, [0x17] = 20, /* p q r s t */
|
||
[0x18] = 22, [0x19] = 47, [0x1A] = 17, [0x1B] = 45, [0x1C] = 21, /* u v w x y */
|
||
[0x1D] = 44, /* z */
|
||
[0x1E] = 2, [0x1F] = 3, [0x20] = 4, [0x21] = 5, [0x22] = 6, /* 1 2 3 4 5 */
|
||
[0x23] = 7, [0x24] = 8, [0x25] = 9, [0x26] = 10, [0x27] = 11, /* 6 7 8 9 0 */
|
||
[0x28] = 28, [0x29] = 1, [0x2A] = 14, [0x2B] = 15, [0x2C] = 57, /* enter esc bksp tab space */
|
||
[0x2D] = 12, [0x2E] = 13, [0x2F] = 26, [0x30] = 27, [0x31] = 43, /* - = [ ] \ */
|
||
[0x32] = 43, [0x33] = 39, [0x34] = 40, [0x35] = 41, [0x36] = 51, /* non-US # ; ' ` , */
|
||
[0x37] = 52, [0x38] = 53, [0x39] = 58, /* . / capslock */
|
||
[0x3A] = 59, [0x3B] = 60, [0x3C] = 61, [0x3D] = 62, [0x3E] = 63, /* F1-F5 */
|
||
[0x3F] = 64, [0x40] = 65, [0x41] = 66, [0x42] = 67, [0x43] = 68, /* F6-F10 */
|
||
[0x44] = 87, [0x45] = 88, /* F11 F12 */
|
||
[0x46] = 99, [0x47] = 70, [0x48] = 119, /* printscreen scrolllock pause */
|
||
[0x49] = 110, [0x4A] = 102, [0x4B] = 104, /* insert home pageup */
|
||
[0x4C] = 111, [0x4D] = 107, [0x4E] = 109, /* delete end pagedown */
|
||
[0x4F] = 106, [0x50] = 105, [0x51] = 108, [0x52] = 103, /* right left down up */
|
||
[0x53] = 69, /* numlock */
|
||
[0x54] = 98, [0x55] = 55, [0x56] = 74, [0x57] = 78, [0x58] = 96, /* kp/ kp* kp- kp+ kpenter */
|
||
[0x59] = 79, [0x5A] = 80, [0x5B] = 81, [0x5C] = 75, [0x5D] = 76, /* kp1 kp2 kp3 kp4 kp5 */
|
||
[0x5E] = 77, [0x5F] = 71, [0x60] = 72, [0x61] = 73, [0x62] = 82, /* kp6 kp7 kp8 kp9 kp0 */
|
||
[0x63] = 83, [0x64] = 86, [0x65] = 127, /* kp. non-US\ compose(menu) */
|
||
};
|
||
|
||
/* Modifier bit n -> Linux keycode: LCtrl LShift LAlt LGUI RCtrl RShift RAlt RGUI. */
|
||
static const uint8_t modifier_key[8] = { 29, 42, 56, 125, 97, 54, 100, 126 };
|
||
|
||
#define KBD_EVENTS 64u
|
||
static struct { uint16_t keycode; uint8_t pressed; } g_events[KBD_EVENTS];
|
||
static uint32_t g_head, g_count;
|
||
/* Num Lock on to start, matching the console (repl.c). */
|
||
static uint8_t g_leds_want = USB_KBD_LED_NUM;
|
||
|
||
static void push(uint16_t keycode, int pressed)
|
||
{
|
||
if (keycode == 0 || g_count == KBD_EVENTS) return; /* a full queue drops: nothing reads it */
|
||
g_events[(g_head + g_count) % KBD_EVENTS].keycode = keycode;
|
||
g_events[(g_head + g_count) % KBD_EVENTS].pressed = (uint8_t)(pressed != 0);
|
||
g_count++;
|
||
}
|
||
|
||
static uint16_t key_for(uint8_t usage)
|
||
{
|
||
return usage < sizeof usage_to_key ? usage_to_key[usage] : 0;
|
||
}
|
||
|
||
static int held(const uint8_t *keys, uint32_t n, uint8_t usage)
|
||
{
|
||
uint32_t i;
|
||
for (i = 0; i < n; i++)
|
||
if (keys[i] == usage) return 1;
|
||
return 0;
|
||
}
|
||
|
||
void usb_kbd_report(uint8_t prev[8], const uint8_t *report, uint32_t len)
|
||
{
|
||
uint8_t now[8] = {0};
|
||
uint32_t i, n;
|
||
|
||
if (!report || len < 3) return;
|
||
if (len > 8) len = 8;
|
||
for (i = 0; i < len; i++) now[i] = report[i];
|
||
if (now[2] == 0x01) return; /* ErrorRollOver: nothing known */
|
||
|
||
for (i = 0; i < 8; i++) {
|
||
uint8_t bit = (uint8_t)(1u << i);
|
||
if ((now[0] & bit) != (prev[0] & bit)) push(modifier_key[i], (now[0] & bit) != 0);
|
||
}
|
||
n = 6;
|
||
for (i = 2; i < 8; i++) /* released first, then pressed */
|
||
if (prev[i] > 0x01 && !held(now + 2, n, prev[i])) push(key_for(prev[i]), 0);
|
||
for (i = 2; i < 8; i++)
|
||
if (now[i] > 0x01 && !held(prev + 2, n, now[i])) push(key_for(now[i]), 1);
|
||
|
||
for (i = 0; i < 8; i++) prev[i] = now[i];
|
||
}
|
||
|
||
void usb_kbd_forget(uint8_t prev[8])
|
||
{
|
||
static const uint8_t none[8] = {0};
|
||
usb_kbd_report(prev, none, 8); /* everything held, released */
|
||
}
|
||
|
||
void usb_kbd_set_leds(uint8_t leds) { g_leds_want = leds; }
|
||
|
||
uint8_t usb_kbd_leds_wanted(void) { return g_leds_want; }
|
||
|
||
int usb_kbd_pop_event(uint16_t *keycode, int *pressed)
|
||
{
|
||
if (g_count == 0) return 0;
|
||
*keycode = g_events[g_head].keycode;
|
||
*pressed = g_events[g_head].pressed;
|
||
g_head = (g_head + 1u) % KBD_EVENTS;
|
||
g_count--;
|
||
return 1;
|
||
}
|