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 KBDMUX_UNLOCK(state); 661 return (NOKEY); 662 } 663 /* XXX FIXME: check for -1 if wait == 1! */ 664 665 kbd->kb_count ++; 666 667 /* return the byte as is for the K_RAW mode */ 668 if (state->ks_mode == K_RAW) { 669 KBDMUX_UNLOCK(state); 670 return (scancode); 671 } 672 673 /* translate the scan code into a keycode */ 674 keycode = scancode & 0x7F; 675 switch (state->ks_prefix) { 676 case 0x00: /* normal scancode */ 677 switch(scancode) { 678 case 0xB8: /* left alt (compose key) released */ 679 if (state->ks_flags & COMPOSE) { 680 state->ks_flags &= ~COMPOSE; 681 if (state->ks_composed_char > UCHAR_MAX) 682 state->ks_composed_char = 0; 683 } 684 break; 685 case 0x38: /* left alt (compose key) pressed */ 686 if (!(state->ks_flags & COMPOSE)) { 687 state->ks_flags |= COMPOSE; 688 state->ks_composed_char = 0; 689 } 690 break; 691 case 0xE0: 692 case 0xE1: 693 state->ks_prefix = scancode; 694 goto next_code; 695 } 696 break; 697 case 0xE0: /* 0xE0 prefix */ 698 state->ks_prefix = 0; 699 switch (keycode) { 700 case 0x1C: /* right enter key */ 701 keycode = 0x59; 702 break; 703 case 0x1D: /* right ctrl key */ 704 keycode = 0x5A; 705 break; 706 case 0x35: /* keypad divide key */ 707 keycode = 0x5B; 708 break; 709 case 0x37: /* print scrn key */ 710 keycode = 0x5C; 711 break; 712 case 0x38: /* right alt key (alt gr) */ 713 keycode = 0x5D; 714 break; 715 case 0x46: /* ctrl-pause/break on AT 101 (see below) */ 716 keycode = 0x68; 717 break; 718 case 0x47: /* grey home key */ 719 keycode = 0x5E; 720 break; 721 case 0x48: /* grey up arrow key */ 722 keycode = 0x5F; 723 break; 724 case 0x49: /* grey page up key */ 725 keycode = 0x60; 726 break; 727 case 0x4B: /* grey left arrow key */ 728 keycode = 0x61; 729 break; 730 case 0x4D: /* grey right arrow key */ 731 keycode = 0x62; 732 break; 733 case 0x4F: /* grey end key */ 734 keycode = 0x63; 735 break; 736 case 0x50: /* grey down arrow key */ 737 keycode = 0x64; 738 break; 739 case 0x51: /* grey page down key */ 740 keycode = 0x65; 741 break; 742 case 0x52: /* grey insert key */ 743 keycode = 0x66; 744 break; 745 case 0x53: /* grey delete key */ 746 keycode = 0x67; 747 break; 748 /* the following 3 are only used on the MS "Natural" keyboard */ 749 case 0x5b: /* left Window key */ 750 keycode = 0x69; 751 break; 752 case 0x5c: /* right Window key */ 753 keycode = 0x6a; 754 break; 755 case 0x5d: /* menu key */ 756 keycode = 0x6b; 757 break; 758 case 0x5e: /* power key */ 759 keycode = 0x6d; 760 break; 761 case 0x5f: /* sleep key */ 762 keycode = 0x6e; 763 break; 764 case 0x63: /* wake key */ 765 keycode = 0x6f; 766 break; 767 default: /* ignore everything else */ 768 goto next_code; 769 } 770 break; 771 case 0xE1: /* 0xE1 prefix */ 772 /* 773 * The pause/break key on the 101 keyboard produces: 774 * E1-1D-45 E1-9D-C5 775 * Ctrl-pause/break produces: 776 * E0-46 E0-C6 (See above.) 777 */ 778 state->ks_prefix = 0; 779 if (keycode == 0x1D) 780 state->ks_prefix = 0x1D; 781 goto next_code; 782 /* NOT REACHED */ 783 case 0x1D: /* pause / break */ 784 state->ks_prefix = 0; 785 if (keycode != 0x45) 786 goto next_code; 787 keycode = 0x68; 788 break; 789 } 790 791 /* XXX assume 101/102 keys AT keyboard */ 792 switch (keycode) { 793 case 0x5c: /* print screen */ 794 if (state->ks_flags & ALTS) 795 keycode = 0x54; /* sysrq */ 796 break; 797 case 0x68: /* pause/break */ 798 if (state->ks_flags & CTLS) 799 keycode = 0x6c; /* break */ 800 break; 801 } 802 803 /* return the key code in the K_CODE mode */ 804 if (state->ks_mode == K_CODE) { 805 KBDMUX_UNLOCK(state); 806 return (keycode | (scancode & 0x80)); 807 } 808 809 /* compose a character code */ 810 if (state->ks_flags & COMPOSE) { 811 switch (keycode | (scancode & 0x80)) { 812 /* key pressed, process it */ 813 case 0x47: case 0x48: case 0x49: /* keypad 7,8,9 */ 814 state->ks_composed_char *= 10; 815 state->ks_composed_char += keycode - 0x40; 816 if (state->ks_composed_char > UCHAR_MAX) { 817 KBDMUX_UNLOCK(state); 818 return (ERRKEY); 819 } 820 goto next_code; 821 case 0x4B: case 0x4C: case 0x4D: /* keypad 4,5,6 */ 822 state->ks_composed_char *= 10; 823 state->ks_composed_char += keycode - 0x47; 824 if (state->ks_composed_char > UCHAR_MAX) { 825 KBDMUX_UNLOCK(state); 826 return (ERRKEY); 827 } 828 goto next_code; 829 case 0x4F: case 0x50: case 0x51: /* keypad 1,2,3 */ 830 state->ks_composed_char *= 10; 831 state->ks_composed_char += keycode - 0x4E; 832 if (state->ks_composed_char > UCHAR_MAX) { 833 KBDMUX_UNLOCK(state); 834 return (ERRKEY); 835 } 836 goto next_code; 837 case 0x52: /* keypad 0 */ 838 state->ks_composed_char *= 10; 839 if (state->ks_composed_char > UCHAR_MAX) { 840 KBDMUX_UNLOCK(state); 841 return (ERRKEY); 842 } 843 goto next_code; 844 845 /* key released, no interest here */ 846 case 0xC7: case 0xC8: case 0xC9: /* keypad 7,8,9 */ 847 case 0xCB: case 0xCC: case 0xCD: /* keypad 4,5,6 */ 848 case 0xCF: case 0xD0: case 0xD1: /* keypad 1,2,3 */ 849 case 0xD2: /* keypad 0 */ 850 goto next_code; 851 852 case 0x38: /* left alt key */ 853 break; 854 855 default: 856 if (state->ks_composed_char > 0) { 857 state->ks_flags &= ~COMPOSE; 858 state->ks_composed_char = 0; 859 KBDMUX_UNLOCK(state); 860 return (ERRKEY); 861 } 862 break; 863 } 864 } 865 866 /* keycode to key action */ 867 action = genkbd_keyaction(kbd, keycode, scancode & 0x80, 868 &state->ks_state, &state->ks_accents); 869 if (action == NOKEY) 870 goto next_code; 871 872 KBDMUX_UNLOCK(state); 873 874 return (action); 875 } 876 877 /* 878 * Check if char is waiting 879 */ 880 static int 881 kbdmux_check_char(keyboard_t *kbd) 882 { 883 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 884 int ready; 885 886 if (!KBD_IS_ACTIVE(kbd)) 887 return (FALSE); 888 889 KBDMUX_LOCK(state); 890 891 if (!(state->ks_flags & COMPOSE) && (state->ks_composed_char != 0)) 892 ready = TRUE; 893 else 894 ready = (state->ks_inq.c_cc > 0)? TRUE : FALSE; 895 896 KBDMUX_UNLOCK(state); 897 898 return (ready); 899 } 900 901 /* 902 * Keyboard ioctl's 903 */ 904 static int 905 kbdmux_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 906 { 907 static int delays[] = { 908 250, 500, 750, 1000 909 }; 910 911 static int rates[] = { 912 34, 38, 42, 46, 50, 55, 59, 63, 913 68, 76, 84, 92, 100, 110, 118, 126, 914 136, 152, 168, 184, 200, 220, 236, 252, 915 272, 304, 336, 368, 400, 440, 472, 504 916 }; 917 918 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 919 kbdmux_kbd_t *k; 920 keyboard_info_t *ki; 921 int error = 0, mode; 922 923 if (state == NULL) 924 return (ENXIO); 925 926 switch (cmd) { 927 case KBADDKBD: /* add keyboard to the mux */ 928 ki = (keyboard_info_t *) arg; 929 930 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' || 931 strcmp(ki->kb_name, "*") == 0) 932 return (EINVAL); /* bad input */ 933 934 KBDMUX_LOCK(state); 935 936 SLIST_FOREACH(k, &state->ks_kbds, next) 937 if (k->kbd->kb_unit == ki->kb_unit && 938 strcmp(k->kbd->kb_name, ki->kb_name) == 0) 939 break; 940 941 if (k != NULL) { 942 KBDMUX_UNLOCK(state); 943 944 return (0); /* keyboard already in the mux */ 945 } 946 947 k = malloc(sizeof(*k), M_KBDMUX, M_NOWAIT | M_ZERO); 948 if (k == NULL) { 949 KBDMUX_UNLOCK(state); 950 951 return (ENOMEM); /* out of memory */ 952 } 953 954 k->kbd = kbd_get_keyboard( 955 kbd_allocate( 956 ki->kb_name, 957 ki->kb_unit, 958 (void *) &k->kbd, 959 kbdmux_kbd_event, (void *) state)); 960 if (k->kbd == NULL) { 961 KBDMUX_UNLOCK(state); 962 free(k, M_KBDMUX); 963 964 return (EINVAL); /* bad keyboard */ 965 } 966 967 KBDMUX_ENABLE(k->kbd); 968 KBDMUX_CLEAR_STATE(k->kbd); 969 970 /* set K_RAW mode on slave keyboard */ 971 mode = K_RAW; 972 error = KBDMUX_IOCTL(k->kbd, KDSKBMODE, &mode); 973 if (error == 0) { 974 /* set lock keys state on slave keyboard */ 975 mode = state->ks_state & LOCK_MASK; 976 error = KBDMUX_IOCTL(k->kbd, KDSKBSTATE, &mode); 977 } 978 979 if (error != 0) { 980 KBDMUX_UNLOCK(state); 981 982 kbd_release(k->kbd, &k->kbd); 983 k->kbd = NULL; 984 985 free(k, M_KBDMUX); 986 987 return (error); /* could not set mode */ 988 } 989 990 SLIST_INSERT_HEAD(&state->ks_kbds, k, next); 991 992 KBDMUX_UNLOCK(state); 993 break; 994 995 case KBRELKBD: /* release keyboard from the mux */ 996 ki = (keyboard_info_t *) arg; 997 998 if (ki == NULL || ki->kb_unit < 0 || ki->kb_name[0] == '\0' || 999 strcmp(ki->kb_name, "*") == 0) 1000 return (EINVAL); /* bad input */ 1001 1002 KBDMUX_LOCK(state); 1003 1004 SLIST_FOREACH(k, &state->ks_kbds, next) 1005 if (k->kbd->kb_unit == ki->kb_unit && 1006 strcmp(k->kbd->kb_name, ki->kb_name) == 0) 1007 break; 1008 1009 if (k != NULL) { 1010 error = kbd_release(k->kbd, &k->kbd); 1011 if (error == 0) { 1012 SLIST_REMOVE(&state->ks_kbds, k, kbdmux_kbd, next); 1013 1014 k->kbd = NULL; 1015 1016 free(k, M_KBDMUX); 1017 } 1018 } else 1019 error = ENXIO; /* keyboard is not in the mux */ 1020 1021 KBDMUX_UNLOCK(state); 1022 break; 1023 1024 case KDGKBMODE: /* get kyboard mode */ 1025 KBDMUX_LOCK(state); 1026 *((intptr_t *) arg) = state->ks_mode; 1027 KBDMUX_UNLOCK(state); 1028 break; 1029 1030 case KDSKBMODE: /* set keyboard mode */ 1031 KBDMUX_LOCK(state); 1032 1033 switch (*((intptr_t *) arg)) { 1034 case K_XLATE: 1035 if (state->ks_mode != K_XLATE) { 1036 /* make lock key state and LED state match */ 1037 state->ks_state &= ~LOCK_MASK; 1038 state->ks_state |= KBD_LED_VAL(kbd); 1039 } 1040 /* FALLTHROUGH */ 1041 1042 case K_RAW: 1043 case K_CODE: 1044 if (state->ks_mode != *((intptr_t *) arg)) { 1045 kbdmux_clear_state_locked(state); 1046 state->ks_mode = *((intptr_t *) arg); 1047 } 1048 break; 1049 1050 default: 1051 error = EINVAL; 1052 break; 1053 } 1054 1055 KBDMUX_UNLOCK(state); 1056 break; 1057 1058 case KDGETLED: /* get keyboard LED */ 1059 KBDMUX_LOCK(state); 1060 *((intptr_t *) arg) = KBD_LED_VAL(kbd); 1061 KBDMUX_UNLOCK(state); 1062 break; 1063 1064 case KDSETLED: /* set keyboard LED */ 1065 KBDMUX_LOCK(state); 1066 1067 /* NOTE: lock key state in ks_state won't be changed */ 1068 if (*((intptr_t *) arg) & ~LOCK_MASK) { 1069 KBDMUX_UNLOCK(state); 1070 1071 return (EINVAL); 1072 } 1073 1074 KBD_LED_VAL(kbd) = *((intptr_t *) arg); 1075 1076 /* KDSETLED on all slave keyboards */ 1077 SLIST_FOREACH(k, &state->ks_kbds, next) 1078 KBDMUX_IOCTL(k->kbd, KDSETLED, arg); 1079 1080 KBDMUX_UNLOCK(state); 1081 break; 1082 1083 case KDGKBSTATE: /* get lock key state */ 1084 KBDMUX_LOCK(state); 1085 *((intptr_t *) arg) = state->ks_state & LOCK_MASK; 1086 KBDMUX_UNLOCK(state); 1087 break; 1088 1089 case KDSKBSTATE: /* set lock key state */ 1090 KBDMUX_LOCK(state); 1091 1092 if (*((intptr_t *) arg) & ~LOCK_MASK) { 1093 KBDMUX_UNLOCK(state); 1094 1095 return (EINVAL); 1096 } 1097 1098 state->ks_state &= ~LOCK_MASK; 1099 state->ks_state |= *((intptr_t *) arg); 1100 1101 /* KDSKBSTATE on all slave keyboards */ 1102 SLIST_FOREACH(k, &state->ks_kbds, next) 1103 KBDMUX_IOCTL(k->kbd, KDSKBSTATE, arg); 1104 1105 KBDMUX_UNLOCK(state); 1106 1107 return (kbdmux_ioctl(kbd, KDSETLED, arg)); 1108 /* NOT REACHED */ 1109 1110 case KDSETREPEAT: /* set keyboard repeat rate (new interface) */ 1111 case KDSETRAD: /* set keyboard repeat rate (old interface) */ 1112 KBDMUX_LOCK(state); 1113 1114 if (cmd == KDSETREPEAT) { 1115 int i; 1116 1117 /* lookup delay */ 1118 for (i = sizeof(delays)/sizeof(delays[0]) - 1; i > 0; i --) 1119 if (((intptr_t *) arg)[0] >= delays[i]) 1120 break; 1121 mode = i << 5; 1122 1123 /* lookup rate */ 1124 for (i = sizeof(rates)/sizeof(rates[0]) - 1; i > 0; i --) 1125 if (((intptr_t *) arg)[1] >= rates[i]) 1126 break; 1127 mode |= i; 1128 } else 1129 mode = *((intptr_t *) arg); 1130 1131 if (mode & ~0x7f) { 1132 KBDMUX_UNLOCK(state); 1133 1134 return (EINVAL); 1135 } 1136 1137 kbd->kb_delay1 = delays[(mode >> 5) & 3]; 1138 kbd->kb_delay2 = rates[mode & 0x1f]; 1139 1140 /* perform command on all slave keyboards */ 1141 SLIST_FOREACH(k, &state->ks_kbds, next) 1142 KBDMUX_IOCTL(k->kbd, cmd, arg); 1143 1144 KBDMUX_UNLOCK(state); 1145 break; 1146 1147 case PIO_KEYMAP: /* set keyboard translation table */ 1148 case PIO_KEYMAPENT: /* set keyboard translation table entry */ 1149 case PIO_DEADKEYMAP: /* set accent key translation table */ 1150 KBDMUX_LOCK(state); 1151 state->ks_accents = 0; 1152 1153 /* perform command on all slave keyboards */ 1154 SLIST_FOREACH(k, &state->ks_kbds, next) 1155 KBDMUX_IOCTL(k->kbd, cmd, arg); 1156 1157 KBDMUX_UNLOCK(state); 1158 /* FALLTHROUGH */ 1159 1160 default: 1161 error = genkbd_commonioctl(kbd, cmd, arg); 1162 break; 1163 } 1164 1165 return (error); 1166 } 1167 1168 /* 1169 * Lock the access to the keyboard 1170 */ 1171 static int 1172 kbdmux_lock(keyboard_t *kbd, int lock) 1173 { 1174 return (1); /* XXX */ 1175 } 1176 1177 /* 1178 * Clear the internal state of the keyboard 1179 */ 1180 static void 1181 kbdmux_clear_state_locked(kbdmux_state_t *state) 1182 { 1183 KBDMUX_LOCK_ASSERT(state, MA_OWNED); 1184 1185 state->ks_flags &= ~(COMPOSE|POLLING); 1186 state->ks_state &= LOCK_MASK; /* preserve locking key state */ 1187 state->ks_accents = 0; 1188 state->ks_composed_char = 0; 1189 /* state->ks_prefix = 0; XXX */ 1190 1191 ndflush(&state->ks_inq, state->ks_inq.c_cc); 1192 } 1193 1194 static void 1195 kbdmux_clear_state(keyboard_t *kbd) 1196 { 1197 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 1198 1199 KBDMUX_LOCK(state); 1200 kbdmux_clear_state_locked(state); 1201 KBDMUX_UNLOCK(state); 1202 } 1203 1204 /* 1205 * Save the internal state 1206 */ 1207 static int 1208 kbdmux_get_state(keyboard_t *kbd, void *buf, size_t len) 1209 { 1210 if (len == 0) 1211 return (sizeof(kbdmux_state_t)); 1212 if (len < sizeof(kbdmux_state_t)) 1213 return (-1); 1214 1215 bcopy(kbd->kb_data, buf, sizeof(kbdmux_state_t)); /* XXX locking? */ 1216 1217 return (0); 1218 } 1219 1220 /* 1221 * Set the internal state 1222 */ 1223 static int 1224 kbdmux_set_state(keyboard_t *kbd, void *buf, size_t len) 1225 { 1226 if (len < sizeof(kbdmux_state_t)) 1227 return (ENOMEM); 1228 1229 bcopy(buf, kbd->kb_data, sizeof(kbdmux_state_t)); /* XXX locking? */ 1230 1231 return (0); 1232 } 1233 1234 /* 1235 * Set polling 1236 */ 1237 static int 1238 kbdmux_poll(keyboard_t *kbd, int on) 1239 { 1240 kbdmux_state_t *state = (kbdmux_state_t *) kbd->kb_data; 1241 kbdmux_kbd_t *k; 1242 1243 KBDMUX_LOCK(state); 1244 1245 if (on) 1246 state->ks_flags |= POLLING; 1247 else 1248 state->ks_flags &= ~POLLING; 1249 1250 /* set poll on slave keyboards */ 1251 SLIST_FOREACH(k, &state->ks_kbds, next) 1252 KBDMUX_POLL(k->kbd, on); 1253 1254 KBDMUX_UNLOCK(state); 1255 1256 return (0); 1257 } 1258 1259 /***************************************************************************** 1260 ***************************************************************************** 1261 ** Module 1262 ***************************************************************************** 1263 *****************************************************************************/ 1264 1265 KEYBOARD_DRIVER(kbdmux, kbdmuxsw, kbdmux_configure); 1266 1267 static int 1268 kbdmux_modevent(module_t mod, int type, void *data) 1269 { 1270 keyboard_switch_t *sw; 1271 keyboard_t *kbd; 1272 int error; 1273 1274 switch (type) { 1275 case MOD_LOAD: 1276 if ((error = kbd_add_driver(&kbdmux_kbd_driver)) != 0) 1277 break; 1278 1279 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) { 1280 kbd_delete_driver(&kbdmux_kbd_driver); 1281 error = ENXIO; 1282 break; 1283 } 1284 1285 kbd = NULL; 1286 1287 if ((error = (*sw->probe)(0, NULL, 0)) != 0 || 1288 (error = (*sw->init)(0, &kbd, NULL, 0)) != 0) { 1289 kbd_delete_driver(&kbdmux_kbd_driver); 1290 break; 1291 } 1292 1293 #ifdef KBD_INSTALL_CDEV 1294 if ((error = kbd_attach(kbd)) != 0) { 1295 (*sw->term)(kbd); 1296 kbd_delete_driver(&kbdmux_kbd_driver); 1297 break; 1298 } 1299 #endif 1300 1301 if ((error = (*sw->enable)(kbd)) != 0) { 1302 (*sw->disable)(kbd); 1303 #ifdef KBD_INSTALL_CDEV 1304 kbd_detach(kbd); 1305 #endif 1306 (*sw->term)(kbd); 1307 kbd_delete_driver(&kbdmux_kbd_driver); 1308 break; 1309 } 1310 break; 1311 1312 case MOD_UNLOAD: 1313 if ((sw = kbd_get_switch(KEYBOARD_NAME)) == NULL) 1314 panic("kbd_get_switch(" KEYBOARD_NAME ") == NULL"); 1315 1316 kbd = kbd_get_keyboard(kbd_find_keyboard(KEYBOARD_NAME, 0)); 1317 if (kbd == NULL) 1318 panic("kbd_get_keyboard(kbd_find_keyboard(" KEYBOARD_NAME ", 0)) == NULL"); 1319 1320 (*sw->disable)(kbd); 1321 #ifdef KBD_INSTALL_CDEV 1322 kbd_detach(kbd); 1323 #endif 1324 (*sw->term)(kbd); 1325 kbd_delete_driver(&kbdmux_kbd_driver); 1326 error = 0; 1327 break; 1328 1329 default: 1330 error = EOPNOTSUPP; 1331 break; 1332 } 1333 1334 return (0); 1335 } 1336 1337 DEV_MODULE(kbdmux, kbdmux_modevent, NULL); 1338 1339