Help with Mouse Programming

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Gandalf

Help with Mouse Programming

Post 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
St8ic

RE:Help with Mouse Programming

Post 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!
SystemHalted

RE:Help with Mouse Programming

Post by SystemHalted »

yes I also gave up on mouse programming(for now) and trashed my GUI.
CodeSlasher

RE:Help with Mouse Programming

Post 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.
Post Reply