Reduce warnings/errors in libpayload when using picky compiler options
[coreboot.git] / payloads / libpayload / curses / keyboard.c
1 /*
2  * This file is part of the libpayload project.
3  *
4  * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
5  * Copyright (C) 2008 Advanced Micro Devices, Inc.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
17  *
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
28  * SUCH DAMAGE.
29  */
30
31 /*
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)
35  *
36  * TODO:
37  * Actually cook the serial (handle special keys)
38  */
39
40 #include <libpayload-config.h>
41 #include <usb/usb.h>
42 #include "local.h"
43
44 static int _halfdelay = 0;
45
46 /* ============== Serial ==================== */
47
48 #ifdef CONFIG_SERIAL_CONSOLE
49 /* We treat serial like a vt100 terminal.  For now we
50    do the cooking in here, but we should probably eventually
51    pass it to dedicated vt100 code */
52
53 static int getkeyseq(char *buffer, int len, int max)
54 {
55         int i;
56
57         while (1) {
58                 for(i = 0; i < 75; i++) {
59                         if (serial_havechar())
60                                 break;
61                         mdelay(1);
62                 }
63
64                 if (i == 75)
65                         return len;
66
67                 buffer[len++] = serial_getchar();
68                 if (len == max)
69                         return len;
70         }
71 }
72
73 static struct {
74         const char *seq;
75         int key;
76 } escape_codes[] = {
77         { "[A", KEY_UP },
78         { "[B", KEY_DOWN },
79         { "[C", KEY_RIGHT },
80         { "[D", KEY_LEFT },
81         { "[F", KEY_END },
82         { "[H", KEY_HOME },
83         { "[2~", KEY_IC },
84         { "[3~", KEY_DC },
85         { "[5~", KEY_PPAGE },
86         { "[6~", KEY_NPAGE },
87         { "OP", KEY_F(1) },
88         { "OQ", KEY_F(2) },
89         { "OR", KEY_F(3) },
90         { "OS", KEY_F(4) },
91         { "[15~", KEY_F(5) },
92         { "[17~", KEY_F(6) },
93         { "[18~", KEY_F(7) },
94         { "[19~", KEY_F(8) },
95         { "[20~", KEY_F(9) },
96         { "[21~", KEY_F(10) },
97         { "[23~", KEY_F(11) },
98         { "[24~", KEY_F(12) },
99         { NULL },
100 };
101
102 static int handle_escape(void)
103 {
104         char buffer[5];
105         int len = getkeyseq(buffer, 0, sizeof(buffer));
106         int i, t;
107
108         if (len == 0)
109                 return 27;
110
111         for(i = 0; escape_codes[i].seq != NULL; i++) {
112                 const char *p = escape_codes[i].seq;
113
114                 for(t = 0; t < len; t++) {
115                         if (!*p || *p != buffer[t])
116                                 break;
117                         p++;
118                 }
119
120                 if (t == len)
121                         return escape_codes[i].key;
122         }
123
124         return 0;
125 }
126
127 static int cook_serial(unsigned char ch)
128 {
129         switch(ch) {
130         case 8:
131                 return KEY_BACKSPACE;
132
133         case 13:
134                 return KEY_ENTER;
135
136         case 27:
137                 return handle_escape();
138
139         default:
140                 return ch;
141         }
142 }
143 #endif
144
145 /* ================ Keyboard ================ */
146
147 static int curses_getchar(int _delay)
148 {
149 #if defined(CONFIG_USB_HID) || defined(CONFIG_PC_KEYBOARD) || defined(CONFIG_SERIAL_CONSOLE)
150         unsigned short c;
151 #endif
152
153         do {
154 #ifdef CONFIG_USB_HID
155                 usb_poll();
156                 if ((curses_flags & F_ENABLE_CONSOLE) &&
157                     usbhid_havechar()) {
158                         c = usbhid_getchar();
159                         if (c != 0) return c;
160                 }
161 #endif
162 #ifdef CONFIG_PC_KEYBOARD
163                 if ((curses_flags & F_ENABLE_CONSOLE) &&
164                     keyboard_havechar()) {
165                         c = keyboard_getchar();
166                         if (c != 0) return c;
167                 }
168 #endif
169
170 #ifdef CONFIG_SERIAL_CONSOLE
171                 if ((curses_flags & F_ENABLE_SERIAL) &&
172                     serial_havechar()) {
173                         c = serial_getchar();
174                         return cook_serial(c);
175                 }
176 #endif
177
178                 if (_delay == 0)
179                         break;
180
181                 if (_delay > 0) {
182                         mdelay(1);
183                         _delay--;
184                 }
185
186
187         } while (1);
188
189         return ERR;
190 }
191
192 /* === Public functions === */
193
194 int wgetch(WINDOW *win)
195 {
196         int _delay = -1;
197
198         if (_halfdelay)
199                 _delay = _halfdelay;
200         else
201                 _delay = win->_delay;
202
203         return curses_getchar(_delay);
204 }
205
206 int nodelay(WINDOW *win, NCURSES_BOOL flag)
207 {
208         win->_delay = flag ? 0 : -1;
209         return 0;
210 }
211
212 int halfdelay(int tenths)
213 {
214         if (tenths > 255)
215                 return ERR;
216
217         _halfdelay = tenths;
218         return 0;
219 }
220
221 int nocbreak(void)
222 {
223         /* Remove half delay timeout. */
224         _halfdelay = 0;
225         return 0;
226 }
227
228 #ifdef CONFIG_VGA_VIDEO_CONSOLE
229 void curses_enable_vga(int state)
230 {
231         if (state)
232                 curses_flags |= F_ENABLE_CONSOLE;
233         else
234                 curses_flags &= ~F_ENABLE_CONSOLE;
235 }
236
237 int curses_vga_enabled(void)
238 {
239         return (curses_flags & F_ENABLE_CONSOLE) != 0;
240 }
241 #else
242 void curses_enable_vga(int state) { }
243 int curses_vga_enabled(void) { return 0; }
244 #endif
245
246 #ifdef CONFIG_SERIAL_CONSOLE
247 void curses_enable_serial(int state)
248 {
249         if (state)
250                 curses_flags |= F_ENABLE_SERIAL;
251         else
252                 curses_flags &= ~F_ENABLE_SERIAL;
253 }
254
255 int curses_serial_enabled(void)
256 {
257         return (curses_flags & F_ENABLE_SERIAL) != 0;
258 }
259
260 #else
261 void curses_enable_serial(int state) { }
262 int curses_serial_enabled(void) { return 0; }
263 #endif
264