kbd.c revision 127752
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 127752 2004-04-02 16:41:16Z des $");
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
51typedef 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
58static	SLIST_HEAD(, keyboard_driver) keyboard_drivers =
59	SLIST_HEAD_INITIALIZER(keyboard_drivers);
60
61SET_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
71static int		keyboards = 1;
72static keyboard_t	*kbd_ini;
73static keyboard_t	**keyboard = &kbd_ini;
74static keyboard_switch_t *kbdsw_ini;
75       keyboard_switch_t **kbdsw = &kbdsw_ini;
76
77static int keymap_restrict_change;
78SYSCTL_NODE(_hw, OID_AUTO, kbd, CTLFLAG_RD, 0, "kbd");
79SYSCTL_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
84static int
85kbd_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 */
131void
132kbd_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
154void
155kbd_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 */
165int
166kbd_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
174int
175kbd_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 */
183int
184kbd_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
226int
227kbd_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 */
259keyboard_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 */
286int
287kbd_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 */
306int
307kbd_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
333int
334kbd_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
356int
357kbd_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 */
380keyboard_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
398int
399kbd_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
427static d_open_t		genkbdopen;
428static d_close_t	genkbdclose;
429static d_read_t		genkbdread;
430static d_write_t	genkbdwrite;
431static d_ioctl_t	genkbdioctl;
432static d_poll_t		genkbdpoll;
433
434
435static 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
447int
448kbd_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
465int
466kbd_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
489static kbd_callback_func_t genkbd_event;
490
491static int
492genkbdopen(dev_t 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
529static int
530genkbdclose(dev_t 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
555static int
556genkbdread(dev_t 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
608static int
609genkbdwrite(dev_t 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
619static int
620genkbdioctl(dev_t 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
634static int
635genkbdpoll(dev_t 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
658static int
659genkbd_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
766static int key_change_ok(struct keyent_t *, struct keyent_t *, struct thread *);
767static int keymap_change_ok(keymap_t *, keymap_t *, struct thread *);
768static int accent_change_ok(accentmap_t *, accentmap_t *, struct thread *);
769static int fkey_change_ok(fkeytab_t *, fkeyarg_t *, struct thread *);
770#endif
771
772int
773genkbd_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
924static int
925key_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
962static int
963keymap_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
975static int
976accent_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
1005static int
1006fkey_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 */
1020u_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 */
1033static 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
1053void
1054genkbd_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
1077static u_int
1078save_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
1106static u_int
1107make_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
1133int
1134genkbd_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