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