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