]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
sandbox: Improve sandbox serial port keyboard interface
authorTaylor Hutt <thutt@chromium.org>
Sun, 24 Feb 2013 17:33:13 +0000 (17:33 +0000)
committerSimon Glass <sjg@chromium.org>
Fri, 1 Mar 2013 03:09:21 +0000 (19:09 -0800)
Implements the tstc() interface for the serial driver.  Multiplexing
the console between the serial port and a keyboard uses a polling
method of checking if characters are available; this means that the
serial console must be non-blocking when attempting to read
characters.

Signed-off-by: Taylor Hutt <thutt@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
arch/sandbox/cpu/os.c
drivers/serial/sandbox.c
include/os.h

index 36637af6ce4c578a19e4133025822afe82ec6001..3e37c930b06d6c690a9c7054562982dd313d8ac3 100644 (file)
@@ -44,6 +44,14 @@ ssize_t os_read(int fd, void *buf, size_t count)
        return read(fd, buf, count);
 }
 
+ssize_t os_read_no_block(int fd, void *buf, size_t count)
+{
+       const int flags = fcntl(fd, F_GETFL, 0);
+
+       fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+       return os_read(fd, buf, count);
+}
+
 ssize_t os_write(int fd, const void *buf, size_t count)
 {
        return write(fd, buf, count);
index cb19401df6c42e61a6ec1a7743be256099a2281a..b73520ca940740351e69aea3e4f3ece04f94336f 100644 (file)
 #include <serial.h>
 #include <linux/compiler.h>
 
+/*
+ *
+ *   serial_buf: A buffer that holds keyboard characters for the
+ *              Sandbox U-boot.
+ *
+ * invariants:
+ *   serial_buf_write           == serial_buf_read -> empty buffer
+ *   (serial_buf_write + 1) % 16 == serial_buf_read -> full buffer
+ */
+static char serial_buf[16];
+static unsigned int serial_buf_write;
+static unsigned int serial_buf_read;
+
 static int sandbox_serial_init(void)
 {
        os_tty_raw(0);
@@ -50,18 +63,37 @@ static void sandbox_serial_puts(const char *str)
        os_write(1, str, strlen(str));
 }
 
-static int sandbox_serial_getc(void)
+static unsigned int increment_buffer_index(unsigned int index)
+{
+       return (index + 1) % ARRAY_SIZE(serial_buf);
+}
+
+static int sandbox_serial_tstc(void)
 {
-       char buf;
+       const unsigned int next_index =
+               increment_buffer_index(serial_buf_write);
        ssize_t count;
 
-       count = os_read(0, &buf, 1);
-       return count == 1 ? buf : 0;
+       os_usleep(100);
+       if (next_index == serial_buf_read)
+               return 1;       /* buffer full */
+
+       count = os_read_no_block(0, &serial_buf[serial_buf_write], 1);
+       if (count == 1)
+               serial_buf_write = next_index;
+       return serial_buf_write != serial_buf_read;
 }
 
-static int sandbox_serial_tstc(void)
+static int sandbox_serial_getc(void)
 {
-       return 0;
+       int result;
+
+       while (!sandbox_serial_tstc())
+               ;       /* buffer empty */
+
+       result = serial_buf[serial_buf_read];
+       serial_buf_read = increment_buffer_index(serial_buf_read);
+       return result;
 }
 
 static struct serial_device sandbox_serial_drv = {
index 699682a4089beed0869c88fbf5974243aa647221..c452d1b56ef8a87cc3d73e966be86f64dc76f083 100644 (file)
@@ -39,6 +39,16 @@ struct sandbox_state;
  */
 ssize_t os_read(int fd, void *buf, size_t count);
 
+/**
+ * Access to the OS read() system call with non-blocking access
+ *
+ * \param fd   File descriptor as returned by os_open()
+ * \param buf  Buffer to place data
+ * \param count        Number of bytes to read
+ * \return number of bytes read, or -1 on error
+ */
+ssize_t os_read_no_block(int fd, void *buf, size_t count);
+
 /**
  * Access to the OS write() system call
  *