Mouse improvements (stability, scaling)

This commit is contained in:
Kevin Lange 2012-02-04 22:29:46 -06:00
parent 1110a119c5
commit 6590b285b5
8 changed files with 115 additions and 58 deletions

View File

@ -95,17 +95,22 @@ irq_install() {
bfinish(0);
}
void irq_ack(int irq_no) {
if (irq_no >= 12) {
outportb(0xA0, 0x20);
}
outportb(0x20, 0x20);
}
void
irq_handler(struct regs *r) {
IRQ_OFF;
void (*handler)(struct regs *r);
handler = irq_routines[r->int_no - 32];
if (r->int_no >= 40) {
outportb(0xA0, 0x20);
}
outportb(0x20, 0x20);
if (handler) {
handler(r);
} else {
irq_ack(r->int_no - 32);
}
IRQ_RES;
}

View File

@ -26,6 +26,7 @@
#define KEY_PENDING 0x64
#define KEYBOARD_NOTICES 0
#define KEYBOARD_IRQ 1
/* A bit-map to store the keyboard states */
struct keyboard_states {
@ -246,6 +247,7 @@ keyboard_handler(
unsigned char scancode;
keyboard_wait();
scancode = inportb(KEY_DEVICE);
irq_ack(KEYBOARD_IRQ);
if (keyboard_direct_handler) {
keyboard_direct_handler(scancode);
return;
@ -256,6 +258,7 @@ keyboard_handler(
if (handler) {
handler(scancode);
}
}
/*
@ -276,7 +279,7 @@ keyboard_install() {
current_process->fds.entries[0] = keyboard_pipe;
/* Install the interrupt handler */
irq_install_handler(1, keyboard_handler);
irq_install_handler(KEYBOARD_IRQ, keyboard_handler);
bfinish(0);
}

View File

@ -12,93 +12,121 @@ int8_t mouse_byte[3];
#define PACKETS_IN_PIPE 64
#define DISCARD_POINT 32
#define MOUSE_IRQ 12
#define MOUSE_PORT 0x60
#define MOUSE_STATUS 0x64
#define MOUSE_ABIT 0x02
#define MOUSE_BBIT 0x01
#define MOUSE_WRITE 0xD4
#define MOUSE_F_BIT 0x20
fs_node_t * mouse_pipe;
void mouse_handler(struct regs *r) {
switch (mouse_cycle) {
case 0:
mouse_byte[0] = inportb(0x60);
++mouse_cycle;
break;
case 1:
mouse_byte[1] = inportb(0x60);
++mouse_cycle;
break;
case 2:
mouse_byte[2] = inportb(0x60);
mouse_device_packet_t packet;
packet.magic = MOUSE_MAGIC;
packet.x_difference = mouse_byte[1];
packet.y_difference = mouse_byte[2];
packet.buttons = 0;
if (mouse_byte[0] & 0x01) {
packet.buttons |= LEFT_CLICK;
}
if (mouse_byte[0] & 0x02) {
packet.buttons |= RIGHT_CLICK;
}
mouse_cycle = 0;
mouse_device_packet_t bitbucket;
while (pipe_size(mouse_pipe) > (DISCARD_POINT * sizeof(packet))) {
read_fs(mouse_pipe, 0, sizeof(packet), (uint8_t *)&bitbucket);
}
write_fs(mouse_pipe, 0, sizeof(packet), (uint8_t *)&packet);
break;
}
}
void mouse_wait(uint8_t a_type) {
uint32_t timeout = 100000;
if (!a_type) {
while (--timeout) {
if ((inportb(0x64) & 0x01) == 1) {
if ((inportb(MOUSE_STATUS) & MOUSE_BBIT) == 1) {
return;
}
}
kprintf("[mouse] timeout\n");
return;
} else {
while (--timeout) {
if (!((inportb(0x64) & 0x02))) {
if (!((inportb(MOUSE_STATUS) & MOUSE_ABIT))) {
return;
}
}
kprintf("[mouse] timeout\n");
return;
}
}
void mouse_write(uint8_t write) {
mouse_wait(1);
outportb(0x64, 0xD4);
outportb(MOUSE_STATUS, MOUSE_WRITE);
mouse_wait(1);
outportb(0x60, write);
outportb(MOUSE_PORT, write);
}
uint8_t mouse_read() {
mouse_wait(0);
char t = inportb(0x60);
char t = inportb(MOUSE_PORT);
return t;
}
void mouse_handler(struct regs *r) {
uint8_t status = inportb(MOUSE_STATUS);
while (status & MOUSE_BBIT) {
int8_t mouse_in = inportb(MOUSE_PORT);
if (status & MOUSE_F_BIT) {
switch (mouse_cycle) {
case 0:
mouse_byte[0] = mouse_in;
++mouse_cycle;
break;
case 1:
mouse_byte[1] = mouse_in;
++mouse_cycle;
break;
case 2:
mouse_byte[2] = mouse_in;
/* We now have a full mouse packet ready to use */
if (mouse_byte[0] & 0x80 || mouse_byte[0] & 0x40) {
/* x/y overflow? bad packet! */
break;
}
mouse_device_packet_t packet;
packet.magic = MOUSE_MAGIC;
packet.x_difference = mouse_byte[1];
packet.y_difference = mouse_byte[2];
packet.buttons = 0;
if (mouse_byte[0] & 0x01) {
packet.buttons |= LEFT_CLICK;
}
if (mouse_byte[0] & 0x02) {
packet.buttons |= RIGHT_CLICK;
}
if (mouse_byte[0] & 0x04) {
packet.buttons |= MIDDLE_CLICK;
}
mouse_cycle = 0;
mouse_device_packet_t bitbucket;
while (pipe_size(mouse_pipe) > (DISCARD_POINT * sizeof(packet))) {
read_fs(mouse_pipe, 0, sizeof(packet), (uint8_t *)&bitbucket);
}
write_fs(mouse_pipe, 0, sizeof(packet), (uint8_t *)&packet);
break;
}
}
status = inportb(MOUSE_STATUS);
}
irq_ack(MOUSE_IRQ);
}
void mouse_install() {
LOG(INFO, "Initializing mouse cursor driver");
uint8_t status;
IRQ_OFF;
mouse_pipe = make_pipe(sizeof(mouse_device_packet_t) * PACKETS_IN_PIPE);
mouse_wait(1);
outportb(0x64,0xA8);
outportb(MOUSE_STATUS, 0xA8);
mouse_wait(1);
outportb(0x64,0x20);
outportb(MOUSE_STATUS, 0x20);
mouse_wait(0);
status = inportb(0x60) | 2;
mouse_wait(1);
outportb(0x64, 0x60);
outportb(MOUSE_STATUS, 0x60);
mouse_wait(1);
outportb(0x60, status);
outportb(MOUSE_PORT, status);
mouse_write(0xF6);
mouse_read();
mouse_write(0xF4);
mouse_read();
IRQ_RES;
irq_install_handler(12, mouse_handler);
irq_install_handler(MOUSE_IRQ, mouse_handler);
}

View File

@ -10,11 +10,14 @@
#define SERIAL_PORT_C 0x3E8
#define SERIAL_PORT_D 0x2E8
#define SERIAL_IRQ 4
void
serial_handler(
struct regs *r
) {
char serial = serial_recv();
irq_ack(SERIAL_IRQ);
/*
* Fix the serial input assuming it is ascii
*/
@ -45,7 +48,7 @@ serial_install() {
outportb(SERIAL_PORT_A + 3, 0x03);
outportb(SERIAL_PORT_A + 2, 0xC7);
outportb(SERIAL_PORT_A + 4, 0x0B);
irq_install_handler(4, serial_handler); /* Install the serial input handler */
irq_install_handler(SERIAL_IRQ, serial_handler); /* Install the serial input handler */
outportb(SERIAL_PORT_A + 1, 0x01); /* Enable interrupts on receive */
bfinish(0);
}

View File

@ -14,6 +14,8 @@
#define PIT_SCALE 1193180
#define PIT_SET 0x36
#define TIMER_IRQ 0
/*
* Set the phase (in hertz) for the Programmable
* Interrupt Timer (PIT).
@ -42,6 +44,7 @@ timer_handler(
struct regs *r
) {
++timer_ticks;
irq_ack(TIMER_IRQ);
switch_task(1);
}
@ -51,7 +54,7 @@ timer_handler(
void timer_install() {
blog("Installing Programmable Interval Timer...");
LOG(INFO,"Initializing interval timer");
irq_install_handler(0, timer_handler);
irq_install_handler(TIMER_IRQ, timer_handler);
timer_phase(100); /* 100Hz */
bfinish(0);
}

View File

@ -124,6 +124,7 @@ extern void irq_install();
extern void irq_install_handler(int irq, irq_handler_t);
extern void irq_uninstall_handler(int irq);
extern void irq_gates();
extern void irq_ack();
/* Timer */
extern void timer_install();

View File

@ -37,7 +37,7 @@ void start_terminal() {
if (!pid) {
#endif
char * tokens[] = {
"/bin/compositor",
"/bin/terminal",
NULL
};
int i = execve(tokens[0], tokens, NULL);

View File

@ -19,6 +19,8 @@
#define FONT_SIZE 13
#define MOUSE_SCALE 6
static unsigned int timer_tick = 0;
#define TIMER_TICK 400000
@ -2995,14 +2997,26 @@ int main(int argc, char ** argv) {
int r = read(mfd, buf, 1);
goto fail_mouse;
}
cell_redraw((mouse_x * term_width) / graphics_width, (mouse_y * term_height) / graphics_height);
mouse_x += packet->x_difference;
mouse_y -= packet->y_difference;
cell_redraw(((mouse_x / MOUSE_SCALE) * term_width) / graphics_width, ((mouse_y / MOUSE_SCALE) * term_height) / graphics_height);
/* Apply mouse movement */
int c, l;
c = abs(packet->x_difference);
l = 0;
while (c >>= 1) {
l++;
}
mouse_x += packet->x_difference * l;
c = abs(packet->y_difference);
l = 0;
while (c >>= 1) {
l++;
}
mouse_y -= packet->y_difference * l;
if (mouse_x < 0) mouse_x = 0;
if (mouse_y < 0) mouse_y = 0;
if (mouse_x >= graphics_width) mouse_x = graphics_width - char_width;
if (mouse_y >= graphics_height) mouse_y = graphics_height - char_height;
cell_redraw_inverted((mouse_x * term_width) / graphics_width, (mouse_y * term_height) / graphics_height);
if (mouse_x >= graphics_width * MOUSE_SCALE) mouse_x = (graphics_width - char_width) * MOUSE_SCALE;
if (mouse_y >= graphics_height * MOUSE_SCALE) mouse_y = (graphics_height - char_height) * MOUSE_SCALE;
cell_redraw_inverted(((mouse_x / MOUSE_SCALE) * term_width) / graphics_width, ((mouse_y / MOUSE_SCALE) * term_height) / graphics_height);
fstat(mfd, &_stat);
}
fail_mouse: