1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Generic keyboard support:  streams and administration.
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #define	KEYMAP_SIZE_VARIABLE
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/kbd.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/kbio.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/consdev.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/kbtrans.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/policy.h>
51*7c478bd9Sstevel@tonic-gate #include "kbtrans_lower.h"
52*7c478bd9Sstevel@tonic-gate #include "kbtrans_streams.h"
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
55*7c478bd9Sstevel@tonic-gate int	kbtrans_errmask;
56*7c478bd9Sstevel@tonic-gate int	kbtrans_errlevel;
57*7c478bd9Sstevel@tonic-gate #endif
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate /*
60*7c478bd9Sstevel@tonic-gate  * Repeat rates set in static variables so they can be tweeked with
61*7c478bd9Sstevel@tonic-gate  * debugger.
62*7c478bd9Sstevel@tonic-gate  */
63*7c478bd9Sstevel@tonic-gate static int kbtrans_repeat_rate;
64*7c478bd9Sstevel@tonic-gate static int kbtrans_repeat_delay;
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate /* Printing message on q overflow */
67*7c478bd9Sstevel@tonic-gate static int kbtrans_overflow_msg = 1;
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate /*
70*7c478bd9Sstevel@tonic-gate  * This value corresponds approximately to max 10 fingers
71*7c478bd9Sstevel@tonic-gate  */
72*7c478bd9Sstevel@tonic-gate static int	kbtrans_downs_size = 15;
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate /*
75*7c478bd9Sstevel@tonic-gate  * modload support
76*7c478bd9Sstevel@tonic-gate  */
77*7c478bd9Sstevel@tonic-gate extern struct mod_ops mod_miscops;
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate static struct modlmisc modlmisc	= {
80*7c478bd9Sstevel@tonic-gate 	&mod_miscops,	/* Type	of module */
81*7c478bd9Sstevel@tonic-gate 	"kbtrans (key translation) 1.32"
82*7c478bd9Sstevel@tonic-gate };
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
85*7c478bd9Sstevel@tonic-gate 	MODREV_1, (void	*)&modlmisc, NULL
86*7c478bd9Sstevel@tonic-gate };
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate int
89*7c478bd9Sstevel@tonic-gate _init(void)
90*7c478bd9Sstevel@tonic-gate {
91*7c478bd9Sstevel@tonic-gate 	return (mod_install(&modlinkage));
92*7c478bd9Sstevel@tonic-gate }
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate int
95*7c478bd9Sstevel@tonic-gate _fini(void)
96*7c478bd9Sstevel@tonic-gate {
97*7c478bd9Sstevel@tonic-gate 	return (mod_remove(&modlinkage));
98*7c478bd9Sstevel@tonic-gate }
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate int
101*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
102*7c478bd9Sstevel@tonic-gate {
103*7c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
104*7c478bd9Sstevel@tonic-gate }
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate /*
107*7c478bd9Sstevel@tonic-gate  * Internal Function Prototypes
108*7c478bd9Sstevel@tonic-gate  */
109*7c478bd9Sstevel@tonic-gate static char	*kbtrans_strsetwithdecimal(char *, uint_t, uint_t);
110*7c478bd9Sstevel@tonic-gate static void	kbtrans_set_translation_callback(struct kbtrans *);
111*7c478bd9Sstevel@tonic-gate static void	kbtrans_reioctl(void *);
112*7c478bd9Sstevel@tonic-gate static void	kbtrans_send_esc_event(char, struct kbtrans *);
113*7c478bd9Sstevel@tonic-gate static void	kbtrans_keypressed(struct kbtrans *, uchar_t, Firm_event *,
114*7c478bd9Sstevel@tonic-gate 			ushort_t);
115*7c478bd9Sstevel@tonic-gate static void	kbtrans_putbuf(char *, queue_t *);
116*7c478bd9Sstevel@tonic-gate static void	kbtrans_cancelrpt(struct kbtrans *);
117*7c478bd9Sstevel@tonic-gate static void	kbtrans_queuepress(struct kbtrans *, uchar_t, Firm_event *);
118*7c478bd9Sstevel@tonic-gate static void	kbtrans_putcode(register struct kbtrans *, uint_t);
119*7c478bd9Sstevel@tonic-gate static void	kbtrans_keyreleased(struct kbtrans *, uchar_t);
120*7c478bd9Sstevel@tonic-gate static void	kbtrans_queueevent(struct kbtrans *, Firm_event *);
121*7c478bd9Sstevel@tonic-gate static void	kbtrans_untrans_keypressed_raw(struct kbtrans *, kbtrans_key_t);
122*7c478bd9Sstevel@tonic-gate static void	kbtrans_untrans_keyreleased_raw(struct kbtrans *,
123*7c478bd9Sstevel@tonic-gate 			    kbtrans_key_t);
124*7c478bd9Sstevel@tonic-gate static void	kbtrans_ascii_keypressed(struct kbtrans *, uint_t,
125*7c478bd9Sstevel@tonic-gate 			kbtrans_key_t, uint_t);
126*7c478bd9Sstevel@tonic-gate static void	kbtrans_ascii_keyreleased(struct kbtrans *, kbtrans_key_t);
127*7c478bd9Sstevel@tonic-gate static void	kbtrans_ascii_setup_repeat(struct kbtrans *, uint_t,
128*7c478bd9Sstevel@tonic-gate 			kbtrans_key_t);
129*7c478bd9Sstevel@tonic-gate static void	kbtrans_trans_event_keypressed(struct kbtrans *, uint_t,
130*7c478bd9Sstevel@tonic-gate 			kbtrans_key_t, uint_t);
131*7c478bd9Sstevel@tonic-gate static void	kbtrans_trans_event_keyreleased(struct kbtrans *,
132*7c478bd9Sstevel@tonic-gate 			kbtrans_key_t);
133*7c478bd9Sstevel@tonic-gate static void	kbtrans_trans_event_setup_repeat(struct kbtrans *, uint_t,
134*7c478bd9Sstevel@tonic-gate 			kbtrans_key_t);
135*7c478bd9Sstevel@tonic-gate static void	kbtrans_rpt(void *);
136*7c478bd9Sstevel@tonic-gate static void	kbtrans_setled(struct kbtrans *);
137*7c478bd9Sstevel@tonic-gate static void	kbtrans_flush(struct kbtrans *);
138*7c478bd9Sstevel@tonic-gate static enum kbtrans_message_response 	kbtrans_ioctl(struct kbtrans *upper,
139*7c478bd9Sstevel@tonic-gate 						mblk_t *mp);
140*7c478bd9Sstevel@tonic-gate static int	kbtrans_setkey(struct kbtrans_lower *, struct kiockey *,
141*7c478bd9Sstevel@tonic-gate 			cred_t *);
142*7c478bd9Sstevel@tonic-gate static int	kbtrans_getkey(struct kbtrans_lower *, struct kiockey *);
143*7c478bd9Sstevel@tonic-gate static int	kbtrans_skey(struct kbtrans_lower *, struct kiockeymap *,
144*7c478bd9Sstevel@tonic-gate 				cred_t *cr);
145*7c478bd9Sstevel@tonic-gate static int 	kbtrans_gkey(struct kbtrans_lower *, struct kiockeymap *);
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate /*
148*7c478bd9Sstevel@tonic-gate  * Keyboard Translation Mode (TR_NONE)
149*7c478bd9Sstevel@tonic-gate  *
150*7c478bd9Sstevel@tonic-gate  * Functions to be called when keyboard translation is turned off
151*7c478bd9Sstevel@tonic-gate  * and up/down key codes are reported.
152*7c478bd9Sstevel@tonic-gate  */
153*7c478bd9Sstevel@tonic-gate struct keyboard_callback	untrans_event_callback  = {
154*7c478bd9Sstevel@tonic-gate 	kbtrans_untrans_keypressed_raw,
155*7c478bd9Sstevel@tonic-gate 	kbtrans_untrans_keyreleased_raw,
156*7c478bd9Sstevel@tonic-gate 	NULL,
157*7c478bd9Sstevel@tonic-gate 	NULL,
158*7c478bd9Sstevel@tonic-gate 	NULL,
159*7c478bd9Sstevel@tonic-gate 	NULL,
160*7c478bd9Sstevel@tonic-gate 	NULL,
161*7c478bd9Sstevel@tonic-gate };
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate /*
164*7c478bd9Sstevel@tonic-gate  * Keyboard Translation Mode (TR_ASCII)
165*7c478bd9Sstevel@tonic-gate  *
166*7c478bd9Sstevel@tonic-gate  * Functions to be called when ISO 8859/1 codes are reported
167*7c478bd9Sstevel@tonic-gate  */
168*7c478bd9Sstevel@tonic-gate struct keyboard_callback	ascii_callback  = {
169*7c478bd9Sstevel@tonic-gate 	NULL,
170*7c478bd9Sstevel@tonic-gate 	NULL,
171*7c478bd9Sstevel@tonic-gate 	kbtrans_ascii_keypressed,
172*7c478bd9Sstevel@tonic-gate 	kbtrans_ascii_keyreleased,
173*7c478bd9Sstevel@tonic-gate 	kbtrans_ascii_setup_repeat,
174*7c478bd9Sstevel@tonic-gate 	kbtrans_cancelrpt,
175*7c478bd9Sstevel@tonic-gate 	kbtrans_setled,
176*7c478bd9Sstevel@tonic-gate };
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate /*
179*7c478bd9Sstevel@tonic-gate  * Keyboard Translation Mode (TR_EVENT)
180*7c478bd9Sstevel@tonic-gate  *
181*7c478bd9Sstevel@tonic-gate  * Functions to be called when firm_events are reported.
182*7c478bd9Sstevel@tonic-gate  */
183*7c478bd9Sstevel@tonic-gate struct keyboard_callback	trans_event_callback  = {
184*7c478bd9Sstevel@tonic-gate 	NULL,
185*7c478bd9Sstevel@tonic-gate 	NULL,
186*7c478bd9Sstevel@tonic-gate 	kbtrans_trans_event_keypressed,
187*7c478bd9Sstevel@tonic-gate 	kbtrans_trans_event_keyreleased,
188*7c478bd9Sstevel@tonic-gate 	kbtrans_trans_event_setup_repeat,
189*7c478bd9Sstevel@tonic-gate 	kbtrans_cancelrpt,
190*7c478bd9Sstevel@tonic-gate 	kbtrans_setled,
191*7c478bd9Sstevel@tonic-gate };
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate /*
194*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_init:
195*7c478bd9Sstevel@tonic-gate  *	Initialize the stream, keytables, callbacks, etc.
196*7c478bd9Sstevel@tonic-gate  */
197*7c478bd9Sstevel@tonic-gate int
198*7c478bd9Sstevel@tonic-gate kbtrans_streams_init(
199*7c478bd9Sstevel@tonic-gate 	queue_t 			*q,
200*7c478bd9Sstevel@tonic-gate 	int 				sflag,
201*7c478bd9Sstevel@tonic-gate 	cred_t				*crp,
202*7c478bd9Sstevel@tonic-gate 	struct kbtrans_hardware 	*hw,
203*7c478bd9Sstevel@tonic-gate 	struct kbtrans_callbacks 	*hw_cb,
204*7c478bd9Sstevel@tonic-gate 	struct kbtrans 			**ret_kbd,
205*7c478bd9Sstevel@tonic-gate 	int 				initial_leds,
206*7c478bd9Sstevel@tonic-gate 	int 				initial_led_mask)
207*7c478bd9Sstevel@tonic-gate {
208*7c478bd9Sstevel@tonic-gate 	struct kbtrans *upper;
209*7c478bd9Sstevel@tonic-gate 	struct kbtrans_lower *lower;
210*7c478bd9Sstevel@tonic-gate 	int err;
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 	/*
213*7c478bd9Sstevel@tonic-gate 	 * Default to relatively generic tables.
214*7c478bd9Sstevel@tonic-gate 	 */
215*7c478bd9Sstevel@tonic-gate 	extern signed char			kb_compose_map[];
216*7c478bd9Sstevel@tonic-gate 	extern struct compose_sequence_t	kb_compose_table[];
217*7c478bd9Sstevel@tonic-gate 	extern struct fltaccent_sequence_t	kb_fltaccent_table[];
218*7c478bd9Sstevel@tonic-gate 	extern char				keystringtab[][KTAB_STRLEN];
219*7c478bd9Sstevel@tonic-gate 	extern unsigned char			kb_numlock_table[];
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate 	/* Set these up only once so that they could be changed from adb */
222*7c478bd9Sstevel@tonic-gate 	if (!kbtrans_repeat_rate) {
223*7c478bd9Sstevel@tonic-gate 		kbtrans_repeat_rate = (hz+29)/30;
224*7c478bd9Sstevel@tonic-gate 		kbtrans_repeat_delay = hz/2;
225*7c478bd9Sstevel@tonic-gate 	}
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	/*
228*7c478bd9Sstevel@tonic-gate 	 * Only allow open requests to succeed for privileged users.  This
229*7c478bd9Sstevel@tonic-gate 	 * necessary to prevent users from pushing the this module again
230*7c478bd9Sstevel@tonic-gate 	 * on the stream associated with /dev/kbd.
231*7c478bd9Sstevel@tonic-gate 	 */
232*7c478bd9Sstevel@tonic-gate 	err = secpolicy_console(crp);
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	if (err != 0) {
235*7c478bd9Sstevel@tonic-gate 		return (err);
236*7c478bd9Sstevel@tonic-gate 	}
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 	switch (sflag) {
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	case MODOPEN:
241*7c478bd9Sstevel@tonic-gate 		break;
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	case CLONEOPEN:
244*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L1, PRINT_MASK_OPEN, (NULL,
245*7c478bd9Sstevel@tonic-gate 			"kbtrans_streams_init: Clone open not supported"));
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
248*7c478bd9Sstevel@tonic-gate 	}
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	/* allocate keyboard state structure */
251*7c478bd9Sstevel@tonic-gate 	upper = kmem_zalloc(sizeof (struct kbtrans), KM_SLEEP);
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 	*ret_kbd = upper;
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_polled_buf[0] = '\0';
256*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_polled_pending_chars = upper->kbtrans_polled_buf;
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_hw = hw;
259*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_hw_callbacks = hw_cb;
260*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_readq = q;
261*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_iocpending = NULL;
262*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_translatable = TR_CAN;
263*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_overflow_cnt = 0;
264*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_translate_mode = TR_ASCII;
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	/* Set the translation callback based on the translation type */
267*7c478bd9Sstevel@tonic-gate 	kbtrans_set_translation_callback(upper);
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	lower = &upper->kbtrans_lower;
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 	/*
272*7c478bd9Sstevel@tonic-gate 	 * Set defaults for relatively generic tables.
273*7c478bd9Sstevel@tonic-gate 	 */
274*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_compose_map = kb_compose_map;
275*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_compose_table = kb_compose_table;
276*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_fltaccent_table = kb_fltaccent_table;
277*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_numlock_table = kb_numlock_table;
278*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_keystringtab = keystringtab;
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_upper = upper;
281*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_compat = 1;
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 	/*
284*7c478bd9Sstevel@tonic-gate 	 * We have a generic default for the LED state, and let the
285*7c478bd9Sstevel@tonic-gate 	 * hardware-specific driver supply overrides.
286*7c478bd9Sstevel@tonic-gate 	 */
287*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_led_state = 0;
288*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_led_state &= ~initial_led_mask;
289*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_led_state |= initial_leds;
290*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_togglemask = 0;
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	if (lower->kbtrans_led_state & LED_CAPS_LOCK)
293*7c478bd9Sstevel@tonic-gate 		lower->kbtrans_togglemask |= CAPSMASK;
294*7c478bd9Sstevel@tonic-gate 	if (lower->kbtrans_led_state & LED_NUM_LOCK)
295*7c478bd9Sstevel@tonic-gate 		lower->kbtrans_togglemask |= NUMLOCKMASK;
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate #if	defined(SCROLLMASK)
298*7c478bd9Sstevel@tonic-gate 	if (lower->kbtrans_led_state & LED_SCROLL_LOCK)
299*7c478bd9Sstevel@tonic-gate 		lower->kbtrans_togglemask |= SCROLLMASK;
300*7c478bd9Sstevel@tonic-gate #endif
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_shiftmask = lower->kbtrans_togglemask;
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_vuid_addr.ascii = ASCII_FIRST;
305*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_vuid_addr.top = TOP_FIRST;
306*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_vuid_addr.vkey = VKEY_FIRST;
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	/* Allocate dynamic memory for downs table */
309*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_num_downs_entries = kbtrans_downs_size;
310*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_downs_bytes =
311*7c478bd9Sstevel@tonic-gate 			(uint32_t)(kbtrans_downs_size * sizeof (Key_event));
312*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_downs =
313*7c478bd9Sstevel@tonic-gate 		kmem_zalloc(upper->kbtrans_streams_downs_bytes, KM_SLEEP);
314*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_abortable = B_FALSE;
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_flags = KBTRANS_STREAMS_OPEN;
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L1, PRINT_MASK_OPEN, (upper, "kbtrans_streams_init "
319*7c478bd9Sstevel@tonic-gate 					    "exiting"));
320*7c478bd9Sstevel@tonic-gate 	return (0);
321*7c478bd9Sstevel@tonic-gate }
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate /*
325*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_fini:
326*7c478bd9Sstevel@tonic-gate  *	Free structures and uninitialize the stream
327*7c478bd9Sstevel@tonic-gate  */
328*7c478bd9Sstevel@tonic-gate int
329*7c478bd9Sstevel@tonic-gate kbtrans_streams_fini(struct kbtrans *upper)
330*7c478bd9Sstevel@tonic-gate {
331*7c478bd9Sstevel@tonic-gate 	/*
332*7c478bd9Sstevel@tonic-gate 	 * Since we're about to destroy our private data, turn off
333*7c478bd9Sstevel@tonic-gate 	 * our open flag first, so we don't accept any more input
334*7c478bd9Sstevel@tonic-gate 	 * and try to use that data.
335*7c478bd9Sstevel@tonic-gate 	 */
336*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_flags = 0;
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	/* clear all timeouts */
339*7c478bd9Sstevel@tonic-gate 	if (upper->kbtrans_streams_bufcallid) {
340*7c478bd9Sstevel@tonic-gate 		qunbufcall(upper->kbtrans_streams_readq,
341*7c478bd9Sstevel@tonic-gate 			upper->kbtrans_streams_bufcallid);
342*7c478bd9Sstevel@tonic-gate 	}
343*7c478bd9Sstevel@tonic-gate 	if (upper->kbtrans_streams_rptid) {
344*7c478bd9Sstevel@tonic-gate 		(void) quntimeout(upper->kbtrans_streams_readq,
345*7c478bd9Sstevel@tonic-gate 			upper->kbtrans_streams_rptid);
346*7c478bd9Sstevel@tonic-gate 	}
347*7c478bd9Sstevel@tonic-gate 	kmem_free(upper->kbtrans_streams_downs,
348*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_downs_bytes);
349*7c478bd9Sstevel@tonic-gate 	kmem_free(upper, sizeof (struct kbtrans));
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L1, PRINT_MASK_CLOSE, (upper, "kbtrans_streams_fini "
352*7c478bd9Sstevel@tonic-gate 					    "exiting"));
353*7c478bd9Sstevel@tonic-gate 	return (0);
354*7c478bd9Sstevel@tonic-gate }
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate /*
357*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_releaseall :
358*7c478bd9Sstevel@tonic-gate  *	This function releases all the held keys.
359*7c478bd9Sstevel@tonic-gate  */
360*7c478bd9Sstevel@tonic-gate void
361*7c478bd9Sstevel@tonic-gate kbtrans_streams_releaseall(struct kbtrans *upper)
362*7c478bd9Sstevel@tonic-gate {
363*7c478bd9Sstevel@tonic-gate 	register struct key_event *ke;
364*7c478bd9Sstevel@tonic-gate 	register int i;
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "USBKBM RELEASE ALL\n"));
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate 	/* Scan table of down key stations */
369*7c478bd9Sstevel@tonic-gate 	for (i = 0, ke = upper->kbtrans_streams_downs;
370*7c478bd9Sstevel@tonic-gate 	    i < upper->kbtrans_streams_num_downs_entries; i++, ke++) {
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 		/* Key station not zero */
373*7c478bd9Sstevel@tonic-gate 		if (ke->key_station) {
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 			kbtrans_keyreleased(upper, ke->key_station);
376*7c478bd9Sstevel@tonic-gate 			/* kbtrans_keyreleased resets downs entry */
377*7c478bd9Sstevel@tonic-gate 		}
378*7c478bd9Sstevel@tonic-gate 	}
379*7c478bd9Sstevel@tonic-gate }
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate /*
382*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_message:
383*7c478bd9Sstevel@tonic-gate  *	keyboard module output queue put procedure: handles M_IOCTL
384*7c478bd9Sstevel@tonic-gate  *	messages.
385*7c478bd9Sstevel@tonic-gate  *
386*7c478bd9Sstevel@tonic-gate  * 	Return KBTRANS_MESSAGE_HANDLED if the message was handled by
387*7c478bd9Sstevel@tonic-gate  *	kbtrans and KBTRANS_MESSAGE_NOT_HANDLED otherwise. If
388*7c478bd9Sstevel@tonic-gate  *	KBTRANS_MESSAGE_HANDLED is returned, no further action is required.
389*7c478bd9Sstevel@tonic-gate  *	If KBTRANS_MESSAGE_NOT_HANDLED is returned, the hardware module
390*7c478bd9Sstevel@tonic-gate  *	is responsible for any action.
391*7c478bd9Sstevel@tonic-gate  */
392*7c478bd9Sstevel@tonic-gate enum kbtrans_message_response
393*7c478bd9Sstevel@tonic-gate kbtrans_streams_message(struct kbtrans *upper, register mblk_t *mp)
394*7c478bd9Sstevel@tonic-gate {
395*7c478bd9Sstevel@tonic-gate 	queue_t *q = upper->kbtrans_streams_readq;
396*7c478bd9Sstevel@tonic-gate 	enum kbtrans_message_response ret;
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L1, PRINT_MASK_ALL, (upper,
399*7c478bd9Sstevel@tonic-gate 		"kbtrans_streams_message entering"));
400*7c478bd9Sstevel@tonic-gate 	/*
401*7c478bd9Sstevel@tonic-gate 	 * Process M_FLUSH, and some M_IOCTL, messages here; pass
402*7c478bd9Sstevel@tonic-gate 	 * everything else down.
403*7c478bd9Sstevel@tonic-gate 	 */
404*7c478bd9Sstevel@tonic-gate 	switch (mp->b_datap->db_type) {
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 	case M_IOCTL:
407*7c478bd9Sstevel@tonic-gate 		ret = kbtrans_ioctl(upper, mp);
408*7c478bd9Sstevel@tonic-gate 		break;
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 	case M_FLUSH:
411*7c478bd9Sstevel@tonic-gate 		if (*mp->b_rptr & FLUSHW)
412*7c478bd9Sstevel@tonic-gate 			flushq(q, FLUSHDATA);
413*7c478bd9Sstevel@tonic-gate 		if (*mp->b_rptr & FLUSHR)
414*7c478bd9Sstevel@tonic-gate 			flushq(RD(q), FLUSHDATA);
415*7c478bd9Sstevel@tonic-gate 		/*
416*7c478bd9Sstevel@tonic-gate 		 * White lie:  we say we didn't handle the message,
417*7c478bd9Sstevel@tonic-gate 		 * so that it gets handled by our client.
418*7c478bd9Sstevel@tonic-gate 		 */
419*7c478bd9Sstevel@tonic-gate 		ret = KBTRANS_MESSAGE_NOT_HANDLED;
420*7c478bd9Sstevel@tonic-gate 		break;
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	default:
423*7c478bd9Sstevel@tonic-gate 		ret = KBTRANS_MESSAGE_NOT_HANDLED;
424*7c478bd9Sstevel@tonic-gate 		break;
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L1, PRINT_MASK_ALL, (upper,
428*7c478bd9Sstevel@tonic-gate 		"kbtrans_streams_message exiting\n"));
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 	return (ret);
431*7c478bd9Sstevel@tonic-gate }
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate /*
434*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_key:
435*7c478bd9Sstevel@tonic-gate  * 	When a key is pressed or released, the hardware module should
436*7c478bd9Sstevel@tonic-gate  * 	call kbtrans, passing the key number and its new
437*7c478bd9Sstevel@tonic-gate  * 	state.  kbtrans is responsible for autorepeat handling;
438*7c478bd9Sstevel@tonic-gate  * 	the hardware module should report only actual press/release
439*7c478bd9Sstevel@tonic-gate  * 	events, suppressing any hardware-generated autorepeat.
440*7c478bd9Sstevel@tonic-gate  */
441*7c478bd9Sstevel@tonic-gate void
442*7c478bd9Sstevel@tonic-gate kbtrans_streams_key(
443*7c478bd9Sstevel@tonic-gate     struct kbtrans *upper,
444*7c478bd9Sstevel@tonic-gate     kbtrans_key_t key,
445*7c478bd9Sstevel@tonic-gate     enum keystate state)
446*7c478bd9Sstevel@tonic-gate {
447*7c478bd9Sstevel@tonic-gate 	struct kbtrans_lower *lower;
448*7c478bd9Sstevel@tonic-gate 	struct keyboard *kp;
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 	lower = &upper->kbtrans_lower;
451*7c478bd9Sstevel@tonic-gate 	kp = lower->kbtrans_keyboard;
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 	if (upper->kbtrans_streams_abortable) {
454*7c478bd9Sstevel@tonic-gate 		switch (upper->kbtrans_streams_abort_state) {
455*7c478bd9Sstevel@tonic-gate 		case ABORT_NORMAL:
456*7c478bd9Sstevel@tonic-gate 			if (state != KEY_PRESSED)
457*7c478bd9Sstevel@tonic-gate 				break;
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 			if (key == (kbtrans_key_t)kp->k_abort1 ||
460*7c478bd9Sstevel@tonic-gate 			    key == (kbtrans_key_t)kp->k_abort1a) {
461*7c478bd9Sstevel@tonic-gate 				upper->kbtrans_streams_abort_state =
462*7c478bd9Sstevel@tonic-gate 					ABORT_ABORT1_RECEIVED;
463*7c478bd9Sstevel@tonic-gate 				upper->kbtrans_streams_abort1_key = key;
464*7c478bd9Sstevel@tonic-gate 				return;
465*7c478bd9Sstevel@tonic-gate 			}
466*7c478bd9Sstevel@tonic-gate 			break;
467*7c478bd9Sstevel@tonic-gate 		case ABORT_ABORT1_RECEIVED:
468*7c478bd9Sstevel@tonic-gate 			upper->kbtrans_streams_abort_state = ABORT_NORMAL;
469*7c478bd9Sstevel@tonic-gate 			if (state == KEY_PRESSED &&
470*7c478bd9Sstevel@tonic-gate 			    key == (kbtrans_key_t)kp->k_abort2) {
471*7c478bd9Sstevel@tonic-gate 				abort_sequence_enter((char *)NULL);
472*7c478bd9Sstevel@tonic-gate 				return;
473*7c478bd9Sstevel@tonic-gate 			} else {
474*7c478bd9Sstevel@tonic-gate 				kbtrans_processkey(lower,
475*7c478bd9Sstevel@tonic-gate 					upper->kbtrans_streams_callback,
476*7c478bd9Sstevel@tonic-gate 					upper->kbtrans_streams_abort1_key,
477*7c478bd9Sstevel@tonic-gate 					KEY_PRESSED);
478*7c478bd9Sstevel@tonic-gate 			}
479*7c478bd9Sstevel@tonic-gate 		}
480*7c478bd9Sstevel@tonic-gate 	}
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate 	kbtrans_processkey(lower, upper->kbtrans_streams_callback, key, state);
483*7c478bd9Sstevel@tonic-gate }
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate /*
486*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_set_keyboard:
487*7c478bd9Sstevel@tonic-gate  * 	At any time after calling kbtrans_streams_init, the hardware
488*7c478bd9Sstevel@tonic-gate  * 	module should make this call to report the id of the keyboard
489*7c478bd9Sstevel@tonic-gate  * 	attached. id is the keyboard type, typically KB_SUN4,
490*7c478bd9Sstevel@tonic-gate  * 	KB_PC, or KB_USB.
491*7c478bd9Sstevel@tonic-gate  */
492*7c478bd9Sstevel@tonic-gate void
493*7c478bd9Sstevel@tonic-gate kbtrans_streams_set_keyboard(
494*7c478bd9Sstevel@tonic-gate     struct kbtrans 	*upper,
495*7c478bd9Sstevel@tonic-gate     int 		id,
496*7c478bd9Sstevel@tonic-gate     struct keyboard 	*k)
497*7c478bd9Sstevel@tonic-gate {
498*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_lower.kbtrans_keyboard = k;
499*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_id = id;
500*7c478bd9Sstevel@tonic-gate }
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate /*
503*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_has_reset:
504*7c478bd9Sstevel@tonic-gate  * 	At any time between kbtrans_streams_init and kbtrans_streams_fini,
505*7c478bd9Sstevel@tonic-gate  * 	the hardware module can call this routine to report that the
506*7c478bd9Sstevel@tonic-gate  * 	keyboard has been reset, e.g. by being unplugged and reattached.
507*7c478bd9Sstevel@tonic-gate  */
508*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
509*7c478bd9Sstevel@tonic-gate void
510*7c478bd9Sstevel@tonic-gate kbtrans_streams_has_reset(struct kbtrans *upper)
511*7c478bd9Sstevel@tonic-gate {
512*7c478bd9Sstevel@tonic-gate 	/*
513*7c478bd9Sstevel@tonic-gate 	 * If this routine is implemented it should probably (a)
514*7c478bd9Sstevel@tonic-gate 	 * simulate releases of all pressed keys and (b) call
515*7c478bd9Sstevel@tonic-gate 	 * the hardware module to set the LEDs.
516*7c478bd9Sstevel@tonic-gate 	 */
517*7c478bd9Sstevel@tonic-gate }
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate /*
520*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_enable:
521*7c478bd9Sstevel@tonic-gate  *	This is the routine that is called back when the the stream is ready
522*7c478bd9Sstevel@tonic-gate  *	to take messages.
523*7c478bd9Sstevel@tonic-gate  */
524*7c478bd9Sstevel@tonic-gate void
525*7c478bd9Sstevel@tonic-gate kbtrans_streams_enable(struct kbtrans *upper)
526*7c478bd9Sstevel@tonic-gate {
527*7c478bd9Sstevel@tonic-gate 	/* Set the LED's */
528*7c478bd9Sstevel@tonic-gate 	kbtrans_setled(upper);
529*7c478bd9Sstevel@tonic-gate }
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate /*
532*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_set_queue:
533*7c478bd9Sstevel@tonic-gate  *      Set the overlying queue, to support multiplexors.
534*7c478bd9Sstevel@tonic-gate  */
535*7c478bd9Sstevel@tonic-gate void
536*7c478bd9Sstevel@tonic-gate kbtrans_streams_set_queue(struct kbtrans *upper, queue_t *q)
537*7c478bd9Sstevel@tonic-gate {
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_readq = q;
540*7c478bd9Sstevel@tonic-gate }
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate /*
543*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_get_queue:
544*7c478bd9Sstevel@tonic-gate  *      Return the overlying queue.
545*7c478bd9Sstevel@tonic-gate  */
546*7c478bd9Sstevel@tonic-gate queue_t *
547*7c478bd9Sstevel@tonic-gate kbtrans_streams_get_queue(struct kbtrans *upper)
548*7c478bd9Sstevel@tonic-gate {
549*7c478bd9Sstevel@tonic-gate 	return (upper->kbtrans_streams_readq);
550*7c478bd9Sstevel@tonic-gate }
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate /*
553*7c478bd9Sstevel@tonic-gate  * kbtrans_streams_untimeout
554*7c478bd9Sstevel@tonic-gate  *      Cancell all timeout
555*7c478bd9Sstevel@tonic-gate  */
556*7c478bd9Sstevel@tonic-gate void
557*7c478bd9Sstevel@tonic-gate kbtrans_streams_untimeout(struct kbtrans *upper)
558*7c478bd9Sstevel@tonic-gate {
559*7c478bd9Sstevel@tonic-gate 	/* clear all timeouts */
560*7c478bd9Sstevel@tonic-gate 	if (upper->kbtrans_streams_bufcallid) {
561*7c478bd9Sstevel@tonic-gate 		qunbufcall(upper->kbtrans_streams_readq,
562*7c478bd9Sstevel@tonic-gate 			upper->kbtrans_streams_bufcallid);
563*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_bufcallid = 0;
564*7c478bd9Sstevel@tonic-gate 	}
565*7c478bd9Sstevel@tonic-gate 	if (upper->kbtrans_streams_rptid) {
566*7c478bd9Sstevel@tonic-gate 		(void) quntimeout(upper->kbtrans_streams_readq,
567*7c478bd9Sstevel@tonic-gate 			upper->kbtrans_streams_rptid);
568*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_rptid = 0;
569*7c478bd9Sstevel@tonic-gate 	}
570*7c478bd9Sstevel@tonic-gate }
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate /*
573*7c478bd9Sstevel@tonic-gate  * kbtrans_reioctl:
574*7c478bd9Sstevel@tonic-gate  * 	This function is set up as call-back function should an ioctl fail
575*7c478bd9Sstevel@tonic-gate  * 	to allocate required resources.
576*7c478bd9Sstevel@tonic-gate  */
577*7c478bd9Sstevel@tonic-gate static void
578*7c478bd9Sstevel@tonic-gate kbtrans_reioctl(void	*arg)
579*7c478bd9Sstevel@tonic-gate {
580*7c478bd9Sstevel@tonic-gate 	struct kbtrans *upper = (struct kbtrans *)arg;
581*7c478bd9Sstevel@tonic-gate 	mblk_t *mp;
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_bufcallid = 0;
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate 	if ((mp = upper->kbtrans_streams_iocpending) != NULL) {
586*7c478bd9Sstevel@tonic-gate 		/* not pending any more */
587*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_iocpending = NULL;
588*7c478bd9Sstevel@tonic-gate 		(void) kbtrans_ioctl(upper, mp);
589*7c478bd9Sstevel@tonic-gate 	}
590*7c478bd9Sstevel@tonic-gate }
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate /*
593*7c478bd9Sstevel@tonic-gate  * kbtrans_ioctl:
594*7c478bd9Sstevel@tonic-gate  * 	process ioctls we recognize and own.  Otherwise, pass it down.
595*7c478bd9Sstevel@tonic-gate  */
596*7c478bd9Sstevel@tonic-gate static enum kbtrans_message_response
597*7c478bd9Sstevel@tonic-gate kbtrans_ioctl(struct kbtrans *upper, register mblk_t *mp)
598*7c478bd9Sstevel@tonic-gate {
599*7c478bd9Sstevel@tonic-gate 	register struct iocblk *iocp;
600*7c478bd9Sstevel@tonic-gate 	register short	new_translate;
601*7c478bd9Sstevel@tonic-gate 	register Vuid_addr_probe *addr_probe;
602*7c478bd9Sstevel@tonic-gate 	register short	*addr_ptr;
603*7c478bd9Sstevel@tonic-gate 	size_t	ioctlrespsize;
604*7c478bd9Sstevel@tonic-gate 	int	err = 0;
605*7c478bd9Sstevel@tonic-gate 	struct kbtrans_lower *lower;
606*7c478bd9Sstevel@tonic-gate 	mblk_t *datap;
607*7c478bd9Sstevel@tonic-gate 	int	translate;
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	static int kiocgetkey, kiocsetkey;
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate 	lower = &upper->kbtrans_lower;
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate 	iocp = (struct iocblk *)mp->b_rptr;
614*7c478bd9Sstevel@tonic-gate 
615*7c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper,
616*7c478bd9Sstevel@tonic-gate 		"kbtrans_ioctl: ioc_cmd 0x%x - ", iocp->ioc_cmd));
617*7c478bd9Sstevel@tonic-gate 	switch (iocp->ioc_cmd) {
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate 	case VUIDSFORMAT:
620*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSFORMAT\n"));
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (int));
623*7c478bd9Sstevel@tonic-gate 		if (err != 0)
624*7c478bd9Sstevel@tonic-gate 			break;
625*7c478bd9Sstevel@tonic-gate 		new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ?
626*7c478bd9Sstevel@tonic-gate 		    TR_ASCII : TR_EVENT;
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate 		if (new_translate == upper->kbtrans_streams_translate_mode)
629*7c478bd9Sstevel@tonic-gate 			break;
630*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_translate_mode = new_translate;
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 		kbtrans_set_translation_callback(upper);
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 		kbtrans_flush(upper);
635*7c478bd9Sstevel@tonic-gate 		break;
636*7c478bd9Sstevel@tonic-gate 
637*7c478bd9Sstevel@tonic-gate 	case KIOCTRANS:
638*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANS\n"));
639*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (int));
640*7c478bd9Sstevel@tonic-gate 		if (err != 0)
641*7c478bd9Sstevel@tonic-gate 			break;
642*7c478bd9Sstevel@tonic-gate 		new_translate = *(int *)mp->b_cont->b_rptr;
643*7c478bd9Sstevel@tonic-gate 		if (new_translate == upper->kbtrans_streams_translate_mode)
644*7c478bd9Sstevel@tonic-gate 			break;
645*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_translate_mode = new_translate;
646*7c478bd9Sstevel@tonic-gate 		kbtrans_set_translation_callback(upper);
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 		kbtrans_flush(upper);
649*7c478bd9Sstevel@tonic-gate 		break;
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 	case KIOCSLED:
652*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSLED\n"));
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (uchar_t));
655*7c478bd9Sstevel@tonic-gate 		if (err != 0)
656*7c478bd9Sstevel@tonic-gate 			break;
657*7c478bd9Sstevel@tonic-gate 		lower->kbtrans_led_state = *(uchar_t *)mp->b_cont->b_rptr;
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 		kbtrans_setled(upper);
660*7c478bd9Sstevel@tonic-gate 		break;
661*7c478bd9Sstevel@tonic-gate 
662*7c478bd9Sstevel@tonic-gate 	case KIOCGLED:
663*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGLED\n"));
664*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) {
665*7c478bd9Sstevel@tonic-gate 			ioctlrespsize = sizeof (int);
666*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
667*7c478bd9Sstevel@tonic-gate 		}
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate 		*(uchar_t *)datap->b_wptr = lower->kbtrans_led_state;
670*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (uchar_t);
671*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont)
672*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
673*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;
674*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (uchar_t);
675*7c478bd9Sstevel@tonic-gate 		break;
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate 	case VUIDGFORMAT:
678*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGFORMAT\n"));
679*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
680*7c478bd9Sstevel@tonic-gate 			ioctlrespsize = sizeof (int);
681*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
682*7c478bd9Sstevel@tonic-gate 		}
683*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr =
684*7c478bd9Sstevel@tonic-gate 		    (upper->kbtrans_streams_translate_mode == TR_EVENT ||
685*7c478bd9Sstevel@tonic-gate 		    upper->kbtrans_streams_translate_mode == TR_UNTRANS_EVENT) ?
686*7c478bd9Sstevel@tonic-gate 			VUID_FIRM_EVENT: VUID_NATIVE;
687*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
688*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont)  /* free msg to prevent memory leak */
689*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
690*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;
691*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);
692*7c478bd9Sstevel@tonic-gate 		break;
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	case KIOCGTRANS:
695*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANS\n"));
696*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
697*7c478bd9Sstevel@tonic-gate 			ioctlrespsize = sizeof (int);
698*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
699*7c478bd9Sstevel@tonic-gate 		}
700*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = upper->kbtrans_streams_translate_mode;
701*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
702*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont)  /* free msg to prevent memory leak */
703*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
704*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;
705*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);
706*7c478bd9Sstevel@tonic-gate 		break;
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate 	case VUIDSADDR:
709*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDSADDR\n"));
710*7c478bd9Sstevel@tonic-gate 
711*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
712*7c478bd9Sstevel@tonic-gate 		if (err != 0)
713*7c478bd9Sstevel@tonic-gate 			break;
714*7c478bd9Sstevel@tonic-gate 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
715*7c478bd9Sstevel@tonic-gate 		switch (addr_probe->base) {
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 		case ASCII_FIRST:
718*7c478bd9Sstevel@tonic-gate 			addr_ptr = &upper->kbtrans_streams_vuid_addr.ascii;
719*7c478bd9Sstevel@tonic-gate 			break;
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 		case TOP_FIRST:
722*7c478bd9Sstevel@tonic-gate 			addr_ptr = &upper->kbtrans_streams_vuid_addr.top;
723*7c478bd9Sstevel@tonic-gate 			break;
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate 		case VKEY_FIRST:
726*7c478bd9Sstevel@tonic-gate 			addr_ptr = &upper->kbtrans_streams_vuid_addr.vkey;
727*7c478bd9Sstevel@tonic-gate 			break;
728*7c478bd9Sstevel@tonic-gate 
729*7c478bd9Sstevel@tonic-gate 		default:
730*7c478bd9Sstevel@tonic-gate 			err = ENODEV;
731*7c478bd9Sstevel@tonic-gate 		}
732*7c478bd9Sstevel@tonic-gate 
733*7c478bd9Sstevel@tonic-gate 		if ((err == 0) && (*addr_ptr != addr_probe->data.next)) {
734*7c478bd9Sstevel@tonic-gate 			*addr_ptr = addr_probe->data.next;
735*7c478bd9Sstevel@tonic-gate 			kbtrans_flush(upper);
736*7c478bd9Sstevel@tonic-gate 		}
737*7c478bd9Sstevel@tonic-gate 		break;
738*7c478bd9Sstevel@tonic-gate 
739*7c478bd9Sstevel@tonic-gate 	case VUIDGADDR:
740*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "VUIDGADDR\n"));
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
743*7c478bd9Sstevel@tonic-gate 		if (err != 0)
744*7c478bd9Sstevel@tonic-gate 			break;
745*7c478bd9Sstevel@tonic-gate 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
746*7c478bd9Sstevel@tonic-gate 		switch (addr_probe->base) {
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate 		case ASCII_FIRST:
749*7c478bd9Sstevel@tonic-gate 			addr_probe->data.current =
750*7c478bd9Sstevel@tonic-gate 				upper->kbtrans_streams_vuid_addr.ascii;
751*7c478bd9Sstevel@tonic-gate 			break;
752*7c478bd9Sstevel@tonic-gate 
753*7c478bd9Sstevel@tonic-gate 		case TOP_FIRST:
754*7c478bd9Sstevel@tonic-gate 			addr_probe->data.current =
755*7c478bd9Sstevel@tonic-gate 				upper->kbtrans_streams_vuid_addr.top;
756*7c478bd9Sstevel@tonic-gate 			break;
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate 		case VKEY_FIRST:
759*7c478bd9Sstevel@tonic-gate 			addr_probe->data.current =
760*7c478bd9Sstevel@tonic-gate 				upper->kbtrans_streams_vuid_addr.vkey;
761*7c478bd9Sstevel@tonic-gate 			break;
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate 		default:
764*7c478bd9Sstevel@tonic-gate 			err = ENODEV;
765*7c478bd9Sstevel@tonic-gate 		}
766*7c478bd9Sstevel@tonic-gate 		break;
767*7c478bd9Sstevel@tonic-gate 
768*7c478bd9Sstevel@tonic-gate 	case KIOCTRANSABLE:
769*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTRANSABLE\n"));
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (int));
772*7c478bd9Sstevel@tonic-gate 		if (err != 0)
773*7c478bd9Sstevel@tonic-gate 			break;
774*7c478bd9Sstevel@tonic-gate 		/*
775*7c478bd9Sstevel@tonic-gate 		 * called during console setup in kbconfig()
776*7c478bd9Sstevel@tonic-gate 		 * If set to false, means we are a serial keyboard,
777*7c478bd9Sstevel@tonic-gate 		 * and we should pass all data up without modification.
778*7c478bd9Sstevel@tonic-gate 		 */
779*7c478bd9Sstevel@tonic-gate 		translate = *(int *)mp->b_cont->b_rptr;
780*7c478bd9Sstevel@tonic-gate 		if (upper->kbtrans_streams_translatable != translate)
781*7c478bd9Sstevel@tonic-gate 			upper->kbtrans_streams_translatable = translate;
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 		if (translate != TR_CAN)
784*7c478bd9Sstevel@tonic-gate 			DPRINTF(PRINT_L4, PRINT_MASK_ALL, (upper,
785*7c478bd9Sstevel@tonic-gate 			    "Cannot translate keyboard using tables.\n"));
786*7c478bd9Sstevel@tonic-gate 		break;
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 	case KIOCGTRANSABLE:
789*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGTRANSABLE\n"));
790*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
791*7c478bd9Sstevel@tonic-gate 			ioctlrespsize = sizeof (int);
792*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
793*7c478bd9Sstevel@tonic-gate 		}
794*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = upper->kbtrans_streams_translatable;
795*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
796*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont)  /* free msg to prevent memory leak */
797*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
798*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;
799*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);
800*7c478bd9Sstevel@tonic-gate 		break;
801*7c478bd9Sstevel@tonic-gate 
802*7c478bd9Sstevel@tonic-gate 	case KIOCSCOMPAT:
803*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSCOMPAT\n"));
804*7c478bd9Sstevel@tonic-gate 
805*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (int));
806*7c478bd9Sstevel@tonic-gate 		if (err != 0)
807*7c478bd9Sstevel@tonic-gate 			break;
808*7c478bd9Sstevel@tonic-gate 		lower->kbtrans_compat = *(int *)mp->b_cont->b_rptr;
809*7c478bd9Sstevel@tonic-gate 		break;
810*7c478bd9Sstevel@tonic-gate 
811*7c478bd9Sstevel@tonic-gate 	case KIOCGCOMPAT:
812*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGCOMPAT\n"));
813*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
814*7c478bd9Sstevel@tonic-gate 			ioctlrespsize = sizeof (int);
815*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
816*7c478bd9Sstevel@tonic-gate 		}
817*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = lower->kbtrans_compat;
818*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
819*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont)  /* free msg to prevent memory leak */
820*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
821*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;
822*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);
823*7c478bd9Sstevel@tonic-gate 		break;
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate 	case KIOCSETKEY:
826*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSETKEY %d\n",
827*7c478bd9Sstevel@tonic-gate 							kiocsetkey++));
828*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (struct kiockey));
829*7c478bd9Sstevel@tonic-gate 		if (err != 0)
830*7c478bd9Sstevel@tonic-gate 			break;
831*7c478bd9Sstevel@tonic-gate 		err = kbtrans_setkey(&upper->kbtrans_lower,
832*7c478bd9Sstevel@tonic-gate 		    (struct kiockey *)mp->b_cont->b_rptr, iocp->ioc_cr);
833*7c478bd9Sstevel@tonic-gate 		/*
834*7c478bd9Sstevel@tonic-gate 		 * Since this only affects any subsequent key presses,
835*7c478bd9Sstevel@tonic-gate 		 * don't flush soft state.  One might want to
836*7c478bd9Sstevel@tonic-gate 		 * toggle the keytable entries dynamically.
837*7c478bd9Sstevel@tonic-gate 		 */
838*7c478bd9Sstevel@tonic-gate 		break;
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 	case KIOCGETKEY:
841*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGETKEY %d\n",
842*7c478bd9Sstevel@tonic-gate 							kiocgetkey++));
843*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (struct kiockey));
844*7c478bd9Sstevel@tonic-gate 		if (err != 0)
845*7c478bd9Sstevel@tonic-gate 			break;
846*7c478bd9Sstevel@tonic-gate 		err = kbtrans_getkey(&upper->kbtrans_lower,
847*7c478bd9Sstevel@tonic-gate 		    (struct kiockey *)mp->b_cont->b_rptr);
848*7c478bd9Sstevel@tonic-gate 		break;
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate 	case KIOCSKEY:
851*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (struct kiockeymap));
852*7c478bd9Sstevel@tonic-gate 		if (err != 0)
853*7c478bd9Sstevel@tonic-gate 			break;
854*7c478bd9Sstevel@tonic-gate 		err = kbtrans_skey(&upper->kbtrans_lower,
855*7c478bd9Sstevel@tonic-gate 		    (struct kiockeymap *)mp->b_cont->b_rptr, iocp->ioc_cr);
856*7c478bd9Sstevel@tonic-gate 		/*
857*7c478bd9Sstevel@tonic-gate 		 * Since this only affects any subsequent key presses,
858*7c478bd9Sstevel@tonic-gate 		 * don't flush soft state.  One might want to
859*7c478bd9Sstevel@tonic-gate 		 * toggle the keytable entries dynamically.
860*7c478bd9Sstevel@tonic-gate 		 */
861*7c478bd9Sstevel@tonic-gate 		break;
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 	case KIOCGKEY:
864*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (struct kiockeymap));
865*7c478bd9Sstevel@tonic-gate 		if (err != 0)
866*7c478bd9Sstevel@tonic-gate 			break;
867*7c478bd9Sstevel@tonic-gate 		err = kbtrans_gkey(&upper->kbtrans_lower,
868*7c478bd9Sstevel@tonic-gate 		    (struct kiockeymap *)mp->b_cont->b_rptr);
869*7c478bd9Sstevel@tonic-gate 		break;
870*7c478bd9Sstevel@tonic-gate 
871*7c478bd9Sstevel@tonic-gate 	case KIOCSDIRECT:
872*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSDIRECT\n"));
873*7c478bd9Sstevel@tonic-gate 		kbtrans_flush(upper);
874*7c478bd9Sstevel@tonic-gate 		break;
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate 	case KIOCGDIRECT:
877*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSGDIRECT\n"));
878*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
879*7c478bd9Sstevel@tonic-gate 			ioctlrespsize = sizeof (int);
880*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
881*7c478bd9Sstevel@tonic-gate 		}
882*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = 1;	/* always direct */
883*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
884*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont) /* free msg to prevent memory leak */
885*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
886*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;
887*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);
888*7c478bd9Sstevel@tonic-gate 		break;
889*7c478bd9Sstevel@tonic-gate 
890*7c478bd9Sstevel@tonic-gate 	case KIOCTYPE:
891*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCTYPE\n"));
892*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
893*7c478bd9Sstevel@tonic-gate 			ioctlrespsize = sizeof (int);
894*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
895*7c478bd9Sstevel@tonic-gate 		}
896*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = upper->kbtrans_streams_id;
897*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
898*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont) /* free msg to prevent memory leak */
899*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
900*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;
901*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);
902*7c478bd9Sstevel@tonic-gate 		break;
903*7c478bd9Sstevel@tonic-gate 
904*7c478bd9Sstevel@tonic-gate 	case CONSSETABORTENABLE:
905*7c478bd9Sstevel@tonic-gate 		/*
906*7c478bd9Sstevel@tonic-gate 		 * Peek as it goes by; must be a TRANSPARENT ioctl.
907*7c478bd9Sstevel@tonic-gate 		 */
908*7c478bd9Sstevel@tonic-gate 		if (iocp->ioc_count != TRANSPARENT) {
909*7c478bd9Sstevel@tonic-gate 			err = EINVAL;
910*7c478bd9Sstevel@tonic-gate 			break;
911*7c478bd9Sstevel@tonic-gate 		}
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_abortable =
914*7c478bd9Sstevel@tonic-gate 		    (boolean_t)*(intptr_t *)mp->b_cont->b_rptr;
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 		/*
917*7c478bd9Sstevel@tonic-gate 		 * Let the hardware module see it too.
918*7c478bd9Sstevel@tonic-gate 		 */
919*7c478bd9Sstevel@tonic-gate 		return (KBTRANS_MESSAGE_NOT_HANDLED);
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 	case KIOCGRPTDELAY:
922*7c478bd9Sstevel@tonic-gate 		/*
923*7c478bd9Sstevel@tonic-gate 		 * Report the autorepeat delay, unit in millisecond
924*7c478bd9Sstevel@tonic-gate 		 */
925*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTDELAY\n"));
926*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
927*7c478bd9Sstevel@tonic-gate 			ioctlrespsize = sizeof (int);
928*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
929*7c478bd9Sstevel@tonic-gate 		}
930*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_delay);
931*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
932*7c478bd9Sstevel@tonic-gate 
933*7c478bd9Sstevel@tonic-gate 		/* free msg to prevent memory leak */
934*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont != NULL)
935*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
936*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;
937*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);
938*7c478bd9Sstevel@tonic-gate 		break;
939*7c478bd9Sstevel@tonic-gate 
940*7c478bd9Sstevel@tonic-gate 	case KIOCSRPTDELAY:
941*7c478bd9Sstevel@tonic-gate 		/*
942*7c478bd9Sstevel@tonic-gate 		 * Set the autorepeat delay
943*7c478bd9Sstevel@tonic-gate 		 */
944*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTDELAY\n"));
945*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (int));
946*7c478bd9Sstevel@tonic-gate 
947*7c478bd9Sstevel@tonic-gate 		if (err != 0)
948*7c478bd9Sstevel@tonic-gate 			break;
949*7c478bd9Sstevel@tonic-gate 
950*7c478bd9Sstevel@tonic-gate 		/* validate the input */
951*7c478bd9Sstevel@tonic-gate 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) {
952*7c478bd9Sstevel@tonic-gate 			err = EINVAL;
953*7c478bd9Sstevel@tonic-gate 			break;
954*7c478bd9Sstevel@tonic-gate 		}
955*7c478bd9Sstevel@tonic-gate 		kbtrans_repeat_delay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
956*7c478bd9Sstevel@tonic-gate 		if (kbtrans_repeat_delay <= 0)
957*7c478bd9Sstevel@tonic-gate 			kbtrans_repeat_delay = 1;
958*7c478bd9Sstevel@tonic-gate 		break;
959*7c478bd9Sstevel@tonic-gate 
960*7c478bd9Sstevel@tonic-gate 	case KIOCGRPTRATE:
961*7c478bd9Sstevel@tonic-gate 		/*
962*7c478bd9Sstevel@tonic-gate 		 * Report the autorepeat rate
963*7c478bd9Sstevel@tonic-gate 		 */
964*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCGRPTRATE\n"));
965*7c478bd9Sstevel@tonic-gate 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
966*7c478bd9Sstevel@tonic-gate 			ioctlrespsize = sizeof (int);
967*7c478bd9Sstevel@tonic-gate 			goto allocfailure;
968*7c478bd9Sstevel@tonic-gate 		}
969*7c478bd9Sstevel@tonic-gate 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbtrans_repeat_rate);
970*7c478bd9Sstevel@tonic-gate 		datap->b_wptr += sizeof (int);
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate 		/* free msg to prevent memory leak */
973*7c478bd9Sstevel@tonic-gate 		if (mp->b_cont != NULL)
974*7c478bd9Sstevel@tonic-gate 			freemsg(mp->b_cont);
975*7c478bd9Sstevel@tonic-gate 		mp->b_cont = datap;
976*7c478bd9Sstevel@tonic-gate 		iocp->ioc_count = sizeof (int);
977*7c478bd9Sstevel@tonic-gate 		break;
978*7c478bd9Sstevel@tonic-gate 
979*7c478bd9Sstevel@tonic-gate 	case KIOCSRPTRATE:
980*7c478bd9Sstevel@tonic-gate 		/*
981*7c478bd9Sstevel@tonic-gate 		 * Set the autorepeat rate
982*7c478bd9Sstevel@tonic-gate 		 */
983*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "KIOCSRPTRATE\n"));
984*7c478bd9Sstevel@tonic-gate 		err = miocpullup(mp, sizeof (int));
985*7c478bd9Sstevel@tonic-gate 
986*7c478bd9Sstevel@tonic-gate 		if (err != 0)
987*7c478bd9Sstevel@tonic-gate 			break;
988*7c478bd9Sstevel@tonic-gate 
989*7c478bd9Sstevel@tonic-gate 		/* validate the input */
990*7c478bd9Sstevel@tonic-gate 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) {
991*7c478bd9Sstevel@tonic-gate 			err = EINVAL;
992*7c478bd9Sstevel@tonic-gate 			break;
993*7c478bd9Sstevel@tonic-gate 		}
994*7c478bd9Sstevel@tonic-gate 		kbtrans_repeat_rate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
995*7c478bd9Sstevel@tonic-gate 		if (kbtrans_repeat_rate <= 0)
996*7c478bd9Sstevel@tonic-gate 			kbtrans_repeat_rate = 1;
997*7c478bd9Sstevel@tonic-gate 		break;
998*7c478bd9Sstevel@tonic-gate 
999*7c478bd9Sstevel@tonic-gate 	default:
1000*7c478bd9Sstevel@tonic-gate 		DPRINTF(PRINT_L0, PRINT_MASK_ALL, (upper, "unknown\n"));
1001*7c478bd9Sstevel@tonic-gate 		return (KBTRANS_MESSAGE_NOT_HANDLED);
1002*7c478bd9Sstevel@tonic-gate 	} /* end switch */
1003*7c478bd9Sstevel@tonic-gate 
1004*7c478bd9Sstevel@tonic-gate 	if (err != 0) {
1005*7c478bd9Sstevel@tonic-gate 		iocp->ioc_rval = 0;
1006*7c478bd9Sstevel@tonic-gate 		iocp->ioc_error = err;
1007*7c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_IOCNAK;
1008*7c478bd9Sstevel@tonic-gate 	} else {
1009*7c478bd9Sstevel@tonic-gate 		iocp->ioc_rval = 0;
1010*7c478bd9Sstevel@tonic-gate 		iocp->ioc_error = 0;	/* brain rot */
1011*7c478bd9Sstevel@tonic-gate 		mp->b_datap->db_type = M_IOCACK;
1012*7c478bd9Sstevel@tonic-gate 	}
1013*7c478bd9Sstevel@tonic-gate 	putnext(upper->kbtrans_streams_readq, mp);
1014*7c478bd9Sstevel@tonic-gate 
1015*7c478bd9Sstevel@tonic-gate 	return (KBTRANS_MESSAGE_HANDLED);
1016*7c478bd9Sstevel@tonic-gate 
1017*7c478bd9Sstevel@tonic-gate allocfailure:
1018*7c478bd9Sstevel@tonic-gate 	/*
1019*7c478bd9Sstevel@tonic-gate 	 * We needed to allocate something to handle this "ioctl", but
1020*7c478bd9Sstevel@tonic-gate 	 * couldn't; save this "ioctl" and arrange to get called back when
1021*7c478bd9Sstevel@tonic-gate 	 * it's more likely that we can get what we need.
1022*7c478bd9Sstevel@tonic-gate 	 * If there's already one being saved, throw it out, since it
1023*7c478bd9Sstevel@tonic-gate 	 * must have timed out.
1024*7c478bd9Sstevel@tonic-gate 	 */
1025*7c478bd9Sstevel@tonic-gate 	if (upper->kbtrans_streams_iocpending != NULL)
1026*7c478bd9Sstevel@tonic-gate 		freemsg(upper->kbtrans_streams_iocpending);
1027*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_iocpending = mp;
1028*7c478bd9Sstevel@tonic-gate 	if (upper->kbtrans_streams_bufcallid) {
1029*7c478bd9Sstevel@tonic-gate 		qunbufcall(upper->kbtrans_streams_readq,
1030*7c478bd9Sstevel@tonic-gate 			upper->kbtrans_streams_bufcallid);
1031*7c478bd9Sstevel@tonic-gate 	}
1032*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_bufcallid =
1033*7c478bd9Sstevel@tonic-gate 		qbufcall(upper->kbtrans_streams_readq, ioctlrespsize, BPRI_HI,
1034*7c478bd9Sstevel@tonic-gate 			kbtrans_reioctl, upper);
1035*7c478bd9Sstevel@tonic-gate 	/*
1036*7c478bd9Sstevel@tonic-gate 	 * This is a white lie... we *will* handle it, eventually.
1037*7c478bd9Sstevel@tonic-gate 	 */
1038*7c478bd9Sstevel@tonic-gate 	return (KBTRANS_MESSAGE_HANDLED);
1039*7c478bd9Sstevel@tonic-gate }
1040*7c478bd9Sstevel@tonic-gate 
1041*7c478bd9Sstevel@tonic-gate /*
1042*7c478bd9Sstevel@tonic-gate  * kbtrans_flush:
1043*7c478bd9Sstevel@tonic-gate  *	Flush data upstream
1044*7c478bd9Sstevel@tonic-gate  */
1045*7c478bd9Sstevel@tonic-gate static void
1046*7c478bd9Sstevel@tonic-gate kbtrans_flush(register struct kbtrans *upper)
1047*7c478bd9Sstevel@tonic-gate {
1048*7c478bd9Sstevel@tonic-gate 	register queue_t *q;
1049*7c478bd9Sstevel@tonic-gate 
1050*7c478bd9Sstevel@tonic-gate 	/* Flush pending data already sent upstream */
1051*7c478bd9Sstevel@tonic-gate 	if ((q = upper->kbtrans_streams_readq) != NULL && q->q_next != NULL)
1052*7c478bd9Sstevel@tonic-gate 		(void) putnextctl1(q, M_FLUSH, FLUSHR);
1053*7c478bd9Sstevel@tonic-gate 
1054*7c478bd9Sstevel@tonic-gate 	/* Flush pending ups */
1055*7c478bd9Sstevel@tonic-gate 	bzero(upper->kbtrans_streams_downs, upper->kbtrans_streams_downs_bytes);
1056*7c478bd9Sstevel@tonic-gate 
1057*7c478bd9Sstevel@tonic-gate 	kbtrans_cancelrpt(upper);
1058*7c478bd9Sstevel@tonic-gate }
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate /*
1061*7c478bd9Sstevel@tonic-gate  * kbtrans_setled:
1062*7c478bd9Sstevel@tonic-gate  *	 Update the keyboard LEDs to match the current keyboard state.
1063*7c478bd9Sstevel@tonic-gate  */
1064*7c478bd9Sstevel@tonic-gate static void
1065*7c478bd9Sstevel@tonic-gate kbtrans_setled(struct kbtrans *upper)
1066*7c478bd9Sstevel@tonic-gate {
1067*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_hw_callbacks->kbtrans_streams_setled(
1068*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_hw,
1069*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_lower.kbtrans_led_state);
1070*7c478bd9Sstevel@tonic-gate }
1071*7c478bd9Sstevel@tonic-gate 
1072*7c478bd9Sstevel@tonic-gate /*
1073*7c478bd9Sstevel@tonic-gate  * kbtrans_rpt:
1074*7c478bd9Sstevel@tonic-gate  *	If a key is held down, this function is set up to be called
1075*7c478bd9Sstevel@tonic-gate  * 	after kbtrans_repeat_rate time elapses.
1076*7c478bd9Sstevel@tonic-gate  */
1077*7c478bd9Sstevel@tonic-gate static void
1078*7c478bd9Sstevel@tonic-gate kbtrans_rpt(void *arg)
1079*7c478bd9Sstevel@tonic-gate {
1080*7c478bd9Sstevel@tonic-gate 	struct kbtrans	*upper = arg;
1081*7c478bd9Sstevel@tonic-gate 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1082*7c478bd9Sstevel@tonic-gate 
1083*7c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL,
1084*7c478bd9Sstevel@tonic-gate 		"kbtrans_rpt: repeat key %X\n",
1085*7c478bd9Sstevel@tonic-gate 		lower->kbtrans_repeatkey));
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_rptid = 0;
1088*7c478bd9Sstevel@tonic-gate 
1089*7c478bd9Sstevel@tonic-gate 	/*
1090*7c478bd9Sstevel@tonic-gate 	 * NB:  polled code zaps kbtrans_repeatkey without cancelling
1091*7c478bd9Sstevel@tonic-gate 	 * timeout.
1092*7c478bd9Sstevel@tonic-gate 	 */
1093*7c478bd9Sstevel@tonic-gate 	if (lower->kbtrans_repeatkey != 0) {
1094*7c478bd9Sstevel@tonic-gate 		kbtrans_keyreleased(upper, lower->kbtrans_repeatkey);
1095*7c478bd9Sstevel@tonic-gate 
1096*7c478bd9Sstevel@tonic-gate 		kbtrans_processkey(lower,
1097*7c478bd9Sstevel@tonic-gate 			upper->kbtrans_streams_callback,
1098*7c478bd9Sstevel@tonic-gate 			lower->kbtrans_repeatkey,
1099*7c478bd9Sstevel@tonic-gate 			KEY_PRESSED);
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_rptid =
1102*7c478bd9Sstevel@tonic-gate 			qtimeout(upper->kbtrans_streams_readq, kbtrans_rpt,
1103*7c478bd9Sstevel@tonic-gate 			    (caddr_t)upper, kbtrans_repeat_rate);
1104*7c478bd9Sstevel@tonic-gate 	}
1105*7c478bd9Sstevel@tonic-gate }
1106*7c478bd9Sstevel@tonic-gate 
1107*7c478bd9Sstevel@tonic-gate /*
1108*7c478bd9Sstevel@tonic-gate  * kbtrans_cancelrpt:
1109*7c478bd9Sstevel@tonic-gate  * 	Cancel the repeating key
1110*7c478bd9Sstevel@tonic-gate  */
1111*7c478bd9Sstevel@tonic-gate static void
1112*7c478bd9Sstevel@tonic-gate kbtrans_cancelrpt(struct kbtrans	*upper)
1113*7c478bd9Sstevel@tonic-gate {
1114*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_lower.kbtrans_repeatkey = 0;
1115*7c478bd9Sstevel@tonic-gate 
1116*7c478bd9Sstevel@tonic-gate 	if (upper->kbtrans_streams_rptid != 0) {
1117*7c478bd9Sstevel@tonic-gate 		(void) quntimeout(upper->kbtrans_streams_readq,
1118*7c478bd9Sstevel@tonic-gate 				    upper->kbtrans_streams_rptid);
1119*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_rptid = 0;
1120*7c478bd9Sstevel@tonic-gate 	}
1121*7c478bd9Sstevel@tonic-gate }
1122*7c478bd9Sstevel@tonic-gate 
1123*7c478bd9Sstevel@tonic-gate /*
1124*7c478bd9Sstevel@tonic-gate  * kbtrans_send_esc_event:
1125*7c478bd9Sstevel@tonic-gate  *	Send character up stream. Used for the case of
1126*7c478bd9Sstevel@tonic-gate  *	sending strings upstream.
1127*7c478bd9Sstevel@tonic-gate  */
1128*7c478bd9Sstevel@tonic-gate static void
1129*7c478bd9Sstevel@tonic-gate kbtrans_send_esc_event(char c, register struct kbtrans *upper)
1130*7c478bd9Sstevel@tonic-gate {
1131*7c478bd9Sstevel@tonic-gate 	Firm_event fe;
1132*7c478bd9Sstevel@tonic-gate 
1133*7c478bd9Sstevel@tonic-gate 	fe.id = c;
1134*7c478bd9Sstevel@tonic-gate 	fe.value = 1;
1135*7c478bd9Sstevel@tonic-gate 	fe.pair_type = FE_PAIR_NONE;
1136*7c478bd9Sstevel@tonic-gate 	fe.pair = 0;
1137*7c478bd9Sstevel@tonic-gate 	/*
1138*7c478bd9Sstevel@tonic-gate 	 * Pretend as if each cp pushed and released
1139*7c478bd9Sstevel@tonic-gate 	 * Calling kbtrans_queueevent avoids addr translation
1140*7c478bd9Sstevel@tonic-gate 	 * and pair base determination of kbtrans_keypressed.
1141*7c478bd9Sstevel@tonic-gate 	 */
1142*7c478bd9Sstevel@tonic-gate 	kbtrans_queueevent(upper, &fe);
1143*7c478bd9Sstevel@tonic-gate 	fe.value = 0;
1144*7c478bd9Sstevel@tonic-gate 	kbtrans_queueevent(upper, &fe);
1145*7c478bd9Sstevel@tonic-gate }
1146*7c478bd9Sstevel@tonic-gate 
1147*7c478bd9Sstevel@tonic-gate /*
1148*7c478bd9Sstevel@tonic-gate  * kbtrans_strsetwithdecimal:
1149*7c478bd9Sstevel@tonic-gate  *	Used for expanding a function key to the ascii equivalent
1150*7c478bd9Sstevel@tonic-gate  */
1151*7c478bd9Sstevel@tonic-gate static char *
1152*7c478bd9Sstevel@tonic-gate kbtrans_strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs)
1153*7c478bd9Sstevel@tonic-gate {
1154*7c478bd9Sstevel@tonic-gate 	int	hradix = 5;
1155*7c478bd9Sstevel@tonic-gate 	char	*bp;
1156*7c478bd9Sstevel@tonic-gate 	int	lowbit;
1157*7c478bd9Sstevel@tonic-gate 	char	*tab = "0123456789abcdef";
1158*7c478bd9Sstevel@tonic-gate 
1159*7c478bd9Sstevel@tonic-gate 	bp = buf + maxdigs;
1160*7c478bd9Sstevel@tonic-gate 	*(--bp) = '\0';
1161*7c478bd9Sstevel@tonic-gate 	while (val) {
1162*7c478bd9Sstevel@tonic-gate 		lowbit = val & 1;
1163*7c478bd9Sstevel@tonic-gate 		val = (val >> 1);
1164*7c478bd9Sstevel@tonic-gate 		*(--bp) = tab[val % hradix * 2 + lowbit];
1165*7c478bd9Sstevel@tonic-gate 		val /= hradix;
1166*7c478bd9Sstevel@tonic-gate 	}
1167*7c478bd9Sstevel@tonic-gate 	return (bp);
1168*7c478bd9Sstevel@tonic-gate }
1169*7c478bd9Sstevel@tonic-gate 
1170*7c478bd9Sstevel@tonic-gate /*
1171*7c478bd9Sstevel@tonic-gate  * kbtrans_keypressed:
1172*7c478bd9Sstevel@tonic-gate  *	Modify Firm event to be sent up the stream
1173*7c478bd9Sstevel@tonic-gate  */
1174*7c478bd9Sstevel@tonic-gate static void
1175*7c478bd9Sstevel@tonic-gate kbtrans_keypressed(struct kbtrans *upper, uchar_t key_station,
1176*7c478bd9Sstevel@tonic-gate 		    Firm_event *fe, ushort_t base)
1177*7c478bd9Sstevel@tonic-gate {
1178*7c478bd9Sstevel@tonic-gate 
1179*7c478bd9Sstevel@tonic-gate 	register short	id_addr;
1180*7c478bd9Sstevel@tonic-gate 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1181*7c478bd9Sstevel@tonic-gate 
1182*7c478bd9Sstevel@tonic-gate 	/* Set pair values */
1183*7c478bd9Sstevel@tonic-gate 	if (fe->id < (ushort_t)VKEY_FIRST) {
1184*7c478bd9Sstevel@tonic-gate 		/*
1185*7c478bd9Sstevel@tonic-gate 		 * If CTRLed, find the ID that would have been used had it
1186*7c478bd9Sstevel@tonic-gate 		 * not been CTRLed.
1187*7c478bd9Sstevel@tonic-gate 		 */
1188*7c478bd9Sstevel@tonic-gate 		if (lower->kbtrans_shiftmask & (CTRLMASK | CTLSMASK)) {
1189*7c478bd9Sstevel@tonic-gate 			unsigned short *ke;
1190*7c478bd9Sstevel@tonic-gate 			unsigned int mask;
1191*7c478bd9Sstevel@tonic-gate 
1192*7c478bd9Sstevel@tonic-gate 			mask = lower->kbtrans_shiftmask &
1193*7c478bd9Sstevel@tonic-gate 				~(CTRLMASK | CTLSMASK | UPMASK);
1194*7c478bd9Sstevel@tonic-gate 
1195*7c478bd9Sstevel@tonic-gate 			ke = kbtrans_find_entry(lower, mask, key_station);
1196*7c478bd9Sstevel@tonic-gate 			if (ke == NULL)
1197*7c478bd9Sstevel@tonic-gate 				return;
1198*7c478bd9Sstevel@tonic-gate 
1199*7c478bd9Sstevel@tonic-gate 			base = *ke;
1200*7c478bd9Sstevel@tonic-gate 		}
1201*7c478bd9Sstevel@tonic-gate 		if (base != fe->id) {
1202*7c478bd9Sstevel@tonic-gate 			fe->pair_type = FE_PAIR_SET;
1203*7c478bd9Sstevel@tonic-gate 			fe->pair = (uchar_t)base;
1204*7c478bd9Sstevel@tonic-gate 
1205*7c478bd9Sstevel@tonic-gate 			goto send;
1206*7c478bd9Sstevel@tonic-gate 		}
1207*7c478bd9Sstevel@tonic-gate 	}
1208*7c478bd9Sstevel@tonic-gate 	fe->pair_type = FE_PAIR_NONE;
1209*7c478bd9Sstevel@tonic-gate 	fe->pair = 0;
1210*7c478bd9Sstevel@tonic-gate 
1211*7c478bd9Sstevel@tonic-gate send:
1212*7c478bd9Sstevel@tonic-gate 	/* Adjust event id address for multiple keyboard/workstation support */
1213*7c478bd9Sstevel@tonic-gate 	switch (vuid_id_addr(fe->id)) {
1214*7c478bd9Sstevel@tonic-gate 	case ASCII_FIRST:
1215*7c478bd9Sstevel@tonic-gate 		id_addr = upper->kbtrans_streams_vuid_addr.ascii;
1216*7c478bd9Sstevel@tonic-gate 		break;
1217*7c478bd9Sstevel@tonic-gate 	case TOP_FIRST:
1218*7c478bd9Sstevel@tonic-gate 		id_addr = upper->kbtrans_streams_vuid_addr.top;
1219*7c478bd9Sstevel@tonic-gate 		break;
1220*7c478bd9Sstevel@tonic-gate 	case VKEY_FIRST:
1221*7c478bd9Sstevel@tonic-gate 		id_addr = upper->kbtrans_streams_vuid_addr.vkey;
1222*7c478bd9Sstevel@tonic-gate 		break;
1223*7c478bd9Sstevel@tonic-gate 	default:
1224*7c478bd9Sstevel@tonic-gate 		id_addr = vuid_id_addr(fe->id);
1225*7c478bd9Sstevel@tonic-gate 		break;
1226*7c478bd9Sstevel@tonic-gate 	}
1227*7c478bd9Sstevel@tonic-gate 	fe->id = vuid_id_offset(fe->id) | id_addr;
1228*7c478bd9Sstevel@tonic-gate 
1229*7c478bd9Sstevel@tonic-gate 	kbtrans_queuepress(upper, key_station, fe);
1230*7c478bd9Sstevel@tonic-gate }
1231*7c478bd9Sstevel@tonic-gate 
1232*7c478bd9Sstevel@tonic-gate /*
1233*7c478bd9Sstevel@tonic-gate  * kbtrans_queuepress:
1234*7c478bd9Sstevel@tonic-gate  *	Add keypress to the "downs" table
1235*7c478bd9Sstevel@tonic-gate  */
1236*7c478bd9Sstevel@tonic-gate static void
1237*7c478bd9Sstevel@tonic-gate kbtrans_queuepress(struct kbtrans *upper,
1238*7c478bd9Sstevel@tonic-gate 		    uchar_t key_station, Firm_event *fe)
1239*7c478bd9Sstevel@tonic-gate {
1240*7c478bd9Sstevel@tonic-gate 	register struct key_event *ke, *ke_free;
1241*7c478bd9Sstevel@tonic-gate 	register int i;
1242*7c478bd9Sstevel@tonic-gate 
1243*7c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "kbtrans_queuepress:"
1244*7c478bd9Sstevel@tonic-gate 		" key=%d", key_station));
1245*7c478bd9Sstevel@tonic-gate 
1246*7c478bd9Sstevel@tonic-gate 	ke_free = 0;
1247*7c478bd9Sstevel@tonic-gate 
1248*7c478bd9Sstevel@tonic-gate 	/* Scan table of down key stations */
1249*7c478bd9Sstevel@tonic-gate 
1250*7c478bd9Sstevel@tonic-gate 	for (i = 0, ke = upper->kbtrans_streams_downs;
1251*7c478bd9Sstevel@tonic-gate 	    i < upper->kbtrans_streams_num_downs_entries; i++, ke++) {
1252*7c478bd9Sstevel@tonic-gate 
1253*7c478bd9Sstevel@tonic-gate 		/* Keycode already down? */
1254*7c478bd9Sstevel@tonic-gate 		if (ke->key_station == key_station) {
1255*7c478bd9Sstevel@tonic-gate 
1256*7c478bd9Sstevel@tonic-gate 			DPRINTF(PRINT_L0, PRINT_MASK_ALL,
1257*7c478bd9Sstevel@tonic-gate 				(NULL, "kbtrans: Double "
1258*7c478bd9Sstevel@tonic-gate 				"entry in downs table (%d,%d)!\n",
1259*7c478bd9Sstevel@tonic-gate 				key_station, i));
1260*7c478bd9Sstevel@tonic-gate 
1261*7c478bd9Sstevel@tonic-gate 			goto add_event;
1262*7c478bd9Sstevel@tonic-gate 		}
1263*7c478bd9Sstevel@tonic-gate 
1264*7c478bd9Sstevel@tonic-gate 		if (ke->key_station == 0)
1265*7c478bd9Sstevel@tonic-gate 			ke_free = ke;
1266*7c478bd9Sstevel@tonic-gate 	}
1267*7c478bd9Sstevel@tonic-gate 
1268*7c478bd9Sstevel@tonic-gate 	if (ke_free) {
1269*7c478bd9Sstevel@tonic-gate 		ke = ke_free;
1270*7c478bd9Sstevel@tonic-gate 		goto add_event;
1271*7c478bd9Sstevel@tonic-gate 	}
1272*7c478bd9Sstevel@tonic-gate 
1273*7c478bd9Sstevel@tonic-gate 	ke = upper->kbtrans_streams_downs;
1274*7c478bd9Sstevel@tonic-gate 
1275*7c478bd9Sstevel@tonic-gate add_event:
1276*7c478bd9Sstevel@tonic-gate 	ke->key_station = key_station;
1277*7c478bd9Sstevel@tonic-gate 	ke->event = *fe;
1278*7c478bd9Sstevel@tonic-gate 	kbtrans_queueevent(upper, fe);
1279*7c478bd9Sstevel@tonic-gate }
1280*7c478bd9Sstevel@tonic-gate 
1281*7c478bd9Sstevel@tonic-gate /*
1282*7c478bd9Sstevel@tonic-gate  * kbtrans_keyreleased:
1283*7c478bd9Sstevel@tonic-gate  * 	Remove entry from the downs table
1284*7c478bd9Sstevel@tonic-gate  */
1285*7c478bd9Sstevel@tonic-gate static void
1286*7c478bd9Sstevel@tonic-gate kbtrans_keyreleased(register struct kbtrans *upper, uchar_t key_station)
1287*7c478bd9Sstevel@tonic-gate {
1288*7c478bd9Sstevel@tonic-gate 	register struct key_event *ke;
1289*7c478bd9Sstevel@tonic-gate 	register int i;
1290*7c478bd9Sstevel@tonic-gate 
1291*7c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L0, PRINT_MASK_ALL, (NULL, "RELEASE key=%d\n",
1292*7c478bd9Sstevel@tonic-gate 		key_station));
1293*7c478bd9Sstevel@tonic-gate 
1294*7c478bd9Sstevel@tonic-gate 	if (upper->kbtrans_streams_translate_mode != TR_EVENT &&
1295*7c478bd9Sstevel@tonic-gate 	    upper->kbtrans_streams_translate_mode != TR_UNTRANS_EVENT) {
1296*7c478bd9Sstevel@tonic-gate 
1297*7c478bd9Sstevel@tonic-gate 		return;
1298*7c478bd9Sstevel@tonic-gate 	}
1299*7c478bd9Sstevel@tonic-gate 
1300*7c478bd9Sstevel@tonic-gate 	/* Scan table of down key stations */
1301*7c478bd9Sstevel@tonic-gate 	for (i = 0, ke = upper->kbtrans_streams_downs;
1302*7c478bd9Sstevel@tonic-gate 	    i < upper->kbtrans_streams_num_downs_entries;
1303*7c478bd9Sstevel@tonic-gate 	    i++, ke++) {
1304*7c478bd9Sstevel@tonic-gate 		/* Found? */
1305*7c478bd9Sstevel@tonic-gate 		if (ke->key_station == key_station) {
1306*7c478bd9Sstevel@tonic-gate 			ke->key_station = 0;
1307*7c478bd9Sstevel@tonic-gate 			ke->event.value = 0;
1308*7c478bd9Sstevel@tonic-gate 			kbtrans_queueevent(upper, &ke->event);
1309*7c478bd9Sstevel@tonic-gate 		}
1310*7c478bd9Sstevel@tonic-gate 	}
1311*7c478bd9Sstevel@tonic-gate 
1312*7c478bd9Sstevel@tonic-gate 	/*
1313*7c478bd9Sstevel@tonic-gate 	 * Ignore if couldn't find because may be called twice
1314*7c478bd9Sstevel@tonic-gate 	 * for the same key station in the case of the kbtrans_rpt
1315*7c478bd9Sstevel@tonic-gate 	 * routine being called unnecessarily.
1316*7c478bd9Sstevel@tonic-gate 	 */
1317*7c478bd9Sstevel@tonic-gate }
1318*7c478bd9Sstevel@tonic-gate 
1319*7c478bd9Sstevel@tonic-gate 
1320*7c478bd9Sstevel@tonic-gate /*
1321*7c478bd9Sstevel@tonic-gate  * kbtrans_putcode:
1322*7c478bd9Sstevel@tonic-gate  *	 Pass a keycode up the stream, if you can, otherwise throw it away.
1323*7c478bd9Sstevel@tonic-gate  */
1324*7c478bd9Sstevel@tonic-gate static void
1325*7c478bd9Sstevel@tonic-gate kbtrans_putcode(register struct kbtrans *upper, uint_t code)
1326*7c478bd9Sstevel@tonic-gate {
1327*7c478bd9Sstevel@tonic-gate 	register mblk_t *bp;
1328*7c478bd9Sstevel@tonic-gate 
1329*7c478bd9Sstevel@tonic-gate 	/*
1330*7c478bd9Sstevel@tonic-gate 	 * If we can't send it up, then we just drop it.
1331*7c478bd9Sstevel@tonic-gate 	 */
1332*7c478bd9Sstevel@tonic-gate 	if (!canputnext(upper->kbtrans_streams_readq)) {
1333*7c478bd9Sstevel@tonic-gate 
1334*7c478bd9Sstevel@tonic-gate 		return;
1335*7c478bd9Sstevel@tonic-gate 	}
1336*7c478bd9Sstevel@tonic-gate 
1337*7c478bd9Sstevel@tonic-gate 	/*
1338*7c478bd9Sstevel@tonic-gate 	 * Allocate a messsage block to send up.
1339*7c478bd9Sstevel@tonic-gate 	 */
1340*7c478bd9Sstevel@tonic-gate 	if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL) {
1341*7c478bd9Sstevel@tonic-gate 
1342*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "kbtrans_putcode: Can't allocate block\
1343*7c478bd9Sstevel@tonic-gate 			for keycode.");
1344*7c478bd9Sstevel@tonic-gate 
1345*7c478bd9Sstevel@tonic-gate 		return;
1346*7c478bd9Sstevel@tonic-gate 	}
1347*7c478bd9Sstevel@tonic-gate 
1348*7c478bd9Sstevel@tonic-gate 	/*
1349*7c478bd9Sstevel@tonic-gate 	 * We will strip out any high order information here.
1350*7c478bd9Sstevel@tonic-gate 	 */
1351*7c478bd9Sstevel@tonic-gate 	/* NOTE the implicit cast here */
1352*7c478bd9Sstevel@tonic-gate 	*bp->b_wptr++ = (uchar_t)code;
1353*7c478bd9Sstevel@tonic-gate 
1354*7c478bd9Sstevel@tonic-gate 	/*
1355*7c478bd9Sstevel@tonic-gate 	 * Send the message up.
1356*7c478bd9Sstevel@tonic-gate 	 */
1357*7c478bd9Sstevel@tonic-gate 	(void) putnext(upper->kbtrans_streams_readq, bp);
1358*7c478bd9Sstevel@tonic-gate }
1359*7c478bd9Sstevel@tonic-gate 
1360*7c478bd9Sstevel@tonic-gate 
1361*7c478bd9Sstevel@tonic-gate /*
1362*7c478bd9Sstevel@tonic-gate  * kbtrans_putbuf:
1363*7c478bd9Sstevel@tonic-gate  *	Pass generated keycode sequence to upstream, if possible.
1364*7c478bd9Sstevel@tonic-gate  */
1365*7c478bd9Sstevel@tonic-gate static void
1366*7c478bd9Sstevel@tonic-gate kbtrans_putbuf(char *buf, queue_t *q)
1367*7c478bd9Sstevel@tonic-gate {
1368*7c478bd9Sstevel@tonic-gate 	register mblk_t *bp;
1369*7c478bd9Sstevel@tonic-gate 
1370*7c478bd9Sstevel@tonic-gate 	if (!canputnext(q)) {
1371*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "kbtrans_putbuf: Can't put block for keycode");
1372*7c478bd9Sstevel@tonic-gate 	} else {
1373*7c478bd9Sstevel@tonic-gate 		if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL) {
1374*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "kbtrans_putbuf: "
1375*7c478bd9Sstevel@tonic-gate 			    "Can't allocate block for keycode");
1376*7c478bd9Sstevel@tonic-gate 		} else {
1377*7c478bd9Sstevel@tonic-gate 			while (*buf) {
1378*7c478bd9Sstevel@tonic-gate 				*bp->b_wptr++ = *buf;
1379*7c478bd9Sstevel@tonic-gate 				buf++;
1380*7c478bd9Sstevel@tonic-gate 			}
1381*7c478bd9Sstevel@tonic-gate 			putnext(q, bp);
1382*7c478bd9Sstevel@tonic-gate 		}
1383*7c478bd9Sstevel@tonic-gate 	}
1384*7c478bd9Sstevel@tonic-gate }
1385*7c478bd9Sstevel@tonic-gate 
1386*7c478bd9Sstevel@tonic-gate /*
1387*7c478bd9Sstevel@tonic-gate  * kbtrans_queueevent:
1388*7c478bd9Sstevel@tonic-gate  *	 Pass a VUID "firm event" up the stream, if you can.
1389*7c478bd9Sstevel@tonic-gate  */
1390*7c478bd9Sstevel@tonic-gate static void
1391*7c478bd9Sstevel@tonic-gate kbtrans_queueevent(struct kbtrans *upper, Firm_event *fe)
1392*7c478bd9Sstevel@tonic-gate {
1393*7c478bd9Sstevel@tonic-gate 	register queue_t *q;
1394*7c478bd9Sstevel@tonic-gate 	register mblk_t *bp;
1395*7c478bd9Sstevel@tonic-gate 
1396*7c478bd9Sstevel@tonic-gate 	if ((q = upper->kbtrans_streams_readq) == NULL)
1397*7c478bd9Sstevel@tonic-gate 
1398*7c478bd9Sstevel@tonic-gate 		return;
1399*7c478bd9Sstevel@tonic-gate 
1400*7c478bd9Sstevel@tonic-gate 	if (!canputnext(q)) {
1401*7c478bd9Sstevel@tonic-gate 		if (kbtrans_overflow_msg) {
1402*7c478bd9Sstevel@tonic-gate 			DPRINTF(PRINT_L2, PRINT_MASK_ALL, (NULL,
1403*7c478bd9Sstevel@tonic-gate 				"kbtrans: Buffer flushed when overflowed."));
1404*7c478bd9Sstevel@tonic-gate 		}
1405*7c478bd9Sstevel@tonic-gate 
1406*7c478bd9Sstevel@tonic-gate 		kbtrans_flush(upper);
1407*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_overflow_cnt++;
1408*7c478bd9Sstevel@tonic-gate 	} else {
1409*7c478bd9Sstevel@tonic-gate 		if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL) {
1410*7c478bd9Sstevel@tonic-gate 			cmn_err(CE_WARN, "kbtrans_queueevent: Can't allocate \
1411*7c478bd9Sstevel@tonic-gate 					block for event.");
1412*7c478bd9Sstevel@tonic-gate 		} else {
1413*7c478bd9Sstevel@tonic-gate 			uniqtime32(&fe->time);
1414*7c478bd9Sstevel@tonic-gate 			 *(Firm_event *)bp->b_wptr = *fe;
1415*7c478bd9Sstevel@tonic-gate 			bp->b_wptr += sizeof (Firm_event);
1416*7c478bd9Sstevel@tonic-gate 			(void) putnext(q, bp);
1417*7c478bd9Sstevel@tonic-gate 
1418*7c478bd9Sstevel@tonic-gate 
1419*7c478bd9Sstevel@tonic-gate 		}
1420*7c478bd9Sstevel@tonic-gate 	}
1421*7c478bd9Sstevel@tonic-gate }
1422*7c478bd9Sstevel@tonic-gate 
1423*7c478bd9Sstevel@tonic-gate /*
1424*7c478bd9Sstevel@tonic-gate  * kbtrans_set_translation_callback:
1425*7c478bd9Sstevel@tonic-gate  *	This code sets the translation_callback pointer based on the
1426*7c478bd9Sstevel@tonic-gate  * 	translation mode.
1427*7c478bd9Sstevel@tonic-gate  */
1428*7c478bd9Sstevel@tonic-gate static void
1429*7c478bd9Sstevel@tonic-gate kbtrans_set_translation_callback(register struct kbtrans *upper)
1430*7c478bd9Sstevel@tonic-gate {
1431*7c478bd9Sstevel@tonic-gate 	switch (upper->kbtrans_streams_translate_mode) {
1432*7c478bd9Sstevel@tonic-gate 
1433*7c478bd9Sstevel@tonic-gate 	default:
1434*7c478bd9Sstevel@tonic-gate 	case TR_ASCII:
1435*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_callback = &ascii_callback;
1436*7c478bd9Sstevel@tonic-gate 
1437*7c478bd9Sstevel@tonic-gate 		break;
1438*7c478bd9Sstevel@tonic-gate 
1439*7c478bd9Sstevel@tonic-gate 	case TR_EVENT:
1440*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_callback = &trans_event_callback;
1441*7c478bd9Sstevel@tonic-gate 
1442*7c478bd9Sstevel@tonic-gate 		break;
1443*7c478bd9Sstevel@tonic-gate 
1444*7c478bd9Sstevel@tonic-gate 	case TR_UNTRANS_EVENT:
1445*7c478bd9Sstevel@tonic-gate 		upper->kbtrans_streams_callback = &untrans_event_callback;
1446*7c478bd9Sstevel@tonic-gate 
1447*7c478bd9Sstevel@tonic-gate 		break;
1448*7c478bd9Sstevel@tonic-gate 	}
1449*7c478bd9Sstevel@tonic-gate }
1450*7c478bd9Sstevel@tonic-gate 
1451*7c478bd9Sstevel@tonic-gate /*
1452*7c478bd9Sstevel@tonic-gate  * kbtrans_untrans_keypressed_raw:
1453*7c478bd9Sstevel@tonic-gate  *	This is the callback we get if we are in TR_UNTRANS_EVENT and a
1454*7c478bd9Sstevel@tonic-gate  * 	key is pressed.  This code will just send the scancode up the
1455*7c478bd9Sstevel@tonic-gate  * 	stream.
1456*7c478bd9Sstevel@tonic-gate  */
1457*7c478bd9Sstevel@tonic-gate static void
1458*7c478bd9Sstevel@tonic-gate kbtrans_untrans_keypressed_raw(struct kbtrans *upper, kbtrans_key_t key)
1459*7c478bd9Sstevel@tonic-gate {
1460*7c478bd9Sstevel@tonic-gate 	Firm_event	fe;
1461*7c478bd9Sstevel@tonic-gate 
1462*7c478bd9Sstevel@tonic-gate 	bzero(&fe, sizeof (fe));
1463*7c478bd9Sstevel@tonic-gate 
1464*7c478bd9Sstevel@tonic-gate 	/*
1465*7c478bd9Sstevel@tonic-gate 	 * fill in the event
1466*7c478bd9Sstevel@tonic-gate 	 */
1467*7c478bd9Sstevel@tonic-gate 	fe.id = (unsigned short)key;
1468*7c478bd9Sstevel@tonic-gate 	fe.value = 1;
1469*7c478bd9Sstevel@tonic-gate 
1470*7c478bd9Sstevel@tonic-gate 	/*
1471*7c478bd9Sstevel@tonic-gate 	 * Send the event upstream.
1472*7c478bd9Sstevel@tonic-gate 	 */
1473*7c478bd9Sstevel@tonic-gate 	kbtrans_queuepress(upper, key, &fe);
1474*7c478bd9Sstevel@tonic-gate }
1475*7c478bd9Sstevel@tonic-gate 
1476*7c478bd9Sstevel@tonic-gate /*
1477*7c478bd9Sstevel@tonic-gate  * kbtrans_untrans_keyreleased_raw:
1478*7c478bd9Sstevel@tonic-gate  *	This is the callback we get if we are in TR_UNTRANS_EVENT mode
1479*7c478bd9Sstevel@tonic-gate  * 	and a key is released.  This code will just send the scancode up
1480*7c478bd9Sstevel@tonic-gate  * 	the stream.
1481*7c478bd9Sstevel@tonic-gate  */
1482*7c478bd9Sstevel@tonic-gate static void
1483*7c478bd9Sstevel@tonic-gate kbtrans_untrans_keyreleased_raw(struct kbtrans *upper, kbtrans_key_t key)
1484*7c478bd9Sstevel@tonic-gate {
1485*7c478bd9Sstevel@tonic-gate 	/*
1486*7c478bd9Sstevel@tonic-gate 	 * Deal with a key released event.
1487*7c478bd9Sstevel@tonic-gate 	 */
1488*7c478bd9Sstevel@tonic-gate 	kbtrans_keyreleased(upper, key);
1489*7c478bd9Sstevel@tonic-gate }
1490*7c478bd9Sstevel@tonic-gate 
1491*7c478bd9Sstevel@tonic-gate /*
1492*7c478bd9Sstevel@tonic-gate  * kbtrans_ascii_keypressed:
1493*7c478bd9Sstevel@tonic-gate  *	This is the code if we are in TR_ASCII mode and a key
1494*7c478bd9Sstevel@tonic-gate  * 	is pressed.  This is where we will do any special processing that
1495*7c478bd9Sstevel@tonic-gate  * 	is specific to ASCII key translation.
1496*7c478bd9Sstevel@tonic-gate  */
1497*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
1498*7c478bd9Sstevel@tonic-gate static void
1499*7c478bd9Sstevel@tonic-gate kbtrans_ascii_keypressed(
1500*7c478bd9Sstevel@tonic-gate     struct kbtrans	*upper,
1501*7c478bd9Sstevel@tonic-gate     uint_t 		entrytype,
1502*7c478bd9Sstevel@tonic-gate     kbtrans_key_t 	key,
1503*7c478bd9Sstevel@tonic-gate     uint_t 		entry)
1504*7c478bd9Sstevel@tonic-gate {
1505*7c478bd9Sstevel@tonic-gate 	register char	*cp;
1506*7c478bd9Sstevel@tonic-gate 	register char	*bufp;
1507*7c478bd9Sstevel@tonic-gate 	char		buf[14];
1508*7c478bd9Sstevel@tonic-gate 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1509*7c478bd9Sstevel@tonic-gate 
1510*7c478bd9Sstevel@tonic-gate 	/*
1511*7c478bd9Sstevel@tonic-gate 	 * Based on the type of key, we may need to do some ASCII
1512*7c478bd9Sstevel@tonic-gate 	 * specific post processing.
1513*7c478bd9Sstevel@tonic-gate 	 */
1514*7c478bd9Sstevel@tonic-gate 	switch (entrytype) {
1515*7c478bd9Sstevel@tonic-gate 
1516*7c478bd9Sstevel@tonic-gate 	case BUCKYBITS:
1517*7c478bd9Sstevel@tonic-gate 	case SHIFTKEYS:
1518*7c478bd9Sstevel@tonic-gate 	case FUNNY:
1519*7c478bd9Sstevel@tonic-gate 		/*
1520*7c478bd9Sstevel@tonic-gate 		 * There is no ascii equivalent.  We will ignore these
1521*7c478bd9Sstevel@tonic-gate 		 * keys
1522*7c478bd9Sstevel@tonic-gate 		 */
1523*7c478bd9Sstevel@tonic-gate 		return;
1524*7c478bd9Sstevel@tonic-gate 
1525*7c478bd9Sstevel@tonic-gate 	case FUNCKEYS:
1526*7c478bd9Sstevel@tonic-gate 		/*
1527*7c478bd9Sstevel@tonic-gate 		 * We need to expand this key to get the ascii
1528*7c478bd9Sstevel@tonic-gate 		 * equivalent.  These are the function keys (F1, F2 ...)
1529*7c478bd9Sstevel@tonic-gate 		 */
1530*7c478bd9Sstevel@tonic-gate 		bufp = buf;
1531*7c478bd9Sstevel@tonic-gate 		cp = kbtrans_strsetwithdecimal(bufp + 2,
1532*7c478bd9Sstevel@tonic-gate 			(uint_t)((entry & 0x003F) + 192),
1533*7c478bd9Sstevel@tonic-gate 			sizeof (buf) - 5);
1534*7c478bd9Sstevel@tonic-gate 		*bufp++ = '\033'; /* Escape */
1535*7c478bd9Sstevel@tonic-gate 		*bufp++ = '[';
1536*7c478bd9Sstevel@tonic-gate 		while (*cp != '\0')
1537*7c478bd9Sstevel@tonic-gate 			*bufp++ = *cp++;
1538*7c478bd9Sstevel@tonic-gate 		*bufp++ = 'z';
1539*7c478bd9Sstevel@tonic-gate 		*bufp = '\0';
1540*7c478bd9Sstevel@tonic-gate 
1541*7c478bd9Sstevel@tonic-gate 		/*
1542*7c478bd9Sstevel@tonic-gate 		 * Send the result upstream.
1543*7c478bd9Sstevel@tonic-gate 		 */
1544*7c478bd9Sstevel@tonic-gate 		kbtrans_putbuf(buf, upper->kbtrans_streams_readq);
1545*7c478bd9Sstevel@tonic-gate 
1546*7c478bd9Sstevel@tonic-gate 		return;
1547*7c478bd9Sstevel@tonic-gate 
1548*7c478bd9Sstevel@tonic-gate 	case STRING:
1549*7c478bd9Sstevel@tonic-gate 		/*
1550*7c478bd9Sstevel@tonic-gate 		 * These are the multi byte keys (Home, Up, Down ...)
1551*7c478bd9Sstevel@tonic-gate 		 */
1552*7c478bd9Sstevel@tonic-gate 		cp = &lower->kbtrans_keystringtab[entry & 0x0F][0];
1553*7c478bd9Sstevel@tonic-gate 
1554*7c478bd9Sstevel@tonic-gate 		/*
1555*7c478bd9Sstevel@tonic-gate 		 * Copy the string from the keystringtable, and send it
1556*7c478bd9Sstevel@tonic-gate 		 * upstream a character at a time.
1557*7c478bd9Sstevel@tonic-gate 		 */
1558*7c478bd9Sstevel@tonic-gate 		while (*cp != '\0') {
1559*7c478bd9Sstevel@tonic-gate 
1560*7c478bd9Sstevel@tonic-gate 			kbtrans_putcode(upper, (uchar_t)*cp);
1561*7c478bd9Sstevel@tonic-gate 
1562*7c478bd9Sstevel@tonic-gate 			cp++;
1563*7c478bd9Sstevel@tonic-gate 		}
1564*7c478bd9Sstevel@tonic-gate 
1565*7c478bd9Sstevel@tonic-gate 		return;
1566*7c478bd9Sstevel@tonic-gate 
1567*7c478bd9Sstevel@tonic-gate 	case PADKEYS:
1568*7c478bd9Sstevel@tonic-gate 		/*
1569*7c478bd9Sstevel@tonic-gate 		 * These are the keys on the keypad.  Look up the
1570*7c478bd9Sstevel@tonic-gate 		 * answer in the kb_numlock_table and send it upstream.
1571*7c478bd9Sstevel@tonic-gate 		 */
1572*7c478bd9Sstevel@tonic-gate 		kbtrans_putcode(upper,
1573*7c478bd9Sstevel@tonic-gate 			    lower->kbtrans_numlock_table[entry&0x1F]);
1574*7c478bd9Sstevel@tonic-gate 
1575*7c478bd9Sstevel@tonic-gate 		return;
1576*7c478bd9Sstevel@tonic-gate 
1577*7c478bd9Sstevel@tonic-gate 	case 0:	/* normal character */
1578*7c478bd9Sstevel@tonic-gate 	default:
1579*7c478bd9Sstevel@tonic-gate 		break;
1580*7c478bd9Sstevel@tonic-gate 	}
1581*7c478bd9Sstevel@tonic-gate 
1582*7c478bd9Sstevel@tonic-gate 	/*
1583*7c478bd9Sstevel@tonic-gate 	 * Send the byte upstream.
1584*7c478bd9Sstevel@tonic-gate 	 */
1585*7c478bd9Sstevel@tonic-gate 	kbtrans_putcode(upper, entry);
1586*7c478bd9Sstevel@tonic-gate 
1587*7c478bd9Sstevel@tonic-gate }
1588*7c478bd9Sstevel@tonic-gate 
1589*7c478bd9Sstevel@tonic-gate /*
1590*7c478bd9Sstevel@tonic-gate  * kbtrans_ascii_keyreleased:
1591*7c478bd9Sstevel@tonic-gate  *	This is the function if we are in TR_ASCII mode and a key
1592*7c478bd9Sstevel@tonic-gate  * 	is released.  ASCII doesn't have the concept of released keys,
1593*7c478bd9Sstevel@tonic-gate  * 	or make/break codes.  So there is nothing for us to do.
1594*7c478bd9Sstevel@tonic-gate  */
1595*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
1596*7c478bd9Sstevel@tonic-gate static void
1597*7c478bd9Sstevel@tonic-gate kbtrans_ascii_keyreleased(struct kbtrans *upper, kbtrans_key_t key)
1598*7c478bd9Sstevel@tonic-gate {
1599*7c478bd9Sstevel@tonic-gate 	/* Nothing to do ... for now */
1600*7c478bd9Sstevel@tonic-gate }
1601*7c478bd9Sstevel@tonic-gate 
1602*7c478bd9Sstevel@tonic-gate /*
1603*7c478bd9Sstevel@tonic-gate  * kbtrans_ascii_setup_repeat:
1604*7c478bd9Sstevel@tonic-gate  *	This is the function if we are in TR_ASCII mode and the
1605*7c478bd9Sstevel@tonic-gate  * 	translation module has decided that a key needs to be repeated.
1606*7c478bd9Sstevel@tonic-gate  */
1607*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
1608*7c478bd9Sstevel@tonic-gate static void
1609*7c478bd9Sstevel@tonic-gate kbtrans_ascii_setup_repeat(
1610*7c478bd9Sstevel@tonic-gate     struct kbtrans *upper,
1611*7c478bd9Sstevel@tonic-gate     uint_t entrytype,
1612*7c478bd9Sstevel@tonic-gate     kbtrans_key_t key)
1613*7c478bd9Sstevel@tonic-gate {
1614*7c478bd9Sstevel@tonic-gate 	struct kbtrans_lower *lower = &upper->kbtrans_lower;
1615*7c478bd9Sstevel@tonic-gate 
1616*7c478bd9Sstevel@tonic-gate 	/*
1617*7c478bd9Sstevel@tonic-gate 	 * Cancel any currently repeating keys.  This will be a new
1618*7c478bd9Sstevel@tonic-gate 	 * key to repeat.
1619*7c478bd9Sstevel@tonic-gate 	 */
1620*7c478bd9Sstevel@tonic-gate 	kbtrans_cancelrpt(upper);
1621*7c478bd9Sstevel@tonic-gate 
1622*7c478bd9Sstevel@tonic-gate 	/*
1623*7c478bd9Sstevel@tonic-gate 	 * Set the value of the key to be repeated.
1624*7c478bd9Sstevel@tonic-gate 	 */
1625*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_repeatkey = key;
1626*7c478bd9Sstevel@tonic-gate 
1627*7c478bd9Sstevel@tonic-gate 	/*
1628*7c478bd9Sstevel@tonic-gate 	 * Start the timeout for repeating this key.  kbtrans_rpt will
1629*7c478bd9Sstevel@tonic-gate 	 * be called to repeat the key.
1630*7c478bd9Sstevel@tonic-gate 	 */
1631*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq,
1632*7c478bd9Sstevel@tonic-gate 		kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay);
1633*7c478bd9Sstevel@tonic-gate }
1634*7c478bd9Sstevel@tonic-gate 
1635*7c478bd9Sstevel@tonic-gate /*
1636*7c478bd9Sstevel@tonic-gate  * kbtrans_trans_event_keypressed:
1637*7c478bd9Sstevel@tonic-gate  *	This is the function if we are in TR_EVENT mode and a key
1638*7c478bd9Sstevel@tonic-gate  * 	is pressed.  This is where we will do any special processing that
1639*7c478bd9Sstevel@tonic-gate  * 	is specific to EVENT key translation.
1640*7c478bd9Sstevel@tonic-gate  */
1641*7c478bd9Sstevel@tonic-gate static void
1642*7c478bd9Sstevel@tonic-gate kbtrans_trans_event_keypressed(
1643*7c478bd9Sstevel@tonic-gate 	struct kbtrans 	*upper,
1644*7c478bd9Sstevel@tonic-gate 	uint_t 		entrytype,
1645*7c478bd9Sstevel@tonic-gate 	kbtrans_key_t 	key,
1646*7c478bd9Sstevel@tonic-gate 	uint_t 		entry)
1647*7c478bd9Sstevel@tonic-gate {
1648*7c478bd9Sstevel@tonic-gate 	Firm_event	fe;
1649*7c478bd9Sstevel@tonic-gate 	register char	*cp;
1650*7c478bd9Sstevel@tonic-gate 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
1651*7c478bd9Sstevel@tonic-gate 
1652*7c478bd9Sstevel@tonic-gate 	/*
1653*7c478bd9Sstevel@tonic-gate 	 * Based on the type of key, we may need to do some EVENT
1654*7c478bd9Sstevel@tonic-gate 	 * specific post processing.
1655*7c478bd9Sstevel@tonic-gate 	 */
1656*7c478bd9Sstevel@tonic-gate 	switch (entrytype) {
1657*7c478bd9Sstevel@tonic-gate 
1658*7c478bd9Sstevel@tonic-gate 	case SHIFTKEYS:
1659*7c478bd9Sstevel@tonic-gate 		/*
1660*7c478bd9Sstevel@tonic-gate 		 * Relying on ordinal correspondence between
1661*7c478bd9Sstevel@tonic-gate 		 * vuid_event.h SHIFT_META-SHIFT_TOP &
1662*7c478bd9Sstevel@tonic-gate 		 * kbd.h METABIT-SYSTEMBIT in order to
1663*7c478bd9Sstevel@tonic-gate 		 * correctly translate entry into fe.id.
1664*7c478bd9Sstevel@tonic-gate 		 */
1665*7c478bd9Sstevel@tonic-gate 		fe.id = SHIFT_CAPSLOCK + (entry & 0x0F);
1666*7c478bd9Sstevel@tonic-gate 		fe.value = 1;
1667*7c478bd9Sstevel@tonic-gate 		kbtrans_keypressed(upper, key, &fe, fe.id);
1668*7c478bd9Sstevel@tonic-gate 
1669*7c478bd9Sstevel@tonic-gate 		return;
1670*7c478bd9Sstevel@tonic-gate 
1671*7c478bd9Sstevel@tonic-gate 	case BUCKYBITS:
1672*7c478bd9Sstevel@tonic-gate 		/*
1673*7c478bd9Sstevel@tonic-gate 		 * Relying on ordinal correspondence between
1674*7c478bd9Sstevel@tonic-gate 		 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
1675*7c478bd9Sstevel@tonic-gate 		 * kbd.h CAPSLOCK-RIGHTCTRL in order to
1676*7c478bd9Sstevel@tonic-gate 		 * correctly translate entry into fe.id.
1677*7c478bd9Sstevel@tonic-gate 		 */
1678*7c478bd9Sstevel@tonic-gate 		fe.id = SHIFT_META + (entry & 0x0F);
1679*7c478bd9Sstevel@tonic-gate 		fe.value = 1;
1680*7c478bd9Sstevel@tonic-gate 		kbtrans_keypressed(upper, key, &fe, fe.id);
1681*7c478bd9Sstevel@tonic-gate 
1682*7c478bd9Sstevel@tonic-gate 		return;
1683*7c478bd9Sstevel@tonic-gate 
1684*7c478bd9Sstevel@tonic-gate 	case FUNCKEYS:
1685*7c478bd9Sstevel@tonic-gate 		/*
1686*7c478bd9Sstevel@tonic-gate 		 * Take advantage of the similar
1687*7c478bd9Sstevel@tonic-gate 		 * ordering of kbd.h function keys and
1688*7c478bd9Sstevel@tonic-gate 		 * vuid_event.h function keys to do a
1689*7c478bd9Sstevel@tonic-gate 		 * simple translation to achieve a
1690*7c478bd9Sstevel@tonic-gate 		 * mapping between the 2 different
1691*7c478bd9Sstevel@tonic-gate 		 * address spaces.
1692*7c478bd9Sstevel@tonic-gate 		 */
1693*7c478bd9Sstevel@tonic-gate 		fe.id = KEY_LEFTFIRST + (entry & 0x003F);
1694*7c478bd9Sstevel@tonic-gate 		fe.value = 1;
1695*7c478bd9Sstevel@tonic-gate 
1696*7c478bd9Sstevel@tonic-gate 		/*
1697*7c478bd9Sstevel@tonic-gate 		 * Assume "up" table only generates
1698*7c478bd9Sstevel@tonic-gate 		 * shift changes.
1699*7c478bd9Sstevel@tonic-gate 		 */
1700*7c478bd9Sstevel@tonic-gate 		kbtrans_keypressed(upper, key, &fe, fe.id);
1701*7c478bd9Sstevel@tonic-gate 
1702*7c478bd9Sstevel@tonic-gate 		/*
1703*7c478bd9Sstevel@tonic-gate 		 * Function key events can be expanded
1704*7c478bd9Sstevel@tonic-gate 		 * by terminal emulator software to
1705*7c478bd9Sstevel@tonic-gate 		 * produce the standard escape sequence
1706*7c478bd9Sstevel@tonic-gate 		 * generated by the TR_ASCII case above
1707*7c478bd9Sstevel@tonic-gate 		 * if a function key event is not used
1708*7c478bd9Sstevel@tonic-gate 		 * by terminal emulator software
1709*7c478bd9Sstevel@tonic-gate 		 * directly.
1710*7c478bd9Sstevel@tonic-gate 		 */
1711*7c478bd9Sstevel@tonic-gate 		return;
1712*7c478bd9Sstevel@tonic-gate 
1713*7c478bd9Sstevel@tonic-gate 	case STRING:
1714*7c478bd9Sstevel@tonic-gate 		/*
1715*7c478bd9Sstevel@tonic-gate 		 * These are the multi byte keys (Home, Up, Down ...)
1716*7c478bd9Sstevel@tonic-gate 		 */
1717*7c478bd9Sstevel@tonic-gate 		cp = &lower->kbtrans_keystringtab[entry & 0x0F][0];
1718*7c478bd9Sstevel@tonic-gate 
1719*7c478bd9Sstevel@tonic-gate 		/*
1720*7c478bd9Sstevel@tonic-gate 		 * Copy the string from the keystringtable, and send it
1721*7c478bd9Sstevel@tonic-gate 		 * upstream a character at a time.
1722*7c478bd9Sstevel@tonic-gate 		 */
1723*7c478bd9Sstevel@tonic-gate 		while (*cp != '\0') {
1724*7c478bd9Sstevel@tonic-gate 
1725*7c478bd9Sstevel@tonic-gate 			kbtrans_send_esc_event(*cp, upper);
1726*7c478bd9Sstevel@tonic-gate 
1727*7c478bd9Sstevel@tonic-gate 			cp++;
1728*7c478bd9Sstevel@tonic-gate 		}
1729*7c478bd9Sstevel@tonic-gate 
1730*7c478bd9Sstevel@tonic-gate 		return;
1731*7c478bd9Sstevel@tonic-gate 
1732*7c478bd9Sstevel@tonic-gate 	case PADKEYS:
1733*7c478bd9Sstevel@tonic-gate 		/*
1734*7c478bd9Sstevel@tonic-gate 		 * Take advantage of the similar
1735*7c478bd9Sstevel@tonic-gate 		 * ordering of kbd.h keypad keys and
1736*7c478bd9Sstevel@tonic-gate 		 * vuid_event.h keypad keys to do a
1737*7c478bd9Sstevel@tonic-gate 		 * simple translation to achieve a
1738*7c478bd9Sstevel@tonic-gate 		 * mapping between the 2 different
1739*7c478bd9Sstevel@tonic-gate 		 * address spaces.
1740*7c478bd9Sstevel@tonic-gate 		 */
1741*7c478bd9Sstevel@tonic-gate 		fe.id = VKEY_FIRSTPAD + (entry & 0x001F);
1742*7c478bd9Sstevel@tonic-gate 		fe.value = 1;
1743*7c478bd9Sstevel@tonic-gate 
1744*7c478bd9Sstevel@tonic-gate 		/*
1745*7c478bd9Sstevel@tonic-gate 		 * Assume "up" table only generates
1746*7c478bd9Sstevel@tonic-gate 		 * shift changes.
1747*7c478bd9Sstevel@tonic-gate 		 */
1748*7c478bd9Sstevel@tonic-gate 		kbtrans_keypressed(upper, key, &fe, fe.id);
1749*7c478bd9Sstevel@tonic-gate 
1750*7c478bd9Sstevel@tonic-gate 		/*
1751*7c478bd9Sstevel@tonic-gate 		 * Keypad key events can be expanded
1752*7c478bd9Sstevel@tonic-gate 		 * by terminal emulator software to
1753*7c478bd9Sstevel@tonic-gate 		 * produce the standard ascii character
1754*7c478bd9Sstevel@tonic-gate 		 * generated by the TR_ASCII case above
1755*7c478bd9Sstevel@tonic-gate 		 * if a keypad key event is not used
1756*7c478bd9Sstevel@tonic-gate 		 * by terminal emulator software
1757*7c478bd9Sstevel@tonic-gate 		 * directly.
1758*7c478bd9Sstevel@tonic-gate 		 */
1759*7c478bd9Sstevel@tonic-gate 		return;
1760*7c478bd9Sstevel@tonic-gate 
1761*7c478bd9Sstevel@tonic-gate 	case FUNNY:
1762*7c478bd9Sstevel@tonic-gate 		/*
1763*7c478bd9Sstevel@tonic-gate 		 * These are not events.
1764*7c478bd9Sstevel@tonic-gate 		 */
1765*7c478bd9Sstevel@tonic-gate 		switch (entry) {
1766*7c478bd9Sstevel@tonic-gate 		case IDLE:
1767*7c478bd9Sstevel@tonic-gate 		case RESET:
1768*7c478bd9Sstevel@tonic-gate 		case ERROR:
1769*7c478bd9Sstevel@tonic-gate 			/*
1770*7c478bd9Sstevel@tonic-gate 			 * Something has happened.  Mark all keys as released.
1771*7c478bd9Sstevel@tonic-gate 			 */
1772*7c478bd9Sstevel@tonic-gate 			kbtrans_streams_releaseall(upper);
1773*7c478bd9Sstevel@tonic-gate 			break;
1774*7c478bd9Sstevel@tonic-gate 		}
1775*7c478bd9Sstevel@tonic-gate 
1776*7c478bd9Sstevel@tonic-gate 		return;
1777*7c478bd9Sstevel@tonic-gate 
1778*7c478bd9Sstevel@tonic-gate 	case 0: /* normal character */
1779*7c478bd9Sstevel@tonic-gate 	default:
1780*7c478bd9Sstevel@tonic-gate 		break;
1781*7c478bd9Sstevel@tonic-gate 	}
1782*7c478bd9Sstevel@tonic-gate 
1783*7c478bd9Sstevel@tonic-gate 	/*
1784*7c478bd9Sstevel@tonic-gate 	 * Send the event upstream.
1785*7c478bd9Sstevel@tonic-gate 	 */
1786*7c478bd9Sstevel@tonic-gate 	fe.id = entry;
1787*7c478bd9Sstevel@tonic-gate 
1788*7c478bd9Sstevel@tonic-gate 	fe.value = 1;
1789*7c478bd9Sstevel@tonic-gate 
1790*7c478bd9Sstevel@tonic-gate 	kbtrans_queueevent(upper, &fe);
1791*7c478bd9Sstevel@tonic-gate }
1792*7c478bd9Sstevel@tonic-gate 
1793*7c478bd9Sstevel@tonic-gate /*
1794*7c478bd9Sstevel@tonic-gate  * kbtrans_trans_event_keyreleased:
1795*7c478bd9Sstevel@tonic-gate  *	This is the function if we are in TR_EVENT mode and a key
1796*7c478bd9Sstevel@tonic-gate  * 	is released.
1797*7c478bd9Sstevel@tonic-gate  */
1798*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
1799*7c478bd9Sstevel@tonic-gate static void
1800*7c478bd9Sstevel@tonic-gate kbtrans_trans_event_keyreleased(struct kbtrans *upper, kbtrans_key_t key)
1801*7c478bd9Sstevel@tonic-gate {
1802*7c478bd9Sstevel@tonic-gate 	/*
1803*7c478bd9Sstevel@tonic-gate 	 * Mark the key as released and send an event upstream.
1804*7c478bd9Sstevel@tonic-gate 	 */
1805*7c478bd9Sstevel@tonic-gate 	kbtrans_keyreleased(upper, key);
1806*7c478bd9Sstevel@tonic-gate }
1807*7c478bd9Sstevel@tonic-gate 
1808*7c478bd9Sstevel@tonic-gate /*
1809*7c478bd9Sstevel@tonic-gate  * kbtrans_trans_event_setup_repeat:
1810*7c478bd9Sstevel@tonic-gate  *	This is the function if we are in TR_EVENT mode and the
1811*7c478bd9Sstevel@tonic-gate  *	translation module has decided that a key needs to be repeated.
1812*7c478bd9Sstevel@tonic-gate  * 	We will set a timeout to retranslate the repeat key.
1813*7c478bd9Sstevel@tonic-gate  */
1814*7c478bd9Sstevel@tonic-gate static void
1815*7c478bd9Sstevel@tonic-gate kbtrans_trans_event_setup_repeat(
1816*7c478bd9Sstevel@tonic-gate 	struct kbtrans	*upper,
1817*7c478bd9Sstevel@tonic-gate 	uint_t 		entrytype,
1818*7c478bd9Sstevel@tonic-gate 	kbtrans_key_t	key)
1819*7c478bd9Sstevel@tonic-gate {
1820*7c478bd9Sstevel@tonic-gate 	struct kbtrans_lower *lower = &upper->kbtrans_lower;
1821*7c478bd9Sstevel@tonic-gate 
1822*7c478bd9Sstevel@tonic-gate 	/*
1823*7c478bd9Sstevel@tonic-gate 	 * Function keys and keypad keys do not repeat when we are in
1824*7c478bd9Sstevel@tonic-gate 	 * EVENT mode.
1825*7c478bd9Sstevel@tonic-gate 	 */
1826*7c478bd9Sstevel@tonic-gate 	if (entrytype == FUNCKEYS || entrytype == PADKEYS) {
1827*7c478bd9Sstevel@tonic-gate 
1828*7c478bd9Sstevel@tonic-gate 		return;
1829*7c478bd9Sstevel@tonic-gate 	}
1830*7c478bd9Sstevel@tonic-gate 
1831*7c478bd9Sstevel@tonic-gate 	/*
1832*7c478bd9Sstevel@tonic-gate 	 * Cancel any currently repeating keys.  This will be a new
1833*7c478bd9Sstevel@tonic-gate 	 * key to repeat.
1834*7c478bd9Sstevel@tonic-gate 	 */
1835*7c478bd9Sstevel@tonic-gate 	kbtrans_cancelrpt(upper);
1836*7c478bd9Sstevel@tonic-gate 
1837*7c478bd9Sstevel@tonic-gate 	/*
1838*7c478bd9Sstevel@tonic-gate 	 * Set the value of the key to be repeated.
1839*7c478bd9Sstevel@tonic-gate 	 */
1840*7c478bd9Sstevel@tonic-gate 	lower->kbtrans_repeatkey = key;
1841*7c478bd9Sstevel@tonic-gate 
1842*7c478bd9Sstevel@tonic-gate 	/*
1843*7c478bd9Sstevel@tonic-gate 	 * Start the timeout for repeating this key.  kbtrans_rpt will
1844*7c478bd9Sstevel@tonic-gate 	 * be called to repeat the key.
1845*7c478bd9Sstevel@tonic-gate 	 */
1846*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_streams_rptid = qtimeout(upper->kbtrans_streams_readq,
1847*7c478bd9Sstevel@tonic-gate 		kbtrans_rpt, (caddr_t)upper, kbtrans_repeat_delay);
1848*7c478bd9Sstevel@tonic-gate }
1849*7c478bd9Sstevel@tonic-gate 
1850*7c478bd9Sstevel@tonic-gate /*
1851*7c478bd9Sstevel@tonic-gate  * Administer the key tables.
1852*7c478bd9Sstevel@tonic-gate  */
1853*7c478bd9Sstevel@tonic-gate 
1854*7c478bd9Sstevel@tonic-gate /*
1855*7c478bd9Sstevel@tonic-gate  * Old special codes.
1856*7c478bd9Sstevel@tonic-gate  */
1857*7c478bd9Sstevel@tonic-gate #define	OLD_SHIFTKEYS	0x80
1858*7c478bd9Sstevel@tonic-gate #define	OLD_BUCKYBITS	0x90
1859*7c478bd9Sstevel@tonic-gate #define	OLD_FUNNY	0xA0
1860*7c478bd9Sstevel@tonic-gate #define	OLD_FA_UMLAUT	0xA9
1861*7c478bd9Sstevel@tonic-gate #define	OLD_FA_CFLEX	0xAA
1862*7c478bd9Sstevel@tonic-gate #define	OLD_FA_TILDE	0xAB
1863*7c478bd9Sstevel@tonic-gate #define	OLD_FA_CEDILLA	0xAC
1864*7c478bd9Sstevel@tonic-gate #define	OLD_FA_ACUTE	0xAD
1865*7c478bd9Sstevel@tonic-gate #define	OLD_FA_GRAVE	0xAE
1866*7c478bd9Sstevel@tonic-gate #define	OLD_ISOCHAR	0xAF
1867*7c478bd9Sstevel@tonic-gate #define	OLD_STRING	0xB0
1868*7c478bd9Sstevel@tonic-gate #define	OLD_LEFTFUNC	0xC0
1869*7c478bd9Sstevel@tonic-gate #define	OLD_RIGHTFUNC	0xD0
1870*7c478bd9Sstevel@tonic-gate #define	OLD_TOPFUNC	0xE0
1871*7c478bd9Sstevel@tonic-gate #define	OLD_BOTTOMFUNC	0xF0
1872*7c478bd9Sstevel@tonic-gate 
1873*7c478bd9Sstevel@tonic-gate /*
1874*7c478bd9Sstevel@tonic-gate  * Map old special codes to new ones.
1875*7c478bd9Sstevel@tonic-gate  * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F.
1876*7c478bd9Sstevel@tonic-gate  */
1877*7c478bd9Sstevel@tonic-gate static ushort_t  special_old_to_new[] = {
1878*7c478bd9Sstevel@tonic-gate 	SHIFTKEYS,
1879*7c478bd9Sstevel@tonic-gate 	BUCKYBITS,
1880*7c478bd9Sstevel@tonic-gate 	FUNNY,
1881*7c478bd9Sstevel@tonic-gate 	STRING,
1882*7c478bd9Sstevel@tonic-gate 	LEFTFUNC,
1883*7c478bd9Sstevel@tonic-gate 	RIGHTFUNC,
1884*7c478bd9Sstevel@tonic-gate 	TOPFUNC,
1885*7c478bd9Sstevel@tonic-gate 	BOTTOMFUNC,
1886*7c478bd9Sstevel@tonic-gate };
1887*7c478bd9Sstevel@tonic-gate 
1888*7c478bd9Sstevel@tonic-gate 
1889*7c478bd9Sstevel@tonic-gate /*
1890*7c478bd9Sstevel@tonic-gate  * kbtrans_setkey:
1891*7c478bd9Sstevel@tonic-gate  *	 Set individual keystation translation from old-style entry.
1892*7c478bd9Sstevel@tonic-gate  */
1893*7c478bd9Sstevel@tonic-gate static int
1894*7c478bd9Sstevel@tonic-gate kbtrans_setkey(struct kbtrans_lower *lower, struct kiockey *key, cred_t *cr)
1895*7c478bd9Sstevel@tonic-gate {
1896*7c478bd9Sstevel@tonic-gate 	int	strtabindex, i;
1897*7c478bd9Sstevel@tonic-gate 	unsigned short	*ke;
1898*7c478bd9Sstevel@tonic-gate 	register int tablemask;
1899*7c478bd9Sstevel@tonic-gate 	register ushort_t entry;
1900*7c478bd9Sstevel@tonic-gate 	register struct keyboard *kp;
1901*7c478bd9Sstevel@tonic-gate 
1902*7c478bd9Sstevel@tonic-gate 	kp = lower->kbtrans_keyboard;
1903*7c478bd9Sstevel@tonic-gate 
1904*7c478bd9Sstevel@tonic-gate 	if (key->kio_station >= kp->k_keymap_size)
1905*7c478bd9Sstevel@tonic-gate 
1906*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
1907*7c478bd9Sstevel@tonic-gate 
1908*7c478bd9Sstevel@tonic-gate 	if (lower->kbtrans_keyboard == NULL)
1909*7c478bd9Sstevel@tonic-gate 
1910*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
1911*7c478bd9Sstevel@tonic-gate 
1912*7c478bd9Sstevel@tonic-gate 	tablemask = key->kio_tablemask;
1913*7c478bd9Sstevel@tonic-gate 
1914*7c478bd9Sstevel@tonic-gate 	switch (tablemask) {
1915*7c478bd9Sstevel@tonic-gate 	case KIOCABORT1:
1916*7c478bd9Sstevel@tonic-gate 	case KIOCABORT1A:
1917*7c478bd9Sstevel@tonic-gate 	case KIOCABORT2:
1918*7c478bd9Sstevel@tonic-gate 		i = secpolicy_console(cr);
1919*7c478bd9Sstevel@tonic-gate 		if (i != 0)
1920*7c478bd9Sstevel@tonic-gate 			return (i);
1921*7c478bd9Sstevel@tonic-gate 
1922*7c478bd9Sstevel@tonic-gate 		switch (tablemask) {
1923*7c478bd9Sstevel@tonic-gate 		case KIOCABORT1:
1924*7c478bd9Sstevel@tonic-gate 			kp->k_abort1 = key->kio_station;
1925*7c478bd9Sstevel@tonic-gate 			break;
1926*7c478bd9Sstevel@tonic-gate 		case KIOCABORT1A:
1927*7c478bd9Sstevel@tonic-gate 			kp->k_abort1a = key->kio_station;
1928*7c478bd9Sstevel@tonic-gate 			break;
1929*7c478bd9Sstevel@tonic-gate 		case KIOCABORT2:
1930*7c478bd9Sstevel@tonic-gate 			kp->k_abort2 = key->kio_station;
1931*7c478bd9Sstevel@tonic-gate 			break;
1932*7c478bd9Sstevel@tonic-gate 		}
1933*7c478bd9Sstevel@tonic-gate 		return (0);
1934*7c478bd9Sstevel@tonic-gate 	}
1935*7c478bd9Sstevel@tonic-gate 
1936*7c478bd9Sstevel@tonic-gate 	if (tablemask & ALTGRAPHMASK)
1937*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
1938*7c478bd9Sstevel@tonic-gate 
1939*7c478bd9Sstevel@tonic-gate 	ke = kbtrans_find_entry(lower, (uint_t)tablemask, key->kio_station);
1940*7c478bd9Sstevel@tonic-gate 	if (ke == NULL)
1941*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
1942*7c478bd9Sstevel@tonic-gate 
1943*7c478bd9Sstevel@tonic-gate 	if (key->kio_entry >= (uchar_t)OLD_STRING &&
1944*7c478bd9Sstevel@tonic-gate 	    key->kio_entry <= (uchar_t)(OLD_STRING + 15)) {
1945*7c478bd9Sstevel@tonic-gate 		strtabindex = key->kio_entry - OLD_STRING;
1946*7c478bd9Sstevel@tonic-gate 		bcopy(key->kio_string,
1947*7c478bd9Sstevel@tonic-gate 			lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN);
1948*7c478bd9Sstevel@tonic-gate 		lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
1949*7c478bd9Sstevel@tonic-gate 	}
1950*7c478bd9Sstevel@tonic-gate 
1951*7c478bd9Sstevel@tonic-gate 	entry = key->kio_entry;
1952*7c478bd9Sstevel@tonic-gate 
1953*7c478bd9Sstevel@tonic-gate 	/*
1954*7c478bd9Sstevel@tonic-gate 	 * There's nothing we need do with OLD_ISOCHAR.
1955*7c478bd9Sstevel@tonic-gate 	 */
1956*7c478bd9Sstevel@tonic-gate 	if (entry != OLD_ISOCHAR) {
1957*7c478bd9Sstevel@tonic-gate 		if (entry & 0x80) {
1958*7c478bd9Sstevel@tonic-gate 			if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE)
1959*7c478bd9Sstevel@tonic-gate 				entry = FA_CLASS + (entry & 0x0F) - 9;
1960*7c478bd9Sstevel@tonic-gate 			else
1961*7c478bd9Sstevel@tonic-gate 				entry =
1962*7c478bd9Sstevel@tonic-gate 				    special_old_to_new[entry >> 4 & 0x07]
1963*7c478bd9Sstevel@tonic-gate 				    + (entry & 0x0F);
1964*7c478bd9Sstevel@tonic-gate 		}
1965*7c478bd9Sstevel@tonic-gate 	}
1966*7c478bd9Sstevel@tonic-gate 
1967*7c478bd9Sstevel@tonic-gate 	*ke = entry;
1968*7c478bd9Sstevel@tonic-gate 
1969*7c478bd9Sstevel@tonic-gate 	return (0);
1970*7c478bd9Sstevel@tonic-gate }
1971*7c478bd9Sstevel@tonic-gate 
1972*7c478bd9Sstevel@tonic-gate 
1973*7c478bd9Sstevel@tonic-gate /*
1974*7c478bd9Sstevel@tonic-gate  * Map new special codes to old ones.
1975*7c478bd9Sstevel@tonic-gate  * Indexed by (new special code) >> 8; add (new special code) & 0xFF.
1976*7c478bd9Sstevel@tonic-gate  */
1977*7c478bd9Sstevel@tonic-gate static uchar_t   special_new_to_old[] = {
1978*7c478bd9Sstevel@tonic-gate 	0,			/* normal */
1979*7c478bd9Sstevel@tonic-gate 	OLD_SHIFTKEYS,		/* SHIFTKEYS */
1980*7c478bd9Sstevel@tonic-gate 	OLD_BUCKYBITS,		/* BUCKYBITS */
1981*7c478bd9Sstevel@tonic-gate 	OLD_FUNNY,		/* FUNNY */
1982*7c478bd9Sstevel@tonic-gate 	OLD_FA_UMLAUT,		/* FA_CLASS */
1983*7c478bd9Sstevel@tonic-gate 	OLD_STRING,		/* STRING */
1984*7c478bd9Sstevel@tonic-gate 	OLD_LEFTFUNC,		/* FUNCKEYS */
1985*7c478bd9Sstevel@tonic-gate };
1986*7c478bd9Sstevel@tonic-gate 
1987*7c478bd9Sstevel@tonic-gate 
1988*7c478bd9Sstevel@tonic-gate /*
1989*7c478bd9Sstevel@tonic-gate  * kbtrans_getkey:
1990*7c478bd9Sstevel@tonic-gate  *	Get individual keystation translation as old-style entry.
1991*7c478bd9Sstevel@tonic-gate  */
1992*7c478bd9Sstevel@tonic-gate static int
1993*7c478bd9Sstevel@tonic-gate kbtrans_getkey(struct kbtrans_lower *lower, struct kiockey *key)
1994*7c478bd9Sstevel@tonic-gate {
1995*7c478bd9Sstevel@tonic-gate 	int	strtabindex;
1996*7c478bd9Sstevel@tonic-gate 	unsigned short	*ke;
1997*7c478bd9Sstevel@tonic-gate 	register ushort_t entry;
1998*7c478bd9Sstevel@tonic-gate 	struct keyboard *kp;
1999*7c478bd9Sstevel@tonic-gate 
2000*7c478bd9Sstevel@tonic-gate 	kp = lower->kbtrans_keyboard;
2001*7c478bd9Sstevel@tonic-gate 
2002*7c478bd9Sstevel@tonic-gate 	if (key->kio_station >= kp->k_keymap_size)
2003*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2004*7c478bd9Sstevel@tonic-gate 
2005*7c478bd9Sstevel@tonic-gate 	if (lower->kbtrans_keyboard == NULL)
2006*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2007*7c478bd9Sstevel@tonic-gate 
2008*7c478bd9Sstevel@tonic-gate 	switch (key->kio_tablemask) {
2009*7c478bd9Sstevel@tonic-gate 	case KIOCABORT1:
2010*7c478bd9Sstevel@tonic-gate 		key->kio_station = kp->k_abort1;
2011*7c478bd9Sstevel@tonic-gate 		return (0);
2012*7c478bd9Sstevel@tonic-gate 	case KIOCABORT1A:
2013*7c478bd9Sstevel@tonic-gate 		key->kio_station = kp->k_abort1a;
2014*7c478bd9Sstevel@tonic-gate 		return (0);
2015*7c478bd9Sstevel@tonic-gate 	case KIOCABORT2:
2016*7c478bd9Sstevel@tonic-gate 		key->kio_station = kp->k_abort2;
2017*7c478bd9Sstevel@tonic-gate 		return (0);
2018*7c478bd9Sstevel@tonic-gate 	}
2019*7c478bd9Sstevel@tonic-gate 
2020*7c478bd9Sstevel@tonic-gate 	ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2021*7c478bd9Sstevel@tonic-gate 		key->kio_station);
2022*7c478bd9Sstevel@tonic-gate 	if (ke == NULL)
2023*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2024*7c478bd9Sstevel@tonic-gate 
2025*7c478bd9Sstevel@tonic-gate 	entry = *ke;
2026*7c478bd9Sstevel@tonic-gate 
2027*7c478bd9Sstevel@tonic-gate 	if (entry & 0xFF00)
2028*7c478bd9Sstevel@tonic-gate 		key->kio_entry =
2029*7c478bd9Sstevel@tonic-gate 		    special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8]
2030*7c478bd9Sstevel@tonic-gate 		    + (entry & 0x00FF);
2031*7c478bd9Sstevel@tonic-gate 	else {
2032*7c478bd9Sstevel@tonic-gate 		if (entry & 0x80)
2033*7c478bd9Sstevel@tonic-gate 			key->kio_entry = (ushort_t)OLD_ISOCHAR;	/* you lose */
2034*7c478bd9Sstevel@tonic-gate 		else
2035*7c478bd9Sstevel@tonic-gate 			key->kio_entry = (ushort_t)entry;
2036*7c478bd9Sstevel@tonic-gate 	}
2037*7c478bd9Sstevel@tonic-gate 
2038*7c478bd9Sstevel@tonic-gate 	if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) {
2039*7c478bd9Sstevel@tonic-gate 		strtabindex = entry - STRING;
2040*7c478bd9Sstevel@tonic-gate 		bcopy(lower->kbtrans_keystringtab[strtabindex],
2041*7c478bd9Sstevel@tonic-gate 			key->kio_string, KTAB_STRLEN);
2042*7c478bd9Sstevel@tonic-gate 	}
2043*7c478bd9Sstevel@tonic-gate 	return (0);
2044*7c478bd9Sstevel@tonic-gate }
2045*7c478bd9Sstevel@tonic-gate 
2046*7c478bd9Sstevel@tonic-gate 
2047*7c478bd9Sstevel@tonic-gate /*
2048*7c478bd9Sstevel@tonic-gate  * kbtrans_skey:
2049*7c478bd9Sstevel@tonic-gate  *	Set individual keystation translation from new-style entry.
2050*7c478bd9Sstevel@tonic-gate  */
2051*7c478bd9Sstevel@tonic-gate static int
2052*7c478bd9Sstevel@tonic-gate kbtrans_skey(struct kbtrans_lower *lower, struct kiockeymap *key, cred_t *cr)
2053*7c478bd9Sstevel@tonic-gate {
2054*7c478bd9Sstevel@tonic-gate 	int	strtabindex, i;
2055*7c478bd9Sstevel@tonic-gate 	unsigned short *ke;
2056*7c478bd9Sstevel@tonic-gate 	struct keyboard *kp;
2057*7c478bd9Sstevel@tonic-gate 
2058*7c478bd9Sstevel@tonic-gate 	kp = lower->kbtrans_keyboard;
2059*7c478bd9Sstevel@tonic-gate 
2060*7c478bd9Sstevel@tonic-gate 	if (key->kio_station >= kp->k_keymap_size) {
2061*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2062*7c478bd9Sstevel@tonic-gate 
2063*7c478bd9Sstevel@tonic-gate 	}
2064*7c478bd9Sstevel@tonic-gate 
2065*7c478bd9Sstevel@tonic-gate 	if (lower->kbtrans_keyboard == NULL) {
2066*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2067*7c478bd9Sstevel@tonic-gate 	}
2068*7c478bd9Sstevel@tonic-gate 
2069*7c478bd9Sstevel@tonic-gate 	switch (key->kio_tablemask) {
2070*7c478bd9Sstevel@tonic-gate 	case KIOCABORT1:
2071*7c478bd9Sstevel@tonic-gate 	case KIOCABORT1A:
2072*7c478bd9Sstevel@tonic-gate 	case KIOCABORT2:
2073*7c478bd9Sstevel@tonic-gate 		i = secpolicy_console(cr);
2074*7c478bd9Sstevel@tonic-gate 		if (i != 0)
2075*7c478bd9Sstevel@tonic-gate 			return (i);
2076*7c478bd9Sstevel@tonic-gate 		switch (key->kio_tablemask) {
2077*7c478bd9Sstevel@tonic-gate 		case KIOCABORT1:
2078*7c478bd9Sstevel@tonic-gate 			kp->k_abort1 = key->kio_station;
2079*7c478bd9Sstevel@tonic-gate 			break;
2080*7c478bd9Sstevel@tonic-gate 		case KIOCABORT1A:
2081*7c478bd9Sstevel@tonic-gate 			kp->k_abort1a = key->kio_station;
2082*7c478bd9Sstevel@tonic-gate 			break;
2083*7c478bd9Sstevel@tonic-gate 		case KIOCABORT2:
2084*7c478bd9Sstevel@tonic-gate 			kp->k_abort2 = key->kio_station;
2085*7c478bd9Sstevel@tonic-gate 			break;
2086*7c478bd9Sstevel@tonic-gate 		}
2087*7c478bd9Sstevel@tonic-gate 		return (0);
2088*7c478bd9Sstevel@tonic-gate 	}
2089*7c478bd9Sstevel@tonic-gate 
2090*7c478bd9Sstevel@tonic-gate 	ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2091*7c478bd9Sstevel@tonic-gate 		key->kio_station);
2092*7c478bd9Sstevel@tonic-gate 	if (ke == NULL)
2093*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2094*7c478bd9Sstevel@tonic-gate 
2095*7c478bd9Sstevel@tonic-gate 	if (key->kio_entry >= STRING &&
2096*7c478bd9Sstevel@tonic-gate 	    key->kio_entry <= (ushort_t)(STRING + 15)) {
2097*7c478bd9Sstevel@tonic-gate 		strtabindex = key->kio_entry-STRING;
2098*7c478bd9Sstevel@tonic-gate 		bcopy(key->kio_string,
2099*7c478bd9Sstevel@tonic-gate 			lower->kbtrans_keystringtab[strtabindex], KTAB_STRLEN);
2100*7c478bd9Sstevel@tonic-gate 		lower->kbtrans_keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
2101*7c478bd9Sstevel@tonic-gate 	}
2102*7c478bd9Sstevel@tonic-gate 
2103*7c478bd9Sstevel@tonic-gate 	*ke = key->kio_entry;
2104*7c478bd9Sstevel@tonic-gate 
2105*7c478bd9Sstevel@tonic-gate 	return (0);
2106*7c478bd9Sstevel@tonic-gate }
2107*7c478bd9Sstevel@tonic-gate 
2108*7c478bd9Sstevel@tonic-gate 
2109*7c478bd9Sstevel@tonic-gate /*
2110*7c478bd9Sstevel@tonic-gate  * kbtrans_gkey:
2111*7c478bd9Sstevel@tonic-gate  *	Get individual keystation translation as new-style entry.
2112*7c478bd9Sstevel@tonic-gate  */
2113*7c478bd9Sstevel@tonic-gate static int
2114*7c478bd9Sstevel@tonic-gate kbtrans_gkey(struct kbtrans_lower *lower, struct	kiockeymap *key)
2115*7c478bd9Sstevel@tonic-gate {
2116*7c478bd9Sstevel@tonic-gate 	int	strtabindex;
2117*7c478bd9Sstevel@tonic-gate 	unsigned short *ke;
2118*7c478bd9Sstevel@tonic-gate 	struct keyboard *kp;
2119*7c478bd9Sstevel@tonic-gate 
2120*7c478bd9Sstevel@tonic-gate 	kp = lower->kbtrans_keyboard;
2121*7c478bd9Sstevel@tonic-gate 
2122*7c478bd9Sstevel@tonic-gate 	if (key->kio_station >= kp->k_keymap_size)
2123*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2124*7c478bd9Sstevel@tonic-gate 
2125*7c478bd9Sstevel@tonic-gate 	if (lower->kbtrans_keyboard == NULL)
2126*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2127*7c478bd9Sstevel@tonic-gate 
2128*7c478bd9Sstevel@tonic-gate 	switch (key->kio_tablemask) {
2129*7c478bd9Sstevel@tonic-gate 	case KIOCABORT1:
2130*7c478bd9Sstevel@tonic-gate 		key->kio_station = kp->k_abort1;
2131*7c478bd9Sstevel@tonic-gate 		return (0);
2132*7c478bd9Sstevel@tonic-gate 	case KIOCABORT1A:
2133*7c478bd9Sstevel@tonic-gate 		key->kio_station = kp->k_abort1a;
2134*7c478bd9Sstevel@tonic-gate 		return (0);
2135*7c478bd9Sstevel@tonic-gate 	case KIOCABORT2:
2136*7c478bd9Sstevel@tonic-gate 		key->kio_station = kp->k_abort2;
2137*7c478bd9Sstevel@tonic-gate 		return (0);
2138*7c478bd9Sstevel@tonic-gate 	}
2139*7c478bd9Sstevel@tonic-gate 
2140*7c478bd9Sstevel@tonic-gate 	ke = kbtrans_find_entry(lower, (uint_t)key->kio_tablemask,
2141*7c478bd9Sstevel@tonic-gate 		key->kio_station);
2142*7c478bd9Sstevel@tonic-gate 	if (ke == NULL)
2143*7c478bd9Sstevel@tonic-gate 		return (EINVAL);
2144*7c478bd9Sstevel@tonic-gate 
2145*7c478bd9Sstevel@tonic-gate 	key->kio_entry = *ke;
2146*7c478bd9Sstevel@tonic-gate 
2147*7c478bd9Sstevel@tonic-gate 	if (key->kio_entry >= STRING &&
2148*7c478bd9Sstevel@tonic-gate 	    key->kio_entry <= (ushort_t)(STRING + 15)) {
2149*7c478bd9Sstevel@tonic-gate 		strtabindex = key->kio_entry-STRING;
2150*7c478bd9Sstevel@tonic-gate 		bcopy(lower->kbtrans_keystringtab[strtabindex],
2151*7c478bd9Sstevel@tonic-gate 			key->kio_string, KTAB_STRLEN);
2152*7c478bd9Sstevel@tonic-gate 	}
2153*7c478bd9Sstevel@tonic-gate 	return (0);
2154*7c478bd9Sstevel@tonic-gate }
2155