Page 1 of 1

Mouse driver not working

Posted: Sat Feb 23, 2019 6:52 pm
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.

Re: Mouse driver not working

Posted: Sat Feb 23, 2019 9:58 pm
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.

Re: Mouse driver not working

Posted: Sat Feb 23, 2019 10:58 pm
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

Re: Mouse driver not working

Posted: Sun Feb 24, 2019 9:11 am
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.

Re: Mouse driver not working

Posted: Sun Feb 24, 2019 9:45 am
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

Re: Mouse driver not working

Posted: Sun Feb 24, 2019 11:38 am
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

Re: Mouse driver not working

Posted: Mon Feb 25, 2019 8:23 am
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.

Re: Mouse driver not working

Posted: Mon Feb 25, 2019 9:43 am
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.

Re: Mouse driver not working

Posted: Mon Feb 25, 2019 10:24 am
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.

Re: Mouse driver not working

Posted: Mon Feb 25, 2019 12:47 pm
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

Re: Mouse driver not working

Posted: Tue Feb 26, 2019 7:08 am
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!

Re: Mouse driver not working

Posted: Thu Feb 28, 2019 4:45 pm
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! :)