#include "kbd.h" #include "process.h" #include "scheduler.h" #include "common.h" #include #include #include #define KBD_BUFFER_SIZE 256 static spinlock_t kbd_lock = {0}; static process_t* kbd_waiting_task = NULL; static char kbd_buffer[KBD_BUFFER_SIZE]; static int kbd_head = 0; static int kbd_tail = 0; static void lock_kbd() { disable_interrupts(); spin_lock(&kbd_lock); } static void unlock_kbd() { spin_unlock(&kbd_lock); enable_interrupts(); } static void kbd_set_waiting(process_t* task) { lock_kbd(); if (kbd_head == kbd_tail) { kbd_waiting_task = task; } unlock_kbd(); } static char kbd_pop() { char c = 0; lock_kbd(); if (kbd_head != kbd_tail) { c = kbd_buffer[kbd_tail]; kbd_tail = (kbd_tail + 1) % KBD_BUFFER_SIZE; } unlock_kbd(); return c; } void kbd_push(char c) { spin_lock(&kbd_lock); // push to buffer first, very important int next_head = (kbd_head + 1) % KBD_BUFFER_SIZE; if (next_head != kbd_tail) { kbd_buffer[kbd_head] = c; kbd_head = next_head; } if (kbd_waiting_task != NULL) { wake(kbd_waiting_task); kbd_waiting_task = NULL; } spin_unlock(&kbd_lock); } int kbd_ready() { int ready = 0; lock_kbd(); ready = (kbd_head != kbd_tail); unlock_kbd(); return ready; } void kbd_wait() { process_t* task = current_task(); while (!kbd_ready()) { task->state = STATE_BLOCKED; kbd_set_waiting(task); yield(); } } char kbd_read() { return kbd_pop(); }