sandbox: Allow Ctrl-C to work in sandbox
authorSimon Glass <sjg@chromium.org>
Thu, 27 Feb 2014 20:26:22 +0000 (13:26 -0700)
committerSimon Glass <sjg@chromium.org>
Tue, 18 Mar 2014 02:05:49 +0000 (20:05 -0600)
It is useful for Cltl-C to be handled by U-Boot as it is on other boards.
But it is also useful to be able to terminate U-Boot with Ctrl-C.

Add an option to enable signals while in raw mode, and make this the
default. Add an option to leave the terminal cooked, which is useful for
redirecting output.

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

index 52e1096f36ce18d66623db607acd7f8dfd03d79d..9de71bb2b4ff21d210950f555b12d52121293866 100644 (file)
@@ -104,21 +104,22 @@ void os_exit(int exit_code)
 
 /* Restore tty state when we exit */
 static struct termios orig_term;
+static bool term_setup;
 
 static void os_fd_restore(void)
 {
-       tcsetattr(0, TCSANOW, &orig_term);
+       if (term_setup)
+               tcsetattr(0, TCSANOW, &orig_term);
 }
 
 /* Put tty into raw mode so <tab> and <ctrl+c> work */
-void os_tty_raw(int fd)
+void os_tty_raw(int fd, bool allow_sigs)
 {
-       static int setup = 0;
        struct termios term;
 
-       if (setup)
+       if (term_setup)
                return;
-       setup = 1;
+       term_setup = true;
 
        /* If not a tty, don't complain */
        if (tcgetattr(fd, &orig_term))
@@ -128,7 +129,7 @@ void os_tty_raw(int fd)
        term.c_iflag = IGNBRK | IGNPAR;
        term.c_oflag = OPOST | ONLCR;
        term.c_cflag = CS8 | CREAD | CLOCAL;
-       term.c_lflag = 0;
+       term.c_lflag = allow_sigs ? ISIG : 0;
        if (tcsetattr(fd, TCSANOW, &term))
                return;
 
index 4d5569e6476725d1f2a099a07369e40bd5237914..36dfc0a408e960cc2dde7723f14cfc3c4a2a1e58 100644 (file)
@@ -184,6 +184,34 @@ static int sandbox_cmdline_cb_show_lcd(struct sandbox_state *state,
 SANDBOX_CMDLINE_OPT_SHORT(show_lcd, 'l', 0,
                          "Show the sandbox LCD display");
 
+static const char *term_args[STATE_TERM_COUNT] = {
+       "raw-with-sigs",
+       "raw",
+       "cooked",
+};
+
+static int sandbox_cmdline_cb_terminal(struct sandbox_state *state,
+                                      const char *arg)
+{
+       int i;
+
+       for (i = 0; i < STATE_TERM_COUNT; i++) {
+               if (!strcmp(arg, term_args[i])) {
+                       state->term_raw = i;
+                       return 0;
+               }
+       }
+
+       printf("Unknown terminal setting '%s' (", arg);
+       for (i = 0; i < STATE_TERM_COUNT; i++)
+               printf("%s%s", i ? ", " : "", term_args[i]);
+       puts(")\n");
+
+       return 1;
+}
+SANDBOX_CMDLINE_OPT_SHORT(terminal, 't', 1,
+                         "Set terminal to raw/cooked mode");
+
 int main(int argc, char *argv[])
 {
        struct sandbox_state *state;
index 895b3a4ec7b3b5f2add23d03f25dbf0511dcab79..56bd9a07b62c7e95292f5767d3c7f0e6bb79ab0b 100644 (file)
@@ -17,6 +17,29 @@ enum exit_type_id {
        STATE_EXIT_POWER_OFF,
 };
 
+/**
+ * Selects the behavior of the serial terminal.
+ *
+ * If Ctrl-C is processed by U-Boot, then the only way to quit sandbox is with
+ * the 'reset' command, or equivalent.
+ *
+ * If the terminal is cooked, then Ctrl-C will terminate U-Boot, and the
+ * command line will not be quite such a faithful emulation.
+ *
+ * Options are:
+ *
+ *     raw-with-sigs           - Raw, but allow signals (Ctrl-C will quit)
+ *     raw                     - Terminal is always raw
+ *     cooked                  - Terminal is always cooked
+ */
+enum state_terminal_raw {
+       STATE_TERM_RAW_WITH_SIGS,       /* Default */
+       STATE_TERM_RAW,
+       STATE_TERM_COOKED,
+
+       STATE_TERM_COUNT,
+};
+
 struct sandbox_spi_info {
        const char *spec;
        const struct sandbox_spi_emu_ops *ops;
@@ -42,6 +65,7 @@ struct sandbox_state {
        bool write_state;               /* Write sandbox state on exit */
        bool ignore_missing_state_on_read;      /* No error if state missing */
        bool show_lcd;                  /* Show LCD on start-up */
+       enum state_terminal_raw term_raw;       /* Terminal raw/cooked */
 
        /* Pointer to information for each SPI bus/cs */
        struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS]
index c27b5b8fe52b4420e2b5b6160d193a758eff8653..51fd871dff9b3fbfd939ac4cd6d54c88bb01502f 100644 (file)
@@ -15,6 +15,7 @@
 #include <os.h>
 #include <serial.h>
 #include <linux/compiler.h>
+#include <asm/state.h>
 
 /*
  *
@@ -31,7 +32,10 @@ static unsigned int serial_buf_read;
 
 static int sandbox_serial_init(void)
 {
-       os_tty_raw(0);
+       struct sandbox_state *state = state_get_current();
+
+       if (state->term_raw != STATE_TERM_COOKED)
+               os_tty_raw(0, state->term_raw == STATE_TERM_RAW_WITH_SIGS);
        return 0;
 }
 
index 9b5da5c43d5845fe40af9edd6d637e08aaaff91f..0230a7f40da07893ff2d9d92f1929e7b9cabc1d2 100644 (file)
@@ -103,8 +103,12 @@ void os_exit(int exit_code) __attribute__((noreturn));
 
 /**
  * Put tty into raw mode to mimic serial console better
+ *
+ * @param fd           File descriptor of stdin (normally 0)
+ * @param allow_sigs   Allow Ctrl-C, Ctrl-Z to generate signals rather than
+ *                     be handled by U-Boot
  */
-void os_tty_raw(int fd);
+void os_tty_raw(int fd, bool allow_sigs);
 
 /**
  * Acquires some memory from the underlying os.