Home | History | Annotate | Line # | Download | only in dev
zkbd.c revision 1.1
      1  1.1  ober /*	$NetBSD: zkbd.c,v 1.1 2006/12/16 05:22:02 ober Exp $	*/
      2  1.1  ober /* $OpenBSD: zaurus_kbd.c,v 1.28 2005/12/21 20:36:03 deraadt Exp $ */
      3  1.1  ober 
      4  1.1  ober /*
      5  1.1  ober  * Copyright (c) 2005 Dale Rahn <drahn (at) openbsd.org>
      6  1.1  ober  *
      7  1.1  ober  * Permission to use, copy, modify, and distribute this software for any
      8  1.1  ober  * purpose with or without fee is hereby granted, provided that the above
      9  1.1  ober  * copyright notice and this permission notice appear in all copies.
     10  1.1  ober  *
     11  1.1  ober  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12  1.1  ober  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13  1.1  ober  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14  1.1  ober  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15  1.1  ober  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16  1.1  ober  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17  1.1  ober  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  1.1  ober  */
     19  1.1  ober 
     20  1.1  ober #include <sys/cdefs.h>
     21  1.1  ober __KERNEL_RCSID(0, "$NetBSD: zkbd.c,v 1.1 2006/12/16 05:22:02 ober Exp $");
     22  1.1  ober 
     23  1.1  ober #include "opt_wsdisplay_compat.h"
     24  1.1  ober #include "lcd.h"
     25  1.1  ober #if 0	/* XXX */
     26  1.1  ober #include "apm.h"
     27  1.1  ober #endif
     28  1.1  ober 
     29  1.1  ober #include <sys/param.h>
     30  1.1  ober #include <sys/systm.h>
     31  1.1  ober #include <sys/device.h>
     32  1.1  ober #include <sys/malloc.h>
     33  1.1  ober #include <sys/kernel.h>
     34  1.1  ober #include <sys/proc.h>
     35  1.1  ober #include <sys/signalvar.h>
     36  1.1  ober #include <sys/callout.h>
     37  1.1  ober 
     38  1.1  ober #include <arm/xscale/pxa2x0reg.h>
     39  1.1  ober #include <arm/xscale/pxa2x0_gpio.h>
     40  1.1  ober 
     41  1.1  ober #include <dev/wscons/wsconsio.h>
     42  1.1  ober #include <dev/wscons/wskbdvar.h>
     43  1.1  ober #include <dev/wscons/wsksymdef.h>
     44  1.1  ober #include <dev/wscons/wsksymvar.h>
     45  1.1  ober 
     46  1.1  ober #include <zaurus/dev/zkbdmap.h>
     47  1.1  ober #include <zaurus/zaurus/zaurus_var.h>
     48  1.1  ober 
     49  1.1  ober static const int gpio_sense_pins_c3000[] = {
     50  1.1  ober 	12,
     51  1.1  ober 	17,
     52  1.1  ober 	91,
     53  1.1  ober 	34,
     54  1.1  ober 	36,
     55  1.1  ober 	38,
     56  1.1  ober 	39,
     57  1.1  ober 	-1
     58  1.1  ober };
     59  1.1  ober 
     60  1.1  ober static const int gpio_strobe_pins_c3000[] = {
     61  1.1  ober 	88,
     62  1.1  ober 	23,
     63  1.1  ober 	24,
     64  1.1  ober 	25,
     65  1.1  ober 	26,
     66  1.1  ober 	27,
     67  1.1  ober 	52,
     68  1.1  ober 	103,
     69  1.1  ober 	107,
     70  1.1  ober 	-1,
     71  1.1  ober 	108,
     72  1.1  ober 	114
     73  1.1  ober };
     74  1.1  ober 
     75  1.1  ober static const int stuck_keys[] = {
     76  1.1  ober 	7,
     77  1.1  ober 	15,
     78  1.1  ober 	23,
     79  1.1  ober 	31
     80  1.1  ober };
     81  1.1  ober 
     82  1.1  ober 
     83  1.1  ober #define REP_DELAY1 400
     84  1.1  ober #define REP_DELAYN 100
     85  1.1  ober 
     86  1.1  ober struct zkbd_softc {
     87  1.1  ober 	struct device sc_dev;
     88  1.1  ober 
     89  1.1  ober 	const int *sc_sense_array;
     90  1.1  ober 	const int *sc_strobe_array;
     91  1.1  ober 	int sc_nsense;
     92  1.1  ober 	int sc_nstrobe;
     93  1.1  ober 
     94  1.1  ober 	short sc_onkey_pin;
     95  1.1  ober 	short sc_sync_pin;
     96  1.1  ober 	short sc_swa_pin;
     97  1.1  ober 	short sc_swb_pin;
     98  1.1  ober 	char *sc_okeystate;
     99  1.1  ober 	char *sc_keystate;
    100  1.1  ober 	char sc_hinge;		/* 0=open, 1=nonsense, 2=backwards, 3=closed */
    101  1.1  ober 	char sc_maxkbdcol;
    102  1.1  ober 
    103  1.1  ober 	struct callout sc_roll_to;
    104  1.1  ober 
    105  1.1  ober 	/* console stuff */
    106  1.1  ober 	int sc_polling;
    107  1.1  ober 	int sc_pollUD;
    108  1.1  ober 	int sc_pollkey;
    109  1.1  ober 
    110  1.1  ober 	/* wskbd bits */
    111  1.1  ober 	struct device   *sc_wskbddev;
    112  1.1  ober 	int sc_rawkbd;
    113  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    114  1.1  ober 	const char *sc_xt_keymap;
    115  1.1  ober 	struct callout sc_rawrepeat_ch;
    116  1.1  ober #define MAXKEYS 20
    117  1.1  ober 	char sc_rep[MAXKEYS];
    118  1.1  ober 	int sc_nrep;
    119  1.1  ober #endif
    120  1.1  ober 	void *sc_powerhook;
    121  1.1  ober };
    122  1.1  ober 
    123  1.1  ober struct zkbd_softc *zkbd_dev; /* XXX */
    124  1.1  ober 
    125  1.1  ober static int	zkbd_match(struct device *, struct cfdata *, void *);
    126  1.1  ober static void	zkbd_attach(struct device *, struct device *, void *);
    127  1.1  ober 
    128  1.1  ober CFATTACH_DECL(zkbd, sizeof(struct zkbd_softc),
    129  1.1  ober 	zkbd_match, zkbd_attach, NULL, NULL);
    130  1.1  ober 
    131  1.1  ober static int	zkbd_irq(void *v);
    132  1.1  ober static void	zkbd_poll(void *v);
    133  1.1  ober static int	zkbd_on(void *v);
    134  1.1  ober static int	zkbd_sync(void *v);
    135  1.1  ober static int	zkbd_hinge(void *v);
    136  1.1  ober static void	zkbd_power(int why, void *arg);
    137  1.1  ober 
    138  1.1  ober int zkbd_modstate;
    139  1.1  ober 
    140  1.1  ober static int	zkbd_enable(void *, int);
    141  1.1  ober static void	zkbd_set_leds(void *, int);
    142  1.1  ober static int	zkbd_ioctl(void *, u_long, caddr_t, int, struct lwp *);
    143  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    144  1.1  ober static void	zkbd_rawrepeat(void *v);
    145  1.1  ober #endif
    146  1.1  ober 
    147  1.1  ober struct wskbd_accessops zkbd_accessops = {
    148  1.1  ober 	zkbd_enable,
    149  1.1  ober 	zkbd_set_leds,
    150  1.1  ober 	zkbd_ioctl,
    151  1.1  ober };
    152  1.1  ober 
    153  1.1  ober static void	zkbd_cngetc(void *, u_int *, int *);
    154  1.1  ober static void	zkbd_cnpollc(void *, int);
    155  1.1  ober 
    156  1.1  ober struct wskbd_consops zkbd_consops = {
    157  1.1  ober 	zkbd_cngetc,
    158  1.1  ober 	zkbd_cnpollc,
    159  1.1  ober };
    160  1.1  ober 
    161  1.1  ober struct wskbd_mapdata zkbd_keymapdata = {
    162  1.1  ober 	zkbd_keydesctab,
    163  1.1  ober 	KB_US,
    164  1.1  ober };
    165  1.1  ober 
    166  1.1  ober static int
    167  1.1  ober zkbd_match(struct device *parent, struct cfdata *cf, void *aux)
    168  1.1  ober {
    169  1.1  ober 
    170  1.1  ober 	return 1;
    171  1.1  ober }
    172  1.1  ober 
    173  1.1  ober static void
    174  1.1  ober zkbd_attach(struct device *parent, struct device *self, void *aux)
    175  1.1  ober {
    176  1.1  ober 	struct zkbd_softc *sc = (struct zkbd_softc *)self;
    177  1.1  ober 	struct wskbddev_attach_args a;
    178  1.1  ober 	int pin, i;
    179  1.1  ober 
    180  1.1  ober 	zkbd_dev = sc;
    181  1.1  ober 	sc->sc_polling = 0;
    182  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    183  1.1  ober 	sc->sc_rawkbd = 0;
    184  1.1  ober #endif
    185  1.1  ober 	/* Determine which system we are - XXX */
    186  1.1  ober 
    187  1.1  ober 	sc->sc_powerhook = powerhook_establish(sc->sc_dev.dv_xname,
    188  1.1  ober 	    zkbd_power, sc);
    189  1.1  ober 	if (sc->sc_powerhook == NULL) {
    190  1.1  ober 		printf(": unable to establish powerhook\n");
    191  1.1  ober 		return;
    192  1.1  ober 	}
    193  1.1  ober 
    194  1.1  ober 	if (1 /* C3000 */) {
    195  1.1  ober 		sc->sc_sense_array = gpio_sense_pins_c3000;
    196  1.1  ober 		sc->sc_strobe_array = gpio_strobe_pins_c3000;
    197  1.1  ober 		sc->sc_nsense = sizeof(gpio_sense_pins_c3000)/sizeof(int);
    198  1.1  ober 		sc->sc_nstrobe = sizeof(gpio_strobe_pins_c3000)/sizeof(int);
    199  1.1  ober 		sc->sc_maxkbdcol = 10;
    200  1.1  ober 		sc->sc_onkey_pin = 95;
    201  1.1  ober 		sc->sc_sync_pin = 16;
    202  1.1  ober 		sc->sc_swa_pin = 97;
    203  1.1  ober 		sc->sc_swb_pin = 96;
    204  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    205  1.1  ober 		sc->sc_xt_keymap = xt_keymap;
    206  1.1  ober #endif
    207  1.1  ober 	} /* XXX */
    208  1.1  ober 
    209  1.1  ober 	sc->sc_okeystate = malloc(sc->sc_nsense * sc->sc_nstrobe,
    210  1.1  ober 	    M_DEVBUF, M_NOWAIT);
    211  1.1  ober 	memset(sc->sc_okeystate, 0, (sc->sc_nsense * sc->sc_nstrobe));
    212  1.1  ober 
    213  1.1  ober 	sc->sc_keystate = malloc(sc->sc_nsense * sc->sc_nstrobe,
    214  1.1  ober 	    M_DEVBUF, M_NOWAIT);
    215  1.1  ober 	memset(sc->sc_keystate, 0, (sc->sc_nsense * sc->sc_nstrobe));
    216  1.1  ober 
    217  1.1  ober 	/* set all the strobe bits */
    218  1.1  ober 	for (i = 0; i < sc->sc_nstrobe; i++) {
    219  1.1  ober 		pin = sc->sc_strobe_array[i];
    220  1.1  ober 		if (pin == -1) {
    221  1.1  ober 			continue;
    222  1.1  ober 		}
    223  1.1  ober 		pxa2x0_gpio_set_function(pin, GPIO_SET|GPIO_OUT);
    224  1.1  ober 	}
    225  1.1  ober 	/* set all the sense bits */
    226  1.1  ober 	for (i = 0; i < sc->sc_nsense; i++) {
    227  1.1  ober 		pin = sc->sc_sense_array[i];
    228  1.1  ober 		if (pin == -1) {
    229  1.1  ober 			continue;
    230  1.1  ober 		}
    231  1.1  ober 		pxa2x0_gpio_set_function(pin, GPIO_IN);
    232  1.1  ober 		pxa2x0_gpio_intr_establish(pin, IST_EDGE_BOTH, IPL_TTY,
    233  1.1  ober 		    zkbd_irq, sc);
    234  1.1  ober 	}
    235  1.1  ober 	pxa2x0_gpio_intr_establish(sc->sc_onkey_pin, IST_EDGE_BOTH, IPL_TTY,
    236  1.1  ober 	    zkbd_on, sc);
    237  1.1  ober 	pxa2x0_gpio_intr_establish(sc->sc_sync_pin, IST_EDGE_RISING, IPL_TTY,
    238  1.1  ober 	    zkbd_sync, sc);
    239  1.1  ober 	pxa2x0_gpio_intr_establish(sc->sc_swa_pin, IST_EDGE_BOTH, IPL_TTY,
    240  1.1  ober 	    zkbd_hinge, sc);
    241  1.1  ober 	pxa2x0_gpio_intr_establish(sc->sc_swb_pin, IST_EDGE_BOTH, IPL_TTY,
    242  1.1  ober 	    zkbd_hinge, sc);
    243  1.1  ober 
    244  1.1  ober 	if (glass_console) {
    245  1.1  ober 		wskbd_cnattach(&zkbd_consops, sc, &zkbd_keymapdata);
    246  1.1  ober 		a.console = 1;
    247  1.1  ober 	} else {
    248  1.1  ober 		a.console = 0;
    249  1.1  ober 	}
    250  1.1  ober 
    251  1.1  ober 	a.keymap = &zkbd_keymapdata;
    252  1.1  ober 	a.accessops = &zkbd_accessops;
    253  1.1  ober 	a.accesscookie = sc;
    254  1.1  ober 
    255  1.1  ober 	printf("\n");
    256  1.1  ober 
    257  1.1  ober 	zkbd_hinge(sc);		/* to initialize sc_hinge */
    258  1.1  ober 
    259  1.1  ober 	sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
    260  1.1  ober 
    261  1.1  ober 	callout_init(&sc->sc_roll_to);
    262  1.1  ober 	callout_setfunc(&sc->sc_roll_to, zkbd_poll, sc);
    263  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    264  1.1  ober 	callout_setfunc(&sc->sc_rawrepeat_ch, zkbd_rawrepeat, sc);
    265  1.1  ober #endif
    266  1.1  ober }
    267  1.1  ober 
    268  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    269  1.1  ober static void
    270  1.1  ober zkbd_rawrepeat(void *v)
    271  1.1  ober {
    272  1.1  ober 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    273  1.1  ober 	int s;
    274  1.1  ober 
    275  1.1  ober 	s = spltty();
    276  1.1  ober 	wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
    277  1.1  ober 	splx(s);
    278  1.1  ober 	callout_schedule(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000);
    279  1.1  ober }
    280  1.1  ober #endif
    281  1.1  ober 
    282  1.1  ober /* XXX only deal with keys that can be pressed when display is open? */
    283  1.1  ober /* XXX are some not in the array? */
    284  1.1  ober /* handle keypress interrupt */
    285  1.1  ober static int
    286  1.1  ober zkbd_irq(void *v)
    287  1.1  ober {
    288  1.1  ober 
    289  1.1  ober 	zkbd_poll(v);
    290  1.1  ober 
    291  1.1  ober 	return 1;
    292  1.1  ober }
    293  1.1  ober 
    294  1.1  ober static void
    295  1.1  ober zkbd_poll(void *v)
    296  1.1  ober {
    297  1.1  ober 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    298  1.1  ober 	int i, j, col, pin, type, keysdown = 0, s;
    299  1.1  ober 	int stuck;
    300  1.1  ober 	int keystate;
    301  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    302  1.1  ober 	int npress = 0, ncbuf = 0, c;
    303  1.1  ober 	char cbuf[MAXKEYS *2];
    304  1.1  ober #endif
    305  1.1  ober 
    306  1.1  ober 	s = spltty();
    307  1.1  ober 
    308  1.1  ober 	/* discharge all */
    309  1.1  ober 	for (i = 0; i < sc->sc_nstrobe; i++) {
    310  1.1  ober 		pin = sc->sc_strobe_array[i];
    311  1.1  ober 		if (pin != -1) {
    312  1.1  ober 			pxa2x0_gpio_clear_bit(pin);
    313  1.1  ober 			pxa2x0_gpio_set_dir(pin, GPIO_IN);
    314  1.1  ober 		}
    315  1.1  ober 	}
    316  1.1  ober 
    317  1.1  ober 	delay (10);
    318  1.1  ober 	for(col = 0; col < sc->sc_nstrobe; col++) {
    319  1.1  ober 		if (sc->sc_strobe_array[i] == -1)
    320  1.1  ober 			continue;
    321  1.1  ober 
    322  1.1  ober 		pin = sc->sc_strobe_array[col];
    323  1.1  ober 
    324  1.1  ober 		/* activate_col */
    325  1.1  ober 		pxa2x0_gpio_set_bit(pin);
    326  1.1  ober 		pxa2x0_gpio_set_dir(pin, GPIO_OUT);
    327  1.1  ober 
    328  1.1  ober 		/* wait activate delay */
    329  1.1  ober 		delay(10);
    330  1.1  ober 
    331  1.1  ober 		/* read row */
    332  1.1  ober 		for (i = 0; i < sc->sc_nsense; i++) {
    333  1.1  ober 			int bit;
    334  1.1  ober 
    335  1.1  ober 			if (sc->sc_sense_array[i] == -1)
    336  1.1  ober 				continue;
    337  1.1  ober 
    338  1.1  ober 			bit = pxa2x0_gpio_get_bit(sc->sc_sense_array[i]);
    339  1.1  ober 			if (bit && sc->sc_hinge && col < sc->sc_maxkbdcol)
    340  1.1  ober 				continue;
    341  1.1  ober 			sc->sc_keystate[i + (col * sc->sc_nsense)] = bit;
    342  1.1  ober 		}
    343  1.1  ober 
    344  1.1  ober 		/* reset_col */
    345  1.1  ober 		pxa2x0_gpio_set_dir(pin, GPIO_IN);
    346  1.1  ober 		/* wait discharge delay */
    347  1.1  ober 		delay(10);
    348  1.1  ober 	}
    349  1.1  ober 	/* charge all */
    350  1.1  ober 	for (i = 0; i < sc->sc_nstrobe; i++) {
    351  1.1  ober 		pin = sc->sc_strobe_array[i];
    352  1.1  ober 		if (pin != -1) {
    353  1.1  ober 			pxa2x0_gpio_set_bit(pin);
    354  1.1  ober 			pxa2x0_gpio_set_dir(pin, GPIO_OUT);
    355  1.1  ober 		}
    356  1.1  ober 	}
    357  1.1  ober 
    358  1.1  ober 	/* force the irqs to clear as we have just played with them. */
    359  1.1  ober 	for (i = 0; i < sc->sc_nsense; i++)
    360  1.1  ober 		if (sc->sc_sense_array[i] != -1)
    361  1.1  ober 			pxa2x0_gpio_clear_intr(sc->sc_sense_array[i]);
    362  1.1  ober 
    363  1.1  ober 	/* process after resetting interrupt */
    364  1.1  ober 
    365  1.1  ober 	zkbd_modstate = (
    366  1.1  ober 		(sc->sc_keystate[84] ? (1 << 0) : 0) | /* shift */
    367  1.1  ober 		(sc->sc_keystate[93] ? (1 << 1) : 0) | /* Fn */
    368  1.1  ober 		(sc->sc_keystate[14] ? (1 << 2) : 0)); /* 'alt' */
    369  1.1  ober 
    370  1.1  ober 	for (i = 0; i < (sc->sc_nsense * sc->sc_nstrobe); i++) {
    371  1.1  ober 		stuck = 0;
    372  1.1  ober 		/* extend  xt_keymap to do this faster. */
    373  1.1  ober 		/* ignore 'stuck' keys' */
    374  1.1  ober 		for (j = 0; j < sizeof(stuck_keys)/sizeof(stuck_keys[0]); j++) {
    375  1.1  ober 			if (stuck_keys[j] == i) {
    376  1.1  ober 				stuck = 1 ;
    377  1.1  ober 				break;
    378  1.1  ober 			}
    379  1.1  ober 		}
    380  1.1  ober 		if (stuck)
    381  1.1  ober 			continue;
    382  1.1  ober 		keystate = sc->sc_keystate[i];
    383  1.1  ober 
    384  1.1  ober 		keysdown |= keystate; /* if any keys held */
    385  1.1  ober 
    386  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    387  1.1  ober 		if (sc->sc_polling == 0 && sc->sc_rawkbd) {
    388  1.1  ober 			if ((keystate) || (sc->sc_okeystate[i] != keystate)) {
    389  1.1  ober 				c = sc->sc_xt_keymap[i];
    390  1.1  ober 				if (c & 0x80) {
    391  1.1  ober 					cbuf[ncbuf++] = 0xe0;
    392  1.1  ober 				}
    393  1.1  ober 				cbuf[ncbuf] = c & 0x7f;
    394  1.1  ober 
    395  1.1  ober 				if (keystate) {
    396  1.1  ober 					if (c & 0x80) {
    397  1.1  ober 						sc->sc_rep[npress++] = 0xe0;
    398  1.1  ober 					}
    399  1.1  ober 					sc->sc_rep[npress++] = c & 0x7f;
    400  1.1  ober 				} else {
    401  1.1  ober 					cbuf[ncbuf] |= 0x80;
    402  1.1  ober 				}
    403  1.1  ober 				ncbuf++;
    404  1.1  ober 				sc->sc_okeystate[i] = keystate;
    405  1.1  ober 			}
    406  1.1  ober 		}
    407  1.1  ober #endif
    408  1.1  ober 
    409  1.1  ober 		if ((!sc->sc_rawkbd) && (sc->sc_okeystate[i] != keystate)) {
    410  1.1  ober 
    411  1.1  ober 			type = keystate ? WSCONS_EVENT_KEY_DOWN :
    412  1.1  ober 			    WSCONS_EVENT_KEY_UP;
    413  1.1  ober 
    414  1.1  ober 			if (sc->sc_polling) {
    415  1.1  ober 				sc->sc_pollkey = i;
    416  1.1  ober 				sc->sc_pollUD = type;
    417  1.1  ober 			} else {
    418  1.1  ober 				wskbd_input(sc->sc_wskbddev, type, i);
    419  1.1  ober 			}
    420  1.1  ober 
    421  1.1  ober 			sc->sc_okeystate[i] = keystate;
    422  1.1  ober 		}
    423  1.1  ober 	}
    424  1.1  ober 
    425  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    426  1.1  ober 	if (sc->sc_polling == 0 && sc->sc_rawkbd) {
    427  1.1  ober 		wskbd_rawinput(sc->sc_wskbddev, cbuf, ncbuf);
    428  1.1  ober 		sc->sc_nrep = npress;
    429  1.1  ober 		if (npress != 0)
    430  1.1  ober 			callout_schedule(&sc->sc_rawrepeat_ch,
    431  1.1  ober 			    hz * REP_DELAY1 / 1000);
    432  1.1  ober 		else
    433  1.1  ober 			callout_stop(&sc->sc_rawrepeat_ch);
    434  1.1  ober 	}
    435  1.1  ober #endif
    436  1.1  ober 	if (keysdown)
    437  1.1  ober 		callout_schedule(&sc->sc_roll_to, hz * REP_DELAYN / 1000 / 2);
    438  1.1  ober 	else
    439  1.1  ober 		callout_stop(&sc->sc_roll_to);	/* always cancel? */
    440  1.1  ober 
    441  1.1  ober 	splx(s);
    442  1.1  ober }
    443  1.1  ober 
    444  1.1  ober #if NAPM > 0
    445  1.1  ober extern	int kbd_reset;
    446  1.1  ober extern	int apm_suspends;
    447  1.1  ober static	int zkbdondown;				/* on key is pressed */
    448  1.1  ober static	struct timeval zkbdontv = { 0, 0 };	/* last on key event */
    449  1.1  ober const	struct timeval zkbdhalttv = { 3, 0 };	/*  3s for safe shutdown */
    450  1.1  ober const	struct timeval zkbdsleeptv = { 0, 250000 };	/* .25s for suspend */
    451  1.1  ober extern	int lid_suspend;
    452  1.1  ober #endif
    453  1.1  ober 
    454  1.1  ober static int
    455  1.1  ober zkbd_on(void *v)
    456  1.1  ober {
    457  1.1  ober #if NAPM > 0
    458  1.1  ober 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    459  1.1  ober 	int down = pxa2x0_gpio_get_bit(sc->sc_onkey_pin) ? 1 : 0;
    460  1.1  ober 
    461  1.1  ober 	/*
    462  1.1  ober 	 * Change run mode depending on how long the key is held down.
    463  1.1  ober 	 * Ignore the key if it gets pressed while the lid is closed.
    464  1.1  ober 	 *
    465  1.1  ober 	 * Keys can bounce and we have to work around missed interrupts.
    466  1.1  ober 	 * Only the second edge is detected upon exit from sleep mode.
    467  1.1  ober 	 */
    468  1.1  ober 	if (down) {
    469  1.1  ober 		if (sc->sc_hinge == 3) {
    470  1.1  ober 			zkbdondown = 0;
    471  1.1  ober 		} else {
    472  1.1  ober 			microuptime(&zkbdontv);
    473  1.1  ober 			zkbdondown = 1;
    474  1.1  ober 		}
    475  1.1  ober 	} else if (zkbdondown) {
    476  1.1  ober 		if (ratecheck(&zkbdontv, &zkbdhalttv)) {
    477  1.1  ober 			if (kbd_reset == 1) {
    478  1.1  ober 				kbd_reset = 0;
    479  1.1  ober 				psignal(initproc, SIGUSR1);
    480  1.1  ober 			}
    481  1.1  ober 		} else if (ratecheck(&zkbdontv, &zkbdsleeptv)) {
    482  1.1  ober 			apm_suspends++;
    483  1.1  ober 		}
    484  1.1  ober 		zkbdondown = 0;
    485  1.1  ober 	}
    486  1.1  ober #endif
    487  1.1  ober 	return 1;
    488  1.1  ober }
    489  1.1  ober 
    490  1.1  ober static int
    491  1.1  ober zkbd_sync(void *v)
    492  1.1  ober {
    493  1.1  ober 
    494  1.1  ober 	return 1;
    495  1.1  ober }
    496  1.1  ober 
    497  1.1  ober static int
    498  1.1  ober zkbd_hinge(void *v)
    499  1.1  ober {
    500  1.1  ober 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    501  1.1  ober 	int a = pxa2x0_gpio_get_bit(sc->sc_swa_pin) ? 1 : 0;
    502  1.1  ober 	int b = pxa2x0_gpio_get_bit(sc->sc_swb_pin) ? 2 : 0;
    503  1.1  ober #if NLCD > 0
    504  1.1  ober 	extern void lcd_blank(int);
    505  1.1  ober #endif
    506  1.1  ober 
    507  1.1  ober 	sc->sc_hinge = a | b;
    508  1.1  ober 
    509  1.1  ober 	if (sc->sc_hinge == 3) {
    510  1.1  ober #if NAPM > 0
    511  1.1  ober 		if (lid_suspend)
    512  1.1  ober 			apm_suspends++;
    513  1.1  ober #endif
    514  1.1  ober #if NLCD > 0
    515  1.1  ober 		lcd_blank(1);
    516  1.1  ober #endif
    517  1.1  ober 	} else {
    518  1.1  ober #if NLCD > 0
    519  1.1  ober 		lcd_blank(0);
    520  1.1  ober #endif
    521  1.1  ober 	}
    522  1.1  ober 
    523  1.1  ober 	return 1;
    524  1.1  ober }
    525  1.1  ober 
    526  1.1  ober static int
    527  1.1  ober zkbd_enable(void *v, int on)
    528  1.1  ober {
    529  1.1  ober 
    530  1.1  ober 	return 0;
    531  1.1  ober }
    532  1.1  ober 
    533  1.1  ober void
    534  1.1  ober zkbd_set_leds(void *v, int on)
    535  1.1  ober {
    536  1.1  ober }
    537  1.1  ober 
    538  1.1  ober static int
    539  1.1  ober zkbd_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct lwp *l)
    540  1.1  ober {
    541  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    542  1.1  ober 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    543  1.1  ober #endif
    544  1.1  ober 
    545  1.1  ober 	switch (cmd) {
    546  1.1  ober 	case WSKBDIO_GTYPE:
    547  1.1  ober 		*(int *)data = WSKBD_TYPE_ZAURUS;
    548  1.1  ober 		return 0;
    549  1.1  ober 
    550  1.1  ober 	case WSKBDIO_SETLEDS:
    551  1.1  ober 		return 0;
    552  1.1  ober 
    553  1.1  ober 	case WSKBDIO_GETLEDS:
    554  1.1  ober 		*(int *)data = 0;
    555  1.1  ober 		return 0;
    556  1.1  ober 
    557  1.1  ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    558  1.1  ober 	case WSKBDIO_SETMODE:
    559  1.1  ober 		sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
    560  1.1  ober 		callout_stop(&sc->sc_rawrepeat_ch);
    561  1.1  ober 		return 0;
    562  1.1  ober #endif
    563  1.1  ober 
    564  1.1  ober 	}
    565  1.1  ober 	/* kbdioctl(...); */
    566  1.1  ober 
    567  1.1  ober 	return -1;
    568  1.1  ober }
    569  1.1  ober 
    570  1.1  ober /* implement polling for zaurus_kbd */
    571  1.1  ober static void
    572  1.1  ober zkbd_cngetc(void *v, u_int *type, int *data)
    573  1.1  ober {
    574  1.1  ober 	struct zkbd_softc *sc = (struct zkbd_softc *)zkbd_dev;
    575  1.1  ober 
    576  1.1  ober 	sc->sc_pollkey = -1;
    577  1.1  ober 	sc->sc_pollUD = -1;
    578  1.1  ober 	sc->sc_polling = 1;
    579  1.1  ober 	while (sc->sc_pollkey == -1) {
    580  1.1  ober 		zkbd_poll(zkbd_dev);
    581  1.1  ober 		DELAY(10000);	/* XXX */
    582  1.1  ober 	}
    583  1.1  ober 	sc->sc_polling = 0;
    584  1.1  ober 	*data = sc->sc_pollkey;
    585  1.1  ober 	*type = sc->sc_pollUD;
    586  1.1  ober }
    587  1.1  ober 
    588  1.1  ober static void
    589  1.1  ober zkbd_cnpollc(void *v, int on)
    590  1.1  ober {
    591  1.1  ober }
    592  1.1  ober 
    593  1.1  ober static void
    594  1.1  ober zkbd_power(int why, void *arg)
    595  1.1  ober {
    596  1.1  ober 
    597  1.1  ober 	zkbd_hinge(arg);
    598  1.1  ober }
    599