Mouse driver not working

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
deleted8917
Member
Member
Posts: 119
Joined: Wed Dec 12, 2018 12:16 pm

Mouse driver not working

Post by deleted8917 »

I'm trying to do an mouse driver, but I can't detect the mouse. I'm following the "8042" PS/2 Controller and Mouse input.
Here is the code:

Code: Select all

#include "kernel.h"
#include "terminal.h"
#include "irq.h"
#include "bool.h"

typedef enum MouseCommands
{
    MOUSE_ACK = 0xFA,
    MOUSE_IDENTITY = 0xF2,
    MOUSE_DISABLE_DATA = 0xF5,
} MouseCommands;

bool __mouse_self_test;
bool __mouse_has_2channels;
bool __mouse_interface1_test = false, __mouse_interface2_test = false;

void mouse_write(uint8_t val)
{
    outb(0x64, val);
}

uint8_t mouse_read(void)
{
    return inb(0x60);
}

/*
None 	Ancient AT keyboard with translation enabled in the PS/Controller (not possible for the second PS/2 port)
0x00 	Standard PS/2 mouse
0x03 	Mouse with scroll wheel
0x04 	5-button mouse
0xAB, 0x41 or 0xAB, 0xC1 	MF2 keyboard with translation enabled in the PS/Controller (not possible for the second PS/2 port)
0xAB, 0x83 	MF2 keyboard 
*/
uint8_t mouse_type(void)
{
    mouse_write(MOUSE_DISABLE_DATA);
    if (mouse_read() == MOUSE_ACK)
    {
        mouse_write(MOUSE_IDENTITY);
        if (mouse_read() == MOUSE_ACK)
            return mouse_read();
    }
}

void mouse_handler(struct regs *r)
{
    /* Nothing to do yet... */
}

int mouse_installer(void)
{
    /* Disabling any other device that can mess up */
    mouse_write(0xAD);
    mouse_write(0xA7);
    /*
    Mouse self test. 0x55 test passed, 0xFC failed
    In some systems, it resets the computer.
    */
    mouse_write(0xAA);
    if (mouse_read() == 0x55)
        __mouse_self_test = true;
    else
        __mouse_self_test = false;

    /* Check if we have 2 channels */
    mouse_write(0xA8);
    if (inb(0x20) & (5 << 0))
    {
        __mouse_has_2channels = false;
    }
    else
    {
        __mouse_has_2channels = true;
        /* Disable second PS/2 port again */
        mouse_write(0xA7);
    }
    /* Interface tests */
    if (__mouse_has_2channels)
    {
        mouse_write(0xAB);
        if (inb(0x60) == 0x00)
        {
            __mouse_interface1_test = true;
            /* Enable port 1! */
            mouse_write(0xA8);
            outb(0x60, 1);
        }
    }
    else
    {
        mouse_write(0xA9);
        if (inb(0x60) == 0x00)
        {
            __mouse_interface2_test = true;
            /* Enable port 2! */
            mouse_write(0xAE);
            outb(0x60, 0);
        }
    }
    

    /* Enable packet streaming */
    mouse_write(0xF4);

    if (inb(0x64) == MOUSE_ACK)
    {
        kputs("mouse detected, received ACK response");
        irq_install_handler(12, mouse_handler);
    }
    else
    {
        kputs("no mouse detected");
        return -1;
    }
}
Also, when I use the mouse_type function, the keyboard driver stop working.
MichaelPetch
Member
Member
Posts: 798
Joined: Fri Aug 26, 2016 1:41 pm
Libera.chat IRC: mpetch

Re: Mouse driver not working

Post by MichaelPetch »

Have you sent an End of Interrupt (EOI) to the appropriate PIC(s) when your IRQ handlers are finished? You also seem to be reading port 0x20? That is the master PIC.
Last edited by MichaelPetch on Sun Feb 24, 2019 1:51 am, edited 1 time in total.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: Mouse driver not working

Post by BenLunt »

Code: Select all

void mouse_write(uint8_t val)
{
    outb(0x64, val);
}

uint8_t mouse_read(void)
{
    return inb(0x60);
}
These two need to test to see if the buffer is ready to receive a byte and if there is a byte in the buffer to read. Reading from an empty buffer will return undefined results.

Ben
- http://www.fysnet.net/input_and_output_devices.htm
Octocontrabass
Member
Member
Posts: 5586
Joined: Mon Mar 25, 2013 7:01 pm

