PS/2 Mice Initialization Order

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.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

PS/2 Mice Initialization Order

Post by XCHG »

Can somebody, please, tell me what commands I should send to the Keyboard controller to initialize and enable a PS/2 mouse up to the point I can receive its interrupts? Thanks in advance.

P.S: It'd be great if the ports to which the commands had to be sent and read from, could be mentioned too.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Try here... I had the same problem, couldn't get the interrupts. Now I can :D. Happy reading![/url]
User avatar
salil_bhagurkar
Member
Member
Posts: 261
Joined: Mon Feb 19, 2007 10:40 am
Location: India

Post by salil_bhagurkar »

Hello pcmattman i wrote the mouse and kbd code separately. Could you please tell me how i can make both of them work separately on different IRQs? (both ps2).
Could i get some code? Thanx...
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

There has been alot of people with mouse problem in the forum, so i have code a simple demo, of a working mouse driver, that does not use any OS code and is fully self contained.
Here is the fasm code and a bootable program to test it, (Note: it will run from dos, but not a dosbox under windows).
http://www.dex4u.com/tuts/MouseDemo.zip

I will add comment in the next day or two, but for now, the code is there.

PS: The demo is running in MiniDos, if you want the code let me know.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

salil_bhagurkar wrote:Hello pcmattman i wrote the mouse and kbd code separately. Could you please tell me how i can make both of them work separately on different IRQs? (both ps2).
Could i get some code? Thanx...
Keyboard is on IRQ 1, mouse is on IRQ 12. Also, to setup the mouse you must use the keyboard controller.

Code for my mouse driver:

Code: Select all

// commands for PS2
#define ENABLE_PS2	0xA8
#define KBD_STAT	0x64
#define MOUSE		0xD4
#define MOUSE_STREAM	0xF4
#define MOUSE_DISABLE	0xF5
#define KBD_CMD		0x60
#define DISABLE_KBD	0xAD
#define ENABLE_KBD	0xAE

// checks the port
void CheckPort()
{
	unsigned char temp;
	while( true )
	{
		temp = inportb( KBD_STAT );
		if( (  temp & 2 ) == 0 )
			break;
	}
}

// waits for the ouse buffer to be full
void MouseBufferFull()
{
	unsigned char temp;
	while( true )
	{
		temp = inportb( KBD_STAT );
		if( (  temp & 0x20 ) == 0 )
			break;
	}
}

// checks the mouse
char CheckMouse()
{
	unsigned char temp;
	temp = inportb( KBD_STAT );

	if( temp & 1 )
		return 0;
	else
		return 1;
}

// set the ps2 bytes
void PS2Set()
{
	// mouse enabled
	outportb( KBD_STAT, ENABLE_PS2 );
	CheckPort();
}

// waits for the mouse
void WaitMouse()
{
	outportb( KBD_STAT, MOUSE );
	CheckPort();
}

// sets the streaming mode
void StartStream()
{
	WaitMouse();
	outportb( KBD_CMD, MOUSE_STREAM );
	CheckPort();
	CheckMouse();
}

// disables the keyboard
void DisableKeyboard()
{
	outportb( KBD_STAT, DISABLE_KBD );
	CheckPort();
}

// enables the keyboard
void EnableKeyboard()
{
	outportb( KBD_STAT, ENABLE_KBD );
	CheckPort();
}

// wait for the mouse - this is in the OSFAQ (http://www.osdev.org/osfaq2)
void MouseWait( char thetype )
{
	long timeout = 100000;
	if( thetype == 0 )
	{
		while( timeout-- )
		{
			if( inportb( 0x64 ) & 1 )
			{
				return;
			}
		}
		return;
	}
	if( thetype == 1 )
	{
		while( timeout-- )
		{
			if( ( inportb( 0x64 ) & 2 ) == 0 )
			{
				return;
			}
		}
		return;
	}
}

// get a byte from the port
char GetByte()
{
	MouseWait( 0 );
	char ret = inportb( 0x60 );

	return ret;
}

// info
int readable = 0;

// data pointer
MOUSEDATA LocalData;

// irq handler for the mouse
void MouseIRQ( struct regs* r )
{
	LocalData.status = GetByte();
	LocalData.xcoord = GetByte();
	LocalData.ycoord = GetByte();

	readable = 1;
}

// installs the IRQ
void InstallMouseIRQ()
{
	// enable the irq
	outportb( 0x64, 0x20 );
	KeyContWaitReady();
	unsigned char c = inportb( 0x60 ) | 2;
	outportb( 0x64, 0x60 );
	KeyContWaitReady();
	outportb( 0x60, c );

	// install the irq handler
	irq_install_handler( 12, MouseIRQ );
}

