Page 1 of 1

PS/2 Mouse irq's not firing/firing once.

Posted: Mon Sep 21, 2020 11:44 pm
by Danyy
This is my first time on the OSDev Forums so excuse the style of the question. This was y question from stackoverflow so the "edits" are not actually edits.

I have written "some" keyboard drivers and I wanted make a little mouse support, maybe a cursor. I read several guides on ps/2 mouse especially on the wiki and copied a bunch of code from Sanik's to start. (viewtopic.php?t=10247)

However I cannot get the mouse to respond. I initialise the mouse and setup irq12 but the output is not consistent. Here is the code.

Code: Select all

void mouse_install()
{
  unsigned char _status;  //unsigned char
    
    mouse_write(0xFF);
    mouse_read();

 
  //Enable the interrupts
  mouse_wait(1);
  outb(0x64, 0x20);
  mouse_wait(0);
   _status=inb(0x60);          
   _status = (_status | 2) ;
  mouse_wait(1);
  outb(0x64, 0x60);
  mouse_wait(1);
  outb(0x60, _status);
 mouse_read();
 
 
 
  //Enable the mouse
  mouse_write(0xF4);
  mouse_read();  //Acknowledge

}
I call this directly from the kernel after the interrupts are setup. I know for a fact that irq's work because keyboard works. This next code is the mouse handler. I call a printf after I get the mouse_x.

Code: Select all

void irq12_handler(interrupt_frame_t* frame) //struct regs *a_r (not used but just there)
{
    
  switch(mouse_cycle)
  {
    case 0:
      mouse_byte[0]=inb(0x60);
      mouse_cycle++;
      break;
    case 1:
      mouse_byte[1]=inb(0x60);
      mouse_cycle++;
      break;
    case 2:
      mouse_byte[2]=inb(0x60);
      
      
      mouse_x = mouse_byte[1];
      mouse_y = mouse_byte[2];
      
     
      
      mouse_cycle=0;
      break;
  }
    
  printf(mouse_x);
  
  default_irq_handler(frame); // <- This is just outb(0x20, 0x20); outb(0xA0, 0x20);
  
}
The problem is I get 3 outputs at the initalisation and I don't get any more output when I move the mouse. However, the first time I wrote this code it did work. I got a bunch of values outputted when I moved the mouse but the next time I compiled it without changing any code it stopped working which is funny.

What may the problem be? I am running this on QEmu.

Important edit:

I just kept making little changes and I didnt change anything related to the mouse code however I got the following output

Image

This is the output I got as I moved the mouse. It is very interesting because I didn't change anything at all. The code that didn't work before now works, and it is likely to get broken in the future.

Edit: I think I know the problem. If I were to run the program on qemu and at the moment it runs, click on the qemu screen so I can capture the input; the mouse is detected and some garbage is printed on the screen (that garbage is the unformatted deltaXs). The problem is that if I wait for a moment before clicking the screen I think the mouse is not detected thus it is not emulated as a ps/2 mouse in the qemu therefore it is not initialised. How can I resolve this issue.

Edit: These are the output with printf("%d", mouse_x) they make more sense

Image

These are the deltaX from the mouse which means it works. The problem is with the timing that the mouse is connected to the computer. How can I solve the problem?

So the overall problem is that I need to detect the mouse being plugged into the computer (or QEmu in this case) and initialise the mouse after it is plugged. Is this normal behaviour? How can I solve the issue?

Feel free to request more code. Thank you.

Re: PS/2 Mouse irq's not firing/firing once.

Posted: Tue Sep 22, 2020 12:57 pm
by Klakap
Welcome in this community Danyy. Here are my notes to your code:

Code: Select all

    //in mouse_init
    mouse_write(0xFF);
    mouse_read();
I dont know what are you doing. This should be:

Code: Select all

    mouse_wait(1);
    outb(0x64, 0xA8);
And after this you can use your code

Code: Select all

  //Enable the interrupts
  mouse_wait(1);
  outb(0x64, 0x20);
  mouse_wait(0);
   _status=inb(0x60);          
   _status = (_status | 2) ;
  mouse_wait(1);
  outb(0x64, 0x60);
  mouse_wait(1);
  outb(0x60, _status);


After this code is mouse ready to accept commands. So you should delete your mouse_read() in next line, this doing nothing here. You can write this commands:

Code: Select all

    //set default mouse settings - 3 bytes packet
    mouse_write(0xF6);
    mouse_read();

    //start sending packets
    mouse_write(0xF4);
    mouse_read();
Now is mouse correctly initalized and you can captured IRQ12. In PS/2 ports you can't detect drives, but after right initalisation will be irq fired 3 times always if connected mouse is moving or button is pressed.

Re: PS/2 Mouse irq's not firing/firing once.

Posted: Tue Sep 22, 2020 11:10 pm
by Danyy
Hi Thanks for your answers Klakap (Do we reply to answers here)

For the first part,

I wanted to reset the mouse before the actual initialisation so that it would be set to default settings and if there is an error or something like that it would reset.

Code: Select all

    mouse_wait(1);
    outb(0x64, 0xA8);
I removed this piece of code because it is noted on the wiki that "Please note that using this command is not necessary if setting the Compaq Status byte is successful".

Code: Select all

  //Enable the interrupts
  mouse_wait(1);
  outb(0x64, 0x20);
  mouse_wait(0);
   _status=inb(0x60);         
   _status = (_status | 2) ;
  mouse_wait(1);
  outb(0x64, 0x60);
  mouse_wait(1);
  outb(0x60, _status);
This already works so no problem here.

Code: Select all

    mouse_write(0xF6);
    mouse_read();
I already reset the mouse so it is already defaulted, this code is not neccessary.

The real problem here is checking if a mouse is plugged in and initialising the mouse after it is plugged AND being able to unplug and replug the mouse and make it still work because it somehow breaks in QEmu (It may be specific to QEmu though).

Re: PS/2 Mouse irq's not firing/firing once.

Posted: Thu Sep 24, 2020 11:53 am
by Klakap
As I stated, there is no way to detect if is mouse plugged or unplugged. But, PS/2 mouse aren't used on real computers today and in emulators mouse work after one initialization, no matter how many times the mouse is disconnected and connected. If QEMU make some wrong with irq fires, mistake is probably in variable mouse_cycle. If you write code in C, there is no guarantee that any variable after start operating system have value 0. If mouse_cycle have another value, after first mouse plug it probably dont seem that there is error, but after replugged here can comes many strange outputs. So try to write before command 0xF4

Code: Select all

mouse_cycle=0;
Hope this help.