diff options
Diffstat (limited to 'payloads/libpayload/curses/pdcurses-backend/pdckbd.c')
-rw-r--r-- | payloads/libpayload/curses/pdcurses-backend/pdckbd.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/payloads/libpayload/curses/pdcurses-backend/pdckbd.c b/payloads/libpayload/curses/pdcurses-backend/pdckbd.c new file mode 100644 index 0000000000..4a039ffbc4 --- /dev/null +++ b/payloads/libpayload/curses/pdcurses-backend/pdckbd.c @@ -0,0 +1,194 @@ +/* Public Domain Curses */ + +#include "lppdc.h" +#include <usb/usb.h> + +unsigned long pdc_key_modifiers = 0L; + +#ifdef CONFIG_SERIAL_CONSOLE +/* We treat serial like a vt100 terminal. For now we + do the cooking in here, but we should probably eventually + pass it to dedicated vt100 code */ + +static int getkeyseq(char *buffer, int len, int max) +{ + int i; + + while (1) { + for(i = 0; i < 75; i++) { + if (serial_havechar()) + break; + mdelay(1); + } + + if (i == 75) + return len; + + buffer[len++] = serial_getchar(); + if (len == max) + return len; + } +} + +static struct { + const char *seq; + int key; +} escape_codes[] = { + { "[A", KEY_UP }, + { "[B", KEY_DOWN }, + { "[C", KEY_RIGHT }, + { "[D", KEY_LEFT }, + { "[F", KEY_END }, + { "[H", KEY_HOME }, + { "[2~", KEY_IC }, + { "[3~", KEY_DC }, + { "[5~", KEY_PPAGE }, + { "[6~", KEY_NPAGE }, + { "OP", KEY_F(1) }, + { "OQ", KEY_F(2) }, + { "OR", KEY_F(3) }, + { "OS", KEY_F(4) }, + { "[15~", KEY_F(5) }, + { "[17~", KEY_F(6) }, + { "[18~", KEY_F(7) }, + { "[19~", KEY_F(8) }, + { "[20~", KEY_F(9) }, + { "[21~", KEY_F(10) }, + { "[23~", KEY_F(11) }, + { "[24~", KEY_F(12) }, + { NULL }, +}; + +static int handle_escape(void) +{ + char buffer[5]; + int len = getkeyseq(buffer, 0, sizeof(buffer)); + int i, t; + + if (len == 0) + return 27; + + for(i = 0; escape_codes[i].seq != NULL; i++) { + const char *p = escape_codes[i].seq; + + for(t = 0; t < len; t++) { + if (!*p || *p != buffer[t]) + break; + p++; + } + + if (t == len) + return escape_codes[i].key; + } + + return 0; +} + +static int cook_serial(unsigned char ch) +{ + switch(ch) { + case 8: + return KEY_BACKSPACE; + + case 27: + return handle_escape(); + + default: + return ch; + } +} +#endif + +void PDC_set_keyboard_binary(bool on) +{ + PDC_LOG(("PDC_set_keyboard_binary() - called\n")); +} + +/* check if a key event is waiting */ + +bool PDC_check_key(void) +{ +#ifdef CONFIG_USB_HID + usb_poll(); + if ((curses_flags & F_ENABLE_CONSOLE) && + usbhid_havechar()) { + return TRUE; + } +#endif + +#ifdef CONFIG_PC_KEYBOARD + if ((curses_flags & F_ENABLE_CONSOLE) && + keyboard_havechar()) { + return TRUE; + } +#endif + +#ifdef CONFIG_SERIAL_CONSOLE + if ((curses_flags & F_ENABLE_SERIAL) && + serial_havechar()) { + return TRUE; + } +#endif + + return FALSE; +} + +/* return the next available key event */ + +int PDC_get_key(void) +{ + int c = 0; + +#ifdef CONFIG_USB_HID + usb_poll(); + if ((curses_flags & F_ENABLE_CONSOLE) && + usbhid_havechar()) { + c = usbhid_getchar(); + } +#endif + +#ifdef CONFIG_PC_KEYBOARD + if ((curses_flags & F_ENABLE_CONSOLE) && + keyboard_havechar()) { + c = keyboard_getchar(); + } +#endif + +#ifdef CONFIG_SERIAL_CONSOLE + if ((curses_flags & F_ENABLE_SERIAL) && + serial_havechar()) { + c = cook_serial(serial_getchar()); + } +#endif + + SP->key_code = FALSE; + + if (c == 0) { + c = ERR; + } + if (c >= KEY_MIN) { + SP->key_code = TRUE; + } + + return c; +} + +/* discard any pending keyboard input -- this is the core + routine for flushinp() */ + +void PDC_flushinp(void) +{ + PDC_LOG(("PDC_flushinp() - called\n")); + + while (PDC_check_key()) PDC_get_key(); +} + +int PDC_mouse_set(void) +{ + return ERR; +} + +int PDC_modifiers_set(void) +{ + return OK; +} |