1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * Generic Keyboard Support: Polled I/O support for kbtrans-supported keyboards.
29*7c478bd9Sstevel@tonic-gate  */
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #define	KEYMAP_SIZE_VARIABLE
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/kbd.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/kbio.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/consdev.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/kbtrans.h>
40*7c478bd9Sstevel@tonic-gate #include "kbtrans_lower.h"
41*7c478bd9Sstevel@tonic-gate #include "kbtrans_streams.h"
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate /*
44*7c478bd9Sstevel@tonic-gate  * Internal Function Prototypes
45*7c478bd9Sstevel@tonic-gate  */
46*7c478bd9Sstevel@tonic-gate static void kbtrans_polled_pressed(struct kbtrans *, uint_t, kbtrans_key_t,
47*7c478bd9Sstevel@tonic-gate 			uint_t);
48*7c478bd9Sstevel@tonic-gate static void kbtrans_polled_released(struct kbtrans *, kbtrans_key_t);
49*7c478bd9Sstevel@tonic-gate static void kbtrans_polled_setled(struct kbtrans *);
50*7c478bd9Sstevel@tonic-gate static void kbtrans_polled_setup_repeat(struct kbtrans *, uint_t,
51*7c478bd9Sstevel@tonic-gate 			kbtrans_key_t);
52*7c478bd9Sstevel@tonic-gate static void kbtrans_polled_cancel_repeat(struct kbtrans *);
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /*
55*7c478bd9Sstevel@tonic-gate  * Functions to be called when a key is translated during polled
56*7c478bd9Sstevel@tonic-gate  * mode
57*7c478bd9Sstevel@tonic-gate  */
58*7c478bd9Sstevel@tonic-gate struct keyboard_callback kbtrans_polled_callbacks = {
59*7c478bd9Sstevel@tonic-gate 	NULL,				/* keypressed_raw */
60*7c478bd9Sstevel@tonic-gate 	NULL,				/* keyreleased_raw */
61*7c478bd9Sstevel@tonic-gate 	kbtrans_polled_pressed,		/* keypressed */
62*7c478bd9Sstevel@tonic-gate 	kbtrans_polled_released,	/* keyreleased */
63*7c478bd9Sstevel@tonic-gate 	kbtrans_polled_setup_repeat,	/* setup_repeat */
64*7c478bd9Sstevel@tonic-gate 	kbtrans_polled_cancel_repeat,	/* cancel_repeat */
65*7c478bd9Sstevel@tonic-gate 	kbtrans_polled_setled,		/* setled */
66*7c478bd9Sstevel@tonic-gate };
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate /*
69*7c478bd9Sstevel@tonic-gate  * kbtrans_ischar:
70*7c478bd9Sstevel@tonic-gate  *	Return B_TRUE if character is pending, else return B_FALSE
71*7c478bd9Sstevel@tonic-gate  */
72*7c478bd9Sstevel@tonic-gate boolean_t
kbtrans_ischar(struct kbtrans * upper)73*7c478bd9Sstevel@tonic-gate kbtrans_ischar(struct kbtrans *upper)
74*7c478bd9Sstevel@tonic-gate {
75*7c478bd9Sstevel@tonic-gate 	struct kbtrans_callbacks *cb;
76*7c478bd9Sstevel@tonic-gate 	struct kbtrans_hardware *hw;
77*7c478bd9Sstevel@tonic-gate 	kbtrans_key_t key;
78*7c478bd9Sstevel@tonic-gate 	enum keystate state;
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate 	/*
81*7c478bd9Sstevel@tonic-gate 	 * If we've still got input pending, say so.
82*7c478bd9Sstevel@tonic-gate 	 */
83*7c478bd9Sstevel@tonic-gate 	if (*upper->kbtrans_polled_pending_chars != '\0') {
84*7c478bd9Sstevel@tonic-gate 		return (B_TRUE);
85*7c478bd9Sstevel@tonic-gate 	}
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	/*
88*7c478bd9Sstevel@tonic-gate 	 * Reset to an empty buffer.
89*7c478bd9Sstevel@tonic-gate 	 */
90*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_polled_buf[0] = '\0';
91*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_polled_pending_chars = upper->kbtrans_polled_buf;
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 	cb = upper->kbtrans_streams_hw_callbacks;
94*7c478bd9Sstevel@tonic-gate 	hw = upper->kbtrans_streams_hw;
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 	/*
97*7c478bd9Sstevel@tonic-gate 	 * Process scancodes until either we have input ready
98*7c478bd9Sstevel@tonic-gate 	 * or we run out of scancodes.
99*7c478bd9Sstevel@tonic-gate 	 */
100*7c478bd9Sstevel@tonic-gate 	while (cb->kbtrans_polled_keycheck(hw, &key, &state)) {
101*7c478bd9Sstevel@tonic-gate 		kbtrans_processkey(&upper->kbtrans_lower,
102*7c478bd9Sstevel@tonic-gate 			&kbtrans_polled_callbacks, key, state);
103*7c478bd9Sstevel@tonic-gate 		/*
104*7c478bd9Sstevel@tonic-gate 		 * If that generated any input, we're ready.
105*7c478bd9Sstevel@tonic-gate 		 */
106*7c478bd9Sstevel@tonic-gate 		if (*upper->kbtrans_polled_pending_chars != '\0') {
107*7c478bd9Sstevel@tonic-gate 			return (B_TRUE);
108*7c478bd9Sstevel@tonic-gate 		}
109*7c478bd9Sstevel@tonic-gate 	}
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 	return (B_FALSE);
112*7c478bd9Sstevel@tonic-gate }
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate /*
115*7c478bd9Sstevel@tonic-gate  * kbtrans_getchar:
116*7c478bd9Sstevel@tonic-gate  * 	Return a character
117*7c478bd9Sstevel@tonic-gate  */
118*7c478bd9Sstevel@tonic-gate int
kbtrans_getchar(struct kbtrans * upper)119*7c478bd9Sstevel@tonic-gate kbtrans_getchar(struct kbtrans *upper)
120*7c478bd9Sstevel@tonic-gate {
121*7c478bd9Sstevel@tonic-gate 	while (!kbtrans_ischar(upper))
122*7c478bd9Sstevel@tonic-gate 		/* LOOP */;
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate 	return (*upper->kbtrans_polled_pending_chars++);
125*7c478bd9Sstevel@tonic-gate }
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate void
kbtrans_polled_putcode(struct kbtrans * upper,char code)128*7c478bd9Sstevel@tonic-gate kbtrans_polled_putcode(struct kbtrans *upper, char code)
129*7c478bd9Sstevel@tonic-gate {
130*7c478bd9Sstevel@tonic-gate 	int i;
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	/*
133*7c478bd9Sstevel@tonic-gate 	 * NB:  KBTRANS_POLLED_BUF_SIZE is one smaller than
134*7c478bd9Sstevel@tonic-gate 	 * the size of the buffer, to allow for a trailing
135*7c478bd9Sstevel@tonic-gate 	 * null.
136*7c478bd9Sstevel@tonic-gate 	 */
137*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < KBTRANS_POLLED_BUF_SIZE; i++) {
138*7c478bd9Sstevel@tonic-gate 		if (upper->kbtrans_polled_buf[i] == '\0') {
139*7c478bd9Sstevel@tonic-gate 			upper->kbtrans_polled_buf[i] = code;
140*7c478bd9Sstevel@tonic-gate 			upper->kbtrans_polled_buf[i+1] = '\0';
141*7c478bd9Sstevel@tonic-gate 			return;
142*7c478bd9Sstevel@tonic-gate 		}
143*7c478bd9Sstevel@tonic-gate 	}
144*7c478bd9Sstevel@tonic-gate 	DPRINTF(PRINT_L2, PRINT_MASK_PACKET,
145*7c478bd9Sstevel@tonic-gate 		(upper, "kbtrans_polled_pressed:  "
146*7c478bd9Sstevel@tonic-gate 		"buffer overflow, character 0x%x discarded\n", code));
147*7c478bd9Sstevel@tonic-gate 	/*
148*7c478bd9Sstevel@tonic-gate 	 * Didn't fit, throw it on the floor.
149*7c478bd9Sstevel@tonic-gate 	 */
150*7c478bd9Sstevel@tonic-gate }
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate /*
153*7c478bd9Sstevel@tonic-gate  * kbtrans_polled_pressed:
154*7c478bd9Sstevel@tonic-gate  *	This function is called when we are in polled mode and a key is
155*7c478bd9Sstevel@tonic-gate  * 	pressed.  The key is put into the kbtrans_polled_buf so that it
156*7c478bd9Sstevel@tonic-gate  * 	can be picked up later by kbtrans_ischar()
157*7c478bd9Sstevel@tonic-gate  */
158*7c478bd9Sstevel@tonic-gate /*ARGSUSED2*/
159*7c478bd9Sstevel@tonic-gate static void
kbtrans_polled_pressed(struct kbtrans * upper,uint_t entrytype,kbtrans_key_t key,uint_t entry)160*7c478bd9Sstevel@tonic-gate kbtrans_polled_pressed(
161*7c478bd9Sstevel@tonic-gate     struct kbtrans *upper,
162*7c478bd9Sstevel@tonic-gate     uint_t entrytype,
163*7c478bd9Sstevel@tonic-gate     kbtrans_key_t key,
164*7c478bd9Sstevel@tonic-gate     uint_t entry)
165*7c478bd9Sstevel@tonic-gate {
166*7c478bd9Sstevel@tonic-gate 	struct kbtrans_lower	*lower = &upper->kbtrans_lower;
167*7c478bd9Sstevel@tonic-gate 	register char	*cp;
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	/*
170*7c478bd9Sstevel@tonic-gate 	 * Based on the type of key, we may need to do some ASCII
171*7c478bd9Sstevel@tonic-gate 	 * specific post processing.
172*7c478bd9Sstevel@tonic-gate 	 */
173*7c478bd9Sstevel@tonic-gate 	switch (entrytype) {
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	case BUCKYBITS:
176*7c478bd9Sstevel@tonic-gate 	case SHIFTKEYS:
177*7c478bd9Sstevel@tonic-gate 	case FUNNY:
178*7c478bd9Sstevel@tonic-gate 		/*
179*7c478bd9Sstevel@tonic-gate 		 * There is no ascii equivalent.  We will ignore these
180*7c478bd9Sstevel@tonic-gate 		 * keys
181*7c478bd9Sstevel@tonic-gate 		 */
182*7c478bd9Sstevel@tonic-gate 		break;
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 	case FUNCKEYS:
185*7c478bd9Sstevel@tonic-gate 		/*
186*7c478bd9Sstevel@tonic-gate 		 * These will no doubt only cause problems.  Ignore them.
187*7c478bd9Sstevel@tonic-gate 		 */
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 		break;
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 	case STRING:
192*7c478bd9Sstevel@tonic-gate 		/*
193*7c478bd9Sstevel@tonic-gate 		 * These are the multi byte keys (Home, Up, Down ...)
194*7c478bd9Sstevel@tonic-gate 		 */
195*7c478bd9Sstevel@tonic-gate 		cp = &lower->kbtrans_keystringtab[entry & 0x0F][0];
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate 		/*
198*7c478bd9Sstevel@tonic-gate 		 * Copy the string from the keystringtable, and send it
199*7c478bd9Sstevel@tonic-gate 		 * upstream a character at a time.
200*7c478bd9Sstevel@tonic-gate 		 */
201*7c478bd9Sstevel@tonic-gate 		while (*cp != '\0') {
202*7c478bd9Sstevel@tonic-gate 			kbtrans_polled_putcode(upper, *cp);
203*7c478bd9Sstevel@tonic-gate 			cp++;
204*7c478bd9Sstevel@tonic-gate 		}
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 		return;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	case PADKEYS:
209*7c478bd9Sstevel@tonic-gate 		/*
210*7c478bd9Sstevel@tonic-gate 		 * These are the keys on the keypad.  Look up the
211*7c478bd9Sstevel@tonic-gate 		 * answer in the kb_numlock_table and send it upstream.
212*7c478bd9Sstevel@tonic-gate 		 */
213*7c478bd9Sstevel@tonic-gate 		kbtrans_polled_putcode(upper,
214*7c478bd9Sstevel@tonic-gate 			lower->kbtrans_numlock_table[entry&0x1F]);
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 		break;
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate 	case 0:	/* normal character */
219*7c478bd9Sstevel@tonic-gate 	default:
220*7c478bd9Sstevel@tonic-gate 		/*
221*7c478bd9Sstevel@tonic-gate 		 * Send the byte upstream.
222*7c478bd9Sstevel@tonic-gate 		 */
223*7c478bd9Sstevel@tonic-gate 		kbtrans_polled_putcode(upper, (char)entry);
224*7c478bd9Sstevel@tonic-gate 		break;
225*7c478bd9Sstevel@tonic-gate 	}
226*7c478bd9Sstevel@tonic-gate }
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate /*
229*7c478bd9Sstevel@tonic-gate  * kbtrans_polled_released:
230*7c478bd9Sstevel@tonic-gate  *	This function is called when a key is released.  Nothing is
231*7c478bd9Sstevel@tonic-gate  * 	done.
232*7c478bd9Sstevel@tonic-gate  */
233*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
234*7c478bd9Sstevel@tonic-gate static void
kbtrans_polled_released(struct kbtrans * upper,kbtrans_key_t key)235*7c478bd9Sstevel@tonic-gate kbtrans_polled_released(struct kbtrans *upper, kbtrans_key_t key)
236*7c478bd9Sstevel@tonic-gate {
237*7c478bd9Sstevel@tonic-gate 	/* Nothing for now */
238*7c478bd9Sstevel@tonic-gate }
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate /*
241*7c478bd9Sstevel@tonic-gate  * kbtrans_polled_setled:
242*7c478bd9Sstevel@tonic-gate  *	This function is called to set the LEDs.
243*7c478bd9Sstevel@tonic-gate  */
244*7c478bd9Sstevel@tonic-gate static void
kbtrans_polled_setled(struct kbtrans * upper)245*7c478bd9Sstevel@tonic-gate kbtrans_polled_setled(struct kbtrans *upper)
246*7c478bd9Sstevel@tonic-gate {
247*7c478bd9Sstevel@tonic-gate 	struct kbtrans_callbacks *cb;
248*7c478bd9Sstevel@tonic-gate 	struct kbtrans_hardware *hw;
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	cb = upper->kbtrans_streams_hw_callbacks;
251*7c478bd9Sstevel@tonic-gate 	hw = upper->kbtrans_streams_hw;
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 	cb->kbtrans_polled_setled(hw, upper->kbtrans_lower.kbtrans_led_state);
254*7c478bd9Sstevel@tonic-gate }
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate /*
257*7c478bd9Sstevel@tonic-gate  * kbtrans_polled_setup_repeat:
258*7c478bd9Sstevel@tonic-gate  *	Function to be called in order to handle a repeating key.
259*7c478bd9Sstevel@tonic-gate  *	Nothing is done.
260*7c478bd9Sstevel@tonic-gate  */
261*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
262*7c478bd9Sstevel@tonic-gate static void
kbtrans_polled_setup_repeat(struct kbtrans * upper,uint_t entrytype,kbtrans_key_t key)263*7c478bd9Sstevel@tonic-gate kbtrans_polled_setup_repeat(
264*7c478bd9Sstevel@tonic-gate     struct kbtrans *upper,
265*7c478bd9Sstevel@tonic-gate     uint_t entrytype,
266*7c478bd9Sstevel@tonic-gate     kbtrans_key_t key)
267*7c478bd9Sstevel@tonic-gate {
268*7c478bd9Sstevel@tonic-gate 	/* Nothing for now */
269*7c478bd9Sstevel@tonic-gate }
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate /*
272*7c478bd9Sstevel@tonic-gate  * kbtrans_polled_cancel_repeat:
273*7c478bd9Sstevel@tonic-gate  *	Function to be called to cancel a repeating key,
274*7c478bd9Sstevel@tonic-gate  *	so that we don't end up with an autorepeating key
275*7c478bd9Sstevel@tonic-gate  * 	on the stream because its release was handled by the
276*7c478bd9Sstevel@tonic-gate  * 	polled code.
277*7c478bd9Sstevel@tonic-gate  */
278*7c478bd9Sstevel@tonic-gate static void
kbtrans_polled_cancel_repeat(struct kbtrans * upper)279*7c478bd9Sstevel@tonic-gate kbtrans_polled_cancel_repeat(struct kbtrans *upper)
280*7c478bd9Sstevel@tonic-gate {
281*7c478bd9Sstevel@tonic-gate 	/*
282*7c478bd9Sstevel@tonic-gate 	 * Streams code will time out and will discard the
283*7c478bd9Sstevel@tonic-gate 	 * autorepeat.
284*7c478bd9Sstevel@tonic-gate 	 */
285*7c478bd9Sstevel@tonic-gate 	upper->kbtrans_lower.kbtrans_repeatkey = 0;
286*7c478bd9Sstevel@tonic-gate }
287