1 /* $OpenBSD: wskbd.c,v 1.80 2014/07/12 18:48:53 tedu Exp $ */ 2 /* $NetBSD: wskbd.c,v 1.80 2005/05/04 01:52:16 augustss Exp $ */ 3 4 /* 5 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. 6 * 7 * Keysym translator: 8 * Contributed to The NetBSD Foundation by Juergen Hannken-Illjes. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by Christopher G. Demetriou 21 * for the NetBSD Project. 22 * 4. The name of the author may not be used to endorse or promote products 23 * derived from this software without specific prior written permission 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 /* 38 * Copyright (c) 1992, 1993 39 * The Regents of the University of California. All rights reserved. 40 * 41 * This software was developed by the Computer Systems Engineering group 42 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 43 * contributed to Berkeley. 44 * 45 * All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the University of 48 * California, Lawrence Berkeley Laboratory. 49 * 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 1. Redistributions of source code must retain the above copyright 54 * notice, this list of conditions and the following disclaimer. 55 * 2. Redistributions in binary form must reproduce the above copyright 56 * notice, this list of conditions and the following disclaimer in the 57 * documentation and/or other materials provided with the distribution. 58 * 3. Neither the name of the University nor the names of its contributors 59 * may be used to endorse or promote products derived from this software 60 * without specific prior written permission. 61 * 62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 72 * SUCH DAMAGE. 73 * 74 * @(#)kbd.c 8.2 (Berkeley) 10/30/93 75 */ 76 77 /* 78 * Keyboard driver (/dev/wskbd*). Translates incoming bytes to ASCII or 79 * to `wscons_events' and passes them up to the appropriate reader. 80 */ 81 82 #include <sys/param.h> 83 #include <sys/conf.h> 84 #include <sys/device.h> 85 #include <sys/ioctl.h> 86 #include <sys/kernel.h> 87 #include <sys/proc.h> 88 #include <sys/syslog.h> 89 #include <sys/systm.h> 90 #include <sys/timeout.h> 91 #include <sys/malloc.h> 92 #include <sys/tty.h> 93 #include <sys/signalvar.h> 94 #include <sys/errno.h> 95 #include <sys/fcntl.h> 96 #include <sys/vnode.h> 97 #include <sys/poll.h> 98 99 #include <ddb/db_var.h> 100 101 #include <dev/wscons/wscons_features.h> 102 #include <dev/wscons/wsconsio.h> 103 #include <dev/wscons/wskbdvar.h> 104 #include <dev/wscons/wsksymdef.h> 105 #include <dev/wscons/wsksymvar.h> 106 #include <dev/wscons/wsdisplayvar.h> 107 #include <dev/wscons/wseventvar.h> 108 #include <dev/wscons/wscons_callbacks.h> 109 110 #include "audio.h" /* NAUDIO (mixer tuning) */ 111 #include "wsdisplay.h" 112 #include "wskbd.h" 113 #include "wsmux.h" 114 115 #ifdef WSKBD_DEBUG 116 #define DPRINTF(x) if (wskbddebug) printf x 117 int wskbddebug = 0; 118 #else 119 #define DPRINTF(x) 120 #endif 121 122 #include <dev/wscons/wsmuxvar.h> 123 124 struct wskbd_internal { 125 const struct wskbd_consops *t_consops; 126 void *t_consaccesscookie; 127 128 int t_modifiers; 129 int t_composelen; /* remaining entries in t_composebuf */ 130 keysym_t t_composebuf[2]; 131 132 int t_flags; 133 #define WSKFL_METAESC 1 134 135 #define MAXKEYSYMSPERKEY 2 /* ESC <key> at max */ 136 keysym_t t_symbols[MAXKEYSYMSPERKEY]; 137 138 struct wskbd_softc *t_sc; /* back pointer */ 139 140 struct wskbd_mapdata t_keymap; /* translation map table and 141 current layout */ 142 }; 143 144 struct wskbd_softc { 145 struct wsevsrc sc_base; 146 147 struct wskbd_internal *id; 148 149 const struct wskbd_accessops *sc_accessops; 150 void *sc_accesscookie; 151 152 int sc_ledstate; 153 154 int sc_isconsole; 155 156 struct wskbd_bell_data sc_bell_data; 157 struct wskbd_keyrepeat_data sc_keyrepeat_data; 158 159 int sc_repeating; /* we've called timeout() */ 160 int sc_repkey; 161 struct timeout sc_repeat_ch; 162 u_int sc_repeat_type; 163 int sc_repeat_value; 164 165 int sc_translating; /* xlate to chars for emulation */ 166 167 int sc_maplen; /* number of entries in sc_map */ 168 struct wscons_keymap *sc_map; /* current translation map */ 169 170 int sc_refcnt; 171 u_char sc_dying; /* device is being detached */ 172 }; 173 174 #define MOD_SHIFT_L (1 << 0) 175 #define MOD_SHIFT_R (1 << 1) 176 #define MOD_SHIFTLOCK (1 << 2) 177 #define MOD_CAPSLOCK (1 << 3) 178 #define MOD_CONTROL_L (1 << 4) 179 #define MOD_CONTROL_R (1 << 5) 180 #define MOD_META_L (1 << 6) 181 #define MOD_META_R (1 << 7) 182 #define MOD_MODESHIFT (1 << 8) 183 #define MOD_NUMLOCK (1 << 9) 184 #define MOD_COMPOSE (1 << 10) 185 #define MOD_HOLDSCREEN (1 << 11) 186 #define MOD_COMMAND (1 << 12) 187 #define MOD_COMMAND1 (1 << 13) 188 #define MOD_COMMAND2 (1 << 14) 189 #define MOD_MODELOCK (1 << 15) 190 191 #define MOD_ANYSHIFT (MOD_SHIFT_L | MOD_SHIFT_R | MOD_SHIFTLOCK) 192 #define MOD_ANYCONTROL (MOD_CONTROL_L | MOD_CONTROL_R) 193 #define MOD_ANYMETA (MOD_META_L | MOD_META_R) 194 #define MOD_ANYLED (MOD_SHIFTLOCK | MOD_CAPSLOCK | MOD_NUMLOCK | \ 195 MOD_COMPOSE | MOD_HOLDSCREEN) 196 197 #define MOD_ONESET(id, mask) (((id)->t_modifiers & (mask)) != 0) 198 #define MOD_ALLSET(id, mask) (((id)->t_modifiers & (mask)) == (mask)) 199 200 keysym_t ksym_upcase(keysym_t); 201 202 int wskbd_match(struct device *, void *, void *); 203 void wskbd_attach(struct device *, struct device *, void *); 204 int wskbd_detach(struct device *, int); 205 int wskbd_activate(struct device *, int); 206 207 int wskbd_displayioctl(struct device *, u_long, caddr_t, int, struct proc *); 208 209 void update_leds(struct wskbd_internal *); 210 void update_modifier(struct wskbd_internal *, u_int, int, int); 211 int internal_command(struct wskbd_softc *, u_int *, keysym_t, keysym_t); 212 int wskbd_translate(struct wskbd_internal *, u_int, int); 213 int wskbd_enable(struct wskbd_softc *, int); 214 #if NWSDISPLAY > 0 215 void change_displayparam(struct wskbd_softc *, int, int, int); 216 #endif 217 218 int wskbd_do_ioctl_sc(struct wskbd_softc *, u_long, caddr_t, int, 219 struct proc *); 220 void wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value); 221 222 #if NWSMUX > 0 223 int wskbd_mux_open(struct wsevsrc *, struct wseventvar *); 224 int wskbd_mux_close(struct wsevsrc *); 225 #else 226 #define wskbd_mux_open NULL 227 #define wskbd_mux_close NULL 228 #endif 229 230 int wskbd_do_open(struct wskbd_softc *, struct wseventvar *); 231 int wskbd_do_ioctl(struct device *, u_long, caddr_t, int, struct proc *); 232 233 struct cfdriver wskbd_cd = { 234 NULL, "wskbd", DV_TTY 235 }; 236 237 struct cfattach wskbd_ca = { 238 sizeof (struct wskbd_softc), wskbd_match, wskbd_attach, 239 wskbd_detach, wskbd_activate 240 }; 241 242 #if defined(__i386__) || defined(__amd64__) 243 extern int kbd_reset; 244 #endif 245 246 #ifndef WSKBD_DEFAULT_BELL_PITCH 247 #define WSKBD_DEFAULT_BELL_PITCH 400 /* 400Hz */ 248 #endif 249 #ifndef WSKBD_DEFAULT_BELL_PERIOD 250 #define WSKBD_DEFAULT_BELL_PERIOD 100 /* 100ms */ 251 #endif 252 #ifndef WSKBD_DEFAULT_BELL_VOLUME 253 #define WSKBD_DEFAULT_BELL_VOLUME 50 /* 50% volume */ 254 #endif 255 256 struct wskbd_bell_data wskbd_default_bell_data = { 257 WSKBD_BELL_DOALL, 258 WSKBD_DEFAULT_BELL_PITCH, 259 WSKBD_DEFAULT_BELL_PERIOD, 260 WSKBD_DEFAULT_BELL_VOLUME, 261 }; 262 263 #ifndef WSKBD_DEFAULT_KEYREPEAT_DEL1 264 #define WSKBD_DEFAULT_KEYREPEAT_DEL1 400 /* 400ms to start repeating */ 265 #endif 266 #ifndef WSKBD_DEFAULT_KEYREPEAT_DELN 267 #define WSKBD_DEFAULT_KEYREPEAT_DELN 100 /* 100ms to between repeats */ 268 #endif 269 270 struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = { 271 WSKBD_KEYREPEAT_DOALL, 272 WSKBD_DEFAULT_KEYREPEAT_DEL1, 273 WSKBD_DEFAULT_KEYREPEAT_DELN, 274 }; 275 276 #if NWSMUX > 0 || NWSDISPLAY > 0 277 struct wssrcops wskbd_srcops = { 278 WSMUX_KBD, 279 wskbd_mux_open, wskbd_mux_close, wskbd_do_ioctl, 280 wskbd_displayioctl, 281 #if NWSDISPLAY > 0 282 wskbd_set_display 283 #else 284 NULL 285 #endif 286 }; 287 #endif 288 289 #if NWSDISPLAY > 0 290 void wskbd_repeat(void *v); 291 #endif 292 293 static int wskbd_console_initted; 294 static struct wskbd_softc *wskbd_console_device; 295 static struct wskbd_internal wskbd_console_data; 296 297 void wskbd_update_layout(struct wskbd_internal *, kbd_t); 298 299 #if NAUDIO > 0 300 extern int wskbd_set_mixervolume(long, long); 301 #endif 302 303 void 304 wskbd_update_layout(struct wskbd_internal *id, kbd_t enc) 305 { 306 if (enc & KB_METAESC) 307 id->t_flags |= WSKFL_METAESC; 308 else 309 id->t_flags &= ~WSKFL_METAESC; 310 311 id->t_keymap.layout = enc; 312 } 313 314 /* 315 * Print function (for parent devices). 316 */ 317 int 318 wskbddevprint(void *aux, const char *pnp) 319 { 320 #if 0 321 struct wskbddev_attach_args *ap = aux; 322 #endif 323 324 if (pnp) 325 printf("wskbd at %s", pnp); 326 #if 0 327 printf(" console %d", ap->console); 328 #endif 329 330 return (UNCONF); 331 } 332 333 int 334 wskbd_match(struct device *parent, void *match, void *aux) 335 { 336 struct cfdata *cf = match; 337 struct wskbddev_attach_args *ap = aux; 338 339 if (cf->wskbddevcf_console != WSKBDDEVCF_CONSOLE_UNK) { 340 /* 341 * If console-ness of device specified, either match 342 * exactly (at high priority), or fail. 343 */ 344 if (cf->wskbddevcf_console != 0 && ap->console != 0) 345 return (10); 346 else 347 return (0); 348 } 349 350 /* If console-ness unspecified, it wins. */ 351 return (1); 352 } 353 354 void 355 wskbd_attach(struct device *parent, struct device *self, void *aux) 356 { 357 struct wskbd_softc *sc = (struct wskbd_softc *)self; 358 struct wskbddev_attach_args *ap = aux; 359 kbd_t layout; 360 #if NWSMUX > 0 361 struct wsmux_softc *wsmux_sc; 362 int mux, error; 363 #endif 364 365 sc->sc_isconsole = ap->console; 366 367 #if NWSMUX > 0 || NWSDISPLAY > 0 368 sc->sc_base.me_ops = &wskbd_srcops; 369 #endif 370 #if NWSMUX > 0 371 mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux; 372 if (ap->console) { 373 /* Ignore mux for console; it always goes to the console mux. */ 374 /* printf(" (mux %d ignored for console)", mux); */ 375 mux = -1; 376 } 377 if (mux >= 0) { 378 printf(" mux %d", mux); 379 wsmux_sc = wsmux_getmux(mux); 380 } else 381 wsmux_sc = NULL; 382 #else 383 #if 0 /* not worth keeping, especially since the default value is not -1... */ 384 if (sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux >= 0) 385 printf(" (mux ignored)"); 386 #endif 387 #endif /* NWSMUX > 0 */ 388 389 if (ap->console) { 390 sc->id = &wskbd_console_data; 391 } else { 392 sc->id = malloc(sizeof(struct wskbd_internal), 393 M_DEVBUF, M_WAITOK | M_ZERO); 394 bcopy(ap->keymap, &sc->id->t_keymap, sizeof(sc->id->t_keymap)); 395 } 396 397 #if NWSDISPLAY > 0 398 timeout_set(&sc->sc_repeat_ch, wskbd_repeat, sc); 399 #endif 400 401 sc->id->t_sc = sc; 402 403 sc->sc_accessops = ap->accessops; 404 sc->sc_accesscookie = ap->accesscookie; 405 sc->sc_repeating = 0; 406 sc->sc_translating = 1; 407 sc->sc_ledstate = -1; /* force update */ 408 409 /* 410 * If this layout is the default choice of the driver (i.e. the 411 * driver doesn't know better), pick the existing layout of the 412 * current mux, if any. 413 */ 414 layout = sc->id->t_keymap.layout; 415 #if NWSMUX > 0 416 if (layout & KB_DEFAULT) { 417 if (wsmux_sc != NULL && wsmux_get_layout(wsmux_sc) != KB_NONE) 418 layout = wsmux_get_layout(wsmux_sc); 419 } 420 #endif 421 for (;;) { 422 if (wskbd_load_keymap(&sc->id->t_keymap, layout, &sc->sc_map, 423 &sc->sc_maplen) == 0) 424 break; 425 #if NWSMUX > 0 426 if (layout == sc->id->t_keymap.layout) 427 panic("cannot load keymap"); 428 if (wsmux_sc != NULL && wsmux_get_layout(wsmux_sc) != KB_NONE) { 429 printf("\n%s: cannot load keymap, " 430 "falling back to default\n%s", 431 sc->sc_base.me_dv.dv_xname, 432 sc->sc_base.me_dv.dv_xname); 433 layout = wsmux_get_layout(wsmux_sc); 434 } else 435 #endif 436 panic("cannot load keymap"); 437 } 438 wskbd_update_layout(sc->id, layout); 439 440 /* set default bell and key repeat data */ 441 sc->sc_bell_data = wskbd_default_bell_data; 442 sc->sc_keyrepeat_data = wskbd_default_keyrepeat_data; 443 444 if (ap->console) { 445 KASSERT(wskbd_console_initted); 446 KASSERT(wskbd_console_device == NULL); 447 448 wskbd_console_device = sc; 449 450 printf(": console keyboard"); 451 452 #if NWSDISPLAY > 0 453 wsdisplay_set_console_kbd(&sc->sc_base); /* sets sc_displaydv */ 454 if (sc->sc_displaydv != NULL) 455 printf(", using %s", sc->sc_displaydv->dv_xname); 456 #endif 457 } 458 printf("\n"); 459 460 #if NWSMUX > 0 461 if (wsmux_sc != NULL) { 462 error = wsmux_attach_sc(wsmux_sc, &sc->sc_base); 463 if (error) 464 printf("%s: attach error=%d\n", 465 sc->sc_base.me_dv.dv_xname, error); 466 467 /* 468 * Try and set this encoding as the mux default if it 469 * hasn't any yet, and if this is not a driver default 470 * layout (i.e. parent driver pretends to know better). 471 * Note that wsmux_set_layout() rejects layouts with 472 * KB_DEFAULT set. 473 */ 474 if (wsmux_get_layout(wsmux_sc) == KB_NONE) 475 wsmux_set_layout(wsmux_sc, layout); 476 } 477 #endif 478 479 #if NWSDISPLAY > 0 && NWSMUX == 0 480 if (ap->console == 0) { 481 /* 482 * In the non-wsmux world, always connect wskbd0 and wsdisplay0 483 * together. 484 */ 485 extern struct cfdriver wsdisplay_cd; 486 487 if (wsdisplay_cd.cd_ndevs != 0 && self->dv_unit == 0) { 488 if (wskbd_set_display(self, 489 wsdisplay_cd.cd_devs[0]) == 0) 490 wsdisplay_set_kbd(wsdisplay_cd.cd_devs[0], 491 (struct wsevsrc *)sc); 492 } 493 } 494 #endif 495 } 496 497 void 498 wskbd_cnattach(const struct wskbd_consops *consops, void *conscookie, 499 const struct wskbd_mapdata *mapdata) 500 { 501 502 KASSERT(!wskbd_console_initted); 503 504 bcopy(mapdata, &wskbd_console_data.t_keymap, sizeof(*mapdata)); 505 wskbd_update_layout(&wskbd_console_data, mapdata->layout); 506 507 wskbd_console_data.t_consops = consops; 508 wskbd_console_data.t_consaccesscookie = conscookie; 509 510 #if NWSDISPLAY > 0 511 wsdisplay_set_cons_kbd(wskbd_cngetc, wskbd_cnpollc, wskbd_cnbell); 512 #endif 513 514 wskbd_console_initted = 1; 515 } 516 517 void 518 wskbd_cndetach(void) 519 { 520 KASSERT(wskbd_console_initted); 521 522 wskbd_console_data.t_keymap.keydesc = NULL; 523 wskbd_console_data.t_keymap.layout = KB_NONE; 524 525 wskbd_console_data.t_consops = NULL; 526 wskbd_console_data.t_consaccesscookie = NULL; 527 528 #if NWSDISPLAY > 0 529 wsdisplay_unset_cons_kbd(); 530 #endif 531 532 wskbd_console_initted = 0; 533 } 534 535 #if NWSDISPLAY > 0 536 void 537 wskbd_repeat(void *v) 538 { 539 struct wskbd_softc *sc = (struct wskbd_softc *)v; 540 int s = spltty(); 541 542 if (sc->sc_repeating == 0) { 543 /* 544 * race condition: a "key up" event came in when wskbd_repeat() 545 * was already called but not yet spltty()'d 546 */ 547 splx(s); 548 return; 549 } 550 if (sc->sc_translating) { 551 /* deliver keys */ 552 if (sc->sc_displaydv != NULL) 553 wsdisplay_kbdinput(sc->sc_displaydv, 554 sc->id->t_keymap.layout, 555 sc->id->t_symbols, sc->sc_repeating); 556 } else { 557 /* queue event */ 558 wskbd_deliver_event(sc, sc->sc_repeat_type, 559 sc->sc_repeat_value); 560 } 561 if (sc->sc_keyrepeat_data.delN != 0) 562 timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.delN); 563 splx(s); 564 } 565 #endif 566 567 int 568 wskbd_activate(struct device *self, int act) 569 { 570 struct wskbd_softc *sc = (struct wskbd_softc *)self; 571 572 if (act == DVACT_DEACTIVATE) 573 sc->sc_dying = 1; 574 return (0); 575 } 576 577 /* 578 * Detach a keyboard. To keep track of users of the softc we keep 579 * a reference count that's incremented while inside, e.g., read. 580 * If the keyboard is active and the reference count is > 0 (0 is the 581 * normal state) we post an event and then wait for the process 582 * that had the reference to wake us up again. Then we blow away the 583 * vnode and return (which will deallocate the softc). 584 */ 585 int 586 wskbd_detach(struct device *self, int flags) 587 { 588 struct wskbd_softc *sc = (struct wskbd_softc *)self; 589 struct wseventvar *evar; 590 int maj, mn; 591 int s; 592 593 #if NWSMUX > 0 594 /* Tell parent mux we're leaving. */ 595 if (sc->sc_base.me_parent != NULL) 596 wsmux_detach_sc(&sc->sc_base); 597 #endif 598 599 #if NWSDISPLAY > 0 600 if (sc->sc_repeating) { 601 sc->sc_repeating = 0; 602 timeout_del(&sc->sc_repeat_ch); 603 } 604 #endif 605 606 if (sc->sc_isconsole) { 607 KASSERT(wskbd_console_device == sc); 608 wskbd_console_device = NULL; 609 } 610 611 evar = sc->sc_base.me_evp; 612 if (evar != NULL && evar->io != NULL) { 613 s = spltty(); 614 if (--sc->sc_refcnt >= 0) { 615 /* Wake everyone by generating a dummy event. */ 616 if (++evar->put >= WSEVENT_QSIZE) 617 evar->put = 0; 618 WSEVENT_WAKEUP(evar); 619 /* Wait for processes to go away. */ 620 if (tsleep(sc, PZERO, "wskdet", hz * 60)) 621 printf("wskbd_detach: %s didn't detach\n", 622 sc->sc_base.me_dv.dv_xname); 623 } 624 splx(s); 625 } 626 627 free(sc->sc_map, M_DEVBUF, 0); 628 629 /* locate the major number */ 630 for (maj = 0; maj < nchrdev; maj++) 631 if (cdevsw[maj].d_open == wskbdopen) 632 break; 633 634 /* Nuke the vnodes for any open instances. */ 635 mn = self->dv_unit; 636 vdevgone(maj, mn, mn, VCHR); 637 638 return (0); 639 } 640 641 void 642 wskbd_input(struct device *dev, u_int type, int value) 643 { 644 struct wskbd_softc *sc = (struct wskbd_softc *)dev; 645 #if NWSDISPLAY > 0 646 int num; 647 #endif 648 649 #if NWSDISPLAY > 0 650 if (sc->sc_repeating) { 651 sc->sc_repeating = 0; 652 timeout_del(&sc->sc_repeat_ch); 653 } 654 655 /* 656 * If /dev/wskbdN is not connected in event mode translate and 657 * send upstream. 658 */ 659 if (sc->sc_translating) { 660 #ifdef HAVE_BURNER_SUPPORT 661 if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_displaydv != NULL) 662 wsdisplay_burn(sc->sc_displaydv, WSDISPLAY_BURN_KBD); 663 #endif 664 num = wskbd_translate(sc->id, type, value); 665 if (num > 0) { 666 if (sc->sc_displaydv != NULL) { 667 #ifdef HAVE_SCROLLBACK_SUPPORT 668 /* XXX - Shift_R+PGUP(release) emits PrtSc */ 669 if (sc->id->t_symbols[0] != KS_Print_Screen) { 670 wsscrollback(sc->sc_displaydv, 671 WSDISPLAY_SCROLL_RESET); 672 } 673 #endif 674 wsdisplay_kbdinput(sc->sc_displaydv, 675 sc->id->t_keymap.layout, 676 sc->id->t_symbols, num); 677 } 678 679 if (sc->sc_keyrepeat_data.del1 != 0) { 680 sc->sc_repeating = num; 681 timeout_add_msec(&sc->sc_repeat_ch, 682 sc->sc_keyrepeat_data.del1); 683 } 684 } 685 return; 686 } 687 #endif 688 689 wskbd_deliver_event(sc, type, value); 690 691 #if NWSDISPLAY > 0 692 /* Repeat key presses if enabled. */ 693 if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_keyrepeat_data.del1 != 0) { 694 sc->sc_repeat_type = type; 695 sc->sc_repeat_value = value; 696 sc->sc_repeating = 1; 697 timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.del1); 698 } 699 #endif 700 } 701 702 /* 703 * Keyboard is generating events. Turn this keystroke into an 704 * event and put it in the queue. If the queue is full, the 705 * keystroke is lost (sorry!). 706 */ 707 void 708 wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value) 709 { 710 struct wseventvar *evar; 711 struct wscons_event *ev; 712 int put; 713 714 evar = sc->sc_base.me_evp; 715 716 if (evar == NULL) { 717 DPRINTF(("wskbd_input: not open\n")); 718 return; 719 } 720 721 #ifdef DIAGNOSTIC 722 if (evar->q == NULL) { 723 printf("wskbd_input: evar->q=NULL\n"); 724 return; 725 } 726 #endif 727 728 put = evar->put; 729 ev = &evar->q[put]; 730 put = (put + 1) % WSEVENT_QSIZE; 731 if (put == evar->get) { 732 log(LOG_WARNING, "%s: event queue overflow\n", 733 sc->sc_base.me_dv.dv_xname); 734 return; 735 } 736 ev->type = type; 737 ev->value = value; 738 nanotime(&ev->time); 739 evar->put = put; 740 WSEVENT_WAKEUP(evar); 741 } 742 743 #ifdef WSDISPLAY_COMPAT_RAWKBD 744 void 745 wskbd_rawinput(struct device *dev, u_char *buf, int len) 746 { 747 #if NWSDISPLAY > 0 748 struct wskbd_softc *sc = (struct wskbd_softc *)dev; 749 750 if (sc->sc_displaydv != NULL) 751 wsdisplay_rawkbdinput(sc->sc_displaydv, buf, len); 752 #endif 753 } 754 #endif /* WSDISPLAY_COMPAT_RAWKBD */ 755 756 int 757 wskbd_enable(struct wskbd_softc *sc, int on) 758 { 759 int error; 760 761 #if NWSDISPLAY > 0 762 if (sc->sc_displaydv != NULL) 763 return (0); 764 765 /* Always cancel auto repeat when fiddling with the kbd. */ 766 if (sc->sc_repeating) { 767 sc->sc_repeating = 0; 768 timeout_del(&sc->sc_repeat_ch); 769 } 770 #endif 771 772 error = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on); 773 DPRINTF(("wskbd_enable: sc=%p on=%d res=%d\n", sc, on, error)); 774 return (error); 775 } 776 777 #if NWSMUX > 0 778 int 779 wskbd_mux_open(struct wsevsrc *me, struct wseventvar *evp) 780 { 781 struct wskbd_softc *sc = (struct wskbd_softc *)me; 782 783 if (sc->sc_dying) 784 return (EIO); 785 786 if (sc->sc_base.me_evp != NULL) 787 return (EBUSY); 788 789 return (wskbd_do_open(sc, evp)); 790 } 791 #endif 792 793 int 794 wskbdopen(dev_t dev, int flags, int mode, struct proc *p) 795 { 796 struct wskbd_softc *sc; 797 struct wseventvar *evar; 798 int unit, error; 799 800 unit = minor(dev); 801 if (unit >= wskbd_cd.cd_ndevs || /* make sure it was attached */ 802 (sc = wskbd_cd.cd_devs[unit]) == NULL) 803 return (ENXIO); 804 805 #if NWSMUX > 0 806 DPRINTF(("wskbdopen: %s mux=%p p=%p\n", sc->sc_base.me_dv.dv_xname, 807 sc->sc_base.me_parent, p)); 808 #endif 809 810 if (sc->sc_dying) 811 return (EIO); 812 813 if ((flags & (FREAD | FWRITE)) == FWRITE) { 814 /* Not opening for read, only ioctl is available. */ 815 return (0); 816 } 817 818 #if NWSMUX > 0 819 if (sc->sc_base.me_parent != NULL) { 820 /* Grab the keyboard out of the greedy hands of the mux. */ 821 DPRINTF(("wskbdopen: detach\n")); 822 wsmux_detach_sc(&sc->sc_base); 823 } 824 #endif 825 826 if (sc->sc_base.me_evp != NULL) 827 return (EBUSY); 828 829 evar = &sc->sc_base.me_evar; 830 wsevent_init(evar); 831 evar->io = p->p_p; 832 833 error = wskbd_do_open(sc, evar); 834 if (error) { 835 DPRINTF(("wskbdopen: %s open failed\n", 836 sc->sc_base.me_dv.dv_xname)); 837 sc->sc_base.me_evp = NULL; 838 wsevent_fini(evar); 839 } 840 return (error); 841 } 842 843 int 844 wskbd_do_open(struct wskbd_softc *sc, struct wseventvar *evp) 845 { 846 sc->sc_base.me_evp = evp; 847 sc->sc_translating = 0; 848 849 return (wskbd_enable(sc, 1)); 850 } 851 852 int 853 wskbdclose(dev_t dev, int flags, int mode, struct proc *p) 854 { 855 struct wskbd_softc *sc = 856 (struct wskbd_softc *)wskbd_cd.cd_devs[minor(dev)]; 857 struct wseventvar *evar = sc->sc_base.me_evp; 858 859 if (evar == NULL) 860 /* not open for read */ 861 return (0); 862 863 sc->sc_base.me_evp = NULL; 864 sc->sc_translating = 1; 865 (void)wskbd_enable(sc, 0); 866 wsevent_fini(evar); 867 868 #if NWSMUX > 0 869 if (sc->sc_base.me_parent == NULL) { 870 int mux, error; 871 872 DPRINTF(("wskbdclose: attach\n")); 873 mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux; 874 if (mux >= 0) { 875 error = wsmux_attach_sc(wsmux_getmux(mux), &sc->sc_base); 876 if (error) 877 printf("%s: can't attach mux (error=%d)\n", 878 sc->sc_base.me_dv.dv_xname, error); 879 } 880 } 881 #endif 882 883 return (0); 884 } 885 886 #if NWSMUX > 0 887 int 888 wskbd_mux_close(struct wsevsrc *me) 889 { 890 struct wskbd_softc *sc = (struct wskbd_softc *)me; 891 892 sc->sc_base.me_evp = NULL; 893 sc->sc_translating = 1; 894 (void)wskbd_enable(sc, 0); 895 896 return (0); 897 } 898 #endif 899 900 int 901 wskbdread(dev_t dev, struct uio *uio, int flags) 902 { 903 struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)]; 904 int error; 905 906 if (sc->sc_dying) 907 return (EIO); 908 909 #ifdef DIAGNOSTIC 910 if (sc->sc_base.me_evp == NULL) { 911 printf("wskbdread: evp == NULL\n"); 912 return (EINVAL); 913 } 914 #endif 915 916 sc->sc_refcnt++; 917 error = wsevent_read(&sc->sc_base.me_evar, uio, flags); 918 if (--sc->sc_refcnt < 0) { 919 wakeup(sc); 920 error = EIO; 921 } 922 return (error); 923 } 924 925 int 926 wskbdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 927 { 928 return (wskbd_do_ioctl(wskbd_cd.cd_devs[minor(dev)], cmd, data, flag,p)); 929 } 930 931 /* A wrapper around the ioctl() workhorse to make reference counting easy. */ 932 int 933 wskbd_do_ioctl(struct device *dv, u_long cmd, caddr_t data, int flag, 934 struct proc *p) 935 { 936 struct wskbd_softc *sc = (struct wskbd_softc *)dv; 937 int error; 938 939 sc->sc_refcnt++; 940 error = wskbd_do_ioctl_sc(sc, cmd, data, flag, p); 941 if (--sc->sc_refcnt < 0) 942 wakeup(sc); 943 return (error); 944 } 945 946 int 947 wskbd_do_ioctl_sc(struct wskbd_softc *sc, u_long cmd, caddr_t data, int flag, 948 struct proc *p) 949 { 950 int error; 951 952 /* 953 * Try the generic ioctls that the wskbd interface supports. 954 */ 955 switch (cmd) { 956 case FIONBIO: /* we will remove this someday (soon???) */ 957 return (0); 958 959 case FIOASYNC: 960 if (sc->sc_base.me_evp == NULL) 961 return (EINVAL); 962 sc->sc_base.me_evp->async = *(int *)data != 0; 963 return (0); 964 965 case FIOSETOWN: 966 if (sc->sc_base.me_evp == NULL) 967 return (EINVAL); 968 if (-*(int *)data != sc->sc_base.me_evp->io->ps_pgid && 969 *(int *)data != sc->sc_base.me_evp->io->ps_pid) 970 return (EPERM); 971 return (0); 972 973 case TIOCSPGRP: 974 if (sc->sc_base.me_evp == NULL) 975 return (EINVAL); 976 if (*(int *)data != sc->sc_base.me_evp->io->ps_pgid) 977 return (EPERM); 978 return (0); 979 } 980 981 /* 982 * Try the keyboard driver for WSKBDIO ioctls. It returns -1 983 * if it didn't recognize the request. 984 */ 985 error = wskbd_displayioctl(&sc->sc_base.me_dv, cmd, data, flag, p); 986 return (error != -1 ? error : ENOTTY); 987 } 988 989 /* 990 * WSKBDIO ioctls, handled in both emulation mode and in ``raw'' mode. 991 * Some of these have no real effect in raw mode, however. 992 */ 993 int 994 wskbd_displayioctl(struct device *dev, u_long cmd, caddr_t data, int flag, 995 struct proc *p) 996 { 997 struct wskbd_softc *sc = (struct wskbd_softc *)dev; 998 struct wskbd_bell_data *ubdp, *kbdp; 999 struct wskbd_keyrepeat_data *ukdp, *kkdp; 1000 struct wskbd_map_data *umdp; 1001 kbd_t enc; 1002 void *buf; 1003 int len, error; 1004 1005 switch (cmd) { 1006 case WSKBDIO_BELL: 1007 case WSKBDIO_COMPLEXBELL: 1008 case WSKBDIO_SETBELL: 1009 case WSKBDIO_SETKEYREPEAT: 1010 case WSKBDIO_SETDEFAULTKEYREPEAT: 1011 case WSKBDIO_SETMAP: 1012 case WSKBDIO_SETENCODING: 1013 if ((flag & FWRITE) == 0) 1014 return (EACCES); 1015 } 1016 1017 switch (cmd) { 1018 #define SETBELL(dstp, srcp, dfltp) \ 1019 do { \ 1020 (dstp)->pitch = ((srcp)->which & WSKBD_BELL_DOPITCH) ? \ 1021 (srcp)->pitch : (dfltp)->pitch; \ 1022 (dstp)->period = ((srcp)->which & WSKBD_BELL_DOPERIOD) ? \ 1023 (srcp)->period : (dfltp)->period; \ 1024 (dstp)->volume = ((srcp)->which & WSKBD_BELL_DOVOLUME) ? \ 1025 (srcp)->volume : (dfltp)->volume; \ 1026 (dstp)->which = WSKBD_BELL_DOALL; \ 1027 } while (0) 1028 1029 case WSKBDIO_BELL: 1030 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, 1031 WSKBDIO_COMPLEXBELL, (caddr_t)&sc->sc_bell_data, flag, p)); 1032 1033 case WSKBDIO_COMPLEXBELL: 1034 ubdp = (struct wskbd_bell_data *)data; 1035 SETBELL(ubdp, ubdp, &sc->sc_bell_data); 1036 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, 1037 WSKBDIO_COMPLEXBELL, (caddr_t)ubdp, flag, p)); 1038 1039 case WSKBDIO_SETBELL: 1040 kbdp = &sc->sc_bell_data; 1041 setbell: 1042 ubdp = (struct wskbd_bell_data *)data; 1043 SETBELL(kbdp, ubdp, kbdp); 1044 return (0); 1045 1046 case WSKBDIO_GETBELL: 1047 kbdp = &sc->sc_bell_data; 1048 getbell: 1049 ubdp = (struct wskbd_bell_data *)data; 1050 SETBELL(ubdp, kbdp, kbdp); 1051 return (0); 1052 1053 case WSKBDIO_SETDEFAULTBELL: 1054 if ((error = suser(p, 0)) != 0) 1055 return (error); 1056 kbdp = &wskbd_default_bell_data; 1057 goto setbell; 1058 1059 1060 case WSKBDIO_GETDEFAULTBELL: 1061 kbdp = &wskbd_default_bell_data; 1062 goto getbell; 1063 1064 #undef SETBELL 1065 1066 #define SETKEYREPEAT(dstp, srcp, dfltp) \ 1067 do { \ 1068 (dstp)->del1 = ((srcp)->which & WSKBD_KEYREPEAT_DODEL1) ? \ 1069 (srcp)->del1 : (dfltp)->del1; \ 1070 (dstp)->delN = ((srcp)->which & WSKBD_KEYREPEAT_DODELN) ? \ 1071 (srcp)->delN : (dfltp)->delN; \ 1072 (dstp)->which = WSKBD_KEYREPEAT_DOALL; \ 1073 } while (0) 1074 1075 case WSKBDIO_SETKEYREPEAT: 1076 kkdp = &sc->sc_keyrepeat_data; 1077 setkeyrepeat: 1078 ukdp = (struct wskbd_keyrepeat_data *)data; 1079 SETKEYREPEAT(kkdp, ukdp, kkdp); 1080 return (0); 1081 1082 case WSKBDIO_GETKEYREPEAT: 1083 kkdp = &sc->sc_keyrepeat_data; 1084 getkeyrepeat: 1085 ukdp = (struct wskbd_keyrepeat_data *)data; 1086 SETKEYREPEAT(ukdp, kkdp, kkdp); 1087 return (0); 1088 1089 case WSKBDIO_SETDEFAULTKEYREPEAT: 1090 if ((error = suser(p, 0)) != 0) 1091 return (error); 1092 kkdp = &wskbd_default_keyrepeat_data; 1093 goto setkeyrepeat; 1094 1095 1096 case WSKBDIO_GETDEFAULTKEYREPEAT: 1097 kkdp = &wskbd_default_keyrepeat_data; 1098 goto getkeyrepeat; 1099 1100 #undef SETKEYREPEAT 1101 1102 case WSKBDIO_SETMAP: 1103 umdp = (struct wskbd_map_data *)data; 1104 if (umdp->maplen > WSKBDIO_MAXMAPLEN) 1105 return (EINVAL); 1106 1107 len = umdp->maplen * sizeof(struct wscons_keymap); 1108 buf = malloc(len, M_TEMP, M_WAITOK); 1109 error = copyin(umdp->map, buf, len); 1110 if (error == 0) { 1111 wskbd_init_keymap(umdp->maplen, 1112 &sc->sc_map, &sc->sc_maplen); 1113 memcpy(sc->sc_map, buf, len); 1114 /* drop the variant bits handled by the map */ 1115 enc = KB_USER | (KB_VARIANT(sc->id->t_keymap.layout) & 1116 KB_HANDLEDBYWSKBD); 1117 wskbd_update_layout(sc->id, enc); 1118 } 1119 free(buf, M_TEMP, 0); 1120 return(error); 1121 1122 case WSKBDIO_GETMAP: 1123 umdp = (struct wskbd_map_data *)data; 1124 if (umdp->maplen > sc->sc_maplen) 1125 umdp->maplen = sc->sc_maplen; 1126 error = copyout(sc->sc_map, umdp->map, 1127 umdp->maplen*sizeof(struct wscons_keymap)); 1128 return(error); 1129 1130 case WSKBDIO_GETENCODING: 1131 *((kbd_t *)data) = sc->id->t_keymap.layout & ~KB_DEFAULT; 1132 return(0); 1133 1134 case WSKBDIO_SETENCODING: 1135 enc = *((kbd_t *)data); 1136 if (KB_ENCODING(enc) == KB_USER) { 1137 /* user map must already be loaded */ 1138 if (KB_ENCODING(sc->id->t_keymap.layout) != KB_USER) 1139 return (EINVAL); 1140 /* map variants make no sense */ 1141 if (KB_VARIANT(enc) & ~KB_HANDLEDBYWSKBD) 1142 return (EINVAL); 1143 } else { 1144 error = wskbd_load_keymap(&sc->id->t_keymap, enc, 1145 &sc->sc_map, &sc->sc_maplen); 1146 if (error) 1147 return (error); 1148 } 1149 wskbd_update_layout(sc->id, enc); 1150 #if NWSMUX > 0 1151 /* Update mux default layout */ 1152 if (sc->sc_base.me_parent != NULL) 1153 wsmux_set_layout(sc->sc_base.me_parent, enc); 1154 #endif 1155 return (0); 1156 } 1157 1158 /* 1159 * Try the keyboard driver for WSKBDIO ioctls. It returns -1 1160 * if it didn't recognize the request, and in turn we return 1161 * -1 if we didn't recognize the request. 1162 */ 1163 /* printf("kbdaccess\n"); */ 1164 error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data, 1165 flag, p); 1166 #ifdef WSDISPLAY_COMPAT_RAWKBD 1167 if (!error && cmd == WSKBDIO_SETMODE && *(int *)data == WSKBD_RAW) { 1168 int s = spltty(); 1169 sc->id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R 1170 | MOD_CONTROL_L | MOD_CONTROL_R 1171 | MOD_META_L | MOD_META_R 1172 | MOD_COMMAND 1173 | MOD_COMMAND1 | MOD_COMMAND2); 1174 #if NWSDISPLAY > 0 1175 if (sc->sc_repeating) { 1176 sc->sc_repeating = 0; 1177 timeout_del(&sc->sc_repeat_ch); 1178 } 1179 #endif 1180 splx(s); 1181 } 1182 #endif 1183 return (error); 1184 } 1185 1186 int 1187 wskbdpoll(dev_t dev, int events, struct proc *p) 1188 { 1189 struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)]; 1190 1191 if (sc->sc_base.me_evp == NULL) 1192 return (POLLERR); 1193 return (wsevent_poll(sc->sc_base.me_evp, events, p)); 1194 } 1195 1196 #if NWSDISPLAY > 0 1197 1198 int 1199 wskbd_pickfree(void) 1200 { 1201 int i; 1202 struct wskbd_softc *sc; 1203 1204 for (i = 0; i < wskbd_cd.cd_ndevs; i++) { 1205 if ((sc = wskbd_cd.cd_devs[i]) == NULL) 1206 continue; 1207 if (sc->sc_displaydv == NULL) 1208 return (i); 1209 } 1210 return (-1); 1211 } 1212 1213 struct wsevsrc * 1214 wskbd_set_console_display(struct device *displaydv, struct wsevsrc *me) 1215 { 1216 struct wskbd_softc *sc = wskbd_console_device; 1217 1218 if (sc == NULL) 1219 return (NULL); 1220 sc->sc_displaydv = displaydv; 1221 #if NWSMUX > 0 1222 (void)wsmux_attach_sc((struct wsmux_softc *)me, &sc->sc_base); 1223 #endif 1224 return (&sc->sc_base); 1225 } 1226 1227 int 1228 wskbd_set_display(struct device *dv, struct device *displaydv) 1229 { 1230 struct wskbd_softc *sc = (struct wskbd_softc *)dv; 1231 struct device *odisplaydv; 1232 int error; 1233 1234 DPRINTF(("wskbd_set_display: %s odisp=%p disp=%p cons=%d\n", 1235 dv->dv_xname, sc->sc_displaydv, displaydv, 1236 sc->sc_isconsole)); 1237 1238 if (sc->sc_isconsole) 1239 return (EBUSY); 1240 1241 if (displaydv != NULL) { 1242 if (sc->sc_displaydv != NULL) 1243 return (EBUSY); 1244 } else { 1245 if (sc->sc_displaydv == NULL) 1246 return (ENXIO); 1247 } 1248 1249 odisplaydv = sc->sc_displaydv; 1250 sc->sc_displaydv = NULL; 1251 error = wskbd_enable(sc, displaydv != NULL); 1252 sc->sc_displaydv = displaydv; 1253 if (error) { 1254 sc->sc_displaydv = odisplaydv; 1255 return (error); 1256 } 1257 1258 if (displaydv) 1259 printf("%s: connecting to %s\n", 1260 sc->sc_base.me_dv.dv_xname, displaydv->dv_xname); 1261 else 1262 printf("%s: disconnecting from %s\n", 1263 sc->sc_base.me_dv.dv_xname, odisplaydv->dv_xname); 1264 1265 return (0); 1266 } 1267 1268 #endif /* NWSDISPLAY > 0 */ 1269 1270 #if NWSMUX > 0 1271 int 1272 wskbd_add_mux(int unit, struct wsmux_softc *muxsc) 1273 { 1274 struct wskbd_softc *sc; 1275 1276 if (unit < 0 || unit >= wskbd_cd.cd_ndevs || 1277 (sc = wskbd_cd.cd_devs[unit]) == NULL) 1278 return (ENXIO); 1279 1280 if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL) 1281 return (EBUSY); 1282 1283 return (wsmux_attach_sc(muxsc, &sc->sc_base)); 1284 } 1285 #endif 1286 1287 /* 1288 * Console interface. 1289 */ 1290 int 1291 wskbd_cngetc(dev_t dev) 1292 { 1293 static int num = 0; 1294 static int pos; 1295 u_int type; 1296 int data; 1297 keysym_t ks; 1298 1299 if (!wskbd_console_initted) 1300 return 0; 1301 1302 if (wskbd_console_device != NULL && 1303 !wskbd_console_device->sc_translating) 1304 return 0; 1305 1306 for(;;) { 1307 if (num-- > 0) { 1308 ks = wskbd_console_data.t_symbols[pos++]; 1309 if (KS_GROUP(ks) == KS_GROUP_Ascii) 1310 return (KS_VALUE(ks)); 1311 } else { 1312 (*wskbd_console_data.t_consops->getc) 1313 (wskbd_console_data.t_consaccesscookie, 1314 &type, &data); 1315 num = wskbd_translate(&wskbd_console_data, type, data); 1316 pos = 0; 1317 } 1318 } 1319 } 1320 1321 void 1322 wskbd_cnpollc(dev_t dev, int poll) 1323 { 1324 1325 if (!wskbd_console_initted) 1326 return; 1327 1328 if (wskbd_console_device != NULL && 1329 !wskbd_console_device->sc_translating) 1330 return; 1331 1332 (*wskbd_console_data.t_consops->pollc) 1333 (wskbd_console_data.t_consaccesscookie, poll); 1334 } 1335 1336 void 1337 wskbd_cnbell(dev_t dev, u_int pitch, u_int period, u_int volume) 1338 { 1339 if (!wskbd_console_initted) 1340 return; 1341 1342 if (wskbd_console_data.t_consops->bell != NULL) 1343 (*wskbd_console_data.t_consops->bell) 1344 (wskbd_console_data.t_consaccesscookie, pitch, period, 1345 volume); 1346 } 1347 1348 void 1349 update_leds(struct wskbd_internal *id) 1350 { 1351 int new_state; 1352 1353 new_state = 0; 1354 if (id->t_modifiers & (MOD_SHIFTLOCK | MOD_CAPSLOCK)) 1355 new_state |= WSKBD_LED_CAPS; 1356 if (id->t_modifiers & MOD_NUMLOCK) 1357 new_state |= WSKBD_LED_NUM; 1358 if (id->t_modifiers & MOD_COMPOSE) 1359 new_state |= WSKBD_LED_COMPOSE; 1360 if (id->t_modifiers & MOD_HOLDSCREEN) 1361 new_state |= WSKBD_LED_SCROLL; 1362 1363 if (id->t_sc && new_state != id->t_sc->sc_ledstate) { 1364 (*id->t_sc->sc_accessops->set_leds) 1365 (id->t_sc->sc_accesscookie, new_state); 1366 id->t_sc->sc_ledstate = new_state; 1367 } 1368 } 1369 1370 void 1371 update_modifier(struct wskbd_internal *id, u_int type, int toggle, int mask) 1372 { 1373 if (toggle) { 1374 if (type == WSCONS_EVENT_KEY_DOWN) 1375 id->t_modifiers ^= mask; 1376 } else { 1377 if (type == WSCONS_EVENT_KEY_DOWN) 1378 id->t_modifiers |= mask; 1379 else 1380 id->t_modifiers &= ~mask; 1381 } 1382 if (mask & MOD_ANYLED) 1383 update_leds(id); 1384 } 1385 1386 #if NWSDISPLAY > 0 1387 void 1388 change_displayparam(struct wskbd_softc *sc, int param, int updown, 1389 int wraparound) 1390 { 1391 int res; 1392 struct wsdisplay_param dp; 1393 1394 dp.param = param; 1395 res = wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_GETPARAM, &dp); 1396 1397 if (res == EINVAL) 1398 return; /* no such parameter */ 1399 1400 dp.curval += updown; 1401 if (dp.max < dp.curval) 1402 dp.curval = wraparound ? dp.min : dp.max; 1403 else 1404 if (dp.curval < dp.min) 1405 dp.curval = wraparound ? dp.max : dp.min; 1406 wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_SETPARAM, &dp); 1407 } 1408 #endif 1409 1410 int 1411 internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym, 1412 keysym_t ksym2) 1413 { 1414 switch (ksym) { 1415 case KS_Cmd: 1416 update_modifier(sc->id, *type, 0, MOD_COMMAND); 1417 ksym = ksym2; 1418 break; 1419 1420 case KS_Cmd1: 1421 update_modifier(sc->id, *type, 0, MOD_COMMAND1); 1422 break; 1423 1424 case KS_Cmd2: 1425 update_modifier(sc->id, *type, 0, MOD_COMMAND2); 1426 break; 1427 } 1428 1429 if (*type != WSCONS_EVENT_KEY_DOWN) 1430 return (0); 1431 1432 #ifdef HAVE_SCROLLBACK_SUPPORT 1433 #if NWSDISPLAY > 0 1434 switch (ksym) { 1435 case KS_Cmd_ScrollBack: 1436 if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) { 1437 if (sc->sc_displaydv != NULL) 1438 wsscrollback(sc->sc_displaydv, 1439 WSDISPLAY_SCROLL_BACKWARD); 1440 return (1); 1441 } 1442 break; 1443 1444 case KS_Cmd_ScrollFwd: 1445 if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) { 1446 if (sc->sc_displaydv != NULL) 1447 wsscrollback(sc->sc_displaydv, 1448 WSDISPLAY_SCROLL_FORWARD); 1449 return (1); 1450 } 1451 break; 1452 } 1453 #endif 1454 #endif 1455 1456 if (!MOD_ONESET(sc->id, MOD_COMMAND) && 1457 !MOD_ALLSET(sc->id, MOD_COMMAND1 | MOD_COMMAND2)) 1458 return (0); 1459 1460 #ifdef DDB 1461 if (ksym == KS_Cmd_Debugger) { 1462 if (sc->sc_isconsole && db_console) 1463 Debugger(); 1464 /* discard this key (ddb discarded command modifiers) */ 1465 *type = WSCONS_EVENT_KEY_UP; 1466 return (1); 1467 } 1468 #endif 1469 1470 #if NWSDISPLAY > 0 1471 if (sc->sc_displaydv == NULL) 1472 return (0); 1473 1474 switch (ksym) { 1475 case KS_Cmd_Screen0: 1476 case KS_Cmd_Screen1: 1477 case KS_Cmd_Screen2: 1478 case KS_Cmd_Screen3: 1479 case KS_Cmd_Screen4: 1480 case KS_Cmd_Screen5: 1481 case KS_Cmd_Screen6: 1482 case KS_Cmd_Screen7: 1483 case KS_Cmd_Screen8: 1484 case KS_Cmd_Screen9: 1485 case KS_Cmd_Screen10: 1486 case KS_Cmd_Screen11: 1487 wsdisplay_switch(sc->sc_displaydv, ksym - KS_Cmd_Screen0, 0); 1488 return (1); 1489 case KS_Cmd_ResetEmul: 1490 wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETEMUL); 1491 return (1); 1492 case KS_Cmd_ResetClose: 1493 wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETCLOSE); 1494 return (1); 1495 #if defined(__i386__) || defined(__amd64__) 1496 case KS_Cmd_KbdReset: 1497 switch (kbd_reset) { 1498 #ifdef DDB 1499 case 2: 1500 if (sc->sc_isconsole && db_console) 1501 Debugger(); 1502 /* discard this key (ddb discarded command modifiers) */ 1503 *type = WSCONS_EVENT_KEY_UP; 1504 break; 1505 #endif 1506 case 1: 1507 kbd_reset = 0; 1508 prsignal(initprocess, SIGUSR1); 1509 break; 1510 default: 1511 break; 1512 } 1513 return (1); 1514 #endif 1515 case KS_Cmd_BacklightOn: 1516 case KS_Cmd_BacklightOff: 1517 case KS_Cmd_BacklightToggle: 1518 change_displayparam(sc, WSDISPLAYIO_PARAM_BACKLIGHT, 1519 ksym == KS_Cmd_BacklightOff ? -1 : 1, 1520 ksym == KS_Cmd_BacklightToggle ? 1 : 0); 1521 return (1); 1522 case KS_Cmd_BrightnessUp: 1523 case KS_Cmd_BrightnessDown: 1524 case KS_Cmd_BrightnessRotate: 1525 change_displayparam(sc, WSDISPLAYIO_PARAM_BRIGHTNESS, 1526 ksym == KS_Cmd_BrightnessDown ? -1 : 1, 1527 ksym == KS_Cmd_BrightnessRotate ? 1 : 0); 1528 return (1); 1529 case KS_Cmd_ContrastUp: 1530 case KS_Cmd_ContrastDown: 1531 case KS_Cmd_ContrastRotate: 1532 change_displayparam(sc, WSDISPLAYIO_PARAM_CONTRAST, 1533 ksym == KS_Cmd_ContrastDown ? -1 : 1, 1534 ksym == KS_Cmd_ContrastRotate ? 1 : 0); 1535 return (1); 1536 } 1537 #endif 1538 return (0); 1539 } 1540 1541 int 1542 wskbd_translate(struct wskbd_internal *id, u_int type, int value) 1543 { 1544 struct wskbd_softc *sc = id->t_sc; 1545 keysym_t ksym, res, *group; 1546 struct wscons_keymap kpbuf, *kp; 1547 int gindex, iscommand = 0; 1548 1549 if (type == WSCONS_EVENT_ALL_KEYS_UP) { 1550 #if NWSDISPLAY > 0 1551 if (sc != NULL && sc->sc_repeating) { 1552 sc->sc_repeating = 0; 1553 timeout_del(&sc->sc_repeat_ch); 1554 } 1555 #endif 1556 id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R | 1557 MOD_CONTROL_L | MOD_CONTROL_R | 1558 MOD_META_L | MOD_META_R | 1559 MOD_MODESHIFT | MOD_MODELOCK | 1560 MOD_COMMAND | MOD_COMMAND1 | MOD_COMMAND2); 1561 return (0); 1562 } 1563 1564 if (sc != NULL) { 1565 if (value < 0 || value >= sc->sc_maplen) { 1566 #ifdef DEBUG 1567 printf("wskbd_translate: keycode %d out of range\n", 1568 value); 1569 #endif 1570 return (0); 1571 } 1572 kp = sc->sc_map + value; 1573 } else { 1574 kp = &kpbuf; 1575 wskbd_get_mapentry(&id->t_keymap, value, kp); 1576 } 1577 1578 /* if this key has a command, process it first */ 1579 if (sc != NULL && kp->command != KS_voidSymbol) 1580 iscommand = internal_command(sc, &type, kp->command, 1581 kp->group1[0]); 1582 1583 /* Now update modifiers */ 1584 switch (kp->group1[0]) { 1585 case KS_Shift_L: 1586 update_modifier(id, type, 0, MOD_SHIFT_L); 1587 break; 1588 1589 case KS_Shift_R: 1590 update_modifier(id, type, 0, MOD_SHIFT_R); 1591 break; 1592 1593 case KS_Shift_Lock: 1594 update_modifier(id, type, 1, MOD_SHIFTLOCK); 1595 break; 1596 1597 case KS_Caps_Lock: 1598 update_modifier(id, type, 1, MOD_CAPSLOCK); 1599 break; 1600 1601 case KS_Control_L: 1602 update_modifier(id, type, 0, MOD_CONTROL_L); 1603 break; 1604 1605 case KS_Control_R: 1606 update_modifier(id, type, 0, MOD_CONTROL_R); 1607 break; 1608 1609 case KS_Alt_L: 1610 update_modifier(id, type, 0, MOD_META_L); 1611 break; 1612 1613 case KS_Alt_R: 1614 update_modifier(id, type, 0, MOD_META_R); 1615 break; 1616 1617 case KS_Mode_switch: 1618 update_modifier(id, type, 0, MOD_MODESHIFT); 1619 break; 1620 1621 case KS_Mode_Lock: 1622 update_modifier(id, type, 1, MOD_MODELOCK); 1623 break; 1624 1625 case KS_Num_Lock: 1626 update_modifier(id, type, 1, MOD_NUMLOCK); 1627 break; 1628 1629 #if NWSDISPLAY > 0 1630 case KS_Hold_Screen: 1631 if (sc != NULL) { 1632 update_modifier(id, type, 1, MOD_HOLDSCREEN); 1633 if (sc->sc_displaydv != NULL) 1634 wsdisplay_kbdholdscreen(sc->sc_displaydv, 1635 id->t_modifiers & MOD_HOLDSCREEN); 1636 } 1637 break; 1638 1639 default: 1640 if (sc != NULL && sc->sc_repeating && 1641 ((type == WSCONS_EVENT_KEY_UP && value != sc->sc_repkey) || 1642 (type == WSCONS_EVENT_KEY_DOWN && value == sc->sc_repkey))) 1643 return (0); 1644 break; 1645 #endif 1646 } 1647 1648 #if NWSDISPLAY > 0 1649 if (sc != NULL) { 1650 if (sc->sc_repeating) { 1651 sc->sc_repeating = 0; 1652 timeout_del(&sc->sc_repeat_ch); 1653 } 1654 sc->sc_repkey = value; 1655 } 1656 #endif 1657 1658 /* If this is a key release or we are in command mode, we are done */ 1659 if (type != WSCONS_EVENT_KEY_DOWN || iscommand) 1660 return (0); 1661 1662 /* Get the keysym */ 1663 if (id->t_modifiers & (MOD_MODESHIFT|MOD_MODELOCK) && 1664 !MOD_ONESET(id, MOD_ANYCONTROL)) 1665 group = & kp->group2[0]; 1666 else 1667 group = & kp->group1[0]; 1668 1669 if ((id->t_modifiers & MOD_NUMLOCK) && 1670 KS_GROUP(group[1]) == KS_GROUP_Keypad) { 1671 gindex = !MOD_ONESET(id, MOD_ANYSHIFT); 1672 ksym = group[gindex]; 1673 } else { 1674 /* CAPS alone should only affect letter keys */ 1675 if ((id->t_modifiers & (MOD_CAPSLOCK | MOD_ANYSHIFT)) == 1676 MOD_CAPSLOCK) { 1677 gindex = 0; 1678 ksym = ksym_upcase(group[0]); 1679 } else { 1680 gindex = MOD_ONESET(id, MOD_ANYSHIFT); 1681 ksym = group[gindex]; 1682 } 1683 } 1684 1685 /* Submit Audio keys for hotkey processing */ 1686 if (KS_GROUP(ksym) == KS_GROUP_Function) { 1687 switch (ksym) { 1688 #if NAUDIO > 0 1689 case KS_AudioMute: 1690 wskbd_set_mixervolume(0, 1); 1691 return (0); 1692 case KS_AudioLower: 1693 wskbd_set_mixervolume(-1, 1); 1694 return (0); 1695 case KS_AudioRaise: 1696 wskbd_set_mixervolume(1, 1); 1697 return (0); 1698 #endif 1699 default: 1700 break; 1701 } 1702 } 1703 1704 /* Process compose sequence and dead accents */ 1705 res = KS_voidSymbol; 1706 1707 switch (KS_GROUP(ksym)) { 1708 case KS_GROUP_Ascii: 1709 case KS_GROUP_Keypad: 1710 case KS_GROUP_Function: 1711 res = ksym; 1712 break; 1713 1714 case KS_GROUP_Mod: 1715 if (ksym == KS_Multi_key) { 1716 update_modifier(id, 1, 0, MOD_COMPOSE); 1717 id->t_composelen = 2; 1718 } 1719 break; 1720 1721 case KS_GROUP_Dead: 1722 if (id->t_composelen == 0) { 1723 update_modifier(id, 1, 0, MOD_COMPOSE); 1724 id->t_composelen = 1; 1725 id->t_composebuf[0] = ksym; 1726 } else 1727 res = ksym; 1728 break; 1729 } 1730 1731 if (res == KS_voidSymbol) 1732 return (0); 1733 1734 if (id->t_composelen > 0) { 1735 /* 1736 * If the compose key also serves as AltGr (i.e. set to both 1737 * KS_Multi_key and KS_Mode_switch), and would provide a valid, 1738 * distinct combination as AltGr, leave compose mode. 1739 */ 1740 if (id->t_composelen == 2 && group == &kp->group2[0]) { 1741 if (kp->group1[gindex] != kp->group2[gindex]) 1742 id->t_composelen = 0; 1743 } 1744 1745 if (id->t_composelen != 0) { 1746 id->t_composebuf[2 - id->t_composelen] = res; 1747 if (--id->t_composelen == 0) { 1748 res = wskbd_compose_value(id->t_composebuf); 1749 update_modifier(id, 0, 0, MOD_COMPOSE); 1750 } else { 1751 return (0); 1752 } 1753 } 1754 } 1755 1756 /* We are done, return the symbol */ 1757 if (KS_GROUP(res) == KS_GROUP_Ascii) { 1758 if (MOD_ONESET(id, MOD_ANYCONTROL)) { 1759 if ((res >= KS_at && res <= KS_z) || res == KS_space) 1760 res = res & 0x1f; 1761 else if (res == KS_2) 1762 res = 0x00; 1763 else if (res >= KS_3 && res <= KS_7) 1764 res = KS_Escape + (res - KS_3); 1765 else if (res == KS_8) 1766 res = KS_Delete; 1767 } 1768 if (MOD_ONESET(id, MOD_ANYMETA)) { 1769 if (id->t_flags & WSKFL_METAESC) { 1770 id->t_symbols[0] = KS_Escape; 1771 id->t_symbols[1] = res; 1772 return (2); 1773 } else 1774 res |= 0x80; 1775 } 1776 } 1777 1778 id->t_symbols[0] = res; 1779 return (1); 1780 } 1781