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