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