//https://wiki.osdev.org/PS/2_Mouse //TODO: ignore last packet for 4 packets mouse? #include #include "mouse.h" #include "ringbuffer.h" #include "compositor.h" #include "interrupts.h" #include "kernel/kernel.h" #include "log.h" #include "driver/vesa.h" #include "asm_x86.h" static volatile uint8_t mouse_cycle; static volatile uint8_t mouse_byte[3]; // data stream coming from the mouse will be waiting inside this buffer static ringbuffer mouse_in; // called on each interrupt (keep it small) // just pushes mouse data into the buffer uint32_t mouse_interrupt(uint32_t esp) { if(!ringbuffer_put(&mouse_in,x86_inb(0x60)))kpanic("full"); return esp; } // process data in buffer (return true if anything was processed) bool mouse_worker() { if(ringbuffer_full(&mouse_in)) { kpanic("mouse buffer full"); // heavy debugging } bool wake=false; while(ringbuffer_has(&mouse_in)){ mouse_handler(ringbuffer_get(&mouse_in)); wake=true; } return wake; } // void mouse_wait(uint8_t a_type) //unsigned char { uint32_t _time_out=100000; //unsigned int if(a_type==0) { while(_time_out--) //Data { if((x86_inb(0x64) & 1)==1) { return; } } return; } else { while(_time_out--) //Signal { if((x86_inb(0x64) & 2)==0) { return; } } return; } } static uint8_t mouse_read() { //Get's response from mouse mouse_wait(0); return x86_inb(0x60); } static void mouse_write(uint8_t a_write) { //Wait to be able to send a command mouse_wait(1); //Tell the mouse we are sending a command x86_outb(0x64, 0xD4); //Wait for the final part mouse_wait(1); //Finally write x86_outb(0x60, a_write); } void mouse_init() { mouse_in=ringbuffer_init(1);// 4096 bytes ringbuffer; uint8_t _status; //unsigned char //Enable the auxiliary mouse device mouse_wait(1); x86_outb(0x64, 0xA8); //Enable the interrupts mouse_wait(1); x86_outb(0x64, 0x20); mouse_wait(0); _status=(x86_inb(0x60) | 2); mouse_wait(1); x86_outb(0x64, 0x60); mouse_wait(1); x86_outb(0x60, _status); //Tell the mouse to use default settings mouse_write(0xF6); mouse_read(); //Acknowledge //Enable the mouse mouse_write(0xF4); mouse_read(); //Acknowledge interrupt_register(INTERRUPT_MOUSE,&mouse_interrupt); } // called every time after the 3 bytes have been filled. void mouse_action() { /* 3rd byte bits have this meaning: * * key 0 left button 1 * key 1 right button 2 * key 2 middle button 4 * key 3 always one! 8 * * key 4 x-axis sign bit 16 * key 5 y-axis sign bit 32 * * key 6 x-axis overflow 64 * key 7 y-axis overflow 128 */ int rel_x=0; int rel_y=0; /* ignore overflows? or assume max? */ if(mouse_byte[0]&0x80) { return; // klog("x overflow"); } if(mouse_byte[0]&0x40) { return; // klog("y overflow"); } rel_x = mouse_byte[1] - ((mouse_byte[0] << 4) & 0x100); rel_y = mouse_byte[2] - ((mouse_byte[0] << 3) & 0x100); // we pass the state through compositor_mouse_handle(rel_x,-rel_y,mouse_byte[0]); } void mouse_handler(uint8_t byte)//struct regs *a_r) //struct regs *a_r (not used but just there) { // X86_IRQ_BEGIN switch(mouse_cycle) { case 0: mouse_byte[0]=byte; mouse_cycle++; // this bit is ALWAYS one, otherwise we are out of sync! if(!(mouse_byte[0]&0x8)) { // klog("mouse out of sync (try next packet) ..."); mouse_cycle--; } break; case 1: mouse_byte[1]=byte; mouse_cycle++; break; case 2: mouse_byte[2]=byte; mouse_cycle=0; mouse_action(); break; } // X86_IRQ_END }