Files
RockOS/kernel/kbd.c

84 lines
1.6 KiB
C
Raw Normal View History

#include "kbd.h"
#include "process.h"
#include "scheduler.h"
#include "common.h"
#include <lib/tasks.h>
#include <lib/print.h>
#include <stddef.h>
#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();
}