aboutsummaryrefslogtreecommitdiff
path: root/payloads/libpayload/curses/pdcurses-backend/pdckbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'payloads/libpayload/curses/pdcurses-backend/pdckbd.c')
-rw-r--r--payloads/libpayload/curses/pdcurses-backend/pdckbd.c194
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;
+}