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