Home | History | Annotate | Line # | Download | only in sun
kbd.c revision 1.63
      1 /*	$NetBSD: kbd.c,v 1.63 2009/05/12 14:46:39 cegger Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1992, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * This software was developed by the Computer Systems Engineering group
      8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
      9  * contributed to Berkeley.
     10  *
     11  * All advertising materials mentioning features or use of this software
     12  * must display the following acknowledgement:
     13  *	This product includes software developed by the University of
     14  *	California, Lawrence Berkeley Laboratory.
     15  *
     16  * Redistribution and use in source and binary forms, with or without
     17  * modification, are permitted provided that the following conditions
     18  * are met:
     19  * 1. Redistributions of source code must retain the above copyright
     20  *    notice, this list of conditions and the following disclaimer.
     21  * 2. Redistributions in binary form must reproduce the above copyright
     22  *    notice, this list of conditions and the following disclaimer in the
     23  *    documentation and/or other materials provided with the distribution.
     24  * 3. Neither the name of the University nor the names of its contributors
     25  *    may be used to endorse or promote products derived from this software
     26  *    without specific prior written permission.
     27  *
     28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     38  * SUCH DAMAGE.
     39  *
     40  *	@(#)kbd.c	8.2 (Berkeley) 10/30/93
     41  */
     42 
     43 /*
     44  * Keyboard driver (/dev/kbd -- note that we do not have minor numbers
     45  * [yet?]).  Translates incoming bytes to ASCII or to `firm_events' and
     46  * passes them up to the appropriate reader.
     47  */
     48 
     49 #include <sys/cdefs.h>
     50 __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.63 2009/05/12 14:46:39 cegger Exp $");
     51 
     52 #include <sys/param.h>
     53 #include <sys/systm.h>
     54 #include <sys/conf.h>
     55 #include <sys/device.h>
     56 #include <sys/ioctl.h>
     57 #include <sys/kernel.h>
     58 #include <sys/proc.h>
     59 #include <sys/malloc.h>
     60 #include <sys/signal.h>
     61 #include <sys/signalvar.h>
     62 #include <sys/time.h>
     63 #include <sys/syslog.h>
     64 #include <sys/select.h>
     65 #include <sys/poll.h>
     66 #include <sys/file.h>
     67 
     68 #include <dev/wscons/wsksymdef.h>
     69 
     70 #include <dev/sun/kbd_reg.h>
     71 #include <dev/sun/kbio.h>
     72 #include <dev/sun/vuid_event.h>
     73 #include <dev/sun/event_var.h>
     74 #include <dev/sun/kbd_xlate.h>
     75 #include <dev/sun/kbdvar.h>
     76 
     77 #include "ioconf.h"
     78 #include "locators.h"
     79 
     80 dev_type_open(kbdopen);
     81 dev_type_close(kbdclose);
     82 dev_type_read(kbdread);
     83 dev_type_ioctl(kbdioctl);
     84 dev_type_poll(kbdpoll);
     85 dev_type_kqfilter(kbdkqfilter);
     86 
     87 const struct cdevsw kbd_cdevsw = {
     88 	kbdopen, kbdclose, kbdread, nowrite, kbdioctl,
     89 	nostop, notty, kbdpoll, nommap, kbdkqfilter, D_OTHER
     90 };
     91 
     92 #if NWSKBD > 0
     93 static int	wssunkbd_enable(void *, int);
     94 static void	wssunkbd_set_leds(void *, int);
     95 static int	wssunkbd_ioctl(void *, u_long, void *, int, struct lwp *);
     96 static void	sunkbd_wskbd_cngetc(void *, u_int *, int *);
     97 static void	sunkbd_wskbd_cnpollc(void *, int);
     98 static void	sunkbd_wskbd_cnbell(void *, u_int, u_int, u_int);
     99 static void	sunkbd_bell_off(void *v);
    100 static void	kbd_enable(device_t); /* deferred keyboard init */
    101 
    102 const struct wskbd_accessops sunkbd_wskbd_accessops = {
    103 	wssunkbd_enable,
    104 	wssunkbd_set_leds,
    105 	wssunkbd_ioctl,
    106 };
    107 
    108 extern const struct wscons_keydesc wssun_keydesctab[];
    109 const struct wskbd_mapdata sunkbd_wskbd_keymapdata = {
    110 	wssun_keydesctab,
    111 #ifdef SUNKBD_LAYOUT
    112 	SUNKBD_LAYOUT,
    113 #else
    114 	KB_US,
    115 #endif
    116 };
    117 
    118 const struct wskbd_consops sunkbd_wskbd_consops = {
    119         sunkbd_wskbd_cngetc,
    120         sunkbd_wskbd_cnpollc,
    121         sunkbd_wskbd_cnbell,
    122 };
    123 
    124 void kbd_wskbd_attach(struct kbd_softc *, int);
    125 #endif
    126 
    127 /* ioctl helpers */
    128 static int kbd_iockeymap(struct kbd_state *, u_long, struct kiockeymap *);
    129 #ifdef KIOCGETKEY
    130 static int kbd_oldkeymap(struct kbd_state *, u_long, struct okiockey *);
    131 #endif
    132 
    133 
    134 /* callbacks for console driver */
    135 static int kbd_cc_open(struct cons_channel *);
    136 static int kbd_cc_close(struct cons_channel *);
    137 
    138 /* console input */
    139 static void	kbd_input_console(struct kbd_softc *, int);
    140 static void	kbd_repeat(void *);
    141 static int	kbd_input_keysym(struct kbd_softc *, int);
    142 static void	kbd_input_string(struct kbd_softc *, char *);
    143 static void	kbd_input_funckey(struct kbd_softc *, int);
    144 static void	kbd_update_leds(struct kbd_softc *);
    145 
    146 #if NWSKBD > 0
    147 static void	kbd_input_wskbd(struct kbd_softc *, int);
    148 #endif
    149 
    150 /* firm events input */
    151 static void	kbd_input_event(struct kbd_softc *, int);
    152 
    153 
    154 
    155 /****************************************************************
    156  *  Entry points for /dev/kbd
    157  *  (open,close,read,write,...)
    158  ****************************************************************/
    159 
    160 /*
    161  * Open:
    162  * Check exclusion, open actual device (_iopen),
    163  * setup event channel, clear ASCII repeat stuff.
    164  */
    165 int
    166 kbdopen(dev_t dev, int flags, int mode, struct lwp *l)
    167 {
    168 	struct kbd_softc *k;
    169 	int error;
    170 
    171 	/* locate device */
    172 	k = device_lookup_private(&kbd_cd, minor(dev));
    173 	if (k == NULL)
    174 		return ENXIO;
    175 
    176 #if NWSKBD > 0
    177 	/*
    178 	 * NB: wscons support: while we can track if wskbd has called
    179 	 * enable(), we can't tell if that's for console input or for
    180 	 * events input, so we should probably just let the open to
    181 	 * always succeed regardless (e.g. Xsun opening /dev/kbd).
    182 	 */
    183 	if (!k->k_wsenabled)
    184 		wssunkbd_enable(k, 1);
    185 #endif
    186 
    187 	/* exclusive open required for /dev/kbd */
    188 	if (k->k_events.ev_io)
    189 		return EBUSY;
    190 	k->k_events.ev_io = l->l_proc;
    191 
    192 	/* stop pending autorepeat of console input */
    193 	if (k->k_repeating) {
    194 		k->k_repeating = 0;
    195 		callout_stop(&k->k_repeat_ch);
    196 	}
    197 
    198 	/* open actual underlying device */
    199 	if (k->k_ops != NULL && k->k_ops->open != NULL)
    200 		if ((error = (*k->k_ops->open)(k)) != 0) {
    201 			k->k_events.ev_io = NULL;
    202 			return error;
    203 		}
    204 
    205 	ev_init(&k->k_events);
    206 	k->k_evmode = 0;	/* XXX: OK? */
    207 
    208 	return 0;
    209 }
    210 
    211 
    212 /*
    213  * Close:
    214  * Turn off event mode, dump the queue, and close the keyboard
    215  * unless it is supplying console input.
    216  */
    217 int
    218 kbdclose(dev_t dev, int flags, int mode, struct lwp *l)
    219 {
    220 	struct kbd_softc *k;
    221 
    222 	k = device_lookup_private(&kbd_cd, minor(dev));
    223 	k->k_evmode = 0;
    224 	ev_fini(&k->k_events);
    225 	k->k_events.ev_io = NULL;
    226 
    227 	if (k->k_ops != NULL && k->k_ops->close != NULL) {
    228 		int error;
    229 		if ((error = (*k->k_ops->close)(k)) != 0)
    230 			return error;
    231 	}
    232 	return 0;
    233 }
    234 
    235 
    236 int
    237 kbdread(dev_t dev, struct uio *uio, int flags)
    238 {
    239 	struct kbd_softc *k;
    240 
    241 	k = device_lookup_private(&kbd_cd, minor(dev));
    242 	return ev_read(&k->k_events, uio, flags);
    243 }
    244 
    245 
    246 int
    247 kbdpoll(dev_t dev, int events, struct lwp *l)
    248 {
    249 	struct kbd_softc *k;
    250 
    251 	k = device_lookup_private(&kbd_cd, minor(dev));
    252 	return ev_poll(&k->k_events, events, l);
    253 }
    254 
    255 int
    256 kbdkqfilter(dev_t dev, struct knote *kn)
    257 {
    258 	struct kbd_softc *k;
    259 
    260 	k = device_lookup_private(&kbd_cd, minor(dev));
    261 	return ev_kqfilter(&k->k_events, kn);
    262 }
    263 
    264 int
    265 kbdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
    266 {
    267 	struct kbd_softc *k;
    268 	struct kbd_state *ks;
    269 	int error = 0;
    270 
    271 	k = device_lookup_private(&kbd_cd, minor(dev));
    272 	ks = &k->k_state;
    273 
    274 	switch (cmd) {
    275 
    276 	case KIOCTRANS: 	/* Set translation mode */
    277 		/* We only support "raw" mode on /dev/kbd */
    278 		if (*(int *)data != TR_UNTRANS_EVENT)
    279 			error = EINVAL;
    280 		break;
    281 
    282 	case KIOCGTRANS:	/* Get translation mode */
    283 		/* We only support "raw" mode on /dev/kbd */
    284 		*(int *)data = TR_UNTRANS_EVENT;
    285 		break;
    286 
    287 #ifdef KIOCGETKEY
    288 	case KIOCGETKEY:	/* Get keymap entry (old format) */
    289 		error = kbd_oldkeymap(ks, cmd, (struct okiockey *)data);
    290 		break;
    291 #endif /* KIOCGETKEY */
    292 
    293 	case KIOCSKEY:  	/* Set keymap entry */
    294 		/* FALLTHROUGH */
    295 	case KIOCGKEY:  	/* Get keymap entry */
    296 		error = kbd_iockeymap(ks, cmd, (struct kiockeymap *)data);
    297 		break;
    298 
    299 	case KIOCCMD:		/* Send a command to the keyboard */
    300 		/* pass it to the middle layer */
    301 		if (k->k_ops != NULL && k->k_ops->docmd != NULL)
    302 			error = (*k->k_ops->docmd)(k, *(int *)data, 1);
    303 		break;
    304 
    305 	case KIOCTYPE:		/* Get keyboard type */
    306 		*(int *)data = ks->kbd_id;
    307 		break;
    308 
    309 	case KIOCSDIRECT:	/* Where to send input */
    310 		k->k_evmode = *(int *)data;
    311 		break;
    312 
    313 	case KIOCLAYOUT:	/* Get keyboard layout */
    314 		*(int *)data = ks->kbd_layout;
    315 		break;
    316 
    317 	case KIOCSLED:		/* Set keyboard LEDs */
    318 		/* pass the request to the middle layer */
    319 		if (k->k_ops != NULL && k->k_ops->setleds != NULL)
    320 			error = (*k->k_ops->setleds)(k, *(char *)data, 1);
    321 		break;
    322 
    323 	case KIOCGLED:		/* Get keyboard LEDs */
    324 		*(char *)data = ks->kbd_leds;
    325 		break;
    326 
    327 	case FIONBIO:		/* we will remove this someday (soon???) */
    328 		break;
    329 
    330 	case FIOASYNC:
    331 		k->k_events.ev_async = (*(int *)data != 0);
    332 		break;
    333 
    334 	case FIOSETOWN:
    335 		if (-*(int *)data != k->k_events.ev_io->p_pgid
    336 		    && *(int *)data != k->k_events.ev_io->p_pid)
    337 			error = EPERM;
    338 		break;
    339 
    340 	case TIOCSPGRP:
    341 		if (*(int *)data != k->k_events.ev_io->p_pgid)
    342 			error = EPERM;
    343 		break;
    344 
    345 	default:
    346 		error = ENOTTY;
    347 		break;
    348 	}
    349 
    350 	return error;
    351 }
    352 
    353 
    354 /****************************************************************
    355  * ioctl helpers
    356  ****************************************************************/
    357 
    358 /*
    359  * Get/Set keymap entry
    360  */
    361 static int
    362 kbd_iockeymap(struct kbd_state *ks, u_long cmd, struct kiockeymap *kio)
    363 {
    364 	u_short *km;
    365 	u_int station;
    366 
    367 	switch (kio->kio_tablemask) {
    368 	case KIOC_NOMASK:
    369 		km = ks->kbd_k.k_normal;
    370 		break;
    371 	case KIOC_SHIFTMASK:
    372 		km = ks->kbd_k.k_shifted;
    373 		break;
    374 	case KIOC_CTRLMASK:
    375 		km = ks->kbd_k.k_control;
    376 		break;
    377 	case KIOC_UPMASK:
    378 		km = ks->kbd_k.k_release;
    379 		break;
    380 	default:
    381 		/* Silently ignore unsupported masks */
    382 		return 0;
    383 	}
    384 
    385 	/* Range-check the table position. */
    386 	station = kio->kio_station;
    387 	if (station >= KEYMAP_SIZE)
    388 		return EINVAL;
    389 
    390 	switch (cmd) {
    391 
    392 	case KIOCGKEY:	/* Get keymap entry */
    393 		kio->kio_entry = km[station];
    394 		break;
    395 
    396 	case KIOCSKEY:	/* Set keymap entry */
    397 		km[station] = kio->kio_entry;
    398 		break;
    399 
    400 	default:
    401 		return ENOTTY;
    402 	}
    403 	return 0;
    404 }
    405 
    406 
    407 #ifdef KIOCGETKEY
    408 /*
    409  * Get/Set keymap entry,
    410  * old format (compatibility)
    411  */
    412 int
    413 kbd_oldkeymap(struct kbd_state *ks, u_long cmd, struct okiockey *kio)
    414 {
    415 	int error = 0;
    416 
    417 	switch (cmd) {
    418 
    419 	case KIOCGETKEY:
    420 		if (kio->kio_station == 118) {
    421 			/*
    422 			 * This is X11 asking if a type 3 keyboard is
    423 			 * really a type 3 keyboard.  Say yes, it is,
    424 			 * by reporting key station 118 as a "hole".
    425 			 * Note old (SunOS 3.5) definition of HOLE!
    426 			 */
    427 			kio->kio_entry = 0xA2;
    428 			break;
    429 		}
    430 		/* fall through */
    431 
    432 	default:
    433 		error = ENOTTY;
    434 		break;
    435 	}
    436 
    437 	return error;
    438 }
    439 #endif /* KIOCGETKEY */
    440 
    441 
    442 
    443 /****************************************************************
    444  *  Keyboard input - called by middle layer at spltty().
    445  ****************************************************************/
    446 
    447 void
    448 kbd_input(struct kbd_softc *k, int code)
    449 {
    450 	if (k->k_evmode) {
    451 		/*
    452 		 * XXX: is this still true?
    453 		 * IDLEs confuse the MIT X11R4 server badly, so we must drop them.
    454 		 * This is bad as it means the server will not automatically resync
    455 		 * on all-up IDLEs, but I did not drop them before, and the server
    456 		 * goes crazy when it comes time to blank the screen....
    457 		 */
    458 		if (code == KBD_IDLE)
    459 			return;
    460 
    461 		/*
    462 		 * Keyboard is generating firm events.  Turn this keystroke
    463 		 * into an event and put it in the queue.
    464 		 */
    465 		kbd_input_event(k, code);
    466 		return;
    467 	}
    468 
    469 #if NWSKBD > 0
    470 	if (k->k_wskbd != NULL && k->k_wsenabled) {
    471 		/*
    472 		 * We are using wskbd input mode, pass the event up.
    473 		 */
    474 		if (code == KBD_IDLE)
    475 			return;	/* this key is not in the mapped */
    476 		kbd_input_wskbd(k, code);
    477 		return;
    478 	}
    479 #endif
    480 
    481 	/*
    482 	 * If /dev/kbd is not connected in event mode, or wskbd mode,
    483 	 * translate and send upstream (to console).
    484 	 */
    485 	kbd_input_console(k, code);
    486 }
    487 
    488 
    489 
    490 /****************************************************************
    491  *  Open/close routines called upon opening /dev/console
    492  *  if we serve console input.
    493  ****************************************************************/
    494 
    495 struct cons_channel *
    496 kbd_cc_alloc(struct kbd_softc *k)
    497 {
    498 	struct cons_channel *cc;
    499 
    500 	if ((cc = malloc(sizeof *cc, M_DEVBUF, M_NOWAIT)) == NULL)
    501 		return NULL;
    502 
    503 	/* our callbacks for the console driver */
    504 	cc->cc_private = k;
    505 	cc->cc_iopen = kbd_cc_open;
    506 	cc->cc_iclose = kbd_cc_close;
    507 
    508 	/* will be provided by the console driver so that we can feed input */
    509 	cc->cc_upstream = NULL;
    510 
    511 	/*
    512 	 * TODO: clean up cons_attach_input() vs kd_attach_input() in
    513 	 * lower layers and move that code here.
    514 	 */
    515 
    516 	k->k_cc = cc;
    517 	return cc;
    518 }
    519 
    520 
    521 static int
    522 kbd_cc_open(struct cons_channel *cc)
    523 {
    524 	struct kbd_softc *k;
    525 	int ret;
    526 
    527 	if (cc == NULL)
    528 		return 0;
    529 
    530 	k = cc->cc_private;
    531 	if (k == NULL)
    532 		return 0;
    533 
    534 	if (k->k_ops != NULL && k->k_ops->open != NULL)
    535 		ret = (*k->k_ops->open)(k);
    536 	else
    537 		ret = 0;
    538 
    539 	/* XXX: verify that callout is not active? */
    540 	k->k_repeat_start = hz/2;
    541 	k->k_repeat_step = hz/20;
    542 	callout_init(&k->k_repeat_ch, 0);
    543 
    544 	return ret;
    545 }
    546 
    547 
    548 static int
    549 kbd_cc_close(struct cons_channel *cc)
    550 {
    551 	struct kbd_softc *k;
    552 	int ret;
    553 
    554 	if (cc == NULL)
    555 		return 0;
    556 
    557 	k = cc->cc_private;
    558 	if (k == NULL)
    559 		return 0;
    560 
    561 	if (k->k_ops != NULL && k->k_ops->close != NULL)
    562 		ret = (*k->k_ops->close)(k);
    563 	else
    564 		ret = 0;
    565 
    566 	/* stop any pending auto-repeat */
    567 	if (k->k_repeating) {
    568 		k->k_repeating = 0;
    569 		callout_stop(&k->k_repeat_ch);
    570 	}
    571 
    572 	return ret;
    573 }
    574 
    575 
    576 
    577 /****************************************************************
    578  *  Console input - called by middle layer at spltty().
    579  ****************************************************************/
    580 
    581 static void
    582 kbd_input_console(struct kbd_softc *k, int code)
    583 {
    584 	struct kbd_state *ks= &k->k_state;
    585 	int keysym;
    586 
    587 	/* any input stops auto-repeat (i.e. key release) */
    588 	if (k->k_repeating) {
    589 		k->k_repeating = 0;
    590 		callout_stop(&k->k_repeat_ch);
    591 	}
    592 
    593 	keysym = kbd_code_to_keysym(ks, code);
    594 
    595 	/* pass to console */
    596 	if (kbd_input_keysym(k, keysym)) {
    597 		log(LOG_WARNING, "%s: code=0x%x with mod=0x%x"
    598 		    " produced unexpected keysym 0x%x\n",
    599 		    device_xname(k->k_dev),
    600 		    code, ks->kbd_modbits, keysym);
    601 		return;		/* no point in auto-repeat here */
    602 	}
    603 
    604 	if (KEYSYM_NOREPEAT(keysym))
    605 		return;
    606 
    607 	/* setup for auto-repeat after initial delay */
    608 	k->k_repeating = 1;
    609 	k->k_repeatsym = keysym;
    610 	callout_reset(&k->k_repeat_ch, k->k_repeat_start,
    611 		      kbd_repeat, k);
    612 }
    613 
    614 
    615 /*
    616  * This is the autorepeat callout function scheduled by kbd_input() above.
    617  * Called at splsoftclock().
    618  */
    619 static void
    620 kbd_repeat(void *arg)
    621 {
    622 	struct kbd_softc *k = arg;
    623 	int s;
    624 
    625 	s = spltty();
    626 	if (k->k_repeating && k->k_repeatsym >= 0) {
    627 		/* feed typematic keysym to the console */
    628 		(void)kbd_input_keysym(k, k->k_repeatsym);
    629 
    630 		/* reschedule next repeat */
    631 		callout_reset(&k->k_repeat_ch, k->k_repeat_step,
    632 			      kbd_repeat, k);
    633 	}
    634 	splx(s);
    635 }
    636 
    637 
    638 
    639 /*
    640  * Supply keysym as console input.  Convert keysym to character(s) and
    641  * pass them up to cons_channel's upstream hook.
    642  *
    643  * Return zero on success, else the keysym that we could not handle
    644  * (so that the caller may complain).
    645  */
    646 static int
    647 kbd_input_keysym(struct kbd_softc *k, int keysym)
    648 {
    649 	struct kbd_state *ks = &k->k_state;
    650 	int data;
    651 	/* Check if a recipient has been configured */
    652 	if (k->k_cc == NULL || k->k_cc->cc_upstream == NULL)
    653 		return 0;
    654 
    655 	switch (KEYSYM_CLASS(keysym)) {
    656 
    657 	case KEYSYM_ASCII:
    658 		data = KEYSYM_DATA(keysym);
    659 		if (ks->kbd_modbits & KBMOD_META_MASK)
    660 			data |= 0x80;
    661 		(*k->k_cc->cc_upstream)(data);
    662 		break;
    663 
    664 	case KEYSYM_STRING:
    665 		data = keysym & 0xF;
    666 		kbd_input_string(k, kbd_stringtab[data]);
    667 		break;
    668 
    669 	case KEYSYM_FUNC:
    670 		kbd_input_funckey(k, keysym);
    671 		break;
    672 
    673 	case KEYSYM_CLRMOD:
    674 		data = 1 << (keysym & 0x1F);
    675 		ks->kbd_modbits &= ~data;
    676 		break;
    677 
    678 	case KEYSYM_SETMOD:
    679 		data = 1 << (keysym & 0x1F);
    680 		ks->kbd_modbits |= data;
    681 		break;
    682 
    683 	case KEYSYM_INVMOD:
    684 		data = 1 << (keysym & 0x1F);
    685 		ks->kbd_modbits ^= data;
    686 		kbd_update_leds(k);
    687 		break;
    688 
    689 	case KEYSYM_ALL_UP:
    690 		ks->kbd_modbits &= ~0xFFFF;
    691 		break;
    692 
    693 	case KEYSYM_SPECIAL:
    694 		if (keysym == KEYSYM_NOP)
    695 			break;
    696 		/* FALLTHROUGH */
    697 	default:
    698 		/* We could not handle it. */
    699 		return keysym;
    700 	}
    701 
    702 	return 0;
    703 }
    704 
    705 
    706 /*
    707  * Send string upstream.
    708  */
    709 static void
    710 kbd_input_string(struct kbd_softc *k, char *str)
    711 {
    712 
    713 	while (*str) {
    714 		(*k->k_cc->cc_upstream)(*str);
    715 		++str;
    716 	}
    717 }
    718 
    719 
    720 /*
    721  * Format the F-key sequence and send as a string.
    722  * XXX: Ugly compatibility mappings.
    723  */
    724 static void
    725 kbd_input_funckey(struct kbd_softc *k, int keysym)
    726 {
    727 	int n;
    728 	char str[12];
    729 
    730 	n = 0xC0 + (keysym & 0x3F);
    731 	snprintf(str, sizeof(str), "\033[%dz", n);
    732 	kbd_input_string(k, str);
    733 }
    734 
    735 
    736 /*
    737  * Update LEDs to reflect console input state.
    738  */
    739 static void
    740 kbd_update_leds(struct kbd_softc *k)
    741 {
    742 	struct kbd_state *ks = &k->k_state;
    743 	char leds;
    744 
    745 	leds = ks->kbd_leds;
    746 	leds &= ~(LED_CAPS_LOCK|LED_NUM_LOCK);
    747 
    748 	if (ks->kbd_modbits & (1 << KBMOD_CAPSLOCK))
    749 		leds |= LED_CAPS_LOCK;
    750 	if (ks->kbd_modbits & (1 << KBMOD_NUMLOCK))
    751 		leds |= LED_NUM_LOCK;
    752 
    753 	if (k->k_ops != NULL && k->k_ops->setleds != NULL)
    754 		(void)(*k->k_ops->setleds)(k, leds, 0);
    755 }
    756 
    757 
    758 
    759 /****************************************************************
    760  *  Events input - called by middle layer at spltty().
    761  ****************************************************************/
    762 
    763 /*
    764  * Supply raw keystrokes when keyboard is open in firm event mode.
    765  *
    766  * Turn the keystroke into an event and put it in the queue.
    767  * If the queue is full, the keystroke is lost (sorry!).
    768  */
    769 static void
    770 kbd_input_event(struct kbd_softc *k, int code)
    771 {
    772 	struct firm_event *fe;
    773 	int put;
    774 
    775 #ifdef DIAGNOSTIC
    776 	if (!k->k_evmode) {
    777 		printf("%s: kbd_input_event called when not in event mode\n",
    778 		    device_xname(k->k_dev));
    779 		return;
    780 	}
    781 #endif
    782 	put = k->k_events.ev_put;
    783 	fe = &k->k_events.ev_q[put];
    784 	put = (put + 1) % EV_QSIZE;
    785 	if (put == k->k_events.ev_get) {
    786 		log(LOG_WARNING, "%s: event queue overflow\n",
    787 		    device_xname(k->k_dev));
    788 		return;
    789 	}
    790 
    791 	fe->id = KEY_CODE(code);
    792 	fe->value = KEY_UP(code) ? VKEY_UP : VKEY_DOWN;
    793 	firm_gettime(fe);
    794 	k->k_events.ev_put = put;
    795 	EV_WAKEUP(&k->k_events);
    796 }
    797 
    798 
    799 
    800 /****************************************************************
    801  *  Translation stuff declared in kbd_xlate.h
    802  ****************************************************************/
    803 
    804 /*
    805  * Initialization - called by either lower layer attach or by kdcninit.
    806  */
    807 void
    808 kbd_xlate_init(struct kbd_state *ks)
    809 {
    810 	struct keyboard *ktbls;
    811 	int id;
    812 
    813 	id = ks->kbd_id;
    814 	if (id < KBD_MIN_TYPE)
    815 		id = KBD_MIN_TYPE;
    816 	if (id > kbd_max_type)
    817 		id = kbd_max_type;
    818 	ktbls = keyboards[id];
    819 
    820 	ks->kbd_k = *ktbls; 	/* struct assignment */
    821 	ks->kbd_modbits = 0;
    822 }
    823 
    824 /*
    825  * Turn keyboard up/down codes into a KEYSYM.
    826  * Note that the "kd" driver (on sun3 and sparc64) uses this too!
    827  */
    828 int
    829 kbd_code_to_keysym(struct kbd_state *ks, int c)
    830 {
    831 	u_short *km;
    832 	int keysym;
    833 
    834 	/*
    835 	 * Get keymap pointer.  One of these:
    836 	 * release, control, shifted, normal, ...
    837 	 */
    838 	if (KEY_UP(c))
    839 		km = ks->kbd_k.k_release;
    840 	else if (ks->kbd_modbits & KBMOD_CTRL_MASK)
    841 		km = ks->kbd_k.k_control;
    842 	else if (ks->kbd_modbits & KBMOD_SHIFT_MASK)
    843 		km = ks->kbd_k.k_shifted;
    844 	else
    845 		km = ks->kbd_k.k_normal;
    846 
    847 	if (km == NULL) {
    848 		/*
    849 		 * Do not know how to translate yet.
    850 		 * We will find out when a RESET comes along.
    851 		 */
    852 		return KEYSYM_NOP;
    853 	}
    854 	keysym = km[KEY_CODE(c)];
    855 
    856 	/*
    857 	 * Post-processing for Caps-lock
    858 	 */
    859 	if ((ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) &&
    860 		(KEYSYM_CLASS(keysym) == KEYSYM_ASCII) )
    861 	{
    862 		if (('a' <= keysym) && (keysym <= 'z'))
    863 			keysym -= ('a' - 'A');
    864 	}
    865 
    866 	/*
    867 	 * Post-processing for Num-lock.  All "function"
    868 	 * keysyms get indirected through another table.
    869 	 * (XXX: Only if numlock on.  Want off also!)
    870 	 */
    871 	if ((ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) &&
    872 		(KEYSYM_CLASS(keysym) == KEYSYM_FUNC) )
    873 	{
    874 		keysym = kbd_numlock_map[keysym & 0x3F];
    875 	}
    876 
    877 	return keysym;
    878 }
    879 
    880 
    881 /*
    882  * Back door for rcons (fb.c)
    883  */
    884 void
    885 kbd_bell(int on)
    886 {
    887 	struct kbd_softc *k;
    888 
    889 	k = device_lookup_private(&kbd_cd, 0); /* XXX: hardcoded minor */
    890 
    891 	if (k == NULL || k->k_ops == NULL || k->k_ops->docmd == NULL)
    892 		return;
    893 
    894 	(void)(*k->k_ops->docmd)(k, on ? KBD_CMD_BELL : KBD_CMD_NOBELL, 0);
    895 }
    896 
    897 #if NWSKBD > 0
    898 static void
    899 kbd_input_wskbd(struct kbd_softc *k, int code)
    900 {
    901 	int type, key;
    902 
    903 #ifdef WSDISPLAY_COMPAT_RAWKBD
    904 	if (k->k_wsraw) {
    905 		u_char buf;
    906 
    907 		buf = code;
    908 		wskbd_rawinput(k->k_wskbd, &buf, 1);
    909 		return;
    910 	}
    911 #endif
    912 
    913 	type = KEY_UP(code) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
    914 	key = KEY_CODE(code);
    915 	wskbd_input(k->k_wskbd, type, key);
    916 }
    917 
    918 int
    919 wssunkbd_enable(void *v, int on)
    920 {
    921 	struct kbd_softc *k = v;
    922 	if (k->k_wsenabled != on) {
    923 		k->k_wsenabled = on;
    924 		if (on) {
    925 			/* open actual underlying device */
    926 			if (k->k_ops != NULL && k->k_ops->open != NULL)
    927 				(*k->k_ops->open)(k);
    928 			ev_init(&k->k_events);
    929 			k->k_evmode = 0;	/* XXX: OK? */
    930 		} else {
    931 			/* close underlying device */
    932 			if (k->k_ops != NULL && k->k_ops->close != NULL)
    933 				(*k->k_ops->close)(k);
    934 		}
    935 	}
    936 	return 0;
    937 }
    938 
    939 void
    940 wssunkbd_set_leds(void *v, int leds)
    941 {
    942 	struct kbd_softc *k = v;
    943 	int l = 0;
    944 
    945 	if (leds & WSKBD_LED_CAPS)
    946 		l |= LED_CAPS_LOCK;
    947 	if (leds & WSKBD_LED_NUM)
    948 		l |= LED_NUM_LOCK;
    949 	if (leds & WSKBD_LED_SCROLL)
    950 		l |= LED_SCROLL_LOCK;
    951 	if (leds & WSKBD_LED_COMPOSE)
    952 		l |= LED_COMPOSE;
    953 	if (k->k_ops != NULL && k->k_ops->setleds != NULL)
    954 		(*k->k_ops->setleds)(k, l, 0);
    955 	k->k_leds=l;
    956 }
    957 
    958 static int
    959 wssunkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
    960 {
    961 	struct kbd_softc *k = v;
    962 
    963 	switch (cmd) {
    964 		case WSKBDIO_GTYPE:
    965 			/* we can't tell  4 from  5 or 6 */
    966 			*(int *)data = k->k_state.kbd_id < KB_SUN4 ?
    967 			    WSKBD_TYPE_SUN : WSKBD_TYPE_SUN5;
    968 			return 0;
    969 		case WSKBDIO_SETLEDS:
    970 			wssunkbd_set_leds(v, *(int *)data);
    971 			return 0;
    972 		case WSKBDIO_GETLEDS:
    973 			*(int *)data = k->k_leds;
    974 			return 0;
    975 #ifdef WSDISPLAY_COMPAT_RAWKBD
    976 		case WSKBDIO_SETMODE:
    977 			k->k_wsraw = *(int *)data == WSKBD_RAW;
    978 			return 0;
    979 #endif
    980 	}
    981 	return EPASSTHROUGH;
    982 }
    983 
    984 extern int	prom_cngetc(dev_t);
    985 
    986 static void
    987 sunkbd_wskbd_cngetc(void *v, u_int *type, int *data)
    988 {
    989 	/* struct kbd_sun_softc *k = v; */
    990 
    991 	*data = prom_cngetc(0);
    992 	*type = WSCONS_EVENT_ASCII;
    993 }
    994 
    995 void
    996 sunkbd_wskbd_cnpollc(void *v, int on)
    997 {
    998 }
    999 
   1000 static void
   1001 sunkbd_bell_off(void *v)
   1002 {
   1003 	struct kbd_softc *k = v;
   1004 
   1005 	k->k_ops->docmd(k, KBD_CMD_NOBELL, 0);
   1006 }
   1007 
   1008 void
   1009 sunkbd_wskbd_cnbell(void *v, u_int pitch, u_int period, u_int volume)
   1010 {
   1011 	struct kbd_softc *k = v;
   1012 
   1013 	callout_reset(&k->k_wsbell, period * 1000 / hz, sunkbd_bell_off, v);
   1014 	k->k_ops->docmd(k, KBD_CMD_BELL, 0);
   1015 }
   1016 
   1017 void
   1018 kbd_enable(device_t dev)
   1019 {
   1020 	struct kbd_softc *k = device_private(dev);
   1021 	struct wskbddev_attach_args a;
   1022 
   1023 	if (k->k_isconsole)
   1024 		wskbd_cnattach(&sunkbd_wskbd_consops, k,
   1025 		    &sunkbd_wskbd_keymapdata);
   1026 
   1027 	a.console = k->k_isconsole;
   1028 	a.keymap = &sunkbd_wskbd_keymapdata;
   1029 	a.accessops = &sunkbd_wskbd_accessops;
   1030 	a.accesscookie = k;
   1031 
   1032 	/* XXX why? */
   1033 	k->k_wsenabled = 0;
   1034 
   1035 	/* Attach the wskbd */
   1036 	k->k_wskbd = config_found(k->k_dev, &a, wskbddevprint);
   1037 
   1038 	callout_init(&k->k_wsbell, 0);
   1039 
   1040 	wssunkbd_enable(k,1);
   1041 
   1042 	wssunkbd_set_leds(k, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS);
   1043 	delay(100000);
   1044 	wssunkbd_set_leds(k, 0);
   1045 }
   1046 
   1047 void
   1048 kbd_wskbd_attach(struct kbd_softc *k, int isconsole)
   1049 {
   1050 	k->k_isconsole = isconsole;
   1051 
   1052 	config_interrupts(k->k_dev, kbd_enable);
   1053 }
   1054 #endif
   1055