// get data from the mouse
void GetMouseData( MOUSEDATA* data )
{
	// is there data?
	if( ! readable )
	{
		// there's no data yet, so just make no movement
		*data.status = 0;
		*data.xcoord = 0;
		*data.ycoord = 0;
		
		// go back to caller
		return;
	}
	
	// disable interrupts
	__asm__ __volatile__ ( "cli" );

	// readable is false now
	readable = 0;

	// get the important stuff
	LocalData.leftbut = LocalData.status & 1;
	LocalData.rightbut = ( LocalData.status & 2 ) >> 1;
	LocalData.midbut = ( LocalData.status & 4 ) >> 2;
	LocalData.xsign = ( LocalData.status & 16 ) >> 4;
	LocalData.ysign = ( LocalData.status & 32 ) >> 5;
	LocalData.xover = ( LocalData.status & 64 ) >> 6;
	LocalData.yover = ( LocalData.status & 128 ) >> 7;

	// return the data
	*data = LocalData;
	
	// enable interrupts
	__asm__ __volatile__ ( "sti" );
}

// init the mouse
void InitMouse()
{
	PS2Set();
	InstallMouseIRQ();
	StartStream();
}
Header:

Code: Select all


typedef struct tagMOUSEDATA
{
	char xover;
	char yover;
	char xsign;
	char ysign;
	char midbut;
	char rightbut;
	char leftbut;
	char status;
	char xcoord;
	char ycoord; 
} MOUSEDATA;

// init the mouse
void InitMouse();

// get data from the mouse
void GetMouseData( MOUSEDATA* data );
You should be able to pick up what's happening from this. It works perfectly in my OS when I run it like so:

Code: Select all

MOUSEDATA m;
GetMouseData( &m );

MouseX += ( m.xcoord * 1 );
MouseY += ( m.xcoord * -1 );
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Well I still have problems getting the mouse to work but it's more because I haven't had enough time to fiddle around with mouse. Thank you everyone for your replies.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Okay great. IRQ 12 is being sent to my kernel now. I will post the commented assembly source code soon so other people will be able to use it later.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Okey Dokey. Here is the code for initializing the PS/2 Mouse. The code is written in NASM. All procedures use the StdCall calling convention. Below is the INVOKE macro that I have written in NASM that allows you to call these procedures with the StdCall calling convention.

Code: Select all

; --------------------------------------------------
%MACRO INVOKE 1-*
  %REP    %0 - 1
    %ROTATE   -1
    PUSH    DWORD %1
  %ENDREP
  %ROTATE -1
  CALL    %1
%ENDMACRO
; --------------------------------------------------
Every single line of the code is commented. All you have to do is to INVOKE the __SetUpMouse procedure.
Attachments
MouseKeyboard.asm
How to set up and initialize PS/2 Mice
(17.12 KiB) Downloaded 177 times
Nitro
Posts: 12
Joined: Thu May 08, 2008 12:42 pm

Post by Nitro »

Hi

