Update
[hackover2013-badge-firmware.git] / core / cmd / cmd.c
1 /*******************************************************************
2 Copyright (C) 2009 FreakLabs
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 3. Neither the name of the the copyright holder nor the names of its contributors
15 may be used to endorse or promote products derived from this software
16 without specific prior written permission.
17
18 THIS SOFTWARE IS PROVIDED BY THE THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
22 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 SUCH DAMAGE.
29
30 Originally written by Christopher Wang aka Akiba.
31 Please post support questions to the FreakLabs forum.
32 *******************************************************************/
33
34 /**************************************************************************/
35 /*!
36 @file cmd.c
37 @author Christopher Wang (Freaklabs)
38 Modified by: K. Townsend (microBuilder.eu)
39 @date 19 May 2010
40
41 Original code taken from the FreakUSB Open Source USB Device Stack
42 http://freaklabs.org/index.php/FreakUSB-Open-Source-USB-Device-Stack.html
43
44 If it works well, you can thank Akiba at Freaklabs. If it fails
45 miserably, you can blame me (since parts of it it were rather
46 ungraciously modified). :-)
47
48 */
49 /**************************************************************************/
50
51 #include <stdio.h>
52 #include <string.h>
53
54 #include "cmd.h"
55 #include "project/cmd_tbl.h"
56
57 #ifdef CFG_PRINTF_UART
58 #include "core/uart/uart.h"
59 #endif
60
61 #ifdef CFG_PRINTF_USBCDC
62 #include "core/usbcdc/cdcuser.h"
63 static char usbcdcBuf [32];
64 #endif
65
66 #if CFG_INTERFACE_ENABLEIRQ == 1
67 #include "core/gpio/gpio.h"
68 #endif
69
70 static uint8_t msg[CFG_INTERFACE_MAXMSGSIZE];
71 static uint8_t *msg_ptr;
72
73 /**************************************************************************/
74 /*!
75 @brief Polls the relevant incoming message queue to see if anything
76 is waiting to be processed.
77 */
78 /**************************************************************************/
79 void cmdPoll()
80 {
81 #if defined CFG_PRINTF_UART
82 while (uartRxBufferDataPending())
83 {
84 uint8_t c = uartRxBufferRead();
85 cmdRx(c);
86 }
87 #endif
88
89 #if defined CFG_PRINTF_USBCDC
90 int numBytesToRead, numBytesRead, numAvailByte;
91
92 CDC_OutBufAvailChar (&numAvailByte);
93 if (numAvailByte > 0)
94 {
95 numBytesToRead = numAvailByte > 32 ? 32 : numAvailByte;
96 numBytesRead = CDC_RdOutBuf (&usbcdcBuf[0], &numBytesToRead);
97 int i;
98 for (i = 0; i < numBytesRead; i++)
99 {
100 cmdRx(usbcdcBuf[i]);
101 }
102 }
103 #endif
104 }
105
106 /**************************************************************************/
107 /*!
108 @brief Handles a single incoming character. If a new line is
109 detected, the entire command will be passed to the command
110 parser. If a text character is detected, it will be added to
111 the message buffer until a new line is detected (up to the
112 maximum queue size, CFG_INTERFACE_MAXMSGSIZE).
113
114 @param[in] c
115 The character to parse.
116 */
117 /**************************************************************************/
118 void cmdRx(uint8_t c)
119 {
120 // read out the data in the buffer and echo it back to the host.
121 switch (c)
122 {
123 case '\r':
124 #if CFG_INTERFACE_DROPCR == 1
125 break;
126 #endif
127 case '\n':
128 // terminate the msg and reset the msg ptr. then send
129 // it to the handler for processing.
130 *msg_ptr = '\0';
131 #if CFG_INTERFACE_SILENTMODE == 0
132 printf("%s", CFG_PRINTF_NEWLINE);
133 #endif
134 cmdParse((char *)msg);
135 msg_ptr = msg;
136 break;
137
138 case '\b':
139 #if CFG_INTERFACE_SILENTMODE == 0
140 printf("%c",c);
141 #endif
142 if (msg_ptr == msg)
143 {
144 // Send bell alert and space (to maintain position)
145 printf("\a ");
146 }
147 else if (msg_ptr > msg)
148 {
149 msg_ptr--;
150 }
151 break;
152
153 default:
154 #if CFG_INTERFACE_SILENTMODE == 0
155 printf("%c",c);
156 #endif
157 *msg_ptr++ = c;
158 break;
159 }
160 }
161
162 /**************************************************************************/
163 /*!
164 @brief Displays the command prompt. The text that appears is defined
165 in projectconfig.h.
166 */
167 /**************************************************************************/
168 static void cmdMenu()
169 {
170 #if CFG_INTERFACE_SILENTMODE == 0
171 printf(CFG_PRINTF_NEWLINE);
172 printf(CFG_INTERFACE_PROMPT);
173 #endif
174 #if CFG_INTERFACE_CONFIRMREADY == 1
175 printf("%s%s", CFG_INTERFACE_CONFIRMREADY_TEXT, CFG_PRINTF_NEWLINE);
176 #endif
177 }
178
179 /**************************************************************************/
180 /*!
181 @brief Parse the command line. This function tokenizes the command
182 input, then searches for the command table entry associated
183 with the commmand. Once found, it will jump to the
184 corresponding function.
185
186 @param[in] cmd
187 The entire command string to be parsed
188 */
189 /**************************************************************************/
190 void cmdParse(char *cmd)
191 {
192 size_t argc, i = 0;
193 char *argv[30];
194
195 argv[i] = strtok(cmd, " ");
196 do
197 {
198 argv[++i] = strtok(NULL, " ");
199 } while ((i < 30) && (argv[i] != NULL));
200
201 argc = i;
202 for (i=0; i < CMD_COUNT; i++)
203 {
204 if (!strcmp(argv[0], cmd_tbl[i].command))
205 {
206 if ((argc == 2) && !strcmp (argv [1], "?"))
207 {
208 // Display parameter help menu on 'command ?'
209 printf ("%s%s%s", cmd_tbl[i].description, CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
210 printf ("%s%s", cmd_tbl[i].parameters, CFG_PRINTF_NEWLINE);
211 }
212 else if ((argc - 1) < cmd_tbl[i].minArgs)
213 {
214 // Too few arguments supplied
215 #if CFG_INTERFACE_SHORTERRORS == 1
216 printf ("%s%s", CFG_INTERFACE_SHORTERRORS_TOOFEWARGS, CFG_PRINTF_NEWLINE);
217 #else
218 printf ("Too few arguments (%d expected)%s", cmd_tbl[i].minArgs, CFG_PRINTF_NEWLINE);
219 printf ("%sType '%s ?' for more information%s%s", CFG_PRINTF_NEWLINE, cmd_tbl[i].command, CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
220 #endif
221 }
222 else if ((argc - 1) > cmd_tbl[i].maxArgs)
223 {
224 // Too many arguments supplied
225 #if CFG_INTERFACE_SHORTERRORS == 1
226 printf ("%s%s", CFG_INTERFACE_SHORTERRORS_TOOMANYARGS, CFG_PRINTF_NEWLINE);
227 #else
228 printf ("Too many arguments (%d maximum)%s", cmd_tbl[i].maxArgs, CFG_PRINTF_NEWLINE);
229 printf ("%sType '%s ?' for more information%s%s", CFG_PRINTF_NEWLINE, cmd_tbl[i].command, CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
230 #endif
231 }
232 else
233 {
234 #if CFG_INTERFACE_ENABLEIRQ != 0
235 // Set the IRQ pin high at start of a command
236 gpioSetValue(CFG_INTERFACE_IRQPORT, CFG_INTERFACE_IRQPIN, 1);
237 #endif
238 // Dispatch command to the appropriate function
239 cmd_tbl[i].func(argc - 1, &argv [1]);
240 #if CFG_INTERFACE_ENABLEIRQ != 0
241 // Set the IRQ pin low to signal the end of a command
242 gpioSetValue(CFG_INTERFACE_IRQPORT, CFG_INTERFACE_IRQPIN, 0);
243 #endif
244 }
245
246 // Refresh the command prompt
247 cmdMenu();
248 return;
249 }
250 }
251 // Command not recognized
252 #if CFG_INTERFACE_SHORTERRORS == 1
253 printf ("%s%s", CFG_INTERFACE_SHORTERRORS_UNKNOWNCOMMAND, CFG_PRINTF_NEWLINE);
254 #else
255 printf("Command not recognized: '%s'%s%s", cmd, CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
256 #if CFG_INTERFACE_SILENTMODE == 0
257 printf("Type '?' for a list of all available commands%s", CFG_PRINTF_NEWLINE);
258 #endif
259 #endif
260
261 cmdMenu();
262 }
263
264 /**************************************************************************/
265 /*!
266 @brief Initialises the command line using the appropriate interface
267 */
268 /**************************************************************************/
269 void cmdInit()
270 {
271 #if defined CFG_INTERFACE && defined CFG_INTERFACE_UART
272 // Check if UART is already initialised
273 uart_pcb_t *pcb = uartGetPCB();
274 if (!pcb->initialised)
275 {
276 uartInit(CFG_UART_BAUDRATE);
277 }
278 #endif
279
280 #if CFG_INTERFACE_ENABLEIRQ != 0
281 // Set IRQ pin as output
282 gpioSetDir(CFG_INTERFACE_IRQPORT, CFG_INTERFACE_IRQPIN, gpioDirection_Output);
283 gpioSetValue(CFG_INTERFACE_IRQPORT, CFG_INTERFACE_IRQPIN, 1);
284 #endif
285
286 // init the msg ptr
287 msg_ptr = msg;
288
289 // Show the menu
290 cmdMenu();
291
292 // Set the IRQ pin low by default
293 #if CFG_INTERFACE_ENABLEIRQ != 0
294 gpioSetValue(CFG_INTERFACE_IRQPORT, CFG_INTERFACE_IRQPIN, 0);
295 #endif
296 }
297
298 /**************************************************************************/
299 /*!
300 'help' command handler
301 */
302 /**************************************************************************/
303 void cmd_help(uint8_t argc, char **argv)
304 {
305 size_t i;
306
307 printf("Command Description%s", CFG_PRINTF_NEWLINE);
308 printf("------- -----------%s", CFG_PRINTF_NEWLINE);
309
310 // Display full command list
311 for (i=0; i < CMD_COUNT; i++)
312 {
313 if (!cmd_tbl[i].hidden)
314 {
315 printf ("%-10s %s%s", cmd_tbl[i].command, cmd_tbl[i].description, CFG_PRINTF_NEWLINE);
316 }
317 }
318
319 printf("%sCommand parameters can be seen by entering: <command-name> ?%s", CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
320 }
This page took 0.064231 seconds and 5 git commands to generate.