summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux-4.02/gpxe/src/core/pc_kbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux-4.02/gpxe/src/core/pc_kbd.c')
-rw-r--r--contrib/syslinux-4.02/gpxe/src/core/pc_kbd.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/gpxe/src/core/pc_kbd.c b/contrib/syslinux-4.02/gpxe/src/core/pc_kbd.c
new file mode 100644
index 0000000..799c8be
--- /dev/null
+++ b/contrib/syslinux-4.02/gpxe/src/core/pc_kbd.c
@@ -0,0 +1,112 @@
+/* Minimal polling PC keyboard driver
+ * - No interrupt
+ * - No LED
+ * - No special keys
+ *
+ * still Enough For Me to type a filename.
+ *
+ * 2003-07 by SONE Takesh
+ * 2004-04 moved by LYH From filo to Etherboot
+ * yhlu@tyan.com
+ */
+
+#include <gpxe/io.h>
+#include "console.h"
+
+static char key_map[][128] = {
+ {
+ "\0\x1b""1234567890-=\b\t"
+ "qwertyuiop[]\r\0as"
+ "dfghjkl;'`\0\\zxcv"
+ "bnm,./\0*\0 \0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0""789-456+1"
+ "230."
+ },{
+ "\0\x1b""!@#$%^&*()_+\b\t"
+ "QWERTYUIOP{}\r\0AS"
+ "DFGHJKL:\"~\0|ZXCV"
+ "BNM<>?\0\0\0 \0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0""789-456+1"
+ "230."
+ }
+};
+
+static int cur_scan;
+static unsigned int shift_state;
+#define SHIFT 1
+#define CONTROL 2
+#define CAPS 4
+
+static int get_scancode(void)
+{
+ int scan;
+
+ if ((inb(0x64) & 1) == 0)
+ return 0;
+ scan = inb(0x60);
+
+ switch (scan) {
+ case 0x2a:
+ case 0x36:
+ shift_state |= SHIFT;
+ break;
+ case 0xaa:
+ case 0xb6:
+ shift_state &= ~SHIFT;
+ break;
+ case 0x1d:
+ shift_state |= CONTROL;
+ break;
+ case 0x9d:
+ shift_state &= ~CONTROL;
+ break;
+ case 0x3a:
+ shift_state ^= CAPS;
+ break;
+ }
+
+ if (scan & 0x80)
+ return 0; /* ignore break code or 0xe0 etc! */
+ return scan;
+}
+
+static int kbd_havekey(void)
+{
+ if (!cur_scan)
+ cur_scan = get_scancode();
+ return cur_scan != 0;
+}
+
+static int kbd_ischar(void)
+{
+ if (!kbd_havekey())
+ return 0;
+ if (!key_map[shift_state & SHIFT][cur_scan]) {
+ cur_scan = 0;
+ return 0;
+ }
+ return 1;
+}
+
+static int kbd_getc(void)
+{
+ int c;
+
+ while (!kbd_ischar())
+ ;
+ c = key_map[shift_state & SHIFT][cur_scan];
+ if (shift_state & (CONTROL | CAPS)) {
+ if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
+ if (shift_state & CONTROL)
+ c &= 0x1f;
+ else if (shift_state & CAPS)
+ c ^= ('A' ^ 'a');
+ }
+ }
+ cur_scan = 0;
+ return c;
+}
+
+struct console_driver pc_kbd_console __console_driver = {
+ .getchar = kbd_getc,
+};