[SeaBIOS] [RFC PATCH 2/2] serial console, input
Gerd Hoffmann
kraxel at redhat.com
Fri Jul 1 12:54:31 CEST 2016
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
---
src/clock.c | 1 +
src/serial.c | 255 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/util.h | 1 +
3 files changed, 257 insertions(+)
diff --git a/src/clock.c b/src/clock.c
index e83e0f3..e44e112 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -295,6 +295,7 @@ clock_update(void)
floppy_tick();
usb_check_event();
ps2_check_event();
+ sercon_check_event();
}
// INT 08h System Timer ISR Entry Point
diff --git a/src/serial.c b/src/serial.c
index 74b91bb..d72dd01 100644
--- a/src/serial.c
+++ b/src/serial.c
@@ -655,3 +655,258 @@ void sercon_enable(void)
outb(0x01, addr + 0x02); // enable fifo
enable_vga_console();
}
+
+/****************************************************************
+ * serial input
+ ****************************************************************/
+
+VARLOW u8 rx_buf[16];
+VARLOW u8 rx_bytes;
+
+VARLOW struct {
+ char seq[4];
+ u8 len;
+ u8 scancode;
+} termseq[] = {
+ { .seq = "OP", .len = 2, .scancode = 0x3b }, // F1
+ { .seq = "OQ", .len = 2, .scancode = 0x3c }, // F2
+ { .seq = "OR", .len = 2, .scancode = 0x3d }, // F3
+ { .seq = "OS", .len = 2, .scancode = 0x3e }, // F4
+ { .seq = "[A", .len = 2, .scancode = 0xc8 }, // up
+ { .seq = "[B", .len = 2, .scancode = 0xd0 }, // down
+ { .seq = "[C", .len = 2, .scancode = 0xcd }, // right
+ { .seq = "[D", .len = 2, .scancode = 0xcb }, // left
+};
+
+#define FLAG_CTRL (1<<0)
+#define FLAG_SHIFT (1<<1)
+
+VARLOW struct {
+ u8 flags;
+ u8 scancode;
+} termchr[256] = {
+ [ '1' ] = { .scancode = 0x02, },
+ [ '!' ] = { .scancode = 0x02, .flags = FLAG_SHIFT },
+ [ '2' ] = { .scancode = 0x03, },
+ [ '@' ] = { .scancode = 0x03, .flags = FLAG_SHIFT },
+ [ '3' ] = { .scancode = 0x04, },
+ [ '#' ] = { .scancode = 0x04, .flags = FLAG_SHIFT },
+ [ '4' ] = { .scancode = 0x05, },
+ [ '$' ] = { .scancode = 0x05, .flags = FLAG_SHIFT },
+ [ '5' ] = { .scancode = 0x06, },
+ [ '%' ] = { .scancode = 0x06, .flags = FLAG_SHIFT },
+ [ '6' ] = { .scancode = 0x07, },
+ [ '^' ] = { .scancode = 0x07, .flags = FLAG_SHIFT },
+ [ '7' ] = { .scancode = 0x08, },
+ [ '&' ] = { .scancode = 0x08, .flags = FLAG_SHIFT },
+ [ '8' ] = { .scancode = 0x09, },
+ [ '*' ] = { .scancode = 0x09, .flags = FLAG_SHIFT },
+ [ '9' ] = { .scancode = 0x0a, },
+ [ '(' ] = { .scancode = 0x0a, .flags = FLAG_SHIFT },
+ [ '0' ] = { .scancode = 0x0b, },
+ [ ')' ] = { .scancode = 0x0b, .flags = FLAG_SHIFT },
+ [ '-' ] = { .scancode = 0x0c, },
+ [ '=' ] = { .scancode = 0x0d, },
+ [ '+' ] = { .scancode = 0x0d, .flags = FLAG_SHIFT },
+
+ [ 'q' ] = { .scancode = 0x10, },
+ [ 'Q' ] = { .scancode = 0x10, .flags = FLAG_SHIFT },
+ [ 'Q' & 0x1f ] = { .scancode = 0x10, .flags = FLAG_CTRL },
+ [ 'w' ] = { .scancode = 0x11, },
+ [ 'W' ] = { .scancode = 0x11, .flags = FLAG_SHIFT },
+ [ 'W' & 0x1f ] = { .scancode = 0x11, .flags = FLAG_CTRL },
+ [ 'e' ] = { .scancode = 0x12, },
+ [ 'E' ] = { .scancode = 0x12, .flags = FLAG_SHIFT },
+ [ 'E' & 0x1f ] = { .scancode = 0x12, .flags = FLAG_CTRL },
+ [ 'r' ] = { .scancode = 0x13, },
+ [ 'R' ] = { .scancode = 0x13, .flags = FLAG_SHIFT },
+ [ 'R' & 0x1f ] = { .scancode = 0x13, .flags = FLAG_CTRL },
+ [ 't' ] = { .scancode = 0x14, },
+ [ 'T' ] = { .scancode = 0x14, .flags = FLAG_SHIFT },
+ [ 'T' & 0x1f ] = { .scancode = 0x14, .flags = FLAG_CTRL },
+ [ 'y' ] = { .scancode = 0x15, },
+ [ 'Y' ] = { .scancode = 0x15, .flags = FLAG_SHIFT },
+ [ 'Y' & 0x1f ] = { .scancode = 0x15, .flags = FLAG_CTRL },
+ [ 'u' ] = { .scancode = 0x16, },
+ [ 'U' ] = { .scancode = 0x16, .flags = FLAG_SHIFT },
+ [ 'U' & 0x1f ] = { .scancode = 0x16, .flags = FLAG_CTRL },
+ [ 'i' ] = { .scancode = 0x17, },
+ [ 'I' ] = { .scancode = 0x17, .flags = FLAG_SHIFT },
+ [ 'I' & 0x1f ] = { .scancode = 0x17, .flags = FLAG_CTRL },
+ [ 'o' ] = { .scancode = 0x18, },
+ [ 'O' ] = { .scancode = 0x18, .flags = FLAG_SHIFT },
+ [ 'O' & 0x1f ] = { .scancode = 0x18, .flags = FLAG_CTRL },
+ [ 'p' ] = { .scancode = 0x19, },
+ [ 'P' ] = { .scancode = 0x19, .flags = FLAG_SHIFT },
+ [ 'P' & 0x1f ] = { .scancode = 0x19, .flags = FLAG_CTRL },
+ [ '[' ] = { .scancode = 0x1a, },
+ [ '{' ] = { .scancode = 0x1a, .flags = FLAG_SHIFT },
+ [ ']' ] = { .scancode = 0x1b, },
+ [ '}' ] = { .scancode = 0x1b, .flags = FLAG_SHIFT },
+
+ [ 'a' ] = { .scancode = 0x1e, },
+ [ 'A' ] = { .scancode = 0x1e, .flags = FLAG_SHIFT },
+ [ 'A' & 0x1f ] = { .scancode = 0x1e, .flags = FLAG_CTRL },
+ [ 's' ] = { .scancode = 0x1f, },
+ [ 'S' ] = { .scancode = 0x1f, .flags = FLAG_SHIFT },
+ [ 'S' & 0x1f ] = { .scancode = 0x1f, .flags = FLAG_CTRL },
+ [ 'd' ] = { .scancode = 0x20, },
+ [ 'D' ] = { .scancode = 0x20, .flags = FLAG_SHIFT },
+ [ 'D' & 0x1f ] = { .scancode = 0x20, .flags = FLAG_CTRL },
+ [ 'f' ] = { .scancode = 0x21, },
+ [ 'F' ] = { .scancode = 0x21, .flags = FLAG_SHIFT },
+ [ 'F' & 0x1f ] = { .scancode = 0x21, .flags = FLAG_CTRL },
+ [ 'g' ] = { .scancode = 0x22, },
+ [ 'G' ] = { .scancode = 0x22, .flags = FLAG_SHIFT },
+ [ 'G' & 0x1f ] = { .scancode = 0x22, .flags = FLAG_CTRL },
+ [ 'h' ] = { .scancode = 0x23, },
+ [ 'H' ] = { .scancode = 0x23, .flags = FLAG_SHIFT },
+ [ 'H' & 0x1f ] = { .scancode = 0x23, .flags = FLAG_CTRL },
+ [ 'j' ] = { .scancode = 0x24, },
+ [ 'J' ] = { .scancode = 0x24, .flags = FLAG_SHIFT },
+ [ 'J' & 0x1f ] = { .scancode = 0x24, .flags = FLAG_CTRL },
+ [ 'k' ] = { .scancode = 0x25, },
+ [ 'K' ] = { .scancode = 0x25, .flags = FLAG_SHIFT },
+ [ 'K' & 0x1f ] = { .scancode = 0x25, .flags = FLAG_CTRL },
+ [ 'l' ] = { .scancode = 0x26, },
+ [ 'L' ] = { .scancode = 0x26, .flags = FLAG_SHIFT },
+ [ 'L' & 0x1f ] = { .scancode = 0x26, .flags = FLAG_CTRL },
+ [ ';' ] = { .scancode = 0x27, },
+ [ ':' ] = { .scancode = 0x27, .flags = FLAG_SHIFT },
+ [ '\'' ] = { .scancode = 0x28, },
+ [ '"' ] = { .scancode = 0x28, .flags = FLAG_SHIFT },
+
+ [ '\\' ] = { .scancode = 0x2b, },
+ [ '|' ] = { .scancode = 0x2b, .flags = FLAG_SHIFT },
+ [ 'z' ] = { .scancode = 0x2c, },
+ [ 'Z' ] = { .scancode = 0x2c, .flags = FLAG_SHIFT },
+ [ 'Z' & 0x1f ] = { .scancode = 0x2c, .flags = FLAG_CTRL },
+ [ 'x' ] = { .scancode = 0x2d, },
+ [ 'X' ] = { .scancode = 0x2d, .flags = FLAG_SHIFT },
+ [ 'X' & 0x1f ] = { .scancode = 0x2d, .flags = FLAG_CTRL },
+ [ 'c' ] = { .scancode = 0x2e, },
+ [ 'C' ] = { .scancode = 0x2e, .flags = FLAG_SHIFT },
+ [ 'C' & 0x1f ] = { .scancode = 0x2e, .flags = FLAG_CTRL },
+ [ 'v' ] = { .scancode = 0x2f, },
+ [ 'V' ] = { .scancode = 0x2f, .flags = FLAG_SHIFT },
+ [ 'V' & 0x1f ] = { .scancode = 0x2f, .flags = FLAG_CTRL },
+ [ 'b' ] = { .scancode = 0x30, },
+ [ 'B' ] = { .scancode = 0x30, .flags = FLAG_SHIFT },
+ [ 'B' & 0x1f ] = { .scancode = 0x30, .flags = FLAG_CTRL },
+ [ 'n' ] = { .scancode = 0x31, },
+ [ 'N' ] = { .scancode = 0x31, .flags = FLAG_SHIFT },
+ [ 'N' & 0x1f ] = { .scancode = 0x31, .flags = FLAG_CTRL },
+ [ 'm' ] = { .scancode = 0x32, },
+ [ 'M' ] = { .scancode = 0x32, .flags = FLAG_SHIFT },
+ [ 'M' & 0x1f ] = { .scancode = 0x32, .flags = FLAG_CTRL },
+ [ ',' ] = { .scancode = 0x33, },
+ [ '<' ] = { .scancode = 0x33, .flags = FLAG_SHIFT },
+ [ '.' ] = { .scancode = 0x34, },
+ [ '>' ] = { .scancode = 0x34, .flags = FLAG_SHIFT },
+ [ '?' ] = { .scancode = 0x35, },
+ [ '|' ] = { .scancode = 0x35, .flags = FLAG_SHIFT },
+
+ [ '\x1b' ] = { .scancode = 0x01, },
+ [ '\t' ] = { .scancode = 0x0f, },
+ [ '\r' ] = { .scancode = 0x1c, },
+ [ '\n' ] = { .scancode = 0x1c, },
+ [ ' ' ] = { .scancode = 0x39, },
+};
+
+static void shiftbuf(int remove)
+{
+ int i, remaining;
+
+ remaining = GET_LOW(rx_bytes) - remove;
+ SET_LOW(rx_bytes, remaining);
+ for (i = 0; i < remaining; i++)
+ SET_LOW(rx_buf[i], GET_LOW(rx_buf[i + remove]));
+}
+
+static void sercon_sendkey(u8 scancode, u8 flags)
+{
+ if (flags & FLAG_CTRL)
+ process_key(0x1d);
+ if (flags & FLAG_SHIFT)
+ process_key(0x2a);
+
+ if (scancode & 0x80) {
+ process_key(0xe0);
+ process_key(scancode & ~0x80);
+ process_key(0xe0);
+ process_key(scancode);
+ } else {
+ process_key(scancode);
+ process_key(scancode | 0x80);
+ }
+
+ if (flags & FLAG_SHIFT)
+ process_key(0x2a | 0x80);
+ if (flags & FLAG_CTRL)
+ process_key(0x1d | 0x80);
+}
+
+void VISIBLE16
+sercon_check_event(void)
+{
+ u16 addr = GET_LOW(sercon_port);
+ u8 byte, scancode, flags, count = 0;
+ int seq, chr, len;
+
+ // check to see if there is a active serial port
+ if (!addr)
+ return;
+ if (inb(addr + SEROFF_LSR) == 0xFF)
+ return;
+
+ // flush pending output
+ sercon_flush_lazy();
+
+ // read all available data
+ while (inb(addr + SEROFF_LSR) & 0x01) {
+ byte = inb(addr + SEROFF_DATA);
+ if (GET_LOW(rx_bytes) < sizeof(rx_buf)) {
+ SET_LOW(rx_buf[rx_bytes], byte);
+ SET_LOW(rx_bytes, GET_LOW(rx_bytes) + 1);
+ count++;
+ }
+ }
+
+next_char:
+ // no (more) input data
+ if (!GET_LOW(rx_bytes))
+ return;
+
+ // lookup escape sequences
+ if (GET_LOW(rx_bytes) > 1 && GET_LOW(rx_buf[0]) == 0x1b) {
+ for (seq = 0; seq < ARRAY_SIZE(termseq); seq++) {
+ len = GET_LOW(termseq[seq].len);
+ if (GET_LOW(rx_bytes) < len + 1)
+ continue;
+ for (chr = 0; chr < len; chr++) {
+ if (GET_LOW(termseq[seq].seq[chr]) != GET_LOW(rx_buf[chr + 1]))
+ break;
+ }
+ if (chr == len) {
+ scancode = GET_LOW(termseq[seq].scancode);
+ sercon_sendkey(scancode, 0);
+ shiftbuf(len + 1);
+ goto next_char;
+ }
+ }
+ }
+
+ // Seems we got a escape sequence we didn't recognise.
+ // -> If we received data wait for more, maybe it is just incomplete.
+ if (GET_LOW(rx_buf[0]) == 0x1b && count)
+ return;
+
+ // Handle input as individual chars.
+ chr = GET_LOW(rx_buf[0]);
+ scancode = GET_LOW(termchr[chr].scancode);
+ flags = GET_LOW(termchr[chr].flags);
+ if (scancode)
+ sercon_sendkey(scancode, flags);
+ shiftbuf(1);
+ goto next_char;
+}
diff --git a/src/util.h b/src/util.h
index 29f17be..3e7366b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -232,6 +232,7 @@ void serial_setup(void);
void lpt_setup(void);
void sercon_10(struct bregs *regs);
void sercon_enable(void);
+void sercon_check_event(void);
// vgahooks.c
void handle_155f(struct bregs *regs);
--
1.8.3.1
More information about the SeaBIOS
mailing list