2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
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.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD: src/sys/dev/kbd/kbd.c,v 1.17.2.2 2001/07/30 16:46:43 yokota Exp $
27 * $DragonFly: src/sys/dev/misc/kbd/kbd.c,v 1.23 2007/05/08 02:31:39 dillon Exp $
30 * Generic keyboard driver.
32 * Interrupt note: keyboards use clist functions and since usb keyboard
33 * interrupts are not protected by spltty(), we must use a critical section
34 * to protect against corruption.
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
47 #include <sys/vnode.h>
49 #include <sys/thread.h>
50 #include <sys/thread2.h>
52 #include <machine/console.h>
56 #define KBD_INDEX(dev) minor(dev)
59 int gkb_flags
; /* flag/status bits */
60 #define KB_ASLEEP (1 << 0)
61 struct clist gkb_q
; /* input queue */
62 struct selinfo gkb_rsel
;
65 typedef struct genkbd_softc
*genkbd_softc_t
;
67 static SLIST_HEAD(, keyboard_driver
) keyboard_drivers
=
68 SLIST_HEAD_INITIALIZER(keyboard_drivers
);
70 SET_DECLARE(kbddriver_set
, const keyboard_driver_t
);
75 * We need at least one entry each in order to initialize a keyboard
76 * for the kernel console. The arrays will be increased dynamically
80 static int keyboards
= 1;
81 static keyboard_t
*kbd_ini
;
82 static keyboard_t
**keyboard
= &kbd_ini
;
83 static keyboard_switch_t
*kbdsw_ini
;
84 keyboard_switch_t
**kbdsw
= &kbdsw_ini
;
89 kbd_realloc_array(void)
92 keyboard_switch_t
**new_kbdsw
;
95 newsize
= ((keyboards
+ ARRAY_DELTA
)/ARRAY_DELTA
)*ARRAY_DELTA
;
96 new_kbd
= kmalloc(sizeof(*new_kbd
) * newsize
, M_DEVBUF
,
98 new_kbdsw
= kmalloc(sizeof(*new_kbdsw
) * newsize
, M_DEVBUF
,
100 bcopy(keyboard
, new_kbd
, sizeof(*keyboard
)*keyboards
);
101 bcopy(kbdsw
, new_kbdsw
, sizeof(*kbdsw
)*keyboards
);
104 kfree(keyboard
, M_DEVBUF
);
105 kfree(kbdsw
, M_DEVBUF
);
113 kprintf("kbd: new array size %d\n", keyboards
);
119 * Low-level keyboard driver functions.
121 * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard
122 * driver, call these functions to initialize the keyboard_t structure
123 * and register it to the virtual keyboard driver `kbd'.
125 * The reinit call is made when a driver has partially detached a keyboard
126 * but does not unregistered it, then wishes to reinitialize it later on.
127 * This is how the USB keyboard driver handles the 'default' keyboard,
128 * because unregistering the keyboard associated with the console will
129 * destroy its console association forever.
132 kbd_reinit_struct(keyboard_t
*kbd
, int config
, int pref
)
134 kbd
->kb_flags
|= KB_NO_DEVICE
; /* device has not been found */
135 kbd
->kb_config
= config
& ~KB_CONF_PROBE_ONLY
;
136 kbd
->kb_led
= 0; /* unknown */
138 kbd
->kb_keymap
= NULL
;
139 kbd
->kb_accentmap
= NULL
;
140 kbd
->kb_fkeytab
= NULL
;
141 kbd
->kb_fkeytab_size
= 0;
142 kbd
->kb_delay1
= KB_DELAY1
; /* these values are advisory only */
143 kbd
->kb_delay2
= KB_DELAY2
;
146 bzero(kbd
->kb_lastact
, sizeof(kbd
->kb_lastact
));
149 /* initialize the keyboard_t structure */
151 kbd_init_struct(keyboard_t
*kbd
, char *name
, int type
, int unit
, int config
,
152 int pref
, int port
, int port_size
)
158 kbd
->kb_io_base
= port
;
159 kbd
->kb_io_size
= port_size
;
160 kbd_reinit_struct(kbd
, config
, pref
);
164 kbd_set_maps(keyboard_t
*kbd
, keymap_t
*keymap
, accentmap_t
*accmap
,
165 fkeytab_t
*fkeymap
, int fkeymap_size
)
167 kbd
->kb_keymap
= keymap
;
168 kbd
->kb_accentmap
= accmap
;
169 kbd
->kb_fkeytab
= fkeymap
;
170 kbd
->kb_fkeytab_size
= fkeymap_size
;
173 /* declare a new keyboard driver */
175 kbd_add_driver(keyboard_driver_t
*driver
)
177 if (SLIST_NEXT(driver
, link
))
179 SLIST_INSERT_HEAD(&keyboard_drivers
, driver
, link
);
184 kbd_delete_driver(keyboard_driver_t
*driver
)
186 SLIST_REMOVE(&keyboard_drivers
, driver
, keyboard_driver
, link
);
187 SLIST_NEXT(driver
, link
) = NULL
;
191 /* register a keyboard and associate it with a function table */
193 kbd_register(keyboard_t
*kbd
)
195 const keyboard_driver_t
**list
;
196 const keyboard_driver_t
*p
;
199 for (index
= 0; index
< keyboards
; ++index
) {
200 if (keyboard
[index
] == NULL
)
203 if (index
>= keyboards
) {
204 if (kbd_realloc_array())
208 kbd
->kb_index
= index
;
211 kbd
->kb_active
= 0; /* disabled until someone calls kbd_enable() */
212 kbd
->kb_token
= NULL
;
213 kbd
->kb_callback
.kc_func
= NULL
;
214 kbd
->kb_callback
.kc_arg
= NULL
;
215 callout_init(&kbd
->kb_atkbd_timeout_ch
);
217 SLIST_FOREACH(p
, &keyboard_drivers
, link
) {
218 if (strcmp(p
->name
, kbd
->kb_name
) == 0) {
219 keyboard
[index
] = kbd
;
220 kbdsw
[index
] = p
->kbdsw
;
224 SET_FOREACH(list
, kbddriver_set
) {
226 if (strcmp(p
->name
, kbd
->kb_name
) == 0) {
227 keyboard
[index
] = kbd
;
228 kbdsw
[index
] = p
->kbdsw
;
237 kbd_unregister(keyboard_t
*kbd
)
241 if ((kbd
->kb_index
< 0) || (kbd
->kb_index
>= keyboards
))
243 if (keyboard
[kbd
->kb_index
] != kbd
)
247 callout_stop(&kbd
->kb_atkbd_timeout_ch
);
248 if (KBD_IS_BUSY(kbd
)) {
249 error
= (*kbd
->kb_callback
.kc_func
)(kbd
, KBDIO_UNLOADING
,
250 kbd
->kb_callback
.kc_arg
);
255 if (KBD_IS_BUSY(kbd
)) {
261 keyboard
[kbd
->kb_index
] = NULL
;
262 kbdsw
[kbd
->kb_index
] = NULL
;
268 /* find a funciton table by the driver name */
270 kbd_get_switch(char *driver
)
272 const keyboard_driver_t
**list
;
273 const keyboard_driver_t
*p
;
275 SLIST_FOREACH(p
, &keyboard_drivers
, link
) {
276 if (strcmp(p
->name
, driver
) == 0)
279 SET_FOREACH(list
, kbddriver_set
) {
281 if (strcmp(p
->name
, driver
) == 0)
289 * Keyboard client functions
290 * Keyboard clients, such as the console driver `syscons' and the keyboard
291 * cdev driver, use these functions to claim and release a keyboard for
295 /* find the keyboard specified by a driver name and a unit number */
297 kbd_find_keyboard(char *driver
, int unit
)
306 for (i
= 0; i
< keyboards
; ++i
) {
307 if (keyboard
[i
] == NULL
)
309 if (!KBD_IS_VALID(keyboard
[i
]))
311 if (strcmp("*", driver
) && strcmp(keyboard
[i
]->kb_name
, driver
))
313 if ((unit
!= -1) && (keyboard
[i
]->kb_unit
!= unit
))
315 if (pref
<= keyboard
[i
]->kb_pref
) {
316 pref
= keyboard
[i
]->kb_pref
;
323 /* allocate a keyboard */
325 kbd_allocate(char *driver
, int unit
, void *id
, kbd_callback_func_t
*func
,
334 index
= kbd_find_keyboard(driver
, unit
);
336 if (KBD_IS_BUSY(keyboard
[index
])) {
340 keyboard
[index
]->kb_token
= id
;
341 KBD_BUSY(keyboard
[index
]);
342 keyboard
[index
]->kb_callback
.kc_func
= func
;
343 keyboard
[index
]->kb_callback
.kc_arg
= arg
;
344 (*kbdsw
[index
]->clear_state
)(keyboard
[index
]);
351 kbd_release(keyboard_t
*kbd
, void *id
)
356 if (!KBD_IS_VALID(kbd
) || !KBD_IS_BUSY(kbd
)) {
358 } else if (kbd
->kb_token
!= id
) {
361 kbd
->kb_token
= NULL
;
363 kbd
->kb_callback
.kc_func
= NULL
;
364 kbd
->kb_callback
.kc_arg
= NULL
;
365 (*kbdsw
[kbd
->kb_index
]->clear_state
)(kbd
);
373 kbd_change_callback(keyboard_t
*kbd
, void *id
, kbd_callback_func_t
*func
,
379 if (!KBD_IS_VALID(kbd
) || !KBD_IS_BUSY(kbd
)) {
381 } else if (kbd
->kb_token
!= id
) {
383 } else if (func
== NULL
) {
386 kbd
->kb_callback
.kc_func
= func
;
387 kbd
->kb_callback
.kc_arg
= arg
;
394 /* get a keyboard structure */
396 kbd_get_keyboard(int index
)
398 if ((index
< 0) || (index
>= keyboards
))
400 if (keyboard
[index
] == NULL
)
402 if (!KBD_IS_VALID(keyboard
[index
]))
404 return keyboard
[index
];
408 * The back door for the console driver; configure keyboards
409 * This function is for the kernel console to initialize keyboards
410 * at very early stage.
414 kbd_configure(int flags
)
416 const keyboard_driver_t
**list
;
417 const keyboard_driver_t
*p
;
419 SLIST_FOREACH(p
, &keyboard_drivers
, link
) {
420 if (p
->configure
!= NULL
)
421 (*p
->configure
)(flags
);
423 SET_FOREACH(list
, kbddriver_set
) {
425 if (p
->configure
!= NULL
)
426 (*p
->configure
)(flags
);
432 #ifdef KBD_INSTALL_CDEV
435 * Virtual keyboard cdev driver functions
436 * The virtual keyboard driver dispatches driver functions to
437 * appropriate subdrivers.
440 #define KBD_UNIT(dev) minor(dev)
442 static d_open_t genkbdopen
;
443 static d_close_t genkbdclose
;
444 static d_read_t genkbdread
;
445 static d_write_t genkbdwrite
;
446 static d_ioctl_t genkbdioctl
;
447 static d_poll_t genkbdpoll
;
449 #define CDEV_MAJOR 112
451 static struct dev_ops kbd_ops
= {
452 { "kbd", CDEV_MAJOR
, 0 },
453 .d_open
= genkbdopen
,
454 .d_close
= genkbdclose
,
455 .d_read
= genkbdread
,
456 .d_write
= genkbdwrite
,
457 .d_ioctl
= genkbdioctl
,
458 .d_poll
= genkbdpoll
,
464 * NOTE: The usb driver does not detach the default keyboard if it is
465 * unplugged, but calls kbd_attach() when it is plugged back in.
468 kbd_attach(keyboard_t
*kbd
)
472 if (kbd
->kb_index
>= keyboards
)
474 if (keyboard
[kbd
->kb_index
] != kbd
)
477 if (kbd
->kb_dev
== NULL
) {
478 kbd
->kb_dev
= make_dev(&kbd_ops
, kbd
->kb_index
,
479 UID_ROOT
, GID_WHEEL
, 0600,
480 "kbd%r", kbd
->kb_index
);
483 if (dev
->si_drv1
== NULL
) {
484 dev
->si_drv1
= kmalloc(sizeof(struct genkbd_softc
), M_DEVBUF
,
487 bzero(dev
->si_drv1
, sizeof(struct genkbd_softc
));
489 kprintf("kbd%d at %s%d\n", kbd
->kb_index
, kbd
->kb_name
, kbd
->kb_unit
);
494 kbd_detach(keyboard_t
*kbd
)
498 if (kbd
->kb_index
>= keyboards
)
500 if (keyboard
[kbd
->kb_index
] != kbd
)
503 if ((dev
= kbd
->kb_dev
) != NULL
) {
505 kfree(dev
->si_drv1
, M_DEVBUF
);
510 dev_ops_remove_minor(&kbd_ops
, kbd
->kb_index
);
515 * Generic keyboard cdev driver functions
516 * Keyboard subdrivers may call these functions to implement common
521 #define KB_BUFSIZE 64
523 static kbd_callback_func_t genkbd_event
;
526 genkbdopen(struct dev_open_args
*ap
)
528 cdev_t dev
= ap
->a_head
.a_dev
;
535 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
536 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
540 i
= kbd_allocate(kbd
->kb_name
, kbd
->kb_unit
, sc
,
541 genkbd_event
, (void *)sc
);
546 /* assert(i == kbd->kb_index) */
547 /* assert(kbd == kbd_get_keyboard(i)) */
550 * NOTE: even when we have successfully claimed a keyboard,
551 * the device may still be missing (!KBD_HAS_DEVICE(kbd)).
555 bzero(&sc
->gkb_q
, sizeof(sc
->gkb_q
));
557 clist_alloc_cblocks(&sc
->gkb_q
, KB_QSIZE
, KB_QSIZE
/2); /* XXX */
558 sc
->gkb_rsel
.si_flags
= 0;
559 sc
->gkb_rsel
.si_pid
= 0;
566 genkbdclose(struct dev_close_args
*ap
)
568 cdev_t dev
= ap
->a_head
.a_dev
;
573 * NOTE: the device may have already become invalid.
574 * kbd == NULL || !KBD_IS_VALID(kbd)
578 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
579 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
580 /* XXX: we shall be forgiving and don't report error... */
582 kbd_release(kbd
, (void *)sc
);
584 clist_free_cblocks(&sc
->gkb_q
);
592 genkbdread(struct dev_read_args
*ap
)
594 cdev_t dev
= ap
->a_head
.a_dev
;
595 struct uio
*uio
= ap
->a_uio
;
598 u_char buffer
[KB_BUFSIZE
];
605 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
606 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
610 while (sc
->gkb_q
.c_cc
== 0) {
611 if (ap
->a_ioflag
& IO_NDELAY
) {
615 sc
->gkb_flags
|= KB_ASLEEP
;
616 error
= tsleep((caddr_t
)sc
, PCATCH
, "kbdrea", 0);
617 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
618 if ((kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
620 return ENXIO
; /* our keyboard has gone... */
623 sc
->gkb_flags
&= ~KB_ASLEEP
;
630 /* copy as much input as possible */
632 while (uio
->uio_resid
> 0) {
633 len
= (int)szmin(uio
->uio_resid
, sizeof(buffer
));
634 len
= q_to_b(&sc
->gkb_q
, buffer
, len
);
637 error
= uiomove(buffer
, (size_t)len
, uio
);
646 genkbdwrite(struct dev_write_args
*ap
)
648 cdev_t dev
= ap
->a_head
.a_dev
;
651 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
652 if ((kbd
== NULL
) || !KBD_IS_VALID(kbd
))
658 genkbdioctl(struct dev_ioctl_args
*ap
)
660 cdev_t dev
= ap
->a_head
.a_dev
;
664 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
665 if ((kbd
== NULL
) || !KBD_IS_VALID(kbd
))
667 error
= (*kbdsw
[kbd
->kb_index
]->ioctl
)(kbd
, ap
->a_cmd
, ap
->a_data
);
668 if (error
== ENOIOCTL
)
674 genkbdpoll(struct dev_poll_args
*ap
)
676 cdev_t dev
= ap
->a_head
.a_dev
;
684 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
685 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
686 revents
= POLLHUP
; /* the keyboard has gone */
687 } else if (ap
->a_events
& (POLLIN
| POLLRDNORM
)) {
688 if (sc
->gkb_q
.c_cc
> 0)
689 revents
= ap
->a_events
& (POLLIN
| POLLRDNORM
);
691 selrecord(curthread
, &sc
->gkb_rsel
);
694 ap
->a_events
= revents
;
699 genkbd_event(keyboard_t
*kbd
, int event
, void *arg
)
707 /* assert(KBD_IS_VALID(kbd)) */
708 sc
= (genkbd_softc_t
)arg
;
713 case KBDIO_UNLOADING
:
714 /* the keyboard is going... */
715 kbd_release(kbd
, (void *)sc
);
716 if (sc
->gkb_flags
& KB_ASLEEP
) {
717 sc
->gkb_flags
&= ~KB_ASLEEP
;
720 selwakeup(&sc
->gkb_rsel
);
726 /* obtain the current key input mode */
727 if ((*kbdsw
[kbd
->kb_index
]->ioctl
)(kbd
, KDGKBMODE
, (caddr_t
)&mode
))
730 /* read all pending input */
731 while ((*kbdsw
[kbd
->kb_index
]->check_char
)(kbd
)) {
732 c
= (*kbdsw
[kbd
->kb_index
]->read_char
)(kbd
, FALSE
);
735 if (c
== ERRKEY
) /* XXX: ring bell? */
737 if (!KBD_IS_BUSY(kbd
))
738 /* the device is not open, discard the input */
741 /* store the byte as is for K_RAW and K_CODE modes */
742 if (mode
!= K_XLATE
) {
743 clist_putc(KEYCHAR(c
), &sc
->gkb_q
);
748 if (c
& RELKEY
) /* key release is ignored */
751 /* process special keys; most of them are just ignored... */
753 switch (KEYCHAR(c
)) {
757 case BTAB
: /* a backtab: ESC [ Z */
758 clist_putc(0x1b, &sc
->gkb_q
);
759 clist_putc('[', &sc
->gkb_q
);
760 clist_putc('Z', &sc
->gkb_q
);
765 /* normal chars, normal chars with the META, function keys */
766 switch (KEYFLAGS(c
)) {
767 case 0: /* a normal char */
768 clist_putc(KEYCHAR(c
), &sc
->gkb_q
);
770 case MKEY
: /* the META flag: prepend ESC */
771 clist_putc(0x1b, &sc
->gkb_q
);
772 clist_putc(KEYCHAR(c
), &sc
->gkb_q
);
774 case FKEY
| SPCLKEY
: /* a function key, return string */
775 cp
= (*kbdsw
[kbd
->kb_index
]->get_fkeystr
)(kbd
,
779 clist_putc(*cp
++, &sc
->gkb_q
);
785 /* wake up sleeping/polling processes */
786 if (sc
->gkb_q
.c_cc
> 0) {
787 if (sc
->gkb_flags
& KB_ASLEEP
) {
788 sc
->gkb_flags
&= ~KB_ASLEEP
;
791 selwakeup(&sc
->gkb_rsel
);
797 #endif /* KBD_INSTALL_CDEV */
800 * Generic low-level keyboard functions
801 * The low-level functions in the keyboard subdriver may use these
806 genkbd_commonioctl(keyboard_t
*kbd
, u_long cmd
, caddr_t arg
)
815 case KDGKBINFO
: /* get keyboard information */
816 ((keyboard_info_t
*)arg
)->kb_index
= kbd
->kb_index
;
817 i
= imin(strlen(kbd
->kb_name
) + 1,
818 sizeof(((keyboard_info_t
*)arg
)->kb_name
));
819 bcopy(kbd
->kb_name
, ((keyboard_info_t
*)arg
)->kb_name
, i
);
820 ((keyboard_info_t
*)arg
)->kb_unit
= kbd
->kb_unit
;
821 ((keyboard_info_t
*)arg
)->kb_type
= kbd
->kb_type
;
822 ((keyboard_info_t
*)arg
)->kb_config
= kbd
->kb_config
;
823 ((keyboard_info_t
*)arg
)->kb_flags
= kbd
->kb_flags
;
826 case KDGKBTYPE
: /* get keyboard type */
827 *(int *)arg
= kbd
->kb_type
;
830 case KDGETREPEAT
: /* get keyboard repeat rate */
831 ((int *)arg
)[0] = kbd
->kb_delay1
;
832 ((int *)arg
)[1] = kbd
->kb_delay2
;
835 case GIO_KEYMAP
: /* get keyboard translation table */
836 bcopy(kbd
->kb_keymap
, arg
, sizeof(*kbd
->kb_keymap
));
838 case PIO_KEYMAP
: /* set keyboard translation table */
839 #ifndef KBD_DISABLE_KEYMAP_LOAD
840 bzero(kbd
->kb_accentmap
, sizeof(*kbd
->kb_accentmap
));
841 bcopy(arg
, kbd
->kb_keymap
, sizeof(*kbd
->kb_keymap
));
848 case GIO_KEYMAPENT
: /* get keyboard translation table entry */
849 keyp
= (keyarg_t
*)arg
;
850 if (keyp
->keynum
>= sizeof(kbd
->kb_keymap
->key
)
851 /sizeof(kbd
->kb_keymap
->key
[0])) {
855 bcopy(&kbd
->kb_keymap
->key
[keyp
->keynum
], &keyp
->key
,
858 case PIO_KEYMAPENT
: /* set keyboard translation table entry */
859 #ifndef KBD_DISABLE_KEYMAP_LOAD
860 keyp
= (keyarg_t
*)arg
;
861 if (keyp
->keynum
>= sizeof(kbd
->kb_keymap
->key
)
862 /sizeof(kbd
->kb_keymap
->key
[0])) {
866 bcopy(&keyp
->key
, &kbd
->kb_keymap
->key
[keyp
->keynum
],
874 case GIO_DEADKEYMAP
: /* get accent key translation table */
875 bcopy(kbd
->kb_accentmap
, arg
, sizeof(*kbd
->kb_accentmap
));
877 case PIO_DEADKEYMAP
: /* set accent key translation table */
878 #ifndef KBD_DISABLE_KEYMAP_LOAD
879 bcopy(arg
, kbd
->kb_accentmap
, sizeof(*kbd
->kb_accentmap
));
886 case GETFKEY
: /* get functionkey string */
887 fkeyp
= (fkeyarg_t
*)arg
;
888 if (fkeyp
->keynum
>= kbd
->kb_fkeytab_size
) {
892 bcopy(kbd
->kb_fkeytab
[fkeyp
->keynum
].str
, fkeyp
->keydef
,
893 kbd
->kb_fkeytab
[fkeyp
->keynum
].len
);
894 fkeyp
->flen
= kbd
->kb_fkeytab
[fkeyp
->keynum
].len
;
896 case SETFKEY
: /* set functionkey string */
897 #ifndef KBD_DISABLE_KEYMAP_LOAD
898 fkeyp
= (fkeyarg_t
*)arg
;
899 if (fkeyp
->keynum
>= kbd
->kb_fkeytab_size
) {
903 kbd
->kb_fkeytab
[fkeyp
->keynum
].len
= imin(fkeyp
->flen
, MAXFK
);
904 bcopy(fkeyp
->keydef
, kbd
->kb_fkeytab
[fkeyp
->keynum
].str
,
905 kbd
->kb_fkeytab
[fkeyp
->keynum
].len
);
921 /* get a pointer to the string associated with the given function key */
923 genkbd_get_fkeystr(keyboard_t
*kbd
, int fkey
, size_t *len
)
928 if (fkey
> kbd
->kb_fkeytab_size
)
930 *len
= kbd
->kb_fkeytab
[fkey
].len
;
931 return kbd
->kb_fkeytab
[fkey
].str
;
934 /* diagnostic dump */
936 get_kbd_type_name(int type
)
943 { KB_101
, "AT 101/102" },
944 { KB_OTHER
, "generic" },
948 for (i
= 0; i
< sizeof(name_table
)/sizeof(name_table
[0]); ++i
) {
949 if (type
== name_table
[i
].type
)
950 return name_table
[i
].name
;
956 genkbd_diag(keyboard_t
*kbd
, int level
)
959 kprintf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x",
960 kbd
->kb_index
, kbd
->kb_name
, kbd
->kb_unit
,
961 get_kbd_type_name(kbd
->kb_type
), kbd
->kb_type
,
962 kbd
->kb_config
, kbd
->kb_flags
);
963 if (kbd
->kb_io_base
> 0)
964 kprintf(", port:0x%x-0x%x", kbd
->kb_io_base
,
965 kbd
->kb_io_base
+ kbd
->kb_io_size
- 1);
970 #define set_lockkey_state(k, s, l) \
971 if (!((s) & l ## DOWN)) { \
975 i = (s) & LOCK_MASK; \
976 (*kbdsw[(k)->kb_index]->ioctl)((k), KDSETLED, (caddr_t)&i); \
980 save_accent_key(keyboard_t
*kbd
, u_int key
, int *accents
)
984 /* make an index into the accent map */
986 if ((i
> kbd
->kb_accentmap
->n_accs
)
987 || (kbd
->kb_accentmap
->acc
[i
- 1].accchar
== 0)) {
988 /* the index is out of range or pointing to an empty entry */
994 * If the same accent key has been hit twice, produce the accent char
998 key
= kbd
->kb_accentmap
->acc
[i
- 1].accchar
;
1003 /* remember the index and wait for the next key */
1009 make_accent_char(keyboard_t
*kbd
, u_int ch
, int *accents
)
1014 acc
= &kbd
->kb_accentmap
->acc
[*accents
- 1];
1018 * If the accent key is followed by the space key,
1019 * produce the accent char itself.
1022 return acc
->accchar
;
1024 /* scan the accent map */
1025 for (i
= 0; i
< NUM_ACCENTCHARS
; ++i
) {
1026 if (acc
->map
[i
][0] == 0) /* end of table */
1028 if (acc
->map
[i
][0] == ch
)
1029 return acc
->map
[i
][1];
1031 /* this char cannot be accented... */
1036 genkbd_keyaction(keyboard_t
*kbd
, int keycode
, int up
, int *shiftstate
,
1039 struct keyent_t
*key
;
1040 int state
= *shiftstate
;
1046 f
= state
& (AGRS
| ALKED
);
1047 if ((f
== AGRS1
) || (f
== AGRS2
) || (f
== ALKED
))
1049 key
= &kbd
->kb_keymap
->key
[i
];
1050 i
= ((state
& SHIFTS
) ? 1 : 0)
1051 | ((state
& CTLS
) ? 2 : 0)
1052 | ((state
& ALTS
) ? 4 : 0);
1053 if (((key
->flgs
& FLAG_LOCK_C
) && (state
& CLKED
))
1054 || ((key
->flgs
& FLAG_LOCK_N
) && (state
& NLKED
)) )
1057 if (up
) { /* break: key released */
1058 action
= kbd
->kb_lastact
[keycode
];
1059 kbd
->kb_lastact
[keycode
] = NOP
;
1062 if (state
& SHIFTAON
) {
1063 set_lockkey_state(kbd
, state
, ALK
);
1072 if (state
& SHIFTAON
) {
1073 set_lockkey_state(kbd
, state
, ALK
);
1082 if (state
& SHIFTAON
) {
1083 set_lockkey_state(kbd
, state
, ALK
);
1092 if (state
& SHIFTAON
) {
1093 set_lockkey_state(kbd
, state
, ALK
);
1102 if (state
& SHIFTAON
) {
1103 set_lockkey_state(kbd
, state
, ALK
);
1112 if (state
& SHIFTAON
) {
1113 set_lockkey_state(kbd
, state
, ALK
);
1140 /* release events of regular keys are not reported */
1141 *shiftstate
&= ~SHIFTAON
;
1144 *shiftstate
= state
& ~SHIFTAON
;
1145 return (SPCLKEY
| RELKEY
| action
);
1146 } else { /* make: key pressed */
1147 action
= key
->map
[i
];
1149 if (key
->spcl
& (0x80 >> i
)) {
1151 if (kbd
->kb_lastact
[keycode
] == NOP
)
1152 kbd
->kb_lastact
[keycode
] = action
;
1153 if (kbd
->kb_lastact
[keycode
] != action
)
1158 set_lockkey_state(kbd
, state
, NLK
);
1161 set_lockkey_state(kbd
, state
, CLK
);
1164 set_lockkey_state(kbd
, state
, SLK
);
1167 set_lockkey_state(kbd
, state
, ALK
);
1169 /* NON-LOCKING KEYS */
1170 case SPSC
: case RBT
: case SUSP
: case STBY
:
1171 case DBG
: case NEXT
: case PREV
: case PNC
:
1172 case HALT
: case PDWN
:
1228 *shiftstate
= state
;
1231 /* is this an accent (dead) key? */
1232 *shiftstate
= state
;
1233 if (action
>= F_ACC
&& action
<= L_ACC
) {
1234 action
= save_accent_key(kbd
, action
,
1242 return (action
| MKEY
);
1248 /* other special keys */
1253 if (action
>= F_FN
&& action
<= L_FN
)
1255 /* XXX: return fkey string for the FKEY? */
1256 return (SPCLKEY
| action
);
1258 *shiftstate
= state
;
1259 return (SPCLKEY
| action
);
1262 kbd
->kb_lastact
[keycode
] = NOP
;
1263 *shiftstate
= state
;
1265 /* make an accented char */
1266 action
= make_accent_char(kbd
, action
, accents
);
1267 if (action
== ERRKEY
)