quinn-os/mouse.c
2022-06-29 21:47:22 +10:00

292 lines
5.7 KiB
C

// Mouse.inc by SANiK
// License: Use as you wish, except to cause damage
#include "console.h"
#include "interrupts.h"
#include "io.h"
extern volatile unsigned long timer_ticks;
unsigned char mouse_cycle = 0; // unsigned char
unsigned char mouse_byte[4]; // signed char
short mouse_x = 0; // signed char
short mouse_y = 0; // signed char
char middle_btn = 0;
char left_btn = 0;
char right_btn = 0;
unsigned char mouse_type = 0;
unsigned int left_cycles_down = 0;
unsigned int right_cycles_down = 0;
unsigned int middle_cycles_down = 0;
char middle_click = 0;
char right_click = 0;
char left_click = 0;
int mouse_pos_x = 0;
int mouse_pos_y = 0;
volatile unsigned long last_ticks = 0;
extern unsigned short width;
extern unsigned short height;
int mouse_is_dragging(int btn) {
switch (btn) {
case 0:
if (left_btn == 1 && left_cycles_down > 1) {
return 1;
}
break;
case 1:
if (right_btn == 1 && right_cycles_down > 1) {
return 1;
}
break;
case 2:
if (middle_btn == 1 && middle_cycles_down > 1) {
return 1;
}
break;
}
return 0;
}
int mouse_get_click(int btn) {
int ret = 0;
switch (btn) {
case 0:
ret = left_click;
left_click = 0;
break;
case 1:
ret = right_click;
right_click = 0;
break;
case 2:
ret = middle_click;
middle_click = 0;
break;
}
return ret;
}
// Mouse functions
void mouse_handler(struct regs *a_r) // struct regs *a_r (not used but just there)
{
short state;
short d;
switch (mouse_cycle) {
case 0:
mouse_byte[0] = inportb(0x60);
if (mouse_byte[0] & 0x08) {
mouse_cycle++;
}
break;
case 1:
mouse_byte[1] = inportb(0x60);
mouse_cycle++;
break;
case 2:
mouse_byte[2] = inportb(0x60);
if (mouse_byte[0] & 4) {
if (middle_btn == 1) {
middle_cycles_down += (timer_ticks - last_ticks);
}
middle_btn = 1;
} else if (middle_cycles_down < 100) {
if (middle_btn == 1) {
middle_click = 1;
}
middle_cycles_down = 0;
middle_btn = 0;
} else {
middle_cycles_down = 0;
middle_btn = 0;
}
if (mouse_byte[0] & 2) {
if (right_btn == 1) {
right_cycles_down += (timer_ticks - last_ticks);
}
right_btn = 1;
} else if (right_cycles_down < 100) {
if (right_btn == 1) {
right_click = 1;
}
right_cycles_down = 0;
right_btn = 0;
} else {
right_cycles_down = 0;
right_btn = 0;
}
if (mouse_byte[0] & 1) {
if (left_btn == 1) {
left_cycles_down += (timer_ticks - last_ticks);
}
left_btn = 1;
} else if (left_cycles_down < 100) {
if (left_btn == 1) {
left_click = 1;
}
left_cycles_down = 0;
left_btn = 0;
} else {
left_cycles_down = 0;
left_btn = 0;
}
state = mouse_byte[0];
d = mouse_byte[1];
mouse_x = d - ((state << 4) & 0x100);
d = mouse_byte[2];
mouse_y = d - ((state << 3) & 0x100);
mouse_pos_x += mouse_x;
if (mouse_pos_x > width) {
mouse_pos_x = width;
}
if (mouse_pos_x < 0) {
mouse_pos_x = 0;
}
mouse_pos_y += -mouse_y;
if (mouse_pos_y > height) {
mouse_pos_y = height;
}
if (mouse_pos_y < 0) {
mouse_pos_y = 0;
}
if (mouse_type == 0x03 || mouse_type == 0x04) {
mouse_cycle = 3;
} else {
mouse_cycle = 0;
}
last_ticks = timer_ticks;
break;
case 3:
mouse_byte[3] = inportb(0x60);
// kprintf("Byte0 0x%x X 0x%x Y 0x%x Z 0x%x\n", mouse_byte[0], mouse_byte[1], mouse_byte[2], mouse_byte[3]);
mouse_cycle = 0;
break;
}
}
static inline void mouse_wait(unsigned char a_type) // unsigned char
{
unsigned int _time_out = 100000; // unsigned int
if (a_type == 0) {
while (_time_out--) // Data
{
if ((inportb(0x64) & 1) == 1) {
return;
}
}
return;
} else {
while (_time_out--) // Signal
{
if ((inportb(0x64) & 2) == 0) {
return;
}
}
return;
}
}
static inline void mouse_write(unsigned char a_write) // unsigned char
{
// Wait to be able to send a command
mouse_wait(1);
// Tell the mouse we are sending a command
outportb(0x64, 0xD4);
// Wait for the final part
mouse_wait(1);
// Finally write
outportb(0x60, a_write);
}
unsigned char mouse_read() {
// Get's response from mouse
mouse_wait(0);
return inportb(0x60);
}
void mouse_sample_rate(unsigned char sample_rate) {
mouse_write(0xF3);
mouse_wait(0);
mouse_read();
mouse_write(sample_rate);
mouse_wait(0);
mouse_read();
}
void wait_for_ack() {
int timeout = 100000;
while (mouse_read() != 0xFA) {
timeout--;
if (!timeout) {
break;
}
}
}
void init_mouse() {
unsigned char _status; // unsigned char
last_ticks = 0;
// Enable the auxiliary mouse device
mouse_wait(1);
outportb(0x64, 0xA8);
// Enable the interrupts
mouse_wait(1);
outportb(0x64, 0x20);
mouse_wait(0);
_status = (inportb(0x60) | 2);
mouse_wait(1);
outportb(0x64, 0x60);
mouse_wait(1);
outportb(0x60, _status);
// Tell the mouse to use default settings
mouse_write(0xF6);
wait_for_ack();
mouse_write(0xF5);
wait_for_ack();
mouse_sample_rate(200);
mouse_sample_rate(100);
mouse_sample_rate(80);
mouse_write(0xF2);
wait_for_ack();
mouse_type = mouse_read();
if (mouse_type == 3) {
mouse_sample_rate(200);
mouse_sample_rate(200);
mouse_sample_rate(80);
mouse_write(0xF2);
wait_for_ack();
mouse_type = mouse_read();
}
kprintf("Mouse type 0x%x\n", mouse_type);
// Enable the mouse
mouse_write(0xF4);
wait_for_ack(); // Acknowledge
// Setup the mouse handler
irq_install_handler(12, mouse_handler, 0);
}