FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/psm.c
1 /*-
2 * Copyright (c) 1992, 1993 Erik Forsberg.
3 * Copyright (c) 1996, 1997 Kazutaka YOKOTA.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
15 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 *
23 * $FreeBSD$
24 */
25
26 /*
27 * Ported to 386bsd Oct 17, 1992
28 * Sandi Donno, Computer Science, University of Cape Town, South Africa
29 * Please send bug reports to sandi@cs.uct.ac.za
30 *
31 * Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca -
32 * although I was only partially successful in getting the alpha release
33 * of his "driver for the Logitech and ATI Inport Bus mice for use with
34 * 386bsd and the X386 port" to work with my Microsoft mouse, I nevertheless
35 * found his code to be an invaluable reference when porting this driver
36 * to 386bsd.
37 *
38 * Further modifications for latest 386BSD+patchkit and port to NetBSD,
39 * Andrew Herbert <andrew@werple.apana.org.au> - 8 June 1993
40 *
41 * Cloned from the Microsoft Bus Mouse driver, also by Erik Forsberg, by
42 * Andrew Herbert - 12 June 1993
43 *
44 * Modified for PS/2 mouse by Charles Hannum <mycroft@ai.mit.edu>
45 * - 13 June 1993
46 *
47 * Modified for PS/2 AUX mouse by Shoji Yuen <yuen@nuie.nagoya-u.ac.jp>
48 * - 24 October 1993
49 *
50 * Hardware access routines and probe logic rewritten by
51 * Kazutaka Yokota <yokota@zodiac.mech.utsunomiya-u.ac.jp>
52 * - 3, 14, 22 October 1996.
53 * - 12 November 1996. IOCTLs and rearranging `psmread', `psmioctl'...
54 * - 14, 30 November 1996. Uses `kbdio.c'.
55 * - 13 December 1996. Uses queuing version of `kbdio.c'.
56 * - January/February 1997. Tweaked probe logic for
57 * HiNote UltraII/Latitude/Armada laptops.
58 * - 30 July 1997. Added APM support.
59 * - 5 March 1997. Defined driver configuration flags (PSM_CONFIG_XXX).
60 * Improved sync check logic.
61 * Vendor specific support routines.
62 */
63
64 #include "psm.h"
65 #include "apm.h"
66 #include "opt_devfs.h"
67 #include "opt_psm.h"
68
69 #if NPSM > 0
70
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/kernel.h>
74 #include <sys/conf.h>
75 #include <sys/poll.h>
76 #include <sys/syslog.h>
77 #include <sys/malloc.h>
78 #ifdef DEVFS
79 #include <sys/devfsext.h>
80 #endif
81 #include <sys/select.h>
82 #include <sys/uio.h>
83
84 #include <machine/apm_bios.h>
85 #include <machine/clock.h>
86 #include <machine/limits.h>
87 #include <machine/mouse.h>
88
89 #include <dev/kbd/atkbdcreg.h>
90
91 #include <i386/isa/isa.h>
92 #include <i386/isa/isa_device.h>
93
94 /*
95 * Driver specific options: the following options may be set by
96 * `options' statements in the kernel configuration file.
97 */
98
99 /* debugging */
100 #ifndef PSM_DEBUG
101 #define PSM_DEBUG 0 /* logging: 0: none, 1: brief, 2: verbose */
102 #endif
103
104 /* end of driver specific options */
105
106 /* input queue */
107 #define PSM_BUFSIZE 960
108 #define PSM_SMALLBUFSIZE 240
109
110 /* operation levels */
111 #define PSM_LEVEL_BASE 0
112 #define PSM_LEVEL_STANDARD 1
113 #define PSM_LEVEL_NATIVE 2
114 #define PSM_LEVEL_MIN PSM_LEVEL_BASE
115 #define PSM_LEVEL_MAX PSM_LEVEL_NATIVE
116
117 /* Logitech PS2++ protocol */
118 #define MOUSE_PS2PLUS_CHECKBITS(b) \
119 ((((b[2] & 0x03) << 2) | 0x02) == (b[1] & 0x0f))
120 #define MOUSE_PS2PLUS_PACKET_TYPE(b) \
121 (((b[0] & 0x30) >> 2) | ((b[1] & 0x30) >> 4))
122
123 /* some macros */
124 #define PSM_UNIT(dev) (minor(dev) >> 1)
125 #define PSM_NBLOCKIO(dev) (minor(dev) & 1)
126 #define PSM_MKMINOR(unit,block) (((unit) << 1) | ((block) ? 0:1))
127
128 #ifndef max
129 #define max(x,y) ((x) > (y) ? (x) : (y))
130 #endif
131 #ifndef min
132 #define min(x,y) ((x) < (y) ? (x) : (y))
133 #endif
134
135 #define abs(x) (((x) < 0) ? -(x) : (x))
136
137 /* ring buffer */
138 typedef struct ringbuf {
139 int count; /* # of valid elements in the buffer */
140 int head; /* head pointer */
141 int tail; /* tail poiner */
142 unsigned char buf[PSM_BUFSIZE];
143 } ringbuf_t;
144
145 /* driver control block */
146 static struct psm_softc { /* Driver status information */
147 struct selinfo rsel; /* Process selecting for Input */
148 unsigned char state; /* Mouse driver state */
149 int config; /* driver configuration flags */
150 int flags; /* other flags */
151 KBDC kbdc; /* handle to access the keyboard controller */
152 int addr; /* I/O port address */
153 mousehw_t hw; /* hardware information */
154 mousemode_t mode; /* operation mode */
155 mousemode_t dflt_mode; /* default operation mode */
156 mousestatus_t status; /* accumulated mouse movement */
157 ringbuf_t queue; /* mouse status queue */
158 unsigned char ipacket[16]; /* interim input buffer */
159 int inputbytes; /* # of bytes in the input buffer */
160 int button; /* the latest button state */
161 int xold; /* previous absolute X position */
162 int yold; /* previous absolute Y position */
163 int watchdog; /* watchdog timer flag */
164 struct callout_handle callout; /* watchdog timer call out */
165 #ifdef DEVFS
166 void *devfs_token;
167 void *b_devfs_token;
168 #endif
169 #if NAPM > 0
170 struct apmhook resumehook;
171 #endif
172 } *psm_softc[NPSM];
173
174 /* driver state flags (state) */
175 #define PSM_VALID 0x80
176 #define PSM_OPEN 1 /* Device is open */
177 #define PSM_ASLP 2 /* Waiting for mouse data */
178
179 /* driver configuration flags (config) */
180 #define PSM_CONFIG_RESOLUTION 0x000f /* resolution */
181 #define PSM_CONFIG_ACCEL 0x00f0 /* acceleration factor */
182 #define PSM_CONFIG_NOCHECKSYNC 0x0100 /* disable sync. test */
183 #define PSM_CONFIG_NOIDPROBE 0x0200 /* disable mouse model probe */
184 #define PSM_CONFIG_NORESET 0x0400 /* don't reset the mouse */
185 #define PSM_CONFIG_FORCETAP 0x0800 /* assume `tap' action exists */
186 #define PSM_CONFIG_IGNPORTERROR 0x1000 /* ignore error in aux port test */
187 #define PSM_CONFIG_HOOKRESUME 0x2000 /* hook the system resume event */
188 #define PSM_CONFIG_INITAFTERSUSPEND 0x4000 /* init the device at the resume event */
189
190 #define PSM_CONFIG_FLAGS (PSM_CONFIG_RESOLUTION \
191 | PSM_CONFIG_ACCEL \
192 | PSM_CONFIG_NOCHECKSYNC \
193 | PSM_CONFIG_NOIDPROBE \
194 | PSM_CONFIG_NORESET \
195 | PSM_CONFIG_FORCETAP \
196 | PSM_CONFIG_IGNPORTERROR \
197 | PSM_CONFIG_HOOKRESUME \
198 | PSM_CONFIG_INITAFTERSUSPEND)
199
200 /* other flags (flags) */
201 #define PSM_FLAGS_FINGERDOWN 0x0001 /* VersaPad finger down */
202
203 /* for backward compatibility */
204 #define OLD_MOUSE_GETHWINFO _IOR('M', 1, old_mousehw_t)
205 #define OLD_MOUSE_GETMODE _IOR('M', 2, old_mousemode_t)
206 #define OLD_MOUSE_SETMODE _IOW('M', 3, old_mousemode_t)
207
208 typedef struct old_mousehw {
209 int buttons;
210 int iftype;
211 int type;
212 int hwid;
213 } old_mousehw_t;
214
215 typedef struct old_mousemode {
216 int protocol;
217 int rate;
218 int resolution;
219 int accelfactor;
220 } old_mousemode_t;
221
222 /* packet formatting function */
223 typedef int packetfunc_t __P((struct psm_softc *, unsigned char *,
224 int *, int, mousestatus_t *));
225
226 /* function prototypes */
227 static int psmprobe __P((struct isa_device *));
228 static int psmattach __P((struct isa_device *));
229 static void psm_drvinit __P((void *));
230 #if NAPM > 0
231 static int psmresume __P((void *));
232 #endif
233
234 static d_open_t psmopen;
235 static d_close_t psmclose;
236 static d_read_t psmread;
237 static d_ioctl_t psmioctl;
238 static d_poll_t psmpoll;
239
240 static int enable_aux_dev __P((KBDC));
241 static int disable_aux_dev __P((KBDC));
242 static int get_mouse_status __P((KBDC, int *, int, int));
243 static int get_aux_id __P((KBDC));
244 static int set_mouse_sampling_rate __P((KBDC, int));
245 static int set_mouse_scaling __P((KBDC, int));
246 static int set_mouse_resolution __P((KBDC, int));
247 #if NAPM > 0
248 static int set_mouse_mode __P((KBDC));
249 #endif
250 static int get_mouse_buttons __P((KBDC));
251 static int is_a_mouse __P((int));
252 static void recover_from_error __P((KBDC));
253 static int restore_controller __P((KBDC, int));
254 #if NAPM > 0
255 static int reinitialize __P((int, mousemode_t *));
256 #endif
257 static int doopen __P((int, int));
258 static char *model_name __P((int));
259 static ointhand2_t psmintr;
260 static void psmtimeout __P((void *));
261
262 /* vendor specific features */
263 typedef int probefunc_t __P((struct psm_softc *));
264
265 static int mouse_id_proc1 __P((KBDC, int, int, int *));
266 static probefunc_t enable_groller;
267 static probefunc_t enable_gmouse;
268 static probefunc_t enable_aglide;
269 static probefunc_t enable_kmouse;
270 static probefunc_t enable_msexplorer;
271 static probefunc_t enable_msintelli;
272 static probefunc_t enable_4dmouse;
273 static probefunc_t enable_4dplus;
274 static probefunc_t enable_mmanplus;
275 static probefunc_t enable_versapad;
276 static int tame_mouse __P((struct psm_softc *, mousestatus_t *, unsigned char *));
277
278 static struct {
279 int model;
280 unsigned char syncmask;
281 int packetsize;
282 probefunc_t *probefunc;
283 } vendortype[] = {
284 /*
285 * WARNING: the order of probe is very important. Don't mess it
286 * unless you know what you are doing.
287 */
288 { MOUSE_MODEL_NET, /* Genius NetMouse */
289 0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_gmouse, },
290 { MOUSE_MODEL_NETSCROLL, /* Genius NetScroll */
291 0xc8, 6, enable_groller, },
292 { MOUSE_MODEL_MOUSEMANPLUS, /* Logitech MouseMan+ */
293 0x08, MOUSE_PS2_PACKETSIZE, enable_mmanplus, },
294 { MOUSE_MODEL_EXPLORER, /* Microsoft IntelliMouse Explorer */
295 0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msexplorer, },
296 { MOUSE_MODEL_4D, /* A4 Tech 4D Mouse */
297 0x08, MOUSE_4D_PACKETSIZE, enable_4dmouse, },
298 { MOUSE_MODEL_4DPLUS, /* A4 Tech 4D+ Mouse */
299 0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus, },
300 { MOUSE_MODEL_INTELLI, /* Microsoft IntelliMouse */
301 0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli, },
302 { MOUSE_MODEL_GLIDEPOINT, /* ALPS GlidePoint */
303 0xc0, MOUSE_PS2_PACKETSIZE, enable_aglide, },
304 { MOUSE_MODEL_THINK, /* Kensignton ThinkingMouse */
305 0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse, },
306 { MOUSE_MODEL_VERSAPAD, /* Interlink electronics VersaPad */
307 0xe8, MOUSE_PS2VERSA_PACKETSIZE, enable_versapad, },
308 { MOUSE_MODEL_GENERIC,
309 0xc0, MOUSE_PS2_PACKETSIZE, NULL, },
310 };
311 #define GENERIC_MOUSE_ENTRY 7
312
313 /* device driver declarateion */
314 struct isa_driver psmdriver = { psmprobe, psmattach, "psm", FALSE };
315 #define CDEV_MAJOR 21
316
317 static struct cdevsw psm_cdevsw = {
318 psmopen, psmclose, psmread, nowrite, /* 21 */
319 psmioctl, nostop, nullreset, nodevtotty,
320 psmpoll, nommap, NULL, "psm", NULL, -1
321 };
322
323 /* debug message level */
324 static int verbose = PSM_DEBUG;
325
326 /* device I/O routines */
327 static int
328 enable_aux_dev(KBDC kbdc)
329 {
330 int res;
331
332 res = send_aux_command(kbdc, PSMC_ENABLE_DEV);
333 if (verbose >= 2)
334 log(LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res);
335
336 return (res == PSM_ACK);
337 }
338
339 static int
340 disable_aux_dev(KBDC kbdc)
341 {
342 int res;
343
344 res = send_aux_command(kbdc, PSMC_DISABLE_DEV);
345 if (verbose >= 2)
346 log(LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n", res);
347
348 return (res == PSM_ACK);
349 }
350
351 static int
352 get_mouse_status(KBDC kbdc, int *status, int flag, int len)
353 {
354 int cmd;
355 int res;
356 int i;
357
358 switch (flag) {
359 case 0:
360 default:
361 cmd = PSMC_SEND_DEV_STATUS;
362 break;
363 case 1:
364 cmd = PSMC_SEND_DEV_DATA;
365 break;
366 }
367 empty_aux_buffer(kbdc, 5);
368 res = send_aux_command(kbdc, cmd);
369 if (verbose >= 2)
370 log(LOG_DEBUG, "psm: SEND_AUX_DEV_%s return code:%04x\n",
371 (flag == 1) ? "DATA" : "STATUS", res);
372 if (res != PSM_ACK)
373 return 0;
374
375 for (i = 0; i < len; ++i) {
376 status[i] = read_aux_data(kbdc);
377 if (status[i] < 0)
378 break;
379 }
380
381 if (verbose) {
382 log(LOG_DEBUG, "psm: %s %02x %02x %02x\n",
383 (flag == 1) ? "data" : "status", status[0], status[1], status[2]);
384 }
385
386 return i;
387 }
388
389 static int
390 get_aux_id(KBDC kbdc)
391 {
392 int res;
393 int id;
394
395 empty_aux_buffer(kbdc, 5);
396 res = send_aux_command(kbdc, PSMC_SEND_DEV_ID);
397 if (verbose >= 2)
398 log(LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n", res);
399 if (res != PSM_ACK)
400 return (-1);
401
402 /* 10ms delay */
403 DELAY(10000);
404
405 id = read_aux_data(kbdc);
406 if (verbose >= 2)
407 log(LOG_DEBUG, "psm: device ID: %04x\n", id);
408
409 return id;
410 }
411
412 static int
413 set_mouse_sampling_rate(KBDC kbdc, int rate)
414 {
415 int res;
416
417 res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, rate);
418 if (verbose >= 2)
419 log(LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res);
420
421 return ((res == PSM_ACK) ? rate : -1);
422 }
423
424 static int
425 set_mouse_scaling(KBDC kbdc, int scale)
426 {
427 int res;
428
429 switch (scale) {
430 case 1:
431 default:
432 scale = PSMC_SET_SCALING11;
433 break;
434 case 2:
435 scale = PSMC_SET_SCALING21;
436 break;
437 }
438 res = send_aux_command(kbdc, scale);
439 if (verbose >= 2)
440 log(LOG_DEBUG, "psm: SET_SCALING%s return code:%04x\n",
441 (scale == PSMC_SET_SCALING21) ? "21" : "11", res);
442
443 return (res == PSM_ACK);
444 }
445
446 /* `val' must be 0 through PSMD_MAX_RESOLUTION */
447 static int
448 set_mouse_resolution(KBDC kbdc, int val)
449 {
450 int res;
451
452 res = send_aux_command_and_data(kbdc, PSMC_SET_RESOLUTION, val);
453 if (verbose >= 2)
454 log(LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", val, res);
455
456 return ((res == PSM_ACK) ? val : -1);
457 }
458
459 #if NAPM > 0
460 /*
461 * NOTE: once `set_mouse_mode()' is called, the mouse device must be
462 * re-enabled by calling `enable_aux_dev()'
463 */
464 static int
465 set_mouse_mode(KBDC kbdc)
466 {
467 int res;
468
469 res = send_aux_command(kbdc, PSMC_SET_STREAM_MODE);
470 if (verbose >= 2)
471 log(LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res);
472
473 return (res == PSM_ACK);
474 }
475 #endif /* NAPM > 0 */
476
477 static int
478 get_mouse_buttons(KBDC kbdc)
479 {
480 int c = 2; /* assume two buttons by default */
481 int status[3];
482
483 /*
484 * NOTE: a special sequence to obtain Logitech Mouse specific
485 * information: set resolution to 25 ppi, set scaling to 1:1, set
486 * scaling to 1:1, set scaling to 1:1. Then the second byte of the
487 * mouse status bytes is the number of available buttons.
488 * Some manufactures also support this sequence.
489 */
490 if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)
491 return c;
492 if (set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1)
493 && set_mouse_scaling(kbdc, 1)
494 && (get_mouse_status(kbdc, status, 0, 3) >= 3)) {
495 if (status[1] != 0)
496 return status[1];
497 }
498 return c;
499 }
500
501 /* misc subroutines */
502 /*
503 * Someday, I will get the complete list of valid pointing devices and
504 * their IDs... XXX
505 */
506 static int
507 is_a_mouse(int id)
508 {
509 #if 0
510 static int valid_ids[] = {
511 PSM_MOUSE_ID, /* mouse */
512 PSM_BALLPOINT_ID, /* ballpoint device */
513 PSM_INTELLI_ID, /* Intellimouse */
514 PSM_EXPLORER_ID, /* Intellimouse Explorer */
515 -1 /* end of table */
516 };
517 int i;
518
519 for (i = 0; valid_ids[i] >= 0; ++i)
520 if (valid_ids[i] == id)
521 return TRUE;
522 return FALSE;
523 #else
524 return TRUE;
525 #endif
526 }
527
528 static char *
529 model_name(int model)
530 {
531 static struct {
532 int model_code;
533 char *model_name;
534 } models[] = {
535 { MOUSE_MODEL_NETSCROLL, "NetScroll" },
536 { MOUSE_MODEL_NET, "NetMouse/NetScroll Optical" },
537 { MOUSE_MODEL_GLIDEPOINT, "GlidePoint" },
538 { MOUSE_MODEL_THINK, "ThinkingMouse" },
539 { MOUSE_MODEL_INTELLI, "IntelliMouse" },
540 { MOUSE_MODEL_MOUSEMANPLUS, "MouseMan+" },
541 { MOUSE_MODEL_VERSAPAD, "VersaPad" },
542 { MOUSE_MODEL_EXPLORER, "IntelliMouse Explorer" },
543 { MOUSE_MODEL_4D, "4D Mouse" },
544 { MOUSE_MODEL_4DPLUS, "4D+ Mouse" },
545 { MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" },
546 { MOUSE_MODEL_UNKNOWN, NULL },
547 };
548 int i;
549
550 for (i = 0; models[i].model_code != MOUSE_MODEL_UNKNOWN; ++i) {
551 if (models[i].model_code == model)
552 return models[i].model_name;
553 }
554 return "Unknown";
555 }
556
557 static void
558 recover_from_error(KBDC kbdc)
559 {
560 /* discard anything left in the output buffer */
561 empty_both_buffers(kbdc, 10);
562
563 #if 0
564 /*
565 * NOTE: KBDC_RESET_KBD may not restore the communication between the
566 * keyboard and the controller.
567 */
568 reset_kbd(kbdc);
569 #else
570 /*
571 * NOTE: somehow diagnostic and keyboard port test commands bring the
572 * keyboard back.
573 */
574 if (!test_controller(kbdc))
575 log(LOG_ERR, "psm: keyboard controller failed.\n");
576 /* if there isn't a keyboard in the system, the following error is OK */
577 if (test_kbd_port(kbdc) != 0) {
578 if (verbose)
579 log(LOG_ERR, "psm: keyboard port failed.\n");
580 }
581 #endif
582 }
583
584 static int
585 restore_controller(KBDC kbdc, int command_byte)
586 {
587 empty_both_buffers(kbdc, 10);
588
589 if (!set_controller_command_byte(kbdc, 0xff, command_byte)) {
590 log(LOG_ERR, "psm: failed to restore the keyboard controller "
591 "command byte.\n");
592 empty_both_buffers(kbdc, 10);
593 return FALSE;
594 } else {
595 empty_both_buffers(kbdc, 10);
596 return TRUE;
597 }
598 }
599
600 #if NAPM > 0
601 /*
602 * Re-initialize the aux port and device. The aux port must be enabled
603 * and its interrupt must be disabled before calling this routine.
604 * The aux device will be disabled before returning.
605 * The keyboard controller must be locked via `kbdc_lock()' before
606 * calling this routine.
607 */
608 static int
609 reinitialize(int unit, mousemode_t *mode)
610 {
611 struct psm_softc *sc = psm_softc[unit];
612 KBDC kbdc = psm_softc[unit]->kbdc;
613 int stat[3];
614 int i;
615
616 switch((i = test_aux_port(kbdc))) {
617 case 1: /* ignore this error */
618 case PSM_ACK:
619 if (verbose)
620 log(LOG_DEBUG, "psm%d: strange result for test aux port (%d).\n",
621 unit, i);
622 /* fall though */
623 case 0: /* no error */
624 break;
625 case -1: /* time out */
626 default: /* error */
627 recover_from_error(kbdc);
628 if (sc->config & PSM_CONFIG_IGNPORTERROR)
629 break;
630 log(LOG_ERR, "psm%d: the aux port is not functioning (%d).\n",
631 unit, i);
632 return FALSE;
633 }
634
635 if (sc->config & PSM_CONFIG_NORESET) {
636 /*
637 * Don't try to reset the pointing device. It may possibly be
638 * left in the unknown state, though...
639 */
640 } else {
641 /*
642 * NOTE: some controllers appears to hang the `keyboard' when
643 * the aux port doesn't exist and `PSMC_RESET_DEV' is issued.
644 */
645 if (!reset_aux_dev(kbdc)) {
646 recover_from_error(kbdc);
647 log(LOG_ERR, "psm%d: failed to reset the aux device.\n", unit);
648 return FALSE;
649 }
650 }
651
652 /*
653 * both the aux port and the aux device is functioning, see
654 * if the device can be enabled.
655 */
656 if (!enable_aux_dev(kbdc) || !disable_aux_dev(kbdc)) {
657 log(LOG_ERR, "psm%d: failed to enable the aux device.\n", unit);
658 return FALSE;
659 }
660 empty_both_buffers(kbdc, 10); /* remove stray data if any */
661
662 if (sc->config & PSM_CONFIG_NOIDPROBE) {
663 i = GENERIC_MOUSE_ENTRY;
664 } else {
665 /* FIXME: hardware ID, mouse buttons? */
666
667 /* other parameters */
668 for (i = 0; vendortype[i].probefunc != NULL; ++i) {
669 if ((*vendortype[i].probefunc)(sc)) {
670 if (verbose >= 2)
671 log(LOG_ERR, "psm%d: found %s\n",
672 unit, model_name(vendortype[i].model));
673 break;
674 }
675 }
676 }
677
678 sc->hw.model = vendortype[i].model;
679 sc->mode.packetsize = vendortype[i].packetsize;
680
681 /* set mouse parameters */
682 if (mode != (mousemode_t *)NULL) {
683 if (mode->rate > 0)
684 mode->rate = set_mouse_sampling_rate(kbdc, mode->rate);
685 if (mode->resolution >= 0)
686 mode->resolution = set_mouse_resolution(kbdc, mode->resolution);
687 set_mouse_scaling(kbdc, 1);
688 set_mouse_mode(kbdc);
689 }
690
691 /* request a data packet and extract sync. bits */
692 if (get_mouse_status(kbdc, stat, 1, 3) < 3) {
693 log(LOG_DEBUG, "psm%d: failed to get data (reinitialize).\n", unit);
694 sc->mode.syncmask[0] = 0;
695 } else {
696 sc->mode.syncmask[1] = stat[0] & sc->mode.syncmask[0]; /* syncbits */
697 /* the NetScroll Mouse will send three more bytes... Ignore them */
698 empty_aux_buffer(kbdc, 5);
699 }
700
701 /* just check the status of the mouse */
702 if (get_mouse_status(kbdc, stat, 0, 3) < 3)
703 log(LOG_DEBUG, "psm%d: failed to get status (reinitialize).\n", unit);
704
705 return TRUE;
706 }
707 #endif /* NAPM > 0 */
708
709 static int
710 doopen(int unit, int command_byte)
711 {
712 struct psm_softc *sc = psm_softc[unit];
713 int stat[3];
714
715 /* enable the mouse device */
716 if (!enable_aux_dev(sc->kbdc)) {
717 /* MOUSE ERROR: failed to enable the mouse because:
718 * 1) the mouse is faulty,
719 * 2) the mouse has been removed(!?)
720 * In the latter case, the keyboard may have hung, and need
721 * recovery procedure...
722 */
723 recover_from_error(sc->kbdc);
724 #if 0
725 /* FIXME: we could reset the mouse here and try to enable
726 * it again. But it will take long time and it's not a good
727 * idea to disable the keyboard that long...
728 */
729 if (!reinitialize(unit, &sc->mode) || !enable_aux_dev(sc->kbdc)) {
730 recover_from_error(sc->kbdc);
731 #else
732 {
733 #endif
734 restore_controller(sc->kbdc, command_byte);
735 /* mark this device is no longer available */
736 sc->state &= ~PSM_VALID;
737 log(LOG_ERR, "psm%d: failed to enable the device (doopen).\n",
738 unit);
739 return (EIO);
740 }
741 }
742
743 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
744 log(LOG_DEBUG, "psm%d: failed to get status (doopen).\n", unit);
745
746 /* enable the aux port and interrupt */
747 if (!set_controller_command_byte(sc->kbdc,
748 kbdc_get_device_mask(sc->kbdc),
749 (command_byte & KBD_KBD_CONTROL_BITS)
750 | KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT)) {
751 /* CONTROLLER ERROR */
752 disable_aux_dev(sc->kbdc);
753 restore_controller(sc->kbdc, command_byte);
754 log(LOG_ERR, "psm%d: failed to enable the aux interrupt (doopen).\n",
755 unit);
756 return (EIO);
757 }
758
759 /* start the watchdog timer */
760 sc->watchdog = FALSE;
761 sc->callout = timeout(psmtimeout, (void *)unit, hz*2);
762
763 return (0);
764 }
765
766 /* psm driver entry points */
767
768 #define endprobe(v) { if (bootverbose) \
769 --verbose; \
770 kbdc_set_device_mask(sc->kbdc, mask); \
771 kbdc_lock(sc->kbdc, FALSE); \
772 free(sc, M_DEVBUF); \
773 return (v); \
774 }
775
776 static int
777 psmprobe(struct isa_device *dvp)
778 {
779 int unit = dvp->id_unit;
780 struct psm_softc *sc;
781 int stat[3];
782 int command_byte;
783 int mask;
784 int i;
785
786 /* validate unit number */
787 if (unit >= NPSM)
788 return (0);
789
790 psm_softc[unit] = NULL;
791
792 sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT);
793 if (sc == NULL)
794 return (0);
795 bzero(sc, sizeof *sc);
796
797 #if 0
798 kbdc_debug(TRUE);
799 #endif
800 sc->addr = dvp->id_iobase;
801 sc->kbdc = kbdc_open(sc->addr);
802 sc->config = dvp->id_flags & PSM_CONFIG_FLAGS;
803 /* XXX: for backward compatibility */
804 #if defined(PSM_HOOKAPM)
805 sc->config |=
806 #ifdef PSM_RESETAFTERSUSPEND
807 PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
808 #else
809 PSM_CONFIG_HOOKRESUME;
810 #endif
811 #endif /* PSM_HOOKAPM */
812 sc->flags = 0;
813 if (bootverbose)
814 ++verbose;
815
816 if (!kbdc_lock(sc->kbdc, TRUE)) {
817 printf("psm%d: unable to lock the controller.\n", unit);
818 if (bootverbose)
819 --verbose;
820 free(sc, M_DEVBUF);
821 return (0);
822 }
823
824 /*
825 * NOTE: two bits in the command byte controls the operation of the
826 * aux port (mouse port): the aux port disable bit (bit 5) and the aux
827 * port interrupt (IRQ 12) enable bit (bit 2).
828 */
829
830 /* discard anything left after the keyboard initialization */
831 empty_both_buffers(sc->kbdc, 10);
832
833 /* save the current command byte; it will be used later */
834 mask = kbdc_get_device_mask(sc->kbdc) & ~KBD_AUX_CONTROL_BITS;
835 command_byte = get_controller_command_byte(sc->kbdc);
836 if (verbose)
837 printf("psm%d: current command byte:%04x\n", unit, command_byte);
838 if (command_byte == -1) {
839 /* CONTROLLER ERROR */
840 printf("psm%d: unable to get the current command byte value.\n",
841 unit);
842 endprobe(0);
843 }
844
845 /*
846 * disable the keyboard port while probing the aux port, which must be
847 * enabled during this routine
848 */
849 if (!set_controller_command_byte(sc->kbdc,
850 KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,
851 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
852 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
853 /*
854 * this is CONTROLLER ERROR; I don't know how to recover
855 * from this error...
856 */
857 restore_controller(sc->kbdc, command_byte);
858 printf("psm%d: unable to set the command byte.\n", unit);
859 endprobe(0);
860 }
861 write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT);
862
863 /*
864 * NOTE: `test_aux_port()' is designed to return with zero if the aux
865 * port exists and is functioning. However, some controllers appears
866 * to respond with zero even when the aux port doesn't exist. (It may
867 * be that this is only the case when the controller DOES have the aux
868 * port but the port is not wired on the motherboard.) The keyboard
869 * controllers without the port, such as the original AT, are
870 * supporsed to return with an error code or simply time out. In any
871 * case, we have to continue probing the port even when the controller
872 * passes this test.
873 *
874 * XXX: some controllers erroneously return the error code 1 when
875 * it has the perfectly functional aux port. We have to ignore this
876 * error code. Even if the controller HAS error with the aux port,
877 * it will be detected later...
878 * XXX: another incompatible controller returns PSM_ACK (0xfa)...
879 */
880 switch ((i = test_aux_port(sc->kbdc))) {
881 case 1: /* ignore this error */
882 case PSM_ACK:
883 if (verbose)
884 printf("psm%d: strange result for test aux port (%d).\n",
885 unit, i);
886 /* fall though */
887 case 0: /* no error */
888 break;
889 case -1: /* time out */
890 default: /* error */
891 recover_from_error(sc->kbdc);
892 if (sc->config & PSM_CONFIG_IGNPORTERROR)
893 break;
894 restore_controller(sc->kbdc, command_byte);
895 if (verbose)
896 printf("psm%d: the aux port is not functioning (%d).\n",
897 unit, i);
898 endprobe(0);
899 }
900
901 if (sc->config & PSM_CONFIG_NORESET) {
902 /*
903 * Don't try to reset the pointing device. It may possibly be
904 * left in the unknown state, though...
905 */
906 } else {
907 /*
908 * NOTE: some controllers appears to hang the `keyboard' when the aux
909 * port doesn't exist and `PSMC_RESET_DEV' is issued.
910 */
911 if (!reset_aux_dev(sc->kbdc)) {
912 recover_from_error(sc->kbdc);
913 restore_controller(sc->kbdc, command_byte);
914 if (verbose)
915 printf("psm%d: failed to reset the aux device.\n", unit);
916 endprobe(0);
917 }
918 }
919
920 /*
921 * both the aux port and the aux device is functioning, see if the
922 * device can be enabled. NOTE: when enabled, the device will start
923 * sending data; we shall immediately disable the device once we know
924 * the device can be enabled.
925 */
926 if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {
927 /* MOUSE ERROR */
928 recover_from_error(sc->kbdc);
929 restore_controller(sc->kbdc, command_byte);
930 if (verbose)
931 printf("psm%d: failed to enable the aux device.\n", unit);
932 endprobe(0);
933 }
934
935 /* save the default values after reset */
936 if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) {
937 sc->dflt_mode.rate = sc->mode.rate = stat[2];
938 sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
939 } else {
940 sc->dflt_mode.rate = sc->mode.rate = -1;
941 sc->dflt_mode.resolution = sc->mode.resolution = -1;
942 }
943
944 /* hardware information */
945 sc->hw.iftype = MOUSE_IF_PS2;
946
947 /* verify the device is a mouse */
948 sc->hw.hwid = get_aux_id(sc->kbdc);
949 if (!is_a_mouse(sc->hw.hwid)) {
950 restore_controller(sc->kbdc, command_byte);
951 if (verbose)
952 printf("psm%d: unknown device type (%d).\n", unit, sc->hw.hwid);
953 endprobe(0);
954 }
955 switch (sc->hw.hwid) {
956 case PSM_BALLPOINT_ID:
957 sc->hw.type = MOUSE_TRACKBALL;
958 break;
959 case PSM_MOUSE_ID:
960 case PSM_INTELLI_ID:
961 case PSM_EXPLORER_ID:
962 case PSM_4DMOUSE_ID:
963 case PSM_4DPLUS_ID:
964 sc->hw.type = MOUSE_MOUSE;
965 break;
966 default:
967 sc->hw.type = MOUSE_UNKNOWN;
968 break;
969 }
970
971 if (sc->config & PSM_CONFIG_NOIDPROBE) {
972 sc->hw.buttons = 2;
973 i = GENERIC_MOUSE_ENTRY;
974 } else {
975 /* # of buttons */
976 sc->hw.buttons = get_mouse_buttons(sc->kbdc);
977
978 /* other parameters */
979 for (i = 0; vendortype[i].probefunc != NULL; ++i) {
980 if ((*vendortype[i].probefunc)(sc)) {
981 if (verbose >= 2)
982 printf("psm%d: found %s\n",
983 unit, model_name(vendortype[i].model));
984 break;
985 }
986 }
987 }
988
989 sc->hw.model = vendortype[i].model;
990
991 sc->dflt_mode.level = PSM_LEVEL_BASE;
992 sc->dflt_mode.packetsize = MOUSE_PS2_PACKETSIZE;
993 sc->dflt_mode.accelfactor = (sc->config & PSM_CONFIG_ACCEL) >> 4;
994 if (sc->config & PSM_CONFIG_NOCHECKSYNC)
995 sc->dflt_mode.syncmask[0] = 0;
996 else
997 sc->dflt_mode.syncmask[0] = vendortype[i].syncmask;
998 if (sc->config & PSM_CONFIG_FORCETAP)
999 sc->mode.syncmask[0] &= ~MOUSE_PS2_TAP;
1000 sc->dflt_mode.syncmask[1] = 0; /* syncbits */
1001 sc->mode = sc->dflt_mode;
1002 sc->mode.packetsize = vendortype[i].packetsize;
1003
1004 /* set mouse parameters */
1005 #if 0
1006 /*
1007 * A version of Logitech FirstMouse+ won't report wheel movement,
1008 * if SET_DEFAULTS is sent... Don't use this command.
1009 * This fix was found by Takashi Nishida.
1010 */
1011 i = send_aux_command(sc->kbdc, PSMC_SET_DEFAULTS);
1012 if (verbose >= 2)
1013 printf("psm%d: SET_DEFAULTS return code:%04x\n", unit, i);
1014 #endif
1015 if (sc->config & PSM_CONFIG_RESOLUTION) {
1016 sc->mode.resolution
1017 = set_mouse_resolution(sc->kbdc,
1018 (sc->config & PSM_CONFIG_RESOLUTION) - 1);
1019 } else if (sc->mode.resolution >= 0) {
1020 sc->mode.resolution
1021 = set_mouse_resolution(sc->kbdc, sc->dflt_mode.resolution);
1022 }
1023 if (sc->mode.rate > 0) {
1024 sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, sc->dflt_mode.rate);
1025 }
1026 set_mouse_scaling(sc->kbdc, 1);
1027
1028 /* request a data packet and extract sync. bits */
1029 if (get_mouse_status(sc->kbdc, stat, 1, 3) < 3) {
1030 printf("psm%d: failed to get data.\n", unit);
1031 sc->mode.syncmask[0] = 0;
1032 } else {
1033 sc->mode.syncmask[1] = stat[0] & sc->mode.syncmask[0]; /* syncbits */
1034 /* the NetScroll Mouse will send three more bytes... Ignore them */
1035 empty_aux_buffer(sc->kbdc, 5);
1036 }
1037
1038 /* just check the status of the mouse */
1039 /*
1040 * NOTE: XXX there are some arcane controller/mouse combinations out
1041 * there, which hung the controller unless there is data transmission
1042 * after ACK from the mouse.
1043 */
1044 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) {
1045 printf("psm%d: failed to get status.\n", unit);
1046 } else {
1047 /*
1048 * When in its native mode, some mice operate with different
1049 * default parameters than in the PS/2 compatible mode.
1050 */
1051 sc->dflt_mode.rate = sc->mode.rate = stat[2];
1052 sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
1053 }
1054
1055 /* disable the aux port for now... */
1056 if (!set_controller_command_byte(sc->kbdc,
1057 KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,
1058 (command_byte & KBD_KBD_CONTROL_BITS)
1059 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1060 /*
1061 * this is CONTROLLER ERROR; I don't know the proper way to
1062 * recover from this error...
1063 */
1064 restore_controller(sc->kbdc, command_byte);
1065 printf("psm%d: unable to set the command byte.\n", unit);
1066 endprobe(0);
1067 }
1068
1069 /* done */
1070 psm_softc[unit] = sc;
1071 kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS);
1072 kbdc_lock(sc->kbdc, FALSE);
1073 return ((dvp->id_iobase < 0) ? -1 : IO_PSMSIZE);
1074 }
1075
1076 static int
1077 psmattach(struct isa_device *dvp)
1078 {
1079 int unit = dvp->id_unit;
1080 struct psm_softc *sc = psm_softc[unit];
1081
1082 dvp->id_ointr = psmintr;
1083
1084 if (sc == NULL) /* shouldn't happen */
1085 return (0);
1086
1087 /* Setup initial state */
1088 sc->state = PSM_VALID;
1089 callout_handle_init(&sc->callout);
1090
1091 /* Done */
1092 #ifdef DEVFS
1093 sc->devfs_token =
1094 devfs_add_devswf(&psm_cdevsw, PSM_MKMINOR(unit, FALSE),
1095 DV_CHR, 0, 0, 0666, "psm%d", unit);
1096 sc->b_devfs_token =
1097 devfs_add_devswf(&psm_cdevsw, PSM_MKMINOR(unit, TRUE),
1098 DV_CHR, 0, 0, 0666, "bpsm%d", unit);
1099 #endif /* DEVFS */
1100
1101 #if NAPM > 0
1102 sc->resumehook.ah_name = "PS/2 mouse";
1103 sc->resumehook.ah_fun = psmresume;
1104 sc->resumehook.ah_arg = (void *)unit;
1105 sc->resumehook.ah_order = APM_MID_ORDER;
1106 apm_hook_establish(APM_HOOK_RESUME , &sc->resumehook);
1107 if (verbose)
1108 printf("psm%d: APM hooks installed.\n", unit);
1109 #endif /* NAPM > 0 */
1110
1111 if (!verbose) {
1112 printf("psm%d: model %s, device ID %d\n",
1113 unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff);
1114 } else {
1115 printf("psm%d: model %s, device ID %d-%02x, %d buttons\n",
1116 unit, model_name(sc->hw.model),
1117 sc->hw.hwid & 0x00ff, sc->hw.hwid >> 8, sc->hw.buttons);
1118 printf("psm%d: config:%08x, flags:%08x, packet size:%d\n",
1119 unit, sc->config, sc->flags, sc->mode.packetsize);
1120 printf("psm%d: syncmask:%02x, syncbits:%02x\n",
1121 unit, sc->mode.syncmask[0], sc->mode.syncmask[1]);
1122 }
1123
1124 if (bootverbose)
1125 --verbose;
1126
1127 return (1);
1128 }
1129
1130 static int
1131 psmopen(dev_t dev, int flag, int fmt, struct proc *p)
1132 {
1133 int unit = PSM_UNIT(dev);
1134 struct psm_softc *sc;
1135 int command_byte;
1136 int err;
1137 int s;
1138
1139 /* Validate unit number */
1140 if (unit >= NPSM)
1141 return (ENXIO);
1142
1143 /* Get device data */
1144 sc = psm_softc[unit];
1145 if ((sc == NULL) || (sc->state & PSM_VALID) == 0)
1146 /* the device is no longer valid/functioning */
1147 return (ENXIO);
1148
1149 /* Disallow multiple opens */
1150 if (sc->state & PSM_OPEN)
1151 return (EBUSY);
1152
1153 /* Initialize state */
1154 sc->rsel.si_flags = 0;
1155 sc->rsel.si_pid = 0;
1156 sc->mode.level = sc->dflt_mode.level;
1157 sc->mode.protocol = sc->dflt_mode.protocol;
1158 sc->watchdog = FALSE;
1159
1160 /* flush the event queue */
1161 sc->queue.count = 0;
1162 sc->queue.head = 0;
1163 sc->queue.tail = 0;
1164 sc->status.flags = 0;
1165 sc->status.button = 0;
1166 sc->status.obutton = 0;
1167 sc->status.dx = 0;
1168 sc->status.dy = 0;
1169 sc->status.dz = 0;
1170 sc->button = 0;
1171
1172 /* empty input buffer */
1173 bzero(sc->ipacket, sizeof(sc->ipacket));
1174 sc->inputbytes = 0;
1175
1176 /* don't let timeout routines in the keyboard driver to poll the kbdc */
1177 if (!kbdc_lock(sc->kbdc, TRUE))
1178 return (EIO);
1179
1180 /* save the current controller command byte */
1181 s = spltty();
1182 command_byte = get_controller_command_byte(sc->kbdc);
1183
1184 /* enable the aux port and temporalily disable the keyboard */
1185 if ((command_byte == -1)
1186 || !set_controller_command_byte(sc->kbdc,
1187 kbdc_get_device_mask(sc->kbdc),
1188 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
1189 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1190 /* CONTROLLER ERROR; do you know how to get out of this? */
1191 kbdc_lock(sc->kbdc, FALSE);
1192 splx(s);
1193 log(LOG_ERR, "psm%d: unable to set the command byte (psmopen).\n",
1194 unit);
1195 return (EIO);
1196 }
1197 /*
1198 * Now that the keyboard controller is told not to generate
1199 * the keyboard and mouse interrupts, call `splx()' to allow
1200 * the other tty interrupts. The clock interrupt may also occur,
1201 * but timeout routines will be blocked by the poll flag set
1202 * via `kbdc_lock()'
1203 */
1204 splx(s);
1205
1206 /* enable the mouse device */
1207 err = doopen(unit, command_byte);
1208
1209 /* done */
1210 if (err == 0)
1211 sc->state |= PSM_OPEN;
1212 kbdc_lock(sc->kbdc, FALSE);
1213 return (err);
1214 }
1215
1216 static int
1217 psmclose(dev_t dev, int flag, int fmt, struct proc *p)
1218 {
1219 struct psm_softc *sc = psm_softc[PSM_UNIT(dev)];
1220 int stat[3];
1221 int command_byte;
1222 int s;
1223
1224 /* don't let timeout routines in the keyboard driver to poll the kbdc */
1225 if (!kbdc_lock(sc->kbdc, TRUE))
1226 return (EIO);
1227
1228 /* save the current controller command byte */
1229 s = spltty();
1230 command_byte = get_controller_command_byte(sc->kbdc);
1231 if (command_byte == -1) {
1232 kbdc_lock(sc->kbdc, FALSE);
1233 splx(s);
1234 return (EIO);
1235 }
1236
1237 /* disable the aux interrupt and temporalily disable the keyboard */
1238 if (!set_controller_command_byte(sc->kbdc,
1239 kbdc_get_device_mask(sc->kbdc),
1240 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
1241 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1242 log(LOG_ERR, "psm%d: failed to disable the aux int (psmclose).\n",
1243 PSM_UNIT(dev));
1244 /* CONTROLLER ERROR;
1245 * NOTE: we shall force our way through. Because the only
1246 * ill effect we shall see is that we may not be able
1247 * to read ACK from the mouse, and it doesn't matter much
1248 * so long as the mouse will accept the DISABLE command.
1249 */
1250 }
1251 splx(s);
1252
1253 /* stop the watchdog timer */
1254 untimeout(psmtimeout, (void *)PSM_UNIT(dev), sc->callout);
1255 callout_handle_init(&sc->callout);
1256
1257 /* remove anything left in the output buffer */
1258 empty_aux_buffer(sc->kbdc, 10);
1259
1260 /* disable the aux device, port and interrupt */
1261 if (sc->state & PSM_VALID) {
1262 if (!disable_aux_dev(sc->kbdc)) {
1263 /* MOUSE ERROR;
1264 * NOTE: we don't return error and continue, pretending
1265 * we have successfully disabled the device. It's OK because
1266 * the interrupt routine will discard any data from the mouse
1267 * hereafter.
1268 */
1269 log(LOG_ERR, "psm%d: failed to disable the device (psmclose).\n",
1270 PSM_UNIT(dev));
1271 }
1272
1273 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
1274 log(LOG_DEBUG, "psm%d: failed to get status (psmclose).\n",
1275 PSM_UNIT(dev));
1276 }
1277
1278 if (!set_controller_command_byte(sc->kbdc,
1279 kbdc_get_device_mask(sc->kbdc),
1280 (command_byte & KBD_KBD_CONTROL_BITS)
1281 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1282 /* CONTROLLER ERROR;
1283 * we shall ignore this error; see the above comment.
1284 */
1285 log(LOG_ERR, "psm%d: failed to disable the aux port (psmclose).\n",
1286 PSM_UNIT(dev));
1287 }
1288
1289 /* remove anything left in the output buffer */
1290 empty_aux_buffer(sc->kbdc, 10);
1291
1292 /* close is almost always successful */
1293 sc->state &= ~PSM_OPEN;
1294 kbdc_lock(sc->kbdc, FALSE);
1295 return (0);
1296 }
1297
1298 static int
1299 tame_mouse(struct psm_softc *sc, mousestatus_t *status, unsigned char *buf)
1300 {
1301 static unsigned char butmapps2[8] = {
1302 0,
1303 MOUSE_PS2_BUTTON1DOWN,
1304 MOUSE_PS2_BUTTON2DOWN,
1305 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN,
1306 MOUSE_PS2_BUTTON3DOWN,
1307 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON3DOWN,
1308 MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN,
1309 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN,
1310 };
1311 static unsigned char butmapmsc[8] = {
1312 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
1313 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
1314 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
1315 MOUSE_MSC_BUTTON3UP,
1316 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
1317 MOUSE_MSC_BUTTON2UP,
1318 MOUSE_MSC_BUTTON1UP,
1319 0,
1320 };
1321 int mapped;
1322 int i;
1323
1324 if (sc->mode.level == PSM_LEVEL_BASE) {
1325 mapped = status->button & ~MOUSE_BUTTON4DOWN;
1326 if (status->button & MOUSE_BUTTON4DOWN)
1327 mapped |= MOUSE_BUTTON1DOWN;
1328 status->button = mapped;
1329 buf[0] = MOUSE_PS2_SYNC | butmapps2[mapped & MOUSE_STDBUTTONS];
1330 i = max(min(status->dx, 255), -256);
1331 if (i < 0)
1332 buf[0] |= MOUSE_PS2_XNEG;
1333 buf[1] = i;
1334 i = max(min(status->dy, 255), -256);
1335 if (i < 0)
1336 buf[0] |= MOUSE_PS2_YNEG;
1337 buf[2] = i;
1338 return MOUSE_PS2_PACKETSIZE;
1339 } else if (sc->mode.level == PSM_LEVEL_STANDARD) {
1340 buf[0] = MOUSE_MSC_SYNC | butmapmsc[status->button & MOUSE_STDBUTTONS];
1341 i = max(min(status->dx, 255), -256);
1342 buf[1] = i >> 1;
1343 buf[3] = i - buf[1];
1344 i = max(min(status->dy, 255), -256);
1345 buf[2] = i >> 1;
1346 buf[4] = i - buf[2];
1347 i = max(min(status->dz, 127), -128);
1348 buf[5] = (i >> 1) & 0x7f;
1349 buf[6] = (i - (i >> 1)) & 0x7f;
1350 buf[7] = (~status->button >> 3) & 0x7f;
1351 return MOUSE_SYS_PACKETSIZE;
1352 }
1353 return sc->inputbytes;;
1354 }
1355
1356 static int
1357 psmread(dev_t dev, struct uio *uio, int flag)
1358 {
1359 register struct psm_softc *sc = psm_softc[PSM_UNIT(dev)];
1360 unsigned char buf[PSM_SMALLBUFSIZE];
1361 int error = 0;
1362 int s;
1363 int l;
1364
1365 if ((sc->state & PSM_VALID) == 0)
1366 return EIO;
1367
1368 /* block until mouse activity occured */
1369 s = spltty();
1370 while (sc->queue.count <= 0) {
1371 if (PSM_NBLOCKIO(dev)) {
1372 splx(s);
1373 return EWOULDBLOCK;
1374 }
1375 sc->state |= PSM_ASLP;
1376 error = tsleep((caddr_t) sc, PZERO | PCATCH, "psmrea", 0);
1377 sc->state &= ~PSM_ASLP;
1378 if (error) {
1379 splx(s);
1380 return error;
1381 } else if ((sc->state & PSM_VALID) == 0) {
1382 /* the device disappeared! */
1383 splx(s);
1384 return EIO;
1385 }
1386 }
1387 splx(s);
1388
1389 /* copy data to the user land */
1390 while ((sc->queue.count > 0) && (uio->uio_resid > 0)) {
1391 s = spltty();
1392 l = min(sc->queue.count, uio->uio_resid);
1393 if (l > sizeof(buf))
1394 l = sizeof(buf);
1395 if (l > sizeof(sc->queue.buf) - sc->queue.head) {
1396 bcopy(&sc->queue.buf[sc->queue.head], &buf[0],
1397 sizeof(sc->queue.buf) - sc->queue.head);
1398 bcopy(&sc->queue.buf[0],
1399 &buf[sizeof(sc->queue.buf) - sc->queue.head],
1400 l - (sizeof(sc->queue.buf) - sc->queue.head));
1401 } else {
1402 bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l);
1403 }
1404 sc->queue.count -= l;
1405 sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf);
1406 splx(s);
1407 error = uiomove(buf, l, uio);
1408 if (error)
1409 break;
1410 }
1411
1412 return error;
1413 }
1414
1415 static int
1416 block_mouse_data(struct psm_softc *sc, int *c)
1417 {
1418 int s;
1419
1420 if (!kbdc_lock(sc->kbdc, TRUE))
1421 return EIO;
1422
1423 s = spltty();
1424 *c = get_controller_command_byte(sc->kbdc);
1425 if ((*c == -1)
1426 || !set_controller_command_byte(sc->kbdc,
1427 kbdc_get_device_mask(sc->kbdc),
1428 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
1429 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1430 /* this is CONTROLLER ERROR */
1431 splx(s);
1432 kbdc_lock(sc->kbdc, FALSE);
1433 return EIO;
1434 }
1435
1436 /*
1437 * The device may be in the middle of status data transmission.
1438 * The transmission will be interrupted, thus, incomplete status
1439 * data must be discarded. Although the aux interrupt is disabled
1440 * at the keyboard controller level, at most one aux interrupt
1441 * may have already been pending and a data byte is in the
1442 * output buffer; throw it away. Note that the second argument
1443 * to `empty_aux_buffer()' is zero, so that the call will just
1444 * flush the internal queue.
1445 * `psmintr()' will be invoked after `splx()' if an interrupt is
1446 * pending; it will see no data and returns immediately.
1447 */
1448 empty_aux_buffer(sc->kbdc, 0); /* flush the queue */
1449 read_aux_data_no_wait(sc->kbdc); /* throw away data if any */
1450 sc->inputbytes = 0;
1451 splx(s);
1452
1453 return 0;
1454 }
1455
1456 static int
1457 unblock_mouse_data(struct psm_softc *sc, int c)
1458 {
1459 int error = 0;
1460
1461 /*
1462 * We may have seen a part of status data during `set_mouse_XXX()'.
1463 * they have been queued; flush it.
1464 */
1465 empty_aux_buffer(sc->kbdc, 0);
1466
1467 /* restore ports and interrupt */
1468 if (!set_controller_command_byte(sc->kbdc,
1469 kbdc_get_device_mask(sc->kbdc),
1470 c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
1471 /* CONTROLLER ERROR; this is serious, we may have
1472 * been left with the inaccessible keyboard and
1473 * the disabled mouse interrupt.
1474 */
1475 error = EIO;
1476 }
1477
1478 kbdc_lock(sc->kbdc, FALSE);
1479 return error;
1480 }
1481
1482 static int
1483 psmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1484 {
1485 struct psm_softc *sc = psm_softc[PSM_UNIT(dev)];
1486 mousemode_t mode;
1487 mousestatus_t status;
1488 #if (defined(MOUSE_GETVARS))
1489 mousevar_t *var;
1490 #endif
1491 mousedata_t *data;
1492 int stat[3];
1493 int command_byte;
1494 int error = 0;
1495 int s;
1496
1497 /* Perform IOCTL command */
1498 switch (cmd) {
1499
1500 case OLD_MOUSE_GETHWINFO:
1501 s = spltty();
1502 ((old_mousehw_t *)addr)->buttons = sc->hw.buttons;
1503 ((old_mousehw_t *)addr)->iftype = sc->hw.iftype;
1504 ((old_mousehw_t *)addr)->type = sc->hw.type;
1505 ((old_mousehw_t *)addr)->hwid = sc->hw.hwid & 0x00ff;
1506 splx(s);
1507 break;
1508
1509 case MOUSE_GETHWINFO:
1510 s = spltty();
1511 *(mousehw_t *)addr = sc->hw;
1512 if (sc->mode.level == PSM_LEVEL_BASE)
1513 ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
1514 splx(s);
1515 break;
1516
1517 case OLD_MOUSE_GETMODE:
1518 s = spltty();
1519 switch (sc->mode.level) {
1520 case PSM_LEVEL_BASE:
1521 ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1522 break;
1523 case PSM_LEVEL_STANDARD:
1524 ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
1525 break;
1526 case PSM_LEVEL_NATIVE:
1527 ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1528 break;
1529 }
1530 ((old_mousemode_t *)addr)->rate = sc->mode.rate;
1531 ((old_mousemode_t *)addr)->resolution = sc->mode.resolution;
1532 ((old_mousemode_t *)addr)->accelfactor = sc->mode.accelfactor;
1533 splx(s);
1534 break;
1535
1536 case MOUSE_GETMODE:
1537 s = spltty();
1538 *(mousemode_t *)addr = sc->mode;
1539 ((mousemode_t *)addr)->resolution =
1540 MOUSE_RES_LOW - sc->mode.resolution;
1541 switch (sc->mode.level) {
1542 case PSM_LEVEL_BASE:
1543 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1544 ((mousemode_t *)addr)->packetsize = MOUSE_PS2_PACKETSIZE;
1545 break;
1546 case PSM_LEVEL_STANDARD:
1547 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
1548 ((mousemode_t *)addr)->packetsize = MOUSE_SYS_PACKETSIZE;
1549 ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
1550 ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
1551 break;
1552 case PSM_LEVEL_NATIVE:
1553 /* FIXME: this isn't quite correct... XXX */
1554 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1555 break;
1556 }
1557 splx(s);
1558 break;
1559
1560 case OLD_MOUSE_SETMODE:
1561 case MOUSE_SETMODE:
1562 if (cmd == OLD_MOUSE_SETMODE) {
1563 mode.rate = ((old_mousemode_t *)addr)->rate;
1564 /*
1565 * resolution old I/F new I/F
1566 * default 0 0
1567 * low 1 -2
1568 * medium low 2 -3
1569 * medium high 3 -4
1570 * high 4 -5
1571 */
1572 if (((old_mousemode_t *)addr)->resolution > 0)
1573 mode.resolution = -((old_mousemode_t *)addr)->resolution - 1;
1574 mode.accelfactor = ((old_mousemode_t *)addr)->accelfactor;
1575 mode.level = -1;
1576 } else {
1577 mode = *(mousemode_t *)addr;
1578 }
1579
1580 /* adjust and validate parameters. */
1581 if (mode.rate > UCHAR_MAX)
1582 return EINVAL;
1583 if (mode.rate == 0)
1584 mode.rate = sc->dflt_mode.rate;
1585 else if (mode.rate == -1)
1586 /* don't change the current setting */
1587 ;
1588 else if (mode.rate < 0)
1589 return EINVAL;
1590 if (mode.resolution >= UCHAR_MAX)
1591 return EINVAL;
1592 if (mode.resolution >= 200)
1593 mode.resolution = MOUSE_RES_HIGH;
1594 else if (mode.resolution >= 100)
1595 mode.resolution = MOUSE_RES_MEDIUMHIGH;
1596 else if (mode.resolution >= 50)
1597 mode.resolution = MOUSE_RES_MEDIUMLOW;
1598 else if (mode.resolution > 0)
1599 mode.resolution = MOUSE_RES_LOW;
1600 if (mode.resolution == MOUSE_RES_DEFAULT)
1601 mode.resolution = sc->dflt_mode.resolution;
1602 else if (mode.resolution == -1)
1603 /* don't change the current setting */
1604 ;
1605 else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */
1606 mode.resolution = MOUSE_RES_LOW - mode.resolution;
1607 if (mode.level == -1)
1608 /* don't change the current setting */
1609 mode.level = sc->mode.level;
1610 else if ((mode.level < PSM_LEVEL_MIN) || (mode.level > PSM_LEVEL_MAX))
1611 return EINVAL;
1612 if (mode.accelfactor == -1)
1613 /* don't change the current setting */
1614 mode.accelfactor = sc->mode.accelfactor;
1615 else if (mode.accelfactor < 0)
1616 return EINVAL;
1617
1618 /* don't allow anybody to poll the keyboard controller */
1619 error = block_mouse_data(sc, &command_byte);
1620 if (error)
1621 return error;
1622
1623 /* set mouse parameters */
1624 if (mode.rate > 0)
1625 mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate);
1626 if (mode.resolution >= 0)
1627 mode.resolution = set_mouse_resolution(sc->kbdc, mode.resolution);
1628 set_mouse_scaling(sc->kbdc, 1);
1629 get_mouse_status(sc->kbdc, stat, 0, 3);
1630
1631 s = spltty();
1632 sc->mode.rate = mode.rate;
1633 sc->mode.resolution = mode.resolution;
1634 sc->mode.accelfactor = mode.accelfactor;
1635 sc->mode.level = mode.level;
1636 splx(s);
1637
1638 unblock_mouse_data(sc, command_byte);
1639 break;
1640
1641 case MOUSE_GETLEVEL:
1642 *(int *)addr = sc->mode.level;
1643 break;
1644
1645 case MOUSE_SETLEVEL:
1646 if ((*(int *)addr < PSM_LEVEL_MIN) || (*(int *)addr > PSM_LEVEL_MAX))
1647 return EINVAL;
1648 sc->mode.level = *(int *)addr;
1649 break;
1650
1651 case MOUSE_GETSTATUS:
1652 s = spltty();
1653 status = sc->status;
1654 sc->status.flags = 0;
1655 sc->status.obutton = sc->status.button;
1656 sc->status.button = 0;
1657 sc->status.dx = 0;
1658 sc->status.dy = 0;
1659 sc->status.dz = 0;
1660 splx(s);
1661 *(mousestatus_t *)addr = status;
1662 break;
1663
1664 #if (defined(MOUSE_GETVARS))
1665 case MOUSE_GETVARS:
1666 var = (mousevar_t *)addr;
1667 bzero(var, sizeof(*var));
1668 s = spltty();
1669 var->var[0] = MOUSE_VARS_PS2_SIG;
1670 var->var[1] = sc->config;
1671 var->var[2] = sc->flags;
1672 splx(s);
1673 break;
1674
1675 case MOUSE_SETVARS:
1676 return ENODEV;
1677 #endif /* MOUSE_GETVARS */
1678
1679 case MOUSE_READSTATE:
1680 case MOUSE_READDATA:
1681 data = (mousedata_t *)addr;
1682 if (data->len > sizeof(data->buf)/sizeof(data->buf[0]))
1683 return EINVAL;
1684
1685 error = block_mouse_data(sc, &command_byte);
1686 if (error)
1687 return error;
1688 if ((data->len = get_mouse_status(sc->kbdc, data->buf,
1689 (cmd == MOUSE_READDATA) ? 1 : 0, data->len)) <= 0)
1690 error = EIO;
1691 unblock_mouse_data(sc, command_byte);
1692 break;
1693
1694 #if (defined(MOUSE_SETRESOLUTION))
1695 case MOUSE_SETRESOLUTION:
1696 mode.resolution = *(int *)addr;
1697 if (mode.resolution >= UCHAR_MAX)
1698 return EINVAL;
1699 else if (mode.resolution >= 200)
1700 mode.resolution = MOUSE_RES_HIGH;
1701 else if (mode.resolution >= 100)
1702 mode.resolution = MOUSE_RES_MEDIUMHIGH;
1703 else if (mode.resolution >= 50)
1704 mode.resolution = MOUSE_RES_MEDIUMLOW;
1705 else if (mode.resolution > 0)
1706 mode.resolution = MOUSE_RES_LOW;
1707 if (mode.resolution == MOUSE_RES_DEFAULT)
1708 mode.resolution = sc->dflt_mode.resolution;
1709 else if (mode.resolution == -1)
1710 mode.resolution = sc->mode.resolution;
1711 else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */
1712 mode.resolution = MOUSE_RES_LOW - mode.resolution;
1713
1714 error = block_mouse_data(sc, &command_byte);
1715 if (error)
1716 return error;
1717 sc->mode.resolution = set_mouse_resolution(sc->kbdc, mode.resolution);
1718 if (sc->mode.resolution != mode.resolution)
1719 error = EIO;
1720 unblock_mouse_data(sc, command_byte);
1721 break;
1722 #endif /* MOUSE_SETRESOLUTION */
1723
1724 #if (defined(MOUSE_SETRATE))
1725 case MOUSE_SETRATE:
1726 mode.rate = *(int *)addr;
1727 if (mode.rate > UCHAR_MAX)
1728 return EINVAL;
1729 if (mode.rate == 0)
1730 mode.rate = sc->dflt_mode.rate;
1731 else if (mode.rate < 0)
1732 mode.rate = sc->mode.rate;
1733
1734 error = block_mouse_data(sc, &command_byte);
1735 if (error)
1736 return error;
1737 sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate);
1738 if (sc->mode.rate != mode.rate)
1739 error = EIO;
1740 unblock_mouse_data(sc, command_byte);
1741 break;
1742 #endif /* MOUSE_SETRATE */
1743
1744 #if (defined(MOUSE_SETSCALING))
1745 case MOUSE_SETSCALING:
1746 if ((*(int *)addr <= 0) || (*(int *)addr > 2))
1747 return EINVAL;
1748
1749 error = block_mouse_data(sc, &command_byte);
1750 if (error)
1751 return error;
1752 if (!set_mouse_scaling(sc->kbdc, *(int *)addr))
1753 error = EIO;
1754 unblock_mouse_data(sc, command_byte);
1755 break;
1756 #endif /* MOUSE_SETSCALING */
1757
1758 #if (defined(MOUSE_GETHWID))
1759 case MOUSE_GETHWID:
1760 error = block_mouse_data(sc, &command_byte);
1761 if (error)
1762 return error;
1763 sc->hw.hwid &= ~0x00ff;
1764 sc->hw.hwid |= get_aux_id(sc->kbdc);
1765 *(int *)addr = sc->hw.hwid & 0x00ff;
1766 unblock_mouse_data(sc, command_byte);
1767 break;
1768 #endif /* MOUSE_GETHWID */
1769
1770 default:
1771 return ENOTTY;
1772 }
1773
1774 return error;
1775 }
1776
1777 static void
1778 psmtimeout(void *arg)
1779 {
1780 struct psm_softc *sc;
1781 int unit;
1782
1783 unit = (int)arg;
1784 sc = psm_softc[unit];
1785 if (sc->watchdog) {
1786 if (verbose >= 4)
1787 log(LOG_DEBUG, "psm%d: lost interrupt?\n", unit);
1788 psmintr(unit);
1789 }
1790 sc->watchdog = TRUE;
1791 sc->callout = timeout(psmtimeout, (void *)unit, hz);
1792 }
1793
1794 static void
1795 psmintr(int unit)
1796 {
1797 /*
1798 * the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN)
1799 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
1800 */
1801 static int butmap[8] = {
1802 0,
1803 MOUSE_BUTTON1DOWN,
1804 MOUSE_BUTTON3DOWN,
1805 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
1806 MOUSE_BUTTON2DOWN,
1807 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
1808 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
1809 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
1810 };
1811 static int butmap_versapad[8] = {
1812 0,
1813 MOUSE_BUTTON3DOWN,
1814 0,
1815 MOUSE_BUTTON3DOWN,
1816 MOUSE_BUTTON1DOWN,
1817 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
1818 MOUSE_BUTTON1DOWN,
1819 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN
1820 };
1821 register struct psm_softc *sc = psm_softc[unit];
1822 mousestatus_t ms;
1823 int x, y, z;
1824 int c;
1825 int l;
1826 int x0, y0;
1827
1828 /* read until there is nothing to read */
1829 while((c = read_aux_data_no_wait(sc->kbdc)) != -1) {
1830
1831 /* discard the byte if the device is not open */
1832 if ((sc->state & PSM_OPEN) == 0)
1833 continue;
1834
1835 /*
1836 * Check sync bits. We check for overflow bits and the bit 3
1837 * for most mice. True, the code doesn't work if overflow
1838 * condition occurs. But we expect it rarely happens...
1839 */
1840 if ((sc->inputbytes == 0)
1841 && ((c & sc->mode.syncmask[0]) != sc->mode.syncmask[1])) {
1842 log(LOG_DEBUG, "psmintr: out of sync (%04x != %04x).\n",
1843 c & sc->mode.syncmask[0], sc->mode.syncmask[1]);
1844 continue;
1845 }
1846
1847 sc->ipacket[sc->inputbytes++] = c;
1848 if (sc->inputbytes < sc->mode.packetsize)
1849 continue;
1850
1851 #if 0
1852 log(LOG_DEBUG, "psmintr: %02x %02x %02x %02x %02x %02x\n",
1853 sc->ipacket[0], sc->ipacket[1], sc->ipacket[2],
1854 sc->ipacket[3], sc->ipacket[4], sc->ipacket[5]);
1855 #endif
1856
1857 c = sc->ipacket[0];
1858
1859 /*
1860 * A kludge for Kensington device!
1861 * The MSB of the horizontal count appears to be stored in
1862 * a strange place.
1863 */
1864 if (sc->hw.model == MOUSE_MODEL_THINK)
1865 sc->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0;
1866
1867 /* ignore the overflow bits... */
1868 x = (c & MOUSE_PS2_XNEG) ? sc->ipacket[1] - 256 : sc->ipacket[1];
1869 y = (c & MOUSE_PS2_YNEG) ? sc->ipacket[2] - 256 : sc->ipacket[2];
1870 z = 0;
1871 ms.obutton = sc->button; /* previous button state */
1872 ms.button = butmap[c & MOUSE_PS2_BUTTONS];
1873 /* `tapping' action */
1874 if (sc->config & PSM_CONFIG_FORCETAP)
1875 ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : MOUSE_BUTTON4DOWN;
1876
1877 switch (sc->hw.model) {
1878
1879 case MOUSE_MODEL_EXPLORER:
1880 /*
1881 * b7 b6 b5 b4 b3 b2 b1 b0
1882 * byte 1: oy ox sy sx 1 M R L
1883 * byte 2: x x x x x x x x
1884 * byte 3: y y y y y y y y
1885 * byte 4: * * S2 S1 s d2 d1 d0
1886 *
1887 * L, M, R, S1, S2: left, middle, right and side buttons
1888 * s: wheel data sign bit
1889 * d2-d0: wheel data
1890 */
1891 z = (sc->ipacket[3] & MOUSE_EXPLORER_ZNEG)
1892 ? (sc->ipacket[3] & 0x0f) - 16 : (sc->ipacket[3] & 0x0f);
1893 ms.button |= (sc->ipacket[3] & MOUSE_EXPLORER_BUTTON4DOWN)
1894 ? MOUSE_BUTTON4DOWN : 0;
1895 ms.button |= (sc->ipacket[3] & MOUSE_EXPLORER_BUTTON5DOWN)
1896 ? MOUSE_BUTTON5DOWN : 0;
1897 break;
1898
1899 case MOUSE_MODEL_INTELLI:
1900 case MOUSE_MODEL_NET:
1901 /* wheel data is in the fourth byte */
1902 z = (char)sc->ipacket[3];
1903 /* some mice may send 7 when there is no Z movement?! XXX */
1904 if ((z >= 7) || (z <= -7))
1905 z = 0;
1906 /* some compatible mice have additional buttons */
1907 ms.button |= (c & MOUSE_PS2INTELLI_BUTTON4DOWN)
1908 ? MOUSE_BUTTON4DOWN : 0;
1909 ms.button |= (c & MOUSE_PS2INTELLI_BUTTON5DOWN)
1910 ? MOUSE_BUTTON5DOWN : 0;
1911 break;
1912
1913 case MOUSE_MODEL_MOUSEMANPLUS:
1914 /*
1915 * PS2++ protocl packet
1916 *
1917 * b7 b6 b5 b4 b3 b2 b1 b0
1918 * byte 1: * 1 p3 p2 1 * * *
1919 * byte 2: c1 c2 p1 p0 d1 d0 1 0
1920 *
1921 * p3-p0: packet type
1922 * c1, c2: c1 & c2 == 1, if p2 == 0
1923 * c1 & c2 == 0, if p2 == 1
1924 *
1925 * packet type: 0 (device type)
1926 * See comments in enable_mmanplus() below.
1927 *
1928 * packet type: 1 (wheel data)
1929 *
1930 * b7 b6 b5 b4 b3 b2 b1 b0
1931 * byte 3: h * B5 B4 s d2 d1 d0
1932 *
1933 * h: 1, if horizontal roller data
1934 * 0, if vertical roller data
1935 * B4, B5: button 4 and 5
1936 * s: sign bit
1937 * d2-d0: roller data
1938 *
1939 * packet type: 2 (reserved)
1940 */
1941 if (((c & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC)
1942 && (abs(x) > 191)
1943 && MOUSE_PS2PLUS_CHECKBITS(sc->ipacket)) {
1944 /* the extended data packet encodes button and wheel events */
1945 switch (MOUSE_PS2PLUS_PACKET_TYPE(sc->ipacket)) {
1946 case 1:
1947 /* wheel data packet */
1948 x = y = 0;
1949 if (sc->ipacket[2] & 0x80) {
1950 /* horizontal roller count - ignore it XXX*/
1951 } else {
1952 /* vertical roller count */
1953 z = (sc->ipacket[2] & MOUSE_PS2PLUS_ZNEG)
1954 ? (sc->ipacket[2] & 0x0f) - 16
1955 : (sc->ipacket[2] & 0x0f);
1956 }
1957 ms.button |= (sc->ipacket[2] & MOUSE_PS2PLUS_BUTTON4DOWN)
1958 ? MOUSE_BUTTON4DOWN : 0;
1959 ms.button |= (sc->ipacket[2] & MOUSE_PS2PLUS_BUTTON5DOWN)
1960 ? MOUSE_BUTTON5DOWN : 0;
1961 break;
1962 case 2:
1963 /* this packet type is reserved by Logitech... */
1964 /*
1965 * IBM ScrollPoint Mouse uses this packet type to
1966 * encode both vertical and horizontal scroll movement.
1967 */
1968 x = y = 0;
1969 /* horizontal count */
1970 if (sc->ipacket[2] & 0x0f)
1971 z = (sc->ipacket[2] & MOUSE_SPOINT_WNEG) ? -2 : 2;
1972 /* vertical count */
1973 if (sc->ipacket[2] & 0xf0)
1974 z = (sc->ipacket[2] & MOUSE_SPOINT_ZNEG) ? -1 : 1;
1975 #if 0
1976 /* vertical count */
1977 z = (sc->ipacket[2] & MOUSE_SPOINT_ZNEG)
1978 ? ((sc->ipacket[2] >> 4) & 0x0f) - 16
1979 : ((sc->ipacket[2] >> 4) & 0x0f);
1980 /* horizontal count */
1981 w = (sc->ipacket[2] & MOUSE_SPOINT_WNEG)
1982 ? (sc->ipacket[2] & 0x0f) - 16
1983 : (sc->ipacket[2] & 0x0f);
1984 #endif
1985 break;
1986 case 0:
1987 /* device type packet - shouldn't happen */
1988 /* FALL THROUGH */
1989 default:
1990 x = y = 0;
1991 ms.button = ms.obutton;
1992 if (bootverbose)
1993 log(LOG_DEBUG, "psmintr: unknown PS2++ packet type %d: "
1994 "0x%02x 0x%02x 0x%02x\n",
1995 MOUSE_PS2PLUS_PACKET_TYPE(sc->ipacket),
1996 sc->ipacket[0], sc->ipacket[1], sc->ipacket[2]);
1997 break;
1998 }
1999 } else {
2000 /* preserve button states */
2001 ms.button |= ms.obutton & MOUSE_EXTBUTTONS;
2002 }
2003 break;
2004
2005 case MOUSE_MODEL_GLIDEPOINT:
2006 /* `tapping' action */
2007 ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : MOUSE_BUTTON4DOWN;
2008 break;
2009
2010 case MOUSE_MODEL_NETSCROLL:
2011 /* three addtional bytes encode buttons and wheel events */
2012 ms.button |= (sc->ipacket[3] & MOUSE_PS2_BUTTON3DOWN)
2013 ? MOUSE_BUTTON4DOWN : 0;
2014 ms.button |= (sc->ipacket[3] & MOUSE_PS2_BUTTON1DOWN)
2015 ? MOUSE_BUTTON5DOWN : 0;
2016 z = (sc->ipacket[3] & MOUSE_PS2_XNEG)
2017 ? sc->ipacket[4] - 256 : sc->ipacket[4];
2018 break;
2019
2020 case MOUSE_MODEL_THINK:
2021 /* the fourth button state in the first byte */
2022 ms.button |= (c & MOUSE_PS2_TAP) ? MOUSE_BUTTON4DOWN : 0;
2023 break;
2024
2025 case MOUSE_MODEL_VERSAPAD:
2026 /* VersaPad PS/2 absolute mode message format
2027 *
2028 * [packet1] 7 6 5 4 3 2 1 0(LSB)
2029 * ipacket[0]: 1 1 0 A 1 L T R
2030 * ipacket[1]: H7 H6 H5 H4 H3 H2 H1 H0
2031 * ipacket[2]: V7 V6 V5 V4 V3 V2 V1 V0
2032 * ipacket[3]: 1 1 1 A 1 L T R
2033 * ipacket[4]:V11 V10 V9 V8 H11 H10 H9 H8
2034 * ipacket[5]: 0 P6 P5 P4 P3 P2 P1 P0
2035 *
2036 * [note]
2037 * R: right physical mouse button (1=on)
2038 * T: touch pad virtual button (1=tapping)
2039 * L: left physical mouse button (1=on)
2040 * A: position data is valid (1=valid)
2041 * H: horizontal data (12bit signed integer. H11 is sign bit.)
2042 * V: vertical data (12bit signed integer. V11 is sign bit.)
2043 * P: pressure data
2044 *
2045 * Tapping is mapped to MOUSE_BUTTON4.
2046 */
2047 ms.button = butmap_versapad[c & MOUSE_PS2VERSA_BUTTONS];
2048 ms.button |= (c & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0;
2049 x = y = 0;
2050 if (c & MOUSE_PS2VERSA_IN_USE) {
2051 x0 = sc->ipacket[1] | (((sc->ipacket[4]) & 0x0f) << 8);
2052 y0 = sc->ipacket[2] | (((sc->ipacket[4]) & 0xf0) << 4);
2053 if (x0 & 0x800)
2054 x0 -= 0x1000;
2055 if (y0 & 0x800)
2056 y0 -= 0x1000;
2057 if (sc->flags & PSM_FLAGS_FINGERDOWN) {
2058 x = sc->xold - x0;
2059 y = y0 - sc->yold;
2060 if (x < 0) /* XXX */
2061 x++;
2062 else if (x)
2063 x--;
2064 if (y < 0)
2065 y++;
2066 else if (y)
2067 y--;
2068 } else {
2069 sc->flags |= PSM_FLAGS_FINGERDOWN;
2070 }
2071 sc->xold = x0;
2072 sc->yold = y0;
2073 } else {
2074 sc->flags &= ~PSM_FLAGS_FINGERDOWN;
2075 }
2076 c = ((x < 0) ? MOUSE_PS2_XNEG : 0)
2077 | ((y < 0) ? MOUSE_PS2_YNEG : 0);
2078 break;
2079
2080 case MOUSE_MODEL_4D:
2081 /*
2082 * b7 b6 b5 b4 b3 b2 b1 b0
2083 * byte 1: s2 d2 s1 d1 1 M R L
2084 * byte 2: sx x x x x x x x
2085 * byte 3: sy y y y y y y y
2086 *
2087 * s1: wheel 1 direction
2088 * d1: wheel 1 data
2089 * s2: wheel 2 direction
2090 * d2: wheel 2 data
2091 */
2092 x = (sc->ipacket[1] & 0x80) ? sc->ipacket[1] - 256 : sc->ipacket[1];
2093 y = (sc->ipacket[2] & 0x80) ? sc->ipacket[2] - 256 : sc->ipacket[2];
2094 switch (c & MOUSE_4D_WHEELBITS) {
2095 case 0x10:
2096 z = 1;
2097 break;
2098 case 0x30:
2099 z = -1;
2100 break;
2101 case 0x40: /* 2nd wheel turning right XXX */
2102 z = 2;
2103 break;
2104 case 0xc0: /* 2nd wheel turning left XXX */
2105 z = -2;
2106 break;
2107 }
2108 break;
2109
2110 case MOUSE_MODEL_4DPLUS:
2111 if ((x < 16 - 256) && (y < 16 - 256)) {
2112 /*
2113 * b7 b6 b5 b4 b3 b2 b1 b0
2114 * byte 1: 0 0 1 1 1 M R L
2115 * byte 2: 0 0 0 0 1 0 0 0
2116 * byte 3: 0 0 0 0 S s d1 d0
2117 *
2118 * L, M, R, S: left, middle, right and side buttons
2119 * s: wheel data sign bit
2120 * d1-d0: wheel data
2121 */
2122 x = y = 0;
2123 if (sc->ipacket[2] & MOUSE_4DPLUS_BUTTON4DOWN)
2124 ms.button |= MOUSE_BUTTON4DOWN;
2125 z = (sc->ipacket[2] & MOUSE_4DPLUS_ZNEG)
2126 ? ((sc->ipacket[2] & 0x07) - 8)
2127 : (sc->ipacket[2] & 0x07) ;
2128 } else {
2129 /* preserve previous button states */
2130 ms.button |= ms.obutton & MOUSE_EXTBUTTONS;
2131 }
2132 break;
2133
2134 case MOUSE_MODEL_GENERIC:
2135 default:
2136 break;
2137 }
2138
2139 /* scale values */
2140 if (sc->mode.accelfactor >= 1) {
2141 if (x != 0) {
2142 x = x * x / sc->mode.accelfactor;
2143 if (x == 0)
2144 x = 1;
2145 if (c & MOUSE_PS2_XNEG)
2146 x = -x;
2147 }
2148 if (y != 0) {
2149 y = y * y / sc->mode.accelfactor;
2150 if (y == 0)
2151 y = 1;
2152 if (c & MOUSE_PS2_YNEG)
2153 y = -y;
2154 }
2155 }
2156
2157 ms.dx = x;
2158 ms.dy = y;
2159 ms.dz = z;
2160 ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0)
2161 | (ms.obutton ^ ms.button);
2162
2163 if (sc->mode.level < PSM_LEVEL_NATIVE)
2164 sc->inputbytes = tame_mouse(sc, &ms, sc->ipacket);
2165
2166 sc->status.flags |= ms.flags;
2167 sc->status.dx += ms.dx;
2168 sc->status.dy += ms.dy;
2169 sc->status.dz += ms.dz;
2170 sc->status.button = ms.button;
2171 sc->button = ms.button;
2172
2173 sc->watchdog = FALSE;
2174
2175 /* queue data */
2176 if (sc->queue.count + sc->inputbytes < sizeof(sc->queue.buf)) {
2177 l = min(sc->inputbytes, sizeof(sc->queue.buf) - sc->queue.tail);
2178 bcopy(&sc->ipacket[0], &sc->queue.buf[sc->queue.tail], l);
2179 if (sc->inputbytes > l)
2180 bcopy(&sc->ipacket[l], &sc->queue.buf[0], sc->inputbytes - l);
2181 sc->queue.tail =
2182 (sc->queue.tail + sc->inputbytes) % sizeof(sc->queue.buf);
2183 sc->queue.count += sc->inputbytes;
2184 }
2185 sc->inputbytes = 0;
2186
2187 if (sc->state & PSM_ASLP) {
2188 sc->state &= ~PSM_ASLP;
2189 wakeup((caddr_t) sc);
2190 }
2191 selwakeup(&sc->rsel);
2192 }
2193 }
2194
2195 static int
2196 psmpoll(dev_t dev, int events, struct proc *p)
2197 {
2198 struct psm_softc *sc = psm_softc[PSM_UNIT(dev)];
2199 int s;
2200 int revents = 0;
2201
2202 /* Return true if a mouse event available */
2203 s = spltty();
2204 if (events & (POLLIN | POLLRDNORM))
2205 if (sc->queue.count > 0)
2206 revents |= events & (POLLIN | POLLRDNORM);
2207 else
2208 selrecord(p, &sc->rsel);
2209
2210 splx(s);
2211
2212 return (revents);
2213 }
2214
2215 /* vendor/model specific routines */
2216
2217 static int mouse_id_proc1(KBDC kbdc, int res, int scale, int *status)
2218 {
2219 if (set_mouse_resolution(kbdc, res) != res)
2220 return FALSE;
2221 if (set_mouse_scaling(kbdc, scale)
2222 && set_mouse_scaling(kbdc, scale)
2223 && set_mouse_scaling(kbdc, scale)
2224 && (get_mouse_status(kbdc, status, 0, 3) >= 3))
2225 return TRUE;
2226 return FALSE;
2227 }
2228
2229 #if notyet
2230 /* Logitech MouseMan Cordless II */
2231 static int
2232 enable_lcordless(struct psm_softc *sc)
2233 {
2234 int status[3];
2235 int ch;
2236
2237 if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 2, status))
2238 return FALSE;
2239 if (status[1] == PSMD_RES_HIGH)
2240 return FALSE;
2241 ch = (status[0] & 0x07) - 1; /* channel # */
2242 if ((ch <= 0) || (ch > 4))
2243 return FALSE;
2244 /*
2245 * status[1]: always one?
2246 * status[2]: battery status? (0-100)
2247 */
2248 return TRUE;
2249 }
2250 #endif /* notyet */
2251
2252 /* Genius NetScroll Mouse, MouseSystems SmartScroll Mouse */
2253 static int
2254 enable_groller(struct psm_softc *sc)
2255 {
2256 int status[3];
2257
2258 /*
2259 * The special sequence to enable the fourth button and the
2260 * roller. Immediately after this sequence check status bytes.
2261 * if the mouse is NetScroll, the second and the third bytes are
2262 * '3' and 'D'.
2263 */
2264
2265 /*
2266 * If the mouse is an ordinary PS/2 mouse, the status bytes should
2267 * look like the following.
2268 *
2269 * byte 1 bit 7 always 0
2270 * bit 6 stream mode (0)
2271 * bit 5 disabled (0)
2272 * bit 4 1:1 scaling (0)
2273 * bit 3 always 0
2274 * bit 0-2 button status
2275 * byte 2 resolution (PSMD_RES_HIGH)
2276 * byte 3 report rate (?)
2277 */
2278
2279 if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status))
2280 return FALSE;
2281 if ((status[1] != '3') || (status[2] != 'D'))
2282 return FALSE;
2283 /* FIXME: SmartScroll Mouse has 5 buttons! XXX */
2284 sc->hw.buttons = 4;
2285 return TRUE;
2286 }
2287
2288 /* Genius NetMouse/NetMouse Pro, ASCII Mie Mouse, NetScroll Optical */
2289 static int
2290 enable_gmouse(struct psm_softc *sc)
2291 {
2292 int status[3];
2293
2294 /*
2295 * The special sequence to enable the middle, "rubber" button.
2296 * Immediately after this sequence check status bytes.
2297 * if the mouse is NetMouse, NetMouse Pro, or ASCII MIE Mouse,
2298 * the second and the third bytes are '3' and 'U'.
2299 * NOTE: NetMouse reports that it has three buttons although it has
2300 * two buttons and a rubber button. NetMouse Pro and MIE Mouse
2301 * say they have three buttons too and they do have a button on the
2302 * side...
2303 */
2304 if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status))
2305 return FALSE;
2306 if ((status[1] != '3') || (status[2] != 'U'))
2307 return FALSE;
2308 return TRUE;
2309 }
2310
2311 /* ALPS GlidePoint */
2312 static int
2313 enable_aglide(struct psm_softc *sc)
2314 {
2315 int status[3];
2316
2317 /*
2318 * The special sequence to obtain ALPS GlidePoint specific
2319 * information. Immediately after this sequence, status bytes will
2320 * contain something interesting.
2321 * NOTE: ALPS produces several models of GlidePoint. Some of those
2322 * do not respond to this sequence, thus, cannot be detected this way.
2323 */
2324 if (set_mouse_sampling_rate(sc->kbdc, 100) != 100)
2325 return FALSE;
2326 if (!mouse_id_proc1(sc->kbdc, PSMD_RES_LOW, 2, status))
2327 return FALSE;
2328 if ((status[1] == PSMD_RES_LOW) || (status[2] == 100))
2329 return FALSE;
2330 return TRUE;
2331 }
2332
2333 /* Kensington ThinkingMouse/Trackball */
2334 static int
2335 enable_kmouse(struct psm_softc *sc)
2336 {
2337 static unsigned char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 };
2338 KBDC kbdc = sc->kbdc;
2339 int status[3];
2340 int id1;
2341 int id2;
2342 int i;
2343
2344 id1 = get_aux_id(kbdc);
2345 if (set_mouse_sampling_rate(kbdc, 10) != 10)
2346 return FALSE;
2347 /*
2348 * The device is now in the native mode? It returns a different
2349 * ID value...
2350 */
2351 id2 = get_aux_id(kbdc);
2352 if ((id1 == id2) || (id2 != 2))
2353 return FALSE;
2354
2355 if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)
2356 return FALSE;
2357 #if PSM_DEBUG >= 2
2358 /* at this point, resolution is LOW, sampling rate is 10/sec */
2359 if (get_mouse_status(kbdc, status, 0, 3) < 3)
2360 return FALSE;
2361 #endif
2362
2363 /*
2364 * The special sequence to enable the third and fourth buttons.
2365 * Otherwise they behave like the first and second buttons.
2366 */
2367 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2368 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2369 return FALSE;
2370 }
2371
2372 /*
2373 * At this point, the device is using default resolution and
2374 * sampling rate for the native mode.
2375 */
2376 if (get_mouse_status(kbdc, status, 0, 3) < 3)
2377 return FALSE;
2378 if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1]))
2379 return FALSE;
2380
2381 /* the device appears be enabled by this sequence, diable it for now */
2382 disable_aux_dev(kbdc);
2383 empty_aux_buffer(kbdc, 5);
2384
2385 return TRUE;
2386 }
2387
2388 /* Logitech MouseMan+/FirstMouse+, IBM ScrollPoint Mouse */
2389 static int
2390 enable_mmanplus(struct psm_softc *sc)
2391 {
2392 static char res[] = {
2393 -1, PSMD_RES_LOW, PSMD_RES_HIGH, PSMD_RES_MEDIUM_HIGH,
2394 PSMD_RES_MEDIUM_LOW, -1, PSMD_RES_HIGH, PSMD_RES_MEDIUM_LOW,
2395 PSMD_RES_MEDIUM_HIGH, PSMD_RES_HIGH,
2396 };
2397 KBDC kbdc = sc->kbdc;
2398 int data[3];
2399 int i;
2400
2401 /* the special sequence to enable the fourth button and the roller. */
2402 /*
2403 * NOTE: for ScrollPoint to respond correctly, the SET_RESOLUTION
2404 * must be called exactly three times since the last RESET command
2405 * before this sequence. XXX
2406 */
2407 for (i = 0; i < sizeof(res)/sizeof(res[0]); ++i) {
2408 if (res[i] < 0) {
2409 if (!set_mouse_scaling(kbdc, 1))
2410 return FALSE;
2411 } else {
2412 if (set_mouse_resolution(kbdc, res[i]) != res[i])
2413 return FALSE;
2414 }
2415 }
2416
2417 if (get_mouse_status(kbdc, data, 1, 3) < 3)
2418 return FALSE;
2419
2420 /*
2421 * PS2++ protocl, packet type 0
2422 *
2423 * b7 b6 b5 b4 b3 b2 b1 b0
2424 * byte 1: * 1 p3 p2 1 * * *
2425 * byte 2: 1 1 p1 p0 m1 m0 1 0
2426 * byte 3: m7 m6 m5 m4 m3 m2 m1 m0
2427 *
2428 * p3-p0: packet type: 0
2429 * m7-m0: model ID: MouseMan+:0x50, FirstMouse+:0x51, ScrollPoint:0x58...
2430 */
2431 /* check constant bits */
2432 if ((data[0] & MOUSE_PS2PLUS_SYNCMASK) != MOUSE_PS2PLUS_SYNC)
2433 return FALSE;
2434 if ((data[1] & 0xc3) != 0xc2)
2435 return FALSE;
2436 /* check d3-d0 in byte 2 */
2437 if (!MOUSE_PS2PLUS_CHECKBITS(data))
2438 return FALSE;
2439 /* check p3-p0 */
2440 if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0)
2441 return FALSE;
2442
2443 sc->hw.hwid &= 0x00ff;
2444 sc->hw.hwid |= data[2] << 8; /* save model ID */
2445
2446 /*
2447 * MouseMan+ (or FirstMouse+) is now in its native mode, in which
2448 * the wheel and the fourth button events are encoded in the
2449 * special data packet. The mouse may be put in the IntelliMouse mode
2450 * if it is initialized by the IntelliMouse's method.
2451 */
2452 return TRUE;
2453 }
2454
2455 /* MS IntelliMouse Explorer */
2456 static int
2457 enable_msexplorer(struct psm_softc *sc)
2458 {
2459 static unsigned char rate[] = { 200, 200, 80, };
2460 KBDC kbdc = sc->kbdc;
2461 int id;
2462 int i;
2463
2464 /* the special sequence to enable the extra buttons and the roller. */
2465 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2466 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2467 return FALSE;
2468 }
2469 /* the device will give the genuine ID only after the above sequence */
2470 id = get_aux_id(kbdc);
2471 if (id != PSM_EXPLORER_ID)
2472 return FALSE;
2473
2474 sc->hw.hwid = id;
2475 sc->hw.buttons = 5; /* IntelliMouse Explorer XXX */
2476
2477 return TRUE;
2478 }
2479
2480 /* MS IntelliMouse */
2481 static int
2482 enable_msintelli(struct psm_softc *sc)
2483 {
2484 /*
2485 * Logitech MouseMan+ and FirstMouse+ will also respond to this
2486 * probe routine and act like IntelliMouse.
2487 */
2488
2489 static unsigned char rate[] = { 200, 100, 80, };
2490 KBDC kbdc = sc->kbdc;
2491 int id;
2492 int i;
2493
2494 /* the special sequence to enable the third button and the roller. */
2495 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2496 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2497 return FALSE;
2498 }
2499 /* the device will give the genuine ID only after the above sequence */
2500 id = get_aux_id(kbdc);
2501 if (id != PSM_INTELLI_ID)
2502 return FALSE;
2503
2504 sc->hw.hwid = id;
2505 sc->hw.buttons = 3;
2506
2507 return TRUE;
2508 }
2509
2510 /* A4 Tech 4D Mouse */
2511 static int
2512 enable_4dmouse(struct psm_softc *sc)
2513 {
2514 /*
2515 * Newer wheel mice from A4 Tech may use the 4D+ protocol.
2516 */
2517
2518 static unsigned char rate[] = { 200, 100, 80, 60, 40, 20 };
2519 KBDC kbdc = sc->kbdc;
2520 int id;
2521 int i;
2522
2523 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2524 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2525 return FALSE;
2526 }
2527 id = get_aux_id(kbdc);
2528 /*
2529 * WinEasy 4D, 4 Way Scroll 4D: 6
2530 * Cable-Free 4D: 8 (4DPLUS)
2531 * WinBest 4D+, 4 Way Scroll 4D+: 8 (4DPLUS)
2532 */
2533 if (id != PSM_4DMOUSE_ID)
2534 return FALSE;
2535
2536 sc->hw.hwid = id;
2537 sc->hw.buttons = 3; /* XXX some 4D mice have 4? */
2538
2539 return TRUE;
2540 }
2541
2542 /* A4 Tech 4D+ Mouse */
2543 static int
2544 enable_4dplus(struct psm_softc *sc)
2545 {
2546 /*
2547 * Newer wheel mice from A4 Tech seem to use this protocol.
2548 * Older models are recognized as either 4D Mouse or IntelliMouse.
2549 */
2550 KBDC kbdc = sc->kbdc;
2551 int id;
2552
2553 /*
2554 * enable_4dmouse() already issued the following ID sequence...
2555 static unsigned char rate[] = { 200, 100, 80, 60, 40, 20 };
2556 int i;
2557
2558 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2559 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2560 return FALSE;
2561 }
2562 */
2563
2564 id = get_aux_id(kbdc);
2565 if (id != PSM_4DPLUS_ID)
2566 return FALSE;
2567
2568 sc->hw.hwid = id;
2569 sc->hw.buttons = 4; /* XXX */
2570
2571 return TRUE;
2572 }
2573
2574 /* Interlink electronics VersaPad */
2575 static int
2576 enable_versapad(struct psm_softc *sc)
2577 {
2578 KBDC kbdc = sc->kbdc;
2579 int data[3];
2580
2581 set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */
2582 set_mouse_sampling_rate(kbdc, 100); /* set rate 100 */
2583 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */
2584 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */
2585 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */
2586 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */
2587 if (get_mouse_status(kbdc, data, 0, 3) < 3) /* get status */
2588 return FALSE;
2589 if (data[2] != 0xa || data[1] != 0 ) /* rate == 0xa && res. == 0 */
2590 return FALSE;
2591 set_mouse_scaling(kbdc, 1); /* set scale 1:1 */
2592
2593 sc->config |= PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
2594
2595 return TRUE; /* PS/2 absolute mode */
2596 }
2597
2598 static int psm_devsw_installed = FALSE;
2599
2600 static void
2601 psm_drvinit(void *unused)
2602 {
2603 dev_t dev;
2604
2605 if (!psm_devsw_installed) {
2606 dev = makedev(CDEV_MAJOR, 0);
2607 cdevsw_add(&dev, &psm_cdevsw, NULL);
2608 psm_devsw_installed = TRUE;
2609 }
2610 }
2611
2612 #if NAPM > 0
2613 static int
2614 psmresume(void *dummy)
2615 {
2616 struct psm_softc *sc = psm_softc[(int)dummy];
2617 int unit = (int)dummy;
2618 int err = 0;
2619 int s;
2620 int c;
2621
2622 if (verbose >= 2)
2623 log(LOG_NOTICE, "psm%d: APM resume hook called.\n", unit);
2624
2625 if (!(sc->config & PSM_CONFIG_HOOKRESUME))
2626 return (0);
2627
2628 /* don't let anybody mess with the aux device */
2629 if (!kbdc_lock(sc->kbdc, TRUE))
2630 return (EIO);
2631 s = spltty();
2632
2633 /* block our watchdog timer */
2634 sc->watchdog = FALSE;
2635 untimeout(psmtimeout, (void *)unit, sc->callout);
2636 callout_handle_init(&sc->callout);
2637
2638 /* save the current controller command byte */
2639 empty_both_buffers(sc->kbdc, 10);
2640 c = get_controller_command_byte(sc->kbdc);
2641 if (verbose >= 2)
2642 log(LOG_DEBUG, "psm%d: current command byte: %04x (psmresume).\n",
2643 unit, c);
2644
2645 /* enable the aux port but disable the aux interrupt and the keyboard */
2646 if ((c == -1) || !set_controller_command_byte(sc->kbdc,
2647 kbdc_get_device_mask(sc->kbdc),
2648 KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
2649 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
2650 /* CONTROLLER ERROR */
2651 splx(s);
2652 kbdc_lock(sc->kbdc, FALSE);
2653 log(LOG_ERR, "psm%d: unable to set the command byte (psmresume).\n",
2654 unit);
2655 return (EIO);
2656 }
2657
2658 /* flush any data */
2659 if (sc->state & PSM_VALID) {
2660 disable_aux_dev(sc->kbdc); /* this may fail; but never mind... */
2661 empty_aux_buffer(sc->kbdc, 10);
2662 }
2663 sc->inputbytes = 0;
2664
2665 /* try to detect the aux device; are you still there? */
2666 if (sc->config & PSM_CONFIG_INITAFTERSUSPEND) {
2667 if (reinitialize(unit, &sc->mode)) {
2668 /* yes */
2669 sc->state |= PSM_VALID;
2670 } else {
2671 /* the device has gone! */
2672 restore_controller(sc->kbdc, c);
2673 sc->state &= ~PSM_VALID;
2674 log(LOG_ERR, "psm%d: the aux device has gone! (psmresume).\n",
2675 unit);
2676 err = ENXIO;
2677 }
2678 }
2679 splx(s);
2680
2681 /* restore the driver state */
2682 if ((sc->state & PSM_OPEN) && (err == 0)) {
2683 /* enable the aux device and the port again */
2684 err = doopen(unit, c);
2685 if (err != 0)
2686 log(LOG_ERR, "psm%d: failed to enable the device (psmresume).\n",
2687 unit);
2688 } else {
2689 /* restore the keyboard port and disable the aux port */
2690 if (!set_controller_command_byte(sc->kbdc,
2691 kbdc_get_device_mask(sc->kbdc),
2692 (c & KBD_KBD_CONTROL_BITS)
2693 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
2694 /* CONTROLLER ERROR */
2695 log(LOG_ERR, "psm%d: failed to disable the aux port (psmresume).\n",
2696 unit);
2697 err = EIO;
2698 }
2699 }
2700
2701 /* done */
2702 kbdc_lock(sc->kbdc, FALSE);
2703 if ((sc->state & PSM_ASLP) && !(sc->state & PSM_VALID)) {
2704 /*
2705 * Release the blocked process; it must be notified that the device
2706 * cannot be accessed anymore.
2707 */
2708 sc->state &= ~PSM_ASLP;
2709 wakeup((caddr_t)sc);
2710 }
2711
2712 if (verbose >= 2)
2713 log(LOG_DEBUG, "psm%d: APM resume hook exiting.\n", unit);
2714
2715 return (err);
2716 }
2717 #endif /* NAPM > 0 */
2718
2719 SYSINIT(psmdev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE + CDEV_MAJOR, psm_drvinit, NULL)
2720
2721 #endif /* NPSM > 0 */
Cache object: 48831c1b55a0b9cfbe3d1ff7936d78d3
|