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