Home | History | Annotate | Line # | Download | only in wscons
wskbd.c revision 1.1
      1 /* $NetBSD: wskbd.c,v 1.1 1998/03/22 14:24:03 drochner Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *      This product includes software developed by Christopher G. Demetriou
     17  *	for the NetBSD Project.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 static const char _copyright[] __attribute__ ((unused)) =
     34     "Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.";
     35 static const char _rcsid[] __attribute__ ((unused)) =
     36     "$NetBSD: wskbd.c,v 1.1 1998/03/22 14:24:03 drochner Exp $";
     37 
     38 /*
     39  * Copyright (c) 1992, 1993
     40  *	The Regents of the University of California.  All rights reserved.
     41  *
     42  * This software was developed by the Computer Systems Engineering group
     43  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
     44  * contributed to Berkeley.
     45  *
     46  * All advertising materials mentioning features or use of this software
     47  * must display the following acknowledgement:
     48  *	This product includes software developed by the University of
     49  *	California, Lawrence Berkeley Laboratory.
     50  *
     51  * Redistribution and use in source and binary forms, with or without
     52  * modification, are permitted provided that the following conditions
     53  * are met:
     54  * 1. Redistributions of source code must retain the above copyright
     55  *    notice, this list of conditions and the following disclaimer.
     56  * 2. Redistributions in binary form must reproduce the above copyright
     57  *    notice, this list of conditions and the following disclaimer in the
     58  *    documentation and/or other materials provided with the distribution.
     59  * 3. All advertising materials mentioning features or use of this software
     60  *    must display the following acknowledgement:
     61  *	This product includes software developed by the University of
     62  *	California, Berkeley and its contributors.
     63  * 4. Neither the name of the University nor the names of its contributors
     64  *    may be used to endorse or promote products derived from this software
     65  *    without specific prior written permission.
     66  *
     67  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     68  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     69  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     70  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     71  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     72  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     73  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     74  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     75  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     76  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     77  * SUCH DAMAGE.
     78  *
     79  *	@(#)kbd.c	8.2 (Berkeley) 10/30/93
     80  */
     81 
     82 /*
     83  * Keyboard driver (/dev/wskbd*).  Translates incoming bytes to ASCII or
     84  * to `wscons_events' and passes them up to the appropriate reader.
     85  */
     86 
     87 #include <sys/param.h>
     88 #include <sys/conf.h>
     89 #include <sys/device.h>
     90 #include <sys/ioctl.h>
     91 #include <sys/kernel.h>
     92 #include <sys/proc.h>
     93 #include <sys/syslog.h>
     94 #include <sys/systm.h>
     95 #include <sys/tty.h>
     96 #include <sys/signalvar.h>
     97 #include <sys/errno.h>
     98 #include <sys/fcntl.h>
     99 
    100 #include <dev/wscons/wsconsio.h>
    101 #include <dev/wscons/wskbdvar.h>
    102 #include <dev/wscons/wseventvar.h>
    103 #include <dev/wscons/wscons_callbacks.h>
    104 
    105 struct wskbd_softc {
    106 	struct device	sc_dv;
    107 
    108 	const struct wskbd_accessops *sc_accessops;
    109 	void		*sc_accesscookie;
    110 
    111 	int		sc_ready;	/* accepting events */
    112 	struct wseventvar sc_events;	/* event queue state */
    113 
    114 	int	sc_isconsole;
    115 	struct device	*sc_displaydv;
    116 
    117 	struct wskbd_bell_data sc_bell_data;
    118 	struct wskbd_keyrepeat_data sc_keyrepeat_data;
    119 
    120 	int	sc_repeating;		/* we've called timeout() */
    121 	const u_char *sc_repeatstr;	/* repeated character (string) */
    122 	u_int	sc_repeatstrlen;	/* repeated character (string) len */
    123 
    124 	int	sc_translating;		/* xlate to chars for emulation */
    125 };
    126 
    127 #ifdef __BROKEN_INDIRECT_CONFIG
    128 int	wskbd_match __P((struct device *, void *, void *));
    129 #else
    130 int	wskbd_match __P((struct device *, struct cfdata *, void *));
    131 #endif
    132 void	wskbd_attach __P((struct device *, struct device *, void *));
    133 
    134 struct cfattach wskbd_ca = {
    135 	sizeof (struct wskbd_softc), wskbd_match, wskbd_attach,
    136 };
    137 
    138 extern struct cfdriver wskbd_cd;
    139 
    140 #ifndef WSKBD_DEFAULT_BELL_PITCH
    141 #define	WSKBD_DEFAULT_BELL_PITCH	1500	/* 1500Hz */
    142 #endif
    143 #ifndef WSKBD_DEFAULT_BELL_PERIOD
    144 #define	WSKBD_DEFAULT_BELL_PERIOD	100	/* 100ms */
    145 #endif
    146 #ifndef WSKBD_DEFAULT_BELL_VOLUME
    147 #define	WSKBD_DEFAULT_BELL_VOLUME	50	/* 50% volume */
    148 #endif
    149 
    150 struct wskbd_bell_data wskbd_default_bell_data = {
    151 	WSKBD_BELL_DOALL,
    152 	WSKBD_DEFAULT_BELL_PITCH,
    153 	WSKBD_DEFAULT_BELL_PERIOD,
    154 	WSKBD_DEFAULT_BELL_VOLUME,
    155 };
    156 
    157 #ifndef WSKBD_DEFAULT_KEYREPEAT_DEL1
    158 #define	WSKBD_DEFAULT_KEYREPEAT_DEL1	400	/* 400ms to start repeating */
    159 #endif
    160 #ifndef WSKBD_DEFAULT_KEYREPEAT_DELN
    161 #define	WSKBD_DEFAULT_KEYREPEAT_DELN	100	/* 100ms to between repeats */
    162 #endif
    163 
    164 struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = {
    165 	WSKBD_KEYREPEAT_DOALL,
    166 	WSKBD_DEFAULT_KEYREPEAT_DEL1,
    167 	WSKBD_DEFAULT_KEYREPEAT_DELN,
    168 };
    169 
    170 cdev_decl(wskbd);
    171 static void wskbd_repeat __P((void *v));
    172 
    173 static int wskbd_console_initted;
    174 static struct wskbd_softc *wskbd_console_device;
    175 static const struct wskbd_consops *wskbd_console_ops;
    176 static void *wskbd_console_cookie;
    177 
    178 /*
    179  * Print function (for parent devices).
    180  */
    181 int
    182 wskbddevprint(aux, pnp)
    183 	void *aux;
    184 	const char *pnp;
    185 {
    186 #if 0
    187 	struct wskbddev_attach_args *ap = aux;
    188 #endif
    189 
    190 	if (pnp)
    191 		printf("wskbd at %s", pnp);
    192 #if 0
    193 	printf(" console %d", ap->console);
    194 #endif
    195 
    196 	return (UNCONF);
    197 }
    198 
    199 int
    200 #ifdef __BROKEN_INDIRECT_CONFIG
    201 wskbd_match(parent, matchv, aux)
    202 #else
    203 wskbd_match(parent, match, aux)
    204 #endif
    205 	struct device *parent;
    206 #ifdef __BROKEN_INDIRECT_CONFIG
    207 	void *matchv;
    208 #else
    209 	struct cfdata *match;
    210 #endif
    211 	void *aux;
    212 {
    213 #ifdef __BROKEN_INDIRECT_CONFIG
    214 	struct cfdata *match = matchv;
    215 #endif
    216 	struct wskbddev_attach_args *ap = aux;
    217 
    218 	if (match->wskbddevcf_console != WSKBDDEVCF_CONSOLE_UNK) {
    219 		/*
    220 		 * If console-ness of device specified, either match
    221 		 * exactly (at high priority), or fail.
    222 		 */
    223 		if (match->wskbddevcf_console != 0 && ap->console != 0)
    224 			return (10);
    225 		else
    226 			return (0);
    227 	}
    228 
    229 	/* If console-ness unspecified, it wins. */
    230 	return (1);
    231 }
    232 
    233 void
    234 wskbd_attach(parent, self, aux)
    235 	struct device *parent, *self;
    236 	void *aux;
    237 {
    238 	struct wskbd_softc *sc = (struct wskbd_softc *)self;
    239 	struct wskbddev_attach_args *ap = aux;
    240 
    241 	if (ap->console)
    242 		printf(": console keyboard");
    243 	printf("\n");
    244 
    245 	sc->sc_accessops = ap->accessops;
    246 	sc->sc_accesscookie = ap->accesscookie;
    247 	sc->sc_ready = 0;				/* sanity */
    248 	sc->sc_repeating = 0;
    249 	sc->sc_translating = 1;
    250 
    251 	if (ap->console) {
    252 		KASSERT(wskbd_console_initted);
    253 		KASSERT(wskbd_console_device == NULL);
    254 		wskbd_console_device = sc;
    255 	}
    256 	sc->sc_isconsole = ap->console;
    257 	sc->sc_displaydv = NULL;
    258 
    259 	/* set default bell and key repeat data */
    260 	sc->sc_bell_data = wskbd_default_bell_data;
    261 	sc->sc_keyrepeat_data = wskbd_default_keyrepeat_data;
    262 }
    263 
    264 void
    265 wskbd_cnattach(consops, cookie)
    266 	const struct wskbd_consops *consops;
    267 	void *cookie;
    268 {
    269 
    270 	KASSERT(!wskbd_console_initted);
    271 
    272 	wskbd_console_ops = consops;
    273 	wskbd_console_cookie = cookie;
    274 
    275 	wsdisplay_set_cons_kbd(wskbd_cngetc, wskbd_cnpollc);
    276 
    277 	wskbd_console_initted = 1;
    278 }
    279 
    280 static void
    281 wskbd_repeat(v)
    282 	void *v;
    283 {
    284 	struct wskbd_softc *sc = (struct wskbd_softc *)v;
    285 	int s = spltty();
    286 
    287 	KASSERT(sc->sc_repeating);
    288 	if (sc->sc_repeatstrlen != 0) {
    289 		if (sc->sc_displaydv != NULL)
    290 			wsdisplay_kbdinput(sc->sc_displaydv, sc->sc_repeatstr,
    291 			    sc->sc_repeatstrlen);
    292 		timeout(wskbd_repeat, sc,
    293 		    (hz * sc->sc_keyrepeat_data.delN) / 1000);
    294 	}
    295 	splx(s);
    296 }
    297 
    298 void
    299 wskbd_input(dev, type, value)
    300 	struct device *dev;
    301 	u_int type;
    302 	int value;
    303 {
    304 	struct wskbd_softc *sc = (struct wskbd_softc *)dev;
    305 	struct wscons_event *ev;
    306 	struct timeval xxxtime;
    307 	const char *cp;
    308 	int put;
    309 
    310 	if (sc->sc_repeating) {
    311 		sc->sc_repeating = 0;
    312 		untimeout(wskbd_repeat, sc);
    313 	}
    314 
    315 	/*
    316 	 * If /dev/kbd is not connected in event mode translate and
    317 	 * send upstream.
    318 	 */
    319 	if (sc->sc_translating) {
    320 		cp = (*sc->sc_accessops->translate)(sc->sc_accesscookie,
    321 		    type, value);
    322 		if (cp != NULL) {
    323 			sc->sc_repeatstr = cp;
    324 			sc->sc_repeatstrlen = strlen(cp);
    325 			if (sc->sc_repeatstrlen != 0) {
    326 				if (sc->sc_displaydv != NULL)
    327 					wsdisplay_kbdinput(sc->sc_displaydv,
    328 					    sc->sc_repeatstr,
    329 					    sc->sc_repeatstrlen);
    330 
    331 				sc->sc_repeating = 1;
    332 				timeout(wskbd_repeat, sc,
    333 				    (hz * sc->sc_keyrepeat_data.del1) / 1000);
    334 			}
    335 		}
    336 		return;
    337 	}
    338 
    339 	/*
    340 	 * Keyboard is generating events.  Turn this keystroke into an
    341 	 * event and put it in the queue.  If the queue is full, the
    342 	 * keystroke is lost (sorry!).
    343 	 */
    344 
    345 	/* no one to receive; punt!*/
    346 	if (!sc->sc_ready)
    347 		return;
    348 
    349 	put = sc->sc_events.put;
    350 	ev = &sc->sc_events.q[put];
    351 	put = (put + 1) % WSEVENT_QSIZE;
    352 	if (put == sc->sc_events.get) {
    353 		log(LOG_WARNING, "%s: event queue overflow\n",
    354 		    sc->sc_dv.dv_xname);
    355 		return;
    356 	}
    357 	ev->type = type;
    358 	ev->value = value;
    359 	microtime(&xxxtime);
    360 	TIMEVAL_TO_TIMESPEC(&xxxtime, &ev->time);
    361 	sc->sc_events.put = put;
    362 	WSEVENT_WAKEUP(&sc->sc_events);
    363 }
    364 
    365 void wskbd_ctlinput(dev, val)
    366 	struct device *dev;
    367 	int val;
    368 {
    369 	struct wskbd_softc *sc = (struct wskbd_softc *)dev;
    370 
    371 	if (sc->sc_displaydv != NULL)
    372 		wsdisplay_switch(sc->sc_displaydv, val); /* XXX XXX */
    373 }
    374 
    375 void
    376 wskbd_holdscreen(dev, hold)
    377 	struct device *dev;
    378 	int hold;
    379 {
    380 	struct wskbd_softc *sc = (struct wskbd_softc *)dev;
    381 
    382 	if (sc->sc_displaydv != NULL)
    383 		wsdisplay_kbdholdscreen(sc->sc_displaydv, hold);
    384 }
    385 
    386 int
    387 wskbdopen(dev, flags, mode, p)
    388 	dev_t dev;
    389 	int flags, mode;
    390 	struct proc *p;
    391 {
    392 	struct wskbd_softc *sc;
    393 	int unit;
    394 
    395 	unit = minor(dev);
    396 	if (unit >= wskbd_cd.cd_ndevs ||	/* make sure it was attached */
    397 	    (sc = wskbd_cd.cd_devs[unit]) == NULL)
    398 		return (ENXIO);
    399 
    400 	if (sc->sc_events.io)			/* and that it's not in use */
    401 		return (EBUSY);
    402 
    403 	sc->sc_events.io = p;
    404 	wsevent_init(&sc->sc_events);		/* may cause sleep */
    405 
    406 	sc->sc_ready = 1;			/* start accepting events */
    407 
    408 	/* XXX ENABLE THE DEVICE IF NOT CONSOLE? */
    409 
    410 	return (0);
    411 }
    412 
    413 int
    414 wskbdclose(dev, flags, mode, p)
    415 	dev_t dev;
    416 	int flags, mode;
    417 	struct proc *p;
    418 {
    419 	struct wskbd_softc *sc;
    420 	int unit;
    421 
    422 	unit = minor(dev);
    423 	if (unit >= wskbd_cd.cd_ndevs ||	/* make sure it was attached */
    424 	    (sc = wskbd_cd.cd_devs[unit]) == NULL)
    425 		return (ENXIO);
    426 
    427 	/* XXX DISABLE THE DEVICE IF NOT CONSOLE? */
    428 
    429 	sc->sc_ready = 0;			/* stop accepting events */
    430 	wsevent_fini(&sc->sc_events);
    431 	sc->sc_events.io = NULL;
    432 	return (0);
    433 }
    434 
    435 int
    436 wskbdread(dev, uio, flags)
    437 	dev_t dev;
    438 	struct uio *uio;
    439 	int flags;
    440 {
    441 	struct wskbd_softc *sc;
    442 	int unit;
    443 
    444 	unit = minor(dev);
    445 	if (unit >= wskbd_cd.cd_ndevs ||	/* make sure it was attached */
    446 	    (sc = wskbd_cd.cd_devs[unit]) == NULL)
    447 		return (ENXIO);
    448 
    449 	return (wsevent_read(&sc->sc_events, uio, flags));
    450 }
    451 
    452 int
    453 wskbdioctl(dev, cmd, data, flag, p)
    454 	dev_t dev;
    455 	u_long cmd;
    456 	caddr_t data;
    457 	int flag;
    458 	struct proc *p;
    459 {
    460 	struct wskbd_softc *sc;
    461 	int unit, error;
    462 
    463 	unit = minor(dev);
    464 	if (unit >= wskbd_cd.cd_ndevs ||	/* make sure it was attached */
    465 	    (sc = wskbd_cd.cd_devs[unit]) == NULL)
    466 		return (ENXIO);
    467 
    468 	/*
    469 	 * Try the generic ioctls that the wskbd interface supports.
    470 	 */
    471 	switch (cmd) {
    472 	case FIONBIO:		/* we will remove this someday (soon???) */
    473 		return (0);
    474 
    475 	case FIOASYNC:
    476 		sc->sc_events.async = *(int *)data != 0;
    477 		return (0);
    478 
    479 	case TIOCSPGRP:
    480 		if (*(int *)data != sc->sc_events.io->p_pgid)
    481 			return (EPERM);
    482 		return (0);
    483 	}
    484 
    485 	/*
    486 	 * Try the keyboard driver for WSKBDIO ioctls.  It returns -1
    487 	 * if it didn't recognize the request.
    488 	 */
    489 	error = wskbd_displayioctl((struct device *)sc, cmd, data, flag, p);
    490 	return (error != -1 ? error : ENOTTY);
    491 }
    492 
    493 /*
    494  * WSKBDIO ioctls, handled in both emulation mode and in ``raw'' mode.
    495  * Some of these have no real effect in raw mode, however.
    496  */
    497 int
    498 wskbd_displayioctl(dev, cmd, data, flag, p)
    499 	struct device *dev;
    500 	u_long cmd;
    501 	caddr_t data;
    502 	int flag;
    503 	struct proc *p;
    504 {
    505 	struct wskbd_softc *sc = (struct wskbd_softc *)dev;
    506 	struct wskbd_bell_data *ubdp, *kbdp;
    507 	struct wskbd_keyrepeat_data *ukdp, *kkdp;
    508 	int error;
    509 
    510 	switch (cmd) {
    511 #define	SETBELL(dstp, srcp, dfltp)					\
    512     do {								\
    513 	(dstp)->pitch = ((srcp)->which & WSKBD_BELL_DOPITCH) ?		\
    514 	    (srcp)->pitch : (dfltp)->pitch;				\
    515 	(dstp)->period = ((srcp)->which & WSKBD_BELL_DOPERIOD) ?	\
    516 	    (srcp)->period : (dfltp)->period;				\
    517 	(dstp)->volume = ((srcp)->which & WSKBD_BELL_DOVOLUME) ?	\
    518 	    (srcp)->volume : (dfltp)->volume;				\
    519 	(dstp)->which = WSKBD_BELL_DOALL;				\
    520     } while (0)
    521 
    522 	case WSKBDIO_BELL:
    523 		if ((flag & FWRITE) == 0)
    524 			return (EACCES);
    525 		return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
    526 		    WSKBDIO_COMPLEXBELL, (caddr_t)&sc->sc_bell_data, flag, p));
    527 
    528 	case WSKBDIO_COMPLEXBELL:
    529 		if ((flag & FWRITE) == 0)
    530 			return (EACCES);
    531 		ubdp = (struct wskbd_bell_data *)data;
    532 		SETBELL(ubdp, ubdp, &sc->sc_bell_data);
    533 		return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
    534 		    WSKBDIO_COMPLEXBELL, (caddr_t)ubdp, flag, p));
    535 
    536 	case WSKBDIO_SETBELL:
    537 		if ((flag & FWRITE) == 0)
    538 			return (EACCES);
    539 		kbdp = &sc->sc_bell_data;
    540 setbell:
    541 		ubdp = (struct wskbd_bell_data *)data;
    542 		SETBELL(kbdp, ubdp, kbdp);
    543 		return (0);
    544 
    545 	case WSKBDIO_GETBELL:
    546 		kbdp = &sc->sc_bell_data;
    547 getbell:
    548 		ubdp = (struct wskbd_bell_data *)data;
    549 		SETBELL(ubdp, kbdp, kbdp);
    550 		return (0);
    551 
    552 	case WSKBDIO_SETDEFAULTBELL:
    553 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    554 			return (error);
    555 		kbdp = &wskbd_default_bell_data;
    556 		goto setbell;
    557 
    558 
    559 	case WSKBDIO_GETDEFAULTBELL:
    560 		kbdp = &wskbd_default_bell_data;
    561 		goto getbell;
    562 
    563 #undef SETBELL
    564 
    565 #define	SETKEYREPEAT(dstp, srcp, dfltp)					\
    566     do {								\
    567 	(dstp)->del1 = ((srcp)->which & WSKBD_KEYREPEAT_DODEL1) ?	\
    568 	    (srcp)->del1 : (dfltp)->del1;				\
    569 	(dstp)->delN = ((srcp)->which & WSKBD_KEYREPEAT_DODELN) ?	\
    570 	    (srcp)->delN : (dfltp)->delN;				\
    571 	(dstp)->which = WSKBD_KEYREPEAT_DOALL;				\
    572     } while (0)
    573 
    574 	case WSKBDIO_SETKEYREPEAT:
    575 		if ((flag & FWRITE) == 0)
    576 			return (EACCES);
    577 		kkdp = &sc->sc_keyrepeat_data;
    578 setkeyrepeat:
    579 		ukdp = (struct wskbd_keyrepeat_data *)data;
    580 		SETKEYREPEAT(kkdp, ukdp, kkdp);
    581 		return (0);
    582 
    583 	case WSKBDIO_GETKEYREPEAT:
    584 		kkdp = &sc->sc_keyrepeat_data;
    585 getkeyrepeat:
    586 		ukdp = (struct wskbd_keyrepeat_data *)data;
    587 		SETKEYREPEAT(ukdp, kkdp, kkdp);
    588 		return (0);
    589 
    590 	case WSKBDIO_SETDEFAULTKEYREPEAT:
    591 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    592 			return (error);
    593 		kkdp = &wskbd_default_keyrepeat_data;
    594 		goto setkeyrepeat;
    595 
    596 
    597 	case WSKBDIO_GETDEFAULTKEYREPEAT:
    598 		kkdp = &wskbd_default_keyrepeat_data;
    599 		goto getkeyrepeat;
    600 
    601 #undef SETKEYREPEAT
    602 	}
    603 
    604 	/*
    605 	 * Try the keyboard driver for WSKBDIO ioctls.  It returns -1
    606 	 * if it didn't recognize the request, and in turn we return
    607 	 * -1 if we didn't recognize the request.
    608 	 */
    609 /* printf("kbdaccess\n"); */
    610 	return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd,
    611 	    data, flag, p));
    612 }
    613 
    614 int
    615 wskbdpoll(dev, events, p)
    616 	dev_t dev;
    617 	int events;
    618 	struct proc *p;
    619 {
    620 	struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
    621 
    622 	return (wsevent_poll(&sc->sc_events, events, p));
    623 }
    624 
    625 int
    626 wskbd_is_console(dv)
    627 	struct device *dv;
    628 {
    629 	struct wskbd_softc *sc = (struct wskbd_softc *)dv;
    630 
    631 	KASSERT(sc != NULL);
    632 	return (sc->sc_isconsole);
    633 }
    634 
    635 struct device *
    636 wskbd_display(dv)
    637 	struct device *dv;
    638 {
    639 	struct wskbd_softc *sc = (struct wskbd_softc *)dv;
    640 
    641 	KASSERT(sc != NULL);
    642 	return (sc->sc_displaydv);
    643 }
    644 
    645 void
    646 wskbd_set_display(dv, displaydv)
    647 	struct device *dv, *displaydv;
    648 {
    649 	struct wskbd_softc *sc = (struct wskbd_softc *)dv;
    650 
    651 	KASSERT(sc != NULL);
    652 	sc->sc_displaydv = displaydv;
    653 }
    654 
    655 void
    656 wskbd_set_translation(dv, on)
    657 	struct device *dv;
    658 	int on;
    659 {
    660 	struct wskbd_softc *sc = (struct wskbd_softc *)dv;
    661 
    662 	KASSERT(sc != NULL);
    663 	sc->sc_translating = on;
    664 }
    665 
    666 /*
    667  * Console interface.
    668  */
    669 int
    670 wskbd_cngetc(dev)
    671 	dev_t dev;
    672 {
    673 
    674 	if (!wskbd_console_initted)
    675 		return 0;
    676 
    677 	if (wskbd_console_device != NULL &&
    678 	    !wskbd_console_device->sc_translating)
    679 		return 0;
    680 
    681 	return ((*wskbd_console_ops->getc)(wskbd_console_cookie));
    682 }
    683 
    684 void
    685 wskbd_cnpollc(dev, poll)
    686 	dev_t dev;
    687 	int poll;
    688 {
    689 
    690 	if (!wskbd_console_initted)
    691 		return;
    692 
    693 	if (wskbd_console_device != NULL &&
    694 	    !wskbd_console_device->sc_translating)
    695 		return;
    696 
    697 	(*wskbd_console_ops->pollc)(wskbd_console_cookie, poll);
    698 }
    699