Wire real PS/2 mouse packets through to input events
Replace the mouse driver's synthetic stream with the real path, the way the keyboard was wired: - The auxiliary port's IRQ12 is enumerated on the mouse's own ACPI node (PNP0F13), and the kernel only lets a device's claimer bind or ack its IRQs — so ps2-bus now claims that node alongside the controller whenever port 2 carries a device, binds IRQ12 to its one endpoint, and re-arms whichever line the notification's badge names. The forwarding loop already routed auxiliary bytes by status bit 5. - mouse-packet.zig (new, pure, host-tested): three-byte stream-mode packet assembly — bit-3 sync with resynchronization, ACK/BAT bytes dropped at packet start, nine-bit two's-complement movement, overflow packets discarded, and PS/2 positive-Y-up converted to the screen convention (positive down). - mouse.zig mirrors the keyboard driver: no hardware claim, attaches to the bus as its mouse, and publishes button_down/button_up per changed button plus motion events with the pressed-button mask. Verified end to end in QEMU via monitor mouse_move/mouse_button: motion round-trips in screen coordinates, buttons transition with the right mask, and keyboard events keep flowing alongside. The follow-up is the IntelliMouse magic-knock for a scroll wheel (four-byte packets) and scroll events.
This commit is contained in:
@@ -229,19 +229,41 @@ pub fn main() void {
|
||||
}
|
||||
|
||||
// From here on, only the interrupt path reads the data port. Drop anything a
|
||||
// device sent between enable-scanning and now, bind the IRQ, and only then
|
||||
// let the controller raise it — an interrupt with nobody bound is lost.
|
||||
// device sent between enable-scanning and now, bind the IRQs, and only then
|
||||
// let the controller raise them — an interrupt with nobody bound is lost.
|
||||
controller.drainOutputBuffer();
|
||||
if (!device.irqBind(controller.device_id, interrupt_index, endpoint)) {
|
||||
_ = runtime.system.write("system/drivers/ps2-bus: irq_bind failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Port 2's interrupt (IRQ12) is enumerated on the auxiliary device's own ACPI
|
||||
// node (PNP0F13), not on the controller's — so if port 2 carries a device,
|
||||
// claim that node too and route its IRQ to the same endpoint. The IRQ belongs
|
||||
// to the *port*, whatever device identify found on it.
|
||||
var maybe_auxiliary_interrupt: ?struct { device_id: u64, interrupt_index: u64, gsi: u64 } = null;
|
||||
if (port_device_types[@intFromEnum(ps2.Port.Two)] != null) {
|
||||
if (device.findDeviceDescriptorByHid(buffer, "PNP0F13")) |descriptor| {
|
||||
if (findInterruptResourceIndex(descriptor)) |auxiliary_index| {
|
||||
if (device.claim(descriptor.id) and device.irqBind(descriptor.id, auxiliary_index, endpoint)) {
|
||||
maybe_auxiliary_interrupt = .{
|
||||
.device_id = descriptor.id,
|
||||
.interrupt_index = auxiliary_index,
|
||||
.gsi = descriptor.resources[auxiliary_index].start,
|
||||
};
|
||||
} else {
|
||||
_ = runtime.system.write("system/drivers/ps2-bus: auxiliary irq_bind failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var configuration = controller.readConfigurationByte() orelse {
|
||||
_ = runtime.system.write("system/drivers/ps2-bus: controller configuration timed out\n");
|
||||
return;
|
||||
};
|
||||
if (port_device_types[@intFromEnum(ps2.Port.One)] != null) configuration |= ps2.Port.One.interruptBit();
|
||||
if (port_device_types[@intFromEnum(ps2.Port.Two)] != null) configuration |= ps2.Port.Two.interruptBit();
|
||||
if (maybe_auxiliary_interrupt != null) configuration |= ps2.Port.Two.interruptBit();
|
||||
_ = controller.writeConfigurationByte(configuration);
|
||||
|
||||
_ = runtime.system.write("system/drivers/ps2-bus: ok\n");
|
||||
@@ -269,7 +291,17 @@ pub fn main() void {
|
||||
// An unattached port's byte is dropped — e.g. a keystroke before
|
||||
// the keyboard driver has attached.
|
||||
}
|
||||
_ = device.irqAck(controller.device_id, interrupt_index);
|
||||
// Re-arm the line that woke us: the notification badge carries the
|
||||
// GSI, and IRQ1 and IRQ12 are acked through different device claims.
|
||||
if (maybe_auxiliary_interrupt) |auxiliary| {
|
||||
if (got.source() == auxiliary.gsi) {
|
||||
_ = device.irqAck(auxiliary.device_id, auxiliary.interrupt_index);
|
||||
} else {
|
||||
_ = device.irqAck(controller.device_id, interrupt_index);
|
||||
}
|
||||
} else {
|
||||
_ = device.irqAck(controller.device_id, interrupt_index);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
reply_len = handleAttach(receive[0..got.len], got, &reply_buffer);
|
||||
|
||||
Reference in New Issue
Block a user