razzle/kernel/ps2.c

303 lines
5.7 KiB
C
Raw Normal View History

2024-10-03 07:55:54 +00:00
#pragma once
#include "./scheduler.c"
#include "./vga.c"
#include <stdint.h>
enum key_code_t {
backtick_tilde = 1,
one_bang = 2,
two_at = 3,
three_crunch = 4,
four_dollar = 5,
five_percent = 6,
six_carat = 7,
seven_amp = 8,
eight_star = 9,
nine_lparen = 10,
zero_rparen = 11,
minus_underscore = 12,
equal_plus = 13,
backspace = 14,
tab = 15,
lbracket_lbrace = 26,
rbracket_rbrace = 27,
backslash_pipe = 43,
caps_lock = 58,
semicolon_colon = 39,
quote_dquote = 40,
a = 30,
b = 48,
c = 46,
d = 32,
e = 18,
f = 33,
g = 34,
h = 35,
i = 23,
j = 36,
k = 37,
l = 38,
m = 50,
n = 49,
o = 24,
p = 25,
q = 16,
r = 19,
s = 31,
t = 20,
u = 22,
v = 47,
w = 17,
x = 45,
y = 21,
z = 44,
space = 57,
l_shift = 42,
r_shift = 54,
period_rarr = 52,
enter = 28,
comma_larr = 51,
slash_question = 53
};
struct key_event_t {
enum key_code_t key;
uint8_t is_down;
};
struct kb_state {
uint8_t l_shift;
uint8_t r_shift;
uint8_t l_ctrl;
uint8_t r_ctrl;
uint8_t caps;
};
static struct kb_state kstate;
uint8_t is_shifted() { return kstate.caps | kstate.r_shift | kstate.l_shift; }
char keycode_to_char(enum key_code_t key_code) {
switch (key_code) {
case a:
return is_shifted() ? 'A' : 'a';
break;
case b:
return is_shifted() ? 'B' : 'b';
break;
case c:
return is_shifted() ? 'C' : 'c';
break;
case d:
return is_shifted() ? 'D' : 'd';
break;
case e:
return is_shifted() ? 'E' : 'e';
break;
case f:
return is_shifted() ? 'F' : 'f';
break;
case g:
return is_shifted() ? 'G' : 'g';
break;
case h:
return is_shifted() ? 'H' : 'h';
break;
case i:
return is_shifted() ? 'I' : 'i';
break;
case j:
return is_shifted() ? 'J' : 'j';
break;
case k:
return is_shifted() ? 'K' : 'k';
break;
case l:
return is_shifted() ? 'L' : 'l';
break;
case m:
return is_shifted() ? 'M' : 'm';
break;
case n:
return is_shifted() ? 'N' : 'n';
break;
case o:
return is_shifted() ? 'O' : 'o';
break;
case p:
return is_shifted() ? 'P' : 'p';
break;
case q:
return is_shifted() ? 'Q' : 'q';
break;
case r:
return is_shifted() ? 'R' : 'r';
break;
case s:
return is_shifted() ? 'S' : 's';
break;
case t:
return is_shifted() ? 'T' : 't';
break;
case u:
return is_shifted() ? 'U' : 'u';
break;
case v:
return is_shifted() ? 'V' : 'v';
break;
case w:
return is_shifted() ? 'W' : 'w';
break;
case x:
return is_shifted() ? 'X' : 'x';
break;
case y:
return is_shifted() ? 'Y' : 'y';
break;
case z:
return is_shifted() ? 'Z' : 'z';
break;
case space:
return ' ';
break;
case comma_larr:
return is_shifted() ? '<' : ',';
break;
case period_rarr:
return is_shifted() ? '>' : '.';
break;
case enter:
return '\n';
break;
case backspace:
return '\b';
break;
case backtick_tilde:
return is_shifted() ? '~' : '`';
break;
case one_bang:
return is_shifted() ? '!' : '1';
break;
case two_at:
return is_shifted() ? '@' : '2';
break;
case three_crunch:
return is_shifted() ? '#' : '3';
break;
case four_dollar:
return is_shifted() ? '$' : '4';
break;
case five_percent:
return is_shifted() ? '%' : '5';
break;
case six_carat:
return is_shifted() ? '^' : '6';
break;
case seven_amp:
return is_shifted() ? '&' : '7';
break;
case eight_star:
return is_shifted() ? '*' : '8';
break;
case nine_lparen:
return is_shifted() ? '(' : '9';
break;
case zero_rparen:
return is_shifted() ? ')' : '0';
break;
case minus_underscore:
return is_shifted() ? '_' : '-';
break;
case equal_plus:
return is_shifted() ? '+' : '=';
break;
case tab:
return '\t';
break;
case lbracket_lbrace:
return is_shifted() ? '{' : '[';
break;
case rbracket_rbrace:
return is_shifted() ? '}' : ']';
break;
case semicolon_colon:
return is_shifted() ? ':' : ';';
break;
case quote_dquote:
return is_shifted() ? '"' : '\'';
break;
case backslash_pipe:
return is_shifted() ? '|' : '\\';
break;
case slash_question:
return is_shifted() ? '?' : '/';
break;
case caps_lock:
case r_shift:
case l_shift:
break;
// default:
// printf("%d", key_code);
// break;
}
return '\0';
}
struct ps2_waiter_t {
uint8_t alloc;
uint32_t pid;
};
struct ps2_waiter_t ps2_waiters[MAX_PROCESSES];
void init_ps2() {
for(uint32_t i = 0; i < MAX_PROCESSES; i++) {
ps2_waiters[i].alloc = 0;
}
}
void handle_keypress(uint8_t char_code) {
struct key_event_t event;
if ((char_code & 0b11000000) == 0b10000000) {
event.is_down = 0;
event.key = char_code & 0b00111111;
} else {
event.is_down = 1;
event.key = char_code;
}
switch (event.key) {
case l_shift:
kstate.l_shift = event.is_down;
break;
case r_shift:
kstate.r_shift = event.is_down;
break;
case caps_lock:
if (event.is_down) {
kstate.caps = !kstate.caps;
}
break;
default: {
if (event.is_down) {
char c = keycode_to_char(event.key);
if (c != '\0') {
for(uint32_t i = 0; i < MAX_PROCESSES; i++) {
if(ps2_waiters[i].alloc) {
process_table[ps2_waiters[i].pid].registers.eax = c;
ps2_waiters[i].alloc = 0;
process_table[ps2_waiters[i].pid].state = TASKSTATE_ready;
}
}
}
}
break;
}
}
}