summaryrefslogtreecommitdiff
path: root/kernel/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/drivers')
-rw-r--r--kernel/drivers/mouse.c101
1 files changed, 91 insertions, 10 deletions
diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c
index 0eb6df6..47133b8 100644
--- a/kernel/drivers/mouse.c
+++ b/kernel/drivers/mouse.c
@@ -5,29 +5,69 @@
#include <fs/fifo.h>
#include <fs/vfs.h>
#include <interrupts.h>
+#include <math.h>
#include <typedefs.h>
u8 mouse_cycle = 0;
u8 mouse_u8[3];
-u8 mouse_x = 0;
-u8 mouse_y = 0;
-vfs_inode_t *mouse_inode;
+int mouse_x = 0;
+int mouse_y = 0;
+
+u8 mouse_left_button = 0;
+u8 mouse_middle_button = 0;
+u8 mouse_right_button = 0;
+
+vfs_inode_t *mouse_inode = NULL;
struct mouse_event {
u8 buttons;
- u8 x;
- u8 y;
+ int x;
+ int y;
+};
+
+struct mouse_event previous_event = {
+ .buttons = 0,
+ .x = 0,
+ .y = 0,
};
int fs_mouse_has_data(vfs_inode_t *inode) {
+ if (mouse_x != previous_event.x || mouse_y != previous_event.y) {
+ return 1;
+ }
+
const struct ringbuffer *rb = inode->internal_object;
return !ringbuffer_isempty(rb);
}
int fs_mouse_read(u8 *buffer, u64 offset, u64 len, vfs_fd_t *fd) {
+ mouse_middle_button = mouse_u8[0] & (1 << 2);
+ mouse_right_button = mouse_u8[0] & (1 << 1);
+ mouse_left_button = mouse_u8[0] & (1 << 0);
+
struct ringbuffer *rb = fd->inode->internal_object;
u32 rc = ringbuffer_read(rb, buffer, len);
if (0 == rc && len > 0) {
+ if (mouse_x != previous_event.x || mouse_y != previous_event.y) {
+ int read_len = min(len, sizeof(struct mouse_event));
+
+ struct mouse_event e;
+ e.x = mouse_x;
+ e.y = mouse_y;
+ e.buttons = 0;
+ if (mouse_middle_button) {
+ e.buttons |= (1 << 2);
+ }
+ if (mouse_right_button) {
+ e.buttons |= (1 << 1);
+ }
+ if (mouse_left_button) {
+ e.buttons |= (1 << 0);
+ }
+ memcpy(buffer, &e, read_len);
+ previous_event = e;
+ return read_len;
+ }
return -EAGAIN;
}
return rc;
@@ -56,19 +96,60 @@ void int_mouse(reg_t *r) {
mouse_u8[1] = inb(0x60);
mouse_cycle++;
break;
- case 2:
+ case 2: {
mouse_u8[2] = inb(0x60);
- mouse_x = mouse_u8[1];
- mouse_y = mouse_u8[2];
+ int16_t x = mouse_u8[1];
+ int16_t y = mouse_u8[2];
+ uint8_t xs = mouse_u8[0] & (1 << 4);
+ uint8_t ys = mouse_u8[0] & (1 << 5);
+ if (xs)
+ x |= 0xFF00;
+ if (ys)
+ y |= 0xFF00;
+
+ mouse_x += x;
+ mouse_y -= y;
+
+ if (mouse_x < 0)
+ mouse_x = 0;
+ if (mouse_y < 0)
+ mouse_y = 0;
+
+ mouse_middle_button = mouse_u8[0] & (1 << 2);
+ mouse_right_button = mouse_u8[0] & (1 << 1);
+ mouse_left_button = mouse_u8[0] & (1 << 0);
+
mouse_cycle = 0;
+
+ // If there is a change in the mouse buttons that event should be written.
+ // The mouse movements will be generated upon request. This avoids
+ // filling the ringbuffer with a ton of small mouse movements.
+
+ int button_change = 0;
+ if (mouse_middle_button != (previous_event.buttons & (1 << 2))) {
+ button_change = 1;
+ } else if (mouse_right_button != (previous_event.buttons & (1 << 1))) {
+ button_change = 1;
+ } else if (mouse_left_button != (previous_event.buttons & (1 << 0))) {
+ button_change = 1;
+ }
+
+ if (!button_change) {
+ break;
+ }
+
struct mouse_event e;
e.buttons = mouse_u8[0];
e.x = mouse_x;
e.y = mouse_y;
- struct ringbuffer *rb = mouse_inode->internal_object;
- ringbuffer_write(rb, (u8 *)&e, sizeof(e));
+ previous_event = e;
+ if (mouse_inode) {
+ struct ringbuffer *rb = mouse_inode->internal_object;
+ ringbuffer_write(rb, (u8 *)&e, sizeof(e));
+ }
break;
}
+ }
EOI(0xC);
}