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