ps2 mouse driver in asm

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
User avatar
turdus
Member
Member
Posts: 496
Joined: Tue Feb 08, 2011 1:58 pm

ps2 mouse driver in asm

Post by turdus »

Here's a full (wheel, 4th, 5th button) ps2 mouse driver source in fasm syntax. Released under CC0 (public domain).

First, we need some misc functions to communicate with keyboard.

Code: Select all

;dl=1 read, dl=2 write
ps2wait:	mov			ecx, 1000
@@:		in			al, 64h
		and			al, dl
		jnz			@f
		dec			ecx
		jnz			@b
@@:		ret
ps2wr:	mov			dh, al
		mov			dl, 2
		call			ps2wait
		mov			al, 0D4h
		out			64h, al
		call			ps2wait
		mov			al, dh
		out			60h, al
		;no ret, fall into read code to read ack
.ps2rd:	mov			dl, 1
		call			ps2wait
		in			al, 60h
		ret
ps2wait waits until an operation can be done (read or write). ps2wr writes a byte, ps2rd reads, simple. The write does not return, it continues to read function to get acknowledge byte.

Now the initialization code, it's a bit ughly, but has to be done only once. Don't cause trouble if called several times.

Code: Select all

		;variables
packetsize: db 0
resolution: db 3
samplerate: db 200

		;initialize legacy ps2 user input
		xor			rax, rax
		mov			dl, 2
		call			ps2wait
		mov			al, 0A8h
		out			64h, al
		;get ack
		call			ps2rd
		;some compaq voodoo magic to enable irq12
		mov			dl, 2
		call			ps2wait
		mov			al, 020h
		out			64h, al
		mov			dl, 1
		call			ps2wait
		in			al, 60h
		bts			ax, 1
		btr			ax, 5
		mov			bl, al
		mov			dl, 2
		call			ps2wait
		mov			al, 060h
		out			64h, al
		call			ps2wait
		mov			al, bl
		out			60h, al
		;get optional ack
		mov			dl, 1
		call			ps2wait

		;restore to defaults
		mov			al, 0F6h
		call			ps2wr
		;enable Z axis
		mov			al, 0F3h
		call			ps2wr
		mov			al, 200
		call			ps2wr
		mov			al, 0F3h
		call			ps2wr
		mov			al, 100
		call			ps2wr
		mov			al, 0F3h
		call			ps2wr
		mov			al, 80
		call			ps2wr
		mov			al, 0F2h
		call			ps2wr
		call			ps2rd
		mov			byte [packetsize], 3
		or			al, al
		jz			.noZaxis
		mov			byte [packetsize], 4
.noZaxis:	;enable 4th and 5th buttons
		mov			al, 0F3h
		call			ps2wr
		mov			al, 200
		call			ps2wr
		mov			al, 0F3h
		call			ps2wr
		mov			al, 200
		call			ps2wr
		mov			al, 0F3h
		call			ps2wr
		mov			al, 80
		call			ps2wr
		mov			al, 0F2h
		call			ps2wr
		call			ps2rd

		;set sample rate
		mov			al, 0F3h
		call			ps2wr
		mov			al, byte[samplerate] ;200
		call			ps2wr
		;set resolution
		mov			al, 0E8h
		call			ps2wr
		mov			al, byte [resolution] ;3
		call			ps2wr
		;set scaling 1:1
		mov			al, 0E6h
		call			ps2wr
		;enable
		mov			al, 0F4h
		call			ps2wr

		;reset variables
		xor			eax, eax
		mov			dword [cnt], eax
		mov			dword [y], eax
And finally, the communication. You'll have to install an ISR calling this using your own PIC/IOAPIC, IDT implementation. Note that this code is not an ISR, it does not save and restore cpu state for example, it deals with the mouse only. When set up correctly, it will run every time you click or move the mouse. It calculates absolute pointer positions from delta values, but it's up to you what you do with the data.

Code: Select all

		;variables
