wskbd.c revision 1.1 1 /* $NetBSD: wskbd.c,v 1.1 1998/03/22 14:24:03 drochner Exp $ */
2
3 /*
4 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Christopher G. Demetriou
17 * for the NetBSD Project.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 static const char _copyright[] __attribute__ ((unused)) =
34 "Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.";
35 static const char _rcsid[] __attribute__ ((unused)) =
36 "$NetBSD: wskbd.c,v 1.1 1998/03/22 14:24:03 drochner Exp $";
37
38 /*
39 * Copyright (c) 1992, 1993
40 * The Regents of the University of California. All rights reserved.
41 *
42 * This software was developed by the Computer Systems Engineering group
43 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
44 * contributed to Berkeley.
45 *
46 * All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Lawrence Berkeley Laboratory.
50 *
51 * Redistribution and use in source and binary forms, with or without
52 * modification, are permitted provided that the following conditions
53 * are met:
54 * 1. Redistributions of source code must retain the above copyright
55 * notice, this list of conditions and the following disclaimer.
56 * 2. Redistributions in binary form must reproduce the above copyright
57 * notice, this list of conditions and the following disclaimer in the
58 * documentation and/or other materials provided with the distribution.
59 * 3. All advertising materials mentioning features or use of this software
60 * must display the following acknowledgement:
61 * This product includes software developed by the University of
62 * California, Berkeley and its contributors.
63 * 4. Neither the name of the University nor the names of its contributors
64 * may be used to endorse or promote products derived from this software
65 * without specific prior written permission.
66 *
67 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
68 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
69 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
70 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
71 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
72 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
73 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
74 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
75 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
76 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
77 * SUCH DAMAGE.
78 *
79 * @(#)kbd.c 8.2 (Berkeley) 10/30/93
80 */
81
82 /*
83 * Keyboard driver (/dev/wskbd*). Translates incoming bytes to ASCII or
84 * to `wscons_events' and passes them up to the appropriate reader.
85 */
86
87 #include <sys/param.h>
88 #include <sys/conf.h>
89 #include <sys/device.h>
90 #include <sys/ioctl.h>
91 #include <sys/kernel.h>
92 #include <sys/proc.h>
93 #include <sys/syslog.h>
94 #include <sys/systm.h>
95 #include <sys/tty.h>
96 #include <sys/signalvar.h>
97 #include <sys/errno.h>
98 #include <sys/fcntl.h>
99
100 #include <dev/wscons/wsconsio.h>
101 #include <dev/wscons/wskbdvar.h>
102 #include <dev/wscons/wseventvar.h>
103 #include <dev/wscons/wscons_callbacks.h>
104
105 struct wskbd_softc {
106 struct device sc_dv;
107
108 const struct wskbd_accessops *sc_accessops;
109 void *sc_accesscookie;
110
111 int sc_ready; /* accepting events */
112 struct wseventvar sc_events; /* event queue state */
113
114 int sc_isconsole;
115 struct device *sc_displaydv;
116
117 struct wskbd_bell_data sc_bell_data;
118 struct wskbd_keyrepeat_data sc_keyrepeat_data;
119
120 int sc_repeating; /* we've called timeout() */
121 const u_char *sc_repeatstr; /* repeated character (string) */
122 u_int sc_repeatstrlen; /* repeated character (string) len */
123
124 int sc_translating; /* xlate to chars for emulation */
125 };
126
127 #ifdef __BROKEN_INDIRECT_CONFIG
128 int wskbd_match __P((struct device *, void *, void *));
129 #else
130 int wskbd_match __P((struct device *, struct cfdata *, void *));
131 #endif
132 void wskbd_attach __P((struct device *, struct device *, void *));
133
134 struct cfattach wskbd_ca = {
135 sizeof (struct wskbd_softc), wskbd_match, wskbd_attach,
136 };
137
138 extern struct cfdriver wskbd_cd;
139
140 #ifndef WSKBD_DEFAULT_BELL_PITCH
141 #define WSKBD_DEFAULT_BELL_PITCH 1500 /* 1500Hz */
142 #endif
143 #ifndef WSKBD_DEFAULT_BELL_PERIOD
144 #define WSKBD_DEFAULT_BELL_PERIOD 100 /* 100ms */
145 #endif
146 #ifndef WSKBD_DEFAULT_BELL_VOLUME
147 #define WSKBD_DEFAULT_BELL_VOLUME 50 /* 50% volume */
148 #endif
149
150 struct wskbd_bell_data wskbd_default_bell_data = {
151 WSKBD_BELL_DOALL,
152 WSKBD_DEFAULT_BELL_PITCH,
153 WSKBD_DEFAULT_BELL_PERIOD,
154 WSKBD_DEFAULT_BELL_VOLUME,
155 };
156
157 #ifndef WSKBD_DEFAULT_KEYREPEAT_DEL1
158 #define WSKBD_DEFAULT_KEYREPEAT_DEL1 400 /* 400ms to start repeating */
159 #endif
160 #ifndef WSKBD_DEFAULT_KEYREPEAT_DELN
161 #define WSKBD_DEFAULT_KEYREPEAT_DELN 100 /* 100ms to between repeats */
162 #endif
163
164 struct wskbd_keyrepeat_data wskbd_default_keyrepeat_data = {
165 WSKBD_KEYREPEAT_DOALL,
166 WSKBD_DEFAULT_KEYREPEAT_DEL1,
167 WSKBD_DEFAULT_KEYREPEAT_DELN,
168 };
169
170 cdev_decl(wskbd);
171 static void wskbd_repeat __P((void *v));
172
173 static int wskbd_console_initted;
174 static struct wskbd_softc *wskbd_console_device;
175 static const struct wskbd_consops *wskbd_console_ops;
176 static void *wskbd_console_cookie;
177
178 /*
179 * Print function (for parent devices).
180 */
181 int
182 wskbddevprint(aux, pnp)
183 void *aux;
184 const char *pnp;
185 {
186 #if 0
187 struct wskbddev_attach_args *ap = aux;
188 #endif
189
190 if (pnp)
191 printf("wskbd at %s", pnp);
192 #if 0
193 printf(" console %d", ap->console);
194 #endif
195
196 return (UNCONF);
197 }
198
199 int
200 #ifdef __BROKEN_INDIRECT_CONFIG
201 wskbd_match(parent, matchv, aux)
202 #else
203 wskbd_match(parent, match, aux)
204 #endif
205 struct device *parent;
206 #ifdef __BROKEN_INDIRECT_CONFIG
207 void *matchv;
208 #else
209 struct cfdata *match;
210 #endif
211 void *aux;
212 {
213 #ifdef __BROKEN_INDIRECT_CONFIG
214 struct cfdata *match = matchv;
215 #endif
216 struct wskbddev_attach_args *ap = aux;
217
218 if (match->wskbddevcf_console != WSKBDDEVCF_CONSOLE_UNK) {
219 /*
220 * If console-ness of device specified, either match
221 * exactly (at high priority), or fail.
222 */
223 if (match->wskbddevcf_console != 0 && ap->console != 0)
224 return (10);
225 else
226 return (0);
227 }
228
229 /* If console-ness unspecified, it wins. */
230 return (1);
231 }
232
233 void
234 wskbd_attach(parent, self, aux)
235 struct device *parent, *self;
236 void *aux;
237 {
238 struct wskbd_softc *sc = (struct wskbd_softc *)self;
239 struct wskbddev_attach_args *ap = aux;
240
241 if (ap->console)
242 printf(": console keyboard");
243 printf("\n");
244
245 sc->sc_accessops = ap->accessops;
246 sc->sc_accesscookie = ap->accesscookie;
247 sc->sc_ready = 0; /* sanity */
248 sc->sc_repeating = 0;
249 sc->sc_translating = 1;
250
251 if (ap->console) {
252 KASSERT(wskbd_console_initted);
253 KASSERT(wskbd_console_device == NULL);
254 wskbd_console_device = sc;
255 }
256 sc->sc_isconsole = ap->console;
257 sc->sc_displaydv = NULL;
258
259 /* set default bell and key repeat data */
260 sc->sc_bell_data = wskbd_default_bell_data;
261 sc->sc_keyrepeat_data = wskbd_default_keyrepeat_data;
262 }
263
264 void
265 wskbd_cnattach(consops, cookie)
266 const struct wskbd_consops *consops;
267 void *cookie;
268 {
269
270 KASSERT(!wskbd_console_initted);
271
272 wskbd_console_ops = consops;
273 wskbd_console_cookie = cookie;
274
275 wsdisplay_set_cons_kbd(wskbd_cngetc, wskbd_cnpollc);
276
277 wskbd_console_initted = 1;
278 }
279
280 static void
281 wskbd_repeat(v)
282 void *v;
283 {
284 struct wskbd_softc *sc = (struct wskbd_softc *)v;
285 int s = spltty();
286
287 KASSERT(sc->sc_repeating);
288 if (sc->sc_repeatstrlen != 0) {
289 if (sc->sc_displaydv != NULL)
290 wsdisplay_kbdinput(sc->sc_displaydv, sc->sc_repeatstr,
291 sc->sc_repeatstrlen);
292 timeout(wskbd_repeat, sc,
293 (hz * sc->sc_keyrepeat_data.delN) / 1000);
294 }
295 splx(s);
296 }
297
298 void
299 wskbd_input(dev, type, value)
300 struct device *dev;
301 u_int type;
302 int value;
303 {
304 struct wskbd_softc *sc = (struct wskbd_softc *)dev;
305 struct wscons_event *ev;
306 struct timeval xxxtime;
307 const char *cp;
308 int put;
309
310 if (sc->sc_repeating) {
311 sc->sc_repeating = 0;
312 untimeout(wskbd_repeat, sc);
313 }
314
315 /*
316 * If /dev/kbd is not connected in event mode translate and
317 * send upstream.
318 */
319 if (sc->sc_translating) {
320 cp = (*sc->sc_accessops->translate)(sc->sc_accesscookie,
321 type, value);
322 if (cp != NULL) {
323 sc->sc_repeatstr = cp;
324 sc->sc_repeatstrlen = strlen(cp);
325 if (sc->sc_repeatstrlen != 0) {
326 if (sc->sc_displaydv != NULL)
327 wsdisplay_kbdinput(sc->sc_displaydv,
328 sc->sc_repeatstr,
329 sc->sc_repeatstrlen);
330
331 sc->sc_repeating = 1;
332 timeout(wskbd_repeat, sc,
333 (hz * sc->sc_keyrepeat_data.del1) / 1000);
334 }
335 }
336 return;
337 }
338
339 /*
340 * Keyboard is generating events. Turn this keystroke into an
341 * event and put it in the queue. If the queue is full, the
342 * keystroke is lost (sorry!).
343 */
344
345 /* no one to receive; punt!*/
346 if (!sc->sc_ready)
347 return;
348
349 put = sc->sc_events.put;
350 ev = &sc->sc_events.q[put];
351 put = (put + 1) % WSEVENT_QSIZE;
352 if (put == sc->sc_events.get) {
353 log(LOG_WARNING, "%s: event queue overflow\n",
354 sc->sc_dv.dv_xname);
355 return;
356 }
357 ev->type = type;
358 ev->value = value;
359 microtime(&xxxtime);
360 TIMEVAL_TO_TIMESPEC(&xxxtime, &ev->time);
361 sc->sc_events.put = put;
362 WSEVENT_WAKEUP(&sc->sc_events);
363 }
364
365 void wskbd_ctlinput(dev, val)
366 struct device *dev;
367 int val;
368 {
369 struct wskbd_softc *sc = (struct wskbd_softc *)dev;
370
371 if (sc->sc_displaydv != NULL)
372 wsdisplay_switch(sc->sc_displaydv, val); /* XXX XXX */
373 }
374
375 void
376 wskbd_holdscreen(dev, hold)
377 struct device *dev;
378 int hold;
379 {
380 struct wskbd_softc *sc = (struct wskbd_softc *)dev;
381
382 if (sc->sc_displaydv != NULL)
383 wsdisplay_kbdholdscreen(sc->sc_displaydv, hold);
384 }
385
386 int
387 wskbdopen(dev, flags, mode, p)
388 dev_t dev;
389 int flags, mode;
390 struct proc *p;
391 {
392 struct wskbd_softc *sc;
393 int unit;
394
395 unit = minor(dev);
396 if (unit >= wskbd_cd.cd_ndevs || /* make sure it was attached */
397 (sc = wskbd_cd.cd_devs[unit]) == NULL)
398 return (ENXIO);
399
400 if (sc->sc_events.io) /* and that it's not in use */
401 return (EBUSY);
402
403 sc->sc_events.io = p;
404 wsevent_init(&sc->sc_events); /* may cause sleep */
405
406 sc->sc_ready = 1; /* start accepting events */
407
408 /* XXX ENABLE THE DEVICE IF NOT CONSOLE? */
409
410 return (0);
411 }
412
413 int
414 wskbdclose(dev, flags, mode, p)
415 dev_t dev;
416 int flags, mode;
417 struct proc *p;
418 {
419 struct wskbd_softc *sc;
420 int unit;
421
422 unit = minor(dev);
423 if (unit >= wskbd_cd.cd_ndevs || /* make sure it was attached */
424 (sc = wskbd_cd.cd_devs[unit]) == NULL)
425 return (ENXIO);
426
427 /* XXX DISABLE THE DEVICE IF NOT CONSOLE? */
428
429 sc->sc_ready = 0; /* stop accepting events */
430 wsevent_fini(&sc->sc_events);
431 sc->sc_events.io = NULL;
432 return (0);
433 }
434
435 int
436 wskbdread(dev, uio, flags)
437 dev_t dev;
438 struct uio *uio;
439 int flags;
440 {
441 struct wskbd_softc *sc;
442 int unit;
443
444 unit = minor(dev);
445 if (unit >= wskbd_cd.cd_ndevs || /* make sure it was attached */
446 (sc = wskbd_cd.cd_devs[unit]) == NULL)
447 return (ENXIO);
448
449 return (wsevent_read(&sc->sc_events, uio, flags));
450 }
451
452 int
453 wskbdioctl(dev, cmd, data, flag, p)
454 dev_t dev;
455 u_long cmd;
456 caddr_t data;
457 int flag;
458 struct proc *p;
459 {
460 struct wskbd_softc *sc;
461 int unit, error;
462
463 unit = minor(dev);
464 if (unit >= wskbd_cd.cd_ndevs || /* make sure it was attached */
465 (sc = wskbd_cd.cd_devs[unit]) == NULL)
466 return (ENXIO);
467
468 /*
469 * Try the generic ioctls that the wskbd interface supports.
470 */
471 switch (cmd) {
472 case FIONBIO: /* we will remove this someday (soon???) */
473 return (0);
474
475 case FIOASYNC:
476 sc->sc_events.async = *(int *)data != 0;
477 return (0);
478
479 case TIOCSPGRP:
480 if (*(int *)data != sc->sc_events.io->p_pgid)
481 return (EPERM);
482 return (0);
483 }
484
485 /*
486 * Try the keyboard driver for WSKBDIO ioctls. It returns -1
487 * if it didn't recognize the request.
488 */
489 error = wskbd_displayioctl((struct device *)sc, cmd, data, flag, p);
490 return (error != -1 ? error : ENOTTY);
491 }
492
493 /*
494 * WSKBDIO ioctls, handled in both emulation mode and in ``raw'' mode.
495 * Some of these have no real effect in raw mode, however.
496 */
497 int
498 wskbd_displayioctl(dev, cmd, data, flag, p)
499 struct device *dev;
500 u_long cmd;
501 caddr_t data;
502 int flag;
503 struct proc *p;
504 {
505 struct wskbd_softc *sc = (struct wskbd_softc *)dev;
506 struct wskbd_bell_data *ubdp, *kbdp;
507 struct wskbd_keyrepeat_data *ukdp, *kkdp;
508 int error;
509
510 switch (cmd) {
511 #define SETBELL(dstp, srcp, dfltp) \
512 do { \
513 (dstp)->pitch = ((srcp)->which & WSKBD_BELL_DOPITCH) ? \
514 (srcp)->pitch : (dfltp)->pitch; \
515 (dstp)->period = ((srcp)->which & WSKBD_BELL_DOPERIOD) ? \
516 (srcp)->period : (dfltp)->period; \
517 (dstp)->volume = ((srcp)->which & WSKBD_BELL_DOVOLUME) ? \
518 (srcp)->volume : (dfltp)->volume; \
519 (dstp)->which = WSKBD_BELL_DOALL; \
520 } while (0)
521
522 case WSKBDIO_BELL:
523 if ((flag & FWRITE) == 0)
524 return (EACCES);
525 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
526 WSKBDIO_COMPLEXBELL, (caddr_t)&sc->sc_bell_data, flag, p));
527
528 case WSKBDIO_COMPLEXBELL:
529 if ((flag & FWRITE) == 0)
530 return (EACCES);
531 ubdp = (struct wskbd_bell_data *)data;
532 SETBELL(ubdp, ubdp, &sc->sc_bell_data);
533 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie,
534 WSKBDIO_COMPLEXBELL, (caddr_t)ubdp, flag, p));
535
536 case WSKBDIO_SETBELL:
537 if ((flag & FWRITE) == 0)
538 return (EACCES);
539 kbdp = &sc->sc_bell_data;
540 setbell:
541 ubdp = (struct wskbd_bell_data *)data;
542 SETBELL(kbdp, ubdp, kbdp);
543 return (0);
544
545 case WSKBDIO_GETBELL:
546 kbdp = &sc->sc_bell_data;
547 getbell:
548 ubdp = (struct wskbd_bell_data *)data;
549 SETBELL(ubdp, kbdp, kbdp);
550 return (0);
551
552 case WSKBDIO_SETDEFAULTBELL:
553 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
554 return (error);
555 kbdp = &wskbd_default_bell_data;
556 goto setbell;
557
558
559 case WSKBDIO_GETDEFAULTBELL:
560 kbdp = &wskbd_default_bell_data;
561 goto getbell;
562
563 #undef SETBELL
564
565 #define SETKEYREPEAT(dstp, srcp, dfltp) \
566 do { \
567 (dstp)->del1 = ((srcp)->which & WSKBD_KEYREPEAT_DODEL1) ? \
568 (srcp)->del1 : (dfltp)->del1; \
569 (dstp)->delN = ((srcp)->which & WSKBD_KEYREPEAT_DODELN) ? \
570 (srcp)->delN : (dfltp)->delN; \
571 (dstp)->which = WSKBD_KEYREPEAT_DOALL; \
572 } while (0)
573
574 case WSKBDIO_SETKEYREPEAT:
575 if ((flag & FWRITE) == 0)
576 return (EACCES);
577 kkdp = &sc->sc_keyrepeat_data;
578 setkeyrepeat:
579 ukdp = (struct wskbd_keyrepeat_data *)data;
580 SETKEYREPEAT(kkdp, ukdp, kkdp);
581 return (0);
582
583 case WSKBDIO_GETKEYREPEAT:
584 kkdp = &sc->sc_keyrepeat_data;
585 getkeyrepeat:
586 ukdp = (struct wskbd_keyrepeat_data *)data;
587 SETKEYREPEAT(ukdp, kkdp, kkdp);
588 return (0);
589
590 case WSKBDIO_SETDEFAULTKEYREPEAT:
591 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
592 return (error);
593 kkdp = &wskbd_default_keyrepeat_data;
594 goto setkeyrepeat;
595
596
597 case WSKBDIO_GETDEFAULTKEYREPEAT:
598 kkdp = &wskbd_default_keyrepeat_data;
599 goto getkeyrepeat;
600
601 #undef SETKEYREPEAT
602 }
603
604 /*
605 * Try the keyboard driver for WSKBDIO ioctls. It returns -1
606 * if it didn't recognize the request, and in turn we return
607 * -1 if we didn't recognize the request.
608 */
609 /* printf("kbdaccess\n"); */
610 return ((*sc->sc_accessops->ioctl)(sc->sc_accesscookie, cmd,
611 data, flag, p));
612 }
613
614 int
615 wskbdpoll(dev, events, p)
616 dev_t dev;
617 int events;
618 struct proc *p;
619 {
620 struct wskbd_softc *sc = wskbd_cd.cd_devs[minor(dev)];
621
622 return (wsevent_poll(&sc->sc_events, events, p));
623 }
624
625 int
626 wskbd_is_console(dv)
627 struct device *dv;
628 {
629 struct wskbd_softc *sc = (struct wskbd_softc *)dv;
630
631 KASSERT(sc != NULL);
632 return (sc->sc_isconsole);
633 }
634
635 struct device *
636 wskbd_display(dv)
637 struct device *dv;
638 {
639 struct wskbd_softc *sc = (struct wskbd_softc *)dv;
640
641 KASSERT(sc != NULL);
642 return (sc->sc_displaydv);
643 }
644
645 void
646 wskbd_set_display(dv, displaydv)
647 struct device *dv, *displaydv;
648 {
649 struct wskbd_softc *sc = (struct wskbd_softc *)dv;
650
651 KASSERT(sc != NULL);
652 sc->sc_displaydv = displaydv;
653 }
654
655 void
656 wskbd_set_translation(dv, on)
657 struct device *dv;
658 int on;
659 {
660 struct wskbd_softc *sc = (struct wskbd_softc *)dv;
661
662 KASSERT(sc != NULL);
663 sc->sc_translating = on;
664 }
665
666 /*
667 * Console interface.
668 */
669 int
670 wskbd_cngetc(dev)
671 dev_t dev;
672 {
673
674 if (!wskbd_console_initted)
675 return 0;
676
677 if (wskbd_console_device != NULL &&
678 !wskbd_console_device->sc_translating)
679 return 0;
680
681 return ((*wskbd_console_ops->getc)(wskbd_console_cookie));
682 }
683
684 void
685 wskbd_cnpollc(dev, poll)
686 dev_t dev;
687 int poll;
688 {
689
690 if (!wskbd_console_initted)
691 return;
692
693 if (wskbd_console_device != NULL &&
694 !wskbd_console_device->sc_translating)
695 return;
696
697 (*wskbd_console_ops->pollc)(wskbd_console_cookie, poll);
698 }
699