<p>Kévin Redon <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/13036">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Kévin Redon: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Add mnimalistic command line interface "command.c"<br><br>This is a very simplistic command line interface parser which<br>various parts of the code can use to register textual commands<br>on the debug UART.<br><br>Change-Id: I2d289228fb97ecde5602e9756f3d7c51fa65a3b7<br>---<br>A sysmoOCTSIM/command.c<br>A sysmoOCTSIM/command.h<br>M sysmoOCTSIM/gcc/Makefile<br>M sysmoOCTSIM/main.c<br>4 files changed, 135 insertions(+), 5 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/sysmoOCTSIM/command.c b/sysmoOCTSIM/command.c</span><br><span>new file mode 100644</span><br><span>index 0000000..9502f05</span><br><span>--- /dev/null</span><br><span>+++ b/sysmoOCTSIM/command.c</span><br><span>@@ -0,0 +1,101 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "atmel_start.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "command.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct cmd_state {</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *prompt;</span><br><span style="color: hsl(120, 100%, 40%);">+   char buf[128];</span><br><span style="color: hsl(120, 100%, 40%);">+        unsigned int buf_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct command_fn *cmd[32];</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int cmd_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct cmd_state g_cmds;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int command_register(const struct command_fn *cmd)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (g_cmds.cmd_idx >= ARRAY_SIZE(g_cmds.cmd))</span><br><span style="color: hsl(120, 100%, 40%);">+              return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    g_cmds.cmd[g_cmds.cmd_idx++] = cmd;</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(help, help_cmd, "help", "Print command reference")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+       printf("Help:\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        printf(" Command          Help\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       printf(" ---------------- ----\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 0; i < g_cmds.cmd_idx; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+               printf(" %-16s %s\r\n", g_cmds.cmd[i]->command, g_cmds.cmd[i]->help);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void cmd_execute()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      char *argv[16];</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+       int argc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *cur;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+     memset(argv, 0, sizeof(argv));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      for (cur = strtok(g_cmds.buf, " "); cur; cur = strtok(NULL, " ")) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (argc >= ARRAY_SIZE(argv))</span><br><span style="color: hsl(120, 100%, 40%);">+                      break;</span><br><span style="color: hsl(120, 100%, 40%);">+                argv[argc++] = cur;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < g_cmds.cmd_idx; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (!strcmp(g_cmds.cmd[i]->command, argv[0])) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    g_cmds.cmd[i]->fn(argc, argv);</span><br><span style="color: hsl(120, 100%, 40%);">+                     return;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("Unknown command: '%s'\r\n", argv[0]);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void cmd_buf_reset(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      memset(g_cmds.buf, 0, sizeof(g_cmds.buf));</span><br><span style="color: hsl(120, 100%, 40%);">+    g_cmds.buf_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void cmd_buf_append(char c)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       g_cmds.buf[g_cmds.buf_idx++] = c;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void command_try_recv(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        unsigned int i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* yield CPU after maximum of 10 received characters */</span><br><span style="color: hsl(120, 100%, 40%);">+       while (usart_sync_is_rx_not_empty(&UART_debug) && (i < 10)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          int c = getchar();</span><br><span style="color: hsl(120, 100%, 40%);">+            if (c < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                 return;</span><br><span style="color: hsl(120, 100%, 40%);">+               putchar(c);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (c == '\r' || c == '\n' || g_cmds.buf_idx >= sizeof(g_cmds.buf)-1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    cmd_execute();</span><br><span style="color: hsl(120, 100%, 40%);">+                        cmd_buf_reset();</span><br><span style="color: hsl(120, 100%, 40%);">+                      printf(g_cmds.prompt);</span><br><span style="color: hsl(120, 100%, 40%);">+                        return;</span><br><span style="color: hsl(120, 100%, 40%);">+               }</span><br><span style="color: hsl(120, 100%, 40%);">+             /* append character */</span><br><span style="color: hsl(120, 100%, 40%);">+                cmd_buf_append(c);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          i++;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void command_init(const char *prompt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      g_cmds.prompt = prompt;</span><br><span style="color: hsl(120, 100%, 40%);">+       command_register(&help_cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/sysmoOCTSIM/command.h b/sysmoOCTSIM/command.h</span><br><span>new file mode 100644</span><br><span>index 0000000..cdf256d</span><br><span>--- /dev/null</span><br><span>+++ b/sysmoOCTSIM/command.h</span><br><span>@@ -0,0 +1,20 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct command_fn {</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *command;</span><br><span style="color: hsl(120, 100%, 40%);">+  const char *help;</span><br><span style="color: hsl(120, 100%, 40%);">+     void (*fn)(int argc, char **argv);</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEFUN(funcname, cmdname, cmdstr, helpstr)     \</span><br><span style="color: hsl(120, 100%, 40%);">+     static void funcname(int argc, char **argv);            \</span><br><span style="color: hsl(120, 100%, 40%);">+     static struct command_fn cmdname = {                    \</span><br><span style="color: hsl(120, 100%, 40%);">+             .command = cmdstr,                              \</span><br><span style="color: hsl(120, 100%, 40%);">+             .help = helpstr,                                \</span><br><span style="color: hsl(120, 100%, 40%);">+             .fn = funcname,                                 \</span><br><span style="color: hsl(120, 100%, 40%);">+     };                                                      \</span><br><span style="color: hsl(120, 100%, 40%);">+     static void funcname(int argc, char **argv)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void command_init(const char *prompt);</span><br><span style="color: hsl(120, 100%, 40%);">+int command_register(const struct command_fn *cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+void command_try_recv(void);</span><br><span>diff --git a/sysmoOCTSIM/gcc/Makefile b/sysmoOCTSIM/gcc/Makefile</span><br><span>index 1c90257..7496377 100644</span><br><span>--- a/sysmoOCTSIM/gcc/Makefile</span><br><span>+++ b/sysmoOCTSIM/gcc/Makefile</span><br><span>@@ -80,6 +80,7 @@</span><br><span> i2c_bitbang.o \</span><br><span> octsim_i2c.o \</span><br><span> ncn8025.o \</span><br><span style="color: hsl(120, 100%, 40%);">+command.o \</span><br><span> hpl/osc32kctrl/hpl_osc32kctrl.o \</span><br><span> examples/driver_examples.o \</span><br><span> driver_init.o \</span><br><span>@@ -126,6 +127,7 @@</span><br><span> "i2c_bitbang.o" \</span><br><span> "octsim_i2c.o" \</span><br><span> "ncn8025.o" \</span><br><span style="color: hsl(120, 100%, 40%);">+"command.o" \</span><br><span> "hpl/osc32kctrl/hpl_osc32kctrl.o" \</span><br><span> "examples/driver_examples.o" \</span><br><span> "driver_init.o" \</span><br><span>@@ -178,6 +180,7 @@</span><br><span> "i2c_bitbang.d" \</span><br><span> "octsim_i2c.d" \</span><br><span> "ncn8025.d" \</span><br><span style="color: hsl(120, 100%, 40%);">+"command.d" \</span><br><span> "examples/driver_examples.d" \</span><br><span> "hal/src/hal_cache.d" \</span><br><span> "hal/src/hal_sleep.d" \</span><br><span>diff --git a/sysmoOCTSIM/main.c b/sysmoOCTSIM/main.c</span><br><span>index c79d5aa..ef87162 100644</span><br><span>--- a/sysmoOCTSIM/main.c</span><br><span>+++ b/sysmoOCTSIM/main.c</span><br><span>@@ -27,6 +27,8 @@</span><br><span> #include "octsim_i2c.h"</span><br><span> #include "ncn8025.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include "command.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> static void board_init()</span><br><span> {</span><br><span>@@ -47,6 +49,12 @@</span><br><span>   hri_port_set_PINCFG_DRVSTR_bit(PORT, 0, 11);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+DEFUN(hello_fn, cmd_hello,</span><br><span style="color: hsl(120, 100%, 40%);">+     "hello", "Hello World example command")</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        printf("Hello World!\r\n");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int main(void)</span><br><span> {</span><br><span>    atmel_start_init();</span><br><span>@@ -56,13 +64,11 @@</span><br><span>    usb_start();</span><br><span> </span><br><span>     board_init();</span><br><span style="color: hsl(120, 100%, 40%);">+ command_init("sysmoOCTSIM> ");</span><br><span style="color: hsl(120, 100%, 40%);">+   command_register(&cmd_hello);</span><br><span> </span><br><span>        printf("\r\n\r\nsysmocom sysmoOCTSIM\r\n");</span><br><span>        while (true) { // main loop</span><br><span style="color: hsl(0, 100%, 40%);">-             if (usart_sync_is_rx_not_empty(&UART_debug)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      gpio_toggle_pin_level(USER_LED);</span><br><span style="color: hsl(0, 100%, 40%);">-                        int c = getchar();</span><br><span style="color: hsl(0, 100%, 40%);">-                      putchar(c);</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(120, 100%, 40%);">+             command_try_recv();</span><br><span>  }</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13036">change 13036</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/13036"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-ccid-firmware </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I2d289228fb97ecde5602e9756f3d7c51fa65a3b7 </div>
<div style="display:none"> Gerrit-Change-Number: 13036 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>
<div style="display:none"> Gerrit-Reviewer: Kévin Redon <kredon@sysmocom.de> </div>