keyboard driver
This commit is contained in:
2
makefile
2
makefile
@@ -4,7 +4,7 @@ LD = x86_64-elf-ld
|
||||
CFLAGS = -m64 -ffreestanding -fno-builtin -Wall -Wextra -Wshadow -std=c23
|
||||
LDFLAGS =
|
||||
|
||||
SRC_C := src/kernel.c src/vga.c src/idt.c src/string.c
|
||||
SRC_C := src/kernel.c src/vga.c src/idt.c src/string.c src/keyboard.c
|
||||
SRC_ASM := src/boot.asm src/idt_stub.asm
|
||||
|
||||
OBJ_C := $(SRC_C:src/%.c=.build/%.o)
|
||||
|
||||
@@ -195,8 +195,8 @@ long_mode_start:
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
extern kernel_main
|
||||
call kernel_main
|
||||
extern kmain
|
||||
call kmain
|
||||
|
||||
cli
|
||||
.hang:
|
||||
|
||||
19
src/idt.c
19
src/idt.c
@@ -66,18 +66,6 @@ static const char* exception_messages[32] = { "divide by zero",
|
||||
|
||||
static interrupt_descriptor idt[IDT_SIZE];
|
||||
|
||||
static inline void outb(uint16_t port, uint8_t val)
|
||||
{
|
||||
__asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||
}
|
||||
|
||||
static inline uint8_t inb(uint16_t port)
|
||||
{
|
||||
uint8_t ret;
|
||||
__asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pic_remap(int offset1, int offset2)
|
||||
{
|
||||
uint8_t a1, a2;
|
||||
@@ -129,7 +117,7 @@ static inline void idt_set_descriptor(uint8_t vector, void* handler, uint8_t dpl
|
||||
entry->reserved = 0;
|
||||
}
|
||||
|
||||
void idt_init(void)
|
||||
void init_idt(void)
|
||||
{
|
||||
pic_remap(0x20, 0x28);
|
||||
|
||||
@@ -144,11 +132,6 @@ void idt_init(void)
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
void idt_enable(void)
|
||||
{
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
void handle_isr(isr_frame_t* frame)
|
||||
{
|
||||
if (frame->int_no < 32)
|
||||
|
||||
16
src/idt.h
16
src/idt.h
@@ -13,6 +13,18 @@ typedef struct
|
||||
|
||||
typedef void (*irq_handler_t)(isr_frame_t*);
|
||||
|
||||
void idt_init(void);
|
||||
void idt_enable(void);
|
||||
void init_idt(void);
|
||||
|
||||
static inline void outb(uint16_t port, uint8_t val)
|
||||
{
|
||||
__asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||
}
|
||||
|
||||
static inline uint8_t inb(uint16_t port)
|
||||
{
|
||||
uint8_t ret;
|
||||
__asm__ volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void register_irq_handler(uint8_t irq, irq_handler_t handler);
|
||||
28
src/kernel.c
28
src/kernel.c
@@ -1,21 +1,43 @@
|
||||
#include "kernel.h"
|
||||
#include "idt.h"
|
||||
#include "keyboard.h"
|
||||
#include "vga.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
void kernel_main(void)
|
||||
void keyboard_handler(keyboard_event_t* event)
|
||||
{
|
||||
if (event->pressed)
|
||||
{
|
||||
vga_print_int(event->scan_code);
|
||||
vga_print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void kmain(void)
|
||||
{
|
||||
vga_clear();
|
||||
vga_print_success();
|
||||
vga_print(" VGA intialzied\n");
|
||||
|
||||
idt_init();
|
||||
idt_enable();
|
||||
init_idt();
|
||||
vga_print_success();
|
||||
vga_print(" IDT intialzied\n");
|
||||
|
||||
init_keyboard();
|
||||
vga_print_success();
|
||||
vga_print(" Keyboard driver intialzied\n");
|
||||
|
||||
vga_print("\nWelcome to nub OS\n");
|
||||
|
||||
register_keypress_handler(keyboard_handler);
|
||||
|
||||
while (true)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void kpanic()
|
||||
{
|
||||
vga_print("Kernel panic!\n");
|
||||
__asm__ volatile("cli; hlt");
|
||||
}
|
||||
3
src/kernel.h
Normal file
3
src/kernel.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void kpanic();
|
||||
72
src/keyboard.c
Normal file
72
src/keyboard.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "keyboard.h"
|
||||
#include "idt.h"
|
||||
#include "kernel.h"
|
||||
#include "vga.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define SCANCODE_LEFT_SHIFT 42
|
||||
#define SCANCODE_RIGHT_SHIFT 54
|
||||
#define SCANCODE_CAPS_LOCK 58
|
||||
|
||||
#define KEYBOARD_HANDLERS_LENGTH 32
|
||||
|
||||
bool shift = false;
|
||||
bool caps_lock = false;
|
||||
|
||||
// todo(nub): make dynamic when a memory allocator is implemented
|
||||
static keyboard_handler_t keyboard_handlers[KEYBOARD_HANDLERS_LENGTH];
|
||||
static int handler_index = 0;
|
||||
|
||||
void handle_keyboard(isr_frame_t* frame)
|
||||
{
|
||||
uint8_t code = inb(0x60);
|
||||
uint8_t scan_code = code & 0x7F;
|
||||
bool pressed = (code & 0x80) == 0;
|
||||
|
||||
switch (scan_code)
|
||||
{
|
||||
case SCANCODE_LEFT_SHIFT:
|
||||
case SCANCODE_RIGHT_SHIFT:
|
||||
{
|
||||
shift = pressed;
|
||||
break;
|
||||
}
|
||||
case SCANCODE_CAPS_LOCK:
|
||||
{
|
||||
if (pressed)
|
||||
{
|
||||
caps_lock = !caps_lock;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
keyboard_event_t event = { .scan_code = scan_code, .pressed = pressed, .caps_lock = caps_lock, .shift = shift };
|
||||
|
||||
for (int i = 0; i < handler_index; i++)
|
||||
{
|
||||
keyboard_handlers[i](&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void register_keypress_handler(keyboard_handler_t handler)
|
||||
{
|
||||
// todo(nub31): remove when a memory allocator is implemented and keyboard_handlers is a dynamic list
|
||||
if (handler_index >= KEYBOARD_HANDLERS_LENGTH)
|
||||
{
|
||||
vga_print_error();
|
||||
vga_print(" Maximum keyboard handlers reached\n");
|
||||
kpanic();
|
||||
}
|
||||
|
||||
keyboard_handlers[handler_index] = handler;
|
||||
handler_index += 1;
|
||||
}
|
||||
|
||||
void init_keyboard()
|
||||
{
|
||||
register_irq_handler(1, handle_keyboard);
|
||||
}
|
||||
17
src/keyboard.h
Normal file
17
src/keyboard.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t scan_code;
|
||||
bool pressed;
|
||||
bool shift;
|
||||
bool caps_lock;
|
||||
} keyboard_event_t;
|
||||
|
||||
typedef void (*keyboard_handler_t)(keyboard_event_t*);
|
||||
|
||||
void init_keyboard();
|
||||
void register_keypress_handler(keyboard_handler_t handler);
|
||||
@@ -51,7 +51,7 @@ void vga_set_cursor_position(uint8_t row, uint8_t col)
|
||||
}
|
||||
}
|
||||
|
||||
void vga_print_char(char character, vga_color_t color)
|
||||
void vga_print_char_colored(char character, vga_color_t color)
|
||||
{
|
||||
switch (character)
|
||||
{
|
||||
@@ -101,11 +101,16 @@ void vga_print_char(char character, vga_color_t color)
|
||||
}
|
||||
}
|
||||
|
||||
void vga_print_char(char character)
|
||||
{
|
||||
vga_print_char_colored(character, vga_default_color());
|
||||
}
|
||||
|
||||
void vga_print_colored(const char* string, vga_color_t color)
|
||||
{
|
||||
for (uint8_t i = 0; string[i] != '\0'; i++)
|
||||
{
|
||||
vga_print_char(string[i], color);
|
||||
vga_print_char_colored(string[i], color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user