coreboot/payloads/libpayload/curses/keyboard.c
<<
>>
Prefs
   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
  44static 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
  53static 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
  73static struct {
  74        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
 102static 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                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
 127static 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
 147static 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
 194int 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
 206int nodelay(WINDOW *win, NCURSES_BOOL flag)
 207{
 208        win->_delay = flag ? 0 : -1;
 209        return 0;
 210}
 211
 212int halfdelay(int tenths)
 213{
 214        if (tenths > 255)
 215                return ERR;
 216
 217        _halfdelay = tenths;
 218        return 0;
 219}
 220
 221int nocbreak(void)
 222{
 223        /* Remove half delay timeout. */
 224        _halfdelay = 0;
 225        return 0;
 226}
 227
 228#ifdef CONFIG_VGA_VIDEO_CONSOLE
 229void 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
 237int curses_vga_enabled(void)
 238{
 239        return (curses_flags & F_ENABLE_CONSOLE) != 0;
 240}
 241#else
 242void curses_enable_vga(int state) { }
 243int curses_vga_enabled(void) { return 0; }
 244#endif
 245
 246#ifdef CONFIG_SERIAL_CONSOLE
 247void 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
 255int curses_serial_enabled(void)
 256{
 257        return (curses_flags & F_ENABLE_SERIAL) != 0;
 258}
 259
 260#else
 261void curses_enable_serial(int state) { }
 262int curses_serial_enabled(void) { return 0; }
 263#endif
 264
 265
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.