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