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