MOUSE: добавлена поддержка (в UART)
This commit is contained in:
parent
ef565c6afb
commit
a66b0416d5
7 changed files with 150 additions and 4 deletions
3
Makefile
3
Makefile
|
|
@ -25,7 +25,8 @@ OBJ = boot/boot.o \
|
|||
drivers/vga.o \
|
||||
drivers/speaker.o \
|
||||
drivers/timer.o \
|
||||
drivers/keyboard.o
|
||||
drivers/keyboard.o \
|
||||
drivers/mouse.o
|
||||
|
||||
# Дефолтное правило (просто сборка бинарника)
|
||||
all: $(TARGET)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
- [x] Нормальный драйвер VGA (скролл итд)
|
||||
- [x] Нормальный драйвер клавиатуры (Caps Lock, Shift, Numpad итд)
|
||||
- [x] Драйвер PC Speaker
|
||||
- [ ] Драйвер мыши
|
||||
- [x] Драйвер мыши
|
||||
|
||||
## 2. Процессы, память, user mode, еще драйвера
|
||||
|
||||
|
|
|
|||
123
drivers/mouse.c
Normal file
123
drivers/mouse.c
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
#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");
|
||||
}
|
||||
}
|
||||
9
drivers/mouse.h
Normal file
9
drivers/mouse.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef MOUSE_H
|
||||
#define MOUSE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void mouse_init(void);
|
||||
void mouse_handler(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#include "../drivers/serial.h"
|
||||
#include "../drivers/timer.h"
|
||||
#include "../drivers/keyboard.h"
|
||||
#include "../drivers/mouse.h"
|
||||
|
||||
// Сам массив IDT на 256 векторов и указатель на него
|
||||
struct idt_entry idt[256];
|
||||
|
|
@ -17,7 +18,7 @@ extern void isr16(); extern void isr17(); extern void isr18(); extern void isr19
|
|||
extern void isr20(); extern void isr21();
|
||||
|
||||
// Аппаратные прерывания железа (IRQ)
|
||||
extern void irq0(); extern void irq1();
|
||||
extern void irq0(); extern void irq1(); extern void irq12();
|
||||
|
||||
// Внешняя функция на ассемблере для выполнения 'lidt'
|
||||
extern void idt_load();
|
||||
|
|
@ -61,6 +62,7 @@ void idt_init(void) {
|
|||
// Вешаем аппаратные прерывания (после перемапливания PIC они будут тут)
|
||||
idt_set_gate(32, (uint32_t)irq0, 0x08, 0x8E); // Таймер PIT
|
||||
idt_set_gate(33, (uint32_t)irq1, 0x08, 0x8E); // Клавиатура
|
||||
idt_set_gate(44, (uint32_t)irq12, 0x08, 0x8E); // Мышь PS/2
|
||||
|
||||
// Загружаем IDTR в процессор
|
||||
idt_load();
|
||||
|
|
@ -79,6 +81,8 @@ void irq_handler(struct registers regs) {
|
|||
timer_handler();
|
||||
} else if (regs.int_no == 33) {
|
||||
keyboard_handler(); // <-- Вызываем обработчик клавиатуры при векторе 33
|
||||
} else if (regs.int_no == 44) {
|
||||
mouse_handler(); // <-- Вызываем обработчик клавиатуры при векторе 33
|
||||
} else {
|
||||
char irq_str[4];
|
||||
itoa(regs.int_no, irq_str, 10);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ bits 32
|
|||
global idt_load
|
||||
global isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7, isr8, isr9, isr10
|
||||
global isr11, isr12, isr13, isr14, isr15, isr16, isr17, isr18, isr19, isr20, isr21
|
||||
global irq0, irq1
|
||||
global irq0, irq1, irq12
|
||||
|
||||
; Импортируем Си-обработчики
|
||||
extern idtp
|
||||
|
|
@ -66,6 +66,7 @@ ISR_ERRCODE 21
|
|||
|
||||
IRQ 32, 0 ; IRQ0 - Таймер
|
||||
IRQ 33, 1 ; IRQ1 - Клавиатура
|
||||
IRQ 44, 12 ; IRQ12 - Мышь (вектор 44)
|
||||
|
||||
; Перенаправляем глобальные имена на сгенерированные макросами точки
|
||||
isr0: jmp idt_stub_isr_0
|
||||
|
|
@ -93,6 +94,7 @@ isr21: jmp idt_stub_isr_21
|
|||
|
||||
irq0: jmp idt_stub_irq_0
|
||||
irq1: jmp idt_stub_irq_1
|
||||
irq12: jmp idt_stub_irq_12 ; <-- Сюда процессор прыгнет при векторе 44
|
||||
|
||||
; Общая точка сборки для Исключений Процессора
|
||||
isr_common_stub:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "../drivers/vga.h"
|
||||
#include "../drivers/serial.h"
|
||||
#include "../drivers/mouse.h"
|
||||
#include "../drivers/timer.h"
|
||||
#include "../drivers/speaker.h"
|
||||
#include "gdt.h"
|
||||
|
|
@ -24,8 +25,14 @@ void kernel_main(void) {
|
|||
pic_clear_mask(0);
|
||||
log_info(LOG_NORMAL, "Unmasking IRQ 1... (keyboard)");
|
||||
pic_clear_mask(1);
|
||||
log_info(LOG_NORMAL, "Unmasking IRQ 2... (slave pic)");
|
||||
pic_clear_mask(2);
|
||||
log_info(LOG_NORMAL, "Unmasking IRQ 12... (mouse)");
|
||||
pic_clear_mask(12);
|
||||
log_info(LOG_NORMAL, "Registering timer at 100Hz");
|
||||
timer_init(100);
|
||||
log_info(LOG_NORMAL, "Registering mouse");
|
||||
mouse_init();
|
||||
log_info(LOG_NORMAL, "Enabling IRQ...");
|
||||
__asm__ __volatile__("sti");
|
||||
vga_set_color(VGA_COLOR_LIGHT_GREEN, VGA_COLOR_BLACK);
|
||||
|
|
|
|||
Loading…
Reference in a new issue