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