Page 1 of 1
Help with Mouse Programming
Posted: Sat Jan 24, 2004 12:00 am
by Gandalf
hi friends,
I have completed a reasonably stable multitasking os and its memory management. I want to continue on with support for mouse. I read a few documents available about PS/2 mouse and its I/O commands and data stream format(3byte format).
But none of those documents tell how to interface with the mouse. How am I to send and receive commands from the mouse. Can I access some mouse port like (port 0x60 for Keyboard) to do that ?
And in one of the documents there is info that the 8042 keyboard controller has built-in capability to handle one more auxilary device(like PS/2 mouse) apart from the keyboard. Is that true ?
Thanking you
Gandalf
RE:Help with Mouse Programming
Posted: Sat Jan 24, 2004 12:00 am
by St8ic
A very popular problem. Here is another thread on this board that may help:
http://www.osdev.org/board.jsp?message=5207
You have to use the keyboard port for communication
(e.g. send 0x60 to 0x64 to enable mouse's interface)
of course this is just the very basics, and I can't guarentee that I'm right. When I tried to program PS/2 mouse I gave up and took out the whole GUI!
RE:Help with Mouse Programming
Posted: Sat Jan 24, 2004 12:00 am
by SystemHalted
yes I also gave up on mouse programming(for now) and trashed my GUI.
RE:Help with Mouse Programming
Posted: Sat Jan 24, 2004 12:00 am
by CodeSlasher
Programming the Ps2 mouse is easy.
You need to do two things
1st initialize the controller and mouse
2nd install a mouse handler at IRQ 12
void initialize_mouse()
{
unsigned char data;
while(test_keyboard_data()) //empty data buffer on keyboard controller
inportb(0x60);
wait_keyboard(); //wait for keyboard controller to be ready
outportb(0x64,0xa8); /*tell controller to enable AUX interface*/
wait_keyboard();
outportb(0x64,0xd4); /*tell controller to send next command to Aux device*/
wait_keyboard();
outportb(0x60,0xea); /*tell device to enable itself*/
wait_keyboard_data();
if(test_keyboard_data()) //this is for my personal debugging. I'm expecting an
printf("KEYBOARD ACK 3 [%02x]\n",inportb(0x60)); //acknowledge from keyboard
outportb(0x64,0x20); /*read command byte*/
wait_keyboard_data();
data=inportb(0x60);
data=data|0x43; //enable the int 12 bit. check docs
outportb(0x64,0x60); /*write command byte*/
wait_keyboard();
outportb(0x60,data);
wait_keyboard();
k_memset(mouse_data,0,sizeof(mouse_data)); // clear driver mouse data buffer
outportb(0x64,0xd4); /*tell controller to send next command to Aux device*/
wait_keyboard();
outportb(0x60,0xf4); /*reset mode*/
wait_keyboard_data();
if(test_keyboard_data())
printf("KEYBOARD ACK 4 [%02x]\n",inportb(0x60)); //my debugging stuff.
inportb(0x60);
while(test_keyboard_data())
inportb(0x60);
kenable_level(12); //NOW This is the most important part. It it tells the PIC
// to enables IRQ 12. That is both the Master and Slave.
return;
}
now for the IRQ 12 mouse ISR, you need to read a byte from port 60 and store it for each intterupt reported. They will be 3 that are needed to send the full mouse data i.e. mouse_data[0]=data from 1st int,mouse_data[1]=data from 2nd int and mouse_data[2]=data from 3rd int. Increment a counter during each int fired and acknowledge the int to the pic. Then when the counter is 3, you reset the counter to 0, and then interpret the 3 bytes you have stored based.
_mouse_int:
push eax
push edi
push ecx
push ebx
movzx ebx,byte [_mouse_in] ;number of bytes i've recieved so far
lea edi,[_mouse_data] ;buffer where i store mouse data bytes
in al,0x60
mov [edi+ebx],byte al ;store the byte
inc ebx ;increment counter
cmp ebx,0x03 ;check if i've collected 3 byted
jb .mouse_out_pre ;not 3 bytes yet so can't process mouse info
mov ch,byte [edi] ;last byte from mouse is multi infor byte
mov [_mouse_button],byte ch ;store mouse button info
test ch,0x40 ;check for X overflow
jz .no_x_overflow
mov [_mouse_dx],byte 0xff ;maximum x value
jmp .check_y_overflow
.mouse_out_pre:
jmp .mouse_out
.no_x_overflow:
mov cl,byte [edi+0x01] ;get change in x byte
mov [_mouse_dx],byte cl
.check_y_overflow:
test ch,0x80 ;check for Y overflow
jz .no_y_overflow
mov [_mouse_dy],byte 0xff ;sign bit set so 255 is maximum
jmp .check_x_sign
.no_y_overflow:
mov cl,byte [edi+0x02] ;get change in y byte
mov [_mouse_dy],byte cl
.check_x_sign:
test ch,0x10
jz .positive_x
movsx eax,byte [_mouse_dx]
jmp .check_y_sign
.positive_x:
movzx eax,byte [_mouse_dx]
.check_y_sign:
test ch,0x20
jz .positive_y
movsx ecx,byte [_mouse_dy]
jmp .going_out
.positive_y:
movzx ecx,byte [_mouse_dy]
.going_out:
mov ebx,0
add [_mouse_x],word ax
neg cx
add [_mouse_y],word cx
push dword [_mouse_semaphore]
call _wake
pop eax
.mouse_out:
mov [_mouse_in],byte bl
mov al,0x20
out 0xa0,al
out 0x20,al
pop ebx
pop ecx
pop edi
pop eax
iret
jmp $
Remember to install the mouse Isr at the right place. If you reprogram the pic to use 0x20 - 0x27 for the master pic and 0x28 - 0x2f for the slave pic, then IRQ 12 is on the slave pic and uses ISR 0x2C.