All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: seabios@seabios.org
Cc: qemu-devel@nongnu.org, Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [RFC PATCH 2/2] serial console, input
Date: Fri,  1 Jul 2016 12:54:31 +0200	[thread overview]
Message-ID: <1467370471-20554-3-git-send-email-kraxel@redhat.com> (raw)
In-Reply-To: <1467370471-20554-1-git-send-email-kraxel@redhat.com>

Signed-off-by: Gerd Hoffmann <kraxel@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

  parent reply	other threads:[~2016-07-01 10:54 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-01 10:54 [Qemu-devel] [RFC PATCH 0/2] seabios: add serial console support Gerd Hoffmann
2016-07-01 10:54 ` [Qemu-devel] [RFC PATCH 1/2] serial console, output Gerd Hoffmann
2016-07-01 15:47   ` [Qemu-devel] [SeaBIOS] " Kevin O'Connor
2016-07-04  8:16     ` Gerd Hoffmann
2016-07-04  9:11       ` [Qemu-devel] " Paolo Bonzini
2016-07-04 12:46         ` Gerd Hoffmann
2016-07-04 12:48           ` Paolo Bonzini
2016-07-04 15:26           ` Kevin O'Connor
2016-07-04 15:45             ` Paolo Bonzini
2016-07-04 20:10               ` Gerd Hoffmann
2016-07-04 16:00             ` Kevin O'Connor
2016-07-04 16:03               ` Paolo Bonzini
2016-07-04 17:28                 ` Kevin O'Connor
2016-07-04 20:18                   ` Gerd Hoffmann
2016-07-04 20:23             ` Gerd Hoffmann
2016-07-01 10:54 ` Gerd Hoffmann [this message]
2016-07-01 17:07   ` [Qemu-devel] [SeaBIOS] [RFC PATCH 2/2] serial console, input Kevin O'Connor
2016-07-01 18:07     ` Kevin O'Connor
2016-07-04  9:16     ` Gerd Hoffmann
2016-07-04 15:34       ` Kevin O'Connor
2016-07-04 20:03         ` Gerd Hoffmann
2016-07-01 15:47 ` [Qemu-devel] [RFC PATCH 0/2] seabios: add serial console support Gerd Hoffmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1467370471-20554-3-git-send-email-kraxel@redhat.com \
    --to=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=seabios@seabios.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.