Пример #1
0
static int
btnmgr_hook(void *ctx, int type, long id, void *msg)
{
	struct btnmgr_softc *sc = ctx;

	DPRINTF(("%s button: %s\n", btnmgr_name(id), msg ? "ON" : "OFF"));

	if (button_config[id].kevent) {
		u_int evtype;
		evtype = msg ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
#ifdef WSDISPLAY_COMPAT_RAWKBD
		if (sc->sc_rawkbd) {
			int n;
			u_char data[16];
			n = pckbd_encode(evtype, button_config[id].keycode,
			    data);
			wskbd_rawinput(sc->sc_wskbddev, data, n);
		} else
#endif
			wskbd_input(sc->sc_wskbddev, evtype,
			    button_config[id].keycode);
	}

	if (id == CONFIG_HOOK_BUTTONEVENT_POWER && msg)
		config_hook_call(CONFIG_HOOK_PMEVENT,
		    CONFIG_HOOK_PMEVENT_SUSPENDREQ, NULL);
	else if (id == CONFIG_HOOK_BUTTONEVENT_COVER)
		config_hook_call(CONFIG_HOOK_POWERCONTROL,
		    CONFIG_HOOK_POWERCONTROL_LCDLIGHT, (void*)(msg ? 0: 1));

	return (0);
}
Пример #2
0
static void
omkbd_input(void *v, int data)
{
    struct ws_softc *sc = v;
    u_int type;
    int key;

    omkbd_decode(v, data, &type, &key);

#ifdef WSDISPLAY_COMPAT_RAWKBD
    if (sc->sc_rawkbd) {
        uint8_t cbuf[2];
        int c, j = 0;

        c = omkbd_raw[key];
        if (c != 0x00) {
            /* fake extended scancode if necessary */
            if (c & 0x80)
                cbuf[j++] = 0xe0;
            cbuf[j] = c & 0x7f;
            if (type == WSCONS_EVENT_KEY_UP)
                cbuf[j] |= 0x80;
            j++;

            wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
        }
    } else
#endif
    {
        if (sc->sc_wskbddev != NULL)
            wskbd_input(sc->sc_wskbddev, type, key);
    }
}
Пример #3
0
void
zskbd_wskbd_input(struct zs_chanstate *cs, uint8_t key)
{
	struct zskbd_softc     *sc = cs->cs_private;
	u_int			type;
#ifdef WSDISPLAY_COMPAT_RAWKBD
	int			s;
#endif

	if (sc->sc_dc->wskbddev == NULL)
		return;	/* why bother */

	if (key & ZSKBD_KEY_UP) {
		if ((key & ZSKBD_KEY_ALL_UP) == ZSKBD_KEY_ALL_UP)
			type = WSCONS_EVENT_ALL_KEYS_UP;
		else
			type = WSCONS_EVENT_KEY_UP;
	} else
		type = WSCONS_EVENT_KEY_DOWN;

	wskbd_input(sc->sc_dc->wskbddev, type, (key & ~ZSKBD_KEY_UP));

	DPRINTF(("zskbd_wskbd_input: inputted key 0x%x\n", key));

#ifdef WSDISPLAY_COMPAT_RAWKBD
	if (sc->sc_rawkbd &&
	    type != WSCONS_EVENT_ALL_KEYS_UP) {
		s = spltty();
		wskbd_rawinput(sc->sc_dc->wskbddev, &key, 1);
		splx(s);
	}
#endif
}
Пример #4
0
void
sunkbd_input(struct sunkbd_softc *sc, u_int8_t *buf, u_int buflen)
{
	u_int type;
	int value;
	int s;

	if (sc->sc_wskbddev == NULL)
		return;	/* why bother */

#ifdef WSDISPLAY_COMPAT_RAWKBD
	if (sc->sc_rawkbd) {
		u_char rbuf[SUNKBD_MAX_INPUT_SIZE * 2];
		int c, rlen, npress;

		timeout_del(&sc->sc_rawrepeat_tmo);

		npress = rlen = 0;
		while (buflen-- != 0) {
			(*sc->sc_decode)(*buf++, &type, &value);
			c = sunkbd_rawmap[value];
			if (c == RAWKEY_Null)
				continue;
			/* fake extended scancode if necessary */
			if (c & 0x80)
				rbuf[rlen++] = 0xe0;
			rbuf[rlen] = c & 0x7f;
			if (type == WSCONS_EVENT_KEY_UP)
				rbuf[rlen] |= 0x80;
			else {
				/* remember down keys for autorepeat */
				if (c & 0x80)
					sc->sc_rep[npress++] = 0xe0;
				sc->sc_rep[npress++] = c & 0x7f;
			}
			rlen++;
		}

		s = spltty();
		wskbd_rawinput(sc->sc_wskbddev, rbuf, rlen);
		splx(s);
		sc->sc_nrep = npress;
		if (npress != 0)
			timeout_add_msec(&sc->sc_rawrepeat_tmo, REP_DELAY1);
	} else
#endif
	{
		s = spltty();
		while (buflen-- != 0) {
			(*sc->sc_decode)(*buf++, &type, &value);
			wskbd_input(sc->sc_wskbddev, type, value);
		}
		splx(s);
	}
}
Пример #5
0
void
sunkbd_rawrepeat(void *v)
{
	struct sunkbd_softc *sc = v;
	int s;

	s = spltty();
	wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
	splx(s);
	timeout_add_msec(&sc->sc_rawrepeat_tmo, REP_DELAYN);
}
Пример #6
0
static void
zkbd_rawrepeat(void *v)
{
	struct zkbd_softc *sc = (struct zkbd_softc *)v;
	int s;

	s = spltty();
	wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
	splx(s);
	callout_schedule(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000);
}
Пример #7
0
void
ukbd_rawrepeat(void *v)
{
	struct ukbd_softc *sc = v;
	int s;

	s = spltty();
	wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
	splx(s);
	timeout_add(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000);
}
Пример #8
0
static void
btkbd_repeat(void *arg)
{
	struct btkbd_softc *sc = arg;
	int s;

	s = spltty();
	wskbd_rawinput(sc->sc_wskbd, sc->sc_rep, sc->sc_nrep);
	splx(s);
	callout_schedule(&sc->sc_repeat, hz * REP_DELAYN / 1000);
}
Пример #9
0
void
ukbd_rawrepeat(void *v)
{
	struct ukbd_softc *sc = v;
	int s;

	s = spltty();
	wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
	splx(s);
	usb_callout(sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000,
	    ukbd_rawrepeat, sc);
}
Пример #10
0
void
akbd_input(struct akbd_softc *sc, int key)
{
	int press, val;
	int type;

	press = ADBK_PRESS(key);
	val = ADBK_KEYVAL(key);

	type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;

	if (adb_polling) {
		adb_polledkey = key;
#ifdef WSDISPLAY_COMPAT_RAWKBD
	} else if (sc->sc_rawkbd) {
		char cbuf[MAXKEYS *2];
		int c, j, s;
		int npress;

		j = npress = 0;

		c = keyboard[val];
		if (c == 0) {
			return; /* XXX */
		}
		if (c & 0x80)
			cbuf[j++] = 0xe0;
		cbuf[j] = c & 0x7f;
		if (type == WSCONS_EVENT_KEY_UP) {
			cbuf[j] |= 0x80;
		} else {
			/* this only records last key pressed */
			if (c & 0x80)
				sc->sc_rep[npress++] = 0xe0;
			sc->sc_rep[npress++] = c & 0x7f;
		}
		j++;
		s = spltty();
		wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
		splx(s);
		timeout_del(&sc->sc_rawrepeat_ch);
		sc->sc_nrep = npress;
		if (npress != 0)
			timeout_add(&sc->sc_rawrepeat_ch, hz * REP_DELAY1/1000);
#endif
	} else {
		wskbd_input(sc->sc_wskbddev, type, val);
	}
}
Пример #11
0
void
dnevent_kbd_internal(struct dnkbd_softc *sc, int dat)
{
	u_int type;
	int key;
	int s;

	dnkbd_decode(dat, &type, &key);

#ifdef WSDISPLAY_COMPAT_RAWKBD
	if (sc->sc_rawkbd) {
		u_char cbuf[2];
		int c, j = 0;

		c = dnkbd_raw[key];
		if (c != RAWKEY_Null) {
			/* fake extended scancode if necessary */
			if (c & 0x80)
				cbuf[j++] = 0xe0;
			cbuf[j] = c & 0x7f;
			if (type == WSCONS_EVENT_KEY_UP)
				cbuf[j] |= 0x80;
			else {
				/* remember pressed key for autorepeat */
				bcopy(cbuf, sc->sc_rep, sizeof(sc->sc_rep));
			}
			j++;
		}

		if (j != 0) {
			s = spltty();
			wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
			splx(s);
			timeout_del(&sc->sc_rawrepeat_ch);
			sc->sc_nrep = j;
			timeout_add(&sc->sc_rawrepeat_ch,
			    (hz * REP_DELAY1) / 1000);
		}
	} else
#endif
	{
		s = spltty();
		wskbd_input(sc->sc_wskbddev, type, key);
		splx(s);
	}
}
Пример #12
0
/*
 * Got a console receive interrupt -
 * the console processor wants to give us a character.
 */
