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