]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/kbdmux/kbdmux.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / kbdmux / kbdmux.c
1 /*
2  * kbdmux.c
3  */
4
5 /*-
6  * Copyright (c) 2005 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $Id: kbdmux.c,v 1.4 2005/07/14 17:38:35 max Exp $
31  * $FreeBSD$
32  */
33
34 #include "opt_compat.h"
35 #include "opt_kbd.h"
36
37 #include <sys/param.h>
38 #include <sys/bus.h>
39 #include <sys/conf.h>
40 #include <sys/consio.h>
41 #include <sys/fcntl.h>
42 #include <sys/kbio.h>
43 #include <sys/kernel.h>
44 #include <sys/limits.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/module.h>
48 #include <sys/mutex.h>
49 #include <sys/poll.h>
50 #include <sys/proc.h>
51 #include <sys/queue.h>
52 #include <sys/selinfo.h>
53 #include <sys/systm.h>
54 #include <sys/taskqueue.h>
55 #include <sys/uio.h>
56 #include <dev/kbd/kbdreg.h>
57 #include <dev/kbd/kbdtables.h>
58
59 #define KEYBOARD_NAME   "kbdmux"
60
61 MALLOC_DECLARE(M_KBDMUX);
62 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
63
64 /*****************************************************************************
65  *****************************************************************************
66  **                             Keyboard state
67  *****************************************************************************
68  *****************************************************************************/
69
70 #define KBDMUX_Q_SIZE   512     /* input queue size */
71
72 /*
73  * XXX
74  * For now rely on Giant mutex to protect our data structures.
75  * Just like the rest of keyboard drivers and syscons(4) do.
76  * Note that callout is initialized as not MP-safe to make sure
77  * Giant is held.
78  */
79
80 #if 0 /* not yet */
81 #define KBDMUX_LOCK_DECL_GLOBAL \
82         struct mtx ks_lock
83 #define KBDMUX_LOCK_INIT(s) \
84         mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
85 #define KBDMUX_LOCK_DESTROY(s) \
86         mtx_destroy(&(s)->ks_lock)
87 #define KBDMUX_LOCK(s) \
88         mtx_lock(&(s)->ks_lock)
89 #define KBDMUX_UNLOCK(s) \
90         mtx_unlock(&(s)->ks_lock)
91 #define KBDMUX_LOCK_ASSERT(s, w) \
92         mtx_assert(&(s)->ks_lock, (w))
93 #define KBDMUX_SLEEP(s, f, d, t) \
94         msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
95 #define KBDMUX_CALLOUT_INIT(s) \
96         callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
97 #define KBDMUX_QUEUE_INTR(s) \
98         taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
99 #else
100 #define KBDMUX_LOCK_DECL_GLOBAL
101
102 #define KBDMUX_LOCK_INIT(s)
103
104 #define KBDMUX_LOCK_DESTROY(s)
105
106 #define KBDMUX_LOCK(s)
107
108 #define KBDMUX_UNLOCK(s)
109
110 #define KBDMUX_LOCK_ASSERT(s, w)
111
112 #define KBDMUX_SLEEP(s, f, d, t) \
113         tsleep(&(s)->f, PCATCH | (PZERO + 1), (d), (t))
114 #define KBDMUX_CALLOUT_INIT(s) \
115         callout_init(&(s)->ks_timo, 0)
116 #define KBDMUX_QUEUE_INTR(s) \
117         taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
118 #endif /* not yet */
119
120 /*
121  * kbdmux keyboard
122  */
123 struct kbdmux_kbd
124 {
125         keyboard_t              *kbd;   /* keyboard */
126         SLIST_ENTRY(kbdmux_kbd)  next;  /* link to next */
127 };
128
129 typedef struct kbdmux_kbd       kbdmux_kbd_t;
130
131 /*
132  * kbdmux state
133  */
134 struct kbdmux_state
135 {
136         char                     ks_inq[KBDMUX_Q_SIZE]; /* input chars queue */
137         unsigned int             ks_inq_start;
138         unsigned int             ks_inq_length;
139         struct task              ks_task;       /* interrupt task */
140         struct callout           ks_timo;       /* timeout handler */
141 #define TICKS                   (hz)            /* rate */
142
143         int                      ks_flags;      /* flags */
144 #define COMPOSE                 (1 << 0)        /* compose char flag */ 
145 #define POLLING                 (1 << 1)        /* polling */
146 #define TASK                    (1 << 2)        /* interrupt task queued */
147
148         int                      ks_mode;       /* K_XLATE, K_RAW, K_CODE */
149         int                      ks_state;      /* state */
150         int                      ks_accents;    /* accent key index (> 0) */
151         u_int                    ks_composed_char; /* composed char code */
152         u_char                   ks_prefix;     /* AT scan code prefix */
153
154         SLIST_HEAD(, kbdmux_kbd) ks_kbds;       /* keyboards */
155
156         KBDMUX_LOCK_DECL_GLOBAL;
157 };
158
159 typedef struct kbdmux_state     kbdmux_state_t;
160
161 /*****************************************************************************
162  *****************************************************************************
163  **                             Helper functions
164  *****************************************************************************
165  *****************************************************************************/
166
167 static task_fn_t                kbdmux_kbd_intr;
168 static timeout_t                kbdmux_kbd_intr_timo;
169 static kbd_callback_func_t      kbdmux_kbd_event;
170
171 static void
172 kbdmux_kbd_putc(kbdmux_state_t *state, char c)
173 {
174         unsigned int p;
175
176         if (state->ks_inq_length == KBDMUX_Q_SIZE)
177                 return;
178
179         p = (state->ks_inq_start + state->ks_inq_length) % KBDMUX_Q_SIZE;
180         state->ks_inq[p] = c;
181         state->ks_inq_length++;
182 }
183
184 static int
185 kbdmux_kbd_getc(kbdmux_state_t *state)
186 {
187         unsigned char c;
188
189         if (state->ks_inq_length == 0)
190                 return (-1);
191
192         c = state->ks_inq[state->ks_inq_start];
193         state->ks_inq_start = (state->ks_inq_start + 1) % KBDMUX_Q_SIZE;
194         state->ks_inq_length--;
195
196         return (c);
197 }
198
199 /*
200  * Interrupt handler task
201  */
202 void
203 kbdmux_kbd_intr(void *xkbd, int pending)
204 {
205         keyboard_t      *kbd = (keyboard_t *) xkbd;
206         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
207
208         kbdd_intr(kbd, NULL);
209
210         KBDMUX_LOCK(state);
211
212         state->ks_flags &= ~TASK;
213         wakeup(&state->ks_task);
214
215         KBDMUX_UNLOCK(state);
216 }
217
218 /*
219  * Schedule interrupt handler on timeout. Called with locked state.
220  */
221 void
222 kbdmux_kbd_intr_timo(void *xstate)
223 {
224         kbdmux_state_t  *state = (kbdmux_state_t *) xstate;
225
226         KBDMUX_LOCK_ASSERT(state, MA_OWNED);
227
228         if (callout_pending(&state->ks_timo))
229                 return; /* callout was reset */
230
231         if (!callout_active(&state->ks_timo))
232                 return; /* callout was stopped */
233
234         callout_deactivate(&state->ks_timo);
235
236         /* queue interrupt task if needed */
237         if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
238             KBDMUX_QUEUE_INTR(state) == 0)
239                 state->ks_flags |= TASK;
240
241         /* re-schedule timeout */
242         callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
243 }
244
245 /*
246  * Process event from one of our keyboards
247  */
248 static int
249 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
250 {
251         kbdmux_state_t  *state = (kbdmux_state_t *) arg;
252
253         switch (event) {
254         case KBDIO_KEYINPUT: {
255                 int     c;
256
257                 KBDMUX_LOCK(state);
258
259                 /*
260                  * Read all chars from the keyboard
261                  *
262                  * Turns out that atkbd(4) check_char() method may return
263                  * "true" while read_char() method returns NOKEY. If this
264                  * happens we could stuck in the loop below. Avoid this
265                  * by breaking out of the loop if read_char() method returns
266                  * NOKEY.
267                  */
268
269                 while (kbdd_check_char(kbd)) {
270                         c = kbdd_read_char(kbd, 0);
271                         if (c == NOKEY)
272                                 break;
273                         if (c == ERRKEY)
274                                 continue; /* XXX ring bell */
275                         if (!KBD_IS_BUSY(kbd))
276                                 continue; /* not open - discard the input */
277
278                         kbdmux_kbd_putc(state, c);
279                 }
280
281                 /* queue interrupt task if needed */
282                 if (state->ks_inq_length > 0 && !(state->ks_flags & TASK) &&
283                     KBDMUX_QUEUE_INTR(state) == 0)
284                         state->ks_flags |= TASK;
285
286                 KBDMUX_UNLOCK(state);
287                 } break;
288
289         case KBDIO_UNLOADING: {
290                 kbdmux_kbd_t    *k;
291
292                 KBDMUX_LOCK(state);
293
294                 SLIST_FOREACH(k, &state->ks_kbds, next)
295                         if (k->kbd == kbd)
296                                 break;
297
298                 if (k != NULL) {
299                         kbd_release(k->kbd, &k->kbd);
300                         SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
301
302                         k->kbd = NULL;
303
304                         free(k, M_KBDMUX);
305                 }
306
307                 KBDMUX_UNLOCK(state);
308                 } break;
309
310         default:
311                 return (EINVAL);
312                 /* NOT REACHED */
313         }
314
315         return (0);
316 }
317
318 /****************************************************************************
319  ****************************************************************************
320  **                              Keyboard driver
321  ****************************************************************************
322  ****************************************************************************/
323
324 static int              kbdmux_configure(int flags);
325 static kbd_probe_t      kbdmux_probe;
326 static kbd_init_t       kbdmux_init;
327 static kbd_term_t       kbdmux_term;
328 static kbd_intr_t       kbdmux_intr;
329 static kbd_test_if_t    kbdmux_test_if;
330 static kbd_enable_t     kbdmux_enable;
331 static kbd_disable_t    kbdmux_disable;
332 static kbd_read_t       kbdmux_read;
333 static kbd_check_t      kbdmux_check;
334 static kbd_read_char_t  kbdmux_read_char;
335 static kbd_check_char_t kbdmux_check_char;
336 static kbd_ioctl_t      kbdmux_ioctl;
337 static kbd_lock_t       kbdmux_lock;
338 static void             kbdmux_clear_state_locked(kbdmux_state_t *state);
339 static kbd_clear_state_t kbdmux_clear_state;
340 static kbd_get_state_t  kbdmux_get_state;
341 static kbd_set_state_t  kbdmux_set_state;
342 static kbd_poll_mode_t  kbdmux_poll;
343
344 static keyboard_switch_t kbdmuxsw = {
345         .probe =        kbdmux_probe,
346         .init =         kbdmux_init,
347         .term =         kbdmux_term,
348         .intr =         kbdmux_intr,
349         .test_if =      kbdmux_test_if,
350         .enable =       kbdmux_enable,
351         .disable =      kbdmux_disable,
352         .read =         kbdmux_read,
353         .check =        kbdmux_check,
354         .read_char =    kbdmux_read_char,
355         .check_char =   kbdmux_check_char,
356         .ioctl =        kbdmux_ioctl,
357         .lock =         kbdmux_lock,
358         .clear_state =  kbdmux_clear_state,
359         .get_state =    kbdmux_get_state,
360         .set_state =    kbdmux_set_state,
361         .get_fkeystr =  genkbd_get_fkeystr,
362         .poll =         kbdmux_poll,
363         .diag =         genkbd_diag,
364 };
365
366 /*
367  * Return the number of found keyboards
368  */
369 static int
370 kbdmux_configure(int flags)
371 {
372         return (1);
373 }
374
375 /*
376  * Detect a keyboard
377  */
378 static int
379 kbdmux_probe(int unit, void *arg, int flags)
380 {
381         if (resource_disabled(KEYBOARD_NAME, unit))
382                 return (ENXIO);
383
384         return (0);
385 }
386
387 /*
388  * Reset and initialize the keyboard (stolen from atkbd.c)
389  */
390 static int
391 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
392 {
393         keyboard_t      *kbd = NULL;
394         kbdmux_state_t  *state = NULL;
395         keymap_t        *keymap = NULL;
396         accentmap_t     *accmap = NULL;
397         fkeytab_t       *fkeymap = NULL;
398         int              error, needfree, fkeymap_size, delay[2];
399
400         if (*kbdp == NULL) {
401                 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
402                 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
403                 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
404                 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
405                 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
406                 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
407                 needfree = 1;
408
409                 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
410                     (accmap == NULL) || (fkeymap == NULL)) {
411                         error = ENOMEM;
412                         goto bad;
413                 }
414
415                 KBDMUX_LOCK_INIT(state);
416                 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
417                 KBDMUX_CALLOUT_INIT(state);
418                 SLIST_INIT(&state->ks_kbds);
419         } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
420                 return (0);
421         } else {
422                 kbd = *kbdp;
423                 state = (kbdmux_state_t *) kbd->kb_data;
424                 keymap = kbd->kb_keymap;
425                 accmap = kbd->kb_accentmap;
426                 fkeymap = kbd->kb_fkeytab;
427                 fkeymap_size = kbd->kb_fkeytab_size;
428                 needfree = 0;
429         }
430
431         if (!KBD_IS_PROBED(kbd)) {
432                 /* XXX assume 101/102 keys keyboard */
433                 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0);
434                 bcopy(&key_map, keymap, sizeof(key_map));
435                 bcopy(&accent_map, accmap, sizeof(accent_map));
436                 bcopy(fkey_tab, fkeymap,
437                         imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
438                 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
439                 kbd->kb_data = (void *)state;
440         
441                 KBD_FOUND_DEVICE(kbd);
442                 KBD_PROBE_DONE(kbd);
443
444                 KBDMUX_LOCK(state);
445                 kbdmux_clear_state_locked(state);
446                 state->ks_mode = K_XLATE;
447                 KBDMUX_UNLOCK(state);
448         }
449
450         if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
451                 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
452
453                 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
454
455                 delay[0] = kbd->kb_delay1;
456                 delay[1] = kbd->kb_delay2;
457                 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
458
459                 KBD_INIT_DONE(kbd);
460         }
461
462         if (!KBD_IS_CONFIGURED(kbd)) {
463                 if (kbd_register(kbd) < 0) {
464                         error = ENXIO;
465                         goto bad;
466                 }
467
468                 KBD_CONFIG_DONE(kbd);
469
470                 KBDMUX_LOCK(state);
471                 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
472                 KBDMUX_UNLOCK(state);
473         }
474
475         return (0);
476 bad:
477         if (needfree) {
478                 if (state != NULL)
479                         free(state, M_KBDMUX);
480                 if (keymap != NULL)
481                         free(keymap, M_KBDMUX);
482                 if (accmap != NULL)
483                         free(accmap, M_KBDMUX);
484                 if (fkeymap != NULL)
485                         free(fkeymap, M_KBDMUX);
486                 if (kbd != NULL) {
487                         free(kbd, M_KBDMUX);
488                         *kbdp = NULL;   /* insure ref doesn't leak to caller */
489                 }
490         }
491
492         return (error);
493 }
494
495 /*
496  * Finish using this keyboard
497  */
498 static int
499 kbdmux_term(keyboard_t *kbd)
500 {
501         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
502         kbdmux_kbd_t    *k;
503
504         KBDMUX_LOCK(state);
505
506         /* kill callout */
507         callout_stop(&state->ks_timo);
508
509         /* wait for interrupt task */
510         while (state->ks_flags & TASK)
511                 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
512
513         /* release all keyboards from the mux */
514         while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
515                 kbd_release(k->kbd, &k->kbd);
516                 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
517
518                 k->kbd = NULL;
519
520                 free(k, M_KBDMUX);
521         }
522
523         KBDMUX_UNLOCK(state);
524
525         kbd_unregister(kbd);
526
527         KBDMUX_LOCK_DESTROY(state);
528         bzero(state, sizeof(*state));
529         free(state, M_KBDMUX);
530
531         free(kbd->kb_keymap, M_KBDMUX);
532         free(kbd->kb_accentmap, M_KBDMUX);
533         free(kbd->kb_fkeytab, M_KBDMUX);
534         free(kbd, M_KBDMUX);
535
536         return (0);
537 }
538
539 /*
540  * Keyboard interrupt routine
541  */
542 static int
543 kbdmux_intr(keyboard_t *kbd, void *arg)
544 {
545         int     c;
546
547         if (KBD_IS_ACTIVE(kbd) && KBD_IS_BUSY(kbd)) {
548                 /* let the callback function to process the input */
549                 (*kbd->kb_callback.kc_func)(kbd, KBDIO_KEYINPUT,
550                                             kbd->kb_callback.kc_arg);
551         } else {
552                 /* read and discard the input; no one is waiting for input */
553                 do {
554                         c = kbdmux_read_char(kbd, FALSE);
555                 } while (c != NOKEY);
556         }
557
558         return (0);
559 }
560
561 /*
562  * Test the interface to the device
563  */
564 static int
565 kbdmux_test_if(keyboard_t *kbd)
566 {
567         return (0);
568 }
569
570 /* 
571  * Enable the access to the device; until this function is called,
572  * the client cannot read from the keyboard.
573  */
574 static int
575 kbdmux_enable(keyboard_t *kbd)
576 {
577         KBD_ACTIVATE(kbd);
578         return (0);
579 }
580
581 /*
582  * Disallow the access to the device
583  */
584 static int
585 kbdmux_disable(keyboard_t *kbd)
586 {
587         KBD_DEACTIVATE(kbd);
588         return (0);
589 }
590
591 /*
592  * Read one byte from the keyboard if it's allowed
593  */
594 static int
595 kbdmux_read(keyboard_t *kbd, int wait)
596 {
597         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
598         int              c;
599
600         KBDMUX_LOCK(state);
601         c = kbdmux_kbd_getc(state);
602         KBDMUX_UNLOCK(state);
603
604         if (c != -1)
605                 kbd->kb_count ++;
606
607         return (KBD_IS_ACTIVE(kbd)? c : -1);
608 }
609
610 /*
611  * Check if data is waiting
612  */
613 static int
614 kbdmux_check(keyboard_t *kbd)
615 {
616         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
617         int              ready;
618
619         if (!KBD_IS_ACTIVE(kbd))
620                 return (FALSE);
621
622         KBDMUX_LOCK(state);
623         ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
624         KBDMUX_UNLOCK(state);
625
626         return (ready);
627 }
628
629 /*
630  * Read char from the keyboard (stolen from atkbd.c)
631  */
632 static u_int
633 kbdmux_read_char(keyboard_t *kbd, int wait)
634 {
635         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
636         u_int            action;
637         int              scancode, keycode;
638
639         KBDMUX_LOCK(state);
640
641 next_code:
642
643         /* do we have a composed char to return? */
644         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char > 0)) {
645                 action = state->ks_composed_char;
646                 state->ks_composed_char = 0;
647                 if (action > UCHAR_MAX) {
648                         KBDMUX_UNLOCK(state);
649
650                         return (ERRKEY);
651                 }
652
653                 KBDMUX_UNLOCK(state);
654
655                 return (action);
656         }
657
658         /* see if there is something in the keyboard queue */
659         scancode = kbdmux_kbd_getc(state);
660         if (scancode == -1) {
661                 if (state->ks_flags & POLLING) {
662                         kbdmux_kbd_t    *k;
663
664                         SLIST_FOREACH(k, &state->ks_kbds, next) {
665                                 while (kbdd_check_char(k->kbd)) {
666                                         scancode = kbdd_read_char(k->kbd, 0);
667                                         if (scancode == NOKEY)
668                                                 break;
669                                         if (scancode == ERRKEY)
670                                                 continue;
671                                         if (!KBD_IS_BUSY(k->kbd))
672                                                 continue; 
673
674                                         kbdmux_kbd_putc(state, scancode);
675                                 }
676                         }
677
678                         if (state->ks_inq_length > 0)
679                                 goto next_code;
680                 }
681
682                 KBDMUX_UNLOCK(state);
683                 return (NOKEY);
684         }
685         /* XXX FIXME: check for -1 if wait == 1! */
686
687         kbd->kb_count ++;
688
689         /* return the byte as is for the K_RAW mode */
690         if (state->ks_mode == K_RAW) {
691                 KBDMUX_UNLOCK(state);
692                 return (scancode);
693         }
694
695         /* translate the scan code into a keycode */
696         keycode = scancode & 0x7F;
697         switch (state->ks_prefix) {
698         case 0x00:      /* normal scancode */
699                 switch(scancode) {
700                 case 0xB8:      /* left alt (compose key) released */
701                         if (state->ks_flags & COMPOSE) {
702                                 state->ks_flags &= ~COMPOSE;
703                                 if (state->ks_composed_char > UCHAR_MAX)
704                                         state->ks_composed_char = 0;
705                         }
706                         break;
707                 case 0x38:      /* left alt (compose key) pressed */
708                         if (!(state->ks_flags & COMPOSE)) {
709                                 state->ks_flags |= COMPOSE;
710                                 state->ks_composed_char = 0;
711                         }
712                         break;
713                 case 0xE0:
714                 case 0xE1:
715                         state->ks_prefix = scancode;
716                         goto next_code;
717                 }
718                 break;
719         case 0xE0:      /* 0xE0 prefix */
720                 state->ks_prefix = 0;
721                 switch (keycode) {
722                 case 0x1C:      /* right enter key */
723                         keycode = 0x59;
724                         break;
725                 case 0x1D:      /* right ctrl key */
726                         keycode = 0x5A;
727                         break;
728                 case 0x35:      /* keypad divide key */
729                         keycode = 0x5B;
730                         break;
731                 case 0x37:      /* print scrn key */
732                         keycode = 0x5C;
733                         break;
734                 case 0x38:      /* right alt key (alt gr) */
735                         keycode = 0x5D;
736                         break;
737                 case 0x46:      /* ctrl-pause/break on AT 101 (see below) */
738                         keycode = 0x68;
739                         break;
740                 case 0x47:      /* grey home key */
741                         keycode = 0x5E;
742                         break;
743                 case 0x48:      /* grey up arrow key */
744                         keycode = 0x5F;
745                         break;
746                 case 0x49:      /* grey page up key */
747                         keycode = 0x60;
748                         break;
749                 case 0x4B:      /* grey left arrow key */
750                         keycode = 0x61;
751                         break;
752                 case 0x4D:      /* grey right arrow key */
753                         keycode = 0x62;
754                         break;
755                 case 0x4F:      /* grey end key */
756                         keycode = 0x63;
757                         break;
758                 case 0x50:      /* grey down arrow key */
759                         keycode = 0x64;
760                         break;
761                 case 0x51:      /* grey page down key */
762                         keycode = 0x65;
763                         break;
764                 case 0x52:      /* grey insert key */
765                         keycode = 0x66;
766                         break;
767                 case 0x53:      /* grey delete key */
768                         keycode = 0x67;
769                         break;
770                 /* the following 3 are only used on the MS "Natural" keyboard */
771                 case 0x5b:      /* left Window key */
772                         keycode = 0x69;
773                         break;
774                 case 0x5c:      /* right Window key */
775                         keycode = 0x6a;
776                         break;
777                 case 0x5d:      /* menu key */
778                         keycode = 0x6b;
779                         break;
780                 case 0x5e:      /* power key */
781                         keycode = 0x6d;
782                         break;
783                 case 0x5f:      /* sleep key */
784                         keycode = 0x6e;
785                         break;
786                 case 0x63:      /* wake key */
787                         keycode = 0x6f;
788                         break;
789                 case 0x64:      /* [JP106USB] backslash, underscore */
790                         keycode = 0x73;
791                         break;
792                 default:        /* ignore everything else */
793                         goto next_code;
794                 }
795                 break;
796         case 0xE1:      /* 0xE1 prefix */
797                 /* 
798                  * The pause/break key on the 101 keyboard produces:
799                  * E1-1D-45 E1-9D-C5
800                  * Ctrl-pause/break produces:
801                  * E0-46 E0-C6 (See above.)
802                  */
803                 state->ks_prefix = 0;
804                 if (keycode == 0x1D)
805                         state->ks_prefix = 0x1D;
806                 goto next_code;
807                 /* NOT REACHED */
808         case 0x1D:      /* pause / break */
809                 state->ks_prefix = 0;
810                 if (keycode != 0x45)
811                         goto next_code;
812                 keycode = 0x68;
813                 break;
814         }
815
816         /* XXX assume 101/102 keys AT keyboard */
817         switch (keycode) {
818         case 0x5c:      /* print screen */
819                 if (state->ks_flags & ALTS)
820                         keycode = 0x54; /* sysrq */
821                 break;
822         case 0x68:      /* pause/break */
823                 if (state->ks_flags & CTLS)
824                         keycode = 0x6c; /* break */
825                 break;
826         }
827
828         /* return the key code in the K_CODE mode */
829         if (state->ks_mode == K_CODE) {
830                 KBDMUX_UNLOCK(state);
831                 return (keycode | (scancode & 0x80));
832         }
833
834         /* compose a character code */
835         if (state->ks_flags & COMPOSE) {
836                 switch (keycode | (scancode & 0x80)) {
837                 /* key pressed, process it */
838                 case 0x47: case 0x48: case 0x49:        /* keypad 7,8,9 */
839                         state->ks_composed_char *= 10;
840                         state->ks_composed_char += keycode - 0x40;
841                         if (state->ks_composed_char > UCHAR_MAX) {
842                                 KBDMUX_UNLOCK(state);
843                                 return (ERRKEY);
844                         }
845                         goto next_code;
846                 case 0x4B: case 0x4C: case 0x4D:        /* keypad 4,5,6 */
847                         state->ks_composed_char *= 10;
848                         state->ks_composed_char += keycode - 0x47;
849                         if (state->ks_composed_char > UCHAR_MAX) {
850                                 KBDMUX_UNLOCK(state);
851                                 return (ERRKEY);
852                         }
853                         goto next_code;
854                 case 0x4F: case 0x50: case 0x51:        /* keypad 1,2,3 */
855                         state->ks_composed_char *= 10;
856                         state->ks_composed_char += keycode - 0x4E;
857                         if (state->ks_composed_char > UCHAR_MAX) {
858                                 KBDMUX_UNLOCK(state);
859                                 return (ERRKEY);
860                         }
861                         goto next_code;
862                 case 0x52:      /* keypad 0 */
863                         state->ks_composed_char *= 10;
864                         if (state->ks_composed_char > UCHAR_MAX) {
865                                 KBDMUX_UNLOCK(state);
866                                 return (ERRKEY);
867                         }
868                         goto next_code;
869
870                 /* key released, no interest here */
871                 case 0xC7: case 0xC8: case 0xC9:        /* keypad 7,8,9 */
872                 case 0xCB: case 0xCC: case 0xCD:        /* keypad 4,5,6 */
873                 case 0xCF: case 0xD0: case 0xD1:        /* keypad 1,2,3 */
874                 case 0xD2:                              /* keypad 0 */
875                         goto next_code;
876
877                 case 0x38:                              /* left alt key */
878                         break;
879
880                 default:
881                         if (state->ks_composed_char > 0) {
882                                 state->ks_flags &= ~COMPOSE;
883                                 state->ks_composed_char = 0;
884                                 KBDMUX_UNLOCK(state);
885                                 return (ERRKEY);
886                         }
887                         break;
888                 }
889         }
890
891         /* keycode to key action */
892         action = genkbd_keyaction(kbd, keycode, scancode & 0x80,
893                         &state->ks_state, &state->ks_accents);
894         if (action == NOKEY)
895                 goto next_code;
896
897         KBDMUX_UNLOCK(state);
898
899         return (action);
900 }
901
902 /*
903  * Check if char is waiting
904  */
905 static int
906 kbdmux_check_char(keyboard_t *kbd)
907 {
908         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
909         int              ready;
910
911         if (!KBD_IS_ACTIVE(kbd))
912                 return (FALSE);
913
914         KBDMUX_LOCK(state);
915
916         if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0))
917                 ready = TRUE;
918         else
919                 ready = (state->ks_inq_length > 0) ? TRUE : FALSE;
920
921         KBDMUX_UNLOCK(state);
922
923         return (ready);
924 }
925
926 /*
927  * Keyboard ioctl's
928  */
929 static int
930 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg)
931 {
932         static int       delays[] = {
933                 250, 500, 750, 1000
934         };
935
936         static int       rates[]  =  {
937                 34,  38,  42,  46,  50,   55,  59,  63,
938                 68,  76,  84,  92,  100, 110, 118, 126,
939                 136, 152, 168, 184, 200, 220, 236, 252,
940                 272, 304, 336, 368, 400, 440, 472, 504
941         };
942
943         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
944         kbdmux_kbd_t    *k;
945         keyboard_info_t *ki;
946         int              error = 0, mode;
947 #ifdef COMPAT_FREEBSD6
948         int              ival;
949 #endif
950
951         if (state == NULL)
952                 return (ENXIO);
953
954         switch (cmd) {
955         case KBADDKBD: /* add keyboard to the mux */
956                 ki = (keyboard_info_t *) arg;
957
958                 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
959                     strcmp(ki->kb_name, "*") == 0)
960                         return (EINVAL); /* bad input */
961
962                 KBDMUX_LOCK(state);
963
964                 SLIST_FOREACH(k, &state->ks_kbds, next)
965                         if (k->kbd->kb_unit == ki->kb_unit &&
966                             strcmp(k->kbd->kb_name, ki->kb_name) == 0)
967                                 break;
968
969                 if (k != NULL) {
970                         KBDMUX_UNLOCK(state);
971
972                         return (0); /* keyboard already in the mux */
973                 }
974
975                 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO);
976                 if (k == NULL) {
977                         KBDMUX_UNLOCK(state);
978
979                         return (ENOMEM); /* out of memory */
980                 }
981
982                 k->kbd = kbd_get_keyboard(
983                                 kbd_allocate(
984                                         ki->kb_name,
985                                         ki->kb_unit,
986                                         (void *) &k->kbd,
987                                         kbdmux_kbd_event, (void *) state));
988                 if (k->kbd == NULL) {
989                         KBDMUX_UNLOCK(state);
990                         free(k, M_KBDMUX);
991
992                         return (EINVAL); /* bad keyboard */
993                 }
994
995                 kbdd_enable(k->kbd);
996                 kbdd_clear_state(k->kbd);
997
998                 /* set K_RAW mode on slave keyboard */
999                 mode = K_RAW;
1000                 error = kbdd_ioctl(k->kbd, KDSKBMODE, (caddr_t)&mode);
1001                 if (error == 0) {
1002                         /* set lock keys state on slave keyboard */
1003                         mode = state->ks_state & LOCK_MASK;
1004                         error = kbdd_ioctl(k->kbd, KDSKBSTATE, (caddr_t)&mode);
1005                 }
1006
1007                 if (error != 0) {
1008                         KBDMUX_UNLOCK(state);
1009
1010                         kbd_release(k->kbd, &k->kbd);
1011                         k->kbd = NULL;
1012
1013                         free(k, M_KBDMUX);
1014
1015                         return (error); /* could not set mode */
1016                 }
1017
1018                 SLIST_INSERT_HEAD(&state->ks_kbds, k, next);
1019
1020                 KBDMUX_UNLOCK(state);
1021                 break;
1022
1023         case KBRELKBD: /* release keyboard from the mux */
1024                 ki = (keyboard_info_t *) arg;
1025
1026                 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' ||
1027                     strcmp(ki->kb_name, "*") == 0)
1028                         return (EINVAL); /* bad input */
1029
1030                 KBDMUX_LOCK(state);
1031
1032                 SLIST_FOREACH(k, &state->ks_kbds, next)
1033                         if (k->kbd->kb_unit == ki->kb_unit &&
1034                             strcmp(k->kbd->kb_name, ki->kb_name) == 0)
1035                                 break;
1036
1037                 if (k != NULL) {
1038                         error = kbd_release(k->kbd, &k->kbd);
1039                         if (error == 0) {
1040                                 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
1041
1042                                 k->kbd = NULL;
1043
1044                                 free(k, M_KBDMUX);
1045                         }
1046                 } else
1047                         error = ENXIO; /* keyboard is not in the mux */
1048
1049                 KBDMUX_UNLOCK(state);
1050                 break;
1051
1052         case KDGKBMODE: /* get kyboard mode */
1053                 KBDMUX_LOCK(state);
1054                 *(int *)arg = state->ks_mode;
1055                 KBDMUX_UNLOCK(state);
1056                 break;
1057
1058 #ifdef COMPAT_FREEBSD6
1059         case _IO('K', 7):
1060                 ival = IOCPARM_IVAL(arg);
1061                 arg = (caddr_t)&ival;
1062                 /* FALLTHROUGH */
1063 #endif
1064         case KDSKBMODE: /* set keyboard mode */
1065                 KBDMUX_LOCK(state);
1066
1067                 switch (*(int *)arg) {
1068                 case K_XLATE:
1069                         if (state->ks_mode != K_XLATE) {
1070                                 /* make lock key state and LED state match */
1071                                 state->ks_state &= ~LOCK_MASK;
1072                                 state->ks_state |= KBD_LED_VAL(kbd);
1073                         }
1074                         /* FALLTHROUGH */
1075
1076                 case K_RAW:
1077                 case K_CODE:
1078                         if (state->ks_mode != *(int *)arg) {
1079                                 kbdmux_clear_state_locked(state);
1080                                 state->ks_mode = *(int *)arg;
1081                         }
1082                         break;
1083
1084                 default:
1085                         error = EINVAL;
1086                         break;
1087                 }
1088
1089                 KBDMUX_UNLOCK(state);
1090                 break;
1091
1092         case KDGETLED: /* get keyboard LED */
1093                 KBDMUX_LOCK(state);
1094                 *(int *)arg = KBD_LED_VAL(kbd);
1095                 KBDMUX_UNLOCK(state);
1096                 break;
1097
1098 #ifdef COMPAT_FREEBSD6
1099         case _IO('K', 66):
1100                 ival = IOCPARM_IVAL(arg);
1101                 arg = (caddr_t)&ival;
1102                 /* FALLTHROUGH */
1103 #endif
1104         case KDSETLED: /* set keyboard LED */
1105                 KBDMUX_LOCK(state);
1106
1107                 /* NOTE: lock key state in ks_state won't be changed */
1108                 if (*(int *)arg & ~LOCK_MASK) {
1109                         KBDMUX_UNLOCK(state);
1110
1111                         return (EINVAL);
1112                 }
1113
1114                 KBD_LED_VAL(kbd) = *(int *)arg;
1115
1116                 /* KDSETLED on all slave keyboards */
1117                 SLIST_FOREACH(k, &state->ks_kbds, next)
1118                         (void)kbdd_ioctl(k->kbd, KDSETLED, arg);
1119
1120                 KBDMUX_UNLOCK(state);
1121                 break;
1122
1123         case KDGKBSTATE: /* get lock key state */
1124                 KBDMUX_LOCK(state);
1125                 *(int *)arg = state->ks_state & LOCK_MASK;
1126                 KBDMUX_UNLOCK(state);
1127                 break;
1128
1129 #ifdef COMPAT_FREEBSD6
1130         case _IO('K', 20):
1131                 ival = IOCPARM_IVAL(arg);
1132                 arg = (caddr_t)&ival;
1133                 /* FALLTHROUGH */
1134 #endif
1135         case KDSKBSTATE: /* set lock key state */
1136                 KBDMUX_LOCK(state);
1137
1138                 if (*(int *)arg & ~LOCK_MASK) {
1139                         KBDMUX_UNLOCK(state);
1140
1141                         return (EINVAL);
1142                 }
1143
1144                 state->ks_state &= ~LOCK_MASK;
1145                 state->ks_state |= *(int *)arg;
1146
1147                 /* KDSKBSTATE on all slave keyboards */
1148                 SLIST_FOREACH(k, &state->ks_kbds, next)
1149                         (void)kbdd_ioctl(k->kbd, KDSKBSTATE, arg);
1150
1151                 KBDMUX_UNLOCK(state);
1152
1153                 return (kbdmux_ioctl(kbd, KDSETLED, arg));
1154                 /* NOT REACHED */
1155
1156 #ifdef COMPAT_FREEBSD6
1157         case _IO('K', 67):
1158                 cmd = KDSETRAD;
1159                 ival = IOCPARM_IVAL(arg);
1160                 arg = (caddr_t)&ival;
1161                 /* FALLTHROUGH */
1162 #endif
1163         case KDSETREPEAT: /* set keyboard repeat rate (new interface) */
1164         case KDSETRAD: /* set keyboard repeat rate (old interface) */
1165                 KBDMUX_LOCK(state);
1166
1167                 if (cmd == KDSETREPEAT) {
1168                         int     i;
1169
1170                         /* lookup delay */
1171                         for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --)
1172                                 if (((int *)arg)[0] >= delays[i])
1173                                         break;
1174                         mode = i << 5;
1175
1176                         /* lookup rate */
1177                         for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --)
1178                                 if (((int *)arg)[1] >= rates[i])
1179                                         break;
1180                         mode |= i;
1181                 } else
1182                         mode = *(int *)arg;
1183
1184                 if (mode & ~0x7f) {
1185                         KBDMUX_UNLOCK(state);
1186
1187                         return (EINVAL);
1188                 }
1189
1190                 kbd->kb_delay1 = delays[(mode >> 5) & 3];
1191                 kbd->kb_delay2 = rates[mode & 0x1f];
1192
1193                 /* perform command on all slave keyboards */
1194                 SLIST_FOREACH(k, &state->ks_kbds, next)
1195                         (void)kbdd_ioctl(k->kbd, cmd, arg);
1196
1197                 KBDMUX_UNLOCK(state);
1198                 break;
1199
1200         case PIO_KEYMAP:        /* set keyboard translation table */
1201         case OPIO_KEYMAP:       /* set keyboard translation table (compat) */
1202         case PIO_KEYMAPENT:     /* set keyboard translation table entry */
1203         case PIO_DEADKEYMAP:    /* set accent key translation table */
1204                 KBDMUX_LOCK(state);
1205                 state->ks_accents = 0;
1206
1207                 /* perform command on all slave keyboards */
1208                 SLIST_FOREACH(k, &state->ks_kbds, next)
1209                         (void)kbdd_ioctl(k->kbd, cmd, arg);
1210
1211                 KBDMUX_UNLOCK(state);
1212                 /* FALLTHROUGH */
1213
1214         default:
1215                 error = genkbd_commonioctl(kbd, cmd, arg);
1216                 break;
1217         }
1218
1219         return (error);
1220 }
1221
1222 /*
1223  * Lock the access to the keyboard
1224  */
1225 static int
1226 kbdmux_lock(keyboard_t *kbd, int lock)
1227 {
1228         return (1); /* XXX */
1229 }
1230
1231 /*
1232  * Clear the internal state of the keyboard
1233  */
1234 static void
1235 kbdmux_clear_state_locked(kbdmux_state_t *state)
1236 {
1237         KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1238
1239         state->ks_flags &= ~(COMPOSE|POLLING);
1240         state->ks_state &= LOCK_MASK;   /* preserve locking key state */
1241         state->ks_accents = 0;
1242         state->ks_composed_char = 0;
1243 /*      state->ks_prefix = 0;           XXX */
1244         state->ks_inq_length = 0;
1245 }
1246
1247 static void
1248 kbdmux_clear_state(keyboard_t *kbd)
1249 {
1250         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
1251
1252         KBDMUX_LOCK(state);
1253         kbdmux_clear_state_locked(state);
1254         KBDMUX_UNLOCK(state);
1255 }
1256
1257 /*
1258  * Save the internal state
1259  */
1260 static int
1261 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len)
1262 {
1263         if (len == 0)
1264                 return (sizeof(kbdmux_state_t));
1265         if (len < sizeof(kbdmux_state_t))
1266                 return (-1);
1267
1268         bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */
1269
1270         return (0);
1271 }
1272
1273 /*
1274  * Set the internal state
1275  */
1276 static int
1277 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len)
1278 {
1279         if (len < sizeof(kbdmux_state_t))
1280                 return (ENOMEM);
1281
1282         bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */
1283
1284         return (0);
1285 }
1286
1287 /*
1288  * Set polling
1289  */
1290 static int
1291 kbdmux_poll(keyboard_t *kbd, int on)
1292 {
1293         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
1294         kbdmux_kbd_t    *k;
1295
1296         KBDMUX_LOCK(state);
1297
1298         if (on)
1299                 state->ks_flags |= POLLING; 
1300         else
1301                 state->ks_flags &= ~POLLING;
1302
1303         /* set poll on slave keyboards */
1304         SLIST_FOREACH(k, &state->ks_kbds, next)
1305                 kbdd_poll(k->kbd, on);
1306
1307         KBDMUX_UNLOCK(state);
1308
1309         return (0);
1310 }
1311
1312 /*****************************************************************************
1313  *****************************************************************************
1314  **                                    Module 
1315  *****************************************************************************
1316  *****************************************************************************/
1317
1318 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure);
1319
1320 static int
1321 kbdmux_modevent(module_t mod, int type, void *data)
1322 {
1323         keyboard_switch_t       *sw;
1324         keyboard_t              *kbd;
1325         int                      error;
1326
1327         switch (type) {
1328         case MOD_LOAD:
1329                 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0)
1330                         break;
1331
1332                 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) {
1333                         kbd_delete_driver(&kbdmux_kbd_driver);
1334                         error = ENXIO;
1335                         break;
1336                 }
1337
1338                 kbd = NULL;
1339
1340                 if ((error = (*sw->probe)(0, NULL, 0)) != 0 ||
1341                     (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) {
1342                         kbd_delete_driver(&kbdmux_kbd_driver);
1343                         break;
1344                 }
1345
1346 #ifdef KBD_INSTALL_CDEV
1347                 if ((error = kbd_attach(kbd)) != 0) {
1348                         (*sw->term)(kbd);
1349                         kbd_delete_driver(&kbdmux_kbd_driver);
1350                         break;
1351                 }
1352 #endif
1353
1354                 if ((error = (*sw->enable)(kbd)) != 0) {
1355                         (*sw->disable)(kbd);
1356 #ifdef KBD_INSTALL_CDEV
1357                         kbd_detach(kbd);
1358 #endif
1359                         (*sw->term)(kbd);
1360                         kbd_delete_driver(&kbdmux_kbd_driver);
1361                         break;
1362                 }
1363                 break;
1364
1365         case MOD_UNLOAD:
1366                 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL)
1367                         panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL");
1368
1369                 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0));
1370                 if (kbd != NULL) {
1371                         (*sw->disable)(kbd);
1372 #ifdef KBD_INSTALL_CDEV
1373                         kbd_detach(kbd);
1374 #endif
1375                         (*sw->term)(kbd);
1376                         kbd_delete_driver(&kbdmux_kbd_driver);
1377                 }
1378                 error = 0;
1379                 break;
1380
1381         default:
1382                 error = EOPNOTSUPP;
1383                 break;
1384         }
1385
1386         return (error);
1387 }
1388
1389 DEV_MODULE(kbdmux, kbdmux_modevent, NULL);
1390