blob: 9502f055b856c1e5bf35fc8a06a45f2e9ec066df [file] [log] [blame]
Harald Welteff9f4ce2019-02-24 22:51:09 +01001#include <string.h>
2#include <stdint.h>
3#include <stdio.h>
4
5#include <utils.h>
6
7#include "atmel_start.h"
8#include "command.h"
9
10struct cmd_state {
11 const char *prompt;
12 char buf[128];
13 unsigned int buf_idx;
14 const struct command_fn *cmd[32];
15 unsigned int cmd_idx;
16};
17
18static struct cmd_state g_cmds;
19
20int command_register(const struct command_fn *cmd)
21{
22 if (g_cmds.cmd_idx >= ARRAY_SIZE(g_cmds.cmd))
23 return -1;
24 g_cmds.cmd[g_cmds.cmd_idx++] = cmd;
25 return 0;
26}
27
28DEFUN(help, help_cmd, "help", "Print command reference")
29{
30 unsigned int i;
31 printf("Help:\r\n");
32 printf(" Command Help\r\n");
33 printf(" ---------------- ----\r\n");
34 for (i = 0; i < g_cmds.cmd_idx; i++)
35 printf(" %-16s %s\r\n", g_cmds.cmd[i]->command, g_cmds.cmd[i]->help);
36}
37
38static void cmd_execute()
39{
40 char *argv[16];
41 unsigned int i;
42 int argc = 0;
43 char *cur;
44
45 printf("\r\n");
46 memset(argv, 0, sizeof(argv));
47
48 for (cur = strtok(g_cmds.buf, " "); cur; cur = strtok(NULL, " ")) {
49 if (argc >= ARRAY_SIZE(argv))
50 break;
51 argv[argc++] = cur;
52 }
53
54 for (i = 0; i < g_cmds.cmd_idx; i++) {
55 if (!strcmp(g_cmds.cmd[i]->command, argv[0])) {
56 g_cmds.cmd[i]->fn(argc, argv);
57 return;
58 }
59 }
60 printf("Unknown command: '%s'\r\n", argv[0]);
61}
62
63static void cmd_buf_reset(void)
64{
65 memset(g_cmds.buf, 0, sizeof(g_cmds.buf));
66 g_cmds.buf_idx = 0;
67}
68
69static void cmd_buf_append(char c)
70{
71 g_cmds.buf[g_cmds.buf_idx++] = c;
72}
73
74void command_try_recv(void)
75{
76 unsigned int i = 0;
77
78 /* yield CPU after maximum of 10 received characters */
79 while (usart_sync_is_rx_not_empty(&UART_debug) && (i < 10)) {
80 int c = getchar();
81 if (c < 0)
82 return;
83 putchar(c);
84 if (c == '\r' || c == '\n' || g_cmds.buf_idx >= sizeof(g_cmds.buf)-1) {
85 cmd_execute();
86 cmd_buf_reset();
87 printf(g_cmds.prompt);
88 return;
89 }
90 /* append character */
91 cmd_buf_append(c);
92
93 i++;
94 }
95}
96
97void command_init(const char *prompt)
98{
99 g_cmds.prompt = prompt;
100 command_register(&help_cmd);
101}