1 /* $NetBSD: zkbd.c,v 1.9 2009/01/29 16:00:33 nonaka Exp $ */
2 /* $OpenBSD: zaurus_kbd.c,v 1.28 2005/12/21 20:36:03 deraadt Exp $ */
5 * Copyright (c) 2005 Dale Rahn <drahn@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: zkbd.c,v 1.9 2009/01/29 16:00:33 nonaka Exp $");
23 #include "opt_wsdisplay_compat.h"
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/device.h>
32 #include <sys/malloc.h>
33 #include <sys/kernel.h>
35 #include <sys/signalvar.h>
36 #include <sys/callout.h>
38 #include <arm/xscale/pxa2x0reg.h>
39 #include <arm/xscale/pxa2x0_gpio.h>
41 #include <dev/wscons/wsconsio.h>
42 #include <dev/wscons/wskbdvar.h>
43 #include <dev/wscons/wsksymdef.h>
44 #include <dev/wscons/wsksymvar.h>
46 #include <zaurus/dev/zkbdmap.h>
47 #include <zaurus/zaurus/zaurus_var.h>
49 static const int gpio_sense_pins_c3000
[] = {
60 static const int gpio_strobe_pins_c3000
[] = {
75 static const int stuck_keys
[] = {
82 #define REP_DELAY1 400
83 #define REP_DELAYN 100
88 const int *sc_sense_array
;
89 const int *sc_strobe_array
;
99 char sc_hinge
; /* 0=open, 1=nonsense, 2=backwards, 3=closed */
102 struct callout sc_roll_to
;
110 struct device
*sc_wskbddev
;
112 #ifdef WSDISPLAY_COMPAT_RAWKBD
113 const char *sc_xt_keymap
;
114 struct callout sc_rawrepeat_ch
;
116 char sc_rep
[MAXKEYS
];
121 static struct zkbd_softc
*zkbd_sc
;
123 static int zkbd_match(device_t
, cfdata_t
, void *);
124 static void zkbd_attach(device_t
, device_t
, void *);
126 CFATTACH_DECL_NEW(zkbd
, sizeof(struct zkbd_softc
),
127 zkbd_match
, zkbd_attach
, NULL
, NULL
);
129 static int zkbd_irq(void *v
);
130 static void zkbd_poll(void *v
);
131 static int zkbd_on(void *v
);
132 static int zkbd_sync(void *v
);
133 static int zkbd_hinge(void *v
);
134 static bool zkbd_resume(device_t dv
, pmf_qual_t
);
138 static int zkbd_enable(void *, int);
139 static void zkbd_set_leds(void *, int);
140 static int zkbd_ioctl(void *, u_long
, void *, int, struct lwp
*);
141 #ifdef WSDISPLAY_COMPAT_RAWKBD
142 static void zkbd_rawrepeat(void *v
);
145 static struct wskbd_accessops zkbd_accessops
= {
151 static void zkbd_cngetc(void *, u_int
*, int *);
152 static void zkbd_cnpollc(void *, int);
154 static struct wskbd_consops zkbd_consops
= {
159 static struct wskbd_mapdata zkbd_keymapdata
= {
165 zkbd_match(device_t parent
, cfdata_t cf
, void *aux
)
175 zkbd_attach(device_t parent
, device_t self
, void *aux
)
177 struct zkbd_softc
*sc
= device_private(self
);
178 struct wskbddev_attach_args a
;
188 #ifdef WSDISPLAY_COMPAT_RAWKBD
192 callout_init(&sc
->sc_roll_to
, 0);
193 callout_setfunc(&sc
->sc_roll_to
, zkbd_poll
, sc
);
194 #ifdef WSDISPLAY_COMPAT_RAWKBD
195 callout_init(&sc
->sc_rawrepeat_ch
, 0);
196 callout_setfunc(&sc
->sc_rawrepeat_ch
, zkbd_rawrepeat
, sc
);
199 if (ZAURUS_ISC3000
) {
200 sc
->sc_sense_array
= gpio_sense_pins_c3000
;
201 sc
->sc_strobe_array
= gpio_strobe_pins_c3000
;
202 sc
->sc_nsense
= __arraycount(gpio_sense_pins_c3000
);
203 sc
->sc_nstrobe
= __arraycount(gpio_strobe_pins_c3000
);
204 sc
->sc_maxkbdcol
= 10;
205 sc
->sc_onkey_pin
= 95;
206 sc
->sc_sync_pin
= 16;
209 #ifdef WSDISPLAY_COMPAT_RAWKBD
210 sc
->sc_xt_keymap
= xt_keymap
;
217 if (!pmf_device_register(sc
->sc_dev
, NULL
, zkbd_resume
))
218 aprint_error_dev(sc
->sc_dev
,
219 "couldn't establish power handler\n");
221 sc
->sc_okeystate
= malloc(sc
->sc_nsense
* sc
->sc_nstrobe
,
223 memset(sc
->sc_okeystate
, 0, sc
->sc_nsense
* sc
->sc_nstrobe
);
225 sc
->sc_keystate
= malloc(sc
->sc_nsense
* sc
->sc_nstrobe
,
227 memset(sc
->sc_keystate
, 0, sc
->sc_nsense
* sc
->sc_nstrobe
);
229 /* set all the strobe bits */
230 for (i
= 0; i
< sc
->sc_nstrobe
; i
++) {
231 pin
= sc
->sc_strobe_array
[i
];
234 pxa2x0_gpio_set_function(pin
, GPIO_SET
|GPIO_OUT
);
237 /* set all the sense bits */
238 for (i
= 0; i
< sc
->sc_nsense
; i
++) {
239 pin
= sc
->sc_sense_array
[i
];
242 pxa2x0_gpio_set_function(pin
, GPIO_IN
);
243 pxa2x0_gpio_intr_establish(pin
, IST_EDGE_BOTH
, IPL_TTY
,
247 pxa2x0_gpio_intr_establish(sc
->sc_onkey_pin
, IST_EDGE_BOTH
, IPL_TTY
,
249 pxa2x0_gpio_intr_establish(sc
->sc_sync_pin
, IST_EDGE_RISING
, IPL_TTY
,
251 pxa2x0_gpio_intr_establish(sc
->sc_swa_pin
, IST_EDGE_BOTH
, IPL_TTY
,
253 pxa2x0_gpio_intr_establish(sc
->sc_swb_pin
, IST_EDGE_BOTH
, IPL_TTY
,
257 wskbd_cnattach(&zkbd_consops
, sc
, &zkbd_keymapdata
);
262 a
.keymap
= &zkbd_keymapdata
;
263 a
.accessops
= &zkbd_accessops
;
266 zkbd_hinge(sc
); /* to initialize sc_hinge */
268 sc
->sc_wskbddev
= config_found(self
, &a
, wskbddevprint
);
271 #ifdef WSDISPLAY_COMPAT_RAWKBD
273 zkbd_rawrepeat(void *v
)
275 struct zkbd_softc
*sc
= (struct zkbd_softc
*)v
;
279 wskbd_rawinput(sc
->sc_wskbddev
, sc
->sc_rep
, sc
->sc_nrep
);
281 callout_schedule(&sc
->sc_rawrepeat_ch
, hz
* REP_DELAYN
/ 1000);
285 /* XXX only deal with keys that can be pressed when display is open? */
286 /* XXX are some not in the array? */
287 /* handle keypress interrupt */
300 struct zkbd_softc
*sc
= (struct zkbd_softc
*)v
;
301 int i
, j
, col
, pin
, type
, keysdown
= 0;
305 #ifdef WSDISPLAY_COMPAT_RAWKBD
306 int npress
= 0, ncbuf
= 0, c
;
307 char cbuf
[MAXKEYS
* 2];
313 for (i
= 0; i
< sc
->sc_nstrobe
; i
++) {
314 pin
= sc
->sc_strobe_array
[i
];
317 pxa2x0_gpio_clear_bit(pin
);
318 pxa2x0_gpio_set_dir(pin
, GPIO_IN
);
322 for (col
= 0; col
< sc
->sc_nstrobe
; col
++) {
323 pin
= sc
->sc_strobe_array
[col
];
328 pxa2x0_gpio_set_bit(pin
);
329 pxa2x0_gpio_set_dir(pin
, GPIO_OUT
);
331 /* wait activate delay */
335 for (i
= 0; i
< sc
->sc_nsense
; i
++) {
338 if (sc
->sc_sense_array
[i
] == -1)
340 bit
= pxa2x0_gpio_get_bit(sc
->sc_sense_array
[i
]);
341 if (bit
&& sc
->sc_hinge
&& col
< sc
->sc_maxkbdcol
)
343 sc
->sc_keystate
[i
+ (col
* sc
->sc_nsense
)] = bit
;
347 pxa2x0_gpio_set_dir(pin
, GPIO_IN
);
349 /* wait discharge delay */
354 for (i
= 0; i
< sc
->sc_nstrobe
; i
++) {
355 pin
= sc
->sc_strobe_array
[i
];
358 pxa2x0_gpio_set_bit(pin
);
359 pxa2x0_gpio_set_dir(pin
, GPIO_OUT
);
362 /* force the irqs to clear as we have just played with them. */
363 for (i
= 0; i
< sc
->sc_nsense
; i
++) {
364 pin
= sc
->sc_sense_array
[i
];
367 pxa2x0_gpio_clear_intr(pin
);
370 /* process after resetting interrupt */
372 (sc
->sc_keystate
[84] ? (1 << 0) : 0) | /* shift */
373 (sc
->sc_keystate
[93] ? (1 << 1) : 0) | /* Fn */
374 (sc
->sc_keystate
[14] ? (1 << 2) : 0)); /* 'alt' */
376 for (i
= 0; i
< sc
->sc_nsense
* sc
->sc_nstrobe
; i
++) {
378 /* extend xt_keymap to do this faster. */
379 /* ignore 'stuck' keys' */
380 for (j
= 0; j
< __arraycount(stuck_keys
); j
++) {
381 if (stuck_keys
[j
] == i
) {
389 keystate
= sc
->sc_keystate
[i
];
390 keysdown
|= keystate
; /* if any keys held */
392 #ifdef WSDISPLAY_COMPAT_RAWKBD
393 if (sc
->sc_polling
== 0 && sc
->sc_rawkbd
) {
394 if ((keystate
) || (sc
->sc_okeystate
[i
] != keystate
)) {
395 c
= sc
->sc_xt_keymap
[i
];
397 cbuf
[ncbuf
++] = 0xe0;
399 cbuf
[ncbuf
] = c
& 0x7f;
403 sc
->sc_rep
[npress
++] = 0xe0;
405 sc
->sc_rep
[npress
++] = c
& 0x7f;
410 sc
->sc_okeystate
[i
] = keystate
;
415 if ((!sc
->sc_rawkbd
) && (sc
->sc_okeystate
[i
] != keystate
)) {
416 type
= keystate
? WSCONS_EVENT_KEY_DOWN
:
419 if (sc
->sc_polling
) {
421 sc
->sc_pollUD
= type
;
423 wskbd_input(sc
->sc_wskbddev
, type
, i
);
426 sc
->sc_okeystate
[i
] = keystate
;
430 #ifdef WSDISPLAY_COMPAT_RAWKBD
431 if (sc
->sc_polling
== 0 && sc
->sc_rawkbd
) {
432 wskbd_rawinput(sc
->sc_wskbddev
, cbuf
, ncbuf
);
433 sc
->sc_nrep
= npress
;
435 callout_schedule(&sc
->sc_rawrepeat_ch
,
436 hz
* REP_DELAY1
/ 1000);
438 callout_stop(&sc
->sc_rawrepeat_ch
);
442 callout_schedule(&sc
->sc_roll_to
, hz
* REP_DELAYN
/ 1000 / 2);
444 callout_stop(&sc
->sc_roll_to
); /* always cancel? */
450 extern int kbd_reset
;
451 extern int apm_suspends
;
452 static int zkbdondown
; /* on key is pressed */
453 static struct timeval zkbdontv
= { 0, 0 }; /* last on key event */
454 const struct timeval zkbdhalttv
= { 3, 0 }; /* 3s for safe shutdown */
455 const struct timeval zkbdsleeptv
= { 0, 250000 }; /* .25s for suspend */
456 extern int lid_suspend
;
463 struct zkbd_softc
*sc
= (struct zkbd_softc
*)v
;
464 int down
= pxa2x0_gpio_get_bit(sc
->sc_onkey_pin
) ? 1 : 0;
467 * Change run mode depending on how long the key is held down.
468 * Ignore the key if it gets pressed while the lid is closed.
470 * Keys can bounce and we have to work around missed interrupts.
471 * Only the second edge is detected upon exit from sleep mode.
474 if (sc
->sc_hinge
== 3) {
477 microuptime(&zkbdontv
);
480 } else if (zkbdondown
) {
481 if (ratecheck(&zkbdontv
, &zkbdhalttv
)) {
482 if (kbd_reset
== 1) {
484 psignal(initproc
, SIGUSR1
);
486 } else if (ratecheck(&zkbdontv
, &zkbdsleeptv
)) {
505 struct zkbd_softc
*sc
= (struct zkbd_softc
*)v
;
506 int a
= pxa2x0_gpio_get_bit(sc
->sc_swa_pin
) ? 1 : 0;
507 int b
= pxa2x0_gpio_get_bit(sc
->sc_swb_pin
) ? 2 : 0;
509 extern void lcd_blank(int);
512 sc
->sc_hinge
= a
| b
;
514 if (sc
->sc_hinge
== 3) {
532 zkbd_enable(void *v
, int on
)
539 zkbd_set_leds(void *v
, int on
)
544 zkbd_ioctl(void *v
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
546 #ifdef WSDISPLAY_COMPAT_RAWKBD
547 struct zkbd_softc
*sc
= (struct zkbd_softc
*)v
;
552 *(int *)data
= WSKBD_TYPE_ZAURUS
;
555 case WSKBDIO_SETLEDS
:
558 case WSKBDIO_GETLEDS
:
562 #ifdef WSDISPLAY_COMPAT_RAWKBD
563 case WSKBDIO_SETMODE
:
564 sc
->sc_rawkbd
= *(int *)data
== WSKBD_RAW
;
565 callout_stop(&sc
->sc_rawrepeat_ch
);
573 /* implement polling for zaurus_kbd */
575 zkbd_cngetc(void *v
, u_int
*type
, int *data
)
577 struct zkbd_softc
*sc
= (struct zkbd_softc
*)zkbd_sc
;
582 while (sc
->sc_pollkey
== -1) {
584 DELAY(10000); /* XXX */
587 *data
= sc
->sc_pollkey
;
588 *type
= sc
->sc_pollUD
;
592 zkbd_cnpollc(void *v
, int on
)
597 zkbd_resume(device_t dv
, pmf_qual_t qual
)
599 struct zkbd_softc
*sc
= device_private(dv
);