4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 /* From: SunOS4.0 sundev/kbd.c */
31 * Keyboard input streams module - handles conversion of up/down codes to
32 * ASCII or event format.
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/sysmacros.h>
37 #include <sys/signal.h>
38 #include <sys/termios.h>
39 #include <sys/termio.h>
40 #include <sys/stream.h>
41 #include <sys/stropts.h>
42 #include <sys/strsun.h>
46 #include <sys/errno.h>
48 #include <sys/consdev.h>
51 #include <sys/kbdreg.h>
52 #include <sys/vuid_event.h>
53 #include <sys/debug.h>
55 #include <sys/sunddi.h>
56 #include <sys/policy.h>
58 #include <sys/modctl.h>
60 #include <sys/int_limits.h>
62 static struct streamtab kbd_info
;
64 static struct fmodsw fsw
= {
71 * Module linkage information for the kernel.
74 static struct modlstrmod modlstrmod
= {
75 &mod_strmodops
, "streams module for keyboard", &fsw
78 static struct modlinkage modlinkage
= {
79 MODREV_1
, (void *)&modlstrmod
, NULL
85 return (mod_install(&modlinkage
));
91 return (mod_remove(&modlinkage
));
95 _info(struct modinfo
*modinfop
)
97 return (mod_info(&modlinkage
, modinfop
));
101 * For now these are shared.
102 * These data structures are static (defined in keytables.c) thus
103 * there is no need to perform any locking.
105 extern struct keyboards keytables
[];
106 extern char keystringtab
[16][KTAB_STRLEN
];
107 extern struct compose_sequence_t kb_compose_table
[];
108 extern signed char kb_compose_map
[];
109 extern struct fltaccent_sequence_t kb_fltaccent_table
[];
110 extern uchar_t kb_numlock_table
[];
113 * This value corresponds approximately to max 10 fingers
115 static int kbd_downs_size
= 15;
117 typedef struct key_event
{
118 uchar_t key_station
; /* Physical key station associated with event */
119 Firm_event event
; /* Event that sent out on down */
123 queue_t
*kbdd_writeq
;
124 mblk_t
*kbdd_iocpending
; /* "ioctl" awaiting buffer */
125 mblk_t
*kbdd_replypending
; /* "ioctl" reply awaiting result */
126 int kbdd_flags
; /* random flags */
127 bufcall_id_t kbdd_bufcallid
; /* bufcall id */
128 timeout_id_t kbdd_rptid
; /* timeout id for kbdrpt() */
129 timeout_id_t kbdd_layoutid
; /* timeout id for kbdlayout() */
130 int kbdd_iocid
; /* ID of "ioctl" being waited for */
131 int kbdd_iocerror
; /* error return from "ioctl" */
132 struct keyboardstate kbdd_state
;
134 * State of keyboard & keyboard
135 * specific settings, e.g., tables
137 int kbdd_translate
; /* Translate keycodes? */
138 int kbdd_translatable
; /* Keyboard is translatable? */
139 int kbdd_compat
; /* Generating pre-4.1 events? */
140 short kbdd_ascii_addr
; /* Vuid_id_addr for ascii events */
141 short kbdd_top_addr
; /* Vuid_id_addr for top events */
142 short kbdd_vkey_addr
; /* Vuid_id_addr for vkey events */
143 struct key_event
*kbdd_downs
;
145 * Table of key stations currently down
146 * that have firm events that need
147 * to be matched with up transitions
148 * when kbdd_translate is TR_*EVENT
150 int kbdd_downs_entries
; /* # of possible entries in kbdd_downs */
151 uint_t kbdd_downs_bytes
; /* # of bytes allocated for kbdd_downs */
152 ushort_t compose_key
; /* first compose key */
153 ushort_t fltaccent_entry
; /* floating accent keymap entry */
154 char led_state
; /* current state of LEDs */
155 unsigned char shiftkey
; /* used for the new abort keys */
158 #define KBD_OPEN 0x00000001 /* keyboard is open for business */
159 #define KBD_IOCWAIT 0x00000002 /* "open" waiting for "ioctl" to finish */
161 #define NO_HARD_RESET 0 /* don't do hard reset */
162 #define HARD_RESET 1 /* do hard reset */
166 * Constants setup during the first open of a kbd (so that they can be patched
167 * for debugging purposes).
169 static int kbd_repeatrate
;
170 static int kbd_repeatdelay
;
172 static int kbd_overflow_cnt
; /* Number of times kbd overflowed input q */
173 static int kbd_overflow_msg
= 1; /* Whether to print message on q overflow */
177 int kbd_ra_debug
= 0;
178 int kbd_raw_debug
= 0;
179 int kbd_rpt_debug
= 0;
180 int kbd_input_debug
= 0;
181 #endif /* KBD_DEBUG */
183 static int kbdopen(queue_t
*, dev_t
*, int, int, cred_t
*);
184 static int kbdclose(queue_t
*, int, cred_t
*);
185 static void kbdwput(queue_t
*, mblk_t
*);
186 static void kbdrput(queue_t
*, mblk_t
*);
188 static struct module_info kbdmiinfo
= {
197 static struct qinit kbdrinit
= {
206 static struct module_info kbdmoinfo
= {
215 static struct qinit kbdwinit
= {
224 static struct streamtab kbd_info
= {
231 static void kbdreioctl(void *);
232 static void kbdioctl(queue_t
*, mblk_t
*);
233 static void kbdflush(struct kbddata
*);
234 static void kbduse(struct kbddata
*, unsigned);
235 static void kbdsetled(struct kbddata
*);
236 static void kbd_beep_off(void *arg
);
237 static void kbd_beep_on(void *arg
);
238 static void kbdcmd(queue_t
*, char);
239 static void kbdreset(struct kbddata
*, uint_t
);
240 static int kbdsetkey(struct kbddata
*, struct kiockey
*, cred_t
*);
241 static int kbdgetkey(struct kbddata
*, struct kiockey
*);
242 static int kbdskey(struct kbddata
*, struct kiockeymap
*, cred_t
*);
243 static int kbdgkey(struct kbddata
*, struct kiockeymap
*);
244 static void kbdlayouttimeout(void *);
245 static void kbdinput(struct kbddata
*, unsigned);
246 static void kbdid(struct kbddata
*, int);
247 static struct keymap
*settable(struct kbddata
*, uint_t
);
248 static void kbdrpt(void *);
249 static void kbdcancelrpt(struct kbddata
*);
250 static void kbdtranslate(struct kbddata
*, unsigned, queue_t
*);
251 static int kbd_do_compose(ushort_t
, ushort_t
, ushort_t
*);
252 static void kbd_send_esc_event(char, struct kbddata
*);
253 char *strsetwithdecimal(char *, uint_t
, uint_t
);
254 static void kbdkeypressed(struct kbddata
*, uchar_t
, Firm_event
*,
256 static void kbdqueuepress(struct kbddata
*, uchar_t
, Firm_event
*);
257 static void kbdkeyreleased(struct kbddata
*, uchar_t
);
258 static void kbdreleaseall(struct kbddata
*);
259 static void kbdputcode(uint_t
, queue_t
*);
260 static void kbdputbuf(char *, queue_t
*);
261 static void kbdqueueevent(struct kbddata
*, Firm_event
*);
264 * Dummy qbufcall callback routine used by open and close.
265 * The framework will wake up qwait_sig when we return from
266 * this routine (as part of leaving the perimeters.)
267 * (The framework enters the perimeters before calling the qbufcall() callback
268 * and leaves the perimeters after the callback routine has executed. The
269 * framework performs an implicit wakeup of any thread in qwait/qwait_sig
270 * when it leaves the perimeter. See qwait(9E).)
273 static void dummy_callback(void *arg
)
279 * Ttyopen sets line characteristics
283 kbdopen(queue_t
*q
, dev_t
*devp
, int oflag
, int sflag
, cred_t
*crp
)
286 register struct kbddata
*kbdd
;
289 register struct iocblk
*iocb
;
290 register struct termios
*cb
;
292 /* Set these up only once so that they could be changed from adb */
293 if (!kbd_repeatrate
) {
294 kbd_repeatrate
= (hz
+29)/30;
295 kbd_repeatdelay
= hz
/2;
298 if (q
->q_ptr
!= NULL
)
299 return (0); /* already attached */
302 * Only allow open requests to succeed for privileged users. This
303 * necessary to prevent users from pushing the "kb" module again
304 * on the stream associated with /dev/kbd.
306 if (secpolicy_console(crp
) != 0) {
317 return (EINVAL
); /* No Bozos! */
320 /* allocate keyboard */
322 kbdd
= kmem_zalloc(sizeof (struct kbddata
), KM_SLEEP
);
326 * Set up queue pointers, so that the "put" procedure will accept
327 * the reply to the "ioctl" message we send down.
337 while ((mp
= mkiocb(TCSETSF
)) == NULL
) {
338 timeout_id_t id
= qbufcall(q
, sizeof (struct iocblk
), BPRI_HI
,
339 dummy_callback
, NULL
);
342 kmem_free(kbdd
, sizeof (struct kbddata
));
348 while ((datap
= allocb(sizeof (struct termios
), BPRI_HI
)) ==
350 timeout_id_t id
= qbufcall(q
, sizeof (struct termios
), BPRI_HI
,
351 dummy_callback
, NULL
);
355 kmem_free(kbdd
, sizeof (struct kbddata
));
362 iocb
= (struct iocblk
*)mp
->b_rptr
;
363 iocb
->ioc_count
= sizeof (struct termios
);
365 cb
= (struct termios
*)datap
->b_rptr
;
368 cb
->c_cflag
= CREAD
|CS8
|B1200
;
370 bzero(cb
->c_cc
, NCCS
);
371 datap
->b_wptr
+= sizeof (struct termios
);
373 kbdd
->kbdd_flags
|= KBD_IOCWAIT
; /* indicate that we're */
374 kbdd
->kbdd_iocid
= iocb
->ioc_id
; /* waiting for this response */
378 * Now wait for it. Let our read queue put routine wake us up
381 while (kbdd
->kbdd_flags
& KBD_IOCWAIT
) {
387 if ((error
= kbdd
->kbdd_iocerror
) != 0)
391 * Set up private data.
393 kbdd
->kbdd_readq
= q
;
394 kbdd
->kbdd_writeq
= WR(q
);
395 kbdd
->kbdd_iocpending
= NULL
;
396 kbdd
->kbdd_translatable
= TR_CAN
;
397 kbdd
->kbdd_translate
= TR_ASCII
;
398 kbdd
->kbdd_compat
= 1;
399 kbdd
->kbdd_ascii_addr
= ASCII_FIRST
;
400 kbdd
->kbdd_top_addr
= TOP_FIRST
;
401 kbdd
->kbdd_vkey_addr
= VKEY_FIRST
;
402 /* Allocate dynamic memory for downs table */
403 kbdd
->kbdd_downs_entries
= kbd_downs_size
;
404 kbdd
->kbdd_downs_bytes
= kbd_downs_size
* sizeof (Key_event
);
405 kbdd
->kbdd_downs
= kmem_alloc(kbdd
->kbdd_downs_bytes
, KM_SLEEP
);
406 kbdd
->kbdd_flags
= KBD_OPEN
;
412 kbdreset(kbdd
, HARD_RESET
);
414 (void) beep_init((void *)WR(q
), kbd_beep_on
, kbd_beep_off
, NULL
);
420 kmem_free(kbdd
, sizeof (struct kbddata
));
429 kbdclose(register queue_t
*q
, int flag
, cred_t
*crp
)
431 register struct kbddata
*kbdd
= (struct kbddata
*)q
->q_ptr
;
437 * Since we're about to destroy our private data, turn off
438 * our open flag first, so we don't accept any more input
439 * and try to use that data.
441 kbdd
->kbdd_flags
= 0;
443 if ((mp
= kbdd
->kbdd_replypending
) != NULL
) {
445 * There was a KIOCLAYOUT pending; presumably, it timed out.
446 * Throw the reply away.
448 kbdd
->kbdd_replypending
= NULL
;
452 /* clear all timeouts */
453 if (kbdd
->kbdd_bufcallid
)
454 qunbufcall(q
, kbdd
->kbdd_bufcallid
);
455 if (kbdd
->kbdd_rptid
)
456 (void) quntimeout(q
, kbdd
->kbdd_rptid
);
457 if (kbdd
->kbdd_layoutid
)
458 (void) quntimeout(q
, kbdd
->kbdd_layoutid
);
459 kmem_free(kbdd
->kbdd_downs
, kbdd
->kbdd_downs_bytes
);
460 kmem_free(kbdd
, sizeof (struct kbddata
));
465 * Line discipline output queue put procedure: handles M_IOCTL
469 kbdwput(register queue_t
*q
, register mblk_t
*mp
)
472 * Process M_FLUSH, and some M_IOCTL, messages here; pass
473 * everything else down.
475 switch (mp
->b_datap
->db_type
) {
478 if (*mp
->b_rptr
& FLUSHW
)
479 flushq(q
, FLUSHDATA
);
480 if (*mp
->b_rptr
& FLUSHR
)
481 flushq(RD(q
), FLUSHDATA
);
484 putnext(q
, mp
); /* pass it down the line */
495 kbdreioctl(void *kbdd_addr
)
497 struct kbddata
*kbdd
= kbdd_addr
;
501 kbdd
->kbdd_bufcallid
= 0;
502 q
= kbdd
->kbdd_writeq
;
503 if ((mp
= kbdd
->kbdd_iocpending
) != NULL
) {
504 kbdd
->kbdd_iocpending
= NULL
; /* not pending any more */
510 kbdioctl(register queue_t
*q
, register mblk_t
*mp
)
512 register struct kbddata
*kbdd
= (struct kbddata
*)q
->q_ptr
;
513 register struct iocblk
*iocp
;
514 register short new_translate
;
515 register Vuid_addr_probe
*addr_probe
;
516 register short *addr_ptr
;
518 size_t ioctlrespsize
;
525 iocp
= (struct iocblk
*)mp
->b_rptr
;
527 switch (iocp
->ioc_cmd
) {
530 err
= miocpullup(mp
, sizeof (int));
534 new_translate
= (*(int *)mp
->b_cont
->b_rptr
== VUID_NATIVE
) ?
536 if (new_translate
== kbdd
->kbdd_translate
)
538 kbdd
->kbdd_translate
= new_translate
;
539 goto output_format_change
;
542 err
= miocpullup(mp
, sizeof (int));
546 new_translate
= *(int *)mp
->b_cont
->b_rptr
;
547 if (new_translate
== kbdd
->kbdd_translate
)
549 kbdd
->kbdd_translate
= new_translate
;
550 goto output_format_change
;
553 err
= miocpullup(mp
, sizeof (int));
557 tmp
= (char)(*(int *)mp
->b_cont
->b_rptr
);
558 if (tmp
== KBD_CMD_BELL
)
559 (void) beeper_on(BEEP_TYPE4
);
560 else if (tmp
== KBD_CMD_NOBELL
)
567 if (iocp
->ioc_count
!= TRANSPARENT
) {
569 * We don't support non-transparent ioctls,
575 tmp
= (int)(*(intptr_t *)mp
->b_cont
->b_rptr
);
576 cycles
= tmp
& 0xffff;
577 msecs
= (tmp
>> 16) & 0xffff;
580 frequency
= UINT16_MAX
;
581 else if (cycles
== UINT16_MAX
)
584 frequency
= (PIT_HZ
+ cycles
/ 2) / cycles
;
585 if (frequency
> UINT16_MAX
)
586 frequency
= UINT16_MAX
;
589 err
= beep_mktone(frequency
, msecs
);
593 err
= miocpullup(mp
, sizeof (uchar_t
));
597 kbdd
->led_state
= *(uchar_t
*)mp
->b_cont
->b_rptr
;
602 if ((datap
= allocb(sizeof (uchar_t
), BPRI_HI
)) == NULL
) {
603 ioctlrespsize
= sizeof (int);
606 *(uchar_t
*)datap
->b_wptr
= kbdd
->led_state
;
607 datap
->b_wptr
+= sizeof (uchar_t
);
608 if (mp
->b_cont
) /* free msg to prevent memory leak */
611 iocp
->ioc_count
= sizeof (uchar_t
);
615 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
616 ioctlrespsize
= sizeof (int);
619 *(int *)datap
->b_wptr
=
620 (kbdd
->kbdd_translate
== TR_EVENT
||
621 kbdd
->kbdd_translate
== TR_UNTRANS_EVENT
) ?
622 VUID_FIRM_EVENT
: VUID_NATIVE
;
623 datap
->b_wptr
+= sizeof (int);
624 if (mp
->b_cont
) /* free msg to prevent memory leak */
627 iocp
->ioc_count
= sizeof (int);
631 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
632 ioctlrespsize
= sizeof (int);
635 *(int *)datap
->b_wptr
= kbdd
->kbdd_translate
;
636 datap
->b_wptr
+= sizeof (int);
637 if (mp
->b_cont
) /* free msg to prevent memory leak */
640 iocp
->ioc_count
= sizeof (int);
644 err
= miocpullup(mp
, sizeof (Vuid_addr_probe
));
648 addr_probe
= (Vuid_addr_probe
*)mp
->b_cont
->b_rptr
;
649 switch (addr_probe
->base
) {
652 addr_ptr
= &kbdd
->kbdd_ascii_addr
;
656 addr_ptr
= &kbdd
->kbdd_top_addr
;
660 addr_ptr
= &kbdd
->kbdd_vkey_addr
;
666 if ((err
== 0) && (*addr_ptr
!= addr_probe
->data
.next
)) {
667 *addr_ptr
= addr_probe
->data
.next
;
668 goto output_format_change
;
673 err
= miocpullup(mp
, sizeof (Vuid_addr_probe
));
677 addr_probe
= (Vuid_addr_probe
*)mp
->b_cont
->b_rptr
;
678 switch (addr_probe
->base
) {
681 addr_probe
->data
.current
= kbdd
->kbdd_ascii_addr
;
685 addr_probe
->data
.current
= kbdd
->kbdd_top_addr
;
689 addr_probe
->data
.current
= kbdd
->kbdd_vkey_addr
;
698 err
= miocpullup(mp
, sizeof (int));
702 if (kbdd
->kbdd_translatable
!= *(int *)mp
->b_cont
->b_rptr
) {
703 kbdd
->kbdd_translatable
= *(int *)mp
->b_cont
->b_rptr
;
704 kbdreset(kbdd
, HARD_RESET
);
705 goto output_format_change
;
710 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
711 ioctlrespsize
= sizeof (int);
714 *(int *)datap
->b_wptr
= kbdd
->kbdd_translatable
;
715 datap
->b_wptr
+= sizeof (int);
716 if (mp
->b_cont
) /* free msg to prevent memory leak */
719 iocp
->ioc_count
= sizeof (int);
723 err
= miocpullup(mp
, sizeof (int));
727 kbdd
->kbdd_compat
= *(int *)mp
->b_cont
->b_rptr
;
731 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
732 ioctlrespsize
= sizeof (int);
735 *(int *)datap
->b_wptr
= kbdd
->kbdd_compat
;
736 datap
->b_wptr
+= sizeof (int);
737 if (mp
->b_cont
) /* free msg to prevent memory leak */
740 iocp
->ioc_count
= sizeof (int);
744 err
= miocpullup(mp
, sizeof (struct kiockey
));
748 err
= kbdsetkey(kbdd
, (struct kiockey
*)mp
->b_cont
->b_rptr
,
751 * Since this only affects any subsequent key presses,
752 * don't goto output_format_change. One might want to
753 * toggle the keytable entries dynamically.
758 err
= miocpullup(mp
, sizeof (struct kiockey
));
762 err
= kbdgetkey(kbdd
, (struct kiockey
*)mp
->b_cont
->b_rptr
);
766 err
= miocpullup(mp
, sizeof (struct kiockeymap
));
770 err
= kbdskey(kbdd
, (struct kiockeymap
*)mp
->b_cont
->b_rptr
,
773 * Since this only affects any subsequent key presses,
774 * don't goto output_format_change. One might want to
775 * toggle the keytable entries dynamically.
780 err
= miocpullup(mp
, sizeof (struct kiockeymap
));
784 err
= kbdgkey(kbdd
, (struct kiockeymap
*)mp
->b_cont
->b_rptr
);
788 goto output_format_change
;
791 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
792 ioctlrespsize
= sizeof (int);
795 *(int *)datap
->b_wptr
= 1; /* always direct */
796 datap
->b_wptr
+= sizeof (int);
797 if (mp
->b_cont
) /* free msg to prevent memory leak */
800 iocp
->ioc_count
= sizeof (int);
804 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
805 ioctlrespsize
= sizeof (int);
808 *(int *)datap
->b_wptr
= kbdd
->kbdd_state
.k_id
;
809 datap
->b_wptr
+= sizeof (int);
810 if (mp
->b_cont
) /* free msg to prevent memory leak */
813 iocp
->ioc_count
= sizeof (int);
817 if ((datap
= kbdd
->kbdd_replypending
) != NULL
) {
819 * There was an earlier KIOCLAYOUT pending; presumably,
820 * it timed out. Throw the reply away.
822 kbdd
->kbdd_replypending
= NULL
;
826 if (kbdd
->kbdd_state
.k_id
== KB_SUN4
||
827 kbdd
->kbdd_state
.k_id
== KB_PC
) {
828 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
829 ioctlrespsize
= sizeof (int);
833 iocp
->ioc_error
= 0; /* brain rot */
834 iocp
->ioc_count
= sizeof (int);
835 if (mp
->b_cont
) /* free msg to prevent memory leak */
838 mp
->b_datap
->db_type
= M_IOCACK
;
839 kbdd
->kbdd_replypending
= mp
;
840 kbdcmd(q
, (char)KBD_CMD_GETLAYOUT
);
841 if (kbdd
->kbdd_layoutid
)
842 (void) quntimeout(q
, kbdd
->kbdd_layoutid
);
843 kbdd
->kbdd_layoutid
= qtimeout(q
, kbdlayouttimeout
,
845 return; /* wait for reply from keyboard */
848 * Not a Type 4 keyboard; return an immediate error.
856 * Report the autorepeat delay, unit in millisecond
858 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
859 ioctlrespsize
= sizeof (int);
862 *(int *)datap
->b_wptr
= TICK_TO_MSEC(kbd_repeatdelay
);
863 datap
->b_wptr
+= sizeof (int);
865 /* free msg to prevent memory leak */
866 if (mp
->b_cont
!= NULL
)
869 iocp
->ioc_count
= sizeof (int);
874 * Set the autorepeat delay
876 err
= miocpullup(mp
, sizeof (int));
881 /* validate the input */
882 if (*(int *)mp
->b_cont
->b_rptr
< KIOCRPTDELAY_MIN
) {
886 kbd_repeatdelay
= MSEC_TO_TICK(*(int *)mp
->b_cont
->b_rptr
);
887 if (kbd_repeatdelay
<= 0)
893 * Report the autorepeat rate
895 if ((datap
= allocb(sizeof (int), BPRI_HI
)) == NULL
) {
896 ioctlrespsize
= sizeof (int);
899 *(int *)datap
->b_wptr
= TICK_TO_MSEC(kbd_repeatrate
);
900 datap
->b_wptr
+= sizeof (int);
902 /* free msg to prevent memory leak */
903 if (mp
->b_cont
!= NULL
)
906 iocp
->ioc_count
= sizeof (int);
911 * Set the autorepeat rate
913 err
= miocpullup(mp
, sizeof (int));
918 /* validate the input */
919 if (*(int *)mp
->b_cont
->b_rptr
< KIOCRPTRATE_MIN
) {
923 kbd_repeatrate
= MSEC_TO_TICK(*(int *)mp
->b_cont
->b_rptr
);
924 if (kbd_repeatrate
<= 0)
929 putnext(q
, mp
); /* pass it down the line */
934 output_format_change
:
940 iocp
->ioc_error
= err
;
941 mp
->b_datap
->db_type
= M_IOCNAK
;
944 iocp
->ioc_error
= 0; /* brain rot */
945 mp
->b_datap
->db_type
= M_IOCACK
;
952 * We needed to allocate something to handle this "ioctl", but
953 * couldn't; save this "ioctl" and arrange to get called back when
954 * it's more likely that we can get what we need.
955 * If there's already one being saved, throw it out, since it
956 * must have timed out.
958 if (kbdd
->kbdd_iocpending
!= NULL
)
959 freemsg(kbdd
->kbdd_iocpending
);
960 kbdd
->kbdd_iocpending
= mp
;
961 if (kbdd
->kbdd_bufcallid
)
962 qunbufcall(q
, kbdd
->kbdd_bufcallid
);
963 kbdd
->kbdd_bufcallid
= qbufcall(q
, ioctlrespsize
, BPRI_HI
,
968 kbdflush(register struct kbddata
*kbdd
)
972 /* Flush pending data already sent upstream */
973 if ((q
= kbdd
->kbdd_readq
) != NULL
&& q
->q_next
!= NULL
)
974 (void) putnextctl1(q
, M_FLUSH
, FLUSHR
);
975 /* Flush pending ups */
976 bzero(kbdd
->kbdd_downs
, kbdd
->kbdd_downs_bytes
);
981 * Pass keycode upstream, either translated or untranslated.
984 kbduse(register struct kbddata
*kbdd
, unsigned keycode
)
986 register queue_t
*readq
;
989 if (kbd_input_debug
) printf("KBD USE key=%d\n", keycode
);
992 if ((readq
= kbdd
->kbdd_readq
) == NULL
)
994 if (!kbdd
->kbdd_translatable
||
995 kbdd
->kbdd_translate
== TR_NONE
)
996 kbdputcode(keycode
, readq
);
998 kbdtranslate(kbdd
, keycode
, readq
);
1002 kbd_beep_on(void *arg
)
1004 kbdcmd((queue_t
*)arg
, KBD_CMD_BELL
);
1009 kbd_beep_off(void *arg
)
1011 kbdcmd((queue_t
*)arg
, KBD_CMD_NOBELL
);
1016 * kbdclick is used to remember the current click value of the
1017 * Sun-3 keyboard. This brain damaged keyboard will reset the
1018 * clicking to the "default" value after a reset command and
1019 * there is no way to read out the current click value. We
1020 * cannot send a click command immediately after the reset
1021 * command or the keyboard gets screwed up. So we wait until
1022 * we get the ID byte before we send back the click command.
1023 * Unfortunately, this means that there is a small window
1024 * where the keyboard can click when it really shouldn't be.
1025 * A value of -1 means that kbdclick has not been initialized yet.
1027 static int kbdclick
= -1;
1030 * Send command byte to keyboard, if you can.
1033 kbdcmd(register queue_t
*q
, char cmd
)
1035 register mblk_t
*bp
;
1038 if ((bp
= allocb(1, BPRI_MED
)) == NULL
)
1040 "kbdcmd: Can't allocate block for command");
1042 *bp
->b_wptr
++ = cmd
;
1044 if (cmd
== KBD_CMD_NOCLICK
)
1046 else if (cmd
== KBD_CMD_CLICK
)
1053 * Update the keyboard LEDs to match the current keyboard state.
1054 * Do this only on Type 4 keyboards; other keyboards don't support the
1055 * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs).
1058 kbdsetled(register struct kbddata
*kbdd
)
1060 if (kbdd
->kbdd_state
.k_id
== KB_SUN4
||
1061 kbdd
->kbdd_state
.k_id
== KB_PC
) {
1062 kbdcmd(kbdd
->kbdd_writeq
, KBD_CMD_SETLED
);
1063 kbdcmd(kbdd
->kbdd_writeq
, kbdd
->led_state
);
1068 * Reset the keyboard
1071 kbdreset(register struct kbddata
*kbdd
, uint_t hard_reset
)
1073 register struct keyboardstate
*k
;
1075 k
= &kbdd
->kbdd_state
;
1076 if (kbdd
->kbdd_translatable
) {
1077 k
->k_idstate
= KID_NONE
;
1079 k
->k_state
= NORMAL
;
1081 kbdcmd(kbdd
->kbdd_writeq
, KBD_CMD_RESET
);
1083 bzero(k
, sizeof (struct keyboardstate
));
1085 k
->k_idstate
= KID_OK
;
1090 * Old special codes.
1092 #define OLD_SHIFTKEYS 0x80
1093 #define OLD_BUCKYBITS 0x90
1094 #define OLD_FUNNY 0xA0
1095 #define OLD_FA_UMLAUT 0xA9
1096 #define OLD_FA_CFLEX 0xAA
1097 #define OLD_FA_TILDE 0xAB
1098 #define OLD_FA_CEDILLA 0xAC
1099 #define OLD_FA_ACUTE 0xAD
1100 #define OLD_FA_GRAVE 0xAE
1101 #define OLD_ISOCHAR 0xAF
1102 #define OLD_STRING 0xB0
1103 #define OLD_LEFTFUNC 0xC0
1104 #define OLD_RIGHTFUNC 0xD0
1105 #define OLD_TOPFUNC 0xE0
1106 #define OLD_BOTTOMFUNC 0xF0
1109 * Map old special codes to new ones.
1110 * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F.
1112 static ushort_t special_old_to_new
[] = {
1124 * Set individual keystation translation from old-style entry.
1125 * TODO: Have each keyboard own own translation tables.
1128 kbdsetkey(register struct kbddata
*kbdd
, struct kiockey
*key
, cred_t
*cr
)
1132 register int tablemask
;
1133 register ushort_t entry
;
1135 if (key
->kio_station
>= KEYMAP_SIZE
)
1137 if (kbdd
->kbdd_state
.k_curkeyboard
== NULL
)
1139 tablemask
= key
->kio_tablemask
;
1140 if (tablemask
== KIOCABORT1
) {
1141 if (secpolicy_console(cr
) != 0)
1143 kbdd
->kbdd_state
.k_curkeyboard
->k_abort1
= key
->kio_station
;
1146 if (tablemask
== KIOCABORT2
) {
1147 if (secpolicy_console(cr
) != 0)
1149 kbdd
->kbdd_state
.k_curkeyboard
->k_abort2
= key
->kio_station
;
1152 if ((tablemask
& ALTGRAPHMASK
) ||
1153 (km
= settable(kbdd
, (uint_t
)tablemask
)) == NULL
)
1155 if (key
->kio_entry
>= (uchar_t
)OLD_STRING
&&
1156 key
->kio_entry
<= (uchar_t
)(OLD_STRING
+ 15)) {
1157 strtabindex
= key
->kio_entry
- OLD_STRING
;
1158 for (i
= 0; i
< KTAB_STRLEN
; i
++)
1159 keystringtab
[strtabindex
][i
] = key
->kio_string
[i
];
1160 keystringtab
[strtabindex
][KTAB_STRLEN
-1] = '\0';
1162 entry
= key
->kio_entry
;
1164 * There's nothing we need do with OLD_ISOCHAR.
1166 if (entry
!= OLD_ISOCHAR
) {
1168 if (entry
>= OLD_FA_UMLAUT
&& entry
<= OLD_FA_GRAVE
)
1169 entry
= FA_CLASS
+ (entry
& 0x0F) - 9;
1172 special_old_to_new
[entry
>> 4 & 0x07]
1176 km
->keymap
[key
->kio_station
] = entry
;
1181 * Map new special codes to old ones.
1182 * Indexed by (new special code) >> 8; add (new special code) & 0xFF.
1184 static uchar_t special_new_to_old
[] = {
1186 OLD_SHIFTKEYS
, /* SHIFTKEYS */
1187 OLD_BUCKYBITS
, /* BUCKYBITS */
1188 OLD_FUNNY
, /* FUNNY */
1189 OLD_FA_UMLAUT
, /* FA_CLASS */
1190 OLD_STRING
, /* STRING */
1191 OLD_LEFTFUNC
, /* FUNCKEYS */
1195 * Get individual keystation translation as old-style entry.
1198 kbdgetkey(register struct kbddata
*kbdd
, struct kiockey
*key
)
1202 register ushort_t entry
;
1204 if (key
->kio_station
>= KEYMAP_SIZE
)
1206 if (kbdd
->kbdd_state
.k_curkeyboard
== NULL
)
1208 if (key
->kio_tablemask
== KIOCABORT1
) {
1209 key
->kio_station
= kbdd
->kbdd_state
.k_curkeyboard
->k_abort1
;
1212 if (key
->kio_tablemask
== KIOCABORT2
) {
1213 key
->kio_station
= kbdd
->kbdd_state
.k_curkeyboard
->k_abort2
;
1216 if ((km
= settable(kbdd
, (uint_t
)key
->kio_tablemask
)) == NULL
)
1218 entry
= km
->keymap
[key
->kio_station
];
1221 special_new_to_old
[(ushort_t
)(entry
& 0xFF00) >> 8]
1225 key
->kio_entry
= (ushort_t
)OLD_ISOCHAR
; /* you lose */
1227 key
->kio_entry
= (ushort_t
)entry
;
1229 if (entry
>= STRING
&& entry
<= (uchar_t
)(STRING
+ 15)) {
1230 strtabindex
= entry
- STRING
;
1231 for (i
= 0; i
< KTAB_STRLEN
; i
++)
1232 key
->kio_string
[i
] = keystringtab
[strtabindex
][i
];
1238 * Set individual keystation translation from new-style entry.
1239 * TODO: Have each keyboard own own translation tables.
1242 kbdskey(register struct kbddata
*kbdd
, struct kiockeymap
*key
, cred_t
*cr
)
1247 if (key
->kio_station
>= KEYMAP_SIZE
)
1249 if (kbdd
->kbdd_state
.k_curkeyboard
== NULL
)
1251 if (key
->kio_tablemask
== KIOCABORT1
) {
1252 if (secpolicy_console(cr
) != 0)
1254 kbdd
->kbdd_state
.k_curkeyboard
->k_abort1
= key
->kio_station
;
1257 if (key
->kio_tablemask
== KIOCABORT2
) {
1258 if (secpolicy_console(cr
) != 0)
1260 kbdd
->kbdd_state
.k_curkeyboard
->k_abort2
= key
->kio_station
;
1263 if ((km
= settable(kbdd
, (uint_t
)key
->kio_tablemask
)) == NULL
)
1265 if (key
->kio_entry
>= STRING
&&
1266 key
->kio_entry
<= (ushort_t
)(STRING
+ 15)) {
1267 strtabindex
= key
->kio_entry
-STRING
;
1268 for (i
= 0; i
< KTAB_STRLEN
; i
++)
1269 keystringtab
[strtabindex
][i
] = key
->kio_string
[i
];
1270 keystringtab
[strtabindex
][KTAB_STRLEN
-1] = '\0';
1272 km
->keymap
[key
->kio_station
] = key
->kio_entry
;
1277 * Get individual keystation translation as new-style entry.
1280 kbdgkey(register struct kbddata
*kbdd
, struct kiockeymap
*key
)
1285 if (key
->kio_station
>= KEYMAP_SIZE
)
1287 if (kbdd
->kbdd_state
.k_curkeyboard
== NULL
)
1289 if (key
->kio_tablemask
== KIOCABORT1
) {
1290 key
->kio_station
= kbdd
->kbdd_state
.k_curkeyboard
->k_abort1
;
1293 if (key
->kio_tablemask
== KIOCABORT2
) {
1294 key
->kio_station
= kbdd
->kbdd_state
.k_curkeyboard
->k_abort2
;
1297 if ((km
= settable(kbdd
, (uint_t
)key
->kio_tablemask
)) == NULL
)
1299 key
->kio_entry
= km
->keymap
[key
->kio_station
];
1300 if (key
->kio_entry
>= STRING
&&
1301 key
->kio_entry
<= (ushort_t
)(STRING
+ 15)) {
1302 strtabindex
= key
->kio_entry
-STRING
;
1303 for (i
= 0; i
< KTAB_STRLEN
; i
++)
1304 key
->kio_string
[i
] = keystringtab
[strtabindex
][i
];
1310 kbdlayouttimeout(void *arg
)
1312 struct kbddata
*kbdd
= arg
;
1315 kbdd
->kbdd_layoutid
= 0;
1318 * Timed out waiting for reply to "get keyboard layout" command.
1319 * Return an ETIME error.
1321 if ((mp
= kbdd
->kbdd_replypending
) != NULL
) {
1322 kbdd
->kbdd_replypending
= NULL
;
1323 mp
->b_datap
->db_type
= M_IOCNAK
;
1324 ((struct iocblk
*)mp
->b_rptr
)->ioc_error
= ETIME
;
1325 putnext(kbdd
->kbdd_readq
, mp
);
1330 * Put procedure for input from driver end of stream (read queue).
1333 kbdrput(register queue_t
*q
, register mblk_t
*mp
)
1335 struct kbddata
*kbdd
= (struct kbddata
*)q
->q_ptr
;
1336 register mblk_t
*bp
;
1337 register uchar_t
*readp
;
1338 struct iocblk
*iocp
;
1341 freemsg(mp
); /* nobody's listening */
1345 switch (mp
->b_datap
->db_type
) {
1348 if (*mp
->b_rptr
& FLUSHW
)
1349 flushq(WR(q
), FLUSHDATA
);
1350 if (*mp
->b_rptr
& FLUSHR
)
1351 flushq(q
, FLUSHDATA
);
1359 * Will get M_BREAK only if this is not the system
1360 * keyboard, otherwise serial port will eat break
1361 * and call kmdb/OBP, without passing anything up.
1369 * If we are doing an "ioctl" ourselves, check if this
1370 * is the reply to that code. If so, wake up the
1371 * "open" routine, and toss the reply, otherwise just
1374 iocp
= (struct iocblk
*)mp
->b_rptr
;
1375 if (!(kbdd
->kbdd_flags
& KBD_IOCWAIT
) ||
1376 iocp
->ioc_id
!= kbdd
->kbdd_iocid
) {
1378 * This isn't the reply we're looking for. Move along.
1380 if (kbdd
->kbdd_flags
& KBD_OPEN
)
1383 freemsg(mp
); /* not ready to listen */
1385 kbdd
->kbdd_flags
&= ~KBD_IOCWAIT
;
1386 kbdd
->kbdd_iocerror
= iocp
->ioc_error
;
1392 if (!(kbdd
->kbdd_flags
& KBD_OPEN
)) {
1393 freemsg(mp
); /* not read to listen */
1400 * A data message, consisting of bytes from the keyboard.
1401 * Ram them through our state machine.
1407 while (readp
< bp
->b_wptr
)
1408 kbdinput(kbdd
, *readp
++);
1410 } while ((bp
= bp
->b_cont
) != NULL
); /* next block, if any */
1416 * A keypress was received. Process it through the state machine
1417 * to check for aborts.
1420 kbdinput(register struct kbddata
*kbdd
, register unsigned key
)
1422 register struct keyboardstate
*k
;
1423 register mblk_t
*mp
;
1425 k
= &kbdd
->kbdd_state
;
1427 if (kbd_input_debug
)
1428 printf("kbdinput key %x\n", key
);
1431 switch (k
->k_idstate
) {
1434 if (key
== RESETKEY
) {
1435 k
->k_idstate
= KID_GOT_PREFACE
;
1437 kbdreset(kbdd
, HARD_RESET
);
1438 /* allows hot plug of kbd after booting without kbd */
1442 case KID_GOT_PREFACE
:
1443 kbdid(kbdd
, (int)key
);
1446 * We just did a reset command to a Type 3 or Type 4
1447 * keyboard which sets the click back to the default
1448 * (which is currently ON!). We use the kbdclick
1449 * variable to see if the keyboard should be turned on
1450 * or off. If it has not been set, then we use the
1451 * keyboard-click? property.
1455 kbdcmd(kbdd
->kbdd_writeq
, KBD_CMD_NOCLICK
);
1458 kbdcmd(kbdd
->kbdd_writeq
, KBD_CMD_CLICK
);
1466 kbdcmd(kbdd
->kbdd_writeq
, KBD_CMD_NOCLICK
);
1470 if (ddi_getlongprop_buf(DDI_DEV_T_ANY
,
1471 ddi_root_node(), 0, "keyboard-click?",
1472 (caddr_t
)wrkbuf
, &len
) ==
1474 len
> 0 && len
< 8) {
1475 if (strcmp(wrkbuf
, "true") == 0) {
1476 kbdcmd(kbdd
->kbdd_writeq
,
1484 * A keyboard reset clears the LEDs.
1485 * Restore the LEDs from the last value we set
1494 #if defined(KBD_PRESSED_PREFIX)
1495 case KBD_PRESSED_PREFIX
:
1496 k
->k_idstate
= KID_GOT_PRESSED
;
1500 #if defined(KBD_RELEASED_PREFIX)
1501 case KBD_RELEASED_PREFIX
:
1502 k
->k_idstate
= KID_GOT_RELEASED
;
1507 kbdreset(kbdd
, HARD_RESET
);
1511 * we want to check for ID only if we are in
1512 * translatable mode.
1515 kbdreset(kbdd
, NO_HARD_RESET
);
1516 if (k
->k_idstate
== KID_NONE
) {
1517 k
->k_idstate
= KID_GOT_PREFACE
;
1522 k
->k_idstate
= KID_GOT_LAYOUT
;
1527 #if defined(KBD_PRESSED_PREFIX)
1528 case KID_GOT_PRESSED
:
1529 key
= BUILDKEY(key
, PRESSED
);
1530 k
->k_idstate
= KID_OK
;
1533 #if defined(KBD_RELEASED_PREFIX)
1534 case KID_GOT_RELEASED
:
1535 key
= BUILDKEY(key
, RELEASED
);
1536 k
->k_idstate
= KID_OK
;
1540 case KID_GOT_LAYOUT
:
1541 if (kbdd
->kbdd_layoutid
)
1542 (void) quntimeout(kbdd
->kbdd_readq
,
1543 kbdd
->kbdd_layoutid
);
1544 if ((mp
= kbdd
->kbdd_replypending
) != NULL
) {
1545 kbdd
->kbdd_replypending
= NULL
;
1546 *(int *)mp
->b_cont
->b_wptr
= key
;
1547 mp
->b_cont
->b_wptr
+= sizeof (int);
1548 putnext(kbdd
->kbdd_readq
, mp
);
1550 k
->k_idstate
= KID_OK
;
1554 switch (k
->k_state
) {
1556 #if defined(__sparc)
1558 k
->k_state
= NORMAL
;
1562 #if defined(__sparc)
1563 if (k
->k_curkeyboard
) {
1564 if (key
== k
->k_curkeyboard
->k_abort1
) {
1565 k
->k_state
= ABORT1
;
1568 if ((key
== k
->k_curkeyboard
->k_newabort1
) ||
1569 (key
== k
->k_curkeyboard
->k_newabort1a
)) {
1570 k
->k_state
= NEWABORT1
;
1571 kbdd
->shiftkey
= key
;
1578 #if defined(__sparc)
1580 if (k
->k_curkeyboard
) {
1582 * Only recognize this as an abort sequence if
1583 * the "hardware" console is set to be this device.
1585 if (key
== k
->k_curkeyboard
->k_abort2
&&
1586 rconsvp
== wsconsvp
) {
1588 abort_sequence_enter((char *)NULL
);
1589 k
->k_state
= NORMAL
;
1590 kbduse(kbdd
, IDLEKEY
); /* fake */
1593 kbduse(kbdd
, k
->k_curkeyboard
->k_abort1
);
1599 if (k
->k_curkeyboard
) {
1601 * Only recognize this as an abort sequence if
1602 * the "hardware" console is set to be this device.
1604 if (key
== k
->k_curkeyboard
->k_newabort2
&&
1605 rconsvp
== wsconsvp
) {
1607 abort_sequence_enter((char *)NULL
);
1608 k
->k_state
= NORMAL
;
1609 kbdd
->shiftkey
|= RELEASED
;
1610 kbduse(kbdd
, kbdd
->shiftkey
);
1611 kbduse(kbdd
, IDLEKEY
); /* fake */
1630 kbdid(register struct kbddata
*kbdd
, int id
)
1632 register struct keyboardstate
*k
;
1635 k
= &kbdd
->kbdd_state
;
1637 k
->k_idstate
= KID_OK
;
1642 * Reset k_rptkey to IDLEKEY. We need to cancel
1643 * the autorepeat feature, if any.
1645 if (k
->k_rptkey
!= IDLEKEY
) {
1646 if (kbdd
->kbdd_rptid
)
1647 (void) quntimeout(kbdd
->kbdd_readq
, kbdd
->kbdd_rptid
);
1648 kbdd
->kbdd_rptid
= 0;
1649 k
->k_rptkey
= IDLEKEY
;
1652 k
->k_curkeyboard
= NULL
;
1653 for (i
= 0; keytables
[i
].table
; i
++) {
1654 if (keytables
[i
].id
== id
) {
1656 k
->k_curkeyboard
= keytables
[i
].table
;
1660 if (!k
->k_curkeyboard
) {
1661 k
->k_id
= keytables
[0].id
;
1662 k
->k_curkeyboard
= keytables
[0].table
;
1663 cmn_err(CE_WARN
, "kbd: Unknown keyboard type, "
1664 "Type %d assumed", k
->k_id
);
1669 * This routine determines which table we should look in to decode
1670 * the current keycode.
1672 static struct keymap
*
1673 settable(register struct kbddata
*kbdd
, register uint_t mask
)
1675 register struct keyboard
*kp
;
1677 kp
= kbdd
->kbdd_state
.k_curkeyboard
;
1682 if (mask
& NUMLOCKMASK
)
1683 return (kp
->k_numlock
);
1684 if (mask
& CTRLMASK
)
1685 return (kp
->k_control
);
1686 if (mask
& ALTGRAPHMASK
)
1687 return (kp
->k_altgraph
);
1688 if (mask
& SHIFTMASK
)
1689 return (kp
->k_shifted
);
1690 if (mask
& CAPSMASK
)
1691 return (kp
->k_caps
);
1692 return (kp
->k_normal
);
1698 struct kbddata
*kbdd
= arg
;
1699 struct keyboardstate
*k
;
1701 k
= &kbdd
->kbdd_state
;
1704 printf("kbdrpt key %x\n", k
->k_rptkey
);
1706 kbdd
->kbdd_rptid
= 0;
1708 kbdkeyreleased(kbdd
, KEYOF(k
->k_rptkey
));
1709 kbduse(kbdd
, k
->k_rptkey
);
1710 if (k
->k_rptkey
!= IDLEKEY
) {
1711 kbdd
->kbdd_rptid
= qtimeout(kbdd
->kbdd_readq
, kbdrpt
,
1712 kbdd
, kbd_repeatrate
);
1717 kbdcancelrpt(register struct kbddata
*kbdd
)
1719 register struct keyboardstate
*k
;
1721 k
= &kbdd
->kbdd_state
;
1722 if (k
->k_rptkey
!= IDLEKEY
) {
1723 if (kbdd
->kbdd_rptid
)
1724 (void) quntimeout(kbdd
->kbdd_readq
, kbdd
->kbdd_rptid
);
1725 kbdd
->kbdd_rptid
= 0;
1726 k
->k_rptkey
= IDLEKEY
;
1728 ASSERT(kbdd
->kbdd_rptid
== 0);
1732 kbdtranslate(struct kbddata
*kbdd
, unsigned keycode
, queue_t
*q
)
1734 register uchar_t key
;
1735 register unsigned newstate
;
1737 register ushort_t entry
, entrytype
;
1738 register char *cp
, *bufp
;
1739 register struct keyboardstate
*k
;
1740 ushort_t result_iso
;
1746 k
= &kbdd
->kbdd_state
;
1747 newstate
= STATEOF(keycode
);
1748 key
= KEYOF(keycode
);
1751 if (kbd_input_debug
) {
1752 printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n",
1753 keycode
, newstate
, key
);
1757 if (kbdd
->kbdd_translate
== TR_UNTRANS_EVENT
) {
1758 if (newstate
== PRESSED
) {
1759 bzero(&fe
, sizeof (fe
));
1762 kbdqueuepress(kbdd
, key
, &fe
);
1764 kbdkeyreleased(kbdd
, key
);
1769 shiftmask
= k
->k_shiftmask
;
1770 if (newstate
== RELEASED
)
1771 shiftmask
|= UPMASK
;
1773 km
= settable(kbdd
, shiftmask
);
1774 if (km
== NULL
) { /* gross error */
1779 if (key
>= KEYMAP_SIZE
)
1781 entry
= km
->keymap
[key
];
1783 if (entry
== NONL
) {
1785 * NONL appears only in the Num Lock table, and indicates that
1786 * this key is not affected by Num Lock. This means we should
1787 * ask for the table we would have gotten had Num Lock not been
1788 * down, and translate using that table.
1790 km
= settable(kbdd
, shiftmask
& ~NUMLOCKMASK
);
1791 if (km
== NULL
) { /* gross error */
1795 entry
= km
->keymap
[key
];
1797 entrytype
= (ushort_t
)(entry
& 0xFF00) >> 8;
1799 if (entrytype
== (SHIFTKEYS
>> 8)) {
1801 * Handle the state of toggle shifts specially.
1802 * Ups should be ignored, and downs should be mapped to ups if
1803 * that shift is currently on.
1805 if ((1 << (entry
& 0x0F)) & k
->k_curkeyboard
->k_toggleshifts
) {
1806 if ((1 << (entry
& 0x0F)) & k
->k_togglemask
) {
1807 newstate
= RELEASED
; /* toggling off */
1809 newstate
= PRESSED
; /* toggling on */
1814 * Handle Compose and floating accent key sequences
1816 if (k
->k_state
== COMPOSE1
) {
1817 if (newstate
== RELEASED
)
1819 if (entry
< ASCII_SET_SIZE
) {
1820 if (kb_compose_map
[entry
] >= 0) {
1821 kbdd
->compose_key
= entry
;
1822 k
->k_state
= COMPOSE2
;
1826 k
->k_state
= NORMAL
;
1827 kbdd
->led_state
&= ~LED_COMPOSE
;
1830 } else if (k
->k_state
== COMPOSE2
) {
1831 if (newstate
== RELEASED
)
1833 k
->k_state
= NORMAL
; /* next state is "normal" */
1834 kbdd
->led_state
&= ~LED_COMPOSE
;
1836 if (entry
< ASCII_SET_SIZE
) {
1837 if (kb_compose_map
[entry
] >= 0) {
1838 if (kbdd
->compose_key
<= entry
) {
1839 ret_val
= kbd_do_compose(
1844 ret_val
= kbd_do_compose(
1850 if (kbdd
->kbdd_translate
==
1853 (kbdd
->kbdd_compat
?
1862 kbdd
->kbdd_translate
==
1871 } else if (k
->k_state
== FLTACCENT
) {
1872 if (newstate
== RELEASED
)
1874 k
->k_state
= NORMAL
; /* next state is "normal" */
1876 (kb_fltaccent_table
[i
].fa_entry
1877 != kbdd
->fltaccent_entry
) ||
1878 (kb_fltaccent_table
[i
].ascii
!= entry
);
1880 if (kb_fltaccent_table
[i
].fa_entry
== 0)
1881 /* Invalid second key: ignore key */
1884 if (kbdd
->kbdd_translate
== TR_EVENT
) {
1885 fe
.id
= (kbdd
->kbdd_compat
?
1886 ISO_FIRST
: EUC_FIRST
)
1887 + kb_fltaccent_table
[i
].iso
;
1889 kbdqueueevent(kbdd
, &fe
);
1890 } else if (kbdd
->kbdd_translate
== TR_ASCII
)
1891 kbdputcode(kb_fltaccent_table
[i
].iso
, q
);
1897 * If the key is going down, and it's not one of the keys that doesn't
1898 * auto-repeat, set up the auto-repeat timeout.
1900 * The keys that don't auto-repeat are the Compose key,
1901 * the shift keys, the "bucky bit" keys, the "floating accent" keys,
1902 * and the function keys when in TR_EVENT mode.
1904 if (newstate
== PRESSED
&& entrytype
!= (SHIFTKEYS
>> 8) &&
1905 entrytype
!= (BUCKYBITS
>> 8) && entrytype
!= (FUNNY
>> 8) &&
1906 entrytype
!= (FA_CLASS
>> 8) &&
1907 !((entrytype
== (FUNCKEYS
>> 8) || entrytype
== (PADKEYS
>> 8)) &&
1908 kbdd
->kbdd_translate
== TR_EVENT
)) {
1909 if (k
->k_rptkey
!= keycode
) {
1911 kbdd
->kbdd_rptid
= qtimeout(q
, kbdrpt
, kbdd
,
1913 k
->k_rptkey
= keycode
;
1915 } else if (key
== KEYOF(k
->k_rptkey
)) /* key going up */
1917 if ((newstate
== RELEASED
) && (kbdd
->kbdd_translate
== TR_EVENT
))
1918 kbdkeyreleased(kbdd
, key
);
1921 * We assume here that keys other than shift keys and bucky keys have
1922 * entries in the "up" table that cause nothing to be done, and thus we
1923 * don't have to check for newstate == RELEASED.
1925 switch (entrytype
) {
1927 case 0x0: /* regular key */
1928 switch (kbdd
->kbdd_translate
) {
1931 fe
.id
= entry
| k
->k_buckybits
;
1933 kbdkeypressed(kbdd
, key
, &fe
, entry
);
1937 kbdputcode(entry
| k
->k_buckybits
, q
);
1942 case SHIFTKEYS
>> 8: {
1943 uint_t shiftbit
= 1 << (entry
& 0x0F);
1945 /* Modify toggle state (see toggle processing above) */
1946 if (shiftbit
& k
->k_curkeyboard
->k_toggleshifts
) {
1947 if (newstate
== RELEASED
) {
1948 if (shiftbit
== CAPSMASK
) {
1949 kbdd
->led_state
&= ~LED_CAPS_LOCK
;
1951 } else if (shiftbit
== NUMLOCKMASK
) {
1952 kbdd
->led_state
&= ~LED_NUM_LOCK
;
1955 k
->k_togglemask
&= ~shiftbit
;
1957 if (shiftbit
== CAPSMASK
) {
1958 kbdd
->led_state
|= LED_CAPS_LOCK
;
1960 } else if (shiftbit
== NUMLOCKMASK
) {
1961 kbdd
->led_state
|= LED_NUM_LOCK
;
1964 k
->k_togglemask
|= shiftbit
;
1968 if (newstate
== RELEASED
)
1969 k
->k_shiftmask
&= ~shiftbit
;
1971 k
->k_shiftmask
|= shiftbit
;
1973 if (kbdd
->kbdd_translate
== TR_EVENT
&& newstate
== PRESSED
) {
1975 * Relying on ordinal correspondence between
1976 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
1977 * kbd.h CAPSLOCK-RIGHTCTRL in order to
1978 * correctly translate entry into fe.id.
1980 fe
.id
= SHIFT_CAPSLOCK
+ (entry
& 0x0F);
1982 kbdkeypressed(kbdd
, key
, &fe
, fe
.id
);
1987 case BUCKYBITS
>> 8:
1988 k
->k_buckybits
^= 1 << (7 + (entry
& 0x0F));
1989 if (kbdd
->kbdd_translate
== TR_EVENT
&& newstate
== PRESSED
) {
1991 * Relying on ordinal correspondence between
1992 * vuid_event.h SHIFT_META-SHIFT_TOP &
1993 * kbd.h METABIT-SYSTEMBIT in order to
1994 * correctly translate entry into fe.id.
1996 fe
.id
= SHIFT_META
+ (entry
& 0x0F);
1998 kbdkeypressed(kbdd
, key
, &fe
, fe
.id
);
2008 /* Fall thru into RESET code */
2012 k
->k_shiftmask
&= k
->k_curkeyboard
->k_idleshifts
;
2013 k
->k_shiftmask
|= k
->k_togglemask
;
2014 k
->k_buckybits
&= k
->k_curkeyboard
->k_idlebuckys
;
2016 kbdreleaseall(kbdd
);
2020 cmn_err(CE_WARN
, "kbd: Error detected");
2024 k
->k_state
= COMPOSE1
;
2025 kbdd
->led_state
|= LED_COMPOSE
;
2029 * Remember when adding new entries that,
2030 * if they should NOT auto-repeat,
2031 * they should be put into the IF statement
2032 * just above this switch block.
2040 if (k
->k_state
== NORMAL
) {
2041 kbdd
->fltaccent_entry
= entry
;
2042 k
->k_state
= FLTACCENT
;
2047 cp
= &keystringtab
[entry
& 0x0F][0];
2048 while (*cp
!= '\0') {
2049 switch (kbdd
->kbdd_translate
) {
2052 kbd_send_esc_event(*cp
, kbdd
);
2056 kbdputcode((uchar_t
)*cp
, q
);
2064 switch (kbdd
->kbdd_translate
) {
2068 cp
= strsetwithdecimal(bufp
+ 2,
2069 (uint_t
)((entry
& 0x003F) + 192),
2071 *bufp
++ = '\033'; /* Escape */
2082 * Take advantage of the similar
2083 * ordering of kbd.h function keys and
2084 * vuid_event.h function keys to do a
2085 * simple translation to achieve a
2086 * mapping between the 2 different
2089 fe
.id
= (entry
& 0x003F) + KEY_LEFTFIRST
;
2092 * Assume "up" table only generates
2095 kbdkeypressed(kbdd
, key
, &fe
, fe
.id
);
2097 * Function key events can be expanded
2098 * by terminal emulator software to
2099 * produce the standard escape sequence
2100 * generated by the TR_ASCII case above
2101 * if a function key event is not used
2102 * by terminal emulator software
2110 * Remember when adding new entries that,
2111 * if they should NOT auto-repeat,
2112 * they should be put into the IF statement
2113 * just above this switch block.
2116 switch (kbdd
->kbdd_translate
) {
2119 kbdputcode(kb_numlock_table
[entry
&0x1F], q
);
2124 * Take advantage of the similar
2125 * ordering of kbd.h keypad keys and
2126 * vuid_event.h keypad keys to do a
2127 * simple translation to achieve a
2128 * mapping between the 2 different
2131 fe
.id
= (entry
& 0x001F) + VKEY_FIRSTPAD
;
2134 * Assume "up" table only generates
2137 kbdkeypressed(kbdd
, key
, &fe
, fe
.id
);
2139 * Keypad key events can be expanded
2140 * by terminal emulator software to
2141 * produce the standard ascii character
2142 * generated by the TR_ASCII case above
2143 * if a keypad key event is not used
2144 * by terminal emulator software
2156 kbd_do_compose(ushort_t first_entry
, ushort_t second_entry
,
2157 ushort_t
*result_iso_ptr
)
2159 struct compose_sequence_t
*ptr
;
2161 ptr
= &kb_compose_table
[kb_compose_map
[first_entry
]];
2162 while (ptr
->first
== first_entry
) {
2163 if (ptr
->second
== second_entry
) {
2164 *result_iso_ptr
= ptr
->iso
;
2173 kbd_send_esc_event(char c
, register struct kbddata
*kbdd
)
2179 fe
.pair_type
= FE_PAIR_NONE
;
2182 * Pretend as if each cp pushed and released
2183 * Calling kbdqueueevent avoids addr translation
2184 * and pair base determination of kbdkeypressed.
2186 kbdqueueevent(kbdd
, &fe
);
2188 kbdqueueevent(kbdd
, &fe
);
2192 strsetwithdecimal(char *buf
, uint_t val
, uint_t maxdigs
)
2197 char *tab
= "0123456789abcdef";
2204 *(--bp
) = tab
[val
% hradix
* 2 + lowbit
];
2211 kbdkeypressed(struct kbddata
*kbdd
, uchar_t key_station
, Firm_event
*fe
,
2214 register struct keyboardstate
*k
;
2215 register short id_addr
;
2217 /* Set pair values */
2218 if (fe
->id
< (ushort_t
)VKEY_FIRST
) {
2220 * If CTRLed, find the ID that would have been used had it
2223 k
= &kbdd
->kbdd_state
;
2224 if (k
->k_shiftmask
& (CTRLMASK
| CTLSMASK
)) {
2228 k
->k_shiftmask
& ~(CTRLMASK
| CTLSMASK
| UPMASK
));
2231 base
= km
->keymap
[key_station
];
2233 if (base
!= fe
->id
) {
2234 fe
->pair_type
= FE_PAIR_SET
;
2239 fe
->pair_type
= FE_PAIR_NONE
;
2242 /* Adjust event id address for multiple keyboard/workstation support */
2243 switch (vuid_id_addr(fe
->id
)) {
2245 id_addr
= kbdd
->kbdd_ascii_addr
;
2248 id_addr
= kbdd
->kbdd_top_addr
;
2251 id_addr
= kbdd
->kbdd_vkey_addr
;
2254 id_addr
= vuid_id_addr(fe
->id
);
2256 fe
->id
= vuid_id_offset(fe
->id
) | id_addr
;
2257 kbdqueuepress(kbdd
, key_station
, fe
);
2261 kbdqueuepress(struct kbddata
*kbdd
, uchar_t key_station
, Firm_event
*fe
)
2263 register struct key_event
*ke
, *ke_free
;
2266 if (key_station
== IDLEKEY
)
2269 if (kbd_input_debug
) printf("KBD PRESSED key=%d\n", key_station
);
2272 /* Scan table of down key stations */
2273 if (kbdd
->kbdd_translate
== TR_EVENT
||
2274 kbdd
->kbdd_translate
== TR_UNTRANS_EVENT
) {
2275 for (i
= 0, ke
= kbdd
->kbdd_downs
;
2276 i
< kbdd
->kbdd_downs_entries
;
2278 /* Keycode already down? */
2279 if (ke
->key_station
== key_station
) {
2281 printf("kbd: Double entry in downs table (%d,%d)!\n", key_station
, i
);
2285 if (ke
->key_station
== 0)
2292 cmn_err(CE_WARN
, "kbd: Too many keys down!");
2293 ke
= kbdd
->kbdd_downs
;
2296 ke
->key_station
= key_station
;
2298 kbdqueueevent(kbdd
, fe
);
2302 kbdkeyreleased(register struct kbddata
*kbdd
, uchar_t key_station
)
2304 register struct key_event
*ke
;
2307 if (key_station
== IDLEKEY
)
2310 if (kbd_input_debug
)
2311 printf("KBD RELEASE key=%d\n", key_station
);
2313 if (kbdd
->kbdd_translate
!= TR_EVENT
&&
2314 kbdd
->kbdd_translate
!= TR_UNTRANS_EVENT
)
2316 /* Scan table of down key stations */
2317 for (i
= 0, ke
= kbdd
->kbdd_downs
;
2318 i
< kbdd
->kbdd_downs_entries
;
2321 if (ke
->key_station
== key_station
) {
2322 ke
->key_station
= 0;
2323 ke
->event
.value
= 0;
2324 kbdqueueevent(kbdd
, &ke
->event
);
2329 * Ignore if couldn't find because may be called twice
2330 * for the same key station in the case of the kbdrpt
2331 * routine being called unnecessarily.
2336 kbdreleaseall(struct kbddata
*kbdd
)
2338 register struct key_event
*ke
;
2342 if (kbd_debug
&& kbd_ra_debug
) printf("KBD RELEASE ALL\n");
2344 /* Scan table of down key stations */
2345 for (i
= 0, ke
= kbdd
->kbdd_downs
;
2346 i
< kbdd
->kbdd_downs_entries
; i
++, ke
++) {
2347 /* Key station not zero */
2348 if (ke
->key_station
)
2349 kbdkeyreleased(kbdd
, ke
->key_station
);
2350 /* kbdkeyreleased resets kbdd_downs entry */
2355 * Pass a keycode up the stream, if you can, otherwise throw it away.
2358 kbdputcode(uint_t code
, queue_t
*q
)
2360 register mblk_t
*bp
;
2363 cmn_err(CE_WARN
, "kbdputcode: Can't put block for keycode");
2365 if ((bp
= allocb(sizeof (uint_t
), BPRI_HI
)) == NULL
)
2367 "kbdputcode: Can't allocate block for keycode");
2369 *bp
->b_wptr
++ = code
;
2376 * Pass generated keycode sequence to upstream, if possible.
2379 kbdputbuf(char *buf
, queue_t
*q
)
2381 register mblk_t
*bp
;
2384 cmn_err(CE_WARN
, "kbdputbuf: Can't put block for keycode");
2386 if ((bp
= allocb((int)strlen(buf
), BPRI_HI
)) == NULL
)
2388 "kbdputbuf: Can't allocate block for keycode");
2391 *bp
->b_wptr
++ = *buf
;
2400 * Pass a VUID "firm event" up the stream, if you can.
2403 kbdqueueevent(struct kbddata
*kbdd
, Firm_event
*fe
)
2405 register queue_t
*q
;
2406 register mblk_t
*bp
;
2408 if ((q
= kbdd
->kbdd_readq
) == NULL
)
2411 if (kbd_overflow_msg
)
2413 "kbd: Buffer flushed when overflowed");
2417 if ((bp
= allocb(sizeof (Firm_event
), BPRI_HI
)) == NULL
)
2419 "kbdqueueevent: Can't allocate block for event");
2425 * XX64: This is something of a compromise. It
2426 * seems justifiable based on the usage of these
2427 * timestamps as an ordering relation as opposed
2428 * to a strict timing thing.
2430 * But should we restore Firm_event's time stamp
2431 * to be a timeval, and send 32-bit and 64-bit
2432 * events up the pipe?
2435 TIMEVAL_TO_TIMEVAL32(&fe
->time
, &now
);
2437 uniqtime(&fe
->time
);
2439 *(Firm_event
*)bp
->b_wptr
= *fe
;
2440 bp
->b_wptr
+= sizeof (Firm_event
);