4 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer as
12 * the first lines of this file unmodified.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * $FreeBSD: src/sys/dev/kbd/kbd.c,v 1.17.2.2 2001/07/30 16:46:43 yokota Exp $
31 * Generic keyboard driver.
33 * Interrupt note: keyboards use clist functions and since usb keyboard
34 * interrupts are not protected by spltty(), we must use a critical section
35 * to protect against corruption.
36 * XXX: this keyboard driver doesn't use clist functions anymore!
38 * MPSAFE NOTE: all keyboards could easily be put under a different global token.
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
50 #include <sys/event.h>
51 #include <sys/vnode.h>
53 #include <sys/thread.h>
54 #include <sys/thread2.h>
56 #include <machine/console.h>
61 #define lwkt_gettoken(x)
62 #define lwkt_reltoken(x)
65 #define KBD_INDEX(dev) minor(dev)
71 int gkb_flags
; /* flag/status bits */
72 #define KB_ASLEEP (1 << 0)
73 struct kqinfo gkb_rkq
;
74 char gkb_q
[KB_QSIZE
]; /* input queue */
75 unsigned int gkb_q_start
;
76 unsigned int gkb_q_length
;
79 typedef struct genkbd_softc
*genkbd_softc_t
;
81 static SLIST_HEAD(, keyboard_driver
) keyboard_drivers
=
82 SLIST_HEAD_INITIALIZER(keyboard_drivers
);
84 SET_DECLARE(kbddriver_set
, const keyboard_driver_t
);
89 * We need at least one entry each in order to initialize a keyboard
90 * for the kernel console. The arrays will be increased dynamically
94 static int keyboards
= 1;
95 static keyboard_t
*kbd_ini
;
96 static keyboard_t
**keyboard
= &kbd_ini
;
97 static keyboard_switch_t
*kbdsw_ini
;
98 keyboard_switch_t
**kbdsw
= &kbdsw_ini
;
100 #define ARRAY_DELTA 4
103 kbd_realloc_array(void)
105 keyboard_t
**new_kbd
;
106 keyboard_switch_t
**new_kbdsw
;
109 lwkt_gettoken(&tty_token
);
110 newsize
= ((keyboards
+ ARRAY_DELTA
)/ARRAY_DELTA
)*ARRAY_DELTA
;
111 new_kbd
= kmalloc(sizeof(*new_kbd
) * newsize
, M_DEVBUF
,
113 new_kbdsw
= kmalloc(sizeof(*new_kbdsw
) * newsize
, M_DEVBUF
,
115 bcopy(keyboard
, new_kbd
, sizeof(*keyboard
)*keyboards
);
116 bcopy(kbdsw
, new_kbdsw
, sizeof(*kbdsw
)*keyboards
);
119 kfree(keyboard
, M_DEVBUF
);
120 kfree(kbdsw
, M_DEVBUF
);
128 kprintf("kbd: new array size %d\n", keyboards
);
130 lwkt_reltoken(&tty_token
);
135 * Low-level keyboard driver functions.
137 * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard
138 * driver, call these functions to initialize the keyboard_t structure
139 * and register it to the virtual keyboard driver `kbd'.
141 * The reinit call is made when a driver has partially detached a keyboard
142 * but does not unregistered it, then wishes to reinitialize it later on.
143 * This is how the USB keyboard driver handles the 'default' keyboard,
144 * because unregistering the keyboard associated with the console will
145 * destroy its console association forever.
148 kbd_reinit_struct(keyboard_t
*kbd
, int config
, int pref
)
150 lwkt_gettoken(&tty_token
);
151 kbd
->kb_flags
|= KB_NO_DEVICE
; /* device has not been found */
152 kbd
->kb_config
= config
& ~KB_CONF_PROBE_ONLY
;
153 kbd
->kb_led
= 0; /* unknown */
155 kbd
->kb_keymap
= NULL
;
156 kbd
->kb_accentmap
= NULL
;
157 kbd
->kb_fkeytab
= NULL
;
158 kbd
->kb_fkeytab_size
= 0;
159 kbd
->kb_delay1
= KB_DELAY1
; /* these values are advisory only */
160 kbd
->kb_delay2
= KB_DELAY2
;
163 bzero(kbd
->kb_lastact
, sizeof(kbd
->kb_lastact
));
164 lwkt_reltoken(&tty_token
);
167 /* initialize the keyboard_t structure */
169 kbd_init_struct(keyboard_t
*kbd
, char *name
, int type
, int unit
, int config
,
170 int pref
, int port
, int port_size
)
172 lwkt_gettoken(&tty_token
);
177 kbd
->kb_io_base
= port
;
178 kbd
->kb_io_size
= port_size
;
179 kbd_reinit_struct(kbd
, config
, pref
);
180 lockinit(&kbd
->kb_lock
, name
, 0, LK_CANRECURSE
);
181 lwkt_reltoken(&tty_token
);
185 kbd_set_maps(keyboard_t
*kbd
, keymap_t
*keymap
, accentmap_t
*accmap
,
186 fkeytab_t
*fkeymap
, int fkeymap_size
)
188 lwkt_gettoken(&tty_token
);
189 kbd
->kb_keymap
= keymap
;
190 kbd
->kb_accentmap
= accmap
;
191 kbd
->kb_fkeytab
= fkeymap
;
192 kbd
->kb_fkeytab_size
= fkeymap_size
;
193 lwkt_reltoken(&tty_token
);
196 /* declare a new keyboard driver */
198 kbd_add_driver(keyboard_driver_t
*driver
)
200 lwkt_gettoken(&tty_token
);
201 if (SLIST_NEXT(driver
, link
)) {
202 lwkt_reltoken(&tty_token
);
205 SLIST_INSERT_HEAD(&keyboard_drivers
, driver
, link
);
206 lwkt_reltoken(&tty_token
);
211 kbd_delete_driver(keyboard_driver_t
*driver
)
213 lwkt_gettoken(&tty_token
);
214 SLIST_REMOVE(&keyboard_drivers
, driver
, keyboard_driver
, link
);
215 SLIST_NEXT(driver
, link
) = NULL
;
216 lwkt_reltoken(&tty_token
);
220 /* register a keyboard and associate it with a function table */
222 kbd_register(keyboard_t
*kbd
)
224 const keyboard_driver_t
**list
;
225 const keyboard_driver_t
*p
;
230 lwkt_gettoken(&tty_token
);
231 mux
= kbd_get_keyboard(kbd_find_keyboard("kbdmux", -1));
233 for (index
= 0; index
< keyboards
; ++index
) {
234 if (keyboard
[index
] == NULL
)
237 if (index
>= keyboards
) {
238 if (kbd_realloc_array()) {
239 lwkt_reltoken(&tty_token
);
244 kbd
->kb_index
= index
;
247 kbd
->kb_active
= 0; /* disabled until someone calls kbd_enable() */
248 kbd
->kb_token
= NULL
;
249 kbd
->kb_callback
.kc_func
= NULL
;
250 kbd
->kb_callback
.kc_arg
= NULL
;
251 callout_init_mp(&kbd
->kb_atkbd_timeout_ch
);
253 SLIST_FOREACH(p
, &keyboard_drivers
, link
) {
254 if (strcmp(p
->name
, kbd
->kb_name
) == 0) {
255 keyboard
[index
] = kbd
;
256 kbdsw
[index
] = p
->kbdsw
;
259 bzero(&ki
, sizeof(ki
));
260 strcpy(ki
.kb_name
, kbd
->kb_name
);
261 ki
.kb_unit
= kbd
->kb_unit
;
262 kbd_ioctl(mux
, KBADDKBD
, (caddr_t
) &ki
);
265 lwkt_reltoken(&tty_token
);
269 SET_FOREACH(list
, kbddriver_set
) {
271 if (strcmp(p
->name
, kbd
->kb_name
) == 0) {
272 keyboard
[index
] = kbd
;
273 kbdsw
[index
] = p
->kbdsw
;
276 bzero(&ki
, sizeof(ki
));
277 strcpy(ki
.kb_name
, kbd
->kb_name
);
278 ki
.kb_unit
= kbd
->kb_unit
;
279 kbd_ioctl(mux
, KBADDKBD
, (caddr_t
) &ki
);
282 lwkt_reltoken(&tty_token
);
287 lwkt_reltoken(&tty_token
);
292 kbd_unregister(keyboard_t
*kbd
)
296 KBD_LOCK_ASSERT(kbd
);
297 lwkt_gettoken(&tty_token
);
298 if ((kbd
->kb_index
< 0) || (kbd
->kb_index
>= keyboards
)) {
299 lwkt_reltoken(&tty_token
);
302 if (keyboard
[kbd
->kb_index
] != kbd
) {
303 lwkt_reltoken(&tty_token
);
308 callout_stop(&kbd
->kb_atkbd_timeout_ch
);
309 if (KBD_IS_BUSY(kbd
)) {
310 error
= (*kbd
->kb_callback
.kc_func
)(kbd
, KBDIO_UNLOADING
,
311 kbd
->kb_callback
.kc_arg
);
314 lwkt_reltoken(&tty_token
);
317 if (KBD_IS_BUSY(kbd
)) {
319 lwkt_reltoken(&tty_token
);
323 KBD_CONFIG_LOST(kbd
);
325 keyboard
[kbd
->kb_index
] = NULL
;
326 kbdsw
[kbd
->kb_index
] = NULL
;
328 KBD_ALWAYS_UNLOCK(kbd
);
329 lockuninit(&kbd
->kb_lock
);
332 lwkt_reltoken(&tty_token
);
336 /* find a funciton table by the driver name */
338 kbd_get_switch(char *driver
)
340 const keyboard_driver_t
**list
;
341 const keyboard_driver_t
*p
;
343 lwkt_gettoken(&tty_token
);
345 SLIST_FOREACH(p
, &keyboard_drivers
, link
) {
346 if (strcmp(p
->name
, driver
) == 0) {
347 lwkt_reltoken(&tty_token
);
351 SET_FOREACH(list
, kbddriver_set
) {
353 if (strcmp(p
->name
, driver
) == 0) {
354 lwkt_reltoken(&tty_token
);
359 lwkt_reltoken(&tty_token
);
364 * Keyboard client functions
365 * Keyboard clients, such as the console driver `syscons' and the keyboard
366 * cdev driver, use these functions to claim and release a keyboard for
370 * find the keyboard specified by a driver name and a unit number
371 * starting at given index
374 kbd_find_keyboard2(char *driver
, int unit
, int index
, int legacy
)
383 lwkt_gettoken(&tty_token
);
384 if ((index
< 0) || (index
>= keyboards
)) {
385 lwkt_reltoken(&tty_token
);
389 for (i
= index
; i
< keyboards
; ++i
) {
390 if (keyboard
[i
] == NULL
)
392 if (!KBD_IS_VALID(keyboard
[i
]))
394 if (strcmp("*", driver
) && strcmp(keyboard
[i
]->kb_name
, driver
))
396 if ((unit
!= -1) && (keyboard
[i
]->kb_unit
!= unit
))
399 * If we are in legacy mode, we do the old preference magic and
400 * don't return on the first found unit.
403 if (pref
<= keyboard
[i
]->kb_pref
) {
404 pref
= keyboard
[i
]->kb_pref
;
408 lwkt_reltoken(&tty_token
);
414 KKASSERT(pref_index
== -1);
416 lwkt_reltoken(&tty_token
);
420 /* find the keyboard specified by a driver name and a unit number */
422 kbd_find_keyboard(char *driver
, int unit
)
424 return (kbd_find_keyboard2(driver
, unit
, 0, 1));
427 /* allocate a keyboard */
429 kbd_allocate(char *driver
, int unit
, void *id
, kbd_callback_func_t
*func
,
438 lwkt_gettoken(&tty_token
);
440 index
= kbd_find_keyboard(driver
, unit
);
442 if (KBD_IS_BUSY(keyboard
[index
])) {
444 lwkt_reltoken(&tty_token
);
447 keyboard
[index
]->kb_token
= id
;
448 KBD_BUSY(keyboard
[index
]);
449 keyboard
[index
]->kb_callback
.kc_func
= func
;
450 keyboard
[index
]->kb_callback
.kc_arg
= arg
;
451 kbd_clear_state(keyboard
[index
]);
454 lwkt_reltoken(&tty_token
);
460 kbd_release(keyboard_t
*kbd
, void *id
)
465 lwkt_gettoken(&tty_token
);
467 if (!KBD_IS_VALID(kbd
) || !KBD_IS_BUSY(kbd
)) {
469 } else if (kbd
->kb_token
!= id
) {
472 kbd
->kb_token
= NULL
;
474 kbd
->kb_callback
.kc_func
= NULL
;
475 kbd
->kb_callback
.kc_arg
= NULL
;
476 kbd_clear_state(kbd
);
480 lwkt_reltoken(&tty_token
);
486 kbd_change_callback(keyboard_t
*kbd
, void *id
, kbd_callback_func_t
*func
,
492 lwkt_gettoken(&tty_token
);
494 if (!KBD_IS_VALID(kbd
) || !KBD_IS_BUSY(kbd
)) {
496 } else if (kbd
->kb_token
!= id
) {
498 } else if (func
== NULL
) {
501 kbd
->kb_callback
.kc_func
= func
;
502 kbd
->kb_callback
.kc_arg
= arg
;
506 lwkt_reltoken(&tty_token
);
511 /* get a keyboard structure */
513 kbd_get_keyboard(int index
)
517 lwkt_gettoken(&tty_token
);
518 if ((index
< 0) || (index
>= keyboards
)) {
519 lwkt_reltoken(&tty_token
);
522 if (keyboard
[index
] == NULL
) {
523 lwkt_reltoken(&tty_token
);
526 if (!KBD_IS_VALID(keyboard
[index
])) {
527 lwkt_reltoken(&tty_token
);
530 kbd
= keyboard
[index
];
531 lwkt_reltoken(&tty_token
);
537 * The back door for the console driver; configure keyboards
538 * This function is for the kernel console to initialize keyboards
539 * at very early stage.
543 kbd_configure(int flags
)
545 const keyboard_driver_t
**list
;
546 const keyboard_driver_t
*p
;
548 lwkt_gettoken(&tty_token
);
550 SLIST_FOREACH(p
, &keyboard_drivers
, link
) {
551 if (p
->configure
!= NULL
)
552 (*p
->configure
)(flags
);
554 SET_FOREACH(list
, kbddriver_set
) {
556 if (p
->configure
!= NULL
)
557 (*p
->configure
)(flags
);
560 lwkt_reltoken(&tty_token
);
564 #ifdef KBD_INSTALL_CDEV
567 * Virtual keyboard cdev driver functions
568 * The virtual keyboard driver dispatches driver functions to
569 * appropriate subdrivers.
572 #define KBD_UNIT(dev) minor(dev)
574 static d_open_t genkbdopen
;
575 static d_close_t genkbdclose
;
576 static d_read_t genkbdread
;
577 static d_write_t genkbdwrite
;
578 static d_ioctl_t genkbdioctl
;
579 static d_kqfilter_t genkbdkqfilter
;
581 static void genkbdfiltdetach(struct knote
*);
582 static int genkbdfilter(struct knote
*, long);
584 static struct dev_ops kbd_ops
= {
585 { "kbd", 0, D_MPSAFE
},
586 .d_open
= genkbdopen
,
587 .d_close
= genkbdclose
,
588 .d_read
= genkbdread
,
589 .d_write
= genkbdwrite
,
590 .d_ioctl
= genkbdioctl
,
591 .d_kqfilter
= genkbdkqfilter
597 * NOTE: The usb driver does not detach the default keyboard if it is
598 * unplugged, but calls kbd_attach() when it is plugged back in.
601 kbd_attach(keyboard_t
*kbd
)
604 char tbuf
[MAKEDEV_MINNBUF
];
606 lwkt_gettoken(&tty_token
);
607 if (kbd
->kb_index
>= keyboards
) {
608 lwkt_reltoken(&tty_token
);
611 if (keyboard
[kbd
->kb_index
] != kbd
) {
612 lwkt_reltoken(&tty_token
);
616 if (kbd
->kb_dev
== NULL
) {
617 kbd
->kb_dev
= make_dev(&kbd_ops
, kbd
->kb_index
,
618 UID_ROOT
, GID_WHEEL
, 0600, "kbd%s",
619 makedev_unit_b32(tbuf
, kbd
->kb_index
));
622 if (dev
->si_drv1
== NULL
) {
623 dev
->si_drv1
= kmalloc(sizeof(struct genkbd_softc
), M_DEVBUF
,
626 bzero(dev
->si_drv1
, sizeof(struct genkbd_softc
));
628 kprintf("kbd%d at %s%d\n", kbd
->kb_index
, kbd
->kb_name
, kbd
->kb_unit
);
629 lwkt_reltoken(&tty_token
);
634 kbd_detach(keyboard_t
*kbd
)
638 lwkt_gettoken(&tty_token
);
640 if (kbd
->kb_index
>= keyboards
) {
641 lwkt_reltoken(&tty_token
);
644 if (keyboard
[kbd
->kb_index
] != kbd
) {
645 lwkt_reltoken(&tty_token
);
649 if ((dev
= kbd
->kb_dev
) != NULL
) {
651 kfree(dev
->si_drv1
, M_DEVBUF
);
656 dev_ops_remove_minor(&kbd_ops
, kbd
->kb_index
);
657 lwkt_reltoken(&tty_token
);
662 * Generic keyboard cdev driver functions
663 * Keyboard subdrivers may call these functions to implement common
668 genkbd_putc(genkbd_softc_t sc
, char c
)
672 lwkt_gettoken(&tty_token
);
674 if (sc
->gkb_q_length
== KB_QSIZE
) {
675 lwkt_reltoken(&tty_token
);
679 p
= (sc
->gkb_q_start
+ sc
->gkb_q_length
) % KB_QSIZE
;
683 lwkt_reltoken(&tty_token
);
687 genkbd_getc(genkbd_softc_t sc
, char *buf
, size_t len
)
690 lwkt_gettoken(&tty_token
);
692 /* Determine copy size. */
693 if (sc
->gkb_q_length
== 0) {
694 lwkt_reltoken(&tty_token
);
697 if (len
>= sc
->gkb_q_length
)
698 len
= sc
->gkb_q_length
;
699 if (len
>= KB_QSIZE
- sc
->gkb_q_start
)
700 len
= KB_QSIZE
- sc
->gkb_q_start
;
702 /* Copy out data and progress offset. */
703 memcpy(buf
, sc
->gkb_q
+ sc
->gkb_q_start
, len
);
704 sc
->gkb_q_start
= (sc
->gkb_q_start
+ len
) % KB_QSIZE
;
705 sc
->gkb_q_length
-= len
;
707 lwkt_reltoken(&tty_token
);
711 static kbd_callback_func_t genkbd_event
;
714 genkbdopen(struct dev_open_args
*ap
)
716 cdev_t dev
= ap
->a_head
.a_dev
;
722 lwkt_gettoken(&tty_token
);
724 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
725 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
726 lwkt_reltoken(&tty_token
);
730 i
= kbd_allocate(kbd
->kb_name
, kbd
->kb_unit
, sc
,
733 lwkt_reltoken(&tty_token
);
737 /* assert(i == kbd->kb_index) */
738 /* assert(kbd == kbd_get_keyboard(i)) */
741 * NOTE: even when we have successfully claimed a keyboard,
742 * the device may still be missing (!KBD_HAS_DEVICE(kbd)).
745 sc
->gkb_q_length
= 0;
746 lwkt_reltoken(&tty_token
);
753 genkbdclose(struct dev_close_args
*ap
)
755 cdev_t dev
= ap
->a_head
.a_dev
;
760 * NOTE: the device may have already become invalid.
761 * kbd == NULL || !KBD_IS_VALID(kbd)
764 lwkt_gettoken(&tty_token
);
766 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
767 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
768 /* XXX: we shall be forgiving and don't report error... */
770 kbd_release(kbd
, sc
);
772 lwkt_reltoken(&tty_token
);
778 genkbdread(struct dev_read_args
*ap
)
780 cdev_t dev
= ap
->a_head
.a_dev
;
781 struct uio
*uio
= ap
->a_uio
;
784 u_char buffer
[KB_BUFSIZE
];
790 lwkt_gettoken(&tty_token
);
792 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
793 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
794 lwkt_reltoken(&tty_token
);
798 while (sc
->gkb_q_length
== 0) {
799 if (ap
->a_ioflag
& IO_NDELAY
) { /* O_NONBLOCK? */
800 lwkt_reltoken(&tty_token
);
804 sc
->gkb_flags
|= KB_ASLEEP
;
805 error
= tsleep((caddr_t
)sc
, PCATCH
, "kbdrea", 0);
806 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
807 if ((kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
808 lwkt_reltoken(&tty_token
);
810 return ENXIO
; /* our keyboard has gone... */
813 sc
->gkb_flags
&= ~KB_ASLEEP
;
814 lwkt_reltoken(&tty_token
);
819 lwkt_reltoken(&tty_token
);
822 /* copy as much input as possible */
824 while (uio
->uio_resid
> 0) {
825 len
= (int)szmin(uio
->uio_resid
, sizeof(buffer
));
826 len
= genkbd_getc(sc
, buffer
, len
);
829 error
= uiomove(buffer
, (size_t)len
, uio
);
838 genkbdwrite(struct dev_write_args
*ap
)
840 cdev_t dev
= ap
->a_head
.a_dev
;
843 lwkt_gettoken(&tty_token
);
844 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
845 if ((kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
846 lwkt_reltoken(&tty_token
);
849 lwkt_reltoken(&tty_token
);
854 genkbdioctl(struct dev_ioctl_args
*ap
)
856 cdev_t dev
= ap
->a_head
.a_dev
;
860 lwkt_gettoken(&tty_token
);
861 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
862 if ((kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
863 lwkt_reltoken(&tty_token
);
866 error
= kbd_ioctl(kbd
, ap
->a_cmd
, ap
->a_data
);
867 if (error
== ENOIOCTL
)
870 lwkt_reltoken(&tty_token
);
874 static struct filterops genkbdfiltops
=
875 { FILTEROP_ISFD
, NULL
, genkbdfiltdetach
, genkbdfilter
};
878 genkbdkqfilter(struct dev_kqfilter_args
*ap
)
880 cdev_t dev
= ap
->a_head
.a_dev
;
881 struct knote
*kn
= ap
->a_kn
;
887 switch (kn
->kn_filter
) {
889 kn
->kn_fop
= &genkbdfiltops
;
890 kn
->kn_hook
= (caddr_t
)dev
;
893 ap
->a_result
= EOPNOTSUPP
;
898 klist
= &sc
->gkb_rkq
.ki_note
;
899 knote_insert(klist
, kn
);
905 genkbdfiltdetach(struct knote
*kn
)
907 cdev_t dev
= (cdev_t
)kn
->kn_hook
;
912 klist
= &sc
->gkb_rkq
.ki_note
;
913 knote_remove(klist
, kn
);
917 genkbdfilter(struct knote
*kn
, long hint
)
919 cdev_t dev
= (cdev_t
)kn
->kn_hook
;
925 lwkt_gettoken(&tty_token
);
927 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
928 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
929 /* The keyboard has gone */
930 kn
->kn_flags
|= (EV_EOF
| EV_NODATA
);
933 if (sc
->gkb_q_length
> 0)
936 lwkt_reltoken(&tty_token
);
943 genkbd_event(keyboard_t
*kbd
, int event
, void *arg
)
951 lwkt_gettoken(&tty_token
);
952 /* assert(KBD_IS_VALID(kbd)) */
953 sc
= (genkbd_softc_t
)arg
;
958 case KBDIO_UNLOADING
:
959 /* the keyboard is going... */
960 kbd_release(kbd
, sc
);
961 if (sc
->gkb_flags
& KB_ASLEEP
) {
962 sc
->gkb_flags
&= ~KB_ASLEEP
;
965 KNOTE(&sc
->gkb_rkq
.ki_note
, 0);
966 lwkt_reltoken(&tty_token
);
969 lwkt_reltoken(&tty_token
);
973 /* obtain the current key input mode */
974 if (kbd_ioctl(kbd
, KDGKBMODE
, (caddr_t
)&mode
))
977 /* read all pending input */
978 while (kbd_check_char(kbd
)) {
979 c
= kbd_read_char(kbd
, FALSE
);
982 if (c
== ERRKEY
) /* XXX: ring bell? */
984 if (!KBD_IS_BUSY(kbd
))
985 /* the device is not open, discard the input */
988 /* store the byte as is for K_RAW and K_CODE modes */
989 if (mode
!= K_XLATE
) {
990 genkbd_putc(sc
, KEYCHAR(c
));
995 if (c
& RELKEY
) /* key release is ignored */
998 /* process special keys; most of them are just ignored... */
1000 switch (KEYCHAR(c
)) {
1002 /* ignore them... */
1004 case BTAB
: /* a backtab: ESC [ Z */
1005 genkbd_putc(sc
, 0x1b);
1006 genkbd_putc(sc
, '[');
1007 genkbd_putc(sc
, 'Z');
1012 /* normal chars, normal chars with the META, function keys */
1013 switch (KEYFLAGS(c
)) {
1014 case 0: /* a normal char */
1015 genkbd_putc(sc
, KEYCHAR(c
));
1017 case MKEY
: /* the META flag: prepend ESC */
1018 genkbd_putc(sc
, 0x1b);
1019 genkbd_putc(sc
, KEYCHAR(c
));
1021 case FKEY
| SPCLKEY
: /* a function key, return string */
1022 cp
= kbd_get_fkeystr(kbd
, KEYCHAR(c
), &len
);
1025 genkbd_putc(sc
, *cp
++);
1031 /* wake up sleeping/polling processes */
1032 if (sc
->gkb_q_length
> 0) {
1033 if (sc
->gkb_flags
& KB_ASLEEP
) {
1034 sc
->gkb_flags
&= ~KB_ASLEEP
;
1035 wakeup((caddr_t
)sc
);
1037 KNOTE(&sc
->gkb_rkq
.ki_note
, 0);
1040 lwkt_reltoken(&tty_token
);
1044 #endif /* KBD_INSTALL_CDEV */
1047 * Generic low-level keyboard functions
1048 * The low-level functions in the keyboard subdriver may use these
1053 genkbd_commonioctl(keyboard_t
*kbd
, u_long cmd
, caddr_t arg
)
1060 lwkt_gettoken(&tty_token
);
1063 case KDGKBINFO
: /* get keyboard information */
1064 ((keyboard_info_t
*)arg
)->kb_index
= kbd
->kb_index
;
1065 i
= imin(strlen(kbd
->kb_name
) + 1,
1066 sizeof(((keyboard_info_t
*)arg
)->kb_name
));
1067 bcopy(kbd
->kb_name
, ((keyboard_info_t
*)arg
)->kb_name
, i
);
1068 ((keyboard_info_t
*)arg
)->kb_unit
= kbd
->kb_unit
;
1069 ((keyboard_info_t
*)arg
)->kb_type
= kbd
->kb_type
;
1070 ((keyboard_info_t
*)arg
)->kb_config
= kbd
->kb_config
;
1071 ((keyboard_info_t
*)arg
)->kb_flags
= kbd
->kb_flags
;
1074 case KDGKBTYPE
: /* get keyboard type */
1075 *(int *)arg
= kbd
->kb_type
;
1078 case KDGETREPEAT
: /* get keyboard repeat rate */
1079 ((int *)arg
)[0] = kbd
->kb_delay1
;
1080 ((int *)arg
)[1] = kbd
->kb_delay2
;
1083 case GIO_KEYMAP
: /* get keyboard translation table */
1084 bcopy(kbd
->kb_keymap
, arg
, sizeof(*kbd
->kb_keymap
));
1086 case PIO_KEYMAP
: /* set keyboard translation table */
1087 #ifndef KBD_DISABLE_KEYMAP_LOAD
1088 bzero(kbd
->kb_accentmap
, sizeof(*kbd
->kb_accentmap
));
1089 bcopy(arg
, kbd
->kb_keymap
, sizeof(*kbd
->kb_keymap
));
1092 lwkt_reltoken(&tty_token
);
1097 case GIO_KEYMAPENT
: /* get keyboard translation table entry */
1098 keyp
= (keyarg_t
*)arg
;
1099 if (keyp
->keynum
>= sizeof(kbd
->kb_keymap
->key
)
1100 /sizeof(kbd
->kb_keymap
->key
[0])) {
1101 lwkt_reltoken(&tty_token
);
1105 bcopy(&kbd
->kb_keymap
->key
[keyp
->keynum
], &keyp
->key
,
1108 case PIO_KEYMAPENT
: /* set keyboard translation table entry */
1109 #ifndef KBD_DISABLE_KEYMAP_LOAD
1110 keyp
= (keyarg_t
*)arg
;
1111 if (keyp
->keynum
>= sizeof(kbd
->kb_keymap
->key
)
1112 /sizeof(kbd
->kb_keymap
->key
[0])) {
1113 lwkt_reltoken(&tty_token
);
1117 bcopy(&keyp
->key
, &kbd
->kb_keymap
->key
[keyp
->keynum
],
1121 lwkt_reltoken(&tty_token
);
1126 case GIO_DEADKEYMAP
: /* get accent key translation table */
1127 bcopy(kbd
->kb_accentmap
, arg
, sizeof(*kbd
->kb_accentmap
));
1129 case PIO_DEADKEYMAP
: /* set accent key translation table */
1130 #ifndef KBD_DISABLE_KEYMAP_LOAD
1131 bcopy(arg
, kbd
->kb_accentmap
, sizeof(*kbd
->kb_accentmap
));
1134 lwkt_reltoken(&tty_token
);
1139 case GETFKEY
: /* get functionkey string */
1140 fkeyp
= (fkeyarg_t
*)arg
;
1141 if (fkeyp
->keynum
>= kbd
->kb_fkeytab_size
) {
1142 lwkt_reltoken(&tty_token
);
1146 bcopy(kbd
->kb_fkeytab
[fkeyp
->keynum
].str
, fkeyp
->keydef
,
1147 kbd
->kb_fkeytab
[fkeyp
->keynum
].len
);
1148 fkeyp
->flen
= kbd
->kb_fkeytab
[fkeyp
->keynum
].len
;
1150 case SETFKEY
: /* set functionkey string */
1151 #ifndef KBD_DISABLE_KEYMAP_LOAD
1152 fkeyp
= (fkeyarg_t
*)arg
;
1153 if (fkeyp
->keynum
>= kbd
->kb_fkeytab_size
) {
1154 lwkt_reltoken(&tty_token
);
1158 kbd
->kb_fkeytab
[fkeyp
->keynum
].len
= imin(fkeyp
->flen
, MAXFK
);
1159 bcopy(fkeyp
->keydef
, kbd
->kb_fkeytab
[fkeyp
->keynum
].str
,
1160 kbd
->kb_fkeytab
[fkeyp
->keynum
].len
);
1163 lwkt_reltoken(&tty_token
);
1169 lwkt_reltoken(&tty_token
);
1174 lwkt_reltoken(&tty_token
);
1179 /* get a pointer to the string associated with the given function key */
1181 genkbd_get_fkeystr(keyboard_t
*kbd
, int fkey
, size_t *len
)
1188 lwkt_gettoken(&tty_token
);
1190 if (fkey
> kbd
->kb_fkeytab_size
) {
1191 lwkt_reltoken(&tty_token
);
1194 *len
= kbd
->kb_fkeytab
[fkey
].len
;
1195 ch
= kbd
->kb_fkeytab
[fkey
].str
;
1197 lwkt_reltoken(&tty_token
);
1201 /* diagnostic dump */
1203 get_kbd_type_name(int type
)
1210 { KB_101
, "AT 101/102" },
1211 { KB_OTHER
, "generic" },
1215 for (i
= 0; i
< NELEM(name_table
); ++i
) {
1216 if (type
== name_table
[i
].type
)
1217 return name_table
[i
].name
;
1223 genkbd_diag(keyboard_t
*kbd
, int level
)
1226 kprintf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x",
1227 kbd
->kb_index
, kbd
->kb_name
, kbd
->kb_unit
,
1228 get_kbd_type_name(kbd
->kb_type
), kbd
->kb_type
,
1229 kbd
->kb_config
, kbd
->kb_flags
);
1230 if (kbd
->kb_io_base
> 0)
1231 kprintf(", port:0x%x-0x%x", kbd
->kb_io_base
,
1232 kbd
->kb_io_base
+ kbd
->kb_io_size
- 1);
1237 #define set_lockkey_state(k, s, l) \
1238 if (!((s) & l ## DOWN)) { \
1242 i = (s) & LOCK_MASK; \
1243 kbd_ioctl((k), KDSETLED, (caddr_t)&i); \
1247 save_accent_key(keyboard_t
*kbd
, u_int key
, int *accents
)
1251 lwkt_gettoken(&tty_token
);
1252 /* make an index into the accent map */
1253 i
= key
- F_ACC
+ 1;
1254 if ((i
> kbd
->kb_accentmap
->n_accs
)
1255 || (kbd
->kb_accentmap
->acc
[i
- 1].accchar
== 0)) {
1256 /* the index is out of range or pointing to an empty entry */
1258 lwkt_reltoken(&tty_token
);
1263 * If the same accent key has been hit twice, produce the accent char
1266 if (i
== *accents
) {
1267 key
= kbd
->kb_accentmap
->acc
[i
- 1].accchar
;
1269 lwkt_reltoken(&tty_token
);
1273 /* remember the index and wait for the next key */
1275 lwkt_reltoken(&tty_token
);
1280 make_accent_char(keyboard_t
*kbd
, u_int ch
, int *accents
)
1285 lwkt_gettoken(&tty_token
);
1286 acc
= &kbd
->kb_accentmap
->acc
[*accents
- 1];
1290 * If the accent key is followed by the space key,
1291 * produce the accent char itself.
1294 lwkt_reltoken(&tty_token
);
1295 return acc
->accchar
;
1298 /* scan the accent map */
1299 for (i
= 0; i
< NUM_ACCENTCHARS
; ++i
) {
1300 if (acc
->map
[i
][0] == 0) /* end of table */
1302 if (acc
->map
[i
][0] == ch
) {
1303 lwkt_reltoken(&tty_token
);
1304 return acc
->map
[i
][1];
1307 lwkt_reltoken(&tty_token
);
1308 /* this char cannot be accented... */
1313 genkbd_keyaction(keyboard_t
*kbd
, int keycode
, int up
, int *shiftstate
,
1316 struct keyent_t
*key
;
1317 int state
= *shiftstate
;
1322 lwkt_gettoken(&tty_token
);
1324 f
= state
& (AGRS
| ALKED
);
1325 if ((f
== AGRS1
) || (f
== AGRS2
) || (f
== ALKED
))
1327 key
= &kbd
->kb_keymap
->key
[i
];
1328 i
= ((state
& SHIFTS
) ? 1 : 0)
1329 | ((state
& CTLS
) ? 2 : 0)
1330 | ((state
& ALTS
) ? 4 : 0);
1331 if (((key
->flgs
& FLAG_LOCK_C
) && (state
& CLKED
))
1332 || ((key
->flgs
& FLAG_LOCK_N
) && (state
& NLKED
)) )
1335 if (up
) { /* break: key released */
1336 action
= kbd
->kb_lastact
[keycode
];
1337 kbd
->kb_lastact
[keycode
] = NOP
;
1340 if (state
& SHIFTAON
) {
1341 set_lockkey_state(kbd
, state
, ALK
);
1350 if (state
& SHIFTAON
) {
1351 set_lockkey_state(kbd
, state
, ALK
);
1360 if (state
& SHIFTAON
) {
1361 set_lockkey_state(kbd
, state
, ALK
);
1370 if (state
& SHIFTAON
) {
1371 set_lockkey_state(kbd
, state
, ALK
);
1380 if (state
& SHIFTAON
) {
1381 set_lockkey_state(kbd
, state
, ALK
);
1390 if (state
& SHIFTAON
) {
1391 set_lockkey_state(kbd
, state
, ALK
);
1418 /* release events of regular keys are not reported */
1419 *shiftstate
&= ~SHIFTAON
;
1420 lwkt_reltoken(&tty_token
);
1423 *shiftstate
= state
& ~SHIFTAON
;
1424 lwkt_reltoken(&tty_token
);
1425 return (SPCLKEY
| RELKEY
| action
);
1426 } else { /* make: key pressed */
1427 action
= key
->map
[i
];
1429 if (key
->spcl
& (0x80 >> i
)) {
1431 if (kbd
->kb_lastact
[keycode
] == NOP
)
1432 kbd
->kb_lastact
[keycode
] = action
;
1433 if (kbd
->kb_lastact
[keycode
] != action
)
1438 set_lockkey_state(kbd
, state
, NLK
);
1441 set_lockkey_state(kbd
, state
, CLK
);
1444 set_lockkey_state(kbd
, state
, SLK
);
1447 set_lockkey_state(kbd
, state
, ALK
);
1449 /* NON-LOCKING KEYS */
1450 case SPSC
: case RBT
: case SUSP
: case STBY
:
1451 case DBG
: case NEXT
: case PREV
: case PNC
:
1452 case HALT
: case PDWN
:
1508 *shiftstate
= state
;
1509 lwkt_reltoken(&tty_token
);
1512 /* is this an accent (dead) key? */
1513 *shiftstate
= state
;
1514 if (action
>= F_ACC
&& action
<= L_ACC
) {
1515 action
= save_accent_key(kbd
, action
,
1520 lwkt_reltoken(&tty_token
);
1523 if (state
& METAS
) {
1524 lwkt_reltoken(&tty_token
);
1525 return (action
| MKEY
);
1527 lwkt_reltoken(&tty_token
);
1533 /* other special keys */
1536 lwkt_reltoken(&tty_token
);
1539 if (action
>= F_FN
&& action
<= L_FN
)
1541 /* XXX: return fkey string for the FKEY? */
1542 lwkt_reltoken(&tty_token
);
1543 return (SPCLKEY
| action
);
1545 *shiftstate
= state
;
1546 lwkt_reltoken(&tty_token
);
1547 return (SPCLKEY
| action
);
1550 kbd
->kb_lastact
[keycode
] = NOP
;
1551 *shiftstate
= state
;
1553 /* make an accented char */
1554 action
= make_accent_char(kbd
, action
, accents
);
1555 if (action
== ERRKEY
) {
1556 lwkt_reltoken(&tty_token
);
1562 lwkt_reltoken(&tty_token
);
1567 lwkt_reltoken(&tty_token
);