84 lines
1.6 KiB
C
84 lines
1.6 KiB
C
#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();
|
|
} |