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