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