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