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