FreeBSD/Linux Kernel Cross Reference
sys/i386at/kd_mouse.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: kd_mouse.c,v $
29 * Revision 2.16 93/08/10 15:57:52 mrt
30 * Make protocol 5 (-- minor [40-47] ) be Microsoft mouse
31 * but 7 bits. If this works universally, change protocol 1.
32 * [93/08/03 rvb]
33 * Support Logitech TrackMan mouse (V [or M+]) protocol as
34 * protocol 4 -- minor [32-39]
35 *
36 * Revision 2.15 93/05/11 13:58:56 rvb
37 * Typo
38 *
39 * Revision 2.14 93/05/10 21:19:45 rvb
40 * Lint.
41 * [93/05/08 11:22:15 af]
42 *
43 * Revision 2.13 93/05/10 17:43:39 rvb
44 * Allow for mouse speed to be patchable
45 *
46 * Revision 2.12 93/01/24 13:18:05 danner
47 * Added 3 button ps2 mouse from Jim Reese.
48 * [93/01/19 13:15:08 rvb]
49 *
50 * Revision 2.11 93/01/14 17:31:28 danner
51 * Proper spl typing.
52 * [92/11/30 af]
53 *
54 * Revision 2.10 92/07/09 22:54:39 rvb
55 * Fix microsoft 2 button mouse emulation to ignore two buttons down
56 * simultaneously and let X11R5 handle it.
57 * [92/07/06 rvb]
58 *
59 * Revision 2.9 92/02/19 16:30:17 elf
60 * On ps2_mouse_close, wait a bit and then drain console. For
61 * T2200 and sometime the IBM axion bus extender, data will show
62 * up after a while (a 0) w/o interrupt and your kbd would hang.
63 * [92/01/30 rvb]
64 *
65 * Allow for only "keyboard mouse". Does not use serial line.
66 * [92/01/25 rvb]
67 *
68 * Revision 2.8 91/10/07 17:26:02 af
69 * Add support for ibm ps2 "keyboard" mouse. Try to be general
70 * about it to support other "keyboard mice", but we don't have
71 * any.
72 * [91/09/25 rvb]
73 * Add support for MicroSoft 2 button Mouse from 2.5
74 * [91/09/04 rvb]
75 *
76 * Revision 2.7 91/08/24 11:58:51 af
77 * New MI autoconf.
78 * [91/08/02 02:49:38 af]
79 *
80 * Revision 2.6 91/05/14 16:27:26 mrt
81 * Correcting copyright
82 *
83 * Revision 2.5 91/02/05 17:19:17 mrt
84 * Changed to new Mach copyright
85 * [91/02/01 17:45:43 mrt]
86 *
87 * Revision 2.4 91/01/08 17:33:25 rpd
88 * Trim $ Header
89 * [90/11/27 11:44:31 rvb]
90 *
91 * Revision 2.3 90/11/26 14:50:33 rvb
92 * jsb bet me to XMK34, sigh ...
93 * [90/11/26 rvb]
94 * Synched 2.5 & 3.0 at I386q (r1.5.1.5) & XMK35 (r2.3)
95 * [90/11/15 rvb]
96 *
97 * Revision 1.5.1.4 90/07/10 11:45:04 rvb
98 * Allow mouse minor to select the serial line the mouse is on.
99 * [90/06/15 rvb]
100 *
101 * Revision 2.2 90/05/21 13:27:25 dbg
102 * Convert for pure kernel.
103 * [90/04/24 dbg]
104 *
105 * Revision 1.5.1.3 90/02/28 15:50:25 rvb
106 * Fix numerous typo's in Olivetti disclaimer.
107 * [90/02/28 rvb]
108 *
109 * Revision 1.5.1.2 90/01/08 13:30:55 rvb
110 * Add Olivetti copyright.
111 * [90/01/08 rvb]
112 *
113 * Revision 1.5.1.1 89/10/22 11:34:32 rvb
114 * Received from Intel October 5, 1989.
115 * [89/10/13 rvb]
116 *
117 * Revision 1.5 89/07/17 10:41:24 rvb
118 * Olivetti Changes to X79 upto 5/9/89:
119 * [89/07/11 rvb]
120 *
121 * Revision 1.4.1.1 89/04/27 12:21:17 kupfer
122 * Merge X79 with our latest and greatest.
123 *
124 * Revision 1.2.1.1 89/04/27 11:54:40 kupfer
125 * X79 from CMU.
126 *
127 * Revision 1.4 89/03/09 20:06:46 rpd
128 * More cleanup.
129 *
130 * Revision 1.3 89/02/26 12:42:38 gm0w
131 * Changes for cleanup.
132 *
133 */
134
135 /* **********************************************************************
136 File: kd_mouse.c
137 Description: mouse driver as part of keyboard/display driver
138
139 $ Header: $
140
141 Copyright Ing. C. Olivetti & C. S.p.A. 1989.
142 All rights reserved.
143 ********************************************************************** */
144 /*
145 Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
146 Cupertino, California.
147
148 All Rights Reserved
149
150 Permission to use, copy, modify, and distribute this software and
151 its documentation for any purpose and without fee is hereby
152 granted, provided that the above copyright notice appears in all
153 copies and that both the copyright notice and this permission notice
154 appear in supporting documentation, and that the name of Olivetti
155 not be used in advertising or publicity pertaining to distribution
156 of the software without specific, written prior permission.
157
158 OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
159 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
160 IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
161 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
162 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
163 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
164 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
165 */
166
167 /*
168 * Hacked up support for serial mouse connected to COM1, using Mouse
169 * Systems 5-byte protocol at 1200 baud. This should work for
170 * Mouse Systems, SummaMouse, and Logitek C7 mice.
171 *
172 * The interface provided by /dev/mouse is a series of events as
173 * described in i386at/kd.h.
174 */
175
176 #include <mach/boolean.h>
177 #include <sys/types.h>
178 #ifdef MACH_KERNEL
179 #include <device/errno.h>
180 #include <device/io_req.h>
181 #else MACH_KERNEL
182 #include <sys/file.h>
183 #include <sys/errno.h>
184 #include <kern/thread.h>
185 #include <sys/user.h>
186 #include <sys/proc.h>
187 #include <sys/kernel.h>
188 #include <sys/ioctl.h>
189 #include <sys/tty.h>
190 #endif MACH_KERNEL
191 #include <i386/ipl.h>
192 #include <chips/busses.h>
193 #include <i386at/kd.h>
194 #include <i386at/kd_queue.h>
195 #include <i386at/i8250.h>
196
197 static int (*oldvect)(); /* old interrupt vector */
198 static int oldunit;
199 static spl_t oldspl;
200 extern struct bus_device *cominfo[];
201
202 kd_event_queue mouse_queue; /* queue of mouse events */
203 boolean_t mouse_in_use = FALSE;
204 #ifdef MACH_KERNEL
205 queue_head_t mouse_read_queue = { &mouse_read_queue, &mouse_read_queue };
206 #else MACH_KERNEL
207 struct proc *mouse_sel = 0; /* selecting process, if any */
208 short mousepgrp = 0; /* process group leader when dev is open */
209 #endif MACH_KERNEL
210
211 #ifdef MACH_KERNEL
212 #else MACH_KERNEL
213 int mouseflag = 0;
214 #define MOUSE_COLL 1 /* select collision */
215 #define MOUSE_ASYNC 2 /* user wants asynch notification */
216 #define MOUSE_NBIO 4 /* user wants non-blocking I/O */
217 #endif MACH_KERNEL
218
219 /*
220 * The state of the 3 buttons is encoded in the low-order 3 bits (both
221 * here and in other variables in the driver).
222 */
223 u_char lastbuttons; /* previous state of mouse buttons */
224 #define MOUSE_UP 1
225 #define MOUSE_DOWN 0
226 #define MOUSE_ALL_UP 0x7
227
228 int mouseintr();
229 void mouse_enqueue();
230 int mouse_baud = BCNT1200;
231
232 /*
233 * init_mouse_hw - initialize the serial port.
234 */
235 init_mouse_hw(unit, mode)
236 {
237 caddr_t base_addr = (caddr_t)cominfo[unit]->address;
238
239 outb(base_addr + RIE, 0);
240 outb(base_addr + RLC, LCDLAB);
241 outb(base_addr + RDLSB, mouse_baud & 0xff);
242 outb(base_addr + RDMSB, (mouse_baud >> 8) & 0xff);
243 outb(base_addr + RLC, mode);
244 outb(base_addr + RMC, MCDTR | MCRTS | MCOUT2);
245 outb(base_addr + RIE, IERD | IELS);
246 }
247
248
249 /*
250 * mouseopen - Verify that the request is read-only, initialize,
251 * and remember process group leader.
252 */
253 /*
254 * Low 3 bits of minor are the com port #.
255 * The high 5 bits of minor are the mouse type
256 */
257 #define MOUSE_SYSTEM_MOUSE 0
258 #define MICROSOFT_MOUSE 1
259 #define IBM_MOUSE 2
260 #define NO_MOUSE 3
261 #define LOGITECH_TRACKMAN 4
262 #define MICROSOFT_MOUSE7 5
263 static int mouse_type;
264 static int mousebufsize;
265 int track_man[10];
266
267 /*ARGSUSED*/
268 mouseopen(dev, flags)
269 dev_t dev;
270 int flags;
271 {
272 #ifdef MACH_KERNEL
273 #else MACH_KERNEL
274 if (flags & FWRITE)
275 return(ENODEV);
276 #endif MACH_KERNEL
277 if (mouse_in_use)
278 return(EBUSY);
279 mouse_in_use = TRUE; /* locking? */
280 kdq_reset(&mouse_queue);
281 lastbuttons = MOUSE_ALL_UP;
282 #ifdef MACH_KERNEL
283 #else MACH_KERNEL
284 mousepgrp = u.u_procp->p_pgrp;
285 #endif MACH_KERNEL
286
287 switch (mouse_type = ((minor(dev) & 0xf8) >> 3)) {
288 case MICROSOFT_MOUSE7:
289 mousebufsize = 3;
290 serial_mouse_open(dev);
291 init_mouse_hw(dev&7, LC7);
292 case MICROSOFT_MOUSE:
293 mousebufsize = 3;
294 serial_mouse_open(dev);
295 init_mouse_hw(dev&7, LC8);
296 break;
297 case MOUSE_SYSTEM_MOUSE:
298 mousebufsize = 5;
299 serial_mouse_open(dev);
300 init_mouse_hw(dev&7, LC8);
301 break;
302 case LOGITECH_TRACKMAN:
303 mousebufsize = 3;
304 serial_mouse_open(dev);
305 init_mouse_hw(dev&7, LC7);
306 track_man[0] = comgetc(dev&7);
307 track_man[1] = comgetc(dev&7);
308 if (track_man[0] != 0x4d &&
309 track_man[1] != 0x33) {
310 printf("LOGITECH_TRACKMAN: NOT M3");
311 }
312 break;
313 case IBM_MOUSE:
314 mousebufsize = 3;
315 kd_mouse_open(dev, 12);
316 ibm_ps2_mouse_open(dev);
317 break;
318 case NO_MOUSE:
319 break;
320 }
321 return(0);
322 }
323
324 serial_mouse_open(dev)
325 {
326 int unit = minor(dev) & 0x7;
327 int mouse_pic = cominfo[unit]->sysdep1;
328
329 spl_t s = splhi(); /* disable interrupts */
330
331 oldvect = ivect[mouse_pic];
332 ivect[mouse_pic] = mouseintr;
333
334 oldunit = iunit[mouse_pic];
335 iunit[mouse_pic] = unit;
336
337 /* XXX other arrays to init? */
338 splx(s); /* XXX - should come after init? */
339 }
340
341 int mouse_packets = 0;
342 kd_mouse_open(dev, mouse_pic)
343 {
344 spl_t s = splhi(); /* disable interrupts */
345 extern int kdintr();
346
347 oldvect = ivect[mouse_pic];
348 ivect[mouse_pic] = kdintr;
349 oldspl = intpri[mouse_pic];
350 intpri[mouse_pic] = SPL6;
351 form_pic_mask();
352 splx(s);
353 }
354
355 /*
356 * mouseclose - Disable interrupts on the serial port, reset driver flags,
357 * and restore the serial port interrupt vector.
358 */
359 mouseclose(dev, flags)
360 {
361 switch (mouse_type) {
362 case MICROSOFT_MOUSE:
363 case MICROSOFT_MOUSE7:
364 case MOUSE_SYSTEM_MOUSE:
365 case LOGITECH_TRACKMAN:
366 serial_mouse_close(dev);
367 break;
368 case IBM_MOUSE:
369 ibm_ps2_mouse_close(dev);
370 kd_mouse_close(dev, 12);
371 {int i = 20000; for (;i--;); }
372 kd_mouse_drain();
373 break;
374 case NO_MOUSE:
375 break;
376 }
377
378 kdq_reset(&mouse_queue); /* paranoia */
379 mouse_in_use = FALSE;
380 #ifdef MACH_KERNEL
381 #else MACH_KERNEL
382 mousepgrp = 0;
383 mouseflag = 0;
384 mouse_sel = 0;
385 #endif MACH_KERNEL
386 }
387
388 /*ARGSUSED*/
389 serial_mouse_close(dev, flags)
390 dev_t dev;
391 int flags;
392 {
393 spl_t o_pri = splhi(); /* mutex with open() */
394 int unit = minor(dev) & 0x7;
395 int mouse_pic = cominfo[unit]->sysdep1;
396 caddr_t base_addr = (caddr_t)cominfo[unit]->address;
397
398 assert(ivect[mouse_pic] == mouseintr);
399 outb(base_addr + RIE, 0); /* disable serial port */
400 outb(base_addr + RMC, 0); /* no rts */
401 ivect[mouse_pic] = oldvect;
402 iunit[mouse_pic] = oldunit;
403
404 (void)splx(o_pri);
405 }
406
407 kd_mouse_close(dev, mouse_pic)
408 {
409 spl_t s = splhi();
410
411 ivect[mouse_pic] = oldvect;
412 intpri[mouse_pic] = oldspl;
413 form_pic_mask();
414 splx(s);
415 }
416
417 #ifdef MACH_KERNEL
418 #else MACH_KERNEL
419 /*
420 * mouseioctl - handling for asynch & non-blocking I/O.
421 */
422
423 /*ARGSUSED*/
424 mouseioctl(dev, cmd, data, flag)
425 dev_t dev;
426 int cmd;
427 caddr_t data;
428 int flag;
429 {
430 int s = SPLKD();
431 int err = 0;
432
433 switch (cmd) {
434 case FIONBIO:
435 if (*(int *)data)
436 mouseflag |= MOUSE_NBIO;
437 else
438 mouseflag &= ~MOUSE_NBIO;
439 break;
440 case FIOASYNC:
441 if (*(int *)data)
442 mouseflag |= MOUSE_ASYNC;
443 else
444 mouseflag &= ~MOUSE_ASYNC;
445 break;
446 default:
447 err = ENOTTY;
448 break;
449 }
450
451 splx(s);
452 return(err);
453 }
454
455
456 /*
457 * mouseselect - check for pending events, etc.
458 */
459
460 /*ARGSUSED*/
461 mouseselect(dev, rw)
462 {
463 int s = SPLKD();
464
465 if (!kdq_empty(&mouse_queue)) {
466 splx(s);
467 return(1);
468 }
469
470 if (mouse_sel)
471 mouseflag |= MOUSE_COLL;
472 else
473 mouse_sel = (struct proc *)current_thread();
474 /* eeeyuck */
475
476 splx(s);
477 return(0);
478 }
479 #endif MACH_KERNEL
480
481 /*
482 * mouseread - dequeue and return any queued events.
483 */
484 #ifdef MACH_KERNEL
485 boolean_t mouse_read_done(); /* forward */
486
487 mouseread(dev, ior)
488 dev_t dev;
489 register io_req_t ior;
490 {
491 register int err, count;
492 register spl_t s;
493
494 err = device_read_alloc(ior, (vm_size_t)ior->io_count);
495 if (err != KERN_SUCCESS)
496 return (err);
497
498 s = SPLKD();
499 if (kdq_empty(&mouse_queue)) {
500 if (ior->io_mode & D_NOWAIT) {
501 splx(s);
502 return (D_WOULD_BLOCK);
503 }
504 ior->io_done = mouse_read_done;
505 enqueue_tail(&mouse_read_queue, (queue_entry_t)ior);
506 splx(s);
507 return (D_IO_QUEUED);
508 }
509 count = 0;
510 while (!kdq_empty(&mouse_queue) && count < ior->io_count) {
511 register kd_event *ev;
512
513 ev = kdq_get(&mouse_queue);
514 *(kd_event *)(&ior->io_data[count]) = *ev;
515 count += sizeof(kd_event);
516 }
517 splx(s);
518 ior->io_residual = ior->io_count - count;
519 return (D_SUCCESS);
520 }
521
522 boolean_t mouse_read_done(ior)
523 register io_req_t ior;
524 {
525 register int count;
526 register spl_t s;
527
528 s = SPLKD();
529 if (kdq_empty(&mouse_queue)) {
530 ior->io_done = mouse_read_done;
531 enqueue_tail(&mouse_read_queue, (queue_entry_t)ior);
532 splx(s);
533 return (FALSE);
534 }
535
536 count = 0;
537 while (!kdq_empty(&mouse_queue) && count < ior->io_count) {
538 register kd_event *ev;
539
540 ev = kdq_get(&mouse_queue);
541 *(kd_event *)(&ior->io_data[count]) = *ev;
542 count += sizeof(kd_event);
543 }
544 splx(s);
545
546 ior->io_residual = ior->io_count - count;
547 ds_read_done(ior);
548
549 return (TRUE);
550 }
551
552 #else MACH_KERNEL
553 /*ARGSUSED*/
554 mouseread(dev, uio)
555 dev_t dev;
556 struct uio *uio;
557 {
558 int s = SPLKD();
559 int err = 0;
560 kd_event *ev;
561 int i;
562 char *cp;
563
564 if (kdq_empty(&mouse_queue))
565 if (mouseflag & MOUSE_NBIO) {
566 err = EWOULDBLOCK;
567 goto done;
568 } else
569 while (kdq_empty(&mouse_queue)) {
570 splx(s);
571 sleep((caddr_t)&mouse_queue, TTIPRI);
572 s = SPLKD();
573 }
574
575 while (!kdq_empty(&mouse_queue) && uio->uio_resid >= sizeof(kd_event)) {
576 ev = kdq_get(&mouse_queue);
577 for (cp = (char *)ev, i = 0; i < sizeof(kd_event);
578 ++i, ++cp) {
579 err = ureadc(*cp, uio);
580 if (err)
581 goto done;
582 }
583 }
584
585 done:
586 splx(s);
587 return(err);
588 }
589 #endif MACH_KERNEL
590
591
592 /*
593 * mouseintr - Get a byte and pass it up for handling. Called at SPLKD.
594 */
595 mouseintr(unit)
596 {
597 caddr_t base_addr = (caddr_t)cominfo[unit]->address;
598 unsigned char id, ls;
599
600 /* get reason for interrupt and line status */
601 id = inb(base_addr + RID);
602 ls = inb(base_addr + RLS);
603
604 /* handle status changes */
605 if (id == IDLS) {
606 if (ls & LSDR) {
607 inb(base_addr + RDAT); /* flush bad character */
608 }
609 return; /* ignore status change */
610 }
611
612 if (id & IDRD) {
613 mouse_handle_byte((u_char)(inb(base_addr + RDAT) & 0xff));
614 }
615 }
616
617
618 /*
619 * handle_byte - Accumulate bytes until we have an entire packet.
620 * If the mouse has moved or any of the buttons have changed state (up
621 * or down), enqueue the corresponding events.
622 * Called at SPLKD.
623 * XXX - magic numbers.
624 */
625 int show_mouse_byte = 0;
626 /*
627 X down; middle down; middle up; X up 50 0 0; 50 0 0 22; 50 0 0 02; 40 0 0
628 X down; middle down; X up; middle up 50 0 0; 50 0 0 22; 40 0 0 22; 40 0 0 2
629 *
630 * The trick here is that all the while the middle button is down you get 4 byte
631 * packets with the last byte 0x22. When the middle button goes up you get a
632 * last packet with 0x02.
633 */
634 int lastgitech = 0x40; /* figure whether the first 3 bytes imply */
635 /* its time to expect a fourth */
636 int fourthgitech = 0; /* look for the 4th byte; we must process it */
637 int middlegitech = 0; /* what should the middle button be */
638
639 #define MOUSEBUFSIZE 5 /* num bytes def'd by protocol */
640 static u_char mousebuf[MOUSEBUFSIZE]; /* 5-byte packet from mouse */
641 static short mbindex = 0; /* index into mousebuf */
642
643 mouse_handle_byte(ch)
644 u_char ch;
645 {
646 if (show_mouse_byte) {
647 printf("%x(%c) ", ch, ch);
648 }
649 if (mbindex == 0) {
650 switch (mouse_type) {
651 case MICROSOFT_MOUSE7:
652 if ((ch & 0x40) != 0x40)
653 return;
654 break;
655 case MICROSOFT_MOUSE:
656 if ((ch & 0xc0) != 0xc0)
657 return;
658 break;
659 case MOUSE_SYSTEM_MOUSE:
660 if ((ch & 0xf8) != 0x80)
661 return;
662 break;
663 case LOGITECH_TRACKMAN:
664 if (fourthgitech == 1) {
665 fourthgitech = 0;
666 if (ch & 0xf0)
667 middlegitech = 0x4;
668 else
669 middlegitech = 0x0;
670 mouse_packet_microsoft_mouse(mousebuf);
671 return;
672 } else if ((ch & 0xc0) != 0x40)
673 return;
674 break;
675 case IBM_MOUSE:
676 break;
677 }
678 }
679
680 mousebuf[mbindex++] = ch;
681 if (mbindex < mousebufsize)
682 return;
683
684 /* got a packet */
685 mbindex = 0;
686
687 switch (mouse_type) {
688 case MICROSOFT_MOUSE7:
689 case MICROSOFT_MOUSE:
690 mouse_packet_microsoft_mouse(mousebuf);
691 break;
692 case MOUSE_SYSTEM_MOUSE:
693 mouse_packet_mouse_system_mouse(mousebuf);
694 break;
695 case LOGITECH_TRACKMAN:
696 if ( mousebuf[1] || mousebuf[2] ||
697 mousebuf[0] != lastgitech) {
698 mouse_packet_microsoft_mouse(mousebuf);
699 lastgitech = mousebuf[0] & 0xf0;
700 } else {
701 fourthgitech = 1;
702 }
703 break;
704 case IBM_MOUSE:
705 mouse_packet_ibm_ps2_mouse(mousebuf);
706 break;
707 }
708 }
709
710 mouse_packet_mouse_system_mouse(mousebuf)
711 u_char mousebuf[MOUSEBUFSIZE];
712 {
713 u_char buttons, buttonchanges;
714 struct mouse_motion moved;
715
716 buttons = mousebuf[0] & 0x7; /* get current state of buttons */
717 buttonchanges = buttons ^ lastbuttons;
718 moved.mm_deltaX = (char)mousebuf[1] + (char)mousebuf[3];
719 moved.mm_deltaY = (char)mousebuf[2] + (char)mousebuf[4];
720
721 if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0)
722 mouse_moved(moved);
723
724 if (buttonchanges != 0) {
725 lastbuttons = buttons;
726 if (buttonchanges & 1)
727 mouse_button(MOUSE_RIGHT, buttons & 1);
728 if (buttonchanges & 2)
729 mouse_button(MOUSE_MIDDLE, (buttons & 2) >> 1);
730 if (buttonchanges & 4)
731 mouse_button(MOUSE_LEFT, (buttons & 4) >> 2);
732 }
733 }
734
735 /* same as above for microsoft mouse */
736 /*
737 * 3 byte microsoft format used
738 *
739 * 7 6 5 4 3 2 1 0
740 * 1 1 L R Y7 Y6 X7 X6
741 * 1 0 X5 X4 X3 X3 X1 X0
742 * 1 0 Y5 Y4 Y3 Y2 Y1 Y0
743 *
744 */
745 mouse_packet_microsoft_mouse(mousebuf)
746 u_char mousebuf[MOUSEBUFSIZE];
747 {
748 u_char buttons, buttonchanges;
749 struct mouse_motion moved;
750
751 buttons = ((mousebuf[0] & 0x30) >> 4);
752 buttons |= middlegitech;
753 /* get current state of buttons */
754 #ifdef gross_hack
755 if (buttons == 0x03) /* both buttons down */
756 buttons = 0x04;
757 #endif /* gross_hack */
758 buttons = (~buttons) & 0x07; /* convert to not pressed */
759
760 buttonchanges = buttons ^ lastbuttons;
761 moved.mm_deltaX = ((mousebuf[0] & 0x03) << 6) | (mousebuf[1] & 0x3F);
762 moved.mm_deltaY = ((mousebuf[0] & 0x0c) << 4) | (mousebuf[2] & 0x3F);
763 if (moved.mm_deltaX & 0x80) /* negative, in fact */
764 moved.mm_deltaX = moved.mm_deltaX - 0x100;
765 if (moved.mm_deltaY & 0x80) /* negative, in fact */
766 moved.mm_deltaY = moved.mm_deltaY - 0x100;
767 /* and finally the Y orientation is different for the microsoft mouse */
768 moved.mm_deltaY = -moved.mm_deltaY;
769
770 if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0)
771 mouse_moved(moved);
772
773 if (buttonchanges != 0) {
774 lastbuttons = buttons;
775 if (buttonchanges & 1)
776 mouse_button(MOUSE_RIGHT, (buttons & 1) ?
777 MOUSE_UP : MOUSE_DOWN);
778 if (buttonchanges & 2)
779 mouse_button(MOUSE_LEFT, (buttons & 2) ?
780 MOUSE_UP : MOUSE_DOWN);
781 if (buttonchanges & 4)
782 mouse_button(MOUSE_MIDDLE, (buttons & 4) ?
783 MOUSE_UP : MOUSE_DOWN);
784 }
785 }
786
787 ibm_ps2_mouse_open(dev)
788 {
789 char buf[4] = {0,0,0,0};
790
791 lastbuttons = 0;
792 mbindex = 0;
793
794 kd_sendcmd(0xa8); /* enable mouse in kbd */
795
796 kd_cmdreg_write(0x47); /* allow mouse interrupts */
797 /* magic number for ibm? */
798
799 if (kd_mouse_write(0xff) != 0xfa) /* reset mouse */
800 return;
801
802 kd_mouse_read(2, buf);
803
804 kd_mouse_write(0xea); /* stream mode */
805 kd_mouse_write(0xf4); /* enable */
806
807 }
808
809 ibm_ps2_mouse_close(dev)
810 {
811 char buf[4] = {0,0,0,0};
812
813 if (kd_mouse_write(0xff) == 0xfa) /* reset mouse */
814 kd_mouse_read(2, buf);
815
816 kd_sendcmd(0xa7); /* disable mouse in kbd */
817 kd_cmdreg_write(0x65); /* disallow mouse interrupts */
818 /* magic number for ibm? */
819 }
820
821 /*
822 * 3 byte ibm ps2 format used
823 *
824 * 7 6 5 4 3 2 1 0
825 * YO XO YS XS 1 M R L
826 * X7 X6 X5 X4 X3 X3 X1 X0
827 * Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
828 *
829 */
830 mouse_packet_ibm_ps2_mouse(mousebuf)
831 u_char mousebuf[MOUSEBUFSIZE];
832 {
833 u_char buttons, buttonchanges;
834 struct mouse_motion moved;
835
836 buttons = mousebuf[0] & 0x7; /* get current state of buttons */
837 buttonchanges = buttons ^ lastbuttons;
838 moved.mm_deltaX = ((mousebuf[0]&0x10) ? 0xffffff00 : 0 ) | (u_char)mousebuf[1];
839 moved.mm_deltaY = ((mousebuf[0]&0x20) ? 0xffffff00 : 0 ) | (u_char)mousebuf[2];
840 if (mouse_packets) {
841 printf("(%x:%x:%x)", mousebuf[0], mousebuf[1], mousebuf[2]);
842 return;
843 }
844
845 if (moved.mm_deltaX != 0 || moved.mm_deltaY != 0)
846 mouse_moved(moved);
847
848 if (buttonchanges != 0) {
849 lastbuttons = buttons;
850 if (buttonchanges & 1)
851 mouse_button(MOUSE_LEFT, !(buttons & 1));
852 if (buttonchanges & 2)
853 mouse_button(MOUSE_RIGHT, !((buttons & 2) >> 1));
854 if (buttonchanges & 4)
855 mouse_button(MOUSE_MIDDLE, !((buttons & 4) >> 2));
856 }
857 }
858
859 /*
860 * Enqueue a mouse-motion event. Called at SPLKD.
861 */
862 mouse_moved(where)
863 struct mouse_motion where;
864 {
865 kd_event ev;
866
867 ev.type = MOUSE_MOTION;
868 ev.time = time;
869 ev.value.mmotion = where;
870 mouse_enqueue(&ev);
871 }
872
873
874 /*
875 * Enqueue an event for mouse button press or release. Called at SPLKD.
876 */
877 mouse_button(which, direction)
878 kev_type which;
879 u_char direction;
880 {
881 kd_event ev;
882
883 ev.type = which;
884 ev.time = time;
885 ev.value.up = (direction == MOUSE_UP) ? TRUE : FALSE;
886 mouse_enqueue(&ev);
887 }
888
889
890 /*
891 * mouse_enqueue - enqueue an event and wake up selecting processes, if
892 * any. Called at SPLKD.
893 */
894
895 void
896 mouse_enqueue(ev)
897 kd_event *ev;
898 {
899 if (kdq_full(&mouse_queue))
900 printf("mouse: queue full\n");
901 else
902 kdq_put(&mouse_queue, ev);
903
904 #ifdef MACH_KERNEL
905 {
906 register io_req_t ior;
907 while ((ior = (io_req_t)dequeue_head(&mouse_read_queue)) != 0)
908 iodone(ior);
909 }
910 #else MACH_KERNEL
911 if (mouse_sel) {
912 selwakeup(mouse_sel, mouseflag & MOUSE_COLL);
913 mouse_sel = 0;
914 mouseflag &= ~MOUSE_COLL;
915 }
916 if (mouseflag & MOUSE_ASYNC)
917 gsignal(mousepgrp, SIGIO);
918 wakeup((caddr_t)&mouse_queue);
919 #endif MACH_KERNEL
920 }
Cache object: 94cb8773d75521b97ad9e59d0ac90541
|