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