1 /*- 2 * (MPSAFE) 3 * 4 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer as 12 * the first lines of this file unmodified. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD: src/sys/dev/kbd/kbd.c,v 1.17.2.2 2001/07/30 16:46:43 yokota Exp $ 29 */ 30 /* 31 * Generic keyboard driver. 32 * 33 * Interrupt note: keyboards use clist functions and since usb keyboard 34 * interrupts are not protected by spltty(), we must use a critical section 35 * to protect against corruption. 36 * XXX: this keyboard driver doesn't use clist functions anymore! 37 * 38 * MPSAFE NOTE: all keyboards could easily be put under a different global token. 39 */ 40 41 #include "opt_kbd.h" 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kernel.h> 46 #include <sys/malloc.h> 47 #include <sys/conf.h> 48 #include <sys/proc.h> 49 #include <sys/tty.h> 50 #include <sys/event.h> 51 #include <sys/vnode.h> 52 #include <sys/uio.h> 53 #include <sys/thread.h> 54 #include <sys/thread2.h> 55 56 #include <machine/console.h> 57 58 #include "kbdreg.h" 59 60 #if 0 61 #define lwkt_gettoken(x) 62 #define lwkt_reltoken(x) 63 #endif 64 65 #define KBD_INDEX(dev) minor(dev) 66 67 #define KB_QSIZE 512 68 #define KB_BUFSIZE 64 69 70 struct genkbd_softc { 71 int gkb_flags; /* flag/status bits */ 72 #define KB_ASLEEP (1 << 0) 73 struct kqinfo gkb_rkq; 74 char gkb_q[KB_QSIZE]; /* input queue */ 75 unsigned int gkb_q_start; 76 unsigned int gkb_q_length; 77 }; 78 79 typedef struct genkbd_softc *genkbd_softc_t; 80 81 static SLIST_HEAD(, keyboard_driver) keyboard_drivers = 82 SLIST_HEAD_INITIALIZER(keyboard_drivers); 83 84 SET_DECLARE(kbddriver_set, const keyboard_driver_t); 85 86 /* local arrays */ 87 88 /* 89 * We need at least one entry each in order to initialize a keyboard 90 * for the kernel console. The arrays will be increased dynamically 91 * when necessary. 92 */ 93 94 static int keyboards = 1; 95 static keyboard_t *kbd_ini; 96 static keyboard_t **keyboard = &kbd_ini; 97 static keyboard_switch_t *kbdsw_ini; 98 keyboard_switch_t **kbdsw = &kbdsw_ini; 99 100 #define ARRAY_DELTA 4 101 102 static int 103 kbd_realloc_array(void) 104 { 105 keyboard_t **new_kbd; 106 keyboard_switch_t **new_kbdsw; 107 int newsize; 108 109 lwkt_gettoken(&tty_token); 110 newsize = ((keyboards + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA; 111 new_kbd = kmalloc(sizeof(*new_kbd) * newsize, M_DEVBUF, 112 M_WAITOK | M_ZERO); 113 new_kbdsw = kmalloc(sizeof(*new_kbdsw) * newsize, M_DEVBUF, 114 M_WAITOK | M_ZERO); 115 bcopy(keyboard, new_kbd, sizeof(*keyboard)*keyboards); 116 bcopy(kbdsw, new_kbdsw, sizeof(*kbdsw)*keyboards); 117 crit_enter(); 118 if (keyboards > 1) { 119 kfree(keyboard, M_DEVBUF); 120 kfree(kbdsw, M_DEVBUF); 121 } 122 keyboard = new_kbd; 123 kbdsw = new_kbdsw; 124 keyboards = newsize; 125 crit_exit(); 126 127 if (bootverbose) 128 kprintf("kbd: new array size %d\n", keyboards); 129 130 lwkt_reltoken(&tty_token); 131 return 0; 132 } 133 134 /* 135 * Low-level keyboard driver functions. 136 * 137 * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard 138 * driver, call these functions to initialize the keyboard_t structure 139 * and register it to the virtual keyboard driver `kbd'. 140 * 141 * The reinit call is made when a driver has partially detached a keyboard 142 * but does not unregistered it, then wishes to reinitialize it later on. 143 * This is how the USB keyboard driver handles the 'default' keyboard, 144 * because unregistering the keyboard associated with the console will 145 * destroy its console association forever. 146 */ 147 void 148 kbd_reinit_struct(keyboard_t *kbd, int config, int pref) 149 { 150 lwkt_gettoken(&tty_token); 151 kbd->kb_flags |= KB_NO_DEVICE; /* device has not been found */ 152 kbd->kb_config = config & ~KB_CONF_PROBE_ONLY; 153 kbd->kb_led = 0; /* unknown */ 154 kbd->kb_data = NULL; 155 kbd->kb_keymap = NULL; 156 kbd->kb_accentmap = NULL; 157 kbd->kb_fkeytab = NULL; 158 kbd->kb_fkeytab_size = 0; 159 kbd->kb_delay1 = KB_DELAY1; /* these values are advisory only */ 160 kbd->kb_delay2 = KB_DELAY2; 161 kbd->kb_count = 0; 162 kbd->kb_pref = pref; 163 bzero(kbd->kb_lastact, sizeof(kbd->kb_lastact)); 164 lwkt_reltoken(&tty_token); 165 } 166 167 /* initialize the keyboard_t structure */ 168 void 169 kbd_init_struct(keyboard_t *kbd, char *name, int type, int unit, int config, 170 int pref, int port, int port_size) 171 { 172 lwkt_gettoken(&tty_token); 173 kbd->kb_flags = 0; 174 kbd->kb_name = name; 175 kbd->kb_type = type; 176 kbd->kb_unit = unit; 177 kbd->kb_io_base = port; 178 kbd->kb_io_size = port_size; 179 kbd_reinit_struct(kbd, config, pref); 180 lockinit(&kbd->kb_lock, name, 0, LK_CANRECURSE); 181 lwkt_reltoken(&tty_token); 182 } 183 184 void 185 kbd_set_maps(keyboard_t *kbd, keymap_t *keymap, accentmap_t *accmap, 186 fkeytab_t *fkeymap, int fkeymap_size) 187 { 188 lwkt_gettoken(&tty_token); 189 kbd->kb_keymap = keymap; 190 kbd->kb_accentmap = accmap; 191 kbd->kb_fkeytab = fkeymap; 192 kbd->kb_fkeytab_size = fkeymap_size; 193 lwkt_reltoken(&tty_token); 194 } 195 196 /* declare a new keyboard driver */ 197 int 198 kbd_add_driver(keyboard_driver_t *driver) 199 { 200 lwkt_gettoken(&tty_token); 201 if (SLIST_NEXT(driver, link)) { 202 lwkt_reltoken(&tty_token); 203 return EINVAL; 204 } 205 SLIST_INSERT_HEAD(&keyboard_drivers, driver, link); 206 lwkt_reltoken(&tty_token); 207 return 0; 208 } 209 210 int 211 kbd_delete_driver(keyboard_driver_t *driver) 212 { 213 lwkt_gettoken(&tty_token); 214 SLIST_REMOVE(&keyboard_drivers, driver, keyboard_driver, link); 215 SLIST_NEXT(driver, link) = NULL; 216 lwkt_reltoken(&tty_token); 217 return 0; 218 } 219 220 /* register a keyboard and associate it with a function table */ 221 int 222 kbd_register(keyboard_t *kbd) 223 { 224 const keyboard_driver_t **list; 225 const keyboard_driver_t *p; 226 keyboard_t *mux; 227 keyboard_info_t ki; 228 int index; 229 230 lwkt_gettoken(&tty_token); 231 mux = kbd_get_keyboard(kbd_find_keyboard("kbdmux", -1)); 232 233 for (index = 0; index < keyboards; ++index) { 234 if (keyboard[index] == NULL) 235 break; 236 } 237 if (index >= keyboards) { 238 if (kbd_realloc_array()) { 239 lwkt_reltoken(&tty_token); 240 return -1; 241 } 242 } 243 244 kbd->kb_index = index; 245 KBD_UNBUSY(kbd); 246 KBD_VALID(kbd); 247 kbd->kb_active = 0; /* disabled until someone calls kbd_enable() */ 248 kbd->kb_token = NULL; 249 kbd->kb_callback.kc_func = NULL; 250 kbd->kb_callback.kc_arg = NULL; 251 callout_init_mp(&kbd->kb_atkbd_timeout_ch); 252 253 SLIST_FOREACH(p, &keyboard_drivers, link) { 254 if (strcmp(p->name, kbd->kb_name) == 0) { 255 keyboard[index] = kbd; 256 kbdsw[index] = p->kbdsw; 257 258 if (mux != NULL) { 259 bzero(&ki, sizeof(ki)); 260 strcpy(ki.kb_name, kbd->kb_name); 261 ki.kb_unit = kbd->kb_unit; 262 kbd_ioctl(mux, KBADDKBD, (caddr_t) &ki); 263 } 264 265 lwkt_reltoken(&tty_token); 266 return index; 267 } 268 } 269 SET_FOREACH(list, kbddriver_set) { 270 p = *list; 271 if (strcmp(p->name, kbd->kb_name) == 0) { 272 keyboard[index] = kbd; 273 kbdsw[index] = p->kbdsw; 274 275 if (mux != NULL) { 276 bzero(&ki, sizeof(ki)); 277 strcpy(ki.kb_name, kbd->kb_name); 278 ki.kb_unit = kbd->kb_unit; 279 kbd_ioctl(mux, KBADDKBD, (caddr_t) &ki); 280 } 281 282 lwkt_reltoken(&tty_token); 283 return index; 284 } 285 } 286 287 lwkt_reltoken(&tty_token); 288 return -1; 289 } 290 291 int 292 kbd_unregister(keyboard_t *kbd) 293 { 294 int error; 295 296 lwkt_gettoken(&tty_token); 297 if ((kbd->kb_index < 0) || (kbd->kb_index >= keyboards)) { 298 lwkt_reltoken(&tty_token); 299 return ENOENT; 300 } 301 if (keyboard[kbd->kb_index] != kbd) { 302 lwkt_reltoken(&tty_token); 303 return ENOENT; 304 } 305 306 crit_enter(); 307 callout_stop(&kbd->kb_atkbd_timeout_ch); 308 if (KBD_IS_BUSY(kbd)) { 309 error = (*kbd->kb_callback.kc_func)(kbd, KBDIO_UNLOADING, 310 kbd->kb_callback.kc_arg); 311 if (error) { 312 crit_exit(); 313 lwkt_reltoken(&tty_token); 314 return error; 315 } 316 if (KBD_IS_BUSY(kbd)) { 317 crit_exit(); 318 lwkt_reltoken(&tty_token); 319 return EBUSY; 320 } 321 } 322 KBD_CONFIG_LOST(kbd); 323 KBD_INVALID(kbd); 324 keyboard[kbd->kb_index] = NULL; 325 kbdsw[kbd->kb_index] = NULL; 326 327 KBD_ALWAYS_UNLOCK(kbd); 328 lockuninit(&kbd->kb_lock); 329 330 crit_exit(); 331 lwkt_reltoken(&tty_token); 332 return 0; 333 } 334 335 /* find a funciton table by the driver name */ 336 keyboard_switch_t * 337 kbd_get_switch(char *driver) 338 { 339 const keyboard_driver_t **list; 340 const keyboard_driver_t *p; 341 342 lwkt_gettoken(&tty_token); 343 344 SLIST_FOREACH(p, &keyboard_drivers, link) { 345 if (strcmp(p->name, driver) == 0) { 346 lwkt_reltoken(&tty_token); 347 return p->kbdsw; 348 } 349 } 350 SET_FOREACH(list, kbddriver_set) { 351 p = *list; 352 if (strcmp(p->name, driver) == 0) { 353 lwkt_reltoken(&tty_token); 354 return p->kbdsw; 355 } 356 } 357 358 lwkt_reltoken(&tty_token); 359 return NULL; 360 } 361 362 /* 363 * Keyboard client functions 364 * Keyboard clients, such as the console driver `syscons' and the keyboard 365 * cdev driver, use these functions to claim and release a keyboard for 366 * exclusive use. 367 */ 368 /* 369 * find the keyboard specified by a driver name and a unit number 370 * starting at given index 371 */ 372 int 373 kbd_find_keyboard2(char *driver, int unit, int index, int legacy) 374 { 375 int i; 376 int pref; 377 int pref_index; 378 379 pref = 0; 380 pref_index = -1; 381 382 lwkt_gettoken(&tty_token); 383 if ((index < 0) || (index >= keyboards)) { 384 lwkt_reltoken(&tty_token); 385 return (-1); 386 } 387 388 for (i = index; i < keyboards; ++i) { 389 if (keyboard[i] == NULL) 390 continue; 391 if (!KBD_IS_VALID(keyboard[i])) 392 continue; 393 if (strcmp("*", driver) && strcmp(keyboard[i]->kb_name, driver)) 394 continue; 395 if ((unit != -1) && (keyboard[i]->kb_unit != unit)) 396 continue; 397 /* 398 * If we are in legacy mode, we do the old preference magic and 399 * don't return on the first found unit. 400 */ 401 if (legacy) { 402 if (pref <= keyboard[i]->kb_pref) { 403 pref = keyboard[i]->kb_pref; 404 pref_index = i; 405 } 406 } else { 407 lwkt_reltoken(&tty_token); 408 return i; 409 } 410 } 411 412 if (!legacy) 413 KKASSERT(pref_index == -1); 414 415 lwkt_reltoken(&tty_token); 416 return (pref_index); 417 } 418 419 /* find the keyboard specified by a driver name and a unit number */ 420 int 421 kbd_find_keyboard(char *driver, int unit) 422 { 423 return (kbd_find_keyboard2(driver, unit, 0, 1)); 424 } 425 426 /* allocate a keyboard */ 427 int 428 kbd_allocate(char *driver, int unit, void *id, kbd_callback_func_t *func, 429 void *arg) 430 { 431 int index; 432 433 if (func == NULL) 434 return -1; 435 436 crit_enter(); 437 lwkt_gettoken(&tty_token); 438 439 index = kbd_find_keyboard(driver, unit); 440 if (index >= 0) { 441 if (KBD_IS_BUSY(keyboard[index])) { 442 crit_exit(); 443 lwkt_reltoken(&tty_token); 444 return -1; 445 } 446 keyboard[index]->kb_token = id; 447 KBD_BUSY(keyboard[index]); 448 keyboard[index]->kb_callback.kc_func = func; 449 keyboard[index]->kb_callback.kc_arg = arg; 450 kbd_clear_state(keyboard[index]); 451 } 452 453 lwkt_reltoken(&tty_token); 454 crit_exit(); 455 return index; 456 } 457 458 int 459 kbd_release(keyboard_t *kbd, void *id) 460 { 461 int error; 462 463 crit_enter(); 464 lwkt_gettoken(&tty_token); 465 466 if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) { 467 error = EINVAL; 468 } else if (kbd->kb_token != id) { 469 error = EPERM; 470 } else { 471 kbd->kb_token = NULL; 472 KBD_UNBUSY(kbd); 473 kbd->kb_callback.kc_func = NULL; 474 kbd->kb_callback.kc_arg = NULL; 475 kbd_clear_state(kbd); 476 error = 0; 477 } 478 479 lwkt_reltoken(&tty_token); 480 crit_exit(); 481 return error; 482 } 483 484 int 485 kbd_change_callback(keyboard_t *kbd, void *id, kbd_callback_func_t *func, 486 void *arg) 487 { 488 int error; 489 490 crit_enter(); 491 lwkt_gettoken(&tty_token); 492 493 if (!KBD_IS_VALID(kbd) || !KBD_IS_BUSY(kbd)) { 494 error = EINVAL; 495 } else if (kbd->kb_token != id) { 496 error = EPERM; 497 } else if (func == NULL) { 498 error = EINVAL; 499 } else { 500 kbd->kb_callback.kc_func = func; 501 kbd->kb_callback.kc_arg = arg; 502 error = 0; 503 } 504 505 lwkt_reltoken(&tty_token); 506 crit_exit(); 507 return error; 508 } 509 510 /* get a keyboard structure */ 511 keyboard_t * 512 kbd_get_keyboard(int index) 513 { 514 keyboard_t *kbd; 515 516 lwkt_gettoken(&tty_token); 517 if ((index < 0) || (index >= keyboards)) { 518 lwkt_reltoken(&tty_token); 519 return NULL; 520 } 521 if (keyboard[index] == NULL) { 522 lwkt_reltoken(&tty_token); 523 return NULL; 524 } 525 if (!KBD_IS_VALID(keyboard[index])) { 526 lwkt_reltoken(&tty_token); 527 return NULL; 528 } 529 kbd = keyboard[index]; 530 lwkt_reltoken(&tty_token); 531 532 return kbd; 533 } 534 535 /* 536 * The back door for the console driver; configure keyboards 537 * This function is for the kernel console to initialize keyboards 538 * at very early stage. 539 */ 540 541 int 542 kbd_configure(int flags) 543 { 544 const keyboard_driver_t **list; 545 const keyboard_driver_t *p; 546 547 lwkt_gettoken(&tty_token); 548 549 SLIST_FOREACH(p, &keyboard_drivers, link) { 550 if (p->configure != NULL) 551 (*p->configure)(flags); 552 } 553 SET_FOREACH(list, kbddriver_set) { 554 p = *list; 555 if (p->configure != NULL) 556 (*p->configure)(flags); 557 } 558 559 lwkt_reltoken(&tty_token); 560 return 0; 561 } 562 563 #ifdef KBD_INSTALL_CDEV 564 565 /* 566 * Virtual keyboard cdev driver functions 567 * The virtual keyboard driver dispatches driver functions to 568 * appropriate subdrivers. 569 */ 570 571 #define KBD_UNIT(dev) minor(dev) 572 573 static d_open_t genkbdopen; 574 static d_close_t genkbdclose; 575 static d_read_t genkbdread; 576 static d_write_t genkbdwrite; 577 static d_ioctl_t genkbdioctl; 578 static d_kqfilter_t genkbdkqfilter; 579 580 static void genkbdfiltdetach(struct knote *); 581 static int genkbdfilter(struct knote *, long); 582 583 static struct dev_ops kbd_ops = { 584 { "kbd", 0, 0 }, 585 .d_open = genkbdopen, 586 .d_close = genkbdclose, 587 .d_read = genkbdread, 588 .d_write = genkbdwrite, 589 .d_ioctl = genkbdioctl, 590 .d_kqfilter = genkbdkqfilter 591 }; 592 593 /* 594 * Attach a keyboard. 595 * 596 * NOTE: The usb driver does not detach the default keyboard if it is 597 * unplugged, but calls kbd_attach() when it is plugged back in. 598 */ 599 int 600 kbd_attach(keyboard_t *kbd) 601 { 602 cdev_t dev; 603 604 lwkt_gettoken(&tty_token); 605 if (kbd->kb_index >= keyboards) { 606 lwkt_reltoken(&tty_token); 607 return EINVAL; 608 } 609 if (keyboard[kbd->kb_index] != kbd) { 610 lwkt_reltoken(&tty_token); 611 return EINVAL; 612 } 613 614 if (kbd->kb_dev == NULL) { 615 kbd->kb_dev = make_dev(&kbd_ops, kbd->kb_index, 616 UID_ROOT, GID_WHEEL, 0600, 617 "kbd%r", kbd->kb_index); 618 } 619 dev = kbd->kb_dev; 620 if (dev->si_drv1 == NULL) { 621 dev->si_drv1 = kmalloc(sizeof(struct genkbd_softc), M_DEVBUF, 622 M_WAITOK); 623 } 624 bzero(dev->si_drv1, sizeof(struct genkbd_softc)); 625 626 kprintf("kbd%d at %s%d\n", kbd->kb_index, kbd->kb_name, kbd->kb_unit); 627 lwkt_reltoken(&tty_token); 628 return 0; 629 } 630 631 int 632 kbd_detach(keyboard_t *kbd) 633 { 634 cdev_t dev; 635 636 lwkt_gettoken(&tty_token); 637 638 if (kbd->kb_index >= keyboards) { 639 lwkt_reltoken(&tty_token); 640 return EINVAL; 641 } 642 if (keyboard[kbd->kb_index] != kbd) { 643 lwkt_reltoken(&tty_token); 644 return EINVAL; 645 } 646 647 if ((dev = kbd->kb_dev) != NULL) { 648 if (dev->si_drv1) { 649 kfree(dev->si_drv1, M_DEVBUF); 650 dev->si_drv1 = NULL; 651 } 652 kbd->kb_dev = NULL; 653 } 654 dev_ops_remove_minor(&kbd_ops, kbd->kb_index); 655 lwkt_reltoken(&tty_token); 656 return 0; 657 } 658 659 /* 660 * Generic keyboard cdev driver functions 661 * Keyboard subdrivers may call these functions to implement common 662 * driver functions. 663 */ 664 665 static void 666 genkbd_putc(genkbd_softc_t sc, char c) 667 { 668 unsigned int p; 669 670 lwkt_gettoken(&tty_token); 671 672 if (sc->gkb_q_length == KB_QSIZE) { 673 lwkt_reltoken(&tty_token); 674 return; 675 } 676 677 p = (sc->gkb_q_start + sc->gkb_q_length) % KB_QSIZE; 678 sc->gkb_q[p] = c; 679 sc->gkb_q_length++; 680 681 lwkt_reltoken(&tty_token); 682 } 683 684 static size_t 685 genkbd_getc(genkbd_softc_t sc, char *buf, size_t len) 686 { 687 688 lwkt_gettoken(&tty_token); 689 690 /* Determine copy size. */ 691 if (sc->gkb_q_length == 0) { 692 lwkt_reltoken(&tty_token); 693 return (0); 694 } 695 if (len >= sc->gkb_q_length) 696 len = sc->gkb_q_length; 697 if (len >= KB_QSIZE - sc->gkb_q_start) 698 len = KB_QSIZE - sc->gkb_q_start; 699 700 /* Copy out data and progress offset. */ 701 memcpy(buf, sc->gkb_q + sc->gkb_q_start, len); 702 sc->gkb_q_start = (sc->gkb_q_start + len) % KB_QSIZE; 703 sc->gkb_q_length -= len; 704 705 lwkt_reltoken(&tty_token); 706 return (len); 707 } 708 709 static kbd_callback_func_t genkbd_event; 710 711 static int 712 genkbdopen(struct dev_open_args *ap) 713 { 714 cdev_t dev = ap->a_head.a_dev; 715 keyboard_t *kbd; 716 genkbd_softc_t sc; 717 int i; 718 719 crit_enter(); 720 lwkt_gettoken(&tty_token); 721 sc = dev->si_drv1; 722 kbd = kbd_get_keyboard(KBD_INDEX(dev)); 723 if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 724 lwkt_reltoken(&tty_token); 725 crit_exit(); 726 return ENXIO; 727 } 728 i = kbd_allocate(kbd->kb_name, kbd->kb_unit, sc, 729 genkbd_event, (void *)sc); 730 if (i < 0) { 731 lwkt_reltoken(&tty_token); 732 crit_exit(); 733 return EBUSY; 734 } 735 /* assert(i == kbd->kb_index) */ 736 /* assert(kbd == kbd_get_keyboard(i)) */ 737 738 /* 739 * NOTE: even when we have successfully claimed a keyboard, 740 * the device may still be missing (!KBD_HAS_DEVICE(kbd)). 741 */ 742 743 sc->gkb_q_length = 0; 744 lwkt_reltoken(&tty_token); 745 crit_exit(); 746 747 return 0; 748 } 749 750 static int 751 genkbdclose(struct dev_close_args *ap) 752 { 753 cdev_t dev = ap->a_head.a_dev; 754 keyboard_t *kbd; 755 genkbd_softc_t sc; 756 757 /* 758 * NOTE: the device may have already become invalid. 759 * kbd == NULL || !KBD_IS_VALID(kbd) 760 */ 761 crit_enter(); 762 lwkt_gettoken(&tty_token); 763 sc = dev->si_drv1; 764 kbd = kbd_get_keyboard(KBD_INDEX(dev)); 765 if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 766 /* XXX: we shall be forgiving and don't report error... */ 767 } else { 768 kbd_release(kbd, (void *)sc); 769 } 770 lwkt_reltoken(&tty_token); 771 crit_exit(); 772 return 0; 773 } 774 775 static int 776 genkbdread(struct dev_read_args *ap) 777 { 778 cdev_t dev = ap->a_head.a_dev; 779 struct uio *uio = ap->a_uio; 780 keyboard_t *kbd; 781 genkbd_softc_t sc; 782 u_char buffer[KB_BUFSIZE]; 783 int len; 784 int error; 785 786 /* wait for input */ 787 crit_enter(); 788 lwkt_gettoken(&tty_token); 789 sc = dev->si_drv1; 790 kbd = kbd_get_keyboard(KBD_INDEX(dev)); 791 if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 792 lwkt_reltoken(&tty_token); 793 crit_exit(); 794 return ENXIO; 795 } 796 while (sc->gkb_q_length == 0) { 797 if (ap->a_ioflag & IO_NDELAY) { /* O_NONBLOCK? */ 798 lwkt_reltoken(&tty_token); 799 crit_exit(); 800 return EWOULDBLOCK; 801 } 802 sc->gkb_flags |= KB_ASLEEP; 803 error = tsleep((caddr_t)sc, PCATCH, "kbdrea", 0); 804 kbd = kbd_get_keyboard(KBD_INDEX(dev)); 805 if ((kbd == NULL) || !KBD_IS_VALID(kbd)) { 806 lwkt_reltoken(&tty_token); 807 crit_exit(); 808 return ENXIO; /* our keyboard has gone... */ 809 } 810 if (error) { 811 sc->gkb_flags &= ~KB_ASLEEP; 812 lwkt_reltoken(&tty_token); 813 crit_exit(); 814 return error; 815 } 816 } 817 lwkt_reltoken(&tty_token); 818 crit_exit(); 819 820 /* copy as much input as possible */ 821 error = 0; 822 while (uio->uio_resid > 0) { 823 len = (int)szmin(uio->uio_resid, sizeof(buffer)); 824 len = genkbd_getc(sc, buffer, len); 825 if (len <= 0) 826 break; 827 error = uiomove(buffer, (size_t)len, uio); 828 if (error) 829 break; 830 } 831 832 return error; 833 } 834 835 static int 836 genkbdwrite(struct dev_write_args *ap) 837 { 838 cdev_t dev = ap->a_head.a_dev; 839 keyboard_t *kbd; 840 841 lwkt_gettoken(&tty_token); 842 kbd = kbd_get_keyboard(KBD_INDEX(dev)); 843 if ((kbd == NULL) || !KBD_IS_VALID(kbd)) { 844 lwkt_reltoken(&tty_token); 845 return ENXIO; 846 } 847 lwkt_reltoken(&tty_token); 848 return ENODEV; 849 } 850 851 static int 852 genkbdioctl(struct dev_ioctl_args *ap) 853 { 854 cdev_t dev = ap->a_head.a_dev; 855 keyboard_t *kbd; 856 int error; 857 858 lwkt_gettoken(&tty_token); 859 kbd = kbd_get_keyboard(KBD_INDEX(dev)); 860 if ((kbd == NULL) || !KBD_IS_VALID(kbd)) { 861 lwkt_reltoken(&tty_token); 862 return ENXIO; 863 } 864 error = kbd_ioctl(kbd, ap->a_cmd, ap->a_data); 865 if (error == ENOIOCTL) 866 error = ENODEV; 867 868 lwkt_reltoken(&tty_token); 869 return error; 870 } 871 872 static struct filterops genkbdfiltops = 873 { FILTEROP_ISFD, NULL, genkbdfiltdetach, genkbdfilter }; 874 875 static int 876 genkbdkqfilter(struct dev_kqfilter_args *ap) 877 { 878 cdev_t dev = ap->a_head.a_dev; 879 struct knote *kn = ap->a_kn; 880 genkbd_softc_t sc; 881 struct klist *klist; 882 883 ap->a_result = 0; 884 885 switch (kn->kn_filter) { 886 case EVFILT_READ: 887 kn->kn_fop = &genkbdfiltops; 888 kn->kn_hook = (caddr_t)dev; 889 break; 890 default: 891 ap->a_result = EOPNOTSUPP; 892 return (0); 893 } 894 895 sc = dev->si_drv1; 896 klist = &sc->gkb_rkq.ki_note; 897 knote_insert(klist, kn); 898 899 return (0); 900 } 901 902 static void 903 genkbdfiltdetach(struct knote *kn) 904 { 905 cdev_t dev = (cdev_t)kn->kn_hook; 906 genkbd_softc_t sc; 907 struct klist *klist; 908 909 sc = dev->si_drv1; 910 klist = &sc->gkb_rkq.ki_note; 911 knote_remove(klist, kn); 912 } 913 914 static int 915 genkbdfilter(struct knote *kn, long hint) 916 { 917 cdev_t dev = (cdev_t)kn->kn_hook; 918 keyboard_t *kbd; 919 genkbd_softc_t sc; 920 int ready = 0; 921 922 crit_enter(); 923 lwkt_gettoken(&tty_token); 924 sc = dev->si_drv1; 925 kbd = kbd_get_keyboard(KBD_INDEX(dev)); 926 if ((sc == NULL) || (kbd == NULL) || !KBD_IS_VALID(kbd)) { 927 kn->kn_flags |= EV_EOF; /* the keyboard has gone */ 928 ready = 1; 929 } else { 930 if (sc->gkb_q_length > 0) 931 ready = 1; 932 } 933 lwkt_reltoken(&tty_token); 934 crit_exit(); 935 936 return (ready); 937 } 938 939 static int 940 genkbd_event(keyboard_t *kbd, int event, void *arg) 941 { 942 genkbd_softc_t sc; 943 size_t len; 944 u_char *cp; 945 int mode; 946 int c; 947 948 lwkt_gettoken(&tty_token); 949 /* assert(KBD_IS_VALID(kbd)) */ 950 sc = (genkbd_softc_t)arg; 951 952 switch (event) { 953 case KBDIO_KEYINPUT: 954 break; 955 case KBDIO_UNLOADING: 956 /* the keyboard is going... */ 957 kbd_release(kbd, (void *)sc); 958 if (sc->gkb_flags & KB_ASLEEP) { 959 sc->gkb_flags &= ~KB_ASLEEP; 960 wakeup((caddr_t)sc); 961 } 962 KNOTE(&sc->gkb_rkq.ki_note, 0); 963 lwkt_reltoken(&tty_token); 964 return 0; 965 default: 966 lwkt_reltoken(&tty_token); 967 return EINVAL; 968 } 969 970 /* obtain the current key input mode */ 971 if (kbd_ioctl(kbd, KDGKBMODE, (caddr_t)&mode)) 972 mode = K_XLATE; 973 974 /* read all pending input */ 975 while (kbd_check_char(kbd)) { 976 c = kbd_read_char(kbd, FALSE); 977 if (c == NOKEY) 978 continue; 979 if (c == ERRKEY) /* XXX: ring bell? */ 980 continue; 981 if (!KBD_IS_BUSY(kbd)) 982 /* the device is not open, discard the input */ 983 continue; 984 985 /* store the byte as is for K_RAW and K_CODE modes */ 986 if (mode != K_XLATE) { 987 genkbd_putc(sc, KEYCHAR(c)); 988 continue; 989 } 990 991 /* K_XLATE */ 992 if (c & RELKEY) /* key release is ignored */ 993 continue; 994 995 /* process special keys; most of them are just ignored... */ 996 if (c & SPCLKEY) { 997 switch (KEYCHAR(c)) { 998 default: 999 /* ignore them... */ 1000 continue; 1001 case BTAB: /* a backtab: ESC [ Z */ 1002 genkbd_putc(sc, 0x1b); 1003 genkbd_putc(sc, '['); 1004 genkbd_putc(sc, 'Z'); 1005 continue; 1006 } 1007 } 1008 1009 /* normal chars, normal chars with the META, function keys */ 1010 switch (KEYFLAGS(c)) { 1011 case 0: /* a normal char */ 1012 genkbd_putc(sc, KEYCHAR(c)); 1013 break; 1014 case MKEY: /* the META flag: prepend ESC */ 1015 genkbd_putc(sc, 0x1b); 1016 genkbd_putc(sc, KEYCHAR(c)); 1017 break; 1018 case FKEY | SPCLKEY: /* a function key, return string */ 1019 cp = kbd_get_fkeystr(kbd, KEYCHAR(c), &len); 1020 if (cp != NULL) { 1021 while (len-- > 0) 1022 genkbd_putc(sc, *cp++); 1023 } 1024 break; 1025 } 1026 } 1027 1028 /* wake up sleeping/polling processes */ 1029 if (sc->gkb_q_length > 0) { 1030 if (sc->gkb_flags & KB_ASLEEP) { 1031 sc->gkb_flags &= ~KB_ASLEEP; 1032 wakeup((caddr_t)sc); 1033 } 1034 KNOTE(&sc->gkb_rkq.ki_note, 0); 1035 } 1036 1037 lwkt_reltoken(&tty_token); 1038 return 0; 1039 } 1040 1041 #endif /* KBD_INSTALL_CDEV */ 1042 1043 /* 1044 * Generic low-level keyboard functions 1045 * The low-level functions in the keyboard subdriver may use these 1046 * functions. 1047 */ 1048 1049 int 1050 genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 1051 { 1052 keyarg_t *keyp; 1053 fkeyarg_t *fkeyp; 1054 int i; 1055 1056 crit_enter(); 1057 lwkt_gettoken(&tty_token); 1058 switch (cmd) { 1059 1060 case KDGKBINFO: /* get keyboard information */ 1061 ((keyboard_info_t *)arg)->kb_index = kbd->kb_index; 1062 i = imin(strlen(kbd->kb_name) + 1, 1063 sizeof(((keyboard_info_t *)arg)->kb_name)); 1064 bcopy(kbd->kb_name, ((keyboard_info_t *)arg)->kb_name, i); 1065 ((keyboard_info_t *)arg)->kb_unit = kbd->kb_unit; 1066 ((keyboard_info_t *)arg)->kb_type = kbd->kb_type; 1067 ((keyboard_info_t *)arg)->kb_config = kbd->kb_config; 1068 ((keyboard_info_t *)arg)->kb_flags = kbd->kb_flags; 1069 break; 1070 1071 case KDGKBTYPE: /* get keyboard type */ 1072 *(int *)arg = kbd->kb_type; 1073 break; 1074 1075 case KDGETREPEAT: /* get keyboard repeat rate */ 1076 ((int *)arg)[0] = kbd->kb_delay1; 1077 ((int *)arg)[1] = kbd->kb_delay2; 1078 break; 1079 1080 case GIO_KEYMAP: /* get keyboard translation table */ 1081 bcopy(kbd->kb_keymap, arg, sizeof(*kbd->kb_keymap)); 1082 break; 1083 case PIO_KEYMAP: /* set keyboard translation table */ 1084 #ifndef KBD_DISABLE_KEYMAP_LOAD 1085 bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); 1086 bcopy(arg, kbd->kb_keymap, sizeof(*kbd->kb_keymap)); 1087 break; 1088 #else 1089 lwkt_reltoken(&tty_token); 1090 crit_exit(); 1091 return ENODEV; 1092 #endif 1093 1094 case GIO_KEYMAPENT: /* get keyboard translation table entry */ 1095 keyp = (keyarg_t *)arg; 1096 if (keyp->keynum >= sizeof(kbd->kb_keymap->key) 1097 /sizeof(kbd->kb_keymap->key[0])) { 1098 lwkt_reltoken(&tty_token); 1099 crit_exit(); 1100 return EINVAL; 1101 } 1102 bcopy(&kbd->kb_keymap->key[keyp->keynum], &keyp->key, 1103 sizeof(keyp->key)); 1104 break; 1105 case PIO_KEYMAPENT: /* set keyboard translation table entry */ 1106 #ifndef KBD_DISABLE_KEYMAP_LOAD 1107 keyp = (keyarg_t *)arg; 1108 if (keyp->keynum >= sizeof(kbd->kb_keymap->key) 1109 /sizeof(kbd->kb_keymap->key[0])) { 1110 lwkt_reltoken(&tty_token); 1111 crit_exit(); 1112 return EINVAL; 1113 } 1114 bcopy(&keyp->key, &kbd->kb_keymap->key[keyp->keynum], 1115 sizeof(keyp->key)); 1116 break; 1117 #else 1118 lwkt_reltoken(&tty_token); 1119 crit_exit(); 1120 return ENODEV; 1121 #endif 1122 1123 case GIO_DEADKEYMAP: /* get accent key translation table */ 1124 bcopy(kbd->kb_accentmap, arg, sizeof(*kbd->kb_accentmap)); 1125 break; 1126 case PIO_DEADKEYMAP: /* set accent key translation table */ 1127 #ifndef KBD_DISABLE_KEYMAP_LOAD 1128 bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); 1129 break; 1130 #else 1131 lwkt_reltoken(&tty_token); 1132 crit_exit(); 1133 return ENODEV; 1134 #endif 1135 1136 case GETFKEY: /* get functionkey string */ 1137 fkeyp = (fkeyarg_t *)arg; 1138 if (fkeyp->keynum >= kbd->kb_fkeytab_size) { 1139 lwkt_reltoken(&tty_token); 1140 crit_exit(); 1141 return EINVAL; 1142 } 1143 bcopy(kbd->kb_fkeytab[fkeyp->keynum].str, fkeyp->keydef, 1144 kbd->kb_fkeytab[fkeyp->keynum].len); 1145 fkeyp->flen = kbd->kb_fkeytab[fkeyp->keynum].len; 1146 break; 1147 case SETFKEY: /* set functionkey string */ 1148 #ifndef KBD_DISABLE_KEYMAP_LOAD 1149 fkeyp = (fkeyarg_t *)arg; 1150 if (fkeyp->keynum >= kbd->kb_fkeytab_size) { 1151 lwkt_reltoken(&tty_token); 1152 crit_exit(); 1153 return EINVAL; 1154 } 1155 kbd->kb_fkeytab[fkeyp->keynum].len = imin(fkeyp->flen, MAXFK); 1156 bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str, 1157 kbd->kb_fkeytab[fkeyp->keynum].len); 1158 break; 1159 #else 1160 lwkt_reltoken(&tty_token); 1161 crit_exit(); 1162 return ENODEV; 1163 #endif 1164 1165 default: 1166 lwkt_reltoken(&tty_token); 1167 crit_exit(); 1168 return ENOIOCTL; 1169 } 1170 1171 lwkt_reltoken(&tty_token); 1172 crit_exit(); 1173 return 0; 1174 } 1175 1176 /* get a pointer to the string associated with the given function key */ 1177 u_char * 1178 genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len) 1179 { 1180 u_char *ch; 1181 1182 if (kbd == NULL) 1183 return NULL; 1184 1185 lwkt_gettoken(&tty_token); 1186 fkey -= F_FN; 1187 if (fkey > kbd->kb_fkeytab_size) { 1188 lwkt_reltoken(&tty_token); 1189 return NULL; 1190 } 1191 *len = kbd->kb_fkeytab[fkey].len; 1192 ch = kbd->kb_fkeytab[fkey].str; 1193 1194 lwkt_reltoken(&tty_token); 1195 return ch; 1196 } 1197 1198 /* diagnostic dump */ 1199 static char * 1200 get_kbd_type_name(int type) 1201 { 1202 static struct { 1203 int type; 1204 char *name; 1205 } name_table[] = { 1206 { KB_84, "AT 84" }, 1207 { KB_101, "AT 101/102" }, 1208 { KB_OTHER, "generic" }, 1209 }; 1210 int i; 1211 1212 for (i = 0; i < sizeof(name_table)/sizeof(name_table[0]); ++i) { 1213 if (type == name_table[i].type) 1214 return name_table[i].name; 1215 } 1216 return "unknown"; 1217 } 1218 1219 void 1220 genkbd_diag(keyboard_t *kbd, int level) 1221 { 1222 if (level > 0) { 1223 kprintf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x", 1224 kbd->kb_index, kbd->kb_name, kbd->kb_unit, 1225 get_kbd_type_name(kbd->kb_type), kbd->kb_type, 1226 kbd->kb_config, kbd->kb_flags); 1227 if (kbd->kb_io_base > 0) 1228 kprintf(", port:0x%x-0x%x", kbd->kb_io_base, 1229 kbd->kb_io_base + kbd->kb_io_size - 1); 1230 kprintf("\n"); 1231 } 1232 } 1233 1234 #define set_lockkey_state(k, s, l) \ 1235 if (!((s) & l ## DOWN)) { \ 1236 int i; \ 1237 (s) |= l ## DOWN; \ 1238 (s) ^= l ## ED; \ 1239 i = (s) & LOCK_MASK; \ 1240 kbd_ioctl((k), KDSETLED, (caddr_t)&i); \ 1241 } 1242 1243 static u_int 1244 save_accent_key(keyboard_t *kbd, u_int key, int *accents) 1245 { 1246 int i; 1247 1248 lwkt_gettoken(&tty_token); 1249 /* make an index into the accent map */ 1250 i = key - F_ACC + 1; 1251 if ((i > kbd->kb_accentmap->n_accs) 1252 || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) { 1253 /* the index is out of range or pointing to an empty entry */ 1254 *accents = 0; 1255 lwkt_reltoken(&tty_token); 1256 return ERRKEY; 1257 } 1258 1259 /* 1260 * If the same accent key has been hit twice, produce the accent char 1261 * itself. 1262 */ 1263 if (i == *accents) { 1264 key = kbd->kb_accentmap->acc[i - 1].accchar; 1265 *accents = 0; 1266 lwkt_reltoken(&tty_token); 1267 return key; 1268 } 1269 1270 /* remember the index and wait for the next key */ 1271 *accents = i; 1272 lwkt_reltoken(&tty_token); 1273 return NOKEY; 1274 } 1275 1276 static u_int 1277 make_accent_char(keyboard_t *kbd, u_int ch, int *accents) 1278 { 1279 struct acc_t *acc; 1280 int i; 1281 1282 lwkt_gettoken(&tty_token); 1283 acc = &kbd->kb_accentmap->acc[*accents - 1]; 1284 *accents = 0; 1285 1286 /* 1287 * If the accent key is followed by the space key, 1288 * produce the accent char itself. 1289 */ 1290 if (ch == ' ') { 1291 lwkt_reltoken(&tty_token); 1292 return acc->accchar; 1293 } 1294 1295 /* scan the accent map */ 1296 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 1297 if (acc->map[i][0] == 0) /* end of table */ 1298 break; 1299 if (acc->map[i][0] == ch) { 1300 lwkt_reltoken(&tty_token); 1301 return acc->map[i][1]; 1302 } 1303 } 1304 lwkt_reltoken(&tty_token); 1305 /* this char cannot be accented... */ 1306 return ERRKEY; 1307 } 1308 1309 int 1310 genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate, 1311 int *accents) 1312 { 1313 struct keyent_t *key; 1314 int state = *shiftstate; 1315 int action; 1316 int f; 1317 int i; 1318 1319 lwkt_gettoken(&tty_token); 1320 i = keycode; 1321 f = state & (AGRS | ALKED); 1322 if ((f == AGRS1) || (f == AGRS2) || (f == ALKED)) 1323 i += ALTGR_OFFSET; 1324 key = &kbd->kb_keymap->key[i]; 1325 i = ((state & SHIFTS) ? 1 : 0) 1326 | ((state & CTLS) ? 2 : 0) 1327 | ((state & ALTS) ? 4 : 0); 1328 if (((key->flgs & FLAG_LOCK_C) && (state & CLKED)) 1329 || ((key->flgs & FLAG_LOCK_N) && (state & NLKED)) ) 1330 i ^= 1; 1331 1332 if (up) { /* break: key released */ 1333 action = kbd->kb_lastact[keycode]; 1334 kbd->kb_lastact[keycode] = NOP; 1335 switch (action) { 1336 case LSHA: 1337 if (state & SHIFTAON) { 1338 set_lockkey_state(kbd, state, ALK); 1339 state &= ~ALKDOWN; 1340 } 1341 action = LSH; 1342 /* FALL THROUGH */ 1343 case LSH: 1344 state &= ~SHIFTS1; 1345 break; 1346 case RSHA: 1347 if (state & SHIFTAON) { 1348 set_lockkey_state(kbd, state, ALK); 1349 state &= ~ALKDOWN; 1350 } 1351 action = RSH; 1352 /* FALL THROUGH */ 1353 case RSH: 1354 state &= ~SHIFTS2; 1355 break; 1356 case LCTRA: 1357 if (state & SHIFTAON) { 1358 set_lockkey_state(kbd, state, ALK); 1359 state &= ~ALKDOWN; 1360 } 1361 action = LCTR; 1362 /* FALL THROUGH */ 1363 case LCTR: 1364 state &= ~CTLS1; 1365 break; 1366 case RCTRA: 1367 if (state & SHIFTAON) { 1368 set_lockkey_state(kbd, state, ALK); 1369 state &= ~ALKDOWN; 1370 } 1371 action = RCTR; 1372 /* FALL THROUGH */ 1373 case RCTR: 1374 state &= ~CTLS2; 1375 break; 1376 case LALTA: 1377 if (state & SHIFTAON) { 1378 set_lockkey_state(kbd, state, ALK); 1379 state &= ~ALKDOWN; 1380 } 1381 action = LALT; 1382 /* FALL THROUGH */ 1383 case LALT: 1384 state &= ~ALTS1; 1385 break; 1386 case RALTA: 1387 if (state & SHIFTAON) { 1388 set_lockkey_state(kbd, state, ALK); 1389 state &= ~ALKDOWN; 1390 } 1391 action = RALT; 1392 /* FALL THROUGH */ 1393 case RALT: 1394 state &= ~ALTS2; 1395 break; 1396 case ASH: 1397 state &= ~AGRS1; 1398 break; 1399 case META: 1400 state &= ~METAS1; 1401 break; 1402 case NLK: 1403 state &= ~NLKDOWN; 1404 break; 1405 case CLK: 1406 state &= ~CLKDOWN; 1407 break; 1408 case SLK: 1409 state &= ~SLKDOWN; 1410 break; 1411 case ALK: 1412 state &= ~ALKDOWN; 1413 break; 1414 case NOP: 1415 /* release events of regular keys are not reported */ 1416 *shiftstate &= ~SHIFTAON; 1417 lwkt_reltoken(&tty_token); 1418 return NOKEY; 1419 } 1420 *shiftstate = state & ~SHIFTAON; 1421 lwkt_reltoken(&tty_token); 1422 return (SPCLKEY | RELKEY | action); 1423 } else { /* make: key pressed */ 1424 action = key->map[i]; 1425 state &= ~SHIFTAON; 1426 if (key->spcl & (0x80 >> i)) { 1427 /* special keys */ 1428 if (kbd->kb_lastact[keycode] == NOP) 1429 kbd->kb_lastact[keycode] = action; 1430 if (kbd->kb_lastact[keycode] != action) 1431 action = NOP; 1432 switch (action) { 1433 /* LOCKING KEYS */ 1434 case NLK: 1435 set_lockkey_state(kbd, state, NLK); 1436 break; 1437 case CLK: 1438 set_lockkey_state(kbd, state, CLK); 1439 break; 1440 case SLK: 1441 set_lockkey_state(kbd, state, SLK); 1442 break; 1443 case ALK: 1444 set_lockkey_state(kbd, state, ALK); 1445 break; 1446 /* NON-LOCKING KEYS */ 1447 case SPSC: case RBT: case SUSP: case STBY: 1448 case DBG: case NEXT: case PREV: case PNC: 1449 case HALT: case PDWN: 1450 *accents = 0; 1451 break; 1452 case BTAB: 1453 *accents = 0; 1454 action |= BKEY; 1455 break; 1456 case LSHA: 1457 state |= SHIFTAON; 1458 action = LSH; 1459 /* FALL THROUGH */ 1460 case LSH: 1461 state |= SHIFTS1; 1462 break; 1463 case RSHA: 1464 state |= SHIFTAON; 1465 action = RSH; 1466 /* FALL THROUGH */ 1467 case RSH: 1468 state |= SHIFTS2; 1469 break; 1470 case LCTRA: 1471 state |= SHIFTAON; 1472 action = LCTR; 1473 /* FALL THROUGH */ 1474 case LCTR: 1475 state |= CTLS1; 1476 break; 1477 case RCTRA: 1478 state |= SHIFTAON; 1479 action = RCTR; 1480 /* FALL THROUGH */ 1481 case RCTR: 1482 state |= CTLS2; 1483 break; 1484 case LALTA: 1485 state |= SHIFTAON; 1486 action = LALT; 1487 /* FALL THROUGH */ 1488 case LALT: 1489 state |= ALTS1; 1490 break; 1491 case RALTA: 1492 state |= SHIFTAON; 1493 action = RALT; 1494 /* FALL THROUGH */ 1495 case RALT: 1496 state |= ALTS2; 1497 break; 1498 case ASH: 1499 state |= AGRS1; 1500 break; 1501 case META: 1502 state |= METAS1; 1503 break; 1504 case NOP: 1505 *shiftstate = state; 1506 lwkt_reltoken(&tty_token); 1507 return NOKEY; 1508 default: 1509 /* is this an accent (dead) key? */ 1510 *shiftstate = state; 1511 if (action >= F_ACC && action <= L_ACC) { 1512 action = save_accent_key(kbd, action, 1513 accents); 1514 switch (action) { 1515 case NOKEY: 1516 case ERRKEY: 1517 lwkt_reltoken(&tty_token); 1518 return action; 1519 default: 1520 if (state & METAS) { 1521 lwkt_reltoken(&tty_token); 1522 return (action | MKEY); 1523 } else { 1524 lwkt_reltoken(&tty_token); 1525 return action; 1526 } 1527 } 1528 /* NOT REACHED */ 1529 } 1530 /* other special keys */ 1531 if (*accents > 0) { 1532 *accents = 0; 1533 lwkt_reltoken(&tty_token); 1534 return ERRKEY; 1535 } 1536 if (action >= F_FN && action <= L_FN) 1537 action |= FKEY; 1538 /* XXX: return fkey string for the FKEY? */ 1539 lwkt_reltoken(&tty_token); 1540 return (SPCLKEY | action); 1541 } 1542 *shiftstate = state; 1543 lwkt_reltoken(&tty_token); 1544 return (SPCLKEY | action); 1545 } else { 1546 /* regular keys */ 1547 kbd->kb_lastact[keycode] = NOP; 1548 *shiftstate = state; 1549 if (*accents > 0) { 1550 /* make an accented char */ 1551 action = make_accent_char(kbd, action, accents); 1552 if (action == ERRKEY) { 1553 lwkt_reltoken(&tty_token); 1554 return action; 1555 } 1556 } 1557 if (state & METAS) 1558 action |= MKEY; 1559 lwkt_reltoken(&tty_token); 1560 return action; 1561 } 1562 } 1563 /* NOT REACHED */ 1564 lwkt_reltoken(&tty_token); 1565 } 1566