Files
novaos/kernel/arch/io/keyb.c

202 lines
4.3 KiB
C

#include <stdbool.h>
#include <stdint.h>
#include <queue.h>
#ifdef __TESTING__
#include <kernel/_kernel.h>
#include <stdio.h>
#endif
#include <kernel/x86/keyb.h>
#include <kernel/x86/io.h>
bool is_shift_down = false;
queue kb_cmd_queue;
// current plan is to create a a multi d array
//
//
// 16 entries each for each scan code... so
// 0x01..0x0F (15)/ this is the top row, so esc - 1..0, etc
// 0x10..0x1F (16) ...
// 0x20..0x2F ...
// these arrays will keep a 0/1 flag to see if these keys are pressed
// as a stort of state machine
// this will also let us tell multiple keys pressed
//
// another more simple version, which i could start with
//
// is do a Single character as currently pressed
// and a bitflag we can mask for leftshift, leftctrl, right shift, right ctrl, alt, etc being pressed down
//
//
//
struct keyboard_state keyb_state;
void init_kb(void)
{
#ifdef __TESTING__
puts("Initializing keyboard driver!");
#endif
keyb_state.ready = false;
keyb_state.waiting_for_commands = true;
init_queue(&kb_cmd_queue);
keyb_state.leds = 0;
keyb_state.flags = 0;
queue_kb_command(KEYB_CMD_ENABLE_SCANNING);
queue_kb_command(KEYB_CMD_SET_TYPEMATIC);
queue_kb_command(0x1F);
queue_kb_command(KEYB_CMD_DO_SCAN_CODE);
/**
* TODO: look into this further,
* this is setting scan code 2, but the scan code this results in (on my hardware) is scan code set 1 according to https://wiki.osdev.org/PS/2_Keyboard
*/
queue_kb_command(0x2); // lets use scan code set 1
send_kb_commands();
keyb_state.ready = true;
keyb_state.waiting_for_commands = false;
#ifdef __TESTING__
puts("Initialized keyboard driver!");
#endif
}
void queue_kb_command(uint8_t command)
{enqueue(&kb_cmd_queue, command);}
void send_kb_commands(void)
{
int i;
uint8_t resp, cmd;
while (!queue_is_empty(&kb_cmd_queue)) {
cmd = queue_peek(&kb_cmd_queue);
for (i = 0; i < KEYB_CMD_RETRIES; i++) {
outb(KEYB_PORT, cmd);
io_wait();
resp = inb(KEYB_PORT);
io_wait();
switch(resp) {
case KEYB_RESP_ACK:
break;
case KEYB_RESP_RESEND:
continue;
default:
break;
}
}
dequeue(&kb_cmd_queue);
}
}
kb_key_code_t decode_scancode(uint8_t scancode)
{
switch (scancode) {
case KEYB_RESP_ERR:
case KEYB_RESP_SELF_TEST_PASSED:
case KEYB_RESP_ECHO:
case KEYB_RESP_ACK:
case KEYB_RESP_SELF_TEST_FAILED:
case KEYB_RESP_SELF_TEST_FAILED_TWO:
case KEYB_RESP_RESEND:
case KEYB_RESP_ERR_TWO:
keyb_state.waiting_for_commands = false;
return KEY_NONE;
default:
keyb_state.waiting_for_commands = false;
return (kb_key_code_t) scancode;
}
}
key_press_t do_keypress(kb_key_code_t keycode)
{
key_press_t packet;
if (!keyb_state.ready || keycode == KEY_NONE) {
packet.key_code = KEY_NONE;
return packet;
}
if (keycode >= KEY_ESC_R) {
packet.key_code = keycode - KEY_PRESS_RELEASE_DIFF;
packet.release = true;
} else {
packet.key_code = keycode;
packet.release = false;
}
switch (keycode) {
case KEY_LEFT_SHIFT:
keyb_state.flags |= (STATUS_FLAG_LSHIFT);
break;
case KEY_LEFT_SHIFT_R:
keyb_state.flags &= ~(STATUS_FLAG_LSHIFT);
break;
case KEY_RIGHT_SHIFT:
keyb_state.flags |= (STATUS_FLAG_RSHIFT);
break;
case KEY_RIGHT_SHIFT_R:
keyb_state.flags &= ~(STATUS_FLAG_RSHIFT);
break;
case KEY_LEFT_CTRL:
keyb_state.flags |= (STATUS_FLAG_CTRL);
break;
case KEY_LEFT_CTRL_R:
keyb_state.flags &= ~(STATUS_FLAG_CTRL);
break;
case KEY_LEFT_ALT:
keyb_state.flags |= (STATUS_FLAG_ALT);
break;
case KEY_LEFT_ALT_R:
keyb_state.flags &= ~(STATUS_FLAG_ALT);
break;
case KEY_CAPSLOCK:
keyb_state.flags ^= (STATUS_FLAG_CAPS_LOCK);
keyb_state.leds ^= (KEYB_LED_CAP_LCK);
queue_kb_command(KEYB_CMD_SET_LEDS);
queue_kb_command(keyb_state.leds);
break;
case KEY_NUMLOCK:
keyb_state.flags ^= (STATUS_FLAG_NUM_LOCK);
keyb_state.leds ^= (KEYB_LED_NUM_LCK);
queue_kb_command(KEYB_CMD_SET_LEDS);
queue_kb_command(keyb_state.leds);
break;
case KEY_SCROLLLOCK:
keyb_state.flags ^= (STATUS_FLAG_NUM_LOCK);
keyb_state.leds ^= (KEYB_LED_SCRL_LCK);
queue_kb_command(KEYB_CMD_SET_LEDS);
queue_kb_command(keyb_state.leds);
break;
// case KEY_INSERT TODO: this shit baby
default:
break;
}
send_kb_commands();
packet.flags = keyb_state.flags;
return packet;
}
/**
* shift
* ctrl
* alt
* caps
* num
* scroll
*/