121 lines
4 KiB
C
121 lines
4 KiB
C
#include "keyboard.h"
|
||
#include "serial.h"
|
||
#include "io.h"
|
||
|
||
// Состояние модификаторов клавиатуры
|
||
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',
|
||
'\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
|
||
};
|
||
|
||
// Таблица 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) {
|
||
shift_pressed = 0;
|
||
caps_lock_active = 0;
|
||
is_e0 = 0;
|
||
kprint_serial("[INFO] Full keyboard driver with Modifiers initialized.\n");
|
||
}
|
||
|
||
void keyboard_handler(void) {
|
||
uint8_t status = inb(0x64);
|
||
|
||
// Бит 5 равен 1, если данные пришли от мыши (Auxiliary Device)
|
||
// Мышь не должна обрабатываться здесь!
|
||
if (status & 0x20) {
|
||
// Очистим порт, чтобы не висел, но не обрабатываем как клаву
|
||
inb(0x60);
|
||
return;
|
||
}
|
||
|
||
// Если мы здесь, значит это точно клавиатура
|
||
if (!(status & 0x01)) return; // Нет данных
|
||
|
||
uint8_t scancode = inb(0x60);
|
||
|
||
// Обработка префикса 0xE0
|
||
if (scancode == 0xE0) {
|
||
is_e0 = 1;
|
||
return;
|
||
}
|
||
|
||
// Обработка Break Code (отпускание)
|
||
if (scancode & 0x80) {
|
||
uint8_t released_code = scancode & 0x7F;
|
||
if (released_code == SCAN_LSHIFT || released_code == SCAN_RSHIFT) {
|
||
shift_pressed = 0;
|
||
}
|
||
is_e0 = 0; // Сброс префикса
|
||
return;
|
||
}
|
||
|
||
// Обработка стрелок (расширенные)
|
||
if (is_e0) {
|
||
is_e0 = 0;
|
||
switch (scancode) {
|
||
case SCAN_UP: /* ... */ break;
|
||
case SCAN_DOWN: /* ... */ break;
|
||
case SCAN_LEFT: /* ... */ break;
|
||
case SCAN_RIGHT: /* ... */ break;
|
||
}
|
||
return;
|
||
}
|
||
|
||
// Обычные модификаторы
|
||
if (scancode == SCAN_LSHIFT || scancode == SCAN_RSHIFT) {
|
||
shift_pressed = 1;
|
||
return;
|
||
}
|
||
|
||
if (scancode == SCAN_CAPS_LOCK) {
|
||
caps_lock_active = !caps_lock_active;
|
||
return;
|
||
}
|
||
|
||
// Печать символов
|
||
if (scancode < 128) {
|
||
char c = 0;
|
||
int use_upper = shift_pressed;
|
||
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;
|
||
|
||
c = (use_upper) ? kbdus_upper[scancode] : kbdus_lower[scancode];
|
||
|
||
if (c != 0) {
|
||
char str[2] = {c, 0};
|
||
kprint_serial(str);
|
||
}
|
||
}
|
||
}
|