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