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