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