ROADMAP: закрыт пункт нормального драйвера клавиатуры
This commit is contained in:
parent
7136ac3155
commit
bcbb8f8303
2 changed files with 112 additions and 18 deletions
|
|
@ -13,7 +13,7 @@
|
||||||
- [x] Драйвер таймера
|
- [x] Драйвер таймера
|
||||||
- [x] Драйвер клавиатуры
|
- [x] Драйвер клавиатуры
|
||||||
- [x] Нормальный драйвер VGA (скролл итд)
|
- [x] Нормальный драйвер VGA (скролл итд)
|
||||||
- [ ] Нормальный драйвер клавиатуры (Caps Lock, Shift, Numpad итд)
|
- [x] Нормальный драйвер клавиатуры (Caps Lock, Shift, Numpad итд)
|
||||||
- [ ] Драйвер PC Speaker
|
- [ ] Драйвер PC Speaker
|
||||||
- [ ] Screen buffers (как tty в Linux)
|
- [ ] Screen buffers (как tty в Linux)
|
||||||
- [ ] ANSI Escape в screen buffers
|
- [ ] ANSI Escape в screen buffers
|
||||||
|
|
|
||||||
|
|
@ -1,41 +1,135 @@
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
#include "../kernel/io.h" // Отсюда заберём inb
|
#include "../kernel/io.h"
|
||||||
#include "../kernel/logger.h"
|
|
||||||
|
|
||||||
// Карта скан-кодов (US Layout, первый сет). 0 — это непечатаемые символы
|
// Состояние модификаторов клавиатуры
|
||||||
static const char kbdus[128] = {
|
static int is_e0 = 0;
|
||||||
|
static int shift_pressed = 0;
|
||||||
|
static int caps_lock_active = 0;
|
||||||
|
|
||||||
|
// Скан-коды управления (Set 1)
|
||||||
|
#define SCAN_LSHIFT 0x2A
|
||||||
|
#define SCAN_RSHIFT 0x36
|
||||||
|
#define SCAN_CAPS_LOCK 0x3A
|
||||||
|
|
||||||
|
// Скан-коды стрелок (после 0xE0)
|
||||||
|
#define SCAN_UP 0x48
|
||||||
|
#define SCAN_DOWN 0x50
|
||||||
|
#define SCAN_LEFT 0x4B
|
||||||
|
#define SCAN_RIGHT 0x4D
|
||||||
|
|
||||||
|
// Таблица 1: Обычные символы (без Shift)
|
||||||
|
static const char kbdus_lower[128] = {
|
||||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
|
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',
|
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
|
||||||
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0,
|
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0,
|
||||||
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 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, 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
|
||||||
|
};
|
||||||
|
|
||||||
|
// Таблица 2: Символы при зажатом Shift
|
||||||
|
static const char kbdus_upper[128] = {
|
||||||
|
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\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) {
|
void keyboard_init(void) {
|
||||||
// Чисто для логов, unmask мы уже сделали в kmain
|
shift_pressed = 0;
|
||||||
log_info(LOG_NORMAL, "Keyboard driver ready.\n");
|
caps_lock_active = 0;
|
||||||
|
is_e0 = 0;
|
||||||
|
kprint_serial("[INFO] Full keyboard driver with Modifiers initialized.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void keyboard_handler(void) {
|
void keyboard_handler(void) {
|
||||||
// Читаем байт из порта контроллера клавиатуры (8042)
|
|
||||||
uint8_t scancode = inb(0x60);
|
uint8_t scancode = inb(0x60);
|
||||||
|
|
||||||
// Если старший бит (0x80) установлен, это отпускание клавиши (Key Release). Игнорируем пока.
|
// 1. Ловим префикс расширенных кодов
|
||||||
|
if (scancode == 0xE0) {
|
||||||
|
is_e0 = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Обработка ОТПУСКАНИЯ клавиш (Key Release / Break code)
|
||||||
|
// В Set 1 код отпускания — это код нажатия + 0x80 (установлен старший бит)
|
||||||
if (scancode & 0x80) {
|
if (scancode & 0x80) {
|
||||||
// Здесь можно отслеживать отпускание Shift/Ctrl
|
uint8_t released_code = scancode & 0x7F; // Получаем чистый код нажатия
|
||||||
} else {
|
|
||||||
// Клавиша нажата (Key Press). Проверяем, входит ли в нашу карту
|
if (is_e0) {
|
||||||
if (scancode < 128 && kbdus[scancode] != 0) {
|
is_e0 = 0; // Для расширенных кодов просто сбрасываем флаг
|
||||||
char c = kbdus[scancode];
|
return;
|
||||||
|
}
|
||||||
// Выводим символ на экран через VGA драйвер
|
|
||||||
|
// Если отпустили левый или правый Shift — выключаем режим шифта
|
||||||
|
if (released_code == SCAN_LSHIFT || released_code == SCAN_RSHIFT) {
|
||||||
|
shift_pressed = 0;
|
||||||
|
kprint_serial("[KEY] Shift Released\n");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Обработка НАЖАТИЯ клавиш (Key Press / Make code)
|
||||||
|
if (is_e0) {
|
||||||
|
// Обработка расширенных клавиш (стрелочки)
|
||||||
|
switch (scancode) {
|
||||||
|
case SCAN_UP: kprint_serial("[KEY] UP\n"); break;
|
||||||
|
case SCAN_DOWN: kprint_serial("[KEY] DOWN\n"); break;
|
||||||
|
case SCAN_LEFT: kprint_serial("[KEY] LEFT\n"); break;
|
||||||
|
case SCAN_RIGHT: kprint_serial("[KEY] RIGHT\n"); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
is_e0 = 0; // Сбрасываем префикс после обработки
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обработка обычных управляющих клавиш
|
||||||
|
if (scancode == SCAN_LSHIFT || scancode == SCAN_RSHIFT) {
|
||||||
|
shift_pressed = 1;
|
||||||
|
kprint_serial("[KEY] Shift Pressed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scancode == SCAN_CAPS_LOCK) {
|
||||||
|
caps_lock_active = !caps_lock_active; // Инвертируем состояние
|
||||||
|
kprint_serial("[KEY] Caps Lock Toggled\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Печать символов из таблиц
|
||||||
|
if (scancode < 128) {
|
||||||
|
char c = 0;
|
||||||
|
|
||||||
|
// Определяем, какую таблицу использовать и нужно ли менять регистр букв
|
||||||
|
// Логика для букв: Shift XOR CapsLock (если нажат Shift и включен Caps, буквы будут маленькими)
|
||||||
|
int use_upper = shift_pressed;
|
||||||
|
|
||||||
|
// Проверяем, является ли символ буквой, чтобы к нему применялся Caps Lock
|
||||||
|
char base_char = kbdus_lower[scancode];
|
||||||
|
int is_alpha = (base_char >= 'a' && base_char <= 'z');
|
||||||
|
|
||||||
|
if (is_alpha && caps_lock_active) {
|
||||||
|
use_upper = !use_upper; // Caps Lock инвертирует поведение Shift для букв
|
||||||
|
}
|
||||||
|
|
||||||
|
// Выбираем символ из нужной матрицы
|
||||||
|
if (use_upper) {
|
||||||
|
c = kbdus_upper[scancode];
|
||||||
|
} else {
|
||||||
|
c = kbdus_lower[scancode];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если символ есть в раскладке — выводим
|
||||||
|
if (c != 0) {
|
||||||
vga_putchar(c);
|
vga_putchar(c);
|
||||||
|
|
||||||
// И дублируем в сериал для надежной отладки
|
// Дублируем в сериал отладку
|
||||||
char str[2] = {c, 0};
|
char str[2] = {c, 0};
|
||||||
kprint_serial(str);
|
kprint_serial(str);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue