peredOS/drivers/mouse.c

123 lines
3.7 KiB
C
Raw Permalink 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 "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");
}
}