2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer as
12 * the first lines of this file unmodified.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
40 #include <sys/fcntl.h>
44 #include <sys/selinfo.h>
45 #include <sys/sysctl.h>
50 #include <dev/evdev/input-event-codes.h>
51 #include <dev/kbd/kbdreg.h>
53 #define KBD_INDEX(dev) dev2unit(dev)
58 typedef struct genkbd_softc {
59 int gkb_flags; /* flag/status bits */
60 #define KB_ASLEEP (1 << 0)
61 struct selinfo gkb_rsel;
62 char gkb_q[KB_QSIZE]; /* input queue */
63 unsigned int gkb_q_start;
64 unsigned int gkb_q_length;
67 static SLIST_HEAD(, keyboard_driver) keyboard_drivers =
68 SLIST_HEAD_INITIALIZER(keyboard_drivers);
70 SET_DECLARE(kbddriver_set, const keyboard_driver_t);
75 * We need at least one entry each in order to initialize a keyboard
76 * for the kernel console. The arrays will be increased dynamically
80 static int keyboards = 1;
81 static keyboard_t *kbd_ini;
82 static keyboard_t **keyboard = &kbd_ini;
83 static keyboard_switch_t *kbdsw_ini;
84 keyboard_switch_t **kbdsw = &kbdsw_ini;
86 static int keymap_restrict_change;
87 static SYSCTL_NODE(_hw, OID_AUTO, kbd, CTLFLAG_RD, 0, "kbd");
88 SYSCTL_INT(_hw_kbd, OID_AUTO, keymap_restrict_change, CTLFLAG_RW,
89 &keymap_restrict_change, 0, "restrict ability to change keymap");
94 kbd_realloc_array(void)
97 keyboard_switch_t **new_kbdsw;
102 newsize = rounddown(keyboards + ARRAY_DELTA, ARRAY_DELTA);
103 new_kbd = malloc(sizeof(*new_kbd)*newsize, M_DEVBUF, M_NOWAIT|M_ZERO);
104 if (new_kbd == NULL) {
108 new_kbdsw = malloc(sizeof(*new_kbdsw)*newsize, M_DEVBUF,
110 if (new_kbdsw == NULL) {
111 free(new_kbd, M_DEVBUF);
115 bcopy(keyboard, new_kbd, sizeof(*keyboard)*keyboards);
116 bcopy(kbdsw, new_kbdsw, sizeof(*kbdsw)*keyboards);
118 free(keyboard, M_DEVBUF);
119 free(kbdsw, M_DEVBUF);
127 printf("kbd: new array size %d\n", keyboards);
133 * Low-level keyboard driver functions
134 * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard
135 * driver, call these functions to initialize the keyboard_t structure
136 * and register it to the virtual keyboard driver `kbd'.
139 /* initialize the keyboard_t structure */
141 kbd_init_struct(keyboard_t *kbd, char *name, int type, int unit, int config,
142 int port, int port_size)
144 kbd->kb_flags = KB_NO_DEVICE; /* device has not been found */
148 kbd->kb_config = config & ~KB_CONF_PROBE_ONLY;
149 kbd->kb_led = 0; /* unknown */
150 kbd->kb_io_base = port;
151 kbd->kb_io_size = port_size;
153 kbd->kb_keymap = NULL;
154 kbd->kb_accentmap = NULL;
155 kbd->kb_fkeytab = NULL;
156 kbd->kb_fkeytab_size = 0;
157 kbd->kb_delay1 = KB_DELAY1; /* these values are advisory only */
158 kbd->kb_delay2 = KB_DELAY2;
160 bzero(kbd->kb_lastact, sizeof(kbd->kb_lastact));
164 kbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accentmap_t *accmap,
165 fkeytab_t *fkeymap, int fkeymap_size)
167 kbd->kb_keymap = keymap;
168 kbd->kb_accentmap = accmap;
169 kbd->kb_fkeytab = fkeymap;
170 kbd->kb_fkeytab_size = fkeymap_size;
173 /* declare a new keyboard driver */
175 kbd_add_driver(keyboard_driver_t *driver)
177 if (SLIST_NEXT(driver, link))
179 if (driver->kbdsw->get_fkeystr == NULL)
180 driver->kbdsw->get_fkeystr = genkbd_get_fkeystr;
181 if (driver->kbdsw->diag == NULL)
182 driver->kbdsw->diag = genkbd_diag;
183 SLIST_INSERT_HEAD(&keyboard_drivers, driver, link);
188 kbd_delete_driver(keyboard_driver_t *driver)
190 SLIST_REMOVE(&keyboard_drivers, driver, keyboard_driver, link);
191 SLIST_NEXT(driver, link) = NULL;
195 /* register a keyboard and associate it with a function table */
197 kbd_register(keyboard_t *kbd)
199 const keyboard_driver_t **list;
200 const keyboard_driver_t *p;
205 mux = kbd_get_keyboard(kbd_find_keyboard("kbdmux", -1));
207 for (index = 0; index < keyboards; ++index) {
208 if (keyboard[index] == NULL)
211 if (index >= keyboards) {
212 if (kbd_realloc_array())
216 kbd->kb_index = index;
219 kbd->kb_active = 0; /* disabled until someone calls kbd_enable() */
220 kbd->kb_token = NULL;
221 kbd->kb_callback.kc_func = NULL;
222 kbd->kb_callback.kc_arg = NULL;
224 SLIST_FOREACH(p, &keyboard_drivers, link) {
225 if (strcmp(p->name, kbd->kb_name) == 0) {
226 keyboard[index] = kbd;
227 kbdsw[index] = p->kbdsw;
230 bzero(&ki, sizeof(ki));
231 strcpy(ki.kb_name, kbd->kb_name);
232 ki.kb_unit = kbd->kb_unit;
234 (void)kbdd_ioctl(mux, KBADDKBD, (caddr_t) &ki);
240 SET_FOREACH(list, kbddriver_set) {
242 if (strcmp(p->name, kbd->kb_name) == 0) {
243 keyboard[index] = kbd;
244 kbdsw[index] = p->kbdsw;
247 bzero(&ki, sizeof(ki));
248 strcpy(ki.kb_name, kbd->kb_name);
249 ki.kb_unit = kbd->kb_unit;
251 (void)kbdd_ioctl(mux, KBADDKBD, (caddr_t) &ki);
262 kbd_unregister(keyboard_t *kbd)
267 if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards))
269 if (keyboard[kbd->kb_index] != kbd)
273 if (KBD_IS_BUSY(kbd)) {
274 error = (*kbd->kb_callback.kc_func)(kbd, KBDIO_UNLOADING,
275 kbd->kb_callback.kc_arg);
280 if (KBD_IS_BUSY(kbd)) {
286 keyboard[kbd->kb_index] = NULL;
287 kbdsw[kbd->kb_index] = NULL;
293 /* find a function table by the driver name */
295 kbd_get_switch(char *driver)
297 const keyboard_driver_t **list;
298 const keyboard_driver_t *p;
300 SLIST_FOREACH(p, &keyboard_drivers, link) {
301 if (strcmp(p->name, driver) == 0)
304 SET_FOREACH(list, kbddriver_set) {
306 if (strcmp(p->name, driver) == 0)
314 * Keyboard client functions
315 * Keyboard clients, such as the console driver `syscons' and the keyboard
316 * cdev driver, use these functions to claim and release a keyboard for
321 * find the keyboard specified by a driver name and a unit number
322 * starting at given index
325 kbd_find_keyboard2(char *driver, int unit, int index)
329 if ((index < 0) || (index >= keyboards))
332 for (i = index; i < keyboards; ++i) {
333 if (keyboard[i] == NULL)
335 if (!KBD_IS_VALID(keyboard[i]))
337 if (strcmp("*", driver) && strcmp(keyboard[i]->kb_name, driver))
339 if ((unit != -1) && (keyboard[i]->kb_unit != unit))
347 /* find the keyboard specified by a driver name and a unit number */
349 kbd_find_keyboard(char *driver, int unit)
351 return (kbd_find_keyboard2(driver, unit, 0));
354 /* allocate a keyboard */
356 kbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func,
366 index = kbd_find_keyboard(driver, unit);
368 if (KBD_IS_BUSY(keyboard[index])) {
372 keyboard[index]->kb_token = id;
373 KBD_BUSY(keyboard[index]);
374 keyboard[index]->kb_callback.kc_func = func;
375 keyboard[index]->kb_callback.kc_arg = arg;
376 kbdd_clear_state(keyboard[index]);
383 kbd_release(keyboard_t *kbd, void *id)
389 if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
391 } else if (kbd->kb_token != id) {
394 kbd->kb_token = NULL;
396 kbd->kb_callback.kc_func = NULL;
397 kbd->kb_callback.kc_arg = NULL;
398 kbdd_clear_state(kbd);
406 kbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func,
413 if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
415 } else if (kbd->kb_token != id) {
417 } else if (func == NULL) {
420 kbd->kb_callback.kc_func = func;
421 kbd->kb_callback.kc_arg = arg;
428 /* get a keyboard structure */
430 kbd_get_keyboard(int index)
432 if ((index < 0) || (index >= keyboards))
434 if (keyboard[index] == NULL)
436 if (!KBD_IS_VALID(keyboard[index]))
438 return (keyboard[index]);
442 * The back door for the console driver; configure keyboards
443 * This function is for the kernel console to initialize keyboards
444 * at very early stage.
448 kbd_configure(int flags)
450 const keyboard_driver_t **list;
451 const keyboard_driver_t *p;
453 SLIST_FOREACH(p, &keyboard_drivers, link) {
454 if (p->configure != NULL)
455 (*p->configure)(flags);
457 SET_FOREACH(list, kbddriver_set) {
459 if (p->configure != NULL)
460 (*p->configure)(flags);
466 #ifdef KBD_INSTALL_CDEV
469 * Virtual keyboard cdev driver functions
470 * The virtual keyboard driver dispatches driver functions to
471 * appropriate subdrivers.
474 #define KBD_UNIT(dev) dev2unit(dev)
476 static d_open_t genkbdopen;
477 static d_close_t genkbdclose;
478 static d_read_t genkbdread;
479 static d_write_t genkbdwrite;
480 static d_ioctl_t genkbdioctl;
481 static d_poll_t genkbdpoll;
484 static struct cdevsw kbd_cdevsw = {
485 .d_version = D_VERSION,
486 .d_flags = D_NEEDGIANT,
487 .d_open = genkbdopen,
488 .d_close = genkbdclose,
489 .d_read = genkbdread,
490 .d_write = genkbdwrite,
491 .d_ioctl = genkbdioctl,
492 .d_poll = genkbdpoll,
497 kbd_attach(keyboard_t *kbd)
500 if (kbd->kb_index >= keyboards)
502 if (keyboard[kbd->kb_index] != kbd)
505 kbd->kb_dev = make_dev(&kbd_cdevsw, kbd->kb_index, UID_ROOT, GID_WHEEL,
506 0600, "%s%r", kbd->kb_name, kbd->kb_unit);
507 make_dev_alias(kbd->kb_dev, "kbd%r", kbd->kb_index);
508 kbd->kb_dev->si_drv1 = malloc(sizeof(genkbd_softc_t), M_DEVBUF,
510 printf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit);
515 kbd_detach(keyboard_t *kbd)
518 if (kbd->kb_index >= keyboards)
520 if (keyboard[kbd->kb_index] != kbd)
523 free(kbd->kb_dev->si_drv1, M_DEVBUF);
524 destroy_dev(kbd->kb_dev);
530 * Generic keyboard cdev driver functions
531 * Keyboard subdrivers may call these functions to implement common
536 genkbd_putc(genkbd_softc_t *sc, char c)
540 if (sc->gkb_q_length == KB_QSIZE)
543 p = (sc->gkb_q_start + sc->gkb_q_length) % KB_QSIZE;
549 genkbd_getc(genkbd_softc_t *sc, char *buf, size_t len)
552 /* Determine copy size. */
553 if (sc->gkb_q_length == 0)
555 if (len >= sc->gkb_q_length)
556 len = sc->gkb_q_length;
557 if (len >= KB_QSIZE - sc->gkb_q_start)
558 len = KB_QSIZE - sc->gkb_q_start;
560 /* Copy out data and progress offset. */
561 memcpy(buf, sc->gkb_q + sc->gkb_q_start, len);
562 sc->gkb_q_start = (sc->gkb_q_start + len) % KB_QSIZE;
563 sc->gkb_q_length -= len;
568 static kbd_callback_func_t genkbd_event;
571 genkbdopen(struct cdev *dev, int mode, int flag, struct thread *td)
580 kbd = kbd_get_keyboard(KBD_INDEX(dev));
581 if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
585 i = kbd_allocate(kbd->kb_name, kbd->kb_unit, sc,
586 genkbd_event, (void *)sc);
591 /* assert(i == kbd->kb_index) */
592 /* assert(kbd == kbd_get_keyboard(i)) */
595 * NOTE: even when we have successfully claimed a keyboard,
596 * the device may still be missing (!KBD_HAS_DEVICE(kbd)).
599 sc->gkb_q_length = 0;
606 genkbdclose(struct cdev *dev, int mode, int flag, struct thread *td)
613 * NOTE: the device may have already become invalid.
614 * kbd == NULL || !KBD_IS_VALID(kbd)
618 kbd = kbd_get_keyboard(KBD_INDEX(dev));
619 if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
620 /* XXX: we shall be forgiving and don't report error... */
622 kbd_release(kbd, (void *)sc);
629 genkbdread(struct cdev *dev, struct uio *uio, int flag)
633 u_char buffer[KB_BUFSIZE];
641 kbd = kbd_get_keyboard(KBD_INDEX(dev));
642 if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
646 while (sc->gkb_q_length == 0) {
647 if (flag & O_NONBLOCK) {
649 return (EWOULDBLOCK);
651 sc->gkb_flags |= KB_ASLEEP;
652 error = tsleep(sc, PZERO | PCATCH, "kbdrea", 0);
653 kbd = kbd_get_keyboard(KBD_INDEX(dev));
654 if ((kbd == NULL) || !KBD_IS_VALID(kbd)) {
656 return (ENXIO); /* our keyboard has gone... */
659 sc->gkb_flags &= ~KB_ASLEEP;
666 /* copy as much input as possible */
668 while (uio->uio_resid > 0) {
669 len = imin(uio->uio_resid, sizeof(buffer));
670 len = genkbd_getc(sc, buffer, len);
673 error = uiomove(buffer, len, uio);
682 genkbdwrite(struct cdev *dev, struct uio *uio, int flag)
686 kbd = kbd_get_keyboard(KBD_INDEX(dev));
687 if ((kbd == NULL) || !KBD_IS_VALID(kbd))
693 genkbdioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
698 kbd = kbd_get_keyboard(KBD_INDEX(dev));
699 if ((kbd == NULL) || !KBD_IS_VALID(kbd))
701 error = kbdd_ioctl(kbd, cmd, arg);
702 if (error == ENOIOCTL)
708 genkbdpoll(struct cdev *dev, int events, struct thread *td)
718 kbd = kbd_get_keyboard(KBD_INDEX(dev));
719 if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) {
720 revents = POLLHUP; /* the keyboard has gone */
721 } else if (events & (POLLIN | POLLRDNORM)) {
722 if (sc->gkb_q_length > 0)
723 revents = events & (POLLIN | POLLRDNORM);
725 selrecord(td, &sc->gkb_rsel);
732 genkbd_event(keyboard_t *kbd, int event, void *arg)
740 /* assert(KBD_IS_VALID(kbd)) */
741 sc = (genkbd_softc_t *)arg;
746 case KBDIO_UNLOADING:
747 /* the keyboard is going... */
748 kbd_release(kbd, (void *)sc);
749 if (sc->gkb_flags & KB_ASLEEP) {
750 sc->gkb_flags &= ~KB_ASLEEP;
753 selwakeuppri(&sc->gkb_rsel, PZERO);
759 /* obtain the current key input mode */
760 if (kbdd_ioctl(kbd, KDGKBMODE, (caddr_t)&mode))
763 /* read all pending input */
764 while (kbdd_check_char(kbd)) {
765 c = kbdd_read_char(kbd, FALSE);
768 if (c == ERRKEY) /* XXX: ring bell? */
770 if (!KBD_IS_BUSY(kbd))
771 /* the device is not open, discard the input */
774 /* store the byte as is for K_RAW and K_CODE modes */
775 if (mode != K_XLATE) {
776 genkbd_putc(sc, KEYCHAR(c));
781 if (c & RELKEY) /* key release is ignored */
784 /* process special keys; most of them are just ignored... */
786 switch (KEYCHAR(c)) {
790 case BTAB: /* a backtab: ESC [ Z */
791 genkbd_putc(sc, 0x1b);
792 genkbd_putc(sc, '[');
793 genkbd_putc(sc, 'Z');
798 /* normal chars, normal chars with the META, function keys */
799 switch (KEYFLAGS(c)) {
800 case 0: /* a normal char */
801 genkbd_putc(sc, KEYCHAR(c));
803 case MKEY: /* the META flag: prepend ESC */
804 genkbd_putc(sc, 0x1b);
805 genkbd_putc(sc, KEYCHAR(c));
807 case FKEY | SPCLKEY: /* a function key, return string */
808 cp = kbdd_get_fkeystr(kbd, KEYCHAR(c), &len);
811 genkbd_putc(sc, *cp++);
817 /* wake up sleeping/polling processes */
818 if (sc->gkb_q_length > 0) {
819 if (sc->gkb_flags & KB_ASLEEP) {
820 sc->gkb_flags &= ~KB_ASLEEP;
823 selwakeuppri(&sc->gkb_rsel, PZERO);
829 #endif /* KBD_INSTALL_CDEV */
832 * Generic low-level keyboard functions
833 * The low-level functions in the keyboard subdriver may use these
837 #ifndef KBD_DISABLE_KEYMAP_LOAD
838 static int key_change_ok(struct keyent_t *, struct keyent_t *, struct thread *);
839 static int keymap_change_ok(keymap_t *, keymap_t *, struct thread *);
840 static int accent_change_ok(accentmap_t *, accentmap_t *, struct thread *);
841 static int fkey_change_ok(fkeytab_t *, fkeyarg_t *, struct thread *);
845 genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
858 case KDGKBINFO: /* get keyboard information */
859 ((keyboard_info_t *)arg)->kb_index = kbd->kb_index;
860 i = imin(strlen(kbd->kb_name) + 1,
861 sizeof(((keyboard_info_t *)arg)->kb_name));
862 bcopy(kbd->kb_name, ((keyboard_info_t *)arg)->kb_name, i);
863 ((keyboard_info_t *)arg)->kb_unit = kbd->kb_unit;
864 ((keyboard_info_t *)arg)->kb_type = kbd->kb_type;
865 ((keyboard_info_t *)arg)->kb_config = kbd->kb_config;
866 ((keyboard_info_t *)arg)->kb_flags = kbd->kb_flags;
869 case KDGKBTYPE: /* get keyboard type */
870 *(int *)arg = kbd->kb_type;
873 case KDGETREPEAT: /* get keyboard repeat rate */
874 ((int *)arg)[0] = kbd->kb_delay1;
875 ((int *)arg)[1] = kbd->kb_delay2;
878 case GIO_KEYMAP: /* get keyboard translation table */
879 error = copyout(kbd->kb_keymap, *(void **)arg,
883 case OGIO_KEYMAP: /* get keyboard translation table (compat) */
884 mapp = kbd->kb_keymap;
885 omapp = (okeymap_t *)arg;
886 omapp->n_keys = mapp->n_keys;
887 for (i = 0; i < NUM_KEYS; i++) {
888 for (j = 0; j < NUM_STATES; j++)
889 omapp->key[i].map[j] =
891 omapp->key[i].spcl = mapp->key[i].spcl;
892 omapp->key[i].flgs = mapp->key[i].flgs;
895 case PIO_KEYMAP: /* set keyboard translation table */
896 case OPIO_KEYMAP: /* set keyboard translation table (compat) */
897 #ifndef KBD_DISABLE_KEYMAP_LOAD
898 mapp = malloc(sizeof *mapp, M_TEMP, M_WAITOK);
899 if (cmd == OPIO_KEYMAP) {
900 omapp = (okeymap_t *)arg;
901 mapp->n_keys = omapp->n_keys;
902 for (i = 0; i < NUM_KEYS; i++) {
903 for (j = 0; j < NUM_STATES; j++)
904 mapp->key[i].map[j] =
905 omapp->key[i].map[j];
906 mapp->key[i].spcl = omapp->key[i].spcl;
907 mapp->key[i].flgs = omapp->key[i].flgs;
910 error = copyin(*(void **)arg, mapp, sizeof *mapp);
918 error = keymap_change_ok(kbd->kb_keymap, mapp, curthread);
924 bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
925 bcopy(mapp, kbd->kb_keymap, sizeof(*kbd->kb_keymap));
933 case GIO_KEYMAPENT: /* get keyboard translation table entry */
934 keyp = (keyarg_t *)arg;
935 if (keyp->keynum >= sizeof(kbd->kb_keymap->key) /
936 sizeof(kbd->kb_keymap->key[0])) {
940 bcopy(&kbd->kb_keymap->key[keyp->keynum], &keyp->key,
943 case PIO_KEYMAPENT: /* set keyboard translation table entry */
944 #ifndef KBD_DISABLE_KEYMAP_LOAD
945 keyp = (keyarg_t *)arg;
946 if (keyp->keynum >= sizeof(kbd->kb_keymap->key) /
947 sizeof(kbd->kb_keymap->key[0])) {
951 error = key_change_ok(&kbd->kb_keymap->key[keyp->keynum],
952 &keyp->key, curthread);
957 bcopy(&keyp->key, &kbd->kb_keymap->key[keyp->keynum],
965 case GIO_DEADKEYMAP: /* get accent key translation table */
966 bcopy(kbd->kb_accentmap, arg, sizeof(*kbd->kb_accentmap));
968 case PIO_DEADKEYMAP: /* set accent key translation table */
969 #ifndef KBD_DISABLE_KEYMAP_LOAD
970 error = accent_change_ok(kbd->kb_accentmap,
971 (accentmap_t *)arg, curthread);
976 bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
983 case GETFKEY: /* get functionkey string */
984 fkeyp = (fkeyarg_t *)arg;
985 if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
989 bcopy(kbd->kb_fkeytab[fkeyp->keynum].str, fkeyp->keydef,
990 kbd->kb_fkeytab[fkeyp->keynum].len);
991 fkeyp->flen = kbd->kb_fkeytab[fkeyp->keynum].len;
993 case SETFKEY: /* set functionkey string */
994 #ifndef KBD_DISABLE_KEYMAP_LOAD
995 fkeyp = (fkeyarg_t *)arg;
996 if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
1000 error = fkey_change_ok(&kbd->kb_fkeytab[fkeyp->keynum],
1006 kbd->kb_fkeytab[fkeyp->keynum].len = min(fkeyp->flen, MAXFK);
1007 bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str,
1008 kbd->kb_fkeytab[fkeyp->keynum].len);
1024 #ifndef KBD_DISABLE_KEYMAP_LOAD
1025 #define RESTRICTED_KEY(key, i) \
1026 ((key->spcl & (0x80 >> i)) && \
1027 (key->map[i] == RBT || key->map[i] == SUSP || \
1028 key->map[i] == STBY || key->map[i] == DBG || \
1029 key->map[i] == PNC || key->map[i] == HALT || \
1030 key->map[i] == PDWN))
1033 key_change_ok(struct keyent_t *oldkey, struct keyent_t *newkey, struct thread *td)
1037 /* Low keymap_restrict_change means any changes are OK. */
1038 if (keymap_restrict_change <= 0)
1041 /* High keymap_restrict_change means only root can change the keymap. */
1042 if (keymap_restrict_change >= 2) {
1043 for (i = 0; i < NUM_STATES; i++)
1044 if (oldkey->map[i] != newkey->map[i])
1045 return priv_check(td, PRIV_KEYBOARD);
1046 if (oldkey->spcl != newkey->spcl)
1047 return priv_check(td, PRIV_KEYBOARD);
1048 if (oldkey->flgs != newkey->flgs)
1049 return priv_check(td, PRIV_KEYBOARD);
1053 /* Otherwise we have to see if any special keys are being changed. */
1054 for (i = 0; i < NUM_STATES; i++) {
1056 * If either the oldkey or the newkey action is restricted
1057 * then we must make sure that the action doesn't change.
1059 if (!RESTRICTED_KEY(oldkey, i) && !RESTRICTED_KEY(newkey, i))
1061 if ((oldkey->spcl & (0x80 >> i)) == (newkey->spcl & (0x80 >> i))
1062 && oldkey->map[i] == newkey->map[i])
1064 return priv_check(td, PRIV_KEYBOARD);
1071 keymap_change_ok(keymap_t *oldmap, keymap_t *newmap, struct thread *td)
1075 for (keycode = 0; keycode < NUM_KEYS; keycode++) {
1076 if ((error = key_change_ok(&oldmap->key[keycode],
1077 &newmap->key[keycode], td)) != 0)
1084 accent_change_ok(accentmap_t *oldmap, accentmap_t *newmap, struct thread *td)
1086 struct acc_t *oldacc, *newacc;
1089 if (keymap_restrict_change <= 2)
1092 if (oldmap->n_accs != newmap->n_accs)
1093 return priv_check(td, PRIV_KEYBOARD);
1095 for (accent = 0; accent < oldmap->n_accs; accent++) {
1096 oldacc = &oldmap->acc[accent];
1097 newacc = &newmap->acc[accent];
1098 if (oldacc->accchar != newacc->accchar)
1099 return priv_check(td, PRIV_KEYBOARD);
1100 for (i = 0; i < NUM_ACCENTCHARS; ++i) {
1101 if (oldacc->map[i][0] != newacc->map[i][0])
1102 return priv_check(td, PRIV_KEYBOARD);
1103 if (oldacc->map[i][0] == 0) /* end of table */
1105 if (oldacc->map[i][1] != newacc->map[i][1])
1106 return priv_check(td, PRIV_KEYBOARD);
1114 fkey_change_ok(fkeytab_t *oldkey, fkeyarg_t *newkey, struct thread *td)
1116 if (keymap_restrict_change <= 3)
1119 if (oldkey->len != newkey->flen ||
1120 bcmp(oldkey->str, newkey->keydef, oldkey->len) != 0)
1121 return priv_check(td, PRIV_KEYBOARD);
1127 /* get a pointer to the string associated with the given function key */
1129 genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len)
1134 if (fkey > kbd->kb_fkeytab_size)
1136 *len = kbd->kb_fkeytab[fkey].len;
1137 return (kbd->kb_fkeytab[fkey].str);
1140 /* diagnostic dump */
1142 get_kbd_type_name(int type)
1149 { KB_101, "AT 101/102" },
1150 { KB_OTHER, "generic" },
1154 for (i = 0; i < nitems(name_table); ++i) {
1155 if (type == name_table[i].type)
1156 return (name_table[i].name);
1162 genkbd_diag(keyboard_t *kbd, int level)
1165 printf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x",
1166 kbd->kb_index, kbd->kb_name, kbd->kb_unit,
1167 get_kbd_type_name(kbd->kb_type), kbd->kb_type,
1168 kbd->kb_config, kbd->kb_flags);
1169 if (kbd->kb_io_base > 0)
1170 printf(", port:0x%x-0x%x", kbd->kb_io_base,
1171 kbd->kb_io_base + kbd->kb_io_size - 1);
1176 #define set_lockkey_state(k, s, l) \
1177 if (!((s) & l ## DOWN)) { \
1181 i = (s) & LOCK_MASK; \
1182 (void)kbdd_ioctl((k), KDSETLED, (caddr_t)&i); \
1186 save_accent_key(keyboard_t *kbd, u_int key, int *accents)
1190 /* make an index into the accent map */
1191 i = key - F_ACC + 1;
1192 if ((i > kbd->kb_accentmap->n_accs)
1193 || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) {
1194 /* the index is out of range or pointing to an empty entry */
1200 * If the same accent key has been hit twice, produce the accent
1203 if (i == *accents) {
1204 key = kbd->kb_accentmap->acc[i - 1].accchar;
1209 /* remember the index and wait for the next key */
1215 make_accent_char(keyboard_t *kbd, u_int ch, int *accents)
1220 acc = &kbd->kb_accentmap->acc[*accents - 1];
1224 * If the accent key is followed by the space key,
1225 * produce the accent char itself.
1228 return (acc->accchar);
1230 /* scan the accent map */
1231 for (i = 0; i < NUM_ACCENTCHARS; ++i) {
1232 if (acc->map[i][0] == 0) /* end of table */
1234 if (acc->map[i][0] == ch)
1235 return (acc->map[i][1]);
1237 /* this char cannot be accented... */
1242 genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
1245 struct keyent_t *key;
1246 int state = *shiftstate;
1252 f = state & (AGRS | ALKED);
1253 if ((f == AGRS1) || (f == AGRS2) || (f == ALKED))
1255 key = &kbd->kb_keymap->key[i];
1256 i = ((state & SHIFTS) ? 1 : 0)
1257 | ((state & CTLS) ? 2 : 0)
1258 | ((state & ALTS) ? 4 : 0);
1259 if (((key->flgs & FLAG_LOCK_C) && (state & CLKED))
1260 || ((key->flgs & FLAG_LOCK_N) && (state & NLKED)) )
1263 if (up) { /* break: key released */
1264 action = kbd->kb_lastact[keycode];
1265 kbd->kb_lastact[keycode] = NOP;
1268 if (state & SHIFTAON) {
1269 set_lockkey_state(kbd, state, ALK);
1278 if (state & SHIFTAON) {
1279 set_lockkey_state(kbd, state, ALK);
1288 if (state & SHIFTAON) {
1289 set_lockkey_state(kbd, state, ALK);
1298 if (state & SHIFTAON) {
1299 set_lockkey_state(kbd, state, ALK);
1308 if (state & SHIFTAON) {
1309 set_lockkey_state(kbd, state, ALK);
1318 if (state & SHIFTAON) {
1319 set_lockkey_state(kbd, state, ALK);
1346 /* release events of regular keys are not reported */
1347 *shiftstate &= ~SHIFTAON;
1350 *shiftstate = state & ~SHIFTAON;
1351 return (SPCLKEY | RELKEY | action);
1352 } else { /* make: key pressed */
1353 action = key->map[i];
1355 if (key->spcl & (0x80 >> i)) {
1357 if (kbd->kb_lastact[keycode] == NOP)
1358 kbd->kb_lastact[keycode] = action;
1359 if (kbd->kb_lastact[keycode] != action)
1364 set_lockkey_state(kbd, state, NLK);
1367 set_lockkey_state(kbd, state, CLK);
1370 set_lockkey_state(kbd, state, SLK);
1373 set_lockkey_state(kbd, state, ALK);
1375 /* NON-LOCKING KEYS */
1376 case SPSC: case RBT: case SUSP: case STBY:
1377 case DBG: case NEXT: case PREV: case PNC:
1378 case HALT: case PDWN:
1434 *shiftstate = state;
1437 /* is this an accent (dead) key? */
1438 *shiftstate = state;
1439 if (action >= F_ACC && action <= L_ACC) {
1440 action = save_accent_key(kbd, action,
1448 return (action | MKEY);
1454 /* other special keys */
1459 if (action >= F_FN && action <= L_FN)
1461 /* XXX: return fkey string for the FKEY? */
1462 return (SPCLKEY | action);
1464 *shiftstate = state;
1465 return (SPCLKEY | action);
1468 kbd->kb_lastact[keycode] = NOP;
1469 *shiftstate = state;
1471 /* make an accented char */
1472 action = make_accent_char(kbd, action, accents);
1473 if (action == ERRKEY)
1485 kbd_ev_event(keyboard_t *kbd, uint16_t type, uint16_t code, int32_t value)
1487 int delay[2], led = 0, leds, oleds;
1489 if (type == EV_LED) {
1490 leds = oleds = KBD_LED_VAL(kbd);
1509 kbdd_ioctl(kbd, KDSETLED, (caddr_t)&leds);
1511 } else if (type == EV_REP && code == REP_DELAY) {
1513 delay[1] = kbd->kb_delay2;
1514 kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
1515 } else if (type == EV_REP && code == REP_PERIOD) {
1516 delay[0] = kbd->kb_delay1;
1518 kbdd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
1525 const keyboard_driver_t **list;
1526 const keyboard_driver_t *p;
1528 SET_FOREACH(list, kbddriver_set) {
1530 if (p->kbdsw->get_fkeystr == NULL)
1531 p->kbdsw->get_fkeystr = genkbd_get_fkeystr;
1532 if (p->kbdsw->diag == NULL)
1533 p->kbdsw->diag = genkbd_diag;
1537 SYSINIT(kbd_drv_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, kbd_drv_init, NULL);