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.
35 * XXX: this keyboard driver doesn't use clist functions anymore!
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
48 #include <sys/vnode.h>
50 #include <sys/thread.h>
51 #include <sys/thread2.h>
53 #include <machine/console.h>
57 #define KBD_INDEX(dev) minor(dev)
63 int gkb_flags
; /* flag/status bits */
64 #define KB_ASLEEP (1 << 0)
65 struct selinfo gkb_rsel
;
66 char gkb_q
[KB_QSIZE
]; /* input queue */
67 unsigned int gkb_q_start
;
68 unsigned int gkb_q_length
;
71 typedef struct genkbd_softc
*genkbd_softc_t
;
73 static SLIST_HEAD(, keyboard_driver
) keyboard_drivers
=
74 SLIST_HEAD_INITIALIZER(keyboard_drivers
);
76 SET_DECLARE(kbddriver_set
, const keyboard_driver_t
);
81 * We need at least one entry each in order to initialize a keyboard
82 * for the kernel console. The arrays will be increased dynamically
86 static int keyboards
= 1;
87 static keyboard_t
*kbd_ini
;
88 static keyboard_t
**keyboard
= &kbd_ini
;
89 static keyboard_switch_t
*kbdsw_ini
;
90 keyboard_switch_t
**kbdsw
= &kbdsw_ini
;
95 kbd_realloc_array(void)
98 keyboard_switch_t
**new_kbdsw
;
101 newsize
= ((keyboards
+ ARRAY_DELTA
)/ARRAY_DELTA
)*ARRAY_DELTA
;
102 new_kbd
= kmalloc(sizeof(*new_kbd
) * newsize
, M_DEVBUF
,
104 new_kbdsw
= kmalloc(sizeof(*new_kbdsw
) * newsize
, M_DEVBUF
,
106 bcopy(keyboard
, new_kbd
, sizeof(*keyboard
)*keyboards
);
107 bcopy(kbdsw
, new_kbdsw
, sizeof(*kbdsw
)*keyboards
);
110 kfree(keyboard
, M_DEVBUF
);
111 kfree(kbdsw
, M_DEVBUF
);
119 kprintf("kbd: new array size %d\n", keyboards
);
125 * Low-level keyboard driver functions.
127 * Keyboard subdrivers, such as the AT keyboard driver and the USB keyboard
128 * driver, call these functions to initialize the keyboard_t structure
129 * and register it to the virtual keyboard driver `kbd'.
131 * The reinit call is made when a driver has partially detached a keyboard
132 * but does not unregistered it, then wishes to reinitialize it later on.
133 * This is how the USB keyboard driver handles the 'default' keyboard,
134 * because unregistering the keyboard associated with the console will
135 * destroy its console association forever.
138 kbd_reinit_struct(keyboard_t
*kbd
, int config
, int pref
)
140 kbd
->kb_flags
|= KB_NO_DEVICE
; /* device has not been found */
141 kbd
->kb_config
= config
& ~KB_CONF_PROBE_ONLY
;
142 kbd
->kb_led
= 0; /* unknown */
144 kbd
->kb_keymap
= NULL
;
145 kbd
->kb_accentmap
= NULL
;
146 kbd
->kb_fkeytab
= NULL
;
147 kbd
->kb_fkeytab_size
= 0;
148 kbd
->kb_delay1
= KB_DELAY1
; /* these values are advisory only */
149 kbd
->kb_delay2
= KB_DELAY2
;
152 bzero(kbd
->kb_lastact
, sizeof(kbd
->kb_lastact
));
155 /* initialize the keyboard_t structure */
157 kbd_init_struct(keyboard_t
*kbd
, char *name
, int type
, int unit
, int config
,
158 int pref
, int port
, int port_size
)
164 kbd
->kb_io_base
= port
;
165 kbd
->kb_io_size
= port_size
;
166 kbd_reinit_struct(kbd
, config
, pref
);
170 kbd_set_maps(keyboard_t
*kbd
, keymap_t
*keymap
, accentmap_t
*accmap
,
171 fkeytab_t
*fkeymap
, int fkeymap_size
)
173 kbd
->kb_keymap
= keymap
;
174 kbd
->kb_accentmap
= accmap
;
175 kbd
->kb_fkeytab
= fkeymap
;
176 kbd
->kb_fkeytab_size
= fkeymap_size
;
179 /* declare a new keyboard driver */
181 kbd_add_driver(keyboard_driver_t
*driver
)
183 if (SLIST_NEXT(driver
, link
))
185 SLIST_INSERT_HEAD(&keyboard_drivers
, driver
, link
);
190 kbd_delete_driver(keyboard_driver_t
*driver
)
192 SLIST_REMOVE(&keyboard_drivers
, driver
, keyboard_driver
, link
);
193 SLIST_NEXT(driver
, link
) = NULL
;
197 /* register a keyboard and associate it with a function table */
199 kbd_register(keyboard_t
*kbd
)
201 const keyboard_driver_t
**list
;
202 const keyboard_driver_t
*p
;
207 mux
= kbd_get_keyboard(kbd_find_keyboard("kbdmux", -1));
209 for (index
= 0; index
< keyboards
; ++index
) {
210 if (keyboard
[index
] == NULL
)
213 if (index
>= keyboards
) {
214 if (kbd_realloc_array())
218 kbd
->kb_index
= index
;
221 kbd
->kb_active
= 0; /* disabled until someone calls kbd_enable() */
222 kbd
->kb_token
= NULL
;
223 kbd
->kb_callback
.kc_func
= NULL
;
224 kbd
->kb_callback
.kc_arg
= NULL
;
225 callout_init(&kbd
->kb_atkbd_timeout_ch
);
227 SLIST_FOREACH(p
, &keyboard_drivers
, link
) {
228 if (strcmp(p
->name
, kbd
->kb_name
) == 0) {
229 keyboard
[index
] = kbd
;
230 kbdsw
[index
] = p
->kbdsw
;
233 bzero(&ki
, sizeof(ki
));
234 strcpy(ki
.kb_name
, kbd
->kb_name
);
235 ki
.kb_unit
= kbd
->kb_unit
;
236 kbd_ioctl(mux
, KBADDKBD
, (caddr_t
) &ki
);
242 SET_FOREACH(list
, kbddriver_set
) {
244 if (strcmp(p
->name
, kbd
->kb_name
) == 0) {
245 keyboard
[index
] = kbd
;
246 kbdsw
[index
] = p
->kbdsw
;
249 bzero(&ki
, sizeof(ki
));
250 strcpy(ki
.kb_name
, kbd
->kb_name
);
251 ki
.kb_unit
= kbd
->kb_unit
;
252 kbd_ioctl(mux
, KBADDKBD
, (caddr_t
) &ki
);
263 kbd_unregister(keyboard_t
*kbd
)
267 if ((kbd
->kb_index
< 0) || (kbd
->kb_index
>= keyboards
))
269 if (keyboard
[kbd
->kb_index
] != kbd
)
273 callout_stop(&kbd
->kb_atkbd_timeout_ch
);
274 if (KBD_IS_BUSY(kbd
)) {
275 error
= (*kbd
->kb_callback
.kc_func
)(kbd
, KBDIO_UNLOADING
,
276 kbd
->kb_callback
.kc_arg
);
281 if (KBD_IS_BUSY(kbd
)) {
287 keyboard
[kbd
->kb_index
] = NULL
;
288 kbdsw
[kbd
->kb_index
] = NULL
;
294 /* find a funciton table by the driver name */
296 kbd_get_switch(char *driver
)
298 const keyboard_driver_t
**list
;
299 const keyboard_driver_t
*p
;
301 SLIST_FOREACH(p
, &keyboard_drivers
, link
) {
302 if (strcmp(p
->name
, driver
) == 0)
305 SET_FOREACH(list
, kbddriver_set
) {
307 if (strcmp(p
->name
, driver
) == 0)
315 * Keyboard client functions
316 * Keyboard clients, such as the console driver `syscons' and the keyboard
317 * cdev driver, use these functions to claim and release a keyboard for
321 * find the keyboard specified by a driver name and a unit number
322 * starting at given index
325 kbd_find_keyboard2(char *driver
, int unit
, int index
, int legacy
)
334 if ((index
< 0) || (index
>= keyboards
))
337 for (i
= index
; i
< keyboards
; ++i
) {
338 if (keyboard
[i
] == NULL
)
340 if (!KBD_IS_VALID(keyboard
[i
]))
342 if (strcmp("*", driver
) && strcmp(keyboard
[i
]->kb_name
, driver
))
344 if ((unit
!= -1) && (keyboard
[i
]->kb_unit
!= unit
))
347 * If we are in legacy mode, we do the old preference magic and
348 * don't return on the first found unit.
351 if (pref
<= keyboard
[i
]->kb_pref
) {
352 pref
= keyboard
[i
]->kb_pref
;
361 KKASSERT(pref_index
== -1);
366 /* find the keyboard specified by a driver name and a unit number */
368 kbd_find_keyboard(char *driver
, int unit
)
370 return (kbd_find_keyboard2(driver
, unit
, 0, 1));
373 /* allocate a keyboard */
375 kbd_allocate(char *driver
, int unit
, void *id
, kbd_callback_func_t
*func
,
384 index
= kbd_find_keyboard(driver
, unit
);
386 if (KBD_IS_BUSY(keyboard
[index
])) {
390 keyboard
[index
]->kb_token
= id
;
391 KBD_BUSY(keyboard
[index
]);
392 keyboard
[index
]->kb_callback
.kc_func
= func
;
393 keyboard
[index
]->kb_callback
.kc_arg
= arg
;
394 kbd_clear_state(keyboard
[index
]);
401 kbd_release(keyboard_t
*kbd
, void *id
)
406 if (!KBD_IS_VALID(kbd
) || !KBD_IS_BUSY(kbd
)) {
408 } else if (kbd
->kb_token
!= id
) {
411 kbd
->kb_token
= NULL
;
413 kbd
->kb_callback
.kc_func
= NULL
;
414 kbd
->kb_callback
.kc_arg
= NULL
;
415 kbd_clear_state(kbd
);
423 kbd_change_callback(keyboard_t
*kbd
, void *id
, kbd_callback_func_t
*func
,
429 if (!KBD_IS_VALID(kbd
) || !KBD_IS_BUSY(kbd
)) {
431 } else if (kbd
->kb_token
!= id
) {
433 } else if (func
== NULL
) {
436 kbd
->kb_callback
.kc_func
= func
;
437 kbd
->kb_callback
.kc_arg
= arg
;
444 /* get a keyboard structure */
446 kbd_get_keyboard(int index
)
448 if ((index
< 0) || (index
>= keyboards
))
450 if (keyboard
[index
] == NULL
)
452 if (!KBD_IS_VALID(keyboard
[index
]))
454 return keyboard
[index
];
458 * The back door for the console driver; configure keyboards
459 * This function is for the kernel console to initialize keyboards
460 * at very early stage.
464 kbd_configure(int flags
)
466 const keyboard_driver_t
**list
;
467 const keyboard_driver_t
*p
;
469 SLIST_FOREACH(p
, &keyboard_drivers
, link
) {
470 if (p
->configure
!= NULL
)
471 (*p
->configure
)(flags
);
473 SET_FOREACH(list
, kbddriver_set
) {
475 if (p
->configure
!= NULL
)
476 (*p
->configure
)(flags
);
482 #ifdef KBD_INSTALL_CDEV
485 * Virtual keyboard cdev driver functions
486 * The virtual keyboard driver dispatches driver functions to
487 * appropriate subdrivers.
490 #define KBD_UNIT(dev) minor(dev)
492 static d_open_t genkbdopen
;
493 static d_close_t genkbdclose
;
494 static d_read_t genkbdread
;
495 static d_write_t genkbdwrite
;
496 static d_ioctl_t genkbdioctl
;
497 static d_poll_t genkbdpoll
;
499 #define CDEV_MAJOR 112
501 static struct dev_ops kbd_ops
= {
502 { "kbd", CDEV_MAJOR
, 0 },
503 .d_open
= genkbdopen
,
504 .d_close
= genkbdclose
,
505 .d_read
= genkbdread
,
506 .d_write
= genkbdwrite
,
507 .d_ioctl
= genkbdioctl
,
508 .d_poll
= genkbdpoll
,
514 * NOTE: The usb driver does not detach the default keyboard if it is
515 * unplugged, but calls kbd_attach() when it is plugged back in.
518 kbd_attach(keyboard_t
*kbd
)
522 if (kbd
->kb_index
>= keyboards
)
524 if (keyboard
[kbd
->kb_index
] != kbd
)
527 if (kbd
->kb_dev
== NULL
) {
528 kbd
->kb_dev
= make_dev(&kbd_ops
, kbd
->kb_index
,
529 UID_ROOT
, GID_WHEEL
, 0600,
530 "kbd%r", kbd
->kb_index
);
533 if (dev
->si_drv1
== NULL
) {
534 dev
->si_drv1
= kmalloc(sizeof(struct genkbd_softc
), M_DEVBUF
,
537 bzero(dev
->si_drv1
, sizeof(struct genkbd_softc
));
539 kprintf("kbd%d at %s%d\n", kbd
->kb_index
, kbd
->kb_name
, kbd
->kb_unit
);
544 kbd_detach(keyboard_t
*kbd
)
548 if (kbd
->kb_index
>= keyboards
)
550 if (keyboard
[kbd
->kb_index
] != kbd
)
553 if ((dev
= kbd
->kb_dev
) != NULL
) {
555 kfree(dev
->si_drv1
, M_DEVBUF
);
560 dev_ops_remove_minor(&kbd_ops
, kbd
->kb_index
);
565 * Generic keyboard cdev driver functions
566 * Keyboard subdrivers may call these functions to implement common
571 genkbd_putc(genkbd_softc_t sc
, char c
)
575 if (sc
->gkb_q_length
== KB_QSIZE
)
578 p
= (sc
->gkb_q_start
+ sc
->gkb_q_length
) % KB_QSIZE
;
584 genkbd_getc(genkbd_softc_t sc
, char *buf
, size_t len
)
587 /* Determine copy size. */
588 if (sc
->gkb_q_length
== 0)
590 if (len
>= sc
->gkb_q_length
)
591 len
= sc
->gkb_q_length
;
592 if (len
>= KB_QSIZE
- sc
->gkb_q_start
)
593 len
= KB_QSIZE
- sc
->gkb_q_start
;
595 /* Copy out data and progress offset. */
596 memcpy(buf
, sc
->gkb_q
+ sc
->gkb_q_start
, len
);
597 sc
->gkb_q_start
= (sc
->gkb_q_start
+ len
) % KB_QSIZE
;
598 sc
->gkb_q_length
-= len
;
603 static kbd_callback_func_t genkbd_event
;
606 genkbdopen(struct dev_open_args
*ap
)
608 cdev_t dev
= ap
->a_head
.a_dev
;
615 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
616 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
620 i
= kbd_allocate(kbd
->kb_name
, kbd
->kb_unit
, sc
,
621 genkbd_event
, (void *)sc
);
626 /* assert(i == kbd->kb_index) */
627 /* assert(kbd == kbd_get_keyboard(i)) */
630 * NOTE: even when we have successfully claimed a keyboard,
631 * the device may still be missing (!KBD_HAS_DEVICE(kbd)).
634 sc
->gkb_q_length
= 0;
641 genkbdclose(struct dev_close_args
*ap
)
643 cdev_t dev
= ap
->a_head
.a_dev
;
648 * NOTE: the device may have already become invalid.
649 * kbd == NULL || !KBD_IS_VALID(kbd)
653 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
654 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
655 /* XXX: we shall be forgiving and don't report error... */
657 kbd_release(kbd
, (void *)sc
);
664 genkbdread(struct dev_read_args
*ap
)
666 cdev_t dev
= ap
->a_head
.a_dev
;
667 struct uio
*uio
= ap
->a_uio
;
670 u_char buffer
[KB_BUFSIZE
];
677 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
678 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
682 while (sc
->gkb_q_length
== 0) {
683 if (ap
->a_ioflag
& IO_NDELAY
) { /* O_NONBLOCK? */
687 sc
->gkb_flags
|= KB_ASLEEP
;
688 error
= tsleep((caddr_t
)sc
, PCATCH
, "kbdrea", 0);
689 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
690 if ((kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
692 return ENXIO
; /* our keyboard has gone... */
695 sc
->gkb_flags
&= ~KB_ASLEEP
;
702 /* copy as much input as possible */
704 while (uio
->uio_resid
> 0) {
705 len
= (int)szmin(uio
->uio_resid
, sizeof(buffer
));
706 len
= genkbd_getc(sc
, buffer
, len
);
709 error
= uiomove(buffer
, (size_t)len
, uio
);
718 genkbdwrite(struct dev_write_args
*ap
)
720 cdev_t dev
= ap
->a_head
.a_dev
;
723 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
724 if ((kbd
== NULL
) || !KBD_IS_VALID(kbd
))
730 genkbdioctl(struct dev_ioctl_args
*ap
)
732 cdev_t dev
= ap
->a_head
.a_dev
;
736 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
737 if ((kbd
== NULL
) || !KBD_IS_VALID(kbd
))
739 error
= kbd_ioctl(kbd
, ap
->a_cmd
, ap
->a_data
);
740 if (error
== ENOIOCTL
)
746 genkbdpoll(struct dev_poll_args
*ap
)
748 cdev_t dev
= ap
->a_head
.a_dev
;
756 kbd
= kbd_get_keyboard(KBD_INDEX(dev
));
757 if ((sc
== NULL
) || (kbd
== NULL
) || !KBD_IS_VALID(kbd
)) {
758 revents
= POLLHUP
; /* the keyboard has gone */
759 } else if (ap
->a_events
& (POLLIN
| POLLRDNORM
)) {
760 if (sc
->gkb_q_length
> 0)
761 revents
= ap
->a_events
& (POLLIN
| POLLRDNORM
);
763 selrecord(curthread
, &sc
->gkb_rsel
);
766 ap
->a_events
= revents
;
771 genkbd_event(keyboard_t
*kbd
, int event
, void *arg
)
779 /* assert(KBD_IS_VALID(kbd)) */
780 sc
= (genkbd_softc_t
)arg
;
785 case KBDIO_UNLOADING
:
786 /* the keyboard is going... */
787 kbd_release(kbd
, (void *)sc
);
788 if (sc
->gkb_flags
& KB_ASLEEP
) {
789 sc
->gkb_flags
&= ~KB_ASLEEP
;
792 selwakeup(&sc
->gkb_rsel
);
798 /* obtain the current key input mode */
799 if (kbd_ioctl(kbd
, KDGKBMODE
, (caddr_t
)&mode
))
802 /* read all pending input */
803 while (kbd_check_char(kbd
)) {
804 c
= kbd_read_char(kbd
, FALSE
);
807 if (c
== ERRKEY
) /* XXX: ring bell? */
809 if (!KBD_IS_BUSY(kbd
))
810 /* the device is not open, discard the input */
813 /* store the byte as is for K_RAW and K_CODE modes */
814 if (mode
!= K_XLATE
) {
815 genkbd_putc(sc
, KEYCHAR(c
));
820 if (c
& RELKEY
) /* key release is ignored */
823 /* process special keys; most of them are just ignored... */
825 switch (KEYCHAR(c
)) {
829 case BTAB
: /* a backtab: ESC [ Z */
830 genkbd_putc(sc
, 0x1b);
831 genkbd_putc(sc
, '[');
832 genkbd_putc(sc
, 'Z');
837 /* normal chars, normal chars with the META, function keys */
838 switch (KEYFLAGS(c
)) {
839 case 0: /* a normal char */
840 genkbd_putc(sc
, KEYCHAR(c
));
842 case MKEY
: /* the META flag: prepend ESC */
843 genkbd_putc(sc
, 0x1b);
844 genkbd_putc(sc
, KEYCHAR(c
));
846 case FKEY
| SPCLKEY
: /* a function key, return string */
847 cp
= kbd_get_fkeystr(kbd
, KEYCHAR(c
), &len
);
850 genkbd_putc(sc
, *cp
++);
856 /* wake up sleeping/polling processes */
857 if (sc
->gkb_q_length
> 0) {
858 if (sc
->gkb_flags
& KB_ASLEEP
) {
859 sc
->gkb_flags
&= ~KB_ASLEEP
;
862 selwakeup(&sc
->gkb_rsel
);
868 #endif /* KBD_INSTALL_CDEV */
871 * Generic low-level keyboard functions
872 * The low-level functions in the keyboard subdriver may use these
877 genkbd_commonioctl(keyboard_t
*kbd
, u_long cmd
, caddr_t arg
)
886 case KDGKBINFO
: /* get keyboard information */
887 ((keyboard_info_t
*)arg
)->kb_index
= kbd
->kb_index
;
888 i
= imin(strlen(kbd
->kb_name
) + 1,
889 sizeof(((keyboard_info_t
*)arg
)->kb_name
));
890 bcopy(kbd
->kb_name
, ((keyboard_info_t
*)arg
)->kb_name
, i
);
891 ((keyboard_info_t
*)arg
)->kb_unit
= kbd
->kb_unit
;
892 ((keyboard_info_t
*)arg
)->kb_type
= kbd
->kb_type
;
893 ((keyboard_info_t
*)arg
)->kb_config
= kbd
->kb_config
;
894 ((keyboard_info_t
*)arg
)->kb_flags
= kbd
->kb_flags
;
897 case KDGKBTYPE
: /* get keyboard type */
898 *(int *)arg
= kbd
->kb_type
;
901 case KDGETREPEAT
: /* get keyboard repeat rate */
902 ((int *)arg
)[0] = kbd
->kb_delay1
;
903 ((int *)arg
)[1] = kbd
->kb_delay2
;
906 case GIO_KEYMAP
: /* get keyboard translation table */
907 bcopy(kbd
->kb_keymap
, arg
, sizeof(*kbd
->kb_keymap
));
909 case PIO_KEYMAP
: /* set keyboard translation table */
910 #ifndef KBD_DISABLE_KEYMAP_LOAD
911 bzero(kbd
->kb_accentmap
, sizeof(*kbd
->kb_accentmap
));
912 bcopy(arg
, kbd
->kb_keymap
, sizeof(*kbd
->kb_keymap
));
919 case GIO_KEYMAPENT
: /* get keyboard translation table entry */
920 keyp
= (keyarg_t
*)arg
;
921 if (keyp
->keynum
>= sizeof(kbd
->kb_keymap
->key
)
922 /sizeof(kbd
->kb_keymap
->key
[0])) {
926 bcopy(&kbd
->kb_keymap
->key
[keyp
->keynum
], &keyp
->key
,
929 case PIO_KEYMAPENT
: /* set keyboard translation table entry */
930 #ifndef KBD_DISABLE_KEYMAP_LOAD
931 keyp
= (keyarg_t
*)arg
;
932 if (keyp
->keynum
>= sizeof(kbd
->kb_keymap
->key
)
933 /sizeof(kbd
->kb_keymap
->key
[0])) {
937 bcopy(&keyp
->key
, &kbd
->kb_keymap
->key
[keyp
->keynum
],
945 case GIO_DEADKEYMAP
: /* get accent key translation table */
946 bcopy(kbd
->kb_accentmap
, arg
, sizeof(*kbd
->kb_accentmap
));
948 case PIO_DEADKEYMAP
: /* set accent key translation table */
949 #ifndef KBD_DISABLE_KEYMAP_LOAD
950 bcopy(arg
, kbd
->kb_accentmap
, sizeof(*kbd
->kb_accentmap
));
957 case GETFKEY
: /* get functionkey string */
958 fkeyp
= (fkeyarg_t
*)arg
;
959 if (fkeyp
->keynum
>= kbd
->kb_fkeytab_size
) {
963 bcopy(kbd
->kb_fkeytab
[fkeyp
->keynum
].str
, fkeyp
->keydef
,
964 kbd
->kb_fkeytab
[fkeyp
->keynum
].len
);
965 fkeyp
->flen
= kbd
->kb_fkeytab
[fkeyp
->keynum
].len
;
967 case SETFKEY
: /* set functionkey string */
968 #ifndef KBD_DISABLE_KEYMAP_LOAD
969 fkeyp
= (fkeyarg_t
*)arg
;
970 if (fkeyp
->keynum
>= kbd
->kb_fkeytab_size
) {
974 kbd
->kb_fkeytab
[fkeyp
->keynum
].len
= imin(fkeyp
->flen
, MAXFK
);
975 bcopy(fkeyp
->keydef
, kbd
->kb_fkeytab
[fkeyp
->keynum
].str
,
976 kbd
->kb_fkeytab
[fkeyp
->keynum
].len
);
992 /* get a pointer to the string associated with the given function key */
994 genkbd_get_fkeystr(keyboard_t
*kbd
, int fkey
, size_t *len
)
999 if (fkey
> kbd
->kb_fkeytab_size
)
1001 *len
= kbd
->kb_fkeytab
[fkey
].len
;
1002 return kbd
->kb_fkeytab
[fkey
].str
;
1005 /* diagnostic dump */
1007 get_kbd_type_name(int type
)
1014 { KB_101
, "AT 101/102" },
1015 { KB_OTHER
, "generic" },
1019 for (i
= 0; i
< sizeof(name_table
)/sizeof(name_table
[0]); ++i
) {
1020 if (type
== name_table
[i
].type
)
1021 return name_table
[i
].name
;
1027 genkbd_diag(keyboard_t
*kbd
, int level
)
1030 kprintf("kbd%d: %s%d, %s (%d), config:0x%x, flags:0x%x",
1031 kbd
->kb_index
, kbd
->kb_name
, kbd
->kb_unit
,
1032 get_kbd_type_name(kbd
->kb_type
), kbd
->kb_type
,
1033 kbd
->kb_config
, kbd
->kb_flags
);
1034 if (kbd
->kb_io_base
> 0)
1035 kprintf(", port:0x%x-0x%x", kbd
->kb_io_base
,
1036 kbd
->kb_io_base
+ kbd
->kb_io_size
- 1);
1041 #define set_lockkey_state(k, s, l) \
1042 if (!((s) & l ## DOWN)) { \
1046 i = (s) & LOCK_MASK; \
1047 kbd_ioctl((k), KDSETLED, (caddr_t)&i); \
1051 save_accent_key(keyboard_t
*kbd
, u_int key
, int *accents
)
1055 /* make an index into the accent map */
1056 i
= key
- F_ACC
+ 1;
1057 if ((i
> kbd
->kb_accentmap
->n_accs
)
1058 || (kbd
->kb_accentmap
->acc
[i
- 1].accchar
== 0)) {
1059 /* the index is out of range or pointing to an empty entry */
1065 * If the same accent key has been hit twice, produce the accent char
1068 if (i
== *accents
) {
1069 key
= kbd
->kb_accentmap
->acc
[i
- 1].accchar
;
1074 /* remember the index and wait for the next key */
1080 make_accent_char(keyboard_t
*kbd
, u_int ch
, int *accents
)
1085 acc
= &kbd
->kb_accentmap
->acc
[*accents
- 1];
1089 * If the accent key is followed by the space key,
1090 * produce the accent char itself.
1093 return acc
->accchar
;
1095 /* scan the accent map */
1096 for (i
= 0; i
< NUM_ACCENTCHARS
; ++i
) {
1097 if (acc
->map
[i
][0] == 0) /* end of table */
1099 if (acc
->map
[i
][0] == ch
)
1100 return acc
->map
[i
][1];
1102 /* this char cannot be accented... */
1107 genkbd_keyaction(keyboard_t
*kbd
, int keycode
, int up
, int *shiftstate
,
1110 struct keyent_t
*key
;
1111 int state
= *shiftstate
;
1117 f
= state
& (AGRS
| ALKED
);
1118 if ((f
== AGRS1
) || (f
== AGRS2
) || (f
== ALKED
))
1120 key
= &kbd
->kb_keymap
->key
[i
];
1121 i
= ((state
& SHIFTS
) ? 1 : 0)
1122 | ((state
& CTLS
) ? 2 : 0)
1123 | ((state
& ALTS
) ? 4 : 0);
1124 if (((key
->flgs
& FLAG_LOCK_C
) && (state
& CLKED
))
1125 || ((key
->flgs
& FLAG_LOCK_N
) && (state
& NLKED
)) )
1128 if (up
) { /* break: key released */
1129 action
= kbd
->kb_lastact
[keycode
];
1130 kbd
->kb_lastact
[keycode
] = NOP
;
1133 if (state
& SHIFTAON
) {
1134 set_lockkey_state(kbd
, state
, ALK
);
1143 if (state
& SHIFTAON
) {
1144 set_lockkey_state(kbd
, state
, ALK
);
1153 if (state
& SHIFTAON
) {
1154 set_lockkey_state(kbd
, state
, ALK
);
1163 if (state
& SHIFTAON
) {
1164 set_lockkey_state(kbd
, state
, ALK
);
1173 if (state
& SHIFTAON
) {
1174 set_lockkey_state(kbd
, state
, ALK
);
1183 if (state
& SHIFTAON
) {
1184 set_lockkey_state(kbd
, state
, ALK
);
1211 /* release events of regular keys are not reported */
1212 *shiftstate
&= ~SHIFTAON
;
1215 *shiftstate
= state
& ~SHIFTAON
;
1216 return (SPCLKEY
| RELKEY
| action
);
1217 } else { /* make: key pressed */
1218 action
= key
->map
[i
];
1220 if (key
->spcl
& (0x80 >> i
)) {
1222 if (kbd
->kb_lastact
[keycode
] == NOP
)
1223 kbd
->kb_lastact
[keycode
] = action
;
1224 if (kbd
->kb_lastact
[keycode
] != action
)
1229 set_lockkey_state(kbd
, state
, NLK
);
1232 set_lockkey_state(kbd
, state
, CLK
);
1235 set_lockkey_state(kbd
, state
, SLK
);
1238 set_lockkey_state(kbd
, state
, ALK
);
1240 /* NON-LOCKING KEYS */
1241 case SPSC
: case RBT
: case SUSP
: case STBY
:
1242 case DBG
: case NEXT
: case PREV
: case PNC
:
1243 case HALT
: case PDWN
:
1299 *shiftstate
= state
;
1302 /* is this an accent (dead) key? */
1303 *shiftstate
= state
;
1304 if (action
>= F_ACC
&& action
<= L_ACC
) {
1305 action
= save_accent_key(kbd
, action
,
1313 return (action
| MKEY
);
1319 /* other special keys */
1324 if (action
>= F_FN
&& action
<= L_FN
)
1326 /* XXX: return fkey string for the FKEY? */
1327 return (SPCLKEY
| action
);
1329 *shiftstate
= state
;
1330 return (SPCLKEY
| action
);
1333 kbd
->kb_lastact
[keycode
] = NOP
;
1334 *shiftstate
= state
;
1336 /* make an accented char */
1337 action
= make_accent_char(kbd
, action
, accents
);
1338 if (action
== ERRKEY
)