Project

General

Profile

Download (3.77 KB) Statistics
| Branch: | Tag: | Revision:
1

    
2
/* (C) 2012 by Harald Welte <laforge@gnumonks.org>
3
 *
4
 * All Rights Reserved
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19

    
20
#include <string.h>
21
#include <stdint.h>
22
#include <stdio.h>
23
#include <errno.h>
24
#include <stdarg.h>
25

    
26
#include <uart_cmd.h>
27

    
28
void strbuf_reset(struct strbuf *sb)
29
{
30
	sb->idx = 0;
31
	memset(sb->buf, 0, sizeof(sb->buf));
32
}
33

    
34
void strbuf_append(struct strbuf *sb, char ch)
35
{
36
	if (sb->idx < sizeof(sb->buf)-1)
37
		sb->buf[sb->idx++] = ch;
38
}
39

    
40
static LLIST_HEAD(cmd_list);
41

    
42
void uart_cmd_register(struct cmd *c)
43
{
44
	llist_add_tail(&c->list, &cmd_list);
45
}
46

    
47
void uart_cmd_unregister(struct cmd *c)
48
{
49
	llist_del(&c->list);
50
}
51

    
52
void uart_cmds_register(struct cmd *c, unsigned int num)
53
{
54
	int i;
55

    
56
	for (i = 0; i < num; i++)
57
		uart_cmd_register(&c[i]);
58
}
59

    
60
#define CMD_MAX_ARGS	10
61

    
62
static int handle_cb(struct cmd_state *cs, int op, char *cmd, char *arg)
63
{
64
	struct cmd *c;
65
	int rc;
66
	char *argv[CMD_MAX_ARGS];
67
	int argc = 0;
68

    
69
	if (arg) {
70
		char *tok;
71
		/* tokenize the argument portion into individual arguments */
72
		for (tok = strtok(arg, ","); tok; tok = strtok(NULL, ",")) {
73
			if (argc >= CMD_MAX_ARGS)
74
				break;
75
			argv[argc++] = tok;
76
		}
77
	}
78

    
79
	llist_for_each_entry(c, &cmd_list, list) {
80
		if (!strcmp(c->cmd, cmd)) {
81
			if (!(c->ops & op)) {
82
				uart_cmd_out(cs, "Command `%s' doesn't "
83
					     "support this operation\n\r", c->cmd);
84
				return -EINVAL;
85
			}
86

    
87
			rc = c->cb(cs, op, cmd, argc, argv);
88
			if (rc < 0)
89
				uart_cmd_out(cs, "Error executing command\n\r");
90
			return rc;
91
		}
92
	}
93

    
94
	uart_cmd_out(cs, "Unknown command `%s'\n\r", cmd);
95
	return -EINVAL;
96
}
97

    
98
static void print_list(struct cmd_state *cs)
99
{
100
	struct cmd *c;
101

    
102
	uart_cmd_out(cs, "Supported commands:\r\n");
103

    
104
	llist_for_each_entry(c, &cmd_list, list){
105
		const char *help = "";
106

    
107
		if (c->help)
108
			help = c->help;
109

    
110
		uart_cmd_out(cs, "%s  --  %s\n\r", c->cmd, c->help);
111
	}
112
}
113

    
114
int uart_cmd_char(struct cmd_state *cs, uint8_t ch)
115
{
116
	int rc;
117

    
118
	uart_cmd_out(cs, "%c", ch);
119

    
120
	switch (cs->state) {
121
	case ST_IN_CMD:
122
		switch (ch) {
123
		case '=':
124
			cs->state = ST_IN_ARG;
125
			break;
126
		case '?':
127
			uart_cmd_out(cs, "\n\r");
128
			if (cs->cmd.idx == 0)
129
				print_list(cs);
130
			else
131
				rc = handle_cb(cs, CMD_OP_GET, cs->cmd.buf, NULL);
132
			uart_cmd_reset(cs);
133
			break;
134
		case '!':
135
			uart_cmd_out(cs, "\n\r");
136
			rc = handle_cb(cs, CMD_OP_EXEC, cs->cmd.buf, NULL);
137
			uart_cmd_reset(cs);
138
			break;
139
		case ' ':
140
		case '\t':
141
			/* ignore any whitespace */
142
			break;
143
		case '\n':
144
		case '\r':
145
			/* new line always resets buffer */
146
			uart_cmd_reset(cs);
147
			break;
148
		default:
149
			strbuf_append(&cs->cmd, ch);
150
			break;
151
		}
152
		break;
153
	case ST_IN_ARG:
154
		switch (ch) {
155
		case '\r':
156
			uart_cmd_out(cs, "\n");
157
			/* fall through */
158
		case '\n':
159
			rc = handle_cb(cs, CMD_OP_SET, cs->cmd.buf, cs->arg.buf);
160
			uart_cmd_reset(cs);
161
			break;
162
		case ' ':
163
		case '\t':
164
			/* ignore any whitespace */
165
			break;
166
		default:
167
			strbuf_append(&cs->arg, ch);
168
			break;
169
		}
170
	}
171

    
172
	if (ch == '\r')
173
		return 1;
174

    
175
	return 0;
176
}
177

    
178
int uart_cmd_out(struct cmd_state *cs, char *format, ...)
179
{
180
	va_list ap;
181

    
182
	va_start(ap, format);
183
	cs->out(format, ap);
184
	va_end(ap);
185
}
186

    
187
int uart_cmd_reset(struct cmd_state *cs)
188
{
189
	strbuf_reset(&cs->cmd);
190
	strbuf_reset(&cs->arg);
191
	cs->state = ST_IN_CMD;
192

    
193
	uart_cmd_out(cs, "\r\n > ");
194

    
195
	return 0;
196
}
(11-11/11)
Add picture from clipboard (Maximum size: 48.8 MB)