1 /* $NetBSD: kbd.c,v 1.40 2004/04/22 00:17:13 itojun 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.40 2004/04/22 00:17:13 itojun 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 __P((void *, int)); 95 void wssunkbd_set_leds __P((void *, int)); 96 int wssunkbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 97 98 void sunkbd_wskbd_cngetc __P((void *, u_int *, int *)); 99 void sunkbd_wskbd_cnpollc __P((void *, int)); 100 void sunkbd_wskbd_cnbell __P((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 #ifdef KBD_IDLE_EVENTS 482 /* 483 * XXX: is this still true? 484 * IDLEs confuse the MIT X11R4 server badly, so we must drop them. 485 * This is bad as it means the server will not automatically resync 486 * on all-up IDLEs, but I did not drop them before, and the server 487 * goes crazy when it comes time to blank the screen.... 488 */ 489 if (code == KBD_IDLE) 490 return; 491 #endif 492 493 /* 494 * Keyboard is generating firm events. Turn this keystroke 495 * into an event and put it in the queue. 496 */ 497 kbd_input_event(k, code); 498 return; 499 } 500 501 #if NWSKBD > 0 502 if (k->k_wskbd != NULL && k->k_wsenabled) { 503 /* 504 * We are using wskbd input mode, pass the event up. 505 */ 506 kbd_input_wskbd(k, code); 507 return; 508 } 509 #endif 510 511 /* 512 * If /dev/kbd is not connected in event mode, or wskbd mode, 513 * translate and send upstream (to console). 514 */ 515 kbd_input_console(k, code); 516 } 517 518 519 520 /**************************************************************** 521 * Open/close routines called upon opening /dev/console 522 * if we serve console input. 523 ****************************************************************/ 524 525 struct cons_channel * 526 kbd_cc_alloc(k) 527 struct kbd_softc *k; 528 { 529 struct cons_channel *cc; 530 531 if ((cc = malloc(sizeof *cc, M_DEVBUF, M_NOWAIT)) == NULL) 532 return (NULL); 533 534 /* our callbacks for the console driver */ 535 cc->cc_dev = k; 536 cc->cc_iopen = kbd_cc_open; 537 cc->cc_iclose = kbd_cc_close; 538 539 /* will be provided by the console driver so that we can feed input */ 540 cc->cc_upstream = NULL; 541 542 /* 543 * TODO: clean up cons_attach_input() vs kd_attach_input() in 544 * lower layers and move that code here. 545 */ 546 547 k->k_cc = cc; 548 return (cc); 549 } 550 551 552 static int 553 kbd_cc_open(cc) 554 struct cons_channel *cc; 555 { 556 struct kbd_softc *k; 557 int ret; 558 559 if (cc == NULL) 560 return (0); 561 562 k = (struct kbd_softc *)cc->cc_dev; 563 if (k == NULL) 564 return (0); 565 566 if (k->k_ops != NULL && k->k_ops->open != NULL) 567 ret = (*k->k_ops->open)(k); 568 else 569 ret = 0; 570 571 /* XXX: verify that callout is not active? */ 572 k->k_repeat_start = hz/2; 573 k->k_repeat_step = hz/20; 574 callout_init(&k->k_repeat_ch); 575 576 return (ret); 577 } 578 579 580 static int 581 kbd_cc_close(cc) 582 struct cons_channel *cc; 583 { 584 struct kbd_softc *k; 585 int ret; 586 587 if (cc == NULL) 588 return (0); 589 590 k = (struct kbd_softc *)cc->cc_dev; 591 if (k == NULL) 592 return (0); 593 594 if (k->k_ops != NULL && k->k_ops->close != NULL) 595 ret = (*k->k_ops->close)(k); 596 else 597 ret = 0; 598 599 /* stop any pending auto-repeat */ 600 if (k->k_repeating) { 601 k->k_repeating = 0; 602 callout_stop(&k->k_repeat_ch); 603 } 604 605 return (ret); 606 } 607 608 609 610 /**************************************************************** 611 * Console input - called by middle layer at spltty(). 612 ****************************************************************/ 613 614 static void 615 kbd_input_console(k, code) 616 struct kbd_softc *k; 617 int code; 618 { 619 struct kbd_state *ks= &k->k_state; 620 int keysym; 621 622 /* any input stops auto-repeat (i.e. key release) */ 623 if (k->k_repeating) { 624 k->k_repeating = 0; 625 callout_stop(&k->k_repeat_ch); 626 } 627 628 keysym = kbd_code_to_keysym(ks, code); 629 630 /* pass to console */ 631 if (kbd_input_keysym(k, keysym)) { 632 log(LOG_WARNING, "%s: code=0x%x with mod=0x%x" 633 " produced unexpected keysym 0x%x\n", 634 k->k_dev.dv_xname, 635 code, ks->kbd_modbits, keysym); 636 return; /* no point in auto-repeat here */ 637 } 638 639 if (KEYSYM_NOREPEAT(keysym)) 640 return; 641 642 /* setup for auto-repeat after initial delay */ 643 k->k_repeating = 1; 644 k->k_repeatsym = keysym; 645 callout_reset(&k->k_repeat_ch, k->k_repeat_start, 646 kbd_repeat, k); 647 } 648 649 650 /* 651 * This is the autorepeat callout function scheduled by kbd_input() above. 652 * Called at splsoftclock(). 653 */ 654 static void 655 kbd_repeat(arg) 656 void *arg; 657 { 658 struct kbd_softc *k = (struct kbd_softc *)arg; 659 int s; 660 661 s = spltty(); 662 if (k->k_repeating && k->k_repeatsym >= 0) { 663 /* feed typematic keysym to the console */ 664 (void)kbd_input_keysym(k, k->k_repeatsym); 665 666 /* reschedule next repeat */ 667 callout_reset(&k->k_repeat_ch, k->k_repeat_step, 668 kbd_repeat, k); 669 } 670 splx(s); 671 } 672 673 674 675 /* 676 * Supply keysym as console input. Convert keysym to character(s) and 677 * pass them up to cons_channel's upstream hook. 678 * 679 * Return zero on success, else the keysym that we could not handle 680 * (so that the caller may complain). 681 */ 682 static int 683 kbd_input_keysym(k, keysym) 684 struct kbd_softc *k; 685 int keysym; 686 { 687 struct kbd_state *ks = &k->k_state; 688 int data; 689 690 /* Check if a recipient has been configured */ 691 if (k->k_cc == NULL || k->k_cc->cc_upstream == NULL) 692 return (0); 693 694 switch (KEYSYM_CLASS(keysym)) { 695 696 case KEYSYM_ASCII: 697 data = KEYSYM_DATA(keysym); 698 if (ks->kbd_modbits & KBMOD_META_MASK) 699 data |= 0x80; 700 (*k->k_cc->cc_upstream)(data); 701 break; 702 703 case KEYSYM_STRING: 704 data = keysym & 0xF; 705 kbd_input_string(k, kbd_stringtab[data]); 706 break; 707 708 case KEYSYM_FUNC: 709 kbd_input_funckey(k, keysym); 710 break; 711 712 case KEYSYM_CLRMOD: 713 data = 1 << (keysym & 0x1F); 714 ks->kbd_modbits &= ~data; 715 break; 716 717 case KEYSYM_SETMOD: 718 data = 1 << (keysym & 0x1F); 719 ks->kbd_modbits |= data; 720 break; 721 722 case KEYSYM_INVMOD: 723 data = 1 << (keysym & 0x1F); 724 ks->kbd_modbits ^= data; 725 kbd_update_leds(k); 726 break; 727 728 case KEYSYM_ALL_UP: 729 ks->kbd_modbits &= ~0xFFFF; 730 break; 731 732 case KEYSYM_SPECIAL: 733 if (keysym == KEYSYM_NOP) 734 break; 735 /* FALLTHROUGH */ 736 default: 737 /* We could not handle it. */ 738 return (keysym); 739 } 740 741 return (0); 742 } 743 744 745 /* 746 * Send string upstream. 747 */ 748 static void 749 kbd_input_string(k, str) 750 struct kbd_softc *k; 751 char *str; 752 { 753 754 while (*str) { 755 (*k->k_cc->cc_upstream)(*str); 756 ++str; 757 } 758 } 759 760 761 /* 762 * Format the F-key sequence and send as a string. 763 * XXX: Ugly compatibility mappings. 764 */ 765 static void 766 kbd_input_funckey(k, keysym) 767 struct kbd_softc *k; 768 int keysym; 769 { 770 int n; 771 char str[12]; 772 773 n = 0xC0 + (keysym & 0x3F); 774 snprintf(str, sizeof(str), "\033[%dz", n); 775 kbd_input_string(k, str); 776 } 777 778 779 /* 780 * Update LEDs to reflect console input state. 781 */ 782 static void 783 kbd_update_leds(k) 784 struct kbd_softc *k; 785 { 786 struct kbd_state *ks = &k->k_state; 787 char leds; 788 789 leds = ks->kbd_leds; 790 leds &= ~(LED_CAPS_LOCK|LED_NUM_LOCK); 791 792 if (ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) 793 leds |= LED_CAPS_LOCK; 794 if (ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) 795 leds |= LED_NUM_LOCK; 796 797 if (k->k_ops != NULL && k->k_ops->setleds != NULL) 798 (void)(*k->k_ops->setleds)(k, leds, 0); 799 } 800 801 802 803 /**************************************************************** 804 * Events input - called by middle layer at spltty(). 805 ****************************************************************/ 806 807 /* 808 * Supply raw keystrokes when keyboard is open in firm event mode. 809 * 810 * Turn the keystroke into an event and put it in the queue. 811 * If the queue is full, the keystroke is lost (sorry!). 812 */ 813 static void 814 kbd_input_event(k, code) 815 struct kbd_softc *k; 816 int code; 817 { 818 struct firm_event *fe; 819 int put; 820 821 #ifdef DIAGNOSTIC 822 if (!k->k_evmode) { 823 printf("%s: kbd_input_event called when not in event mode\n", 824 k->k_dev.dv_xname); 825 return; 826 } 827 #endif 828 put = k->k_events.ev_put; 829 fe = &k->k_events.ev_q[put]; 830 put = (put + 1) % EV_QSIZE; 831 if (put == k->k_events.ev_get) { 832 log(LOG_WARNING, "%s: event queue overflow\n", 833 k->k_dev.dv_xname); 834 return; 835 } 836 837 fe->id = KEY_CODE(code); 838 fe->value = KEY_UP(code) ? VKEY_UP : VKEY_DOWN; 839 fe->time = time; 840 k->k_events.ev_put = put; 841 EV_WAKEUP(&k->k_events); 842 } 843 844 845 846 /**************************************************************** 847 * Translation stuff declared in kbd_xlate.h 848 ****************************************************************/ 849 850 /* 851 * Initialization - called by either lower layer attach or by kdcninit. 852 */ 853 void 854 kbd_xlate_init(ks) 855 struct kbd_state *ks; 856 { 857 struct keyboard *ktbls; 858 int id; 859 860 id = ks->kbd_id; 861 if (id < KBD_MIN_TYPE) 862 id = KBD_MIN_TYPE; 863 if (id > kbd_max_type) 864 id = kbd_max_type; 865 ktbls = keyboards[id]; 866 867 ks->kbd_k = *ktbls; /* struct assignment */ 868 ks->kbd_modbits = 0; 869 } 870 871 /* 872 * Turn keyboard up/down codes into a KEYSYM. 873 * Note that the "kd" driver (on sun3 and sparc64) uses this too! 874 */ 875 int 876 kbd_code_to_keysym(ks, c) 877 struct kbd_state *ks; 878 int c; 879 { 880 u_short *km; 881 int keysym; 882 883 /* 884 * Get keymap pointer. One of these: 885 * release, control, shifted, normal, ... 886 */ 887 if (KEY_UP(c)) 888 km = ks->kbd_k.k_release; 889 else if (ks->kbd_modbits & KBMOD_CTRL_MASK) 890 km = ks->kbd_k.k_control; 891 else if (ks->kbd_modbits & KBMOD_SHIFT_MASK) 892 km = ks->kbd_k.k_shifted; 893 else 894 km = ks->kbd_k.k_normal; 895 896 if (km == NULL) { 897 /* 898 * Do not know how to translate yet. 899 * We will find out when a RESET comes along. 900 */ 901 return (KEYSYM_NOP); 902 } 903 keysym = km[KEY_CODE(c)]; 904 905 /* 906 * Post-processing for Caps-lock 907 */ 908 if ((ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) && 909 (KEYSYM_CLASS(keysym) == KEYSYM_ASCII) ) 910 { 911 if (('a' <= keysym) && (keysym <= 'z')) 912 keysym -= ('a' - 'A'); 913 } 914 915 /* 916 * Post-processing for Num-lock. All "function" 917 * keysyms get indirected through another table. 918 * (XXX: Only if numlock on. Want off also!) 919 */ 920 if ((ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) && 921 (KEYSYM_CLASS(keysym) == KEYSYM_FUNC) ) 922 { 923 keysym = kbd_numlock_map[keysym & 0x3F]; 924 } 925 926 return (keysym); 927 } 928 929 930 /* 931 * Back door for rcons (fb.c) 932 */ 933 void 934 kbd_bell(on) 935 int on; 936 { 937 struct kbd_softc *k = kbd_cd.cd_devs[0]; /* XXX: hardcoded minor */ 938 939 if (k == NULL || k->k_ops == NULL || k->k_ops->docmd == NULL) 940 return; 941 942 (void)(*k->k_ops->docmd)(k, on ? KBD_CMD_BELL : KBD_CMD_NOBELL, 0); 943 } 944 945 #if NWSKBD > 0 946 static void 947 kbd_input_wskbd(struct kbd_softc *k, int code) 948 { 949 int type, key; 950 951 type = KEY_UP(code) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 952 key = KEY_CODE(code); 953 wskbd_input(k->k_wskbd, type, key); 954 } 955 956 int 957 wssunkbd_enable(v, on) 958 void *v; 959 int on; 960 { 961 struct kbd_softc *k = v; 962 963 k->k_wsenabled = on; 964 if (on) { 965 /* open actual underlying device */ 966 if (k->k_ops != NULL && k->k_ops->open != NULL) 967 (*k->k_ops->open)(k); 968 ev_init(&k->k_events); 969 k->k_evmode = 0; /* XXX: OK? */ 970 } else { 971 /* close underlying device */ 972 if (k->k_ops != NULL && k->k_ops->close != NULL) 973 (*k->k_ops->close)(k); 974 } 975 976 return 0; 977 } 978 979 void 980 wssunkbd_set_leds(v, leds) 981 void *v; 982 int leds; 983 { 984 struct kbd_softc *k = v; 985 int l = 0; 986 987 if (leds & WSKBD_LED_CAPS) 988 l |= LED_CAPS_LOCK; 989 if (leds & WSKBD_LED_NUM) 990 l |= LED_NUM_LOCK; 991 if (leds & WSKBD_LED_SCROLL) 992 l |= LED_SCROLL_LOCK; 993 if (leds & WSKBD_LED_COMPOSE) 994 l |= LED_COMPOSE; 995 if (k->k_ops != NULL && k->k_ops->setleds != NULL) 996 (*k->k_ops->setleds)(k, l, 0); 997 } 998 999 int 1000 wssunkbd_ioctl(v, cmd, data, flag, p) 1001 void *v; 1002 u_long cmd; 1003 caddr_t data; 1004 int flag; 1005 struct proc *p; 1006 { 1007 return EPASSTHROUGH; 1008 } 1009 1010 void 1011 sunkbd_wskbd_cngetc(v, type, data) 1012 void *v; 1013 u_int *type; 1014 int *data; 1015 { 1016 /* struct kbd_sun_softc *k = v; */ 1017 } 1018 1019 void 1020 sunkbd_wskbd_cnpollc(v, on) 1021 void *v; 1022 int on; 1023 { 1024 } 1025 1026 static void 1027 sunkbd_bell_off(v) 1028 void *v; 1029 { 1030 struct kbd_softc *k = v; 1031 k->k_ops->docmd(k, KBD_CMD_NOBELL, 0); 1032 } 1033 1034 void 1035 sunkbd_wskbd_cnbell(v, pitch, period, volume) 1036 void *v; 1037 u_int pitch, period, volume; 1038 { 1039 struct kbd_softc *k = v; 1040 1041 callout_reset(&k->k_wsbell, period*1000/hz, sunkbd_bell_off, v); 1042 k->k_ops->docmd(k, KBD_CMD_BELL, 0); 1043 } 1044 1045 void 1046 kbd_wskbd_attach(k, isconsole) 1047 struct kbd_softc *k; 1048 int isconsole; 1049 { 1050 struct wskbddev_attach_args a; 1051 1052 a.console = isconsole; 1053 1054 if (a.console) 1055 wskbd_cnattach(&sunkbd_wskbd_consops, k, &sunkbd_wskbd_keymapdata); 1056 1057 a.keymap = &sunkbd_wskbd_keymapdata; 1058 1059 a.accessops = &sunkbd_wskbd_accessops; 1060 a.accesscookie = k; 1061 1062 /* Attach the wskbd */ 1063 k->k_wskbd = config_found(&k->k_dev, &a, wskbddevprint); 1064 k->k_wsenabled = 0; 1065 callout_init(&k->k_wsbell); 1066 } 1067 #endif 1068