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