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
|
CFLAGS = -m64 -ffreestanding -fno-builtin -Wall -Wextra -Wshadow -std=c23
|
||||||
LDFLAGS =
|
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
|
SRC_ASM := src/boot.asm src/idt_stub.asm
|
||||||
|
|
||||||
OBJ_C := $(SRC_C:src/%.c=.build/%.o)
|
OBJ_C := $(SRC_C:src/%.c=.build/%.o)
|
||||||
|
|||||||
@@ -195,8 +195,8 @@ long_mode_start:
|
|||||||
mov fs, ax
|
mov fs, ax
|
||||||
mov gs, ax
|
mov gs, ax
|
||||||
|
|
||||||
extern kernel_main
|
extern kmain
|
||||||
call kernel_main
|
call kmain
|
||||||
|
|
||||||
cli
|
cli
|
||||||
.hang:
|
.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 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)
|
static void pic_remap(int offset1, int offset2)
|
||||||
{
|
{
|
||||||
uint8_t a1, a2;
|
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;
|
entry->reserved = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void idt_init(void)
|
void init_idt(void)
|
||||||
{
|
{
|
||||||
pic_remap(0x20, 0x28);
|
pic_remap(0x20, 0x28);
|
||||||
|
|
||||||
@@ -144,11 +132,6 @@ void idt_init(void)
|
|||||||
__asm__ volatile("sti");
|
__asm__ volatile("sti");
|
||||||
}
|
}
|
||||||
|
|
||||||
void idt_enable(void)
|
|
||||||
{
|
|
||||||
__asm__ volatile("sti");
|
|
||||||
}
|
|
||||||
|
|
||||||
void handle_isr(isr_frame_t* frame)
|
void handle_isr(isr_frame_t* frame)
|
||||||
{
|
{
|
||||||
if (frame->int_no < 32)
|
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*);
|
typedef void (*irq_handler_t)(isr_frame_t*);
|
||||||
|
|
||||||
void idt_init(void);
|
void init_idt(void);
|
||||||
void idt_enable(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);
|
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 "idt.h"
|
||||||
|
#include "keyboard.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
#include <stdbool.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_clear();
|
||||||
vga_print_success();
|
vga_print_success();
|
||||||
vga_print(" VGA intialzied\n");
|
vga_print(" VGA intialzied\n");
|
||||||
|
|
||||||
idt_init();
|
init_idt();
|
||||||
idt_enable();
|
|
||||||
vga_print_success();
|
vga_print_success();
|
||||||
vga_print(" IDT intialzied\n");
|
vga_print(" IDT intialzied\n");
|
||||||
|
|
||||||
|
init_keyboard();
|
||||||
|
vga_print_success();
|
||||||
|
vga_print(" Keyboard driver intialzied\n");
|
||||||
|
|
||||||
vga_print("\nWelcome to nub OS\n");
|
vga_print("\nWelcome to nub OS\n");
|
||||||
|
|
||||||
|
register_keypress_handler(keyboard_handler);
|
||||||
|
|
||||||
while (true)
|
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)
|
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)
|
void vga_print_colored(const char* string, vga_color_t color)
|
||||||
{
|
{
|
||||||
for (uint8_t i = 0; string[i] != '\0'; i++)
|
for (uint8_t i = 0; string[i] != '\0'; i++)
|
||||||
{
|
{
|
||||||
vga_print_char(string[i], color);
|
vga_print_char_colored(string[i], color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ typedef uint8_t vga_color_t;
|
|||||||
void vga_clear(void);
|
void vga_clear(void);
|
||||||
void vga_set_cursor_position(uint8_t row, uint8_t col);
|
void vga_set_cursor_position(uint8_t row, uint8_t col);
|
||||||
|
|
||||||
|
void vga_print_char(char character);
|
||||||
void vga_print_colored(const char* string, vga_color_t color);
|
void vga_print_colored(const char* string, vga_color_t color);
|
||||||
void vga_print(const char* string);
|
void vga_print(const char* string);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user