quinn-os/mouse.c
2021-11-26 19:12:50 +10:00

297 lines
5.8 KiB
C

//Mouse.inc by SANiK
//License: Use as you wish, except to cause damage
#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;
extern unsigned short width;
extern unsigned short height;
int mouse_is_dragging(int btn) {
int ret = 0;
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 init_mouse()
{
unsigned char _status; //unsigned char
last_ticks = timer_ticks;
//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);
mouse_read(); //Acknowledge
mouse_write(0xF5);
mouse_read();
mouse_sample_rate(200);
mouse_sample_rate(100);
mouse_sample_rate(80);
mouse_write(0xF2);
mouse_read();
mouse_type = mouse_read();
if (mouse_type == 3) {
mouse_sample_rate(200);
mouse_sample_rate(200);
mouse_sample_rate(80);
mouse_write(0xF2);
mouse_read();
mouse_type = mouse_read();
}
kprintf("Mouse type 0x%x\n", mouse_type);
//Enable the mouse
mouse_write(0xF4);
mouse_read(); //Acknowledge
//Setup the mouse handler
irq_install_handler(12, mouse_handler, 0);
}