packet: dd 0	;raw packet
;keep them together
cnt: db 0		;byte counter
buttons: db 0	;buttons, each bit represents one button from bits 1-5, 0-released, 1-pressed
x: dw 0		;position on x,y,z axis
y: dw 0
z: dw 0

		xor			ecx, ecx
		mov			cx, 1000
		xor			eax, eax
.waitkey:	in			al, 64h
		dec			cl
		jnz			@f
		ret
@@:		and			al, 20h
		jz			.waitkey
		in			al, 60h
		mov			cl, al
		in			al, 61h
		out			61h, al
		xor			ebx, ebx
		mov			bl, byte [cnt]
		add			ebx, packet
		mov			byte [ebx], cl
		inc			byte [cnt]
		mov			bl, byte [cnt]
		cmp			bl, byte [packetsize]
		jb			.end
		mov			byte [cnt], 0

		;get buttons state
@@:		mov			al, byte [packet]
		and			al, 7
		mov			cl, byte [packet+3]
		and			cl, 0F0h
		cmp			cl, 0F0h
		je			.no45btn
		shr			cl, 1
		or			al, cl
.no45btn:	mov			byte [buttons], al
		;get delta X
		movsx		eax, byte [packet+1]
		add			word [x], ax
		;get delta Y
		movsx		eax, byte [packet+2]
		add			word [y], ax
		;get delta Z
		mov			cl, byte [packet+3]
		and			cl, 0Fh
		cmp			cl, 8
		jb			@f
		or			cl, 0F0h
@@:		movsx		eax, cl
		add			word [z], ax

;buttons,x,y,z variables contains valid values now.
;here you possibly want to send a mouse event message to your gui process.
.end:		ret
Tested on Bochs, VirtualBox and real hardware. On real hardware it supports wheel-less mice and 3 button wheel mice. I did not have a mouse with 4th or 5th button to test with, but should work fine. Also worked with a legacy-mode USB wheel mouse. Brands: Genius, Logitech, Microsoft all ok.

ps.: sorry for the tabs, it looked fine in editor.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: ps2 mouse driver in asm

Post by Brendan »

Hi,

berkus wrote:
turdus wrote:ps.: sorry for the tabs, it looked fine in editor.
Point in favor of tabs2spaces conversion.
If you have a look at the page source, not only have the tabs been converted to spaces they've been converted to " " sequences (even though the page uses "charset=UTF-8" where a non-breaking space can be done as a normal character and needs no bloated "6 characters to represent one character" escape sequence).

Had the tabs been left as tabs it would've been up to the browser to handle it. In this case I doubt it'd look any worse (and I wouldn't be surprised if it looked a lot better). Ironically, all the indentation in the page's javascript uses tabs, and it causes no problems at all (when you do "view page source").

Point decidedly against (bad) tabs2spaces conversion... ;)


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: ps2 mouse driver in asm

Post by Solar »

Brendan wrote:Ironically, all the indentation in the page's javascript uses tabs, and it causes no problems at all (when you do "view page source").
Well yes, but it just has to be executed, not displayed. ;-)

As for Turdus' recommendable contribution, how about putting it up on some website, then linking to it from the OSDev Wiki? This forum thread will soon sink down into the cesspits of the forum database, and be forgotten...
Every good solution is obvious once you've found it.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: ps2 mouse driver in asm

Post by Combuster »

If you mean the wiki, we can just do that ;)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Chandra
Member
Member
Posts: 487
Joined: Sat Jul 17, 2010 12:45 am

Re: ps2 mouse driver in asm

Post by Chandra »

Combuster wrote:If you mean the wiki, we can just do that ;)
Yeah, linking to this thread from the relevant article of the Wiki will work best.
Programming is not about using a language to solve a problem, it's about using logic to find a solution !
User avatar
turdus
Member
Member
Posts: 496
Joined: Tue Feb 08, 2011 1:58 pm

Re: ps2 mouse driver in asm

Post by turdus »

Brendan is right (as usual), if I edit the post, I see tabs, and it look much better. Anyway, I linked this thread on wiki.
Post Reply