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 /* The keyboard has gone */ 928 kn->kn_flags |= (EV_EOF | EV_NODATA); 929 ready = 1; 930 } else { 931 if (sc->gkb_q_length > 0) 932 ready = 1; 933 } 934 lwkt_reltoken(&tty_token); 935 crit_exit(); 936 937 return (ready); 938 } 939 940 static int 941 genkbd_event(keyboard_t *kbd, int event, void *arg) 942 { 943 genkbd_softc_t sc; 944 size_t len; 945 u_char *cp; 946 int mode; 947 int c; 948 949 lwkt_gettoken(&tty_token); 950 /* assert(KBD_IS_VALID(kbd)) */ 951 sc = (genkbd_softc_t)arg; 952 953 switch (event) { 954 case KBDIO_KEYINPUT: 955 break; 956 case KBDIO_UNLOADING: 957 /* the keyboard is going... */ 958 kbd_release(kbd, (void *)sc); 959 if (sc->gkb_flags & KB_ASLEEP) { 960 sc->gkb_flags &= ~KB_ASLEEP; 961 wakeup((caddr_t)sc); 962 } 963 KNOTE(&sc->gkb_rkq.ki_note, 0); 964 lwkt_reltoken(&tty_token); 965 return 0; 966 default: 967 lwkt_reltoken(&tty_token); 968 return EINVAL; 969 } 970 971 /* obtain the current key input mode */ 972 if (kbd_ioctl(kbd, KDGKBMODE, (caddr_t)&mode)) 973 mode = K_XLATE; 974 975 /* read all pending input */ 976 while (kbd_check_char(kbd)) { 977 c = kbd_read_char(kbd, FALSE); 978 if (c == NOKEY) 979 continue; 980 if (c == ERRKEY) /* XXX: ring bell? */ 981 continue; 982 if (!KBD_IS_BUSY(kbd)) 983 /* the device is not open, discard the input */ 984 continue; 985 986 /* store the byte as is for K_RAW and K_CODE modes */ 987 if (mode != K_XLATE) { 988 genkbd_putc(sc, KEYCHAR(c)); 989 continue; 990 } 991 992 /* K_XLATE */ 993 if (c & RELKEY) /* key release is ignored */ 994 continue; 995 996 /* process special keys; most of them are just ignored... */ 997 if (c & SPCLKEY) { 998 switch (KEYCHAR(c)) { 999 default: 1000 /* ignore them... */ 1001 continue; 1002 case BTAB: /* a backtab: ESC [ Z */ 1003 genkbd_putc(sc, 0x1b); 1004 genkbd_putc(sc, '['); 1005 genkbd_putc(sc, 'Z'); 1006 continue; 1007 } 1008 } 1009 1010 /* normal chars, normal chars with the META, function keys */ 1011 switch (KEYFLAGS(c)) { 1012 case 0: /* a normal char */ 1013 genkbd_putc(sc, KEYCHAR(c)); 1014 break; 1015 case MKEY: /* the META flag: prepend ESC */ 1016 genkbd_putc(sc, 0x1b); 1017 genkbd_putc(sc, KEYCHAR(c)); 1018 break; 1019 case FKEY | SPCLKEY: /* a function key, return string */ 1020 cp = kbd_get_fkeystr(kbd, KEYCHAR(c), &len); 1021 if (cp != NULL) { 1022 while (len-- > 0) 1023 genkbd_putc(sc, *cp++); 1024 } 1025 break; 1026 } 1027 } 1028 1029 /* wake up sleeping/polling processes */ 1030 if (sc->gkb_q_length > 0) { 1031 if (sc->gkb_flags & KB_ASLEEP) { 1032 sc->gkb_flags &= ~KB_ASLEEP; 1033 wakeup((caddr_t)sc); 1034 } 1035 KNOTE(&sc->gkb_rkq.ki_note, 0); 1036 } 1037 1038 lwkt_reltoken(&tty_token); 1039 return 0; 1040 } 1041 1042 #endif /* KBD_INSTALL_CDEV */ 1043 1044 /* 1045 * Generic low-level keyboard functions 1046 * The low-level functions in the keyboard subdriver may use these 1047 * functions. 1048 */ 1049 1050 int 1051 genkbd_commonioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) 1052 { 1053 keyarg_t *keyp; 1054 fkeyarg_t *fkeyp; 1055 int i; 1056 1057 crit_enter(); 1058 lwkt_gettoken(&tty_token); 1059 switch (cmd) { 1060 1061 case KDGKBINFO: /* get keyboard information */ 1062 ((keyboard_info_t *)arg)->kb_index = kbd->kb_index; 1063 i = imin(strlen(kbd->kb_name) + 1, 1064 sizeof(((keyboard_info_t *)arg)->kb_name)); 1065 bcopy(kbd->kb_name, ((keyboard_info_t *)arg)->kb_name, i); 1066 ((keyboard_info_t *)arg)->kb_unit = kbd->kb_unit; 1067 ((keyboard_info_t *)arg)->kb_type = kbd->kb_type; 1068 ((keyboard_info_t *)arg)->kb_config = kbd->kb_config; 1069 ((keyboard_info_t *)arg)->kb_flags = kbd->kb_flags; 1070 break; 1071 1072 case KDGKBTYPE: /* get keyboard type */ 1073 *(int *)arg = kbd->kb_type; 1074 break; 1075 1076 case KDGETREPEAT: /* get keyboard repeat rate */ 1077 ((int *)arg)[0] = kbd->kb_delay1; 1078 ((int *)arg)[1] = kbd->kb_delay2; 1079 break; 1080 1081 case GIO_KEYMAP: /* get keyboard translation table */ 1082 bcopy(kbd->kb_keymap, arg, sizeof(*kbd->kb_keymap)); 1083 break; 1084 case PIO_KEYMAP: /* set keyboard translation table */ 1085 #ifndef KBD_DISABLE_KEYMAP_LOAD 1086 bzero(kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); 1087 bcopy(arg, kbd->kb_keymap, sizeof(*kbd->kb_keymap)); 1088 break; 1089 #else 1090 lwkt_reltoken(&tty_token); 1091 crit_exit(); 1092 return ENODEV; 1093 #endif 1094 1095 case GIO_KEYMAPENT: /* get keyboard translation table entry */ 1096 keyp = (keyarg_t *)arg; 1097 if (keyp->keynum >= sizeof(kbd->kb_keymap->key) 1098 /sizeof(kbd->kb_keymap->key[0])) { 1099 lwkt_reltoken(&tty_token); 1100 crit_exit(); 1101 return EINVAL; 1102 } 1103 bcopy(&kbd->kb_keymap->key[keyp->keynum], &keyp->key, 1104 sizeof(keyp->key)); 1105 break; 1106 case PIO_KEYMAPENT: /* set keyboard translation table entry */ 1107 #ifndef KBD_DISABLE_KEYMAP_LOAD 1108 keyp = (keyarg_t *)arg; 1109 if (keyp->keynum >= sizeof(kbd->kb_keymap->key) 1110 /sizeof(kbd->kb_keymap->key[0])) { 1111 lwkt_reltoken(&tty_token); 1112 crit_exit(); 1113 return EINVAL; 1114 } 1115 bcopy(&keyp->key, &kbd->kb_keymap->key[keyp->keynum], 1116 sizeof(keyp->key)); 1117 break; 1118 #else 1119 lwkt_reltoken(&tty_token); 1120 crit_exit(); 1121 return ENODEV; 1122 #endif 1123 1124 case GIO_DEADKEYMAP: /* get accent key translation table */ 1125 bcopy(kbd->kb_accentmap, arg, sizeof(*kbd->kb_accentmap)); 1126 break; 1127 case PIO_DEADKEYMAP: /* set accent key translation table */ 1128 #ifndef KBD_DISABLE_KEYMAP_LOAD 1129 bcopy(arg, kbd->kb_accentmap, sizeof(*kbd->kb_accentmap)); 1130 break; 1131 #else 1132 lwkt_reltoken(&tty_token); 1133 crit_exit(); 1134 return ENODEV; 1135 #endif 1136 1137 case GETFKEY: /* get functionkey string */ 1138 fkeyp = (fkeyarg_t *)arg; 1139 if (fkeyp->keynum >= kbd->kb_fkeytab_size) { 1140 lwkt_reltoken(&tty_token); 1141 crit_exit(); 1142 return EINVAL; 1143 } 1144 bcopy(kbd->kb_fkeytab[fkeyp->keynum].str, fkeyp->keydef, 1145 kbd->kb_fkeytab[fkeyp->keynum].len); 1146 fkeyp->flen = kbd->kb_fkeytab[fkeyp->keynum].len; 1147 break; 1148 case SETFKEY: /* set functionkey string */ 1149 #ifndef KBD_DISABLE_KEYMAP_LOAD 1150 fkeyp = (fkeyarg_t *)arg; 1151 if (fkeyp->keynum >= kbd->kb_fkeytab_size) { 1152 lwkt_reltoken(&tty_token); 1153 crit_exit(); 1154 return EINVAL; 1155 } 1156 kbd->kb_fkeytab[fkeyp->keynum].len = imin(fkeyp->flen, MAXFK); 1157 bcopy(fkeyp->keydef, kbd->kb_fkeytab[fkeyp->keynum].str, 1158 kbd->kb_fkeytab[fkeyp->keynum].len); 1159 break; 1160 #else 1161 lwkt_reltoken(&tty_token); 1162 crit_exit(); 1163 return ENODEV; 1164 #endif 1165 1166 default: 1167 lwkt_reltoken(&tty_token); 1168 crit_exit(); 1169 return ENOIOCTL; 1170 } 1171 1172 lwkt_reltoken(&tty_token); 1173 crit_exit(); 1174 return 0; 1175 } 1176 1177 /* get a pointer to the string associated with the given function key */ 1178 u_char * 1179 genkbd_get_fkeystr(keyboard_t *kbd, int fkey, size_t *len) 1180 { 1181 u_char *ch; 1182 1183 if (kbd == NULL) 1184 return NULL; 1185 1186 lwkt_gettoken(&tty_token); 1187 fkey -= F_FN; 1188 if (fkey > kbd->kb_fkeytab_size) { 1189 lwkt_reltoken(&tty_token); 1190 return NULL; 1191 } 1192 *len = kbd->kb_fkeytab[fkey].len; 1193 ch = kbd->kb_fkeytab[fkey].str; 1194 1195 lwkt_reltoken(&tty_token); 1196 return ch; 1197 } 1198 1199 /* diagnostic dump */ 1200 static char * 1201 get_kbd_type_name(int type) 1202 { 1203 static struct { 1204 int type; 1205 char *name; 1206 } name_table[] = { 1207 { KB_84, "AT 84" }, 1208 { KB_101, "AT 101/102" }, 1209 { KB_OTHER, "generic" }, 1210 }; 1211 int i; 1212 1213 for (i = 0; i < NELEM(name_table); ++i) { 1214 if (type == name_table[i].type) 1215 return name_table[i].name; 1216 } 1217 return "unknown"; 1218 } 1219 1220 void 1221 genkbd_diag(keyboard_t *kbd, int level) 1222 { 1223 if (level > 0) { 1224 kprintf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x", 1225 kbd->kb_index, kbd->kb_name, kbd->kb_unit, 1226 get_kbd_type_name(kbd->kb_type), kbd->kb_type, 1227 kbd->kb_config, kbd->kb_flags); 1228 if (kbd->kb_io_base > 0) 1229 kprintf(", port:0x%x-0x%x", kbd->kb_io_base, 1230 kbd->kb_io_base + kbd->kb_io_size - 1); 1231 kprintf("\n"); 1232 } 1233 } 1234 1235 #define set_lockkey_state(k, s, l) \ 1236 if (!((s) & l ## DOWN)) { \ 1237 int i; \ 1238 (s) |= l ## DOWN; \ 1239 (s) ^= l ## ED; \ 1240 i = (s) & LOCK_MASK; \ 1241 kbd_ioctl((k), KDSETLED, (caddr_t)&i); \ 1242 } 1243 1244 static u_int 1245 save_accent_key(keyboard_t *kbd, u_int key, int *accents) 1246 { 1247 int i; 1248 1249 lwkt_gettoken(&tty_token); 1250 /* make an index into the accent map */ 1251 i = key - F_ACC + 1; 1252 if ((i > kbd->kb_accentmap->n_accs) 1253 || (kbd->kb_accentmap->acc[i - 1].accchar == 0)) { 1254 /* the index is out of range or pointing to an empty entry */ 1255 *accents = 0; 1256 lwkt_reltoken(&tty_token); 1257 return ERRKEY; 1258 } 1259 1260 /* 1261 * If the same accent key has been hit twice, produce the accent char 1262 * itself. 1263 */ 1264 if (i == *accents) { 1265 key = kbd->kb_accentmap->acc[i - 1].accchar; 1266 *accents = 0; 1267 lwkt_reltoken(&tty_token); 1268 return key; 1269 } 1270 1271 /* remember the index and wait for the next key */ 1272 *accents = i; 1273 lwkt_reltoken(&tty_token); 1274 return NOKEY; 1275 } 1276 1277 static u_int 1278 make_accent_char(keyboard_t *kbd, u_int ch, int *accents) 1279 { 1280 struct acc_t *acc; 1281 int i; 1282 1283 lwkt_gettoken(&tty_token); 1284 acc = &kbd->kb_accentmap->acc[*accents - 1]; 1285 *accents = 0; 1286 1287 /* 1288 * If the accent key is followed by the space key, 1289 * produce the accent char itself. 1290 */ 1291 if (ch == ' ') { 1292 lwkt_reltoken(&tty_token); 1293 return acc->accchar; 1294 } 1295 1296 /* scan the accent map */ 1297 for (i = 0; i < NUM_ACCENTCHARS; ++i) { 1298 if (acc->map[i][0] == 0) /* end of table */ 1299 break; 1300 if (acc->map[i][0] == ch) { 1301 lwkt_reltoken(&tty_token); 1302 return acc->map[i][1]; 1303 } 1304 } 1305 lwkt_reltoken(&tty_token); 1306 /* this char cannot be accented... */ 1307 return ERRKEY; 1308 } 1309 1310 int 1311 genkbd_keyaction(keyboard_t *kbd, int keycode, int up, int *shiftstate, 1312 int *accents) 1313 { 1314 struct keyent_t *key; 1315 int state = *shiftstate; 1316 int action; 1317 int f; 1318 int i; 1319 1320 lwkt_gettoken(&tty_token); 1321 i = keycode; 1322 f = state & (AGRS | ALKED); 1323 if ((f == AGRS1) || (f == AGRS2) || (f == ALKED)) 1324 i += ALTGR_OFFSET; 1325 key = &kbd->kb_keymap->key[i]; 1326 i = ((state & SHIFTS) ? 1 : 0) 1327 | ((state & CTLS) ? 2 : 0) 1328 | ((state & ALTS) ? 4 : 0); 1329 if (((key->flgs & FLAG_LOCK_C) && (state & CLKED)) 1330 || ((key->flgs & FLAG_LOCK_N) && (state & NLKED)) ) 1331 i ^= 1; 1332 1333 if (up) { /* break: key released */ 1334 action = kbd->kb_lastact[keycode]; 1335 kbd->kb_lastact[keycode] = NOP; 1336 switch (action) { 1337 case LSHA: 1338 if (state & SHIFTAON) { 1339 set_lockkey_state(kbd, state, ALK); 1340 state &= ~ALKDOWN; 1341 } 1342 action = LSH; 1343 /* FALL THROUGH */ 1344 case LSH: 1345 state &= ~SHIFTS1; 1346 break; 1347 case RSHA: 1348 if (state & SHIFTAON) { 1349 set_lockkey_state(kbd, state, ALK); 1350 state &= ~ALKDOWN; 1351 } 1352 action = RSH; 1353 /* FALL THROUGH */ 1354 case RSH: 1355 state &= ~SHIFTS2; 1356 break; 1357 case LCTRA: 1358 if (state & SHIFTAON) { 1359 set_lockkey_state(kbd, state, ALK); 1360 state &= ~ALKDOWN; 1361 } 1362 action = LCTR; 1363 /* FALL THROUGH */ 1364 case LCTR: 1365 state &= ~CTLS1; 1366 break; 1367 case RCTRA: 1368 if (state & SHIFTAON) { 1369 set_lockkey_state(kbd, state, ALK); 1370 state &= ~ALKDOWN; 1371 } 1372 action = RCTR; 1373 /* FALL THROUGH */ 1374 case RCTR: 1375 state &= ~CTLS2; 1376 break; 1377 case LALTA: 1378 if (state & SHIFTAON) { 1379 set_lockkey_state(kbd, state, ALK); 1380 state &= ~ALKDOWN; 1381 } 1382 action = LALT; 1383 /* FALL THROUGH */ 1384 case LALT: 1385 state &= ~ALTS1; 1386 break; 1387 case RALTA: 1388 if (state & SHIFTAON) { 1389 set_lockkey_state(kbd, state, ALK); 1390 state &= ~ALKDOWN; 1391 } 1392 action = RALT; 1393 /* FALL THROUGH */ 1394 case RALT: 1395 state &= ~ALTS2; 1396 break; 1397 case ASH: 1398 state &= ~AGRS1; 1399 break; 1400 case META: 1401 state &= ~METAS1; 1402 break; 1403 case NLK: 1404 state &= ~NLKDOWN; 1405 break; 1406 case CLK: 1407 state &= ~CLKDOWN; 1408 break; 1409 case SLK: 1410 state &= ~SLKDOWN; 1411 break; 1412 case ALK: 1413 state &= ~ALKDOWN; 1414 break; 1415 case NOP: 1416 /* release events of regular keys are not reported */ 1417 *shiftstate &= ~SHIFTAON; 1418 lwkt_reltoken(&tty_token); 1419 return NOKEY; 1420 } 1421 *shiftstate = state & ~SHIFTAON; 1422 lwkt_reltoken(&tty_token); 1423 return (SPCLKEY | RELKEY | action); 1424 } else { /* make: key pressed */ 1425 action = key->map[i]; 1426 state &= ~SHIFTAON; 1427 if (key->spcl & (0x80 >> i)) { 1428 /* special keys */ 1429 if (kbd->kb_lastact[keycode] == NOP) 1430 kbd->kb_lastact[keycode] = action; 1431 if (kbd->kb_lastact[keycode] != action) 1432 action = NOP; 1433 switch (action) { 1434 /* LOCKING KEYS */ 1435 case NLK: 1436 set_lockkey_state(kbd, state, NLK); 1437 break; 1438 case CLK: 1439 set_lockkey_state(kbd, state, CLK); 1440 break; 1441 case SLK: 1442 set_lockkey_state(kbd, state, SLK); 1443 break; 1444 case ALK: 1445 set_lockkey_state(kbd, state, ALK); 1446 break; 1447 /* NON-LOCKING KEYS */ 1448 case SPSC: case RBT: case SUSP: case STBY: 1449 case DBG: case NEXT: case PREV: case PNC: 1450 case HALT: case PDWN: 1451 *accents = 0; 1452 break; 1453 case BTAB: 1454 *accents = 0; 1455 action |= BKEY; 1456 break; 1457 case LSHA: 1458 state |= SHIFTAON; 1459 action = LSH; 1460 /* FALL THROUGH */ 1461 case LSH: 1462 state |= SHIFTS1; 1463 break; 1464 case RSHA: 1465 state |= SHIFTAON; 1466 action = RSH; 1467 /* FALL THROUGH */ 1468 case RSH: 1469 state |= SHIFTS2; 1470 break; 1471 case LCTRA: 1472 state |= SHIFTAON; 1473 action = LCTR; 1474 /* FALL THROUGH */ 1475 case LCTR: 1476 state |= CTLS1; 1477 break; 1478 case RCTRA: 1479 state |= SHIFTAON; 1480 action = RCTR; 1481 /* FALL THROUGH */ 1482 case RCTR: 1483 state |= CTLS2; 1484 break; 1485 case LALTA: 1486 state |= SHIFTAON; 1487 action = LALT; 1488 /* FALL THROUGH */ 1489 case LALT: 1490 state |= ALTS1; 1491 break; 1492 case RALTA: 1493 state |= SHIFTAON; 1494 action = RALT; 1495 /* FALL THROUGH */ 1496 case RALT: 1497 state |= ALTS2; 1498 break; 1499 case ASH: 1500 state |= AGRS1; 1501 break; 1502 case META: 1503 state |= METAS1; 1504 break; 1505 case NOP: 1506 *shiftstate = state; 1507 lwkt_reltoken(&tty_token); 1508 return NOKEY; 1509 default: 1510 /* is this an accent (dead) key? */ 1511 *shiftstate = state; 1512 if (action >= F_ACC && action <= L_ACC) { 1513 action = save_accent_key(kbd, action, 1514 accents); 1515 switch (action) { 1516 case NOKEY: 1517 case ERRKEY: 1518 lwkt_reltoken(&tty_token); 1519 return action; 1520 default: 1521 if (state & METAS) { 1522 lwkt_reltoken(&tty_token); 1523 return (action | MKEY); 1524 } else { 1525 lwkt_reltoken(&tty_token); 1526 return action; 1527 } 1528 } 1529 /* NOT REACHED */ 1530 } 1531 /* other special keys */ 1532 if (*accents > 0) { 1533 *accents = 0; 1534 lwkt_reltoken(&tty_token); 1535 return ERRKEY; 1536 } 1537 if (action >= F_FN && action <= L_FN) 1538 action |= FKEY; 1539 /* XXX: return fkey string for the FKEY? */ 1540 lwkt_reltoken(&tty_token); 1541 return (SPCLKEY | action); 1542 } 1543 *shiftstate = state; 1544 lwkt_reltoken(&tty_token); 1545 return (SPCLKEY | action); 1546 } else { 1547 /* regular keys */ 1548 kbd->kb_lastact[keycode] = NOP; 1549 *shiftstate = state; 1550 if (*accents > 0) { 1551 /* make an accented char */ 1552 action = make_accent_char(kbd, action, accents); 1553 if (action == ERRKEY) { 1554 lwkt_reltoken(&tty_token); 1555 return action; 1556 } 1557 } 1558 if (state & METAS) 1559 action |= MKEY; 1560 lwkt_reltoken(&tty_token); 1561 return action; 1562 } 1563 } 1564 /* NOT REACHED */ 1565 lwkt_reltoken(&tty_token); 1566 } 1567