-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeyboard.cpp
151 lines (136 loc) · 2.96 KB
/
keyboard.cpp
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "keyboard.h"
KeyboardDriver::KeyboardDriver(InterruptManager* manager) :
InterruptHandler(0x21, manager), data(0x60), com(0x64)
{
while(com.read() & 0x1) {
data.read();
}
// tell keybaord to use interrupts
com.write(0xAE);
// change state to ??
// get current state
com.write(0x20);
uint8_t state = (data.read() | 1) & ~0x10;
// set state
com.write(0x60);
data.write(state);
// activate keyboard
data.write(0xF4);
}
KeyboardDriver::~KeyboardDriver() {
}
uint8_t KeyboardDriver::buffer[GETC_BUF_SIZE];
uint32_t KeyboardDriver::head = 0;
uint32_t KeyboardDriver::count = 0;
#define KMAP(code, c) case code: key = c; break;
uint32_t KeyboardDriver::operator()(uint32_t esp) {
uint8_t key = data.read();
switch(key) {
KMAP(0x2, '1');
KMAP(0x3, '2');
KMAP(0x4, '3');
KMAP(0x5, '4');
KMAP(0x6, '5');
KMAP(0x7, '6');
KMAP(0x8, '7');
KMAP(0x9, '8');
KMAP(0xA, '9');
KMAP(0xB, '0');
KMAP(0xE, '\b');
KMAP(0x10, 'q');
KMAP(0x11, 'w');
KMAP(0x12, 'e');
KMAP(0x13, 'r');
KMAP(0x14, 't');
KMAP(0x15, 'y');
KMAP(0x16, 'u');
KMAP(0x17, 'i');
KMAP(0x18, 'o');
KMAP(0x19, 'p');
KMAP(0x1E, 'a');
KMAP(0x1F, 's');
KMAP(0x20, 'd');
KMAP(0x21, 'f');
KMAP(0x22, 'g');
KMAP(0x23, 'h');
KMAP(0x24, 'j');
KMAP(0x25, 'k');
KMAP(0x26, 'l');
KMAP(0x1C, '\n');
KMAP(0x2C, 'z');
KMAP(0x2D, 'x');
KMAP(0x2E, 'c');
KMAP(0x2F, 'v');
KMAP(0x30, 'b');
KMAP(0x31, 'n');
KMAP(0x32, 'm');
KMAP(0x39, ' ');
default:
if (key > 0x80) {
// key up code
return esp;
}
key = '?';
}
if (count < GETC_BUF_SIZE) {
uint32_t index = (head + count) % GETC_BUF_SIZE;
buffer[index] = key;
count++;
}
return esp;
}
extern "C" uint8_t getc() {
while (KeyboardDriver::count == 0) {
// start interrupts and wait for a char
asm volatile("sti\n"
"hlt");
}
asm volatile("cli");
uint8_t result = KeyboardDriver::buffer[KeyboardDriver::head];
KeyboardDriver::head++;
KeyboardDriver::count--;
asm volatile("sti");
return result;
}
extern "C" uint8_t get_line(char* buf, uint32_t length) {
uint8_t c = getc();
int i = 0;
while (c != '\n' && i < length - 1) {
if (c == '\b') {
// only backspace until begining of buffer
if (i > 0) {
putc('\b');
i--;
}
c = getc();
} else {
putc(c);
buf[i] = c;
c = getc();
i++;
}
}
// if the last char was \n insert it
// if not we line ran out of buffer
if (c == '\n') {
putc('\n');
if (i < length - 1) {
buf[i] = '\n';
i++;
}
}
// insert nul term
if (i < length) {
buf[i] = '\0';
}
}
uint8_t KeyboardStdin::read(uint32_t offset, uint8_t* buf, uint32_t bytes) {
// TODO how to handle offset?
// TODO lmao security issue where you can use stdin to write to
// memory you don't own
while (bytes != 0) {
*buf = getc();
buf++;
bytes--;
}
}