]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/kbdmux/kbdmux.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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/tty.h>
56 #include <sys/uio.h>
57 #include <dev/kbd/kbdreg.h>
58 #include <dev/kbd/kbdtables.h>
59
60 #define KEYBOARD_NAME   "kbdmux"
61
62 MALLOC_DECLARE(M_KBDMUX);
63 MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
64
65 /*****************************************************************************
66  *****************************************************************************
67  **                             Keyboard state
68  *****************************************************************************
69  *****************************************************************************/
70
71 #define KBDMUX_Q_SIZE   512     /* input queue size */
72
73 /*
74  * XXX
75  * For now rely on Giant mutex to protect our data structures.
76  * Just like the rest of keyboard drivers and syscons(4) do.
77  * Note that callout is initialized as not MP-safe to make sure
78  * Giant is held.
79  */
80
81 #if 0 /* not yet */
82 #define KBDMUX_LOCK_DECL_GLOBAL \
83         struct mtx ks_lock
84 #define KBDMUX_LOCK_INIT(s) \
85         mtx_init(&(s)->ks_lock, "kbdmux", NULL, MTX_DEF|MTX_RECURSE)
86 #define KBDMUX_LOCK_DESTROY(s) \
87         mtx_destroy(&(s)->ks_lock)
88 #define KBDMUX_LOCK(s) \
89         mtx_lock(&(s)->ks_lock)
90 #define KBDMUX_UNLOCK(s) \
91         mtx_unlock(&(s)->ks_lock)
92 #define KBDMUX_LOCK_ASSERT(s, w) \
93         mtx_assert(&(s)->ks_lock, (w))
94 #define KBDMUX_SLEEP(s, f, d, t) \
95         msleep(&(s)->f, &(s)->ks_lock, PCATCH | (PZERO + 1), (d), (t))
96 #define KBDMUX_CALLOUT_INIT(s) \
97         callout_init_mtx(&(s)->ks_timo, &(s)->ks_lock, 0)
98 #define KBDMUX_QUEUE_INTR(s) \
99         taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
100 #else
101 #define KBDMUX_LOCK_DECL_GLOBAL
102
103 #define KBDMUX_LOCK_INIT(s)
104
105 #define KBDMUX_LOCK_DESTROY(s)
106
107 #define KBDMUX_LOCK(s)
108
109 #define KBDMUX_UNLOCK(s)
110
111 #define KBDMUX_LOCK_ASSERT(s, w)
112
113 #define KBDMUX_SLEEP(s, f, d, t) \
114         tsleep(&(s)->f, PCATCH | (PZERO + 1), (d), (t))
115 #define KBDMUX_CALLOUT_INIT(s) \
116         callout_init(&(s)->ks_timo, 0)
117 #define KBDMUX_QUEUE_INTR(s) \
118         taskqueue_enqueue(taskqueue_swi_giant, &(s)->ks_task)
119 #endif /* not yet */
120
121 #define KBDMUX_INTR(kbd, arg) \
122         (*kbdsw[(kbd)->kb_index]->intr)((kbd), (arg))
123
124 #define KBDMUX_IOCTL(kbd, cmd, arg) \
125         (*kbdsw[(kbd)->kb_index]->ioctl)((kbd), (cmd), (caddr_t) (arg))
126
127 #define KBDMUX_CHECK_CHAR(kbd) \
128         (*kbdsw[(kbd)->kb_index]->check_char)((kbd))
129
130 #define KBDMUX_READ_CHAR(kbd, wait) \
131         (*kbdsw[(kbd)->kb_index]->read_char)((kbd), (wait))
132
133 #define KBDMUX_ENABLE(kbd) \
134         (*kbdsw[(kbd)->kb_index]->enable)((kbd))
135
136 #define KBDMUX_POLL(kbd, on) \
137         (*kbdsw[(kbd)->kb_index]->poll)((kbd), (on))
138
139 #define KBDMUX_CLEAR_STATE(kbd) \
140         (*kbdsw[(kbd)->kb_index]->clear_state)((kbd))
141
142 /*
143  * kbdmux keyboard
144  */
145 struct kbdmux_kbd
146 {
147         keyboard_t              *kbd;   /* keyboard */
148         SLIST_ENTRY(kbdmux_kbd)  next;  /* link to next */
149 };
150
151 typedef struct kbdmux_kbd       kbdmux_kbd_t;
152
153 /*
154  * kbdmux state
155  */
156 struct kbdmux_state
157 {
158         struct clist             ks_inq;        /* input chars queue */
159         struct task              ks_task;       /* interrupt task */
160         struct callout           ks_timo;       /* timeout handler */
161 #define TICKS                   (hz)            /* rate */
162
163         int                      ks_flags;      /* flags */
164 #define COMPOSE                 (1 << 0)        /* compose char flag */ 
165 #define POLLING                 (1 << 1)        /* polling */
166 #define TASK                    (1 << 2)        /* interrupt task queued */
167
168         int                      ks_mode;       /* K_XLATE, K_RAW, K_CODE */
169         int                      ks_state;      /* state */
170         int                      ks_accents;    /* accent key index (> 0) */
171         u_int                    ks_composed_char; /* composed char code */
172         u_char                   ks_prefix;     /* AT scan code prefix */
173
174         SLIST_HEAD(, kbdmux_kbd) ks_kbds;       /* keyboards */
175
176         KBDMUX_LOCK_DECL_GLOBAL;
177 };
178
179 typedef struct kbdmux_state     kbdmux_state_t;
180
181 /*****************************************************************************
182  *****************************************************************************
183  **                             Helper functions
184  *****************************************************************************
185  *****************************************************************************/
186
187 static task_fn_t                kbdmux_kbd_intr;
188 static timeout_t                kbdmux_kbd_intr_timo;
189 static kbd_callback_func_t      kbdmux_kbd_event;
190
191 /*
192  * Interrupt handler task
193  */
194 void
195 kbdmux_kbd_intr(void *xkbd, int pending)
196 {
197         keyboard_t      *kbd = (keyboard_t *) xkbd;
198         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
199
200         KBDMUX_INTR(kbd, NULL);
201
202         KBDMUX_LOCK(state);
203
204         state->ks_flags &= ~TASK;
205         wakeup(&state->ks_task);
206
207         KBDMUX_UNLOCK(state);
208 }
209
210 /*
211  * Schedule interrupt handler on timeout. Called with locked state.
212  */
213 void
214 kbdmux_kbd_intr_timo(void *xstate)
215 {
216         kbdmux_state_t  *state = (kbdmux_state_t *) xstate;
217
218         KBDMUX_LOCK_ASSERT(state, MA_OWNED);
219
220         if (callout_pending(&state->ks_timo))
221                 return; /* callout was reset */
222
223         if (!callout_active(&state->ks_timo))
224                 return; /* callout was stopped */
225
226         callout_deactivate(&state->ks_timo);
227
228         /* queue interrupt task if needed */
229         if (state->ks_inq.c_cc > 0 && !(state->ks_flags & TASK) &&
230             KBDMUX_QUEUE_INTR(state) == 0)
231                 state->ks_flags |= TASK;
232
233         /* re-schedule timeout */
234         callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
235 }
236
237 /*
238  * Process event from one of our keyboards
239  */
240 static int
241 kbdmux_kbd_event(keyboard_t *kbd, int event, void *arg)
242 {
243         kbdmux_state_t  *state = (kbdmux_state_t *) arg;
244
245         switch (event) {
246         case KBDIO_KEYINPUT: {
247                 int     c;
248
249                 KBDMUX_LOCK(state);
250
251                 /*
252                  * Read all chars from the keyboard
253                  *
254                  * Turns out that atkbd(4) check_char() method may return
255                  * "true" while read_char() method returns NOKEY. If this
256                  * happens we could stuck in the loop below. Avoid this
257                  * by breaking out of the loop if read_char() method returns
258                  * NOKEY.
259                  */
260
261                 while (KBDMUX_CHECK_CHAR(kbd)) {
262                         c = KBDMUX_READ_CHAR(kbd, 0);
263                         if (c == NOKEY)
264                                 break;
265                         if (c == ERRKEY)
266                                 continue; /* XXX ring bell */
267                         if (!KBD_IS_BUSY(kbd))
268                                 continue; /* not open - discard the input */
269
270                         putc(c, &state->ks_inq);
271                 }
272
273                 /* queue interrupt task if needed */
274                 if (state->ks_inq.c_cc > 0 && !(state->ks_flags & TASK) &&
275                     KBDMUX_QUEUE_INTR(state) == 0)
276                         state->ks_flags |= TASK;
277
278                 KBDMUX_UNLOCK(state);
279                 } break;
280
281         case KBDIO_UNLOADING: {
282                 kbdmux_kbd_t    *k;
283
284                 KBDMUX_LOCK(state);
285
286                 SLIST_FOREACH(k, &state->ks_kbds, next)
287                         if (k->kbd == kbd)
288                                 break;
289
290                 if (k != NULL) {
291                         kbd_release(k->kbd, &k->kbd);
292                         SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next);
293
294                         k->kbd = NULL;
295
296                         free(k, M_KBDMUX);
297                 }
298
299                 KBDMUX_UNLOCK(state);
300                 } break;
301
302         default:
303                 return (EINVAL);
304                 /* NOT REACHED */
305         }
306
307         return (0);
308 }
309
310 /****************************************************************************
311  ****************************************************************************
312  **                              Keyboard driver
313  ****************************************************************************
314  ****************************************************************************/
315
316 static int              kbdmux_configure(int flags);
317 static kbd_probe_t      kbdmux_probe;
318 static kbd_init_t       kbdmux_init;
319 static kbd_term_t       kbdmux_term;
320 static kbd_intr_t       kbdmux_intr;
321 static kbd_test_if_t    kbdmux_test_if;
322 static kbd_enable_t     kbdmux_enable;
323 static kbd_disable_t    kbdmux_disable;
324 static kbd_read_t       kbdmux_read;
325 static kbd_check_t      kbdmux_check;
326 static kbd_read_char_t  kbdmux_read_char;
327 static kbd_check_char_t kbdmux_check_char;
328 static kbd_ioctl_t      kbdmux_ioctl;
329 static kbd_lock_t       kbdmux_lock;
330 static void             kbdmux_clear_state_locked(kbdmux_state_t *state);
331 static kbd_clear_state_t kbdmux_clear_state;
332 static kbd_get_state_t  kbdmux_get_state;
333 static kbd_set_state_t  kbdmux_set_state;
334 static kbd_poll_mode_t  kbdmux_poll;
335
336 static keyboard_switch_t kbdmuxsw = {
337         .probe =        kbdmux_probe,
338         .init =         kbdmux_init,
339         .term =         kbdmux_term,
340         .intr =         kbdmux_intr,
341         .test_if =      kbdmux_test_if,
342         .enable =       kbdmux_enable,
343         .disable =      kbdmux_disable,
344         .read =         kbdmux_read,
345         .check =        kbdmux_check,
346         .read_char =    kbdmux_read_char,
347         .check_char =   kbdmux_check_char,
348         .ioctl =        kbdmux_ioctl,
349         .lock =         kbdmux_lock,
350         .clear_state =  kbdmux_clear_state,
351         .get_state =    kbdmux_get_state,
352         .set_state =    kbdmux_set_state,
353         .get_fkeystr =  genkbd_get_fkeystr,
354         .poll =         kbdmux_poll,
355         .diag =         genkbd_diag,
356 };
357
358 /*
359  * Return the number of found keyboards
360  */
361 static int
362 kbdmux_configure(int flags)
363 {
364         return (1);
365 }
366
367 /*
368  * Detect a keyboard
369  */
370 static int
371 kbdmux_probe(int unit, void *arg, int flags)
372 {
373         if (resource_disabled(KEYBOARD_NAME, unit))
374                 return (ENXIO);
375
376         return (0);
377 }
378
379 /*
380  * Reset and initialize the keyboard (stolen from atkbd.c)
381  */
382 static int
383 kbdmux_init(int unit, keyboard_t **kbdp, void *arg, int flags)
384 {
385         keyboard_t      *kbd = NULL;
386         kbdmux_state_t  *state = NULL;
387         keymap_t        *keymap = NULL;
388         accentmap_t     *accmap = NULL;
389         fkeytab_t       *fkeymap = NULL;
390         int              error, needfree, fkeymap_size, delay[2];
391
392         if (*kbdp == NULL) {
393                 *kbdp = kbd = malloc(sizeof(*kbd), M_KBDMUX, M_NOWAIT | M_ZERO);
394                 state = malloc(sizeof(*state), M_KBDMUX, M_NOWAIT | M_ZERO);
395                 keymap = malloc(sizeof(key_map), M_KBDMUX, M_NOWAIT);
396                 accmap = malloc(sizeof(accent_map), M_KBDMUX, M_NOWAIT);
397                 fkeymap = malloc(sizeof(fkey_tab), M_KBDMUX, M_NOWAIT);
398                 fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]);
399                 needfree = 1;
400
401                 if ((kbd == NULL) || (state == NULL) || (keymap == NULL) ||
402                     (accmap == NULL) || (fkeymap == NULL)) {
403                         error = ENOMEM;
404                         goto bad;
405                 }
406
407                 KBDMUX_LOCK_INIT(state);
408                 clist_alloc_cblocks(&state->ks_inq,
409                                 KBDMUX_Q_SIZE, KBDMUX_Q_SIZE / 2);
410                 TASK_INIT(&state->ks_task, 0, kbdmux_kbd_intr, (void *) kbd);
411                 KBDMUX_CALLOUT_INIT(state);
412                 SLIST_INIT(&state->ks_kbds);
413         } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) {
414                 return (0);
415         } else {
416                 kbd = *kbdp;
417                 state = (kbdmux_state_t *) kbd->kb_data;
418                 keymap = kbd->kb_keymap;
419                 accmap = kbd->kb_accentmap;
420                 fkeymap = kbd->kb_fkeytab;
421                 fkeymap_size = kbd->kb_fkeytab_size;
422                 needfree = 0;
423         }
424
425         if (!KBD_IS_PROBED(kbd)) {
426                 /* XXX assume 101/102 keys keyboard */
427                 kbd_init_struct(kbd, KEYBOARD_NAME, KB_101, unit, flags, 0, 0);
428                 bcopy(&key_map, keymap, sizeof(key_map));
429                 bcopy(&accent_map, accmap, sizeof(accent_map));
430                 bcopy(fkey_tab, fkeymap,
431                         imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab)));
432                 kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size);
433                 kbd->kb_data = (void *)state;
434         
435                 KBD_FOUND_DEVICE(kbd);
436                 KBD_PROBE_DONE(kbd);
437
438                 KBDMUX_LOCK(state);
439                 kbdmux_clear_state_locked(state);
440                 state->ks_mode = K_XLATE;
441                 KBDMUX_UNLOCK(state);
442         }
443
444         if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) {
445                 kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY;
446
447                 kbdmux_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state);
448
449                 delay[0] = kbd->kb_delay1;
450                 delay[1] = kbd->kb_delay2;
451                 kbdmux_ioctl(kbd, KDSETREPEAT, (caddr_t)delay);
452
453                 KBD_INIT_DONE(kbd);
454         }
455
456         if (!KBD_IS_CONFIGURED(kbd)) {
457                 if (kbd_register(kbd) < 0) {
458                         error = ENXIO;
459                         goto bad;
460                 }
461
462                 KBD_CONFIG_DONE(kbd);
463
464                 KBDMUX_LOCK(state);
465                 callout_reset(&state->ks_timo, TICKS, kbdmux_kbd_intr_timo, state);
466                 KBDMUX_UNLOCK(state);
467         }
468
469         return (0);
470 bad:
471         if (needfree) {
472                 if (state != NULL) {
473                         clist_free_cblocks(&state->ks_inq);
474                         free(state, M_KBDMUX);
475                 }
476                 if (keymap != NULL)
477                         free(keymap, M_KBDMUX);
478                 if (accmap != NULL)
479                         free(accmap, M_KBDMUX);
480                 if (fkeymap != NULL)
481                         free(fkeymap, M_KBDMUX);
482                 if (kbd != NULL) {
483                         free(kbd, M_KBDMUX);
484                         *kbdp = NULL;   /* insure ref doesn't leak to caller */
485                 }
486         }
487
488         return (error);
489 }
490
491 /*
492  * Finish using this keyboard
493  */
494 static int
495 kbdmux_term(keyboard_t *kbd)
496 {
497         kbdmux_state_t  *state = (kbdmux_state_t *) kbd->kb_data;
498         kbdmux_kbd_t    *k;
499
500         KBDMUX_LOCK(state);
501
502         /* kill callout */
503         callout_stop(&state->ks_timo);
504
505         /* wait for interrupt task */
506         while (state->ks_flags & TASK)
507                 KBDMUX_SLEEP(state, ks_task, "kbdmuxc", 0);
508
509         /* release all keyboards from the mux */
510         while ((k = SLIST_FIRST(&state->ks_kbds)) != NULL) {
511                 kbd_release(k->kbd, &k->kbd);
512                 SLIST_REMOVE_HEAD(&state->ks_kbds, next);
513
514                 k->kbd = NULL;
515
516                 free(k, M_KBDMUX);
517         }
518
519         /* flush input queue */
520         ndflush(&state->ks_inq, state->ks_inq.c_cc);
521         clist_free_cblocks(&state->ks_inq);
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 = getc(&state->ks_inq);
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.c_cc > 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 = getc(&state->ks_inq);
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 (KBDMUX_CHECK_CHAR(k->kbd)) {
666                                         scancode = KBDMUX_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                                         putc(scancode, &state->ks_inq);
675                                 }
676                         }
677
678                         if (state->ks_inq.c_cc > 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.c_cc > 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                 KBDMUX_ENABLE(k->kbd);
996                 KBDMUX_CLEAR_STATE(k->kbd);
997
998                 /* set K_RAW mode on slave keyboard */
999                 mode = K_RAW;
1000                 error = KBDMUX_IOCTL(k->kbd, KDSKBMODE, &mode);
1001                 if (error == 0) {
1002                         /* set lock keys state on slave keyboard */
1003                         mode = state->ks_state & LOCK_MASK;
1004                         error = KBDMUX_IOCTL(k->kbd, KDSKBSTATE, &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                         KBDMUX_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                         KBDMUX_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                         KBDMUX_IOCTL(k->kbd, cmd, arg);
1196
1197                 KBDMUX_UNLOCK(state);
1198                 break;
1199
1200         case PIO_KEYMAP:        /* set keyboard translation table */
1201         case PIO_KEYMAPENT:     /* set keyboard translation table entry */
1202         case PIO_DEADKEYMAP:    /* set accent key translation table */
1203                 KBDMUX_LOCK(state);
1204                 state->ks_accents = 0;
1205
1206                 /* perform command on all slave keyboards */
1207                 SLIST_FOREACH(k, &state->ks_kbds, next)
1208                         KBDMUX_IOCTL(k->kbd, cmd, arg);
1209
1210                 KBDMUX_UNLOCK(state);
1211                 /* FALLTHROUGH */
1212
1213         default:
1214                 error = genkbd_commonioctl(kbd, cmd, arg);
1215                 break;
1216         }
1217
1218         return (error);
1219 }
1220
1221 /*
1222  * Lock the access to the keyboard
1223  */
1224 static int
1225 kbdmux_lock(keyboard_t *kbd, int lock)
1226 {
1227         return (1); /* XXX */
1228 }
1229
1230 /*
1231  * Clear the internal state of the keyboard
1232  */
1233 static void
1234 kbdmux_clear_state_locked(kbdmux_state_t *state)
1235 {
1236         KBDMUX_LOCK_ASSERT(state, MA_OWNED);
1237
1238         state->ks_flags &= ~(COMPOSE|POLLING);
1239         state->ks_state &= LOCK_MASK;   /* preserve locking key state */
1240         state->ks_accents = 0;
1241         state->ks_composed_char = 0;
1242 /*      state->ks_prefix = 0;           XXX */
1243
1244         ndflush(&state->ks_inq, state->ks_inq.c_cc);
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                 KBDMUX_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