1 /* $NetBSD: kbd.c,v 1.32 2002/10/03 16:13:25 uwe 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.32 2002/10/03 16:13:25 uwe 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/signal.h> 64 #include <sys/signalvar.h> 65 #include <sys/time.h> 66 #include <sys/syslog.h> 67 #include <sys/select.h> 68 #include <sys/poll.h> 69 #include <sys/file.h> 70 71 #include <machine/vuid_event.h> 72 #include <machine/kbd.h> 73 #include <machine/kbio.h> 74 #include <dev/sun/event_var.h> 75 #include <dev/sun/kbd_xlate.h> 76 #include <dev/sun/kbdvar.h> 77 78 #include "locators.h" 79 80 extern struct cfdriver kbd_cd; 81 82 dev_type_open(kbdopen); 83 dev_type_close(kbdclose); 84 dev_type_read(kbdread); 85 dev_type_ioctl(kbdioctl); 86 dev_type_poll(kbdpoll); 87 88 const struct cdevsw kbd_cdevsw = { 89 kbdopen, kbdclose, kbdread, nowrite, kbdioctl, 90 nostop, notty, kbdpoll, nommap, 91 }; 92 93 94 /* ioctl helpers */ 95 static int kbd_iockeymap(struct kbd_state *ks, 96 u_long cmd, struct kiockeymap *kio); 97 #ifdef KIOCGETKEY 98 static int kbd_oldkeymap(struct kbd_state *ks, 99 u_long cmd, struct okiockey *okio); 100 #endif 101 102 /* console input helpers */ 103 static void kbd_input_string(struct kbd_softc *, char *); 104 static void kbd_input_funckey(struct kbd_softc *, int); 105 static void kbd_update_leds(struct kbd_softc *); 106 107 108 /**************************************************************** 109 * Entry points for /dev/kbd 110 * (open,close,read,write,...) 111 ****************************************************************/ 112 113 /* 114 * Open: 115 * Check exclusion, open actual device (_iopen), 116 * setup event channel, clear ASCII repeat stuff. 117 */ 118 int 119 kbdopen(dev, flags, mode, p) 120 dev_t dev; 121 int flags, mode; 122 struct proc *p; 123 { 124 struct kbd_softc *k; 125 int error, unit; 126 127 /* locate device */ 128 unit = minor(dev); 129 if (unit >= kbd_cd.cd_ndevs) 130 return (ENXIO); 131 k = kbd_cd.cd_devs[unit]; 132 if (k == NULL) 133 return (ENXIO); 134 135 /* exclusive open required for /dev/kbd */ 136 if (k->k_events.ev_io) 137 return (EBUSY); 138 k->k_events.ev_io = p; 139 140 /* open actual underlying device */ 141 if (k->k_ops != NULL && k->k_ops->open != NULL) 142 if ((error = (*k->k_ops->open)(k)) != 0) { 143 k->k_events.ev_io = NULL; 144 return (error); 145 } 146 147 ev_init(&k->k_events); 148 k->k_evmode = 0; /* XXX: OK? */ 149 150 return (0); 151 } 152 153 154 /* 155 * Close: 156 * Turn off event mode, dump the queue, and close the keyboard 157 * unless it is supplying console input. 158 */ 159 int 160 kbdclose(dev, flags, mode, p) 161 dev_t dev; 162 int flags, mode; 163 struct proc *p; 164 { 165 struct kbd_softc *k; 166 167 k = kbd_cd.cd_devs[minor(dev)]; 168 k->k_evmode = 0; 169 ev_fini(&k->k_events); 170 k->k_events.ev_io = NULL; 171 172 if (k->k_ops != NULL && k->k_ops->close != NULL) { 173 int error; 174 if ((error = (*k->k_ops->close)(k)) != 0) 175 return (error); 176 } 177 return (0); 178 } 179 180 181 int 182 kbdread(dev, uio, flags) 183 dev_t dev; 184 struct uio *uio; 185 int flags; 186 { 187 struct kbd_softc *k; 188 189 k = kbd_cd.cd_devs[minor(dev)]; 190 return (ev_read(&k->k_events, uio, flags)); 191 } 192 193 194 int 195 kbdpoll(dev, events, p) 196 dev_t dev; 197 int events; 198 struct proc *p; 199 { 200 struct kbd_softc *k; 201 202 k = kbd_cd.cd_devs[minor(dev)]; 203 return (ev_poll(&k->k_events, events, p)); 204 } 205 206 207 int 208 kbdioctl(dev, cmd, data, flag, p) 209 dev_t dev; 210 u_long cmd; 211 caddr_t data; 212 int flag; 213 struct proc *p; 214 { 215 struct kbd_softc *k; 216 struct kbd_state *ks; 217 int error = 0; 218 219 k = kbd_cd.cd_devs[minor(dev)]; 220 ks = &k->k_state; 221 222 switch (cmd) { 223 224 case KIOCTRANS: /* Set translation mode */ 225 /* We only support "raw" mode on /dev/kbd */ 226 if (*(int *)data != TR_UNTRANS_EVENT) 227 error = EINVAL; 228 break; 229 230 case KIOCGTRANS: /* Get translation mode */ 231 /* We only support "raw" mode on /dev/kbd */ 232 *(int *)data = TR_UNTRANS_EVENT; 233 break; 234 235 #ifdef KIOCGETKEY 236 case KIOCGETKEY: /* Get keymap entry (old format) */ 237 error = kbd_oldkeymap(ks, cmd, (struct okiockey *)data); 238 break; 239 #endif /* KIOCGETKEY */ 240 241 case KIOCSKEY: /* Set keymap entry */ 242 /* FALLTHROUGH */ 243 case KIOCGKEY: /* Get keymap entry */ 244 error = kbd_iockeymap(ks, cmd, (struct kiockeymap *)data); 245 break; 246 247 case KIOCCMD: /* Send a command to the keyboard */ 248 /* pass it to the middle layer */ 249 if (k->k_ops != NULL && k->k_ops->docmd != NULL) 250 error = (*k->k_ops->docmd)(k, *(int *)data, 1); 251 break; 252 253 case KIOCTYPE: /* Get keyboard type */ 254 *(int *)data = ks->kbd_id; 255 break; 256 257 case KIOCSDIRECT: /* Where to send input */ 258 k->k_evmode = *(int *)data; 259 break; 260 261 case KIOCLAYOUT: /* Get keyboard layout */ 262 *(int *)data = ks->kbd_layout; 263 break; 264 265 case KIOCSLED: /* Set keyboard LEDs */ 266 /* pass the request to the middle layer */ 267 if (k->k_ops != NULL && k->k_ops->setleds != NULL) 268 error = (*k->k_ops->setleds)(k, *(char *)data, 1); 269 break; 270 271 case KIOCGLED: /* Get keyboard LEDs */ 272 *(char *)data = ks->kbd_leds; 273 break; 274 275 case FIONBIO: /* we will remove this someday (soon???) */ 276 break; 277 278 case FIOASYNC: 279 k->k_events.ev_async = (*(int *)data != 0); 280 break; 281 282 case TIOCSPGRP: 283 if (*(int *)data != k->k_events.ev_io->p_pgid) 284 error = EPERM; 285 break; 286 287 default: 288 error = ENOTTY; 289 break; 290 } 291 292 return (error); 293 } 294 295 296 /**************************************************************** 297 * ioctl helpers 298 ****************************************************************/ 299 300 /* 301 * Get/Set keymap entry 302 */ 303 static int 304 kbd_iockeymap(ks, cmd, kio) 305 struct kbd_state *ks; 306 u_long cmd; 307 struct kiockeymap *kio; 308 { 309 u_short *km; 310 u_int station; 311 312 switch (kio->kio_tablemask) { 313 case KIOC_NOMASK: 314 km = ks->kbd_k.k_normal; 315 break; 316 case KIOC_SHIFTMASK: 317 km = ks->kbd_k.k_shifted; 318 break; 319 case KIOC_CTRLMASK: 320 km = ks->kbd_k.k_control; 321 break; 322 case KIOC_UPMASK: 323 km = ks->kbd_k.k_release; 324 break; 325 default: 326 /* Silently ignore unsupported masks */ 327 return (0); 328 } 329 330 /* Range-check the table position. */ 331 station = kio->kio_station; 332 if (station >= KEYMAP_SIZE) 333 return (EINVAL); 334 335 switch (cmd) { 336 337 case KIOCGKEY: /* Get keymap entry */ 338 kio->kio_entry = km[station]; 339 break; 340 341 case KIOCSKEY: /* Set keymap entry */ 342 km[station] = kio->kio_entry; 343 break; 344 345 default: 346 return(ENOTTY); 347 } 348 return (0); 349 } 350 351 352 #ifdef KIOCGETKEY 353 /* 354 * Get/Set keymap entry, 355 * old format (compatibility) 356 */ 357 int 358 kbd_oldkeymap(ks, cmd, kio) 359 struct kbd_state *ks; 360 u_long cmd; 361 struct okiockey *kio; 362 { 363 int error = 0; 364 365 switch (cmd) { 366 367 case KIOCGETKEY: 368 if (kio->kio_station == 118) { 369 /* 370 * This is X11 asking if a type 3 keyboard is 371 * really a type 3 keyboard. Say yes, it is, 372 * by reporting key station 118 as a "hole". 373 * Note old (SunOS 3.5) definition of HOLE! 374 */ 375 kio->kio_entry = 0xA2; 376 break; 377 } 378 /* fall through */ 379 380 default: 381 error = ENOTTY; 382 break; 383 } 384 385 return (error); 386 } 387 #endif /* KIOCGETKEY */ 388 389 390 /**************************************************************** 391 * Callbacks we supply to console driver 392 ****************************************************************/ 393 394 /* 395 * Open/close routines called upon opening /dev/console 396 * if we serve console input. 397 */ 398 int 399 kbd_cc_open(cc) 400 struct cons_channel *cc; 401 { 402 struct kbd_softc *k; 403 404 if (cc == NULL) 405 return (0); 406 407 k = (struct kbd_softc *)cc->cc_dev; 408 if (k != NULL && k->k_ops != NULL && k->k_ops->open != NULL) 409 return ((*k->k_ops->open)(k)); 410 else 411 return (0); 412 } 413 414 415 int 416 kbd_cc_close(cc) 417 struct cons_channel *cc; 418 { 419 struct kbd_softc *k; 420 421 if (cc == NULL) 422 return (0); 423 424 k = (struct kbd_softc *)cc->cc_dev; 425 if (k != NULL && k->k_ops != NULL && k->k_ops->close != NULL) 426 return ((*k->k_ops->close)(k)); 427 else 428 return (0); 429 } 430 431 432 /**************************************************************** 433 * Console input - called by middle layer at spltty(). 434 ****************************************************************/ 435 436 /* 437 * Entry point for the middle layer to supply keysym as console input. 438 * Convert keysym to character(s) and pass them up to cons_channel's 439 * upstream hook. 440 * 441 * Return zero on success, else the keysym that we could not handle 442 * (so that the caller may complain). 443 */ 444 int 445 kbd_input_keysym(k, keysym) 446 struct kbd_softc *k; 447 int keysym; 448 { 449 struct kbd_state *ks = &k->k_state; 450 int data; 451 452 /* Check if a recipient has been configured */ 453 if (k->k_cc == NULL || k->k_cc->cc_upstream == NULL) 454 return (0); 455 456 switch (KEYSYM_CLASS(keysym)) { 457 458 case KEYSYM_ASCII: 459 data = KEYSYM_DATA(keysym); 460 if (ks->kbd_modbits & KBMOD_META_MASK) 461 data |= 0x80; 462 (*k->k_cc->cc_upstream)(data); 463 break; 464 465 case KEYSYM_STRING: 466 data = keysym & 0xF; 467 kbd_input_string(k, kbd_stringtab[data]); 468 break; 469 470 case KEYSYM_FUNC: 471 kbd_input_funckey(k, keysym); 472 break; 473 474 case KEYSYM_CLRMOD: 475 data = 1 << (keysym & 0x1F); 476 ks->kbd_modbits &= ~data; 477 break; 478 479 case KEYSYM_SETMOD: 480 data = 1 << (keysym & 0x1F); 481 ks->kbd_modbits |= data; 482 break; 483 484 case KEYSYM_INVMOD: 485 data = 1 << (keysym & 0x1F); 486 ks->kbd_modbits ^= data; 487 kbd_update_leds(k); 488 break; 489 490 case KEYSYM_ALL_UP: 491 ks->kbd_modbits &= ~0xFFFF; 492 break; 493 494 case KEYSYM_SPECIAL: 495 if (keysym == KEYSYM_NOP) 496 break; 497 /* FALLTHROUGH */ 498 default: 499 /* We could not handle it. */ 500 return (keysym); 501 } 502 503 return (0); 504 } 505 506 507 /* 508 * Send string upstream. 509 */ 510 static void 511 kbd_input_string(k, str) 512 struct kbd_softc *k; 513 char *str; 514 { 515 516 while (*str) { 517 (*k->k_cc->cc_upstream)(*str); 518 ++str; 519 } 520 } 521 522 523 /* 524 * Format the F-key sequence and send as a string. 525 * XXX: Ugly compatibility mappings. 526 */ 527 static void 528 kbd_input_funckey(k, keysym) 529 struct kbd_softc *k; 530 int keysym; 531 { 532 int n; 533 char str[12]; 534 535 n = 0xC0 + (keysym & 0x3F); 536 sprintf(str, "\033[%dz", n); 537 kbd_input_string(k, str); 538 } 539 540 541 /* 542 * Update LEDs to reflect console input state. 543 */ 544 static void 545 kbd_update_leds(k) 546 struct kbd_softc *k; 547 { 548 struct kbd_state *ks = &k->k_state; 549 char leds; 550 551 leds = ks->kbd_leds; 552 leds &= ~(LED_CAPS_LOCK|LED_NUM_LOCK); 553 554 if (ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) 555 leds |= LED_CAPS_LOCK; 556 if (ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) 557 leds |= LED_NUM_LOCK; 558 559 if (k->k_ops != NULL && k->k_ops->setleds != NULL) 560 (void)(*k->k_ops->setleds)(k, leds, 0); 561 } 562 563 564 565 /**************************************************************** 566 * Events input - called by middle layer at spltty(). 567 ****************************************************************/ 568 569 /* 570 * Entry point for the middle layer to supply raw keystrokes when 571 * keyboard is open (i.e. is in event mode). 572 * 573 * Turn the keystroke into an event and put it in the queue. 574 * If the queue is full, the keystroke is lost (sorry!). 575 */ 576 void 577 kbd_input_event(k, c) 578 struct kbd_softc *k; 579 int c; 580 { 581 struct firm_event *fe; 582 int put; 583 584 #ifdef DIAGNOSTIC 585 if (!k->k_evmode) { 586 printf("%s: kbd_input_event called when not in event mode\n", 587 k->k_dev.dv_xname); 588 return; 589 } 590 #endif 591 put = k->k_events.ev_put; 592 fe = &k->k_events.ev_q[put]; 593 put = (put + 1) % EV_QSIZE; 594 if (put == k->k_events.ev_get) { 595 log(LOG_WARNING, "%s: event queue overflow\n", 596 k->k_dev.dv_xname); 597 return; 598 } 599 fe->id = KEY_CODE(c); 600 fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN; 601 fe->time = time; 602 k->k_events.ev_put = put; 603 EV_WAKEUP(&k->k_events); 604 } 605 606 607 /**************************************************************** 608 * Translation stuff declared in kbd_xlate.h 609 ****************************************************************/ 610 611 /* 612 * Initialization - called by either lower layer attach or by kdcninit. 613 */ 614 void 615 kbd_xlate_init(ks) 616 struct kbd_state *ks; 617 { 618 struct keyboard *ktbls; 619 int id; 620 621 id = ks->kbd_id; 622 if (id < KBD_MIN_TYPE) 623 id = KBD_MIN_TYPE; 624 if (id > kbd_max_type) 625 id = kbd_max_type; 626 ktbls = keyboards[id]; 627 628 ks->kbd_k = *ktbls; /* struct assignment */ 629 ks->kbd_modbits = 0; 630 } 631 632 /* 633 * Turn keyboard up/down codes into a KEYSYM. 634 * Note that the "kd" driver (on sun3 and sparc64) uses this too! 635 */ 636 int 637 kbd_code_to_keysym(ks, c) 638 struct kbd_state *ks; 639 int c; 640 { 641 u_short *km; 642 int keysym; 643 644 /* 645 * Get keymap pointer. One of these: 646 * release, control, shifted, normal, ... 647 */ 648 if (KEY_UP(c)) 649 km = ks->kbd_k.k_release; 650 else if (ks->kbd_modbits & KBMOD_CTRL_MASK) 651 km = ks->kbd_k.k_control; 652 else if (ks->kbd_modbits & KBMOD_SHIFT_MASK) 653 km = ks->kbd_k.k_shifted; 654 else 655 km = ks->kbd_k.k_normal; 656 657 if (km == NULL) { 658 /* 659 * Do not know how to translate yet. 660 * We will find out when a RESET comes along. 661 */ 662 return (KEYSYM_NOP); 663 } 664 keysym = km[KEY_CODE(c)]; 665 666 /* 667 * Post-processing for Caps-lock 668 */ 669 if ((ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) && 670 (KEYSYM_CLASS(keysym) == KEYSYM_ASCII) ) 671 { 672 if (('a' <= keysym) && (keysym <= 'z')) 673 keysym -= ('a' - 'A'); 674 } 675 676 /* 677 * Post-processing for Num-lock. All "function" 678 * keysyms get indirected through another table. 679 * (XXX: Only if numlock on. Want off also!) 680 */ 681 if ((ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) && 682 (KEYSYM_CLASS(keysym) == KEYSYM_FUNC) ) 683 { 684 keysym = kbd_numlock_map[keysym & 0x3F]; 685 } 686 687 return (keysym); 688 } 689 690 691 /* 692 * Back door for rcons (fb.c) 693 */ 694 void 695 kbd_bell(on) 696 int on; 697 { 698 /* XXX: stub out for now */ 699 return; 700 } 701