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