Files
danos/system/drivers/ps2-bus/keyboard.zig
T
Daniel Samson 1bf91115dd Generalize input module to mouse and joystick/gamepad events
Extend the input service beyond the keyboard so mouse and joystick/gamepad
drivers can broadcast too, with per-device publish and subscribe methods.

- protocol: KeyEvent joins MouseEvent (motion/buttons/scroll) and
  JoystickEvent (axes/buttons), all carried in a common InputEvent envelope
  tagged with a DeviceKind. A subscribe request carries a device_mask, so a
  subscriber names the classes it wants and the service routes each event only
  to interested subscribers (a mouse-only listener never wakes for keystrokes).
- runtime: per-device publish methods (publishKeyboardEvent/publishMouseEvent/
  publishJoystickEvent) and subscribe helpers (subscribeKeyboard/Mouse/Joystick,
  each typed, plus subscribe(mask)/subscribeAll returning the tagged envelope).
- service: subscriber table gains a device_mask; broadcast routes by the
  event's device class.
- mouse driver now publishes (synthetic) mouse events like the keyboard driver;
  input-source cycles all three classes; input-test subscribes to all and only
  emits its "ok" marker once it has received one of each class — so the passing
  test proves per-device routing, not just delivery. Real HID decoding stays a
  follow-up.

No kernel changes: ipc_send is generic and the 36-byte InputEvent fits its
64-byte payload. Full QEMU suite 48/48; serial log confirms keyboard, mouse,
and joystick all reach one subscription.
2026-07-11 15:21:09 +01:00

60 lines
2.4 KiB
Zig

//! PS/2 Keyboard Driver
//!
//! Spawned by the ps2-bus driver once the controller is initialized and port 1
//! has passed its interface test and device reset. The bus driver hands us our
//! device HID as argv[1]; we use it to locate our own device descriptor.
const std = @import("std");
const runtime = @import("runtime");
const ps2 = @import("ps2-library.zig");
const device = runtime.device;
fn writeLine(comptime fmt: []const u8, arguments: anytype) void {
var line: [128]u8 = undefined;
_ = runtime.system.write(std.fmt.bufPrint(&line, fmt, arguments) catch return);
}
pub fn main() void {
const hid = runtime.argument(1);
if (hid.len == 0) {
_ = runtime.system.write("system/drivers/ps2-bus/keyboard: no HID argument\n");
return;
}
writeLine("system/drivers/ps2-bus/keyboard: starting for hid {s}\n", .{hid});
const buffer = runtime.allocator().alloc(device.DeviceDescriptor, 64) catch {
_ = runtime.system.write("system/drivers/ps2-bus/keyboard: out of memory\n");
return;
};
if (device.findDeviceDescriptorByHid(buffer, hid) == null) {
writeLine("system/drivers/ps2-bus/keyboard: no device for hid {s}\n", .{hid});
return;
}
// The 8042 ports (0x60/0x64) and this keyboard's IRQ1 both live on the same
// PNP0303 node, which the ps2-bus driver exclusively owns — so the keyboard is
// served through the bus and does not claim the controller itself.
_ = runtime.system.write("system/drivers/ps2-bus/keyboard: served by ps2-bus (controller owned by bus)\n");
// Broadcast keyboard events through the input service so programs can listen for them
// (docs/input.md). Until the bus reads real IRQ1 scancodes and hands them here (a
// follow-up), we publish the same synthetic stand-in stream the demo source uses — the
// fan-out path is real, only the source of the bytes is placeholder.
var source = runtime.input.connectSource() orelse {
_ = runtime.system.write("system/drivers/ps2-bus/keyboard: input service unavailable\n");
return;
};
_ = runtime.system.write("system/drivers/ps2-bus/keyboard: ok\n");
var step: usize = 0;
while (true) : (step +%= 1) {
_ = source.publishKeyboardEvent(runtime.input.syntheticKeyEvent(step));
runtime.system.sleep(200);
}
}
pub const panic = runtime.panic;
comptime {
_ = &runtime.start._start;
}