176 lines
3.5 KiB
C
176 lines
3.5 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;
|
|
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);
|
|
|
|
send_kb_commands();
|
|
|
|
keyb_state.ready = true;
|
|
|
|
|
|
#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)
|
|
{return (kb_key_code_t) scancode;}
|
|
|
|
key_press_t do_keypress(kb_key_code_t keycode)
|
|
{
|
|
key_press_t packet;
|
|
|
|
if (!keyb_state.ready) {
|
|
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
|
|
*/
|