mouse interrupts working
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
kernel/lib/userinput/mouse.o
Normal file
BIN
kernel/lib/userinput/mouse.o
Normal file
Binary file not shown.
@@ -3,22 +3,22 @@
|
||||
#include "../IO.h"
|
||||
#include "../userinput/keyboard.h"
|
||||
|
||||
__attribute__((interrupt)) void PageFault_Handler(struct interrupt_frame* frame) {
|
||||
__attribute__((interrupt)) void PageFault_Handler(interrupt_frame* frame) {
|
||||
Panic("Page Fault");
|
||||
while (true);
|
||||
}
|
||||
|
||||
__attribute__((interrupt)) void DoubleFault_Handler(struct interrupt_frame* frame) {
|
||||
__attribute__((interrupt)) void DoubleFault_Handler(interrupt_frame* frame) {
|
||||
Panic("Double Fault");
|
||||
while (true);
|
||||
}
|
||||
|
||||
__attribute__((interrupt)) void GPFault_Handler(struct interrupt_frame* frame) {
|
||||
__attribute__((interrupt)) void GPFault_Handler(interrupt_frame* frame) {
|
||||
Panic("General Protection Fault");
|
||||
while (true);
|
||||
}
|
||||
|
||||
__attribute__((interrupt)) void KeyboardInterrupt_Handler(struct interrupt_frame* frame) {
|
||||
__attribute__((interrupt)) void KeyboardInterrupt_Handler(interrupt_frame* frame) {
|
||||
uint8_t scancode = inb(0x60);
|
||||
|
||||
HandleKeyboard(scancode);
|
||||
@@ -26,6 +26,14 @@ __attribute__((interrupt)) void KeyboardInterrupt_Handler(struct interrupt_frame
|
||||
PIC_EndMaster();
|
||||
}
|
||||
|
||||
__attribute__((interrupt)) void MouseInterrupt_Handler(interrupt_frame* frame) {
|
||||
uint8_t mouseData = inb(0x60);
|
||||
|
||||
HandlePS2Mouse(mouseData);
|
||||
|
||||
PIC_EndSlave();
|
||||
}
|
||||
|
||||
void PIC_EndMaster() {
|
||||
outb(PIC1_COMMAND, PIC_EOI);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "../BasicRenderer.h"
|
||||
#include "../userinput/mouse.h"
|
||||
|
||||
#define PIC1_COMMAND 0x20
|
||||
#define PIC1_DATA 0x21
|
||||
@@ -12,11 +13,12 @@
|
||||
#define ICW4_8086 0x01
|
||||
|
||||
struct interrupt_frame;
|
||||
__attribute__((interrupt)) void PageFault_Handler(struct interrupt_frame* frame);
|
||||
__attribute__((interrupt)) void DoubleFault_Handler(struct interrupt_frame* frame);
|
||||
__attribute__((interrupt)) void GPFault_Handler(struct interrupt_frame* frame);
|
||||
__attribute__((interrupt)) void PageFault_Handler(interrupt_frame* frame);
|
||||
__attribute__((interrupt)) void DoubleFault_Handler(interrupt_frame* frame);
|
||||
__attribute__((interrupt)) void GPFault_Handler(interrupt_frame* frame);
|
||||
|
||||
__attribute__((interrupt)) void KeyboardInterrupt_Handler(struct interrupt_frame* frame);
|
||||
__attribute__((interrupt)) void KeyboardInterrupt_Handler(interrupt_frame* frame);
|
||||
__attribute__((interrupt)) void MouseInterrupt_Handler(interrupt_frame* frame);
|
||||
|
||||
void RemapPIC();
|
||||
void PIC_EndMaster();
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
extern "C" void _start(BootInfo* bootInfo) {
|
||||
KernelInfo kernelInfo = InitializeKernel(bootInfo);
|
||||
PageTableManager* pageTableManager = kernelInfo.pageTableManager;
|
||||
|
||||
GlobalRenderer->ClearColour = 0xFF191919;
|
||||
GlobalRenderer->Clear();
|
||||
GlobalRenderer->Print("Kernel initialized successfully!");
|
||||
GlobalRenderer->Next();
|
||||
|
||||
while (true) {
|
||||
ProcessMousePacket();
|
||||
}
|
||||
|
||||
// make sure we never return from our OS
|
||||
while (true);
|
||||
}
|
||||
@@ -45,40 +45,31 @@ void PrepareMemory(BootInfo* bootInfo){
|
||||
}
|
||||
|
||||
IDTR idtr;
|
||||
|
||||
void SetIDTGate(void* handler, uint8_t entryOffset, uint8_t type_attr, uint8_t selector) {
|
||||
IDTDescEntry* interrupt = (IDTDescEntry*)(idtr.Offset + entryOffset * sizeof(IDTDescEntry));
|
||||
interrupt->SetOffset((uint64_t)handler);
|
||||
interrupt->type_attr = type_attr;
|
||||
interrupt->selector = selector;
|
||||
}
|
||||
|
||||
void PrepareInterrupts() {
|
||||
idtr.Limit = 0x0FFF;
|
||||
idtr.Offset = (uint64_t)GlobalAllocator.RequestPage();
|
||||
memset((void*)idtr.Offset, 0, 0x1000);
|
||||
|
||||
IDTDescEntry* int_PageFault = (IDTDescEntry*)(idtr.Offset + 0xE * sizeof(IDTDescEntry));
|
||||
int_PageFault->SetOffset((uint64_t)PageFault_Handler);
|
||||
int_PageFault->type_attr = IDT_TA_InterruptGate;
|
||||
int_PageFault->selector = 0x08; // kernel code segment
|
||||
|
||||
IDTDescEntry* int_DoubleFault = (IDTDescEntry*)(idtr.Offset + 0x8 * sizeof(IDTDescEntry));
|
||||
int_DoubleFault->SetOffset((uint64_t)DoubleFault_Handler);
|
||||
int_DoubleFault->type_attr = IDT_TA_InterruptGate;
|
||||
int_DoubleFault->selector = 0x08; // kernel code segment
|
||||
|
||||
IDTDescEntry* int_GPFault = (IDTDescEntry*)(idtr.Offset + 0xD * sizeof(IDTDescEntry));
|
||||
int_GPFault->SetOffset((uint64_t)GPFault_Handler);
|
||||
int_GPFault->type_attr = IDT_TA_InterruptGate;
|
||||
int_GPFault->selector = 0x08; // kernel code segment
|
||||
|
||||
IDTDescEntry* int_Keyboard = (IDTDescEntry*)(idtr.Offset + 0x21 * sizeof(IDTDescEntry));
|
||||
int_Keyboard->SetOffset((uint64_t)KeyboardInterrupt_Handler);
|
||||
int_Keyboard->type_attr = IDT_TA_InterruptGate;
|
||||
int_Keyboard->selector = 0x08; // kernel code segment
|
||||
|
||||
SetIDTGate((void*)PageFault_Handler, 0xE, IDT_TA_InterruptGate, 0x08);
|
||||
SetIDTGate((void*)DoubleFault_Handler, 0x8, IDT_TA_InterruptGate, 0x08);
|
||||
SetIDTGate((void*)GPFault_Handler, 0xD, IDT_TA_InterruptGate, 0x08);
|
||||
SetIDTGate((void*)KeyboardInterrupt_Handler, 0x21, IDT_TA_InterruptGate, 0x08);
|
||||
SetIDTGate((void*)MouseInterrupt_Handler, 0x2C, IDT_TA_InterruptGate, 0x08);
|
||||
|
||||
// load idt
|
||||
asm("lidt %0" : : "m" (idtr));
|
||||
|
||||
// remap pic so we can get hardware interrupts
|
||||
RemapPIC();
|
||||
outb(PIC1_DATA, 0b11111101); // unmask 2nd interrupt
|
||||
outb(PIC2_DATA, 0b11111111);
|
||||
|
||||
asm ("sti");
|
||||
}
|
||||
|
||||
BasicRenderer r = BasicRenderer(NULL, NULL);
|
||||
@@ -86,16 +77,42 @@ KernelInfo InitializeKernel(BootInfo* bootInfo){
|
||||
r = BasicRenderer(bootInfo->framebuffer, bootInfo->psf1_Font);
|
||||
GlobalRenderer = &r;
|
||||
|
||||
GlobalRenderer->ClearColour = 0xFF191919;
|
||||
GlobalRenderer->Clear();
|
||||
|
||||
GlobalRenderer->Print("Setting up GDT...");
|
||||
GlobalRenderer->Next();
|
||||
|
||||
GDTDescriptor gdtDescriptor;
|
||||
gdtDescriptor.Size = sizeof(GDT) - 1;
|
||||
gdtDescriptor.Offset = (uint64_t)&DefaultGDT;
|
||||
LoadGDT(&gdtDescriptor);
|
||||
|
||||
GlobalRenderer->Print("Preparing memory... (this doesn't always work, you may need to restart. sorry.)");
|
||||
GlobalRenderer->Next();
|
||||
|
||||
PrepareMemory(bootInfo);
|
||||
|
||||
memset(bootInfo->framebuffer->BaseAddress, 0, bootInfo->framebuffer->BufferSize);
|
||||
//memset(bootInfo->framebuffer->BaseAddress, 0, bootInfo->framebuffer->BufferSize);
|
||||
|
||||
GlobalRenderer->Print("Setting up interrupts...");
|
||||
GlobalRenderer->Next();
|
||||
|
||||
PrepareInterrupts();
|
||||
|
||||
GlobalRenderer->Print("Setting up mouse...");
|
||||
GlobalRenderer->Next();
|
||||
InitPS2Mouse();
|
||||
|
||||
outb(PIC1_DATA, 0b11111001); // unmask 2nd interrupt
|
||||
outb(PIC2_DATA, 0b11101111);
|
||||
|
||||
asm ("sti"); // enable interrupts
|
||||
|
||||
GlobalRenderer->Print("Init complete!");
|
||||
GlobalRenderer->Next();
|
||||
|
||||
|
||||
|
||||
return kernelInfo;
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "paging/PageMapIndexer.h"
|
||||
#include "paging/paging.h"
|
||||
#include "paging/PageTableManager.h"
|
||||
#include "userinput/mouse.h"
|
||||
|
||||
struct BootInfo {
|
||||
Framebuffer* framebuffer;
|
||||
|
||||
141
kernel/src/userinput/mouse.cpp
Normal file
141
kernel/src/userinput/mouse.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
#include "mouse.h"
|
||||
#include "../IO.h"
|
||||
|
||||
void MouseWait() {
|
||||
uint64_t timeout = 100000;
|
||||
while (timeout--) {
|
||||
if (inb(0x64) & 0b10 == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MouseWaitInput() {
|
||||
uint64_t timeout = 100000;
|
||||
while (timeout--) {
|
||||
if (inb(0x64) & 0b1)
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MouseWrite(uint8_t value) {
|
||||
MouseWait();
|
||||
outb(0x64, 0xD4);
|
||||
MouseWait();
|
||||
outb(0x60, value);
|
||||
}
|
||||
|
||||
uint8_t MouseRead() {
|
||||
MouseWaitInput();
|
||||
return inb(0x60);
|
||||
}
|
||||
|
||||
uint8_t mouseCycle = 0;
|
||||
uint8_t mousePacket[4];
|
||||
bool mousePacketReady = false;
|
||||
|
||||
Point mousePosition;
|
||||
|
||||
void HandlePS2Mouse(uint8_t data) {
|
||||
switch (mouseCycle) {
|
||||
case 0:
|
||||
if (mousePacketReady) break;
|
||||
|
||||
if (data & 0b00001000 == 0) break;
|
||||
|
||||
mousePacket[0] = data;
|
||||
mouseCycle++;
|
||||
break;
|
||||
case 1:
|
||||
if (mousePacketReady) break;
|
||||
mousePacket[1] = data;
|
||||
mouseCycle++;
|
||||
break;
|
||||
case 2:
|
||||
if (mousePacketReady) break;
|
||||
mousePacket[2] = data;
|
||||
mousePacketReady = true;
|
||||
mouseCycle = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessMousePacket() {
|
||||
if (!mousePacketReady) return;
|
||||
mousePacketReady = false;
|
||||
|
||||
bool xNegative, yNegative, xOverflow, yOverflow;
|
||||
|
||||
if (mousePacket[0] & PS2XSign) {
|
||||
xNegative = true;
|
||||
} else xNegative = false;
|
||||
|
||||
if (mousePacket[0] & PS2YSign) {
|
||||
yNegative = true;
|
||||
} else yNegative = false;
|
||||
|
||||
if (mousePacket[0] & PS2XOverflow) {
|
||||
xOverflow = true;
|
||||
} else xOverflow = false;
|
||||
|
||||
if (mousePacket[0] & PS2YOverflow) {
|
||||
yOverflow = true;
|
||||
} else yOverflow = false;
|
||||
|
||||
if (!xNegative) {
|
||||
mousePosition.x += mousePacket[1];
|
||||
if (xOverflow) {
|
||||
mousePosition.x += 255;
|
||||
}
|
||||
} else {
|
||||
mousePacket[1] = 256 - mousePacket[1];
|
||||
mousePosition.x -= mousePacket[1];
|
||||
if (xOverflow) {
|
||||
mousePosition.x -= 255;
|
||||
}
|
||||
}
|
||||
|
||||
if (!yNegative) {
|
||||
mousePosition.y -= mousePacket[2];
|
||||
if (yOverflow) {
|
||||
mousePosition.y -= 255;
|
||||
}
|
||||
} else {
|
||||
mousePacket[2] = 256 - mousePacket[2];
|
||||
mousePosition.y += mousePacket[2];
|
||||
if (yOverflow) {
|
||||
mousePosition.y += 255;
|
||||
}
|
||||
}
|
||||
|
||||
if (mousePosition.x < 0) mousePosition.x = 0;
|
||||
if (mousePosition.x > GlobalRenderer->targetFramebuffer->Width-1) mousePosition.x = GlobalRenderer->targetFramebuffer->Width;
|
||||
if (mousePosition.y < 0) mousePosition.y = 0;
|
||||
if (mousePosition.y > GlobalRenderer->targetFramebuffer->Height-1) mousePosition.y = GlobalRenderer->targetFramebuffer->Height;
|
||||
}
|
||||
|
||||
void InitPS2Mouse() {
|
||||
|
||||
// enable aux device mouse
|
||||
outb(0x64, 0xA8);
|
||||
MouseWait();
|
||||
|
||||
outb(0x64, 0x20); // tells the keyboard controller we want to send a command to the mouse
|
||||
MouseWaitInput();
|
||||
|
||||
uint8_t status = inb(0x60);
|
||||
status |= 0b10;
|
||||
MouseWait();
|
||||
|
||||
outb(0x64, 0x60);
|
||||
MouseWait();
|
||||
|
||||
outb(0x60, status); // setting the correct bit in the "compaq" status byte
|
||||
|
||||
MouseWrite(0xF6); // default settings
|
||||
MouseRead();
|
||||
|
||||
MouseWrite(0xF4);
|
||||
MouseRead();
|
||||
}
|
||||
19
kernel/src/userinput/mouse.h
Normal file
19
kernel/src/userinput/mouse.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "../math.h"
|
||||
#include "../BasicRenderer.h"
|
||||
|
||||
#define PS2LeftButton 0b00000001
|
||||
#define PS2MiddleButton 0b00000010
|
||||
#define PS2RightButton 0b00000100
|
||||
|
||||
#define PS2XSign 0b00010000
|
||||
#define PS2YSign 0b00100000
|
||||
#define PS2XOverflow 0b01000000
|
||||
#define PS2YOverflow 0b10000000
|
||||
|
||||
extern Point mousePosition;
|
||||
|
||||
void InitPS2Mouse();
|
||||
void HandlePS2Mouse(uint8_t data);
|
||||
void ProcessMousePacket();
|
||||
Reference in New Issue
Block a user