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