allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / cfe / cfe / pccons / kbd_subr.c
blob860db94d1db85d5078ad3a315c74c441efb92bb7
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * PC-style keyboard interface File: KBD_SUBR.C
5 *
6 * This module converts a stream of scancodes into ASCII
7 * characters. The scan codes come from a PC-style
8 * keyboard.
9 *
10 * Author: Mitch Lichtenberg (mpl@broadcom.com)
12 *********************************************************************
14 * Copyright 2000,2001,2002,2003
15 * Broadcom Corporation. All rights reserved.
17 * This software is furnished under license and may be used and
18 * copied only in accordance with the following terms and
19 * conditions. Subject to these conditions, you may download,
20 * copy, install, use, modify and distribute modified or unmodified
21 * copies of this software in source and/or binary form. No title
22 * or ownership is transferred hereby.
24 * 1) Any source code used, modified or distributed must reproduce
25 * and retain this copyright notice and list of conditions
26 * as they appear in the source file.
28 * 2) No right is granted to use any trade name, trademark, or
29 * logo of Broadcom Corporation. The "Broadcom Corporation"
30 * name may not be used to endorse or promote products derived
31 * from this software without the prior written permission of
32 * Broadcom Corporation.
34 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
35 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
36 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
38 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
39 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
40 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
45 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
46 * THE POSSIBILITY OF SUCH DAMAGE.
47 ********************************************************************* */
50 #include "lib_types.h"
51 #include "lib_string.h"
53 #include "kbd_subr.h"
56 /* *********************************************************************
57 * Constants
58 ********************************************************************* */
60 #define FLG_SCROLL 0x0001 /* Toggles: same as bit positions for LEDs! */
61 #define FLG_NUM 0x0002
62 #define FLG_CAPS 0x0004
63 #define FLG_SHIFT 0x0008 /* Shifts */
64 #define FLG_CTRL 0x0100
65 #define FLG_ALT 0x0200
66 #define FLG_FKEY 0x0400 /* function keys */
67 #define FLG_NKPD 0x0800 /* numeric keypad */
68 #define FLG_ASCII 0x1000 /* regular ASCII character */
69 #define FLG_NONE 0x2000
70 #define FLG_BREAKBIT 0x80
73 /* *********************************************************************
74 * Structures
75 ********************************************************************* */
77 #define KC_RESPLEN 4
78 typedef struct keycode_s {
79 int kc_type;
80 char kc_normal[KC_RESPLEN];
81 char kc_shifted[KC_RESPLEN];
82 char kc_ctrl[KC_RESPLEN];
83 } keycode_t;
86 /* *********************************************************************
87 * Scan code conversion table
88 ********************************************************************* */
90 static keycode_t scantable[] = {
91 { FLG_NONE, "", "", "" }, /* 0 */
92 { FLG_ASCII, "\033", "\033", "\033" }, /* 1 ESC */
93 { FLG_ASCII, "1", "!", "!" }, /* 2 1 */
94 { FLG_ASCII, "2", "@", "\000" }, /* 3 2 */
95 { FLG_ASCII, "3", "#", "#" }, /* 4 3 */
96 { FLG_ASCII, "4", "$", "$" }, /* 5 4 */
97 { FLG_ASCII, "5", "%", "%" }, /* 6 5 */
98 { FLG_ASCII, "6", "^", "\036" }, /* 7 6 */
99 { FLG_ASCII, "7", "&", "&" }, /* 8 7 */
100 { FLG_ASCII, "8", "*", "\010" }, /* 9 8 */
101 { FLG_ASCII, "9", "(", "(" }, /* 10 9 */
102 { FLG_ASCII, "0", ")", ")" }, /* 11 0 */
103 { FLG_ASCII, "-", "_", "\037" }, /* 12 - */
104 { FLG_ASCII, "=", "+", "+" }, /* 13 = */
105 { FLG_ASCII, "\177", "\177", "\010" }, /* 14 <- */
106 { FLG_ASCII, "\t", "\177\t", "\t" }, /* 15 ->| */
107 { FLG_ASCII, "q", "Q", "\021" }, /* 16 q */
108 { FLG_ASCII, "w", "W", "\027" }, /* 17 w */
109 { FLG_ASCII, "e", "E", "\005" }, /* 18 e */
110 { FLG_ASCII, "r", "R", "\022" }, /* 19 r */
111 { FLG_ASCII, "t", "T", "\024" }, /* 20 t */
112 { FLG_ASCII, "y", "Y", "\031" }, /* 21 y */
113 { FLG_ASCII, "u", "U", "\025" }, /* 22 u */
114 { FLG_ASCII, "i", "I", "\011" }, /* 23 i */
115 { FLG_ASCII, "o", "O", "\017" }, /* 24 o */
116 { FLG_ASCII, "p", "P", "\020" }, /* 25 p */
117 { FLG_ASCII, "[", "{", "\033" }, /* 26 [ */
118 { FLG_ASCII, "]", "}", "\035" }, /* 27 ] */
119 { FLG_ASCII, "\r", "\r", "\n" }, /* 28 ENT */
120 { FLG_CTRL, "", "", "" }, /* 29 CTRL */
121 { FLG_ASCII, "a", "A", "\001" }, /* 30 a */
122 { FLG_ASCII, "s", "S", "\023" }, /* 31 s */
123 { FLG_ASCII, "d", "D", "\004" }, /* 32 d */
124 { FLG_ASCII, "f", "F", "\006" }, /* 33 f */
125 { FLG_ASCII, "g", "G", "\007" }, /* 34 g */
126 { FLG_ASCII, "h", "H", "\010" }, /* 35 h */
127 { FLG_ASCII, "j", "J", "\n" }, /* 36 j */
128 { FLG_ASCII, "k", "K", "\013" }, /* 37 k */
129 { FLG_ASCII, "l", "L", "\014" }, /* 38 l */
130 { FLG_ASCII, ";", ":", ";" }, /* 39 ; */
131 { FLG_ASCII, "'", "\"", "'" }, /* 40 ' */
132 { FLG_ASCII, "`", "~", "`" }, /* 41 ` */
133 { FLG_SHIFT, "", "", "" }, /* 42 SHIFT */
134 { FLG_ASCII, "\\", "|", "\034" }, /* 43 \ */
135 { FLG_ASCII, "z", "Z", "\032" }, /* 44 z */
136 { FLG_ASCII, "x", "X", "\030" }, /* 45 x */
137 { FLG_ASCII, "c", "C", "\003" }, /* 46 c */
138 { FLG_ASCII, "v", "V", "\026" }, /* 47 v */
139 { FLG_ASCII, "b", "B", "\002" }, /* 48 b */
140 { FLG_ASCII, "n", "N", "\016" }, /* 49 n */
141 { FLG_ASCII, "m", "M", "\r" }, /* 50 m */
142 { FLG_ASCII, ",", "<", "<" }, /* 51 , */
143 { FLG_ASCII, ".", ">", ">" }, /* 52 . */
144 { FLG_ASCII, "/", "?", "\037" }, /* 53 / */
145 { FLG_SHIFT, "", "", "" }, /* 54 SHIFT */
146 { FLG_NKPD, "*", "*", "*" }, /* 55 KP* */
147 { FLG_ALT, "", "", "" }, /* 56 ALT */
148 { FLG_ASCII, " ", " ", "\000" }, /* 57 SPC */
149 { FLG_CAPS, "", "", "" }, /* 58 CAPS */
150 { FLG_FKEY, "\033[M", "\033[Y", "\033[k" }, /* 59 f1 */
151 { FLG_FKEY, "\033[N", "\033[Z", "\033[l" }, /* 60 f2 */
152 { FLG_FKEY, "\033[O", "\033[a", "\033[m" }, /* 61 f3 */
153 { FLG_FKEY, "\033[P", "\033[b", "\033[n" }, /* 62 f4 */
154 { FLG_FKEY, "\033[Q", "\033[c", "\033[o" }, /* 63 f5 */
155 { FLG_FKEY, "\033[R", "\033[d", "\033[p" }, /* 64 f6 */
156 { FLG_FKEY, "\033[S", "\033[e", "\033[q" }, /* 65 f7 */
157 { FLG_FKEY, "\033[T", "\033[f", "\033[r" }, /* 66 f8 */
158 { FLG_FKEY, "\033[U", "\033[g", "\033[s" }, /* 67 f9 */
159 { FLG_FKEY, "\033[V", "\033[h", "\033[t" }, /* 68 f10 */
160 { FLG_NUM, "", "", "" }, /* 69 NUMLK */
161 { FLG_SCROLL, "", "", "" }, /* 70 SCRLK */
162 { FLG_NKPD, "7", "\033[H", "7" }, /* 71 KP7 */
163 { FLG_NKPD, "8", "\033[A", "8" }, /* 72 KP8 */
164 { FLG_NKPD, "9", "\033[I", "9" }, /* 73 KP9 */
165 { FLG_NKPD, "-", "-", "-" }, /* 74 KP- */
166 { FLG_NKPD, "4", "\033[D", "4" }, /* 75 KP4 */
167 { FLG_NKPD, "5", "\033[E", "5" }, /* 76 KP5 */
168 { FLG_NKPD, "6", "\033[C", "6" }, /* 77 KP6 */
169 { FLG_NKPD, "+", "+", "+" }, /* 78 KP+ */
170 { FLG_NKPD, "1", "\033[F", "1" }, /* 79 KP1 */
171 { FLG_NKPD, "2", "\033[B", "2" }, /* 80 KP2 */
172 { FLG_NKPD, "3", "\033[G", "3" }, /* 81 KP3 */
173 { FLG_NKPD, "0", "\033[L", "0" }, /* 82 KP0 */
174 { FLG_NKPD, ".", "\177", "." }, /* 83 KP. */
175 { FLG_NONE, "", "", "" }, /* 84 0 */
176 { FLG_NONE, "100", "", "" }, /* 85 0 */
177 { FLG_NONE, "101", "", "" }, /* 86 0 */
178 { FLG_FKEY, "\033[W", "\033[i", "\033[u" }, /* 87 f11 */
179 { FLG_FKEY, "\033[X", "\033[j", "\033[v" }, /* 88 f12 */
180 { FLG_NONE, "102", "", "" }, /* 89 0 */
181 { FLG_NONE, "103", "", "" }, /* 90 0 */
182 { FLG_NONE, "", "", "" }, /* 91 0 */
183 { FLG_NONE, "", "", "" }, /* 92 0 */
184 { FLG_NONE, "", "", "" }, /* 93 0 */
185 { FLG_NONE, "", "", "" }, /* 94 0 */
186 { FLG_NONE, "", "", "" }, /* 95 0 */
187 { FLG_NONE, "", "", "" }, /* 96 0 */
188 { FLG_NONE, "", "", "" }, /* 97 0 */
189 { FLG_NONE, "", "", "" }, /* 98 0 */
190 { FLG_NONE, "", "", "" }, /* 99 0 */
191 { FLG_NONE, "", "", "" }, /* 100 */
192 { FLG_NONE, "", "", "" }, /* 101 */
193 { FLG_NONE, "", "", "" }, /* 102 */
194 { FLG_NONE, "", "", "" }, /* 103 */
195 { FLG_NONE, "", "", "" }, /* 104 */
196 { FLG_NONE, "", "", "" }, /* 105 */
197 { FLG_NONE, "", "", "" }, /* 106 */
198 { FLG_NONE, "", "", "" }, /* 107 */
199 { FLG_NONE, "", "", "" }, /* 108 */
200 { FLG_NONE, "", "", "" }, /* 109 */
201 { FLG_NONE, "", "", "" }, /* 110 */
202 { FLG_NONE, "", "", "" }, /* 111 */
203 { FLG_NONE, "", "", "" }, /* 112 */
204 { FLG_NONE, "", "", "" }, /* 113 */
205 { FLG_NONE, "", "", "" }, /* 114 */
206 { FLG_NONE, "", "", "" }, /* 115 */
207 { FLG_NONE, "", "", "" }, /* 116 */
208 { FLG_NONE, "", "", "" }, /* 117 */
209 { FLG_NONE, "", "", "" }, /* 118 */
210 { FLG_NONE, "", "", "" }, /* 119 */
211 { FLG_NONE, "", "", "" }, /* 120 */
212 { FLG_NONE, "", "", "" }, /* 121 */
213 { FLG_NONE, "", "", "" }, /* 122 */
214 { FLG_NONE, "", "", "" }, /* 123 */
215 { FLG_NONE, "", "", "" }, /* 124 */
216 { FLG_NONE, "", "", "" }, /* 125 */
217 { FLG_NONE, "", "", "" }, /* 126 */
218 { FLG_NONE, "", "", "" }, /* 127 */
222 /* *********************************************************************
223 * KBD_ENQUEUECHAR(ks,ch)
225 * Put a character on the queue
227 * Input parameters:
228 * ks - keyboard state
229 * ch - character to enqueue
231 * Return value:
232 * nothing
233 ********************************************************************* */
235 static void kbd_enqueuechar(keystate_t *ks,char ch)
237 if (((ks->ks_head+1) & (KEYQUEUELEN-1)) == ks->ks_tail) {
238 /* queue is full */
239 return;
241 ks->ks_queue[ks->ks_head] = ch;
242 ks->ks_head = (ks->ks_head+1) & (KEYQUEUELEN-1);
246 /* *********************************************************************
247 * KBD_DEQUEUECHAR(ks)
249 * Remove a character from the queue
251 * Input parameters:
252 * ks - keystate
254 * Return value:
255 * 0 if no characters in queue
256 * else character from queue
257 ********************************************************************* */
258 static int kbd_dequeuechar(keystate_t *ks)
260 char ch;
262 if (ks->ks_head == ks->ks_tail) return 0;
264 ch = ks->ks_queue[ks->ks_tail];
265 ks->ks_tail = (ks->ks_tail+1) & (KEYQUEUELEN-1);
266 return ch;
269 /* *********************************************************************
270 * KBD_READ(ks)
272 * User call to kbd_dequeuechar - remove a character from
273 * the queue.
275 * Input parameters:
276 * ks - keyboard state
278 * Return value:
279 * character from queue or 0 if no chars
280 ********************************************************************* */
282 int kbd_read(keystate_t *ks)
284 return kbd_dequeuechar(ks);
287 /* *********************************************************************
288 * KBD_INPSTAT(ks)
290 * Test input status (see if a character is waiting)
292 * Input parameters:
293 * ks - keyboard state
295 * Return value:
296 * 0 if no chars waiting, 1 if characters are waiting
297 ********************************************************************* */
299 int kbd_inpstat(keystate_t *ks)
301 return (ks->ks_head != ks->ks_tail);
305 /* *********************************************************************
306 * KBD_DOSCAN(ks,scan)
308 * Process a scan code from the keyboard.
310 * Input parameters:
311 * ks - keyboard state
312 * scan - scan code from the keyboard
314 * Return value:
315 * nothing
316 ********************************************************************* */
318 void kbd_doscan(keystate_t *ks,uint8_t scan)
320 int breakflg;
321 keycode_t *code = 0;
322 char *str;
324 breakflg = (scan & FLG_BREAKBIT);
325 scan &= ~FLG_BREAKBIT;
326 code = &scantable[scan];
328 if (code->kc_type & (FLG_SHIFT|FLG_CTRL|FLG_ALT)) {
329 if (breakflg) ks->ks_shiftflags &= ~code->kc_type;
330 else ks->ks_shiftflags |= code->kc_type;
332 if (code->kc_type & (FLG_CAPS|FLG_SCROLL|FLG_NUM)) {
333 if (!breakflg) ks->ks_shiftflags ^= code->kc_type;
334 if (ks->ks_setleds) {
335 (*(ks->ks_setleds))(ks,ks->ks_shiftflags & (FLG_CAPS|FLG_SCROLL|FLG_NUM));
338 if (code->kc_type & (FLG_ASCII | FLG_FKEY | FLG_NKPD)) {
339 if (ks->ks_shiftflags & (FLG_SHIFT|FLG_CAPS)) str = code->kc_shifted;
340 else if (ks->ks_shiftflags & FLG_CTRL) str = code->kc_ctrl;
341 else str = code->kc_normal;
342 if (!breakflg) {
343 while (*str) {
344 kbd_enqueuechar(ks,*str++);
351 /* *********************************************************************
352 * KBD_INIT(ks,setleds,ref)
354 * Initialize a keyboard state object.
356 * Input parameters:
357 * ks - keyboard state
358 * setleds - routine to call when we want to set the state
359 * of the keyboard's LEDs
360 * ref - data to store in the keyboard state object
362 * Return value:
363 * nothing
364 ********************************************************************* */
366 void kbd_init(keystate_t *ks,int (*setleds)(keystate_t *,int),void *ref)
368 memset(ks,0,sizeof(keystate_t));
369 ks->ks_setleds = setleds;
370 ks->ks_ref = ref;