void
pckbd_input(void *vsc, int data)
{
	struct pckbd_softc *sc = vsc;
	int key;
	u_int type;

#ifdef WSDISPLAY_COMPAT_RAWKBD
	if (sc->rawkbd) {
		u_char d = data;
		wskbd_rawinput(sc->sc_wskbddev, &d, 1);
		return;
	}
#endif
	if (pckbd_decode(sc->id, data, &type, &key))
		wskbd_input(sc->sc_wskbddev, type, key);
}
Пример #13
0
static void
kbd_input_wskbd(struct kbd_softc *k, int code)
{
	int type, key;

#ifdef WSDISPLAY_COMPAT_RAWKBD
	if (k->k_wsraw) {
		u_char buf;

		buf = code;
		wskbd_rawinput(k->k_wskbd, &buf, 1);
		return;
	}
#endif

	type = KEY_UP(code) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
	key = KEY_CODE(code);
	wskbd_input(k->k_wskbd, type, key);
}
Пример #14
0
void
akbd_input(struct akbd_softc *sc, int key)
{
	int press, val;
	int type;

	press = ADBK_PRESS(key);
	val = ADBK_KEYVAL(key);

	if (sc->sc_iso)
		val = akbd_iso_swap(val);

	type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;

	if (adb_polling) {
		adb_polledkey = key;
#ifdef WSDISPLAY_COMPAT_RAWKBD
	} else if (sc->sc_rawkbd) {
		char cbuf[2];
		int c, j, s;

		j = 0;

		c = keyboard[val];
		if (c == 0) {
			return; /* XXX */
		}
		if (c & 0x80)
			cbuf[j++] = 0xe0;
		cbuf[j] = c & 0x7f;
		if (type == WSCONS_EVENT_KEY_UP)
			cbuf[j] |= 0x80;
		j++;
		s = spltty();
		wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
		splx(s);
#endif
	} else {
		wskbd_input(sc->sc_wskbddev, type, val);
	}
}
Пример #15
0
static void
ewskbd_wskbd_input(struct zs_chanstate *cs, uint8_t key)
{
	struct ewskbd_softc *sc;
	u_int type;

	sc = cs->cs_private;

	if (key & EWSKBD_KEY_UP)
		type = WSCONS_EVENT_KEY_UP;
	else
		type = WSCONS_EVENT_KEY_DOWN;

	wskbd_input(sc->sc_dc->wskbddev, type, (key & EWSKBD_KEY_MASK));

	DPRINTF(("ewskbd_wskbd_input: inputted key 0x%x\n", key));

#ifdef WSDISPLAY_COMPAT_RAWKBD
	wskbd_rawinput(sc->sc_dc->wskbddev, &key, 1);
#endif
}
Пример #16
0
static void
btkbd_input(struct bthidev *hidev, uint8_t *data, int len)
{
	struct btkbd_softc *sc = (struct btkbd_softc *)hidev;
	struct btkbd_data *ud = &sc->sc_ndata;
	uint16_t ibuf[MAXKEYS];
	uint32_t mod, omod;
	int nkeys, i, j;
	int key;
	int s;

	if (sc->sc_wskbd == NULL || sc->sc_enabled == 0)
		return;

	/* extract key modifiers */
	ud->modifiers = 0;
	for (i = 0 ; i < sc->sc_nmod ; i++)
		if (hid_get_data(data, &sc->sc_modloc[i]))
			ud->modifiers |= sc->sc_mods[i].mask;

	/* extract keycodes */
	memcpy(ud->keycode, data + (sc->sc_keycodeloc.pos / 8),
	       sc->sc_nkeycode);

	if (ud->keycode[0] == KEY_ERROR)
		return;		/* ignore  */

	nkeys = 0;
	mod = ud->modifiers;
	omod = sc->sc_odata.modifiers;
	if (mod != omod)
		for (i = 0 ; i < sc->sc_nmod ; i++)
			if ((mod & sc->sc_mods[i].mask) !=
			    (omod & sc->sc_mods[i].mask))
				ADDKEY(sc->sc_mods[i].key |
				       (mod & sc->sc_mods[i].mask
					  ? PRESS : RELEASE));

	if (memcmp(ud->keycode, sc->sc_odata.keycode, sc->sc_nkeycode) != 0) {
		/* Check for released keys. */
		for (i = 0 ; i < sc->sc_nkeycode ; i++) {
			key = sc->sc_odata.keycode[i];
			if (key == 0)
				continue;

			for (j = 0 ; j < sc->sc_nkeycode ; j++)
				if (key == ud->keycode[j])
					goto rfound;

			ADDKEY(key | RELEASE);

		rfound:
			;
		}

		/* Check for pressed keys. */
		for (i = 0 ; i < sc->sc_nkeycode ; i++) {
			key = ud->keycode[i];
			if (key == 0)
				continue;

			for (j = 0; j < sc->sc_nkeycode; j++)
				if (key == sc->sc_odata.keycode[j])
					goto pfound;

			ADDKEY(key | PRESS);
		pfound:
			;
		}
	}
	sc->sc_odata = *ud;

	if (nkeys == 0)
		return;

#ifdef WSDISPLAY_COMPAT_RAWKBD
	if (sc->sc_rawkbd) {
		u_char cbuf[MAXKEYS * 2];
		int c;
		int npress;

		for (npress = i = j = 0 ; i < nkeys ; i++) {
			key = ibuf[i];
			c = btkbd_trtab[key & CODEMASK];
			if (c == NN)
				continue;

			if (c & 0x80)
				cbuf[j++] = 0xe0;

			cbuf[j] = c & 0x7f;
			if (key & RELEASE)
				cbuf[j] |= 0x80;
#ifdef BTKBD_REPEAT
			else {
				/* remember pressed keys for autorepeat */
				if (c & 0x80)
					sc->sc_rep[npress++] = 0xe0;

				sc->sc_rep[npress++] = c & 0x7f;
			}
#endif

			j++;
		}

		s = spltty();
		wskbd_rawinput(sc->sc_wskbd, cbuf, j);
		splx(s);
#ifdef BTKBD_REPEAT
		callout_stop(&sc->sc_repeat);
		if (npress != 0) {
			sc->sc_nrep = npress;
			callout_schedule(&sc->sc_repeat, hz * REP_DELAY1 / 1000);
		}
#endif
		return;
	}
#endif

	s = spltty();
	for (i = 0 ; i < nkeys ; i++) {
		key = ibuf[i];
		wskbd_input(sc->sc_wskbd,
		    key & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
		    key & CODEMASK);
	}
	splx(s);
}
Пример #17
0
static inline void
adbkbd_key(struct adbkbd_softc *sc, uint8_t k)
{

	if (sc->sc_poll) {
		if (sc->sc_polled_chars >= 16) {
			aprint_error_dev(sc->sc_dev,"polling buffer is full\n");
		}
		sc->sc_pollbuf[sc->sc_polled_chars] = k;
		sc->sc_polled_chars++;
		return;
	}

#if NWSMOUSE > 0
	/* translate some keys to mouse events */
	if (sc->sc_wsmousedev != NULL) {
		if (ADBK_KEYVAL(k) == sc->sc_trans[1]) {
			wsmouse_input(sc->sc_wsmousedev, ADBK_PRESS(k) ? 2 : 0,
			      0, 0, 0, 0,
			      WSMOUSE_INPUT_DELTA);
			return;
		}			
		if (ADBK_KEYVAL(k) == sc->sc_trans[2]) {
			wsmouse_input(sc->sc_wsmousedev, ADBK_PRESS(k) ? 4 : 0,
			      0, 0, 0, 0,
			      WSMOUSE_INPUT_DELTA);
			return;
		}			
	}
#endif

#ifdef WSDISPLAY_COMPAT_RAWKBD
	if (sc->sc_rawkbd) {
		char cbuf[2];
		int s;

		cbuf[0] = k;

		s = spltty();
		wskbd_rawinput(sc->sc_wskbddev, cbuf, 1);
		splx(s);
	} else {
#endif

	if (ADBK_KEYVAL(k) == 0x39) {
		/* caps lock - send up and down */
		if (ADBK_PRESS(k) != sc->sc_capslock) {
			sc->sc_capslock = ADBK_PRESS(k);
			wskbd_input(sc->sc_wskbddev,
			    WSCONS_EVENT_KEY_DOWN, 0x39);
			wskbd_input(sc->sc_wskbddev,
			    WSCONS_EVENT_KEY_UP, 0x39);
		}
	} else {
		/* normal event */
		int type;

		type = ADBK_PRESS(k) ? 
		    WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
		wskbd_input(sc->sc_wskbddev, type, ADBK_KEYVAL(k));
	}
#ifdef WSDISPLAY_COMPAT_RAWKBD
	}
#endif
}
Пример #18
0
void
ukbd_decode(struct ukbd_softc *sc, struct ukbd_data *ud)
{
	int mod, omod;
	u_int16_t ibuf[MAXKEYS];	/* chars events */
	int s;
	int nkeys, i, j;
	int key;
#define ADDKEY(c) ibuf[nkeys++] = (c)

#ifdef UKBD_DEBUG
	/*
	 * Keep a trace of the last events.  Using printf changes the
	 * timing, so this can be useful sometimes.
	 */
	if (ukbdtrace) {
		struct ukbdtraceinfo *p = &ukbdtracedata[ukbdtraceindex];
		p->unit = sc->sc_hdev.sc_dev.dv_unit;
		microtime(&p->tv);
		p->ud = *ud;
		if (++ukbdtraceindex >= UKBDTRACESIZE)
			ukbdtraceindex = 0;
	}
	if (ukbddebug > 5) {
		struct timeval tv;
		microtime(&tv);
		DPRINTF((" at %lu.%06lu  mod=0x%02x key0=0x%02x key1=0x%02x "
			 "key2=0x%02x key3=0x%02x\n",
			 tv.tv_sec, tv.tv_usec,
			 ud->modifiers, ud->keycode[0], ud->keycode[1],
			 ud->keycode[2], ud->keycode[3]));
	}
#endif

	if (ud->keycode[0] == KEY_ERROR) {
		DPRINTF(("ukbd_intr: KEY_ERROR\n"));
		return;		/* ignore  */
	}
	nkeys = 0;
	mod = ud->modifiers;
	omod = sc->sc_odata.modifiers;
	if (mod != omod)
		for (i = 0; i < sc->sc_nmod; i++)
			if (( mod & sc->sc_mods[i].mask) !=
			    (omod & sc->sc_mods[i].mask))
				ADDKEY(sc->sc_mods[i].key |
				       (mod & sc->sc_mods[i].mask
					  ? PRESS : RELEASE));
	if (memcmp(ud->keycode, sc->sc_odata.keycode, sc->sc_nkeycode) != 0) {
		/* Check for released keys. */
		for (i = 0; i < sc->sc_nkeycode; i++) {
			key = sc->sc_odata.keycode[i];
			if (key == 0)
				continue;
			for (j = 0; j < sc->sc_nkeycode; j++)
				if (key == ud->keycode[j])
					goto rfound;
			DPRINTFN(3,("ukbd_intr: relse key=0x%02x\n", key));
			ADDKEY(key | RELEASE);
		rfound:
			;
		}

		/* Check for pressed keys. */
		for (i = 0; i < sc->sc_nkeycode; i++) {
			key = ud->keycode[i];
			if (key == 0)
				continue;
			for (j = 0; j < sc->sc_nkeycode; j++)
				if (key == sc->sc_odata.keycode[j])
					goto pfound;
			DPRINTFN(2,("ukbd_intr: press key=0x%02x\n", key));
			ADDKEY(key | PRESS);
		pfound:
			;
		}
	}
	sc->sc_odata = *ud;

	if (nkeys == 0)
		return;

	if (sc->sc_polling) {
		DPRINTFN(1,("ukbd_intr: pollchar = 0x%03x\n", ibuf[0]));
		memcpy(sc->sc_pollchars, ibuf, nkeys * sizeof(u_int16_t));
		sc->sc_npollchar = nkeys;
		return;
	}
#ifdef WSDISPLAY_COMPAT_RAWKBD
	if (sc->sc_rawkbd) {
		u_char cbuf[MAXKEYS * 2];
		int c;
		int npress;

		for (npress = i = j = 0; i < nkeys; i++) {
			key = ibuf[i];
			c = ukbd_trtab[key & CODEMASK];
			if (c == NN)
				continue;
			if (c & 0x80)
				cbuf[j++] = 0xe0;
			cbuf[j] = c & 0x7f;
			if (key & RELEASE)
				cbuf[j] |= 0x80;
			else {
				/* remember pressed keys for autorepeat */
				if (c & 0x80)
					sc->sc_rep[npress++] = 0xe0;
				sc->sc_rep[npress++] = c & 0x7f;
			}
			DPRINTFN(1,("ukbd_intr: raw = %s0x%02x\n",
				    c & 0x80 ? "0xe0 " : "",
				    cbuf[j]));
			j++;
		}
		s = spltty();
		wskbd_rawinput(sc->sc_wskbddev, cbuf, j);
		splx(s);
		if (npress != 0) {
			sc->sc_nrep = npress;
			timeout_add(&sc->sc_rawrepeat_ch,
			    hz * REP_DELAY1 / 1000);
		} else
			timeout_del(&sc->sc_rawrepeat_ch);
		return;
	}
#endif

	s = spltty();
	for (i = 0; i < nkeys; i++) {
		key = ibuf[i];
		wskbd_input(sc->sc_wskbddev,
		    key&RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
		    key&CODEMASK);
	}
	splx(s);
}
Пример #19
0
static void
zkbd_poll(void *v)
{
	struct zkbd_softc *sc = (struct zkbd_softc *)v;
	int i, j, col, pin, type, keysdown = 0;
	int stuck;
	int keystate;
	int s;
#ifdef WSDISPLAY_COMPAT_RAWKBD
	int npress = 0, ncbuf = 0, c;
	char cbuf[MAXKEYS * 2];
#endif

	s = spltty();

	/* discharge all */
	for (i = 0; i < sc->sc_nstrobe; i++) {
		pin = sc->sc_strobe_array[i];
		if (pin == -1)
			continue;
		pxa2x0_gpio_clear_bit(pin);
		pxa2x0_gpio_set_dir(pin, GPIO_IN);
	}

	delay(10);
	for (col = 0; col < sc->sc_nstrobe; col++) {
		pin = sc->sc_strobe_array[col];
		if (pin == -1)
			continue;

		/* activate_col */
		pxa2x0_gpio_set_bit(pin);
		pxa2x0_gpio_set_dir(pin, GPIO_OUT);

		/* wait activate delay */
		delay(10);

		/* read row */
		for (i = 0; i < sc->sc_nsense; i++) {
			int bit;

			if (sc->sc_sense_array[i] == -1)
				continue;
			bit = pxa2x0_gpio_get_bit(sc->sc_sense_array[i]);
			if (bit && sc->sc_hinge && col < sc->sc_maxkbdcol)
				continue;
			sc->sc_keystate[i + (col * sc->sc_nsense)] = bit;
		}

		/* reset_col */
		pxa2x0_gpio_set_dir(pin, GPIO_IN);

		/* wait discharge delay */
		delay(10);
	}

	/* charge all */
	for (i = 0; i < sc->sc_nstrobe; i++) {
		pin = sc->sc_strobe_array[i];
		if (pin == -1)
			continue;
		pxa2x0_gpio_set_bit(pin);
		pxa2x0_gpio_set_dir(pin, GPIO_OUT);
	}

	/* force the irqs to clear as we have just played with them. */
	for (i = 0; i < sc->sc_nsense; i++) {
		pin = sc->sc_sense_array[i];
		if (pin == -1)
			continue;
		pxa2x0_gpio_clear_intr(pin);
	}

	/* process after resetting interrupt */
	zkbd_modstate = (
		(sc->sc_keystate[84] ? (1 << 0) : 0) | /* shift */
		(sc->sc_keystate[93] ? (1 << 1) : 0) | /* Fn */
		(sc->sc_keystate[14] ? (1 << 2) : 0)); /* 'alt' */

	for (i = 0; i < sc->sc_nsense * sc->sc_nstrobe; i++) {
		stuck = 0;
		/* extend  xt_keymap to do this faster. */
		/* ignore 'stuck' keys' */
		for (j = 0; j < sc->sc_nstuck; j++) {
			if (sc->sc_stuck_keys[j] == i) {
				stuck = 1;
				break;
			}
		}
		if (stuck)
			continue;

		keystate = sc->sc_keystate[i];
		keysdown |= keystate; /* if any keys held */

#ifdef WSDISPLAY_COMPAT_RAWKBD
		if (sc->sc_polling == 0 && sc->sc_rawkbd) {
			if ((keystate) || (sc->sc_okeystate[i] != keystate)) {
				c = sc->sc_xt_keymap[i];
				if (c & 0x80) {
					cbuf[ncbuf++] = 0xe0;
				}
				cbuf[ncbuf] = c & 0x7f;

				if (keystate) {
					if (c & 0x80) {
						sc->sc_rep[npress++] = 0xe0;
					}
					sc->sc_rep[npress++] = c & 0x7f;
				} else {
					cbuf[ncbuf] |= 0x80;
				}
				ncbuf++;
				sc->sc_okeystate[i] = keystate;
			}
		}
#endif

		if ((!sc->sc_rawkbd) && (sc->sc_okeystate[i] != keystate)) {
			type = keystate ? WSCONS_EVENT_KEY_DOWN :
			    WSCONS_EVENT_KEY_UP;

			if (sc->sc_polling) {
				sc->sc_pollkey = i;
				sc->sc_pollUD = type;
			} else {
				wskbd_input(sc->sc_wskbddev, type, i);
			}

			sc->sc_okeystate[i] = keystate;
		}
	}

#ifdef WSDISPLAY_COMPAT_RAWKBD
	if (sc->sc_polling == 0 && sc->sc_rawkbd) {
		wskbd_rawinput(sc->sc_wskbddev, cbuf, ncbuf);
		sc->sc_nrep = npress;
		if (npress != 0)
			callout_schedule(&sc->sc_rawrepeat_ch,
			    hz * REP_DELAY1 / 1000);
		else 
			callout_stop(&sc->sc_rawrepeat_ch);
	}
#endif
	if (keysdown)
		callout_schedule(&sc->sc_roll_to, hz * REP_DELAYN / 1000 / 2);
	else 
		callout_stop(&sc->sc_roll_to);	/* always cancel? */

	splx(s);
}