Re: Mouse driver not working

Post by Octocontrabass »

Your code has a variety of issues. Perhaps the biggest is the name: you're trying to write a mouse driver, but most of the code you've written is for the PS/2 controller. Those are separate components, and you should name your functions appropriately to avoid confusion. I recommend also separating it into three drivers: one for the PS/2 controller, one for the mouse, and one for the keyboard.

Yes, the keyboard is also connected to the PS/2 controller. That's why your attempt at identifying the mouse causes the keyboard to stop responding.

Once you have clear separation between code that configures the PS/2 controller and code that configures the keyboard/mouse, I can help you more.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: Mouse driver not working

Post by BenLunt »

Octocontrabass wrote:Your code has a variety of issues. Perhaps the biggest is the name: you're trying to write a mouse driver, but most of the code you've written is for the PS/2 controller. Those are separate components, and you should name your functions appropriately to avoid confusion. I recommend also separating it into three drivers: one for the PS/2 controller, one for the mouse, and one for the keyboard.

Yes, the keyboard is also connected to the PS/2 controller. That's why your attempt at identifying the mouse causes the keyboard to stop responding.

Once you have clear separation between code that configures the PS/2 controller and code that configures the keyboard/mouse, I can help you more.
I have to second this. Octocontrabass' point is exactly what I was thinking but didn't comment at the time. I will add just a little to emphasize his point. On some PS/2 controllers, in fact more than not, you might have the mouse and the keyboard swapped and still work. I haven't tried it myself, but have read numerous sources that say it is available. With this in mind, dividing the drivers into three different sources is a very good point. (I had done this myself long ago)

Ben
- http://www.fysnet.net/input_and_output_devices.htm
deleted8917
Member
Member
Posts: 119
Joined: Wed Dec 12, 2018 12:16 pm

Re: Mouse driver not working

Post by deleted8917 »

Here is my code so far:

Code: Select all

#include "kernel.h"
#include "terminal.h"
#include "irq.h"
#include "bool.h"

typedef enum MouseCommands
{
    MOUSE_ACK = 0xFA,
    MOUSE_IDENTITY = 0xF2,
    MOUSE_DISABLE_DATA = 0xF5,
} MouseCommands;

uint8_t offset = 0;
uint8_t buffer[3];
uint8_t mouse_key = 0;
int16_t mouse_x = 0, mouse_y = 0;

void mouse_wait(unsigned char type)
{
    unsigned int time_o = 100000;
    if (type == 0)
    {    
        while (--time_o)
        {
            if ((inb(0x64) & 1) == 1)
            {
                break;
            }
        }
        return;
    }
    else
    {
        while (--time_o)
        {
            if ((inb(0x64) & 2) == 0)
            {
                break;
            }
        }
        return;
    }
}

uint8_t mouse_ctrl_status(void)
{
    mouse_wait(0);
    return inb(0x64);
}

void mouse_send_cmd(uint8_t cmd)
{
    while (1)
	{
    	if ((mouse_ctrl_status() & 2) == 0)
		{
        	break;
		}
	}
    outb(0x64, cmd);
}

void mouse_send_data(uint8_t data)
{
    while (1)
	{
    	if ((mouse_ctrl_status() & 2) == 0)
		{
        	break;
		}
	}
    outb(0x60, data);
}



uint8_t mouse_read_data(void)
{
    mouse_wait(0);
    return inb(0x60);
}

/*
None 	Ancient AT keyboard with translation enabled in the PS/Controller (not possible for the second PS/2 port)
0x00 	Standard PS/2 mouse
0x03 	Mouse with scroll wheel
0x04 	5-button mouse
0xAB, 0x41 or 0xAB, 0xC1 	MF2 keyboard with translation enabled in the PS/Controller (not possible for the second PS/2 port)
0xAB, 0x83 	MF2 keyboard 
*/
uint8_t mouse_type(void)
{
    mouse_send_cmd(MOUSE_DISABLE_DATA);
    if (mouse_read_data() == MOUSE_ACK)
    {
        mouse_send_cmd(MOUSE_IDENTITY);
        if (mouse_read_data() == MOUSE_ACK)
            return mouse_read_data();
    }
}

