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
Help with Mouse Programming
RE:Help with Mouse Programming
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!
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
yes I also gave up on mouse programming(for now) and trashed my GUI.
RE:Help with Mouse Programming
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.
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.