Deleted Added
full compact
kbd.c (42421) kbd.c (42564)
1/*-
2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $Id: $
26 * $Id: kbd.c,v 1.1 1999/01/09 02:44:50 yokota Exp $
27 */
28
29#include "kbd.h"
30#include "opt_kbd.h"
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/conf.h>
37#include <sys/proc.h>
38#include <sys/tty.h>
39#include <sys/poll.h>
40#include <sys/vnode.h>
41#include <sys/uio.h>
42
43#include <machine/console.h>
44
45#include <dev/kbd/kbdreg.h>
46
47/* local arrays */
48
49/*
50 * We need at least one entry each in order to initialize a keyboard
51 * for the kernel console. The arrays will be increased dynamically
52 * when necessary.
53 */
27 */
28
29#include "kbd.h"
30#include "opt_kbd.h"
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/conf.h>
37#include <sys/proc.h>
38#include <sys/tty.h>
39#include <sys/poll.h>
40#include <sys/vnode.h>
41#include <sys/uio.h>
42
43#include <machine/console.h>
44
45#include <dev/kbd/kbdreg.h>
46
47/* local arrays */
48
49/*
50 * We need at least one entry each in order to initialize a keyboard
51 * for the kernel console. The arrays will be increased dynamically
52 * when necessary.
53 */
54static keyboard_t *kbd_ini;
55static keyboard_switch_t *kbdsw_ini;
56static struct cdevsw *kbdcdevsw_ini;
57
54
58static keyboard_t **keyboard = &kbd_ini;
59static int keyboards = 1;
55static int keyboards = 1;
56static keyboard_t *kbd_ini;
57static keyboard_t **keyboard = &kbd_ini;
58static keyboard_switch_t *kbdsw_ini;
60 keyboard_switch_t **kbdsw = &kbdsw_ini;
59 keyboard_switch_t **kbdsw = &kbdsw_ini;
61static struct cdevsw **kbdcdevsw = &kbdcdevsw_ini;
62
60
61#ifdef KBD_INSTALL_CDEV
62
63#define ARRAY_DELTA 4
64
63#define ARRAY_DELTA 4
64
65static struct cdevsw *kbdcdevsw_ini;
66static struct cdevsw **kbdcdevsw = &kbdcdevsw_ini;
67
65static void
66kbd_realloc_array(void)
67{
68 keyboard_t **new_kbd;
69 keyboard_switch_t **new_kbdsw;
70 struct cdevsw **new_cdevsw;
71 int newsize;
72 int s;
73
74 s = spltty();
75 newsize = ((keyboards + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
76 new_kbd = malloc(sizeof(*new_kbd)*newsize, M_DEVBUF, M_NOWAIT);
77 new_kbdsw = malloc(sizeof(*new_kbdsw)*newsize, M_DEVBUF, M_NOWAIT);
78 new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF, M_NOWAIT);
79 bzero(new_kbd, sizeof(*new_kbd)*newsize);
80 bzero(new_kbdsw, sizeof(*new_kbdsw)*newsize);
81 bzero(new_cdevsw, sizeof(*new_cdevsw)*newsize);
82 bcopy(keyboard, new_kbd, sizeof(*keyboard)*keyboards);
83 bcopy(kbdsw, new_kbdsw, sizeof(*kbdsw)*keyboards);
84 bcopy(kbdcdevsw, new_cdevsw, sizeof(*kbdcdevsw)*keyboards);
85 if (keyboards > 1) {
86 free(keyboard, M_DEVBUF);
87 free(kbdsw, M_DEVBUF);
88 free(kbdcdevsw, M_DEVBUF);
89 }
90 keyboard = new_kbd;
91 kbdsw = new_kbdsw;
92 kbdcdevsw = new_cdevsw;
93 keyboards = newsize;
94 splx(s);
95
96 if (bootverbose)
97 printf("kbd: new array size %d\n", keyboards);
98}
99
68static void
69kbd_realloc_array(void)
70{
71 keyboard_t **new_kbd;
72 keyboard_switch_t **new_kbdsw;
73 struct cdevsw **new_cdevsw;
74 int newsize;
75 int s;
76
77 s = spltty();
78 newsize = ((keyboards + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
79 new_kbd = malloc(sizeof(*new_kbd)*newsize, M_DEVBUF, M_NOWAIT);
80 new_kbdsw = malloc(sizeof(*new_kbdsw)*newsize, M_DEVBUF, M_NOWAIT);
81 new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF, M_NOWAIT);
82 bzero(new_kbd, sizeof(*new_kbd)*newsize);
83 bzero(new_kbdsw, sizeof(*new_kbdsw)*newsize);
84 bzero(new_cdevsw, sizeof(*new_cdevsw)*newsize);
85 bcopy(keyboard, new_kbd, sizeof(*keyboard)*keyboards);
86 bcopy(kbdsw, new_kbdsw, sizeof(*kbdsw)*keyboards);
87 bcopy(kbdcdevsw, new_cdevsw, sizeof(*kbdcdevsw)*keyboards);
88 if (keyboards > 1) {
89 free(keyboard, M_DEVBUF);
90 free(kbdsw, M_DEVBUF);
91 free(kbdcdevsw, M_DEVBUF);
92 }
93 keyboard = new_kbd;
94 kbdsw = new_kbdsw;
95 kbdcdevsw = new_cdevsw;
96 keyboards = newsize;
97 splx(s);
98
99 if (bootverbose)
100 printf("kbd: new array size %d\n", keyboards);
101}
102
103#endif /* KBD_INSTALL_CDEV */
104
100/*
101 * Low-level keyboard driver functions
102 * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard
103 * driver, call these functions to initialize the keyboard_t structure
104 * and register it to the virtual keyboard driver `kbd'.
105 */
106
107/* initialize the keyboard_t structure */
108void
109kbd_init_struct(keyboard_t *kbd, char *name, int type, int unit, int config,
110 int port, int port_size)
111{
112 kbd->kb_flags = KB_NO_DEVICE; /* device has not been found */
113 kbd->kb_name = name;
114 kbd->kb_type = type;
115 kbd->kb_unit = unit;
116 kbd->kb_config = config;
117 kbd->kb_led = 0; /* unknown */
118 kbd->kb_io_base = port;
119 kbd->kb_io_size = port_size;
120 kbd->kb_data = NULL;
121 kbd->kb_keymap = NULL;
122 kbd->kb_accentmap = NULL;
123 kbd->kb_fkeytab = NULL;
124 kbd->kb_fkeytab_size = 0;
125}
126
127void
128kbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accentmap_t *accmap,
129 fkeytab_t *fkeymap, int fkeymap_size)
130{
131 kbd->kb_keymap = keymap;
132 kbd->kb_accentmap = accmap;
133 kbd->kb_fkeytab = fkeymap;
134 kbd->kb_fkeytab_size = fkeymap_size;
135}
136
137/* register a keyboard and associate it with a function table */
138int
139kbd_register(keyboard_t *kbd)
140{
141 keyboard_driver_t **list;
142 keyboard_driver_t *p;
143 int index;
144
145 for (index = 0; index < keyboards; ++index) {
146 if (keyboard[index] == NULL)
147 break;
148 }
149 if (index >= keyboards)
150 return -1;
151
152 kbd->kb_index = index;
153 KBD_UNBUSY(kbd);
154 KBD_VALID(kbd);
155 kbd->kb_active = 0; /* disabled until someone calls kbd_enable() */
156 kbd->kb_token = NULL;
157 kbd->kb_callback.kc_func = NULL;
158 kbd->kb_callback.kc_arg = NULL;
159
160 list = (keyboard_driver_t **)kbddriver_set.ls_items;
161 while ((p = *list++) != NULL) {
162 if (strcmp(p->name, kbd->kb_name) == 0) {
163 keyboard[index] = kbd;
164 kbdsw[index] = p->kbdsw;
165 return index;
166 }
167 }
168
169 return -1;
170}
171
172int
173kbd_unregister(keyboard_t *kbd)
174{
175 int error;
176 int s;
177
178 if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards))
179 return ENOENT;
180 if (keyboard[kbd->kb_index] != kbd)
181 return ENOENT;
182
183 s = spltty();
184 if (KBD_IS_BUSY(kbd)) {
185 error = (*kbd->kb_callback.kc_func)(kbd, KBDIO_UNLOADING,
186 kbd->kb_callback.kc_arg);
187 if (error) {
188 splx(s);
189 return error;
190 }
191 if (KBD_IS_BUSY(kbd)) {
192 splx(s);
193 return EBUSY;
194 }
195 }
196 KBD_INVALID(kbd);
197 keyboard[kbd->kb_index] = NULL;
198 kbdsw[kbd->kb_index] = NULL;
199
200 splx(s);
201 return 0;
202}
203
204/* find a funciton table by the driver name */
205keyboard_switch_t
206*kbd_get_switch(char *driver)
207{
208 keyboard_driver_t **list;
209 keyboard_driver_t *p;
210
211 list = (keyboard_driver_t **)kbddriver_set.ls_items;
212 while ((p = *list++) != NULL) {
213 if (strcmp(p->name, driver) == 0)
214 return p->kbdsw;
215 }
216
217 return NULL;
218}
219
220/*
221 * Keyboard client functions
222 * Keyboard clients, such as the console driver `syscons' and the keyboard
223 * cdev driver, use these functions to claim and release a keyboard for
224 * exclusive use.
225 */
226
227/* find the keyboard specified by a driver name and a unit number */
228int
229kbd_find_keyboard(char *driver, int unit)
230{
231 int i;
232
233 for (i = 0; i < keyboards; ++i) {
234 if (keyboard[i] == NULL)
235 continue;
236 if (!KBD_IS_VALID(keyboard[i]))
237 continue;
238 if (strcmp("*", driver) && strcmp(keyboard[i]->kb_name, driver))
239 continue;
240 if ((unit != -1) && (keyboard[i]->kb_unit != unit))
241 continue;
242 return i;
243 }
244 return -1;
245}
246
247/* allocate a keyboard */
248int
249kbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func,
250 void *arg)
251{
252 int index;
253 int s;
254
255 if (func == NULL)
256 return -1;
257
258 s = spltty();
259 index = kbd_find_keyboard(driver, unit);
260 if (index >= 0) {
261 if (KBD_IS_BUSY(keyboard[index])) {
262 splx(s);
263 return -1;
264 }
265 keyboard[index]->kb_token = id;
266 KBD_BUSY(keyboard[index]);
267 keyboard[index]->kb_callback.kc_func = func;
268 keyboard[index]->kb_callback.kc_arg = arg;
269 (*kbdsw[index]->clear_state)(keyboard[index]);
270 }
271 splx(s);
272 return index;
273}
274
275int
276kbd_release(keyboard_t *kbd, void *id)
277{
278 int error;
279 int s;
280
281 s = spltty();
282 if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
283 error = EINVAL;
284 } else if (kbd->kb_token != id) {
285 error = EPERM;
286 } else {
287 kbd->kb_token = NULL;
288 KBD_UNBUSY(kbd);
289 kbd->kb_callback.kc_func = NULL;
290 kbd->kb_callback.kc_arg = NULL;
291 (*kbdsw[kbd->kb_index]->clear_state)(kbd);
292 error = 0;
293 }
294 splx(s);
295 return error;
296}
297
298int
299kbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func,
300 void *arg)
301{
302 int error;
303 int s;
304
305 s = spltty();
306 if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
307 error = EINVAL;
308 } else if (kbd->kb_token != id) {
309 error = EPERM;
310 } else if (func == NULL) {
311 error = EINVAL;
312 } else {
313 kbd->kb_callback.kc_func = func;
314 kbd->kb_callback.kc_arg = arg;
315 error = 0;
316 }
317 splx(s);
318 return error;
319}
320
321/* get a keyboard structure */
322keyboard_t
323*kbd_get_keyboard(int index)
324{
325 if ((index < 0) || (index >= keyboards))
326 return NULL;
327 if (!KBD_IS_VALID(keyboard[index]))
328 return NULL;
329 return keyboard[index];
330}
331
332/*
333 * The back door for the console driver; configure keyboards
334 * This function is for the kernel console to initialize keyboards
335 * at very early stage.
336 */
337
338int
339kbd_configure(int flags)
340{
341 keyboard_driver_t **list;
342 keyboard_driver_t *p;
343
344 list = (keyboard_driver_t **)kbddriver_set.ls_items;
345 while ((p = *list++) != NULL) {
346 if (p->configure != NULL)
347 (*p->configure)(flags);
348 }
349
350 return 0;
351}
352
353#ifdef KBD_INSTALL_CDEV
354
355/*
356 * Virtual keyboard cdev driver functions
357 * The virtual keyboard driver dispatches driver functions to
358 * appropriate subdrivers.
359 */
360
361#define KBD_UNIT(dev) minor(dev)
362
363static d_open_t kbdopen;
364static d_close_t kbdclose;
365static d_read_t kbdread;
366static d_write_t kbdwrite;
367static d_ioctl_t kbdioctl;
368static d_reset_t kbdreset;
369static d_devtotty_t kbddevtotty;
370static d_poll_t kbdpoll;
371static d_mmap_t kbdmmap;
372
373#define CDEV_MAJOR 112
374
375static struct cdevsw kbd_cdevsw = {
376 kbdopen, kbdclose, kbdread, kbdwrite, /* ??? */
377 kbdioctl, nullstop, kbdreset, kbddevtotty,
378 kbdpoll, kbdmmap, nostrategy, "kbd",
379 NULL, -1, nodump, nopsize,
380};
381
382static void
383vkbdattach(void *arg)
384{
385 static int kbd_devsw_installed = FALSE;
386 dev_t dev;
387
388 if (!kbd_devsw_installed) {
389 dev = makedev(CDEV_MAJOR, 0);
390 cdevsw_add(&dev, &kbd_cdevsw, NULL);
391 kbd_devsw_installed = TRUE;
392 }
393}
394
395PSEUDO_SET(vkbdattach, kbd);
396
397int
398kbd_attach(dev_t dev, keyboard_t *kbd, struct cdevsw *cdevsw)
399{
400 int s;
401
402 if (kbd->kb_index >= keyboards)
403 return EINVAL;
404 if (keyboard[kbd->kb_index] != kbd)
405 return EINVAL;
406
407 s = spltty();
408 kbd->kb_minor = minor(dev);
409 kbdcdevsw[kbd->kb_index] = cdevsw;
410 splx(s);
411
412 /* XXX: DEVFS? */
413
414 if (kbd->kb_index + 1 >= keyboards)
415 kbd_realloc_array();
416
417 printf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit);
418 return 0;
419}
420
421int
422kbd_detach(dev_t dev, keyboard_t *kbd, struct cdevsw *cdevsw)
423{
424 int s;
425
426 if (kbd->kb_index >= keyboards)
427 return EINVAL;
428 if (keyboard[kbd->kb_index] != kbd)
429 return EINVAL;
430 if (kbdcdevsw[kbd->kb_index] != cdevsw)
431 return EINVAL;
432
433 s = spltty();
434 (*kbdsw[kbd->kb_index]->term)(kbd);
435 kbdcdevsw[kbd->kb_index] = NULL;
436 splx(s);
437 return 0;
438}
439
440static int
441kbdopen(dev_t dev, int flag, int mode, struct proc *p)
442{
443 int unit;
444
445 unit = KBD_UNIT(dev);
446 if (unit >= keyboards)
447 return ENXIO;
448 if (kbdcdevsw[unit] == NULL)
449 return ENXIO;
450 if (KBD_IS_BUSY(keyboard[unit]))
451 return EBUSY;
452 return (*kbdcdevsw[unit]->d_open)(makedev(0, keyboard[unit]->kb_minor),
453 flag, mode, p);
454}
455
456static int
457kbdclose(dev_t dev, int flag, int mode, struct proc *p)
458{
459 int unit;
460
461 unit = KBD_UNIT(dev);
462 if (kbdcdevsw[unit] == NULL)
463 return ENXIO;
464 return (*kbdcdevsw[unit]->d_close)(makedev(0, keyboard[unit]->kb_minor),
465 flag, mode, p);
466}
467
468static int
469kbdread(dev_t dev, struct uio *uio, int flag)
470{
471 int unit;
472
473 unit = KBD_UNIT(dev);
474 if (kbdcdevsw[unit] == NULL)
475 return ENXIO;
476 return (*kbdcdevsw[unit]->d_read)(makedev(0, keyboard[unit]->kb_minor),
477 uio, flag);
478}
479
480static int
481kbdwrite(dev_t dev, struct uio *uio, int flag)
482{
483 int unit;
484
485 unit = KBD_UNIT(dev);
486 if (kbdcdevsw[unit] == NULL)
487 return ENXIO;
488 return (*kbdcdevsw[unit]->d_write)(makedev(0, keyboard[unit]->kb_minor),
489 uio, flag);
490}
491
492static int
493kbdioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
494{
495 int unit;
496
497 unit = KBD_UNIT(dev);
498 if (kbdcdevsw[unit] == NULL)
499 return ENXIO;
500 return (*kbdcdevsw[unit]->d_ioctl)(makedev(0, keyboard[unit]->kb_minor),
501 cmd, arg, flag, p);
502}
503
504static int
505kbdreset(dev_t dev)
506{
507 int unit;
508
509 unit = KBD_UNIT(dev);
510 if (kbdcdevsw[unit] == NULL)
511 return ENXIO;
512 return (*kbdcdevsw[unit]->d_reset)(makedev(0, keyboard[unit]->kb_minor));
513}
514
515static struct tty
516*kbddevtotty(dev_t dev)
517{
518 int unit;
519
520 unit = KBD_UNIT(dev);
521 if (kbdcdevsw[unit] == NULL)
522 return NULL;
523 return (*kbdcdevsw[unit]->d_devtotty)(makedev(0, keyboard[unit]->kb_minor));
524}
525
526static int
527kbdpoll(dev_t dev, int event, struct proc *p)
528{
529 int unit;
530
531 unit = KBD_UNIT(dev);
532 if (kbdcdevsw[unit] == NULL)
533 return ENXIO;
534 return (*kbdcdevsw[unit]->d_poll)(makedev(0, keyboard[unit]->kb_minor),
535 event, p);
536}
537
538static int
539kbdmmap(dev_t dev, vm_offset_t offset, int nprot)
540{
541 int unit;
542
543 unit = KBD_UNIT(dev);
544 if (kbdcdevsw[unit] == NULL)
545 return ENXIO;
546 return (*kbdcdevsw[unit]->d_mmap)(makedev(0, keyboard[unit]->kb_minor),
547 offset, nprot);
548}
549
550/*
551 * Generic keyboard cdev driver functions
552 * Keyboard subdrivers may call these functions to implement common
553 * driver functions.
554 */
555
556#define KB_QSIZE 512
557#define KB_BUFSIZE 64
558
559static kbd_callback_func_t genkbd_event;
560
561int
562genkbdopen(genkbd_softc_t *sc, keyboard_t *kbd, int mode, int flag,
563 struct proc *p)
564{
565 int s;
566 int i;
567
568 s = spltty();
569 if (!KBD_IS_VALID(kbd)) {
570 splx(s);
571 return ENXIO;
572 }
573 i = kbd_allocate(kbd->kb_name, kbd->kb_unit, sc,
574 genkbd_event, (void *)sc);
575 if (i < 0) {
576 splx(s);
577 return EBUSY;
578 }
579 /* assert(i == kbd->kb_index) */
580 /* assert(kbd == kbd_get_keyboard(i)) */
581
582 /*
583 * NOTE: even when we have successfully claimed a keyboard,
584 * the device may still be missing (!KBD_HAS_DEVICE(kbd)).
585 */
586
587#if 0
588 bzero(&sc->gkb_q, sizeof(sc->gkb_q));
589#endif
590 clist_alloc_cblocks(&sc->gkb_q, KB_QSIZE, KB_QSIZE/2); /* XXX */
591 sc->gkb_rsel.si_flags = 0;
592 sc->gkb_rsel.si_pid = 0;
593 splx(s);
594
595 return 0;
596}
597
598int
599genkbdclose(genkbd_softc_t *sc, keyboard_t *kbd, int mode, int flag,
600 struct proc *p)
601{
602 int s;
603
604 /*
605 * NOTE: the device may have already become invalid.
606 * !KBD_IS_VALID(kbd)
607 */
608 s = spltty();
609 kbd_release(kbd, (void *)sc);
610#if 0
611 clist_free_cblocks(&sc->gkb_q);
612#endif
613 splx(s);
614
615 return 0;
616}
617
618int
619genkbdread(genkbd_softc_t *sc, keyboard_t *kbd, struct uio *uio, int flag)
620{
621 u_char buffer[KB_BUFSIZE];
622 int len;
623 int error;
624 int s;
625
626 /* wait for input */
627 s = spltty();
628 while (sc->gkb_q.c_cc == 0) {
629 if (!KBD_IS_VALID(kbd)) {
630 splx(s);
631 return EIO;
632 }
633 if (flag & IO_NDELAY) {
634 splx(s);
635 return EWOULDBLOCK;
636 }
637 sc->gkb_flags |= KB_ASLEEP;
638 error = tsleep((caddr_t)sc, PZERO | PCATCH, "kbdrea", 0);
639 if (error) {
640 sc->gkb_flags &= ~KB_ASLEEP;
641 splx(s);
642 return error;
643 }
644 }
645 splx(s);
646
647 /* copy as much input as possible */
648 error = 0;
649 while (uio->uio_resid > 0) {
650 len = imin(uio->uio_resid, sizeof(buffer));
651 len = q_to_b(&sc->gkb_q, buffer, len);
652 if (len <= 0)
653 break;
654 error = uiomove(buffer, len, uio);
655 if (error)
656 break;
657 }
658
659 return error;
660}
661
662int
663genkbdwrite(genkbd_softc_t *sc, keyboard_t *kbd, struct uio *uio, int flag)
664{
665 if (!KBD_IS_VALID(kbd))
666 return ENXIO;
667 return ENODEV;
668}
669
670int
671genkbdioctl(genkbd_softc_t *sc, keyboard_t *kbd, u_long cmd, caddr_t arg,
672 int flag, struct proc *p)
673{
674 int error;
675
676 if (kbd == NULL) /* XXX */
677 return ENXIO;
678 if (!KBD_IS_VALID(kbd))
679 return ENXIO;
680 error = (*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, arg);
681 if (error == ENOIOCTL)
682 error = ENODEV;
683 return error;
684}
685
686int
687genkbdpoll(genkbd_softc_t *sc, keyboard_t *kbd, int events, struct proc *p)
688{
689 int revents;
690 int s;
691
692 revents = 0;
693 s = spltty();
694 if (events & (POLLIN | POLLRDNORM)) {
695 if ((sc->gkb_q.c_cc > 0) || !KBD_IS_VALID(kbd))
696 revents |= (POLLIN | POLLRDNORM);
697 else
698 selrecord(p, &sc->gkb_rsel);
699 }
700 splx(s);
701 return revents;
702}
703
704static int
705genkbd_event(keyboard_t *kbd, int event, void *arg)
706{
707 genkbd_softc_t *sc;
708 size_t len;
709 u_char *cp;
710 int mode;
711 int c;
712
713 /* assert(KBD_IS_VALID(kbd)) */
714 sc = (genkbd_softc_t *)arg;
715
716 switch (event) {
717 case KBDIO_KEYINPUT:
718 break;
719 case KBDIO_UNLOADING:
720 /* the keyboard is going... */
721 kbd_release(kbd, (void *)sc);
722 return 0;
723 default:
724 return EINVAL;
725 }
726
727 /* obtain the current key input mode */
728 if ((*kbdsw[kbd->kb_index]->ioctl)(kbd, KDGKBMODE, (caddr_t)&mode))
729 mode = K_XLATE;
730
731 /* read all pending input */
732 while ((*kbdsw[kbd->kb_index]->check_char)(kbd)) {
733 c = (*kbdsw[kbd->kb_index]->read_char)(kbd, FALSE);
734 if (c == NOKEY)
735 continue;
736 if (c == ERRKEY) /* XXX: ring bell? */
737 continue;
738 if (!KBD_IS_BUSY(kbd))
739 /* the device is not open, discard the input */
740 continue;
741
742 /* store the byte as is for K_RAW and K_CODE modes */
743 if (mode != K_XLATE) {
744 putc(KEYCHAR(c), &sc->gkb_q);
745 continue;
746 }
747
748 /* K_XLATE */
749 if (c & RELKEY) /* key release is ignored */
750 continue;
751
752 /* process special keys; most of them are just ignored... */
753 if (c & SPCLKEY) {
754 switch (KEYCHAR(c)) {
755 /* locking keys */
756 case NLK: case CLK: case SLK: case ALK:
757 /* shift keys */
758 case LSH: case RSH: case LCTR: case RCTR:
759 case LALT: case RALT: case ASH: case META:
760 /* other special keys */
761 case NOP: case SPSC: case RBT: case SUSP:
762 case STBY: case DBG: case NEXT:
763 /* ignore them... */
764 continue;
765 case BTAB: /* a backtab: ESC [ Z */
766 putc(0x1b, &sc->gkb_q);
767 putc('[', &sc->gkb_q);
768 putc('Z', &sc->gkb_q);
769 continue;
770 }
771 }
772
773 /* normal chars, normal chars with the META, function keys */
774 switch (KEYFLAGS(c)) {
775 case 0: /* a normal char */
776 putc(KEYCHAR(c), &sc->gkb_q);
777 break;
778 case MKEY: /* the META flag: prepend ESC */
779 putc(0x1b, &sc->gkb_q);
780 putc(KEYCHAR(c), &sc->gkb_q);
781 break;
782 case FKEY | SPCLKEY: /* a function key, return string */
783 cp = (*kbdsw[kbd->kb_index]->get_fkeystr)(kbd,
784 KEYCHAR(c), &len);
785 if (cp != NULL) {
786 while (len-- > 0)
787 putc(*cp++, &sc->gkb_q);
788 }
789 break;
790 }
791 }
792
793 /* wake up sleeping/polling processes */
794 if (sc->gkb_q.c_cc > 0) {
795 if (sc->gkb_flags & KB_ASLEEP) {
796 sc->gkb_flags &= ~KB_ASLEEP;
797 wakeup((caddr_t)sc);
798 }
799 selwakeup(&sc->gkb_rsel);
800 }
801
802 return 0;
803}
804
805#endif /* KBD_INSTALL_CDEV */
806
807/*
808 * Generic low-level keyboard functions
809 * The low-level functions in the keyboard subdriver may use these
810 * functions.
811 */
812
813int
814genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
815{
816 keyarg_t *keyp;
817 fkeyarg_t *fkeyp;
818 int s;
819 int i;
820
821 s = spltty();
822 switch (cmd) {
823
824 case KDGKBINFO: /* get keyboard information */
825 ((keyboard_info_t *)arg)->kb_index = kbd->kb_index;
826 i = imin(strlen(kbd->kb_name) + 1,
827 sizeof(((keyboard_info_t *)arg)->kb_name));
828 bcopy(kbd->kb_name, ((keyboard_info_t *)arg)->kb_name, i);
829 ((keyboard_info_t *)arg)->kb_unit = kbd->kb_unit;
830 ((keyboard_info_t *)arg)->kb_type = kbd->kb_type;
831 ((keyboard_info_t *)arg)->kb_config = kbd->kb_config;
832 ((keyboard_info_t *)arg)->kb_flags = kbd->kb_flags;
833 break;
834
835 case KDGKBTYPE: /* get keyboard type */
836 *(int *)arg = kbd->kb_type;
837 break;
838
839 case GIO_KEYMAP: /* get keyboard translation table */
840 bcopy(kbd->kb_keymap, arg, sizeof(*kbd->kb_keymap));
841 break;
842 case PIO_KEYMAP: /* set keyboard translation table */
843 bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
844 bcopy(arg, kbd->kb_keymap, sizeof(*kbd->kb_keymap));
845 break;
846
847 case GIO_KEYMAPENT: /* get keyboard translation table entry */
848 keyp = (keyarg_t *)arg;
849 if (keyp->keynum >= sizeof(kbd->kb_keymap->key)
850 /sizeof(kbd->kb_keymap->key[0])) {
851 splx(s);
852 return EINVAL;
853 }
854 bcopy(&kbd->kb_keymap[keyp->keynum], &keyp->key,
855 sizeof(keyp->key));
856 break;
857 case PIO_KEYMAPENT: /* set keyboard translation table entry */
858 keyp = (keyarg_t *)arg;
859 if (keyp->keynum >= sizeof(kbd->kb_keymap->key)
860 /sizeof(kbd->kb_keymap->key[0])) {
861 splx(s);
862 return EINVAL;
863 }
864 bcopy(&keyp->key, &kbd->kb_keymap[keyp->keynum],
865 sizeof(keyp->key));
866 break;
867
868 case GIO_DEADKEYMAP: /* get accent key translation table */
869 bcopy(kbd->kb_accentmap, arg, sizeof(*kbd->kb_accentmap));
870 break;
871 case PIO_DEADKEYMAP: /* set accent key translation table */
872 bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
873 break;
874
875 case GETFKEY: /* get functionkey string */
876 fkeyp = (fkeyarg_t *)arg;
877 if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
878 splx(s);
879 return EINVAL;
880 }
881 bcopy(kbd->kb_fkeytab[fkeyp->keynum].str, fkeyp->keydef,
882 kbd->kb_fkeytab[fkeyp->keynum].len);
883 fkeyp->flen = kbd->kb_fkeytab[fkeyp->keynum].len;
884 break;
885 case SETFKEY: /* set functionkey string */
886 fkeyp = (fkeyarg_t *)arg;
887 if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
888 splx(s);
889 return EINVAL;
890 }
891 kbd->kb_fkeytab[fkeyp->keynum].len = imin(fkeyp->flen, MAXFK);
892 bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str,
893 kbd->kb_fkeytab[fkeyp->keynum].len);
894 break;
895
896 default:
897 splx(s);
898 return ENOIOCTL;
899 }
900
901 splx(s);
902 return 0;
903}
904
905/* get a pointer to the string associated with the given function key */
906u_char
907*genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len)
908{
909 if (kbd == NULL)
910 return NULL;
911 fkey -= F_FN;
912 if (fkey > kbd->kb_fkeytab_size)
913 return NULL;
914 *len = kbd->kb_fkeytab[fkey].len;
915 return kbd->kb_fkeytab[fkey].str;
916}
917
918/* diagnostic dump */
919static char
920*get_kbd_type_name(int type)
921{
922 static struct {
923 int type;
924 char *name;
925 } name_table[] = {
926 { KB_84, "AT 84" },
927 { KB_101, "AT 101/102" },
928 { KB_OTHER, "generic" },
929 };
930 int i;
931
932 for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) {
933 if (type == name_table[i].type)
934 return name_table[i].name;
935 }
936 return "unknown";
937}
938
939void
940genkbd_diag(keyboard_t *kbd, int level)
941{
942 if (level > 0) {
943 printf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x",
944 kbd->kb_index, kbd->kb_name, kbd->kb_unit,
945 get_kbd_type_name(kbd->kb_type), kbd->kb_type,
946 kbd->kb_config, kbd->kb_flags);
947 if (kbd->kb_io_base > 0)
948 printf(", port:0x%x-0x%x", kbd->kb_io_base,
949 kbd->kb_io_base + kbd->kb_io_size - 1);
950 printf("\n");
951 }
952}
953
954#define set_lockkey_state(k, s, l) \
955 if (!((s) & l ## DOWN)) { \
956 int i; \
957 (s) |= l ## DOWN; \
958 (s) ^= l ## ED; \
959 i = (s) & LOCK_MASK; \
960 (*kbdsw[(k)->kb_index]->ioctl)((k), KDSETLED, (caddr_t)&i); \
961 }
962
963static u_int
964save_accent_key(keyboard_t *kbd, u_int key, int *accents)
965{
966 int i;
967
968 /* make an index into the accent map */
969 i = key - F_ACC + 1;
970 if ((i > kbd->kb_accentmap->n_accs)
971 || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) {
972 /* the index is out of range or pointing to an empty entry */
973 *accents = 0;
974 return ERRKEY;
975 }
976
977 /*
978 * If the same accent key has been hit twice, produce the accent char
979 * itself.
980 */
981 if (i == *accents) {
982 key = kbd->kb_accentmap->acc[i - 1].accchar;
983 *accents = 0;
984 return key;
985 }
986
987 /* remember the index and wait for the next key */
988 *accents = i;
989 return NOKEY;
990}
991
992static u_int
993make_accent_char(keyboard_t *kbd, u_int ch, int *accents)
994{
995 struct acc_t *acc;
996 int i;
997
998 acc = &kbd->kb_accentmap->acc[*accents - 1];
999 *accents = 0;
1000
1001 /*
1002 * If the accent key is followed by the space key,
1003 * produce the accent char itself.
1004 */
1005 if (ch == ' ')
1006 return acc->accchar;
1007
1008 /* scan the accent map */
1009 for (i = 0; i < NUM_ACCENTCHARS; ++i) {
1010 if (acc->map[i][0] == 0) /* end of table */
1011 break;
1012 if (acc->map[i][0] == ch)
1013 return acc->map[i][1];
1014 }
1015 /* this char cannot be accented... */
1016 return ERRKEY;
1017}
1018
1019int
1020genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
1021 int *accents)
1022{
1023 struct keyent_t *key;
1024 int state = *shiftstate;
1025 int action;
1026 int f;
1027 int i;
1028
1029 f = state & (AGRS | ALKED);
1030 if ((f == AGRS1) || (f == AGRS2) || (f == ALKED))
1031 keycode += ALTGR_OFFSET;
1032 key = &kbd->kb_keymap->key[keycode];
1033 i = ((state & SHIFTS) ? 1 : 0)
1034 | ((state & CTLS) ? 2 : 0)
1035 | ((state & ALTS) ? 4 : 0);
1036 if (((key->flgs & FLAG_LOCK_C) && (state & CLKED))
1037 || ((key->flgs & FLAG_LOCK_N) && (state & NLKED)) )
1038 i ^= 1;
1039
1040 action = key->map[i];
1041 if (up) { /* break: key released */
1042 if (key->spcl & (0x80 >> i)) {
1043 /* special keys */
1044 switch (action) {
1045 case LSH:
1046 state &= ~SHIFTS1;
1047 break;
1048 case RSH:
1049 state &= ~SHIFTS2;
1050 break;
1051 case LCTR:
1052 state &= ~CTLS1;
1053 break;
1054 case RCTR:
1055 state &= ~CTLS2;
1056 break;
1057 case LALT:
1058 state &= ~ALTS1;
1059 break;
1060 case RALT:
1061 state &= ~ALTS2;
1062 break;
1063 case ASH:
1064 state &= ~AGRS1;
1065 break;
1066 case META:
1067 state &= ~METAS1;
1068 break;
1069 case NLK:
1070 state &= ~NLKDOWN;
1071 break;
1072 case CLK:
1073#ifndef PC98
1074 state &= ~CLKDOWN;
1075#else
1076 state &= ~CLKED;
1077 i = state & LOCK_MASK;
1078 (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED,
1079 (caddr_t)&i);
1080#endif
1081 break;
1082 case SLK:
1083 state &= ~SLKDOWN;
1084 break;
1085 case ALK:
1086 state &= ~ALKDOWN;
1087 break;
1088 }
1089 *shiftstate = state;
1090 return (SPCLKEY | RELKEY | action);
1091 }
1092 /* release events of regular keys are not reported */
1093 return NOKEY;
1094 } else { /* make: key pressed */
1095 if (key->spcl & (0x80 >> i)) {
1096 /* special keys */
1097 switch (action) {
1098 /* LOCKING KEYS */
1099 case NLK:
1100 set_lockkey_state(kbd, state, NLK);
1101 break;
1102 case CLK:
1103#ifndef PC98
1104 set_lockkey_state(kbd, state, CLK);
1105#else
1106 state |= CLKED;
1107 i = state & LOCK_MASK;
1108 (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED,
1109 (caddr_t)&i);
1110#endif
1111 break;
1112 case SLK:
1113 set_lockkey_state(kbd, state, SLK);
1114 break;
1115 case ALK:
1116 set_lockkey_state(kbd, state, ALK);
1117 break;
1118 /* NON-LOCKING KEYS */
1119 case SPSC: case RBT: case SUSP: case STBY:
1120 case DBG: case NEXT:
1121 *accents = 0;
1122 break;
1123 case BTAB:
1124 *accents = 0;
1125 action |= BKEY;
1126 break;
1127 case LSH:
1128 state |= SHIFTS1;
1129 break;
1130 case RSH:
1131 state |= SHIFTS2;
1132 break;
1133 case LCTR:
1134 state |= CTLS1;
1135 break;
1136 case RCTR:
1137 state |= CTLS2;
1138 break;
1139 case LALT:
1140 state |= ALTS1;
1141 break;
1142 case RALT:
1143 state |= ALTS2;
1144 break;
1145 case ASH:
1146 state |= AGRS1;
1147 break;
1148 case META:
1149 state |= METAS1;
1150 break;
1151 default:
1152 /* is this an accent (dead) key? */
1153 if (action >= F_ACC && action <= L_ACC) {
1154 action = save_accent_key(kbd, action,
1155 accents);
1156 switch (action) {
1157 case NOKEY:
1158 case ERRKEY:
1159 return action;
1160 default:
1161 if (state & METAS)
1162 return (action | MKEY);
1163 else
1164 return action;
1165 }
1166 /* NOT REACHED */
1167 }
1168 /* other special keys */
1169 if (*accents > 0) {
1170 *accents = 0;
1171 return ERRKEY;
1172 }
1173 if (action >= F_FN && action <= L_FN)
1174 action |= FKEY;
1175 /* XXX: return fkey string for the FKEY? */
1176 }
1177 *shiftstate = state;
1178 return (SPCLKEY | action);
1179 } else {
1180 /* regular keys */
1181 if (*accents > 0) {
1182 /* make an accented char */
1183 action = make_accent_char(kbd, action, accents);
1184 if (action == ERRKEY)
1185 return action;
1186 }
1187 if (state & METAS)
1188 action |= MKEY;
1189 return action;
1190 }
1191 }
1192 /* NOT REACHED */
1193}
105/*
106 * Low-level keyboard driver functions
107 * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard
108 * driver, call these functions to initialize the keyboard_t structure
109 * and register it to the virtual keyboard driver `kbd'.
110 */
111
112/* initialize the keyboard_t structure */
113void
114kbd_init_struct(keyboard_t *kbd, char *name, int type, int unit, int config,
115 int port, int port_size)
116{
117 kbd->kb_flags = KB_NO_DEVICE; /* device has not been found */
118 kbd->kb_name = name;
119 kbd->kb_type = type;
120 kbd->kb_unit = unit;
121 kbd->kb_config = config;
122 kbd->kb_led = 0; /* unknown */
123 kbd->kb_io_base = port;
124 kbd->kb_io_size = port_size;
125 kbd->kb_data = NULL;
126 kbd->kb_keymap = NULL;
127 kbd->kb_accentmap = NULL;
128 kbd->kb_fkeytab = NULL;
129 kbd->kb_fkeytab_size = 0;
130}
131
132void
133kbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accentmap_t *accmap,
134 fkeytab_t *fkeymap, int fkeymap_size)
135{
136 kbd->kb_keymap = keymap;
137 kbd->kb_accentmap = accmap;
138 kbd->kb_fkeytab = fkeymap;
139 kbd->kb_fkeytab_size = fkeymap_size;
140}
141
142/* register a keyboard and associate it with a function table */
143int
144kbd_register(keyboard_t *kbd)
145{
146 keyboard_driver_t **list;
147 keyboard_driver_t *p;
148 int index;
149
150 for (index = 0; index < keyboards; ++index) {
151 if (keyboard[index] == NULL)
152 break;
153 }
154 if (index >= keyboards)
155 return -1;
156
157 kbd->kb_index = index;
158 KBD_UNBUSY(kbd);
159 KBD_VALID(kbd);
160 kbd->kb_active = 0; /* disabled until someone calls kbd_enable() */
161 kbd->kb_token = NULL;
162 kbd->kb_callback.kc_func = NULL;
163 kbd->kb_callback.kc_arg = NULL;
164
165 list = (keyboard_driver_t **)kbddriver_set.ls_items;
166 while ((p = *list++) != NULL) {
167 if (strcmp(p->name, kbd->kb_name) == 0) {
168 keyboard[index] = kbd;
169 kbdsw[index] = p->kbdsw;
170 return index;
171 }
172 }
173
174 return -1;
175}
176
177int
178kbd_unregister(keyboard_t *kbd)
179{
180 int error;
181 int s;
182
183 if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards))
184 return ENOENT;
185 if (keyboard[kbd->kb_index] != kbd)
186 return ENOENT;
187
188 s = spltty();
189 if (KBD_IS_BUSY(kbd)) {
190 error = (*kbd->kb_callback.kc_func)(kbd, KBDIO_UNLOADING,
191 kbd->kb_callback.kc_arg);
192 if (error) {
193 splx(s);
194 return error;
195 }
196 if (KBD_IS_BUSY(kbd)) {
197 splx(s);
198 return EBUSY;
199 }
200 }
201 KBD_INVALID(kbd);
202 keyboard[kbd->kb_index] = NULL;
203 kbdsw[kbd->kb_index] = NULL;
204
205 splx(s);
206 return 0;
207}
208
209/* find a funciton table by the driver name */
210keyboard_switch_t
211*kbd_get_switch(char *driver)
212{
213 keyboard_driver_t **list;
214 keyboard_driver_t *p;
215
216 list = (keyboard_driver_t **)kbddriver_set.ls_items;
217 while ((p = *list++) != NULL) {
218 if (strcmp(p->name, driver) == 0)
219 return p->kbdsw;
220 }
221
222 return NULL;
223}
224
225/*
226 * Keyboard client functions
227 * Keyboard clients, such as the console driver `syscons' and the keyboard
228 * cdev driver, use these functions to claim and release a keyboard for
229 * exclusive use.
230 */
231
232/* find the keyboard specified by a driver name and a unit number */
233int
234kbd_find_keyboard(char *driver, int unit)
235{
236 int i;
237
238 for (i = 0; i < keyboards; ++i) {
239 if (keyboard[i] == NULL)
240 continue;
241 if (!KBD_IS_VALID(keyboard[i]))
242 continue;
243 if (strcmp("*", driver) && strcmp(keyboard[i]->kb_name, driver))
244 continue;
245 if ((unit != -1) && (keyboard[i]->kb_unit != unit))
246 continue;
247 return i;
248 }
249 return -1;
250}
251
252/* allocate a keyboard */
253int
254kbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func,
255 void *arg)
256{
257 int index;
258 int s;
259
260 if (func == NULL)
261 return -1;
262
263 s = spltty();
264 index = kbd_find_keyboard(driver, unit);
265 if (index >= 0) {
266 if (KBD_IS_BUSY(keyboard[index])) {
267 splx(s);
268 return -1;
269 }
270 keyboard[index]->kb_token = id;
271 KBD_BUSY(keyboard[index]);
272 keyboard[index]->kb_callback.kc_func = func;
273 keyboard[index]->kb_callback.kc_arg = arg;
274 (*kbdsw[index]->clear_state)(keyboard[index]);
275 }
276 splx(s);
277 return index;
278}
279
280int
281kbd_release(keyboard_t *kbd, void *id)
282{
283 int error;
284 int s;
285
286 s = spltty();
287 if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
288 error = EINVAL;
289 } else if (kbd->kb_token != id) {
290 error = EPERM;
291 } else {
292 kbd->kb_token = NULL;
293 KBD_UNBUSY(kbd);
294 kbd->kb_callback.kc_func = NULL;
295 kbd->kb_callback.kc_arg = NULL;
296 (*kbdsw[kbd->kb_index]->clear_state)(kbd);
297 error = 0;
298 }
299 splx(s);
300 return error;
301}
302
303int
304kbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func,
305 void *arg)
306{
307 int error;
308 int s;
309
310 s = spltty();
311 if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) {
312 error = EINVAL;
313 } else if (kbd->kb_token != id) {
314 error = EPERM;
315 } else if (func == NULL) {
316 error = EINVAL;
317 } else {
318 kbd->kb_callback.kc_func = func;
319 kbd->kb_callback.kc_arg = arg;
320 error = 0;
321 }
322 splx(s);
323 return error;
324}
325
326/* get a keyboard structure */
327keyboard_t
328*kbd_get_keyboard(int index)
329{
330 if ((index < 0) || (index >= keyboards))
331 return NULL;
332 if (!KBD_IS_VALID(keyboard[index]))
333 return NULL;
334 return keyboard[index];
335}
336
337/*
338 * The back door for the console driver; configure keyboards
339 * This function is for the kernel console to initialize keyboards
340 * at very early stage.
341 */
342
343int
344kbd_configure(int flags)
345{
346 keyboard_driver_t **list;
347 keyboard_driver_t *p;
348
349 list = (keyboard_driver_t **)kbddriver_set.ls_items;
350 while ((p = *list++) != NULL) {
351 if (p->configure != NULL)
352 (*p->configure)(flags);
353 }
354
355 return 0;
356}
357
358#ifdef KBD_INSTALL_CDEV
359
360/*
361 * Virtual keyboard cdev driver functions
362 * The virtual keyboard driver dispatches driver functions to
363 * appropriate subdrivers.
364 */
365
366#define KBD_UNIT(dev) minor(dev)
367
368static d_open_t kbdopen;
369static d_close_t kbdclose;
370static d_read_t kbdread;
371static d_write_t kbdwrite;
372static d_ioctl_t kbdioctl;
373static d_reset_t kbdreset;
374static d_devtotty_t kbddevtotty;
375static d_poll_t kbdpoll;
376static d_mmap_t kbdmmap;
377
378#define CDEV_MAJOR 112
379
380static struct cdevsw kbd_cdevsw = {
381 kbdopen, kbdclose, kbdread, kbdwrite, /* ??? */
382 kbdioctl, nullstop, kbdreset, kbddevtotty,
383 kbdpoll, kbdmmap, nostrategy, "kbd",
384 NULL, -1, nodump, nopsize,
385};
386
387static void
388vkbdattach(void *arg)
389{
390 static int kbd_devsw_installed = FALSE;
391 dev_t dev;
392
393 if (!kbd_devsw_installed) {
394 dev = makedev(CDEV_MAJOR, 0);
395 cdevsw_add(&dev, &kbd_cdevsw, NULL);
396 kbd_devsw_installed = TRUE;
397 }
398}
399
400PSEUDO_SET(vkbdattach, kbd);
401
402int
403kbd_attach(dev_t dev, keyboard_t *kbd, struct cdevsw *cdevsw)
404{
405 int s;
406
407 if (kbd->kb_index >= keyboards)
408 return EINVAL;
409 if (keyboard[kbd->kb_index] != kbd)
410 return EINVAL;
411
412 s = spltty();
413 kbd->kb_minor = minor(dev);
414 kbdcdevsw[kbd->kb_index] = cdevsw;
415 splx(s);
416
417 /* XXX: DEVFS? */
418
419 if (kbd->kb_index + 1 >= keyboards)
420 kbd_realloc_array();
421
422 printf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit);
423 return 0;
424}
425
426int
427kbd_detach(dev_t dev, keyboard_t *kbd, struct cdevsw *cdevsw)
428{
429 int s;
430
431 if (kbd->kb_index >= keyboards)
432 return EINVAL;
433 if (keyboard[kbd->kb_index] != kbd)
434 return EINVAL;
435 if (kbdcdevsw[kbd->kb_index] != cdevsw)
436 return EINVAL;
437
438 s = spltty();
439 (*kbdsw[kbd->kb_index]->term)(kbd);
440 kbdcdevsw[kbd->kb_index] = NULL;
441 splx(s);
442 return 0;
443}
444
445static int
446kbdopen(dev_t dev, int flag, int mode, struct proc *p)
447{
448 int unit;
449
450 unit = KBD_UNIT(dev);
451 if (unit >= keyboards)
452 return ENXIO;
453 if (kbdcdevsw[unit] == NULL)
454 return ENXIO;
455 if (KBD_IS_BUSY(keyboard[unit]))
456 return EBUSY;
457 return (*kbdcdevsw[unit]->d_open)(makedev(0, keyboard[unit]->kb_minor),
458 flag, mode, p);
459}
460
461static int
462kbdclose(dev_t dev, int flag, int mode, struct proc *p)
463{
464 int unit;
465
466 unit = KBD_UNIT(dev);
467 if (kbdcdevsw[unit] == NULL)
468 return ENXIO;
469 return (*kbdcdevsw[unit]->d_close)(makedev(0, keyboard[unit]->kb_minor),
470 flag, mode, p);
471}
472
473static int
474kbdread(dev_t dev, struct uio *uio, int flag)
475{
476 int unit;
477
478 unit = KBD_UNIT(dev);
479 if (kbdcdevsw[unit] == NULL)
480 return ENXIO;
481 return (*kbdcdevsw[unit]->d_read)(makedev(0, keyboard[unit]->kb_minor),
482 uio, flag);
483}
484
485static int
486kbdwrite(dev_t dev, struct uio *uio, int flag)
487{
488 int unit;
489
490 unit = KBD_UNIT(dev);
491 if (kbdcdevsw[unit] == NULL)
492 return ENXIO;
493 return (*kbdcdevsw[unit]->d_write)(makedev(0, keyboard[unit]->kb_minor),
494 uio, flag);
495}
496
497static int
498kbdioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
499{
500 int unit;
501
502 unit = KBD_UNIT(dev);
503 if (kbdcdevsw[unit] == NULL)
504 return ENXIO;
505 return (*kbdcdevsw[unit]->d_ioctl)(makedev(0, keyboard[unit]->kb_minor),
506 cmd, arg, flag, p);
507}
508
509static int
510kbdreset(dev_t dev)
511{
512 int unit;
513
514 unit = KBD_UNIT(dev);
515 if (kbdcdevsw[unit] == NULL)
516 return ENXIO;
517 return (*kbdcdevsw[unit]->d_reset)(makedev(0, keyboard[unit]->kb_minor));
518}
519
520static struct tty
521*kbddevtotty(dev_t dev)
522{
523 int unit;
524
525 unit = KBD_UNIT(dev);
526 if (kbdcdevsw[unit] == NULL)
527 return NULL;
528 return (*kbdcdevsw[unit]->d_devtotty)(makedev(0, keyboard[unit]->kb_minor));
529}
530
531static int
532kbdpoll(dev_t dev, int event, struct proc *p)
533{
534 int unit;
535
536 unit = KBD_UNIT(dev);
537 if (kbdcdevsw[unit] == NULL)
538 return ENXIO;
539 return (*kbdcdevsw[unit]->d_poll)(makedev(0, keyboard[unit]->kb_minor),
540 event, p);
541}
542
543static int
544kbdmmap(dev_t dev, vm_offset_t offset, int nprot)
545{
546 int unit;
547
548 unit = KBD_UNIT(dev);
549 if (kbdcdevsw[unit] == NULL)
550 return ENXIO;
551 return (*kbdcdevsw[unit]->d_mmap)(makedev(0, keyboard[unit]->kb_minor),
552 offset, nprot);
553}
554
555/*
556 * Generic keyboard cdev driver functions
557 * Keyboard subdrivers may call these functions to implement common
558 * driver functions.
559 */
560
561#define KB_QSIZE 512
562#define KB_BUFSIZE 64
563
564static kbd_callback_func_t genkbd_event;
565
566int
567genkbdopen(genkbd_softc_t *sc, keyboard_t *kbd, int mode, int flag,
568 struct proc *p)
569{
570 int s;
571 int i;
572
573 s = spltty();
574 if (!KBD_IS_VALID(kbd)) {
575 splx(s);
576 return ENXIO;
577 }
578 i = kbd_allocate(kbd->kb_name, kbd->kb_unit, sc,
579 genkbd_event, (void *)sc);
580 if (i < 0) {
581 splx(s);
582 return EBUSY;
583 }
584 /* assert(i == kbd->kb_index) */
585 /* assert(kbd == kbd_get_keyboard(i)) */
586
587 /*
588 * NOTE: even when we have successfully claimed a keyboard,
589 * the device may still be missing (!KBD_HAS_DEVICE(kbd)).
590 */
591
592#if 0
593 bzero(&sc->gkb_q, sizeof(sc->gkb_q));
594#endif
595 clist_alloc_cblocks(&sc->gkb_q, KB_QSIZE, KB_QSIZE/2); /* XXX */
596 sc->gkb_rsel.si_flags = 0;
597 sc->gkb_rsel.si_pid = 0;
598 splx(s);
599
600 return 0;
601}
602
603int
604genkbdclose(genkbd_softc_t *sc, keyboard_t *kbd, int mode, int flag,
605 struct proc *p)
606{
607 int s;
608
609 /*
610 * NOTE: the device may have already become invalid.
611 * !KBD_IS_VALID(kbd)
612 */
613 s = spltty();
614 kbd_release(kbd, (void *)sc);
615#if 0
616 clist_free_cblocks(&sc->gkb_q);
617#endif
618 splx(s);
619
620 return 0;
621}
622
623int
624genkbdread(genkbd_softc_t *sc, keyboard_t *kbd, struct uio *uio, int flag)
625{
626 u_char buffer[KB_BUFSIZE];
627 int len;
628 int error;
629 int s;
630
631 /* wait for input */
632 s = spltty();
633 while (sc->gkb_q.c_cc == 0) {
634 if (!KBD_IS_VALID(kbd)) {
635 splx(s);
636 return EIO;
637 }
638 if (flag & IO_NDELAY) {
639 splx(s);
640 return EWOULDBLOCK;
641 }
642 sc->gkb_flags |= KB_ASLEEP;
643 error = tsleep((caddr_t)sc, PZERO | PCATCH, "kbdrea", 0);
644 if (error) {
645 sc->gkb_flags &= ~KB_ASLEEP;
646 splx(s);
647 return error;
648 }
649 }
650 splx(s);
651
652 /* copy as much input as possible */
653 error = 0;
654 while (uio->uio_resid > 0) {
655 len = imin(uio->uio_resid, sizeof(buffer));
656 len = q_to_b(&sc->gkb_q, buffer, len);
657 if (len <= 0)
658 break;
659 error = uiomove(buffer, len, uio);
660 if (error)
661 break;
662 }
663
664 return error;
665}
666
667int
668genkbdwrite(genkbd_softc_t *sc, keyboard_t *kbd, struct uio *uio, int flag)
669{
670 if (!KBD_IS_VALID(kbd))
671 return ENXIO;
672 return ENODEV;
673}
674
675int
676genkbdioctl(genkbd_softc_t *sc, keyboard_t *kbd, u_long cmd, caddr_t arg,
677 int flag, struct proc *p)
678{
679 int error;
680
681 if (kbd == NULL) /* XXX */
682 return ENXIO;
683 if (!KBD_IS_VALID(kbd))
684 return ENXIO;
685 error = (*kbdsw[kbd->kb_index]->ioctl)(kbd, cmd, arg);
686 if (error == ENOIOCTL)
687 error = ENODEV;
688 return error;
689}
690
691int
692genkbdpoll(genkbd_softc_t *sc, keyboard_t *kbd, int events, struct proc *p)
693{
694 int revents;
695 int s;
696
697 revents = 0;
698 s = spltty();
699 if (events & (POLLIN | POLLRDNORM)) {
700 if ((sc->gkb_q.c_cc > 0) || !KBD_IS_VALID(kbd))
701 revents |= (POLLIN | POLLRDNORM);
702 else
703 selrecord(p, &sc->gkb_rsel);
704 }
705 splx(s);
706 return revents;
707}
708
709static int
710genkbd_event(keyboard_t *kbd, int event, void *arg)
711{
712 genkbd_softc_t *sc;
713 size_t len;
714 u_char *cp;
715 int mode;
716 int c;
717
718 /* assert(KBD_IS_VALID(kbd)) */
719 sc = (genkbd_softc_t *)arg;
720
721 switch (event) {
722 case KBDIO_KEYINPUT:
723 break;
724 case KBDIO_UNLOADING:
725 /* the keyboard is going... */
726 kbd_release(kbd, (void *)sc);
727 return 0;
728 default:
729 return EINVAL;
730 }
731
732 /* obtain the current key input mode */
733 if ((*kbdsw[kbd->kb_index]->ioctl)(kbd, KDGKBMODE, (caddr_t)&mode))
734 mode = K_XLATE;
735
736 /* read all pending input */
737 while ((*kbdsw[kbd->kb_index]->check_char)(kbd)) {
738 c = (*kbdsw[kbd->kb_index]->read_char)(kbd, FALSE);
739 if (c == NOKEY)
740 continue;
741 if (c == ERRKEY) /* XXX: ring bell? */
742 continue;
743 if (!KBD_IS_BUSY(kbd))
744 /* the device is not open, discard the input */
745 continue;
746
747 /* store the byte as is for K_RAW and K_CODE modes */
748 if (mode != K_XLATE) {
749 putc(KEYCHAR(c), &sc->gkb_q);
750 continue;
751 }
752
753 /* K_XLATE */
754 if (c & RELKEY) /* key release is ignored */
755 continue;
756
757 /* process special keys; most of them are just ignored... */
758 if (c & SPCLKEY) {
759 switch (KEYCHAR(c)) {
760 /* locking keys */
761 case NLK: case CLK: case SLK: case ALK:
762 /* shift keys */
763 case LSH: case RSH: case LCTR: case RCTR:
764 case LALT: case RALT: case ASH: case META:
765 /* other special keys */
766 case NOP: case SPSC: case RBT: case SUSP:
767 case STBY: case DBG: case NEXT:
768 /* ignore them... */
769 continue;
770 case BTAB: /* a backtab: ESC [ Z */
771 putc(0x1b, &sc->gkb_q);
772 putc('[', &sc->gkb_q);
773 putc('Z', &sc->gkb_q);
774 continue;
775 }
776 }
777
778 /* normal chars, normal chars with the META, function keys */
779 switch (KEYFLAGS(c)) {
780 case 0: /* a normal char */
781 putc(KEYCHAR(c), &sc->gkb_q);
782 break;
783 case MKEY: /* the META flag: prepend ESC */
784 putc(0x1b, &sc->gkb_q);
785 putc(KEYCHAR(c), &sc->gkb_q);
786 break;
787 case FKEY | SPCLKEY: /* a function key, return string */
788 cp = (*kbdsw[kbd->kb_index]->get_fkeystr)(kbd,
789 KEYCHAR(c), &len);
790 if (cp != NULL) {
791 while (len-- > 0)
792 putc(*cp++, &sc->gkb_q);
793 }
794 break;
795 }
796 }
797
798 /* wake up sleeping/polling processes */
799 if (sc->gkb_q.c_cc > 0) {
800 if (sc->gkb_flags & KB_ASLEEP) {
801 sc->gkb_flags &= ~KB_ASLEEP;
802 wakeup((caddr_t)sc);
803 }
804 selwakeup(&sc->gkb_rsel);
805 }
806
807 return 0;
808}
809
810#endif /* KBD_INSTALL_CDEV */
811
812/*
813 * Generic low-level keyboard functions
814 * The low-level functions in the keyboard subdriver may use these
815 * functions.
816 */
817
818int
819genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
820{
821 keyarg_t *keyp;
822 fkeyarg_t *fkeyp;
823 int s;
824 int i;
825
826 s = spltty();
827 switch (cmd) {
828
829 case KDGKBINFO: /* get keyboard information */
830 ((keyboard_info_t *)arg)->kb_index = kbd->kb_index;
831 i = imin(strlen(kbd->kb_name) + 1,
832 sizeof(((keyboard_info_t *)arg)->kb_name));
833 bcopy(kbd->kb_name, ((keyboard_info_t *)arg)->kb_name, i);
834 ((keyboard_info_t *)arg)->kb_unit = kbd->kb_unit;
835 ((keyboard_info_t *)arg)->kb_type = kbd->kb_type;
836 ((keyboard_info_t *)arg)->kb_config = kbd->kb_config;
837 ((keyboard_info_t *)arg)->kb_flags = kbd->kb_flags;
838 break;
839
840 case KDGKBTYPE: /* get keyboard type */
841 *(int *)arg = kbd->kb_type;
842 break;
843
844 case GIO_KEYMAP: /* get keyboard translation table */
845 bcopy(kbd->kb_keymap, arg, sizeof(*kbd->kb_keymap));
846 break;
847 case PIO_KEYMAP: /* set keyboard translation table */
848 bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
849 bcopy(arg, kbd->kb_keymap, sizeof(*kbd->kb_keymap));
850 break;
851
852 case GIO_KEYMAPENT: /* get keyboard translation table entry */
853 keyp = (keyarg_t *)arg;
854 if (keyp->keynum >= sizeof(kbd->kb_keymap->key)
855 /sizeof(kbd->kb_keymap->key[0])) {
856 splx(s);
857 return EINVAL;
858 }
859 bcopy(&kbd->kb_keymap[keyp->keynum], &keyp->key,
860 sizeof(keyp->key));
861 break;
862 case PIO_KEYMAPENT: /* set keyboard translation table entry */
863 keyp = (keyarg_t *)arg;
864 if (keyp->keynum >= sizeof(kbd->kb_keymap->key)
865 /sizeof(kbd->kb_keymap->key[0])) {
866 splx(s);
867 return EINVAL;
868 }
869 bcopy(&keyp->key, &kbd->kb_keymap[keyp->keynum],
870 sizeof(keyp->key));
871 break;
872
873 case GIO_DEADKEYMAP: /* get accent key translation table */
874 bcopy(kbd->kb_accentmap, arg, sizeof(*kbd->kb_accentmap));
875 break;
876 case PIO_DEADKEYMAP: /* set accent key translation table */
877 bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap));
878 break;
879
880 case GETFKEY: /* get functionkey string */
881 fkeyp = (fkeyarg_t *)arg;
882 if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
883 splx(s);
884 return EINVAL;
885 }
886 bcopy(kbd->kb_fkeytab[fkeyp->keynum].str, fkeyp->keydef,
887 kbd->kb_fkeytab[fkeyp->keynum].len);
888 fkeyp->flen = kbd->kb_fkeytab[fkeyp->keynum].len;
889 break;
890 case SETFKEY: /* set functionkey string */
891 fkeyp = (fkeyarg_t *)arg;
892 if (fkeyp->keynum >= kbd->kb_fkeytab_size) {
893 splx(s);
894 return EINVAL;
895 }
896 kbd->kb_fkeytab[fkeyp->keynum].len = imin(fkeyp->flen, MAXFK);
897 bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str,
898 kbd->kb_fkeytab[fkeyp->keynum].len);
899 break;
900
901 default:
902 splx(s);
903 return ENOIOCTL;
904 }
905
906 splx(s);
907 return 0;
908}
909
910/* get a pointer to the string associated with the given function key */
911u_char
912*genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len)
913{
914 if (kbd == NULL)
915 return NULL;
916 fkey -= F_FN;
917 if (fkey > kbd->kb_fkeytab_size)
918 return NULL;
919 *len = kbd->kb_fkeytab[fkey].len;
920 return kbd->kb_fkeytab[fkey].str;
921}
922
923/* diagnostic dump */
924static char
925*get_kbd_type_name(int type)
926{
927 static struct {
928 int type;
929 char *name;
930 } name_table[] = {
931 { KB_84, "AT 84" },
932 { KB_101, "AT 101/102" },
933 { KB_OTHER, "generic" },
934 };
935 int i;
936
937 for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) {
938 if (type == name_table[i].type)
939 return name_table[i].name;
940 }
941 return "unknown";
942}
943
944void
945genkbd_diag(keyboard_t *kbd, int level)
946{
947 if (level > 0) {
948 printf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x",
949 kbd->kb_index, kbd->kb_name, kbd->kb_unit,
950 get_kbd_type_name(kbd->kb_type), kbd->kb_type,
951 kbd->kb_config, kbd->kb_flags);
952 if (kbd->kb_io_base > 0)
953 printf(", port:0x%x-0x%x", kbd->kb_io_base,
954 kbd->kb_io_base + kbd->kb_io_size - 1);
955 printf("\n");
956 }
957}
958
959#define set_lockkey_state(k, s, l) \
960 if (!((s) & l ## DOWN)) { \
961 int i; \
962 (s) |= l ## DOWN; \
963 (s) ^= l ## ED; \
964 i = (s) & LOCK_MASK; \
965 (*kbdsw[(k)->kb_index]->ioctl)((k), KDSETLED, (caddr_t)&i); \
966 }
967
968static u_int
969save_accent_key(keyboard_t *kbd, u_int key, int *accents)
970{
971 int i;
972
973 /* make an index into the accent map */
974 i = key - F_ACC + 1;
975 if ((i > kbd->kb_accentmap->n_accs)
976 || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) {
977 /* the index is out of range or pointing to an empty entry */
978 *accents = 0;
979 return ERRKEY;
980 }
981
982 /*
983 * If the same accent key has been hit twice, produce the accent char
984 * itself.
985 */
986 if (i == *accents) {
987 key = kbd->kb_accentmap->acc[i - 1].accchar;
988 *accents = 0;
989 return key;
990 }
991
992 /* remember the index and wait for the next key */
993 *accents = i;
994 return NOKEY;
995}
996
997static u_int
998make_accent_char(keyboard_t *kbd, u_int ch, int *accents)
999{
1000 struct acc_t *acc;
1001 int i;
1002
1003 acc = &kbd->kb_accentmap->acc[*accents - 1];
1004 *accents = 0;
1005
1006 /*
1007 * If the accent key is followed by the space key,
1008 * produce the accent char itself.
1009 */
1010 if (ch == ' ')
1011 return acc->accchar;
1012
1013 /* scan the accent map */
1014 for (i = 0; i < NUM_ACCENTCHARS; ++i) {
1015 if (acc->map[i][0] == 0) /* end of table */
1016 break;
1017 if (acc->map[i][0] == ch)
1018 return acc->map[i][1];
1019 }
1020 /* this char cannot be accented... */
1021 return ERRKEY;
1022}
1023
1024int
1025genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate,
1026 int *accents)
1027{
1028 struct keyent_t *key;
1029 int state = *shiftstate;
1030 int action;
1031 int f;
1032 int i;
1033
1034 f = state & (AGRS | ALKED);
1035 if ((f == AGRS1) || (f == AGRS2) || (f == ALKED))
1036 keycode += ALTGR_OFFSET;
1037 key = &kbd->kb_keymap->key[keycode];
1038 i = ((state & SHIFTS) ? 1 : 0)
1039 | ((state & CTLS) ? 2 : 0)
1040 | ((state & ALTS) ? 4 : 0);
1041 if (((key->flgs & FLAG_LOCK_C) && (state & CLKED))
1042 || ((key->flgs & FLAG_LOCK_N) && (state & NLKED)) )
1043 i ^= 1;
1044
1045 action = key->map[i];
1046 if (up) { /* break: key released */
1047 if (key->spcl & (0x80 >> i)) {
1048 /* special keys */
1049 switch (action) {
1050 case LSH:
1051 state &= ~SHIFTS1;
1052 break;
1053 case RSH:
1054 state &= ~SHIFTS2;
1055 break;
1056 case LCTR:
1057 state &= ~CTLS1;
1058 break;
1059 case RCTR:
1060 state &= ~CTLS2;
1061 break;
1062 case LALT:
1063 state &= ~ALTS1;
1064 break;
1065 case RALT:
1066 state &= ~ALTS2;
1067 break;
1068 case ASH:
1069 state &= ~AGRS1;
1070 break;
1071 case META:
1072 state &= ~METAS1;
1073 break;
1074 case NLK:
1075 state &= ~NLKDOWN;
1076 break;
1077 case CLK:
1078#ifndef PC98
1079 state &= ~CLKDOWN;
1080#else
1081 state &= ~CLKED;
1082 i = state & LOCK_MASK;
1083 (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED,
1084 (caddr_t)&i);
1085#endif
1086 break;
1087 case SLK:
1088 state &= ~SLKDOWN;
1089 break;
1090 case ALK:
1091 state &= ~ALKDOWN;
1092 break;
1093 }
1094 *shiftstate = state;
1095 return (SPCLKEY | RELKEY | action);
1096 }
1097 /* release events of regular keys are not reported */
1098 return NOKEY;
1099 } else { /* make: key pressed */
1100 if (key->spcl & (0x80 >> i)) {
1101 /* special keys */
1102 switch (action) {
1103 /* LOCKING KEYS */
1104 case NLK:
1105 set_lockkey_state(kbd, state, NLK);
1106 break;
1107 case CLK:
1108#ifndef PC98
1109 set_lockkey_state(kbd, state, CLK);
1110#else
1111 state |= CLKED;
1112 i = state & LOCK_MASK;
1113 (*kbdsw[kbd->kb_index]->ioctl)(kbd, KDSETLED,
1114 (caddr_t)&i);
1115#endif
1116 break;
1117 case SLK:
1118 set_lockkey_state(kbd, state, SLK);
1119 break;
1120 case ALK:
1121 set_lockkey_state(kbd, state, ALK);
1122 break;
1123 /* NON-LOCKING KEYS */
1124 case SPSC: case RBT: case SUSP: case STBY:
1125 case DBG: case NEXT:
1126 *accents = 0;
1127 break;
1128 case BTAB:
1129 *accents = 0;
1130 action |= BKEY;
1131 break;
1132 case LSH:
1133 state |= SHIFTS1;
1134 break;
1135 case RSH:
1136 state |= SHIFTS2;
1137 break;
1138 case LCTR:
1139 state |= CTLS1;
1140 break;
1141 case RCTR:
1142 state |= CTLS2;
1143 break;
1144 case LALT:
1145 state |= ALTS1;
1146 break;
1147 case RALT:
1148 state |= ALTS2;
1149 break;
1150 case ASH:
1151 state |= AGRS1;
1152 break;
1153 case META:
1154 state |= METAS1;
1155 break;
1156 default:
1157 /* is this an accent (dead) key? */
1158 if (action >= F_ACC && action <= L_ACC) {
1159 action = save_accent_key(kbd, action,
1160 accents);
1161 switch (action) {
1162 case NOKEY:
1163 case ERRKEY:
1164 return action;
1165 default:
1166 if (state & METAS)
1167 return (action | MKEY);
1168 else
1169 return action;
1170 }
1171 /* NOT REACHED */
1172 }
1173 /* other special keys */
1174 if (*accents > 0) {
1175 *accents = 0;
1176 return ERRKEY;
1177 }
1178 if (action >= F_FN && action <= L_FN)
1179 action |= FKEY;
1180 /* XXX: return fkey string for the FKEY? */
1181 }
1182 *shiftstate = state;
1183 return (SPCLKEY | action);
1184 } else {
1185 /* regular keys */
1186 if (*accents > 0) {
1187 /* make an accented char */
1188 action = make_accent_char(kbd, action, accents);
1189 if (action == ERRKEY)
1190 return action;
1191 }
1192 if (state & METAS)
1193 action |= MKEY;
1194 return action;
1195 }
1196 }
1197 /* NOT REACHED */
1198}