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