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