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
|
#include "driver.h"
#include <assert.h>
#include <camellia.h>
#include <camellia/compat.h>
#include <camellia/syscalls.h>
#include <err.h>
#include <errno.h>
#include <shared/ring.h>
#include <stdbool.h>
#include <stdlib.h>
#include <thread.h>
static const char keymap_lower[] = {
'\0', '\0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t',
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\r', '\0', 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', '\0', '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', '\0', '*', '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '8', '9', '-', '4', '5', '6', '+', '1',
'2', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
};
static const char keymap_upper[] = {
'\0', '\0', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b', '\t',
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\r', '\0', 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', '\0', '|', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', '<', '>', '?', '\0', '*', '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '7', '8', '9', '-', '4', '5', '6', '+', '1',
'2', '3', '0', '.', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
};
static volatile uint8_t backlog_buf[16];
static volatile ring_t backlog = {(void*)backlog_buf, sizeof backlog_buf, 0, 0};
static bool keys[0x80] = {0};
static void parse_scancode(uint8_t s) {
bool ctrl = keys[0x1D];
bool shift = keys[0x2A] || keys[0x36];
bool down = !(s & 0x80);
char c;
s &= 0x7f;
keys[s] = down;
c = shift ? keymap_upper[s] : keymap_lower[s];
if (ctrl && keymap_upper[s] >= 'A' && keymap_upper[s] <= 'Z')
c = keymap_upper[s] - 'A' + 1;
if (down && c) ring_put1b((void*)&backlog, c);
}
#define QSIZE 16
static hid_t queue[QSIZE] = {0};
static void enqueue(hid_t h) {
for (int i = 0; i < QSIZE; i++) {
if (queue[i] == 0) {
queue[i] = h;
return;
}
}
_sys_fs_respond(h, NULL, -EAGAIN, 0);
}
static void fulfill(void) {
int ret;
char c;
bool queued = false;
for (int i = 0; i < QSIZE; i++) {
if (queue[i] != 0) {
queued = true;
break;
}
}
if (!queued) return;
// only reading a single char at a time because that's easier
ret = ring_get((void*)&backlog, &c, 1);
if (ret == 0) return;
for (int i = 0; i < QSIZE; i++) {
if (queue[i] != 0) {
_sys_fs_respond(queue[i], &c, 1, 0);
queue[i] = 0;
break;
}
}
}
static void kb_thread(void *unused) {
static char buf[512];
int fd;
(void)unused;
fd = camellia_open("/dev/ps2/kb", OPEN_READ);
if (fd < 0) err(1, "open");
while (true) {
int ret = _sys_read(fd, buf, sizeof buf, -1);
if (ret < 0) break;
for (int i = 0; i < ret; i++) {
parse_scancode(buf[i]);
}
fulfill();
}
}
static void fs_thread(void *unused) {
static char buf[512];
(void)unused;
for (;;) {
struct ufs_request res;
hid_t reqh = _sys_fs_wait(buf, sizeof buf, &res);
if (reqh < 0) return;
switch (res.op) {
case VFSOP_OPEN:
if (res.len == 0) {
_sys_fs_respond(reqh, NULL, 1, 0);
} else {
_sys_fs_respond(reqh, NULL, -ENOENT, 0);
}
break;
case VFSOP_READ:
enqueue(reqh);
fulfill();
break;
default:
_sys_fs_respond(reqh, NULL, -1, 0);
break;
}
}
}
void ps2_drv(void) {
thread_create(0, kb_thread, NULL);
thread_create(0, fs_thread, NULL);
_sys_await();
exit(0);
}
|