3 * Copyright (C) 2009 Martin 'povik' Poviser (martin.povik@gmail.com)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 #define KBD_CCMD_KBD_DISABLE 0xAD
31 #define PS2MOUSE_TIMEOUT 500000
32 #define PS2MOUSE_ACK 0xFA
33 #define PS2MOUSE_PORT 0x60
34 #define PS2MOUSE_CTRL 0x64
35 #define PS2MOUSE_COMMAND 0xD4
36 #define PS2MOUSE_COMMAND_RESET 0xFF
37 #define PS2MOUSE_COMMAND_GET_MOUSE_ID 0xF2
38 #define PS2MOUSE_COMMAND_GET_PACKET 0xEB
39 #define PS2MOUSE_COMMAND_ENABLE_PACKETS 0xF4
40 #define PS2MOUSE_COMMAND_SET_SAMPLERATE 0xF3
41 #define PS2MOUSE_COMMAND_SET_RESOLUTION 0xE8
42 #define PS2MOUSE_COMMAND_SET_REMOTE 0xF0
43 #define PS2MOUSE_RESET_ACK 0xAA
44 #define PS2MOUSE_IRQ 12
46 #define PS2MOUSE_SAMPLERATE_80 0x50
47 #define PS2MOUSE_SAMPLERATE_100 0x64
48 #define PS2MOUSE_SAMPLERATE_200 0xC8
50 #define PS2MOUSE_SAMPLERATE PS2MOUSE_SAMPLERATE_100
53 static unsigned ps2mouse_extwheel
= 0;
54 static unsigned ps2mouse_extbuttons
= 0;
56 static dev_mouse_t ps2mouse_state
;
58 static unsigned ps2mouse_reset ();
59 static unsigned ps2mouse_write (unsigned char command
);
60 static unsigned char ps2mouse_read ();
62 /* ps2mouse_reset - reset mouse */
64 unsigned ps2mouse_reset ()
68 for (timeout
= 0; timeout
< PS2MOUSE_TIMEOUT
; timeout
++) {
69 if((inb (PS2MOUSE_CTRL
) && 0x02) != 0x02)
73 outb (PS2MOUSE_CTRL
, PS2MOUSE_COMMAND
);
74 outb (PS2MOUSE_PORT
, PS2MOUSE_COMMAND_RESET
);
78 for (timeout
= 0; timeout
< PS2MOUSE_TIMEOUT
; timeout
++) {
79 unsigned char state
= ps2mouse_read ();
81 if (state
== PS2MOUSE_ACK
)
84 if (ack
&& state
== PS2MOUSE_RESET_ACK
)
94 /* ps2mouse_write - send a command to mouse */
96 unsigned ps2mouse_write (unsigned char command
)
100 for (timeout
= 0; timeout
< PS2MOUSE_TIMEOUT
; timeout
++) {
101 if((inb (PS2MOUSE_CTRL
) && 0x02) != 0x02)
105 outb (PS2MOUSE_CTRL
, PS2MOUSE_COMMAND
);
106 outb (PS2MOUSE_PORT
, command
);
108 short read
= ps2mouse_read ();
110 if (read
== PS2MOUSE_ACK
)
119 /* ps2mouse_read - read a value from mouse */
121 unsigned char ps2mouse_read ()
125 for (timeout
= 0; timeout
< PS2MOUSE_TIMEOUT
; timeout
++) {
126 if ((inb (PS2MOUSE_CTRL
) && 0x01) == 0x01)
127 return inb (PS2MOUSE_PORT
);
133 /* ps2mouse_get_state - get a mouse state */
135 unsigned ps2mouse_get_state ()
137 unsigned char b1
, b2
, b3
, b4
= 0;
139 if (ps2mouse_write (PS2MOUSE_COMMAND_GET_PACKET
) == -1)
142 b1
= ps2mouse_read ();
143 b2
= ps2mouse_read ();
144 b3
= ps2mouse_read ();
146 if (ps2mouse_extwheel
|| ps2mouse_extbuttons
)
147 b4
= ps2mouse_read ();
149 ps2mouse_state
.flags
= 0;
150 ps2mouse_state
.flags
|= ((b1
& 1) ? MOUSE_FLAG_BUTTON1
: 0);
151 ps2mouse_state
.flags
|= ((b1
& 2) ? MOUSE_FLAG_BUTTON2
: 0);
152 ps2mouse_state
.flags
|= ((b1
& 3) ? MOUSE_FLAG_BUTTON3
: 0);
153 ps2mouse_state
.flags
|= ((b1
& 4) ? MOUSE_FLAG_BUTTON4
: 0);
154 ps2mouse_state
.flags
|= ((b1
& 5) ? MOUSE_FLAG_BUTTON5
: 0);
158 dx
= (b1
& 0x10) ? b2
- 256 : b2
;
159 dy
= (b1
& 0x20) ? -(b3
- 256) : -b3
;
160 dz
= (b4
& 0x08) ? (b4
& 7) - 8 : b4
& 7;
162 if (dx
> 5 || dx
< -5)
164 if (dy
> 5 || dy
< -5)
167 ps2mouse_state
.pos_x
= dx
;
168 ps2mouse_state
.pos_y
= dy
;
171 ps2mouse_state
.flags
= ps2mouse_state
.flags
| MOUSE_FLAG_SCROLLUP
;
173 ps2mouse_state
.flags
= ps2mouse_state
.flags
| MOUSE_FLAG_SCROLLDOWN
;
178 unsigned char ps2mouse_get_mouseid ()
182 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE
);
183 ps2mouse_write (PS2MOUSE_SAMPLERATE_200
);
185 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE
);
186 ps2mouse_write (PS2MOUSE_SAMPLERATE_100
);
188 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE
);
189 ps2mouse_write (PS2MOUSE_SAMPLERATE_80
);
191 ps2mouse_write (PS2MOUSE_COMMAND_GET_MOUSE_ID
);
192 mouse_id
= ps2mouse_read ();
197 ps2mouse_extwheel
= true;
199 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE
);
200 ps2mouse_write (PS2MOUSE_SAMPLERATE_200
);
202 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE
);
203 ps2mouse_write (PS2MOUSE_SAMPLERATE_200
);
205 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE
);
206 ps2mouse_write (PS2MOUSE_SAMPLERATE_80
);
208 ps2mouse_write (PS2MOUSE_COMMAND_GET_MOUSE_ID
);
209 mouse_id
= ps2mouse_read ();
212 ps2mouse_extbuttons
= true;
217 unsigned ps2mouse_init ()
221 ps2mouse_extbuttons
= false;
222 ps2mouse_extwheel
= false;
224 if (ps2mouse_reset () != 1)
227 unsigned char type
= ps2mouse_read ();
229 if (type
!= 0) { /* mouse type: 0 = PS2, 3 = IMPS/2, 4 = IMEX */
230 kprintf ("> ps2mouse : failed while detecting mouse type (%d), should be (0)\n", type
);
234 if (ps2mouse_get_mouseid () == -1)
237 ps2mouse_write (PS2MOUSE_COMMAND_SET_REMOTE
);
238 ps2mouse_write (PS2MOUSE_COMMAND_ENABLE_PACKETS
);
243 void ps2mouse_update ()
245 for (;; schedule ()) {
246 if (!ps2mouse_state
.pos_x
&& !ps2mouse_state
.pos_y
)
247 ps2mouse_get_state ();
251 bool ps2mouse_acthandler (unsigned act
, char *block
, unsigned block_len
)
256 dev_flags_t
*flags
= (dev_flags_t
*) block
;
261 if (block_len
!= sizeof (dev_flags_t
))
264 unsigned r
= ps2mouse_init ();
269 flags
->iomem
= (void *) &ps2mouse_state
;
270 flags
->iolen
= sizeof (dev_mouse_t
);
272 //task_t *task = task_create ("mouseps2", (unsigned) &ps2mouse_update, 255);
279 memcpy (block
, &ps2mouse_state
, sizeof (dev_mouse_t
));
286 memcpy (&ps2mouse_state
, block
, sizeof (dev_mouse_t
));
293 ps2mouse_get_state ();