diff --git a/Makefile b/Makefile index 4e3ef4e..52b96c4 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,8 @@ OBJ = boot/boot.o \ kernel/string.o \ drivers/serial.o \ drivers/vga.o \ - drivers/timer.o + drivers/timer.o \ + drivers/keyboard.o # Дефолтное правило (просто сборка бинарника) all: $(TARGET) diff --git a/README.md b/README.md index 205afeb..9bba99d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ - [x] Прерывания (GDT/IDT) - [x] UART отладка - [x] Драйвер таймера -- [ ] Драйвер клавиатуры +- [x] Драйвер клавиатуры - [ ] Нормальный драйвер VGA (скролл итд) - [ ] Нормальный драйвер клавиатуры (Caps Lock, Shift, Numpad итд) - [ ] Драйвер PC Speaker diff --git a/drivers/keyboard.c b/drivers/keyboard.c new file mode 100644 index 0000000..6c0ea57 --- /dev/null +++ b/drivers/keyboard.c @@ -0,0 +1,43 @@ +#include "keyboard.h" +#include "serial.h" +#include "vga.h" +#include "../kernel/io.h" // Отсюда заберём inb +#include "../kernel/logger.h" + +// Карта скан-кодов (US Layout, первый сет). 0 — это непечатаемые символы +static const char kbdus[128] = { + 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', + 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, + '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, + ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, '-', 0, 0, 0, '+', 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // Остальное нули +}; + +void keyboard_init(void) { + // Чисто для логов, unmask мы уже сделали в kmain + log_info(LOG_NORMAL, "Keyboard driver ready.\n"); +} + +void keyboard_handler(void) { + // Читаем байт из порта контроллера клавиатуры (8042) + uint8_t scancode = inb(0x60); + + // Если старший бит (0x80) установлен, это отпускание клавиши (Key Release). Игнорируем пока. + if (scancode & 0x80) { + // Здесь можно отслеживать отпускание Shift/Ctrl + } else { + // Клавиша нажата (Key Press). Проверяем, входит ли в нашу карту + if (scancode < 128 && kbdus[scancode] != 0) { + char c = kbdus[scancode]; + + // Выводим символ на экран через VGA драйвер + vga_putchar(c); + + // И дублируем в сериал для надежной отладки + char str[2] = {c, 0}; + kprint_serial(str); + } + } +} diff --git a/drivers/keyboard.h b/drivers/keyboard.h new file mode 100644 index 0000000..424cc53 --- /dev/null +++ b/drivers/keyboard.h @@ -0,0 +1,10 @@ +#ifndef KEYBOARD_H +#define KEYBOARD_H + +// Инициализация (пока просто выведем лог, что всё ок) +void keyboard_init(void); + +// Основной обработчик прерывания, который мы вызовем из idt.c +void keyboard_handler(void); + +#endif diff --git a/kernel/idt.c b/kernel/idt.c index 2eb6aa7..8e3cc7a 100644 --- a/kernel/idt.c +++ b/kernel/idt.c @@ -2,6 +2,7 @@ #include "string.h" #include "../drivers/serial.h" #include "../drivers/timer.h" +#include "../drivers/keyboard.h" // Сам массив IDT на 256 векторов и указатель на него struct idt_entry idt[256]; @@ -76,6 +77,8 @@ void isr_handler(struct registers regs) { void irq_handler(struct registers regs) { if (regs.int_no == 32) { timer_handler(); + } else if (regs.int_no == 33) { + keyboard_handler(); // <-- Вызываем обработчик клавиатуры при векторе 33 } else { char irq_str[4]; itoa(regs.int_no, irq_str, 10); diff --git a/kernel/kmain.c b/kernel/kmain.c index fe6e0c3..00b6725 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -21,6 +21,8 @@ void kernel_main(void) { pic_remap(32, 40); log_info(LOG_NORMAL, "Unmasking IRQ 0... (timer)"); pic_clear_mask(0); + log_info(LOG_NORMAL, "Unmasking IRQ 1... (keyboard)"); + pic_clear_mask(1); log_info(LOG_NORMAL, "Registering timer at 100Hz"); timer_init(100); log_info(LOG_NORMAL, "Enabling IRQ...");