void mouse_handler(struct regs *r)
{
    uint8_t __status = mouse_ctrl_status();
    if (!(__status & 0x20))
        return;
    buffer[offset] = mouse_read_data();
    offset = (offset + 1) % 3;

    if (offset == 0)
    {
        mouse_x += buffer[1] - (0x100 & (buffer[0] << (8-4)));
        mouse_y -= buffer[2] - (0x100 & (buffer[0] << (8-5)));
    }
}

void mouse_printpos(void)
{ 
    char buf[255];
    kputs(itoa(mouse_x, buf, 10));  
    kputs(itoa(mouse_y, buf, 10));
}

int mouse_installer(void)
{
    uint8_t __status;
    mouse_send_cmd(0xA8);
    mouse_send_cmd(0x20);
    __status = mouse_read_data() | 2;
    mouse_send_data(__status);
    mouse_send_cmd(0xD4);
    mouse_send_data(0xF4);
    mouse_read_data();
    irq_install_handler(12, mouse_handler);
}
In kmain.c I have the mouse_printpos is in a infinite loop, but just prints zeros. And how I saided before, the keyboard does not work. #-o
Klakap
Member
Member
Posts: 299
Joined: Sat Mar 10, 2018 10:16 am

Re: Mouse driver not working

Post by Klakap »

hextakatt wrote:

Code: Select all

