Rev 105 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
105 | pj | 1 | /* |
2 | * Project: S.Ha.R.K. |
||
3 | * |
||
4 | * Coordinators: |
||
5 | * Giorgio Buttazzo <giorgio@sssup.it> |
||
6 | * Paolo Gai <pj@gandalf.sssup.it> |
||
7 | * |
||
8 | * Authors : |
||
9 | * Paolo Gai <pj@gandalf.sssup.it> |
||
10 | * Massimiliano Giorgi <massy@gandalf.sssup.it> |
||
11 | * Luca Abeni <luca@gandalf.sssup.it> |
||
12 | * (see the web pages for full authors list) |
||
13 | * |
||
14 | * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy) |
||
15 | * |
||
16 | * http://www.sssup.it |
||
17 | * http://retis.sssup.it |
||
18 | * http://shark.sssup.it |
||
19 | */ |
||
20 | |||
21 | /** |
||
22 | ------------ |
||
723 | giacomo | 23 | CVS : $Id: mouse.c,v 1.2 2004-06-03 09:51:45 giacomo Exp $ |
105 | pj | 24 | |
25 | File: $File$ |
||
723 | giacomo | 26 | Revision: $Revision: 1.2 $ |
27 | Last update: $Date: 2004-06-03 09:51:45 $ |
||
105 | pj | 28 | ------------ |
29 | |||
30 | Author: Gerardo Lamastra |
||
31 | Date: 9/5/96 |
||
32 | |||
33 | Revision: 1.1b |
||
34 | Last update: 14/apr/1999 |
||
35 | |||
36 | Serial mouse driver |
||
37 | The mouse driver receives data from the serial RxServer() |
||
38 | Then it processes the mouse packet and sets the variables |
||
39 | representing the external mouse status. |
||
40 | |||
41 | **/ |
||
42 | |||
43 | /* |
||
44 | * Copyright (C) 2000 Paolo Gai |
||
45 | * |
||
46 | * This program is free software; you can redistribute it and/or modify |
||
47 | * it under the terms of the GNU General Public License as published by |
||
48 | * the Free Software Foundation; either version 2 of the License, or |
||
49 | * (at your option) any later version. |
||
50 | * |
||
51 | * This program is distributed in the hope that it will be useful, |
||
52 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
53 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
54 | * GNU General Public License for more details. |
||
55 | * |
||
56 | * You should have received a copy of the GNU General Public License |
||
57 | * along with this program; if not, write to the Free Software |
||
58 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
59 | * |
||
60 | */ |
||
61 | |||
62 | /* Revision 1.1 |
||
63 | * Author: Massimiliano Giorgi |
||
64 | * |
||
65 | * -- added support for PS/2 mouse |
||
66 | * |
||
67 | * Detailed changed from 1.0g: |
||
68 | * -- now mouse.c use "virtual operation" |
||
69 | * -- all procedure changed to use "virtual operation" |
||
70 | * ("virtual operation" are indipendent of the phisical device that |
||
71 | * is used to comunicate with mouse so it can handle serial mouse, ps/2 mouse) |
||
72 | * (all changed marked with a "MG") |
||
73 | */ |
||
74 | |||
75 | /* Revision 1.1b |
||
76 | * Author: Massimiliano Giorgi |
||
77 | * |
||
78 | * Changed to compile on 3.2.0 |
||
79 | * -- added wcet time |
||
80 | * -- RECEIVE ports now are STREAM ports |
||
81 | */ |
||
82 | |||
83 | /* |
||
84 | * Changelog: |
||
85 | * -- Added support for various serial mouse |
||
86 | * -- Virtual operations changed |
||
87 | * -- Added support for auto-pointer |
||
88 | */ |
||
89 | |||
90 | /* |
||
91 | * auto-pointer functions now are into |
||
92 | * mcurtxt.c and mcurgrx.c |
||
93 | * (to prevent automatic graphical library inclusion) |
||
94 | */ |
||
95 | |||
96 | //#include <string.h> |
||
97 | //#include <stdlib.h> |
||
98 | //#include <cons.h> |
||
99 | //#include <mem.h> |
||
100 | |||
101 | //#include "vm.h" |
||
102 | #include <kernel/kern.h> |
||
103 | //#include "exc.h" |
||
104 | |||
105 | #include <drivers/mouse.h> |
||
106 | |||
107 | /*if defined: then a trace of the initialization is performed */ |
||
108 | // #define __DEBUG_INIT__ |
||
109 | |||
110 | /* if defined: when a byte is received is displayed on the screen */ |
||
111 | //#define __XTRA_DEBUG_MOUSE__ |
||
112 | |||
113 | /* |
||
114 | * |
||
115 | * Operation on a virtual mouse |
||
116 | * (added by MG) |
||
117 | * |
||
118 | */ |
||
119 | |||
120 | #include "_mouse.h" |
||
121 | #include "sermouse.h" |
||
122 | #include "ps2mouse.h" |
||
123 | |||
124 | struct mouse_operations vmouse[]={ |
||
125 | |||
126 | {"ms", "The original ms protocol, with a middle-button extension.", |
||
127 | {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0, |
||
128 | sermouse_open, |
||
129 | sermouse_close, |
||
130 | sermouse_wait, |
||
131 | sermouse_get, |
||
132 | sermouse_enable, |
||
133 | sermouse_disable, |
||
134 | M_ms |
||
135 | }, |
||
136 | |||
137 | {"ms+", "Like 'ms', but allows dragging with the middle button.", |
||
138 | {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0, |
||
139 | sermouse_open, |
||
140 | sermouse_close, |
||
141 | sermouse_wait, |
||
142 | sermouse_get, |
||
143 | sermouse_enable, |
||
144 | sermouse_disable, |
||
145 | M_ms_plus |
||
146 | }, |
||
147 | |||
148 | {"ms+lr", "'ms+', but you can reset m by pressing lr.", |
||
149 | {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0, |
||
150 | sermouse_open, |
||
151 | sermouse_close, |
||
152 | sermouse_wait, |
||
153 | sermouse_get, |
||
154 | sermouse_enable, |
||
155 | sermouse_disable, |
||
156 | M_ms_plus_lr |
||
157 | }, |
||
158 | |||
159 | {"bare", "Unadorned ms protocol. Needed with some 2-buttons mice.", |
||
160 | {0x40, 0x40, 0x40, 0x00}, 3, 1, 0, 0, 0, |
||
161 | sermouse_open, |
||
162 | sermouse_close, |
||
163 | sermouse_wait, |
||
164 | sermouse_get, |
||
165 | sermouse_enable, |
||
166 | sermouse_disable, |
||
167 | M_bare |
||
168 | }, |
||
169 | |||
170 | {"msc", "Mouse-Systems-Compatible (5bytes). Most 3-button mice.", |
||
171 | {0xf8, 0x80, 0x00, 0x00}, 5, 1, 0, 0, 0, |
||
172 | sermouse_open, |
||
173 | sermouse_close, |
||
174 | sermouse_wait, |
||
175 | sermouse_get, |
||
176 | sermouse_enable, |
||
177 | sermouse_disable, |
||
178 | M_msc |
||
179 | }, |
||
180 | |||
181 | {"sun", "'msc' protocol, but only 3 bytes per packet.", |
||
182 | {0xf8, 0x80, 0x00, 0x00}, 3, 1, 0, 0, 0, |
||
183 | sermouse_open, |
||
184 | sermouse_close, |
||
185 | sermouse_wait, |
||
186 | sermouse_get, |
||
187 | sermouse_enable, |
||
188 | sermouse_disable, |
||
189 | M_sun |
||
190 | }, |
||
191 | |||
192 | {"mm", "MM series. Probably an old protocol...", |
||
193 | {0xe0, 0x80, 0x80, 0x00}, 3, 1, 0, 0, 0, |
||
194 | sermouse_open, |
||
195 | sermouse_close, |
||
196 | sermouse_wait, |
||
197 | sermouse_get, |
||
198 | sermouse_enable, |
||
199 | sermouse_disable, |
||
200 | M_mm |
||
201 | }, |
||
202 | |||
203 | {"logi", "Used in some Logitech devices (only serial).", |
||
204 | {0xe0, 0x80, 0x80, 0x00}, 3, 1, 0, 0, 0, |
||
205 | sermouse_open, |
||
206 | sermouse_close, |
||
207 | sermouse_wait, |
||
208 | sermouse_get, |
||
209 | sermouse_enable, |
||
210 | sermouse_disable, |
||
211 | M_logi |
||
212 | }, |
||
213 | |||
214 | {"ps2", "Busmice of the ps/2 series. Most busmice, actually.", |
||
215 | {0xc0, 0x00, 0x00, 0x00}, 3, 1, 0, 0, 0, |
||
216 | ps2mouse_open, |
||
217 | ps2mouse_close, |
||
218 | ps2mouse_wait, |
||
219 | ps2mouse_get, |
||
220 | ps2mouse_enable, |
||
221 | ps2mouse_disable, |
||
222 | M_ps2 |
||
223 | }, |
||
224 | |||
225 | {"\0", "", |
||
226 | {0, 0, 0, 0}, 0, 0, 0, 0, 0, |
||
227 | NULL, |
||
228 | NULL, |
||
229 | NULL, |
||
230 | NULL, |
||
231 | NULL, |
||
232 | NULL, |
||
233 | NULL |
||
234 | } |
||
235 | |||
236 | }; |
||
237 | |||
238 | int (*open_mouse)(void*); /* open comunication device */ |
||
239 | void (*close_mouse)(void); /* close comunication device */ |
||
240 | void (*wait_mouse)(void); /* wait to have a BYTE (blocking operation)*/ |
||
241 | int (*get_mouse)(BYTE *); /* get last BYTE */ |
||
242 | void (*enable_mouse)(void); /* enable interface */ |
||
243 | void (*disable_mouse)(void); /* disable interface */ |
||
244 | |||
245 | char *name_mouse; /* mouse name */ |
||
246 | char *desc_mouse; /* mouse description */ |
||
247 | BYTE *proto_mouse; /* mouse protocol (see below) */ |
||
248 | int packetlen_mouse; /* mouse packet lenght */ |
||
249 | |||
250 | int (*decode_mouse)(MOUSE_EVT *evt,unsigned char *data); |
||
251 | |||
252 | /* |
||
253 | * proto_mouse is used to syncronize the device driver: |
||
254 | * if A is the first byte read and B the second, this is a valid |
||
255 | * start of a mouse protocol packet if |
||
256 | * (A&proto_mouse[0])==proto_mouse[1])&&(b&proto_mouse[2])==proto_mouse[3]) |
||
257 | */ |
||
258 | |||
259 | /* type of mouse to use for virtual operation */ |
||
260 | int mousetype=NOMOUSE; |
||
261 | |||
262 | /* fill the variabled used to call the virtuals operations */ |
||
263 | static void mouse_settype(int type) |
||
264 | { |
||
265 | mousetype=type; |
||
266 | |||
267 | open_mouse =vmouse[mousetype].open; |
||
268 | close_mouse =vmouse[mousetype].close; |
||
269 | wait_mouse =vmouse[mousetype].wait; |
||
270 | get_mouse =vmouse[mousetype].get; |
||
271 | enable_mouse =vmouse[mousetype].enable; |
||
272 | disable_mouse=vmouse[mousetype].disable; |
||
273 | |||
274 | name_mouse =vmouse[mousetype].name; |
||
275 | desc_mouse =vmouse[mousetype].desc; |
||
276 | proto_mouse =vmouse[mousetype].proto; |
||
277 | packetlen_mouse=vmouse[mousetype].packetlen; |
||
278 | |||
279 | decode_mouse=vmouse[mousetype].decode; |
||
280 | } |
||
281 | |||
282 | /* |
||
283 | * |
||
284 | * end (operation on a virtual mouse) |
||
285 | * |
||
286 | */ |
||
287 | |||
288 | /* MG: this are no "static" (they are used by sermouse.c, ps2mouse.c) */ |
||
289 | /* "threshold" renamed "mouse_thresholdlim" */ |
||
290 | short int mouse_lim_x1 = 0; |
||
291 | short int mouse_lim_y1 = 0; |
||
292 | short int mouse_lim_x2 = 79; |
||
293 | short int mouse_lim_y2 = 24; |
||
294 | short int mouse_x = 40; |
||
295 | short int mouse_x_mick = 0; |
||
296 | short int mouse_y = 12; |
||
297 | short int mouse_y_mick = 0; |
||
298 | short int mouse_buttons = 0; |
||
299 | short int mouse_thresholdlim = 5; |
||
300 | MOUSE_HANDLER mouse_handler = NULL; |
||
301 | |||
302 | MOUSE_HANDLER user_mouse_handler = NULL; |
||
303 | int autocursormode=DISABLE; |
||
304 | |||
305 | static PID mouse_pid = NIL; |
||
306 | |||
307 | /* |
||
308 | * this is a general mouse server |
||
309 | * useable by most mouse protocol implementation |
||
310 | */ |
||
311 | |||
312 | TASK generalmouse_server(void) |
||
313 | { |
||
314 | static MOUSE_EVT event; |
||
315 | BYTE data[8]; |
||
316 | int index; |
||
317 | int mickey; |
||
318 | |||
319 | #ifdef __XTRA_DEBUG_MOUSE__ |
||
320 | char str[40]; |
||
321 | #endif |
||
322 | |||
323 | index=0; |
||
324 | for(;;) { |
||
325 | #ifdef __XTRA_DEBUG_MOUSE__ |
||
326 | puts_xy(0,11,WHITE,"Waiting.."); |
||
327 | #endif |
||
328 | |||
329 | /* wait for mouse data */ |
||
330 | wait_mouse(); |
||
331 | |||
332 | /* get mouse data */ |
||
333 | //data[index]=get_mouse(); |
||
334 | index+=get_mouse(data+index); |
||
335 | |||
336 | #ifdef __XTRA_DEBUG_MOUSE__ |
||
337 | sprintf(str,"Mouse data[%01d]: %2x",index,data[index]); |
||
338 | puts_xy(0,12+index,WHITE,str); |
||
339 | #endif |
||
340 | |||
341 | switch (index) { |
||
342 | case 1: |
||
343 | if ((data[0]&proto_mouse[0])!=proto_mouse[1]) index=0; |
||
344 | break; |
||
345 | case 2: |
||
346 | if ((data[1]&proto_mouse[2])==proto_mouse[3]) index=0; |
||
347 | break; |
||
348 | default: |
||
349 | if (index<packetlen_mouse) break; |
||
350 | |||
351 | if (decode_mouse(&event,data)==0) { |
||
352 | |||
353 | /* Y */ |
||
354 | mickey=event.dy; |
||
355 | mouse_y_mick += mickey; |
||
356 | while (mouse_y_mick > mouse_thresholdlim) { |
||
357 | mouse_y++; |
||
358 | mouse_y_mick -= mouse_thresholdlim; |
||
359 | } |
||
360 | while (mouse_y_mick < -mouse_thresholdlim) { |
||
361 | mouse_y--; |
||
362 | mouse_y_mick += mouse_thresholdlim; |
||
363 | } |
||
364 | if (mouse_y > mouse_lim_y2) mouse_y = mouse_lim_y2; |
||
365 | else if (mouse_y < mouse_lim_y1) mouse_y = mouse_lim_y1; |
||
366 | event.y=mouse_y; |
||
367 | |||
368 | /* X */ |
||
369 | mickey = event.dx; |
||
370 | mouse_x_mick += mickey; |
||
371 | while (mouse_x_mick > mouse_thresholdlim) { |
||
372 | mouse_x++; |
||
373 | mouse_x_mick -= mouse_thresholdlim; |
||
374 | } |
||
375 | while (mouse_x_mick < -mouse_thresholdlim) { |
||
376 | mouse_x--; |
||
377 | mouse_x_mick += mouse_thresholdlim; |
||
378 | } |
||
379 | if (mouse_x > mouse_lim_x2) mouse_x = mouse_lim_x2; |
||
380 | else if (mouse_x < mouse_lim_x1) mouse_x = mouse_lim_x1; |
||
381 | event.x=mouse_x; |
||
382 | |||
383 | /* mouse handler */ |
||
384 | if (mouse_handler!=NULL) mouse_handler(&event); |
||
385 | } |
||
386 | |||
387 | index-=packetlen_mouse; |
||
388 | if (index!=0) memcpy(data,data+packetlen_mouse,index); |
||
389 | break; |
||
390 | |||
391 | } /* switch */ |
||
392 | } /* for */ |
||
393 | } |
||
394 | |||
395 | /* [for SERIAL MOUSE] */ |
||
396 | /* Well, this implementation is a little dispendious as we use */ |
||
397 | /* two different tasks, one as serial receiver, the other as */ |
||
398 | /* mouse-protocol decoder; this has been chosen in order to */ |
||
399 | /* make any mouse-protocol easier. We only need to rewrite the */ |
||
400 | /* the appropriate mouse packet interpreter */ |
||
401 | |||
402 | /* |
||
403 | * MG: rewritten to handle serial and PS/2 mouse and other mouses |
||
404 | */ |
||
405 | |||
406 | /* changed user interface */ |
||
407 | |||
408 | |||
409 | int mouse_init(MOUSE_PARMS *parms) |
||
410 | { |
||
411 | int status=0; |
||
412 | TASK_MODEL *m; |
||
413 | SOFT_TASK_MODEL base_m; |
||
414 | MOUSE_PARMS mparms=BASE_MOUSE; |
||
415 | |||
416 | #ifdef __DEBUG_INIT__ |
||
417 | cprintf("mouse_init: START\n"); |
||
418 | #endif |
||
419 | |||
420 | if (mouse_pid != NIL) return -1; |
||
421 | if (parms==NULL) parms=&mparms; |
||
422 | |||
423 | /* default values */ |
||
424 | |||
425 | #ifdef __DEBUG_INIT__ |
||
426 | cprintf("mouse_init: default values\n"); |
||
427 | #endif |
||
428 | |||
429 | if (parms->tm == (TASK_MODEL *)MOUSE_DEFAULT) { |
||
430 | soft_task_default_model(base_m); |
||
431 | soft_task_def_wcet(base_m,2000); |
||
432 | soft_task_def_met(base_m,500); |
||
433 | soft_task_def_period(base_m,8000); |
||
434 | soft_task_def_system(base_m); |
||
435 | soft_task_def_nokill(base_m); |
||
436 | soft_task_def_aperiodic(base_m); |
||
437 | m = (TASK_MODEL *)&base_m; |
||
438 | } |
||
439 | else |
||
440 | m = parms->tm; |
||
441 | |||
442 | /* try autodetect mouse() */ |
||
443 | if (parms->type==MOUSE_DEFAULT) { |
||
444 | SERMOUSE_INFO *sinfoptr; |
||
445 | |||
446 | #ifdef __DEBUG_INIT__ |
||
447 | cprintf("mouse_init: try autodetecting\n"); |
||
448 | #endif |
||
449 | |||
450 | if (ps2mouse_present()) parms->type=PS2MOUSE; |
||
451 | else { |
||
452 | sinfoptr=sermouse_present(); |
||
453 | if (sinfoptr==NULL) return -2; |
||
454 | parms->type=sinfoptr->type; |
||
455 | parms->port=sinfoptr->port; |
||
456 | } |
||
457 | } |
||
458 | |||
459 | mouse_settype(parms->type); |
||
460 | switch(mousetype) { |
||
461 | case PS2MOUSE: |
||
462 | /* max PS/2 mouse rate: 40 event per second with 3 bytes per event */ |
||
463 | /* 120 bytes/sec -> 8 msec between activation (I hope)*/ |
||
464 | |||
465 | #ifdef __DEBUG_INIT__ |
||
466 | cprintf("mouse_init: creating ps2 server task\n"); |
||
467 | #endif |
||
468 | |||
469 | if (parms->tm==(TASK_MODEL *)MOUSE_DEFAULT) |
||
470 | soft_task_def_period(base_m,8000); |
||
471 | mouse_pid=task_create("PS2Mouse", |
||
472 | ps2mouse_getserveraddr(), |
||
473 | m, NULL); |
||
474 | if (mouse_pid==-1) return -3; |
||
475 | |||
476 | //task_activate(mouse_pid); |
||
477 | |||
478 | #ifdef __DEBUG_INIT__ |
||
479 | cprintf("mouse_init: opening mouse\n"); |
||
480 | #endif |
||
481 | |||
482 | status=open_mouse((void*)&mouse_pid); |
||
483 | break; |
||
484 | |||
485 | case MSMOUSE: |
||
486 | case MSPMOUSE: |
||
487 | case MSPLRMOUSE: |
||
488 | case BAREMOUSE: |
||
489 | case MSCMOUSE: |
||
490 | case SUNMOUSE: |
||
491 | case LOGIMOUSE: |
||
492 | case MMMOUSE: |
||
493 | break; |
||
494 | } |
||
495 | |||
496 | if (status!=0) { |
||
497 | task_kill(mouse_pid); |
||
498 | mouse_pid=NIL; |
||
499 | return -4; |
||
500 | } |
||
501 | |||
502 | #ifdef __DEBUG_INIT__ |
||
503 | cputs("mouse_init: mouse activated\n"); |
||
504 | #endif |
||
505 | |||
506 | return 0; |
||
507 | } |
||
508 | |||
509 | void mouse_end(void) |
||
510 | { |
||
511 | if (mouse_pid==NIL) return; |
||
512 | task_kill(mouse_pid); |
||
513 | mouse_pid=NIL; |
||
514 | close_mouse(); |
||
515 | } |
||
516 | |||
517 | /* MG: all the following procedure are modified */ |
||
518 | /* to use virtual operation */ |
||
519 | |||
520 | void mouse_disable(void) |
||
521 | { |
||
522 | disable_mouse(); |
||
523 | } |
||
524 | |||
525 | void mouse_enable(void) |
||
526 | { |
||
527 | enable_mouse(); |
||
528 | } |
||
529 | |||
530 | void mouse_get(int *x,int *y,BYTE *button) |
||
531 | { |
||
532 | if (x != NULL) *x = mouse_x; |
||
533 | if (y != NULL) *y = mouse_y; |
||
534 | if (button != NULL) *button = mouse_buttons; |
||
535 | } |
||
536 | |||
537 | void mouse_position(int x,int y) |
||
538 | { |
||
539 | disable_mouse(); |
||
540 | mouse_x = x; |
||
541 | mouse_y = y; |
||
542 | enable_mouse(); |
||
543 | } |
||
544 | |||
545 | void mouse_limit(int x1,int y1,int x2,int y2) |
||
546 | { |
||
547 | disable_mouse(); |
||
548 | mouse_lim_x1 = x1; |
||
549 | mouse_lim_y1 = y1; |
||
550 | mouse_lim_x2 = x2; |
||
551 | mouse_lim_y2 = y2; |
||
552 | mouse_x = (x1+x2)/2; |
||
553 | mouse_y = (y1+y2)/2; |
||
554 | enable_mouse(); |
||
555 | } |
||
556 | |||
557 | void mouse_threshold(unsigned t) |
||
558 | { |
||
559 | disable_mouse(); |
||
560 | if (t < 1) t = 1; |
||
561 | else if (t > 100) t = 100; |
||
562 | mouse_thresholdlim = t; |
||
563 | enable_mouse(); |
||
564 | } |
||
565 | |||
566 | void mouse_hook(MOUSE_HANDLER h) |
||
567 | { |
||
568 | /* changed to use the autocursor functions */ |
||
569 | if ((autocursormode&STATUSMASK)==DISABLE) { |
||
570 | mouse_handler = h; |
||
571 | } else { |
||
572 | user_mouse_handler = h; |
||
573 | } |
||
574 | } |