xref: /titanic_50/usr/src/uts/common/io/kbd.c (revision c35aa225b9ae500f1d14f0d39a94f1eb6cda333d)
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  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 						/* SunOS-4.0 1.60	*/
28 /*	From:	SunOS4.0	sundev/kbd.c	*/
29 
30 /*
31  * Keyboard input streams module - handles conversion of up/down codes to
32  * ASCII or event format.
33  */
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/sysmacros.h>
37 #include <sys/signal.h>
38 #include <sys/termios.h>
39 #include <sys/termio.h>
40 #include <sys/stream.h>
41 #include <sys/stropts.h>
42 #include <sys/strsun.h>
43 #include <sys/kmem.h>
44 #include <sys/file.h>
45 #include <sys/uio.h>
46 #include <sys/errno.h>
47 #include <sys/time.h>
48 #include <sys/consdev.h>
49 #include <sys/kbd.h>
50 #include <sys/kbio.h>
51 #include <sys/kbdreg.h>
52 #include <sys/vuid_event.h>
53 #include <sys/debug.h>
54 #include <sys/ddi.h>
55 #include <sys/sunddi.h>
56 #include <sys/policy.h>
57 
58 #include <sys/modctl.h>
59 #include <sys/beep.h>
60 #include <sys/int_limits.h>
61 
62 static struct streamtab kbd_info;
63 
64 static struct fmodsw fsw = {
65 	"kb",
66 	&kbd_info,
67 	D_MP | D_MTPERMOD
68 };
69 
70 /*
71  * Module linkage information for the kernel.
72  */
73 
74 static struct modlstrmod modlstrmod = {
75 	&mod_strmodops, "streams module for keyboard", &fsw
76 };
77 
78 static struct modlinkage modlinkage = {
79 	MODREV_1, (void *)&modlstrmod, NULL
80 };
81 
82 int
_init(void)83 _init(void)
84 {
85 	return (mod_install(&modlinkage));
86 }
87 
88 int
_fini(void)89 _fini(void)
90 {
91 	return (mod_remove(&modlinkage));
92 }
93 
94 int
_info(struct modinfo * modinfop)95 _info(struct modinfo *modinfop)
96 {
97 	return (mod_info(&modlinkage, modinfop));
98 }
99 
100 /*
101  * For now these are shared.
102  * These data structures are static (defined in keytables.c) thus
103  * there is no need to perform any locking.
104  */
105 extern struct keyboards	keytables[];
106 extern char keystringtab[16][KTAB_STRLEN];
107 extern struct compose_sequence_t kb_compose_table[];
108 extern signed char kb_compose_map[];
109 extern struct fltaccent_sequence_t kb_fltaccent_table[];
110 extern uchar_t kb_numlock_table[];
111 
112 /*
113  * This value corresponds approximately to max 10 fingers
114  */
115 static int	kbd_downs_size = 15;
116 
117 typedef	struct	key_event {
118 	uchar_t	key_station;	/* Physical key station associated with event */
119 	Firm_event event;	/* Event that sent out on down */
120 } Key_event;
121 struct	kbddata {
122 	queue_t	*kbdd_readq;
123 	queue_t *kbdd_writeq;
124 	mblk_t	*kbdd_iocpending;	/* "ioctl" awaiting buffer */
125 	mblk_t	*kbdd_replypending;	/* "ioctl" reply awaiting result */
126 	int	kbdd_flags;		/* random flags */
127 	bufcall_id_t kbdd_bufcallid;	/* bufcall id */
128 	timeout_id_t kbdd_rptid;	/* timeout id for kbdrpt() */
129 	timeout_id_t kbdd_layoutid;	/* timeout id for kbdlayout() */
130 	int	kbdd_iocid;		/* ID of "ioctl" being waited for */
131 	int	kbdd_iocerror;		/* error return from "ioctl" */
132 	struct	keyboardstate kbdd_state;
133 					/*
134 					 * State of keyboard & keyboard
135 					 * specific settings, e.g., tables
136 					 */
137 	int	kbdd_translate;		/* Translate keycodes? */
138 	int	kbdd_translatable;	/* Keyboard is translatable? */
139 	int	kbdd_compat;		/* Generating pre-4.1 events? */
140 	short	kbdd_ascii_addr;	/* Vuid_id_addr for ascii events */
141 	short	kbdd_top_addr;		/* Vuid_id_addr for top events */
142 	short	kbdd_vkey_addr;		/* Vuid_id_addr for vkey events */
143 	struct	key_event *kbdd_downs;
144 					/*
145 					 * Table of key stations currently down
146 					 * that have firm events that need
147 					 * to be matched with up transitions
148 					 * when kbdd_translate is TR_*EVENT
149 					 */
150 	int	kbdd_downs_entries; /* # of possible entries in kbdd_downs */
151 	uint_t	kbdd_downs_bytes; /* # of bytes allocated for kbdd_downs */
152 	ushort_t compose_key;		/* first compose key */
153 	ushort_t fltaccent_entry;	/* floating accent keymap entry */
154 	char	led_state;		/* current state of LEDs */
155 	unsigned char shiftkey;		/* used for the new abort keys */
156 };
157 
158 #define	KBD_OPEN	0x00000001 /* keyboard is open for business */
159 #define	KBD_IOCWAIT	0x00000002 /* "open" waiting for "ioctl" to finish */
160 
161 #define	NO_HARD_RESET	0		/* don't do hard reset */
162 #define	HARD_RESET	1		/* do hard reset */
163 
164 
165 /*
166  * Constants setup during the first open of a kbd (so that they can be patched
167  * for debugging purposes).
168  */
169 static int kbd_repeatrate;
170 static int kbd_repeatdelay;
171 
172 static int kbd_overflow_cnt;	/* Number of times kbd overflowed input q */
173 static int kbd_overflow_msg = 1; /* Whether to print message on q overflow */
174 
175 #ifdef	KBD_DEBUG
176 int	kbd_debug = 0;
177 int	kbd_ra_debug = 0;
178 int	kbd_raw_debug = 0;
179 int	kbd_rpt_debug = 0;
180 int	kbd_input_debug = 0;
181 #endif	/* KBD_DEBUG */
182 
183 static int	kbdopen(queue_t *, dev_t *, int, int, cred_t *);
184 static int	kbdclose(queue_t *, int, cred_t *);
185 static void	kbdwput(queue_t *, mblk_t *);
186 static void	kbdrput(queue_t *, mblk_t *);
187 
188 static struct module_info kbdmiinfo = {
189 	0,
190 	"kb",
191 	0,
192 	INFPSZ,
193 	2048,
194 	128
195 };
196 
197 static struct qinit kbdrinit = {
198 	(int (*)())kbdrput,
199 	(int (*)())NULL,
200 	kbdopen,
201 	kbdclose,
202 	(int (*)())NULL,
203 	&kbdmiinfo
204 };
205 
206 static struct module_info kbdmoinfo = {
207 	0,
208 	"kb",
209 	0,
210 	INFPSZ,
211 	2048,
212 	128
213 };
214 
215 static struct qinit kbdwinit = {
216 	(int (*)())kbdwput,
217 	(int (*)())NULL,
218 	kbdopen,
219 	kbdclose,
220 	(int (*)())NULL,
221 	&kbdmoinfo
222 };
223 
224 static struct streamtab kbd_info = {
225 	&kbdrinit,
226 	&kbdwinit,
227 	NULL,
228 	NULL,
229 };
230 
231 static void	kbdreioctl(void *);
232 static void	kbdioctl(queue_t *, mblk_t *);
233 static void	kbdflush(struct kbddata *);
234 static void	kbduse(struct kbddata *, unsigned);
235 static void	kbdsetled(struct kbddata *);
236 static void	kbd_beep_off(void *arg);
237 static void	kbd_beep_on(void *arg);
238 static void	kbdcmd(queue_t *, char);
239 static void	kbdreset(struct kbddata *, uint_t);
240 static int	kbdsetkey(struct kbddata *, struct kiockey *,  cred_t *);
241 static int	kbdgetkey(struct kbddata *, struct kiockey *);
242 static int	kbdskey(struct kbddata *, struct kiockeymap *,  cred_t *);
243 static int	kbdgkey(struct kbddata *, struct kiockeymap *);
244 static void	kbdlayouttimeout(void *);
245 static void	kbdinput(struct kbddata *, unsigned);
246 static void	kbdid(struct kbddata *, int);
247 static struct	keymap *settable(struct kbddata *, uint_t);
248 static void	kbdrpt(void *);
249 static void	kbdcancelrpt(struct kbddata *);
250 static void	kbdtranslate(struct kbddata *, unsigned, queue_t *);
251 static int	kbd_do_compose(ushort_t, ushort_t, ushort_t *);
252 static void	kbd_send_esc_event(char, struct kbddata *);
253 char		*strsetwithdecimal(char *, uint_t, uint_t);
254 static void	kbdkeypressed(struct kbddata *, uchar_t, Firm_event *,
255 								ushort_t);
256 static void	kbdqueuepress(struct kbddata *, uchar_t, Firm_event *);
257 static void	kbdkeyreleased(struct kbddata *, uchar_t);
258 static void	kbdreleaseall(struct kbddata *);
259 static void	kbdputcode(uint_t, queue_t *);
260 static void	kbdputbuf(char *, queue_t *);
261 static void	kbdqueueevent(struct kbddata *, Firm_event *);
262 
263 /*
264  * Dummy qbufcall callback routine used by open and close.
265  * The framework will wake up qwait_sig when we return from
266  * this routine (as part of leaving the perimeters.)
267  * (The framework enters the perimeters before calling the qbufcall() callback
268  * and leaves the perimeters after the callback routine has executed. The
269  * framework performs an implicit wakeup of any thread in qwait/qwait_sig
270  * when it leaves the perimeter. See qwait(9E).)
271  */
272 /* ARGSUSED */
dummy_callback(void * arg)273 static void dummy_callback(void *arg)
274 {}
275 
276 
277 /*
278  * Open a keyboard.
279  * Ttyopen sets line characteristics
280  */
281 /* ARGSUSED */
282 static int
kbdopen(queue_t * q,dev_t * devp,int oflag,int sflag,cred_t * crp)283 kbdopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
284 {
285 	register int  error;
286 	register struct	kbddata *kbdd;
287 	mblk_t *mp;
288 	mblk_t *datap;
289 	register struct iocblk *iocb;
290 	register struct termios *cb;
291 
292 	/* Set these up only once so that they could be changed from adb */
293 	if (!kbd_repeatrate) {
294 		kbd_repeatrate = (hz+29)/30;
295 		kbd_repeatdelay = hz/2;
296 	}
297 
298 	if (q->q_ptr != NULL)
299 		return (0);		/* already attached */
300 
301 	/*
302 	 * Only allow open requests to succeed for privileged users.  This
303 	 * necessary to prevent users from pushing the "kb" module again
304 	 * on the stream associated with /dev/kbd.
305 	 */
306 	if (secpolicy_console(crp) != 0) {
307 		return (EPERM);
308 	}
309 
310 
311 	switch (sflag) {
312 
313 	case MODOPEN:
314 		break;
315 
316 	case CLONEOPEN:
317 		return (EINVAL);	/* No Bozos! */
318 	}
319 
320 	/* allocate keyboard */
321 
322 	kbdd = kmem_zalloc(sizeof (struct kbddata), KM_SLEEP);
323 
324 
325 	/*
326 	 * Set up queue pointers, so that the "put" procedure will accept
327 	 * the reply to the "ioctl" message we send down.
328 	 */
329 	q->q_ptr = kbdd;
330 	WR(q)->q_ptr = kbdd;
331 
332 	qprocson(q);
333 
334 	/*
335 	 * Setup tty modes.
336 	 */
337 	while ((mp = mkiocb(TCSETSF)) == NULL) {
338 		timeout_id_t id = qbufcall(q, sizeof (struct iocblk), BPRI_HI,
339 		    dummy_callback, NULL);
340 		if (!qwait_sig(q)) {
341 			qunbufcall(q, id);
342 			kmem_free(kbdd, sizeof (struct kbddata));
343 			qprocsoff(q);
344 
345 			return (EINTR);
346 		}
347 	}
348 	while ((datap = allocb(sizeof (struct termios), BPRI_HI)) ==
349 	    NULL) {
350 		timeout_id_t id = qbufcall(q, sizeof (struct termios), BPRI_HI,
351 		    dummy_callback, NULL);
352 		if (!qwait_sig(q)) {
353 			qunbufcall(q, id);
354 			freemsg(mp);
355 			kmem_free(kbdd, sizeof (struct kbddata));
356 			qprocsoff(q);
357 
358 			return (EINTR);
359 		}
360 	}
361 
362 	iocb		= (struct iocblk *)mp->b_rptr;
363 	iocb->ioc_count	= sizeof (struct termios);
364 
365 	cb = (struct termios *)datap->b_rptr;
366 	cb->c_iflag = 0;
367 	cb->c_oflag = 0;
368 	cb->c_cflag = CREAD|CS8|B1200;
369 	cb->c_lflag = 0;
370 	bzero(cb->c_cc, NCCS);
371 	datap->b_wptr += sizeof (struct termios);
372 	mp->b_cont = datap;
373 	kbdd->kbdd_flags |= KBD_IOCWAIT;	/* indicate that we're */
374 	kbdd->kbdd_iocid = iocb->ioc_id;	/* waiting for this response */
375 	putnext(WR(q), mp);
376 
377 	/*
378 	 * Now wait for it.  Let our read queue put routine wake us up
379 	 * when it arrives.
380 	 */
381 	while (kbdd->kbdd_flags & KBD_IOCWAIT) {
382 		if (!qwait_sig(q)) {
383 			error = EINTR;
384 			goto error;
385 		}
386 	}
387 	if ((error = kbdd->kbdd_iocerror) != 0)
388 		goto error;
389 
390 	/*
391 	 * Set up private data.
392 	 */
393 	kbdd->kbdd_readq = q;
394 	kbdd->kbdd_writeq = WR(q);
395 	kbdd->kbdd_iocpending = NULL;
396 	kbdd->kbdd_translatable = TR_CAN;
397 	kbdd->kbdd_translate = TR_ASCII;
398 	kbdd->kbdd_compat = 1;
399 	kbdd->kbdd_ascii_addr = ASCII_FIRST;
400 	kbdd->kbdd_top_addr = TOP_FIRST;
401 	kbdd->kbdd_vkey_addr = VKEY_FIRST;
402 	/* Allocate dynamic memory for downs table */
403 	kbdd->kbdd_downs_entries = kbd_downs_size;
404 	kbdd->kbdd_downs_bytes = kbd_downs_size * sizeof (Key_event);
405 	kbdd->kbdd_downs = kmem_alloc(kbdd->kbdd_downs_bytes, KM_SLEEP);
406 	kbdd->kbdd_flags = KBD_OPEN;
407 	kbdd->led_state = 0;
408 
409 	/*
410 	 * Reset kbd.
411 	 */
412 	kbdreset(kbdd, HARD_RESET);
413 
414 	(void) beep_init((void *)WR(q), kbd_beep_on, kbd_beep_off, NULL);
415 
416 	return (0);
417 
418 error:
419 	qprocsoff(q);
420 	kmem_free(kbdd, sizeof (struct kbddata));
421 	return (error);
422 }
423 
424 /*
425  * Close a keyboard.
426  */
427 /* ARGSUSED1 */
428 static int
kbdclose(register queue_t * q,int flag,cred_t * crp)429 kbdclose(register queue_t *q, int flag, cred_t *crp)
430 {
431 	register struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
432 	register mblk_t *mp;
433 
434 	qprocsoff(q);
435 	(void) beep_fini();
436 	/*
437 	 * Since we're about to destroy our private data, turn off
438 	 * our open flag first, so we don't accept any more input
439 	 * and try to use that data.
440 	 */
441 	kbdd->kbdd_flags = 0;
442 
443 	if ((mp = kbdd->kbdd_replypending) != NULL) {
444 		/*
445 		 * There was a KIOCLAYOUT pending; presumably, it timed out.
446 		 * Throw the reply away.
447 		 */
448 		kbdd->kbdd_replypending = NULL;
449 		freemsg(mp);
450 	}
451 
452 	/* clear all timeouts */
453 	if (kbdd->kbdd_bufcallid)
454 		qunbufcall(q, kbdd->kbdd_bufcallid);
455 	if (kbdd->kbdd_rptid)
456 		(void) quntimeout(q, kbdd->kbdd_rptid);
457 	if (kbdd->kbdd_layoutid)
458 		(void) quntimeout(q, kbdd->kbdd_layoutid);
459 	kmem_free(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes);
460 	kmem_free(kbdd, sizeof (struct kbddata));
461 	return (0);
462 }
463 
464 /*
465  * Line discipline output queue put procedure: handles M_IOCTL
466  * messages.
467  */
468 static void
kbdwput(register queue_t * q,register mblk_t * mp)469 kbdwput(register queue_t *q, register mblk_t *mp)
470 {
471 	/*
472 	 * Process M_FLUSH, and some M_IOCTL, messages here; pass
473 	 * everything else down.
474 	 */
475 	switch (mp->b_datap->db_type) {
476 
477 	case M_FLUSH:
478 		if (*mp->b_rptr & FLUSHW)
479 			flushq(q, FLUSHDATA);
480 		if (*mp->b_rptr & FLUSHR)
481 			flushq(RD(q), FLUSHDATA);
482 
483 	default:
484 		putnext(q, mp);	/* pass it down the line */
485 		break;
486 
487 	case M_IOCTL:
488 		kbdioctl(q, mp);
489 		break;
490 	}
491 }
492 
493 
494 static void
kbdreioctl(void * kbdd_addr)495 kbdreioctl(void *kbdd_addr)
496 {
497 	struct kbddata *kbdd = kbdd_addr;
498 	queue_t *q;
499 	mblk_t *mp;
500 
501 	kbdd->kbdd_bufcallid = 0;
502 	q = kbdd->kbdd_writeq;
503 	if ((mp = kbdd->kbdd_iocpending) != NULL) {
504 		kbdd->kbdd_iocpending = NULL;	/* not pending any more */
505 		kbdioctl(q, mp);
506 	}
507 }
508 
509 static void
kbdioctl(register queue_t * q,register mblk_t * mp)510 kbdioctl(register queue_t *q, register mblk_t *mp)
511 {
512 	register struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
513 	register struct iocblk *iocp;
514 	register short	new_translate;
515 	register Vuid_addr_probe *addr_probe;
516 	register short	*addr_ptr;
517 	mblk_t *datap;
518 	size_t	ioctlrespsize;
519 	int	err = 0;
520 	int	tmp;
521 	int	cycles;
522 	int	frequency;
523 	int	msecs;
524 
525 	iocp = (struct iocblk *)mp->b_rptr;
526 
527 	switch (iocp->ioc_cmd) {
528 
529 	case VUIDSFORMAT:
530 		err = miocpullup(mp, sizeof (int));
531 		if (err != 0)
532 			break;
533 
534 		new_translate = (*(int *)mp->b_cont->b_rptr == VUID_NATIVE) ?
535 		    TR_ASCII : TR_EVENT;
536 		if (new_translate == kbdd->kbdd_translate)
537 			break;
538 		kbdd->kbdd_translate = new_translate;
539 		goto output_format_change;
540 
541 	case KIOCTRANS:
542 		err = miocpullup(mp, sizeof (int));
543 		if (err != 0)
544 			break;
545 
546 		new_translate = *(int *)mp->b_cont->b_rptr;
547 		if (new_translate == kbdd->kbdd_translate)
548 			break;
549 		kbdd->kbdd_translate = new_translate;
550 		goto output_format_change;
551 
552 	case KIOCCMD:
553 		err = miocpullup(mp, sizeof (int));
554 		if (err != 0)
555 			break;
556 
557 		tmp = (char)(*(int *)mp->b_cont->b_rptr);
558 		if (tmp == KBD_CMD_BELL)
559 			(void) beeper_on(BEEP_TYPE4);
560 		else if (tmp == KBD_CMD_NOBELL)
561 			(void) beeper_off();
562 		else
563 			kbdcmd(q, tmp);
564 		break;
565 
566 	case KIOCMKTONE:
567 		if (iocp->ioc_count != TRANSPARENT) {
568 			/*
569 			 * We don't support non-transparent ioctls,
570 			 * i.e. I_STR ioctls
571 			 */
572 			err = EINVAL;
573 			break;
574 		}
575 		tmp = (int)(*(intptr_t *)mp->b_cont->b_rptr);
576 		cycles = tmp & 0xffff;
577 		msecs = (tmp >> 16) & 0xffff;
578 
579 		if (cycles == 0)
580 			frequency = UINT16_MAX;
581 		else if (cycles == UINT16_MAX)
582 			frequency = 0;
583 		else {
584 			frequency = (PIT_HZ + cycles / 2) / cycles;
585 			if (frequency > UINT16_MAX)
586 				frequency = UINT16_MAX;
587 		}
588 
589 		err = beep_mktone(frequency, msecs);
590 		break;
591 
592 	case KIOCSLED:
593 		err = miocpullup(mp, sizeof (uchar_t));
594 		if (err != 0)
595 			break;
596 
597 		kbdd->led_state = *(uchar_t *)mp->b_cont->b_rptr;
598 		kbdsetled(kbdd);
599 		break;
600 
601 	case KIOCGLED:
602 		if ((datap = allocb(sizeof (uchar_t), BPRI_HI)) == NULL) {
603 			ioctlrespsize = sizeof (int);
604 			goto allocfailure;
605 		}
606 		*(uchar_t *)datap->b_wptr = kbdd->led_state;
607 		datap->b_wptr += sizeof (uchar_t);
608 		if (mp->b_cont)  /* free msg to prevent memory leak */
609 			freemsg(mp->b_cont);
610 		mp->b_cont = datap;
611 		iocp->ioc_count = sizeof (uchar_t);
612 		break;
613 
614 	case VUIDGFORMAT:
615 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
616 			ioctlrespsize = sizeof (int);
617 			goto allocfailure;
618 		}
619 		*(int *)datap->b_wptr =
620 		    (kbdd->kbdd_translate == TR_EVENT ||
621 		    kbdd->kbdd_translate == TR_UNTRANS_EVENT) ?
622 		    VUID_FIRM_EVENT: VUID_NATIVE;
623 		datap->b_wptr += sizeof (int);
624 		if (mp->b_cont)  /* free msg to prevent memory leak */
625 			freemsg(mp->b_cont);
626 		mp->b_cont = datap;
627 		iocp->ioc_count = sizeof (int);
628 		break;
629 
630 	case KIOCGTRANS:
631 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
632 			ioctlrespsize = sizeof (int);
633 			goto allocfailure;
634 		}
635 		*(int *)datap->b_wptr = kbdd->kbdd_translate;
636 		datap->b_wptr += sizeof (int);
637 		if (mp->b_cont)  /* free msg to prevent memory leak */
638 			freemsg(mp->b_cont);
639 		mp->b_cont = datap;
640 		iocp->ioc_count = sizeof (int);
641 		break;
642 
643 	case VUIDSADDR:
644 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
645 		if (err != 0)
646 			break;
647 
648 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
649 		switch (addr_probe->base) {
650 
651 		case ASCII_FIRST:
652 			addr_ptr = &kbdd->kbdd_ascii_addr;
653 			break;
654 
655 		case TOP_FIRST:
656 			addr_ptr = &kbdd->kbdd_top_addr;
657 			break;
658 
659 		case VKEY_FIRST:
660 			addr_ptr = &kbdd->kbdd_vkey_addr;
661 			break;
662 
663 		default:
664 			err = ENODEV;
665 		}
666 		if ((err == 0) && (*addr_ptr != addr_probe->data.next)) {
667 			*addr_ptr = addr_probe->data.next;
668 			goto output_format_change;
669 		}
670 		break;
671 
672 	case VUIDGADDR:
673 		err = miocpullup(mp, sizeof (Vuid_addr_probe));
674 		if (err != 0)
675 			break;
676 
677 		addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
678 		switch (addr_probe->base) {
679 
680 		case ASCII_FIRST:
681 			addr_probe->data.current = kbdd->kbdd_ascii_addr;
682 			break;
683 
684 		case TOP_FIRST:
685 			addr_probe->data.current = kbdd->kbdd_top_addr;
686 			break;
687 
688 		case VKEY_FIRST:
689 			addr_probe->data.current = kbdd->kbdd_vkey_addr;
690 			break;
691 
692 		default:
693 			err = ENODEV;
694 		}
695 		break;
696 
697 	case KIOCTRANSABLE:
698 		err = miocpullup(mp, sizeof (int));
699 		if (err != 0)
700 			break;
701 
702 		if (kbdd->kbdd_translatable != *(int *)mp->b_cont->b_rptr) {
703 			kbdd->kbdd_translatable = *(int *)mp->b_cont->b_rptr;
704 			kbdreset(kbdd, HARD_RESET);
705 			goto output_format_change;
706 		}
707 		break;
708 
709 	case KIOCGTRANSABLE:
710 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
711 			ioctlrespsize = sizeof (int);
712 			goto allocfailure;
713 		}
714 		*(int *)datap->b_wptr = kbdd->kbdd_translatable;
715 		datap->b_wptr += sizeof (int);
716 		if (mp->b_cont)  /* free msg to prevent memory leak */
717 			freemsg(mp->b_cont);
718 		mp->b_cont = datap;
719 		iocp->ioc_count = sizeof (int);
720 		break;
721 
722 	case KIOCSCOMPAT:
723 		err = miocpullup(mp, sizeof (int));
724 		if (err != 0)
725 			break;
726 
727 		kbdd->kbdd_compat = *(int *)mp->b_cont->b_rptr;
728 		break;
729 
730 	case KIOCGCOMPAT:
731 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
732 			ioctlrespsize = sizeof (int);
733 			goto allocfailure;
734 		}
735 		*(int *)datap->b_wptr = kbdd->kbdd_compat;
736 		datap->b_wptr += sizeof (int);
737 		if (mp->b_cont)  /* free msg to prevent memory leak */
738 			freemsg(mp->b_cont);
739 		mp->b_cont = datap;
740 		iocp->ioc_count = sizeof (int);
741 		break;
742 
743 	case KIOCSETKEY:
744 		err = miocpullup(mp, sizeof (struct kiockey));
745 		if (err != 0)
746 			break;
747 
748 		err = kbdsetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr,
749 		    iocp->ioc_cr);
750 		/*
751 		 * Since this only affects any subsequent key presses,
752 		 * don't goto output_format_change.  One might want to
753 		 * toggle the keytable entries dynamically.
754 		 */
755 		break;
756 
757 	case KIOCGETKEY:
758 		err = miocpullup(mp, sizeof (struct kiockey));
759 		if (err != 0)
760 			break;
761 
762 		err = kbdgetkey(kbdd, (struct kiockey *)mp->b_cont->b_rptr);
763 		break;
764 
765 	case KIOCSKEY:
766 		err = miocpullup(mp, sizeof (struct kiockeymap));
767 		if (err != 0)
768 			break;
769 
770 		err = kbdskey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr,
771 		    iocp->ioc_cr);
772 		/*
773 		 * Since this only affects any subsequent key presses,
774 		 * don't goto output_format_change.  One might want to
775 		 * toggle the keytable entries dynamically.
776 		 */
777 		break;
778 
779 	case KIOCGKEY:
780 		err = miocpullup(mp, sizeof (struct kiockeymap));
781 		if (err != 0)
782 			break;
783 
784 		err = kbdgkey(kbdd, (struct kiockeymap *)mp->b_cont->b_rptr);
785 		break;
786 
787 	case KIOCSDIRECT:
788 		goto output_format_change;
789 
790 	case KIOCGDIRECT:
791 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
792 			ioctlrespsize = sizeof (int);
793 			goto allocfailure;
794 		}
795 		*(int *)datap->b_wptr = 1;	/* always direct */
796 		datap->b_wptr += sizeof (int);
797 		if (mp->b_cont) /* free msg to prevent memory leak */
798 			freemsg(mp->b_cont);
799 		mp->b_cont = datap;
800 		iocp->ioc_count = sizeof (int);
801 		break;
802 
803 	case KIOCTYPE:
804 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
805 			ioctlrespsize = sizeof (int);
806 			goto allocfailure;
807 		}
808 		*(int *)datap->b_wptr = kbdd->kbdd_state.k_id;
809 		datap->b_wptr += sizeof (int);
810 		if (mp->b_cont) /* free msg to prevent memory leak */
811 			freemsg(mp->b_cont);
812 		mp->b_cont = datap;
813 		iocp->ioc_count = sizeof (int);
814 		break;
815 
816 	case KIOCLAYOUT:
817 		if ((datap = kbdd->kbdd_replypending) != NULL) {
818 			/*
819 			 * There was an earlier KIOCLAYOUT pending; presumably,
820 			 * it timed out.  Throw the reply away.
821 			 */
822 			kbdd->kbdd_replypending = NULL;
823 			freemsg(datap);
824 		}
825 
826 		if (kbdd->kbdd_state.k_id == KB_SUN4 ||
827 		    kbdd->kbdd_state.k_id == KB_PC) {
828 			if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
829 				ioctlrespsize = sizeof (int);
830 				goto allocfailure;
831 			}
832 			iocp->ioc_rval = 0;
833 			iocp->ioc_error = 0;	/* brain rot */
834 			iocp->ioc_count = sizeof (int);
835 			if (mp->b_cont)   /* free msg to prevent memory leak */
836 				freemsg(mp->b_cont);
837 			mp->b_cont = datap;
838 			mp->b_datap->db_type = M_IOCACK;
839 			kbdd->kbdd_replypending = mp;
840 			kbdcmd(q, (char)KBD_CMD_GETLAYOUT);
841 			if (kbdd->kbdd_layoutid)
842 				(void) quntimeout(q, kbdd->kbdd_layoutid);
843 			kbdd->kbdd_layoutid = qtimeout(q, kbdlayouttimeout,
844 			    kbdd, hz / 5);
845 			return;		/* wait for reply from keyboard */
846 		} else {
847 			/*
848 			 * Not a Type 4 keyboard; return an immediate error.
849 			 */
850 			err = EINVAL;
851 			break;
852 		}
853 
854 	case KIOCGRPTDELAY:
855 		/*
856 		 * Report the autorepeat delay, unit in millisecond
857 		 */
858 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
859 			ioctlrespsize = sizeof (int);
860 			goto allocfailure;
861 		}
862 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatdelay);
863 		datap->b_wptr += sizeof (int);
864 
865 		/* free msg to prevent memory leak */
866 		if (mp->b_cont != NULL)
867 			freemsg(mp->b_cont);
868 		mp->b_cont = datap;
869 		iocp->ioc_count = sizeof (int);
870 		break;
871 
872 	case KIOCSRPTDELAY:
873 		/*
874 		 * Set the autorepeat delay
875 		 */
876 		err = miocpullup(mp, sizeof (int));
877 
878 		if (err != 0)
879 			break;
880 
881 		/* validate the input */
882 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTDELAY_MIN) {
883 			err = EINVAL;
884 			break;
885 		}
886 		kbd_repeatdelay = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
887 		if (kbd_repeatdelay <= 0)
888 			kbd_repeatdelay = 1;
889 		break;
890 
891 	case KIOCGRPTRATE:
892 		/*
893 		 * Report the autorepeat rate
894 		 */
895 		if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
896 			ioctlrespsize = sizeof (int);
897 			goto allocfailure;
898 		}
899 		*(int *)datap->b_wptr = TICK_TO_MSEC(kbd_repeatrate);
900 		datap->b_wptr += sizeof (int);
901 
902 		/* free msg to prevent memory leak */
903 		if (mp->b_cont != NULL)
904 			freemsg(mp->b_cont);
905 		mp->b_cont = datap;
906 		iocp->ioc_count = sizeof (int);
907 		break;
908 
909 	case KIOCSRPTRATE:
910 		/*
911 		 * Set the autorepeat rate
912 		 */
913 		err = miocpullup(mp, sizeof (int));
914 
915 		if (err != 0)
916 			break;
917 
918 		/* validate the input */
919 		if (*(int *)mp->b_cont->b_rptr < KIOCRPTRATE_MIN) {
920 			err = EINVAL;
921 			break;
922 		}
923 		kbd_repeatrate = MSEC_TO_TICK(*(int *)mp->b_cont->b_rptr);
924 		if (kbd_repeatrate <= 0)
925 			kbd_repeatrate = 1;
926 		break;
927 
928 	default:
929 		putnext(q, mp);	/* pass it down the line */
930 		return;
931 	}
932 	goto done;
933 
934 output_format_change:
935 	kbdflush(kbdd);
936 
937 done:
938 	if (err != 0) {
939 		iocp->ioc_rval = 0;
940 		iocp->ioc_error = err;
941 		mp->b_datap->db_type = M_IOCNAK;
942 	} else {
943 		iocp->ioc_rval = 0;
944 		iocp->ioc_error = 0;	/* brain rot */
945 		mp->b_datap->db_type = M_IOCACK;
946 	}
947 	qreply(q, mp);
948 	return;
949 
950 allocfailure:
951 	/*
952 	 * We needed to allocate something to handle this "ioctl", but
953 	 * couldn't; save this "ioctl" and arrange to get called back when
954 	 * it's more likely that we can get what we need.
955 	 * If there's already one being saved, throw it out, since it
956 	 * must have timed out.
957 	 */
958 	if (kbdd->kbdd_iocpending != NULL)
959 		freemsg(kbdd->kbdd_iocpending);
960 	kbdd->kbdd_iocpending = mp;
961 	if (kbdd->kbdd_bufcallid)
962 		qunbufcall(q, kbdd->kbdd_bufcallid);
963 	kbdd->kbdd_bufcallid = qbufcall(q, ioctlrespsize, BPRI_HI,
964 	    kbdreioctl, kbdd);
965 }
966 
967 static void
kbdflush(register struct kbddata * kbdd)968 kbdflush(register struct kbddata *kbdd)
969 {
970 	register queue_t *q;
971 
972 	/* Flush pending data already sent upstream */
973 	if ((q = kbdd->kbdd_readq) != NULL && q->q_next != NULL)
974 		(void) putnextctl1(q, M_FLUSH, FLUSHR);
975 	/* Flush pending ups */
976 	bzero(kbdd->kbdd_downs, kbdd->kbdd_downs_bytes);
977 	kbdcancelrpt(kbdd);
978 }
979 
980 /*
981  * Pass keycode upstream, either translated or untranslated.
982  */
983 static void
kbduse(register struct kbddata * kbdd,unsigned keycode)984 kbduse(register struct kbddata *kbdd, unsigned keycode)
985 {
986 	register queue_t *readq;
987 
988 #ifdef	KBD_DEBUG
989 	if (kbd_input_debug) printf("KBD USE key=%d\n", keycode);
990 #endif
991 
992 	if ((readq = kbdd->kbdd_readq) == NULL)
993 		return;
994 	if (!kbdd->kbdd_translatable ||
995 	    kbdd->kbdd_translate == TR_NONE)
996 		kbdputcode(keycode, readq);
997 	else
998 		kbdtranslate(kbdd, keycode, readq);
999 }
1000 
1001 static void
kbd_beep_on(void * arg)1002 kbd_beep_on(void *arg)
1003 {
1004 	kbdcmd((queue_t *)arg, KBD_CMD_BELL);
1005 }
1006 
1007 
1008 static void
kbd_beep_off(void * arg)1009 kbd_beep_off(void *arg)
1010 {
1011 	kbdcmd((queue_t *)arg, KBD_CMD_NOBELL);
1012 }
1013 
1014 
1015 /*
1016  * kbdclick is used to remember the current click value of the
1017  * Sun-3 keyboard.  This brain damaged keyboard will reset the
1018  * clicking to the "default" value after a reset command and
1019  * there is no way to read out the current click value.  We
1020  * cannot send a click command immediately after the reset
1021  * command or the keyboard gets screwed up.  So we wait until
1022  * we get the ID byte before we send back the click command.
1023  * Unfortunately, this means that there is a small window
1024  * where the keyboard can click when it really shouldn't be.
1025  * A value of -1 means that kbdclick has not been initialized yet.
1026  */
1027 static int kbdclick = -1;
1028 
1029 /*
1030  * Send command byte to keyboard, if you can.
1031  */
1032 static void
kbdcmd(register queue_t * q,char cmd)1033 kbdcmd(register queue_t *q, char cmd)
1034 {
1035 	register mblk_t *bp;
1036 
1037 	if (canput(q)) {
1038 		if ((bp = allocb(1, BPRI_MED)) == NULL)
1039 			cmn_err(CE_WARN,
1040 			    "kbdcmd: Can't allocate block for command");
1041 		else {
1042 			*bp->b_wptr++ = cmd;
1043 			putnext(q, bp);
1044 			if (cmd == KBD_CMD_NOCLICK)
1045 				kbdclick = 0;
1046 			else if (cmd == KBD_CMD_CLICK)
1047 				kbdclick = 1;
1048 		}
1049 	}
1050 }
1051 
1052 /*
1053  * Update the keyboard LEDs to match the current keyboard state.
1054  * Do this only on Type 4 keyboards; other keyboards don't support the
1055  * KBD_CMD_SETLED command (nor, for that matter, the appropriate LEDs).
1056  */
1057 static void
kbdsetled(register struct kbddata * kbdd)1058 kbdsetled(register struct kbddata *kbdd)
1059 {
1060 	if (kbdd->kbdd_state.k_id == KB_SUN4 ||
1061 	    kbdd->kbdd_state.k_id == KB_PC) {
1062 		kbdcmd(kbdd->kbdd_writeq, KBD_CMD_SETLED);
1063 		kbdcmd(kbdd->kbdd_writeq, kbdd->led_state);
1064 	}
1065 }
1066 
1067 /*
1068  * Reset the keyboard
1069  */
1070 static void
kbdreset(register struct kbddata * kbdd,uint_t hard_reset)1071 kbdreset(register struct kbddata *kbdd, uint_t hard_reset)
1072 {
1073 	register struct keyboardstate *k;
1074 
1075 	k = &kbdd->kbdd_state;
1076 	if (kbdd->kbdd_translatable) {
1077 		k->k_idstate = KID_NONE;
1078 		k->k_id = -1;
1079 		k->k_state = NORMAL;
1080 		if (hard_reset)
1081 			kbdcmd(kbdd->kbdd_writeq, KBD_CMD_RESET);
1082 	} else {
1083 		bzero(k, sizeof (struct keyboardstate));
1084 		k->k_id = KB_ASCII;
1085 		k->k_idstate = KID_OK;
1086 	}
1087 }
1088 
1089 /*
1090  * Old special codes.
1091  */
1092 #define	OLD_SHIFTKEYS	0x80
1093 #define	OLD_BUCKYBITS	0x90
1094 #define	OLD_FUNNY	0xA0
1095 #define	OLD_FA_UMLAUT	0xA9
1096 #define	OLD_FA_CFLEX	0xAA
1097 #define	OLD_FA_TILDE	0xAB
1098 #define	OLD_FA_CEDILLA	0xAC
1099 #define	OLD_FA_ACUTE	0xAD
1100 #define	OLD_FA_GRAVE	0xAE
1101 #define	OLD_ISOCHAR	0xAF
1102 #define	OLD_STRING	0xB0
1103 #define	OLD_LEFTFUNC	0xC0
1104 #define	OLD_RIGHTFUNC	0xD0
1105 #define	OLD_TOPFUNC	0xE0
1106 #define	OLD_BOTTOMFUNC	0xF0
1107 
1108 /*
1109  * Map old special codes to new ones.
1110  * Indexed by ((old special code) >> 4) & 0x07; add (old special code) & 0x0F.
1111  */
1112 static ushort_t	special_old_to_new[] = {
1113 	SHIFTKEYS,
1114 	BUCKYBITS,
1115 	FUNNY,
1116 	STRING,
1117 	LEFTFUNC,
1118 	RIGHTFUNC,
1119 	TOPFUNC,
1120 	BOTTOMFUNC,
1121 };
1122 
1123 /*
1124  * Set individual keystation translation from old-style entry.
1125  * TODO: Have each keyboard own own translation tables.
1126  */
1127 static int
kbdsetkey(register struct kbddata * kbdd,struct kiockey * key,cred_t * cr)1128 kbdsetkey(register struct kbddata *kbdd, struct kiockey *key, cred_t *cr)
1129 {
1130 	int	strtabindex, i;
1131 	struct	keymap *km;
1132 	register int tablemask;
1133 	register ushort_t entry;
1134 
1135 	if (key->kio_station >= KEYMAP_SIZE)
1136 		return (EINVAL);
1137 	if (kbdd->kbdd_state.k_curkeyboard == NULL)
1138 		return (EINVAL);
1139 	tablemask = key->kio_tablemask;
1140 	if (tablemask == KIOCABORT1) {
1141 		if (secpolicy_console(cr) != 0)
1142 			return (EPERM);
1143 		kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station;
1144 		return (0);
1145 	}
1146 	if (tablemask == KIOCABORT2) {
1147 		if (secpolicy_console(cr) != 0)
1148 			return (EPERM);
1149 		kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station;
1150 		return (0);
1151 	}
1152 	if ((tablemask & ALTGRAPHMASK) ||
1153 	    (km = settable(kbdd, (uint_t)tablemask)) == NULL)
1154 		return (EINVAL);
1155 	if (key->kio_entry >= (uchar_t)OLD_STRING &&
1156 	    key->kio_entry <= (uchar_t)(OLD_STRING + 15)) {
1157 		strtabindex = key->kio_entry - OLD_STRING;
1158 		for (i = 0; i < KTAB_STRLEN; i++)
1159 			keystringtab[strtabindex][i] = key->kio_string[i];
1160 		keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
1161 	}
1162 	entry = key->kio_entry;
1163 	/*
1164 	 * There's nothing we need do with OLD_ISOCHAR.
1165 	 */
1166 	if (entry != OLD_ISOCHAR) {
1167 		if (entry & 0x80) {
1168 			if (entry >= OLD_FA_UMLAUT && entry <= OLD_FA_GRAVE)
1169 				entry = FA_CLASS + (entry & 0x0F) - 9;
1170 			else
1171 				entry =
1172 				    special_old_to_new[entry >> 4 & 0x07]
1173 				    + (entry & 0x0F);
1174 		}
1175 	}
1176 	km->keymap[key->kio_station] = entry;
1177 	return (0);
1178 }
1179 
1180 /*
1181  * Map new special codes to old ones.
1182  * Indexed by (new special code) >> 8; add (new special code) & 0xFF.
1183  */
1184 static uchar_t	special_new_to_old[] = {
1185 	0,			/* normal */
1186 	OLD_SHIFTKEYS,		/* SHIFTKEYS */
1187 	OLD_BUCKYBITS,		/* BUCKYBITS */
1188 	OLD_FUNNY,		/* FUNNY */
1189 	OLD_FA_UMLAUT,		/* FA_CLASS */
1190 	OLD_STRING,		/* STRING */
1191 	OLD_LEFTFUNC,		/* FUNCKEYS */
1192 };
1193 
1194 /*
1195  * Get individual keystation translation as old-style entry.
1196  */
1197 static int
kbdgetkey(register struct kbddata * kbdd,struct kiockey * key)1198 kbdgetkey(register struct kbddata *kbdd, struct	kiockey *key)
1199 {
1200 	int	strtabindex, i;
1201 	struct	keymap *km;
1202 	register ushort_t entry;
1203 
1204 	if (key->kio_station >= KEYMAP_SIZE)
1205 		return (EINVAL);
1206 	if (kbdd->kbdd_state.k_curkeyboard == NULL)
1207 		return (EINVAL);
1208 	if (key->kio_tablemask == KIOCABORT1) {
1209 		key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1;
1210 		return (0);
1211 	}
1212 	if (key->kio_tablemask == KIOCABORT2) {
1213 		key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2;
1214 		return (0);
1215 	}
1216 	if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
1217 		return (EINVAL);
1218 	entry = km->keymap[key->kio_station];
1219 	if (entry & 0xFF00)
1220 		key->kio_entry =
1221 		    special_new_to_old[(ushort_t)(entry & 0xFF00) >> 8]
1222 		    + (entry & 0x00FF);
1223 	else {
1224 		if (entry & 0x80)
1225 			key->kio_entry = (ushort_t)OLD_ISOCHAR;	/* you lose */
1226 		else
1227 			key->kio_entry = (ushort_t)entry;
1228 	}
1229 	if (entry >= STRING && entry <= (uchar_t)(STRING + 15)) {
1230 		strtabindex = entry - STRING;
1231 		for (i = 0; i < KTAB_STRLEN; i++)
1232 			key->kio_string[i] = keystringtab[strtabindex][i];
1233 	}
1234 	return (0);
1235 }
1236 
1237 /*
1238  * Set individual keystation translation from new-style entry.
1239  * TODO: Have each keyboard own own translation tables.
1240  */
1241 static int
kbdskey(register struct kbddata * kbdd,struct kiockeymap * key,cred_t * cr)1242 kbdskey(register struct kbddata *kbdd, struct kiockeymap *key, cred_t *cr)
1243 {
1244 	int	strtabindex, i;
1245 	struct	keymap *km;
1246 
1247 	if (key->kio_station >= KEYMAP_SIZE)
1248 		return (EINVAL);
1249 	if (kbdd->kbdd_state.k_curkeyboard == NULL)
1250 		return (EINVAL);
1251 	if (key->kio_tablemask == KIOCABORT1) {
1252 		if (secpolicy_console(cr) != 0)
1253 			return (EPERM);
1254 		kbdd->kbdd_state.k_curkeyboard->k_abort1 = key->kio_station;
1255 		return (0);
1256 	}
1257 	if (key->kio_tablemask == KIOCABORT2) {
1258 		if (secpolicy_console(cr) != 0)
1259 			return (EPERM);
1260 		kbdd->kbdd_state.k_curkeyboard->k_abort2 = key->kio_station;
1261 		return (0);
1262 	}
1263 	if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
1264 		return (EINVAL);
1265 	if (key->kio_entry >= STRING &&
1266 	    key->kio_entry <= (ushort_t)(STRING + 15)) {
1267 		strtabindex = key->kio_entry-STRING;
1268 		for (i = 0; i < KTAB_STRLEN; i++)
1269 			keystringtab[strtabindex][i] = key->kio_string[i];
1270 		keystringtab[strtabindex][KTAB_STRLEN-1] = '\0';
1271 	}
1272 	km->keymap[key->kio_station] = key->kio_entry;
1273 	return (0);
1274 }
1275 
1276 /*
1277  * Get individual keystation translation as new-style entry.
1278  */
1279 static int
kbdgkey(register struct kbddata * kbdd,struct kiockeymap * key)1280 kbdgkey(register struct kbddata *kbdd, struct	kiockeymap *key)
1281 {
1282 	int	strtabindex, i;
1283 	struct	keymap *km;
1284 
1285 	if (key->kio_station >= KEYMAP_SIZE)
1286 		return (EINVAL);
1287 	if (kbdd->kbdd_state.k_curkeyboard == NULL)
1288 		return (EINVAL);
1289 	if (key->kio_tablemask == KIOCABORT1) {
1290 		key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort1;
1291 		return (0);
1292 	}
1293 	if (key->kio_tablemask == KIOCABORT2) {
1294 		key->kio_station = kbdd->kbdd_state.k_curkeyboard->k_abort2;
1295 		return (0);
1296 	}
1297 	if ((km = settable(kbdd, (uint_t)key->kio_tablemask)) == NULL)
1298 		return (EINVAL);
1299 	key->kio_entry = km->keymap[key->kio_station];
1300 	if (key->kio_entry >= STRING &&
1301 	    key->kio_entry <= (ushort_t)(STRING + 15)) {
1302 		strtabindex = key->kio_entry-STRING;
1303 		for (i = 0; i < KTAB_STRLEN; i++)
1304 			key->kio_string[i] = keystringtab[strtabindex][i];
1305 	}
1306 	return (0);
1307 }
1308 
1309 static void
kbdlayouttimeout(void * arg)1310 kbdlayouttimeout(void *arg)
1311 {
1312 	struct kbddata *kbdd = arg;
1313 	mblk_t *mp;
1314 
1315 	kbdd->kbdd_layoutid = 0;
1316 
1317 	/*
1318 	 * Timed out waiting for reply to "get keyboard layout" command.
1319 	 * Return an ETIME error.
1320 	 */
1321 	if ((mp = kbdd->kbdd_replypending) != NULL) {
1322 		kbdd->kbdd_replypending = NULL;
1323 		mp->b_datap->db_type = M_IOCNAK;
1324 		((struct iocblk *)mp->b_rptr)->ioc_error = ETIME;
1325 		putnext(kbdd->kbdd_readq, mp);
1326 	}
1327 }
1328 
1329 /*
1330  * Put procedure for input from driver end of stream (read queue).
1331  */
1332 static void
kbdrput(register queue_t * q,register mblk_t * mp)1333 kbdrput(register queue_t *q, register mblk_t *mp)
1334 {
1335 	struct kbddata *kbdd = (struct kbddata *)q->q_ptr;
1336 	register mblk_t *bp;
1337 	register uchar_t *readp;
1338 	struct iocblk *iocp;
1339 
1340 	if (kbdd == 0) {
1341 		freemsg(mp);	/* nobody's listening */
1342 		return;
1343 	}
1344 
1345 	switch (mp->b_datap->db_type) {
1346 
1347 	case M_FLUSH:
1348 		if (*mp->b_rptr & FLUSHW)
1349 			flushq(WR(q), FLUSHDATA);
1350 		if (*mp->b_rptr & FLUSHR)
1351 			flushq(q, FLUSHDATA);
1352 
1353 	default:
1354 		putnext(q, mp);
1355 		return;
1356 
1357 	case M_BREAK:
1358 		/*
1359 		 * Will get M_BREAK only if this is not the system
1360 		 * keyboard, otherwise serial port will eat break
1361 		 * and call kmdb/OBP, without passing anything up.
1362 		 */
1363 		freemsg(mp);
1364 		return;
1365 
1366 	case M_IOCACK:
1367 	case M_IOCNAK:
1368 		/*
1369 		 * If we are doing an "ioctl" ourselves, check if this
1370 		 * is the reply to that code.  If so, wake up the
1371 		 * "open" routine, and toss the reply, otherwise just
1372 		 * pass it up.
1373 		 */
1374 		iocp = (struct iocblk *)mp->b_rptr;
1375 		if (!(kbdd->kbdd_flags & KBD_IOCWAIT) ||
1376 		    iocp->ioc_id != kbdd->kbdd_iocid) {
1377 			/*
1378 			 * This isn't the reply we're looking for.  Move along.
1379 			 */
1380 			if (kbdd->kbdd_flags & KBD_OPEN)
1381 				putnext(q, mp);
1382 			else
1383 				freemsg(mp);	/* not ready to listen */
1384 		} else {
1385 			kbdd->kbdd_flags &= ~KBD_IOCWAIT;
1386 			kbdd->kbdd_iocerror = iocp->ioc_error;
1387 			freemsg(mp);
1388 		}
1389 		return;
1390 
1391 	case M_DATA:
1392 		if (!(kbdd->kbdd_flags & KBD_OPEN)) {
1393 			freemsg(mp);	/* not read to listen */
1394 			return;
1395 		}
1396 		break;
1397 	}
1398 
1399 	/*
1400 	 * A data message, consisting of bytes from the keyboard.
1401 	 * Ram them through our state machine.
1402 	 */
1403 	bp = mp;
1404 
1405 	do {
1406 		readp = bp->b_rptr;
1407 		while (readp < bp->b_wptr)
1408 			kbdinput(kbdd, *readp++);
1409 		bp->b_rptr = readp;
1410 	} while ((bp = bp->b_cont) != NULL);	/* next block, if any */
1411 
1412 	freemsg(mp);
1413 }
1414 
1415 /*
1416  * A keypress was received. Process it through the state machine
1417  * to check for aborts.
1418  */
1419 static void
kbdinput(register struct kbddata * kbdd,register unsigned key)1420 kbdinput(register struct kbddata *kbdd, register unsigned key)
1421 {
1422 	register struct keyboardstate *k;
1423 	register mblk_t *mp;
1424 
1425 	k = &kbdd->kbdd_state;
1426 #ifdef	KBD_DEBUG
1427 	if (kbd_input_debug)
1428 		printf("kbdinput key %x\n", key);
1429 #endif
1430 
1431 	switch (k->k_idstate) {
1432 
1433 	case KID_NONE:
1434 		if (key == RESETKEY) {
1435 			k->k_idstate = KID_GOT_PREFACE;
1436 		} else  {
1437 			kbdreset(kbdd, HARD_RESET);
1438 			/* allows hot plug of kbd after booting without kbd */
1439 		}
1440 		return;
1441 
1442 	case KID_GOT_PREFACE:
1443 		kbdid(kbdd, (int)key);
1444 
1445 		/*
1446 		 * We just did a reset command to a Type 3 or Type 4
1447 		 * keyboard which sets the click back to the default
1448 		 * (which is currently ON!).  We use the kbdclick
1449 		 * variable to see if the keyboard should be turned on
1450 		 * or off.  If it has not been set, then we use the
1451 		 * keyboard-click? property.
1452 		 */
1453 		switch (kbdclick) {
1454 		case 0:
1455 			kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK);
1456 			break;
1457 		case 1:
1458 			kbdcmd(kbdd->kbdd_writeq, KBD_CMD_CLICK);
1459 			break;
1460 		case -1:
1461 		default:
1462 			{
1463 				char wrkbuf[8];
1464 				int len;
1465 
1466 				kbdcmd(kbdd->kbdd_writeq, KBD_CMD_NOCLICK);
1467 
1468 				bzero(wrkbuf, 8);
1469 				len = 7;
1470 				if (ddi_getlongprop_buf(DDI_DEV_T_ANY,
1471 				    ddi_root_node(), 0, "keyboard-click?",
1472 				    (caddr_t)wrkbuf, &len) ==
1473 				    DDI_PROP_SUCCESS &&
1474 				    len > 0 && len < 8) {
1475 					if (strcmp(wrkbuf, "true") == 0) {
1476 						kbdcmd(kbdd->kbdd_writeq,
1477 						    KBD_CMD_CLICK);
1478 					}
1479 				}
1480 			}
1481 			break;
1482 		}
1483 		/*
1484 		 * A keyboard reset clears the LEDs.
1485 		 * Restore the LEDs from the last value we set
1486 		 * them to.
1487 		 */
1488 		kbdsetled(kbdd);
1489 		return;
1490 
1491 	case KID_OK:
1492 		switch (key) {
1493 
1494 #if	defined(KBD_PRESSED_PREFIX)
1495 		case KBD_PRESSED_PREFIX:
1496 			k->k_idstate = KID_GOT_PRESSED;
1497 			return;
1498 #endif
1499 
1500 #if	defined(KBD_RELEASED_PREFIX)
1501 		case KBD_RELEASED_PREFIX:
1502 			k->k_idstate = KID_GOT_RELEASED;
1503 			return;
1504 #endif
1505 
1506 		case 0:
1507 			kbdreset(kbdd, HARD_RESET);
1508 			return;
1509 
1510 		/*
1511 		 * we want to check for ID only if we are in
1512 		 * translatable mode.
1513 		 */
1514 		case RESETKEY:
1515 			kbdreset(kbdd, NO_HARD_RESET);
1516 			if (k->k_idstate == KID_NONE) {
1517 				k->k_idstate = KID_GOT_PREFACE;
1518 			}
1519 			return;
1520 
1521 		case LAYOUTKEY:
1522 			k->k_idstate = KID_GOT_LAYOUT;
1523 			return;
1524 		}
1525 		break;
1526 
1527 #if	defined(KBD_PRESSED_PREFIX)
1528 	case KID_GOT_PRESSED:
1529 		key = BUILDKEY(key, PRESSED);
1530 		k->k_idstate = KID_OK;
1531 		break;
1532 #endif
1533 #if	defined(KBD_RELEASED_PREFIX)
1534 	case KID_GOT_RELEASED:
1535 		key = BUILDKEY(key, RELEASED);
1536 		k->k_idstate = KID_OK;
1537 		break;
1538 #endif
1539 
1540 	case KID_GOT_LAYOUT:
1541 		if (kbdd->kbdd_layoutid)
1542 			(void) quntimeout(kbdd->kbdd_readq,
1543 			    kbdd->kbdd_layoutid);
1544 		if ((mp = kbdd->kbdd_replypending) != NULL) {
1545 			kbdd->kbdd_replypending = NULL;
1546 			*(int *)mp->b_cont->b_wptr = key;
1547 			mp->b_cont->b_wptr += sizeof (int);
1548 			putnext(kbdd->kbdd_readq, mp);
1549 		}
1550 		k->k_idstate = KID_OK;
1551 		return;
1552 	}
1553 
1554 	switch (k->k_state) {
1555 
1556 #if defined(__sparc)
1557 	normalstate:
1558 		k->k_state = NORMAL;
1559 		/* FALLTHRU */
1560 #endif
1561 	case NORMAL:
1562 #if defined(__sparc)
1563 		if (k->k_curkeyboard) {
1564 			if (key == k->k_curkeyboard->k_abort1) {
1565 				k->k_state = ABORT1;
1566 				break;
1567 			}
1568 			if ((key == k->k_curkeyboard->k_newabort1) ||
1569 			    (key == k->k_curkeyboard->k_newabort1a)) {
1570 				k->k_state = NEWABORT1;
1571 				kbdd->shiftkey = key;
1572 			}
1573 		}
1574 #endif
1575 		kbduse(kbdd, key);
1576 		break;
1577 
1578 #if defined(__sparc)
1579 	case ABORT1:
1580 		if (k->k_curkeyboard) {
1581 			/*
1582 			 * Only recognize this as an abort sequence if
1583 			 * the "hardware" console is set to be this device.
1584 			 */
1585 			if (key == k->k_curkeyboard->k_abort2 &&
1586 			    rconsvp == wsconsvp) {
1587 				DELAY(100000);
1588 				abort_sequence_enter((char *)NULL);
1589 				k->k_state = NORMAL;
1590 				kbduse(kbdd, IDLEKEY);	/* fake */
1591 				return;
1592 			} else {
1593 				kbduse(kbdd, k->k_curkeyboard->k_abort1);
1594 				goto normalstate;
1595 			}
1596 		}
1597 		break;
1598 	case NEWABORT1:
1599 		if (k->k_curkeyboard) {
1600 			/*
1601 			 * Only recognize this as an abort sequence if
1602 			 * the "hardware" console is set to be this device.
1603 			 */
1604 			if (key == k->k_curkeyboard->k_newabort2 &&
1605 			    rconsvp == wsconsvp) {
1606 				DELAY(100000);
1607 				abort_sequence_enter((char *)NULL);
1608 				k->k_state = NORMAL;
1609 				kbdd->shiftkey |= RELEASED;
1610 				kbduse(kbdd, kbdd->shiftkey);
1611 				kbduse(kbdd, IDLEKEY);	/* fake */
1612 				return;
1613 			} else {
1614 				goto normalstate;
1615 			}
1616 		}
1617 		break;
1618 #endif
1619 
1620 	case COMPOSE1:
1621 	case COMPOSE2:
1622 	case FLTACCENT:
1623 		if (key != IDLEKEY)
1624 			kbduse(kbdd, key);
1625 		break;
1626 	}
1627 }
1628 
1629 static void
kbdid(register struct kbddata * kbdd,int id)1630 kbdid(register struct kbddata *kbdd, int id)
1631 {
1632 	register struct keyboardstate *k;
1633 	int	i;
1634 
1635 	k = &kbdd->kbdd_state;
1636 
1637 	k->k_idstate = KID_OK;
1638 	k->k_shiftmask = 0;
1639 	k->k_buckybits = 0;
1640 
1641 	/*
1642 	 * Reset k_rptkey to IDLEKEY. We need to cancel
1643 	 * the autorepeat feature, if any.
1644 	 */
1645 	if (k->k_rptkey != IDLEKEY) {
1646 		if (kbdd->kbdd_rptid)
1647 			(void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid);
1648 		kbdd->kbdd_rptid = 0;
1649 		k->k_rptkey = IDLEKEY;
1650 	}
1651 
1652 	k->k_curkeyboard = NULL;
1653 	for (i = 0; keytables[i].table; i++) {
1654 		if (keytables[i].id == id) {
1655 			k->k_id = id;
1656 			k->k_curkeyboard = keytables[i].table;
1657 			break;
1658 		}
1659 	}
1660 	if (!k->k_curkeyboard) {
1661 		k->k_id = keytables[0].id;
1662 		k->k_curkeyboard = keytables[0].table;
1663 		cmn_err(CE_WARN, "kbd: Unknown keyboard type, "
1664 		    "Type %d assumed", k->k_id);
1665 	}
1666 }
1667 
1668 /*
1669  * This routine determines which table we should look in to decode
1670  * the current keycode.
1671  */
1672 static struct keymap *
settable(register struct kbddata * kbdd,register uint_t mask)1673 settable(register struct kbddata *kbdd, register uint_t mask)
1674 {
1675 	register struct keyboard *kp;
1676 
1677 	kp = kbdd->kbdd_state.k_curkeyboard;
1678 	if (kp == NULL)
1679 		return (NULL);
1680 	if (mask & UPMASK)
1681 		return (kp->k_up);
1682 	if (mask & NUMLOCKMASK)
1683 		return (kp->k_numlock);
1684 	if (mask & CTRLMASK)
1685 		return (kp->k_control);
1686 	if (mask & ALTGRAPHMASK)
1687 		return (kp->k_altgraph);
1688 	if (mask & SHIFTMASK)
1689 		return (kp->k_shifted);
1690 	if (mask & CAPSMASK)
1691 		return (kp->k_caps);
1692 	return (kp->k_normal);
1693 }
1694 
1695 static void
kbdrpt(void * arg)1696 kbdrpt(void *arg)
1697 {
1698 	struct kbddata *kbdd = arg;
1699 	struct keyboardstate *k;
1700 
1701 	k = &kbdd->kbdd_state;
1702 #ifdef	KBD_DEBUG
1703 	if (kbd_rpt_debug)
1704 		printf("kbdrpt key %x\n", k->k_rptkey);
1705 #endif
1706 	kbdd->kbdd_rptid = 0;
1707 
1708 	kbdkeyreleased(kbdd, KEYOF(k->k_rptkey));
1709 	kbduse(kbdd, k->k_rptkey);
1710 	if (k->k_rptkey != IDLEKEY) {
1711 		kbdd->kbdd_rptid = qtimeout(kbdd->kbdd_readq, kbdrpt,
1712 		    kbdd, kbd_repeatrate);
1713 	}
1714 }
1715 
1716 static void
kbdcancelrpt(register struct kbddata * kbdd)1717 kbdcancelrpt(register struct kbddata *kbdd)
1718 {
1719 	register struct keyboardstate *k;
1720 
1721 	k = &kbdd->kbdd_state;
1722 	if (k->k_rptkey != IDLEKEY) {
1723 		if (kbdd->kbdd_rptid)
1724 			(void) quntimeout(kbdd->kbdd_readq, kbdd->kbdd_rptid);
1725 		kbdd->kbdd_rptid = 0;
1726 		k->k_rptkey = IDLEKEY;
1727 	}
1728 	ASSERT(kbdd->kbdd_rptid == 0);
1729 }
1730 
1731 static void
kbdtranslate(struct kbddata * kbdd,unsigned keycode,queue_t * q)1732 kbdtranslate(struct kbddata *kbdd, unsigned keycode, queue_t *q)
1733 {
1734 	register uchar_t key;
1735 	register unsigned newstate;
1736 	unsigned shiftmask;
1737 	register ushort_t entry, entrytype;
1738 	register char *cp, *bufp;
1739 	register struct keyboardstate *k;
1740 	ushort_t result_iso;
1741 	struct keymap *km;
1742 	Firm_event fe;
1743 	int i, ret_val;
1744 	char buf[14];
1745 
1746 	k = &kbdd->kbdd_state;
1747 	newstate = STATEOF(keycode);
1748 	key = KEYOF(keycode);
1749 
1750 #ifdef	KBD_DEBUG
1751 	if (kbd_input_debug) {
1752 		printf("KBD TRANSLATE keycode=0x%x newstate=0x%x key=0x%x\n",
1753 		    keycode, newstate, key);
1754 	}
1755 #endif
1756 
1757 	if (kbdd->kbdd_translate == TR_UNTRANS_EVENT) {
1758 		if (newstate == PRESSED) {
1759 			bzero(&fe, sizeof (fe));
1760 			fe.id = key;
1761 			fe.value = 1;
1762 			kbdqueuepress(kbdd, key, &fe);
1763 		} else {
1764 			kbdkeyreleased(kbdd, key);
1765 		}
1766 		return;
1767 	}
1768 
1769 	shiftmask = k->k_shiftmask;
1770 	if (newstate == RELEASED)
1771 		shiftmask |= UPMASK;
1772 
1773 	km = settable(kbdd, shiftmask);
1774 	if (km == NULL) {		/* gross error */
1775 		kbdcancelrpt(kbdd);
1776 		return;
1777 	}
1778 
1779 	if (key >= KEYMAP_SIZE)
1780 		return;
1781 	entry = km->keymap[key];
1782 
1783 	if (entry == NONL) {
1784 		/*
1785 		 * NONL appears only in the Num Lock table, and indicates that
1786 		 * this key is not affected by Num Lock.  This means we should
1787 		 * ask for the table we would have gotten had Num Lock not been
1788 		 * down, and translate using that table.
1789 		 */
1790 		km = settable(kbdd, shiftmask & ~NUMLOCKMASK);
1791 		if (km == NULL) {		/* gross error */
1792 			kbdcancelrpt(kbdd);
1793 			return;
1794 		}
1795 		entry = km->keymap[key];
1796 	}
1797 	entrytype = (ushort_t)(entry & 0xFF00) >> 8;
1798 
1799 	if (entrytype == (SHIFTKEYS >> 8)) {
1800 		/*
1801 		 * Handle the state of toggle shifts specially.
1802 		 * Ups should be ignored, and downs should be mapped to ups if
1803 		 * that shift is currently on.
1804 		 */
1805 		if ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts) {
1806 			if ((1 << (entry & 0x0F)) & k->k_togglemask) {
1807 				newstate = RELEASED;	/* toggling off */
1808 			} else {
1809 				newstate = PRESSED;	/* toggling on */
1810 			}
1811 		}
1812 	} else {
1813 		/*
1814 		 * Handle Compose and floating accent key sequences
1815 		 */
1816 		if (k->k_state == COMPOSE1) {
1817 			if (newstate == RELEASED)
1818 				return;
1819 			if (entry < ASCII_SET_SIZE) {
1820 				if (kb_compose_map[entry] >= 0) {
1821 					kbdd->compose_key = entry;
1822 					k->k_state = COMPOSE2;
1823 					return;
1824 				}
1825 			}
1826 			k->k_state = NORMAL;
1827 			kbdd->led_state &= ~LED_COMPOSE;
1828 			kbdsetled(kbdd);
1829 			return;
1830 		} else if (k->k_state == COMPOSE2) {
1831 			if (newstate == RELEASED)
1832 				return;
1833 			k->k_state = NORMAL;	/* next state is "normal" */
1834 			kbdd->led_state &= ~LED_COMPOSE;
1835 			kbdsetled(kbdd);
1836 			if (entry < ASCII_SET_SIZE) {
1837 				if (kb_compose_map[entry] >= 0) {
1838 					if (kbdd->compose_key <= entry) {
1839 						ret_val = kbd_do_compose(
1840 						    kbdd->compose_key,
1841 						    entry,
1842 						    &result_iso);
1843 					} else {
1844 						ret_val = kbd_do_compose(
1845 						    entry,
1846 						    kbdd->compose_key,
1847 						    &result_iso);
1848 					}
1849 					if (ret_val == 1) {
1850 						if (kbdd->kbdd_translate ==
1851 						    TR_EVENT) {
1852 							fe.id =
1853 							    (kbdd->kbdd_compat ?
1854 							    ISO_FIRST :
1855 							    EUC_FIRST)
1856 							    + result_iso;
1857 							fe.value = 1;
1858 							kbdqueueevent(
1859 							    kbdd,
1860 							    &fe);
1861 						} else if (
1862 						    kbdd->kbdd_translate ==
1863 						    TR_ASCII)
1864 							kbdputcode(
1865 							    result_iso,
1866 							    q);
1867 					}
1868 				}
1869 			}
1870 			return;
1871 		} else if (k->k_state == FLTACCENT) {
1872 			if (newstate == RELEASED)
1873 				return;
1874 			k->k_state = NORMAL;	/* next state is "normal" */
1875 			for (i = 0;
1876 			    (kb_fltaccent_table[i].fa_entry
1877 			    != kbdd->fltaccent_entry) ||
1878 			    (kb_fltaccent_table[i].ascii != entry);
1879 			    i++) {
1880 				if (kb_fltaccent_table[i].fa_entry == 0)
1881 					/* Invalid second key: ignore key */
1882 					return;
1883 			}
1884 			if (kbdd->kbdd_translate == TR_EVENT) {
1885 				fe.id = (kbdd->kbdd_compat ?
1886 				    ISO_FIRST : EUC_FIRST)
1887 				    + kb_fltaccent_table[i].iso;
1888 				fe.value = 1;
1889 				kbdqueueevent(kbdd, &fe);
1890 			} else if (kbdd->kbdd_translate == TR_ASCII)
1891 				kbdputcode(kb_fltaccent_table[i].iso, q);
1892 			return;
1893 		}
1894 	}
1895 
1896 	/*
1897 	 * If the key is going down, and it's not one of the keys that doesn't
1898 	 * auto-repeat, set up the auto-repeat timeout.
1899 	 *
1900 	 * The keys that don't auto-repeat are the Compose key,
1901 	 * the shift keys, the "bucky bit" keys, the "floating accent" keys,
1902 	 * and the function keys when in TR_EVENT mode.
1903 	 */
1904 	if (newstate == PRESSED && entrytype != (SHIFTKEYS >> 8) &&
1905 	    entrytype != (BUCKYBITS >> 8) && entrytype != (FUNNY >> 8) &&
1906 	    entrytype != (FA_CLASS >> 8) &&
1907 	    !((entrytype == (FUNCKEYS >> 8) || entrytype == (PADKEYS >> 8)) &&
1908 	    kbdd->kbdd_translate == TR_EVENT)) {
1909 		if (k->k_rptkey != keycode) {
1910 			kbdcancelrpt(kbdd);
1911 			kbdd->kbdd_rptid = qtimeout(q, kbdrpt, kbdd,
1912 			    kbd_repeatdelay);
1913 			k->k_rptkey = keycode;
1914 		}
1915 	} else if (key == KEYOF(k->k_rptkey))		/* key going up */
1916 		kbdcancelrpt(kbdd);
1917 	if ((newstate == RELEASED) && (kbdd->kbdd_translate == TR_EVENT))
1918 		kbdkeyreleased(kbdd, key);
1919 
1920 	/*
1921 	 * We assume here that keys other than shift keys and bucky keys have
1922 	 * entries in the "up" table that cause nothing to be done, and thus we
1923 	 * don't have to check for newstate == RELEASED.
1924 	 */
1925 	switch (entrytype) {
1926 
1927 	case 0x0:		/* regular key */
1928 		switch (kbdd->kbdd_translate) {
1929 
1930 		case TR_EVENT:
1931 			fe.id = entry | k->k_buckybits;
1932 			fe.value = 1;
1933 			kbdkeypressed(kbdd, key, &fe, entry);
1934 			break;
1935 
1936 		case TR_ASCII:
1937 			kbdputcode(entry | k->k_buckybits, q);
1938 			break;
1939 		}
1940 		break;
1941 
1942 	case SHIFTKEYS >> 8: {
1943 		uint_t shiftbit = 1 << (entry & 0x0F);
1944 
1945 		/* Modify toggle state (see toggle processing above) */
1946 		if (shiftbit & k->k_curkeyboard->k_toggleshifts) {
1947 			if (newstate == RELEASED) {
1948 				if (shiftbit == CAPSMASK) {
1949 					kbdd->led_state &= ~LED_CAPS_LOCK;
1950 					kbdsetled(kbdd);
1951 				} else if (shiftbit == NUMLOCKMASK) {
1952 					kbdd->led_state &= ~LED_NUM_LOCK;
1953 					kbdsetled(kbdd);
1954 				}
1955 				k->k_togglemask &= ~shiftbit;
1956 			} else {
1957 				if (shiftbit == CAPSMASK) {
1958 					kbdd->led_state |= LED_CAPS_LOCK;
1959 					kbdsetled(kbdd);
1960 				} else if (shiftbit == NUMLOCKMASK) {
1961 					kbdd->led_state |= LED_NUM_LOCK;
1962 					kbdsetled(kbdd);
1963 				}
1964 				k->k_togglemask |= shiftbit;
1965 			}
1966 		}
1967 
1968 		if (newstate == RELEASED)
1969 			k->k_shiftmask &= ~shiftbit;
1970 		else
1971 			k->k_shiftmask |= shiftbit;
1972 
1973 		if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) {
1974 			/*
1975 			 * Relying on ordinal correspondence between
1976 			 * vuid_event.h SHIFT_CAPSLOCK-SHIFT_RIGHTCTRL &
1977 			 * kbd.h CAPSLOCK-RIGHTCTRL in order to
1978 			 * correctly translate entry into fe.id.
1979 			 */
1980 			fe.id = SHIFT_CAPSLOCK + (entry & 0x0F);
1981 			fe.value = 1;
1982 			kbdkeypressed(kbdd, key, &fe, fe.id);
1983 		}
1984 		break;
1985 		}
1986 
1987 	case BUCKYBITS >> 8:
1988 		k->k_buckybits ^= 1 << (7 + (entry & 0x0F));
1989 		if (kbdd->kbdd_translate == TR_EVENT && newstate == PRESSED) {
1990 			/*
1991 			 * Relying on ordinal correspondence between
1992 			 * vuid_event.h SHIFT_META-SHIFT_TOP &
1993 			 * kbd.h METABIT-SYSTEMBIT in order to
1994 			 * correctly translate entry into fe.id.
1995 			 */
1996 			fe.id = SHIFT_META + (entry & 0x0F);
1997 			fe.value = 1;
1998 			kbdkeypressed(kbdd, key, &fe, fe.id);
1999 		}
2000 		break;
2001 
2002 	case FUNNY >> 8:
2003 		switch (entry) {
2004 		case NOP:
2005 			break;
2006 
2007 		case IDLE:
2008 			/* Fall thru into RESET code */
2009 			/* FALLTHRU */
2010 		case RESET:
2011 		gotreset:
2012 			k->k_shiftmask &= k->k_curkeyboard->k_idleshifts;
2013 			k->k_shiftmask |= k->k_togglemask;
2014 			k->k_buckybits &= k->k_curkeyboard->k_idlebuckys;
2015 			kbdcancelrpt(kbdd);
2016 			kbdreleaseall(kbdd);
2017 			break;
2018 
2019 		case ERROR:
2020 			cmn_err(CE_WARN, "kbd: Error detected");
2021 			goto gotreset;
2022 
2023 		case COMPOSE:
2024 			k->k_state = COMPOSE1;
2025 			kbdd->led_state |= LED_COMPOSE;
2026 			kbdsetled(kbdd);
2027 			break;
2028 		/*
2029 		 * Remember when adding new entries that,
2030 		 * if they should NOT auto-repeat,
2031 		 * they should be put into the IF statement
2032 		 * just above this switch block.
2033 		 */
2034 		default:
2035 			goto badentry;
2036 		}
2037 		break;
2038 
2039 	case FA_CLASS >> 8:
2040 		if (k->k_state == NORMAL) {
2041 			kbdd->fltaccent_entry = entry;
2042 			k->k_state = FLTACCENT;
2043 		}
2044 		return;
2045 
2046 	case STRING >> 8:
2047 		cp = &keystringtab[entry & 0x0F][0];
2048 		while (*cp != '\0') {
2049 			switch (kbdd->kbdd_translate) {
2050 
2051 			case TR_EVENT:
2052 				kbd_send_esc_event(*cp, kbdd);
2053 				break;
2054 
2055 			case TR_ASCII:
2056 				kbdputcode((uchar_t)*cp, q);
2057 				break;
2058 			}
2059 			cp++;
2060 		}
2061 		break;
2062 
2063 	case FUNCKEYS >> 8:
2064 		switch (kbdd->kbdd_translate) {
2065 
2066 		case TR_ASCII:
2067 			bufp = buf;
2068 			cp = strsetwithdecimal(bufp + 2,
2069 			    (uint_t)((entry & 0x003F) + 192),
2070 			    sizeof (buf) - 5);
2071 			*bufp++ = '\033'; /* Escape */
2072 			*bufp++ = '[';
2073 			while (*cp != '\0')
2074 				*bufp++ = *cp++;
2075 			*bufp++ = 'z';
2076 			*bufp = '\0';
2077 			kbdputbuf(buf, q);
2078 			break;
2079 
2080 		case TR_EVENT:
2081 			/*
2082 			 * Take advantage of the similar
2083 			 * ordering of kbd.h function keys and
2084 			 * vuid_event.h function keys to do a
2085 			 * simple translation to achieve a
2086 			 * mapping between the 2 different
2087 			 * address spaces.
2088 			 */
2089 			fe.id = (entry & 0x003F) + KEY_LEFTFIRST;
2090 			fe.value = 1;
2091 			/*
2092 			 * Assume "up" table only generates
2093 			 * shift changes.
2094 			 */
2095 			kbdkeypressed(kbdd, key, &fe, fe.id);
2096 			/*
2097 			 * Function key events can be expanded
2098 			 * by terminal emulator software to
2099 			 * produce the standard escape sequence
2100 			 * generated by the TR_ASCII case above
2101 			 * if a function key event is not used
2102 			 * by terminal emulator software
2103 			 * directly.
2104 			 */
2105 			break;
2106 		}
2107 		break;
2108 
2109 	/*
2110 	 * Remember when adding new entries that,
2111 	 * if they should NOT auto-repeat,
2112 	 * they should be put into the IF statement
2113 	 * just above this switch block.
2114 	 */
2115 	case PADKEYS >> 8:
2116 		switch (kbdd->kbdd_translate) {
2117 
2118 		case TR_ASCII:
2119 			kbdputcode(kb_numlock_table[entry&0x1F], q);
2120 			break;
2121 
2122 		case TR_EVENT:
2123 			/*
2124 			 * Take advantage of the similar
2125 			 * ordering of kbd.h keypad keys and
2126 			 * vuid_event.h keypad keys to do a
2127 			 * simple translation to achieve a
2128 			 * mapping between the 2 different
2129 			 * address spaces.
2130 			 */
2131 			fe.id = (entry & 0x001F) + VKEY_FIRSTPAD;
2132 			fe.value = 1;
2133 			/*
2134 			 * Assume "up" table only generates
2135 			 * shift changes.
2136 			 */
2137 			kbdkeypressed(kbdd, key, &fe, fe.id);
2138 			/*
2139 			 * Keypad key events can be expanded
2140 			 * by terminal emulator software to
2141 			 * produce the standard ascii character
2142 			 * generated by the TR_ASCII case above
2143 			 * if a keypad key event is not used
2144 			 * by terminal emulator software
2145 			 * directly.
2146 			 */
2147 			break;
2148 		}
2149 
2150 	badentry:
2151 		break;
2152 	}
2153 }
2154 
2155 static int
kbd_do_compose(ushort_t first_entry,ushort_t second_entry,ushort_t * result_iso_ptr)2156 kbd_do_compose(ushort_t first_entry, ushort_t second_entry,
2157 	ushort_t *result_iso_ptr)
2158 {
2159 	struct compose_sequence_t *ptr;
2160 
2161 	ptr = &kb_compose_table[kb_compose_map[first_entry]];
2162 	while (ptr->first == first_entry) {
2163 		if (ptr->second == second_entry) {
2164 			*result_iso_ptr = ptr->iso;
2165 			return (1);
2166 		}
2167 		ptr++;
2168 	}
2169 	return (0);
2170 }
2171 
2172 static void
kbd_send_esc_event(char c,register struct kbddata * kbdd)2173 kbd_send_esc_event(char c, register struct kbddata *kbdd)
2174 {
2175 	Firm_event fe;
2176 
2177 	fe.id = c;
2178 	fe.value = 1;
2179 	fe.pair_type = FE_PAIR_NONE;
2180 	fe.pair = 0;
2181 	/*
2182 	 * Pretend as if each cp pushed and released
2183 	 * Calling kbdqueueevent avoids addr translation
2184 	 * and pair base determination of kbdkeypressed.
2185 	 */
2186 	kbdqueueevent(kbdd, &fe);
2187 	fe.value = 0;
2188 	kbdqueueevent(kbdd, &fe);
2189 }
2190 
2191 char *
strsetwithdecimal(char * buf,uint_t val,uint_t maxdigs)2192 strsetwithdecimal(char *buf, uint_t val, uint_t maxdigs)
2193 {
2194 	int	hradix = 5;
2195 	char	*bp;
2196 	int	lowbit;
2197 	char	*tab = "0123456789abcdef";
2198 
2199 	bp = buf + maxdigs;
2200 	*(--bp) = '\0';
2201 	while (val) {
2202 		lowbit = val & 1;
2203 		val = (val >> 1);
2204 		*(--bp) = tab[val % hradix * 2 + lowbit];
2205 		val /= hradix;
2206 	}
2207 	return (bp);
2208 }
2209 
2210 static void
kbdkeypressed(struct kbddata * kbdd,uchar_t key_station,Firm_event * fe,ushort_t base)2211 kbdkeypressed(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe,
2212     ushort_t base)
2213 {
2214 	register struct keyboardstate *k;
2215 	register short id_addr;
2216 
2217 	/* Set pair values */
2218 	if (fe->id < (ushort_t)VKEY_FIRST) {
2219 		/*
2220 		 * If CTRLed, find the ID that would have been used had it
2221 		 * not been CTRLed.
2222 		 */
2223 		k = &kbdd->kbdd_state;
2224 		if (k->k_shiftmask & (CTRLMASK | CTLSMASK)) {
2225 			struct keymap *km;
2226 
2227 			km = settable(kbdd,
2228 			    k->k_shiftmask & ~(CTRLMASK | CTLSMASK | UPMASK));
2229 			if (km == NULL)
2230 				return;
2231 			base = km->keymap[key_station];
2232 		}
2233 		if (base != fe->id) {
2234 			fe->pair_type = FE_PAIR_SET;
2235 			fe->pair = base;
2236 			goto send;
2237 		}
2238 	}
2239 	fe->pair_type = FE_PAIR_NONE;
2240 	fe->pair = 0;
2241 send:
2242 	/* Adjust event id address for multiple keyboard/workstation support */
2243 	switch (vuid_id_addr(fe->id)) {
2244 	case ASCII_FIRST:
2245 		id_addr = kbdd->kbdd_ascii_addr;
2246 		break;
2247 	case TOP_FIRST:
2248 		id_addr = kbdd->kbdd_top_addr;
2249 		break;
2250 	case VKEY_FIRST:
2251 		id_addr = kbdd->kbdd_vkey_addr;
2252 		break;
2253 	default:
2254 		id_addr = vuid_id_addr(fe->id);
2255 	}
2256 	fe->id = vuid_id_offset(fe->id) | id_addr;
2257 	kbdqueuepress(kbdd, key_station, fe);
2258 }
2259 
2260 static void
kbdqueuepress(struct kbddata * kbdd,uchar_t key_station,Firm_event * fe)2261 kbdqueuepress(struct kbddata *kbdd, uchar_t key_station, Firm_event *fe)
2262 {
2263 	register struct key_event *ke, *ke_free;
2264 	register int i;
2265 
2266 	if (key_station == IDLEKEY)
2267 		return;
2268 #ifdef	KBD_DEBUG
2269 	if (kbd_input_debug) printf("KBD PRESSED key=%d\n", key_station);
2270 #endif
2271 	ke_free = 0;
2272 	/* Scan table of down key stations */
2273 	if (kbdd->kbdd_translate == TR_EVENT ||
2274 	    kbdd->kbdd_translate == TR_UNTRANS_EVENT) {
2275 		for (i = 0, ke = kbdd->kbdd_downs;
2276 		    i < kbdd->kbdd_downs_entries;
2277 		    i++, ke++) {
2278 			/* Keycode already down? */
2279 			if (ke->key_station == key_station) {
2280 #ifdef	KBD_DEBUG
2281 	printf("kbd: Double entry in downs table (%d,%d)!\n", key_station, i);
2282 #endif
2283 				goto add_event;
2284 			}
2285 			if (ke->key_station == 0)
2286 				ke_free = ke;
2287 		}
2288 		if (ke_free) {
2289 			ke = ke_free;
2290 			goto add_event;
2291 		}
2292 		cmn_err(CE_WARN, "kbd: Too many keys down!");
2293 		ke = kbdd->kbdd_downs;
2294 	}
2295 add_event:
2296 	ke->key_station = key_station;
2297 	ke->event = *fe;
2298 	kbdqueueevent(kbdd, fe);
2299 }
2300 
2301 static void
kbdkeyreleased(register struct kbddata * kbdd,uchar_t key_station)2302 kbdkeyreleased(register struct kbddata *kbdd, uchar_t key_station)
2303 {
2304 	register struct key_event *ke;
2305 	register int i;
2306 
2307 	if (key_station == IDLEKEY)
2308 		return;
2309 #ifdef	KBD_DEBUG
2310 	if (kbd_input_debug)
2311 		printf("KBD RELEASE key=%d\n", key_station);
2312 #endif
2313 	if (kbdd->kbdd_translate != TR_EVENT &&
2314 	    kbdd->kbdd_translate != TR_UNTRANS_EVENT)
2315 		return;
2316 	/* Scan table of down key stations */
2317 	for (i = 0, ke = kbdd->kbdd_downs;
2318 	    i < kbdd->kbdd_downs_entries;
2319 	    i++, ke++) {
2320 		/* Found? */
2321 		if (ke->key_station == key_station) {
2322 			ke->key_station = 0;
2323 			ke->event.value = 0;
2324 			kbdqueueevent(kbdd, &ke->event);
2325 		}
2326 	}
2327 
2328 	/*
2329 	 * Ignore if couldn't find because may be called twice
2330 	 * for the same key station in the case of the kbdrpt
2331 	 * routine being called unnecessarily.
2332 	 */
2333 }
2334 
2335 static void
kbdreleaseall(struct kbddata * kbdd)2336 kbdreleaseall(struct kbddata *kbdd)
2337 {
2338 	register struct key_event *ke;
2339 	register int i;
2340 
2341 #ifdef	KBD_DEBUG
2342 	if (kbd_debug && kbd_ra_debug) printf("KBD RELEASE ALL\n");
2343 #endif
2344 	/* Scan table of down key stations */
2345 	for (i = 0, ke = kbdd->kbdd_downs;
2346 	    i < kbdd->kbdd_downs_entries; i++, ke++) {
2347 		/* Key station not zero */
2348 		if (ke->key_station)
2349 			kbdkeyreleased(kbdd, ke->key_station);
2350 			/* kbdkeyreleased resets kbdd_downs entry */
2351 	}
2352 }
2353 
2354 /*
2355  * Pass a keycode up the stream, if you can, otherwise throw it away.
2356  */
2357 static void
kbdputcode(uint_t code,queue_t * q)2358 kbdputcode(uint_t code, queue_t *q)
2359 {
2360 	register mblk_t *bp;
2361 
2362 	if (!canput(q))
2363 		cmn_err(CE_WARN, "kbdputcode: Can't put block for keycode");
2364 	else {
2365 		if ((bp = allocb(sizeof (uint_t), BPRI_HI)) == NULL)
2366 			cmn_err(CE_WARN,
2367 			    "kbdputcode: Can't allocate block for keycode");
2368 		else {
2369 			*bp->b_wptr++ = code;
2370 			putnext(q, bp);
2371 		}
2372 	}
2373 }
2374 
2375 /*
2376  * Pass  generated keycode sequence to upstream, if possible.
2377  */
2378 static void
kbdputbuf(char * buf,queue_t * q)2379 kbdputbuf(char *buf, queue_t *q)
2380 {
2381 	register mblk_t *bp;
2382 
2383 	if (!canput(q))
2384 		cmn_err(CE_WARN, "kbdputbuf: Can't put block for keycode");
2385 	else {
2386 		if ((bp = allocb((int)strlen(buf), BPRI_HI)) == NULL)
2387 			cmn_err(CE_WARN,
2388 			    "kbdputbuf: Can't allocate block for keycode");
2389 		else {
2390 			while (*buf) {
2391 				*bp->b_wptr++ = *buf;
2392 				buf++;
2393 			}
2394 			putnext(q, bp);
2395 		}
2396 	}
2397 }
2398 
2399 /*
2400  * Pass a VUID "firm event" up the stream, if you can.
2401  */
2402 static void
kbdqueueevent(struct kbddata * kbdd,Firm_event * fe)2403 kbdqueueevent(struct kbddata *kbdd, Firm_event *fe)
2404 {
2405 	register queue_t *q;
2406 	register mblk_t *bp;
2407 
2408 	if ((q = kbdd->kbdd_readq) == NULL)
2409 		return;
2410 	if (!canput(q)) {
2411 		if (kbd_overflow_msg)
2412 			cmn_err(CE_WARN,
2413 			    "kbd: Buffer flushed when overflowed");
2414 		kbdflush(kbdd);
2415 		kbd_overflow_cnt++;
2416 	} else {
2417 		if ((bp = allocb(sizeof (Firm_event), BPRI_HI)) == NULL)
2418 			cmn_err(CE_WARN,
2419 			    "kbdqueueevent: Can't allocate block for event");
2420 		else {
2421 #if 1 /* XX64 */
2422 			struct timeval now;
2423 
2424 			/*
2425 			 * XX64: This is something of a compromise.  It
2426 			 * seems justifiable based on the usage of these
2427 			 * timestamps as an ordering relation as opposed
2428 			 * to a strict timing thing.
2429 			 *
2430 			 * But should we restore Firm_event's time stamp
2431 			 * to be a timeval, and send 32-bit and 64-bit
2432 			 * events up the pipe?
2433 			 */
2434 			uniqtime(&now);
2435 			TIMEVAL_TO_TIMEVAL32(&fe->time, &now);
2436 #else
2437 			uniqtime(&fe->time);
2438 #endif
2439 			*(Firm_event *)bp->b_wptr = *fe;
2440 			bp->b_wptr += sizeof (Firm_event);
2441 			putnext(q, bp);
2442 		}
2443 	}
2444 }
2445