I need SendMouseClick(), SetCursorPosition() functions but without using interrupts (i'm trying to do this on .NET using inpout32.dll).

As a start i was trying to read from mouse, instead of writing..
But even so i found a few problems...

Code: Select all

        void readMouse()
        {
            readMouse = !readMouse;
            short ack;
            short[] data = new short[10];
            int i;

            while (readMouse)
            {
                //Set mouse command: read mouse data packet 
                while ((Inp32(0x64) & 0x02) != 0) ; //Wait Input Buffer empty 
                Out32(0x64, 0xD4); // 0xD4

                //Send read command to mouse 
                while ((Inp32(0x64) & 0x02) != 0) ; //Wait Input Buffer empty 
                Out32(0x60, 0xEB);

                //Send GET PACK to mouse 
                //Wait aux data... (This loops forever... i tryed a delay instead)
                while ((Inp32(0x64) & 0x21) != 0x21) ; 

                ack = Inp32(0x60);   //should be 0xFA if OK 
               // I get ack=0xFE (resend) instead of 0xFA...

                //Get packet of 4 bytes 
                if (ack == 0xFA) 
                {
                    for (i = 0; i < 4; ++i)
                    {
                        //Wait aux data, again it loops forever...
                        //I tryed a delay instead..
                        while ((Inp32(0x64) & 0x21) != 0x21) ; 

                        data[i] = Inp32(0x60); //read next packet byte 
                    }

                    if ((data[0] & 0x01) != 0) {left button pressed...}
                    if ((data[0] & 0x02) != 0) {right button pressed...}
                }
            }    
        }
Any ideas? :?
svdmeer
Member
Member
Posts: 87
Joined: Tue May 06, 2008 9:32 am
Location: The Netherlands

Post by svdmeer »

How about USB mice?

Do they behave like PS/2 mice when connected at boottime?
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

@Nitro: if everything else was working perfectly, your code looks to me like it should work. Which means that everything else is not working perfectly. I know nothing about the .NET inpout32.dll. However, it scares me that you are reading shorts from Out32 at the bottom -- especially with that 32 in the name of both functions. Are you certain that both Inp32 and Out32 transmit BYTES only? Because if there are extra 0 value bytes being sent to port 0x60 when you do an Out32, then that will totally screw up everything.

Also, are you sure that you initialized the mouse successfully, to send 4 byte packets? You got all the proper ACKs during the process? 3 byte packets is default. Somehow, I expect that you are skipping that part -- which is OK -- but you should limit packets to 3 bytes.

Also, are you sure that there is no keyboard handler that is eating bytes from port 0x60 at the same time that you are trying to grab mouse bytes? (It seems to me that you will have no choice at all, but to integrate both drivers together.)

Also, regarding these 0xFE bytes that are coming in -- is the 0x20 bit set on the byte that you read from port 0x64? Or are the 0xFE bytes coming from the KEYBOARD?


@svdmeer: There is something called SMM that automatically translates USB mice data/commands <-> PS2 mice data/commands invisibly, for you, until you turn it off. So, yes, they start off behaving identically.
Nitro
Posts: 12
Joined: Thu May 08, 2008 12:42 pm

Post by Nitro »

bewing wrote: I know nothing about the .NET inpout32.dll. However, it scares me that you are reading shorts from Out32 at the bottom -- especially with that 32 in the name of both functions. Are you certain that both Inp32 and Out32 transmit BYTES only? Because if there are extra 0 value bytes being sent to port 0x60 when you do an Out32, then that will totally screw up everything.
I'm aware that these ports should receive bytes only.
The 32 does not mean that i'm sending/receiving 32bit values, it has to do with the supported architecture.
I also managed to perfectly send keys using this DLL.
bewing wrote: Also, are you sure that you initialized the mouse successfully, to send 4 byte packets? You got all the proper ACKs during the process? 3 byte packets is default. Somehow, I expect that you are skipping that part -- which is OK -- but you should limit packets to 3 bytes.
I didn't any mouse initialization, i tryed to use the mouse_install() posted above, and i got the same results, so i guess the problem isn't there.
bewing wrote: Also, are you sure that there is no keyboard handler that is eating bytes from port 0x60 at the same time that you are trying to grab mouse bytes? (It seems to me that you will have no choice at all, but to integrate both drivers together.)
I'm starting to think that this may be the problem... i dont have any keyboard handlers, at least i didnt included any...

I'm running a .net 2.0 program, maybe something is screweing up the process, it seems that that every command i issue, i always receive a 0xFE reply instead of 0xFA..
bewing wrote: Also, regarding these 0xFE bytes that are coming in -- is the 0x20 bit set on the byte that you read from port 0x64? Or are the 0xFE bytes coming from the KEYBOARD?
I get 0x22 when reading the por 0x64, so yes 0x20 is set.

After writting 0xD4 to the port 0x64 i should receive a 0xFA ack right?
Well again i get 0xFE... these resends probably mean that something is not letting me comunicate with the mouse.

But the critical problem seems to be here:

//Send CMD GET PACK to mouse
while ((Inp32(0x64) & 0x21) != 0x21) ; //Wait aux data
ack = Inp32(0x60);

I get 0xFE instead of 0xFA... so i'm not able to read the packets...

My mouse is connected thru USB, but i guess this is not the problem...

:cry:

Btw the code i posted it's not mine i found it on other site and i don't fully understand it..

How would i write a send click/move for instance? (this is my main goal..)

EDIT: After issuing the enable mouse (0xA8) i managed to receive an ack to read the packets. Later i restarted the pc and the same code no longer worked... :?

My guess is that it has something to do with the mouse initialization, maybe i should not be using the streaming mode (default)?
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post by bewing »

I think you may have not read the wiki article I wrote on this:
http://www.osdev.org/wiki/Mouse_Input

No, the 0xD4 byte does not produce an ACK.

As I recall, streaming mode should work OK -- packet transmission is turned off by default. Using the Read Packet (0xEB) command should work equally well in both modes, I think.
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

How would i write a send click/move for instance? (this is my main goal..)
Your goal is impossible. The mouse (and any other input device) cannot be told where to move or where to click. It senses movement and delivers that movement to the operating system (technically the mouse driver) in the form of deltas along two different axes, and click/unclick information.

It is up to the operating system to interpret these inputs and produce something tangible from them. You cannot tell the mouse when to write something, or what to write, and you cannot 'spoof' commands from the mouse.

Your goal is impossible.

Cheers

James
svdmeer
Member
Member
Posts: 87
Joined: Tue May 06, 2008 9:32 am
Location: The Netherlands

Post by svdmeer »

And the scroll wheel(s)?

Is where any 'official' documentation about de ps/2 mouse?
Post Reply