xref: /freebsd/sys/dev/kbd/kbd.c (revision 06064893b3c62c648518be78604fac29fc0d9d61)
1 /*-
2  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer as
10  *    the first lines of this file unmodified.
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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30 
31 #include "opt_kbd.h"
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
37 #include <sys/conf.h>
38 #include <sys/tty.h>
39 #include <sys/poll.h>
40 #include <sys/proc.h>
41 #include <sys/sysctl.h>
42 #include <sys/vnode.h>
43 #include <sys/uio.h>
44 
45 #include <sys/kbio.h>
46 
47 #include <dev/kbd/kbdreg.h>
48 
49 #define KBD_INDEX(dev)	minor(dev)
50 
51 typedef struct genkbd_softc {
52 	int		gkb_flags;	/* flag/status bits */
53 #define KB_ASLEEP	(1 << 0)
54 	struct clist	gkb_q;		/* input queue */
55 	struct selinfo	gkb_rsel;
56 } genkbd_softc_t;
57 
58 static	SLIST_HEAD(, keyboard_driver) keyboard_drivers =
59 	SLIST_HEAD_INITIALIZER(keyboard_drivers);
60 
61 SET_DECLARE(kbddriver_set, const keyboard_driver_t);
62 
63 /* local arrays */
64 
65 /*
66  * We need at least one entry each in order to initialize a keyboard
67  * for the kernel console.  The arrays will be increased dynamically
68  * when necessary.
69  */
70 
71 static int		keyboards = 1;
72 static keyboard_t	*kbd_ini;
73 static keyboard_t	**keyboard = &kbd_ini;
74 static keyboard_switch_t *kbdsw_ini;
75        keyboard_switch_t **kbdsw = &kbdsw_ini;
76 
77 static int keymap_restrict_change;
78 SYSCTL_NODE(_hw, OID_AUTO, kbd, CTLFLAG_RD, 0, "kbd");
79 SYSCTL_INT(_hw_kbd, OID_AUTO, keymap_restrict_change, CTLFLAG_RW,
80     &keymap_restrict_change, 0, "restrict ability to change keymap");
81 
82 #define ARRAY_DELTA	4
83 
84 static int
85 kbd_realloc_array(void)
86 {
87 	keyboard_t **new_kbd;
88 	keyboard_switch_t **new_kbdsw;
89 	int newsize;
90 	int s;
91 
92 	s = spltty();
93 	newsize = ((keyboards + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
94 	new_kbd = malloc(sizeof(*new_kbd)*newsize, M_DEVBUF, M_NOWAIT|M_ZERO);
95 	if (new_kbd == NULL) {
96 		splx(s);
97 		return (ENOMEM);
98 	}
99 	new_kbdsw = malloc(sizeof(*new_kbdsw)*newsize, M_DEVBUF,
100 			    M_NOWAIT|M_ZERO);
101 	if (new_kbdsw == NULL) {
102 		free(new_kbd, M_DEVBUF);
103 		splx(s);
104 		return (ENOMEM);
105 	}
106 	bcopy(keyboard, new_kbd, sizeof(*keyboard)*keyboards);
107 	bcopy(kbdsw, new_kbdsw, sizeof(*kbdsw)*keyboards);
108 	if (keyboards > 1) {
109 		free(keyboard, M_DEVBUF);
110 		free(kbdsw, M_DEVBUF);
111 	}
112 	keyboard = new_kbd;
113 	kbdsw = new_kbdsw;
114 	keyboards = newsize;
115 	splx(s);
116 
117 	if (bootverbose)
118 		printf("kbd: new array size %d\n", keyboards);
119 
120 	return (0);
121 }
122 
123 /*
124  * Low-level keyboard driver functions
125  * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard
126  * driver, call these functions to initialize the keyboard_t structure
127  * and register it to the virtual keyboard driver `kbd'.
128  */
129 
130 /* initialize the keyboard_t structure */
131 void
132 kbd_init_struct(keyboard_t *kbd, char *name, int type, int unit, int config,
133 		int port, int port_size)
134 {
135 	kbd->kb_flags = KB_NO_DEVICE;	/* device has not been found */
136 	kbd->kb_name = name;
137 	kbd->kb_type = type;
138 	kbd->kb_unit = unit;
139 	kbd->kb_config = config & ~KB_CONF_PROBE_ONLY;
140 	kbd->kb_led = 0;		/* unknown */
141 	kbd->kb_io_base = port;
142 	kbd->kb_io_size = port_size;
143 	kbd->kb_data = NULL;
144 	kbd->kb_keymap = NULL;
145 	kbd->kb_accentmap = NULL;
146 	kbd->kb_fkeytab = NULL;
147 	kbd->kb_fkeytab_size = 0;
148 	kbd->kb_delay1 = KB_DELAY1;	/* these values are advisory only */
149 	kbd->kb_delay2 = KB_DELAY2;
150 	kbd->kb_count = 0L;
151 	bzero(kbd->kb_lastact, sizeof(kbd->kb_lastact));
152 }
153 
154 void
155 kbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accentmap_t *accmap,
156 	     fkeytab_t *fkeymap, int fkeymap_size)
157 {
158 	kbd->kb_keymap = keymap;
159 	kbd->kb_accentmap = accmap;
160 	kbd->kb_fkeytab = fkeymap;
161 	kbd->kb_fkeytab_size = fkeymap_size;
162 }
163 
164 /* declare a new keyboard driver */
165 int
166 kbd_add_driver(keyboard_driver_t *driver)
167 {
168 	if (SLIST_NEXT(driver, link))
169 		return (EINVAL);
170 	SLIST_INSERT_HEAD(&keyboard_drivers, driver, link);
171 	return (0);
172 }
173 
174 int
175 kbd_delete_driver(keyboard_driver_t *driver)
176 {
177 	SLIST_REMOVE(&keyboard_drivers, driver, keyboard_driver, link);
178 	SLIST_NEXT(driver, link) = NULL;
179 	return (0);
180 }
181 
182 /* register a keyboard and associate it with a function table */
183 int
184 kbd_register(keyboard_t *kbd)
185 {
186 	const keyboard_driver_t **list;
187 	const keyboard_driver_t *p;
188 	int index;
189 
190 	for (index = 0; index < keyboards; ++index) {
191 		if (keyboard[index] == NULL)
192 			break;
193 	}
194 	if (index >= keyboards) {
195 		if (kbd_realloc_array())
196 			return (-1);
197 	}
198 
199 	kbd->kb_index = index;
200 	KBD_UNBUSY(kbd);
201 	KBD_VALID(kbd);
202 	kbd->kb_active = 0;	/* disabled until someone calls kbd_enable() */
203 	kbd->kb_token = NULL;
204 	kbd->kb_callback.kc_func = NULL;
205 	kbd->kb_callback.kc_arg = NULL;
206 
207 	SLIST_FOREACH(p, &keyboard_drivers, link) {
208 		if (strcmp(p->name, kbd->kb_name) == 0) {
209 			keyboard[index] = kbd;
210 			kbdsw[index] = p->kbdsw;
211 			return (index);
212 		}
213 	}
214 	SET_FOREACH(list, kbddriver_set) {
215 		p = *list;
216 		if (strcmp(p->name, kbd->kb_name) == 0) {
217 			keyboard[index] = kbd;
218 			kbdsw[index] = p->kbdsw;
219 			return (index);
220 		}
221 	}
222 
223 	return (-1);
224 }
225 
226 int
227 kbd_unregister(keyboard_t *kbd)
228 {
229 	int error;
230 	int s;
231 
232 	if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards))
233 		return (ENOENT);
234 	if (keyboard[kbd->kb_index] != kbd)
235 		return (ENOENT);
236 
237 	s = spltty();
238 	if (KBD_IS_BUSY(kbd)) {
239 		error = (*kbd->kb_callback.kc_func)(kbd, KBDIO_UNLOADING,
240 		    kbd->kb_callback.kc_arg);
241 		if (error) {
242 			splx(s);
243 			return (error);
244 		}
245 		if (KBD_IS_BUSY(kbd)) {
246 			splx(s);
247 			return (EBUSY);
248 		}
249 	}
250 	KBD_INVALID(kbd);
251 	keyboard[kbd->kb_index] = NULL;
252 	kbdsw[kbd->kb_index] = NULL;
253 
254 	splx(s);
255 	return (0);
256 }
257 
258 /* find a funciton table by the driver name */
259 keyboard_switch_t
260 *kbd_get_switch(char *driver)
261 {
262 	const keyboard_driver_t **list;
263 	const keyboard_driver_t *p;
264 
265 	SLIST_FOREACH(p, &keyboard_drivers, link) {
266 		if (strcmp(p->name, driver) == 0)
267 			return (p->kbdsw);
268 	}
269 	SET_FOREACH(list, kbddriver_set) {
270 		p = *list;
271 		if (strcmp(p->name, driver) == 0)
272 			return (p->kbdsw);
273 	}
274 
275 	return (NULL);
276 }
277 
278 /*
279  * Keyboard client functions
280  * Keyboard clients, such as the console driver `syscons' and the keyboard
281  * cdev driver, use these functions to claim and release a keyboard for
282  * exclusive use.
283  */
284 
285 /* find the keyboard specified by a driver name and a unit number */
286 int
287 kbd_find_keyboard(char *driver, int unit)
288 {
289 	int i;
290 
291 	for (i = 0; i < keyboards; ++i) {
292 		if (keyboard[i] == NULL)
293 			continue;
294 		if (!KBD_IS_VALID(keyboard[i]))
295 			continue;
296 		if (strcmp("*", driver) && strcmp(keyboard[i]->kb_name, driver))
297 			continue;
298 		if ((unit != -1) && (keyboard[i]->kb_unit != unit))
299 			continue;
300 		return (i);
301 	}
302 	return (-1);
303 }
304 
305 /* allocate a keyboard */
306 int
307 kbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func,
308 	     void *arg)
309 {
310 	int index;
311 	int s;
312 
313 	if (func == NULL)
314 		return (-1);
315 
316 	s = spltty();
317 	index = kbd_find_keyboard(driver, unit);
318 	if (index >= 0) {
319 		if (KBD_IS_BUSY(keyboard[index])) {
320 			splx(s);
321 			return (-1);
322 		}
323 		keyboard[index]->kb_token = id;
324 		KBD_BUSY(keyboard[index]);
325 		keyboard[index]->kb_callback.kc_func = func;
326 		keyboard[index]->kb_callback.kc_arg = arg;
327 		(*kbdsw[index]->clear_state)(keyboard[index]);
328 	}
329 	splx(s);
330 	return (index);
331 }
332 
333 int
334 kbd_release(keyboard_t *kbd, void *id)
335 {
336 	int error;
337 	int s;
338 
339 	s = spltty();
340 	if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
341 		error = EINVAL;
342 	} else if (kbd->kb_token != id) {
343 		error = EPERM;
344 	} else {
345 		kbd->kb_token = NULL;
346 		KBD_UNBUSY(kbd);
347 		kbd->kb_callback.kc_func = NULL;
348 		kbd->kb_callback.kc_arg = NULL;
349 		(*kbdsw[kbd->kb_index]->clear_state)(kbd);
350 		error = 0;
351 	}
352 	splx(s);
353 	return (error);
354 }
355 
356 int
357 kbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func,
358 		    void *arg)
359 {
360 	int error;
361 	int s;
362 
363 	s = spltty();
364 	if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
365 		error = EINVAL;
366 	} else if (kbd->kb_token != id) {
367 		error = EPERM;
368 	} else if (func == NULL) {
369 		error = EINVAL;
370 	} else {
371 		kbd->kb_callback.kc_func = func;
372 		kbd->kb_callback.kc_arg = arg;
373 		error = 0;
374 	}
375 	splx(s);
376 	return (error);
377 }
378 
379 /* get a keyboard structure */
380 keyboard_t
381 *kbd_get_keyboard(int index)
382 {
383 	if ((index < 0) || (index >= keyboards))
384 		return (NULL);
385 	if (keyboard[index] == NULL)
386 		return (NULL);
387 	if (!KBD_IS_VALID(keyboard[index]))
388 		return (NULL);
389 	return (keyboard[index]);
390 }
391 
392 /*
393  * The back door for the console driver; configure keyboards
394  * This function is for the kernel console to initialize keyboards
395  * at very early stage.
396  */
397 
398 int
399 kbd_configure(int flags)
400 {
401 	const keyboard_driver_t **list;
402 	const keyboard_driver_t *p;
403 
404 	SLIST_FOREACH(p, &keyboard_drivers, link) {
405 		if (p->configure != NULL)
406 			(*p->configure)(flags);
407 	}
408 	SET_FOREACH(list, kbddriver_set) {
409 		p = *list;
410 		if (p->configure != NULL)
411 			(*p->configure)(flags);
412 	}
413 
414 	return (0);
415 }
416 
417 #ifdef KBD_INSTALL_CDEV
418 
419 /*
420  * Virtual keyboard cdev driver functions
421  * The virtual keyboard driver dispatches driver functions to
422  * appropriate subdrivers.
423  */
424 
425 #define KBD_UNIT(dev)	minor(dev)
426 
427 static d_open_t		genkbdopen;
428 static d_close_t	genkbdclose;
429 static d_read_t		genkbdread;
430 static d_write_t	genkbdwrite;
431 static d_ioctl_t	genkbdioctl;
432 static d_poll_t		genkbdpoll;
433 
434 
435 static struct cdevsw kbd_cdevsw = {
436 	.d_version =	D_VERSION,
437 	.d_flags =	D_NEEDGIANT,
438 	.d_open =	genkbdopen,
439 	.d_close =	genkbdclose,
440 	.d_read =	genkbdread,
441 	.d_write =	genkbdwrite,
442 	.d_ioctl =	genkbdioctl,
443 	.d_poll =	genkbdpoll,
444 	.d_name =	"kbd",
445 };
446 
447 int
448 kbd_attach(keyboard_t *kbd)
449 {
450 
451 	if (kbd->kb_index >= keyboards)
452 		return (EINVAL);
453 	if (keyboard[kbd->kb_index] != kbd)
454 		return (EINVAL);
455 
456 	kbd->kb_dev = make_dev(&kbd_cdevsw, kbd->kb_index, UID_ROOT, GID_WHEEL,
457 	    0600, "%s%r", kbd->kb_name, kbd->kb_unit);
458 	make_dev_alias(kbd->kb_dev, "kbd%r", kbd->kb_index);
459 	kbd->kb_dev->si_drv1 = malloc(sizeof(genkbd_softc_t), M_DEVBUF,
460 	    M_WAITOK | M_ZERO);
461 	printf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit);
462 	return (0);
463 }
464 
465 int
466 kbd_detach(keyboard_t *kbd)
467 {
468 
469 	if (kbd->kb_index >= keyboards)
470 		return (EINVAL);
471 	if (keyboard[kbd->kb_index] != kbd)
472 		return (EINVAL);
473 
474 	free(kbd->kb_dev->si_drv1, M_DEVBUF);
475 	destroy_dev(kbd->kb_dev);
476 
477 	return (0);
478 }
479 
480 /*
481  * Generic keyboard cdev driver functions
482  * Keyboard subdrivers may call these functions to implement common
483  * driver functions.
484  */
485 
486 #define KB_QSIZE	512
487 #define KB_BUFSIZE	64
488 
489 static kbd_callback_func_t genkbd_event;
490 
491 static int
492 genkbdopen(struct cdev *dev, int mode, int flag, struct thread *td)
493 {
494 	keyboard_t *kbd;
495 	genkbd_softc_t *sc;
496 	int s;
497 	int i;
498 
499 	s = spltty();
500 	sc = dev->si_drv1;
501 	kbd = kbd_get_keyboard(KBD_INDEX(dev));
502 	if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
503 		splx(s);
504 		return (ENXIO);
505 	}
506 	i = kbd_allocate(kbd->kb_name, kbd->kb_unit, sc,
507 	    genkbd_event, (void *)sc);
508 	if (i < 0) {
509 		splx(s);
510 		return (EBUSY);
511 	}
512 	/* assert(i == kbd->kb_index) */
513 	/* assert(kbd == kbd_get_keyboard(i)) */
514 
515 	/*
516 	 * NOTE: even when we have successfully claimed a keyboard,
517 	 * the device may still be missing (!KBD_HAS_DEVICE(kbd)).
518 	 */
519 
520 #if 0
521 	bzero(&sc->gkb_q, sizeof(sc->gkb_q));
522 #endif
523 	clist_alloc_cblocks(&sc->gkb_q, KB_QSIZE, KB_QSIZE/2); /* XXX */
524 	splx(s);
525 
526 	return (0);
527 }
528 
529 static int
530 genkbdclose(struct cdev *dev, int mode, int flag, struct thread *td)
531 {
532 	keyboard_t *kbd;
533 	genkbd_softc_t *sc;
534 	int s;
535 
536 	/*
537 	 * NOTE: the device may have already become invalid.
538 	 * kbd == NULL || !KBD_IS_VALID(kbd)
539 	 */
540 	s = spltty();
541 	sc = dev->si_drv1;
542 	kbd = kbd_get_keyboard(KBD_INDEX(dev));
543 	if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
544 		/* XXX: we shall be forgiving and don't report error... */
545 	} else {
546 		kbd_release(kbd, (void *)sc);
547 #if 0
548 		clist_free_cblocks(&sc->gkb_q);
549 #endif
550 	}
551 	splx(s);
552 	return (0);
553 }
554 
555 static int
556 genkbdread(struct cdev *dev, struct uio *uio, int flag)
557 {
558 	keyboard_t *kbd;
559 	genkbd_softc_t *sc;
560 	u_char buffer[KB_BUFSIZE];
561 	int len;
562 	int error;
563 	int s;
564 
565 	/* wait for input */
566 	s = spltty();
567 	sc = dev->si_drv1;
568 	kbd = kbd_get_keyboard(KBD_INDEX(dev));
569 	if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
570 		splx(s);
571 		return (ENXIO);
572 	}
573 	while (sc->gkb_q.c_cc == 0) {
574 		if (flag & IO_NDELAY) {
575 			splx(s);
576 			return (EWOULDBLOCK);
577 		}
578 		sc->gkb_flags |= KB_ASLEEP;
579 		error = tsleep(sc, PZERO | PCATCH, "kbdrea", 0);
580 		kbd = kbd_get_keyboard(KBD_INDEX(dev));
581 		if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
582 			splx(s);
583 			return (ENXIO);	/* our keyboard has gone... */
584 		}
585 		if (error) {
586 			sc->gkb_flags &= ~KB_ASLEEP;
587 			splx(s);
588 			return (error);
589 		}
590 	}
591 	splx(s);
592 
593 	/* copy as much input as possible */
594 	error = 0;
595 	while (uio->uio_resid > 0) {
596 		len = imin(uio->uio_resid, sizeof(buffer));
597 		len = q_to_b(&sc->gkb_q, buffer, len);
598 		if (len <= 0)
599 			break;
600 		error = uiomove(buffer, len, uio);
601 		if (error)
602 			break;
603 	}
604 
605 	return (error);
606 }
607 
608 static int
609 genkbdwrite(struct cdev *dev, struct uio *uio, int flag)
610 {
611 	keyboard_t *kbd;
612 
613 	kbd = kbd_get_keyboard(KBD_INDEX(dev));
614 	if ((kbd == NULL) || !KBD_IS_VALID(kbd))
615 		return (ENXIO);
616 	return (ENODEV);
617 }
618 
619 static int
620 genkbdioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
621 {
622 	keyboard_t *kbd;
623 	int error;
624 
625 	kbd = kbd_get_keyboard(KBD_INDEX(dev));
626 	if ((kbd == NULL) || !KBD_IS_VALID(kbd))
627 		return (ENXIO);
628 	error = (*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, arg);
629 	if (error == ENOIOCTL)
630 		error = ENODEV;
631 	return (error);
632 }
633 
634 static int
635 genkbdpoll(struct cdev *dev, int events, struct thread *td)
636 {
637 	keyboard_t *kbd;
638 	genkbd_softc_t *sc;
639 	int revents;
640 	int s;
641 
642 	revents = 0;
643 	s = spltty();
644 	sc = dev->si_drv1;
645 	kbd = kbd_get_keyboard(KBD_INDEX(dev));
646 	if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
647 		revents =  POLLHUP;	/* the keyboard has gone */
648 	} else if (events & (POLLIN | POLLRDNORM)) {
649 		if (sc->gkb_q.c_cc > 0)
650 			revents = events & (POLLIN | POLLRDNORM);
651 		else
652 			selrecord(td, &sc->gkb_rsel);
653 	}
654 	splx(s);
655 	return (revents);
656 }
657 
658 static int
659 genkbd_event(keyboard_t *kbd, int event, void *arg)
660 {
661 	genkbd_softc_t *sc;
662 	size_t len;
663 	u_char *cp;
664 	int mode;
665 	int c;
666 
667 	/* assert(KBD_IS_VALID(kbd)) */
668 	sc = (genkbd_softc_t *)arg;
669 
670 	switch (event) {
671 	case KBDIO_KEYINPUT:
672 		break;
673 	case KBDIO_UNLOADING:
674 		/* the keyboard is going... */
675 		kbd_release(kbd, (void *)sc);
676 		if (sc->gkb_flags & KB_ASLEEP) {
677 			sc->gkb_flags &= ~KB_ASLEEP;
678 			wakeup(sc);
679 		}
680 		selwakeuppri(&sc->gkb_rsel, PZERO);
681 		return (0);
682 	default:
683 		return (EINVAL);
684 	}
685 
686 	/* obtain the current key input mode */
687 	if ((*kbdsw[kbd->kb_index]->ioctl)(kbd, KDGKBMODE, (caddr_t)&mode))
688 		mode = K_XLATE;
689 
690 	/* read all pending input */
691 	while ((*kbdsw[kbd->kb_index]->check_char)(kbd)) {
692 		c = (*kbdsw[kbd->kb_index]->read_char)(kbd, FALSE);
693 		if (c == NOKEY)
694 			continue;
695 		if (c == ERRKEY)	/* XXX: ring bell? */
696 			continue;
697 		if (!KBD_IS_BUSY(kbd))
698 			/* the device is not open, discard the input */
699 			continue;
700 
701 		/* store the byte as is for K_RAW and K_CODE modes */
702 		if (mode != K_XLATE) {
703 			putc(KEYCHAR(c), &sc->gkb_q);
704 			continue;
705 		}
706 
707 		/* K_XLATE */
708 		if (c & RELKEY)	/* key release is ignored */
709 			continue;
710 
711 		/* process special keys; most of them are just ignored... */
712 		if (c & SPCLKEY) {
713 			switch (KEYCHAR(c)) {
714 			default:
715 				/* ignore them... */
716 				continue;
717 			case BTAB:	/* a backtab: ESC [ Z */
718 				putc(0x1b, &sc->gkb_q);
719 				putc('[', &sc->gkb_q);
720 				putc('Z', &sc->gkb_q);
721 				continue;
722 			}
723 		}
724 
725 		/* normal chars, normal chars with the META, function keys */
726 		switch (KEYFLAGS(c)) {
727 		case 0:			/* a normal char */
728 			putc(KEYCHAR(c), &sc->gkb_q);
729 			break;
730 		case MKEY:		/* the META flag: prepend ESC */
731 			putc(0x1b, &sc->gkb_q);
732 			putc(KEYCHAR(c), &sc->gkb_q);
733 			break;
734 		case FKEY | SPCLKEY:	/* a function key, return string */
735 			cp = (*kbdsw[kbd->kb_index]->get_fkeystr)(kbd,
736 			    KEYCHAR(c), &len);
737 			if (cp != NULL) {
738 				while (len-- >  0)
739 					putc(*cp++, &sc->gkb_q);
740 			}
741 			break;
742 		}
743 	}
744 
745 	/* wake up sleeping/polling processes */
746 	if (sc->gkb_q.c_cc > 0) {
747 		if (sc->gkb_flags & KB_ASLEEP) {
748 			sc->gkb_flags &= ~KB_ASLEEP;
749 			wakeup(sc);
750 		}
751 		selwakeuppri(&sc->gkb_rsel, PZERO);
752 	}
753 
754 	return (0);
755 }
756 
757 #endif /* KBD_INSTALL_CDEV */
758 
759 /*
760  * Generic low-level keyboard functions
761  * The low-level functions in the keyboard subdriver may use these
762  * functions.
763  */
764 
765 #ifndef KBD_DISABLE_KEYMAP_LOAD
766 static int key_change_ok(struct keyent_t *, struct keyent_t *, struct thread *);
767 static int keymap_change_ok(keymap_t *, keymap_t *, struct thread *);
768 static int accent_change_ok(accentmap_t *, accentmap_t *, struct thread *);
769 static int fkey_change_ok(fkeytab_t *, fkeyarg_t *, struct thread *);
770 #endif
771 
772 int
773 genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
774 {
775 	keyarg_t *keyp;
776 	fkeyarg_t *fkeyp;
777 	int s;
778 	int i;
779 #ifndef KBD_DISABLE_KEYMAP_LOAD
780 	int error;
781 #endif
782 
783 	s = spltty();
784 	switch (cmd) {
785 
786 	case KDGKBINFO:		/* get keyboard information */
787 		((keyboard_info_t *)arg)->kb_index = kbd->kb_index;
788 		i = imin(strlen(kbd->kb_name) + 1,
789 		    sizeof(((keyboard_info_t *)arg)->kb_name));
790 		bcopy(kbd->kb_name, ((keyboard_info_t *)arg)->kb_name, i);
791 		((keyboard_info_t *)arg)->kb_unit = kbd->kb_unit;
792 		((keyboard_info_t *)arg)->kb_type = kbd->kb_type;
793 		((keyboard_info_t *)arg)->kb_config = kbd->kb_config;
794 		((keyboard_info_t *)arg)->kb_flags = kbd->kb_flags;
795 		break;
796 
797 	case KDGKBTYPE:		/* get keyboard type */
798 		*(int *)arg = kbd->kb_type;
799 		break;
800 
801 	case KDGETREPEAT:	/* get keyboard repeat rate */
802 		((int *)arg)[0] = kbd->kb_delay1;
803 		((int *)arg)[1] = kbd->kb_delay2;
804 		break;
805 
806 	case GIO_KEYMAP:	/* get keyboard translation table */
807 		bcopy(kbd->kb_keymap, arg, sizeof(*kbd->kb_keymap));
808 		break;
809 	case PIO_KEYMAP:	/* set keyboard translation table */
810 #ifndef KBD_DISABLE_KEYMAP_LOAD
811 		error = keymap_change_ok(kbd->kb_keymap, (keymap_t *)arg,
812 		    curthread);
813 		if (error != 0) {
814 			splx(s);
815 			return (error);
816 		}
817 		bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
818 		bcopy(arg, kbd->kb_keymap, sizeof(*kbd->kb_keymap));
819 		break;
820 #else
821 		splx(s);
822 		return (ENODEV);
823 #endif
824 
825 	case GIO_KEYMAPENT:	/* get keyboard translation table entry */
826 		keyp = (keyarg_t *)arg;
827 		if (keyp->keynum >= sizeof(kbd->kb_keymap->key) /
828 		    sizeof(kbd->kb_keymap->key[0])) {
829 			splx(s);
830 			return (EINVAL);
831 		}
832 		bcopy(&kbd->kb_keymap->key[keyp->keynum], &keyp->key,
833 		    sizeof(keyp->key));
834 		break;
835 	case PIO_KEYMAPENT:	/* set keyboard translation table entry */
836 #ifndef KBD_DISABLE_KEYMAP_LOAD
837 		keyp = (keyarg_t *)arg;
838 		if (keyp->keynum >= sizeof(kbd->kb_keymap->key) /
839 		    sizeof(kbd->kb_keymap->key[0])) {
840 			splx(s);
841 			return (EINVAL);
842 		}
843 		error = key_change_ok(&kbd->kb_keymap->key[keyp->keynum],
844 		    &keyp->key, curthread);
845 		if (error != 0) {
846 			splx(s);
847 			return (error);
848 		}
849 		bcopy(&keyp->key, &kbd->kb_keymap->key[keyp->keynum],
850 		    sizeof(keyp->key));
851 		break;
852 #else
853 		splx(s);
854 		return (ENODEV);
855 #endif
856 
857 	case GIO_DEADKEYMAP:	/* get accent key translation table */
858 		bcopy(kbd->kb_accentmap, arg, sizeof(*kbd->kb_accentmap));
859 		break;
860 	case PIO_DEADKEYMAP:	/* set accent key translation table */
861 #ifndef KBD_DISABLE_KEYMAP_LOAD
862 		error = accent_change_ok(kbd->kb_accentmap,
863 		    (accentmap_t *)arg, curthread);
864 		if (error != 0) {
865 			splx(s);
866 			return (error);
867 		}
868 		bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
869 		break;
870 #else
871 		splx(s);
872 		return (ENODEV);
873 #endif
874 
875 	case GETFKEY:		/* get functionkey string */
876 		fkeyp = (fkeyarg_t *)arg;
877 		if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
878 			splx(s);
879 			return (EINVAL);
880 		}
881 		bcopy(kbd->kb_fkeytab[fkeyp->keynum].str, fkeyp->keydef,
882 		    kbd->kb_fkeytab[fkeyp->keynum].len);
883 		fkeyp->flen = kbd->kb_fkeytab[fkeyp->keynum].len;
884 		break;
885 	case SETFKEY:		/* set functionkey string */
886 #ifndef KBD_DISABLE_KEYMAP_LOAD
887 		fkeyp = (fkeyarg_t *)arg;
888 		if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
889 			splx(s);
890 			return (EINVAL);
891 		}
892 		error = fkey_change_ok(&kbd->kb_fkeytab[fkeyp->keynum],
893 		    fkeyp, curthread);
894 		if (error != 0) {
895 			splx(s);
896 			return (error);
897 		}
898 		kbd->kb_fkeytab[fkeyp->keynum].len = imin(fkeyp->flen, MAXFK);
899 		bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str,
900 		    kbd->kb_fkeytab[fkeyp->keynum].len);
901 		break;
902 #else
903 		splx(s);
904 		return (ENODEV);
905 #endif
906 
907 	default:
908 		splx(s);
909 		return (ENOIOCTL);
910 	}
911 
912 	splx(s);
913 	return (0);
914 }
915 
916 #ifndef KBD_DISABLE_KEYMAP_LOAD
917 #define RESTRICTED_KEY(key, i) \
918 	((key->spcl & (0x80 >> i)) && \
919 		(key->map[i] == RBT || key->map[i] == SUSP || \
920 		 key->map[i] == STBY || key->map[i] == DBG || \
921 		 key->map[i] == PNC || key->map[i] == HALT || \
922 		 key->map[i] == PDWN))
923 
924 static int
925 key_change_ok(struct keyent_t *oldkey, struct keyent_t *newkey, struct thread *td)
926 {
927 	int i;
928 
929 	/* Low keymap_restrict_change means any changes are OK. */
930 	if (keymap_restrict_change <= 0)
931 		return (0);
932 
933 	/* High keymap_restrict_change means only root can change the keymap. */
934 	if (keymap_restrict_change >= 2) {
935 		for (i = 0; i < NUM_STATES; i++)
936 			if (oldkey->map[i] != newkey->map[i])
937 				return suser(td);
938 		if (oldkey->spcl != newkey->spcl)
939 			return suser(td);
940 		if (oldkey->flgs != newkey->flgs)
941 			return suser(td);
942 		return (0);
943 	}
944 
945 	/* Otherwise we have to see if any special keys are being changed. */
946 	for (i = 0; i < NUM_STATES; i++) {
947 		/*
948 		 * If either the oldkey or the newkey action is restricted
949 		 * then we must make sure that the action doesn't change.
950 		 */
951 		if (!RESTRICTED_KEY(oldkey, i) && !RESTRICTED_KEY(newkey, i))
952 			continue;
953 		if ((oldkey->spcl & (0x80 >> i)) == (newkey->spcl & (0x80 >> i))
954 		    && oldkey->map[i] == newkey->map[i])
955 			continue;
956 		return suser(td);
957 	}
958 
959 	return (0);
960 }
961 
962 static int
963 keymap_change_ok(keymap_t *oldmap, keymap_t *newmap, struct thread *td)
964 {
965 	int keycode, error;
966 
967 	for (keycode = 0; keycode < NUM_KEYS; keycode++) {
968 		if ((error = key_change_ok(&oldmap->key[keycode],
969 		    &newmap->key[keycode], td)) != 0)
970 			return (error);
971 	}
972 	return (0);
973 }
974 
975 static int
976 accent_change_ok(accentmap_t *oldmap, accentmap_t *newmap, struct thread *td)
977 {
978 	struct acc_t *oldacc, *newacc;
979 	int accent, i;
980 
981 	if (keymap_restrict_change <= 2)
982 		return (0);
983 
984 	if (oldmap->n_accs != newmap->n_accs)
985 		return suser(td);
986 
987 	for (accent = 0; accent < oldmap->n_accs; accent++) {
988 		oldacc = &oldmap->acc[accent];
989 		newacc = &newmap->acc[accent];
990 		if (oldacc->accchar != newacc->accchar)
991 			return suser(td);
992 		for (i = 0; i < NUM_ACCENTCHARS; ++i) {
993 			if (oldacc->map[i][0] != newacc->map[i][0])
994 				return suser(td);
995 			if (oldacc->map[i][0] == 0)	/* end of table */
996 				break;
997 			if (oldacc->map[i][1] != newacc->map[i][1])
998 				return suser(td);
999 		}
1000 	}
1001 
1002 	return (0);
1003 }
1004 
1005 static int
1006 fkey_change_ok(fkeytab_t *oldkey, fkeyarg_t *newkey, struct thread *td)
1007 {
1008 	if (keymap_restrict_change <= 3)
1009 		return (0);
1010 
1011 	if (oldkey->len != newkey->flen ||
1012 	    bcmp(oldkey->str, newkey->keydef, oldkey->len) != 0)
1013 		return suser(td);
1014 
1015 	return (0);
1016 }
1017 #endif
1018 
1019 /* get a pointer to the string associated with the given function key */
1020 u_char
1021 *genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len)
1022 {
1023 	if (kbd == NULL)
1024 		return (NULL);
1025 	fkey -= F_FN;
1026 	if (fkey > kbd->kb_fkeytab_size)
1027 		return (NULL);
1028 	*len = kbd->kb_fkeytab[fkey].len;
1029 	return (kbd->kb_fkeytab[fkey].str);
1030 }
1031 
1032 /* diagnostic dump */
1033 static char
1034 *get_kbd_type_name(int type)
1035 {
1036 	static struct {
1037 		int type;
1038 		char *name;
1039 	} name_table[] = {
1040 		{ KB_84,	"AT 84" },
1041 		{ KB_101,	"AT 101/102" },
1042 		{ KB_OTHER,	"generic" },
1043 	};
1044 	int i;
1045 
1046 	for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) {
1047 		if (type == name_table[i].type)
1048 			return (name_table[i].name);
1049 	}
1050 	return ("unknown");
1051 }
1052 
1053 void
1054 genkbd_diag(keyboard_t *kbd, int level)
1055 {
1056 	if (level > 0) {
1057 		printf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x",
1058 		    kbd->kb_index, kbd->kb_name, kbd->kb_unit,
1059 		    get_kbd_type_name(kbd->kb_type), kbd->kb_type,
1060 		    kbd->kb_config, kbd->kb_flags);
1061 		if (kbd->kb_io_base > 0)
1062 			printf(", port:0x%x-0x%x", kbd->kb_io_base,
1063 			    kbd->kb_io_base + kbd->kb_io_size - 1);
1064 		printf("\n");
1065 	}
1066 }
1067 
1068 #define set_lockkey_state(k, s, l)				\
1069 	if (!((s) & l ## DOWN)) {				\
1070 		int i;						\
1071 		(s) |= l ## DOWN;				\
1072 		(s) ^= l ## ED;					\
1073 		i = (s) & LOCK_MASK;				\
1074 		(*kbdsw[(k)->kb_index]->ioctl)((k), KDSETLED, (caddr_t)&i); \
1075 	}
1076 
1077 static u_int
1078 save_accent_key(keyboard_t *kbd, u_int key, int *accents)
1079 {
1080 	int i;
1081 
1082 	/* make an index into the accent map */
1083 	i = key - F_ACC + 1;
1084 	if ((i > kbd->kb_accentmap->n_accs)
1085 	    || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) {
1086 		/* the index is out of range or pointing to an empty entry */
1087 		*accents = 0;
1088 		return (ERRKEY);
1089 	}
1090 
1091 	/*
1092 	 * If the same accent key has been hit twice, produce the accent
1093 	 * char itself.
1094 	 */
1095 	if (i == *accents) {
1096 		key = kbd->kb_accentmap->acc[i - 1].accchar;
1097 		*accents = 0;
1098 		return (key);
1099 	}
1100 
1101 	/* remember the index and wait for the next key  */
1102 	*accents = i;
1103 	return (NOKEY);
1104 }
1105 
1106 static u_int
1107 make_accent_char(keyboard_t *kbd, u_int ch, int *accents)
1108 {
1109 	struct acc_t *acc;
1110 	int i;
1111 
1112 	acc = &kbd->kb_accentmap->acc[*accents - 1];
1113 	*accents = 0;
1114 
1115 	/*
1116 	 * If the accent key is followed by the space key,
1117 	 * produce the accent char itself.
1118 	 */
1119 	if (ch == ' ')
1120 		return (acc->accchar);
1121 
1122 	/* scan the accent map */
1123 	for (i = 0; i < NUM_ACCENTCHARS; ++i) {
1124 		if (acc->map[i][0] == 0)	/* end of table */
1125 			break;
1126 		if (acc->map[i][0] == ch)
1127 			return (acc->map[i][1]);
1128 	}
1129 	/* this char cannot be accented... */
1130 	return (ERRKEY);
1131 }
1132 
1133 int
1134 genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
1135 		 int *accents)
1136 {
1137 	struct keyent_t *key;
1138 	int state = *shiftstate;
1139 	int action;
1140 	int f;
1141 	int i;
1142 
1143 	i = keycode;
1144 	f = state & (AGRS | ALKED);
1145 	if ((f == AGRS1) || (f == AGRS2) || (f == ALKED))
1146 		i += ALTGR_OFFSET;
1147 	key = &kbd->kb_keymap->key[i];
1148 	i = ((state & SHIFTS) ? 1 : 0)
1149 	    | ((state & CTLS) ? 2 : 0)
1150 	    | ((state & ALTS) ? 4 : 0);
1151 	if (((key->flgs & FLAG_LOCK_C) && (state & CLKED))
1152 		|| ((key->flgs & FLAG_LOCK_N) && (state & NLKED)) )
1153 		i ^= 1;
1154 
1155 	if (up) {	/* break: key released */
1156 		action = kbd->kb_lastact[keycode];
1157 		kbd->kb_lastact[keycode] = NOP;
1158 		switch (action) {
1159 		case LSHA:
1160 			if (state & SHIFTAON) {
1161 				set_lockkey_state(kbd, state, ALK);
1162 				state &= ~ALKDOWN;
1163 			}
1164 			action = LSH;
1165 			/* FALL THROUGH */
1166 		case LSH:
1167 			state &= ~SHIFTS1;
1168 			break;
1169 		case RSHA:
1170 			if (state & SHIFTAON) {
1171 				set_lockkey_state(kbd, state, ALK);
1172 				state &= ~ALKDOWN;
1173 			}
1174 			action = RSH;
1175 			/* FALL THROUGH */
1176 		case RSH:
1177 			state &= ~SHIFTS2;
1178 			break;
1179 		case LCTRA:
1180 			if (state & SHIFTAON) {
1181 				set_lockkey_state(kbd, state, ALK);
1182 				state &= ~ALKDOWN;
1183 			}
1184 			action = LCTR;
1185 			/* FALL THROUGH */
1186 		case LCTR:
1187 			state &= ~CTLS1;
1188 			break;
1189 		case RCTRA:
1190 			if (state & SHIFTAON) {
1191 				set_lockkey_state(kbd, state, ALK);
1192 				state &= ~ALKDOWN;
1193 			}
1194 			action = RCTR;
1195 			/* FALL THROUGH */
1196 		case RCTR:
1197 			state &= ~CTLS2;
1198 			break;
1199 		case LALTA:
1200 			if (state & SHIFTAON) {
1201 				set_lockkey_state(kbd, state, ALK);
1202 				state &= ~ALKDOWN;
1203 			}
1204 			action = LALT;
1205 			/* FALL THROUGH */
1206 		case LALT:
1207 			state &= ~ALTS1;
1208 			break;
1209 		case RALTA:
1210 			if (state & SHIFTAON) {
1211 				set_lockkey_state(kbd, state, ALK);
1212 				state &= ~ALKDOWN;
1213 			}
1214 			action = RALT;
1215 			/* FALL THROUGH */
1216 		case RALT:
1217 			state &= ~ALTS2;
1218 			break;
1219 		case ASH:
1220 			state &= ~AGRS1;
1221 			break;
1222 		case META:
1223 			state &= ~METAS1;
1224 			break;
1225 		case NLK:
1226 			state &= ~NLKDOWN;
1227 			break;
1228 		case CLK:
1229 #ifndef PC98
1230 			state &= ~CLKDOWN;
1231 #else
1232 			state &= ~CLKED;
1233 			i = state & LOCK_MASK;
1234 			(*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED,
1235 						       (caddr_t)&i);
1236 #endif
1237 			break;
1238 		case SLK:
1239 			state &= ~SLKDOWN;
1240 			break;
1241 		case ALK:
1242 			state &= ~ALKDOWN;
1243 			break;
1244 		case NOP:
1245 			/* release events of regular keys are not reported */
1246 			*shiftstate &= ~SHIFTAON;
1247 			return (NOKEY);
1248 		}
1249 		*shiftstate = state & ~SHIFTAON;
1250 		return (SPCLKEY | RELKEY | action);
1251 	} else {	/* make: key pressed */
1252 		action = key->map[i];
1253 		state &= ~SHIFTAON;
1254 		if (key->spcl & (0x80 >> i)) {
1255 			/* special keys */
1256 			if (kbd->kb_lastact[keycode] == NOP)
1257 				kbd->kb_lastact[keycode] = action;
1258 			if (kbd->kb_lastact[keycode] != action)
1259 				action = NOP;
1260 			switch (action) {
1261 			/* LOCKING KEYS */
1262 			case NLK:
1263 				set_lockkey_state(kbd, state, NLK);
1264 				break;
1265 			case CLK:
1266 #ifndef PC98
1267 				set_lockkey_state(kbd, state, CLK);
1268 #else
1269 				state |= CLKED;
1270 				i = state & LOCK_MASK;
1271 				(*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED,
1272 							       (caddr_t)&i);
1273 #endif
1274 				break;
1275 			case SLK:
1276 				set_lockkey_state(kbd, state, SLK);
1277 				break;
1278 			case ALK:
1279 				set_lockkey_state(kbd, state, ALK);
1280 				break;
1281 			/* NON-LOCKING KEYS */
1282 			case SPSC: case RBT:  case SUSP: case STBY:
1283 			case DBG:  case NEXT: case PREV: case PNC:
1284 			case HALT: case PDWN:
1285 				*accents = 0;
1286 				break;
1287 			case BTAB:
1288 				*accents = 0;
1289 				action |= BKEY;
1290 				break;
1291 			case LSHA:
1292 				state |= SHIFTAON;
1293 				action = LSH;
1294 				/* FALL THROUGH */
1295 			case LSH:
1296 				state |= SHIFTS1;
1297 				break;
1298 			case RSHA:
1299 				state |= SHIFTAON;
1300 				action = RSH;
1301 				/* FALL THROUGH */
1302 			case RSH:
1303 				state |= SHIFTS2;
1304 				break;
1305 			case LCTRA:
1306 				state |= SHIFTAON;
1307 				action = LCTR;
1308 				/* FALL THROUGH */
1309 			case LCTR:
1310 				state |= CTLS1;
1311 				break;
1312 			case RCTRA:
1313 				state |= SHIFTAON;
1314 				action = RCTR;
1315 				/* FALL THROUGH */
1316 			case RCTR:
1317 				state |= CTLS2;
1318 				break;
1319 			case LALTA:
1320 				state |= SHIFTAON;
1321 				action = LALT;
1322 				/* FALL THROUGH */
1323 			case LALT:
1324 				state |= ALTS1;
1325 				break;
1326 			case RALTA:
1327 				state |= SHIFTAON;
1328 				action = RALT;
1329 				/* FALL THROUGH */
1330 			case RALT:
1331 				state |= ALTS2;
1332 				break;
1333 			case ASH:
1334 				state |= AGRS1;
1335 				break;
1336 			case META:
1337 				state |= METAS1;
1338 				break;
1339 			case NOP:
1340 				*shiftstate = state;
1341 				return (NOKEY);
1342 			default:
1343 				/* is this an accent (dead) key? */
1344 				*shiftstate = state;
1345 				if (action >= F_ACC && action <= L_ACC) {
1346 					action = save_accent_key(kbd, action,
1347 								 accents);
1348 					switch (action) {
1349 					case NOKEY:
1350 					case ERRKEY:
1351 						return (action);
1352 					default:
1353 						if (state & METAS)
1354 							return (action | MKEY);
1355 						else
1356 							return (action);
1357 					}
1358 					/* NOT REACHED */
1359 				}
1360 				/* other special keys */
1361 				if (*accents > 0) {
1362 					*accents = 0;
1363 					return (ERRKEY);
1364 				}
1365 				if (action >= F_FN && action <= L_FN)
1366 					action |= FKEY;
1367 				/* XXX: return fkey string for the FKEY? */
1368 				return (SPCLKEY | action);
1369 			}
1370 			*shiftstate = state;
1371 			return (SPCLKEY | action);
1372 		} else {
1373 			/* regular keys */
1374 			kbd->kb_lastact[keycode] = NOP;
1375 			*shiftstate = state;
1376 			if (*accents > 0) {
1377 				/* make an accented char */
1378 				action = make_accent_char(kbd, action, accents);
1379 				if (action == ERRKEY)
1380 					return (action);
1381 			}
1382 			if (state & METAS)
1383 				action |= MKEY;
1384 			return (action);
1385 		}
1386 	}
1387 	/* NOT REACHED */
1388 }
1389