void mouse_handler(struct regs *r)
{
    uint8_t __status = mouse_ctrl_status();
    if (!(__status & 0x20))
        return;
    buffer[offset] = mouse_read_data();
    offset = (offset + 1) % 3;

    if (offset == 0)
    {
        mouse_x += buffer[1] - (0x100 & (buffer[0] << (8-4)));
        mouse_y -= buffer[2] - (0x100 & (buffer[0] << (8-5)));
    }
}
In kmain.c I have the mouse_printpos is in a infinite loop, but just prints zeros. And how I saided before, the keyboard does not work. #-o
Here is problem. You don`t send EOI. After send irq, other interrupts is stop and PIC is waiting for EOI. Change your code:

Code: Select all

void mouse_handler(struct regs *r)
{
    //EOI - End Of Interrupt
    outb(0xA0, 0x20);
    outb(0x20, 0x20);

    ...
}
And I think than http://os-development.000webhostapp.com/mys.html maybe help you.
Octocontrabass
Member
Member
Posts: 5586
Joined: Mon Mar 25, 2013 7:01 pm

Re: Mouse driver not working

Post by Octocontrabass »

hextakatt wrote:In kmain.c I have the mouse_printpos is in a infinite loop, but just prints zeros. And how I saided before, the keyboard does not work. #-o
You're still mixing up the PS/2 controller and the mouse. Your "mouse_send_cmd" and "mouse_send_data" functions are sending commands and data to the PS/2 controller, not the mouse. You must separate the PS/2 controller functions from the mouse functions in your code.

The keyboard doesn't work because you're sending nonsense to the PS/2 controller, and the keyboard is connected to the PS/2 controller the same way the mouse is.
Klakap wrote:And I think than http://os-development.000webhostapp.com/mys.html maybe help you.
This is a very bad example. It mixes up the PS/2 controller and the mouse, and interferes with the keyboard.
Klakap
Member
Member
Posts: 299
Joined: Sat Mar 10, 2018 10:16 am

Re: Mouse driver not working

Post by Klakap »

Octocontrabass wrote:
Klakap wrote:And I think than http://os-development.000webhostapp.com/mys.html maybe help you.
This is a very bad example. It mixes up the PS/2 controller and the mouse, and interferes with the keyboard.
Hm. My driver for mouse is based on it and I have not any mistakes. But I am agree, that it mixes PS/2 and mouse.
deleted8917
Member
Member
Posts: 119
Joined: Wed Dec 12, 2018 12:16 pm

Re: Mouse driver not working

Post by deleted8917 »

I managed to make the mouse driver work(¿?), but it is very sensitive, with moving the mouse a little the cursor is already in the corner of the screen. How can I change the sensitivity? Also it says that I pressed a mouse key when I not.
Edit:
mouse.c

Code: Select all

#include "kernel.h"
#include "terminal.h"
#include "irq.h"
#include "bool.h"
#include "mouse.h"

typedef enum MouseCommands
{
    MOUSE_ACK = 0xFA,
    MOUSE_IDENTITY = 0xF2,
    MOUSE_ENABLE_PACKETS = 0xF4,
    MOUSE_DISABLE_DATA = 0xF5,
    MOUSE_READ_PORT = 0x60,
    MOUSE_WRITE_PORT = 0x64,
} MouseCommands;


uint8_t offset;
uint8_t buffer[3];
uint8_t mouse_key;
int8_t mouse_x = 40, mouse_y = 12;

void mouse_wait(unsigned char type)
{
    unsigned int time_o = 100000;
    if (type == 0)
    {    
        while (--time_o)
        {
            if ((inb(0x64) & 1) == 1)
            {
                break;
            }
        }
        return;
    }
    else
    {
        while (--time_o)
        {
            if ((inb(0x64) & 2) == 0)
            {
                break;
            }
        }
        return;
    }
}

uint8_t mouse_ctrl_status(void)
{
    mouse_wait(0);
    return inb(0x64);
}

void mouse_send_cmd(uint8_t cmd)
{
    while (1)
	{
    	if ((mouse_ctrl_status() & 2) == 0)
		{
        	break;
		}
	}
    outb(0x64, cmd);
}

void mouse_send_data(uint8_t data)
{
    mouse_wait(1);
    outb(0x64, 0xD4);
    mouse_wait(1);
    outb(0x60, data);
}



uint8_t mouse_read_data(void)
{
    mouse_wait(0);
    return inb(0x60);
}

/*
None 	Ancient AT keyboard with translation enabled in the PS/Controller (not possible for the second PS/2 port)
0x00 	Standard PS/2 mouse
0x03 	Mouse with scroll wheel
0x04 	5-button mouse
0xAB, 0x41 or 0xAB, 0xC1 	MF2 keyboard with translation enabled in the PS/Controller (not possible for the second PS/2 port)
0xAB, 0x83 	MF2 keyboard 
*/
uint8_t mouse_type(void)
{
    mouse_send_cmd(MOUSE_DISABLE_DATA);
    if (mouse_read_data() == MOUSE_ACK)
    {
        mouse_send_cmd(MOUSE_IDENTITY);
        if (mouse_read_data() == MOUSE_ACK)
            return mouse_read_data();
    }
}

void mouse_handler(struct regs *r)
{
    uint8_t __status = mouse_ctrl_status();
    if (!(__status & 0x20))
        return;
    buffer[offset] = mouse_read_data();
    offset = (offset + 1) % 3;

    if (offset == 0)
    {
        mouse_key = buffer[0];
        mouse_x += buffer[1] - (0x100 & (buffer[0] << (8-4)));
        if (mouse_x < 0) mouse_x = 0;
        if (mouse_x >= 80) mouse_x = 79;

        mouse_y -= buffer[2] - (0x100 & (buffer[0] << (8-5)));
        if (mouse_y < 0) mouse_y = 0;
        if (mouse_y >= 25) mouse_y = 24;
    }
    outb(0xA0, 0x20);
    outb(0x20, 0x20);
}

void mouse_get_pos(int8_t x, int8_t y)
{
    x = mouse_x;
    y = mouse_y;
}

MOUSE_DATA mouse_get_key(void)
{
    for (uint8_t cout = 0; cout < 3; ++cout)
    {
        if ((buffer[0] & (0x01 << cout)) != (mouse_key & (0x01 << cout)))
        {
            kputs("rgh");//return MOUSE_RIGHT_KEY;
        }
    }
}

void mouse_printpos(void)
{ 
    char buf[255];
    kputs("X: ");
    kputs(itoa(mouse_x, buf, 10));  
    kputs(" Y: ");
    kputs(itoa(mouse_y, buf, 10));
    if (mouse_get_key() == MOUSE_RIGHT_KEY)
    {
        kputs("  Right key!");
    }
    else if (mouse_get_key() == MOUSE_LEFT_KEY)
    {
        kputs("  Left key!");
    }
    
    kputs("\r");
}

void mouse_installer(void)
{
   uint8_t status = 0;
    
    mouse_wait(1);
    outb(MOUSE_WRITE_PORT,0xA8);

    mouse_wait(1);
    outb(MOUSE_WRITE_PORT,0x20);

    mouse_wait(0);
    status = (inb(MOUSE_READ_PORT) | 2);

    mouse_wait(1);
    outb(MOUSE_WRITE_PORT, 0x60);

    mouse_wait(1);
    outb(MOUSE_READ_PORT, status);

    //set sample rate
    mouse_send_data(0xF3);
    mouse_read_data();

    mouse_send_data(200);
    mouse_read_data();

    //set sample rate
    mouse_send_data(0xF3);
    mouse_read_data();

    mouse_send_data(200);
    mouse_read_data();

    //set sample rate
    mouse_send_data(0xF3);
    mouse_read_data();

    mouse_send_data(80);
    mouse_read_data();

    //start sending packets
    mouse_send_data(MOUSE_ENABLE_PACKETS);
    mouse_read_data();

    irq_install_handler(12, mouse_handler);
}
and mouse.h

Code: Select all

#ifndef _MOUSE_H_
#define _MOUSE_H_

typedef enum
{
	MOUSE_LEFT_KEY = 0x10,
	MOUSE_RIGHT_KEY = 0x11,
}MOUSE_DATA;

void mouse_handler(struct regs *r);
void mouse_printpos(void);
void mouse_installer(void);

#endif
Klakap
Member
Member
Posts: 299
Joined: Sat Mar 10, 2018 10:16 am

Re: Mouse driver not working

Post by Klakap »

hextakatt wrote:I managed to make the mouse driver work(¿?), but it is very sensitive, with moving the mouse a little the cursor is already in the corner of the screen. How can I change the sensitivity?
You mustn`t change sensitivity. You must write good driver for moving cursor. In LightningOS kernel 0.1.1 is moving cursor quite well with:

