ZalupaCalc2/src/keyboard.c
2026-07-19 14:41:16 +03:00

121 lines
4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}
}
}