summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/pccons/kbd_subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/pccons/kbd_subr.c')
-rw-r--r--cfe/cfe/pccons/kbd_subr.c371
1 files changed, 371 insertions, 0 deletions
diff --git a/cfe/cfe/pccons/kbd_subr.c b/cfe/cfe/pccons/kbd_subr.c
new file mode 100644
index 0000000..860db94
--- /dev/null
+++ b/cfe/cfe/pccons/kbd_subr.c
@@ -0,0 +1,371 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * PC-style keyboard interface File: KBD_SUBR.C
+ *
+ * This module converts a stream of scancodes into ASCII
+ * characters. The scan codes come from a PC-style
+ * keyboard.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+
+#include "kbd_subr.h"
+
+
+/* *********************************************************************
+ * Constants
+ ********************************************************************* */
+
+#define FLG_SCROLL 0x0001 /* Toggles: same as bit positions for LEDs! */
+#define FLG_NUM 0x0002
+#define FLG_CAPS 0x0004
+#define FLG_SHIFT 0x0008 /* Shifts */
+#define FLG_CTRL 0x0100
+#define FLG_ALT 0x0200
+#define FLG_FKEY 0x0400 /* function keys */
+#define FLG_NKPD 0x0800 /* numeric keypad */
+#define FLG_ASCII 0x1000 /* regular ASCII character */
+#define FLG_NONE 0x2000
+#define FLG_BREAKBIT 0x80
+
+
+/* *********************************************************************
+ * Structures
+ ********************************************************************* */
+
+#define KC_RESPLEN 4
+typedef struct keycode_s {
+ int kc_type;
+ char kc_normal[KC_RESPLEN];
+ char kc_shifted[KC_RESPLEN];
+ char kc_ctrl[KC_RESPLEN];
+} keycode_t;
+
+
+/* *********************************************************************
+ * Scan code conversion table
+ ********************************************************************* */
+
+static keycode_t scantable[] = {
+ { FLG_NONE, "", "", "" }, /* 0 */
+ { FLG_ASCII, "\033", "\033", "\033" }, /* 1 ESC */
+ { FLG_ASCII, "1", "!", "!" }, /* 2 1 */
+ { FLG_ASCII, "2", "@", "\000" }, /* 3 2 */
+ { FLG_ASCII, "3", "#", "#" }, /* 4 3 */
+ { FLG_ASCII, "4", "$", "$" }, /* 5 4 */
+ { FLG_ASCII, "5", "%", "%" }, /* 6 5 */
+ { FLG_ASCII, "6", "^", "\036" }, /* 7 6 */
+ { FLG_ASCII, "7", "&", "&" }, /* 8 7 */
+ { FLG_ASCII, "8", "*", "\010" }, /* 9 8 */
+ { FLG_ASCII, "9", "(", "(" }, /* 10 9 */
+ { FLG_ASCII, "0", ")", ")" }, /* 11 0 */
+ { FLG_ASCII, "-", "_", "\037" }, /* 12 - */
+ { FLG_ASCII, "=", "+", "+" }, /* 13 = */
+ { FLG_ASCII, "\177", "\177", "\010" }, /* 14 <- */
+ { FLG_ASCII, "\t", "\177\t", "\t" }, /* 15 ->| */
+ { FLG_ASCII, "q", "Q", "\021" }, /* 16 q */
+ { FLG_ASCII, "w", "W", "\027" }, /* 17 w */
+ { FLG_ASCII, "e", "E", "\005" }, /* 18 e */
+ { FLG_ASCII, "r", "R", "\022" }, /* 19 r */
+ { FLG_ASCII, "t", "T", "\024" }, /* 20 t */
+ { FLG_ASCII, "y", "Y", "\031" }, /* 21 y */
+ { FLG_ASCII, "u", "U", "\025" }, /* 22 u */
+ { FLG_ASCII, "i", "I", "\011" }, /* 23 i */
+ { FLG_ASCII, "o", "O", "\017" }, /* 24 o */
+ { FLG_ASCII, "p", "P", "\020" }, /* 25 p */
+ { FLG_ASCII, "[", "{", "\033" }, /* 26 [ */
+ { FLG_ASCII, "]", "}", "\035" }, /* 27 ] */
+ { FLG_ASCII, "\r", "\r", "\n" }, /* 28 ENT */
+ { FLG_CTRL, "", "", "" }, /* 29 CTRL */
+ { FLG_ASCII, "a", "A", "\001" }, /* 30 a */
+ { FLG_ASCII, "s", "S", "\023" }, /* 31 s */
+ { FLG_ASCII, "d", "D", "\004" }, /* 32 d */
+ { FLG_ASCII, "f", "F", "\006" }, /* 33 f */
+ { FLG_ASCII, "g", "G", "\007" }, /* 34 g */
+ { FLG_ASCII, "h", "H", "\010" }, /* 35 h */
+ { FLG_ASCII, "j", "J", "\n" }, /* 36 j */
+ { FLG_ASCII, "k", "K", "\013" }, /* 37 k */
+ { FLG_ASCII, "l", "L", "\014" }, /* 38 l */
+ { FLG_ASCII, ";", ":", ";" }, /* 39 ; */
+ { FLG_ASCII, "'", "\"", "'" }, /* 40 ' */
+ { FLG_ASCII, "`", "~", "`" }, /* 41 ` */
+ { FLG_SHIFT, "", "", "" }, /* 42 SHIFT */
+ { FLG_ASCII, "\\", "|", "\034" }, /* 43 \ */
+ { FLG_ASCII, "z", "Z", "\032" }, /* 44 z */
+ { FLG_ASCII, "x", "X", "\030" }, /* 45 x */
+ { FLG_ASCII, "c", "C", "\003" }, /* 46 c */
+ { FLG_ASCII, "v", "V", "\026" }, /* 47 v */
+ { FLG_ASCII, "b", "B", "\002" }, /* 48 b */
+ { FLG_ASCII, "n", "N", "\016" }, /* 49 n */
+ { FLG_ASCII, "m", "M", "\r" }, /* 50 m */
+ { FLG_ASCII, ",", "<", "<" }, /* 51 , */
+ { FLG_ASCII, ".", ">", ">" }, /* 52 . */
+ { FLG_ASCII, "/", "?", "\037" }, /* 53 / */
+ { FLG_SHIFT, "", "", "" }, /* 54 SHIFT */
+ { FLG_NKPD, "*", "*", "*" }, /* 55 KP* */
+ { FLG_ALT, "", "", "" }, /* 56 ALT */
+ { FLG_ASCII, " ", " ", "\000" }, /* 57 SPC */
+ { FLG_CAPS, "", "", "" }, /* 58 CAPS */
+ { FLG_FKEY, "\033[M", "\033[Y", "\033[k" }, /* 59 f1 */
+ { FLG_FKEY, "\033[N", "\033[Z", "\033[l" }, /* 60 f2 */
+ { FLG_FKEY, "\033[O", "\033[a", "\033[m" }, /* 61 f3 */
+ { FLG_FKEY, "\033[P", "\033[b", "\033[n" }, /* 62 f4 */
+ { FLG_FKEY, "\033[Q", "\033[c", "\033[o" }, /* 63 f5 */
+ { FLG_FKEY, "\033[R", "\033[d", "\033[p" }, /* 64 f6 */
+ { FLG_FKEY, "\033[S", "\033[e", "\033[q" }, /* 65 f7 */
+ { FLG_FKEY, "\033[T", "\033[f", "\033[r" }, /* 66 f8 */
+ { FLG_FKEY, "\033[U", "\033[g", "\033[s" }, /* 67 f9 */
+ { FLG_FKEY, "\033[V", "\033[h", "\033[t" }, /* 68 f10 */
+ { FLG_NUM, "", "", "" }, /* 69 NUMLK */
+ { FLG_SCROLL, "", "", "" }, /* 70 SCRLK */
+ { FLG_NKPD, "7", "\033[H", "7" }, /* 71 KP7 */
+ { FLG_NKPD, "8", "\033[A", "8" }, /* 72 KP8 */
+ { FLG_NKPD, "9", "\033[I", "9" }, /* 73 KP9 */
+ { FLG_NKPD, "-", "-", "-" }, /* 74 KP- */
+ { FLG_NKPD, "4", "\033[D", "4" }, /* 75 KP4 */
+ { FLG_NKPD, "5", "\033[E", "5" }, /* 76 KP5 */
+ { FLG_NKPD, "6", "\033[C", "6" }, /* 77 KP6 */
+ { FLG_NKPD, "+", "+", "+" }, /* 78 KP+ */
+ { FLG_NKPD, "1", "\033[F", "1" }, /* 79 KP1 */
+ { FLG_NKPD, "2", "\033[B", "2" }, /* 80 KP2 */
+ { FLG_NKPD, "3", "\033[G", "3" }, /* 81 KP3 */
+ { FLG_NKPD, "0", "\033[L", "0" }, /* 82 KP0 */
+ { FLG_NKPD, ".", "\177", "." }, /* 83 KP. */
+ { FLG_NONE, "", "", "" }, /* 84 0 */
+ { FLG_NONE, "100", "", "" }, /* 85 0 */
+ { FLG_NONE, "101", "", "" }, /* 86 0 */
+ { FLG_FKEY, "\033[W", "\033[i", "\033[u" }, /* 87 f11 */
+ { FLG_FKEY, "\033[X", "\033[j", "\033[v" }, /* 88 f12 */
+ { FLG_NONE, "102", "", "" }, /* 89 0 */
+ { FLG_NONE, "103", "", "" }, /* 90 0 */
+ { FLG_NONE, "", "", "" }, /* 91 0 */
+ { FLG_NONE, "", "", "" }, /* 92 0 */
+ { FLG_NONE, "", "", "" }, /* 93 0 */
+ { FLG_NONE, "", "", "" }, /* 94 0 */
+ { FLG_NONE, "", "", "" }, /* 95 0 */
+ { FLG_NONE, "", "", "" }, /* 96 0 */
+ { FLG_NONE, "", "", "" }, /* 97 0 */
+ { FLG_NONE, "", "", "" }, /* 98 0 */
+ { FLG_NONE, "", "", "" }, /* 99 0 */
+ { FLG_NONE, "", "", "" }, /* 100 */
+ { FLG_NONE, "", "", "" }, /* 101 */
+ { FLG_NONE, "", "", "" }, /* 102 */
+ { FLG_NONE, "", "", "" }, /* 103 */
+ { FLG_NONE, "", "", "" }, /* 104 */
+ { FLG_NONE, "", "", "" }, /* 105 */
+ { FLG_NONE, "", "", "" }, /* 106 */
+ { FLG_NONE, "", "", "" }, /* 107 */
+ { FLG_NONE, "", "", "" }, /* 108 */
+ { FLG_NONE, "", "", "" }, /* 109 */
+ { FLG_NONE, "", "", "" }, /* 110 */
+ { FLG_NONE, "", "", "" }, /* 111 */
+ { FLG_NONE, "", "", "" }, /* 112 */
+ { FLG_NONE, "", "", "" }, /* 113 */
+ { FLG_NONE, "", "", "" }, /* 114 */
+ { FLG_NONE, "", "", "" }, /* 115 */
+ { FLG_NONE, "", "", "" }, /* 116 */
+ { FLG_NONE, "", "", "" }, /* 117 */
+ { FLG_NONE, "", "", "" }, /* 118 */
+ { FLG_NONE, "", "", "" }, /* 119 */
+ { FLG_NONE, "", "", "" }, /* 120 */
+ { FLG_NONE, "", "", "" }, /* 121 */
+ { FLG_NONE, "", "", "" }, /* 122 */
+ { FLG_NONE, "", "", "" }, /* 123 */
+ { FLG_NONE, "", "", "" }, /* 124 */
+ { FLG_NONE, "", "", "" }, /* 125 */
+ { FLG_NONE, "", "", "" }, /* 126 */
+ { FLG_NONE, "", "", "" }, /* 127 */
+};
+
+
+/* *********************************************************************
+ * KBD_ENQUEUECHAR(ks,ch)
+ *
+ * Put a character on the queue
+ *
+ * Input parameters:
+ * ks - keyboard state
+ * ch - character to enqueue
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+static void kbd_enqueuechar(keystate_t *ks,char ch)
+{
+ if (((ks->ks_head+1) & (KEYQUEUELEN-1)) == ks->ks_tail) {
+ /* queue is full */
+ return;
+ }
+ ks->ks_queue[ks->ks_head] = ch;
+ ks->ks_head = (ks->ks_head+1) & (KEYQUEUELEN-1);
+}
+
+
+/* *********************************************************************
+ * KBD_DEQUEUECHAR(ks)
+ *
+ * Remove a character from the queue
+ *
+ * Input parameters:
+ * ks - keystate
+ *
+ * Return value:
+ * 0 if no characters in queue
+ * else character from queue
+ ********************************************************************* */
+static int kbd_dequeuechar(keystate_t *ks)
+{
+ char ch;
+
+ if (ks->ks_head == ks->ks_tail) return 0;
+
+ ch = ks->ks_queue[ks->ks_tail];
+ ks->ks_tail = (ks->ks_tail+1) & (KEYQUEUELEN-1);
+ return ch;
+}
+
+/* *********************************************************************
+ * KBD_READ(ks)
+ *
+ * User call to kbd_dequeuechar - remove a character from
+ * the queue.
+ *
+ * Input parameters:
+ * ks - keyboard state
+ *
+ * Return value:
+ * character from queue or 0 if no chars
+ ********************************************************************* */
+
+int kbd_read(keystate_t *ks)
+{
+ return kbd_dequeuechar(ks);
+}
+
+/* *********************************************************************
+ * KBD_INPSTAT(ks)
+ *
+ * Test input status (see if a character is waiting)
+ *
+ * Input parameters:
+ * ks - keyboard state
+ *
+ * Return value:
+ * 0 if no chars waiting, 1 if characters are waiting
+ ********************************************************************* */
+
+int kbd_inpstat(keystate_t *ks)
+{
+ return (ks->ks_head != ks->ks_tail);
+}
+
+
+/* *********************************************************************
+ * KBD_DOSCAN(ks,scan)
+ *
+ * Process a scan code from the keyboard.
+ *
+ * Input parameters:
+ * ks - keyboard state
+ * scan - scan code from the keyboard
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void kbd_doscan(keystate_t *ks,uint8_t scan)
+{
+ int breakflg;
+ keycode_t *code = 0;
+ char *str;
+
+ breakflg = (scan & FLG_BREAKBIT);
+ scan &= ~FLG_BREAKBIT;
+ code = &scantable[scan];
+
+ if (code->kc_type & (FLG_SHIFT|FLG_CTRL|FLG_ALT)) {
+ if (breakflg) ks->ks_shiftflags &= ~code->kc_type;
+ else ks->ks_shiftflags |= code->kc_type;
+ }
+ if (code->kc_type & (FLG_CAPS|FLG_SCROLL|FLG_NUM)) {
+ if (!breakflg) ks->ks_shiftflags ^= code->kc_type;
+ if (ks->ks_setleds) {
+ (*(ks->ks_setleds))(ks,ks->ks_shiftflags & (FLG_CAPS|FLG_SCROLL|FLG_NUM));
+ }
+ }
+ if (code->kc_type & (FLG_ASCII | FLG_FKEY | FLG_NKPD)) {
+ if (ks->ks_shiftflags & (FLG_SHIFT|FLG_CAPS)) str = code->kc_shifted;
+ else if (ks->ks_shiftflags & FLG_CTRL) str = code->kc_ctrl;
+ else str = code->kc_normal;
+ if (!breakflg) {
+ while (*str) {
+ kbd_enqueuechar(ks,*str++);
+ }
+ }
+ }
+}
+
+
+/* *********************************************************************
+ * KBD_INIT(ks,setleds,ref)
+ *
+ * Initialize a keyboard state object.
+ *
+ * Input parameters:
+ * ks - keyboard state
+ * setleds - routine to call when we want to set the state
+ * of the keyboard's LEDs
+ * ref - data to store in the keyboard state object
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void kbd_init(keystate_t *ks,int (*setleds)(keystate_t *,int),void *ref)
+{
+ memset(ks,0,sizeof(keystate_t));
+ ks->ks_setleds = setleds;
+ ks->ks_ref = ref;
+}