hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/kernel/input.rv
blob: 68313b7267e943daf143eef2744df75a7c902d27 (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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# keyboard scancode table
# ts is not a good way to write a driver lmao

const KEYMAP       = "  1234567890-=  qwertyuiop[]  asdfghjkl;'` \\zxcvbnm,./    "
const KEYMAP_SHIFT = "  !@#$%^&*()_+  QWERTYUIOP{}  ASDFGHJKL:\"~ |ZXCVBNM<>?    "

# 8259 pic
fn pic_remap() do
  outb(0x20, 0x11)  outb(0xa0, 0x11)
  outb(0x21, 0x20)  outb(0xa1, 0x28)
  outb(0x21, 0x04)  outb(0xa1, 0x02)
  outb(0x21, 0x01)  outb(0xa1, 0x01)
  outb(0x21, 0xff)  outb(0xa1, 0xff)
end

fn pic_unmask(line)
  outb(0x21, inb(0x21) band (255 bxor (1 shl line)))

# 8253/8254 pit channel 0, mode 3 (square wave)
# divisor 11931 -> ~100 hz (1193182 / 11931)
# the isr just counts ticks
fn pit_init() do
  outb(0x43, 0x36)
  outb(0x40, 11931 band 0xff)
  outb(0x40, (11931 shr 8) band 0xff)
end

# she stroke my keys till i handle
# no fr this is just a key stroke handler
global shell = { shift = :false, extended = :false, ctrl = :false }

fn decode_key(code) -> string | :nil do
  # shift down
  if code == 0x2a or code == 0x36 do
    shell.shift = :true
    return :nil
  end
  # shift up
  if code == 0xaa or code == 0xb6 do
    shell.shift = :false
    return :nil
  end
  # ctrl down
  if code == 0x1d do
    shell.ctrl = :true
    return :nil
  end
  # ctrl up
  if code == 0x9d do
    shell.ctrl = :false
    return :nil
  end
  # other releases
  if (code >= 128)
    return :nil
  # enter
  if (code == 28)
    return "\n"
  # backspace
  if code == 14 do
    if shell.ctrl do
      return "\x7f"
    end
    return "\x08"
  end
  if (code < 2)
    return :nil
  if (code >= KEYMAP:len())
    return :nil

  const character = if (shell.shift) KEYMAP_SHIFT[code] else KEYMAP[code]
  # blank cells = modifiers/unmapped
  if (character == " " and code != 0x39)
    return :nil
  if (shell.ctrl)
    return string.of_ascii(character:ascii() band 0x1f)
  return character
end

global on_key = fn(code) do
  if code == 0xe0 do
    shell.extended = :true
    return :nil
  end

  if shell.extended do
    shell.extended = :false
    let final = 0

    match code
    | 0x48 => final = 65 # up
    | 0x50 => final = 66 # down
    | 0x4d => final = 67 # right
    | 0x4b => final = 68 # left
    | 0x47 => final = 72 # home
    | 0x4f => final = 70 # end
    | _ => :nil

    if final != 0 do
      tty:feed(27) tty:feed(91) tty:feed(final)
    end
    return :nil
  end

  const character = decode_key(code)

  if (character == :nil)
    return :nil
  tty:feed(character:ascii())
end