1 /* $NetBSD: kbd.c,v 1.43 2005/02/27 00:27:49 perry Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratory. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)kbd.c 8.2 (Berkeley) 10/30/93 41 */ 42 43 /* 44 * Keyboard driver (/dev/kbd -- note that we do not have minor numbers 45 * [yet?]). Translates incoming bytes to ASCII or to `firm_events' and 46 * passes them up to the appropriate reader. 47 */ 48 49 #include <sys/cdefs.h> 50 __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.43 2005/02/27 00:27:49 perry Exp $"); 51 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <sys/conf.h> 55 #include <sys/device.h> 56 #include <sys/ioctl.h> 57 #include <sys/kernel.h> 58 #include <sys/proc.h> 59 #include <sys/malloc.h> 60 #include <sys/signal.h> 61 #include <sys/signalvar.h> 62 #include <sys/time.h> 63 #include <sys/syslog.h> 64 #include <sys/select.h> 65 #include <sys/poll.h> 66 #include <sys/file.h> 67 68 #include <dev/wscons/wsksymdef.h> 69 70 #include <dev/sun/kbd_reg.h> 71 #include <dev/sun/kbio.h> 72 #include <dev/sun/vuid_event.h> 73 #include <dev/sun/event_var.h> 74 #include <dev/sun/kbd_xlate.h> 75 #include <dev/sun/kbdvar.h> 76 77 #include "locators.h" 78 79 extern struct cfdriver kbd_cd; 80 81 dev_type_open(kbdopen); 82 dev_type_close(kbdclose); 83 dev_type_read(kbdread); 84 dev_type_ioctl(kbdioctl); 85 dev_type_poll(kbdpoll); 86 dev_type_kqfilter(kbdkqfilter); 87 88 const struct cdevsw kbd_cdevsw = { 89 kbdopen, kbdclose, kbdread, nowrite, kbdioctl, 90 nostop, notty, kbdpoll, nommap, kbdkqfilter 91 }; 92 93 #if NWSKBD > 0 94 int wssunkbd_enable(void *, int); 95 void wssunkbd_set_leds(void *, int); 96 int wssunkbd_ioctl(void *, u_long, caddr_t, int, struct proc *); 97 98 void sunkbd_wskbd_cngetc(void *, u_int *, int *); 99 void sunkbd_wskbd_cnpollc(void *, int); 100 void sunkbd_wskbd_cnbell(void *, u_int, u_int, u_int); 101 static void sunkbd_bell_off(void *v); 102 103 const struct wskbd_accessops sunkbd_wskbd_accessops = { 104 wssunkbd_enable, 105 wssunkbd_set_leds, 106 wssunkbd_ioctl, 107 }; 108 109 extern const struct wscons_keydesc wssun_keydesctab[]; 110 const struct wskbd_mapdata sunkbd_wskbd_keymapdata = { 111 wssun_keydesctab, 112 #ifdef SUNKBD_LAYOUT 113 SUNKBD_LAYOUT, 114 #else 115 KB_US, 116 #endif 117 }; 118 119 const struct wskbd_consops sunkbd_wskbd_consops = { 120 sunkbd_wskbd_cngetc, 121 sunkbd_wskbd_cnpollc, 122 sunkbd_wskbd_cnbell, 123 }; 124 125 void kbd_wskbd_attach(struct kbd_softc *k, int isconsole); 126 #endif 127 128 /* ioctl helpers */ 129 static int kbd_iockeymap(struct kbd_state *ks, 130 u_long cmd, struct kiockeymap *kio); 131 #ifdef KIOCGETKEY 132 static int kbd_oldkeymap(struct kbd_state *ks, 133 u_long cmd, struct okiockey *okio); 134 #endif 135 136 137 /* callbacks for console driver */ 138 static int kbd_cc_open(struct cons_channel *); 139 static int kbd_cc_close(struct cons_channel *); 140 141 /* console input */ 142 static void kbd_input_console(struct kbd_softc *, int); 143 static void kbd_repeat(void *); 144 static int kbd_input_keysym(struct kbd_softc *, int); 145 static void kbd_input_string(struct kbd_softc *, char *); 146 static void kbd_input_funckey(struct kbd_softc *, int); 147 static void kbd_update_leds(struct kbd_softc *); 148 149 #if NWSKBD > 0 150 static void kbd_input_wskbd(struct kbd_softc *, int); 151 #endif 152 153 /* firm events input */ 154 static void kbd_input_event(struct kbd_softc *, int); 155 156 157 158 /**************************************************************** 159 * Entry points for /dev/kbd 160 * (open,close,read,write,...) 161 ****************************************************************/ 162 163 /* 164 * Open: 165 * Check exclusion, open actual device (_iopen), 166 * setup event channel, clear ASCII repeat stuff. 167 */ 168 int 169 kbdopen(dev, flags, mode, p) 170 dev_t dev; 171 int flags, mode; 172 struct proc *p; 173 { 174 struct kbd_softc *k; 175 int error, unit; 176 177 /* locate device */ 178 unit = minor(dev); 179 if (unit >= kbd_cd.cd_ndevs) 180 return (ENXIO); 181 k = kbd_cd.cd_devs[unit]; 182 if (k == NULL) 183 return (ENXIO); 184 185 /* 186 * NB: wscons support: while we can track if wskbd has called 187 * enable(), we can't tell if that's for console input or for 188 * events input, so we should probably just let the open to 189 * always succeed regardless (e.g. Xsun opening /dev/kbd). 190 */ 191 192 /* exclusive open required for /dev/kbd */ 193 if (k->k_events.ev_io) 194 return (EBUSY); 195 k->k_events.ev_io = p; 196 197 /* stop pending autorepeat of console input */ 198 if (k->k_repeating) { 199 k->k_repeating = 0; 200 callout_stop(&k->k_repeat_ch); 201 } 202 203 /* open actual underlying device */ 204 if (k->k_ops != NULL && k->k_ops->open != NULL) 205 if ((error = (*k->k_ops->open)(k)) != 0) { 206 k->k_events.ev_io = NULL; 207 return (error); 208 } 209 210 ev_init(&k->k_events); 211 k->k_evmode = 0; /* XXX: OK? */ 212 213 return (0); 214 } 215 216 217 /* 218 * Close: 219 * Turn off event mode, dump the queue, and close the keyboard 220 * unless it is supplying console input. 221 */ 222 int 223 kbdclose(dev, flags, mode, p) 224 dev_t dev; 225 int flags, mode; 226 struct proc *p; 227 { 228 struct kbd_softc *k; 229 230 k = kbd_cd.cd_devs[minor(dev)]; 231 k->k_evmode = 0; 232 ev_fini(&k->k_events); 233 k->k_events.ev_io = NULL; 234 235 if (k->k_ops != NULL && k->k_ops->close != NULL) { 236 int error; 237 if ((error = (*k->k_ops->close)(k)) != 0) 238 return (error); 239 } 240 return (0); 241 } 242 243 244 int 245 kbdread(dev, uio, flags) 246 dev_t dev; 247 struct uio *uio; 248 int flags; 249 { 250 struct kbd_softc *k; 251 252 k = kbd_cd.cd_devs[minor(dev)]; 253 return (ev_read(&k->k_events, uio, flags)); 254 } 255 256 257 int 258 kbdpoll(dev, events, p) 259 dev_t dev; 260 int events; 261 struct proc *p; 262 { 263 struct kbd_softc *k; 264 265 k = kbd_cd.cd_devs[minor(dev)]; 266 return (ev_poll(&k->k_events, events, p)); 267 } 268 269 int 270 kbdkqfilter(dev, kn) 271 dev_t dev; 272 struct knote *kn; 273 { 274 struct kbd_softc *k; 275 276 k = kbd_cd.cd_devs[minor(dev)]; 277 return (ev_kqfilter(&k->k_events, kn)); 278 } 279 280 int 281 kbdioctl(dev, cmd, data, flag, p) 282 dev_t dev; 283 u_long cmd; 284 caddr_t data; 285 int flag; 286 struct proc *p; 287 { 288 struct kbd_softc *k; 289 struct kbd_state *ks; 290 int error = 0; 291 292 k = kbd_cd.cd_devs[minor(dev)]; 293 ks = &k->k_state; 294 295 switch (cmd) { 296 297 case KIOCTRANS: /* Set translation mode */ 298 /* We only support "raw" mode on /dev/kbd */ 299 if (*(int *)data != TR_UNTRANS_EVENT) 300 error = EINVAL; 301 break; 302 303 case KIOCGTRANS: /* Get translation mode */ 304 /* We only support "raw" mode on /dev/kbd */ 305 *(int *)data = TR_UNTRANS_EVENT; 306 break; 307 308 #ifdef KIOCGETKEY 309 case KIOCGETKEY: /* Get keymap entry (old format) */ 310 error = kbd_oldkeymap(ks, cmd, (struct okiockey *)data); 311 break; 312 #endif /* KIOCGETKEY */ 313 314 case KIOCSKEY: /* Set keymap entry */ 315 /* FALLTHROUGH */ 316 case KIOCGKEY: /* Get keymap entry */ 317 error = kbd_iockeymap(ks, cmd, (struct kiockeymap *)data); 318 break; 319 320 case KIOCCMD: /* Send a command to the keyboard */ 321 /* pass it to the middle layer */ 322 if (k->k_ops != NULL && k->k_ops->docmd != NULL) 323 error = (*k->k_ops->docmd)(k, *(int *)data, 1); 324 break; 325 326 case KIOCTYPE: /* Get keyboard type */ 327 *(int *)data = ks->kbd_id; 328 break; 329 330 case KIOCSDIRECT: /* Where to send input */ 331 k->k_evmode = *(int *)data; 332 break; 333 334 case KIOCLAYOUT: /* Get keyboard layout */ 335 *(int *)data = ks->kbd_layout; 336 break; 337 338 case KIOCSLED: /* Set keyboard LEDs */ 339 /* pass the request to the middle layer */ 340 if (k->k_ops != NULL && k->k_ops->setleds != NULL) 341 error = (*k->k_ops->setleds)(k, *(char *)data, 1); 342 break; 343 344 case KIOCGLED: /* Get keyboard LEDs */ 345 *(char *)data = ks->kbd_leds; 346 break; 347 348 case FIONBIO: /* we will remove this someday (soon???) */ 349 break; 350 351 case FIOASYNC: 352 k->k_events.ev_async = (*(int *)data != 0); 353 break; 354 355 case FIOSETOWN: 356 if (-*(int *)data != k->k_events.ev_io->p_pgid 357 && *(int *)data != k->k_events.ev_io->p_pid) 358 error = EPERM; 359 break; 360 361 case TIOCSPGRP: 362 if (*(int *)data != k->k_events.ev_io->p_pgid) 363 error = EPERM; 364 break; 365 366 default: 367 error = ENOTTY; 368 break; 369 } 370 371 return (error); 372 } 373 374 375 /**************************************************************** 376 * ioctl helpers 377 ****************************************************************/ 378 379 /* 380 * Get/Set keymap entry 381 */ 382 static int 383 kbd_iockeymap(ks, cmd, kio) 384 struct kbd_state *ks; 385 u_long cmd; 386 struct kiockeymap *kio; 387 { 388 u_short *km; 389 u_int station; 390 391 switch (kio->kio_tablemask) { 392 case KIOC_NOMASK: 393 km = ks->kbd_k.k_normal; 394 break; 395 case KIOC_SHIFTMASK: 396 km = ks->kbd_k.k_shifted; 397 break; 398 case KIOC_CTRLMASK: 399 km = ks->kbd_k.k_control; 400 break; 401 case KIOC_UPMASK: 402 km = ks->kbd_k.k_release; 403 break; 404 default: 405 /* Silently ignore unsupported masks */ 406 return (0); 407 } 408 409 /* Range-check the table position. */ 410 station = kio->kio_station; 411 if (station >= KEYMAP_SIZE) 412 return (EINVAL); 413 414 switch (cmd) { 415 416 case KIOCGKEY: /* Get keymap entry */ 417 kio->kio_entry = km[station]; 418 break; 419 420 case KIOCSKEY: /* Set keymap entry */ 421 km[station] = kio->kio_entry; 422 break; 423 424 default: 425 return(ENOTTY); 426 } 427 return (0); 428 } 429 430 431 #ifdef KIOCGETKEY 432 /* 433 * Get/Set keymap entry, 434 * old format (compatibility) 435 */ 436 int 437 kbd_oldkeymap(ks, cmd, kio) 438 struct kbd_state *ks; 439 u_long cmd; 440 struct okiockey *kio; 441 { 442 int error = 0; 443 444 switch (cmd) { 445 446 case KIOCGETKEY: 447 if (kio->kio_station == 118) { 448 /* 449 * This is X11 asking if a type 3 keyboard is 450 * really a type 3 keyboard. Say yes, it is, 451 * by reporting key station 118 as a "hole". 452 * Note old (SunOS 3.5) definition of HOLE! 453 */ 454 kio->kio_entry = 0xA2; 455 break; 456 } 457 /* fall through */ 458 459 default: 460 error = ENOTTY; 461 break; 462 } 463 464 return (error); 465 } 466 #endif /* KIOCGETKEY */ 467 468 469 470 /**************************************************************** 471 * Keyboard input - called by middle layer at spltty(). 472 ****************************************************************/ 473 474 void 475 kbd_input(k, code) 476 struct kbd_softc *k; 477 int code; 478 { 479 if (k->k_evmode) { 480 /* 481 * XXX: is this still true? 482 * IDLEs confuse the MIT X11R4 server badly, so we must drop them. 483 * This is bad as it means the server will not automatically resync 484 * on all-up IDLEs, but I did not drop them before, and the server 485 * goes crazy when it comes time to blank the screen.... 486 */ 487 if (code == KBD_IDLE) 488 return; 489 490 /* 491 * Keyboard is generating firm events. Turn this keystroke 492 * into an event and put it in the queue. 493 */ 494 kbd_input_event(k, code); 495 return; 496 } 497 498 #if NWSKBD > 0 499 if (k->k_wskbd != NULL && k->k_wsenabled) { 500 /* 501 * We are using wskbd input mode, pass the event up. 502 */ 503 kbd_input_wskbd(k, code); 504 return; 505 } 506 #endif 507 508 /* 509 * If /dev/kbd is not connected in event mode, or wskbd mode, 510 * translate and send upstream (to console). 511 */ 512 kbd_input_console(k, code); 513 } 514 515 516 517 /**************************************************************** 518 * Open/close routines called upon opening /dev/console 519 * if we serve console input. 520 ****************************************************************/ 521 522 struct cons_channel * 523 kbd_cc_alloc(k) 524 struct kbd_softc *k; 525 { 526 struct cons_channel *cc; 527 528 if ((cc = malloc(sizeof *cc, M_DEVBUF, M_NOWAIT)) == NULL) 529 return (NULL); 530 531 /* our callbacks for the console driver */ 532 cc->cc_dev = k; 533 cc->cc_iopen = kbd_cc_open; 534 cc->cc_iclose = kbd_cc_close; 535 536 /* will be provided by the console driver so that we can feed input */ 537 cc->cc_upstream = NULL; 538 539 /* 540 * TODO: clean up cons_attach_input() vs kd_attach_input() in 541 * lower layers and move that code here. 542 */ 543 544 k->k_cc = cc; 545 return (cc); 546 } 547 548 549 static int 550 kbd_cc_open(cc) 551 struct cons_channel *cc; 552 { 553 struct kbd_softc *k; 554 int ret; 555 556 if (cc == NULL) 557 return (0); 558 559 k = (struct kbd_softc *)cc->cc_dev; 560 if (k == NULL) 561 return (0); 562 563 if (k->k_ops != NULL && k->k_ops->open != NULL) 564 ret = (*k->k_ops->open)(k); 565 else 566 ret = 0; 567 568 /* XXX: verify that callout is not active? */ 569 k->k_repeat_start = hz/2; 570 k->k_repeat_step = hz/20; 571 callout_init(&k->k_repeat_ch); 572 573 return (ret); 574 } 575 576 577 static int 578 kbd_cc_close(cc) 579 struct cons_channel *cc; 580 { 581 struct kbd_softc *k; 582 int ret; 583 584 if (cc == NULL) 585 return (0); 586 587 k = (struct kbd_softc *)cc->cc_dev; 588 if (k == NULL) 589 return (0); 590 591 if (k->k_ops != NULL && k->k_ops->close != NULL) 592 ret = (*k->k_ops->close)(k); 593 else 594 ret = 0; 595 596 /* stop any pending auto-repeat */ 597 if (k->k_repeating) { 598 k->k_repeating = 0; 599 callout_stop(&k->k_repeat_ch); 600 } 601 602 return (ret); 603 } 604 605 606 607 /**************************************************************** 608 * Console input - called by middle layer at spltty(). 609 ****************************************************************/ 610 611 static void 612 kbd_input_console(k, code) 613 struct kbd_softc *k; 614 int code; 615 { 616 struct kbd_state *ks= &k->k_state; 617 int keysym; 618 619 /* any input stops auto-repeat (i.e. key release) */ 620 if (k->k_repeating) { 621 k->k_repeating = 0; 622 callout_stop(&k->k_repeat_ch); 623 } 624 625 keysym = kbd_code_to_keysym(ks, code); 626 627 /* pass to console */ 628 if (kbd_input_keysym(k, keysym)) { 629 log(LOG_WARNING, "%s: code=0x%x with mod=0x%x" 630 " produced unexpected keysym 0x%x\n", 631 k->k_dev.dv_xname, 632 code, ks->kbd_modbits, keysym); 633 return; /* no point in auto-repeat here */ 634 } 635 636 if (KEYSYM_NOREPEAT(keysym)) 637 return; 638 639 /* setup for auto-repeat after initial delay */ 640 k->k_repeating = 1; 641 k->k_repeatsym = keysym; 642 callout_reset(&k->k_repeat_ch, k->k_repeat_start, 643 kbd_repeat, k); 644 } 645 646 647 /* 648 * This is the autorepeat callout function scheduled by kbd_input() above. 649 * Called at splsoftclock(). 650 */ 651 static void 652 kbd_repeat(arg) 653 void *arg; 654 { 655 struct kbd_softc *k = (struct kbd_softc *)arg; 656 int s; 657 658 s = spltty(); 659 if (k->k_repeating && k->k_repeatsym >= 0) { 660 /* feed typematic keysym to the console */ 661 (void)kbd_input_keysym(k, k->k_repeatsym); 662 663 /* reschedule next repeat */ 664 callout_reset(&k->k_repeat_ch, k->k_repeat_step, 665 kbd_repeat, k); 666 } 667 splx(s); 668 } 669 670 671 672 /* 673 * Supply keysym as console input. Convert keysym to character(s) and 674 * pass them up to cons_channel's upstream hook. 675 * 676 * Return zero on success, else the keysym that we could not handle 677 * (so that the caller may complain). 678 */ 679 static int 680 kbd_input_keysym(k, keysym) 681 struct kbd_softc *k; 682 int keysym; 683 { 684 struct kbd_state *ks = &k->k_state; 685 int data; 686 687 /* Check if a recipient has been configured */ 688 if (k->k_cc == NULL || k->k_cc->cc_upstream == NULL) 689 return (0); 690 691 switch (KEYSYM_CLASS(keysym)) { 692 693 case KEYSYM_ASCII: 694 data = KEYSYM_DATA(keysym); 695 if (ks->kbd_modbits & KBMOD_META_MASK) 696 data |= 0x80; 697 (*k->k_cc->cc_upstream)(data); 698 break; 699 700 case KEYSYM_STRING: 701 data = keysym & 0xF; 702 kbd_input_string(k, kbd_stringtab[data]); 703 break; 704 705 case KEYSYM_FUNC: 706 kbd_input_funckey(k, keysym); 707 break; 708 709 case KEYSYM_CLRMOD: 710 data = 1 << (keysym & 0x1F); 711 ks->kbd_modbits &= ~data; 712 break; 713 714 case KEYSYM_SETMOD: 715 data = 1 << (keysym & 0x1F); 716 ks->kbd_modbits |= data; 717 break; 718 719 case KEYSYM_INVMOD: 720 data = 1 << (keysym & 0x1F); 721 ks->kbd_modbits ^= data; 722 kbd_update_leds(k); 723 break; 724 725 case KEYSYM_ALL_UP: 726 ks->kbd_modbits &= ~0xFFFF; 727 break; 728 729 case KEYSYM_SPECIAL: 730 if (keysym == KEYSYM_NOP) 731 break; 732 /* FALLTHROUGH */ 733 default: 734 /* We could not handle it. */ 735 return (keysym); 736 } 737 738 return (0); 739 } 740 741 742 /* 743 * Send string upstream. 744 */ 745 static void 746 kbd_input_string(k, str) 747 struct kbd_softc *k; 748 char *str; 749 { 750 751 while (*str) { 752 (*k->k_cc->cc_upstream)(*str); 753 ++str; 754 } 755 } 756 757 758 /* 759 * Format the F-key sequence and send as a string. 760 * XXX: Ugly compatibility mappings. 761 */ 762 static void 763 kbd_input_funckey(k, keysym) 764 struct kbd_softc *k; 765 int keysym; 766 { 767 int n; 768 char str[12]; 769 770 n = 0xC0 + (keysym & 0x3F); 771 snprintf(str, sizeof(str), "\033[%dz", n); 772 kbd_input_string(k, str); 773 } 774 775 776 /* 777 * Update LEDs to reflect console input state. 778 */ 779 static void 780 kbd_update_leds(k) 781 struct kbd_softc *k; 782 { 783 struct kbd_state *ks = &k->k_state; 784 char leds; 785 786 leds = ks->kbd_leds; 787 leds &= ~(LED_CAPS_LOCK|LED_NUM_LOCK); 788 789 if (ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) 790 leds |= LED_CAPS_LOCK; 791 if (ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) 792 leds |= LED_NUM_LOCK; 793 794 if (k->k_ops != NULL && k->k_ops->setleds != NULL) 795 (void)(*k->k_ops->setleds)(k, leds, 0); 796 } 797 798 799 800 /**************************************************************** 801 * Events input - called by middle layer at spltty(). 802 ****************************************************************/ 803 804 /* 805 * Supply raw keystrokes when keyboard is open in firm event mode. 806 * 807 * Turn the keystroke into an event and put it in the queue. 808 * If the queue is full, the keystroke is lost (sorry!). 809 */ 810 static void 811 kbd_input_event(k, code) 812 struct kbd_softc *k; 813 int code; 814 { 815 struct firm_event *fe; 816 int put; 817 818 #ifdef DIAGNOSTIC 819 if (!k->k_evmode) { 820 printf("%s: kbd_input_event called when not in event mode\n", 821 k->k_dev.dv_xname); 822 return; 823 } 824 #endif 825 put = k->k_events.ev_put; 826 fe = &k->k_events.ev_q[put]; 827 put = (put + 1) % EV_QSIZE; 828 if (put == k->k_events.ev_get) { 829 log(LOG_WARNING, "%s: event queue overflow\n", 830 k->k_dev.dv_xname); 831 return; 832 } 833 834 fe->id = KEY_CODE(code); 835 fe->value = KEY_UP(code) ? VKEY_UP : VKEY_DOWN; 836 fe->time = time; 837 k->k_events.ev_put = put; 838 EV_WAKEUP(&k->k_events); 839 } 840 841 842 843 /**************************************************************** 844 * Translation stuff declared in kbd_xlate.h 845 ****************************************************************/ 846 847 /* 848 * Initialization - called by either lower layer attach or by kdcninit. 849 */ 850 void 851 kbd_xlate_init(ks) 852 struct kbd_state *ks; 853 { 854 struct keyboard *ktbls; 855 int id; 856 857 id = ks->kbd_id; 858 if (id < KBD_MIN_TYPE) 859 id = KBD_MIN_TYPE; 860 if (id > kbd_max_type) 861 id = kbd_max_type; 862 ktbls = keyboards[id]; 863 864 ks->kbd_k = *ktbls; /* struct assignment */ 865 ks->kbd_modbits = 0; 866 } 867 868 /* 869 * Turn keyboard up/down codes into a KEYSYM. 870 * Note that the "kd" driver (on sun3 and sparc64) uses this too! 871 */ 872 int 873 kbd_code_to_keysym(ks, c) 874 struct kbd_state *ks; 875 int c; 876 { 877 u_short *km; 878 int keysym; 879 880 /* 881 * Get keymap pointer. One of these: 882 * release, control, shifted, normal, ... 883 */ 884 if (KEY_UP(c)) 885 km = ks->kbd_k.k_release; 886 else if (ks->kbd_modbits & KBMOD_CTRL_MASK) 887 km = ks->kbd_k.k_control; 888 else if (ks->kbd_modbits & KBMOD_SHIFT_MASK) 889 km = ks->kbd_k.k_shifted; 890 else 891 km = ks->kbd_k.k_normal; 892 893 if (km == NULL) { 894 /* 895 * Do not know how to translate yet. 896 * We will find out when a RESET comes along. 897 */ 898 return (KEYSYM_NOP); 899 } 900 keysym = km[KEY_CODE(c)]; 901 902 /* 903 * Post-processing for Caps-lock 904 */ 905 if ((ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) && 906 (KEYSYM_CLASS(keysym) == KEYSYM_ASCII) ) 907 { 908 if (('a' <= keysym) && (keysym <= 'z')) 909 keysym -= ('a' - 'A'); 910 } 911 912 /* 913 * Post-processing for Num-lock. All "function" 914 * keysyms get indirected through another table. 915 * (XXX: Only if numlock on. Want off also!) 916 */ 917 if ((ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) && 918 (KEYSYM_CLASS(keysym) == KEYSYM_FUNC) ) 919 { 920 keysym = kbd_numlock_map[keysym & 0x3F]; 921 } 922 923 return (keysym); 924 } 925 926 927 /* 928 * Back door for rcons (fb.c) 929 */ 930 void 931 kbd_bell(on) 932 int on; 933 { 934 struct kbd_softc *k = kbd_cd.cd_devs[0]; /* XXX: hardcoded minor */ 935 936 if (k == NULL || k->k_ops == NULL || k->k_ops->docmd == NULL) 937 return; 938 939 (void)(*k->k_ops->docmd)(k, on ? KBD_CMD_BELL : KBD_CMD_NOBELL, 0); 940 } 941 942 #if NWSKBD > 0 943 static void 944 kbd_input_wskbd(struct kbd_softc *k, int code) 945 { 946 int type, key; 947 948 type = KEY_UP(code) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 949 key = KEY_CODE(code); 950 wskbd_input(k->k_wskbd, type, key); 951 } 952 953 int 954 wssunkbd_enable(v, on) 955 void *v; 956 int on; 957 { 958 struct kbd_softc *k = v; 959 960 k->k_wsenabled = on; 961 if (on) { 962 /* open actual underlying device */ 963 if (k->k_ops != NULL && k->k_ops->open != NULL) 964 (*k->k_ops->open)(k); 965 ev_init(&k->k_events); 966 k->k_evmode = 0; /* XXX: OK? */ 967 } else { 968 /* close underlying device */ 969 if (k->k_ops != NULL && k->k_ops->close != NULL) 970 (*k->k_ops->close)(k); 971 } 972 973 return 0; 974 } 975 976 void 977 wssunkbd_set_leds(v, leds) 978 void *v; 979 int leds; 980 { 981 struct kbd_softc *k = v; 982 int l = 0; 983 984 if (leds & WSKBD_LED_CAPS) 985 l |= LED_CAPS_LOCK; 986 if (leds & WSKBD_LED_NUM) 987 l |= LED_NUM_LOCK; 988 if (leds & WSKBD_LED_SCROLL) 989 l |= LED_SCROLL_LOCK; 990 if (leds & WSKBD_LED_COMPOSE) 991 l |= LED_COMPOSE; 992 if (k->k_ops != NULL && k->k_ops->setleds != NULL) 993 (*k->k_ops->setleds)(k, l, 0); 994 } 995 996 int 997 wssunkbd_ioctl(v, cmd, data, flag, p) 998 void *v; 999 u_long cmd; 1000 caddr_t data; 1001 int flag; 1002 struct proc *p; 1003 { 1004 return EPASSTHROUGH; 1005 } 1006 1007 void 1008 sunkbd_wskbd_cngetc(v, type, data) 1009 void *v; 1010 u_int *type; 1011 int *data; 1012 { 1013 /* struct kbd_sun_softc *k = v; */ 1014 } 1015 1016 void 1017 sunkbd_wskbd_cnpollc(v, on) 1018 void *v; 1019 int on; 1020 { 1021 } 1022 1023 static void 1024 sunkbd_bell_off(v) 1025 void *v; 1026 { 1027 struct kbd_softc *k = v; 1028 k->k_ops->docmd(k, KBD_CMD_NOBELL, 0); 1029 } 1030 1031 void 1032 sunkbd_wskbd_cnbell(v, pitch, period, volume) 1033 void *v; 1034 u_int pitch, period, volume; 1035 { 1036 struct kbd_softc *k = v; 1037 1038 callout_reset(&k->k_wsbell, period*1000/hz, sunkbd_bell_off, v); 1039 k->k_ops->docmd(k, KBD_CMD_BELL, 0); 1040 } 1041 1042 void 1043 kbd_wskbd_attach(k, isconsole) 1044 struct kbd_softc *k; 1045 int isconsole; 1046 { 1047 struct wskbddev_attach_args a; 1048 1049 a.console = isconsole; 1050 1051 if (a.console) 1052 wskbd_cnattach(&sunkbd_wskbd_consops, k, &sunkbd_wskbd_keymapdata); 1053 1054 a.keymap = &sunkbd_wskbd_keymapdata; 1055 1056 a.accessops = &sunkbd_wskbd_accessops; 1057 a.accesscookie = k; 1058 1059 /* Attach the wskbd */ 1060 k->k_wskbd = config_found(&k->k_dev, &a, wskbddevprint); 1061 k->k_wsenabled = 0; 1062 callout_init(&k->k_wsbell); 1063 } 1064 #endif 1065