Added GNU GPL license header to ps2_dev.h.
[ZeXOS.git] / kernel / drivers / char / mouse / ps2.c
blob380167074c589cc257225c95ef7dbaea183ed12d
1 /*
2 * ZeX/OS
3 * Copyright (C) 2009 Martin 'povik' Poviser (martin.povik@gmail.com)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <build.h>
21 #ifdef ARCH_i386
23 #include <system.h>
24 #include <arch/io.h>
25 #include <mouse.h>
27 #define PS2MOUSE_SAMPLES 0x64 // Samples in second - 0x50 for 80, 0x64 for 100, 0xC8 for 200
28 #define PS2MOUSE_RESOLUTION 2
30 #define PS2MOUSE_TIMEOUT 500000
31 #define PS2MOUSE_ACK 0xFA
32 #define PS2MOUSE_PORT 0x60
33 #define PS2MOUSE_CTRL 0x64
34 #define PS2MOUSE_COMMAND 0xD4
35 #define PS2MOUSE_COMMAND_RESET 0xFF
36 #define PS2MOUSE_COMMAND_GET_MOUSE_ID 0xF2
37 #define PS2MOUSE_COMMAND_GET_PACKET 0xEB
38 #define PS2MOUSE_COMMAND_ENABLE_PACKETS 0xF4
39 #define PS2MOUSE_COMMAND_SET_SAMPLERATE 0xF3
40 #define PS2MOUSE_COMMAND_SET_RESOLUTION 0xE8
41 #define PS2MOUSE_COMMAND_SET_REMOTE 0xF0
42 #define PS2MOUSE_RESET_ACK 0xAA
43 #define PS2MOUSE_IRQ 12
45 #define PS2MOUSE_SAMPLERATE_80 0x50
46 #define PS2MOUSE_SAMPLERATE_100 0x64
47 #define PS2MOUSE_SAMPLERATE_200 0xC8
49 #define PS2MOUSE_SAMPLERATE PS2MOUSE_SAMPLERATE_100
52 bool ps2mouse_extwheel = 0;
53 bool ps2mouse_extbuttons = 0;
55 short mouse_id;
57 dev_mouse_t ps2mouse_state;
59 bool ps2mouse_reset ();
60 bool ps2mouse_write (unsigned char command);
61 short ps2mouse_read ();
63 /* ps2mouse_reset - reset mouse */
65 bool ps2mouse_reset ()
67 int timeout;
69 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++)
71 if((inb (PS2MOUSE_CTRL) && 0x02) != 0x02)
72 break;
73 schedule ();
76 outb (PS2MOUSE_CTRL, PS2MOUSE_COMMAND);
77 outb (PS2MOUSE_PORT, PS2MOUSE_COMMAND_RESET);
79 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++)
81 int read = ps2mouse_read ();
82 if (read == PS2MOUSE_RESET_ACK)
83 return 1;
85 if (read == -1)
86 return 0;
88 schedule ();
91 return 0;
94 /* ps2mouse_write - send a command to mouse */
96 bool ps2mouse_write (unsigned char command)
98 int timeout;
100 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++)
102 if((inb (PS2MOUSE_CTRL) && 0x02) != 0x02)
103 break;
104 schedule ();
107 outb (PS2MOUSE_CTRL, PS2MOUSE_COMMAND);
108 outb (PS2MOUSE_PORT, command);
110 short read = ps2mouse_read ();
112 if (read == PS2MOUSE_ACK)
113 return 1;
115 if (read == -1)
116 return 0;
118 return 0;
121 /* ps2mouse_read - read a value from mouse */
123 short ps2mouse_read()
125 int timeout;
127 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++)
129 if ((inb (PS2MOUSE_CTRL) && 0x01) == 0x01)
130 return inb (PS2MOUSE_PORT);
131 schedule ();
134 return -1;
137 /* ps2mouse_get_state - get a mouse state */
139 bool ps2mouse_get_state ()
141 unsigned char b1, b2, b3, b4 = 0;
143 if (ps2mouse_write (PS2MOUSE_COMMAND_GET_PACKET) == -1)
144 return 0;
146 b1 = ps2mouse_read ();
147 b2 = ps2mouse_read ();
148 b3 = ps2mouse_read ();
150 if (ps2mouse_extwheel || ps2mouse_extbuttons)
151 b4 = ps2mouse_read ();
153 ps2mouse_state.flags = 0;
154 ps2mouse_state.flags |= ((b1 & 1) ? MOUSE_FLAG_BUTTON1 : 0);
155 ps2mouse_state.flags |= ((b1 & 2) ? MOUSE_FLAG_BUTTON2 : 0);
156 ps2mouse_state.flags |= ((b1 & 3) ? MOUSE_FLAG_BUTTON3 : 0);
157 ps2mouse_state.flags |= ((b1 & 4) ? MOUSE_FLAG_BUTTON4 : 0);
158 ps2mouse_state.flags |= ((b1 & 5) ? MOUSE_FLAG_BUTTON5 : 0);
160 short dx, dy, dz;
162 dx = (b1 & 0x10) ? b2 - 256 : b2;
163 dy = (b1 & 0x20) ? -(b3 - 256) : -b3;
164 dz = (b4 & 0x08) ? (b4 & 7) - 8 : b4 & 7;
166 if (dx > 5 || dx < -5)
167 dx *= 4;
168 if (dy > 5 || dy < -5)
169 dy *= 4;
171 ps2mouse_state.pos_x = dx;
172 ps2mouse_state.pos_y = dy;
174 if (dz > 0)
175 ps2mouse_state.flags = ps2mouse_state.flags | MOUSE_FLAG_SCROLLUP;
176 if (dz < 0)
177 ps2mouse_state.flags = ps2mouse_state.flags | MOUSE_FLAG_SCROLLDOWN;
179 return 1;
182 void ps2mouse_get_mouseid ()
184 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
185 ps2mouse_write (PS2MOUSE_SAMPLERATE_200);
187 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
188 ps2mouse_write (PS2MOUSE_SAMPLERATE_100);
190 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
191 ps2mouse_write (PS2MOUSE_SAMPLERATE_80);
193 ps2mouse_write (PS2MOUSE_COMMAND_GET_MOUSE_ID);
194 mouse_id = ps2mouse_read ();
196 if (mouse_id < 3)
197 return;
198 else
199 ps2mouse_extwheel = true;
201 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
202 ps2mouse_write (PS2MOUSE_SAMPLERATE_200);
204 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
205 ps2mouse_write (PS2MOUSE_SAMPLERATE_200);
207 ps2mouse_write (PS2MOUSE_COMMAND_SET_SAMPLERATE);
208 ps2mouse_write (PS2MOUSE_SAMPLERATE_80);
210 ps2mouse_write (PS2MOUSE_COMMAND_GET_MOUSE_ID);
211 mouse_id = ps2mouse_read ();
213 if (mouse_id > 3)
214 ps2mouse_extbuttons = true;
217 unsigned ps2mouse_init ()
219 int timeout;
221 ps2mouse_extbuttons = false;
222 ps2mouse_extwheel = false;
224 if(ps2mouse_reset () == 0)
225 return 0;
227 ps2mouse_read (); // Mouse send her ID
229 ps2mouse_get_mouseid ();
231 if (mouse_id == -1)
232 return 0;
234 ps2mouse_write (PS2MOUSE_COMMAND_SET_REMOTE);
235 ps2mouse_write (PS2MOUSE_COMMAND_ENABLE_PACKETS);
237 return 1;
240 bool ps2mouse_acthandler (unsigned act, char *block, unsigned block_len)
242 switch (act) {
243 case DEV_ACT_INIT:
245 return ps2mouse_init ();
247 break;
248 case DEV_ACT_READ:
250 if(!ps2mouse_get_state ())
251 return 0;
252 memcpy (block, &ps2mouse_state, sizeof (dev_mouse_t));
253 return 1;
255 break;
256 case DEV_ACT_WRITE:
258 return 0;
260 break;
263 return 0;
266 #endif