1 /* $OpenBSD: wskbd.c,v 1.106 2020/07/29 05:53:52 anton 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 void wskbd_debugger(struct wskbd_softc *); 215 #if NWSDISPLAY > 0 216 void change_displayparam(struct wskbd_softc *, int, int, int); 217 #endif 218 219 int wskbd_do_ioctl_sc(struct wskbd_softc *, u_long, caddr_t, int, 220 struct proc *); 221 void wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value); 222 223 #if NWSMUX > 0 224 int wskbd_mux_open(struct wsevsrc *, struct wseventvar *); 225 int wskbd_mux_close(struct wsevsrc *); 226 #else 227 #define wskbd_mux_open NULL 228 #define wskbd_mux_close NULL 229 #endif 230 231 int wskbd_do_open(struct wskbd_softc *, struct wseventvar *); 232 int wskbd_do_ioctl(struct device *, u_long, caddr_t, int, struct proc *); 233 234 int (*wskbd_get_backlight)(struct wskbd_backlight *); 235 int (*wskbd_set_backlight)(struct wskbd_backlight *); 236 237 struct cfdriver wskbd_cd = { 238 NULL, "wskbd", DV_TTY 239 }; 240 241 struct cfattach wskbd_ca = { 242 sizeof (struct wskbd_softc), wskbd_match, wskbd_attach, 243 wskbd_detach, wskbd_activate 244 }; 245 246 #if defined(__i386__) || defined(__amd64__) 247 extern int kbd_reset; 248 #endif 249 250 #ifndef WSKBD_DEFAULT_BELL_PITCH 251 #define WSKBD_DEFAULT_BELL_PITCH 400 /* 400Hz */ 252 #endif 253 #ifndef WSKBD_DEFAULT_BELL_PERIOD 254 #define WSKBD_DEFAULT_BELL_PERIOD 100 /* 100ms */ 255 #endif 256 #ifndef WSKBD_DEFAULT_BELL_VOLUME 257 #define WSKBD_DEFAULT_BELL_VOLUME 50 /* 50% volume */ 258 #endif 259 260 struct wskbd_bell_data wskbd_default_bell_data = { 261 WSKBD_BELL_DOALL, 262 WSKBD_DEFAULT_BELL_PITCH, 263 WSKBD_DEFAULT_BELL_PERIOD, 264 WSKBD_DEFAULT_BELL_VOLUME, 265 }; 266 267 #ifndef WSKBD_DEFAULT_KEYREPEAT_DEL1 268 #define WSKBD_DEFAULT_KEYREPEAT_DEL1 400 /* 400ms to start repeating */ 269 #endif 270 #ifndef WSKBD_DEFAULT_KEYREPEAT_DELN 271 #define WSKBD_DEFAULT_KEYREPEAT_DELN 100 /* 100ms to between repeats */ 272 #endif 273 274 struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = { 275 WSKBD_KEYREPEAT_DOALL, 276 WSKBD_DEFAULT_KEYREPEAT_DEL1, 277 WSKBD_DEFAULT_KEYREPEAT_DELN, 278 }; 279 280 #if NWSMUX > 0 || NWSDISPLAY > 0 281 struct wssrcops wskbd_srcops = { 282 .type = WSMUX_KBD, 283 .dopen = wskbd_mux_open, 284 .dclose = wskbd_mux_close, 285 .dioctl = wskbd_do_ioctl, 286 .ddispioctl = wskbd_displayioctl, 287 #if NWSDISPLAY > 0 288 .dsetdisplay = wskbd_set_display, 289 #else 290 .dsetdisplay = NULL, 291 #endif 292 }; 293 #endif 294 295 #if NWSDISPLAY > 0 296 void wskbd_repeat(void *v); 297 #endif 298 299 static int wskbd_console_initted; 300 static struct wskbd_softc *wskbd_console_device; 301 static struct wskbd_internal wskbd_console_data; 302 303 void wskbd_update_layout(struct wskbd_internal *, kbd_t); 304 305 #if NAUDIO > 0 306 extern int wskbd_set_mixervolume(long, long); 307 #endif 308 309 void 310 wskbd_update_layout(struct wskbd_internal *id, kbd_t enc) 311 { 312 if (enc & KB_METAESC) 313 id->t_flags |= WSKFL_METAESC; 314 else 315 id->t_flags &= ~WSKFL_METAESC; 316 317 id->t_keymap.layout = enc; 318 } 319 320 /* 321 * Print function (for parent devices). 322 */ 323 int 324 wskbddevprint(void *aux, const char *pnp) 325 { 326 #if 0 327 struct wskbddev_attach_args *ap = aux; 328 #endif 329 330 if (pnp) 331 printf("wskbd at %s", pnp); 332 #if 0 333 printf(" console %d", ap->console); 334 #endif 335 336 return (UNCONF); 337 } 338 339 int 340 wskbd_match(struct device *parent, void *match, void *aux) 341 { 342 struct cfdata *cf = match; 343 struct wskbddev_attach_args *ap = aux; 344 345 if (cf->wskbddevcf_console != WSKBDDEVCF_CONSOLE_UNK) { 346 /* 347 * If console-ness of device specified, either match 348 * exactly (at high priority), or fail. 349 */ 350 if (cf->wskbddevcf_console != 0 && ap->console != 0) 351 return (10); 352 else 353 return (0); 354 } 355 356 /* If console-ness unspecified, it wins. */ 357 return (1); 358 } 359 360 void 361 wskbd_attach(struct device *parent, struct device *self, void *aux) 362 { 363 struct wskbd_softc *sc = (struct wskbd_softc *)self; 364 struct wskbddev_attach_args *ap = aux; 365 kbd_t layout; 366 #if NWSMUX > 0 367 struct wsmux_softc *wsmux_sc = NULL; 368 int mux, error; 369 #endif 370 371 sc->sc_isconsole = ap->console; 372 373 #if NWSMUX > 0 || NWSDISPLAY > 0 374 sc->sc_base.me_ops = &wskbd_srcops; 375 #endif 376 #if NWSMUX > 0 377 mux = sc->sc_base.me_dv.dv_cfdata->wskbddevcf_mux; 378 if (mux >= 0) 379 wsmux_sc = wsmux_getmux(mux); 380 #endif /* NWSMUX > 0 */ 381 382 if (ap->console) { 383 sc->id = &wskbd_console_data; 384 } else { 385 sc->id = malloc(sizeof(struct wskbd_internal), 386 M_DEVBUF, M_WAITOK | M_ZERO); 387 bcopy(ap->keymap, &sc->id->t_keymap, sizeof(sc->id->t_keymap)); 388 } 389 390 #if NWSDISPLAY > 0 391 timeout_set(&sc->sc_repeat_ch, wskbd_repeat, sc); 392 #endif 393 394 sc->id->t_sc = sc; 395 396 sc->sc_accessops = ap->accessops; 397 sc->sc_accesscookie = ap->accesscookie; 398 sc->sc_repeating = 0; 399 sc->sc_translating = 1; 400 sc->sc_ledstate = -1; /* force update */ 401 402 /* 403 * If this layout is the default choice of the driver (i.e. the 404 * driver doesn't know better), pick the existing layout of the 405 * current mux, if any. 406 */ 407 layout = sc->id->t_keymap.layout; 408 #if NWSMUX > 0 409 if (layout & KB_DEFAULT) { 410 if (wsmux_sc != NULL && wsmux_get_layout(wsmux_sc) != KB_NONE) 411 layout = wsmux_get_layout(wsmux_sc); 412 } 413 #endif 414 for (;;) { 415 if (wskbd_load_keymap(&sc->id->t_keymap, layout, &sc->sc_map, 416 &sc->sc_maplen) == 0) 417 break; 418 #if NWSMUX > 0 419 if (layout == sc->id->t_keymap.layout) 420 panic("cannot load keymap"); 421 if (wsmux_sc != NULL && wsmux_get_layout(wsmux_sc) != KB_NONE) { 422 printf("\n%s: cannot load keymap, " 423 "falling back to default\n%s", 424 sc->sc_base.me_dv.dv_xname, 425 sc->sc_base.me_dv.dv_xname); 426 layout = wsmux_get_layout(wsmux_sc); 427 } else 428 #endif 429 panic("cannot load keymap"); 430 } 431 wskbd_update_layout(sc->id, layout); 432 433 /* set default bell and key repeat data */ 434 sc->sc_bell_data = wskbd_default_bell_data; 435 sc->sc_keyrepeat_data = wskbd_default_keyrepeat_data; 436 437 if (ap->console) { 438 KASSERT(wskbd_console_initted); 439 KASSERT(wskbd_console_device == NULL); 440 441 wskbd_console_device = sc; 442 443 printf(": console keyboard"); 444 445 #if NWSDISPLAY > 0 446 wsdisplay_set_console_kbd(&sc->sc_base); /* sets sc_displaydv */ 447 if (sc->sc_displaydv != NULL) 448 printf(", using %s", sc->sc_displaydv->dv_xname); 449 #endif 450 } 451 452 #if NWSMUX > 0 453 /* Ignore mux for console; it always goes to the console mux. */ 454 if (wsmux_sc != NULL && ap->console == 0) { 455 printf(" mux %d\n", mux); 456 error = wsmux_attach_sc(wsmux_sc, &sc->sc_base); 457 if (error) 458 printf("%s: attach error=%d\n", 459 sc->sc_base.me_dv.dv_xname, error); 460 461 /* 462 * Try and set this encoding as the mux default if it 463 * hasn't any yet, and if this is not a driver default 464 * layout (i.e. parent driver pretends to know better). 465 * Note that wsmux_set_layout() rejects layouts with 466 * KB_DEFAULT set. 467 */ 468 if (wsmux_get_layout(wsmux_sc) == KB_NONE) 469 wsmux_set_layout(wsmux_sc, layout); 470 } else 471 #endif 472 printf("\n"); 473 474 #if NWSDISPLAY > 0 && NWSMUX == 0 475 if (ap->console == 0) { 476 /* 477 * In the non-wsmux world, always connect wskbd0 and wsdisplay0 478 * together. 479 */ 480 extern struct cfdriver wsdisplay_cd; 481 482 if (wsdisplay_cd.cd_ndevs != 0 && self->dv_unit == 0) { 483 if (wskbd_set_display(self, 484 wsdisplay_cd.cd_devs[0]) == 0) 485 wsdisplay_set_kbd(wsdisplay_cd.cd_devs[0], 486 (struct wsevsrc *)sc); 487 } 488 } 489 #endif 490 } 491 492 void 493 wskbd_cnattach(const struct wskbd_consops *consops, void *conscookie, 494 const struct wskbd_mapdata *mapdata) 495 { 496 497 KASSERT(!wskbd_console_initted); 498 499 bcopy(mapdata, &wskbd_console_data.t_keymap, sizeof(*mapdata)); 500 wskbd_update_layout(&wskbd_console_data, mapdata->layout); 501 502 wskbd_console_data.t_consops = consops; 503 wskbd_console_data.t_consaccesscookie = conscookie; 504 505 #if NWSDISPLAY > 0 506 wsdisplay_set_cons_kbd(wskbd_cngetc, wskbd_cnpollc, wskbd_cnbell); 507 #endif 508 509 wskbd_console_initted = 1; 510 } 511 512 void 513 wskbd_cndetach(void) 514 { 515 KASSERT(wskbd_console_initted); 516 517 wskbd_console_data.t_keymap.keydesc = NULL; 518 wskbd_console_data.t_keymap.layout = KB_NONE; 519 520 wskbd_console_data.t_consops = NULL; 521 wskbd_console_data.t_consaccesscookie = NULL; 522 523 #if NWSDISPLAY > 0 524 wsdisplay_unset_cons_kbd(); 525 #endif 526 527 wskbd_console_device = NULL; 528 wskbd_console_initted = 0; 529 } 530 531 #if NWSDISPLAY > 0 532 void 533 wskbd_repeat(void *v) 534 { 535 struct wskbd_softc *sc = (struct wskbd_softc *)v; 536 int s = spltty(); 537 538 if (sc->sc_repeating == 0) { 539 /* 540 * race condition: a "key up" event came in when wskbd_repeat() 541 * was already called but not yet spltty()'d 542 */ 543 splx(s); 544 return; 545 } 546 if (sc->sc_translating) { 547 /* deliver keys */ 548 if (sc->sc_displaydv != NULL) 549 wsdisplay_kbdinput(sc->sc_displaydv, 550 sc->id->t_keymap.layout, 551 sc->id->t_symbols, sc->sc_repeating); 552 } else { 553 /* queue event */ 554 wskbd_deliver_event(sc, sc->sc_repeat_type, 555 sc->sc_repeat_value); 556 } 557 if (sc->sc_keyrepeat_data.delN != 0) 558 timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.delN); 559 splx(s); 560 } 561 #endif 562 563 int 564 wskbd_activate(struct device *self, int act) 565 { 566 struct wskbd_softc *sc = (struct wskbd_softc *)self; 567 568 if (act == DVACT_DEACTIVATE) 569 sc->sc_dying = 1; 570 return (0); 571 } 572 573 /* 574 * Detach a keyboard. To keep track of users of the softc we keep 575 * a reference count that's incremented while inside, e.g., read. 576 * If the keyboard is active and the reference count is > 0 (0 is the 577 * normal state) we post an event and then wait for the process 578 * that had the reference to wake us up again. Then we blow away the 579 * vnode and return (which will deallocate the softc). 580 */ 581 int 582 wskbd_detach(struct device *self, int flags) 583 { 584 struct wskbd_softc *sc = (struct wskbd_softc *)self; 585 struct wseventvar *evar; 586 int maj, mn; 587 int s; 588 589 #if NWSMUX > 0 590 /* Tell parent mux we're leaving. */ 591 if (sc->sc_base.me_parent != NULL) 592 wsmux_detach_sc(&sc->sc_base); 593 #endif 594 595 #if NWSDISPLAY > 0 596 if (sc->sc_repeating) { 597 sc->sc_repeating = 0; 598 timeout_del(&sc->sc_repeat_ch); 599 } 600 #endif 601 602 if (sc->sc_isconsole) { 603 KASSERT(wskbd_console_device == sc); 604 wskbd_cndetach(); 605 } 606 607 evar = sc->sc_base.me_evp; 608 if (evar != NULL) { 609 s = spltty(); 610 if (--sc->sc_refcnt >= 0) { 611 /* Wake everyone by generating a dummy event. */ 612 if (++evar->put >= WSEVENT_QSIZE) 613 evar->put = 0; 614 WSEVENT_WAKEUP(evar); 615 /* Wait for processes to go away. */ 616 if (tsleep_nsec(sc, PZERO, "wskdet", SEC_TO_NSEC(60))) 617 printf("wskbd_detach: %s didn't detach\n", 618 sc->sc_base.me_dv.dv_xname); 619 } 620 splx(s); 621 } 622 623 free(sc->sc_map, M_DEVBUF, 624 sc->sc_maplen * sizeof(struct wscons_keymap)); 625 626 /* locate the major number */ 627 for (maj = 0; maj < nchrdev; maj++) 628 if (cdevsw[maj].d_open == wskbdopen) 629 break; 630 631 /* Nuke the vnodes for any open instances. */ 632 mn = self->dv_unit; 633 vdevgone(maj, mn, mn, VCHR); 634 635 return (0); 636 } 637 638 void 639 wskbd_input(struct device *dev, u_int type, int value) 640 { 641 struct wskbd_softc *sc = (struct wskbd_softc *)dev; 642 #if NWSDISPLAY > 0 643 int num; 644 #endif 645 646 #if NWSDISPLAY > 0 647 if (sc->sc_repeating) { 648 sc->sc_repeating = 0; 649 timeout_del(&sc->sc_repeat_ch); 650 } 651 652 /* 653 * If /dev/wskbdN is not connected in event mode translate and 654 * send upstream. 655 */ 656 if (sc->sc_translating) { 657 #ifdef HAVE_BURNER_SUPPORT 658 if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_displaydv != NULL) 659 wsdisplay_burn(sc->sc_displaydv, WSDISPLAY_BURN_KBD); 660 #endif 661 num = wskbd_translate(sc->id, type, value); 662 if (num > 0) { 663 if (sc->sc_displaydv != NULL) { 664 #ifdef HAVE_SCROLLBACK_SUPPORT 665 /* XXX - Shift_R+PGUP(release) emits PrtSc */ 666 if (sc->id->t_symbols[0] != KS_Print_Screen) { 667 wsscrollback(sc->sc_displaydv, 668 WSDISPLAY_SCROLL_RESET); 669 } 670 #endif 671 wsdisplay_kbdinput(sc->sc_displaydv, 672 sc->id->t_keymap.layout, 673 sc->id->t_symbols, num); 674 } 675 676 if (sc->sc_keyrepeat_data.del1 != 0) { 677 sc->sc_repeating = num; 678 timeout_add_msec(&sc->sc_repeat_ch, 679 sc->sc_keyrepeat_data.del1); 680 } 681 } 682 return; 683 } 684 #endif 685 686 wskbd_deliver_event(sc, type, value); 687 688 #if NWSDISPLAY > 0 689 /* Repeat key presses if enabled. */ 690 if (type == WSCONS_EVENT_KEY_DOWN && sc->sc_keyrepeat_data.del1 != 0) { 691 sc->sc_repeat_type = type; 692 sc->sc_repeat_value = value; 693 sc->sc_repeating = 1; 694 timeout_add_msec(&sc->sc_repeat_ch, sc->sc_keyrepeat_data.del1); 695 } 696 #endif 697 } 698 699 /* 700 * Keyboard is generating events. Turn this keystroke into an 701 * event and put it in the queue. If the queue is full, the 702 * keystroke is lost (sorry!). 703 */ 704 void 705 wskbd_deliver_event(struct wskbd_softc *sc, u_int type, int value) 706 { 707 struct wseventvar *evar; 708 struct wscons_event *ev; 709 int put; 710 711 evar = sc->sc_base.me_evp; 712 713 if (evar == NULL) { 714 DPRINTF(("%s: not open\n", __func__)); 715 return; 716 } 717 718 #ifdef DIAGNOSTIC 719 if (evar->q == NULL) { 720 printf("wskbd_input: evar->q=NULL\n"); 721 return; 722 } 723 #endif 724 725 put = evar->put; 726 ev = &evar->q[put]; 727 put = (put + 1) % WSEVENT_QSIZE; 728 if (put == evar->get) { 729 log(LOG_WARNING, "%s: event queue overflow\n", 730 sc->sc_base.me_dv.dv_xname); 731 return; 732 } 733 ev->type = type; 734 ev->value = value; 735 nanotime(&ev->time); 736 evar->put = put; 737 WSEVENT_WAKEUP(evar); 738 } 739 740 #ifdef WSDISPLAY_COMPAT_RAWKBD 741 void 742 wskbd_rawinput(struct device *dev, u_char *buf, int len) 743 { 744 #if NWSDISPLAY > 0 745 struct wskbd_softc *sc = (struct wskbd_softc *)dev; 746 747 if (sc->sc_displaydv != NULL) 748 wsdisplay_rawkbdinput(sc->sc_displaydv, buf, len); 749 #endif 750 } 751 #endif /* WSDISPLAY_COMPAT_RAWKBD */ 752 753 int 754 wskbd_enable(struct wskbd_softc *sc, int on) 755 { 756 int error; 757 758 #if NWSDISPLAY > 0 759 if (sc->sc_displaydv != NULL) 760 return (0); 761 762 /* Always cancel auto repeat when fiddling with the kbd. */ 763 if (sc->sc_repeating) { 764 sc->sc_repeating = 0; 765 timeout_del(&sc->sc_repeat_ch); 766 } 767 #endif 768 769 error = (*sc->sc_accessops->enable)(sc->sc_accesscookie, on); 770 DPRINTF(("%s: sc=%p on=%d res=%d\n", __func__, sc, on, error)); 771 return (error); 772 } 773 774 #if NWSMUX > 0 775 int 776 wskbd_mux_open(struct wsevsrc *me, struct wseventvar *evp) 777 { 778 struct wskbd_softc *sc = (struct wskbd_softc *)me; 779 780 if (sc->sc_dying) 781 return (EIO); 782 783 return (wskbd_do_open(sc, evp)); 784 } 785 #endif 786 787 int 788 wskbdopen(dev_t dev, int flags, int mode, struct proc *p) 789 { 790 struct wskbd_softc *sc; 791 struct wseventvar *evar; 792 int unit, error; 793 794 unit = minor(dev); 795 if (unit >= wskbd_cd.cd_ndevs || /* make sure it was attached */ 796 (sc = wskbd_cd.cd_devs[unit]) == NULL) 797 return (ENXIO); 798 799 #if NWSMUX > 0 800 DPRINTF(("%s: %s mux=%p\n", __func__, sc->sc_base.me_dv.dv_xname, 801 sc->sc_base.me_parent)); 802 #endif 803 804 if (sc->sc_dying) 805 return (EIO); 806 807 if ((flags & (FREAD | FWRITE)) == FWRITE) { 808 /* Not opening for read, only ioctl is available. */ 809 return (0); 810 } 811 812 #if NWSMUX > 0 813 if (sc->sc_base.me_parent != NULL) { 814 /* Grab the keyboard out of the greedy hands of the mux. */ 815 DPRINTF(("%s: detach\n", __func__)); 816 wsmux_detach_sc(&sc->sc_base); 817 } 818 #endif 819 820 if (sc->sc_base.me_evp != NULL) 821 return (EBUSY); 822 823 evar = &sc->sc_base.me_evar; 824 if (wsevent_init(evar)) 825 return (EBUSY); 826 827 error = wskbd_do_open(sc, evar); 828 if (error) 829 wsevent_fini(evar); 830 return (error); 831 } 832 833 int 834 wskbd_do_open(struct wskbd_softc *sc, struct wseventvar *evp) 835 { 836 int error; 837 838 /* The device could already be attached to a mux. */ 839 if (sc->sc_base.me_evp != NULL) 840 return (EBUSY); 841 842 sc->sc_base.me_evp = evp; 843 sc->sc_translating = 0; 844 845 error = wskbd_enable(sc, 1); 846 if (error) 847 sc->sc_base.me_evp = NULL; 848 return (error); 849 } 850 851 int 852 wskbdclose(dev_t dev, int flags, int mode, struct proc *p) 853 { 854 struct wskbd_softc *sc = 855 (struct wskbd_softc *)wskbd_cd.cd_devs[minor(dev)]; 856 struct wseventvar *evar = sc->sc_base.me_evp; 857 858 if ((flags & (FREAD | FWRITE)) == FWRITE) { 859 /* not open for read */ 860 return (0); 861 } 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(("%s: attach\n", __func__)); 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 (void)wskbd_enable(sc, 0); 893 sc->sc_translating = 1; 894 sc->sc_base.me_evp = NULL; 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 struct wseventvar *evar; 951 int error; 952 953 /* 954 * Try the generic ioctls that the wskbd interface supports. 955 */ 956 switch (cmd) { 957 case FIONBIO: /* we will remove this someday (soon???) */ 958 return (0); 959 960 case FIOASYNC: 961 if (sc->sc_base.me_evp == NULL) 962 return (EINVAL); 963 sc->sc_base.me_evp->async = *(int *)data != 0; 964 return (0); 965 966 case FIOGETOWN: 967 case TIOCGPGRP: 968 evar = sc->sc_base.me_evp; 969 if (evar == NULL) 970 return (EINVAL); 971 sigio_getown(&evar->sigio, cmd, data); 972 return (0); 973 974 case FIOSETOWN: 975 case TIOCSPGRP: 976 evar = sc->sc_base.me_evp; 977 if (evar == NULL) 978 return (EINVAL); 979 return (sigio_setown(&evar->sigio, cmd, data)); 980 } 981 982 /* 983 * Try the keyboard driver for WSKBDIO ioctls. It returns -1 984 * if it didn't recognize the request. 985 */ 986 error = wskbd_displayioctl(&sc->sc_base.me_dv, cmd, data, flag, p); 987 return (error != -1 ? error : ENOTTY); 988 } 989 990 /* 991 * WSKBDIO ioctls, handled in both emulation mode and in ``raw'' mode. 992 * Some of these have no real effect in raw mode, however. 993 */ 994 int 995 wskbd_displayioctl(struct device *dev, u_long cmd, caddr_t data, int flag, 996 struct proc *p) 997 { 998 struct wskbd_softc *sc = (struct wskbd_softc *)dev; 999 struct wskbd_bell_data *ubdp, *kbdp; 1000 struct wskbd_keyrepeat_data *ukdp, *kkdp; 1001 struct wskbd_map_data *umdp; 1002 struct wskbd_encoding_data *uedp; 1003 kbd_t enc; 1004 void *buf; 1005 int len, error; 1006 int count, i; 1007 1008 switch (cmd) { 1009 case WSKBDIO_BELL: 1010 case WSKBDIO_COMPLEXBELL: 1011 case WSKBDIO_SETBELL: 1012 case WSKBDIO_SETKEYREPEAT: 1013 case WSKBDIO_SETDEFAULTKEYREPEAT: 1014 case WSKBDIO_SETMAP: 1015 case WSKBDIO_SETENCODING: 1016 case WSKBDIO_SETBACKLIGHT: 1017 if ((flag & FWRITE) == 0) 1018 return (EACCES); 1019 } 1020 1021 switch (cmd) { 1022 #define SETBELL(dstp, srcp, dfltp) \ 1023 do { \ 1024 (dstp)->pitch = ((srcp)->which & WSKBD_BELL_DOPITCH) ? \ 1025 (srcp)->pitch : (dfltp)->pitch; \ 1026 (dstp)->period = ((srcp)->which & WSKBD_BELL_DOPERIOD) ? \ 1027 (srcp)->period : (dfltp)->period; \ 1028 (dstp)->volume = ((srcp)->which & WSKBD_BELL_DOVOLUME) ? \ 1029 (srcp)->volume : (dfltp)->volume; \ 1030 (dstp)->which = WSKBD_BELL_DOALL; \ 1031 } while (0) 1032 1033 case WSKBDIO_BELL: 1034 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, 1035 WSKBDIO_COMPLEXBELL, (caddr_t)&sc->sc_bell_data, flag, p)); 1036 1037 case WSKBDIO_COMPLEXBELL: 1038 ubdp = (struct wskbd_bell_data *)data; 1039 SETBELL(ubdp, ubdp, &sc->sc_bell_data); 1040 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, 1041 WSKBDIO_COMPLEXBELL, (caddr_t)ubdp, flag, p)); 1042 1043 case WSKBDIO_SETBELL: 1044 kbdp = &sc->sc_bell_data; 1045 setbell: 1046 ubdp = (struct wskbd_bell_data *)data; 1047 SETBELL(kbdp, ubdp, kbdp); 1048 return (0); 1049 1050 case WSKBDIO_GETBELL: 1051 kbdp = &sc->sc_bell_data; 1052 getbell: 1053 ubdp = (struct wskbd_bell_data *)data; 1054 SETBELL(ubdp, kbdp, kbdp); 1055 return (0); 1056 1057 case WSKBDIO_SETDEFAULTBELL: 1058 if ((error = suser(p)) != 0) 1059 return (error); 1060 kbdp = &wskbd_default_bell_data; 1061 goto setbell; 1062 1063 1064 case WSKBDIO_GETDEFAULTBELL: 1065 kbdp = &wskbd_default_bell_data; 1066 goto getbell; 1067 1068 #undef SETBELL 1069 1070 #define SETKEYREPEAT(dstp, srcp, dfltp) \ 1071 do { \ 1072 (dstp)->del1 = ((srcp)->which & WSKBD_KEYREPEAT_DODEL1) ? \ 1073 (srcp)->del1 : (dfltp)->del1; \ 1074 (dstp)->delN = ((srcp)->which & WSKBD_KEYREPEAT_DODELN) ? \ 1075 (srcp)->delN : (dfltp)->delN; \ 1076 (dstp)->which = WSKBD_KEYREPEAT_DOALL; \ 1077 } while (0) 1078 1079 case WSKBDIO_SETKEYREPEAT: 1080 kkdp = &sc->sc_keyrepeat_data; 1081 setkeyrepeat: 1082 ukdp = (struct wskbd_keyrepeat_data *)data; 1083 SETKEYREPEAT(kkdp, ukdp, kkdp); 1084 return (0); 1085 1086 case WSKBDIO_GETKEYREPEAT: 1087 kkdp = &sc->sc_keyrepeat_data; 1088 getkeyrepeat: 1089 ukdp = (struct wskbd_keyrepeat_data *)data; 1090 SETKEYREPEAT(ukdp, kkdp, kkdp); 1091 return (0); 1092 1093 case WSKBDIO_SETDEFAULTKEYREPEAT: 1094 if ((error = suser(p)) != 0) 1095 return (error); 1096 kkdp = &wskbd_default_keyrepeat_data; 1097 goto setkeyrepeat; 1098 1099 1100 case WSKBDIO_GETDEFAULTKEYREPEAT: 1101 kkdp = &wskbd_default_keyrepeat_data; 1102 goto getkeyrepeat; 1103 1104 #undef SETKEYREPEAT 1105 1106 case WSKBDIO_SETMAP: 1107 umdp = (struct wskbd_map_data *)data; 1108 if (umdp->maplen > WSKBDIO_MAXMAPLEN) 1109 return (EINVAL); 1110 1111 buf = mallocarray(umdp->maplen, sizeof(struct wscons_keymap), 1112 M_TEMP, M_WAITOK); 1113 len = umdp->maplen * sizeof(struct wscons_keymap); 1114 1115 error = copyin(umdp->map, buf, len); 1116 if (error == 0) { 1117 wskbd_init_keymap(umdp->maplen, 1118 &sc->sc_map, &sc->sc_maplen); 1119 memcpy(sc->sc_map, buf, len); 1120 /* drop the variant bits handled by the map */ 1121 enc = KB_USER | (KB_VARIANT(sc->id->t_keymap.layout) & 1122 KB_HANDLEDBYWSKBD); 1123 wskbd_update_layout(sc->id, enc); 1124 } 1125 free(buf, M_TEMP, len); 1126 return(error); 1127 1128 case WSKBDIO_GETMAP: 1129 umdp = (struct wskbd_map_data *)data; 1130 if (umdp->maplen > sc->sc_maplen) 1131 umdp->maplen = sc->sc_maplen; 1132 error = copyout(sc->sc_map, umdp->map, 1133 umdp->maplen*sizeof(struct wscons_keymap)); 1134 return(error); 1135 1136 case WSKBDIO_GETENCODING: 1137 *((kbd_t *)data) = sc->id->t_keymap.layout & ~KB_DEFAULT; 1138 return(0); 1139 1140 case WSKBDIO_SETENCODING: 1141 enc = *((kbd_t *)data); 1142 if (KB_ENCODING(enc) == KB_USER) { 1143 /* user map must already be loaded */ 1144 if (KB_ENCODING(sc->id->t_keymap.layout) != KB_USER) 1145 return (EINVAL); 1146 /* map variants make no sense */ 1147 if (KB_VARIANT(enc) & ~KB_HANDLEDBYWSKBD) 1148 return (EINVAL); 1149 } else { 1150 error = wskbd_load_keymap(&sc->id->t_keymap, enc, 1151 &sc->sc_map, &sc->sc_maplen); 1152 if (error) 1153 return (error); 1154 } 1155 wskbd_update_layout(sc->id, enc); 1156 #if NWSMUX > 0 1157 /* Update mux default layout */ 1158 if (sc->sc_base.me_parent != NULL) 1159 wsmux_set_layout(sc->sc_base.me_parent, enc); 1160 #endif 1161 return (0); 1162 1163 case WSKBDIO_GETENCODINGS: 1164 uedp = (struct wskbd_encoding_data *)data; 1165 for (count = 0; sc->id->t_keymap.keydesc[count].name; count++) 1166 ; 1167 if (uedp->nencodings > count) 1168 uedp->nencodings = count; 1169 for (i = 0; i < uedp->nencodings; i++) { 1170 error = copyout(&sc->id->t_keymap.keydesc[i].name, 1171 &uedp->encodings[i], sizeof(kbd_t)); 1172 if (error) 1173 return (error); 1174 } 1175 return (0); 1176 1177 case WSKBDIO_GETBACKLIGHT: 1178 if (wskbd_get_backlight != NULL) 1179 return (*wskbd_get_backlight)((struct wskbd_backlight *)data); 1180 break; 1181 1182 case WSKBDIO_SETBACKLIGHT: 1183 if (wskbd_set_backlight != NULL) 1184 return (*wskbd_set_backlight)((struct wskbd_backlight *)data); 1185 break; 1186 } 1187 1188 /* 1189 * Try the keyboard driver for WSKBDIO ioctls. It returns -1 1190 * if it didn't recognize the request, and in turn we return 1191 * -1 if we didn't recognize the request. 1192 */ 1193 /* printf("kbdaccess\n"); */ 1194 error = (*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd, data, 1195 flag, p); 1196 #ifdef WSDISPLAY_COMPAT_RAWKBD 1197 if (!error && cmd == WSKBDIO_SETMODE && *(int *)data == WSKBD_RAW) { 1198 int s = spltty(); 1199 sc->id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R 1200 | MOD_CONTROL_L | MOD_CONTROL_R 1201 | MOD_META_L | MOD_META_R 1202 | MOD_COMMAND 1203 | MOD_COMMAND1 | MOD_COMMAND2); 1204 #if NWSDISPLAY > 0 1205 if (sc->sc_repeating) { 1206 sc->sc_repeating = 0; 1207 timeout_del(&sc->sc_repeat_ch); 1208 } 1209 #endif 1210 splx(s); 1211 } 1212 #endif 1213 return (error); 1214 } 1215 1216 int 1217 wskbdpoll(dev_t dev, int events, struct proc *p) 1218 { 1219 struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)]; 1220 1221 if (sc->sc_base.me_evp == NULL) 1222 return (POLLERR); 1223 return (wsevent_poll(sc->sc_base.me_evp, events, p)); 1224 } 1225 1226 int 1227 wskbdkqfilter(dev_t dev, struct knote *kn) 1228 { 1229 struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)]; 1230 1231 if (sc->sc_base.me_evp == NULL) 1232 return (ENXIO); 1233 return (wsevent_kqfilter(sc->sc_base.me_evp, kn)); 1234 } 1235 1236 #if NWSDISPLAY > 0 1237 1238 int 1239 wskbd_pickfree(void) 1240 { 1241 int i; 1242 struct wskbd_softc *sc; 1243 1244 for (i = 0; i < wskbd_cd.cd_ndevs; i++) { 1245 if ((sc = wskbd_cd.cd_devs[i]) == NULL) 1246 continue; 1247 if (sc->sc_displaydv == NULL) 1248 return (i); 1249 } 1250 return (-1); 1251 } 1252 1253 struct wsevsrc * 1254 wskbd_set_console_display(struct device *displaydv, struct wsevsrc *me) 1255 { 1256 struct wskbd_softc *sc = wskbd_console_device; 1257 1258 if (sc == NULL) 1259 return (NULL); 1260 sc->sc_displaydv = displaydv; 1261 #if NWSMUX > 0 1262 (void)wsmux_attach_sc((struct wsmux_softc *)me, &sc->sc_base); 1263 #endif 1264 return (&sc->sc_base); 1265 } 1266 1267 int 1268 wskbd_set_display(struct device *dv, struct device *displaydv) 1269 { 1270 struct wskbd_softc *sc = (struct wskbd_softc *)dv; 1271 struct device *odisplaydv; 1272 int error; 1273 1274 DPRINTF(("%s: %s odisp=%p disp=%p cons=%d\n", __func__, 1275 dv->dv_xname, sc->sc_displaydv, displaydv, 1276 sc->sc_isconsole)); 1277 1278 if (sc->sc_isconsole) 1279 return (EBUSY); 1280 1281 if (displaydv != NULL) { 1282 if (sc->sc_displaydv != NULL) 1283 return (EBUSY); 1284 } else { 1285 if (sc->sc_displaydv == NULL) 1286 return (ENXIO); 1287 } 1288 1289 odisplaydv = sc->sc_displaydv; 1290 sc->sc_displaydv = NULL; 1291 error = wskbd_enable(sc, displaydv != NULL); 1292 sc->sc_displaydv = displaydv; 1293 if (error) { 1294 sc->sc_displaydv = odisplaydv; 1295 return (error); 1296 } 1297 1298 if (displaydv) 1299 printf("%s: connecting to %s\n", 1300 sc->sc_base.me_dv.dv_xname, displaydv->dv_xname); 1301 else 1302 printf("%s: disconnecting from %s\n", 1303 sc->sc_base.me_dv.dv_xname, odisplaydv->dv_xname); 1304 1305 return (0); 1306 } 1307 1308 #endif /* NWSDISPLAY > 0 */ 1309 1310 #if NWSMUX > 0 1311 int 1312 wskbd_add_mux(int unit, struct wsmux_softc *muxsc) 1313 { 1314 struct wskbd_softc *sc; 1315 1316 if (unit < 0 || unit >= wskbd_cd.cd_ndevs || 1317 (sc = wskbd_cd.cd_devs[unit]) == NULL) 1318 return (ENXIO); 1319 1320 if (sc->sc_base.me_parent != NULL || sc->sc_base.me_evp != NULL) 1321 return (EBUSY); 1322 1323 return (wsmux_attach_sc(muxsc, &sc->sc_base)); 1324 } 1325 #endif 1326 1327 /* 1328 * Console interface. 1329 */ 1330 int 1331 wskbd_cngetc(dev_t dev) 1332 { 1333 static int num = 0; 1334 static int pos; 1335 u_int type; 1336 int data; 1337 keysym_t ks; 1338 1339 if (!wskbd_console_initted) 1340 return 0; 1341 1342 if (wskbd_console_device != NULL && 1343 !wskbd_console_device->sc_translating) 1344 return 0; 1345 1346 for(;;) { 1347 if (num-- > 0) { 1348 ks = wskbd_console_data.t_symbols[pos++]; 1349 if (KS_GROUP(ks) == KS_GROUP_Ascii) 1350 return (KS_VALUE(ks)); 1351 } else { 1352 (*wskbd_console_data.t_consops->getc) 1353 (wskbd_console_data.t_consaccesscookie, 1354 &type, &data); 1355 num = wskbd_translate(&wskbd_console_data, type, data); 1356 pos = 0; 1357 } 1358 } 1359 } 1360 1361 void 1362 wskbd_cnpollc(dev_t dev, int poll) 1363 { 1364 if (!wskbd_console_initted) 1365 return; 1366 1367 if (wskbd_console_device != NULL && 1368 !wskbd_console_device->sc_translating) 1369 return; 1370 1371 (*wskbd_console_data.t_consops->pollc) 1372 (wskbd_console_data.t_consaccesscookie, poll); 1373 } 1374 1375 void 1376 wskbd_cnbell(dev_t dev, u_int pitch, u_int period, u_int volume) 1377 { 1378 if (!wskbd_console_initted) 1379 return; 1380 1381 if (wskbd_console_data.t_consops->bell != NULL) 1382 (*wskbd_console_data.t_consops->bell) 1383 (wskbd_console_data.t_consaccesscookie, pitch, period, 1384 volume); 1385 } 1386 1387 void 1388 update_leds(struct wskbd_internal *id) 1389 { 1390 int new_state; 1391 1392 new_state = 0; 1393 if (id->t_modifiers & (MOD_SHIFTLOCK | MOD_CAPSLOCK)) 1394 new_state |= WSKBD_LED_CAPS; 1395 if (id->t_modifiers & MOD_NUMLOCK) 1396 new_state |= WSKBD_LED_NUM; 1397 if (id->t_modifiers & MOD_COMPOSE) 1398 new_state |= WSKBD_LED_COMPOSE; 1399 if (id->t_modifiers & MOD_HOLDSCREEN) 1400 new_state |= WSKBD_LED_SCROLL; 1401 1402 if (id->t_sc && new_state != id->t_sc->sc_ledstate) { 1403 (*id->t_sc->sc_accessops->set_leds) 1404 (id->t_sc->sc_accesscookie, new_state); 1405 id->t_sc->sc_ledstate = new_state; 1406 } 1407 } 1408 1409 void 1410 update_modifier(struct wskbd_internal *id, u_int type, int toggle, int mask) 1411 { 1412 if (toggle) { 1413 if (type == WSCONS_EVENT_KEY_DOWN) 1414 id->t_modifiers ^= mask; 1415 } else { 1416 if (type == WSCONS_EVENT_KEY_DOWN) 1417 id->t_modifiers |= mask; 1418 else 1419 id->t_modifiers &= ~mask; 1420 } 1421 if (mask & MOD_ANYLED) 1422 update_leds(id); 1423 } 1424 1425 #if NWSDISPLAY > 0 1426 void 1427 change_displayparam(struct wskbd_softc *sc, int param, int updown, 1428 int wraparound) 1429 { 1430 int res; 1431 struct wsdisplay_param dp; 1432 1433 dp.param = param; 1434 res = wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_GETPARAM, &dp); 1435 1436 if (res == EINVAL) 1437 return; /* no such parameter */ 1438 1439 dp.curval += updown; 1440 if (dp.max < dp.curval) 1441 dp.curval = wraparound ? dp.min : dp.max; 1442 else 1443 if (dp.curval < dp.min) 1444 dp.curval = wraparound ? dp.max : dp.min; 1445 wsdisplay_param(sc->sc_displaydv, WSDISPLAYIO_SETPARAM, &dp); 1446 } 1447 #endif 1448 1449 int 1450 internal_command(struct wskbd_softc *sc, u_int *type, keysym_t ksym, 1451 keysym_t ksym2) 1452 { 1453 switch (ksym) { 1454 case KS_Cmd: 1455 update_modifier(sc->id, *type, 0, MOD_COMMAND); 1456 ksym = ksym2; 1457 break; 1458 1459 case KS_Cmd1: 1460 update_modifier(sc->id, *type, 0, MOD_COMMAND1); 1461 break; 1462 1463 case KS_Cmd2: 1464 update_modifier(sc->id, *type, 0, MOD_COMMAND2); 1465 break; 1466 } 1467 1468 if (*type != WSCONS_EVENT_KEY_DOWN) 1469 return (0); 1470 1471 #ifdef HAVE_SCROLLBACK_SUPPORT 1472 #if NWSDISPLAY > 0 1473 switch (ksym) { 1474 case KS_Cmd_ScrollBack: 1475 if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) { 1476 if (sc->sc_displaydv != NULL) 1477 wsscrollback(sc->sc_displaydv, 1478 WSDISPLAY_SCROLL_BACKWARD); 1479 return (1); 1480 } 1481 break; 1482 1483 case KS_Cmd_ScrollFwd: 1484 if (MOD_ONESET(sc->id, MOD_ANYSHIFT)) { 1485 if (sc->sc_displaydv != NULL) 1486 wsscrollback(sc->sc_displaydv, 1487 WSDISPLAY_SCROLL_FORWARD); 1488 return (1); 1489 } 1490 break; 1491 } 1492 #endif 1493 #endif 1494 1495 if (!MOD_ONESET(sc->id, MOD_COMMAND) && 1496 !MOD_ALLSET(sc->id, MOD_COMMAND1 | MOD_COMMAND2)) 1497 return (0); 1498 1499 #ifdef DDB 1500 if (ksym == KS_Cmd_Debugger) { 1501 wskbd_debugger(sc); 1502 /* discard this key (ddb discarded command modifiers) */ 1503 *type = WSCONS_EVENT_KEY_UP; 1504 return (1); 1505 } 1506 #endif 1507 1508 #if NWSDISPLAY > 0 1509 if (sc->sc_displaydv == NULL) 1510 return (0); 1511 1512 switch (ksym) { 1513 case KS_Cmd_Screen0: 1514 case KS_Cmd_Screen1: 1515 case KS_Cmd_Screen2: 1516 case KS_Cmd_Screen3: 1517 case KS_Cmd_Screen4: 1518 case KS_Cmd_Screen5: 1519 case KS_Cmd_Screen6: 1520 case KS_Cmd_Screen7: 1521 case KS_Cmd_Screen8: 1522 case KS_Cmd_Screen9: 1523 case KS_Cmd_Screen10: 1524 case KS_Cmd_Screen11: 1525 wsdisplay_switch(sc->sc_displaydv, ksym - KS_Cmd_Screen0, 0); 1526 return (1); 1527 case KS_Cmd_ResetEmul: 1528 wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETEMUL); 1529 return (1); 1530 case KS_Cmd_ResetClose: 1531 wsdisplay_reset(sc->sc_displaydv, WSDISPLAY_RESETCLOSE); 1532 return (1); 1533 #if defined(__i386__) || defined(__amd64__) 1534 case KS_Cmd_KbdReset: 1535 switch (kbd_reset) { 1536 #ifdef DDB 1537 case 2: 1538 wskbd_debugger(sc); 1539 /* discard this key (ddb discarded command modifiers) */ 1540 *type = WSCONS_EVENT_KEY_UP; 1541 break; 1542 #endif 1543 case 1: 1544 kbd_reset = 0; 1545 prsignal(initprocess, SIGUSR1); 1546 break; 1547 default: 1548 break; 1549 } 1550 return (1); 1551 #endif 1552 case KS_Cmd_BacklightOn: 1553 case KS_Cmd_BacklightOff: 1554 case KS_Cmd_BacklightToggle: 1555 change_displayparam(sc, WSDISPLAYIO_PARAM_BACKLIGHT, 1556 ksym == KS_Cmd_BacklightOff ? -1 : 1, 1557 ksym == KS_Cmd_BacklightToggle ? 1 : 0); 1558 return (1); 1559 case KS_Cmd_BrightnessUp: 1560 wsdisplay_brightness_step(sc->sc_displaydv, 1); 1561 return (1); 1562 case KS_Cmd_BrightnessDown: 1563 wsdisplay_brightness_step(sc->sc_displaydv, -1); 1564 return (1); 1565 case KS_Cmd_BrightnessRotate: 1566 wsdisplay_brightness_cycle(sc->sc_displaydv); 1567 return (1); 1568 case KS_Cmd_ContrastUp: 1569 case KS_Cmd_ContrastDown: 1570 case KS_Cmd_ContrastRotate: 1571 change_displayparam(sc, WSDISPLAYIO_PARAM_CONTRAST, 1572 ksym == KS_Cmd_ContrastDown ? -1 : 1, 1573 ksym == KS_Cmd_ContrastRotate ? 1 : 0); 1574 return (1); 1575 } 1576 #endif 1577 return (0); 1578 } 1579 1580 int 1581 wskbd_translate(struct wskbd_internal *id, u_int type, int value) 1582 { 1583 struct wskbd_softc *sc = id->t_sc; 1584 keysym_t ksym, res, *group; 1585 struct wscons_keymap kpbuf, *kp; 1586 int gindex, iscommand = 0; 1587 1588 if (type == WSCONS_EVENT_ALL_KEYS_UP) { 1589 #if NWSDISPLAY > 0 1590 if (sc != NULL && sc->sc_repeating) { 1591 sc->sc_repeating = 0; 1592 timeout_del(&sc->sc_repeat_ch); 1593 } 1594 #endif 1595 id->t_modifiers &= ~(MOD_SHIFT_L | MOD_SHIFT_R | 1596 MOD_CONTROL_L | MOD_CONTROL_R | 1597 MOD_META_L | MOD_META_R | 1598 MOD_MODESHIFT | MOD_MODELOCK | 1599 MOD_COMMAND | MOD_COMMAND1 | MOD_COMMAND2); 1600 return (0); 1601 } 1602 1603 if (sc != NULL) { 1604 if (value < 0 || value >= sc->sc_maplen) { 1605 #ifdef DEBUG 1606 printf("wskbd_translate: keycode %d out of range\n", 1607 value); 1608 #endif 1609 return (0); 1610 } 1611 kp = sc->sc_map + value; 1612 } else { 1613 kp = &kpbuf; 1614 wskbd_get_mapentry(&id->t_keymap, value, kp); 1615 } 1616 1617 /* if this key has a command, process it first */ 1618 if (sc != NULL && kp->command != KS_voidSymbol) 1619 iscommand = internal_command(sc, &type, kp->command, 1620 kp->group1[0]); 1621 1622 /* Now update modifiers */ 1623 switch (kp->group1[0]) { 1624 case KS_Shift_L: 1625 update_modifier(id, type, 0, MOD_SHIFT_L); 1626 break; 1627 1628 case KS_Shift_R: 1629 update_modifier(id, type, 0, MOD_SHIFT_R); 1630 break; 1631 1632 case KS_Shift_Lock: 1633 update_modifier(id, type, 1, MOD_SHIFTLOCK); 1634 break; 1635 1636 case KS_Caps_Lock: 1637 update_modifier(id, type, 1, MOD_CAPSLOCK); 1638 break; 1639 1640 case KS_Control_L: 1641 update_modifier(id, type, 0, MOD_CONTROL_L); 1642 break; 1643 1644 case KS_Control_R: 1645 update_modifier(id, type, 0, MOD_CONTROL_R); 1646 break; 1647 1648 case KS_Alt_L: 1649 update_modifier(id, type, 0, MOD_META_L); 1650 break; 1651 1652 case KS_Alt_R: 1653 update_modifier(id, type, 0, MOD_META_R); 1654 break; 1655 1656 case KS_Mode_switch: 1657 update_modifier(id, type, 0, MOD_MODESHIFT); 1658 break; 1659 1660 case KS_Mode_Lock: 1661 update_modifier(id, type, 1, MOD_MODELOCK); 1662 break; 1663 1664 case KS_Num_Lock: 1665 update_modifier(id, type, 1, MOD_NUMLOCK); 1666 break; 1667 1668 #if NWSDISPLAY > 0 1669 case KS_Hold_Screen: 1670 if (sc != NULL) { 1671 update_modifier(id, type, 1, MOD_HOLDSCREEN); 1672 if (sc->sc_displaydv != NULL) 1673 wsdisplay_kbdholdscreen(sc->sc_displaydv, 1674 id->t_modifiers & MOD_HOLDSCREEN); 1675 } 1676 break; 1677 1678 default: 1679 if (sc != NULL && sc->sc_repeating && 1680 ((type == WSCONS_EVENT_KEY_UP && value != sc->sc_repkey) || 1681 (type == WSCONS_EVENT_KEY_DOWN && value == sc->sc_repkey))) 1682 return (0); 1683 break; 1684 #endif 1685 } 1686 1687 #if NWSDISPLAY > 0 1688 if (sc != NULL) { 1689 if (sc->sc_repeating) { 1690 sc->sc_repeating = 0; 1691 timeout_del(&sc->sc_repeat_ch); 1692 } 1693 sc->sc_repkey = value; 1694 } 1695 #endif 1696 1697 /* If this is a key release or we are in command mode, we are done */ 1698 if (type != WSCONS_EVENT_KEY_DOWN || iscommand) 1699 return (0); 1700 1701 /* Get the keysym */ 1702 if (id->t_modifiers & (MOD_MODESHIFT|MOD_MODELOCK) && 1703 !MOD_ONESET(id, MOD_ANYCONTROL)) 1704 group = & kp->group2[0]; 1705 else 1706 group = & kp->group1[0]; 1707 1708 if ((id->t_modifiers & MOD_NUMLOCK) && 1709 KS_GROUP(group[1]) == KS_GROUP_Keypad) { 1710 gindex = !MOD_ONESET(id, MOD_ANYSHIFT); 1711 ksym = group[gindex]; 1712 } else { 1713 /* CAPS alone should only affect letter keys */ 1714 if ((id->t_modifiers & (MOD_CAPSLOCK | MOD_ANYSHIFT)) == 1715 MOD_CAPSLOCK) { 1716 gindex = 0; 1717 ksym = ksym_upcase(group[0]); 1718 } else { 1719 gindex = MOD_ONESET(id, MOD_ANYSHIFT); 1720 ksym = group[gindex]; 1721 } 1722 } 1723 1724 /* Submit Audio keys for hotkey processing */ 1725 if (KS_GROUP(ksym) == KS_GROUP_Function) { 1726 switch (ksym) { 1727 #if NAUDIO > 0 1728 case KS_AudioMute: 1729 wskbd_set_mixervolume(0, 1); 1730 return (0); 1731 case KS_AudioLower: 1732 wskbd_set_mixervolume(-1, 1); 1733 return (0); 1734 case KS_AudioRaise: 1735 wskbd_set_mixervolume(1, 1); 1736 return (0); 1737 #endif 1738 default: 1739 break; 1740 } 1741 } 1742 1743 /* Process compose sequence and dead accents */ 1744 res = KS_voidSymbol; 1745 1746 switch (KS_GROUP(ksym)) { 1747 case KS_GROUP_Ascii: 1748 case KS_GROUP_Keypad: 1749 case KS_GROUP_Function: 1750 res = ksym; 1751 break; 1752 1753 case KS_GROUP_Mod: 1754 if (ksym == KS_Multi_key) { 1755 update_modifier(id, 1, 0, MOD_COMPOSE); 1756 id->t_composelen = 2; 1757 } 1758 break; 1759 1760 case KS_GROUP_Dead: 1761 if (id->t_composelen == 0) { 1762 update_modifier(id, 1, 0, MOD_COMPOSE); 1763 id->t_composelen = 1; 1764 id->t_composebuf[0] = ksym; 1765 } else 1766 res = ksym; 1767 break; 1768 } 1769 1770 if (res == KS_voidSymbol) 1771 return (0); 1772 1773 if (id->t_composelen > 0) { 1774 /* 1775 * If the compose key also serves as AltGr (i.e. set to both 1776 * KS_Multi_key and KS_Mode_switch), and would provide a valid, 1777 * distinct combination as AltGr, leave compose mode. 1778 */ 1779 if (id->t_composelen == 2 && group == &kp->group2[0]) { 1780 if (kp->group1[gindex] != kp->group2[gindex]) 1781 id->t_composelen = 0; 1782 } 1783 1784 if (id->t_composelen != 0) { 1785 id->t_composebuf[2 - id->t_composelen] = res; 1786 if (--id->t_composelen == 0) { 1787 res = wskbd_compose_value(id->t_composebuf); 1788 update_modifier(id, 0, 0, MOD_COMPOSE); 1789 } else { 1790 return (0); 1791 } 1792 } 1793 } 1794 1795 /* We are done, return the symbol */ 1796 if (KS_GROUP(res) == KS_GROUP_Ascii) { 1797 if (MOD_ONESET(id, MOD_ANYCONTROL)) { 1798 if ((res >= KS_at && res <= KS_z) || res == KS_space) 1799 res = res & 0x1f; 1800 else if (res == KS_2) 1801 res = 0x00; 1802 else if (res >= KS_3 && res <= KS_7) 1803 res = KS_Escape + (res - KS_3); 1804 else if (res == KS_8) 1805 res = KS_Delete; 1806 } 1807 if (MOD_ONESET(id, MOD_ANYMETA)) { 1808 if (id->t_flags & WSKFL_METAESC) { 1809 id->t_symbols[0] = KS_Escape; 1810 id->t_symbols[1] = res; 1811 return (2); 1812 } else 1813 res |= 0x80; 1814 } 1815 } 1816 1817 id->t_symbols[0] = res; 1818 return (1); 1819 } 1820 1821 void 1822 wskbd_debugger(struct wskbd_softc *sc) 1823 { 1824 #ifdef DDB 1825 if (sc->sc_isconsole && db_console) { 1826 if (sc->id->t_consops->debugger != NULL) { 1827 (*sc->id->t_consops->debugger) 1828 (sc->id->t_consaccesscookie); 1829 } else 1830 db_enter(); 1831 } 1832 #endif 1833 } 1834