rk30: fiq serial debugger: add using arrow up and down to search those commands we...
authorhhb <hhb@rock-chips.com>
Sat, 31 Mar 2012 01:58:39 +0000 (09:58 +0800)
committerhhb <hhb@rock-chips.com>
Sat, 31 Mar 2012 01:58:39 +0000 (09:58 +0800)
arch/arm/common/fiq_debugger.c

index a0a5a805dfad9fae707a97737075f51b2c69a79d..d0a8aa8a32160c88f5c56bd8e21bf221603e991b 100644 (file)
@@ -44,6 +44,7 @@
 #include "fiq_debugger_ringbuf.h"
 
 #define DEBUG_MAX 64
+#define CMD_COUNT 0x0f
 #define MAX_UNHANDLED_FIQ_COUNT 1000000
 
 #define THREAD_INFO(sp) ((struct thread_info *) \
@@ -68,6 +69,10 @@ struct fiq_debugger_state {
        char debug_buf[DEBUG_MAX];
        int debug_count;
 
+       char cmd_buf[CMD_COUNT+1][DEBUG_MAX];
+       int back_pointer;
+       int current_pointer;
+
        bool no_sleep;
        bool debug_enable;
        bool ignore_next_wakeup_irq;
@@ -543,14 +548,48 @@ static void do_sysrq(struct fiq_debugger_state *state, char rq)
 /* This function CANNOT be called in FIQ context */
 static void debug_irq_exec(struct fiq_debugger_state *state, char *cmd)
 {
+       int invalid_cmd = 0;
        if (!strcmp(cmd, "ps"))
                do_ps(state);
-       if (!strcmp(cmd, "sysrq"))
+       else if (!strcmp(cmd, "sysrq"))
                do_sysrq(state, 'h');
-       if (!strncmp(cmd, "sysrq ", 6))
+       else if (!strncmp(cmd, "sysrq ", 6))
                do_sysrq(state, cmd[6]);
+       else {
+               invalid_cmd = 1;
+               memset(state->debug_buf, 0, DEBUG_MAX);
+       }
+
+       if (invalid_cmd == 0) {
+               state->current_pointer = (state->current_pointer-1) & CMD_COUNT;
+               if (strcmp(state->cmd_buf[state->current_pointer], state->debug_buf)) {
+                       state->current_pointer = (state->current_pointer+1) & CMD_COUNT;
+                       memset(state->cmd_buf[state->current_pointer], 0, DEBUG_MAX);
+                       strcpy(state->cmd_buf[state->current_pointer], state->debug_buf);
+               }
+               memset(state->debug_buf, 0, DEBUG_MAX);
+               state->current_pointer = (state->current_pointer+1) & CMD_COUNT;
+               state->back_pointer = state->current_pointer;
+       }
 }
 
+static char cmd_buf[][16] = {
+               {"pc"},
+               {"regs"},
+               {"allregs"},
+               {"bt"},
+               {"reboot"},
+               {"irqs"},
+               {"kmsg"},
+               {"version"},
+               {"sleep"},
+               {"nosleep"},
+               {"console"},
+               {"cpu"},
+               {"ps"},
+               {"sysrq"},
+};
+
 static void debug_help(struct fiq_debugger_state *state)
 {
        debug_printf(state,     "FIQ Debugger commands:\n"
@@ -745,6 +784,109 @@ static int debug_getc(struct fiq_debugger_state *state)
        return state->pdata->uart_getc(state->pdev);
 }
 
+
+static int debug_cmd_check_back(struct fiq_debugger_state *state, char c)
+{
+       char *s;
+       int i = 0;
+       if (c == 'A') {
+               state->back_pointer = (state->back_pointer-1) & CMD_COUNT;
+               if (state->back_pointer != state->current_pointer) {
+                       s = state->cmd_buf[state->back_pointer];
+                       if (*s != 0) {
+                               for(i = 0; i < strlen(state->debug_buf)-1; i++) {
+                                       state->pdata->uart_putc(state->pdev, 8);
+                                       state->pdata->uart_putc(state->pdev, ' ');
+                                       state->pdata->uart_putc(state->pdev, 8);
+                               }
+                               memset(state->debug_buf, 0, DEBUG_MAX);
+                               strcpy(state->debug_buf, s);
+                               state->debug_count = strlen(state->debug_buf);
+                               debug_printf(state, state->debug_buf);
+                       } else {
+                               state->back_pointer = (state->back_pointer+1) & CMD_COUNT;
+                       }
+
+               } else {
+                       state->back_pointer = (state->back_pointer+1) & CMD_COUNT;
+               }
+       } else if (c == 'B') {
+
+               if (state->back_pointer != state->current_pointer) {
+                       state->back_pointer = (state->back_pointer+1) & CMD_COUNT;
+                       if(state->back_pointer == state->current_pointer){
+                               goto cmd_clear;
+                       } else {
+                               s = state->cmd_buf[state->back_pointer];
+                               if (*s != 0) {
+                                       for(i = 0; i < strlen(state->debug_buf)-1; i++) {
+                                               state->pdata->uart_putc(state->pdev, 8);
+                                               state->pdata->uart_putc(state->pdev, ' ');
+                                               state->pdata->uart_putc(state->pdev, 8);
+                                       }
+                                       memset(state->debug_buf, 0, DEBUG_MAX);
+                                       strcpy(state->debug_buf, s);
+                                       state->debug_count = strlen(state->debug_buf);
+                                       debug_printf(state, state->debug_buf);
+                               }
+                       }
+               } else {
+cmd_clear:
+                       for(i = 0; i < strlen(state->debug_buf)-1; i++) {
+                               state->pdata->uart_putc(state->pdev, 8);
+                               state->pdata->uart_putc(state->pdev, ' ');
+                               state->pdata->uart_putc(state->pdev, 8);
+                       }
+                       memset(state->debug_buf, 0, DEBUG_MAX);
+                       state->debug_count = 0;
+               }
+       }
+       return 0;
+}
+
+static void debug_cmd_tab(struct fiq_debugger_state *state)
+{
+       int i,j;
+       int count = 0;
+
+       for (i = 0; i < ARRAY_SIZE(cmd_buf); i++) {
+               cmd_buf[i][15] = 1;
+       }
+
+       for (j = 1; j <= strlen(state->debug_buf); j++) {
+               count = 0;
+               for (i = 0; i < ARRAY_SIZE(cmd_buf); i++) {
+                       if (cmd_buf[i][15] == 1) {
+                               if (strncmp(state->debug_buf, cmd_buf[i], j)) {
+                                       cmd_buf[i][15] = 0;
+                               } else {
+                                       count++;
+                               }
+                       }
+               }
+               if (count == 0)
+                       break;
+       }
+
+       if (count == 1) {
+               for (i = 0; i < ARRAY_SIZE(cmd_buf); i++) {
+                       if (cmd_buf[i][15] == 1)
+                               break;
+               }
+
+               for(j = 0; j < strlen(state->debug_buf); j++) {
+                       state->pdata->uart_putc(state->pdev, 8);
+                       state->pdata->uart_putc(state->pdev, ' ');
+                       state->pdata->uart_putc(state->pdev, 8);
+               }
+               memset(state->debug_buf, 0, DEBUG_MAX);
+               strcpy(state->debug_buf, cmd_buf[i]);
+               state->debug_count = strlen(state->debug_buf);
+               debug_printf(state, state->debug_buf);
+
+       }
+}
+
 static bool debug_handle_uart_interrupt(struct fiq_debugger_state *state,
                        int this_cpu, void *regs, void *svc_sp)
 {
@@ -784,12 +926,26 @@ static bool debug_handle_uart_interrupt(struct fiq_debugger_state *state,
                        state->console_enable = false;
                        debug_puts(state, "fiq debugger mode\n");
                        state->debug_count = 0;
+                       state->back_pointer = CMD_COUNT;
+                       state->current_pointer = CMD_COUNT;
+                       memset(state->cmd_buf, 0, (CMD_COUNT+1)*DEBUG_MAX);
                        debug_prompt(state);
 #ifdef CONFIG_FIQ_DEBUGGER_CONSOLE
                } else if (state->console_enable && state->tty_rbuf) {
                        fiq_debugger_ringbuf_push(state->tty_rbuf, c);
                        signal_helper = true;
 #endif
+               } else if (last_c == '[' && (c == 'A' || c == 'B' || c == 'C' || c == 'D')) {
+                       if (state->debug_count > 0) {
+                               state->debug_count--;
+                               state->pdata->uart_putc(state->pdev, 8);
+                               state->pdata->uart_putc(state->pdev, ' ');
+                               state->pdata->uart_putc(state->pdev, 8);
+                       }
+                       debug_cmd_check_back(state, c);
+                       //tab
+               } else if (c == 9) {
+                       debug_cmd_tab(state);
                } else if ((c >= ' ') && (c < 127)) {
                        if (state->debug_count < (DEBUG_MAX - 1)) {
                                state->debug_buf[state->debug_count++] = c;
@@ -801,6 +957,7 @@ static bool debug_handle_uart_interrupt(struct fiq_debugger_state *state,
                                state->pdata->uart_putc(state->pdev, 8);
                                state->pdata->uart_putc(state->pdev, ' ');
                                state->pdata->uart_putc(state->pdev, 8);
+                               state->debug_buf[state->debug_count] = 0;
                        }
                } else if ((c == 13) || (c == 10)) {
                        if (c == '\r' || (c == '\n' && last_c != '\r')) {
@@ -813,6 +970,17 @@ static bool debug_handle_uart_interrupt(struct fiq_debugger_state *state,
                                signal_helper |=
                                        debug_fiq_exec(state, state->debug_buf,
                                                       regs, svc_sp);
+                               if (signal_helper == false) {
+                                       state->current_pointer = (state->current_pointer-1) & CMD_COUNT;
+                                       if (strcmp(state->cmd_buf[state->current_pointer], state->debug_buf)) {
+                                               state->current_pointer = (state->current_pointer+1) & CMD_COUNT;
+                                               memset(state->cmd_buf[state->current_pointer], 0, DEBUG_MAX);
+                                               strcpy(state->cmd_buf[state->current_pointer], state->debug_buf);
+                                       }
+                                       memset(state->debug_buf, 0, DEBUG_MAX);
+                                       state->current_pointer = (state->current_pointer+1) & CMD_COUNT;
+                                       state->back_pointer = state->current_pointer;
+                               }
                        } else {
                                debug_prompt(state);
                        }