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