Fixed possible memory corruption in commands exec and netexec; fixed command netcp...
[ZeXOS.git] / kernel / drivers / char / mouse / ps2.c
blobc65cdeabac91d4cc7182a2566f6b7608a73709ab
1 /*
2 * ZeX/OS
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/>.
20 #include <build.h>
22 #ifdef ARCH_i386
24 #include <system.h>
25 #include <arch/io.h>
26 #include <mouse.h>
27 #include <task.h>
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 ()
66 int timeout;
68 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++) {
69 if((inb (PS2MOUSE_CTRL) && 0x02) != 0x02)
70 break;
73 outb (PS2MOUSE_CTRL, PS2MOUSE_COMMAND);
74 outb (PS2MOUSE_PORT, PS2MOUSE_COMMAND_RESET);
76 int ack = 0;
78 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++) {
79 unsigned char state = ps2mouse_read ();
81 if (state == PS2MOUSE_ACK)
82 ack = 1;
84 if (ack && state == PS2MOUSE_RESET_ACK)
85 return 1;
87 if (state == -1)
88 return 0;
91 return -1;
94 /* ps2mouse_write - send a command to mouse */
96 unsigned ps2mouse_write (unsigned char command)
98 int timeout;
100 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++) {
101 if((inb (PS2MOUSE_CTRL) && 0x02) != 0x02)
102 break;
105 outb (PS2MOUSE_CTRL, PS2MOUSE_COMMAND);
106 outb (PS2MOUSE_PORT, command);
108 short read = ps2mouse_read ();
110 if (read == PS2MOUSE_ACK)
111 return 1;
113 if (read == -1)
114 return 0;
116 return 0;
119 /* ps2mouse_read - read a value from mouse */
121 unsigned char ps2mouse_read ()
123 int timeout;
125 for (timeout = 0; timeout < PS2MOUSE_TIMEOUT; timeout ++) {
126 if ((inb (PS2MOUSE_CTRL) && 0x01) == 0x01)
127 return inb (PS2MOUSE_PORT);
130 return -1;
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)
140 return 0;
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);
156 short dx, dy, dz;
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)
163 dx *= 4;
164 if (dy > 5 || dy < -5)
165 dy *= 4;
167 ps2mouse_state.pos_x = dx;
168 ps2mouse_state.pos_y = dy;
170 if (dz > 0)
171 ps2mouse_state.flags = ps2mouse_state.flags | MOUSE_FLAG_SCROLLUP;
172 if (dz < 0)
173 ps2mouse_state.flags = ps2mouse_state.flags | MOUSE_FLAG_SCROLLDOWN;
175 return 1;
178 unsigned char ps2mouse_get_mouseid ()
180 short mouse_id;
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 ();
194 if (mouse_id < 3)
195 goto ret;
196 else
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 ();
211 if (mouse_id > 3)
212 ps2mouse_extbuttons = true;
213 ret:
214 return mouse_id;
217 unsigned ps2mouse_init ()
219 int timeout;
221 ps2mouse_extbuttons = false;
222 ps2mouse_extwheel = false;
224 if (ps2mouse_reset () != 1)
225 return 0;
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);
231 return 0;
234 if (ps2mouse_get_mouseid () == -1)
235 return 0;
237 ps2mouse_write (PS2MOUSE_COMMAND_SET_REMOTE);
238 ps2mouse_write (PS2MOUSE_COMMAND_ENABLE_PACKETS);
240 return 1;
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)
253 switch (act) {
254 case DEV_ACT_INIT:
256 dev_flags_t *flags = (dev_flags_t *) block;
258 if (!flags)
259 return 0;
261 if (block_len != sizeof (dev_flags_t))
262 return 0;
264 unsigned r = ps2mouse_init ();
266 if (!r)
267 return 0;
269 flags->iomem = (void *) &ps2mouse_state;
270 flags->iolen = sizeof (dev_mouse_t);
272 //task_t *task = task_create ("mouseps2", (unsigned) &ps2mouse_update, 255);
274 return r;
276 break;
277 case DEV_ACT_READ:
279 memcpy (block, &ps2mouse_state, sizeof (dev_mouse_t));
281 return 1;
283 break;
284 case DEV_ACT_WRITE:
286 memcpy (&ps2mouse_state, block, sizeof (dev_mouse_t));
288 return 1;
290 break;
291 case DEV_ACT_UPDATE:
293 ps2mouse_get_state ();
295 return 1;
297 break;
300 return 0;
303 #endif