Merge branch 'vendor/GCC47'
[dragonfly.git] / sys / dev / misc / psm / 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 /*
24  *  Ported to 386bsd Oct 17, 1992
25  *  Sandi Donno, Computer Science, University of Cape Town, South Africa
26  *  Please send bug reports to sandi@cs.uct.ac.za
27  *
28  *  Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca -
29  *  although I was only partially successful in getting the alpha release
30  *  of his "driver for the Logitech and ATI Inport Bus mice for use with
31  *  386bsd and the X386 port" to work with my Microsoft mouse, I nevertheless
32  *  found his code to be an invaluable reference when porting this driver
33  *  to 386bsd.
34  *
35  *  Further modifications for latest 386BSD+patchkit and port to NetBSD,
36  *  Andrew Herbert <andrew@werple.apana.org.au> - 8 June 1993
37  *
38  *  Cloned from the Microsoft Bus Mouse driver, also by Erik Forsberg, by
39  *  Andrew Herbert - 12 June 1993
40  *
41  *  Modified for PS/2 mouse by Charles Hannum <mycroft@ai.mit.edu>
42  *  - 13 June 1993
43  *
44  *  Modified for PS/2 AUX mouse by Shoji Yuen <yuen@nuie.nagoya-u.ac.jp>
45  *  - 24 October 1993
46  *
47  *  Hardware access routines and probe logic rewritten by
48  *  Kazutaka Yokota <yokota@zodiac.mech.utsunomiya-u.ac.jp>
49  *  - 3, 14, 22 October 1996.
50  *  - 12 November 1996. IOCTLs and rearranging `psmread', `psmioctl'...
51  *  - 14, 30 November 1996. Uses `kbdio.c'.
52  *  - 13 December 1996. Uses queuing version of `kbdio.c'.
53  *  - January/February 1997. Tweaked probe logic for
54  *    HiNote UltraII/Latitude/Armada laptops.
55  *  - 30 July 1997. Added APM support.
56  *  - 5 March 1997. Defined driver configuration flags (PSM_CONFIG_XXX).
57  *    Improved sync check logic.
58  *    Vendor specific support routines.
59  *
60  * $FreeBSD: src/sys/dev/atkbdc/psm.c,v 1.107 2010/09/09 07:52:15 ed Exp $
61  */
62 #include "opt_psm.h"
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/kernel.h>
67 #include <sys/module.h>
68 #include <sys/bus.h>
69 #include <sys/conf.h>
70 #include <sys/device.h>
71 #include <sys/event.h>
72 #include <sys/syslog.h>
73 #include <sys/malloc.h>
74 #include <sys/rman.h>
75 #include <sys/sysctl.h>
76 #include <sys/thread2.h>
77 #include <sys/time.h>
78 #include <sys/uio.h>
79 #include <sys/machintr.h>
80
81 #include <machine/clock.h>
82 #include <machine/limits.h>
83 #include <sys/mouse.h>
84
85 #include <bus/isa/isavar.h>
86 #include <dev/misc/kbd/atkbdcreg.h>
87
88 /*
89  * Driver specific options: the following options may be set by
90  * `options' statements in the kernel configuration file.
91  */
92
93 /* debugging */
94 #ifndef PSM_DEBUG
95 #define PSM_DEBUG       0       /*
96                                  * logging: 0: none, 1: brief, 2: verbose
97                                  *          3: sync errors, 4: all packets
98                                  */
99 #endif
100 #define VLOG(level, args)       do {    \
101         if (verbose >= level)           \
102                 log args;               \
103 } while (0)
104
105 #ifndef PSM_INPUT_TIMEOUT
106 #define PSM_INPUT_TIMEOUT       2000000 /* 2 sec */
107 #endif
108
109 #ifndef PSM_TAP_TIMEOUT
110 #define PSM_TAP_TIMEOUT         125000
111 #endif
112
113 #ifndef PSM_TAP_THRESHOLD
114 #define PSM_TAP_THRESHOLD       25
115 #endif
116
117 /* end of driver specific options */
118
119 #define PSM_DRIVER_NAME       "psm"
120 #define PSMCPNP_DRIVER_NAME     "psmcpnp"
121
122 /* input queue */
123 #define PSM_BUFSIZE             960
124 #define PSM_SMALLBUFSIZE        240
125
126 /* operation levels */
127 #define PSM_LEVEL_BASE          0
128 #define PSM_LEVEL_STANDARD      1
129 #define PSM_LEVEL_NATIVE        2
130 #define PSM_LEVEL_MIN           PSM_LEVEL_BASE
131 #define PSM_LEVEL_MAX           PSM_LEVEL_NATIVE
132
133 /* Logitech PS2++ protocol */
134 #define MOUSE_PS2PLUS_CHECKBITS(b)      \
135     ((((b[2] & 0x03) << 2) | 0x02) == (b[1] & 0x0f))
136 #define MOUSE_PS2PLUS_PACKET_TYPE(b)    \
137     (((b[0] & 0x30) >> 2) | ((b[1] & 0x30) >> 4))
138
139 /* some macros */
140 #define PSM_UNIT(dev)         (minor(dev) >> 1)
141 #define PSM_NBLOCKIO(dev)     (minor(dev) & 1)
142 #define PSM_MKMINOR(unit,block)    ((((unit) & 0xff) << 1) | ((block) ? 0:1))
143
144 /* ring buffer */
145 typedef struct ringbuf {
146         int             count;  /* # of valid elements in the buffer */
147         int             head;   /* head pointer */
148         int             tail;   /* tail poiner */
149         u_char buf[PSM_BUFSIZE];
150 } ringbuf_t;
151
152 /* data buffer */
153 typedef struct packetbuf {
154         u_char  ipacket[16];    /* interim input buffer */
155         int     inputbytes;     /* # of bytes in the input buffer */
156 } packetbuf_t;
157
158 #ifndef PSM_PACKETQUEUE
159 #define PSM_PACKETQUEUE 128
160 #endif
161
162 enum {
163         SYNAPTICS_SYSCTL_MIN_PRESSURE,
164         SYNAPTICS_SYSCTL_MAX_PRESSURE,
165         SYNAPTICS_SYSCTL_MAX_WIDTH,
166         SYNAPTICS_SYSCTL_MARGIN_TOP,
167         SYNAPTICS_SYSCTL_MARGIN_RIGHT,
168         SYNAPTICS_SYSCTL_MARGIN_BOTTOM,
169         SYNAPTICS_SYSCTL_MARGIN_LEFT,
170         SYNAPTICS_SYSCTL_NA_TOP,
171         SYNAPTICS_SYSCTL_NA_RIGHT,
172         SYNAPTICS_SYSCTL_NA_BOTTOM,
173         SYNAPTICS_SYSCTL_NA_LEFT,
174         SYNAPTICS_SYSCTL_WINDOW_MIN,
175         SYNAPTICS_SYSCTL_WINDOW_MAX,
176         SYNAPTICS_SYSCTL_MULTIPLICATOR,
177         SYNAPTICS_SYSCTL_WEIGHT_CURRENT,
178         SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS,
179         SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA,
180         SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED,
181         SYNAPTICS_SYSCTL_DIV_MIN,
182         SYNAPTICS_SYSCTL_DIV_MAX,
183         SYNAPTICS_SYSCTL_DIV_MAX_NA,
184         SYNAPTICS_SYSCTL_DIV_LEN,
185         SYNAPTICS_SYSCTL_TAP_MAX_DELTA,
186         SYNAPTICS_SYSCTL_TAP_MIN_QUEUE,
187         SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT,
188         SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA,
189         SYNAPTICS_SYSCTL_VSCROLL_VER_AREA,
190         SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA,
191         SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN,
192         SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX
193 };
194
195 typedef struct synapticsinfo {
196         struct sysctl_ctx_list   sysctl_ctx;
197         struct sysctl_oid       *sysctl_tree;
198         int                      directional_scrolls;
199         int                      min_pressure;
200         int                      max_pressure;
201         int                      max_width;
202         int                      margin_top;
203         int                      margin_right;
204         int                      margin_bottom;
205         int                      margin_left;
206         int                      na_top;
207         int                      na_right;
208         int                      na_bottom;
209         int                      na_left;
210         int                      window_min;
211         int                      window_max;
212         int                      multiplicator;
213         int                      weight_current;
214         int                      weight_previous;
215         int                      weight_previous_na;
216         int                      weight_len_squared;
217         int                      div_min;
218         int                      div_max;
219         int                      div_max_na;
220         int                      div_len;
221         int                      tap_max_delta;
222         int                      tap_min_queue;
223         int                      taphold_timeout;
224         int                      vscroll_ver_area;
225         int                      vscroll_hor_area;
226         int                      vscroll_min_delta;
227         int                      vscroll_div_min;
228         int                      vscroll_div_max;
229 } synapticsinfo_t;
230
231 typedef struct synapticspacket {
232         int                     x;
233         int                     y;
234 } synapticspacket_t;
235
236 #define SYNAPTICS_PACKETQUEUE 10
237 #define SYNAPTICS_QUEUE_CURSOR(x)                                       \
238         (x + SYNAPTICS_PACKETQUEUE) % SYNAPTICS_PACKETQUEUE
239
240 typedef struct synapticsaction {
241         synapticspacket_t       queue[SYNAPTICS_PACKETQUEUE];
242         int                     queue_len;
243         int                     queue_cursor;
244         int                     window_min;
245         int                     start_x;
246         int                     start_y;
247         int                     avg_dx;
248         int                     avg_dy;
249         int                     squelch_x;
250         int                     squelch_y;
251         int                     fingers_nb;
252         int                     tap_button;
253         int                     in_taphold;
254         int                     in_vscroll;
255 } synapticsaction_t;
256
257 /* driver control block */
258 struct psm_softc {              /* Driver status information */
259         int             unit;
260         struct kqinfo rkq;         /* Processes with registered kevents */
261         u_char          state;          /* Mouse driver state */
262         int             config;         /* driver configuration flags */
263         int             flags;          /* other flags */
264         KBDC            kbdc;           /* handle to access kbd controller */
265         struct resource *intr;          /* IRQ resource */
266         void            *ih;            /* interrupt handle */
267         mousehw_t       hw;             /* hardware information */
268         synapticshw_t   synhw;          /* Synaptics hardware information */
269         synapticsinfo_t syninfo;        /* Synaptics configuration */
270         synapticsaction_t synaction;    /* Synaptics action context */
271         mousemode_t     mode;           /* operation mode */
272         mousemode_t     dflt_mode;      /* default operation mode */
273         mousestatus_t   status;         /* accumulated mouse movement */
274         ringbuf_t       queue;          /* mouse status queue */
275         packetbuf_t     pqueue[PSM_PACKETQUEUE]; /* mouse data queue */
276         int             pqueue_start;   /* start of data in queue */
277         int             pqueue_end;     /* end of data in queue */
278         int             button;         /* the latest button state */
279         int             xold;           /* previous absolute X position */
280         int             yold;           /* previous absolute Y position */
281         int             xaverage;       /* average X position */
282         int             yaverage;       /* average Y position */
283         int             squelch; /* level to filter movement at low speed */
284         int             zmax;   /* maximum pressure value for touchpads */
285         int             syncerrors; /* # of bytes discarded to synchronize */
286         int             pkterrors;  /* # of packets failed during quaranteen. */
287         struct timeval  inputtimeout;
288         struct timeval  lastsoftintr;   /* time of last soft interrupt */
289         struct timeval  lastinputerr;   /* time last sync error happened */
290         struct timeval  taptimeout;     /* tap timeout for touchpads */
291         int             watchdog;       /* watchdog timer flag */
292         struct callout   callout;       /* watchdog timer call out */
293         struct callout   softcallout; /* buffer timer call out */
294         struct cdev     *dev;
295         struct cdev     *bdev;
296         int             lasterr;
297         int             cmdcount;
298         struct sigio    *async;         /* Processes waiting for SIGIO */
299 };
300 static devclass_t psm_devclass;
301 #define PSM_SOFTC(unit)  ((struct psm_softc*)devclass_get_softc(psm_devclass, unit))
302
303 /* driver state flags (state) */
304 #define PSM_VALID               0x80
305 #define PSM_OPEN                1       /* Device is open */
306 #define PSM_ASLP                2       /* Waiting for mouse data */
307 #define PSM_SOFTARMED           4       /* Software interrupt armed */
308 #define PSM_NEED_SYNCBITS       8       /* Set syncbits using next data pkt */
309
310 /* driver configuration flags (config) */
311 #define PSM_CONFIG_RESOLUTION   0x000f  /* resolution */
312 #define PSM_CONFIG_ACCEL        0x00f0  /* acceleration factor */
313 #define PSM_CONFIG_NOCHECKSYNC  0x0100  /* disable sync. test */
314 #define PSM_CONFIG_NOIDPROBE    0x0200  /* disable mouse model probe */
315 #define PSM_CONFIG_NORESET      0x0400  /* don't reset the mouse */
316 #define PSM_CONFIG_FORCETAP     0x0800  /* assume `tap' action exists */
317 #define PSM_CONFIG_IGNPORTERROR 0x1000  /* ignore error in aux port test */
318 #define PSM_CONFIG_HOOKRESUME   0x2000  /* hook the system resume event */
319 #define PSM_CONFIG_INITAFTERSUSPEND 0x4000 /* init the device at the resume event */
320 #define PSM_CONFIG_SYNCHACK     0x8000  /* enable `out-of-sync' hack */
321
322 #define PSM_CONFIG_FLAGS        \
323     (PSM_CONFIG_RESOLUTION |    \
324     PSM_CONFIG_ACCEL |          \
325     PSM_CONFIG_NOCHECKSYNC |    \
326     PSM_CONFIG_SYNCHACK |       \
327     PSM_CONFIG_NOIDPROBE |      \
328     PSM_CONFIG_NORESET |        \
329     PSM_CONFIG_FORCETAP |       \
330     PSM_CONFIG_IGNPORTERROR |   \
331     PSM_CONFIG_HOOKRESUME |     \
332     PSM_CONFIG_INITAFTERSUSPEND)
333
334 /* other flags (flags) */
335 #define PSM_FLAGS_FINGERDOWN    0x0001  /* VersaPad finger down */
336
337 /* Tunables */
338 static int tap_enabled = -1;
339 TUNABLE_INT("hw.psm.tap_enabled", &tap_enabled);
340
341 static int synaptics_support = 0;
342 TUNABLE_INT("hw.psm.synaptics_support", &synaptics_support);
343
344 static int verbose = PSM_DEBUG;
345 TUNABLE_INT("debug.psm.loglevel", &verbose);
346
347 /* for backward compatibility */
348 #define OLD_MOUSE_GETHWINFO     _IOR('M', 1, old_mousehw_t)
349 #define OLD_MOUSE_GETMODE       _IOR('M', 2, old_mousemode_t)
350 #define OLD_MOUSE_SETMODE       _IOW('M', 3, old_mousemode_t)
351
352 typedef struct old_mousehw {
353         int     buttons;
354         int     iftype;
355         int     type;
356         int     hwid;
357 } old_mousehw_t;
358
359 typedef struct old_mousemode {
360         int     protocol;
361         int     rate;
362         int     resolution;
363         int     accelfactor;
364 } old_mousemode_t;
365
366 /* packet formatting function */
367 typedef int     packetfunc_t(struct psm_softc *, u_char *, int *, int,
368     mousestatus_t *);
369
370 /* function prototypes */
371 static void     psmidentify(driver_t *, device_t);
372 static int      psmprobe(device_t);
373 static int      psmattach(device_t);
374 static int      psmdetach(device_t);
375 static int      psmresume(device_t);
376
377 static d_open_t         psmopen;
378 static d_close_t        psmclose;
379 static d_read_t         psmread;
380 static d_write_t        psmwrite;
381 static d_ioctl_t        psmioctl;
382 static d_kqfilter_t psmkqfilter;
383
384 static int      enable_aux_dev(KBDC);
385 static int      disable_aux_dev(KBDC);
386 static int      get_mouse_status(KBDC, int *, int, int);
387 static int      get_aux_id(KBDC);
388 static int      set_mouse_sampling_rate(KBDC, int);
389 static int      set_mouse_scaling(KBDC, int);
390 static int      set_mouse_resolution(KBDC, int);
391 static int      set_mouse_mode(KBDC);
392 static int      get_mouse_buttons(KBDC);
393 static int      is_a_mouse(int);
394 static void     recover_from_error(KBDC);
395 static int      restore_controller(KBDC, int);
396 static int      doinitialize(struct psm_softc *, mousemode_t *);
397 static int      doopen(struct psm_softc *, int);
398 static int      reinitialize(struct psm_softc *, int);
399 static char     *model_name(int);
400 static void     psmsoftintr(void *);
401 static void     psmintr(void *);
402 static void     psmtimeout(void *);
403 static void    psmfilter_detach(struct knote *);
404 static int     psmfilter(struct knote *, long);
405 static int      timeelapsed(const struct timeval *, int, int,
406                     const struct timeval *);
407 static void     dropqueue(struct psm_softc *);
408 static void     flushpackets(struct psm_softc *);
409 static void     proc_mmanplus(struct psm_softc *, packetbuf_t *,
410                     mousestatus_t *, int *, int *, int *);
411 static int      proc_synaptics(struct psm_softc *, packetbuf_t *,
412                     mousestatus_t *, int *, int *, int *);
413 static void     proc_versapad(struct psm_softc *, packetbuf_t *,
414                     mousestatus_t *, int *, int *, int *);
415 static int      tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *,
416                     u_char *);
417
418 /* vendor specific features */
419 typedef int     probefunc_t(struct psm_softc *);
420
421 static int      mouse_id_proc1(KBDC, int, int, int *);
422 static int      mouse_ext_command(KBDC, int);
423
424 static probefunc_t      enable_groller;
425 static probefunc_t      enable_gmouse;
426 static probefunc_t      enable_aglide;
427 static probefunc_t      enable_kmouse;
428 static probefunc_t      enable_msexplorer;
429 static probefunc_t      enable_msintelli;
430 static probefunc_t      enable_4dmouse;
431 static probefunc_t      enable_4dplus;
432 static probefunc_t      enable_mmanplus;
433 static probefunc_t      enable_synaptics;
434 static probefunc_t      enable_versapad;
435
436 static struct {
437         int             model;
438         u_char          syncmask;
439         int             packetsize;
440         probefunc_t     *probefunc;
441 } vendortype[] = {
442         /*
443          * WARNING: the order of probe is very important.  Don't mess it
444          * unless you know what you are doing.
445          */
446         { MOUSE_MODEL_NET,              /* Genius NetMouse */
447           0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_gmouse },
448         { MOUSE_MODEL_NETSCROLL,        /* Genius NetScroll */
449           0xc8, 6, enable_groller },
450         { MOUSE_MODEL_MOUSEMANPLUS,     /* Logitech MouseMan+ */
451           0x08, MOUSE_PS2_PACKETSIZE, enable_mmanplus },
452         { MOUSE_MODEL_EXPLORER,         /* Microsoft IntelliMouse Explorer */
453           0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msexplorer },
454         { MOUSE_MODEL_4D,               /* A4 Tech 4D Mouse */
455           0x08, MOUSE_4D_PACKETSIZE, enable_4dmouse },
456         { MOUSE_MODEL_4DPLUS,           /* A4 Tech 4D+ Mouse */
457           0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus },
458         { MOUSE_MODEL_SYNAPTICS,        /* Synaptics Touchpad */
459           0xc0, MOUSE_SYNAPTICS_PACKETSIZE, enable_synaptics },
460         { MOUSE_MODEL_INTELLI,          /* Microsoft IntelliMouse */
461           0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli },
462         { MOUSE_MODEL_GLIDEPOINT,       /* ALPS GlidePoint */
463           0xc0, MOUSE_PS2_PACKETSIZE, enable_aglide },
464         { MOUSE_MODEL_THINK,            /* Kensington ThinkingMouse */
465           0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse },
466         { MOUSE_MODEL_VERSAPAD,         /* Interlink electronics VersaPad */
467           0xe8, MOUSE_PS2VERSA_PACKETSIZE, enable_versapad },
468         { MOUSE_MODEL_GENERIC,
469           0xc0, MOUSE_PS2_PACKETSIZE, NULL },
470 };
471 #define GENERIC_MOUSE_ENTRY     (NELEM(vendortype) - 1)
472
473 /* device driver declarateion */
474 static device_method_t psm_methods[] = {
475         /* Device interface */
476         DEVMETHOD(device_identify,      psmidentify),
477         DEVMETHOD(device_probe,         psmprobe),
478         DEVMETHOD(device_attach,        psmattach),
479         DEVMETHOD(device_detach,        psmdetach),
480         DEVMETHOD(device_resume,        psmresume),
481
482         DEVMETHOD_END
483 };
484
485 static driver_t psm_driver = {
486         PSM_DRIVER_NAME,
487         psm_methods,
488         sizeof(struct psm_softc),
489 };
490
491 static struct dev_ops psm_ops = {
492         { PSM_DRIVER_NAME, 0, 0 },
493         .d_open =   psmopen,
494         .d_close =  psmclose,
495         .d_read =   psmread,
496         .d_write =  psmwrite,
497         .d_ioctl =  psmioctl,
498         .d_kqfilter =    psmkqfilter
499 };
500
501 /* device I/O routines */
502 static int
503 enable_aux_dev(KBDC kbdc)
504 {
505         int res;
506
507         res = send_aux_command(kbdc, PSMC_ENABLE_DEV);
508         VLOG(2, (LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res));
509
510         return (res == PSM_ACK);
511 }
512
513 static int
514 disable_aux_dev(KBDC kbdc)
515 {
516         int res;
517
518         res = send_aux_command(kbdc, PSMC_DISABLE_DEV);
519         VLOG(2, (LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n", res));
520
521         return (res == PSM_ACK);
522 }
523
524 static int
525 get_mouse_status(KBDC kbdc, int *status, int flag, int len)
526 {
527         int cmd;
528         int res;
529         int i;
530
531         switch (flag) {
532         case 0:
533         default:
534                 cmd = PSMC_SEND_DEV_STATUS;
535                 break;
536         case 1:
537                 cmd = PSMC_SEND_DEV_DATA;
538                 break;
539         }
540         empty_aux_buffer(kbdc, 5);
541         res = send_aux_command(kbdc, cmd);
542         VLOG(2, (LOG_DEBUG, "psm: SEND_AUX_DEV_%s return code:%04x\n",
543             (flag == 1) ? "DATA" : "STATUS", res));
544         if (res != PSM_ACK)
545                 return (0);
546
547         for (i = 0; i < len; ++i) {
548                 status[i] = read_aux_data(kbdc);
549                 if (status[i] < 0)
550                         break;
551         }
552
553         VLOG(1, (LOG_DEBUG, "psm: %s %02x %02x %02x\n",
554             (flag == 1) ? "data" : "status", status[0], status[1], status[2]));
555
556         return (i);
557 }
558
559 static int
560 get_aux_id(KBDC kbdc)
561 {
562         int res;
563         int id;
564
565         empty_aux_buffer(kbdc, 5);
566         res = send_aux_command(kbdc, PSMC_SEND_DEV_ID);
567         VLOG(2, (LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n", res));
568         if (res != PSM_ACK)
569                 return (-1);
570
571         /* 10ms delay */
572         DRIVERSLEEP(10000);
573
574         id = read_aux_data(kbdc);
575         VLOG(2, (LOG_DEBUG, "psm: device ID: %04x\n", id));
576
577         return (id);
578 }
579
580 static int
581 set_mouse_sampling_rate(KBDC kbdc, int rate)
582 {
583         int res;
584
585         res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, rate);
586         VLOG(2, (LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res));
587
588         return ((res == PSM_ACK) ? rate : -1);
589 }
590
591 static int
592 set_mouse_scaling(KBDC kbdc, int scale)
593 {
594         int res;
595
596         switch (scale) {
597         case 1:
598         default:
599                 scale = PSMC_SET_SCALING11;
600                 break;
601         case 2:
602                 scale = PSMC_SET_SCALING21;
603                 break;
604         }
605         res = send_aux_command(kbdc, scale);
606         VLOG(2, (LOG_DEBUG, "psm: SET_SCALING%s return code:%04x\n",
607             (scale == PSMC_SET_SCALING21) ? "21" : "11", res));
608
609         return (res == PSM_ACK);
610 }
611
612 /* `val' must be 0 through PSMD_MAX_RESOLUTION */
613 static int
614 set_mouse_resolution(KBDC kbdc, int val)
615 {
616         int res;
617
618         res = send_aux_command_and_data(kbdc, PSMC_SET_RESOLUTION, val);
619         VLOG(2, (LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", val, res));
620
621         return ((res == PSM_ACK) ? val : -1);
622 }
623
624 /*
625  * NOTE: once `set_mouse_mode()' is called, the mouse device must be
626  * re-enabled by calling `enable_aux_dev()'
627  */
628 static int
629 set_mouse_mode(KBDC kbdc)
630 {
631         int res;
632
633         res = send_aux_command(kbdc, PSMC_SET_STREAM_MODE);
634         VLOG(2, (LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res));
635
636         return (res == PSM_ACK);
637 }
638
639 static int
640 get_mouse_buttons(KBDC kbdc)
641 {
642         int c = 2;              /* assume two buttons by default */
643         int status[3];
644
645         /*
646          * NOTE: a special sequence to obtain Logitech Mouse specific
647          * information: set resolution to 25 ppi, set scaling to 1:1, set
648          * scaling to 1:1, set scaling to 1:1. Then the second byte of the
649          * mouse status bytes is the number of available buttons.
650          * Some manufactures also support this sequence.
651          */
652         if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)
653                 return (c);
654         if (set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1) &&
655             set_mouse_scaling(kbdc, 1) &&
656             get_mouse_status(kbdc, status, 0, 3) >= 3 && status[1] != 0)
657                 return (status[1]);
658         return (c);
659 }
660
661 /* misc subroutines */
662 /*
663  * Someday, I will get the complete list of valid pointing devices and
664  * their IDs... XXX
665  */
666 static int
667 is_a_mouse(int id)
668 {
669 #if 0
670         static int valid_ids[] = {
671                 PSM_MOUSE_ID,           /* mouse */
672                 PSM_BALLPOINT_ID,       /* ballpoint device */
673                 PSM_INTELLI_ID,         /* Intellimouse */
674                 PSM_EXPLORER_ID,        /* Intellimouse Explorer */
675                 -1                      /* end of table */
676         };
677         int i;
678
679         for (i = 0; valid_ids[i] >= 0; ++i)
680         if (valid_ids[i] == id)
681                 return (TRUE);
682         return (FALSE);
683 #else
684         return (TRUE);
685 #endif
686 }
687
688 static char *
689 model_name(int model)
690 {
691         static struct {
692                 int     model_code;
693                 char    *model_name;
694         } models[] = {
695                 { MOUSE_MODEL_NETSCROLL,        "NetScroll" },
696                 { MOUSE_MODEL_NET,              "NetMouse/NetScroll Optical" },
697                 { MOUSE_MODEL_GLIDEPOINT,       "GlidePoint" },
698                 { MOUSE_MODEL_THINK,            "ThinkingMouse" },
699                 { MOUSE_MODEL_INTELLI,          "IntelliMouse" },
700                 { MOUSE_MODEL_MOUSEMANPLUS,     "MouseMan+" },
701                 { MOUSE_MODEL_VERSAPAD,         "VersaPad" },
702                 { MOUSE_MODEL_EXPLORER,         "IntelliMouse Explorer" },
703                 { MOUSE_MODEL_4D,               "4D Mouse" },
704                 { MOUSE_MODEL_4DPLUS,           "4D+ Mouse" },
705                 { MOUSE_MODEL_SYNAPTICS,        "Synaptics Touchpad" },
706                 { MOUSE_MODEL_GENERIC,          "Generic PS/2 mouse" },
707                 { MOUSE_MODEL_UNKNOWN,          "Unknown" },
708         };
709         int i;
710
711         for (i = 0; models[i].model_code != MOUSE_MODEL_UNKNOWN; ++i)
712                 if (models[i].model_code == model)
713                         break;
714         return (models[i].model_name);
715 }
716
717 static void
718 recover_from_error(KBDC kbdc)
719 {
720         /* discard anything left in the output buffer */
721         empty_both_buffers(kbdc, 10);
722
723 #if 0
724         /*
725          * NOTE: KBDC_RESET_KBD may not restore the communication between the
726          * keyboard and the controller.
727          */
728         reset_kbd(kbdc);
729 #else
730         /*
731          * NOTE: somehow diagnostic and keyboard port test commands bring the
732          * keyboard back.
733          */
734         if (!test_controller(kbdc))
735                 log(LOG_ERR, "psm: keyboard controller failed.\n");
736         /* if there isn't a keyboard in the system, the following error is OK */
737         if (test_kbd_port(kbdc) != 0)
738                 VLOG(1, (LOG_ERR, "psm: keyboard port failed.\n"));
739 #endif
740 }
741
742 static int
743 restore_controller(KBDC kbdc, int command_byte)
744 {
745         empty_both_buffers(kbdc, 10);
746
747         if (!set_controller_command_byte(kbdc, 0xff, command_byte)) {
748                 log(LOG_ERR, "psm: failed to restore the keyboard controller "
749                     "command byte.\n");
750                 empty_both_buffers(kbdc, 10);
751                 return (FALSE);
752         } else {
753                 empty_both_buffers(kbdc, 10);
754                 return (TRUE);
755         }
756 }
757
758 /*
759  * Re-initialize the aux port and device. The aux port must be enabled
760  * and its interrupt must be disabled before calling this routine.
761  * The aux device will be disabled before returning.
762  * The keyboard controller must be locked via `kbdc_lock()' before
763  * calling this routine.
764  */
765 static int
766 doinitialize(struct psm_softc *sc, mousemode_t *mode)
767 {
768         KBDC kbdc = sc->kbdc;
769         int stat[3];
770         int i;
771
772         switch((i = test_aux_port(kbdc))) {
773         case 1: /* ignore these errors */
774         case 2:
775         case 3:
776         case PSM_ACK:
777                 if (verbose)
778                         log(LOG_DEBUG,
779                             "psm%d: strange result for test aux port (%d).\n",
780                             sc->unit, i);
781                 /* FALLTHROUGH */
782         case 0:         /* no error */
783                 break;
784         case -1:        /* time out */
785         default:        /* error */
786                 recover_from_error(kbdc);
787                 if (sc->config & PSM_CONFIG_IGNPORTERROR)
788                         break;
789                 log(LOG_ERR, "psm%d: the aux port is not functioning (%d).\n",
790                     sc->unit, i);
791                 return (FALSE);
792         }
793
794         if (sc->config & PSM_CONFIG_NORESET) {
795                 /*
796                  * Don't try to reset the pointing device.  It may possibly
797                  * be left in the unknown state, though...
798                  */
799         } else {
800                 /*
801                  * NOTE: some controllers appears to hang the `keyboard' when
802                  * the aux port doesn't exist and `PSMC_RESET_DEV' is issued.
803                  */
804                 if (!reset_aux_dev(kbdc)) {
805                         recover_from_error(kbdc);
806                         log(LOG_ERR, "psm%d: failed to reset the aux device.\n",
807                             sc->unit);
808                         return (FALSE);
809                 }
810         }
811
812         /*
813          * both the aux port and the aux device is functioning, see
814          * if the device can be enabled.
815          */
816         if (!enable_aux_dev(kbdc) || !disable_aux_dev(kbdc)) {
817                 log(LOG_ERR, "psm%d: failed to enable the aux device.\n",
818                     sc->unit);
819                 return (FALSE);
820         }
821         empty_both_buffers(kbdc, 10);   /* remove stray data if any */
822
823         if (sc->config & PSM_CONFIG_NOIDPROBE)
824                 i = GENERIC_MOUSE_ENTRY;
825         else {
826                 /* FIXME: hardware ID, mouse buttons? */
827
828                 /* other parameters */
829                 for (i = 0; vendortype[i].probefunc != NULL; ++i)
830                         if ((*vendortype[i].probefunc)(sc)) {
831                                 if (verbose >= 2)
832                                         log(LOG_ERR, "psm%d: found %s\n",
833                                             sc->unit,
834                                             model_name(vendortype[i].model));
835                                 break;
836                         }
837         }
838
839         sc->hw.model = vendortype[i].model;
840         sc->mode.packetsize = vendortype[i].packetsize;
841
842         /* set mouse parameters */
843         if (mode != NULL) {
844                 if (mode->rate > 0)
845                         mode->rate = set_mouse_sampling_rate(kbdc, mode->rate);
846                 if (mode->resolution >= 0)
847                         mode->resolution =
848                             set_mouse_resolution(kbdc, mode->resolution);
849                 set_mouse_scaling(kbdc, 1);
850                 set_mouse_mode(kbdc);
851         }
852
853         /* Record sync on the next data packet we see. */
854         sc->flags |= PSM_NEED_SYNCBITS;
855
856         /* just check the status of the mouse */
857         if (get_mouse_status(kbdc, stat, 0, 3) < 3)
858                 log(LOG_DEBUG, "psm%d: failed to get status (doinitialize).\n",
859                     sc->unit);
860
861         return (TRUE);
862 }
863
864 static int
865 doopen(struct psm_softc *sc, int command_byte)
866 {
867         int stat[3];
868
869         /*
870          * FIXME: Synaptics TouchPad seems to go back to Relative Mode with
871          * no obvious reason. Thus we check the current mode and restore the
872          * Absolute Mode if it was cleared.
873          *
874          * The previous hack at the end of psmprobe() wasn't efficient when
875          * moused(8) was restarted.
876          *
877          * A Reset (FF) or Set Defaults (F6) command would clear the
878          * Absolute Mode bit. But a verbose boot or debug.psm.loglevel=5
879          * doesn't show any evidence of such a command.
880          */
881         if (sc->hw.model == MOUSE_MODEL_SYNAPTICS) {
882                 mouse_ext_command(sc->kbdc, 1);
883                 get_mouse_status(sc->kbdc, stat, 0, 3);
884                 if (stat[1] == 0x47 && stat[2] == 0x40) {
885                         /* Set the mode byte -- request wmode where
886                          * available */
887                         if (sc->synhw.capExtended)
888                                 mouse_ext_command(sc->kbdc, 0xc1);
889                         else
890                                 mouse_ext_command(sc->kbdc, 0xc0);
891                         set_mouse_sampling_rate(sc->kbdc, 20);
892                         VLOG(5, (LOG_DEBUG, "psm%d: Synaptis Absolute Mode "
893                             "hopefully restored\n",
894                             sc->unit));
895                 }
896         }
897
898         /*
899          * A user may want to disable tap and drag gestures on a Synaptics
900          * TouchPad when it operates in Relative Mode.
901          */
902         if (sc->hw.model == MOUSE_MODEL_GENERIC) {
903                 if (tap_enabled > 0) {
904                         /*
905                          * Enable tap & drag gestures. We use a Mode Byte
906                          * and clear the DisGest bit (see Â§2.5 of Synaptics
907                          * TouchPad Interfacing Guide).
908                          */
909                         VLOG(2, (LOG_DEBUG,
910                             "psm%d: enable tap and drag gestures\n",
911                             sc->unit));
912                         mouse_ext_command(sc->kbdc, 0x00);
913                         set_mouse_sampling_rate(sc->kbdc, 20);
914                 } else if (tap_enabled == 0) {
915                         /*
916                          * Disable tap & drag gestures. We use a Mode Byte
917                          * and set the DisGest bit (see Â§2.5 of Synaptics
918                          * TouchPad Interfacing Guide).
919                          */
920                         VLOG(2, (LOG_DEBUG,
921                             "psm%d: disable tap and drag gestures\n",
922                             sc->unit));
923                         mouse_ext_command(sc->kbdc, 0x04);
924                         set_mouse_sampling_rate(sc->kbdc, 20);
925                 }
926         }
927
928         /* enable the mouse device */
929         if (!enable_aux_dev(sc->kbdc)) {
930                 /* MOUSE ERROR: failed to enable the mouse because:
931                  * 1) the mouse is faulty,
932                  * 2) the mouse has been removed(!?)
933                  * In the latter case, the keyboard may have hung, and need
934                  * recovery procedure...
935                  */
936                 recover_from_error(sc->kbdc);
937 #if 0
938                 /* FIXME: we could reset the mouse here and try to enable
939                  * it again. But it will take long time and it's not a good
940                  * idea to disable the keyboard that long...
941                  */
942                 if (!doinitialize(sc, &sc->mode) || !enable_aux_dev(sc->kbdc)) {
943                         recover_from_error(sc->kbdc);
944 #else
945                 {
946 #endif
947                         restore_controller(sc->kbdc, command_byte);
948                         /* mark this device is no longer available */
949                         sc->state &= ~PSM_VALID;
950                         log(LOG_ERR,
951                             "psm%d: failed to enable the device (doopen).\n",
952                         sc->unit);
953                         return (EIO);
954                 }
955         }
956
957         if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
958                 log(LOG_DEBUG, "psm%d: failed to get status (doopen).\n",
959                     sc->unit);
960
961         /* enable the aux port and interrupt */
962         if (!set_controller_command_byte(sc->kbdc,
963             kbdc_get_device_mask(sc->kbdc),
964             (command_byte & KBD_KBD_CONTROL_BITS) |
965             KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT)) {
966                 /* CONTROLLER ERROR */
967                 disable_aux_dev(sc->kbdc);
968                 restore_controller(sc->kbdc, command_byte);
969                 log(LOG_ERR,
970                     "psm%d: failed to enable the aux interrupt (doopen).\n",
971                     sc->unit);
972                 return (EIO);
973         }
974
975         /* start the watchdog timer */
976         sc->watchdog = FALSE;
977         callout_reset(&sc->callout, hz * 2, psmtimeout, (void *)(uintptr_t)sc);
978
979         return (0);
980 }
981
982 static int
983 reinitialize(struct psm_softc *sc, int doinit)
984 {
985         int err;
986         int c;
987
988         /* don't let anybody mess with the aux device */
989         if (!kbdc_lock(sc->kbdc, TRUE))
990                 return (EIO);
991
992         crit_enter();
993
994         /* block our watchdog timer */
995         sc->watchdog = FALSE;
996         callout_stop(&sc->callout);
997
998         /* save the current controller command byte */
999         empty_both_buffers(sc->kbdc, 10);
1000         c = get_controller_command_byte(sc->kbdc);
1001         VLOG(2, (LOG_DEBUG,
1002             "psm%d: current command byte: %04x (reinitialize).\n",
1003             sc->unit, c));
1004
1005         /* enable the aux port but disable the aux interrupt and the keyboard */
1006         if ((c == -1) || !set_controller_command_byte(sc->kbdc,
1007             kbdc_get_device_mask(sc->kbdc),
1008             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
1009             KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1010                 /* CONTROLLER ERROR */
1011                 crit_exit();
1012                 kbdc_lock(sc->kbdc, FALSE);
1013                 log(LOG_ERR,
1014                     "psm%d: unable to set the command byte (reinitialize).\n",
1015                     sc->unit);
1016                 return (EIO);
1017         }
1018
1019         /* flush any data */
1020         if (sc->state & PSM_VALID) {
1021                 /* this may fail; but never mind... */
1022                 disable_aux_dev(sc->kbdc);
1023                 empty_aux_buffer(sc->kbdc, 10);
1024         }
1025         flushpackets(sc);
1026         sc->syncerrors = 0;
1027         sc->pkterrors = 0;
1028         memset(&sc->lastinputerr, 0, sizeof(sc->lastinputerr));
1029
1030         /* try to detect the aux device; are you still there? */
1031         err = 0;
1032         if (doinit) {
1033                 if (doinitialize(sc, &sc->mode)) {
1034                         /* yes */
1035                         sc->state |= PSM_VALID;
1036                 } else {
1037                         /* the device has gone! */
1038                         restore_controller(sc->kbdc, c);
1039                         sc->state &= ~PSM_VALID;
1040                         log(LOG_ERR,
1041                             "psm%d: the aux device has gone! (reinitialize).\n",
1042                             sc->unit);
1043                         err = ENXIO;
1044                 }
1045         }
1046         crit_exit();
1047
1048         /* restore the driver state */
1049         if ((sc->state & PSM_OPEN) && (err == 0)) {
1050                 /* enable the aux device and the port again */
1051                 err = doopen(sc, c);
1052                 if (err != 0)
1053                         log(LOG_ERR, "psm%d: failed to enable the device "
1054                             "(reinitialize).\n", sc->unit);
1055         } else {
1056                 /* restore the keyboard port and disable the aux port */
1057                 if (!set_controller_command_byte(sc->kbdc,
1058                     kbdc_get_device_mask(sc->kbdc),
1059                     (c & KBD_KBD_CONTROL_BITS) |
1060                     KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1061                         /* CONTROLLER ERROR */
1062                         log(LOG_ERR, "psm%d: failed to disable the aux port "
1063                             "(reinitialize).\n", sc->unit);
1064                         err = EIO;
1065                 }
1066         }
1067
1068         kbdc_lock(sc->kbdc, FALSE);
1069         return (err);
1070 }
1071
1072 /* psm driver entry points */
1073
1074 static void
1075 psmidentify(driver_t *driver, device_t parent)
1076 {
1077         device_t psmc;
1078         device_t psm;
1079         u_long irq;
1080         int unit;
1081
1082         unit = device_get_unit(parent);
1083
1084         /* always add at least one child */
1085         psm = BUS_ADD_CHILD(parent, parent, KBDC_RID_AUX, driver->name, unit);
1086         if (psm == NULL)
1087                 return;
1088
1089         irq = bus_get_resource_start(psm, SYS_RES_IRQ, KBDC_RID_AUX);
1090         if (irq > 0)
1091                 return;
1092
1093         /*
1094          * If the PS/2 mouse device has already been reported by ACPI or
1095          * PnP BIOS, obtain the IRQ resource from it.
1096          * (See psmcpnp_attach() below.)
1097          */
1098         psmc = device_find_child(device_get_parent(parent),
1099             PSMCPNP_DRIVER_NAME, unit);
1100         if (psmc == NULL)
1101                 return;
1102         irq = bus_get_resource_start(psmc, SYS_RES_IRQ, 0);
1103         if (irq <= 0)
1104                 return;
1105         bus_set_resource(psm, SYS_RES_IRQ, KBDC_RID_AUX, irq, 1,
1106             machintr_legacy_intr_cpuid(irq));
1107 }
1108
1109 #define endprobe(v)     do {                    \
1110         if (bootverbose)                        \
1111                 --verbose;                      \
1112         kbdc_set_device_mask(sc->kbdc, mask);   \
1113         kbdc_lock(sc->kbdc, FALSE);             \
1114         return (v);                             \
1115 } while (0)
1116
1117 static int
1118 psmprobe(device_t dev)
1119 {
1120         int unit = device_get_unit(dev);
1121         struct psm_softc *sc = device_get_softc(dev);
1122         uintptr_t irq;
1123         uintptr_t flags;
1124         int stat[3];
1125         int command_byte;
1126         int mask;
1127         int i;
1128
1129 #if 0
1130         kbdc_debug(TRUE);
1131 #endif
1132
1133         BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_IRQ, &irq);
1134         BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_FLAGS, &flags);
1135
1136         sc->unit = unit;
1137         sc->kbdc = atkbdc_open(device_get_unit(device_get_parent(dev)));
1138         sc->config = flags & PSM_CONFIG_FLAGS;
1139         /* XXX: for backward compatibility */
1140 #if defined(PSM_HOOKRESUME) || defined(PSM_HOOKAPM)
1141         sc->config |=
1142 #ifdef PSM_RESETAFTERSUSPEND
1143         PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
1144 #else
1145         PSM_CONFIG_HOOKRESUME;
1146 #endif
1147 #endif /* PSM_HOOKRESUME | PSM_HOOKAPM */
1148         sc->flags = 0;
1149         if (bootverbose)
1150                 ++verbose;
1151
1152         device_set_desc(dev, "PS/2 Mouse");
1153
1154         if (!kbdc_lock(sc->kbdc, TRUE)) {
1155                 kprintf("psm%d: unable to lock the controller.\n", unit);
1156                 if (bootverbose)
1157                         --verbose;
1158                 return (ENXIO);
1159         }
1160
1161         /*
1162          * NOTE: two bits in the command byte controls the operation of the
1163          * aux port (mouse port): the aux port disable bit (bit 5) and the aux
1164          * port interrupt (IRQ 12) enable bit (bit 2).
1165          */
1166
1167         /* discard anything left after the keyboard initialization */
1168         empty_both_buffers(sc->kbdc, 10);
1169
1170         /* save the current command byte; it will be used later */
1171         mask = kbdc_get_device_mask(sc->kbdc) & ~KBD_AUX_CONTROL_BITS;
1172         command_byte = get_controller_command_byte(sc->kbdc);
1173         if (verbose)
1174                 kprintf("psm%d: current command byte:%04x\n", unit,
1175                     command_byte);
1176         if (command_byte == -1) {
1177                 /* CONTROLLER ERROR */
1178                 kprintf("psm%d: unable to get the current command byte value.\n",
1179                         unit);
1180                 endprobe(ENXIO);
1181         }
1182
1183         /*
1184          * disable the keyboard port while probing the aux port, which must be
1185          * enabled during this routine
1186          */
1187         if (!set_controller_command_byte(sc->kbdc,
1188             KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,
1189             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
1190             KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1191                 /*
1192                  * this is CONTROLLER ERROR; I don't know how to recover
1193                  * from this error...
1194                  */
1195                 restore_controller(sc->kbdc, command_byte);
1196                 kprintf("psm%d: unable to set the command byte.\n", unit);
1197                 endprobe(ENXIO);
1198         }
1199         write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT);
1200
1201         /*
1202          * NOTE: `test_aux_port()' is designed to return with zero if the aux
1203          * port exists and is functioning. However, some controllers appears
1204          * to respond with zero even when the aux port doesn't exist. (It may
1205          * be that this is only the case when the controller DOES have the aux
1206          * port but the port is not wired on the motherboard.) The keyboard
1207          * controllers without the port, such as the original AT, are
1208          * supporsed to return with an error code or simply time out. In any
1209          * case, we have to continue probing the port even when the controller
1210          * passes this test.
1211          *
1212          * XXX: some controllers erroneously return the error code 1, 2 or 3
1213          * when it has the perfectly functional aux port. We have to ignore
1214          * this error code. Even if the controller HAS error with the aux
1215          * port, it will be detected later...
1216          * XXX: another incompatible controller returns PSM_ACK (0xfa)...
1217          */
1218         switch ((i = test_aux_port(sc->kbdc))) {
1219         case 1:         /* ignore these errors */
1220         case 2:
1221         case 3:
1222         case PSM_ACK:
1223                 if (verbose)
1224                         kprintf("psm%d: strange result for test aux port "
1225                             "(%d).\n", unit, i);
1226                 /* FALLTHROUGH */
1227         case 0:         /* no error */
1228                 break;
1229         case -1:        /* time out */
1230         default:        /* error */
1231                 recover_from_error(sc->kbdc);
1232                 if (sc->config & PSM_CONFIG_IGNPORTERROR)
1233                         break;
1234                 restore_controller(sc->kbdc, command_byte);
1235                 if (verbose)
1236                         kprintf("psm%d: the aux port is not functioning (%d).\n",
1237                             unit, i);
1238                 endprobe(ENXIO);
1239         }
1240
1241         if (sc->config & PSM_CONFIG_NORESET) {
1242                 /*
1243                  * Don't try to reset the pointing device.  It may possibly be
1244                  * left in the unknown state, though...
1245                  */
1246         } else {
1247                 /*
1248                  * NOTE: some controllers appears to hang the `keyboard' when
1249                  * the aux port doesn't exist and `PSMC_RESET_DEV' is issued.
1250                  *
1251                  * Attempt to reset the controller twice -- this helps
1252                  * pierce through some KVM switches. The second reset
1253                  * is non-fatal.
1254                  */
1255                 if (!reset_aux_dev(sc->kbdc)) {
1256                         recover_from_error(sc->kbdc);
1257                         restore_controller(sc->kbdc, command_byte);
1258                         if (verbose)
1259                                 kprintf("psm%d: failed to reset the aux "
1260                                     "device.\n", unit);
1261                         endprobe(ENXIO);
1262                 } else if (!reset_aux_dev(sc->kbdc)) {
1263                         recover_from_error(sc->kbdc);
1264                         if (verbose >= 2)
1265                                 kprintf("psm%d: failed to reset the aux device "
1266                                     "(2).\n", unit);
1267                 }
1268         }
1269
1270         /*
1271          * both the aux port and the aux device is functioning, see if the
1272          * device can be enabled. NOTE: when enabled, the device will start
1273          * sending data; we shall immediately disable the device once we know
1274          * the device can be enabled.
1275          */
1276         if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {
1277                 /* MOUSE ERROR */
1278                 recover_from_error(sc->kbdc);
1279                 restore_controller(sc->kbdc, command_byte);
1280                 if (verbose)
1281                         kprintf("psm%d: failed to enable the aux device.\n",
1282                             unit);
1283                 endprobe(ENXIO);
1284         }
1285
1286         /* save the default values after reset */
1287         if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) {
1288                 sc->dflt_mode.rate = sc->mode.rate = stat[2];
1289                 sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
1290         } else {
1291                 sc->dflt_mode.rate = sc->mode.rate = -1;
1292                 sc->dflt_mode.resolution = sc->mode.resolution = -1;
1293         }
1294
1295         /* hardware information */
1296         sc->hw.iftype = MOUSE_IF_PS2;
1297
1298         /* verify the device is a mouse */
1299         sc->hw.hwid = get_aux_id(sc->kbdc);
1300         if (!is_a_mouse(sc->hw.hwid)) {
1301                 restore_controller(sc->kbdc, command_byte);
1302                 if (verbose)
1303                         kprintf("psm%d: unknown device type (%d).\n", unit,
1304                             sc->hw.hwid);
1305                 endprobe(ENXIO);
1306         }
1307         switch (sc->hw.hwid) {
1308         case PSM_BALLPOINT_ID:
1309                 sc->hw.type = MOUSE_TRACKBALL;
1310                 break;
1311         case PSM_MOUSE_ID:
1312         case PSM_INTELLI_ID:
1313         case PSM_EXPLORER_ID:
1314         case PSM_4DMOUSE_ID:
1315         case PSM_4DPLUS_ID:
1316                 sc->hw.type = MOUSE_MOUSE;
1317                 break;
1318         default:
1319                 sc->hw.type = MOUSE_UNKNOWN;
1320                 break;
1321         }
1322
1323         if (sc->config & PSM_CONFIG_NOIDPROBE) {
1324                 sc->hw.buttons = 2;
1325                 i = GENERIC_MOUSE_ENTRY;
1326         } else {
1327                 /* # of buttons */
1328                 sc->hw.buttons = get_mouse_buttons(sc->kbdc);
1329
1330                 /* other parameters */
1331                 for (i = 0; vendortype[i].probefunc != NULL; ++i)
1332                         if ((*vendortype[i].probefunc)(sc)) {
1333                                 if (verbose >= 2)
1334                                         kprintf("psm%d: found %s\n", unit,
1335                                             model_name(vendortype[i].model));
1336                                 break;
1337                         }
1338         }
1339
1340         sc->hw.model = vendortype[i].model;
1341
1342         sc->dflt_mode.level = PSM_LEVEL_BASE;
1343         sc->dflt_mode.packetsize = MOUSE_PS2_PACKETSIZE;
1344         sc->dflt_mode.accelfactor = (sc->config & PSM_CONFIG_ACCEL) >> 4;
1345         if (sc->config & PSM_CONFIG_NOCHECKSYNC)
1346                 sc->dflt_mode.syncmask[0] = 0;
1347         else
1348                 sc->dflt_mode.syncmask[0] = vendortype[i].syncmask;
1349         if (sc->config & PSM_CONFIG_FORCETAP)
1350                 sc->dflt_mode.syncmask[0] &= ~MOUSE_PS2_TAP;
1351         sc->dflt_mode.syncmask[1] = 0;  /* syncbits */
1352         sc->mode = sc->dflt_mode;
1353         sc->mode.packetsize = vendortype[i].packetsize;
1354
1355         /* set mouse parameters */
1356 #if 0
1357         /*
1358          * A version of Logitech FirstMouse+ won't report wheel movement,
1359          * if SET_DEFAULTS is sent...  Don't use this command.
1360          * This fix was found by Takashi Nishida.
1361          */
1362         i = send_aux_command(sc->kbdc, PSMC_SET_DEFAULTS);
1363         if (verbose >= 2)
1364                 kprintf("psm%d: SET_DEFAULTS return code:%04x\n", unit, i);
1365 #endif
1366         if (sc->config & PSM_CONFIG_RESOLUTION)
1367                 sc->mode.resolution =
1368                     set_mouse_resolution(sc->kbdc,
1369                     (sc->config & PSM_CONFIG_RESOLUTION) - 1);
1370         else if (sc->mode.resolution >= 0)
1371                 sc->mode.resolution =
1372                     set_mouse_resolution(sc->kbdc, sc->dflt_mode.resolution);
1373         if (sc->mode.rate > 0)
1374                 sc->mode.rate =
1375                     set_mouse_sampling_rate(sc->kbdc, sc->dflt_mode.rate);
1376         set_mouse_scaling(sc->kbdc, 1);
1377
1378         /* Record sync on the next data packet we see. */
1379         sc->flags |= PSM_NEED_SYNCBITS;
1380
1381         /* just check the status of the mouse */
1382         /*
1383          * NOTE: XXX there are some arcane controller/mouse combinations out
1384          * there, which hung the controller unless there is data transmission
1385          * after ACK from the mouse.
1386          */
1387         if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
1388                 kprintf("psm%d: failed to get status.\n", unit);
1389         else {
1390                 /*
1391                  * When in its native mode, some mice operate with different
1392                  * default parameters than in the PS/2 compatible mode.
1393                  */
1394                 sc->dflt_mode.rate = sc->mode.rate = stat[2];
1395                 sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
1396         }
1397
1398         /* disable the aux port for now... */
1399         if (!set_controller_command_byte(sc->kbdc,
1400             KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,
1401             (command_byte & KBD_KBD_CONTROL_BITS) |
1402             KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1403                 /*
1404                  * this is CONTROLLER ERROR; I don't know the proper way to
1405                  * recover from this error...
1406                  */
1407                 restore_controller(sc->kbdc, command_byte);
1408                 kprintf("psm%d: unable to set the command byte.\n", unit);
1409                 endprobe(ENXIO);
1410         }
1411
1412         /* done */
1413         kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS);
1414         kbdc_lock(sc->kbdc, FALSE);
1415         return (0);
1416 }
1417
1418 static int
1419 psmattach(device_t dev)
1420 {
1421         int unit = device_get_unit(dev);
1422         struct psm_softc *sc = device_get_softc(dev);
1423         int error;
1424         intptr_t irq;
1425         int rid;
1426
1427         /* Setup initial state */
1428         sc->state = PSM_VALID;
1429         callout_init(&sc->callout);
1430         callout_init(&sc->softcallout);
1431
1432         /* Setup our interrupt handler */
1433         rid = KBDC_RID_AUX;
1434         BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_IRQ, &irq);
1435         sc->intr = bus_alloc_legacy_irq_resource(dev, &rid, irq, RF_ACTIVE);
1436
1437         if (sc->intr == NULL)
1438                 return (ENXIO);
1439         error = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->intr,
1440                         INTR_NOPOLL, psmintr, sc, &sc->ih, NULL, NULL);
1441         if (error) {
1442                 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
1443                 return (error);
1444         }
1445
1446         /* Done */
1447         make_dev(&psm_ops, PSM_MKMINOR(unit, FALSE), 0, 0, 0666, "psm%d", unit);
1448         make_dev(&psm_ops, PSM_MKMINOR(unit, TRUE), 0, 0, 0666, "bpsm%d", unit);
1449
1450         if (!verbose)
1451                 kprintf("psm%d: model %s, device ID %d\n",
1452                     unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff);
1453         else {
1454                 kprintf("psm%d: model %s, device ID %d-%02x, %d buttons\n",
1455                     unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff,
1456                     sc->hw.hwid >> 8, sc->hw.buttons);
1457                 kprintf("psm%d: config:%08x, flags:%08x, packet size:%d\n",
1458                     unit, sc->config, sc->flags, sc->mode.packetsize);
1459                 kprintf("psm%d: syncmask:%02x, syncbits:%02x\n",
1460                     unit, sc->mode.syncmask[0], sc->mode.syncmask[1]);
1461         }
1462
1463         if (bootverbose)
1464                 --verbose;
1465
1466         return (0);
1467 }
1468
1469 static int
1470 psmdetach(device_t dev)
1471 {
1472         struct psm_softc *sc;
1473         int rid;
1474
1475         sc = device_get_softc(dev);
1476         if (sc->state & PSM_OPEN)
1477                 return (EBUSY);
1478
1479         rid = KBDC_RID_AUX;
1480         bus_teardown_intr(dev, sc->intr, sc->ih);
1481         bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
1482
1483         destroy_dev(sc->dev);
1484         destroy_dev(sc->bdev);
1485
1486         return (0);
1487 }
1488
1489 static int
1490 psmopen(struct dev_open_args *ap)
1491 {
1492         cdev_t dev = ap->a_head.a_dev;
1493         int unit = PSM_UNIT(dev);
1494         struct psm_softc *sc;
1495         int command_byte;
1496         int err;
1497
1498         /* Get device data */
1499         sc = PSM_SOFTC(unit);
1500         if ((sc == NULL) || (sc->state & PSM_VALID) == 0) {
1501                 /* the device is no longer valid/functioning */
1502                 return (ENXIO);
1503         }
1504
1505         /* Disallow multiple opens */
1506         if (sc->state & PSM_OPEN)
1507                 return (EBUSY);
1508
1509 #if 0
1510         device_busy(devclass_get_device(psm_devclass, sc->unit));
1511 #endif
1512
1513         /* Initialize state */
1514         sc->mode.level = sc->dflt_mode.level;
1515         sc->mode.protocol = sc->dflt_mode.protocol;
1516         sc->watchdog = FALSE;
1517         sc->async = NULL;
1518
1519         /* flush the event queue */
1520         sc->queue.count = 0;
1521         sc->queue.head = 0;
1522         sc->queue.tail = 0;
1523         sc->status.flags = 0;
1524         sc->status.button = 0;
1525         sc->status.obutton = 0;
1526         sc->status.dx = 0;
1527         sc->status.dy = 0;
1528         sc->status.dz = 0;
1529         sc->button = 0;
1530         sc->pqueue_start = 0;
1531         sc->pqueue_end = 0;
1532
1533         /* empty input buffer */
1534         flushpackets(sc);
1535         sc->syncerrors = 0;
1536         sc->pkterrors = 0;
1537
1538         /* don't let timeout routines in the keyboard driver to poll the kbdc */
1539         if (!kbdc_lock(sc->kbdc, TRUE))
1540                 return (EIO);
1541
1542         /* save the current controller command byte */
1543         crit_enter();
1544         command_byte = get_controller_command_byte(sc->kbdc);
1545
1546         /* enable the aux port and temporalily disable the keyboard */
1547         if (command_byte == -1 || !set_controller_command_byte(sc->kbdc,
1548             kbdc_get_device_mask(sc->kbdc),
1549             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
1550             KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1551                 /* CONTROLLER ERROR; do you know how to get out of this? */
1552                 kbdc_lock(sc->kbdc, FALSE);
1553                 crit_exit();
1554                 log(LOG_ERR,
1555                     "psm%d: unable to set the command byte (psmopen).\n",
1556                     sc->unit);
1557                 return (EIO);
1558         }
1559         /*
1560          * Now that the keyboard controller is told not to generate
1561          * the keyboard and mouse interrupts, call `splx()' to allow
1562          * the other tty interrupts. The clock interrupt may also occur,
1563          * but timeout routines will be blocked by the poll flag set
1564          * via `kbdc_lock()'
1565          */
1566         crit_exit();
1567
1568         /* enable the mouse device */
1569         err = doopen(sc, command_byte);
1570
1571         /* done */
1572         if (err == 0)
1573                 sc->state |= PSM_OPEN;
1574         kbdc_lock(sc->kbdc, FALSE);
1575         return (err);
1576 }
1577
1578 static int
1579 psmclose(struct dev_close_args *ap)
1580 {
1581         cdev_t dev = ap->a_head.a_dev;
1582         int unit = PSM_UNIT(dev);
1583         struct psm_softc *sc = PSM_SOFTC(unit);
1584         int stat[3];
1585         int command_byte;
1586
1587         /* don't let timeout routines in the keyboard driver to poll the kbdc */
1588         if (!kbdc_lock(sc->kbdc, TRUE))
1589                 return (EIO);
1590
1591         /* save the current controller command byte */
1592         crit_enter();
1593         command_byte = get_controller_command_byte(sc->kbdc);
1594         if (command_byte == -1) {
1595                 kbdc_lock(sc->kbdc, FALSE);
1596                 crit_exit();
1597                 return (EIO);
1598         }
1599
1600         /* disable the aux interrupt and temporalily disable the keyboard */
1601         if (!set_controller_command_byte(sc->kbdc,
1602             kbdc_get_device_mask(sc->kbdc),
1603             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
1604             KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1605                 log(LOG_ERR,
1606                     "psm%d: failed to disable the aux int (psmclose).\n",
1607                     sc->unit);
1608                 /* CONTROLLER ERROR;
1609                  * NOTE: we shall force our way through. Because the only
1610                  * ill effect we shall see is that we may not be able
1611                  * to read ACK from the mouse, and it doesn't matter much
1612                  * so long as the mouse will accept the DISABLE command.
1613                  */
1614         }
1615         crit_exit();
1616
1617         /* stop the watchdog timer */
1618         callout_stop(&sc->callout);
1619
1620         /* remove anything left in the output buffer */
1621         empty_aux_buffer(sc->kbdc, 10);
1622
1623         /* disable the aux device, port and interrupt */
1624         if (sc->state & PSM_VALID) {
1625                 if (!disable_aux_dev(sc->kbdc)) {
1626                         /* MOUSE ERROR;
1627                          * NOTE: we don't return (error) and continue,
1628                          * pretending we have successfully disabled the device.
1629                          * It's OK because the interrupt routine will discard
1630                          * any data from the mouse hereafter.
1631                          */
1632                         log(LOG_ERR,
1633                             "psm%d: failed to disable the device (psmclose).\n",
1634                             sc->unit);
1635                 }
1636
1637                 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
1638                         log(LOG_DEBUG,
1639                             "psm%d: failed to get status (psmclose).\n",
1640                             sc->unit);
1641         }
1642
1643         if (!set_controller_command_byte(sc->kbdc,
1644             kbdc_get_device_mask(sc->kbdc),
1645             (command_byte & KBD_KBD_CONTROL_BITS) |
1646             KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1647                 /*
1648                  * CONTROLLER ERROR;
1649                  * we shall ignore this error; see the above comment.
1650                  */
1651                 log(LOG_ERR,
1652                     "psm%d: failed to disable the aux port (psmclose).\n",
1653                     sc->unit);
1654         }
1655
1656         /* remove anything left in the output buffer */
1657         empty_aux_buffer(sc->kbdc, 10);
1658
1659         /* close is almost always successful */
1660         sc->state &= ~PSM_OPEN;
1661         kbdc_lock(sc->kbdc, FALSE);
1662 #if 0
1663         device_unbusy(devclass_get_device(psm_devclass, sc->unit));
1664 #endif
1665         return (0);
1666 }
1667
1668 static int
1669 tame_mouse(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *status,
1670     u_char *buf)
1671 {
1672         static u_char butmapps2[8] = {
1673                 0,
1674                 MOUSE_PS2_BUTTON1DOWN,
1675                 MOUSE_PS2_BUTTON2DOWN,
1676                 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN,
1677                 MOUSE_PS2_BUTTON3DOWN,
1678                 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON3DOWN,
1679                 MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN,
1680                 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN |
1681                     MOUSE_PS2_BUTTON3DOWN,
1682         };
1683         static u_char butmapmsc[8] = {
1684                 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP |
1685                     MOUSE_MSC_BUTTON3UP,
1686                 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
1687                 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
1688                 MOUSE_MSC_BUTTON3UP,
1689                 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
1690                 MOUSE_MSC_BUTTON2UP,
1691                 MOUSE_MSC_BUTTON1UP,
1692                 0,
1693         };
1694         int mapped;
1695         int i;
1696
1697         if (sc->mode.level == PSM_LEVEL_BASE) {
1698                 mapped = status->button & ~MOUSE_BUTTON4DOWN;
1699                 if (status->button & MOUSE_BUTTON4DOWN)
1700                         mapped |= MOUSE_BUTTON1DOWN;
1701                 status->button = mapped;
1702                 buf[0] = MOUSE_PS2_SYNC | butmapps2[mapped & MOUSE_STDBUTTONS];
1703                 i = imax(imin(status->dx, 255), -256);
1704                 if (i < 0)
1705                         buf[0] |= MOUSE_PS2_XNEG;
1706                 buf[1] = i;
1707                 i = imax(imin(status->dy, 255), -256);
1708                 if (i < 0)
1709                         buf[0] |= MOUSE_PS2_YNEG;
1710                 buf[2] = i;
1711                 return (MOUSE_PS2_PACKETSIZE);
1712         } else if (sc->mode.level == PSM_LEVEL_STANDARD) {
1713                 buf[0] = MOUSE_MSC_SYNC |
1714                     butmapmsc[status->button & MOUSE_STDBUTTONS];
1715                 i = imax(imin(status->dx, 255), -256);
1716                 buf[1] = i >> 1;
1717                 buf[3] = i - buf[1];
1718                 i = imax(imin(status->dy, 255), -256);
1719                 buf[2] = i >> 1;
1720                 buf[4] = i - buf[2];
1721                 i = imax(imin(status->dz, 127), -128);
1722                 buf[5] = (i >> 1) & 0x7f;
1723                 buf[6] = (i - (i >> 1)) & 0x7f;
1724                 buf[7] = (~status->button >> 3) & 0x7f;
1725                 return (MOUSE_SYS_PACKETSIZE);
1726         }
1727         return (pb->inputbytes);
1728 }
1729
1730 static int
1731 psmread(struct dev_read_args *ap)
1732 {
1733         cdev_t dev = ap->a_head.a_dev;
1734         struct uio *uio = ap->a_uio;
1735         struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
1736         u_char buf[PSM_SMALLBUFSIZE];
1737         int error = 0;
1738         int l;
1739
1740         if ((sc->state & PSM_VALID) == 0)
1741                 return (EIO);
1742
1743         /* block until mouse activity occured */
1744         crit_enter();
1745         while (sc->queue.count <= 0) {
1746                 if (dev != sc->bdev) {
1747                         crit_exit();
1748                         return (EWOULDBLOCK);
1749                 }
1750                 sc->state |= PSM_ASLP;
1751                 error = tsleep((caddr_t) sc, PCATCH, "psmrea", 0);
1752                 sc->state &= ~PSM_ASLP;
1753                 if (error) {
1754                         crit_exit();
1755                         return (error);
1756                 } else if ((sc->state & PSM_VALID) == 0) {
1757                         /* the device disappeared! */
1758                         crit_exit();
1759                         return (EIO);
1760                 }
1761         }
1762         crit_exit();
1763
1764         /* copy data to the user land */
1765         while ((sc->queue.count > 0) && (uio->uio_resid > 0)) {
1766                 crit_enter();
1767                 l = imin(sc->queue.count, uio->uio_resid);
1768                 if (l > sizeof(buf))
1769                         l = sizeof(buf);
1770                 if (l > sizeof(sc->queue.buf) - sc->queue.head) {
1771                         bcopy(&sc->queue.buf[sc->queue.head], &buf[0],
1772                             sizeof(sc->queue.buf) - sc->queue.head);
1773                         bcopy(&sc->queue.buf[0],
1774                             &buf[sizeof(sc->queue.buf) - sc->queue.head],
1775                             l - (sizeof(sc->queue.buf) - sc->queue.head));
1776                 } else
1777                         bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l);
1778                 sc->queue.count -= l;
1779                 sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf);
1780                 crit_exit();
1781                 error = uiomove(buf, (size_t)l, uio);
1782                 if (error)
1783                         break;
1784         }
1785
1786         return (error);
1787 }
1788
1789 static int
1790 block_mouse_data(struct psm_softc *sc, int *c)
1791 {
1792
1793         if (!kbdc_lock(sc->kbdc, TRUE))
1794                 return (EIO);
1795
1796         crit_enter();
1797         *c = get_controller_command_byte(sc->kbdc);
1798         if ((*c == -1) || !set_controller_command_byte(sc->kbdc,
1799             kbdc_get_device_mask(sc->kbdc),
1800             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
1801             KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1802                 /* this is CONTROLLER ERROR */
1803                 crit_exit();
1804                 kbdc_lock(sc->kbdc, FALSE);
1805                 return (EIO);
1806         }
1807
1808         /*
1809          * The device may be in the middle of status data transmission.
1810          * The transmission will be interrupted, thus, incomplete status
1811          * data must be discarded. Although the aux interrupt is disabled
1812          * at the keyboard controller level, at most one aux interrupt
1813          * may have already been pending and a data byte is in the
1814          * output buffer; throw it away. Note that the second argument
1815          * to `empty_aux_buffer()' is zero, so that the call will just
1816          * flush the internal queue.
1817          * `psmintr()' will be invoked after `splx()' if an interrupt is
1818          * pending; it will see no data and returns immediately.
1819          */
1820         empty_aux_buffer(sc->kbdc, 0);          /* flush the queue */
1821         read_aux_data_no_wait(sc->kbdc);        /* throw away data if any */
1822         flushpackets(sc);
1823         crit_exit();
1824
1825         return (0);
1826 }
1827
1828 static void
1829 dropqueue(struct psm_softc *sc)
1830 {
1831
1832         sc->queue.count = 0;
1833         sc->queue.head = 0;
1834         sc->queue.tail = 0;
1835         if ((sc->state & PSM_SOFTARMED) != 0) {
1836                 sc->state &= ~PSM_SOFTARMED;
1837                 callout_stop(&sc->softcallout);
1838         }
1839         sc->pqueue_start = sc->pqueue_end;
1840 }
1841
1842 static void
1843 flushpackets(struct psm_softc *sc)
1844 {
1845
1846         dropqueue(sc);
1847         bzero(&sc->pqueue, sizeof(sc->pqueue));
1848 }
1849
1850 static int
1851 unblock_mouse_data(struct psm_softc *sc, int c)
1852 {
1853         int error = 0;
1854
1855         /*
1856          * We may have seen a part of status data during `set_mouse_XXX()'.
1857          * they have been queued; flush it.
1858          */
1859         empty_aux_buffer(sc->kbdc, 0);
1860
1861         /* restore ports and interrupt */
1862         if (!set_controller_command_byte(sc->kbdc,
1863             kbdc_get_device_mask(sc->kbdc),
1864             c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
1865                 /*
1866                  * CONTROLLER ERROR; this is serious, we may have
1867                  * been left with the inaccessible keyboard and
1868                  * the disabled mouse interrupt.
1869                  */
1870                 error = EIO;
1871         }
1872
1873         kbdc_lock(sc->kbdc, FALSE);
1874         return (error);
1875 }
1876
1877 static int
1878 psmwrite(struct dev_write_args *ap)
1879 {
1880         cdev_t dev = ap->a_head.a_dev;
1881         struct uio *uio = ap->a_uio;
1882         struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
1883         u_char buf[PSM_SMALLBUFSIZE];
1884         int error = 0, i, l;
1885
1886         if ((sc->state & PSM_VALID) == 0)
1887                 return (EIO);
1888
1889         if (sc->mode.level < PSM_LEVEL_NATIVE)
1890                 return (ENODEV);
1891
1892         /* copy data from the user land */
1893         while (uio->uio_resid > 0) {
1894                 l = imin(PSM_SMALLBUFSIZE, uio->uio_resid);
1895                 error = uiomove(buf, l, uio);
1896                 if (error)
1897                         break;
1898                 for (i = 0; i < l; i++) {
1899                         VLOG(4, (LOG_DEBUG, "psm: cmd 0x%x\n", buf[i]));
1900                         if (!write_aux_command(sc->kbdc, buf[i])) {
1901                                 VLOG(2, (LOG_DEBUG,
1902                                     "psm: cmd 0x%x failed.\n", buf[i]));
1903                                 return (reinitialize(sc, FALSE));
1904                         }
1905                 }
1906         }
1907
1908         return (error);
1909 }
1910
1911 static int
1912 psmioctl(struct dev_ioctl_args *ap)
1913 {
1914         cdev_t dev = ap->a_head.a_dev;
1915         caddr_t addr=  ap->a_data;
1916         struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
1917         mousemode_t mode;
1918         mousestatus_t status;
1919 #if (defined(MOUSE_GETVARS))
1920         mousevar_t *var;
1921 #endif
1922         mousedata_t *data;
1923         int stat[3];
1924         int command_byte;
1925         int error = 0;
1926
1927         mode.resolution = -1;
1928
1929         /* Perform IOCTL command */
1930         switch (ap->a_cmd) {
1931
1932         case OLD_MOUSE_GETHWINFO:
1933                 crit_enter();
1934                 ((old_mousehw_t *)addr)->buttons = sc->hw.buttons;
1935                 ((old_mousehw_t *)addr)->iftype = sc->hw.iftype;
1936                 ((old_mousehw_t *)addr)->type = sc->hw.type;
1937                 ((old_mousehw_t *)addr)->hwid = sc->hw.hwid & 0x00ff;
1938                 crit_exit();
1939                 break;
1940
1941         case MOUSE_GETHWINFO:
1942                 crit_enter();
1943                 *(mousehw_t *)addr = sc->hw;
1944                 if (sc->mode.level == PSM_LEVEL_BASE)
1945                         ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
1946                 crit_exit();
1947                 break;
1948
1949         case MOUSE_SYN_GETHWINFO:
1950                 crit_enter();
1951                 if (synaptics_support && sc->hw.model == MOUSE_MODEL_SYNAPTICS)
1952                         *(synapticshw_t *)addr = sc->synhw;
1953                 else
1954                         error = EINVAL;
1955                 crit_exit();
1956                 break;
1957
1958         case OLD_MOUSE_GETMODE:
1959                 crit_enter();
1960                 switch (sc->mode.level) {
1961                 case PSM_LEVEL_BASE:
1962                         ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1963                         break;
1964                 case PSM_LEVEL_STANDARD:
1965                         ((old_mousemode_t *)addr)->protocol =
1966                             MOUSE_PROTO_SYSMOUSE;
1967                         break;
1968                 case PSM_LEVEL_NATIVE:
1969                         ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1970                         break;
1971                 }
1972                 ((old_mousemode_t *)addr)->rate = sc->mode.rate;
1973                 ((old_mousemode_t *)addr)->resolution = sc->mode.resolution;
1974                 ((old_mousemode_t *)addr)->accelfactor = sc->mode.accelfactor;
1975                 crit_exit();
1976                 break;
1977
1978         case MOUSE_GETMODE:
1979                 crit_enter();
1980                 *(mousemode_t *)addr = sc->mode;
1981                 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) {
1982                         ((mousemode_t *)addr)->syncmask[0] = 0;
1983                         ((mousemode_t *)addr)->syncmask[1] = 0;
1984                 }
1985                 ((mousemode_t *)addr)->resolution =
1986                         MOUSE_RES_LOW - sc->mode.resolution;
1987                 switch (sc->mode.level) {
1988                 case PSM_LEVEL_BASE:
1989                         ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1990                         ((mousemode_t *)addr)->packetsize =
1991                             MOUSE_PS2_PACKETSIZE;
1992                         break;
1993                 case PSM_LEVEL_STANDARD:
1994                         ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
1995                         ((mousemode_t *)addr)->packetsize =
1996                             MOUSE_SYS_PACKETSIZE;
1997                         ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
1998                         ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
1999                         break;
2000                 case PSM_LEVEL_NATIVE:
2001                         /* FIXME: this isn't quite correct... XXX */
2002                         ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
2003                         break;
2004                 }
2005                 crit_exit();
2006                 break;
2007
2008         case OLD_MOUSE_SETMODE:
2009         case MOUSE_SETMODE:
2010                 if (ap->a_cmd == OLD_MOUSE_SETMODE) {
2011                         mode.rate = ((old_mousemode_t *)addr)->rate;
2012                         /*
2013                          * resolution  old I/F   new I/F
2014                          * default        0         0
2015                          * low            1        -2
2016                          * medium low     2        -3
2017                          * medium high    3        -4
2018                          * high           4        -5
2019                          */
2020                         if (((old_mousemode_t *)addr)->resolution > 0)
2021                                 mode.resolution =
2022                                     -((old_mousemode_t *)addr)->resolution - 1;
2023                         else
2024                                 mode.resolution = 0;
2025                         mode.accelfactor =
2026                             ((old_mousemode_t *)addr)->accelfactor;
2027                         mode.level = -1;
2028                 } else
2029                         mode = *(mousemode_t *)addr;
2030
2031                 /* adjust and validate parameters. */
2032                 if (mode.rate > UCHAR_MAX)
2033                         return (EINVAL);
2034                 if (mode.rate == 0)
2035                         mode.rate = sc->dflt_mode.rate;
2036                 else if (mode.rate == -1)
2037                         /* don't change the current setting */
2038                         ;
2039                 else if (mode.rate < 0)
2040                         return (EINVAL);
2041                 if (mode.resolution >= UCHAR_MAX)
2042                         return (EINVAL);
2043                 if (mode.resolution >= 200)
2044                         mode.resolution = MOUSE_RES_HIGH;
2045                 else if (mode.resolution >= 100)
2046                         mode.resolution = MOUSE_RES_MEDIUMHIGH;
2047                 else if (mode.resolution >= 50)
2048                         mode.resolution = MOUSE_RES_MEDIUMLOW;
2049                 else if (mode.resolution > 0)
2050                         mode.resolution = MOUSE_RES_LOW;
2051                 if (mode.resolution == MOUSE_RES_DEFAULT)
2052                         mode.resolution = sc->dflt_mode.resolution;
2053                 else if (mode.resolution == -1)
2054                         /* don't change the current setting */
2055                         ;
2056                 else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */
2057                         mode.resolution = MOUSE_RES_LOW - mode.resolution;
2058                 if (mode.level == -1)
2059                         /* don't change the current setting */
2060                         mode.level = sc->mode.level;
2061                 else if ((mode.level < PSM_LEVEL_MIN) ||
2062                     (mode.level > PSM_LEVEL_MAX))
2063                         return (EINVAL);
2064                 if (mode.accelfactor == -1)
2065                         /* don't change the current setting */
2066                         mode.accelfactor = sc->mode.accelfactor;
2067                 else if (mode.accelfactor < 0)
2068                         return (EINVAL);
2069
2070                 /* don't allow anybody to poll the keyboard controller */
2071                 error = block_mouse_data(sc, &command_byte);
2072                 if (error)
2073                         return (error);
2074
2075                 /* set mouse parameters */
2076                 if (mode.rate > 0)
2077                         mode.rate = set_mouse_sampling_rate(sc->kbdc,
2078                             mode.rate);
2079                 if (mode.resolution >= 0)
2080                         mode.resolution =
2081                             set_mouse_resolution(sc->kbdc, mode.resolution);
2082                 set_mouse_scaling(sc->kbdc, 1);
2083                 get_mouse_status(sc->kbdc, stat, 0, 3);
2084
2085                 crit_enter();
2086                 sc->mode.rate = mode.rate;
2087                 sc->mode.resolution = mode.resolution;
2088                 sc->mode.accelfactor = mode.accelfactor;
2089                 sc->mode.level = mode.level;
2090                 crit_exit();
2091
2092                 unblock_mouse_data(sc, command_byte);
2093                 break;
2094
2095         case MOUSE_GETLEVEL:
2096                 *(int *)addr = sc->mode.level;
2097                 break;
2098
2099         case MOUSE_SETLEVEL:
2100                 if ((*(int *)addr < PSM_LEVEL_MIN) ||
2101                     (*(int *)addr > PSM_LEVEL_MAX))
2102                         return (EINVAL);
2103                 sc->mode.level = *(int *)addr;
2104                 break;
2105
2106         case MOUSE_GETSTATUS:
2107                 crit_enter();
2108                 status = sc->status;
2109                 sc->status.flags = 0;
2110                 sc->status.obutton = sc->status.button;
2111                 sc->status.button = 0;
2112                 sc->status.dx = 0;
2113                 sc->status.dy = 0;
2114                 sc->status.dz = 0;
2115                 crit_exit();
2116                 *(mousestatus_t *)addr = status;
2117                 break;
2118
2119 #if (defined(MOUSE_GETVARS))
2120         case MOUSE_GETVARS:
2121                 var = (mousevar_t *)addr;
2122                 bzero(var, sizeof(*var));
2123                 crit_enter();
2124                 var->var[0] = MOUSE_VARS_PS2_SIG;
2125                 var->var[1] = sc->config;
2126                 var->var[2] = sc->flags;
2127                 crit_exit();
2128                 break;
2129
2130         case MOUSE_SETVARS:
2131                 return (ENODEV);
2132 #endif /* MOUSE_GETVARS */
2133
2134         case MOUSE_READSTATE:
2135         case MOUSE_READDATA:
2136                 data = (mousedata_t *)addr;
2137                 if (data->len > NELEM(data->buf))
2138                         return (EINVAL);
2139
2140                 error = block_mouse_data(sc, &command_byte);
2141                 if (error)
2142                         return (error);
2143                 if ((data->len = get_mouse_status(sc->kbdc, data->buf,
2144                     (ap->a_cmd == MOUSE_READDATA) ? 1 : 0, data->len)) <= 0)
2145                         error = EIO;
2146                 unblock_mouse_data(sc, command_byte);
2147                 break;
2148
2149 #if (defined(MOUSE_SETRESOLUTION))
2150         case MOUSE_SETRESOLUTION:
2151                 mode.resolution = *(int *)addr;
2152                 if (mode.resolution >= UCHAR_MAX)
2153                         return (EINVAL);
2154                 else if (mode.resolution >= 200)
2155                         mode.resolution = MOUSE_RES_HIGH;
2156                 else if (mode.resolution >= 100)
2157                         mode.resolution = MOUSE_RES_MEDIUMHIGH;
2158                 else if (mode.resolution >= 50)
2159                         mode.resolution = MOUSE_RES_MEDIUMLOW;
2160                 else if (mode.resolution > 0)
2161                         mode.resolution = MOUSE_RES_LOW;
2162                 if (mode.resolution == MOUSE_RES_DEFAULT)
2163                         mode.resolution = sc->dflt_mode.resolution;
2164                 else if (mode.resolution == -1)
2165                         mode.resolution = sc->mode.resolution;
2166                 else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */
2167                         mode.resolution = MOUSE_RES_LOW - mode.resolution;
2168
2169                 error = block_mouse_data(sc, &command_byte);
2170                 if (error)
2171                         return (error);
2172                 sc->mode.resolution =
2173                     set_mouse_resolution(sc->kbdc, mode.resolution);
2174                 if (sc->mode.resolution != mode.resolution)
2175                         error = EIO;
2176                 unblock_mouse_data(sc, command_byte);
2177                 break;
2178 #endif /* MOUSE_SETRESOLUTION */
2179
2180 #if (defined(MOUSE_SETRATE))
2181         case MOUSE_SETRATE:
2182                 mode.rate = *(int *)addr;
2183                 if (mode.rate > UCHAR_MAX)
2184                         return (EINVAL);
2185                 if (mode.rate == 0)
2186                         mode.rate = sc->dflt_mode.rate;
2187                 else if (mode.rate < 0)
2188                         mode.rate = sc->mode.rate;
2189
2190                 error = block_mouse_data(sc, &command_byte);
2191                 if (error)
2192                         return (error);
2193                 sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate);
2194                 if (sc->mode.rate != mode.rate)
2195                         error = EIO;
2196                 unblock_mouse_data(sc, command_byte);
2197                 break;
2198 #endif /* MOUSE_SETRATE */
2199
2200 #if (defined(MOUSE_SETSCALING))
2201         case MOUSE_SETSCALING:
2202                 if ((*(int *)addr <= 0) || (*(int *)addr > 2))
2203                         return (EINVAL);
2204
2205                 error = block_mouse_data(sc, &command_byte);
2206                 if (error)
2207                         return (error);
2208                 if (!set_mouse_scaling(sc->kbdc, *(int *)addr))
2209                         error = EIO;
2210                 unblock_mouse_data(sc, command_byte);
2211                 break;
2212 #endif /* MOUSE_SETSCALING */
2213
2214 #if (defined(MOUSE_GETHWID))
2215         case MOUSE_GETHWID:
2216                 error = block_mouse_data(sc, &command_byte);
2217                 if (error)
2218                         return (error);
2219                 sc->hw.hwid &= ~0x00ff;
2220                 sc->hw.hwid |= get_aux_id(sc->kbdc);
2221                 *(int *)addr = sc->hw.hwid & 0x00ff;
2222                 unblock_mouse_data(sc, command_byte);
2223                 break;
2224 #endif /* MOUSE_GETHWID */
2225
2226         default:
2227                 return (ENOTTY);
2228         }
2229
2230         return (error);
2231 }
2232
2233 static void
2234 psmtimeout(void *arg)
2235 {
2236         struct psm_softc *sc;
2237
2238         sc = (struct psm_softc *)arg;
2239         crit_enter();
2240         if (sc->watchdog && kbdc_lock(sc->kbdc, TRUE)) {
2241                 VLOG(4, (LOG_DEBUG, "psm%d: lost interrupt?\n", sc->unit));
2242                 psmintr(sc);
2243                 kbdc_lock(sc->kbdc, FALSE);
2244         }
2245         sc->watchdog = TRUE;
2246         crit_exit();
2247         callout_reset(&sc->callout, hz, psmtimeout, (void *)(uintptr_t)sc);
2248 }
2249
2250 /* Add all sysctls under the debug.psm and hw.psm nodes */
2251 SYSCTL_NODE(_debug, OID_AUTO, psm, CTLFLAG_RD, 0, "ps/2 mouse");
2252 SYSCTL_NODE(_hw, OID_AUTO, psm, CTLFLAG_RD, 0, "ps/2 mouse");
2253
2254 SYSCTL_INT(_debug_psm, OID_AUTO, loglevel, CTLFLAG_RW, &verbose, 0,
2255     "Verbosity level");
2256
2257 static int psmhz = 20;
2258 SYSCTL_INT(_debug_psm, OID_AUTO, hz, CTLFLAG_RW, &psmhz, 0,
2259     "Frequency of the softcallout (in hz)");
2260 static int psmerrsecs = 2;
2261 SYSCTL_INT(_debug_psm, OID_AUTO, errsecs, CTLFLAG_RW, &psmerrsecs, 0,
2262     "Number of seconds during which packets will dropped after a sync error");
2263 static int psmerrusecs = 0;
2264 SYSCTL_INT(_debug_psm, OID_AUTO, errusecs, CTLFLAG_RW, &psmerrusecs, 0,
2265     "Microseconds to add to psmerrsecs");
2266 static int psmsecs = 0;
2267 SYSCTL_INT(_debug_psm, OID_AUTO, secs, CTLFLAG_RW, &psmsecs, 0,
2268     "Max number of seconds between soft interrupts");
2269 static int psmusecs = 500000;
2270 SYSCTL_INT(_debug_psm, OID_AUTO, usecs, CTLFLAG_RW, &psmusecs, 0,
2271     "Microseconds to add to psmsecs");
2272 static int pkterrthresh = 2;
2273 SYSCTL_INT(_debug_psm, OID_AUTO, pkterrthresh, CTLFLAG_RW, &pkterrthresh, 0,
2274     "Number of error packets allowed before reinitializing the mouse");
2275
2276 SYSCTL_INT(_hw_psm, OID_AUTO, tap_enabled, CTLFLAG_RW, &tap_enabled, 0,
2277     "Enable tap and drag gestures");
2278 static int tap_threshold = PSM_TAP_THRESHOLD;
2279 SYSCTL_INT(_hw_psm, OID_AUTO, tap_threshold, CTLFLAG_RW, &tap_threshold, 0,
2280     "Button tap threshold");
2281 static int tap_timeout = PSM_TAP_TIMEOUT;
2282 SYSCTL_INT(_hw_psm, OID_AUTO, tap_timeout, CTLFLAG_RW, &tap_timeout, 0,
2283     "Tap timeout for touchpads");
2284
2285 static void
2286 psmintr(void *arg)
2287 {
2288         struct psm_softc *sc = arg;
2289         struct timeval now;
2290         int c;
2291         packetbuf_t *pb;
2292
2293
2294         /* read until there is nothing to read */
2295         while((c = read_aux_data_no_wait(sc->kbdc)) != -1) {
2296                 pb = &sc->pqueue[sc->pqueue_end];
2297
2298                 /* discard the byte if the device is not open */
2299                 if ((sc->state & PSM_OPEN) == 0)
2300                         continue;
2301
2302                 getmicrouptime(&now);
2303                 if ((pb->inputbytes > 0) &&
2304                     timevalcmp(&now, &sc->inputtimeout, >)) {
2305                         VLOG(3, (LOG_DEBUG, "psmintr: delay too long; "
2306                             "resetting byte count\n"));
2307                         pb->inputbytes = 0;
2308                         sc->syncerrors = 0;
2309                         sc->pkterrors = 0;
2310                 }
2311                 sc->inputtimeout.tv_sec = PSM_INPUT_TIMEOUT / 1000000;
2312                 sc->inputtimeout.tv_usec = PSM_INPUT_TIMEOUT % 1000000;
2313                 timevaladd(&sc->inputtimeout, &now);
2314
2315                 pb->ipacket[pb->inputbytes++] = c;
2316
2317                 if (sc->mode.level == PSM_LEVEL_NATIVE) {
2318                         VLOG(4, (LOG_DEBUG, "psmintr: %02x\n", pb->ipacket[0]));
2319                         sc->syncerrors = 0;
2320                         sc->pkterrors = 0;
2321                         goto next;
2322                 } else {
2323                         if (pb->inputbytes < sc->mode.packetsize)
2324                                 continue;
2325
2326                         VLOG(4, (LOG_DEBUG,
2327                             "psmintr: %02x %02x %02x %02x %02x %02x\n",
2328                             pb->ipacket[0], pb->ipacket[1], pb->ipacket[2],
2329                             pb->ipacket[3], pb->ipacket[4], pb->ipacket[5]));
2330                 }
2331
2332                 c = pb->ipacket[0];
2333
2334                 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) {
2335                         sc->mode.syncmask[1] = (c & sc->mode.syncmask[0]);
2336                         sc->flags &= ~PSM_NEED_SYNCBITS;
2337                         VLOG(2, (LOG_DEBUG,
2338                             "psmintr: Sync bytes now %04x,%04x\n",
2339                             sc->mode.syncmask[0], sc->mode.syncmask[0]));
2340                 } else if ((c & sc->mode.syncmask[0]) != sc->mode.syncmask[1]) {
2341                         VLOG(3, (LOG_DEBUG, "psmintr: out of sync "
2342                             "(%04x != %04x) %d cmds since last error.\n",
2343                             c & sc->mode.syncmask[0], sc->mode.syncmask[1],
2344                             sc->cmdcount - sc->lasterr));
2345                         sc->lasterr = sc->cmdcount;
2346                         /*
2347                          * The sync byte test is a weak measure of packet
2348                          * validity.  Conservatively discard any input yet
2349                          * to be seen by userland when we detect a sync
2350                          * error since there is a good chance some of
2351                          * the queued packets have undetected errors.
2352                          */
2353                         dropqueue(sc);
2354                         if (sc->syncerrors == 0)
2355                                 sc->pkterrors++;
2356                         ++sc->syncerrors;
2357                         sc->lastinputerr = now;
2358                         if (sc->syncerrors >= sc->mode.packetsize * 2 ||
2359                             sc->pkterrors >= pkterrthresh) {
2360                                 /*
2361                                  * If we've failed to find a single sync byte
2362                                  * in 2 packets worth of data, or we've seen
2363                                  * persistent packet errors during the
2364                                  * validation period, reinitialize the mouse
2365                                  * in hopes of returning it to the expected
2366                                  * mode.
2367                                  */
2368                                 VLOG(3, (LOG_DEBUG,
2369                                     "psmintr: reset the mouse.\n"));
2370                                 reinitialize(sc, TRUE);
2371                         } else if (sc->syncerrors == sc->mode.packetsize) {
2372                                 /*
2373                                  * Try a soft reset after searching for a sync
2374                                  * byte through a packet length of bytes.
2375                                  */
2376                                 VLOG(3, (LOG_DEBUG,
2377                                     "psmintr: re-enable the mouse.\n"));
2378                                 pb->inputbytes = 0;
2379                                 disable_aux_dev(sc->kbdc);
2380                                 enable_aux_dev(sc->kbdc);
2381                         } else {
2382                                 VLOG(3, (LOG_DEBUG,
2383                                     "psmintr: discard a byte (%d)\n",
2384                                     sc->syncerrors));
2385                                 pb->inputbytes--;
2386                                 bcopy(&pb->ipacket[1], &pb->ipacket[0],
2387                                     pb->inputbytes);
2388                         }
2389                         continue;
2390                 }
2391
2392                 /*
2393                  * We have what appears to be a valid packet.
2394                  * Reset the error counters.
2395                  */
2396                 sc->syncerrors = 0;
2397
2398                 /*
2399                  * Drop even good packets if they occur within a timeout
2400                  * period of a sync error.  This allows the detection of
2401                  * a change in the mouse's packet mode without exposing
2402                  * erratic mouse behavior to the user.  Some KVMs forget
2403                  * enhanced mouse modes during switch events.
2404                  */
2405                 if (!timeelapsed(&sc->lastinputerr, psmerrsecs, psmerrusecs,
2406                     &now)) {
2407                         pb->inputbytes = 0;
2408                         continue;
2409                 }
2410
2411                 /*
2412                  * Now that we're out of the validation period, reset
2413                  * the packet error count.
2414                  */
2415                 sc->pkterrors = 0;
2416
2417                 sc->cmdcount++;
2418 next:
2419                 if (++sc->pqueue_end >= PSM_PACKETQUEUE)
2420                         sc->pqueue_end = 0;
2421                 /*
2422                  * If we've filled the queue then call the softintr ourselves,
2423                  * otherwise schedule the interrupt for later.
2424                  */
2425                 if (!timeelapsed(&sc->lastsoftintr, psmsecs, psmusecs, &now) ||
2426                     (sc->pqueue_end == sc->pqueue_start)) {
2427                         if ((sc->state & PSM_SOFTARMED) != 0) {
2428                                 sc->state &= ~PSM_SOFTARMED;
2429                                 callout_stop(&sc->softcallout);
2430                         }
2431                         psmsoftintr(arg);
2432                 } else if ((sc->state & PSM_SOFTARMED) == 0) {
2433                         sc->state |= PSM_SOFTARMED;
2434                         callout_reset(&sc->softcallout,  psmhz < 1 ? 1 : (hz/psmhz),
2435                               psmsoftintr, arg);
2436                 }
2437         }
2438 }
2439
2440 static void
2441 proc_mmanplus(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
2442     int *x, int *y, int *z)
2443 {
2444
2445         /*
2446          * PS2++ protocl packet
2447          *
2448          *          b7 b6 b5 b4 b3 b2 b1 b0
2449          * byte 1:  *  1  p3 p2 1  *  *  *
2450          * byte 2:  c1 c2 p1 p0 d1 d0 1  0
2451          *
2452          * p3-p0: packet type
2453          * c1, c2: c1 & c2 == 1, if p2 == 0
2454          *         c1 & c2 == 0, if p2 == 1
2455          *
2456          * packet type: 0 (device type)
2457          * See comments in enable_mmanplus() below.
2458          *
2459          * packet type: 1 (wheel data)
2460          *
2461          *          b7 b6 b5 b4 b3 b2 b1 b0
2462          * byte 3:  h  *  B5 B4 s  d2 d1 d0
2463          *
2464          * h: 1, if horizontal roller data
2465          *    0, if vertical roller data
2466          * B4, B5: button 4 and 5
2467          * s: sign bit
2468          * d2-d0: roller data
2469          *
2470          * packet type: 2 (reserved)
2471          */
2472         if (((pb->ipacket[0] & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC) &&
2473             (abs(*x) > 191) && MOUSE_PS2PLUS_CHECKBITS(pb->ipacket)) {
2474                 /*
2475                  * the extended data packet encodes button
2476                  * and wheel events
2477                  */
2478                 switch (MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket)) {
2479                 case 1:
2480                         /* wheel data packet */
2481                         *x = *y = 0;
2482                         if (pb->ipacket[2] & 0x80) {
2483                                 /* XXX horizontal roller count - ignore it */
2484                                 ;
2485                         } else {
2486                                 /* vertical roller count */
2487                                 *z = (pb->ipacket[2] & MOUSE_PS2PLUS_ZNEG) ?
2488                                     (pb->ipacket[2] & 0x0f) - 16 :
2489                                     (pb->ipacket[2] & 0x0f);
2490                         }
2491                         ms->button |= (pb->ipacket[2] &
2492                             MOUSE_PS2PLUS_BUTTON4DOWN) ?
2493                             MOUSE_BUTTON4DOWN : 0;
2494                         ms->button |= (pb->ipacket[2] &
2495                             MOUSE_PS2PLUS_BUTTON5DOWN) ?
2496                             MOUSE_BUTTON5DOWN : 0;
2497                         break;
2498                 case 2:
2499                         /*
2500                          * this packet type is reserved by
2501                          * Logitech...
2502                          */
2503                         /*
2504                          * IBM ScrollPoint Mouse uses this
2505                          * packet type to encode both vertical
2506                          * and horizontal scroll movement.
2507                          */
2508                         *x = *y = 0;
2509                         /* horizontal count */
2510                         if (pb->ipacket[2] & 0x0f)
2511                                 *z = (pb->ipacket[2] & MOUSE_SPOINT_WNEG) ?
2512                                     -2 : 2;
2513                         /* vertical count */
2514                         if (pb->ipacket[2] & 0xf0)
2515                                 *z = (pb->ipacket[2] & MOUSE_SPOINT_ZNEG) ?
2516                                     -1 : 1;
2517                         break;
2518                 case 0:
2519                         /* device type packet - shouldn't happen */
2520                         /* FALLTHROUGH */
2521                 default:
2522                         *x = *y = 0;
2523                         ms->button = ms->obutton;
2524                         VLOG(1, (LOG_DEBUG, "psmintr: unknown PS2++ packet "
2525                             "type %d: 0x%02x 0x%02x 0x%02x\n",
2526                             MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket),
2527                             pb->ipacket[0], pb->ipacket[1], pb->ipacket[2]));
2528                         break;
2529                 }
2530         } else {
2531                 /* preserve button states */
2532                 ms->button |= ms->obutton & MOUSE_EXTBUTTONS;
2533         }
2534 }
2535
2536 static int
2537 proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
2538     int *x, int *y, int *z)
2539 {
2540         static int touchpad_buttons;
2541         static int guest_buttons;
2542         int w, x0, y0;
2543
2544         /* TouchPad PS/2 absolute mode message format
2545          *
2546          *  Bits:        7   6   5   4   3   2   1   0 (LSB)
2547          *  ------------------------------------------------
2548          *  ipacket[0]:  1   0  W3  W2   0  W1   R   L
2549          *  ipacket[1]: Yb  Ya  Y9  Y8  Xb  Xa  X9  X8
2550          *  ipacket[2]: Z7  Z6  Z5  Z4  Z3  Z2  Z1  Z0
2551          *  ipacket[3]:  1   1  Yc  Xc   0  W0   D   U
2552          *  ipacket[4]: X7  X6  X5  X4  X3  X2  X1  X0
2553          *  ipacket[5]: Y7  Y6  Y5  Y4  Y3  Y2  Y1  Y0
2554          *
2555          * Legend:
2556          *  L: left physical mouse button
2557          *  R: right physical mouse button
2558          *  D: down button
2559          *  U: up button
2560          *  W: "wrist" value
2561          *  X: x position
2562          *  Y: y position
2563          *  Z: pressure
2564          *
2565          * Absolute reportable limits:    0 - 6143.
2566          * Typical bezel limits:       1472 - 5472.
2567          * Typical edge marings:       1632 - 5312.
2568          *
2569          * w = 3 Passthrough Packet
2570          *
2571          * Byte 2,5,6 == Byte 1,2,3 of "Guest"
2572          */
2573
2574         if (!synaptics_support)
2575                 return (0);
2576
2577         /* Sanity check for out of sync packets. */
2578         if ((pb->ipacket[0] & 0xc8) != 0x80 ||
2579             (pb->ipacket[3] & 0xc8) != 0xc0)
2580                 return (-1);
2581
2582         *x = *y = 0;
2583
2584         /*
2585          * Pressure value.
2586          * Interpretation:
2587          *   z = 0      No finger contact
2588          *   z = 10     Finger hovering near the pad
2589          *   z = 30     Very light finger contact
2590          *   z = 80     Normal finger contact
2591          *   z = 110    Very heavy finger contact
2592          *   z = 200    Finger lying flat on pad surface
2593          *   z = 255    Maximum reportable Z
2594          */
2595         *z = pb->ipacket[2];
2596
2597         /*
2598          * Finger width value
2599          * Interpretation:
2600          *   w = 0      Two finger on the pad (capMultiFinger needed)
2601          *   w = 1      Three or more fingers (capMultiFinger needed)
2602          *   w = 2      Pen (instead of finger) (capPen needed)
2603          *   w = 3      Reserved (passthrough?)
2604          *   w = 4-7    Finger of normal width (capPalmDetect needed)
2605          *   w = 8-14   Very wide finger or palm (capPalmDetect needed)
2606          *   w = 15     Maximum reportable width (capPalmDetect needed)
2607          */
2608         /* XXX Is checking capExtended enough? */
2609         if (sc->synhw.capExtended)
2610                 w = ((pb->ipacket[0] & 0x30) >> 2) |
2611                     ((pb->ipacket[0] & 0x04) >> 1) |
2612                     ((pb->ipacket[3] & 0x04) >> 2);
2613         else {
2614                 /* Assume a finger of regular width. */
2615                 w = 4;
2616         }
2617
2618         /* Handle packets from the guest device */
2619         /* XXX Documentation? */
2620         if (w == 3 && sc->synhw.capPassthrough) {
2621                 *x = ((pb->ipacket[1] & 0x10) ?
2622                     pb->ipacket[4] - 256 : pb->ipacket[4]);
2623                 *y = ((pb->ipacket[1] & 0x20) ?
2624                     pb->ipacket[5] - 256 : pb->ipacket[5]);
2625                 *z = 0;
2626
2627                 guest_buttons = 0;
2628                 if (pb->ipacket[1] & 0x01)
2629                         guest_buttons |= MOUSE_BUTTON1DOWN;
2630                 if (pb->ipacket[1] & 0x04)
2631                         guest_buttons |= MOUSE_BUTTON2DOWN;
2632                 if (pb->ipacket[1] & 0x02)
2633                         guest_buttons |= MOUSE_BUTTON3DOWN;
2634
2635                 ms->button = touchpad_buttons | guest_buttons;
2636                 goto SYNAPTICS_END;
2637         }
2638
2639         /* Button presses */
2640         touchpad_buttons = 0;
2641         if (pb->ipacket[0] & 0x01)
2642                 touchpad_buttons |= MOUSE_BUTTON1DOWN;
2643         if (pb->ipacket[0] & 0x02)
2644                 touchpad_buttons |= MOUSE_BUTTON3DOWN;
2645
2646         if (sc->synhw.capExtended && sc->synhw.capFourButtons) {
2647                 if ((pb->ipacket[3] & 0x01) && (pb->ipacket[0] & 0x01) == 0)
2648                         touchpad_buttons |= MOUSE_BUTTON4DOWN;
2649                 if ((pb->ipacket[3] & 0x02) && (pb->ipacket[0] & 0x02) == 0)
2650                         touchpad_buttons |= MOUSE_BUTTON5DOWN;
2651         }
2652
2653         /*
2654          * In newer pads - bit 0x02 in the third byte of
2655          * the packet indicates that we have an extended
2656          * button press.
2657          */
2658         /* XXX Documentation? */
2659         if (pb->ipacket[3] & 0x02) {
2660                 /*
2661                  * if directional_scrolls is not 1, we treat any of
2662                  * the scrolling directions as middle-click.
2663                  */
2664                 if (sc->syninfo.directional_scrolls) {
2665                         if (pb->ipacket[4] & 0x01)
2666                                 touchpad_buttons |= MOUSE_BUTTON4DOWN;
2667                         if (pb->ipacket[5] & 0x01)
2668                                 touchpad_buttons |= MOUSE_BUTTON5DOWN;
2669                         if (pb->ipacket[4] & 0x02)
2670                                 touchpad_buttons |= MOUSE_BUTTON6DOWN;
2671                         if (pb->ipacket[5] & 0x02)
2672                                 touchpad_buttons |= MOUSE_BUTTON7DOWN;
2673                 } else {
2674                         if ((pb->ipacket[4] & 0x0F) ||
2675                             (pb->ipacket[5] & 0x0F))
2676                                 touchpad_buttons |= MOUSE_BUTTON2DOWN;
2677                 }
2678         }
2679
2680         ms->button = touchpad_buttons | guest_buttons;
2681
2682         /* Check pressure to detect a real wanted action on the
2683          * touchpad. */
2684         if (*z >= sc->syninfo.min_pressure) {
2685                 synapticsaction_t *synaction;
2686                 int cursor, peer, window;
2687                 int dx, dy, dxp, dyp;
2688                 int max_width, max_pressure;
2689                 int margin_top, margin_right, margin_bottom, margin_left;
2690                 int na_top, na_right, na_bottom, na_left;
2691                 int window_min, window_max;
2692                 int multiplicator;
2693                 int weight_current, weight_previous, weight_len_squared;
2694                 int div_min, div_max, div_len;
2695                 int vscroll_hor_area, vscroll_ver_area;
2696
2697                 int len, weight_prev_x, weight_prev_y;
2698                 int div_max_x, div_max_y, div_x, div_y;
2699
2700                 /* Read sysctl. */
2701                 /* XXX Verify values? */
2702                 max_width = sc->syninfo.max_width;
2703                 max_pressure = sc->syninfo.max_pressure;
2704                 margin_top = sc->syninfo.margin_top;
2705                 margin_right = sc->syninfo.margin_right;
2706                 margin_bottom = sc->syninfo.margin_bottom;
2707                 margin_left = sc->syninfo.margin_left;
2708                 na_top = sc->syninfo.na_top;
2709                 na_right = sc->syninfo.na_right;
2710                 na_bottom = sc->syninfo.na_bottom;
2711                 na_left = sc->syninfo.na_left;
2712                 window_min = sc->syninfo.window_min;
2713                 window_max = sc->syninfo.window_max;
2714                 multiplicator = sc->syninfo.multiplicator;
2715                 weight_current = sc->syninfo.weight_current;
2716                 weight_previous = sc->syninfo.weight_previous;
2717                 weight_len_squared = sc->syninfo.weight_len_squared;
2718                 div_min = sc->syninfo.div_min;
2719                 div_max = sc->syninfo.div_max;
2720                 div_len = sc->syninfo.div_len;
2721                 vscroll_hor_area = sc->syninfo.vscroll_hor_area;
2722                 vscroll_ver_area = sc->syninfo.vscroll_ver_area;
2723
2724                 /* Palm detection. */
2725                 if (!(
2726                     (sc->synhw.capMultiFinger && (w == 0 || w == 1)) ||
2727                     (sc->synhw.capPalmDetect && w >= 4 && w <= max_width) ||
2728                     (!sc->synhw.capPalmDetect && *z <= max_pressure) ||
2729                     (sc->synhw.capPen && w == 2))) {
2730                         /*
2731                          * We consider the packet irrelevant for the current
2732                          * action when:
2733                          *  - the width isn't comprised in:
2734                          *    [4; max_width]
2735                          *  - the pressure isn't comprised in:
2736                          *    [min_pressure; max_pressure]
2737                          *  - pen aren't supported but w is 2
2738                          *
2739                          *  Note that this doesn't terminate the current action.
2740                          */
2741                         VLOG(2, (LOG_DEBUG,
2742                             "synaptics: palm detected! (%d)\n", w));
2743                         goto SYNAPTICS_END;
2744                 }
2745
2746                 /* Read current absolute position. */
2747                 x0 = ((pb->ipacket[3] & 0x10) << 8) |
2748                     ((pb->ipacket[1] & 0x0f) << 8) |
2749                     pb->ipacket[4];
2750                 y0 = ((pb->ipacket[3] & 0x20) << 7) |
2751                     ((pb->ipacket[1] & 0xf0) << 4) |
2752                     pb->ipacket[5];
2753
2754                 synaction = &(sc->synaction);
2755
2756                 /*
2757                  * If the action is just beginning, init the structure and
2758                  * compute tap timeout.
2759                  */
2760                 if (!(sc->flags & PSM_FLAGS_FINGERDOWN)) {
2761                         VLOG(3, (LOG_DEBUG, "synaptics: ----\n"));
2762
2763                         /* Store the first point of this action. */
2764                         synaction->start_x = x0;
2765                         synaction->start_y = y0;
2766                         dx = dy = 0;
2767
2768                         /* Initialize queue. */
2769                         synaction->queue_cursor = SYNAPTICS_PACKETQUEUE;
2770                         synaction->queue_len = 0;
2771                         synaction->window_min = window_min;
2772
2773                         /* Reset average. */
2774                         synaction->avg_dx = 0;
2775                         synaction->avg_dy = 0;
2776
2777                         /* Reset squelch. */
2778                         synaction->squelch_x = 0;
2779                         synaction->squelch_y = 0;
2780
2781                         /* Reset pressure peak. */
2782                         sc->zmax = 0;
2783
2784                         /* Reset fingers count. */
2785                         synaction->fingers_nb = 0;
2786
2787                         /* Reset virtual scrolling state. */
2788                         synaction->in_vscroll = 0;
2789
2790                         /* Compute tap timeout. */
2791                         sc->taptimeout.tv_sec  = tap_timeout / 1000000;
2792                         sc->taptimeout.tv_usec = tap_timeout % 1000000;
2793                         timevaladd(&sc->taptimeout, &sc->lastsoftintr);
2794
2795                         sc->flags |= PSM_FLAGS_FINGERDOWN;
2796                 } else {
2797                         /* Calculate the current delta. */
2798                         cursor = synaction->queue_cursor;
2799                         dx = x0 - synaction->queue[cursor].x;
2800                         dy = y0 - synaction->queue[cursor].y;
2801                 }
2802
2803                 /* If in tap-hold, add the recorded button. */
2804                 if (synaction->in_taphold)
2805                         ms->button |= synaction->tap_button;
2806
2807                 /*
2808                  * From now on, we can use the SYNAPTICS_END label to skip
2809                  * the current packet.
2810                  */
2811
2812                 /*
2813                  * Limit the coordinates to the specified margins because
2814                  * this area isn't very reliable.
2815                  */
2816                 if (x0 <= margin_left)
2817                         x0 = margin_left;
2818                 else if (x0 >= 6143 - margin_right)
2819                         x0 = 6143 - margin_right;
2820                 if (y0 <= margin_bottom)
2821                         y0 = margin_bottom;
2822                 else if (y0 >= 6143 - margin_top)
2823                         y0 = 6143 - margin_top;
2824
2825                 VLOG(3, (LOG_DEBUG, "synaptics: ipacket: [%d, %d], %d, %d\n",
2826                     x0, y0, *z, w));
2827
2828                 /* Queue this new packet. */
2829                 cursor = SYNAPTICS_QUEUE_CURSOR(synaction->queue_cursor - 1);
2830                 synaction->queue[cursor].x = x0;
2831                 synaction->queue[cursor].y = y0;
2832                 synaction->queue_cursor = cursor;
2833                 if (synaction->queue_len < SYNAPTICS_PACKETQUEUE)
2834                         synaction->queue_len++;
2835                 VLOG(5, (LOG_DEBUG,
2836                     "synaptics: cursor[%d]: x=%d, y=%d, dx=%d, dy=%d\n",
2837                     cursor, x0, y0, dx, dy));
2838
2839                 /*
2840                  * For tap, we keep the maximum number of fingers and the
2841                  * pressure peak. Also with multiple fingers, we increase
2842                  * the minimum window.
2843                  */
2844                 switch (w) {
2845                 case 1: /* Three or more fingers. */
2846                         synaction->fingers_nb = imax(3, synaction->fingers_nb);
2847                         synaction->window_min = window_max;
2848                         break;
2849                 case 0: /* Two fingers. */
2850                         synaction->fingers_nb = imax(2, synaction->fingers_nb);
2851                         synaction->window_min = window_max;
2852                         break;
2853                 default: /* One finger or undetectable. */
2854                         synaction->fingers_nb = imax(1, synaction->fingers_nb);
2855                 }
2856                 sc->zmax = imax(*z, sc->zmax);
2857
2858                 /* Do we have enough packets to consider this a movement? */
2859                 if (synaction->queue_len < synaction->window_min)
2860                         goto SYNAPTICS_END;
2861
2862                 /* Is a scrolling action occuring? */
2863                 if (!synaction->in_taphold && !synaction->in_vscroll) {
2864                         /*
2865                          * A scrolling action must not conflict with a tap
2866                          * action. Here are the conditions to consider a
2867                          * scrolling action:
2868                          *  - the action in a configurable area
2869                          *  - one of the following:
2870                          *     . the distance between the last packet and the
2871                          *       first should be above a configurable minimum
2872                          *     . tap timed out
2873                          */
2874                         dxp = abs(synaction->queue[synaction->queue_cursor].x -
2875                             synaction->start_x);
2876                         dyp = abs(synaction->queue[synaction->queue_cursor].y -
2877                             synaction->start_y);
2878
2879                         if (timevalcmp(&sc->lastsoftintr, &sc->taptimeout, >) ||
2880                             dxp >= sc->syninfo.vscroll_min_delta ||
2881                             dyp >= sc->syninfo.vscroll_min_delta) {
2882                                 /* Check for horizontal scrolling. */
2883                                 if ((vscroll_hor_area > 0 &&
2884                                     synaction->start_y <= vscroll_hor_area) ||
2885                                     (vscroll_hor_area < 0 &&
2886                                      synaction->start_y >=
2887                                      6143 + vscroll_hor_area))
2888                                         synaction->in_vscroll += 2;
2889
2890                                 /* Check for vertical scrolling. */
2891                                 if ((vscroll_ver_area > 0 &&
2892                                     synaction->start_x <= vscroll_ver_area) ||
2893                                     (vscroll_ver_area < 0 &&
2894                                      synaction->start_x >=
2895                                      6143 + vscroll_ver_area))
2896                                         synaction->in_vscroll += 1;
2897
2898                                 /* Avoid conflicts if area overlaps. */
2899                                 if (synaction->in_vscroll == 3)
2900                                         synaction->in_vscroll =
2901                                             (dxp > dyp) ? 2 : 1;
2902                         }
2903                         VLOG(5, (LOG_DEBUG,
2904                             "synaptics: virtual scrolling: %s "
2905                             "(direction=%d, dxp=%d, dyp=%d)\n",
2906                             synaction->in_vscroll ? "YES" : "NO",
2907                             synaction->in_vscroll, dxp, dyp));
2908                 }
2909
2910                 weight_prev_x = weight_prev_y = weight_previous;
2911                 div_max_x = div_max_y = div_max;
2912
2913                 if (synaction->in_vscroll) {
2914                         /* Dividers are different with virtual scrolling. */
2915                         div_min = sc->syninfo.vscroll_div_min;
2916                         div_max_x = div_max_y = sc->syninfo.vscroll_div_max;
2917                 } else {
2918                         /*
2919                          * There's a lot of noise in coordinates when
2920                          * the finger is on the touchpad's borders. When
2921                          * using this area, we apply a special weight and
2922                          * div.
2923                          */
2924                         if (x0 <= na_left || x0 >= 6143 - na_right) {
2925                                 weight_prev_x = sc->syninfo.weight_previous_na;
2926                                 div_max_x = sc->syninfo.div_max_na;
2927                         }
2928
2929                         if (y0 <= na_bottom || y0 >= 6143 - na_top) {
2930                                 weight_prev_y = sc->syninfo.weight_previous_na;
2931                                 div_max_y = sc->syninfo.div_max_na;
2932                         }
2933                 }
2934
2935                 /*
2936                  * Calculate weights for the average operands and
2937                  * the divisor. Both depend on the distance between
2938                  * the current packet and a previous one (based on the
2939                  * window width).
2940                  */
2941                 window = imin(synaction->queue_len, window_max);
2942                 peer = SYNAPTICS_QUEUE_CURSOR(cursor + window - 1);
2943                 dxp = abs(x0 - synaction->queue[peer].x) + 1;
2944                 dyp = abs(y0 - synaction->queue[peer].y) + 1;
2945                 len = (dxp * dxp) + (dyp * dyp);
2946                 weight_prev_x = imin(weight_prev_x,
2947                     weight_len_squared * weight_prev_x / len);
2948                 weight_prev_y = imin(weight_prev_y,
2949                     weight_len_squared * weight_prev_y / len);
2950
2951                 len = (dxp + dyp) / 2;
2952                 div_x = div_len * div_max_x / len;
2953                 div_x = imin(div_max_x, div_x);
2954                 div_x = imax(div_min, div_x);
2955                 div_y = div_len * div_max_y / len;
2956                 div_y = imin(div_max_y, div_y);
2957                 div_y = imax(div_min, div_y);
2958
2959                 VLOG(3, (LOG_DEBUG,
2960                     "synaptics: peer=%d, len=%d, weight=%d/%d, div=%d/%d\n",
2961                     peer, len, weight_prev_x, weight_prev_y, div_x, div_y));
2962
2963                 /* Compute averages. */
2964                 synaction->avg_dx =
2965                     (weight_current * dx * multiplicator +
2966                      weight_prev_x * synaction->avg_dx) /
2967                     (weight_current + weight_prev_x);
2968
2969                 synaction->avg_dy =
2970                     (weight_current * dy * multiplicator +
2971                      weight_prev_y * synaction->avg_dy) /
2972                     (weight_current + weight_prev_y);
2973
2974                 VLOG(5, (LOG_DEBUG,
2975                     "synaptics: avg_dx~=%d, avg_dy~=%d\n",
2976                     synaction->avg_dx / multiplicator,
2977                     synaction->avg_dy / multiplicator));
2978
2979                 /* Use these averages to calculate x & y. */
2980                 synaction->squelch_x += synaction->avg_dx;
2981                 *x = synaction->squelch_x / (div_x * multiplicator);
2982                 synaction->squelch_x = synaction->squelch_x %
2983                     (div_x * multiplicator);
2984
2985                 synaction->squelch_y += synaction->avg_dy;
2986                 *y = synaction->squelch_y / (div_y * multiplicator);
2987                 synaction->squelch_y = synaction->squelch_y %
2988                     (div_y * multiplicator);
2989
2990                 if (synaction->in_vscroll) {
2991                         switch(synaction->in_vscroll) {
2992                         case 1: /* Vertical scrolling. */
2993                                 if (*y != 0)
2994                                         ms->button |= (*y > 0) ?
2995                                             MOUSE_BUTTON4DOWN :
2996                                             MOUSE_BUTTON5DOWN;
2997                                 break;
2998                         case 2: /* Horizontal scrolling. */
2999                                 if (*x != 0)
3000                                         ms->button |= (*x > 0) ?
3001                                             MOUSE_BUTTON7DOWN :
3002                                             MOUSE_BUTTON6DOWN;
3003                                 break;
3004                         }
3005
3006                         /* The pointer is not moved. */
3007                         *x = *y = 0;
3008                 } else {
3009                         VLOG(3, (LOG_DEBUG, "synaptics: [%d, %d] -> [%d, %d]\n",
3010                             dx, dy, *x, *y));
3011                 }
3012         } else if (sc->flags & PSM_FLAGS_FINGERDOWN) {
3013                 /*
3014                  * An action is currently taking place but the pressure
3015                  * dropped under the minimum, putting an end to it.
3016                  */
3017                 synapticsaction_t *synaction;
3018                 int taphold_timeout, dx, dy, tap_max_delta;
3019
3020                 synaction = &(sc->synaction);
3021                 dx = abs(synaction->queue[synaction->queue_cursor].x -
3022                     synaction->start_x);
3023                 dy = abs(synaction->queue[synaction->queue_cursor].y -
3024                     synaction->start_y);
3025
3026                 /* Max delta is disabled for multi-fingers tap. */
3027                 if (synaction->fingers_nb > 1)
3028                         tap_max_delta = imax(dx, dy);
3029                 else
3030                         tap_max_delta = sc->syninfo.tap_max_delta;
3031
3032                 sc->flags &= ~PSM_FLAGS_FINGERDOWN;
3033
3034                 /* Check for tap. */
3035                 VLOG(3, (LOG_DEBUG,
3036                     "synaptics: zmax=%d, dx=%d, dy=%d, "
3037                     "delta=%d, fingers=%d, queue=%d\n",
3038                     sc->zmax, dx, dy, tap_max_delta, synaction->fingers_nb,
3039                     synaction->queue_len));
3040                 if (!synaction->in_vscroll && sc->zmax >= tap_threshold &&
3041                     timevalcmp(&sc->lastsoftintr, &sc->taptimeout, <=) &&
3042                     dx <= tap_max_delta && dy <= tap_max_delta &&
3043                     synaction->queue_len >= sc->syninfo.tap_min_queue) {
3044                         /*
3045                          * We have a tap if:
3046                          *   - the maximum pressure went over tap_threshold
3047                          *   - the action ended before tap_timeout
3048                          *
3049                          * To handle tap-hold, we must delay any button push to
3050                          * the next action.
3051                          */
3052                         if (synaction->in_taphold) {
3053                                 /*
3054                                  * This is the second and last tap of a
3055                                  * double tap action, not a tap-hold.
3056                                  */
3057                                 synaction->in_taphold = 0;
3058
3059                                 /*
3060                                  * For double-tap to work:
3061                                  *   - no button press is emitted (to
3062                                  *     simulate a button release)
3063                                  *   - PSM_FLAGS_FINGERDOWN is set to
3064                                  *     force the next packet to emit a
3065                                  *     button press)
3066                                  */
3067                                 VLOG(2, (LOG_DEBUG,
3068                                     "synaptics: button RELEASE: %d\n",
3069                                     synaction->tap_button));
3070                                 sc->flags |= PSM_FLAGS_FINGERDOWN;
3071                         } else {
3072                                 /*
3073                                  * This is the first tap: we set the
3074                                  * tap-hold state and notify the button
3075                                  * down event.
3076                                  */
3077                                 synaction->in_taphold = 1;
3078                                 taphold_timeout = sc->syninfo.taphold_timeout;
3079                                 sc->taptimeout.tv_sec  = taphold_timeout /
3080                                     1000000;
3081                                 sc->taptimeout.tv_usec = taphold_timeout %
3082                                     1000000;
3083                                 timevaladd(&sc->taptimeout, &sc->lastsoftintr);
3084
3085                                 switch (synaction->fingers_nb) {
3086                                 case 3:
3087                                         synaction->tap_button =
3088                                             MOUSE_BUTTON2DOWN;
3089                                         break;
3090                                 case 2:
3091                                         synaction->tap_button =
3092                                             MOUSE_BUTTON3DOWN;
3093                                         break;
3094                                 default:
3095                                         synaction->tap_button =
3096                                             MOUSE_BUTTON1DOWN;
3097                                 }
3098                                 VLOG(2, (LOG_DEBUG,
3099                                     "synaptics: button PRESS: %d\n",
3100                                     synaction->tap_button));
3101                                 ms->button |= synaction->tap_button;
3102                         }
3103                 } else {
3104                         /*
3105                          * Not enough pressure or timeout: reset
3106                          * tap-hold state.
3107                          */
3108                         if (synaction->in_taphold) {
3109                                 VLOG(2, (LOG_DEBUG,
3110                                     "synaptics: button RELEASE: %d\n",
3111                                     synaction->tap_button));
3112                                 synaction->in_taphold = 0;
3113                         } else {
3114                                 VLOG(2, (LOG_DEBUG,
3115                                     "synaptics: not a tap-hold\n"));
3116                         }
3117                 }
3118         } else if (!(sc->flags & PSM_FLAGS_FINGERDOWN) &&
3119             sc->synaction.in_taphold) {
3120                 /*
3121                  * For a tap-hold to work, the button must remain down at
3122                  * least until timeout (where the in_taphold flags will be
3123                  * cleared) or during the next action.
3124                  */
3125                 if (timevalcmp(&sc->lastsoftintr, &sc->taptimeout, <=)) {
3126                         ms->button |= sc->synaction.tap_button;
3127                 } else {
3128                         VLOG(2, (LOG_DEBUG,
3129                             "synaptics: button RELEASE: %d\n",
3130                             sc->synaction.tap_button));
3131                         sc->synaction.in_taphold = 0;
3132                 }
3133         }
3134
3135 SYNAPTICS_END:
3136         /*
3137          * Use the extra buttons as a scrollwheel
3138          *
3139          * XXX X.Org uses the Z axis for vertical wheel only,
3140          * whereas moused(8) understands special values to differ
3141          * vertical and horizontal wheels.
3142          *
3143          * xf86-input-mouse needs therefore a small patch to
3144          * understand these special values. Without it, the
3145          * horizontal wheel acts as a vertical wheel in X.Org.
3146          *
3147          * That's why the horizontal wheel is disabled by
3148          * default for now.
3149          */
3150         if (ms->button & MOUSE_BUTTON4DOWN) {
3151                 *z = -1;
3152                 ms->button &= ~MOUSE_BUTTON4DOWN;
3153         } else if (ms->button & MOUSE_BUTTON5DOWN) {
3154                 *z = 1;
3155                 ms->button &= ~MOUSE_BUTTON5DOWN;
3156         } else if (ms->button & MOUSE_BUTTON6DOWN) {
3157                 *z = -2;
3158                 ms->button &= ~MOUSE_BUTTON6DOWN;
3159         } else if (ms->button & MOUSE_BUTTON7DOWN) {
3160                 *z = 2;
3161                 ms->button &= ~MOUSE_BUTTON7DOWN;
3162         } else
3163                 *z = 0;
3164
3165         return (0);
3166 }
3167
3168 static void
3169 proc_versapad(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
3170     int *x, int *y, int *z)
3171 {
3172         static int butmap_versapad[8] = {
3173                 0,
3174                 MOUSE_BUTTON3DOWN,
3175                 0,
3176                 MOUSE_BUTTON3DOWN,
3177                 MOUSE_BUTTON1DOWN,
3178                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
3179                 MOUSE_BUTTON1DOWN,
3180                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN
3181         };
3182         int c, x0, y0;
3183
3184         /* VersaPad PS/2 absolute mode message format
3185          *
3186          * [packet1]     7   6   5   4   3   2   1   0(LSB)
3187          *  ipacket[0]:  1   1   0   A   1   L   T   R
3188          *  ipacket[1]: H7  H6  H5  H4  H3  H2  H1  H0
3189          *  ipacket[2]: V7  V6  V5  V4  V3  V2  V1  V0
3190          *  ipacket[3]:  1   1   1   A   1   L   T   R
3191          *  ipacket[4]:V11 V10  V9  V8 H11 H10  H9  H8
3192          *  ipacket[5]:  0  P6  P5  P4  P3  P2  P1  P0
3193          *
3194          * [note]
3195          *  R: right physical mouse button (1=on)
3196          *  T: touch pad virtual button (1=tapping)
3197          *  L: left physical mouse button (1=on)
3198          *  A: position data is valid (1=valid)
3199          *  H: horizontal data (12bit signed integer. H11 is sign bit.)
3200          *  V: vertical data (12bit signed integer. V11 is sign bit.)
3201          *  P: pressure data
3202          *
3203          * Tapping is mapped to MOUSE_BUTTON4.
3204          */
3205         c = pb->ipacket[0];
3206         *x = *y = 0;
3207         ms->button = butmap_versapad[c & MOUSE_PS2VERSA_BUTTONS];
3208         ms->button |= (c & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0;
3209         if (c & MOUSE_PS2VERSA_IN_USE) {
3210                 x0 = pb->ipacket[1] | (((pb->ipacket[4]) & 0x0f) << 8);
3211                 y0 = pb->ipacket[2] | (((pb->ipacket[4]) & 0xf0) << 4);
3212                 if (x0 & 0x800)
3213                         x0 -= 0x1000;
3214                 if (y0 & 0x800)
3215                         y0 -= 0x1000;
3216                 if (sc->flags & PSM_FLAGS_FINGERDOWN) {
3217                         *x = sc->xold - x0;
3218                         *y = y0 - sc->yold;
3219                         if (*x < 0)     /* XXX */
3220                                 ++*x;
3221                         else if (*x)
3222                                 --*x;
3223                         if (*y < 0)
3224                                 ++*y;
3225                         else if (*y)
3226                                 --*y;
3227                 } else
3228                         sc->flags |= PSM_FLAGS_FINGERDOWN;
3229                 sc->xold = x0;
3230                 sc->yold = y0;
3231         } else
3232                 sc->flags &= ~PSM_FLAGS_FINGERDOWN;
3233 }
3234
3235 static void
3236 psmsoftintr(void *arg)
3237 {
3238         /*
3239          * the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN)
3240          * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
3241          */
3242         static int butmap[8] = {
3243                 0,
3244                 MOUSE_BUTTON1DOWN,
3245                 MOUSE_BUTTON3DOWN,
3246                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
3247                 MOUSE_BUTTON2DOWN,
3248                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
3249                 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
3250                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
3251         };
3252         struct psm_softc *sc = arg;
3253         mousestatus_t ms;
3254         packetbuf_t *pb;
3255         int x, y, z, c, l;
3256
3257         getmicrouptime(&sc->lastsoftintr);
3258
3259         crit_enter();
3260
3261         do {
3262                 pb = &sc->pqueue[sc->pqueue_start];
3263
3264                 if (sc->mode.level == PSM_LEVEL_NATIVE)
3265                         goto next_native;
3266
3267                 c = pb->ipacket[0];
3268                 /*
3269                  * A kludge for Kensington device!
3270                  * The MSB of the horizontal count appears to be stored in
3271                  * a strange place.
3272                  */
3273                 if (sc->hw.model == MOUSE_MODEL_THINK)
3274                         pb->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0;
3275
3276                 /* ignore the overflow bits... */
3277                 x = (c & MOUSE_PS2_XNEG) ?
3278                     pb->ipacket[1] - 256 : pb->ipacket[1];
3279                 y = (c & MOUSE_PS2_YNEG) ?
3280                     pb->ipacket[2] - 256 : pb->ipacket[2];
3281                 z = 0;
3282                 ms.obutton = sc->button;          /* previous button state */
3283                 ms.button = butmap[c & MOUSE_PS2_BUTTONS];
3284                 /* `tapping' action */
3285                 if (sc->config & PSM_CONFIG_FORCETAP)
3286                         ms.button |= ((c & MOUSE_PS2_TAP)) ?
3287                             0 : MOUSE_BUTTON4DOWN;
3288
3289                 switch (sc->hw.model) {
3290
3291                 case MOUSE_MODEL_EXPLORER:
3292                         /*
3293                          *          b7 b6 b5 b4 b3 b2 b1 b0
3294                          * byte 1:  oy ox sy sx 1  M  R  L
3295                          * byte 2:  x  x  x  x  x  x  x  x
3296                          * byte 3:  y  y  y  y  y  y  y  y
3297                          * byte 4:  *  *  S2 S1 s  d2 d1 d0
3298                          *
3299                          * L, M, R, S1, S2: left, middle, right and side buttons
3300                          * s: wheel data sign bit
3301                          * d2-d0: wheel data
3302                          */
3303                         z = (pb->ipacket[3] & MOUSE_EXPLORER_ZNEG) ?
3304                             (pb->ipacket[3] & 0x0f) - 16 :
3305                             (pb->ipacket[3] & 0x0f);
3306                         ms.button |=
3307                             (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON4DOWN) ?
3308                             MOUSE_BUTTON4DOWN : 0;
3309                         ms.button |=
3310                             (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON5DOWN) ?
3311                             MOUSE_BUTTON5DOWN : 0;
3312                         break;
3313
3314                 case MOUSE_MODEL_INTELLI:
3315                 case MOUSE_MODEL_NET:
3316                         /* wheel data is in the fourth byte */
3317                         z = (char)pb->ipacket[3];
3318                         /*
3319                          * XXX some mice may send 7 when there is no Z movement?                         */
3320                         if ((z >= 7) || (z <= -7))
3321                                 z = 0;
3322                         /* some compatible mice have additional buttons */
3323                         ms.button |= (c & MOUSE_PS2INTELLI_BUTTON4DOWN) ?
3324                             MOUSE_BUTTON4DOWN : 0;
3325                         ms.button |= (c & MOUSE_PS2INTELLI_BUTTON5DOWN) ?
3326                             MOUSE_BUTTON5DOWN : 0;
3327                         break;
3328
3329                 case MOUSE_MODEL_MOUSEMANPLUS:
3330                         proc_mmanplus(sc, pb, &ms, &x, &y, &z);
3331                         break;
3332
3333                 case MOUSE_MODEL_GLIDEPOINT:
3334                         /* `tapping' action */
3335                         ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 :
3336                             MOUSE_BUTTON4DOWN;
3337                         break;
3338
3339                 case MOUSE_MODEL_NETSCROLL:
3340                         /*
3341                          * three addtional bytes encode buttons and
3342                          * wheel events
3343                          */
3344                         ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON3DOWN) ?
3345                             MOUSE_BUTTON4DOWN : 0;
3346                         ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON1DOWN) ?
3347                             MOUSE_BUTTON5DOWN : 0;
3348                         z = (pb->ipacket[3] & MOUSE_PS2_XNEG) ?
3349                             pb->ipacket[4] - 256 : pb->ipacket[4];
3350                         break;
3351
3352                 case MOUSE_MODEL_THINK:
3353                         /* the fourth button state in the first byte */
3354                         ms.button |= (c & MOUSE_PS2_TAP) ?
3355                             MOUSE_BUTTON4DOWN : 0;
3356                         break;
3357
3358                 case MOUSE_MODEL_VERSAPAD:
3359                         proc_versapad(sc, pb, &ms, &x, &y, &z);
3360                         c = ((x < 0) ? MOUSE_PS2_XNEG : 0) |
3361                             ((y < 0) ? MOUSE_PS2_YNEG : 0);
3362                         break;
3363
3364                 case MOUSE_MODEL_4D:
3365                         /*
3366                          *          b7 b6 b5 b4 b3 b2 b1 b0
3367                          * byte 1:  s2 d2 s1 d1 1  M  R  L
3368                          * byte 2:  sx x  x  x  x  x  x  x
3369                          * byte 3:  sy y  y  y  y  y  y  y
3370                          *
3371                          * s1: wheel 1 direction
3372                          * d1: wheel 1 data
3373                          * s2: wheel 2 direction
3374                          * d2: wheel 2 data
3375                          */
3376                         x = (pb->ipacket[1] & 0x80) ?
3377                             pb->ipacket[1] - 256 : pb->ipacket[1];
3378                         y = (pb->ipacket[2] & 0x80) ?
3379                             pb->ipacket[2] - 256 : pb->ipacket[2];
3380                         switch (c & MOUSE_4D_WHEELBITS) {
3381                         case 0x10:
3382                                 z = 1;
3383                                 break;
3384                         case 0x30:
3385                                 z = -1;
3386                                 break;
3387                         case 0x40:      /* XXX 2nd wheel turning right */
3388                                 z = 2;
3389                                 break;
3390                         case 0xc0:      /* XXX 2nd wheel turning left */
3391                                 z = -2;
3392                                 break;
3393                         }
3394                         break;
3395
3396                 case MOUSE_MODEL_4DPLUS:
3397                         if ((x < 16 - 256) && (y < 16 - 256)) {
3398                                 /*
3399                                  *          b7 b6 b5 b4 b3 b2 b1 b0
3400                                  * byte 1:  0  0  1  1  1  M  R  L
3401                                  * byte 2:  0  0  0  0  1  0  0  0
3402                                  * byte 3:  0  0  0  0  S  s  d1 d0
3403                                  *
3404                                  * L, M, R, S: left, middle, right,
3405                                  *             and side buttons
3406                                  * s: wheel data sign bit
3407                                  * d1-d0: wheel data
3408                                  */
3409                                 x = y = 0;
3410                                 if (pb->ipacket[2] & MOUSE_4DPLUS_BUTTON4DOWN)
3411                                         ms.button |= MOUSE_BUTTON4DOWN;
3412                                 z = (pb->ipacket[2] & MOUSE_4DPLUS_ZNEG) ?
3413                                     ((pb->ipacket[2] & 0x07) - 8) :
3414                                     (pb->ipacket[2] & 0x07) ;
3415                         } else {
3416                                 /* preserve previous button states */
3417                                 ms.button |= ms.obutton & MOUSE_EXTBUTTONS;
3418                         }
3419                         break;
3420
3421                 case MOUSE_MODEL_SYNAPTICS:
3422                         if (proc_synaptics(sc, pb, &ms, &x, &y, &z) != 0)
3423                                 goto next;
3424                         break;
3425
3426                 case MOUSE_MODEL_GENERIC:
3427                 default:
3428                         break;
3429                 }
3430
3431         /* scale values */
3432         if (sc->mode.accelfactor >= 1) {
3433                 if (x != 0) {
3434                         x = x * x / sc->mode.accelfactor;
3435                         if (x == 0)
3436                                 x = 1;
3437                         if (c & MOUSE_PS2_XNEG)
3438                                 x = -x;
3439                 }
3440                 if (y != 0) {
3441                         y = y * y / sc->mode.accelfactor;
3442                         if (y == 0)
3443                                 y = 1;
3444                         if (c & MOUSE_PS2_YNEG)
3445                                 y = -y;
3446                 }
3447         }
3448
3449         ms.dx = x;
3450         ms.dy = y;
3451         ms.dz = z;
3452         ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0) |
3453             (ms.obutton ^ ms.button);
3454
3455         pb->inputbytes = tame_mouse(sc, pb, &ms, pb->ipacket);
3456
3457         sc->status.flags |= ms.flags;
3458         sc->status.dx += ms.dx;
3459         sc->status.dy += ms.dy;
3460         sc->status.dz += ms.dz;
3461         sc->status.button = ms.button;
3462         sc->button = ms.button;
3463
3464 next_native:
3465         sc->watchdog = FALSE;
3466
3467         /* queue data */
3468         if (sc->queue.count + pb->inputbytes < sizeof(sc->queue.buf)) {
3469                 l = imin(pb->inputbytes,
3470                     sizeof(sc->queue.buf) - sc->queue.tail);
3471                 bcopy(&pb->ipacket[0], &sc->queue.buf[sc->queue.tail], l);
3472                 if (pb->inputbytes > l)
3473                         bcopy(&pb->ipacket[l], &sc->queue.buf[0],
3474                             pb->inputbytes - l);
3475                 sc->queue.tail = (sc->queue.tail + pb->inputbytes) %
3476                     sizeof(sc->queue.buf);
3477                 sc->queue.count += pb->inputbytes;
3478         }
3479         pb->inputbytes = 0;
3480
3481 next:
3482         if (++sc->pqueue_start >= PSM_PACKETQUEUE)
3483                 sc->pqueue_start = 0;
3484         } while (sc->pqueue_start != sc->pqueue_end);
3485
3486         if (sc->state & PSM_ASLP) {
3487                 sc->state &= ~PSM_ASLP;
3488                 wakeup(sc);
3489         }
3490         KNOTE(&sc->rkq.ki_note, 0);
3491
3492         sc->state &= ~PSM_SOFTARMED;
3493         crit_exit();
3494 }
3495
3496 static struct filterops psmfiltops =
3497         { FILTEROP_ISFD, NULL, psmfilter_detach, psmfilter };
3498
3499 static int
3500 psmkqfilter(struct dev_kqfilter_args *ap)
3501 {
3502         cdev_t dev = ap->a_head.a_dev;
3503         struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
3504         struct knote *kn = ap->a_kn;
3505         struct klist *klist;
3506
3507         ap->a_result = 0;
3508
3509         switch (kn->kn_filter) {
3510                 case EVFILT_READ:
3511                         kn->kn_fop = &psmfiltops;
3512                         kn->kn_hook = (caddr_t)sc;
3513                         break;
3514                 default:
3515                         ap->a_result = EOPNOTSUPP;
3516                         return (0);
3517         }
3518
3519         klist = &sc->rkq.ki_note;
3520         knote_insert(klist, kn);
3521
3522         return (0);
3523 }
3524
3525 static void
3526 psmfilter_detach(struct knote *kn)
3527 {
3528         struct psm_softc *sc = (struct psm_softc *)kn->kn_hook;
3529         struct klist *klist;
3530
3531         klist = &sc->rkq.ki_note;
3532         knote_remove(klist, kn);
3533 }
3534
3535 static int
3536 psmfilter(struct knote *kn, long hint)
3537 {
3538         struct psm_softc *sc = (struct psm_softc *)kn->kn_hook;
3539         int ready = 0;
3540
3541         crit_enter();
3542         if (sc->queue.count > 0)
3543                 ready = 1;
3544         crit_exit();
3545
3546         return (ready);
3547 }
3548
3549 /* vendor/model specific routines */
3550
3551 static int mouse_id_proc1(KBDC kbdc, int res, int scale, int *status)
3552 {
3553         if (set_mouse_resolution(kbdc, res) != res)
3554                 return (FALSE);
3555         if (set_mouse_scaling(kbdc, scale) &&
3556             set_mouse_scaling(kbdc, scale) &&
3557             set_mouse_scaling(kbdc, scale) &&
3558             (get_mouse_status(kbdc, status, 0, 3) >= 3))
3559                 return (TRUE);
3560         return (FALSE);
3561 }
3562
3563 static int
3564 mouse_ext_command(KBDC kbdc, int command)
3565 {
3566         int c;
3567
3568         c = (command >> 6) & 0x03;
3569         if (set_mouse_resolution(kbdc, c) != c)
3570                 return (FALSE);
3571         c = (command >> 4) & 0x03;
3572         if (set_mouse_resolution(kbdc, c) != c)
3573                 return (FALSE);
3574         c = (command >> 2) & 0x03;
3575         if (set_mouse_resolution(kbdc, c) != c)
3576                 return (FALSE);
3577         c = (command >> 0) & 0x03;
3578         if (set_mouse_resolution(kbdc, c) != c)
3579                 return (FALSE);
3580         return (TRUE);
3581 }
3582
3583 #ifdef notyet
3584 /* Logitech MouseMan Cordless II */
3585 static int
3586 enable_lcordless(struct psm_softc *sc)
3587 {
3588         int status[3];
3589         int ch;
3590
3591         if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 2, status))
3592                 return (FALSE);
3593         if (status[1] == PSMD_RES_HIGH)
3594                 return (FALSE);
3595         ch = (status[0] & 0x07) - 1;    /* channel # */
3596         if ((ch <= 0) || (ch > 4))
3597                 return (FALSE);
3598         /*
3599          * status[1]: always one?
3600          * status[2]: battery status? (0-100)
3601          */
3602         return (TRUE);
3603 }
3604 #endif /* notyet */
3605
3606 /* Genius NetScroll Mouse, MouseSystems SmartScroll Mouse */
3607 static int
3608 enable_groller(struct psm_softc *sc)
3609 {
3610         int status[3];
3611
3612         /*
3613          * The special sequence to enable the fourth button and the
3614          * roller. Immediately after this sequence check status bytes.
3615          * if the mouse is NetScroll, the second and the third bytes are
3616          * '3' and 'D'.
3617          */
3618
3619         /*
3620          * If the mouse is an ordinary PS/2 mouse, the status bytes should
3621          * look like the following.
3622          *
3623          * byte 1 bit 7 always 0
3624          *        bit 6 stream mode (0)
3625          *        bit 5 disabled (0)
3626          *        bit 4 1:1 scaling (0)
3627          *        bit 3 always 0
3628          *        bit 0-2 button status
3629          * byte 2 resolution (PSMD_RES_HIGH)
3630          * byte 3 report rate (?)
3631          */
3632
3633         if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status))
3634                 return (FALSE);
3635         if ((status[1] != '3') || (status[2] != 'D'))
3636                 return (FALSE);
3637         /* FIXME: SmartScroll Mouse has 5 buttons! XXX */
3638         sc->hw.buttons = 4;
3639         return (TRUE);
3640 }
3641
3642 /* Genius NetMouse/NetMouse Pro, ASCII Mie Mouse, NetScroll Optical */
3643 static int
3644 enable_gmouse(struct psm_softc *sc)
3645 {
3646         int status[3];
3647
3648         /*
3649          * The special sequence to enable the middle, "rubber" button.
3650          * Immediately after this sequence check status bytes.
3651          * if the mouse is NetMouse, NetMouse Pro, or ASCII MIE Mouse,
3652          * the second and the third bytes are '3' and 'U'.
3653          * NOTE: NetMouse reports that it has three buttons although it has
3654          * two buttons and a rubber button. NetMouse Pro and MIE Mouse
3655          * say they have three buttons too and they do have a button on the
3656          * side...
3657          */
3658         if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status))
3659                 return (FALSE);
3660         if ((status[1] != '3') || (status[2] != 'U'))
3661                 return (FALSE);
3662         return (TRUE);
3663 }
3664
3665 /* ALPS GlidePoint */
3666 static int
3667 enable_aglide(struct psm_softc *sc)
3668 {
3669         int status[3];
3670
3671         /*
3672          * The special sequence to obtain ALPS GlidePoint specific
3673          * information. Immediately after this sequence, status bytes will
3674          * contain something interesting.
3675          * NOTE: ALPS produces several models of GlidePoint. Some of those
3676          * do not respond to this sequence, thus, cannot be detected this way.
3677          */
3678         if (set_mouse_sampling_rate(sc->kbdc, 100) != 100)
3679                 return (FALSE);
3680         if (!mouse_id_proc1(sc->kbdc, PSMD_RES_LOW, 2, status))
3681                 return (FALSE);
3682         if ((status[1] == PSMD_RES_LOW) || (status[2] == 100))
3683                 return (FALSE);
3684         return (TRUE);
3685 }
3686
3687 /* Kensington ThinkingMouse/Trackball */
3688 static int
3689 enable_kmouse(struct psm_softc *sc)
3690 {
3691         static u_char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 };
3692         KBDC kbdc = sc->kbdc;
3693         int status[3];
3694         int id1;
3695         int id2;
3696         int i;
3697
3698         id1 = get_aux_id(kbdc);
3699         if (set_mouse_sampling_rate(kbdc, 10) != 10)
3700                 return (FALSE);
3701         /*
3702          * The device is now in the native mode? It returns a different
3703          * ID value...
3704          */
3705         id2 = get_aux_id(kbdc);
3706         if ((id1 == id2) || (id2 != 2))
3707                 return (FALSE);
3708
3709         if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)
3710                 return (FALSE);
3711 #if PSM_DEBUG >= 2
3712         /* at this point, resolution is LOW, sampling rate is 10/sec */
3713         if (get_mouse_status(kbdc, status, 0, 3) < 3)
3714                 return (FALSE);
3715 #endif
3716
3717         /*
3718          * The special sequence to enable the third and fourth buttons.
3719          * Otherwise they behave like the first and second buttons.
3720          */
3721         for (i = 0; i < NELEM(rate); ++i)
3722                 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
3723                         return (FALSE);
3724
3725         /*
3726          * At this point, the device is using default resolution and
3727          * sampling rate for the native mode.
3728          */
3729         if (get_mouse_status(kbdc, status, 0, 3) < 3)
3730                 return (FALSE);
3731         if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1]))
3732                 return (FALSE);
3733
3734         /* the device appears be enabled by this sequence, diable it for now */
3735         disable_aux_dev(kbdc);
3736         empty_aux_buffer(kbdc, 5);
3737
3738         return (TRUE);
3739 }
3740
3741 /* Logitech MouseMan+/FirstMouse+, IBM ScrollPoint Mouse */
3742 static int
3743 enable_mmanplus(struct psm_softc *sc)
3744 {
3745         KBDC kbdc = sc->kbdc;
3746         int data[3];
3747
3748         /* the special sequence to enable the fourth button and the roller. */
3749         /*
3750          * NOTE: for ScrollPoint to respond correctly, the SET_RESOLUTION
3751          * must be called exactly three times since the last RESET command
3752          * before this sequence. XXX
3753          */
3754         if (!set_mouse_scaling(kbdc, 1))
3755                 return (FALSE);
3756         if (!mouse_ext_command(kbdc, 0x39) || !mouse_ext_command(kbdc, 0xdb))
3757                 return (FALSE);
3758         if (get_mouse_status(kbdc, data, 1, 3) < 3)
3759                 return (FALSE);
3760
3761         /*
3762          * PS2++ protocl, packet type 0
3763          *
3764          *          b7 b6 b5 b4 b3 b2 b1 b0
3765          * byte 1:  *  1  p3 p2 1  *  *  *
3766          * byte 2:  1  1  p1 p0 m1 m0 1  0
3767          * byte 3:  m7 m6 m5 m4 m3 m2 m1 m0
3768          *
3769          * p3-p0: packet type: 0
3770          * m7-m0: model ID: MouseMan+:0x50,
3771          *                  FirstMouse+:0x51,
3772          *                  ScrollPoint:0x58...
3773          */
3774         /* check constant bits */
3775         if ((data[0] & MOUSE_PS2PLUS_SYNCMASK) != MOUSE_PS2PLUS_SYNC)
3776                 return (FALSE);
3777         if ((data[1] & 0xc3) != 0xc2)
3778                 return (FALSE);
3779         /* check d3-d0 in byte 2 */
3780         if (!MOUSE_PS2PLUS_CHECKBITS(data))
3781                 return (FALSE);
3782         /* check p3-p0 */
3783         if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0)
3784                 return (FALSE);
3785
3786         sc->hw.hwid &= 0x00ff;
3787         sc->hw.hwid |= data[2] << 8;    /* save model ID */
3788
3789         /*
3790          * MouseMan+ (or FirstMouse+) is now in its native mode, in which
3791          * the wheel and the fourth button events are encoded in the
3792          * special data packet. The mouse may be put in the IntelliMouse mode
3793          * if it is initialized by the IntelliMouse's method.
3794          */
3795         return (TRUE);
3796 }
3797
3798 /* MS IntelliMouse Explorer */
3799 static int
3800 enable_msexplorer(struct psm_softc *sc)
3801 {
3802         static u_char rate0[] = { 200, 100, 80, };
3803         static u_char rate1[] = { 200, 200, 80, };
3804         KBDC kbdc = sc->kbdc;
3805         int id;
3806         int i;
3807
3808         /*
3809          * This is needed for at least A4Tech X-7xx mice - they do not go
3810          * straight to Explorer mode, but need to be set to Intelli mode
3811          * first.
3812          */
3813         enable_msintelli(sc);
3814
3815         /* the special sequence to enable the extra buttons and the roller. */
3816         for (i = 0; i < NELEM(rate1); ++i)
3817                 if (set_mouse_sampling_rate(kbdc, rate1[i]) != rate1[i])
3818                         return (FALSE);
3819         /* the device will give the genuine ID only after the above sequence */
3820         id = get_aux_id(kbdc);
3821         if (id != PSM_EXPLORER_ID)
3822                 return (FALSE);
3823
3824         sc->hw.hwid = id;
3825         sc->hw.buttons = 5;             /* IntelliMouse Explorer XXX */
3826
3827         /*
3828          * XXX: this is a kludge to fool some KVM switch products
3829          * which think they are clever enough to know the 4-byte IntelliMouse
3830          * protocol, and assume any other protocols use 3-byte packets.
3831          * They don't convey 4-byte data packets from the IntelliMouse Explorer
3832          * correctly to the host computer because of this!
3833          * The following sequence is actually IntelliMouse's "wake up"
3834          * sequence; it will make the KVM think the mouse is IntelliMouse
3835          * when it is in fact IntelliMouse Explorer.
3836          */
3837         for (i = 0; i < NELEM(rate0); ++i)
3838                 if (set_mouse_sampling_rate(kbdc, rate0[i]) != rate0[i])
3839                         break;
3840         id = get_aux_id(kbdc);
3841
3842         return (TRUE);
3843 }
3844
3845 /* MS IntelliMouse */
3846 static int
3847 enable_msintelli(struct psm_softc *sc)
3848 {
3849         /*
3850          * Logitech MouseMan+ and FirstMouse+ will also respond to this
3851          * probe routine and act like IntelliMouse.
3852          */
3853
3854         static u_char rate[] = { 200, 100, 80, };
3855         KBDC kbdc = sc->kbdc;
3856         int id;
3857         int i;
3858
3859         /* the special sequence to enable the third button and the roller. */
3860         for (i = 0; i < NELEM(rate); ++i)
3861                 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
3862                         return (FALSE);
3863         /* the device will give the genuine ID only after the above sequence */
3864         id = get_aux_id(kbdc);
3865         if (id != PSM_INTELLI_ID)
3866                 return (FALSE);
3867
3868         sc->hw.hwid = id;
3869         sc->hw.buttons = 3;
3870
3871         return (TRUE);
3872 }
3873
3874 /* A4 Tech 4D Mouse */
3875 static int
3876 enable_4dmouse(struct psm_softc *sc)
3877 {
3878         /*
3879          * Newer wheel mice from A4 Tech may use the 4D+ protocol.
3880          */
3881
3882         static u_char rate[] = { 200, 100, 80, 60, 40, 20 };
3883         KBDC kbdc = sc->kbdc;
3884         int id;
3885         int i;
3886
3887         for (i = 0; i < NELEM(rate); ++i)
3888                 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
3889                         return (FALSE);
3890         id = get_aux_id(kbdc);
3891         /*
3892          * WinEasy 4D, 4 Way Scroll 4D: 6
3893          * Cable-Free 4D: 8 (4DPLUS)
3894          * WinBest 4D+, 4 Way Scroll 4D+: 8 (4DPLUS)
3895          */
3896         if (id != PSM_4DMOUSE_ID)
3897                 return (FALSE);
3898
3899         sc->hw.hwid = id;
3900         sc->hw.buttons = 3;             /* XXX some 4D mice have 4? */
3901
3902         return (TRUE);
3903 }
3904
3905 /* A4 Tech 4D+ Mouse */
3906 static int
3907 enable_4dplus(struct psm_softc *sc)
3908 {
3909         /*
3910          * Newer wheel mice from A4 Tech seem to use this protocol.
3911          * Older models are recognized as either 4D Mouse or IntelliMouse.
3912          */
3913         KBDC kbdc = sc->kbdc;
3914         int id;
3915
3916         /*
3917          * enable_4dmouse() already issued the following ID sequence...
3918         static u_char rate[] = { 200, 100, 80, 60, 40, 20 };
3919         int i;
3920
3921         for (i = 0; i < NELEM(rate); ++i)
3922                 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
3923                         return (FALSE);
3924         */
3925
3926         id = get_aux_id(kbdc);
3927         switch (id) {
3928         case PSM_4DPLUS_ID:
3929                 sc->hw.buttons = 4;
3930                 break;
3931         case PSM_4DPLUS_RFSW35_ID:
3932                 sc->hw.buttons = 3;
3933                 break;
3934         default:
3935                 return (FALSE);
3936         }
3937
3938         sc->hw.hwid = id;
3939
3940         return (TRUE);
3941 }
3942
3943 /* Synaptics Touchpad */
3944 static int
3945 synaptics_sysctl(SYSCTL_HANDLER_ARGS)
3946 {
3947         int error, arg;
3948
3949         /* Read the current value. */
3950         arg = *(int *)oidp->oid_arg1;
3951         error = sysctl_handle_int(oidp, &arg, 0, req);
3952
3953         /* Sanity check. */
3954         if (error || !req->newptr)
3955                 return (error);
3956
3957         /*
3958          * Check that the new value is in the concerned node's range
3959          * of values.
3960          */
3961         switch (oidp->oid_arg2) {
3962         case SYNAPTICS_SYSCTL_MIN_PRESSURE:
3963         case SYNAPTICS_SYSCTL_MAX_PRESSURE:
3964                 if (arg < 0 || arg > 255)
3965                         return (EINVAL);
3966                 break;
3967         case SYNAPTICS_SYSCTL_MAX_WIDTH:
3968                 if (arg < 4 || arg > 15)
3969                         return (EINVAL);
3970                 break;
3971         case SYNAPTICS_SYSCTL_MARGIN_TOP:
3972         case SYNAPTICS_SYSCTL_MARGIN_RIGHT:
3973         case SYNAPTICS_SYSCTL_MARGIN_BOTTOM:
3974         case SYNAPTICS_SYSCTL_MARGIN_LEFT:
3975         case SYNAPTICS_SYSCTL_NA_TOP:
3976         case SYNAPTICS_SYSCTL_NA_RIGHT:
3977         case SYNAPTICS_SYSCTL_NA_BOTTOM:
3978         case SYNAPTICS_SYSCTL_NA_LEFT:
3979                 if (arg < 0 || arg > 6143)
3980                         return (EINVAL);
3981                 break;
3982         case SYNAPTICS_SYSCTL_WINDOW_MIN:
3983         case SYNAPTICS_SYSCTL_WINDOW_MAX:
3984         case SYNAPTICS_SYSCTL_TAP_MIN_QUEUE:
3985                 if (arg < 1 || arg > SYNAPTICS_PACKETQUEUE)
3986                         return (EINVAL);
3987                 break;
3988         case SYNAPTICS_SYSCTL_MULTIPLICATOR:
3989         case SYNAPTICS_SYSCTL_WEIGHT_CURRENT:
3990         case SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS:
3991         case SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA:
3992         case SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED:
3993         case SYNAPTICS_SYSCTL_DIV_MIN:
3994         case SYNAPTICS_SYSCTL_DIV_MAX:
3995         case SYNAPTICS_SYSCTL_DIV_MAX_NA:
3996         case SYNAPTICS_SYSCTL_DIV_LEN:
3997         case SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN:
3998         case SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX:
3999                 if (arg < 1)
4000                         return (EINVAL);
4001                 break;
4002         case SYNAPTICS_SYSCTL_TAP_MAX_DELTA:
4003         case SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT:
4004         case SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA:
4005                 if (arg < 0)
4006                         return (EINVAL);
4007                 break;
4008         case SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA:
4009         case SYNAPTICS_SYSCTL_VSCROLL_VER_AREA:
4010                 if (arg < -6143 || arg > 6143)
4011                         return (EINVAL);
4012                 break;
4013         default:
4014                 return (EINVAL);
4015         }
4016
4017         /* Update. */
4018         *(int *)oidp->oid_arg1 = arg;
4019
4020         return (error);
4021 }
4022
4023 static void
4024 synaptics_sysctl_create_tree(struct psm_softc *sc)
4025 {
4026
4027         if (sc->syninfo.sysctl_tree != NULL)
4028                 return;
4029
4030         /* Attach extra synaptics sysctl nodes under hw.psm.synaptics */
4031         sysctl_ctx_init(&sc->syninfo.sysctl_ctx);
4032         sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx,
4033             SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, "synaptics", CTLFLAG_RD,
4034             0, "Synaptics TouchPad");
4035
4036         /* hw.psm.synaptics.directional_scrolls. */
4037         sc->syninfo.directional_scrolls = 1;
4038         SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
4039             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4040             "directional_scrolls", CTLFLAG_RW|CTLFLAG_ANYBODY,
4041             &sc->syninfo.directional_scrolls, 0,
4042             "Enable hardware scrolling pad (if non-zero) or register it as "
4043             "a middle-click (if 0)");
4044
4045         /* hw.psm.synaptics.min_pressure. */
4046         sc->syninfo.min_pressure = 16;
4047         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4048             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4049             "min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4050             &sc->syninfo.min_pressure, SYNAPTICS_SYSCTL_MIN_PRESSURE,
4051             synaptics_sysctl, "I",
4052             "Minimum pressure required to start an action");
4053
4054         /* hw.psm.synaptics.max_pressure. */
4055         sc->syninfo.max_pressure = 220;
4056         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4057             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4058             "max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4059             &sc->syninfo.max_pressure, SYNAPTICS_SYSCTL_MAX_PRESSURE,
4060             synaptics_sysctl, "I",
4061             "Maximum pressure to detect palm");
4062
4063         /* hw.psm.synaptics.max_width. */
4064         sc->syninfo.max_width = 10;
4065         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4066             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4067             "max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4068             &sc->syninfo.max_width, SYNAPTICS_SYSCTL_MAX_WIDTH,
4069             synaptics_sysctl, "I",
4070             "Maximum finger width to detect palm");
4071
4072         /* hw.psm.synaptics.top_margin. */
4073         sc->syninfo.margin_top = 200;
4074         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4075             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4076             "margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4077             &sc->syninfo.margin_top, SYNAPTICS_SYSCTL_MARGIN_TOP,
4078             synaptics_sysctl, "I",
4079             "Top margin");
4080
4081         /* hw.psm.synaptics.right_margin. */
4082         sc->syninfo.margin_right = 200;
4083         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4084             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4085             "margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4086             &sc->syninfo.margin_right, SYNAPTICS_SYSCTL_MARGIN_RIGHT,
4087             synaptics_sysctl, "I",
4088             "Right margin");
4089
4090         /* hw.psm.synaptics.bottom_margin. */
4091         sc->syninfo.margin_bottom = 200;
4092         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4093             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4094             "margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4095             &sc->syninfo.margin_bottom, SYNAPTICS_SYSCTL_MARGIN_BOTTOM,
4096             synaptics_sysctl, "I",
4097             "Bottom margin");
4098
4099         /* hw.psm.synaptics.left_margin. */
4100         sc->syninfo.margin_left = 200;
4101         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4102             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4103             "margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4104             &sc->syninfo.margin_left, SYNAPTICS_SYSCTL_MARGIN_LEFT,
4105             synaptics_sysctl, "I",
4106             "Left margin");
4107
4108         /* hw.psm.synaptics.na_top. */
4109         sc->syninfo.na_top = 1783;
4110         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4111             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4112             "na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4113             &sc->syninfo.na_top, SYNAPTICS_SYSCTL_NA_TOP,
4114             synaptics_sysctl, "I",
4115             "Top noisy area, where weight_previous_na is used instead "
4116             "of weight_previous");
4117
4118         /* hw.psm.synaptics.na_right. */
4119         sc->syninfo.na_right = 563;
4120         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4121             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4122             "na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4123             &sc->syninfo.na_right, SYNAPTICS_SYSCTL_NA_RIGHT,
4124             synaptics_sysctl, "I",
4125             "Right noisy area, where weight_previous_na is used instead "
4126             "of weight_previous");
4127
4128         /* hw.psm.synaptics.na_bottom. */
4129         sc->syninfo.na_bottom = 1408;
4130         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4131             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4132             "na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4133             &sc->syninfo.na_bottom, SYNAPTICS_SYSCTL_NA_BOTTOM,
4134             synaptics_sysctl, "I",
4135             "Bottom noisy area, where weight_previous_na is used instead "
4136             "of weight_previous");
4137
4138         /* hw.psm.synaptics.na_left. */
4139         sc->syninfo.na_left = 1600;
4140         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4141             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4142             "na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4143             &sc->syninfo.na_left, SYNAPTICS_SYSCTL_NA_LEFT,
4144             synaptics_sysctl, "I",
4145             "Left noisy area, where weight_previous_na is used instead "
4146             "of weight_previous");
4147
4148         /* hw.psm.synaptics.window_min. */
4149         sc->syninfo.window_min = 4;
4150         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4151             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4152             "window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4153             &sc->syninfo.window_min, SYNAPTICS_SYSCTL_WINDOW_MIN,
4154             synaptics_sysctl, "I",
4155             "Minimum window size to start an action");
4156
4157         /* hw.psm.synaptics.window_max. */
4158         sc->syninfo.window_max = 10;
4159         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4160             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4161             "window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4162             &sc->syninfo.window_max, SYNAPTICS_SYSCTL_WINDOW_MAX,
4163             synaptics_sysctl, "I",
4164             "Maximum window size");
4165
4166         /* hw.psm.synaptics.multiplicator. */
4167         sc->syninfo.multiplicator = 10000;
4168         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4169             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4170             "multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4171             &sc->syninfo.multiplicator, SYNAPTICS_SYSCTL_MULTIPLICATOR,
4172             synaptics_sysctl, "I",
4173             "Multiplicator to increase precision in averages and divisions");
4174
4175         /* hw.psm.synaptics.weight_current. */
4176         sc->syninfo.weight_current = 3;
4177         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4178             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4179             "weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4180             &sc->syninfo.weight_current, SYNAPTICS_SYSCTL_WEIGHT_CURRENT,
4181             synaptics_sysctl, "I",
4182             "Weight of the current movement in the new average");
4183
4184         /* hw.psm.synaptics.weight_previous. */
4185         sc->syninfo.weight_previous = 6;
4186         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4187             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4188             "weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4189             &sc->syninfo.weight_previous, SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS,
4190             synaptics_sysctl, "I",
4191             "Weight of the previous average");
4192
4193         /* hw.psm.synaptics.weight_previous_na. */
4194         sc->syninfo.weight_previous_na = 20;
4195         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4196             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4197             "weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4198             &sc->syninfo.weight_previous_na,
4199             SYNAPTICS_SYSCTL_WEIGHT_PREVIOUS_NA,
4200             synaptics_sysctl, "I",
4201             "Weight of the previous average (inside the noisy area)");
4202
4203         /* hw.psm.synaptics.weight_len_squared. */
4204         sc->syninfo.weight_len_squared = 2000;
4205         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4206             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4207             "weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4208             &sc->syninfo.weight_len_squared,
4209             SYNAPTICS_SYSCTL_WEIGHT_LEN_SQUARED,
4210             synaptics_sysctl, "I",
4211             "Length (squared) of segments where weight_previous "
4212             "starts to decrease");
4213
4214         /* hw.psm.synaptics.div_min. */
4215         sc->syninfo.div_min = 9;
4216         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4217             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4218             "div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4219             &sc->syninfo.div_min, SYNAPTICS_SYSCTL_DIV_MIN,
4220             synaptics_sysctl, "I",
4221             "Divisor for fast movements");
4222
4223         /* hw.psm.synaptics.div_max. */
4224         sc->syninfo.div_max = 17;
4225         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4226             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4227             "div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4228             &sc->syninfo.div_max, SYNAPTICS_SYSCTL_DIV_MAX,
4229             synaptics_sysctl, "I",
4230             "Divisor for slow movements");
4231
4232         /* hw.psm.synaptics.div_max_na. */
4233         sc->syninfo.div_max_na = 30;
4234         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4235             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4236             "div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4237             &sc->syninfo.div_max_na, SYNAPTICS_SYSCTL_DIV_MAX_NA,
4238             synaptics_sysctl, "I",
4239             "Divisor with slow movements (inside the noisy area)");
4240
4241         /* hw.psm.synaptics.div_len. */
4242         sc->syninfo.div_len = 100;
4243         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4244             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4245             "div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4246             &sc->syninfo.div_len, SYNAPTICS_SYSCTL_DIV_LEN,
4247             synaptics_sysctl, "I",
4248             "Length of segments where div_max starts to decrease");
4249
4250         /* hw.psm.synaptics.tap_max_delta. */
4251         sc->syninfo.tap_max_delta = 80;
4252         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4253             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4254             "tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4255             &sc->syninfo.tap_max_delta, SYNAPTICS_SYSCTL_TAP_MAX_DELTA,
4256             synaptics_sysctl, "I",
4257             "Length of segments above which a tap is ignored");
4258
4259         /* hw.psm.synaptics.tap_min_queue. */
4260         sc->syninfo.tap_min_queue = 2;
4261         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4262             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4263             "tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4264             &sc->syninfo.tap_min_queue, SYNAPTICS_SYSCTL_TAP_MIN_QUEUE,
4265             synaptics_sysctl, "I",
4266             "Number of packets required to consider a tap");
4267
4268         /* hw.psm.synaptics.taphold_timeout. */
4269         sc->synaction.in_taphold = 0;
4270         sc->syninfo.taphold_timeout = tap_timeout;
4271         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4272             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4273             "taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4274             &sc->syninfo.taphold_timeout, SYNAPTICS_SYSCTL_TAPHOLD_TIMEOUT,
4275             synaptics_sysctl, "I",
4276             "Maximum elapsed time between two taps to consider a tap-hold "
4277             "action");
4278
4279         /* hw.psm.synaptics.vscroll_hor_area. */
4280         sc->syninfo.vscroll_hor_area = 0; /* 1300 */
4281         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4282             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4283             "vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4284             &sc->syninfo.vscroll_hor_area, SYNAPTICS_SYSCTL_VSCROLL_HOR_AREA,
4285             synaptics_sysctl, "I",
4286             "Area reserved for horizontal virtual scrolling");
4287
4288         /* hw.psm.synaptics.vscroll_ver_area. */
4289         sc->syninfo.vscroll_ver_area = -600;
4290         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4291             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4292             "vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4293             &sc->syninfo.vscroll_ver_area, SYNAPTICS_SYSCTL_VSCROLL_VER_AREA,
4294             synaptics_sysctl, "I",
4295             "Area reserved for vertical virtual scrolling");
4296
4297         /* hw.psm.synaptics.vscroll_min_delta. */
4298         sc->syninfo.vscroll_min_delta = 50;
4299         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4300             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4301             "vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4302             &sc->syninfo.vscroll_min_delta,
4303             SYNAPTICS_SYSCTL_VSCROLL_MIN_DELTA,
4304             synaptics_sysctl, "I",
4305             "Minimum movement to consider virtual scrolling");
4306
4307         /* hw.psm.synaptics.vscroll_div_min. */
4308         sc->syninfo.vscroll_div_min = 100;
4309         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4310             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4311             "vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4312             &sc->syninfo.vscroll_div_min, SYNAPTICS_SYSCTL_VSCROLL_DIV_MIN,
4313             synaptics_sysctl, "I",
4314             "Divisor for fast scrolling");
4315
4316         /* hw.psm.synaptics.vscroll_div_min. */
4317         sc->syninfo.vscroll_div_max = 150;
4318         SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
4319             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
4320             "vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
4321             &sc->syninfo.vscroll_div_max, SYNAPTICS_SYSCTL_VSCROLL_DIV_MAX,
4322             synaptics_sysctl, "I",
4323             "Divisor for slow scrolling");
4324 }
4325
4326 static int
4327 enable_synaptics(struct psm_softc *sc)
4328 {
4329         int status[3];
4330         KBDC kbdc;
4331
4332         if (!synaptics_support)
4333                 return (FALSE);
4334
4335         kbdc = sc->kbdc;
4336         VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n"));
4337         sc->hw.buttons = 3;
4338         sc->squelch = 0;
4339
4340         /*
4341          * Just to be on the safe side: this avoids troubles with
4342          * following mouse_ext_command() when the previous command
4343          * was PSMC_SET_RESOLUTION. Set Scaling has no effect on
4344          * Synaptics Touchpad behaviour.
4345          */
4346         set_mouse_scaling(kbdc, 1);
4347
4348         /* Identify the Touchpad version. */
4349         if (mouse_ext_command(kbdc, 0) == 0)
4350                 return (FALSE);
4351         if (get_mouse_status(kbdc, status, 0, 3) != 3)
4352                 return (FALSE);
4353         if (status[1] != 0x47)
4354                 return (FALSE);
4355
4356         sc->synhw.infoMinor = status[0];
4357         sc->synhw.infoMajor = status[2] & 0x0f;
4358
4359         if (verbose >= 2)
4360                 kprintf("Synaptics Touchpad v%d.%d\n", sc->synhw.infoMajor,
4361                     sc->synhw.infoMinor);
4362
4363         if (sc->synhw.infoMajor < 4) {
4364                 kprintf("  Unsupported (pre-v4) Touchpad detected\n");
4365                 return (FALSE);
4366         }
4367
4368         /* Get the Touchpad model information. */
4369         if (mouse_ext_command(kbdc, 3) == 0)
4370                 return (FALSE);
4371         if (get_mouse_status(kbdc, status, 0, 3) != 3)
4372                 return (FALSE);
4373         if ((status[1] & 0x01) != 0) {
4374                 kprintf("  Failed to read model information\n");
4375                 return (FALSE);
4376         }
4377
4378         sc->synhw.infoRot180   = (status[0] & 0x80) >> 7;
4379         sc->synhw.infoPortrait = (status[0] & 0x40) >> 6;
4380         sc->synhw.infoSensor   =  status[0] & 0x3f;
4381         sc->synhw.infoHardware = (status[1] & 0xfe) >> 1;
4382         sc->synhw.infoNewAbs   = (status[2] & 0x80) >> 7;
4383         sc->synhw.capPen       = (status[2] & 0x40) >> 6;
4384         sc->synhw.infoSimplC   = (status[2] & 0x20) >> 5;
4385         sc->synhw.infoGeometry =  status[2] & 0x0f;
4386
4387         if (verbose >= 2) {
4388                 kprintf("  Model information:\n");
4389                 kprintf("   infoRot180: %d\n", sc->synhw.infoRot180);
4390                 kprintf("   infoPortrait: %d\n", sc->synhw.infoPortrait);
4391                 kprintf("   infoSensor: %d\n", sc->synhw.infoSensor);
4392                 kprintf("   infoHardware: %d\n", sc->synhw.infoHardware);
4393                 kprintf("   infoNewAbs: %d\n", sc->synhw.infoNewAbs);
4394                 kprintf("   capPen: %d\n", sc->synhw.capPen);
4395                 kprintf("   infoSimplC: %d\n", sc->synhw.infoSimplC);
4396                 kprintf("   infoGeometry: %d\n", sc->synhw.infoGeometry);
4397         }
4398
4399         /* Read the extended capability bits. */
4400         if (mouse_ext_command(kbdc, 2) == 0)
4401                 return (FALSE);
4402         if (get_mouse_status(kbdc, status, 0, 3) != 3)
4403                 return (FALSE);
4404         if (status[1] != 0x47) {
4405                 kprintf("  Failed to read extended capability bits\n");
4406                 return (FALSE);
4407         }
4408
4409         /* Set the different capabilities when they exist. */
4410         if ((status[0] & 0x80) >> 7) {
4411                 sc->synhw.capExtended    = (status[0] & 0x80) >> 7;
4412                 sc->synhw.capPassthrough = (status[2] & 0x80) >> 7;
4413                 sc->synhw.capSleep       = (status[2] & 0x10) >> 4;
4414                 sc->synhw.capFourButtons = (status[2] & 0x08) >> 3;
4415                 sc->synhw.capMultiFinger = (status[2] & 0x02) >> 1;
4416                 sc->synhw.capPalmDetect  = (status[2] & 0x01);
4417
4418                 if (verbose >= 2) {
4419                         kprintf("  Extended capabilities:\n");
4420                         kprintf("   capExtended: %d\n", sc->synhw.capExtended);
4421                         kprintf("   capPassthrough: %d\n",
4422                             sc->synhw.capPassthrough);
4423                         kprintf("   capSleep: %d\n", sc->synhw.capSleep);
4424                         kprintf("   capFourButtons: %d\n",
4425                             sc->synhw.capFourButtons);
4426                         kprintf("   capMultiFinger: %d\n",
4427                             sc->synhw.capMultiFinger);
4428                         kprintf("   capPalmDetect: %d\n",
4429                             sc->synhw.capPalmDetect);
4430                 }
4431
4432                 /*
4433                  * If we have bits set in status[0] & 0x70, then we can load
4434                  * more information about buttons using query 0x09.
4435                  */
4436                 if (status[0] & 0x70) {
4437                         if (mouse_ext_command(kbdc, 0x09) == 0)
4438                                 return (FALSE);
4439                         if (get_mouse_status(kbdc, status, 0, 3) != 3)
4440                                 return (FALSE);
4441                         sc->hw.buttons = ((status[1] & 0xf0) >> 4) + 3;
4442                         if (verbose >= 2)
4443                                 kprintf("  Additional Buttons: %d\n",
4444                                     sc->hw.buttons -3);
4445                 }
4446         } else {
4447                 sc->synhw.capExtended = 0;
4448
4449                 if (verbose >= 2)
4450                         kprintf("  No extended capabilities\n");
4451         }
4452
4453         /*
4454          * Read the mode byte.
4455          *
4456          * XXX: Note the Synaptics documentation also defines the first
4457          * byte of the response to this query to be a constant 0x3b, this
4458          * does not appear to be true for Touchpads with guest devices.
4459          */
4460         if (mouse_ext_command(kbdc, 1) == 0)
4461                 return (FALSE);
4462         if (get_mouse_status(kbdc, status, 0, 3) != 3)
4463                 return (FALSE);
4464         if (status[1] != 0x47) {
4465                 kprintf("  Failed to read mode byte\n");
4466                 return (FALSE);
4467         }
4468
4469         /* Set the mode byte; request wmode where available. */
4470         if (sc->synhw.capExtended)
4471                 mouse_ext_command(kbdc, 0xc1);
4472         else
4473                 mouse_ext_command(kbdc, 0xc0);
4474
4475         /* "Commit" the Set Mode Byte command sent above. */
4476         set_mouse_sampling_rate(kbdc, 20);
4477
4478         /*
4479          * Report the correct number of buttons
4480          *
4481          * XXX: I'm not sure this is used anywhere.
4482          */
4483         if (sc->synhw.capExtended && sc->synhw.capFourButtons)
4484                 sc->hw.buttons = 4;
4485
4486         VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n",
4487             sc->hw.buttons));
4488
4489         /* Create sysctl tree. */
4490         synaptics_sysctl_create_tree(sc);
4491
4492         /*
4493          * The touchpad will have to be reinitialized after
4494          * suspend/resume.
4495          */
4496         sc->config |= PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
4497
4498         return (TRUE);
4499 }
4500
4501 /* Interlink electronics VersaPad */
4502 static int
4503 enable_versapad(struct psm_softc *sc)
4504 {
4505         KBDC kbdc = sc->kbdc;
4506         int data[3];
4507
4508         set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */
4509         set_mouse_sampling_rate(kbdc, 100);             /* set rate 100 */
4510         set_mouse_scaling(kbdc, 1);                     /* set scale 1:1 */
4511         set_mouse_scaling(kbdc, 1);                     /* set scale 1:1 */
4512         set_mouse_scaling(kbdc, 1);                     /* set scale 1:1 */
4513         set_mouse_scaling(kbdc, 1);                     /* set scale 1:1 */
4514         if (get_mouse_status(kbdc, data, 0, 3) < 3)     /* get status */
4515                 return (FALSE);
4516         if (data[2] != 0xa || data[1] != 0 )    /* rate == 0xa && res. == 0 */
4517                 return (FALSE);
4518         set_mouse_scaling(kbdc, 1);                     /* set scale 1:1 */
4519
4520         sc->config |= PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
4521
4522         return (TRUE);                          /* PS/2 absolute mode */
4523 }
4524
4525 /*
4526  * Return true if 'now' is earlier than (start + (secs.usecs)).
4527  * Now may be NULL and the function will fetch the current time from
4528  * getmicrouptime(), or a cached 'now' can be passed in.
4529  * All values should be numbers derived from getmicrouptime().
4530  */
4531 static int
4532 timeelapsed(const struct timeval *start, int secs, int usecs,
4533     const struct timeval *now)
4534 {
4535         struct timeval snow, tv;
4536
4537         /* if there is no 'now' passed in, the get it as a convience. */
4538         if (now == NULL) {
4539                 getmicrouptime(&snow);
4540                 now = &snow;
4541         }
4542
4543         tv.tv_sec = secs;
4544         tv.tv_usec = usecs;
4545         timevaladd(&tv, start);
4546         return (timevalcmp(&tv, now, <));
4547 }
4548
4549 static int
4550 psmresume(device_t dev)
4551 {
4552         struct psm_softc *sc = device_get_softc(dev);
4553         int unit = device_get_unit(dev);
4554         int err;
4555
4556         VLOG(2, (LOG_NOTICE, "psm%d: system resume hook called.\n", unit));
4557
4558         if (!(sc->config & PSM_CONFIG_HOOKRESUME))
4559                 return (0);
4560
4561         err = reinitialize(sc, sc->config & PSM_CONFIG_INITAFTERSUSPEND);
4562
4563         if ((sc->state & PSM_ASLP) && !(sc->state & PSM_VALID)) {
4564                 /*
4565                  * Release the blocked process; it must be notified that
4566                  * the device cannot be accessed anymore.
4567                  */
4568                 sc->state &= ~PSM_ASLP;
4569                 wakeup(sc);
4570         }
4571
4572         VLOG(2, (LOG_DEBUG, "psm%d: system resume hook exiting.\n", unit));
4573
4574         return (err);
4575 }
4576
4577 DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, NULL, NULL);
4578
4579
4580 #if 0
4581 /*
4582  * This sucks up assignments from PNPBIOS and ACPI.
4583  */
4584
4585 /*
4586  * When the PS/2 mouse device is reported by ACPI or PnP BIOS, it may
4587  * appear BEFORE the AT keyboard controller.  As the PS/2 mouse device
4588  * can be probed and attached only after the AT keyboard controller is
4589  * attached, we shall quietly reserve the IRQ resource for later use.
4590  * If the PS/2 mouse device is reported to us AFTER the keyboard controller,
4591  * copy the IRQ resource to the PS/2 mouse device instance hanging
4592  * under the keyboard controller, then probe and attach it.
4593  */
4594
4595 static  devclass_t                      psmcpnp_devclass;
4596
4597 static  device_probe_t                  psmcpnp_probe;
4598 static  device_attach_t                 psmcpnp_attach;
4599
4600 static device_method_t psmcpnp_methods[] = {
4601         DEVMETHOD(device_probe,         psmcpnp_probe),
4602         DEVMETHOD(device_attach,        psmcpnp_attach),
4603
4604         DEVMETHOD_END
4605 };
4606
4607 static driver_t psmcpnp_driver = {
4608         PSMCPNP_DRIVER_NAME,
4609         psmcpnp_methods,
4610         1,                      /* no softc */
4611 };
4612
4613 static struct isa_pnp_id psmcpnp_ids[] = {
4614         { 0x030fd041, "PS/2 mouse port" },              /* PNP0F03 */
4615         { 0x0e0fd041, "PS/2 mouse port" },              /* PNP0F0E */
4616         { 0x120fd041, "PS/2 mouse port" },              /* PNP0F12 */
4617         { 0x130fd041, "PS/2 mouse port" },              /* PNP0F13 */
4618         { 0x1303d041, "PS/2 port" },                    /* PNP0313, XXX */
4619         { 0x02002e4f, "Dell PS/2 mouse port" },         /* Lat. X200, Dell */
4620         { 0x0002a906, "ALPS Glide Point" },             /* ALPS Glide Point */
4621         { 0x80374d24, "IBM PS/2 mouse port" },          /* IBM3780, ThinkPad */
4622         { 0x81374d24, "IBM PS/2 mouse port" },          /* IBM3781, ThinkPad */
4623         { 0x0190d94d, "SONY VAIO PS/2 mouse port"},     /* SNY9001, Vaio */
4624         { 0x0290d94d, "SONY VAIO PS/2 mouse port"},     /* SNY9002, Vaio */
4625         { 0x0390d94d, "SONY VAIO PS/2 mouse port"},     /* SNY9003, Vaio */
4626         { 0x0490d94d, "SONY VAIO PS/2 mouse port"},     /* SNY9004, Vaio */
4627         { 0 }
4628 };
4629
4630 static int
4631 create_a_copy(device_t atkbdc, device_t me)
4632 {
4633         device_t psm;
4634         u_long irq;
4635
4636         /* find the PS/2 mouse device instance under the keyboard controller */
4637         psm = device_find_child(atkbdc, PSM_DRIVER_NAME,
4638             device_get_unit(atkbdc));
4639         if (psm == NULL)
4640                 return (ENXIO);
4641         if (device_get_state(psm) != DS_NOTPRESENT)
4642                 return (0);
4643
4644         /* move our resource to the found device */
4645         irq = bus_get_resource_start(me, SYS_RES_IRQ, 0);
4646         bus_set_resource(psm, SYS_RES_IRQ, KBDC_RID_AUX, irq, 1,
4647             machintr_legacy_intr_cpuid(irq));
4648
4649         /* ...then probe and attach it */
4650         return (device_probe_and_attach(psm));
4651 }
4652
4653 static int
4654 psmcpnp_probe(device_t dev)
4655 {
4656         struct resource *res;
4657         u_long irq;
4658         int rid;
4659
4660         if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids))
4661                 return (ENXIO);
4662
4663         /*
4664          * The PnP BIOS and ACPI are supposed to assign an IRQ (12)
4665          * to the PS/2 mouse device node. But, some buggy PnP BIOS
4666          * declares the PS/2 mouse device node without an IRQ resource!
4667          * If this happens, we shall refer to device hints.
4668          * If we still don't find it there, use a hardcoded value... XXX
4669          */
4670         rid = 0;
4671         irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid);
4672         if (irq <= 0) {
4673                 if (resource_long_value(PSM_DRIVER_NAME,
4674                     device_get_unit(dev),"irq", &irq) != 0)
4675                         irq = 12;       /* XXX */
4676                 device_printf(dev, "irq resource info is missing; "
4677                     "assuming irq %ld\n", irq);
4678                 bus_set_resource(dev, SYS_RES_IRQ, rid, irq, 1,
4679                     machintr_legacy_intr_cpuid(irq));
4680         }
4681         res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE);
4682         bus_release_resource(dev, SYS_RES_IRQ, rid, res);
4683
4684         /* keep quiet */
4685         if (!bootverbose)
4686                 device_quiet(dev);
4687
4688         return ((res == NULL) ? ENXIO : 0);
4689 }
4690
4691 static int
4692 psmcpnp_attach(device_t dev)
4693 {
4694         device_t atkbdc;
4695         int rid;
4696
4697         /* find the keyboard controller, which may be on acpi* or isa* bus */
4698         atkbdc = devclass_get_device(devclass_find(ATKBDC_DRIVER_NAME),
4699             device_get_unit(dev));
4700         if ((atkbdc != NULL) && (device_get_state(atkbdc) == DS_ATTACHED))
4701                 create_a_copy(atkbdc, dev);
4702         else {
4703                 /*
4704                  * If we don't have the AT keyboard controller yet,
4705                  * just reserve the IRQ for later use...
4706                  * (See psmidentify() above.)
4707                  */
4708                 rid = 0;
4709                 bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE);
4710         }
4711
4712         return (0);
4713 }
4714
4715 DRIVER_MODULE(psmcpnp, isa, psmcpnp_driver, psmcpnp_devclass, NULL, NULL);
4716 DRIVER_MODULE(psmcpnp, acpi, psmcpnp_driver, psmcpnp_devclass, NULL, NULL);
4717 #endif