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