aboutsummaryrefslogtreecommitdiff
path: root/mirai.old/drivers/keyboard/keyboard.zig
blob: 760e172f33e8fedd55e52081f9ba44d78413d957 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//! PS/2 Keyboard Driver

const ahci_const = @import("../../common/constants/ahci.zig");
const io = @import("../../asm/io.zig");
const kb_const = @import("../../common/constants/keyboard.zig");
const kb_limits = @import("../../common/limits/keyboard.zig");
const ports = @import("../../common/constants/ports.zig");
const scancode = @import("scancode.zig");
const sensei = @import("../../kata/sensei/sensei.zig");
const serial = @import("../serial/serial.zig");

var shift_pressed = false;
var ctrl_pressed = false;
var alt_pressed = false;
var caps_lock = false;

var key_buffer: [kb_limits.BUFFER_SIZE]u8 = undefined;
var read_pos: usize = 0;
var write_pos: usize = 0;

pub fn init() void {
    serial.printf("Initializing PS/2 keyboard...\n", .{});

    while ((io.in_byte(ports.KEYBOARD_STATUS) & 0x01) != 0) {
        _ = io.in_byte(ports.KEYBOARD_DATA);
    }

    serial.printf("Keyboard ready\n", .{});
}

export fn keyboard_handler() void {
    const code = io.in_byte(ports.KEYBOARD_DATA);
    handle_scancode(code);
    io.out_byte(ports.PIC1_CMD, ahci_const.PIC_EOI);
}

fn handle_scancode(code: u8) void {
    const released = (code & kb_const.SCANCODE_RELEASED) != 0;
    const key = code & ~kb_const.SCANCODE_RELEASED;

    switch (key) {
        kb_const.SCANCODE_LSHIFT, kb_const.SCANCODE_RSHIFT => {
            shift_pressed = !released;
            return;
        },
        kb_const.SCANCODE_LCTRL => {
            ctrl_pressed = !released;
            return;
        },
        kb_const.SCANCODE_LALT => {
            alt_pressed = !released;
            return;
        },
        kb_const.SCANCODE_CAPS => {
            if (!released) caps_lock = !caps_lock;
            return;
        },
        else => {},
    }

    if (released) return;

    var ascii: u8 = if (shift_pressed) scancode.shifted[key] else scancode.normal[key];

    if (caps_lock and ascii >= 'a' and ascii <= 'z') {
        ascii -= kb_const.LOWERCASE_TO_UPPERCASE;
    }

    if (ascii != 0) {
        enqueue(ascii);
    }
}

fn enqueue(ascii: u8) void {
    const next = (write_pos + 1) % kb_limits.BUFFER_SIZE;
    if (next != read_pos) {
        key_buffer[write_pos] = ascii;
        write_pos = next;
        sensei.wake_one_blocked_kata();
    }
}

pub fn has_input() bool {
    return read_pos != write_pos;
}

pub fn read_char() ?u8 {
    if (read_pos == write_pos) return null;

    const char = key_buffer[read_pos];
    read_pos = (read_pos + 1) % kb_limits.BUFFER_SIZE;
    return char;
}