#include "mouse.h" #include "../kernel/io.h" #include "../kernel/string.h" #include "../drivers/serial.h" // Для kprint_serial #define PS2_DATA 0x60 #define PS2_STATUS 0x64 #define PS2_COMMAND 0x64 static void ps2_wait_write(void) { while (inb(PS2_STATUS) & 0x02); } static void ps2_wait_read(void) { while (!(inb(PS2_STATUS) & 0x01)); } static void mouse_write(uint8_t data) { ps2_wait_write(); outb(PS2_COMMAND, 0xD4); // Сигнал: шлем команду именно мыши ps2_wait_write(); outb(PS2_DATA, data); } static uint8_t mouse_read(void) { ps2_wait_read(); return inb(PS2_DATA); } void mouse_init(void) { uint8_t status; kprint_serial("Initializing PS/2 Mouse...\n"); // Включаем второй порт PS/2 (мышь) ps2_wait_write(); outb(PS2_COMMAND, 0xA8); io_wait(); // Читаем Command Byte, чтобы включить прерывания ps2_wait_write(); outb(PS2_COMMAND, 0x20); ps2_wait_read(); status = inb(PS2_DATA) | 2; // Бит 1 — прерывания IRQ12 от мыши status &= ~0x20; // Сбрасываем Бит 5 — активируем Mouse Clock // Записываем Command Byte обратно ps2_wait_write(); outb(PS2_COMMAND, 0x60); ps2_wait_write(); outb(PS2_DATA, status); // Настраиваем саму мышь mouse_write(0xF6); // Загрузить дефолтные параметры mouse_read(); // Читаем ACK (0xFA) mouse_write(0xF4); // Включаем передачу пакетов (Data Reporting) mouse_read(); // Читаем ACK (0xFA) kprint_serial("Mouse initialized successfully.\n"); } static uint8_t mouse_cycle = 0; static uint8_t mouse_packet[3]; static int mouse_x = 40; // Стартуем по центру текстового экрана 80x25 static int mouse_y = 12; void mouse_handler(void) { uint8_t status = inb(PS2_STATUS); // Проверяем, что в буфере реально есть данные и они от мыши (бит 5 выставлен) if (!(status & 0x01) || !(status & 0x20)) { return; } mouse_packet[mouse_cycle++] = inb(PS2_DATA); if (mouse_cycle == 3) { mouse_cycle = 0; // Бит 3 первого байта всегда должен быть равен 1 (проверка синхронизации) if (!(mouse_packet[0] & 0x08)) { return; } uint8_t flags = mouse_packet[0]; int offset_x = (int)mouse_packet[1]; int offset_y = (int)mouse_packet[2]; // Обработка знаков смещения (8 бит -> 32 бита с сохранением знака) if (flags & 0x10) offset_x |= 0xFFFFFF00; if (flags & 0x20) offset_y |= 0xFFFFFF00; mouse_x += offset_x; mouse_y -= offset_y; // Инвертируем Y, так как в VGA координатах 0 верх // Ограничиваем рамками консоли 80x25 if (mouse_x < 0) mouse_x = 0; if (mouse_x >= 80) mouse_x = 79; if (mouse_y < 0) mouse_y = 0; if (mouse_y >= 25) mouse_y = 24; // Чек кнопок int left_click = flags & 0x01; int right_click = flags & 0x02; // Выводим инфу в UART через itoa char buf[16]; kprint_serial("Mouse: X="); itoa(mouse_x, buf, 10); kprint_serial(buf); kprint_serial(" Y="); itoa(mouse_y, buf, 10); kprint_serial(buf); if (left_click) kprint_serial(" [LEFT]"); if (right_click) kprint_serial(" [RIGHT]"); kprint_serial("\n"); } }