1 /* $NetBSD: kbd.c,v 1.62 2009/01/11 23:36:39 christos Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * @(#)kbd.c 8.2 (Berkeley) 10/30/93
44 * Keyboard driver (/dev/kbd -- note that we do not have minor numbers
45 * [yet?]). Translates incoming bytes to ASCII or to `firm_events' and
46 * passes them up to the appropriate reader.
49 #include <sys/cdefs.h>
50 __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.62 2009/01/11 23:36:39 christos Exp $");
52 #include <sys/param.h>
53 #include <sys/systm.h>
55 #include <sys/device.h>
56 #include <sys/ioctl.h>
57 #include <sys/kernel.h>
59 #include <sys/malloc.h>
60 #include <sys/signal.h>
61 #include <sys/signalvar.h>
63 #include <sys/syslog.h>
64 #include <sys/select.h>
68 #include <dev/wscons/wsksymdef.h>
70 #include <dev/sun/kbd_reg.h>
71 #include <dev/sun/kbio.h>
72 #include <dev/sun/vuid_event.h>
73 #include <dev/sun/event_var.h>
74 #include <dev/sun/kbd_xlate.h>
75 #include <dev/sun/kbdvar.h>
80 dev_type_open(kbdopen
);
81 dev_type_close(kbdclose
);
82 dev_type_read(kbdread
);
83 dev_type_ioctl(kbdioctl
);
84 dev_type_poll(kbdpoll
);
85 dev_type_kqfilter(kbdkqfilter
);
87 const struct cdevsw kbd_cdevsw
= {
88 kbdopen
, kbdclose
, kbdread
, nowrite
, kbdioctl
,
89 nostop
, notty
, kbdpoll
, nommap
, kbdkqfilter
, D_OTHER
93 static int wssunkbd_enable(void *, int);
94 static void wssunkbd_set_leds(void *, int);
95 static int wssunkbd_ioctl(void *, u_long
, void *, int, struct lwp
*);
96 static void sunkbd_wskbd_cngetc(void *, u_int
*, int *);
97 static void sunkbd_wskbd_cnpollc(void *, int);
98 static void sunkbd_wskbd_cnbell(void *, u_int
, u_int
, u_int
);
99 static void sunkbd_bell_off(void *v
);
100 static void kbd_enable(device_t
); /* deferred keyboard init */
102 const struct wskbd_accessops sunkbd_wskbd_accessops
= {
108 extern const struct wscons_keydesc wssun_keydesctab
[];
109 const struct wskbd_mapdata sunkbd_wskbd_keymapdata
= {
118 const struct wskbd_consops sunkbd_wskbd_consops
= {
120 sunkbd_wskbd_cnpollc
,
124 void kbd_wskbd_attach(struct kbd_softc
*, int);
128 static int kbd_iockeymap(struct kbd_state
*, u_long
, struct kiockeymap
*);
130 static int kbd_oldkeymap(struct kbd_state
*, u_long
, struct okiockey
*);
134 /* callbacks for console driver */
135 static int kbd_cc_open(struct cons_channel
*);
136 static int kbd_cc_close(struct cons_channel
*);
139 static void kbd_input_console(struct kbd_softc
*, int);
140 static void kbd_repeat(void *);
141 static int kbd_input_keysym(struct kbd_softc
*, int);
142 static void kbd_input_string(struct kbd_softc
*, char *);
143 static void kbd_input_funckey(struct kbd_softc
*, int);
144 static void kbd_update_leds(struct kbd_softc
*);
147 static void kbd_input_wskbd(struct kbd_softc
*, int);
150 /* firm events input */
151 static void kbd_input_event(struct kbd_softc
*, int);
155 /****************************************************************
156 * Entry points for /dev/kbd
157 * (open,close,read,write,...)
158 ****************************************************************/
162 * Check exclusion, open actual device (_iopen),
163 * setup event channel, clear ASCII repeat stuff.
166 kbdopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
172 k
= device_lookup_private(&kbd_cd
, minor(dev
));
178 * NB: wscons support: while we can track if wskbd has called
179 * enable(), we can't tell if that's for console input or for
180 * events input, so we should probably just let the open to
181 * always succeed regardless (e.g. Xsun opening /dev/kbd).
184 wssunkbd_enable(k
, 1);
187 /* exclusive open required for /dev/kbd */
188 if (k
->k_events
.ev_io
)
190 k
->k_events
.ev_io
= l
->l_proc
;
192 /* stop pending autorepeat of console input */
193 if (k
->k_repeating
) {
195 callout_stop(&k
->k_repeat_ch
);
198 /* open actual underlying device */
199 if (k
->k_ops
!= NULL
&& k
->k_ops
->open
!= NULL
)
200 if ((error
= (*k
->k_ops
->open
)(k
)) != 0) {
201 k
->k_events
.ev_io
= NULL
;
205 ev_init(&k
->k_events
);
206 k
->k_evmode
= 0; /* XXX: OK? */
214 * Turn off event mode, dump the queue, and close the keyboard
215 * unless it is supplying console input.
218 kbdclose(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
222 k
= device_lookup_private(&kbd_cd
, minor(dev
));
224 ev_fini(&k
->k_events
);
225 k
->k_events
.ev_io
= NULL
;
227 if (k
->k_ops
!= NULL
&& k
->k_ops
->close
!= NULL
) {
229 if ((error
= (*k
->k_ops
->close
)(k
)) != 0)
237 kbdread(dev_t dev
, struct uio
*uio
, int flags
)
241 k
= device_lookup_private(&kbd_cd
, minor(dev
));
242 return ev_read(&k
->k_events
, uio
, flags
);
247 kbdpoll(dev_t dev
, int events
, struct lwp
*l
)
251 k
= device_lookup_private(&kbd_cd
, minor(dev
));
252 return ev_poll(&k
->k_events
, events
, l
);
256 kbdkqfilter(dev_t dev
, struct knote
*kn
)
260 k
= device_lookup_private(&kbd_cd
, minor(dev
));
261 return ev_kqfilter(&k
->k_events
, kn
);
265 kbdioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
268 struct kbd_state
*ks
;
271 k
= device_lookup_private(&kbd_cd
, minor(dev
));
276 case KIOCTRANS
: /* Set translation mode */
277 /* We only support "raw" mode on /dev/kbd */
278 if (*(int *)data
!= TR_UNTRANS_EVENT
)
282 case KIOCGTRANS
: /* Get translation mode */
283 /* We only support "raw" mode on /dev/kbd */
284 *(int *)data
= TR_UNTRANS_EVENT
;
288 case KIOCGETKEY
: /* Get keymap entry (old format) */
289 error
= kbd_oldkeymap(ks
, cmd
, (struct okiockey
*)data
);
291 #endif /* KIOCGETKEY */
293 case KIOCSKEY
: /* Set keymap entry */
295 case KIOCGKEY
: /* Get keymap entry */
296 error
= kbd_iockeymap(ks
, cmd
, (struct kiockeymap
*)data
);
299 case KIOCCMD
: /* Send a command to the keyboard */
300 /* pass it to the middle layer */
301 if (k
->k_ops
!= NULL
&& k
->k_ops
->docmd
!= NULL
)
302 error
= (*k
->k_ops
->docmd
)(k
, *(int *)data
, 1);
305 case KIOCTYPE
: /* Get keyboard type */
306 *(int *)data
= ks
->kbd_id
;
309 case KIOCSDIRECT
: /* Where to send input */
310 k
->k_evmode
= *(int *)data
;
313 case KIOCLAYOUT
: /* Get keyboard layout */
314 *(int *)data
= ks
->kbd_layout
;
317 case KIOCSLED
: /* Set keyboard LEDs */
318 /* pass the request to the middle layer */
319 if (k
->k_ops
!= NULL
&& k
->k_ops
->setleds
!= NULL
)
320 error
= (*k
->k_ops
->setleds
)(k
, *(char *)data
, 1);
323 case KIOCGLED
: /* Get keyboard LEDs */
324 *(char *)data
= ks
->kbd_leds
;
327 case FIONBIO
: /* we will remove this someday (soon???) */
331 k
->k_events
.ev_async
= (*(int *)data
!= 0);
335 if (-*(int *)data
!= k
->k_events
.ev_io
->p_pgid
336 && *(int *)data
!= k
->k_events
.ev_io
->p_pid
)
341 if (*(int *)data
!= k
->k_events
.ev_io
->p_pgid
)
354 /****************************************************************
356 ****************************************************************/
359 * Get/Set keymap entry
362 kbd_iockeymap(struct kbd_state
*ks
, u_long cmd
, struct kiockeymap
*kio
)
367 switch (kio
->kio_tablemask
) {
369 km
= ks
->kbd_k
.k_normal
;
372 km
= ks
->kbd_k
.k_shifted
;
375 km
= ks
->kbd_k
.k_control
;
378 km
= ks
->kbd_k
.k_release
;
381 /* Silently ignore unsupported masks */
385 /* Range-check the table position. */
386 station
= kio
->kio_station
;
387 if (station
>= KEYMAP_SIZE
)
392 case KIOCGKEY
: /* Get keymap entry */
393 kio
->kio_entry
= km
[station
];
396 case KIOCSKEY
: /* Set keymap entry */
397 km
[station
] = kio
->kio_entry
;
409 * Get/Set keymap entry,
410 * old format (compatibility)
413 kbd_oldkeymap(struct kbd_state
*ks
, u_long cmd
, struct okiockey
*kio
)
420 if (kio
->kio_station
== 118) {
422 * This is X11 asking if a type 3 keyboard is
423 * really a type 3 keyboard. Say yes, it is,
424 * by reporting key station 118 as a "hole".
425 * Note old (SunOS 3.5) definition of HOLE!
427 kio
->kio_entry
= 0xA2;
439 #endif /* KIOCGETKEY */
443 /****************************************************************
444 * Keyboard input - called by middle layer at spltty().
445 ****************************************************************/
448 kbd_input(struct kbd_softc
*k
, int code
)
452 * XXX: is this still true?
453 * IDLEs confuse the MIT X11R4 server badly, so we must drop them.
454 * This is bad as it means the server will not automatically resync
455 * on all-up IDLEs, but I did not drop them before, and the server
456 * goes crazy when it comes time to blank the screen....
458 if (code
== KBD_IDLE
)
462 * Keyboard is generating firm events. Turn this keystroke
463 * into an event and put it in the queue.
465 kbd_input_event(k
, code
);
470 if (k
->k_wskbd
!= NULL
&& k
->k_wsenabled
) {
472 * We are using wskbd input mode, pass the event up.
474 if (code
== KBD_IDLE
)
475 return; /* this key is not in the mapped */
476 kbd_input_wskbd(k
, code
);
482 * If /dev/kbd is not connected in event mode, or wskbd mode,
483 * translate and send upstream (to console).
485 kbd_input_console(k
, code
);
490 /****************************************************************
491 * Open/close routines called upon opening /dev/console
492 * if we serve console input.
493 ****************************************************************/
495 struct cons_channel
*
496 kbd_cc_alloc(struct kbd_softc
*k
)
498 struct cons_channel
*cc
;
500 if ((cc
= malloc(sizeof *cc
, M_DEVBUF
, M_NOWAIT
)) == NULL
)
503 /* our callbacks for the console driver */
505 cc
->cc_iopen
= kbd_cc_open
;
506 cc
->cc_iclose
= kbd_cc_close
;
508 /* will be provided by the console driver so that we can feed input */
509 cc
->cc_upstream
= NULL
;
512 * TODO: clean up cons_attach_input() vs kd_attach_input() in
513 * lower layers and move that code here.
522 kbd_cc_open(struct cons_channel
*cc
)
534 if (k
->k_ops
!= NULL
&& k
->k_ops
->open
!= NULL
)
535 ret
= (*k
->k_ops
->open
)(k
);
539 /* XXX: verify that callout is not active? */
540 k
->k_repeat_start
= hz
/2;
541 k
->k_repeat_step
= hz
/20;
542 callout_init(&k
->k_repeat_ch
, 0);
549 kbd_cc_close(struct cons_channel
*cc
)
561 if (k
->k_ops
!= NULL
&& k
->k_ops
->close
!= NULL
)
562 ret
= (*k
->k_ops
->close
)(k
);
566 /* stop any pending auto-repeat */
567 if (k
->k_repeating
) {
569 callout_stop(&k
->k_repeat_ch
);
577 /****************************************************************
578 * Console input - called by middle layer at spltty().
579 ****************************************************************/
582 kbd_input_console(struct kbd_softc
*k
, int code
)
584 struct kbd_state
*ks
= &k
->k_state
;
587 /* any input stops auto-repeat (i.e. key release) */
588 if (k
->k_repeating
) {
590 callout_stop(&k
->k_repeat_ch
);
593 keysym
= kbd_code_to_keysym(ks
, code
);
595 /* pass to console */
596 if (kbd_input_keysym(k
, keysym
)) {
597 log(LOG_WARNING
, "%s: code=0x%x with mod=0x%x"
598 " produced unexpected keysym 0x%x\n",
599 device_xname(k
->k_dev
),
600 code
, ks
->kbd_modbits
, keysym
);
601 return; /* no point in auto-repeat here */
604 if (KEYSYM_NOREPEAT(keysym
))
607 /* setup for auto-repeat after initial delay */
609 k
->k_repeatsym
= keysym
;
610 callout_reset(&k
->k_repeat_ch
, k
->k_repeat_start
,
616 * This is the autorepeat callout function scheduled by kbd_input() above.
617 * Called at splsoftclock().
620 kbd_repeat(void *arg
)
622 struct kbd_softc
*k
= arg
;
626 if (k
->k_repeating
&& k
->k_repeatsym
>= 0) {
627 /* feed typematic keysym to the console */
628 (void)kbd_input_keysym(k
, k
->k_repeatsym
);
630 /* reschedule next repeat */
631 callout_reset(&k
->k_repeat_ch
, k
->k_repeat_step
,
640 * Supply keysym as console input. Convert keysym to character(s) and
641 * pass them up to cons_channel's upstream hook.
643 * Return zero on success, else the keysym that we could not handle
644 * (so that the caller may complain).
647 kbd_input_keysym(struct kbd_softc
*k
, int keysym
)
649 struct kbd_state
*ks
= &k
->k_state
;
651 /* Check if a recipient has been configured */
652 if (k
->k_cc
== NULL
|| k
->k_cc
->cc_upstream
== NULL
)
655 switch (KEYSYM_CLASS(keysym
)) {
658 data
= KEYSYM_DATA(keysym
);
659 if (ks
->kbd_modbits
& KBMOD_META_MASK
)
661 (*k
->k_cc
->cc_upstream
)(data
);
666 kbd_input_string(k
, kbd_stringtab
[data
]);
670 kbd_input_funckey(k
, keysym
);
674 data
= 1 << (keysym
& 0x1F);
675 ks
->kbd_modbits
&= ~data
;
679 data
= 1 << (keysym
& 0x1F);
680 ks
->kbd_modbits
|= data
;
684 data
= 1 << (keysym
& 0x1F);
685 ks
->kbd_modbits
^= data
;
690 ks
->kbd_modbits
&= ~0xFFFF;
694 if (keysym
== KEYSYM_NOP
)
698 /* We could not handle it. */
707 * Send string upstream.
710 kbd_input_string(struct kbd_softc
*k
, char *str
)
714 (*k
->k_cc
->cc_upstream
)(*str
);
721 * Format the F-key sequence and send as a string.
722 * XXX: Ugly compatibility mappings.
725 kbd_input_funckey(struct kbd_softc
*k
, int keysym
)
730 n
= 0xC0 + (keysym
& 0x3F);
731 snprintf(str
, sizeof(str
), "\033[%dz", n
);
732 kbd_input_string(k
, str
);
737 * Update LEDs to reflect console input state.
740 kbd_update_leds(struct kbd_softc
*k
)
742 struct kbd_state
*ks
= &k
->k_state
;
746 leds
&= ~(LED_CAPS_LOCK
|LED_NUM_LOCK
);
748 if (ks
->kbd_modbits
& (1 << KBMOD_CAPSLOCK
))
749 leds
|= LED_CAPS_LOCK
;
750 if (ks
->kbd_modbits
& (1 << KBMOD_NUMLOCK
))
751 leds
|= LED_NUM_LOCK
;
753 if (k
->k_ops
!= NULL
&& k
->k_ops
->setleds
!= NULL
)
754 (void)(*k
->k_ops
->setleds
)(k
, leds
, 0);
759 /****************************************************************
760 * Events input - called by middle layer at spltty().
761 ****************************************************************/
764 * Supply raw keystrokes when keyboard is open in firm event mode.
766 * Turn the keystroke into an event and put it in the queue.
767 * If the queue is full, the keystroke is lost (sorry!).
770 kbd_input_event(struct kbd_softc
*k
, int code
)
772 struct firm_event
*fe
;
777 printf("%s: kbd_input_event called when not in event mode\n",
778 device_xname(k
->k_dev
));
782 put
= k
->k_events
.ev_put
;
783 fe
= &k
->k_events
.ev_q
[put
];
784 put
= (put
+ 1) % EV_QSIZE
;
785 if (put
== k
->k_events
.ev_get
) {
786 log(LOG_WARNING
, "%s: event queue overflow\n",
787 device_xname(k
->k_dev
));
791 fe
->id
= KEY_CODE(code
);
792 fe
->value
= KEY_UP(code
) ? VKEY_UP
: VKEY_DOWN
;
794 k
->k_events
.ev_put
= put
;
795 EV_WAKEUP(&k
->k_events
);
800 /****************************************************************
801 * Translation stuff declared in kbd_xlate.h
802 ****************************************************************/
805 * Initialization - called by either lower layer attach or by kdcninit.
808 kbd_xlate_init(struct kbd_state
*ks
)
810 struct keyboard
*ktbls
;
814 if (id
< KBD_MIN_TYPE
)
816 if (id
> kbd_max_type
)
818 ktbls
= keyboards
[id
];
820 ks
->kbd_k
= *ktbls
; /* struct assignment */
825 * Turn keyboard up/down codes into a KEYSYM.
826 * Note that the "kd" driver (on sun3 and sparc64) uses this too!
829 kbd_code_to_keysym(struct kbd_state
*ks
, int c
)
835 * Get keymap pointer. One of these:
836 * release, control, shifted, normal, ...
839 km
= ks
->kbd_k
.k_release
;
840 else if (ks
->kbd_modbits
& KBMOD_CTRL_MASK
)
841 km
= ks
->kbd_k
.k_control
;
842 else if (ks
->kbd_modbits
& KBMOD_SHIFT_MASK
)
843 km
= ks
->kbd_k
.k_shifted
;
845 km
= ks
->kbd_k
.k_normal
;
849 * Do not know how to translate yet.
850 * We will find out when a RESET comes along.
854 keysym
= km
[KEY_CODE(c
)];
857 * Post-processing for Caps-lock
859 if ((ks
->kbd_modbits
& (1 << KBMOD_CAPSLOCK
)) &&
860 (KEYSYM_CLASS(keysym
) == KEYSYM_ASCII
) )
862 if (('a' <= keysym
) && (keysym
<= 'z'))
863 keysym
-= ('a' - 'A');
867 * Post-processing for Num-lock. All "function"
868 * keysyms get indirected through another table.
869 * (XXX: Only if numlock on. Want off also!)
871 if ((ks
->kbd_modbits
& (1 << KBMOD_NUMLOCK
)) &&
872 (KEYSYM_CLASS(keysym
) == KEYSYM_FUNC
) )
874 keysym
= kbd_numlock_map
[keysym
& 0x3F];
882 * Back door for rcons (fb.c)
889 k
= device_lookup_private(&kbd_cd
, 0); /* XXX: hardcoded minor */
891 if (k
== NULL
|| k
->k_ops
== NULL
|| k
->k_ops
->docmd
== NULL
)
894 (void)(*k
->k_ops
->docmd
)(k
, on
? KBD_CMD_BELL
: KBD_CMD_NOBELL
, 0);
899 kbd_input_wskbd(struct kbd_softc
*k
, int code
)
903 #ifdef WSDISPLAY_COMPAT_RAWKBD
908 wskbd_rawinput(k
->k_wskbd
, &buf
, 1);
913 type
= KEY_UP(code
) ? WSCONS_EVENT_KEY_UP
: WSCONS_EVENT_KEY_DOWN
;
914 key
= KEY_CODE(code
);
915 wskbd_input(k
->k_wskbd
, type
, key
);
919 wssunkbd_enable(void *v
, int on
)
921 struct kbd_softc
*k
= v
;
922 if (k
->k_wsenabled
!= on
) {
925 /* open actual underlying device */
926 if (k
->k_ops
!= NULL
&& k
->k_ops
->open
!= NULL
)
927 (*k
->k_ops
->open
)(k
);
928 ev_init(&k
->k_events
);
929 k
->k_evmode
= 0; /* XXX: OK? */
931 /* close underlying device */
932 if (k
->k_ops
!= NULL
&& k
->k_ops
->close
!= NULL
)
933 (*k
->k_ops
->close
)(k
);
940 wssunkbd_set_leds(void *v
, int leds
)
942 struct kbd_softc
*k
= v
;
945 if (leds
& WSKBD_LED_CAPS
)
947 if (leds
& WSKBD_LED_NUM
)
949 if (leds
& WSKBD_LED_SCROLL
)
950 l
|= LED_SCROLL_LOCK
;
951 if (leds
& WSKBD_LED_COMPOSE
)
953 if (k
->k_ops
!= NULL
&& k
->k_ops
->setleds
!= NULL
)
954 (*k
->k_ops
->setleds
)(k
, l
, 0);
959 wssunkbd_ioctl(void *v
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
961 struct kbd_softc
*k
= v
;
965 /* we can't tell 4 from 5 or 6 */
966 *(int *)data
= k
->k_state
.kbd_id
< KB_SUN4
?
967 WSKBD_TYPE_SUN
: WSKBD_TYPE_SUN5
;
969 case WSKBDIO_SETLEDS
:
970 wssunkbd_set_leds(v
, *(int *)data
);
972 case WSKBDIO_GETLEDS
:
973 *(int *)data
= k
->k_leds
;
975 #ifdef WSDISPLAY_COMPAT_RAWKBD
976 case WSKBDIO_SETMODE
:
977 k
->k_wsraw
= *(int *)data
== WSKBD_RAW
;
984 extern int prom_cngetc(dev_t
);
987 sunkbd_wskbd_cngetc(void *v
, u_int
*type
, int *data
)
989 /* struct kbd_sun_softc *k = v; */
991 *data
= prom_cngetc(0);
992 *type
= WSCONS_EVENT_ASCII
;
996 sunkbd_wskbd_cnpollc(void *v
, int on
)
1001 sunkbd_bell_off(void *v
)
1003 struct kbd_softc
*k
= v
;
1005 k
->k_ops
->docmd(k
, KBD_CMD_NOBELL
, 0);
1009 sunkbd_wskbd_cnbell(void *v
, u_int pitch
, u_int period
, u_int volume
)
1011 struct kbd_softc
*k
= v
;
1013 callout_reset(&k
->k_wsbell
, period
* 1000 / hz
, sunkbd_bell_off
, v
);
1014 k
->k_ops
->docmd(k
, KBD_CMD_BELL
, 0);
1018 kbd_enable(device_t dev
)
1020 struct kbd_softc
*k
= device_private(dev
);
1021 struct wskbddev_attach_args a
;
1024 wskbd_cnattach(&sunkbd_wskbd_consops
, k
,
1025 &sunkbd_wskbd_keymapdata
);
1027 a
.console
= k
->k_isconsole
;
1028 a
.keymap
= &sunkbd_wskbd_keymapdata
;
1029 a
.accessops
= &sunkbd_wskbd_accessops
;
1035 /* Attach the wskbd */
1036 k
->k_wskbd
= config_found(k
->k_dev
, &a
, wskbddevprint
);
1038 callout_init(&k
->k_wsbell
, 0);
1040 wssunkbd_enable(k
,1);
1042 wssunkbd_set_leds(k
, WSKBD_LED_SCROLL
| WSKBD_LED_NUM
| WSKBD_LED_CAPS
);
1044 wssunkbd_set_leds(k
, 0);
1048 kbd_wskbd_attach(struct kbd_softc
*k
, int isconsole
)
1050 k
->k_isconsole
= isconsole
;
1052 config_interrupts(k
->k_dev
, kbd_enable
);