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