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 /* ============== Serial ==================== */
44 /* FIXME: Cook the serial correctly */
46 static int cook_serial(unsigned char ch)
51 /* ================ Keyboard ================ */
55 #define DOWN(_c) (0x80 | (_c))
58 #define ISDOWN(_c) ((_c) & 0x80)
59 #define ISUP(_c) (!ISDOWN((_c)))
61 #define SCANCODE(_c) ((_c) & ~0x80)
63 /* Scancode definitions for the modifiers */
65 #define SCANCODE_RSHIFT 0x36
66 #define SCANCODE_LSHIFT 0x2a
67 #define SCANCODE_CAPSLOCK 0x3a
68 #define SCANCODE_LALT 0x38
69 #define SCANCODE_LCTRL 0x1d
73 #define SHIFT_MODIFIER 0x1
74 #define CAPSLOCK_MODIFIER 0x2
75 #define ALT_MODIFIER 0x4
76 #define CTRL_MODIFIER 0x8
78 #define CTRL(_c) (_c & 0x1f)
85 { CTRL('['), CTRL('[')},
98 { KEY_BACKSPACE, KEY_BACKSPACE},
99 { CTRL('I' ), KEY_BTAB }, /* 0x0F */
112 { KEY_ENTER, KEY_ENTER },
115 { 's', 'S' }, /* 0x1F */
131 { 'v', 'V' }, /* 0x2F */
138 { 0, 0 }, /* RSHIFT */
141 { ' ', ' ' }, /* Space */
142 { 0, 0 }, /* Capslock */
143 { KEY_F(1), KEY_F(1) },
144 { KEY_F(2), KEY_F(2) },
145 { KEY_F(3), KEY_F(3) },
146 { KEY_F(4), KEY_F(4) },
147 { KEY_F(5), KEY_F(5) }, /* 0x3F */
148 { KEY_F(6), KEY_F(6) },
149 { KEY_F(7), KEY_F(7) },
150 { KEY_F(8), KEY_F(8) },
151 { KEY_F(9), KEY_F(9) },
152 { KEY_F(10), KEY_F(10) },
153 { 0, 0 }, /* Numlock */
154 { 0, 0 }, /* Scroll lock */
155 { KEY_HOME, KEY_HOME },
157 { KEY_PPAGE, KEY_PPAGE },
159 { KEY_LEFT, KEY_LEFT },
161 { KEY_RIGHT, KEY_RIGHT },
163 { KEY_END, KEY_END }, /* 0x4F */
164 { KEY_DOWN, KEY_DOWN },
165 { KEY_NPAGE, KEY_NPAGE },
168 { 0, 0 }, /* sysreq */
170 { KEY_F(11), KEY_F(11) },
171 { KEY_F(12), KEY_F(12) },
174 static int cook_scancodes(unsigned char code)
176 static int modifiers = 0;
177 int ch = 0, sc, shift;
180 case DOWN(SCANCODE_RSHIFT):
181 case DOWN(SCANCODE_LSHIFT):
182 modifiers |= SHIFT_MODIFIER;
184 case UP(SCANCODE_RSHIFT):
185 case UP(SCANCODE_LSHIFT):
186 modifiers &= ~SHIFT_MODIFIER;
188 case UP(SCANCODE_CAPSLOCK):
189 if (modifiers & CAPSLOCK_MODIFIER)
190 modifiers &= ~CAPSLOCK_MODIFIER;
192 modifiers |= CAPSLOCK_MODIFIER;
194 case DOWN(SCANCODE_LALT):
195 modifiers |= ALT_MODIFIER;
197 case UP(SCANCODE_LALT):
198 modifiers &= ~ALT_MODIFIER;
200 case DOWN(SCANCODE_LCTRL):
201 modifiers |= CTRL_MODIFIER;
203 case UP(SCANCODE_LCTRL):
204 modifiers &= ~CTRL_MODIFIER;
208 /* Only process keys on an upstroke. */
214 if (sc == 0 || sc > 0x59)
217 shift = (modifiers & SHIFT_MODIFIER) ^ (modifiers & CAPSLOCK_MODIFIER);
219 ch = shift ? scancode_map[sc].shift : scancode_map[sc].normal;
221 if (modifiers & CTRL_MODIFIER)
222 ch = (ch >= 0x3F && ch <= 0x5F) ? CTRL(ch) : 0;
227 static int curses_getchar(int delay)
233 if (curses_flags & F_ENABLE_CONSOLE)
238 if ((curses_flags & F_ENABLE_SERIAL) &&
240 c = serial_getchar();
241 return cook_serial(c);
250 ret = cook_scancodes(c);
261 /* === Public functions === */
263 int wgetch(WINDOW *win)
265 return curses_getchar(win->_delay);
268 int nodelay(WINDOW *win, NCURSES_BOOL flag)
270 win->_delay = flag ? 0 : -1;
273 #ifdef CONFIG_VGA_CONSOLE
274 void curses_enable_vga(int state)
277 curses_flags |= F_ENABLE_CONSOLE;
279 curses_flags &= ~F_ENABLE_CONSOLE;
282 void curses_enable_vga(int state) { }
285 #ifdef CONFIG_SERIAL_CONSOLE
286 void curses_enable_serial(int state)
289 curses_flags |= F_ENABLE_SERIAL;
291 curses_flags &= ~F_ENABLE_SERIAL;
294 void curses_enable_serial(int state) { }