1 1.73 thorpej /* $NetBSD: kbd.c,v 1.73 2021/08/07 16:19:16 thorpej Exp $ */ 2 1.1 gwr 3 1.1 gwr /* 4 1.1 gwr * Copyright (c) 1992, 1993 5 1.1 gwr * The Regents of the University of California. All rights reserved. 6 1.1 gwr * 7 1.1 gwr * This software was developed by the Computer Systems Engineering group 8 1.1 gwr * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 1.1 gwr * contributed to Berkeley. 10 1.1 gwr * 11 1.1 gwr * All advertising materials mentioning features or use of this software 12 1.1 gwr * must display the following acknowledgement: 13 1.1 gwr * This product includes software developed by the University of 14 1.1 gwr * California, Lawrence Berkeley Laboratory. 15 1.1 gwr * 16 1.1 gwr * Redistribution and use in source and binary forms, with or without 17 1.1 gwr * modification, are permitted provided that the following conditions 18 1.1 gwr * are met: 19 1.1 gwr * 1. Redistributions of source code must retain the above copyright 20 1.1 gwr * notice, this list of conditions and the following disclaimer. 21 1.1 gwr * 2. Redistributions in binary form must reproduce the above copyright 22 1.1 gwr * notice, this list of conditions and the following disclaimer in the 23 1.1 gwr * documentation and/or other materials provided with the distribution. 24 1.38 agc * 3. Neither the name of the University nor the names of its contributors 25 1.1 gwr * may be used to endorse or promote products derived from this software 26 1.1 gwr * without specific prior written permission. 27 1.1 gwr * 28 1.1 gwr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 1.1 gwr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 1.1 gwr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 1.1 gwr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 1.1 gwr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 1.1 gwr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 1.1 gwr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 1.1 gwr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 1.1 gwr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 1.1 gwr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 1.1 gwr * SUCH DAMAGE. 39 1.1 gwr * 40 1.1 gwr * @(#)kbd.c 8.2 (Berkeley) 10/30/93 41 1.1 gwr */ 42 1.1 gwr 43 1.1 gwr /* 44 1.1 gwr * Keyboard driver (/dev/kbd -- note that we do not have minor numbers 45 1.1 gwr * [yet?]). Translates incoming bytes to ASCII or to `firm_events' and 46 1.1 gwr * passes them up to the appropriate reader. 47 1.1 gwr */ 48 1.29 lukem 49 1.29 lukem #include <sys/cdefs.h> 50 1.73 thorpej __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.73 2021/08/07 16:19:16 thorpej Exp $"); 51 1.1 gwr 52 1.1 gwr #include <sys/param.h> 53 1.1 gwr #include <sys/systm.h> 54 1.13 gwr #include <sys/conf.h> 55 1.1 gwr #include <sys/device.h> 56 1.1 gwr #include <sys/ioctl.h> 57 1.13 gwr #include <sys/kernel.h> 58 1.13 gwr #include <sys/proc.h> 59 1.33 uwe #include <sys/malloc.h> 60 1.13 gwr #include <sys/signal.h> 61 1.13 gwr #include <sys/signalvar.h> 62 1.1 gwr #include <sys/time.h> 63 1.1 gwr #include <sys/syslog.h> 64 1.9 mrg #include <sys/select.h> 65 1.9 mrg #include <sys/poll.h> 66 1.27 eeh #include <sys/file.h> 67 1.1 gwr 68 1.64 macallan #include <dev/sysmon/sysmon_taskq.h> 69 1.64 macallan 70 1.35 martin #include <dev/wscons/wsksymdef.h> 71 1.35 martin 72 1.33 uwe #include <dev/sun/kbd_reg.h> 73 1.33 uwe #include <dev/sun/kbio.h> 74 1.33 uwe #include <dev/sun/vuid_event.h> 75 1.22 mrg #include <dev/sun/event_var.h> 76 1.22 mrg #include <dev/sun/kbd_xlate.h> 77 1.22 mrg #include <dev/sun/kbdvar.h> 78 1.1 gwr 79 1.61 tsutsui #include "ioconf.h" 80 1.14 jtk #include "locators.h" 81 1.64 macallan #include "opt_sunkbd.h" 82 1.65 martin #include "sysmon_envsys.h" 83 1.1 gwr 84 1.31 gehenna dev_type_open(kbdopen); 85 1.31 gehenna dev_type_close(kbdclose); 86 1.31 gehenna dev_type_read(kbdread); 87 1.31 gehenna dev_type_ioctl(kbdioctl); 88 1.31 gehenna dev_type_poll(kbdpoll); 89 1.34 jdolecek dev_type_kqfilter(kbdkqfilter); 90 1.31 gehenna 91 1.31 gehenna const struct cdevsw kbd_cdevsw = { 92 1.67 dholland .d_open = kbdopen, 93 1.67 dholland .d_close = kbdclose, 94 1.67 dholland .d_read = kbdread, 95 1.67 dholland .d_write = nowrite, 96 1.67 dholland .d_ioctl = kbdioctl, 97 1.67 dholland .d_stop = nostop, 98 1.67 dholland .d_tty = notty, 99 1.67 dholland .d_poll = kbdpoll, 100 1.67 dholland .d_mmap = nommap, 101 1.67 dholland .d_kqfilter = kbdkqfilter, 102 1.68 dholland .d_discard = nodiscard, 103 1.67 dholland .d_flag = D_OTHER 104 1.31 gehenna }; 105 1.1 gwr 106 1.35 martin #if NWSKBD > 0 107 1.54 christos static int wssunkbd_enable(void *, int); 108 1.54 christos static void wssunkbd_set_leds(void *, int); 109 1.58 christos static int wssunkbd_ioctl(void *, u_long, void *, int, struct lwp *); 110 1.54 christos static void sunkbd_wskbd_cngetc(void *, u_int *, int *); 111 1.54 christos static void sunkbd_wskbd_cnpollc(void *, int); 112 1.54 christos static void sunkbd_wskbd_cnbell(void *, u_int, u_int, u_int); 113 1.54 christos static void sunkbd_bell_off(void *v); 114 1.63 cegger static void kbd_enable(device_t); /* deferred keyboard init */ 115 1.35 martin 116 1.35 martin const struct wskbd_accessops sunkbd_wskbd_accessops = { 117 1.35 martin wssunkbd_enable, 118 1.35 martin wssunkbd_set_leds, 119 1.35 martin wssunkbd_ioctl, 120 1.35 martin }; 121 1.35 martin 122 1.35 martin extern const struct wscons_keydesc wssun_keydesctab[]; 123 1.35 martin const struct wskbd_mapdata sunkbd_wskbd_keymapdata = { 124 1.35 martin wssun_keydesctab, 125 1.35 martin #ifdef SUNKBD_LAYOUT 126 1.35 martin SUNKBD_LAYOUT, 127 1.35 martin #else 128 1.35 martin KB_US, 129 1.35 martin #endif 130 1.35 martin }; 131 1.35 martin 132 1.35 martin const struct wskbd_consops sunkbd_wskbd_consops = { 133 1.35 martin sunkbd_wskbd_cngetc, 134 1.35 martin sunkbd_wskbd_cnpollc, 135 1.35 martin sunkbd_wskbd_cnbell, 136 1.35 martin }; 137 1.35 martin 138 1.54 christos void kbd_wskbd_attach(struct kbd_softc *, int); 139 1.35 martin #endif 140 1.32 uwe 141 1.32 uwe /* ioctl helpers */ 142 1.54 christos static int kbd_iockeymap(struct kbd_state *, u_long, struct kiockeymap *); 143 1.32 uwe #ifdef KIOCGETKEY 144 1.54 christos static int kbd_oldkeymap(struct kbd_state *, u_long, struct okiockey *); 145 1.32 uwe #endif 146 1.32 uwe 147 1.33 uwe 148 1.33 uwe /* callbacks for console driver */ 149 1.33 uwe static int kbd_cc_open(struct cons_channel *); 150 1.33 uwe static int kbd_cc_close(struct cons_channel *); 151 1.33 uwe 152 1.33 uwe /* console input */ 153 1.33 uwe static void kbd_input_console(struct kbd_softc *, int); 154 1.33 uwe static void kbd_repeat(void *); 155 1.33 uwe static int kbd_input_keysym(struct kbd_softc *, int); 156 1.33 uwe static void kbd_input_string(struct kbd_softc *, char *); 157 1.33 uwe static void kbd_input_funckey(struct kbd_softc *, int); 158 1.33 uwe static void kbd_update_leds(struct kbd_softc *); 159 1.33 uwe 160 1.35 martin #if NWSKBD > 0 161 1.35 martin static void kbd_input_wskbd(struct kbd_softc *, int); 162 1.35 martin #endif 163 1.35 martin 164 1.33 uwe /* firm events input */ 165 1.33 uwe static void kbd_input_event(struct kbd_softc *, int); 166 1.33 uwe 167 1.1 gwr /**************************************************************** 168 1.1 gwr * Entry points for /dev/kbd 169 1.1 gwr * (open,close,read,write,...) 170 1.1 gwr ****************************************************************/ 171 1.1 gwr 172 1.1 gwr /* 173 1.1 gwr * Open: 174 1.1 gwr * Check exclusion, open actual device (_iopen), 175 1.1 gwr * setup event channel, clear ASCII repeat stuff. 176 1.1 gwr */ 177 1.1 gwr int 178 1.54 christos kbdopen(dev_t dev, int flags, int mode, struct lwp *l) 179 1.1 gwr { 180 1.1 gwr struct kbd_softc *k; 181 1.61 tsutsui int error; 182 1.1 gwr 183 1.32 uwe /* locate device */ 184 1.61 tsutsui k = device_lookup_private(&kbd_cd, minor(dev)); 185 1.1 gwr if (k == NULL) 186 1.61 tsutsui return ENXIO; 187 1.1 gwr 188 1.45 martin #if NWSKBD > 0 189 1.33 uwe /* 190 1.33 uwe * NB: wscons support: while we can track if wskbd has called 191 1.33 uwe * enable(), we can't tell if that's for console input or for 192 1.33 uwe * events input, so we should probably just let the open to 193 1.33 uwe * always succeed regardless (e.g. Xsun opening /dev/kbd). 194 1.33 uwe */ 195 1.44 martin if (!k->k_wsenabled) 196 1.44 martin wssunkbd_enable(k, 1); 197 1.45 martin #endif 198 1.33 uwe 199 1.32 uwe /* exclusive open required for /dev/kbd */ 200 1.1 gwr if (k->k_events.ev_io) 201 1.61 tsutsui return EBUSY; 202 1.53 christos k->k_events.ev_io = l->l_proc; 203 1.1 gwr 204 1.33 uwe /* stop pending autorepeat of console input */ 205 1.71 tsutsui if (k->k_cc != NULL && k->k_repeating) { 206 1.33 uwe k->k_repeating = 0; 207 1.33 uwe callout_stop(&k->k_repeat_ch); 208 1.33 uwe } 209 1.33 uwe 210 1.32 uwe /* open actual underlying device */ 211 1.32 uwe if (k->k_ops != NULL && k->k_ops->open != NULL) 212 1.32 uwe if ((error = (*k->k_ops->open)(k)) != 0) { 213 1.32 uwe k->k_events.ev_io = NULL; 214 1.61 tsutsui return error; 215 1.32 uwe } 216 1.32 uwe 217 1.1 gwr ev_init(&k->k_events); 218 1.27 eeh k->k_evmode = 0; /* XXX: OK? */ 219 1.1 gwr 220 1.61 tsutsui return 0; 221 1.1 gwr } 222 1.1 gwr 223 1.32 uwe 224 1.1 gwr /* 225 1.1 gwr * Close: 226 1.1 gwr * Turn off event mode, dump the queue, and close the keyboard 227 1.1 gwr * unless it is supplying console input. 228 1.1 gwr */ 229 1.1 gwr int 230 1.54 christos kbdclose(dev_t dev, int flags, int mode, struct lwp *l) 231 1.1 gwr { 232 1.1 gwr struct kbd_softc *k; 233 1.1 gwr 234 1.61 tsutsui k = device_lookup_private(&kbd_cd, minor(dev)); 235 1.1 gwr k->k_evmode = 0; 236 1.1 gwr ev_fini(&k->k_events); 237 1.1 gwr k->k_events.ev_io = NULL; 238 1.32 uwe 239 1.32 uwe if (k->k_ops != NULL && k->k_ops->close != NULL) { 240 1.32 uwe int error; 241 1.32 uwe if ((error = (*k->k_ops->close)(k)) != 0) 242 1.61 tsutsui return error; 243 1.32 uwe } 244 1.61 tsutsui return 0; 245 1.1 gwr } 246 1.1 gwr 247 1.32 uwe 248 1.1 gwr int 249 1.54 christos kbdread(dev_t dev, struct uio *uio, int flags) 250 1.1 gwr { 251 1.1 gwr struct kbd_softc *k; 252 1.1 gwr 253 1.61 tsutsui k = device_lookup_private(&kbd_cd, minor(dev)); 254 1.61 tsutsui return ev_read(&k->k_events, uio, flags); 255 1.1 gwr } 256 1.1 gwr 257 1.32 uwe 258 1.1 gwr int 259 1.54 christos kbdpoll(dev_t dev, int events, struct lwp *l) 260 1.1 gwr { 261 1.1 gwr struct kbd_softc *k; 262 1.1 gwr 263 1.61 tsutsui k = device_lookup_private(&kbd_cd, minor(dev)); 264 1.61 tsutsui return ev_poll(&k->k_events, events, l); 265 1.1 gwr } 266 1.1 gwr 267 1.34 jdolecek int 268 1.54 christos kbdkqfilter(dev_t dev, struct knote *kn) 269 1.34 jdolecek { 270 1.34 jdolecek struct kbd_softc *k; 271 1.34 jdolecek 272 1.61 tsutsui k = device_lookup_private(&kbd_cd, minor(dev)); 273 1.61 tsutsui return ev_kqfilter(&k->k_events, kn); 274 1.34 jdolecek } 275 1.1 gwr 276 1.1 gwr int 277 1.58 christos kbdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 278 1.1 gwr { 279 1.1 gwr struct kbd_softc *k; 280 1.1 gwr struct kbd_state *ks; 281 1.1 gwr int error = 0; 282 1.1 gwr 283 1.61 tsutsui k = device_lookup_private(&kbd_cd, minor(dev)); 284 1.1 gwr ks = &k->k_state; 285 1.1 gwr 286 1.1 gwr switch (cmd) { 287 1.1 gwr 288 1.1 gwr case KIOCTRANS: /* Set translation mode */ 289 1.1 gwr /* We only support "raw" mode on /dev/kbd */ 290 1.16 gwr if (*(int *)data != TR_UNTRANS_EVENT) 291 1.1 gwr error = EINVAL; 292 1.1 gwr break; 293 1.1 gwr 294 1.1 gwr case KIOCGTRANS: /* Get translation mode */ 295 1.1 gwr /* We only support "raw" mode on /dev/kbd */ 296 1.16 gwr *(int *)data = TR_UNTRANS_EVENT; 297 1.1 gwr break; 298 1.1 gwr 299 1.32 uwe #ifdef KIOCGETKEY 300 1.1 gwr case KIOCGETKEY: /* Get keymap entry (old format) */ 301 1.1 gwr error = kbd_oldkeymap(ks, cmd, (struct okiockey *)data); 302 1.1 gwr break; 303 1.32 uwe #endif /* KIOCGETKEY */ 304 1.1 gwr 305 1.1 gwr case KIOCSKEY: /* Set keymap entry */ 306 1.32 uwe /* FALLTHROUGH */ 307 1.1 gwr case KIOCGKEY: /* Get keymap entry */ 308 1.1 gwr error = kbd_iockeymap(ks, cmd, (struct kiockeymap *)data); 309 1.1 gwr break; 310 1.1 gwr 311 1.32 uwe case KIOCCMD: /* Send a command to the keyboard */ 312 1.32 uwe /* pass it to the middle layer */ 313 1.32 uwe if (k->k_ops != NULL && k->k_ops->docmd != NULL) 314 1.32 uwe error = (*k->k_ops->docmd)(k, *(int *)data, 1); 315 1.1 gwr break; 316 1.1 gwr 317 1.32 uwe case KIOCTYPE: /* Get keyboard type */ 318 1.16 gwr *(int *)data = ks->kbd_id; 319 1.1 gwr break; 320 1.1 gwr 321 1.32 uwe case KIOCSDIRECT: /* Where to send input */ 322 1.16 gwr k->k_evmode = *(int *)data; 323 1.1 gwr break; 324 1.1 gwr 325 1.1 gwr case KIOCLAYOUT: /* Get keyboard layout */ 326 1.16 gwr *(int *)data = ks->kbd_layout; 327 1.1 gwr break; 328 1.1 gwr 329 1.32 uwe case KIOCSLED: /* Set keyboard LEDs */ 330 1.32 uwe /* pass the request to the middle layer */ 331 1.32 uwe if (k->k_ops != NULL && k->k_ops->setleds != NULL) 332 1.32 uwe error = (*k->k_ops->setleds)(k, *(char *)data, 1); 333 1.1 gwr break; 334 1.1 gwr 335 1.32 uwe case KIOCGLED: /* Get keyboard LEDs */ 336 1.1 gwr *(char *)data = ks->kbd_leds; 337 1.1 gwr break; 338 1.1 gwr 339 1.1 gwr case FIONBIO: /* we will remove this someday (soon???) */ 340 1.1 gwr break; 341 1.1 gwr 342 1.1 gwr case FIOASYNC: 343 1.32 uwe k->k_events.ev_async = (*(int *)data != 0); 344 1.39 jdolecek break; 345 1.39 jdolecek 346 1.39 jdolecek case FIOSETOWN: 347 1.39 jdolecek if (-*(int *)data != k->k_events.ev_io->p_pgid 348 1.39 jdolecek && *(int *)data != k->k_events.ev_io->p_pid) 349 1.39 jdolecek error = EPERM; 350 1.1 gwr break; 351 1.1 gwr 352 1.1 gwr case TIOCSPGRP: 353 1.16 gwr if (*(int *)data != k->k_events.ev_io->p_pgid) 354 1.1 gwr error = EPERM; 355 1.1 gwr break; 356 1.1 gwr 357 1.16 gwr default: 358 1.16 gwr error = ENOTTY; 359 1.16 gwr break; 360 1.1 gwr } 361 1.1 gwr 362 1.61 tsutsui return error; 363 1.1 gwr } 364 1.1 gwr 365 1.32 uwe 366 1.1 gwr /**************************************************************** 367 1.1 gwr * ioctl helpers 368 1.1 gwr ****************************************************************/ 369 1.1 gwr 370 1.1 gwr /* 371 1.1 gwr * Get/Set keymap entry 372 1.1 gwr */ 373 1.7 gwr static int 374 1.54 christos kbd_iockeymap(struct kbd_state *ks, u_long cmd, struct kiockeymap *kio) 375 1.1 gwr { 376 1.13 gwr u_short *km; 377 1.1 gwr u_int station; 378 1.1 gwr 379 1.1 gwr switch (kio->kio_tablemask) { 380 1.1 gwr case KIOC_NOMASK: 381 1.1 gwr km = ks->kbd_k.k_normal; 382 1.1 gwr break; 383 1.1 gwr case KIOC_SHIFTMASK: 384 1.1 gwr km = ks->kbd_k.k_shifted; 385 1.1 gwr break; 386 1.1 gwr case KIOC_CTRLMASK: 387 1.1 gwr km = ks->kbd_k.k_control; 388 1.1 gwr break; 389 1.1 gwr case KIOC_UPMASK: 390 1.1 gwr km = ks->kbd_k.k_release; 391 1.1 gwr break; 392 1.1 gwr default: 393 1.1 gwr /* Silently ignore unsupported masks */ 394 1.61 tsutsui return 0; 395 1.1 gwr } 396 1.1 gwr 397 1.1 gwr /* Range-check the table position. */ 398 1.1 gwr station = kio->kio_station; 399 1.1 gwr if (station >= KEYMAP_SIZE) 400 1.61 tsutsui return EINVAL; 401 1.1 gwr 402 1.1 gwr switch (cmd) { 403 1.1 gwr 404 1.1 gwr case KIOCGKEY: /* Get keymap entry */ 405 1.13 gwr kio->kio_entry = km[station]; 406 1.1 gwr break; 407 1.1 gwr 408 1.1 gwr case KIOCSKEY: /* Set keymap entry */ 409 1.13 gwr km[station] = kio->kio_entry; 410 1.1 gwr break; 411 1.1 gwr 412 1.1 gwr default: 413 1.61 tsutsui return ENOTTY; 414 1.1 gwr } 415 1.61 tsutsui return 0; 416 1.1 gwr } 417 1.1 gwr 418 1.32 uwe 419 1.32 uwe #ifdef KIOCGETKEY 420 1.1 gwr /* 421 1.1 gwr * Get/Set keymap entry, 422 1.1 gwr * old format (compatibility) 423 1.1 gwr */ 424 1.1 gwr int 425 1.54 christos kbd_oldkeymap(struct kbd_state *ks, u_long cmd, struct okiockey *kio) 426 1.1 gwr { 427 1.1 gwr int error = 0; 428 1.1 gwr 429 1.1 gwr switch (cmd) { 430 1.1 gwr 431 1.1 gwr case KIOCGETKEY: 432 1.1 gwr if (kio->kio_station == 118) { 433 1.1 gwr /* 434 1.1 gwr * This is X11 asking if a type 3 keyboard is 435 1.1 gwr * really a type 3 keyboard. Say yes, it is, 436 1.1 gwr * by reporting key station 118 as a "hole". 437 1.1 gwr * Note old (SunOS 3.5) definition of HOLE! 438 1.1 gwr */ 439 1.1 gwr kio->kio_entry = 0xA2; 440 1.1 gwr break; 441 1.1 gwr } 442 1.1 gwr /* fall through */ 443 1.1 gwr 444 1.1 gwr default: 445 1.1 gwr error = ENOTTY; 446 1.1 gwr break; 447 1.1 gwr } 448 1.1 gwr 449 1.61 tsutsui return error; 450 1.1 gwr } 451 1.32 uwe #endif /* KIOCGETKEY */ 452 1.1 gwr 453 1.7 gwr 454 1.33 uwe 455 1.32 uwe /**************************************************************** 456 1.33 uwe * Keyboard input - called by middle layer at spltty(). 457 1.32 uwe ****************************************************************/ 458 1.32 uwe 459 1.33 uwe void 460 1.54 christos kbd_input(struct kbd_softc *k, int code) 461 1.33 uwe { 462 1.35 martin if (k->k_evmode) { 463 1.35 martin /* 464 1.35 martin * XXX: is this still true? 465 1.35 martin * IDLEs confuse the MIT X11R4 server badly, so we must drop them. 466 1.35 martin * This is bad as it means the server will not automatically resync 467 1.35 martin * on all-up IDLEs, but I did not drop them before, and the server 468 1.35 martin * goes crazy when it comes time to blank the screen.... 469 1.35 martin */ 470 1.35 martin if (code == KBD_IDLE) 471 1.35 martin return; 472 1.33 uwe 473 1.35 martin /* 474 1.35 martin * Keyboard is generating firm events. Turn this keystroke 475 1.35 martin * into an event and put it in the queue. 476 1.35 martin */ 477 1.35 martin kbd_input_event(k, code); 478 1.33 uwe return; 479 1.33 uwe } 480 1.33 uwe 481 1.35 martin #if NWSKBD > 0 482 1.35 martin if (k->k_wskbd != NULL && k->k_wsenabled) { 483 1.35 martin /* 484 1.35 martin * We are using wskbd input mode, pass the event up. 485 1.35 martin */ 486 1.51 martin if (code == KBD_IDLE) 487 1.51 martin return; /* this key is not in the mapped */ 488 1.35 martin kbd_input_wskbd(k, code); 489 1.33 uwe return; 490 1.35 martin } 491 1.35 martin #endif 492 1.33 uwe 493 1.33 uwe /* 494 1.35 martin * If /dev/kbd is not connected in event mode, or wskbd mode, 495 1.71 tsutsui * and is attached as console, translate and send upstream 496 1.71 tsutsui * (to console). 497 1.33 uwe */ 498 1.71 tsutsui if (k->k_cc != NULL) 499 1.71 tsutsui kbd_input_console(k, code); 500 1.33 uwe } 501 1.33 uwe 502 1.33 uwe 503 1.33 uwe 504 1.33 uwe /**************************************************************** 505 1.33 uwe * Open/close routines called upon opening /dev/console 506 1.33 uwe * if we serve console input. 507 1.33 uwe ****************************************************************/ 508 1.33 uwe 509 1.33 uwe struct cons_channel * 510 1.54 christos kbd_cc_alloc(struct kbd_softc *k) 511 1.33 uwe { 512 1.33 uwe struct cons_channel *cc; 513 1.33 uwe 514 1.70 chs cc = malloc(sizeof *cc, M_DEVBUF, M_WAITOK); 515 1.33 uwe 516 1.33 uwe /* our callbacks for the console driver */ 517 1.60 tsutsui cc->cc_private = k; 518 1.33 uwe cc->cc_iopen = kbd_cc_open; 519 1.33 uwe cc->cc_iclose = kbd_cc_close; 520 1.33 uwe 521 1.33 uwe /* will be provided by the console driver so that we can feed input */ 522 1.33 uwe cc->cc_upstream = NULL; 523 1.33 uwe 524 1.33 uwe /* 525 1.33 uwe * TODO: clean up cons_attach_input() vs kd_attach_input() in 526 1.33 uwe * lower layers and move that code here. 527 1.33 uwe */ 528 1.33 uwe 529 1.33 uwe k->k_cc = cc; 530 1.61 tsutsui return cc; 531 1.33 uwe } 532 1.33 uwe 533 1.33 uwe 534 1.33 uwe static int 535 1.54 christos kbd_cc_open(struct cons_channel *cc) 536 1.15 gwr { 537 1.7 gwr struct kbd_softc *k; 538 1.33 uwe int ret; 539 1.15 gwr 540 1.32 uwe if (cc == NULL) 541 1.61 tsutsui return 0; 542 1.7 gwr 543 1.60 tsutsui k = cc->cc_private; 544 1.33 uwe if (k == NULL) 545 1.61 tsutsui return 0; 546 1.33 uwe 547 1.33 uwe if (k->k_ops != NULL && k->k_ops->open != NULL) 548 1.33 uwe ret = (*k->k_ops->open)(k); 549 1.32 uwe else 550 1.33 uwe ret = 0; 551 1.33 uwe 552 1.33 uwe /* XXX: verify that callout is not active? */ 553 1.33 uwe k->k_repeat_start = hz/2; 554 1.33 uwe k->k_repeat_step = hz/20; 555 1.59 ad callout_init(&k->k_repeat_ch, 0); 556 1.33 uwe 557 1.61 tsutsui return ret; 558 1.32 uwe } 559 1.7 gwr 560 1.7 gwr 561 1.33 uwe static int 562 1.54 christos kbd_cc_close(struct cons_channel *cc) 563 1.32 uwe { 564 1.7 gwr struct kbd_softc *k; 565 1.33 uwe int ret; 566 1.7 gwr 567 1.32 uwe if (cc == NULL) 568 1.61 tsutsui return 0; 569 1.7 gwr 570 1.60 tsutsui k = cc->cc_private; 571 1.33 uwe if (k == NULL) 572 1.61 tsutsui return 0; 573 1.33 uwe 574 1.33 uwe if (k->k_ops != NULL && k->k_ops->close != NULL) 575 1.33 uwe ret = (*k->k_ops->close)(k); 576 1.32 uwe else 577 1.33 uwe ret = 0; 578 1.33 uwe 579 1.33 uwe /* stop any pending auto-repeat */ 580 1.33 uwe if (k->k_repeating) { 581 1.33 uwe k->k_repeating = 0; 582 1.33 uwe callout_stop(&k->k_repeat_ch); 583 1.33 uwe } 584 1.33 uwe 585 1.61 tsutsui return ret; 586 1.7 gwr } 587 1.7 gwr 588 1.7 gwr 589 1.33 uwe 590 1.1 gwr /**************************************************************** 591 1.32 uwe * Console input - called by middle layer at spltty(). 592 1.1 gwr ****************************************************************/ 593 1.1 gwr 594 1.33 uwe static void 595 1.54 christos kbd_input_console(struct kbd_softc *k, int code) 596 1.33 uwe { 597 1.33 uwe struct kbd_state *ks= &k->k_state; 598 1.33 uwe int keysym; 599 1.33 uwe 600 1.33 uwe /* any input stops auto-repeat (i.e. key release) */ 601 1.33 uwe if (k->k_repeating) { 602 1.33 uwe k->k_repeating = 0; 603 1.33 uwe callout_stop(&k->k_repeat_ch); 604 1.33 uwe } 605 1.33 uwe 606 1.33 uwe keysym = kbd_code_to_keysym(ks, code); 607 1.33 uwe 608 1.33 uwe /* pass to console */ 609 1.33 uwe if (kbd_input_keysym(k, keysym)) { 610 1.33 uwe log(LOG_WARNING, "%s: code=0x%x with mod=0x%x" 611 1.33 uwe " produced unexpected keysym 0x%x\n", 612 1.60 tsutsui device_xname(k->k_dev), 613 1.33 uwe code, ks->kbd_modbits, keysym); 614 1.33 uwe return; /* no point in auto-repeat here */ 615 1.33 uwe } 616 1.33 uwe 617 1.33 uwe if (KEYSYM_NOREPEAT(keysym)) 618 1.33 uwe return; 619 1.33 uwe 620 1.33 uwe /* setup for auto-repeat after initial delay */ 621 1.33 uwe k->k_repeating = 1; 622 1.33 uwe k->k_repeatsym = keysym; 623 1.33 uwe callout_reset(&k->k_repeat_ch, k->k_repeat_start, 624 1.33 uwe kbd_repeat, k); 625 1.33 uwe } 626 1.33 uwe 627 1.33 uwe 628 1.33 uwe /* 629 1.33 uwe * This is the autorepeat callout function scheduled by kbd_input() above. 630 1.33 uwe * Called at splsoftclock(). 631 1.33 uwe */ 632 1.33 uwe static void 633 1.54 christos kbd_repeat(void *arg) 634 1.33 uwe { 635 1.60 tsutsui struct kbd_softc *k = arg; 636 1.33 uwe int s; 637 1.33 uwe 638 1.33 uwe s = spltty(); 639 1.33 uwe if (k->k_repeating && k->k_repeatsym >= 0) { 640 1.33 uwe /* feed typematic keysym to the console */ 641 1.33 uwe (void)kbd_input_keysym(k, k->k_repeatsym); 642 1.33 uwe 643 1.33 uwe /* reschedule next repeat */ 644 1.33 uwe callout_reset(&k->k_repeat_ch, k->k_repeat_step, 645 1.33 uwe kbd_repeat, k); 646 1.33 uwe } 647 1.33 uwe splx(s); 648 1.33 uwe } 649 1.33 uwe 650 1.33 uwe 651 1.33 uwe 652 1.1 gwr /* 653 1.33 uwe * Supply keysym as console input. Convert keysym to character(s) and 654 1.33 uwe * pass them up to cons_channel's upstream hook. 655 1.17 gwr * 656 1.32 uwe * Return zero on success, else the keysym that we could not handle 657 1.32 uwe * (so that the caller may complain). 658 1.1 gwr */ 659 1.33 uwe static int 660 1.54 christos kbd_input_keysym(struct kbd_softc *k, int keysym) 661 1.1 gwr { 662 1.1 gwr struct kbd_state *ks = &k->k_state; 663 1.23 pk int data; 664 1.30 pk /* Check if a recipient has been configured */ 665 1.32 uwe if (k->k_cc == NULL || k->k_cc->cc_upstream == NULL) 666 1.61 tsutsui return 0; 667 1.1 gwr 668 1.4 gwr switch (KEYSYM_CLASS(keysym)) { 669 1.1 gwr 670 1.1 gwr case KEYSYM_ASCII: 671 1.1 gwr data = KEYSYM_DATA(keysym); 672 1.1 gwr if (ks->kbd_modbits & KBMOD_META_MASK) 673 1.1 gwr data |= 0x80; 674 1.23 pk (*k->k_cc->cc_upstream)(data); 675 1.1 gwr break; 676 1.1 gwr 677 1.1 gwr case KEYSYM_STRING: 678 1.1 gwr data = keysym & 0xF; 679 1.1 gwr kbd_input_string(k, kbd_stringtab[data]); 680 1.1 gwr break; 681 1.1 gwr 682 1.1 gwr case KEYSYM_FUNC: 683 1.1 gwr kbd_input_funckey(k, keysym); 684 1.1 gwr break; 685 1.1 gwr 686 1.1 gwr case KEYSYM_CLRMOD: 687 1.1 gwr data = 1 << (keysym & 0x1F); 688 1.1 gwr ks->kbd_modbits &= ~data; 689 1.1 gwr break; 690 1.1 gwr 691 1.1 gwr case KEYSYM_SETMOD: 692 1.1 gwr data = 1 << (keysym & 0x1F); 693 1.1 gwr ks->kbd_modbits |= data; 694 1.1 gwr break; 695 1.1 gwr 696 1.1 gwr case KEYSYM_INVMOD: 697 1.1 gwr data = 1 << (keysym & 0x1F); 698 1.1 gwr ks->kbd_modbits ^= data; 699 1.4 gwr kbd_update_leds(k); 700 1.1 gwr break; 701 1.1 gwr 702 1.1 gwr case KEYSYM_ALL_UP: 703 1.1 gwr ks->kbd_modbits &= ~0xFFFF; 704 1.1 gwr break; 705 1.1 gwr 706 1.1 gwr case KEYSYM_SPECIAL: 707 1.1 gwr if (keysym == KEYSYM_NOP) 708 1.1 gwr break; 709 1.32 uwe /* FALLTHROUGH */ 710 1.1 gwr default: 711 1.17 gwr /* We could not handle it. */ 712 1.61 tsutsui return keysym; 713 1.1 gwr } 714 1.32 uwe 715 1.61 tsutsui return 0; 716 1.1 gwr } 717 1.1 gwr 718 1.32 uwe 719 1.1 gwr /* 720 1.32 uwe * Send string upstream. 721 1.1 gwr */ 722 1.13 gwr static void 723 1.54 christos kbd_input_string(struct kbd_softc *k, char *str) 724 1.1 gwr { 725 1.1 gwr 726 1.32 uwe while (*str) { 727 1.32 uwe (*k->k_cc->cc_upstream)(*str); 728 1.32 uwe ++str; 729 1.1 gwr } 730 1.1 gwr } 731 1.1 gwr 732 1.32 uwe 733 1.1 gwr /* 734 1.32 uwe * Format the F-key sequence and send as a string. 735 1.32 uwe * XXX: Ugly compatibility mappings. 736 1.1 gwr */ 737 1.32 uwe static void 738 1.54 christos kbd_input_funckey(struct kbd_softc *k, int keysym) 739 1.1 gwr { 740 1.32 uwe int n; 741 1.32 uwe char str[12]; 742 1.32 uwe 743 1.32 uwe n = 0xC0 + (keysym & 0x3F); 744 1.40 itojun snprintf(str, sizeof(str), "\033[%dz", n); 745 1.32 uwe kbd_input_string(k, str); 746 1.32 uwe } 747 1.1 gwr 748 1.1 gwr 749 1.32 uwe /* 750 1.32 uwe * Update LEDs to reflect console input state. 751 1.32 uwe */ 752 1.32 uwe static void 753 1.54 christos kbd_update_leds(struct kbd_softc *k) 754 1.32 uwe { 755 1.32 uwe struct kbd_state *ks = &k->k_state; 756 1.32 uwe char leds; 757 1.1 gwr 758 1.32 uwe leds = ks->kbd_leds; 759 1.32 uwe leds &= ~(LED_CAPS_LOCK|LED_NUM_LOCK); 760 1.1 gwr 761 1.32 uwe if (ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) 762 1.32 uwe leds |= LED_CAPS_LOCK; 763 1.32 uwe if (ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) 764 1.32 uwe leds |= LED_NUM_LOCK; 765 1.1 gwr 766 1.32 uwe if (k->k_ops != NULL && k->k_ops->setleds != NULL) 767 1.32 uwe (void)(*k->k_ops->setleds)(k, leds, 0); 768 1.32 uwe } 769 1.1 gwr 770 1.1 gwr 771 1.1 gwr 772 1.32 uwe /**************************************************************** 773 1.32 uwe * Events input - called by middle layer at spltty(). 774 1.32 uwe ****************************************************************/ 775 1.1 gwr 776 1.32 uwe /* 777 1.33 uwe * Supply raw keystrokes when keyboard is open in firm event mode. 778 1.32 uwe * 779 1.32 uwe * Turn the keystroke into an event and put it in the queue. 780 1.32 uwe * If the queue is full, the keystroke is lost (sorry!). 781 1.32 uwe */ 782 1.33 uwe static void 783 1.54 christos kbd_input_event(struct kbd_softc *k, int code) 784 1.32 uwe { 785 1.32 uwe struct firm_event *fe; 786 1.32 uwe int put; 787 1.1 gwr 788 1.32 uwe #ifdef DIAGNOSTIC 789 1.32 uwe if (!k->k_evmode) { 790 1.32 uwe printf("%s: kbd_input_event called when not in event mode\n", 791 1.60 tsutsui device_xname(k->k_dev)); 792 1.1 gwr return; 793 1.1 gwr } 794 1.32 uwe #endif 795 1.1 gwr put = k->k_events.ev_put; 796 1.1 gwr fe = &k->k_events.ev_q[put]; 797 1.1 gwr put = (put + 1) % EV_QSIZE; 798 1.1 gwr if (put == k->k_events.ev_get) { 799 1.1 gwr log(LOG_WARNING, "%s: event queue overflow\n", 800 1.60 tsutsui device_xname(k->k_dev)); 801 1.1 gwr return; 802 1.1 gwr } 803 1.33 uwe 804 1.33 uwe fe->id = KEY_CODE(code); 805 1.33 uwe fe->value = KEY_UP(code) ? VKEY_UP : VKEY_DOWN; 806 1.62 christos firm_gettime(fe); 807 1.1 gwr k->k_events.ev_put = put; 808 1.1 gwr EV_WAKEUP(&k->k_events); 809 1.1 gwr } 810 1.1 gwr 811 1.32 uwe 812 1.33 uwe 813 1.32 uwe /**************************************************************** 814 1.32 uwe * Translation stuff declared in kbd_xlate.h 815 1.32 uwe ****************************************************************/ 816 1.24 pk 817 1.24 pk /* 818 1.32 uwe * Initialization - called by either lower layer attach or by kdcninit. 819 1.24 pk */ 820 1.32 uwe void 821 1.54 christos kbd_xlate_init(struct kbd_state *ks) 822 1.24 pk { 823 1.32 uwe struct keyboard *ktbls; 824 1.32 uwe int id; 825 1.32 uwe 826 1.32 uwe id = ks->kbd_id; 827 1.32 uwe if (id < KBD_MIN_TYPE) 828 1.32 uwe id = KBD_MIN_TYPE; 829 1.32 uwe if (id > kbd_max_type) 830 1.32 uwe id = kbd_max_type; 831 1.32 uwe ktbls = keyboards[id]; 832 1.24 pk 833 1.32 uwe ks->kbd_k = *ktbls; /* struct assignment */ 834 1.32 uwe ks->kbd_modbits = 0; 835 1.24 pk } 836 1.1 gwr 837 1.1 gwr /* 838 1.32 uwe * Turn keyboard up/down codes into a KEYSYM. 839 1.32 uwe * Note that the "kd" driver (on sun3 and sparc64) uses this too! 840 1.1 gwr */ 841 1.1 gwr int 842 1.54 christos kbd_code_to_keysym(struct kbd_state *ks, int c) 843 1.1 gwr { 844 1.32 uwe u_short *km; 845 1.32 uwe int keysym; 846 1.1 gwr 847 1.32 uwe /* 848 1.32 uwe * Get keymap pointer. One of these: 849 1.32 uwe * release, control, shifted, normal, ... 850 1.32 uwe */ 851 1.32 uwe if (KEY_UP(c)) 852 1.32 uwe km = ks->kbd_k.k_release; 853 1.32 uwe else if (ks->kbd_modbits & KBMOD_CTRL_MASK) 854 1.32 uwe km = ks->kbd_k.k_control; 855 1.32 uwe else if (ks->kbd_modbits & KBMOD_SHIFT_MASK) 856 1.32 uwe km = ks->kbd_k.k_shifted; 857 1.32 uwe else 858 1.32 uwe km = ks->kbd_k.k_normal; 859 1.23 pk 860 1.32 uwe if (km == NULL) { 861 1.1 gwr /* 862 1.32 uwe * Do not know how to translate yet. 863 1.32 uwe * We will find out when a RESET comes along. 864 1.1 gwr */ 865 1.61 tsutsui return KEYSYM_NOP; 866 1.1 gwr } 867 1.32 uwe keysym = km[KEY_CODE(c)]; 868 1.1 gwr 869 1.1 gwr /* 870 1.32 uwe * Post-processing for Caps-lock 871 1.1 gwr */ 872 1.32 uwe if ((ks->kbd_modbits & (1 << KBMOD_CAPSLOCK)) && 873 1.32 uwe (KEYSYM_CLASS(keysym) == KEYSYM_ASCII) ) 874 1.32 uwe { 875 1.32 uwe if (('a' <= keysym) && (keysym <= 'z')) 876 1.32 uwe keysym -= ('a' - 'A'); 877 1.1 gwr } 878 1.1 gwr 879 1.1 gwr /* 880 1.32 uwe * Post-processing for Num-lock. All "function" 881 1.32 uwe * keysyms get indirected through another table. 882 1.32 uwe * (XXX: Only if numlock on. Want off also!) 883 1.1 gwr */ 884 1.32 uwe if ((ks->kbd_modbits & (1 << KBMOD_NUMLOCK)) && 885 1.32 uwe (KEYSYM_CLASS(keysym) == KEYSYM_FUNC) ) 886 1.32 uwe { 887 1.32 uwe keysym = kbd_numlock_map[keysym & 0x3F]; 888 1.1 gwr } 889 1.7 gwr 890 1.61 tsutsui return keysym; 891 1.1 gwr } 892 1.1 gwr 893 1.1 gwr 894 1.7 gwr /* 895 1.32 uwe * Back door for rcons (fb.c) 896 1.7 gwr */ 897 1.22 mrg void 898 1.54 christos kbd_bell(int on) 899 1.1 gwr { 900 1.60 tsutsui struct kbd_softc *k; 901 1.60 tsutsui 902 1.61 tsutsui k = device_lookup_private(&kbd_cd, 0); /* XXX: hardcoded minor */ 903 1.33 uwe 904 1.33 uwe if (k == NULL || k->k_ops == NULL || k->k_ops->docmd == NULL) 905 1.33 uwe return; 906 1.33 uwe 907 1.33 uwe (void)(*k->k_ops->docmd)(k, on ? KBD_CMD_BELL : KBD_CMD_NOBELL, 0); 908 1.1 gwr } 909 1.35 martin 910 1.35 martin #if NWSKBD > 0 911 1.66 christos 912 1.66 christos #if NSYSMON_ENVSYS 913 1.66 christos static void 914 1.66 christos kbd_powerbutton(void *cookie) 915 1.66 christos { 916 1.66 christos struct kbd_softc *k = cookie; 917 1.66 christos 918 1.66 christos sysmon_pswitch_event(&k->k_sm_pbutton, k->k_ev); 919 1.66 christos } 920 1.66 christos #endif 921 1.66 christos 922 1.35 martin static void 923 1.35 martin kbd_input_wskbd(struct kbd_softc *k, int code) 924 1.35 martin { 925 1.35 martin int type, key; 926 1.64 macallan 927 1.47 martin #ifdef WSDISPLAY_COMPAT_RAWKBD 928 1.46 martin if (k->k_wsraw) { 929 1.47 martin u_char buf; 930 1.47 martin 931 1.51 martin buf = code; 932 1.51 martin wskbd_rawinput(k->k_wskbd, &buf, 1); 933 1.47 martin return; 934 1.46 martin } 935 1.47 martin #endif 936 1.47 martin 937 1.47 martin type = KEY_UP(code) ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 938 1.47 martin key = KEY_CODE(code); 939 1.64 macallan 940 1.64 macallan if (type == WSCONS_EVENT_KEY_DOWN) { 941 1.64 macallan switch (key) { 942 1.64 macallan #ifdef KBD_HIJACK_VOLUME_BUTTONS 943 1.64 macallan case 0x02: 944 1.64 macallan pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_DOWN); 945 1.64 macallan return; 946 1.64 macallan case 0x04: 947 1.64 macallan pmf_event_inject(NULL, PMFE_AUDIO_VOLUME_UP); 948 1.64 macallan return; 949 1.64 macallan #endif 950 1.64 macallan case 0x30: 951 1.65 martin #if NSYSMON_ENVSYS 952 1.69 mrg if (k->k_isconsole) { 953 1.64 macallan k->k_ev = KEY_UP(code) ? 954 1.64 macallan PSWITCH_EVENT_RELEASED : 955 1.64 macallan PSWITCH_EVENT_PRESSED; 956 1.66 christos sysmon_task_queue_sched(0, 957 1.66 christos kbd_powerbutton, k); 958 1.69 mrg } 959 1.65 martin #endif 960 1.64 macallan return; 961 1.64 macallan } 962 1.64 macallan } 963 1.64 macallan 964 1.47 martin wskbd_input(k->k_wskbd, type, key); 965 1.35 martin } 966 1.35 martin 967 1.35 martin int 968 1.54 christos wssunkbd_enable(void *v, int on) 969 1.35 martin { 970 1.35 martin struct kbd_softc *k = v; 971 1.64 macallan 972 1.44 martin if (k->k_wsenabled != on) { 973 1.44 martin k->k_wsenabled = on; 974 1.44 martin if (on) { 975 1.44 martin /* open actual underlying device */ 976 1.44 martin if (k->k_ops != NULL && k->k_ops->open != NULL) 977 1.44 martin (*k->k_ops->open)(k); 978 1.44 martin ev_init(&k->k_events); 979 1.44 martin k->k_evmode = 0; /* XXX: OK? */ 980 1.44 martin } else { 981 1.44 martin /* close underlying device */ 982 1.44 martin if (k->k_ops != NULL && k->k_ops->close != NULL) 983 1.44 martin (*k->k_ops->close)(k); 984 1.44 martin } 985 1.35 martin } 986 1.35 martin return 0; 987 1.35 martin } 988 1.35 martin 989 1.35 martin void 990 1.54 christos wssunkbd_set_leds(void *v, int leds) 991 1.35 martin { 992 1.35 martin struct kbd_softc *k = v; 993 1.35 martin int l = 0; 994 1.35 martin 995 1.35 martin if (leds & WSKBD_LED_CAPS) 996 1.35 martin l |= LED_CAPS_LOCK; 997 1.35 martin if (leds & WSKBD_LED_NUM) 998 1.35 martin l |= LED_NUM_LOCK; 999 1.35 martin if (leds & WSKBD_LED_SCROLL) 1000 1.35 martin l |= LED_SCROLL_LOCK; 1001 1.35 martin if (leds & WSKBD_LED_COMPOSE) 1002 1.35 martin l |= LED_COMPOSE; 1003 1.35 martin if (k->k_ops != NULL && k->k_ops->setleds != NULL) 1004 1.35 martin (*k->k_ops->setleds)(k, l, 0); 1005 1.44 martin k->k_leds=l; 1006 1.35 martin } 1007 1.35 martin 1008 1.54 christos static int 1009 1.58 christos wssunkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 1010 1.35 martin { 1011 1.44 martin struct kbd_softc *k = v; 1012 1.44 martin 1013 1.44 martin switch (cmd) { 1014 1.44 martin case WSKBDIO_GTYPE: 1015 1.46 martin /* we can't tell 4 from 5 or 6 */ 1016 1.46 martin *(int *)data = k->k_state.kbd_id < KB_SUN4 ? 1017 1.46 martin WSKBD_TYPE_SUN : WSKBD_TYPE_SUN5; 1018 1.61 tsutsui return 0; 1019 1.44 martin case WSKBDIO_SETLEDS: 1020 1.44 martin wssunkbd_set_leds(v, *(int *)data); 1021 1.61 tsutsui return 0; 1022 1.44 martin case WSKBDIO_GETLEDS: 1023 1.44 martin *(int *)data = k->k_leds; 1024 1.61 tsutsui return 0; 1025 1.46 martin #ifdef WSDISPLAY_COMPAT_RAWKBD 1026 1.48 martin case WSKBDIO_SETMODE: 1027 1.48 martin k->k_wsraw = *(int *)data == WSKBD_RAW; 1028 1.61 tsutsui return 0; 1029 1.44 martin #endif 1030 1.44 martin } 1031 1.35 martin return EPASSTHROUGH; 1032 1.35 martin } 1033 1.35 martin 1034 1.44 martin extern int prom_cngetc(dev_t); 1035 1.44 martin 1036 1.54 christos static void 1037 1.54 christos sunkbd_wskbd_cngetc(void *v, u_int *type, int *data) 1038 1.35 martin { 1039 1.35 martin /* struct kbd_sun_softc *k = v; */ 1040 1.61 tsutsui 1041 1.44 martin *data = prom_cngetc(0); 1042 1.44 martin *type = WSCONS_EVENT_ASCII; 1043 1.35 martin } 1044 1.35 martin 1045 1.35 martin void 1046 1.54 christos sunkbd_wskbd_cnpollc(void *v, int on) 1047 1.35 martin { 1048 1.35 martin } 1049 1.35 martin 1050 1.35 martin static void 1051 1.54 christos sunkbd_bell_off(void *v) 1052 1.35 martin { 1053 1.35 martin struct kbd_softc *k = v; 1054 1.61 tsutsui 1055 1.35 martin k->k_ops->docmd(k, KBD_CMD_NOBELL, 0); 1056 1.35 martin } 1057 1.35 martin 1058 1.35 martin void 1059 1.54 christos sunkbd_wskbd_cnbell(void *v, u_int pitch, u_int period, u_int volume) 1060 1.35 martin { 1061 1.35 martin struct kbd_softc *k = v; 1062 1.35 martin 1063 1.61 tsutsui callout_reset(&k->k_wsbell, period * 1000 / hz, sunkbd_bell_off, v); 1064 1.35 martin k->k_ops->docmd(k, KBD_CMD_BELL, 0); 1065 1.35 martin } 1066 1.35 martin 1067 1.35 martin void 1068 1.63 cegger kbd_enable(device_t dev) 1069 1.35 martin { 1070 1.60 tsutsui struct kbd_softc *k = device_private(dev); 1071 1.35 martin struct wskbddev_attach_args a; 1072 1.35 martin 1073 1.44 martin if (k->k_isconsole) 1074 1.44 martin wskbd_cnattach(&sunkbd_wskbd_consops, k, 1075 1.44 martin &sunkbd_wskbd_keymapdata); 1076 1.35 martin 1077 1.44 martin a.console = k->k_isconsole; 1078 1.35 martin a.keymap = &sunkbd_wskbd_keymapdata; 1079 1.35 martin a.accessops = &sunkbd_wskbd_accessops; 1080 1.35 martin a.accesscookie = k; 1081 1.35 martin 1082 1.44 martin /* XXX why? */ 1083 1.44 martin k->k_wsenabled = 0; 1084 1.44 martin 1085 1.35 martin /* Attach the wskbd */ 1086 1.73 thorpej k->k_wskbd = config_found(k->k_dev, &a, wskbddevprint, CFARGS_NONE); 1087 1.44 martin 1088 1.59 ad callout_init(&k->k_wsbell, 0); 1089 1.44 martin 1090 1.44 martin wssunkbd_enable(k,1); 1091 1.44 martin 1092 1.44 martin wssunkbd_set_leds(k, WSKBD_LED_SCROLL | WSKBD_LED_NUM | WSKBD_LED_CAPS); 1093 1.44 martin delay(100000); 1094 1.44 martin wssunkbd_set_leds(k, 0); 1095 1.44 martin } 1096 1.44 martin 1097 1.44 martin void 1098 1.54 christos kbd_wskbd_attach(struct kbd_softc *k, int isconsole) 1099 1.44 martin { 1100 1.55 christos k->k_isconsole = isconsole; 1101 1.64 macallan if (isconsole) { 1102 1.65 martin #if NSYSMON_ENVSYS 1103 1.64 macallan sysmon_task_queue_init(); 1104 1.64 macallan memset(&k->k_sm_pbutton, 0, sizeof(struct sysmon_pswitch)); 1105 1.64 macallan k->k_sm_pbutton.smpsw_name = device_xname(k->k_dev); 1106 1.64 macallan k->k_sm_pbutton.smpsw_type = PSWITCH_TYPE_POWER; 1107 1.64 macallan if (sysmon_pswitch_register(&k->k_sm_pbutton) != 0) 1108 1.64 macallan aprint_error_dev(k->k_dev, 1109 1.64 macallan "unable to register power button with sysmon\n"); 1110 1.65 martin #endif 1111 1.64 macallan } 1112 1.60 tsutsui config_interrupts(k->k_dev, kbd_enable); 1113 1.35 martin } 1114 1.35 martin #endif 1115