Code: Select all

     //move right//
     if(mouse_move_x==0x01 || mouse_move_x==0x04 || mouse_move_x==0x05 || mouse_move_x==0x07 || mouse_move_x==0x09 || mouse_move_x==0x0A) {
         if(mouse_x<79) {
             //move cursor
         }
     }

     //move left//
     if(mouse_move_x==0xFE || mouse_move_x==0xFB || mouse_move_x==0xFA || mouse_move_x==0xF8 || mouse_move_x==0xF6 || mouse_move_x==0xF5) {
        if(mouse_x>0) {
             //move cursor
         }            
     }

     //move up//
     if(mouse_move_y==0x01 || mouse_move_y==0x04 || mouse_move_y==0x05 || mouse_move_y==0x07 || mouse_move_y==0x09 || mouse_move_y==0x0A) {
         if(mouse_y>0) {
             //move cursor
         }         
     }

     //move down//
     if(mouse_move_y==0xFE || mouse_move_y==0xFB || mouse_move_y==0xFA || mouse_move_x==0xF8 || mouse_move_x==0xF6 || mouse_move_x==0xF5) {
         if(mouse_y<24) {
             //move cursor
         } 
     }
Did you see the idea?
hextakatt wrote:

Code: Select all

MOUSE_DATA mouse_get_key(void)
{
    for (uint8_t cout = 0; cout < 3; ++cout)
    {
        if ((buffer[0] & (0x01 << cout)) != (mouse_key & (0x01 << cout)))
        {
            kputs("rgh");//return MOUSE_RIGHT_KEY;
        }
    }
}

typedef enum
{
	MOUSE_LEFT_KEY = 0x10,
	MOUSE_RIGHT_KEY = 0x11,
}MOUSE_DATA;
What are you doing here? Read part Receiving data from mouse of http://os-development.000webhostapp.com/mys.html carefully. The most important sentence for you is(translate):
In fourth byte mouse send information about pressed keys. If in it is 0x10, left key is pressed. If in it is 0x20, right key is pressed. If in it is 0x40, middle key is pressed.
You can detect it in mouse handler:

Code: Select all

    if (mouse_buffer[3] & 0x4) {
        //middle key is pressed
    }

    if (mouse_buffer[3] & 0x2) {           
        //right key is pressed
    }

    if (mouse_bytes[3] & 0x1) {
        //left key is pressed
    }
I test it and it work in Bochs, Qemu and Virtualbox. Good luck!
deleted8917
Member
Member
Posts: 119
Joined: Wed Dec 12, 2018 12:16 pm

Re: Mouse driver not working

Post by deleted8917 »

Oh, sorry I didn't answer, I was busy.
Anyway, I don't know what made me think I would need a mouse driver, if I don't even have a GUI, or even a functional OS. :lol:
Thanks anyway, maybe it will help me someday! :)
Post Reply