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