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