Home | History | Annotate | Line # | Download | only in dev
zkbd.c revision 1.20
      1  1.20   thorpej /*	$NetBSD: zkbd.c,v 1.20 2020/11/21 17:22:03 thorpej 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.20   thorpej __KERNEL_RCSID(0, "$NetBSD: zkbd.c,v 1.20 2020/11/21 17:22:03 thorpej Exp $");
     22   1.1      ober 
     23   1.1      ober #include "opt_wsdisplay_compat.h"
     24   1.1      ober #if 0	/* XXX */
     25   1.1      ober #include "apm.h"
     26   1.1      ober #endif
     27  1.15   tsutsui #include "lcdctl.h"
     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.20   thorpej #include <sys/kmem.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.12    nonaka #include <zaurus/zaurus/zaurus_var.h>
     47   1.1      ober #include <zaurus/dev/zkbdmap.h>
     48  1.15   tsutsui #if NLCDCTL > 0
     49  1.15   tsutsui #include <zaurus/dev/lcdctlvar.h>
     50  1.15   tsutsui #endif
     51   1.1      ober 
     52   1.1      ober static const int gpio_sense_pins_c3000[] = {
     53   1.1      ober 	12,
     54   1.1      ober 	17,
     55   1.1      ober 	91,
     56   1.1      ober 	34,
     57   1.1      ober 	36,
     58   1.1      ober 	38,
     59   1.1      ober 	39,
     60   1.1      ober 	-1
     61   1.1      ober };
     62   1.1      ober 
     63   1.1      ober static const int gpio_strobe_pins_c3000[] = {
     64   1.1      ober 	88,
     65   1.1      ober 	23,
     66   1.1      ober 	24,
     67   1.1      ober 	25,
     68   1.1      ober 	26,
     69   1.1      ober 	27,
     70   1.1      ober 	52,
     71   1.1      ober 	103,
     72   1.1      ober 	107,
     73   1.1      ober 	-1,
     74   1.1      ober 	108,
     75   1.1      ober 	114
     76   1.1      ober };
     77   1.1      ober 
     78  1.18    nonaka static const int stuck_keys_c3000[] = {
     79  1.18    nonaka 	1,  7,  15, 22, 23, 31, 39, 47,
     80  1.18    nonaka 	53, 55, 60, 63, 66, 67, 69, 71,
     81  1.18    nonaka 	72, 73, 74, 75, 76, 77, 78, 79,
     82  1.18    nonaka 	82, 85, 86, 87, 90, 91, 92, 94,
     83  1.18    nonaka 	95
     84  1.18    nonaka };
     85  1.18    nonaka 
     86  1.16   tsutsui static const int gpio_sense_pins_c860[] = {
     87  1.16   tsutsui 	58,
     88  1.16   tsutsui 	59,
     89  1.16   tsutsui 	60,
     90  1.16   tsutsui 	61,
     91  1.16   tsutsui 	62,
     92  1.16   tsutsui 	63,
     93  1.16   tsutsui 	64,
     94  1.16   tsutsui 	65
     95  1.16   tsutsui };
     96  1.16   tsutsui 
     97  1.16   tsutsui static const int gpio_strobe_pins_c860[] = {
     98  1.16   tsutsui 	66,
     99  1.16   tsutsui 	67,
    100  1.16   tsutsui 	68,
    101  1.16   tsutsui 	69,
    102  1.16   tsutsui 	70,
    103  1.16   tsutsui 	71,
    104  1.16   tsutsui 	72,
    105  1.16   tsutsui 	73,
    106  1.16   tsutsui 	74,
    107  1.16   tsutsui 	75,
    108  1.16   tsutsui 	76,
    109  1.16   tsutsui 	77
    110  1.16   tsutsui };
    111  1.16   tsutsui 
    112  1.18    nonaka static const int stuck_keys_c860[] = {
    113  1.18    nonaka 	0,  1,  47, 53, 55, 60, 63, 66,
    114  1.18    nonaka 	67, 69, 71, 72, 73, 74, 76, 77,
    115  1.18    nonaka 	78, 79, 80, 81, 82, 83, 85, 86,
    116  1.18    nonaka 	87, 88, 89, 90, 91, 92, 94, 95
    117   1.1      ober };
    118   1.1      ober 
    119   1.1      ober #define REP_DELAY1 400
    120   1.1      ober #define REP_DELAYN 100
    121   1.1      ober 
    122   1.1      ober struct zkbd_softc {
    123   1.8    nonaka 	device_t sc_dev;
    124   1.1      ober 
    125   1.1      ober 	const int *sc_sense_array;
    126   1.1      ober 	const int *sc_strobe_array;
    127  1.16   tsutsui 	const int *sc_stuck_keys;
    128   1.1      ober 	int sc_nsense;
    129   1.1      ober 	int sc_nstrobe;
    130  1.16   tsutsui 	int sc_nstuck;
    131   1.1      ober 
    132   1.1      ober 	short sc_onkey_pin;
    133   1.1      ober 	short sc_sync_pin;
    134   1.1      ober 	short sc_swa_pin;
    135   1.1      ober 	short sc_swb_pin;
    136   1.1      ober 	char *sc_okeystate;
    137   1.1      ober 	char *sc_keystate;
    138   1.1      ober 	char sc_hinge;		/* 0=open, 1=nonsense, 2=backwards, 3=closed */
    139   1.1      ober 	char sc_maxkbdcol;
    140   1.1      ober 
    141   1.1      ober 	struct callout sc_roll_to;
    142   1.1      ober 
    143   1.1      ober 	/* console stuff */
    144   1.1      ober 	int sc_polling;
    145   1.1      ober 	int sc_pollUD;
    146   1.1      ober 	int sc_pollkey;
    147   1.1      ober 
    148   1.1      ober 	/* wskbd bits */
    149  1.17       chs 	device_t sc_wskbddev;
    150  1.16   tsutsui 	struct wskbd_mapdata *sc_keymapdata;
    151   1.1      ober 	int sc_rawkbd;
    152   1.1      ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    153   1.1      ober 	const char *sc_xt_keymap;
    154   1.1      ober 	struct callout sc_rawrepeat_ch;
    155   1.1      ober #define MAXKEYS 20
    156   1.1      ober 	char sc_rep[MAXKEYS];
    157   1.1      ober 	int sc_nrep;
    158   1.1      ober #endif
    159   1.1      ober };
    160   1.1      ober 
    161   1.2     peter static struct zkbd_softc *zkbd_sc;
    162   1.1      ober 
    163   1.8    nonaka static int	zkbd_match(device_t, cfdata_t, void *);
    164   1.8    nonaka static void	zkbd_attach(device_t, device_t, void *);
    165   1.1      ober 
    166   1.8    nonaka CFATTACH_DECL_NEW(zkbd, sizeof(struct zkbd_softc),
    167   1.1      ober 	zkbd_match, zkbd_attach, NULL, NULL);
    168   1.1      ober 
    169  1.18    nonaka static int	zkbd_irq_c3000(void *v);
    170  1.18    nonaka static int	zkbd_irq_c860(void *v);
    171   1.1      ober static void	zkbd_poll(void *v);
    172   1.1      ober static int	zkbd_on(void *v);
    173   1.1      ober static int	zkbd_sync(void *v);
    174   1.1      ober static int	zkbd_hinge(void *v);
    175  1.11    dyoung static bool	zkbd_resume(device_t dv, const pmf_qual_t *);
    176   1.1      ober 
    177   1.1      ober int zkbd_modstate;
    178   1.1      ober 
    179   1.1      ober static int	zkbd_enable(void *, int);
    180   1.1      ober static void	zkbd_set_leds(void *, int);
    181   1.3  christos static int	zkbd_ioctl(void *, u_long, void *, int, struct lwp *);
    182   1.1      ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    183   1.1      ober static void	zkbd_rawrepeat(void *v);
    184   1.1      ober #endif
    185   1.1      ober 
    186   1.2     peter static struct wskbd_accessops zkbd_accessops = {
    187   1.1      ober 	zkbd_enable,
    188   1.1      ober 	zkbd_set_leds,
    189   1.1      ober 	zkbd_ioctl,
    190   1.1      ober };
    191   1.1      ober 
    192   1.1      ober static void	zkbd_cngetc(void *, u_int *, int *);
    193   1.1      ober static void	zkbd_cnpollc(void *, int);
    194   1.1      ober 
    195   1.2     peter static struct wskbd_consops zkbd_consops = {
    196   1.1      ober 	zkbd_cngetc,
    197   1.1      ober 	zkbd_cnpollc,
    198   1.1      ober };
    199   1.1      ober 
    200   1.2     peter static struct wskbd_mapdata zkbd_keymapdata = {
    201   1.1      ober 	zkbd_keydesctab,
    202   1.1      ober 	KB_US,
    203   1.1      ober };
    204   1.1      ober 
    205  1.16   tsutsui static struct wskbd_mapdata zkbd_keymapdata_c860 = {
    206  1.16   tsutsui 	zkbd_keydesctab_c860,
    207  1.16   tsutsui 	KB_US,
    208  1.16   tsutsui };
    209  1.16   tsutsui 
    210   1.1      ober static int
    211   1.8    nonaka zkbd_match(device_t parent, cfdata_t cf, void *aux)
    212   1.1      ober {
    213   1.1      ober 
    214   1.4    nonaka 	if (zkbd_sc)
    215   1.4    nonaka 		return 0;
    216   1.4    nonaka 
    217   1.1      ober 	return 1;
    218   1.1      ober }
    219   1.1      ober 
    220   1.1      ober static void
    221   1.8    nonaka zkbd_attach(device_t parent, device_t self, void *aux)
    222   1.1      ober {
    223   1.8    nonaka 	struct zkbd_softc *sc = device_private(self);
    224   1.1      ober 	struct wskbddev_attach_args a;
    225   1.1      ober 	int pin, i;
    226   1.1      ober 
    227   1.8    nonaka 	sc->sc_dev = self;
    228   1.2     peter 	zkbd_sc = sc;
    229   1.4    nonaka 
    230   1.8    nonaka 	aprint_normal("\n");
    231   1.8    nonaka 	aprint_naive("\n");
    232   1.4    nonaka 
    233   1.1      ober 	sc->sc_polling = 0;
    234   1.1      ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    235   1.1      ober 	sc->sc_rawkbd = 0;
    236   1.1      ober #endif
    237   1.1      ober 
    238   1.6    nonaka 	callout_init(&sc->sc_roll_to, 0);
    239   1.6    nonaka 	callout_setfunc(&sc->sc_roll_to, zkbd_poll, sc);
    240   1.6    nonaka #ifdef WSDISPLAY_COMPAT_RAWKBD
    241   1.6    nonaka 	callout_init(&sc->sc_rawrepeat_ch, 0);
    242   1.6    nonaka 	callout_setfunc(&sc->sc_rawrepeat_ch, zkbd_rawrepeat, sc);
    243   1.6    nonaka #endif
    244   1.6    nonaka 
    245  1.12    nonaka 	if (ZAURUS_ISC1000 || ZAURUS_ISC3000) {
    246   1.1      ober 		sc->sc_sense_array = gpio_sense_pins_c3000;
    247   1.1      ober 		sc->sc_strobe_array = gpio_strobe_pins_c3000;
    248   1.2     peter 		sc->sc_nsense = __arraycount(gpio_sense_pins_c3000);
    249   1.2     peter 		sc->sc_nstrobe = __arraycount(gpio_strobe_pins_c3000);
    250  1.18    nonaka 		sc->sc_stuck_keys = stuck_keys_c3000;
    251  1.18    nonaka 		sc->sc_nstuck = __arraycount(stuck_keys_c3000);
    252   1.1      ober 		sc->sc_maxkbdcol = 10;
    253   1.1      ober 		sc->sc_onkey_pin = 95;
    254   1.1      ober 		sc->sc_sync_pin = 16;
    255   1.1      ober 		sc->sc_swa_pin = 97;
    256   1.1      ober 		sc->sc_swb_pin = 96;
    257  1.16   tsutsui 		sc->sc_keymapdata = &zkbd_keymapdata;
    258   1.1      ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    259   1.1      ober 		sc->sc_xt_keymap = xt_keymap;
    260   1.1      ober #endif
    261  1.16   tsutsui 	} else if (ZAURUS_ISC860) {
    262  1.16   tsutsui 		sc->sc_sense_array = gpio_sense_pins_c860;
    263  1.16   tsutsui 		sc->sc_strobe_array = gpio_strobe_pins_c860;
    264  1.16   tsutsui 		sc->sc_nsense = __arraycount(gpio_sense_pins_c860);
    265  1.16   tsutsui 		sc->sc_nstrobe = __arraycount(gpio_strobe_pins_c860);
    266  1.18    nonaka 		sc->sc_stuck_keys = stuck_keys_c860;
    267  1.18    nonaka 		sc->sc_nstuck = __arraycount(stuck_keys_c860);
    268  1.16   tsutsui 		sc->sc_maxkbdcol = 0;
    269  1.16   tsutsui 		sc->sc_onkey_pin = -1;
    270  1.16   tsutsui 		sc->sc_sync_pin = -1;
    271  1.16   tsutsui 		sc->sc_swa_pin = -1;
    272  1.16   tsutsui 		sc->sc_swb_pin = -1;
    273  1.16   tsutsui 		sc->sc_keymapdata = &zkbd_keymapdata_c860;
    274  1.16   tsutsui #ifdef WSDISPLAY_COMPAT_RAWKBD
    275  1.16   tsutsui 		sc->sc_xt_keymap = xt_keymap_c860;
    276  1.16   tsutsui #endif
    277   1.4    nonaka 	} else {
    278   1.4    nonaka 		/* XXX */
    279   1.4    nonaka 		return;
    280   1.4    nonaka 	}
    281   1.4    nonaka 
    282   1.9    nonaka 	if (!pmf_device_register(sc->sc_dev, NULL, zkbd_resume))
    283   1.9    nonaka 		aprint_error_dev(sc->sc_dev,
    284   1.9    nonaka 		    "couldn't establish power handler\n");
    285   1.1      ober 
    286  1.20   thorpej 	sc->sc_okeystate = kmem_zalloc(sc->sc_nsense * sc->sc_nstrobe,
    287  1.20   thorpej 	    KM_SLEEP);
    288  1.20   thorpej 	sc->sc_keystate = kmem_zalloc(sc->sc_nsense * sc->sc_nstrobe,
    289  1.20   thorpej 	    KM_SLEEP);
    290   1.1      ober 
    291   1.1      ober 	/* set all the strobe bits */
    292   1.1      ober 	for (i = 0; i < sc->sc_nstrobe; i++) {
    293   1.1      ober 		pin = sc->sc_strobe_array[i];
    294   1.4    nonaka 		if (pin == -1)
    295   1.1      ober 			continue;
    296   1.1      ober 		pxa2x0_gpio_set_function(pin, GPIO_SET|GPIO_OUT);
    297   1.1      ober 	}
    298   1.2     peter 
    299   1.1      ober 	/* set all the sense bits */
    300   1.1      ober 	for (i = 0; i < sc->sc_nsense; i++) {
    301   1.1      ober 		pin = sc->sc_sense_array[i];
    302   1.4    nonaka 		if (pin == -1)
    303   1.1      ober 			continue;
    304   1.1      ober 		pxa2x0_gpio_set_function(pin, GPIO_IN);
    305  1.18    nonaka 		if (ZAURUS_ISC1000 || ZAURUS_ISC3000) {
    306  1.18    nonaka 			pxa2x0_gpio_intr_establish(pin, IST_EDGE_BOTH,
    307  1.18    nonaka 			    IPL_TTY, zkbd_irq_c3000, sc);
    308  1.18    nonaka 		} else if (ZAURUS_ISC860) {
    309  1.18    nonaka 			pxa2x0_gpio_intr_establish(pin, IST_EDGE_RISING,
    310  1.18    nonaka 			    IPL_TTY, zkbd_irq_c860, sc);
    311  1.18    nonaka 		}
    312   1.1      ober 	}
    313   1.2     peter 
    314  1.16   tsutsui 	if (sc->sc_onkey_pin >= 0)
    315  1.16   tsutsui 		pxa2x0_gpio_intr_establish(sc->sc_onkey_pin, IST_EDGE_BOTH,
    316  1.16   tsutsui 		    IPL_TTY, zkbd_on, sc);
    317  1.16   tsutsui 	if (sc->sc_sync_pin >= 0)
    318  1.16   tsutsui 		pxa2x0_gpio_intr_establish(sc->sc_sync_pin, IST_EDGE_RISING,
    319  1.16   tsutsui 		    IPL_TTY, zkbd_sync, sc);
    320  1.16   tsutsui 	if (sc->sc_swa_pin >= 0)
    321  1.16   tsutsui 		pxa2x0_gpio_intr_establish(sc->sc_swa_pin, IST_EDGE_BOTH,
    322  1.16   tsutsui 		    IPL_TTY, zkbd_hinge, sc);
    323  1.16   tsutsui 	if (sc->sc_swb_pin >= 0)
    324  1.16   tsutsui 		pxa2x0_gpio_intr_establish(sc->sc_swb_pin, IST_EDGE_BOTH,
    325  1.16   tsutsui 		    IPL_TTY, zkbd_hinge, sc);
    326   1.1      ober 
    327   1.1      ober 	if (glass_console) {
    328  1.16   tsutsui 		wskbd_cnattach(&zkbd_consops, sc, sc->sc_keymapdata);
    329   1.1      ober 		a.console = 1;
    330   1.1      ober 	} else {
    331   1.1      ober 		a.console = 0;
    332   1.1      ober 	}
    333  1.16   tsutsui 	a.keymap = sc->sc_keymapdata;
    334   1.1      ober 	a.accessops = &zkbd_accessops;
    335   1.1      ober 	a.accesscookie = sc;
    336   1.1      ober 
    337   1.1      ober 	zkbd_hinge(sc);		/* to initialize sc_hinge */
    338   1.1      ober 
    339   1.1      ober 	sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
    340   1.1      ober }
    341   1.1      ober 
    342   1.1      ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    343   1.1      ober static void
    344   1.1      ober zkbd_rawrepeat(void *v)
    345   1.1      ober {
    346   1.1      ober 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    347   1.1      ober 	int s;
    348   1.1      ober 
    349   1.1      ober 	s = spltty();
    350   1.1      ober 	wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
    351   1.1      ober 	splx(s);
    352   1.1      ober 	callout_schedule(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000);
    353   1.1      ober }
    354   1.1      ober #endif
    355   1.1      ober 
    356   1.1      ober /* XXX only deal with keys that can be pressed when display is open? */
    357   1.1      ober /* XXX are some not in the array? */
    358   1.1      ober /* handle keypress interrupt */
    359   1.1      ober static int
    360  1.18    nonaka zkbd_irq_c3000(void *v)
    361   1.1      ober {
    362   1.1      ober 
    363   1.1      ober 	zkbd_poll(v);
    364   1.1      ober 
    365   1.1      ober 	return 1;
    366   1.1      ober }
    367   1.1      ober 
    368  1.18    nonaka /* Avoid chattering only for SL-C7x0/860 */
    369  1.18    nonaka static int
    370  1.18    nonaka zkbd_irq_c860(void *v)
    371  1.18    nonaka {
    372  1.18    nonaka 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    373  1.18    nonaka 
    374  1.18    nonaka 	if (!callout_pending(&sc->sc_roll_to)) {
    375  1.18    nonaka 		zkbd_poll(v);
    376  1.18    nonaka 	}
    377  1.18    nonaka 
    378  1.18    nonaka 	return 1;
    379  1.18    nonaka }
    380  1.18    nonaka 
    381   1.1      ober static void
    382   1.1      ober zkbd_poll(void *v)
    383   1.1      ober {
    384   1.1      ober 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    385   1.2     peter 	int i, j, col, pin, type, keysdown = 0;
    386  1.14    nonaka 	int stuck;
    387   1.1      ober 	int keystate;
    388   1.2     peter 	int s;
    389   1.1      ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    390  1.14    nonaka 	int npress = 0, ncbuf = 0, c;
    391   1.2     peter 	char cbuf[MAXKEYS * 2];
    392   1.1      ober #endif
    393   1.1      ober 
    394   1.1      ober 	s = spltty();
    395   1.1      ober 
    396   1.1      ober 	/* discharge all */
    397   1.1      ober 	for (i = 0; i < sc->sc_nstrobe; i++) {
    398   1.1      ober 		pin = sc->sc_strobe_array[i];
    399   1.4    nonaka 		if (pin == -1)
    400   1.4    nonaka 			continue;
    401   1.4    nonaka 		pxa2x0_gpio_clear_bit(pin);
    402   1.4    nonaka 		pxa2x0_gpio_set_dir(pin, GPIO_IN);
    403   1.1      ober 	}
    404   1.1      ober 
    405   1.2     peter 	delay(10);
    406   1.2     peter 	for (col = 0; col < sc->sc_nstrobe; col++) {
    407   1.2     peter 		pin = sc->sc_strobe_array[col];
    408   1.2     peter 		if (pin == -1)
    409   1.1      ober 			continue;
    410   1.1      ober 
    411   1.1      ober 		/* activate_col */
    412   1.1      ober 		pxa2x0_gpio_set_bit(pin);
    413   1.1      ober 		pxa2x0_gpio_set_dir(pin, GPIO_OUT);
    414   1.1      ober 
    415   1.1      ober 		/* wait activate delay */
    416   1.1      ober 		delay(10);
    417   1.1      ober 
    418   1.1      ober 		/* read row */
    419   1.1      ober 		for (i = 0; i < sc->sc_nsense; i++) {
    420   1.1      ober 			int bit;
    421   1.1      ober 
    422   1.4    nonaka 			if (sc->sc_sense_array[i] == -1)
    423   1.1      ober 				continue;
    424   1.1      ober 			bit = pxa2x0_gpio_get_bit(sc->sc_sense_array[i]);
    425   1.1      ober 			if (bit && sc->sc_hinge && col < sc->sc_maxkbdcol)
    426   1.1      ober 				continue;
    427   1.1      ober 			sc->sc_keystate[i + (col * sc->sc_nsense)] = bit;
    428   1.1      ober 		}
    429   1.1      ober 
    430   1.1      ober 		/* reset_col */
    431   1.1      ober 		pxa2x0_gpio_set_dir(pin, GPIO_IN);
    432   1.2     peter 
    433   1.1      ober 		/* wait discharge delay */
    434   1.1      ober 		delay(10);
    435   1.1      ober 	}
    436   1.2     peter 
    437   1.1      ober 	/* charge all */
    438   1.1      ober 	for (i = 0; i < sc->sc_nstrobe; i++) {
    439   1.1      ober 		pin = sc->sc_strobe_array[i];
    440   1.4    nonaka 		if (pin == -1)
    441   1.4    nonaka 			continue;
    442   1.4    nonaka 		pxa2x0_gpio_set_bit(pin);
    443   1.4    nonaka 		pxa2x0_gpio_set_dir(pin, GPIO_OUT);
    444   1.1      ober 	}
    445   1.1      ober 
    446   1.1      ober 	/* force the irqs to clear as we have just played with them. */
    447   1.2     peter 	for (i = 0; i < sc->sc_nsense; i++) {
    448   1.4    nonaka 		pin = sc->sc_sense_array[i];
    449   1.4    nonaka 		if (pin == -1)
    450   1.4    nonaka 			continue;
    451   1.4    nonaka 		pxa2x0_gpio_clear_intr(pin);
    452   1.2     peter 	}
    453   1.1      ober 
    454   1.1      ober 	/* process after resetting interrupt */
    455   1.1      ober 	zkbd_modstate = (
    456   1.1      ober 		(sc->sc_keystate[84] ? (1 << 0) : 0) | /* shift */
    457   1.1      ober 		(sc->sc_keystate[93] ? (1 << 1) : 0) | /* Fn */
    458   1.1      ober 		(sc->sc_keystate[14] ? (1 << 2) : 0)); /* 'alt' */
    459   1.1      ober 
    460   1.2     peter 	for (i = 0; i < sc->sc_nsense * sc->sc_nstrobe; i++) {
    461  1.14    nonaka 		stuck = 0;
    462   1.1      ober 		/* extend  xt_keymap to do this faster. */
    463   1.1      ober 		/* ignore 'stuck' keys' */
    464  1.16   tsutsui 		for (j = 0; j < sc->sc_nstuck; j++) {
    465  1.16   tsutsui 			if (sc->sc_stuck_keys[j] == i) {
    466   1.2     peter 				stuck = 1;
    467   1.1      ober 				break;
    468   1.1      ober 			}
    469   1.1      ober 		}
    470   1.1      ober 		if (stuck)
    471   1.1      ober 			continue;
    472   1.2     peter 
    473   1.1      ober 		keystate = sc->sc_keystate[i];
    474   1.1      ober 		keysdown |= keystate; /* if any keys held */
    475   1.1      ober 
    476   1.1      ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    477  1.14    nonaka 		if (sc->sc_polling == 0 && sc->sc_rawkbd) {
    478  1.14    nonaka 			if ((keystate) || (sc->sc_okeystate[i] != keystate)) {
    479  1.14    nonaka 				c = sc->sc_xt_keymap[i];
    480   1.1      ober 				if (c & 0x80) {
    481   1.1      ober 					cbuf[ncbuf++] = 0xe0;
    482   1.1      ober 				}
    483   1.1      ober 				cbuf[ncbuf] = c & 0x7f;
    484   1.1      ober 
    485   1.1      ober 				if (keystate) {
    486   1.1      ober 					if (c & 0x80) {
    487   1.1      ober 						sc->sc_rep[npress++] = 0xe0;
    488   1.1      ober 					}
    489   1.1      ober 					sc->sc_rep[npress++] = c & 0x7f;
    490   1.1      ober 				} else {
    491   1.1      ober 					cbuf[ncbuf] |= 0x80;
    492   1.1      ober 				}
    493   1.1      ober 				ncbuf++;
    494   1.1      ober 				sc->sc_okeystate[i] = keystate;
    495   1.1      ober 			}
    496   1.1      ober 		}
    497   1.1      ober #endif
    498   1.1      ober 
    499  1.14    nonaka 		if ((!sc->sc_rawkbd) && (sc->sc_okeystate[i] != keystate)) {
    500   1.1      ober 			type = keystate ? WSCONS_EVENT_KEY_DOWN :
    501   1.1      ober 			    WSCONS_EVENT_KEY_UP;
    502   1.1      ober 
    503   1.1      ober 			if (sc->sc_polling) {
    504   1.1      ober 				sc->sc_pollkey = i;
    505   1.1      ober 				sc->sc_pollUD = type;
    506   1.1      ober 			} else {
    507   1.1      ober 				wskbd_input(sc->sc_wskbddev, type, i);
    508   1.1      ober 			}
    509   1.1      ober 
    510   1.1      ober 			sc->sc_okeystate[i] = keystate;
    511   1.1      ober 		}
    512   1.1      ober 	}
    513   1.1      ober 
    514   1.1      ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    515  1.14    nonaka 	if (sc->sc_polling == 0 && sc->sc_rawkbd) {
    516   1.1      ober 		wskbd_rawinput(sc->sc_wskbddev, cbuf, ncbuf);
    517   1.1      ober 		sc->sc_nrep = npress;
    518   1.1      ober 		if (npress != 0)
    519   1.1      ober 			callout_schedule(&sc->sc_rawrepeat_ch,
    520   1.1      ober 			    hz * REP_DELAY1 / 1000);
    521   1.1      ober 		else
    522   1.1      ober 			callout_stop(&sc->sc_rawrepeat_ch);
    523   1.1      ober 	}
    524   1.1      ober #endif
    525   1.1      ober 	if (keysdown)
    526   1.1      ober 		callout_schedule(&sc->sc_roll_to, hz * REP_DELAYN / 1000 / 2);
    527   1.1      ober 	else
    528   1.1      ober 		callout_stop(&sc->sc_roll_to);	/* always cancel? */
    529   1.1      ober 
    530   1.1      ober 	splx(s);
    531   1.1      ober }
    532   1.1      ober 
    533   1.1      ober #if NAPM > 0
    534   1.1      ober extern	int kbd_reset;
    535   1.1      ober extern	int apm_suspends;
    536   1.1      ober static	int zkbdondown;				/* on key is pressed */
    537   1.1      ober static	struct timeval zkbdontv = { 0, 0 };	/* last on key event */
    538   1.1      ober const	struct timeval zkbdhalttv = { 3, 0 };	/*  3s for safe shutdown */
    539   1.1      ober const	struct timeval zkbdsleeptv = { 0, 250000 };	/* .25s for suspend */
    540   1.1      ober extern	int lid_suspend;
    541   1.1      ober #endif
    542   1.1      ober 
    543   1.1      ober static int
    544   1.1      ober zkbd_on(void *v)
    545   1.1      ober {
    546   1.1      ober #if NAPM > 0
    547   1.1      ober 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    548  1.16   tsutsui 	int down;
    549  1.16   tsutsui 
    550  1.16   tsutsui 	if (sc->sc_onkey_pin < 0)
    551  1.16   tsutsui 		return 1;
    552  1.16   tsutsui 
    553  1.16   tsutsui 	down = pxa2x0_gpio_get_bit(sc->sc_onkey_pin) ? 1 : 0;
    554   1.1      ober 
    555   1.1      ober 	/*
    556   1.1      ober 	 * Change run mode depending on how long the key is held down.
    557   1.1      ober 	 * Ignore the key if it gets pressed while the lid is closed.
    558   1.1      ober 	 *
    559   1.1      ober 	 * Keys can bounce and we have to work around missed interrupts.
    560   1.1      ober 	 * Only the second edge is detected upon exit from sleep mode.
    561   1.1      ober 	 */
    562   1.1      ober 	if (down) {
    563   1.1      ober 		if (sc->sc_hinge == 3) {
    564   1.1      ober 			zkbdondown = 0;
    565   1.1      ober 		} else {
    566   1.1      ober 			microuptime(&zkbdontv);
    567   1.1      ober 			zkbdondown = 1;
    568   1.1      ober 		}
    569   1.1      ober 	} else if (zkbdondown) {
    570   1.1      ober 		if (ratecheck(&zkbdontv, &zkbdhalttv)) {
    571   1.1      ober 			if (kbd_reset == 1) {
    572   1.1      ober 				kbd_reset = 0;
    573   1.1      ober 				psignal(initproc, SIGUSR1);
    574   1.1      ober 			}
    575   1.1      ober 		} else if (ratecheck(&zkbdontv, &zkbdsleeptv)) {
    576   1.1      ober 			apm_suspends++;
    577   1.1      ober 		}
    578   1.1      ober 		zkbdondown = 0;
    579   1.1      ober 	}
    580   1.1      ober #endif
    581   1.1      ober 	return 1;
    582   1.1      ober }
    583   1.1      ober 
    584   1.1      ober static int
    585   1.1      ober zkbd_sync(void *v)
    586   1.1      ober {
    587   1.1      ober 
    588   1.1      ober 	return 1;
    589   1.1      ober }
    590   1.1      ober 
    591   1.1      ober static int
    592   1.1      ober zkbd_hinge(void *v)
    593   1.1      ober {
    594   1.1      ober 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    595  1.16   tsutsui 	int a, b;
    596  1.16   tsutsui 
    597  1.16   tsutsui 	if (sc->sc_swa_pin < 0 || sc->sc_swb_pin < 0)
    598  1.16   tsutsui 		return 1;
    599  1.16   tsutsui 
    600  1.16   tsutsui 	a = pxa2x0_gpio_get_bit(sc->sc_swa_pin) ? 1 : 0;
    601  1.16   tsutsui 	b = pxa2x0_gpio_get_bit(sc->sc_swb_pin) ? 2 : 0;
    602   1.1      ober 
    603   1.1      ober 	sc->sc_hinge = a | b;
    604   1.1      ober 
    605   1.1      ober 	if (sc->sc_hinge == 3) {
    606   1.1      ober #if NAPM > 0
    607   1.1      ober 		if (lid_suspend)
    608   1.1      ober 			apm_suspends++;
    609   1.1      ober #endif
    610  1.15   tsutsui #if NLCDCTL > 0
    611  1.15   tsutsui 		lcdctl_blank(true);
    612  1.15   tsutsui #endif
    613   1.1      ober 	} else {
    614  1.15   tsutsui #if NLCDCTL > 0
    615  1.15   tsutsui 		lcdctl_blank(false);
    616  1.15   tsutsui #endif
    617   1.1      ober 	}
    618   1.1      ober 
    619   1.1      ober 	return 1;
    620   1.1      ober }
    621   1.1      ober 
    622   1.1      ober static int
    623   1.1      ober zkbd_enable(void *v, int on)
    624   1.1      ober {
    625   1.1      ober 
    626   1.1      ober 	return 0;
    627   1.1      ober }
    628   1.1      ober 
    629   1.1      ober void
    630   1.1      ober zkbd_set_leds(void *v, int on)
    631   1.1      ober {
    632   1.1      ober }
    633   1.1      ober 
    634   1.1      ober static int
    635   1.3  christos zkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
    636   1.1      ober {
    637   1.1      ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    638   1.1      ober 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
    639   1.1      ober #endif
    640   1.1      ober 
    641   1.1      ober 	switch (cmd) {
    642   1.1      ober 	case WSKBDIO_GTYPE:
    643   1.1      ober 		*(int *)data = WSKBD_TYPE_ZAURUS;
    644   1.1      ober 		return 0;
    645   1.1      ober 
    646   1.1      ober 	case WSKBDIO_SETLEDS:
    647   1.1      ober 		return 0;
    648   1.1      ober 
    649   1.1      ober 	case WSKBDIO_GETLEDS:
    650   1.1      ober 		*(int *)data = 0;
    651   1.1      ober 		return 0;
    652   1.1      ober 
    653   1.1      ober #ifdef WSDISPLAY_COMPAT_RAWKBD
    654   1.1      ober 	case WSKBDIO_SETMODE:
    655   1.1      ober 		sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
    656   1.1      ober 		callout_stop(&sc->sc_rawrepeat_ch);
    657   1.1      ober 		return 0;
    658   1.1      ober #endif
    659   1.1      ober 
    660   1.1      ober 	}
    661   1.2     peter 	return EPASSTHROUGH;
    662   1.1      ober }
    663   1.1      ober 
    664   1.1      ober /* implement polling for zaurus_kbd */
    665   1.1      ober static void
    666   1.1      ober zkbd_cngetc(void *v, u_int *type, int *data)
    667   1.1      ober {
    668   1.2     peter 	struct zkbd_softc *sc = (struct zkbd_softc *)zkbd_sc;
    669   1.1      ober 
    670   1.1      ober 	sc->sc_pollkey = -1;
    671   1.1      ober 	sc->sc_pollUD = -1;
    672   1.1      ober 	sc->sc_polling = 1;
    673   1.1      ober 	while (sc->sc_pollkey == -1) {
    674   1.2     peter 		zkbd_poll(sc);
    675   1.1      ober 		DELAY(10000);	/* XXX */
    676   1.1      ober 	}
    677   1.1      ober 	sc->sc_polling = 0;
    678   1.1      ober 	*data = sc->sc_pollkey;
    679   1.1      ober 	*type = sc->sc_pollUD;
    680   1.1      ober }
    681   1.1      ober 
    682   1.1      ober static void
    683   1.1      ober zkbd_cnpollc(void *v, int on)
    684   1.1      ober {
    685   1.1      ober }
    686   1.1      ober 
    687   1.9    nonaka static bool
    688  1.11    dyoung zkbd_resume(device_t dv, const pmf_qual_t *qual)
    689   1.1      ober {
    690   1.9    nonaka 	struct zkbd_softc *sc = device_private(dv);
    691   1.9    nonaka 
    692   1.9    nonaka 	zkbd_hinge(sc);
    693   1.1      ober 
    694   1.9    nonaka 	return true;
    695   1.1      ober }
    696