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