solve polled adb keyboard problems with dropped keys and unsynced caps lock

by queueing polled keys.
This commit is contained in:
dbj 2002-02-24 20:20:20 +00:00
parent 31ae0ac1e9
commit 5f15cedc89
2 changed files with 59 additions and 20 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: akbd.c,v 1.20 2002/02/23 10:51:50 dbj Exp $ */
/* $NetBSD: akbd.c,v 1.21 2002/02/24 20:20:20 dbj Exp $ */
/*
* Copyright (C) 1998 Colin Wood
@ -64,6 +64,7 @@ static int akbdmatch __P((struct device *, struct cfdata *, void *));
static void akbdattach __P((struct device *, struct device *, void *));
void kbd_adbcomplete __P((caddr_t buffer, caddr_t data_area, int adb_command));
static void kbd_processevent __P((adb_event_t *event, struct akbd_softc *));
static void kbd_passup __P((struct akbd_softc *sc, int));
#ifdef notyet
static u_char getleds __P((int));
static int setleds __P((struct akbd_softc *, u_char));
@ -243,7 +244,7 @@ akbdattach(parent, self, aux)
#endif
if (akbd_is_console) {
wskbd_cnattach(&akbd_consops, NULL, &akbd_keymapdata);
wskbd_cnattach(&akbd_consops, sc, &akbd_keymapdata);
}
a.console = akbd_is_console;
@ -465,31 +466,53 @@ akbd_ioctl(v, cmd, data, flag, p)
return -1;
}
static int polledkey;
extern int adb_polling;
void
kbd_passup(sc,key)
struct akbd_softc *sc;
int key;
{
if (sc->sc_polling) {
if (sc->sc_npolledkeys <
(sizeof(sc->sc_polledkeys)/sizeof(unsigned char))) {
sc->sc_polledkeys[sc->sc_npolledkeys++] = key;
}
#ifdef ADB_DEBUG
else {
printf("akbd: dumping polled key 0x%02x\n",key);
}
#endif
} else {
int press, val;
int type;
press = ADBK_PRESS(key);
val = ADBK_KEYVAL(key);
type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
wskbd_input(sc->sc_wskbddev, type, val);
}
}
int
kbd_intr(arg)
void *arg;
{
adb_event_t *event = arg;
int key, press, val;
int type;
int key;
struct akbd_softc *sc = akbd_cd.cd_devs[0];
key = event->u.k.key;
press = ADBK_PRESS(key);
val = ADBK_KEYVAL(key);
type = press ? WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
switch (key) {
case 57: /* Caps Lock pressed */
case 185: /* Caps Lock released */
type = WSCONS_EVENT_KEY_DOWN;
wskbd_input(sc->sc_wskbddev, type, val);
type = WSCONS_EVENT_KEY_UP;
key = ADBK_KEYDOWN(ADBK_KEYVAL(key));
kbd_passup(sc,key);
key = ADBK_KEYUP(ADBK_KEYVAL(key));
break;
case 245:
if (pcmcia_soft_eject)
@ -501,10 +524,7 @@ kbd_intr(arg)
break;
}
if (adb_polling)
polledkey = key;
else
wskbd_input(sc->sc_wskbddev, type, val);
kbd_passup(sc,key);
return 0;
}
@ -525,20 +545,25 @@ akbd_cngetc(v, type, data)
{
int key, press, val;
int s;
struct akbd_softc *sc = v;
s = splhigh();
polledkey = -1;
KASSERT(sc->sc_polling);
KASSERT(adb_polling);
while (polledkey == -1) {
while (sc->sc_npolledkeys == 0) {
adb_intr();
DELAY(10000); /* XXX */
}
splx(s);
key = polledkey;
key = sc->sc_polledkeys[0];
sc->sc_npolledkeys--;
memmove(sc->sc_polledkeys,sc->sc_polledkeys+1,
sc->sc_npolledkeys * sizeof(unsigned char));
press = ADBK_PRESS(key);
val = ADBK_KEYVAL(key);
@ -551,5 +576,14 @@ akbd_cnpollc(v, on)
void *v;
int on;
{
struct akbd_softc *sc = v;
sc->sc_polling = on;
if (!on) {
int i;
for(i=0;i<sc->sc_npolledkeys;i++) {
kbd_passup(sc,sc->sc_polledkeys[i]);
}
sc->sc_npolledkeys = 0;
}
adb_polling = on;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: akbdvar.h,v 1.4 1999/02/17 14:56:56 tsubai Exp $ */
/* $NetBSD: akbdvar.h,v 1.5 2002/02/24 20:20:20 dbj Exp $ */
/*
* Copyright (C) 1998 Colin Wood
@ -48,6 +48,11 @@ struct akbd_softc {
u_int8_t sc_leds; /* current LED state */
struct device *sc_wskbddev;
int sc_polling;
int sc_npolledkeys;
unsigned char sc_polledkeys[32];
};
/* LED register bits, inverse of actual register value */