2 * This file is part of the libpayload project.
4 * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
5 * Copyright (C) 2008 Advanced Micro Devices, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * This file handles reading keystrokes from serial and the console
33 * and "cooking" them so that they are correct for curses.
34 * Also, implement key related functions (mainly wgetch)
37 * Actually cook the serial (handle special keys)
42 static int _halfdelay = 0;
44 /* ============== Serial ==================== */
46 /* FIXME: Cook the serial correctly */
48 static int cook_serial(unsigned char ch)
53 /* ================ Keyboard ================ */
57 #define DOWN(_c) (0x80 | (_c))
60 #define ISDOWN(_c) ((_c) & 0x80)
61 #define ISUP(_c) (!ISDOWN((_c)))
63 #define SCANCODE(_c) ((_c) & ~0x80)
65 /* Scancode definitions for the modifiers */
67 #define SCANCODE_RSHIFT 0x36
68 #define SCANCODE_LSHIFT 0x2a
69 #define SCANCODE_CAPSLOCK 0x3a
70 #define SCANCODE_LALT 0x38
71 #define SCANCODE_LCTRL 0x1d
75 #define SHIFT_MODIFIER 0x1
76 #define CAPSLOCK_MODIFIER 0x2
77 #define ALT_MODIFIER 0x4
78 #define CTRL_MODIFIER 0x8
80 #define CTRL(_c) (_c & 0x1f)
87 { CTRL('['), CTRL('[')},
100 { KEY_BACKSPACE, KEY_BACKSPACE},
101 { CTRL('I' ), KEY_BTAB }, /* 0x0F */
114 { KEY_ENTER, KEY_ENTER },
117 { 's', 'S' }, /* 0x1F */
133 { 'v', 'V' }, /* 0x2F */
140 { 0, 0 }, /* RSHIFT */
143 { ' ', ' ' }, /* Space */
144 { 0, 0 }, /* Capslock */
145 { KEY_F(1), KEY_F(1) },
146 { KEY_F(2), KEY_F(2) },
147 { KEY_F(3), KEY_F(3) },
148 { KEY_F(4), KEY_F(4) },
149 { KEY_F(5), KEY_F(5) }, /* 0x3F */
150 { KEY_F(6), KEY_F(6) },
151 { KEY_F(7), KEY_F(7) },
152 { KEY_F(8), KEY_F(8) },
153 { KEY_F(9), KEY_F(9) },
154 { KEY_F(10), KEY_F(10) },
155 { 0, 0 }, /* Numlock */
156 { 0, 0 }, /* Scroll lock */
157 { KEY_HOME, KEY_HOME },
159 { KEY_PPAGE, KEY_PPAGE },
161 { KEY_LEFT, KEY_LEFT },
163 { KEY_RIGHT, KEY_RIGHT },
165 { KEY_END, KEY_END }, /* 0x4F */
166 { KEY_DOWN, KEY_DOWN },
167 { KEY_NPAGE, KEY_NPAGE },
170 { 0, 0 }, /* sysreq */
172 { KEY_F(11), KEY_F(11) },
173 { KEY_F(12), KEY_F(12) },
176 static int cook_scancodes(unsigned char code)
178 static int modifiers = 0;
179 int ch = 0, sc, shift;
182 case DOWN(SCANCODE_RSHIFT):
183 case DOWN(SCANCODE_LSHIFT):
184 modifiers |= SHIFT_MODIFIER;
186 case UP(SCANCODE_RSHIFT):
187 case UP(SCANCODE_LSHIFT):
188 modifiers &= ~SHIFT_MODIFIER;
190 case UP(SCANCODE_CAPSLOCK):
191 if (modifiers & CAPSLOCK_MODIFIER)
192 modifiers &= ~CAPSLOCK_MODIFIER;
194 modifiers |= CAPSLOCK_MODIFIER;
196 case DOWN(SCANCODE_LALT):
197 modifiers |= ALT_MODIFIER;
199 case UP(SCANCODE_LALT):
200 modifiers &= ~ALT_MODIFIER;
202 case DOWN(SCANCODE_LCTRL):
203 modifiers |= CTRL_MODIFIER;
205 case UP(SCANCODE_LCTRL):
206 modifiers &= ~CTRL_MODIFIER;
210 /* Only process keys on an upstroke. */
216 if (sc == 0 || sc > 0x59)
219 shift = (modifiers & SHIFT_MODIFIER) ^ (modifiers & CAPSLOCK_MODIFIER);
221 ch = shift ? scancode_map[sc].shift : scancode_map[sc].normal;
223 if (modifiers & CTRL_MODIFIER)
224 ch = (ch >= 0x3F && ch <= 0x5F) ? CTRL(ch) : 0;
229 static int curses_getchar(int delay)
235 if (curses_flags & F_ENABLE_CONSOLE)
240 if ((curses_flags & F_ENABLE_SERIAL) &&
242 c = serial_getchar();
243 return cook_serial(c);
257 ret = cook_scancodes(c);
268 /* === Public functions === */
270 int wgetch(WINDOW *win)
274 if (_halfdelay || win->_delay)
275 delay = win->_delay ? 0 : _halfdelay;
277 return curses_getchar(delay);
280 int nodelay(WINDOW *win, NCURSES_BOOL flag)
282 win->_delay = flag ? 1 : 0;
286 int halfdelay(int tenths)
297 /* Remove half delay timeout. */
302 #ifdef CONFIG_VGA_CONSOLE
303 void curses_enable_vga(int state)
306 curses_flags |= F_ENABLE_CONSOLE;
308 curses_flags &= ~F_ENABLE_CONSOLE;
311 void curses_enable_vga(int state) { }
314 #ifdef CONFIG_SERIAL_CONSOLE
315 void curses_enable_serial(int state)
318 curses_flags |= F_ENABLE_SERIAL;
320 curses_flags &= ~F_ENABLE_SERIAL;
323 void curses_enable_serial(int state) { }