1 /* $NetBSD: pms.c,v 1.28 2009/03/08 15:06:56 ad Exp $ */
4 * Copyright (c) 2004 Kentaro Kurahone.
5 * Copyright (c) 2004 Ales Krenek.
6 * Copyright (c) 1994 Charles M. Hannum.
7 * Copyright (c) 1992, 1993 Erik Forsberg.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: pms.c,v 1.28 2009/03/08 15:06:56 ad Exp $");
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/device.h>
36 #include <sys/ioctl.h>
37 #include <sys/kernel.h>
38 #include <sys/kthread.h>
42 #include <dev/pckbport/pckbportvar.h>
43 #ifdef PMS_SYNAPTICS_TOUCHPAD
44 #include <dev/pckbport/synapticsvar.h>
46 #ifdef PMS_ELANTECH_TOUCHPAD
47 #include <dev/pckbport/elantechvar.h>
50 #include <dev/pckbport/pmsreg.h>
51 #include <dev/pckbport/pmsvar.h>
54 #include <dev/wscons/wsconsio.h>
55 #include <dev/wscons/wsmousevar.h>
59 #define DPRINTF(x) if (pmsdebug) printf x
64 const enum pms_type tries
[] = {
65 PMS_SCROLL5
, PMS_SCROLL3
, PMS_STANDARD
, PMS_UNKNOWN
68 const struct pms_protocol pms_protocols
[] = {
69 { { 0, 0, 0 }, 0, "unknown protocol" },
70 { { 0, 0, 0 }, 0, "no scroll wheel (3 buttons)" },
71 { { 200, 100, 80 }, 3, "scroll wheel (3 buttons)" },
72 { { 200, 200, 80 }, 4, "scroll wheel (5 buttons)" },
73 { { 0, 0, 0 }, 0, "synaptics" },
74 { { 0, 0, 0 }, 0, "elantech" }
78 int pmsprobe(device_t
, cfdata_t
, void *);
79 void pmsattach(device_t
, device_t
, void *);
80 void pmsinput(void *, int);
82 CFATTACH_DECL_NEW(pms
, sizeof(struct pms_softc
),
83 pmsprobe
, pmsattach
, NULL
, NULL
);
85 static int pms_protocol(pckbport_tag_t
, pckbport_slot_t
);
86 static void do_enable(struct pms_softc
*);
87 static void do_disable(struct pms_softc
*);
88 static void pms_reset_thread(void*);
89 int pms_enable(void *);
90 int pms_ioctl(void *, u_long
, void *, int, struct lwp
*);
91 void pms_disable(void *);
93 static bool pms_suspend(device_t
, pmf_qual_t
);
94 static bool pms_resume(device_t
, pmf_qual_t
);
96 const struct wsmouse_accessops pms_accessops
= {
103 pms_protocol(pckbport_tag_t tag
, pckbport_slot_t slot
)
105 u_char cmd
[2], resp
[1];
107 const struct pms_protocol
*p
;
109 for (j
= 0; j
< sizeof(tries
) / sizeof(tries
[0]); ++j
) {
110 p
= &pms_protocols
[tries
[j
]];
113 cmd
[0] = PMS_SET_SAMPLE
;
114 for (i
= 0; i
< 3; i
++) {
115 cmd
[1] = p
->rates
[i
];
116 res
= pckbport_enqueue_cmd(tag
, slot
, cmd
, 2, 0, 1, 0);
121 cmd
[0] = PMS_SEND_DEV_ID
;
122 res
= pckbport_enqueue_cmd(tag
, slot
, cmd
, 1, 1, 1, resp
);
125 if (resp
[0] == p
->response
) {
126 DPRINTF(("pms_protocol: found mouse protocol %d\n",
131 DPRINTF(("pms_protocol: standard PS/2 protocol (no scroll wheel)\n"));
136 pmsprobe(device_t parent
, cfdata_t match
, void *aux
)
138 struct pckbport_attach_args
*pa
= aux
;
139 u_char cmd
[1], resp
[2];
142 if (pa
->pa_slot
!= PCKBPORT_AUX_SLOT
)
145 /* Flush any garbage. */
146 pckbport_flush(pa
->pa_tag
, pa
->pa_slot
);
148 /* reset the device */
150 res
= pckbport_poll_cmd(pa
->pa_tag
, pa
->pa_slot
, cmd
, 1, 2, resp
, 1);
152 aprint_debug("pmsprobe: reset error %d\n", res
);
155 if (resp
[0] != PMS_RSTDONE
) {
156 printf("pmsprobe: reset response 0x%x\n", resp
[0]);
160 /* get type number (0 = mouse) */
162 aprint_debug("pmsprobe: type 0x%x\n", resp
[1]);
170 pmsattach(device_t parent
, device_t self
, void *aux
)
172 struct pms_softc
*sc
= device_private(self
);
173 struct pckbport_attach_args
*pa
= aux
;
174 struct wsmousedev_attach_args a
;
175 u_char cmd
[2], resp
[2];
179 sc
->sc_kbctag
= pa
->pa_tag
;
180 sc
->sc_kbcslot
= pa
->pa_slot
;
185 /* Flush any garbage. */
186 pckbport_flush(pa
->pa_tag
, pa
->pa_slot
);
188 /* reset the device */
190 res
= pckbport_poll_cmd(pa
->pa_tag
, pa
->pa_slot
, cmd
, 1, 2, resp
, 1);
191 if (res
|| resp
[0] != PMS_RSTDONE
|| resp
[1] != 0) {
192 aprint_debug("pmsattach: reset error\n");
197 sc
->protocol
= PMS_UNKNOWN
;
199 #ifdef PMS_SYNAPTICS_TOUCHPAD
200 /* Probe for synaptics touchpad. */
201 if (pms_synaptics_probe_init(sc
) == 0) {
202 sc
->protocol
= PMS_SYNAPTICS
;
205 #ifdef PMS_ELANTECH_TOUCHPAD
206 if (pms_elantech_probe_init(sc
) == 0) {
207 sc
->protocol
= PMS_ELANTECH
;
210 /* Install generic handler. */
211 pckbport_set_inputhandler(sc
->sc_kbctag
, sc
->sc_kbcslot
,
212 pmsinput
, sc
, device_xname(sc
->sc_dev
));
214 a
.accessops
= &pms_accessops
;
218 * Attach the wsmouse, saving a handle to it.
219 * Note that we don't need to check this pointer against NULL
220 * here or in pmsintr, because if this fails pms_enable() will
221 * never be called, so pmsinput() will never be called.
223 sc
->sc_wsmousedev
= config_found_ia(self
, "wsmousedev", &a
, wsmousedevprint
);
225 /* no interrupts until enabled */
226 cmd
[0] = PMS_DEV_DISABLE
;
227 res
= pckbport_poll_cmd(pa
->pa_tag
, pa
->pa_slot
, cmd
, 1, 0, 0, 0);
229 aprint_error("pmsattach: disable error\n");
230 pckbport_slot_enable(sc
->sc_kbctag
, sc
->sc_kbcslot
, 0);
232 kthread_create(PRI_NONE
, 0, NULL
, pms_reset_thread
, sc
,
233 &sc
->sc_event_thread
, device_xname(sc
->sc_dev
));
235 #ifndef PMS_DISABLE_POWERHOOK
236 sc
->sc_suspended
= 0;
238 if (!pmf_device_register(self
, pms_suspend
, pms_resume
))
239 aprint_error_dev(self
, "couldn't establish power handler\n");
243 do_enable(struct pms_softc
*sc
)
251 pckbport_slot_enable(sc
->sc_kbctag
, sc
->sc_kbcslot
, 1);
253 #ifdef PMS_SYNAPTICS_TOUCHPAD
254 if (sc
->protocol
== PMS_SYNAPTICS
)
255 pms_synaptics_enable(sc
);
257 #ifdef PMS_ELANTECH_TOUCHPAD
258 if (sc
->protocol
== PMS_ELANTECH
)
259 pms_elantech_enable(sc
);
262 cmd
[0] = PMS_DEV_ENABLE
;
263 res
= pckbport_enqueue_cmd(sc
->sc_kbctag
, sc
->sc_kbcslot
, cmd
,
266 aprint_error("pms_enable: command error %d\n", res
);
268 if (sc
->protocol
== PMS_UNKNOWN
)
269 sc
->protocol
= pms_protocol(sc
->sc_kbctag
, sc
->sc_kbcslot
);
270 DPRINTF(("pms_enable: using %s protocol\n",
271 pms_protocols
[sc
->protocol
].name
));
276 scmd
[0] = PMS_SET_RES
;
277 scmd
[1] = 3; /* 8 counts/mm */
278 res
= pckbport_enqueue_cmd(sc
->sc_kbctag
, sc
->sc_kbcslot
, scmd
,
281 printf("pms_enable: setup error1 (%d)\n", res
);
283 scmd
[0] = PMS_SET_SCALE21
;
284 res
= pckbport_enqueue_cmd(sc
->sc_kbctag
, sc
->sc_kbcslot
, scmd
,
287 printf("pms_enable: setup error2 (%d)\n", res
);
289 scmd
[0] = PMS_SET_SAMPLE
;
290 scmd
[1] = 100; /* 100 samples/sec */
291 res
= pckbport_enqueue_cmd(sc
->sc_kbctag
, sc
->sc_kbcslot
, scmd
,
294 printf("pms_enable: setup error3 (%d)\n", res
);
300 do_disable(struct pms_softc
*sc
)
305 cmd
[0] = PMS_DEV_DISABLE
;
306 res
= pckbport_enqueue_cmd(sc
->sc_kbctag
, sc
->sc_kbcslot
, cmd
,
309 aprint_error("pms_disable: command error\n");
311 pckbport_slot_enable(sc
->sc_kbctag
, sc
->sc_kbcslot
, 0);
317 struct pms_softc
*sc
= v
;
335 struct pms_softc
*sc
= v
;
346 pms_suspend(device_t dv
, pmf_qual_t qual
)
348 struct pms_softc
*sc
= device_private(dv
);
357 pms_resume(device_t dv
, pmf_qual_t qual
)
359 struct pms_softc
*sc
= device_private(dv
);
361 #ifdef PMS_SYNAPTICS_TOUCHPAD
362 if (sc
->protocol
== PMS_SYNAPTICS
) {
363 pms_synaptics_resume(sc
);
364 if (sc
->sc_enabled
) {
369 #ifdef PMS_ELANTECH_TOUCHPAD
370 if (sc
->protocol
== PMS_ELANTECH
) {
371 pms_elantech_resume(sc
);
372 if (sc
->sc_enabled
) {
377 if (sc
->sc_enabled
) {
378 /* recheck protocol & init mouse */
379 sc
->protocol
= PMS_UNKNOWN
;
380 do_enable(sc
); /* only if we were suspended */
387 pms_ioctl(void *v
, u_long cmd
, void *data
, int flag
,
390 struct pms_softc
*sc
= v
;
395 case WSMOUSEIO_GTYPE
:
396 *(u_int
*)data
= WSMOUSE_TYPE_PS2
;
400 i
= (*(u_int
*)data
- 12) / 25;
408 kbcmd
[0] = PMS_SET_RES
;
410 i
= pckbport_enqueue_cmd(sc
->sc_kbctag
, sc
->sc_kbcslot
, kbcmd
,
414 printf("pms_ioctl: SET_RES command error\n");
424 pms_reset_thread(void *arg
)
426 struct pms_softc
*sc
= arg
;
427 u_char cmd
[1], resp
[2];
432 tsleep(&sc
->sc_enabled
, PWAIT
, "pmsreset", 0);
436 #if defined(PMSDEBUG) || defined(DIAGNOSTIC)
437 aprint_debug_dev(sc
->sc_dev
,
438 "resetting mouse interface\n");
440 save_protocol
= sc
->protocol
;
443 res
= pckbport_enqueue_cmd(sc
->sc_kbctag
, sc
->sc_kbcslot
, cmd
,
446 DPRINTF(("%s: reset error %d\n",
447 device_xname(sc
->sc_dev
), res
));
450 /* For the synaptics and elantech case, leave the protocol alone. */
451 if (sc
->protocol
!= PMS_SYNAPTICS
&& sc
->protocol
!= PMS_ELANTECH
)
452 sc
->protocol
= PMS_UNKNOWN
;
455 if (sc
->protocol
!= save_protocol
) {
456 #if defined(PMSDEBUG) || defined(DIAGNOSTIC)
457 aprint_verbose_dev(sc
->sc_dev
,
458 "protocol change, sleeping and retrying\n");
462 res
= pckbport_enqueue_cmd(sc
->sc_kbctag
,
463 sc
->sc_kbcslot
, cmd
, 1, 2, 1, resp
);
465 DPRINTF(("%s: reset error %d\n",
466 device_xname(sc
->sc_dev
), res
));
468 tsleep(pms_reset_thread
, PWAIT
, "pmsreset", hz
);
470 res
= pckbport_enqueue_cmd(sc
->sc_kbctag
,
471 sc
->sc_kbcslot
, cmd
, 1, 2, 1, resp
);
473 DPRINTF(("%s: reset error %d\n",
474 device_xname(sc
->sc_dev
), res
));
476 sc
->protocol
= PMS_UNKNOWN
; /* reprobe protocol */
478 #if defined(PMSDEBUG) || defined(DIAGNOSTIC)
479 if (sc
->protocol
!= save_protocol
) {
480 printf("%s: protocol changed.\n",
481 device_xname(sc
->sc_dev
));
488 /* Masks for the first byte of a packet */
489 #define PMS_LBUTMASK 0x01
490 #define PMS_RBUTMASK 0x02
491 #define PMS_MBUTMASK 0x04
492 #define PMS_4BUTMASK 0x10
493 #define PMS_5BUTMASK 0x20
496 pmsinput(void *vsc
, int data
)
498 struct pms_softc
*sc
= vsc
;
503 if (!sc
->sc_enabled
) {
504 /* Interrupts are not expected. Discard the byte. */
508 getmicrouptime(&sc
->current
);
510 if (sc
->inputstate
> 0) {
513 timersub(&sc
->current
, &sc
->last
, &diff
);
515 * Empirically, the delay should be about 1700us on a standard
516 * PS/2 port. I have seen delays as large as 4500us (rarely)
517 * in regular use. When using a confused mouse, I generally
518 * see delays at least as large as 30,000us. -seebs
520 * The thinkpad trackball returns at 22-23ms. So we use
521 * >= 40ms. In the future, I'll implement adaptable timeout
522 * by increasing the timeout if the mouse reset happens
523 * too frequently -christos
525 if (diff
.tv_sec
> 0 || diff
.tv_usec
>= 40000) {
526 DPRINTF(("pms_input: unusual delay (%ld.%06ld s), "
527 "scheduling reset\n",
528 (long)diff
.tv_sec
, (long)diff
.tv_usec
));
531 wakeup(&sc
->sc_enabled
);
535 sc
->last
= sc
->current
;
537 if (sc
->inputstate
== 0) {
539 * Some devices (seen on trackballs anytime, and on
540 * some mice shortly after reset) output garbage bytes
541 * between packets. Just ignore them.
543 if ((data
& 0xc0) != 0)
544 return; /* not in sync yet, discard input */
547 sc
->packet
[sc
->inputstate
++] = data
& 0xff;
548 switch (sc
->inputstate
) {
550 /* no useful processing can be done yet */
555 * Why should we test for bit 0x8 and insist on it here?
556 * The old (psm.c and psm_intelli.c) drivers didn't do
557 * it, and there are devices where it does harm (that's
558 * why it is not used if using PMS_STANDARD protocol).
559 * Anyway, it does not to cause any harm to accept packets
563 if (sc
->protocol
== PMS_STANDARD
)
565 if (!(sc
->packet
[0] & 0x8)) {
566 DPRINTF(("pmsinput: 0x8 not set in first byte "
567 "[0x%02x], resetting\n", sc
->packet
[0]));
570 wakeup(&sc
->sc_enabled
);
580 /* Case 4 is a superset of case 3. This is *not* an accident. */
581 if (sc
->protocol
== PMS_SCROLL3
) {
587 } else if (sc
->protocol
== PMS_SCROLL5
) {
588 dz
= sc
->packet
[3] & 0xf;
591 if (sc
->packet
[3] & PMS_4BUTMASK
)
593 if (sc
->packet
[3] & PMS_5BUTMASK
)
596 DPRINTF(("pmsinput: why am I looking at this byte?\n"));
602 * This is only an endpoint for scroll protocols with 4
603 * bytes, or the standard protocol with 3.
605 if (sc
->protocol
!= PMS_STANDARD
&& sc
->inputstate
== 3)
608 newbuttons
|= ((sc
->packet
[0] & PMS_LBUTMASK
) ? 0x1 : 0) |
609 ((sc
->packet
[0] & PMS_MBUTMASK
) ? 0x2 : 0) |
610 ((sc
->packet
[0] & PMS_RBUTMASK
) ? 0x4 : 0);
625 changed
= (sc
->buttons
^ newbuttons
);
626 sc
->buttons
= newbuttons
;
629 if (sc
->protocol
== PMS_STANDARD
) {
630 DPRINTF(("pms: packet: 0x%02x%02x%02x\n",
631 sc
->packet
[0], sc
->packet
[1], sc
->packet
[2]));
633 DPRINTF(("pms: packet: 0x%02x%02x%02x%02x\n",
634 sc
->packet
[0], sc
->packet
[1], sc
->packet
[2],
638 if (dx
|| dy
|| dz
|| changed
) {
640 DPRINTF(("pms: x %+03d y %+03d z %+03d "
641 "buttons 0x%02x\n", dx
, dy
, dz
, sc
->buttons
));
643 wsmouse_input(sc
->sc_wsmousedev
,
644 sc
->buttons
, dx
, dy
, dz
, 0,
645 WSMOUSE_INPUT_DELTA
);
647 memset(sc
->packet
, 0, 4);
650 /* If we get here, we have problems. */
652 printf("pmsinput: very confused. resetting.\n");
655 wakeup(&sc
->sc_enabled
);