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