add a complete rc_proto stack (not tested)
[protos/xbee-avr.git] / commands.c
1 /*
2  *  Copyright Droids Corporation (2011)
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  *  Revision : $Id: commands.c,v 1.9 2009-11-08 17:24:33 zer0 Exp $
19  *
20  *  Olivier MATZ <zer0@droids-corp.org>
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <inttypes.h>
27 #include <aversive.h>
28 #include <aversive/pgmspace.h>
29 #include <aversive/queue.h>
30 #include <aversive/endian.h>
31 #include <aversive/error.h>
32 #include <aversive/wait.h>
33 #include <parse.h>
34 #include <rdline.h>
35 #include <parse_string.h>
36 #include <parse_num.h>
37 #include <uart.h>
38 #include <xbee.h>
39 #include <callout.h>
40
41 #include "parse_atcmd.h"
42 #include "parse_neighbor.h"
43 #include "parse_monitor.h"
44
45 #include "spi_servo.h"
46 #include "rc_proto.h"
47 #include "xbee_user.h"
48 #include "main.h"
49 #include "cmdline.h"
50 #include "beep.h"
51 #include "eeprom_config.h"
52
53 /* commands_gen.c */
54 extern const parse_inst_t PROGMEM cmd_reset;
55 extern const parse_inst_t PROGMEM cmd_bootloader;
56 extern const parse_inst_t PROGMEM cmd_log;
57 extern const parse_inst_t PROGMEM cmd_log_show;
58 extern const parse_inst_t PROGMEM cmd_log_type;
59 extern const parse_inst_t PROGMEM cmd_stack_space;
60 extern const parse_inst_t PROGMEM cmd_callout;
61
62 static int monitor_period_ms = 1000;
63 static int monitor_running = 0;
64 static int monitor_count = 0;
65 static struct callout monitor_event;
66 struct monitor_reg *monitor_current;
67
68 static int range_period_ms = 1000;
69 static int range_powermask = 0x1F;
70 static uint8_t range_power = 0;
71 static int range_running = 0;
72 static uint64_t range_dstaddr = 0xFFFF; /* broadcast by default */
73 static struct callout range_event;
74 static int range_count = 100;
75 static int range_cur_count = 0;
76
77 static void monitor_cb(struct callout_mgr *cm,
78                        struct callout *clt, void *dummy)
79 {
80         (void)clt;
81         (void)dummy;
82
83         if (monitor_current == NULL)
84                 monitor_current = LIST_FIRST(&xbee_monitor_list);
85
86         /* no rx_cb given: the user must check the monitored values in logs */
87         xbeeapp_send_atcmd(monitor_current->atcmd, NULL, 0, NULL, NULL);
88         monitor_current = LIST_NEXT(monitor_current, next);
89         callout_reschedule(cm, clt, monitor_period_ms / monitor_count);
90 }
91
92 static void range_cb(struct callout_mgr *cm,
93                      struct callout *clt, void *dummy)
94 {
95         struct rc_proto_power_probe power_probe;
96         struct xbee_msg msg;
97         uint8_t i, mask;
98
99         (void)clt;
100         (void)dummy;
101
102         range_cur_count--;
103
104         /* get new xmit power */
105         for (i = 1; i <= 8; i++) {
106                 mask = 1 << ((range_power + i) & 0x7);
107                 if (mask & range_powermask)
108                         break;
109         }
110         range_power = ((range_power + i) & 0x7);
111
112         xbeeapp_send_atcmd("PL", &range_power, sizeof(range_power), NULL, NULL);
113
114         power_probe.type = RC_PROTO_POWER_PROBE;
115         power_probe.power_level = range_power;
116
117         msg.iovlen = 1;
118         msg.iov[0].buf = &power_probe;
119         msg.iov[0].len = sizeof(power_probe);
120
121         xbeeapp_send_msg(range_dstaddr, &msg, NULL, NULL);
122
123         if (range_cur_count == 0) {
124                 range_running = 0;
125                 callout_stop(cm, clt);
126                 return;
127         }
128
129         callout_reschedule(cm, clt, range_period_ms);
130 }
131
132 /* callback invoked when a xbee_send is done */
133 static int8_t send_msg_cb(int8_t retcode, void *frame, unsigned len,
134         void *arg)
135 {
136         struct xbee_recv_hdr *recvframe = frame;
137         uint8_t *done = arg;
138
139         *done = 1;
140         if (retcode == XBEE_USER_RETCODE_TIMEOUT) {
141                 printf_P(PSTR("timeout\r\n"));
142                 return retcode;
143         }
144         if (retcode == XBEE_USER_RETCODE_BAD_FRAME ||
145                 len <  sizeof(*recvframe)) {
146                 printf_P(PSTR("invalid frame\r\n"));
147                 return XBEE_USER_RETCODE_BAD_FRAME;
148         }
149
150         printf_P(PSTR("ok\r\n"));
151         return XBEE_USER_RETCODE_OK;
152 }
153
154 /* callback invoked to dump the response to AT command */
155 static int8_t dump_xbee_atresp_cb(int8_t retcode, void *frame, unsigned len,
156         void *arg)
157 {
158         struct xbee_atresp_hdr *recvframe = frame;
159         char atcmd_str[3];
160         char buf[32];
161         uint8_t *done = arg;
162
163         *done = 1;
164         if (retcode == XBEE_USER_RETCODE_TIMEOUT) {
165                 printf_P(PSTR("timeout\r\n"));
166                 return retcode;
167         }
168         if (retcode == XBEE_USER_RETCODE_BAD_FRAME ||
169                 len <  sizeof(*recvframe)) {
170                 printf_P(PSTR("invalid frame\r\n"));
171                 return XBEE_USER_RETCODE_BAD_FRAME;
172         }
173
174         /* get AT command from frame */
175         memcpy(atcmd_str, &recvframe->cmd, 2);
176         atcmd_str[2] = '\0';
177
178         len -= sizeof(*recvframe);
179         atresp_to_str(buf, sizeof(buf), frame);
180         NOTICE(E_USER_XBEE, "status ok, len=%d, %s", len, buf);
181         return XBEE_USER_RETCODE_OK;
182 }
183
184 /* this structure is filled when cmd_help is parsed successfully */
185 struct cmd_help_result {
186         fixed_string_t help;
187         struct xbee_atcmd *cmd;
188 };
189
190 /* function called when cmd_help is parsed successfully */
191 static void cmd_help_parsed(void *parsed_result, void *data)
192 {
193         struct cmd_help_result *res = parsed_result;
194         struct xbee_atcmd cmdcopy;
195         int type;
196
197         (void)data;
198
199         memcpy_P(&cmdcopy, res->cmd, sizeof(cmdcopy));
200         type = (cmdcopy.flags & (XBEE_ATCMD_F_READ | XBEE_ATCMD_F_WRITE));
201         switch (type) {
202                 case XBEE_ATCMD_F_READ:
203                         printf_P(PSTR("Read-only\r\n"));
204                         break;
205                 case XBEE_ATCMD_F_WRITE:
206                         printf_P(PSTR("Write-only\r\n"));
207                         break;
208                 default:
209                         printf_P(PSTR("Read-write\r\n"));
210                         break;
211         }
212         if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_NONE)
213                 printf_P(PSTR("No argument\r\n"));
214         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_U8)
215                 printf_P(PSTR("Register is unsigned 8 bits\r\n"));
216         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_U16)
217                 printf_P(PSTR("Register is unsigned 16 bits\r\n"));
218         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_U32)
219                 printf_P(PSTR("Register is unsigned 32 bits\r\n"));
220         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_S16)
221                 printf_P(PSTR("Register is signed 16 bits\r\n"));
222         else if (cmdcopy.flags & XBEE_ATCMD_F_PARAM_STRING_20B)
223                 printf_P(PSTR("Register is a 20 bytes string\r\n"));
224         else
225                 printf_P(PSTR("Unknown argument\r\n"));
226
227         printf_P(PSTR("%S\r\n"), cmdcopy.help);
228 }
229 const char PROGMEM str_help_help[] = "help";
230
231 const parse_token_string_t PROGMEM cmd_help_help =
232         TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, str_help_help);
233
234 const parse_token_atcmd_t PROGMEM cmd_help_atcmd =
235         TOKEN_ATCMD_INITIALIZER(struct cmd_help_result, cmd, &xbee_dev,
236                                 0, 0);
237
238 const char PROGMEM help_help[] = "Help a register using an AT command";
239 const parse_inst_t PROGMEM cmd_help = {
240         .f = cmd_help_parsed,  /* function to call */
241         .data = NULL,      /* 2nd arg of func */
242         .help_str = help_help,
243         .tokens = {        /* token list, NULL terminated */
244                 (PGM_P)&cmd_help_help,
245                 (PGM_P)&cmd_help_atcmd,
246                 NULL,
247         },
248 };
249
250 /* ************* */
251
252 struct cmd_neigh_del_result {
253         fixed_string_t cmd;
254         fixed_string_t action;
255         struct xbee_neigh *neigh;
256 };
257
258 static void cmd_neigh_del_parsed(void *parsed_result,
259                                 void *data)
260 {
261         struct cmd_neigh_del_result *res = parsed_result;
262
263         (void)data;
264         xbee_neigh_del(xbee_dev, res->neigh);
265 }
266
267 const char PROGMEM str_neigh_del_neigh[] = "neigh";
268 const parse_token_string_t PROGMEM cmd_neigh_del_cmd =
269         TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, cmd,
270                                  str_neigh_del_neigh);
271 const char PROGMEM str_neigh_del_del[] = "del";
272 const parse_token_string_t PROGMEM cmd_neigh_del_action =
273         TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, action,
274                                  str_neigh_del_del);
275 const parse_token_neighbor_t PROGMEM cmd_neigh_del_neigh =
276         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_neigh_del_result, neigh,
277                                    &xbee_dev);
278
279 const char PROGMEM help_neigh_del[] = "delete a neighbor";
280 const parse_inst_t PROGMEM cmd_neigh_del = {
281         .f = cmd_neigh_del_parsed,  /* function to call */
282         .data = NULL,      /* 2nd arg of func */
283         .help_str = help_neigh_del,
284         .tokens = {        /* token list, NULL terminated */
285                 (PGM_P)&cmd_neigh_del_cmd,
286                 (PGM_P)&cmd_neigh_del_action,
287                 (PGM_P)&cmd_neigh_del_neigh,
288                 NULL,
289         },
290 };
291
292 /* ************* */
293
294 struct cmd_neigh_add_result {
295         fixed_string_t cmd;
296         fixed_string_t action;
297         fixed_string_t name;
298         uint64_t addr;
299 };
300
301 static void cmd_neigh_add_parsed(void *parsed_result,
302                                  void *data)
303 {
304         struct cmd_neigh_add_result *res = parsed_result;
305
306         (void)data;
307         if (xbee_neigh_add(xbee_dev, res->name, res->addr) == NULL)
308                 printf_P(PSTR("name or addr already exist\r\n"));
309 }
310
311 const char PROGMEM str_neigh_add_neigh[] = "neigh";
312 const parse_token_string_t PROGMEM cmd_neigh_add_cmd =
313         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, cmd,
314                                  str_neigh_add_neigh);
315 const char PROGMEM str_neigh_add_add[] = "add";
316 const parse_token_string_t PROGMEM cmd_neigh_add_action =
317         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, action,
318                                  str_neigh_add_add);
319 const parse_token_string_t PROGMEM cmd_neigh_add_name =
320         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, name, NULL);
321 const parse_token_num_t PROGMEM cmd_neigh_add_addr =
322         TOKEN_NUM_INITIALIZER(struct cmd_neigh_add_result, addr, UINT64);
323
324 const char PROGMEM help_neigh_add[] = "add a neighbor";
325 const parse_inst_t PROGMEM cmd_neigh_add = {
326         .f = cmd_neigh_add_parsed,  /* function to call */
327         .data = NULL,      /* 2nd arg of func */
328         .help_str = help_neigh_add,
329         .tokens = {        /* token list, NULL terminated */
330                 (PGM_P)&cmd_neigh_add_cmd,
331                 (PGM_P)&cmd_neigh_add_action,
332                 (PGM_P)&cmd_neigh_add_name,
333                 (PGM_P)&cmd_neigh_add_addr,
334                 NULL,
335         },
336 };
337
338 /* ************* */
339
340 struct cmd_neigh_list_result {
341         fixed_string_t cmd;
342         fixed_string_t action;
343 };
344
345 static void cmd_neigh_list_parsed(void *parsed_result,
346                                 void *data)
347 {
348         struct xbee_neigh *neigh;
349
350         (void)parsed_result;
351         (void)data;
352         LIST_FOREACH(neigh, &xbee_dev->neigh_list, next) {
353                 printf_P(PSTR(" %s: 0x%.8"PRIx32"%.8"PRIx32"\r\n"),
354                          neigh->name,
355                          (uint32_t)(neigh->addr >> 32ULL),
356                          (uint32_t)(neigh->addr & 0xFFFFFFFF));
357         }
358 }
359
360 const char PROGMEM str_neigh_list_neigh[] = "neigh";
361 const parse_token_string_t PROGMEM cmd_neigh_list_cmd =
362         TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, cmd,
363                                  str_neigh_list_neigh);
364 const char PROGMEM str_neigh_list_list[] = "list";
365 const parse_token_string_t PROGMEM cmd_neigh_list_action =
366         TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, action,
367                                  str_neigh_list_list);
368
369 const char PROGMEM help_neigh_list[] = "list all knwon neighbors";
370 const parse_inst_t PROGMEM cmd_neigh_list = {
371         .f = cmd_neigh_list_parsed,  /* function to call */
372         .data = NULL,      /* 2nd arg of func */
373         .help_str = help_neigh_list,
374         .tokens = {        /* token list, NULL terminated */
375                 (PGM_P)&cmd_neigh_list_cmd,
376                 (PGM_P)&cmd_neigh_list_action,
377                 NULL,
378         },
379 };
380
381 /* ************* */
382
383 /* this structure is filled when cmd_read is parsed successfully */
384 struct cmd_read_result {
385         fixed_string_t read;
386         struct xbee_atcmd *cmd;
387 };
388
389 /* function called when cmd_read is parsed successfully */
390 static void cmd_read_parsed(void *parsed_result,
391                             void *data)
392 {
393         struct cmd_read_result *res = parsed_result;
394         struct xbee_atcmd copy;
395         char cmd[3];
396         volatile uint8_t done = 0;
397
398         (void)data;
399         memcpy_P(&copy, res->cmd, sizeof(copy));
400         memcpy_P(&cmd, copy.name, 2);
401         cmd[2] = '\0';
402         xbeeapp_send_atcmd(cmd, NULL, 0, dump_xbee_atresp_cb, (void *)&done);
403         while (done == 0);
404 }
405
406 const char PROGMEM str_read_read[] = "read";
407
408 const parse_token_string_t PROGMEM cmd_read_read =
409         TOKEN_STRING_INITIALIZER(struct cmd_read_result, read,
410                                  str_read_read);
411
412 const parse_token_atcmd_t PROGMEM cmd_read_atcmd =
413         TOKEN_ATCMD_INITIALIZER(struct cmd_read_result, cmd, &xbee_dev,
414                                 XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
415
416 const char PROGMEM help_read[] = "Read a register using an AT command";
417 const parse_inst_t PROGMEM cmd_read = {
418         .f = cmd_read_parsed,  /* function to call */
419         .data = NULL,      /* 2nd arg of func */
420         .help_str = help_read,
421         .tokens = {        /* token list, NULL terminated */
422                 (PGM_P)&cmd_read_read,
423                 (PGM_P)&cmd_read_atcmd,
424                 NULL,
425         },
426 };
427
428
429 /* ************* */
430
431 /* this structure is filled when cmd_write is parsed successfully */
432 struct cmd_write_result {
433         fixed_string_t write;
434         struct xbee_atcmd *cmd;
435         union {
436                 uint8_t u8;
437                 uint16_t u16;
438                 uint32_t u32;
439         };
440 };
441
442 /* function called when cmd_write is parsed successfully */
443 static void cmd_write_parsed(void *parsed_result, void *data)
444 {
445         struct cmd_write_result *res = parsed_result;
446         struct xbee_atcmd copy;
447         char cmd[3];
448         int len;
449         void *param;
450         volatile uint8_t done = 0;
451
452         (void)data;
453         memcpy_P(&copy, res->cmd, sizeof(copy));
454
455         if (copy.flags & XBEE_ATCMD_F_PARAM_NONE) {
456                 len = 0;
457                 param = NULL;
458         }
459         else if (copy.flags & XBEE_ATCMD_F_PARAM_U8) {
460                 len = sizeof(res->u8);
461                 param = &res->u8;
462         }
463         else if (copy.flags & XBEE_ATCMD_F_PARAM_U16) {
464                 len = sizeof(res->u16);
465                 res->u16 = htons(res->u16);
466                 param = &res->u16;
467         }
468         else if (copy.flags & XBEE_ATCMD_F_PARAM_U32) {
469                 len = sizeof(res->u32);
470                 res->u32 = htonl(res->u32);
471                 param = &res->u32;
472         }
473         else {
474                 printf_P(PSTR("Unknown argument type\r\n"));
475                 return;
476         }
477         memcpy_P(&cmd, copy.name, 2);
478         cmd[2] = '\0';
479         xbeeapp_send_atcmd(cmd, param, len, dump_xbee_atresp_cb, (void *)&done);
480         while (done == 0);
481 }
482
483 const char PROGMEM str_write_none[] = "write";
484
485 const parse_token_string_t PROGMEM cmd_write_write =
486         TOKEN_STRING_INITIALIZER(struct cmd_write_result, write,
487                                  str_write_none);
488
489 const parse_token_atcmd_t PROGMEM cmd_write_none_atcmd =
490         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
491                                 &xbee_dev,
492                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE,
493                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE);
494
495 const char PROGMEM help_write_none[] = "Send an AT command (no argument)";
496
497 const parse_inst_t PROGMEM cmd_write_none = {
498         .f = cmd_write_parsed,  /* function to call */
499         .data = NULL,      /* 2nd arg of func */
500         .help_str = help_write_none,
501         .tokens = {        /* token list, NULL terminated */
502                 (PGM_P)&cmd_write_write,
503                 (PGM_P)&cmd_write_none_atcmd,
504                 NULL,
505         },
506 };
507
508 const parse_token_atcmd_t PROGMEM cmd_write_u8_atcmd =
509         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
510                                 &xbee_dev,
511                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8,
512                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8);
513
514 const parse_token_num_t PROGMEM cmd_write_u8_u8 =
515         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u8, UINT8);
516
517 const char PROGMEM help_write_u8[] = "Write a 8 bits register using an AT command";
518
519 const parse_inst_t PROGMEM cmd_write_u8 = {
520         .f = cmd_write_parsed,  /* function to call */
521         .data = NULL,      /* 2nd arg of func */
522         .help_str = help_write_u8,
523         .tokens = {        /* token list, NULL terminated */
524                 (PGM_P)&cmd_write_write,
525                 (PGM_P)&cmd_write_u8_atcmd,
526                 (PGM_P)&cmd_write_u8_u8,
527                 NULL,
528         },
529 };
530
531 const parse_token_atcmd_t PROGMEM cmd_write_u16_atcmd =
532         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
533                                 &xbee_dev,
534                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16,
535                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16);
536
537 const parse_token_num_t PROGMEM cmd_write_u16_u16 =
538         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u16, UINT16);
539
540 const char PROGMEM help_write_u16[] = "Write a 16 bits register using an AT command";
541
542 const parse_inst_t PROGMEM cmd_write_u16 = {
543         .f = cmd_write_parsed,  /* function to call */
544         .data = NULL,      /* 2nd arg of func */
545         .help_str = help_write_u16,
546         .tokens = {        /* token list, NULL terminated */
547                 (PGM_P)&cmd_write_write,
548                 (PGM_P)&cmd_write_u16_atcmd,
549                 (PGM_P)&cmd_write_u16_u16,
550                 NULL,
551         },
552 };
553
554 const parse_token_atcmd_t PROGMEM cmd_write_u32_atcmd =
555         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
556                                 &xbee_dev,
557                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32,
558                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32);
559
560 const parse_token_num_t PROGMEM cmd_write_u32_u32 =
561         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u32, UINT32);
562
563 const char PROGMEM help_write_u32[] = "Write a 32 bits register using an AT command";
564
565 const parse_inst_t PROGMEM cmd_write_u32 = {
566         .f = cmd_write_parsed,  /* function to call */
567         .data = NULL,      /* 2nd arg of func */
568         .help_str = help_write_u32,
569         .tokens = {        /* token list, NULL terminated */
570                 (PGM_P)&cmd_write_write,
571                 (PGM_P)&cmd_write_u32_atcmd,
572                 (PGM_P)&cmd_write_u32_u32,
573                 NULL,
574         },
575 };
576
577
578 /* ************* */
579
580 /* this structure is filled when cmd_sendmsg is parsed successfully */
581 struct cmd_sendmsg_result {
582         fixed_string_t sendmsg;
583         uint64_t addr;
584         fixed_string_t data;
585 };
586
587 /* function called when cmd_sendmsg is parsed successfully */
588 static void cmd_sendmsg_parsed(void *parsed_result, void *data)
589 {
590         struct cmd_sendmsg_result *res = parsed_result;
591         struct xbee_msg msg;
592         volatile uint8_t done = 0;
593
594         (void)data;
595
596         msg.iovlen = 1;
597         msg.iov[0].buf = res->data;
598         msg.iov[0].len = strlen(res->data);
599
600         xbeeapp_send_msg(res->addr, &msg, send_msg_cb, (void *)&done);
601         while (done == 0);
602 }
603
604 const char PROGMEM str_sendmsg[] = "sendmsg";
605
606 const parse_token_string_t PROGMEM cmd_sendmsg_sendmsg =
607         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, sendmsg,
608                                  str_sendmsg);
609
610 const parse_token_num_t PROGMEM cmd_sendmsg_addr =
611         TOKEN_NUM_INITIALIZER(struct cmd_sendmsg_result, addr, UINT64);
612
613 const parse_token_string_t PROGMEM cmd_sendmsg_data =
614         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, data, NULL);
615
616 const char PROGMEM help_sendmsg[] = "Send data to a node using its address";
617
618 const parse_inst_t PROGMEM cmd_sendmsg = {
619         .f = cmd_sendmsg_parsed,  /* function to call */
620         .data = NULL,      /* 2nd arg of func */
621         .help_str = help_sendmsg,
622         .tokens = {        /* token list, NULL terminated */
623                 (PGM_P)&cmd_sendmsg_sendmsg,
624                 (PGM_P)&cmd_sendmsg_addr,
625                 (PGM_P)&cmd_sendmsg_data,
626                 NULL,
627         },
628 };
629
630 /* ************* */
631
632 /* this structure is filled when cmd_send_hello is parsed successfully */
633 struct cmd_send_hello_result {
634         fixed_string_t send_hello;
635         uint64_t addr;
636         struct xbee_neigh *neigh;
637         uint16_t period;
638         uint16_t count;
639         fixed_string_t data;
640 };
641
642 /* function called when cmd_send_hello is parsed successfully */
643 static void cmd_send_hello_parsed(void *parsed_result, void *use_neigh)
644 {
645         struct cmd_send_hello_result *res = parsed_result;
646         uint16_t now, next, diff;
647         uint8_t flags;
648         uint64_t addr;
649
650         if (use_neigh)
651                 addr = res->neigh->addr;
652         else
653                 addr = res->addr;
654
655         IRQ_LOCK(flags);
656         now = global_ms;
657         IRQ_UNLOCK(flags);
658
659         next = now;
660
661         while (!cmdline_keypressed() && res->count != 0) {
662                 IRQ_LOCK(flags);
663                 now = global_ms;
664                 IRQ_UNLOCK(flags);
665
666                 diff = now - next;
667                 if (diff < res->period)
668                         continue;
669
670                 rc_proto_send_hello(addr, res->data, strlen(res->data), -1);
671                 next += res->period;
672                 res->count--;
673         }
674 }
675
676 const char PROGMEM str_send_hello[] = "send_hello";
677
678 const parse_token_string_t PROGMEM cmd_send_hello_send_hello =
679         TOKEN_STRING_INITIALIZER(struct cmd_send_hello_result, send_hello,
680                                  str_send_hello);
681
682 const parse_token_num_t PROGMEM cmd_send_hello_addr =
683         TOKEN_NUM_INITIALIZER(struct cmd_send_hello_result, addr, UINT64);
684
685 const parse_token_num_t PROGMEM cmd_send_hello_period =
686         TOKEN_NUM_INITIALIZER(struct cmd_send_hello_result, period, UINT16);
687
688 const parse_token_num_t PROGMEM cmd_send_hello_count =
689         TOKEN_NUM_INITIALIZER(struct cmd_send_hello_result, count, UINT16);
690
691 const parse_token_string_t PROGMEM cmd_send_hello_data =
692         TOKEN_STRING_INITIALIZER(struct cmd_send_hello_result, data, NULL);
693
694 const char PROGMEM help_send_hello[] =
695         "Send hello msg to a node: addr, period_ms, count, str";
696
697 const parse_inst_t PROGMEM cmd_send_hello = {
698         .f = cmd_send_hello_parsed,  /* function to call */
699         .data = NULL,      /* 2nd arg of func */
700         .help_str = help_send_hello,
701         .tokens = {        /* token list, NULL terminated */
702                 (PGM_P)&cmd_send_hello_send_hello,
703                 (PGM_P)&cmd_send_hello_addr,
704                 (PGM_P)&cmd_send_hello_period,
705                 (PGM_P)&cmd_send_hello_count,
706                 (PGM_P)&cmd_send_hello_data,
707                 NULL,
708         },
709 };
710
711 const parse_token_neighbor_t PROGMEM cmd_send_hello_neigh =
712         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_send_hello_result, neigh,
713                                    &xbee_dev);
714
715 const parse_inst_t PROGMEM cmd_send_hello_name = {
716         .f = cmd_send_hello_parsed,  /* function to call */
717         .data = (void *)1,      /* 2nd arg of func */
718         .help_str = help_send_hello,
719         .tokens = {        /* token list, NULL terminated */
720                 (PGM_P)&cmd_send_hello_send_hello,
721                 (PGM_P)&cmd_send_hello_neigh,
722                 (PGM_P)&cmd_send_hello_period,
723                 (PGM_P)&cmd_send_hello_count,
724                 (PGM_P)&cmd_send_hello_data,
725                 NULL,
726         },
727 };
728
729 /* ************* */
730
731 /* this structure is filled when cmd_sendmsg_name is parsed successfully */
732 struct cmd_sendmsg_name_result {
733         fixed_string_t sendmsg_name;
734         struct xbee_neigh *neigh;
735         fixed_string_t data;
736 };
737
738 /* function called when cmd_sendmsg_name is parsed successfully */
739 static void cmd_sendmsg_name_parsed(void *parsed_result, void *data)
740 {
741         struct cmd_sendmsg_name_result *res = parsed_result;
742         struct xbee_msg msg;
743         volatile uint8_t done = 0;
744
745         (void)data;
746
747         msg.iovlen = 1;
748         msg.iov[0].buf = res->data;
749         msg.iov[0].len = strlen(res->data);
750
751         xbeeapp_send_msg(res->neigh->addr, &msg, send_msg_cb, (void *)&done);
752         while (done == 0);
753 }
754
755 const parse_token_string_t PROGMEM cmd_sendmsg_name_sendmsg_name =
756         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, sendmsg_name,
757                                  str_sendmsg);
758
759 const parse_token_neighbor_t PROGMEM cmd_sendmsg_name_neigh =
760         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_sendmsg_name_result, neigh,
761                                    &xbee_dev);
762
763 const parse_token_string_t PROGMEM cmd_sendmsg_name_data =
764         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, data, NULL);
765
766 const char PROGMEM help_sendmsg_name[] = "Send data to a node using its name";
767
768 const parse_inst_t PROGMEM cmd_sendmsg_name = {
769         .f = cmd_sendmsg_name_parsed,  /* function to call */
770         .data = NULL,      /* 2nd arg of func */
771         .help_str = help_sendmsg_name,
772         .tokens = {        /* token list, NULL terminated */
773                 (PGM_P)&cmd_sendmsg_name_sendmsg_name,
774                 (PGM_P)&cmd_sendmsg_name_neigh,
775                 (PGM_P)&cmd_sendmsg_name_data,
776                 NULL,
777         },
778 };
779
780
781 /* ************* */
782
783 /* this structure is filled when cmd_range is parsed successfully */
784 struct cmd_range_result {
785         fixed_string_t range;
786         fixed_string_t action;
787 };
788
789 /* function called when cmd_range is parsed successfully */
790 static void cmd_range_parsed(void *parsed_result, void *data)
791 {
792         struct cmd_range_result *res = parsed_result;
793
794         (void)data;
795         if (!strcmp_P(res->action, PSTR("show"))) {
796                 printf_P(PSTR("range infos:\r\n"));
797                 printf_P(PSTR("  range period %d\r\n"), range_period_ms);
798                 printf_P(PSTR("  range count %d\r\n"), range_count);
799                 printf_P(PSTR("  range powermask 0x%x\r\n"), range_powermask);
800                 printf_P(PSTR("  range dstaddr 0x%.8"PRIx32"%.8"PRIx32"\r\n"),
801                          (uint32_t)(range_dstaddr >> 32ULL),
802                          (uint32_t)(range_dstaddr & 0xFFFFFFFF));
803
804                 if (range_running)
805                         printf_P(PSTR("  range test is running\r\n"));
806                 else
807                         printf_P(PSTR("  range test is not running\r\n"));
808         }
809         else if (!strcmp(res->action, "start")) {
810                 if (range_running) {
811                         printf_P(PSTR("already running\r\n"));
812                         return;
813                 }
814                 range_cur_count = range_count;
815                 callout_init(&range_event, range_cb, NULL, LOW_PRIO);
816                 range_running = 1;
817                 callout_schedule(&xbeeboard.intr_cm,
818                         &range_event, 0); /* immediate */
819         }
820         else if (!strcmp(res->action, "end")) {
821                 if (range_running == 0) {
822                         printf_P(PSTR("not running\r\n"));
823                         return;
824                 }
825                 callout_stop(&xbeeboard.intr_cm, &range_event);
826                 range_running = 0;
827         }
828 }
829
830 const char PROGMEM str_range[] = "range";
831 const char PROGMEM str_range_tokens[] = "show#start#end";
832
833 const parse_token_string_t PROGMEM cmd_range_range =
834         TOKEN_STRING_INITIALIZER(struct cmd_range_result, range,
835                                  str_range);
836 const parse_token_string_t PROGMEM cmd_range_action =
837         TOKEN_STRING_INITIALIZER(struct cmd_range_result, action,
838                                  str_range_tokens);
839
840 const char PROGMEM help_range[] = "start/stop/show current rangeing";
841
842 const parse_inst_t PROGMEM cmd_range = {
843         .f = cmd_range_parsed,  /* function to call */
844         .data = NULL,      /* 2nd arg of func */
845         .help_str = help_range,
846         .tokens = {        /* token list, NULL terminated */
847                 (PGM_P)&cmd_range_range,
848                 (PGM_P)&cmd_range_action,
849                 NULL,
850         },
851 };
852
853 /* ************* */
854
855 /* this structure is filled when cmd_range_period is parsed successfully */
856 struct cmd_range_period_result {
857         fixed_string_t range;
858         fixed_string_t action;
859         uint32_t period;
860 };
861
862 /* function called when cmd_range_period is parsed successfully */
863 static void cmd_range_period_parsed(void *parsed_result, void *data)
864 {
865         struct cmd_range_period_result *res = parsed_result;
866
867         (void)data;
868         if (res->period < 10) {
869                 printf_P(PSTR("error, minimum period is 10 ms\r\n"));
870                 return;
871         }
872
873         range_period_ms = res->period;
874 }
875
876 const char PROGMEM str_period[] = "period";
877
878 const parse_token_string_t PROGMEM cmd_range_period_range_period =
879         TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, range,
880                                  str_range);
881 const parse_token_string_t PROGMEM cmd_range_period_action =
882         TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, action,
883                                  str_period);
884 const parse_token_num_t PROGMEM cmd_range_period_period =
885         TOKEN_NUM_INITIALIZER(struct cmd_range_period_result, period, UINT32);
886
887 const char PROGMEM help_range_period[] = "set range test period";
888
889 const parse_inst_t PROGMEM cmd_range_period = {
890         .f = cmd_range_period_parsed,  /* function to call */
891         .data = NULL,      /* 2nd arg of func */
892         .help_str = help_range_period,
893         .tokens = {        /* token list, NULL terminated */
894                 (PGM_P)&cmd_range_period_range_period,
895                 (PGM_P)&cmd_range_period_action,
896                 (PGM_P)&cmd_range_period_period,
897                 NULL,
898         },
899 };
900
901 /* ************* */
902
903 /* this structure is filled when cmd_range_count is parsed successfully */
904 struct cmd_range_count_result {
905         fixed_string_t range;
906         fixed_string_t action;
907         uint32_t count;
908 };
909
910 /* function called when cmd_range_count is parsed successfully */
911 static void cmd_range_count_parsed(void *parsed_result, void *data)
912 {
913         struct cmd_range_count_result *res = parsed_result;
914
915         (void)data;
916         range_count = res->count;
917 }
918
919 const char PROGMEM str_count[] = "count";
920
921 const parse_token_string_t PROGMEM cmd_range_count_range_count =
922         TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, range,
923                                  str_range);
924 const parse_token_string_t PROGMEM cmd_range_count_action =
925         TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, action,
926                                  str_count);
927 const parse_token_num_t PROGMEM cmd_range_count_count =
928         TOKEN_NUM_INITIALIZER(struct cmd_range_count_result, count, UINT32);
929
930
931 const char PROGMEM help_range_count[] = "set range test count";
932
933 const parse_inst_t PROGMEM cmd_range_count = {
934         .f = cmd_range_count_parsed,  /* function to call */
935         .data = NULL,      /* 2nd arg of func */
936         .help_str = help_range_count,
937         .tokens = {        /* token list, NULL terminated */
938                 (PGM_P)&cmd_range_count_range_count,
939                 (PGM_P)&cmd_range_count_action,
940                 (PGM_P)&cmd_range_count_count,
941                 NULL,
942         },
943 };
944
945 /* ************* */
946
947 /* this structure is filled when cmd_range_powermask is parsed successfully */
948 struct cmd_range_powermask_result {
949         fixed_string_t range;
950         fixed_string_t action;
951         uint8_t powermask;
952 };
953
954 /* function called when cmd_range_powermask is parsed successfully */
955 static void cmd_range_powermask_parsed(void *parsed_result, void *data)
956 {
957         struct cmd_range_powermask_result *res = parsed_result;
958
959         (void)data;
960         range_powermask = res->powermask;
961 }
962
963 const char PROGMEM str_powermask[] = "powermask";
964
965 const parse_token_string_t PROGMEM cmd_range_powermask_range_powermask =
966         TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, range,
967                                  str_range);
968 const parse_token_string_t PROGMEM cmd_range_powermask_action =
969         TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, action,
970                                  str_powermask);
971 const parse_token_num_t PROGMEM cmd_range_powermask_powermask =
972         TOKEN_NUM_INITIALIZER(struct cmd_range_powermask_result, powermask,
973                               UINT8);
974
975
976 const char PROGMEM help_range_powermask[] = "set range test powermask";
977
978 const parse_inst_t PROGMEM cmd_range_powermask = {
979         .f = cmd_range_powermask_parsed,  /* function to call */
980         .data = NULL,      /* 2nd arg of func */
981         .help_str = help_range_powermask,
982         .tokens = {        /* token list, NULL terminated */
983                 (PGM_P)&cmd_range_powermask_range_powermask,
984                 (PGM_P)&cmd_range_powermask_action,
985                 (PGM_P)&cmd_range_powermask_powermask,
986                 NULL,
987         },
988 };
989
990 /* ************* */
991
992 /* this structure is filled when cmd_range_dstaddr is parsed successfully */
993 struct cmd_range_dstaddr_result {
994         fixed_string_t range;
995         fixed_string_t action;
996         uint64_t dstaddr;
997 };
998
999 /* function called when cmd_range_dstaddr is parsed successfully */
1000 static void cmd_range_dstaddr_parsed(void *parsed_result, void *data)
1001 {
1002         struct cmd_range_dstaddr_result *res = parsed_result;
1003
1004         (void)data;
1005         range_dstaddr = res->dstaddr;
1006 }
1007
1008 const char PROGMEM str_dstaddr[] = "dstaddr";
1009
1010 const parse_token_string_t PROGMEM cmd_range_dstaddr_range_dstaddr =
1011         TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, range,
1012                                  str_range);
1013 const parse_token_string_t PROGMEM cmd_range_dstaddr_action =
1014         TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, action,
1015                                  str_dstaddr);
1016 const parse_token_num_t PROGMEM cmd_range_dstaddr_dstaddr =
1017         TOKEN_NUM_INITIALIZER(struct cmd_range_dstaddr_result, dstaddr, UINT64);
1018
1019
1020 const char PROGMEM help_range_dstaddr[] = "set register rangeing dstaddr";
1021
1022 const parse_inst_t PROGMEM cmd_range_dstaddr = {
1023         .f = cmd_range_dstaddr_parsed,  /* function to call */
1024         .data = NULL,      /* 2nd arg of func */
1025         .help_str = help_range_dstaddr,
1026         .tokens = {        /* token list, NULL terminated */
1027                 (PGM_P)&cmd_range_dstaddr_range_dstaddr,
1028                 (PGM_P)&cmd_range_dstaddr_action,
1029                 (PGM_P)&cmd_range_dstaddr_dstaddr,
1030                 NULL,
1031         },
1032 };
1033
1034
1035 /* ************* */
1036
1037 /* this structure is filled when cmd_monitor is parsed successfully */
1038 struct cmd_monitor_result {
1039         fixed_string_t monitor;
1040         fixed_string_t action;
1041 };
1042
1043 /* function called when cmd_monitor is parsed successfully */
1044 static void cmd_monitor_parsed(void *parsed_result, void *data)
1045 {
1046         struct cmd_monitor_result *res = parsed_result;
1047         struct monitor_reg *m;
1048
1049         (void)data;
1050         if (!strcmp_P(res->action, PSTR("show"))) {
1051                 printf_P(PSTR("monitor period is %d ms, %d regs in list\r\n"),
1052                        monitor_period_ms, monitor_count);
1053                 LIST_FOREACH(m, &xbee_monitor_list, next)
1054                         printf_P(PSTR(" %S\r\n"), m->desc);
1055         }
1056         else if (!strcmp_P(res->action, PSTR("start"))) {
1057                 if (monitor_running) {
1058                         printf_P(PSTR("already running\r\n"));
1059                         return;
1060                 }
1061                 if (monitor_count == 0) {
1062                         printf_P(PSTR("no regs to be monitored\r\n"));
1063                         return;
1064                 }
1065                 callout_init(&monitor_event, monitor_cb, NULL, 1);
1066                 monitor_running = 1;
1067                 monitor_current = LIST_FIRST(&xbee_monitor_list);
1068                 callout_schedule(&xbeeboard.intr_cm,
1069                         &monitor_event, 0); /* immediate */
1070                 printf_P(PSTR("monitor cb: %S %s\r\n"),
1071                          monitor_current->desc,
1072                          monitor_current->atcmd);
1073
1074         }
1075         else if (!strcmp_P(res->action, PSTR("end"))) {
1076                 if (monitor_running == 0) {
1077                         printf_P(PSTR("not running\r\n"));
1078                         return;
1079                 }
1080                 callout_stop(&xbeeboard.intr_cm, &monitor_event);
1081                 monitor_running = 0;
1082         }
1083 }
1084
1085 const char PROGMEM str_monitor[] = "monitor";
1086 const char PROGMEM str_monitor_tokens[] = "show#start#end";
1087
1088 const parse_token_string_t PROGMEM cmd_monitor_monitor =
1089         TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, monitor,
1090                                  str_monitor);
1091 const parse_token_string_t PROGMEM cmd_monitor_action =
1092         TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, action,
1093                                  str_monitor_tokens);
1094
1095 const char PROGMEM help_monitor[] = "start/stop/show current monitoring";
1096
1097 const parse_inst_t PROGMEM cmd_monitor = {
1098         .f = cmd_monitor_parsed,  /* function to call */
1099         .data = NULL,      /* 2nd arg of func */
1100         .help_str = help_monitor,
1101         .tokens = {        /* token list, NULL terminated */
1102                 (PGM_P)&cmd_monitor_monitor,
1103                 (PGM_P)&cmd_monitor_action,
1104                 NULL,
1105         },
1106 };
1107
1108 /* ************* */
1109
1110 /* this structure is filled when cmd_monitor_add is parsed successfully */
1111 struct cmd_monitor_add_result {
1112         fixed_string_t monitor;
1113         fixed_string_t action;
1114         struct xbee_atcmd *cmd;
1115 };
1116
1117 /* function called when cmd_monitor_add is parsed successfully */
1118 static void cmd_monitor_add_parsed(void *parsed_result, void *data)
1119 {
1120         struct cmd_monitor_add_result *res = parsed_result;
1121         struct monitor_reg *m;
1122         struct xbee_atcmd copy;
1123
1124         (void)data;
1125         memcpy_P(&copy, res->cmd, sizeof(copy));
1126         LIST_FOREACH(m, &xbee_monitor_list, next) {
1127                 if (!strcmp_P(m->atcmd, copy.name))
1128                         break;
1129         }
1130
1131         if (m != NULL) {
1132                 printf_P(PSTR("already exist\r\n"));
1133                 return;
1134         }
1135
1136         m = malloc(sizeof(*m));
1137         if (m == NULL) {
1138                 printf_P(PSTR("no mem\r\n"));
1139                 return;
1140         }
1141         m->desc = copy.desc;
1142         strcpy_P(m->atcmd, copy.name);
1143         LIST_INSERT_HEAD(&xbee_monitor_list, m, next);
1144         monitor_count ++;
1145 }
1146
1147 const char PROGMEM str_monitor_add[] = "add";
1148
1149 const parse_token_string_t PROGMEM cmd_monitor_add_monitor_add =
1150         TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, monitor,
1151                                  str_monitor);
1152 const parse_token_string_t PROGMEM cmd_monitor_add_action =
1153         TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, action,
1154                                  str_monitor_add);
1155 const parse_token_atcmd_t PROGMEM cmd_monitor_add_atcmd =
1156         TOKEN_ATCMD_INITIALIZER(struct cmd_monitor_add_result, cmd, &xbee_dev,
1157                                 XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
1158
1159
1160 const char PROGMEM help_monitor_add[] = "add a register in monitor list";
1161
1162 const parse_inst_t PROGMEM cmd_monitor_add = {
1163         .f = cmd_monitor_add_parsed,  /* function to call */
1164         .data = NULL,      /* 2nd arg of func */
1165         .help_str = help_monitor_add,
1166         .tokens = {        /* token list, NULL terminated */
1167                 (PGM_P)&cmd_monitor_add_monitor_add,
1168                 (PGM_P)&cmd_monitor_add_action,
1169                 (PGM_P)&cmd_monitor_add_atcmd,
1170                 NULL,
1171         },
1172 };
1173
1174 /* ************* */
1175
1176 /* this structure is filled when cmd_monitor_period is parsed successfully */
1177 struct cmd_monitor_period_result {
1178         fixed_string_t monitor;
1179         fixed_string_t action;
1180         uint32_t period;
1181 };
1182
1183 /* function called when cmd_monitor_period is parsed successfully */
1184 static void cmd_monitor_period_parsed(void *parsed_result, void *data)
1185 {
1186         struct cmd_monitor_period_result *res = parsed_result;
1187
1188         (void)data;
1189         if (res->period < 100) {
1190                 printf_P(PSTR("error, minimum period is 100 ms\r\n"));
1191                 return;
1192         }
1193
1194         monitor_period_ms = res->period;
1195 }
1196
1197 const char PROGMEM str_monitor_period[] = "period";
1198
1199 const parse_token_string_t PROGMEM cmd_monitor_period_monitor_period =
1200         TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, monitor,
1201                                  str_monitor);
1202 const parse_token_string_t PROGMEM cmd_monitor_period_action =
1203         TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, action,
1204                                  str_monitor_period);
1205 const parse_token_num_t PROGMEM cmd_monitor_period_period =
1206         TOKEN_NUM_INITIALIZER(struct cmd_monitor_period_result, period, UINT32);
1207
1208
1209 const char PROGMEM help_monitor_period[] = "set register monitoring period";
1210
1211 const parse_inst_t PROGMEM cmd_monitor_period = {
1212         .f = cmd_monitor_period_parsed,  /* function to call */
1213         .data = NULL,      /* 2nd arg of func */
1214         .help_str = help_monitor_period,
1215         .tokens = {        /* token list, NULL terminated */
1216                 (PGM_P)&cmd_monitor_period_monitor_period,
1217                 (PGM_P)&cmd_monitor_period_action,
1218                 (PGM_P)&cmd_monitor_period_period,
1219                 NULL,
1220         },
1221 };
1222
1223 /* ************* */
1224
1225 /* this structure is filled when cmd_monitor_del is parsed successfully */
1226 struct cmd_monitor_del_result {
1227         fixed_string_t monitor;
1228         fixed_string_t action;
1229         struct monitor_reg *m;
1230 };
1231
1232 /* function called when cmd_monitor_del is parsed successfully */
1233 static void cmd_monitor_del_parsed(void *parsed_result, void *data)
1234 {
1235         struct cmd_monitor_del_result *res = parsed_result;
1236
1237         (void)data;
1238         monitor_current = LIST_NEXT(res->m, next);
1239         LIST_REMOVE(res->m, next);
1240         free(res->m);
1241         monitor_count --;
1242         if (monitor_count == 0) {
1243                 printf_P(PSTR("Disable monitoring, no more event\r\n"));
1244                 callout_stop(&xbeeboard.intr_cm, &monitor_event);
1245                 monitor_running = 0;
1246                 return;
1247         }
1248 }
1249
1250 const char PROGMEM str_monitor_del[] = "del";
1251
1252 const parse_token_string_t PROGMEM cmd_monitor_del_monitor_del =
1253         TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, monitor,
1254                                  str_monitor);
1255 const parse_token_string_t PROGMEM cmd_monitor_del_action =
1256         TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, action,
1257                                  str_monitor_del);
1258 const parse_token_monitor_t PROGMEM cmd_monitor_del_atcmd =
1259         TOKEN_MONITOR_INITIALIZER(struct cmd_monitor_del_result, m);
1260
1261
1262 const char PROGMEM help_monitor_del[] = "del a register in monitor list";
1263
1264 const parse_inst_t PROGMEM cmd_monitor_del = {
1265         .f = cmd_monitor_del_parsed,  /* function to call */
1266         .data = NULL,      /* 2nd arg of func */
1267         .help_str = help_monitor_del,
1268         .tokens = {        /* token list, NULL terminated */
1269                 (PGM_P)&cmd_monitor_del_monitor_del,
1270                 (PGM_P)&cmd_monitor_del_action,
1271                 (PGM_P)&cmd_monitor_del_atcmd,
1272                 NULL,
1273         },
1274 };
1275
1276
1277 /* ************* */
1278
1279 /* this structure is filled when cmd_ping is parsed successfully */
1280 struct cmd_ping_result {
1281         fixed_string_t ping;
1282 };
1283
1284 /* function called when cmd_ping is parsed successfully */
1285 static void cmd_ping_parsed(void *parsed_result, void *data)
1286 {
1287         volatile uint8_t done = 0;
1288
1289         (void)parsed_result;
1290         (void)data;
1291         xbeeapp_send_atcmd("VL", NULL, 0, dump_xbee_atresp_cb, (void *)&done);
1292         while (done == 0);
1293 }
1294
1295 const char PROGMEM str_ping[] = "ping";
1296
1297 const parse_token_string_t PROGMEM cmd_ping_ping =
1298         TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping,
1299                                  str_ping);
1300
1301 const char PROGMEM help_ping[] = "Send a ping to the xbee device";
1302
1303 const parse_inst_t PROGMEM cmd_ping = {
1304         .f = cmd_ping_parsed,  /* function to call */
1305         .data = NULL,      /* 2nd arg of func */
1306         .help_str = help_ping,
1307         .tokens = {        /* token list, NULL terminated */
1308                 (PGM_P)&cmd_ping_ping,
1309                 NULL,
1310         },
1311 };
1312
1313 /* ************* */
1314
1315 /* this structure is filled when cmd_raw is parsed successfully */
1316 struct cmd_raw_result {
1317         fixed_string_t raw;
1318 };
1319
1320 /* function called when cmd_raw is parsed successfully */
1321 static void cmd_raw_parsed(void *parsed_result, void *data)
1322 {
1323         (void)parsed_result;
1324         (void)data;
1325
1326         if (range_running || monitor_running) {
1327                 printf_P(PSTR("stop running range or monitor first\r\n"));
1328                 return;
1329         }
1330         printf_P(PSTR("switched to raw mode, CTRL-D to exit\r\n"));
1331         rdline_stop(&xbeeboard.rdl); /* don't display prompt when return */
1332         xbee_raw = 1;
1333 }
1334
1335 const char PROGMEM str_raw[] = "raw";
1336
1337 const parse_token_string_t PROGMEM cmd_raw_raw =
1338         TOKEN_STRING_INITIALIZER(struct cmd_raw_result, raw,
1339                                  str_raw);
1340
1341 const char PROGMEM help_raw[] = "Switch to raw mode";
1342
1343 const parse_inst_t PROGMEM cmd_raw = {
1344         .f = cmd_raw_parsed,  /* function to call */
1345         .data = NULL,      /* 2nd arg of func */
1346         .help_str = help_raw,
1347         .tokens = {        /* token list, NULL terminated */
1348                 (PGM_P)&cmd_raw_raw,
1349                 NULL,
1350         },
1351 };
1352
1353 /**********************************************************/
1354
1355 /* this structure is filled when cmd_baudrate is parsed successfully */
1356 struct cmd_baudrate_result {
1357         fixed_string_t arg0;
1358         uint32_t arg1;
1359 };
1360
1361 /* function called when cmd_baudrate is parsed successfully */
1362 static void cmd_baudrate_parsed(void * parsed_result, __attribute__((unused)) void *data)
1363 {
1364         struct cmd_baudrate_result *res = parsed_result;
1365         struct uart_config c;
1366
1367         uart_getconf(XBEE_UART, &c);
1368         c.baudrate = res->arg1;
1369         uart_setconf(XBEE_UART, &c);
1370 }
1371
1372 const char PROGMEM str_baudrate_arg0[] = "baudrate";
1373 const parse_token_string_t PROGMEM cmd_baudrate_arg0 =
1374         TOKEN_STRING_INITIALIZER(struct cmd_baudrate_result, arg0,
1375                                  str_baudrate_arg0);
1376 const parse_token_num_t PROGMEM cmd_baudrate_arg1 =
1377         TOKEN_NUM_INITIALIZER(struct cmd_baudrate_result, arg1,
1378                               UINT32);
1379
1380 const char PROGMEM help_baudrate[] = "Change xbee baudrate";
1381 const parse_inst_t PROGMEM cmd_baudrate = {
1382         .f = cmd_baudrate_parsed,  /* function to call */
1383         .data = NULL,      /* 2nd arg of func */
1384         .help_str = help_baudrate,
1385         .tokens = {        /* token list, NULL terminated */
1386                 (PGM_P)&cmd_baudrate_arg0,
1387                 (PGM_P)&cmd_baudrate_arg1,
1388                 NULL,
1389         },
1390 };
1391
1392
1393 /**********************************************************/
1394
1395 /* this structure is filled when cmd_beep is parsed successfully */
1396 struct cmd_beep_result {
1397         fixed_string_t beep;
1398 };
1399
1400 /* function called when cmd_beep is parsed successfully */
1401 static void cmd_beep_parsed(void *parsed_result, void *data)
1402 {
1403         (void)parsed_result;
1404         (void)data;
1405
1406         beep(0, 3, 3);
1407         beep(1, 3, 3);
1408         beep(2, 3, 3);
1409         beep(0, 1, 1);
1410         beep(1, 1, 1);
1411         beep(2, 1, 1);
1412 }
1413
1414 const char PROGMEM str_beep[] = "beep";
1415 const parse_token_string_t PROGMEM cmd_beep_beep =
1416         TOKEN_STRING_INITIALIZER(struct cmd_beep_result, beep,
1417                                  str_beep);
1418
1419 const char PROGMEM help_beep[] = "Send a beep";
1420
1421 const parse_inst_t PROGMEM cmd_beep = {
1422         .f = cmd_beep_parsed,  /* function to call */
1423         .data = NULL,      /* 2nd arg of func */
1424         .help_str = help_beep,
1425         .tokens = {        /* token list, NULL terminated */
1426                 (PGM_P)&cmd_beep_beep,
1427                 NULL,
1428         },
1429 };
1430
1431 /**********************************************************/
1432
1433 /* this structure is filled when cmd_servo is parsed successfully */
1434 struct cmd_servo_result {
1435         fixed_string_t arg0;
1436         fixed_string_t arg1;
1437         uint16_t num;
1438         uint16_t val;
1439 };
1440
1441 /* function called when cmd_servo is parsed successfully */
1442 static void cmd_servo_parsed(void * parsed_result, void *data)
1443 {
1444         struct cmd_servo_result *res = parsed_result;
1445
1446         (void)data;
1447
1448         if (!strcmp_P(res->arg1, PSTR("set"))) {
1449                 if (res->num >= N_SERVO) {
1450                         printf_P(PSTR("bad servo num\n"));
1451                         return;
1452                 }
1453                 if (res->val >= 1024) {
1454                         printf_P(PSTR("bad servo val\n"));
1455                         return;
1456                 }
1457                 spi_servo_set(res->num, res->val);
1458         }
1459         else if (!strcmp_P(res->arg1, PSTR("bypass"))) {
1460                 spi_servo_set_bypass(!!res->val);
1461         }
1462         else if (!strcmp_P(res->arg1, PSTR("ppm"))) {
1463                 spi_servo_set_ppm(!!res->val);
1464         }
1465         else if (!strcmp_P(res->arg1, PSTR("show"))) {
1466                 spi_servo_dump();
1467         }
1468 }
1469
1470 const char PROGMEM str_servo_arg0[] = "servo";
1471 const parse_token_string_t PROGMEM cmd_servo_arg0 =
1472         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg0,
1473                                  str_servo_arg0);
1474 const char PROGMEM str_servo_arg1_set[] = "set";
1475 const parse_token_string_t PROGMEM cmd_servo_arg1_set =
1476         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1477                                  str_servo_arg1_set);
1478 const parse_token_num_t PROGMEM cmd_servo_num =
1479         TOKEN_NUM_INITIALIZER(struct cmd_servo_result, num,
1480                               UINT16);
1481 const parse_token_num_t PROGMEM cmd_servo_val =
1482         TOKEN_NUM_INITIALIZER(struct cmd_servo_result, val,
1483                               UINT16);
1484
1485 const char PROGMEM help_servo_set[] = "set servo value";
1486 const parse_inst_t PROGMEM cmd_servo_set = {
1487         .f = cmd_servo_parsed,  /* function to call */
1488         .data = NULL,      /* 2nd arg of func */
1489         .help_str = help_servo_set,
1490         .tokens = {        /* token list, NULL terminated */
1491                 (PGM_P)&cmd_servo_arg0,
1492                 (PGM_P)&cmd_servo_arg1_set,
1493                 (PGM_P)&cmd_servo_num,
1494                 (PGM_P)&cmd_servo_val,
1495                 NULL,
1496         },
1497 };
1498
1499 const char PROGMEM str_servo_arg1_show[] = "show";
1500 const parse_token_string_t PROGMEM cmd_servo_arg1_show =
1501         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1502                                  str_servo_arg1_show);
1503
1504 const char PROGMEM help_servo_show[] = "read servo and config";
1505 const parse_inst_t PROGMEM cmd_servo_show = {
1506         .f = cmd_servo_parsed,  /* function to call */
1507         .data = NULL,      /* 2nd arg of func */
1508         .help_str = help_servo_show,
1509         .tokens = {        /* token list, NULL terminated */
1510                 (PGM_P)&cmd_servo_arg0,
1511                 (PGM_P)&cmd_servo_arg1_show,
1512                 NULL,
1513         },
1514 };
1515
1516 const char PROGMEM str_servo_arg1_bypassppm[] = "bypass#ppm";
1517 const parse_token_string_t PROGMEM cmd_servo_arg1_bypassppm =
1518         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1519                                  str_servo_arg1_bypassppm);
1520
1521 const char PROGMEM help_servo_bypassppm[] = "change bypass/ppm";
1522 const parse_inst_t PROGMEM cmd_servo_bypassppm = {
1523         .f = cmd_servo_parsed,  /* function to call */
1524         .data = NULL,      /* 2nd arg of func */
1525         .help_str = help_servo_bypassppm,
1526         .tokens = {        /* token list, NULL terminated */
1527                 (PGM_P)&cmd_servo_arg0,
1528                 (PGM_P)&cmd_servo_arg1_bypassppm,
1529                 (PGM_P)&cmd_servo_val,
1530                 NULL,
1531         },
1532 };
1533
1534 /**********************************************************/
1535
1536 /* this structure is filled when cmd_test_spi is parsed successfully */
1537 struct cmd_test_spi_result {
1538         fixed_string_t arg0;
1539 };
1540
1541 static void cmd_test_spi_parsed(void * parsed_result, void *data)
1542 {
1543         uint8_t i, flags, wait_time = 0;
1544         uint16_t val = 0;
1545
1546         (void)parsed_result;
1547         (void)data;
1548
1549         spi_servo_set_bypass(0);
1550         spi_servo_set_ppm(0);
1551
1552         /* stress test: send many commands, no wait between each servo
1553          * of a series, and a variable delay between series */
1554         printf_P(PSTR("stress test\r\n"));
1555         while (!cmdline_keypressed()) {
1556
1557                 wait_time++;
1558                 if (wait_time > 20)
1559                         wait_time = 0;
1560
1561                 IRQ_LOCK(flags);
1562                 val = global_ms;
1563                 IRQ_UNLOCK(flags);
1564                 val >>= 3;
1565                 val &= 1023;
1566
1567                 for (i = 0; i < 6; i++)
1568                         spi_servo_set(i, val);
1569
1570                 wait_ms(wait_time);
1571                 printf_P(PSTR("%4.4d %4.4d %4.4d %4.4d %4.4d %4.4d\r\n"),
1572                          spi_servo_get(0), spi_servo_get(1), spi_servo_get(2),
1573                          spi_servo_get(3), spi_servo_get(4), spi_servo_get(5));
1574         }
1575
1576         printf_P(PSTR("bypass mode, with spi commands in background\r\n"));
1577         spi_servo_set_bypass(1);
1578
1579         /* test bypass mode */
1580         while (!cmdline_keypressed()) {
1581
1582                 wait_time++;
1583                 if (wait_time > 20)
1584                         wait_time = 0;
1585
1586                 IRQ_LOCK(flags);
1587                 val = global_ms;
1588                 IRQ_UNLOCK(flags);
1589                 val >>= 3;
1590                 val &= 1023;
1591
1592                 for (i = 0; i < 6; i++)
1593                         spi_servo_set(i, val);
1594
1595                 wait_ms(wait_time);
1596                 printf_P(PSTR("%4.4d %4.4d %4.4d %4.4d %4.4d %4.4d\r\n"),
1597                          spi_servo_get(0), spi_servo_get(1), spi_servo_get(2),
1598                          spi_servo_get(3), spi_servo_get(4), spi_servo_get(5));
1599         }
1600
1601         printf_P(PSTR("PPM to servo\r\n"));
1602         spi_servo_set_bypass(0);
1603         spi_servo_set_ppm(0);
1604
1605         /* test PPM to servo (bypass) mode */
1606         while (!cmdline_keypressed()) {
1607                 for (i = 0; i < 6; i++) {
1608                         val = spi_servo_get(i);
1609                         spi_servo_set(i, val);
1610                 }
1611         }
1612
1613         printf_P(PSTR("PPM to (servo + PPM)\r\n"));
1614         spi_servo_set_bypass(0);
1615         spi_servo_set_ppm(1);
1616
1617         /* test PPM to servo (bypass) mode */
1618         while (!cmdline_keypressed()) {
1619                 for (i = 0; i < 6; i++) {
1620                         val = spi_servo_get(i);
1621                         spi_servo_set(i, val);
1622                 }
1623         }
1624 }
1625
1626 const char PROGMEM str_test_spi_arg0[] = "test_spi";
1627 const parse_token_string_t PROGMEM cmd_test_spi_arg0 =
1628         TOKEN_STRING_INITIALIZER(struct cmd_test_spi_result, arg0,
1629                                  str_test_spi_arg0);
1630
1631 const char PROGMEM help_test_spi[] = "Test the spi";
1632 const parse_inst_t PROGMEM cmd_test_spi = {
1633         .f = cmd_test_spi_parsed,  /* function to call */
1634         .data = NULL,      /* 2nd arg of func */
1635         .help_str = help_test_spi,
1636         .tokens = {        /* token list, NULL terminated */
1637                 (PGM_P)&cmd_test_spi_arg0,
1638                 NULL,
1639         },
1640 };
1641
1642 /**********************************************************/
1643
1644 /* this structure is filled when cmd_dump_xbee_stats is parsed successfully */
1645 struct cmd_dump_xbee_stats_result {
1646         fixed_string_t arg0;
1647 };
1648
1649 static void cmd_dump_xbee_stats_parsed(void *parsed_result, void *data)
1650 {
1651         (void)parsed_result;
1652         (void)data;
1653
1654         xbee_dump_stats(xbee_dev);
1655 }
1656
1657 const char PROGMEM str_dump_xbee_stats_arg0[] = "dump_xbee_stats";
1658 const parse_token_string_t PROGMEM cmd_dump_xbee_stats_arg0 =
1659         TOKEN_STRING_INITIALIZER(struct cmd_dump_xbee_stats_result, arg0,
1660                                  str_dump_xbee_stats_arg0);
1661
1662 const char PROGMEM help_dump_xbee_stats[] = "Test the spi";
1663 const parse_inst_t PROGMEM cmd_dump_xbee_stats = {
1664         .f = cmd_dump_xbee_stats_parsed,  /* function to call */
1665         .data = NULL,      /* 2nd arg of func */
1666         .help_str = help_dump_xbee_stats,
1667         .tokens = {        /* token list, NULL terminated */
1668                 (PGM_P)&cmd_dump_xbee_stats_arg0,
1669                 NULL,
1670         },
1671 };
1672
1673 /**********************************************************/
1674
1675 /* this structure is filled when cmd_test_eeprom_config is parsed successfully */
1676 struct cmd_test_eeprom_config_result {
1677         fixed_string_t arg0;
1678 };
1679
1680 static void cmd_test_eeprom_config_parsed(void *parsed_result, void *data)
1681 {
1682         (void)parsed_result;
1683         (void)data;
1684
1685         eeprom_dump_cmds();
1686         eeprom_append_cmd("salut1\n");
1687         eeprom_dump_cmds();
1688         eeprom_append_cmd("salut2\n");
1689         eeprom_append_cmd("salut3\n");
1690         eeprom_append_cmd("salut4\n");
1691         eeprom_dump_cmds();
1692         eeprom_insert_cmd_before("coin\n", 0);
1693         eeprom_insert_cmd_before("coin2\n", 2);
1694         eeprom_dump_cmds();
1695         eeprom_delete_cmd(2);
1696         eeprom_delete_cmd(0);
1697         eeprom_dump_cmds();
1698 }
1699
1700 const char PROGMEM str_test_eeprom_config_arg0[] = "test_eeprom_config";
1701 const parse_token_string_t PROGMEM cmd_test_eeprom_config_arg0 =
1702         TOKEN_STRING_INITIALIZER(struct cmd_test_eeprom_config_result, arg0,
1703                                  str_test_eeprom_config_arg0);
1704
1705 const char PROGMEM help_test_eeprom_config[] = "Test the eeprom configuration";
1706 const parse_inst_t PROGMEM cmd_test_eeprom_config = {
1707         .f = cmd_test_eeprom_config_parsed,  /* function to call */
1708         .data = NULL,      /* 2nd arg of func */
1709         .help_str = help_test_eeprom_config,
1710         .tokens = {        /* token list, NULL terminated */
1711                 (PGM_P)&cmd_test_eeprom_config_arg0,
1712                 NULL,
1713         },
1714 };
1715
1716 /* ************* */
1717
1718 struct cmd_eeprom_del_result {
1719         fixed_string_t cmd;
1720         fixed_string_t action;
1721         uint8_t n;
1722 };
1723
1724 static void cmd_eeprom_del_parsed(void *parsed_result,
1725                                 void *data)
1726 {
1727         struct cmd_eeprom_del_result *res = parsed_result;
1728
1729         (void)data;
1730         if (eeprom_delete_cmd(res->n) < 0)
1731                 printf_P(PSTR("cannot delete command\n"));
1732         eeprom_dump_cmds();
1733 }
1734
1735 const char PROGMEM str_eeprom_del_eeprom[] = "eeprom";
1736 const parse_token_string_t PROGMEM cmd_eeprom_del_cmd =
1737         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_del_result, cmd,
1738                                  str_eeprom_del_eeprom);
1739 const char PROGMEM str_eeprom_del_del[] = "del";
1740 const parse_token_string_t PROGMEM cmd_eeprom_del_action =
1741         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_del_result, action,
1742                                  str_eeprom_del_del);
1743 const parse_token_num_t PROGMEM cmd_eeprom_del_num =
1744         TOKEN_NUM_INITIALIZER(struct cmd_eeprom_del_result, n,
1745                               UINT8);
1746
1747 const char PROGMEM help_eeprom_del[] = "delete an eeprom init command";
1748 const parse_inst_t PROGMEM cmd_eeprom_del = {
1749         .f = cmd_eeprom_del_parsed,  /* function to call */
1750         .data = NULL,      /* 2nd arg of func */
1751         .help_str = help_eeprom_del,
1752         .tokens = {        /* token list, NULL terminated */
1753                 (PGM_P)&cmd_eeprom_del_cmd,
1754                 (PGM_P)&cmd_eeprom_del_action,
1755                 (PGM_P)&cmd_eeprom_del_num,
1756                 NULL,
1757         },
1758 };
1759
1760 /* ************* */
1761
1762 struct cmd_eeprom_add_result {
1763         fixed_string_t cmd;
1764         fixed_string_t action;
1765         uint8_t n;
1766 };
1767
1768 static void cmd_eeprom_add_parsed(void *parsed_result,
1769                                  void *data)
1770 {
1771         struct cmd_eeprom_add_result *res = parsed_result;
1772         struct rdline rdl;
1773         const char *buffer;
1774         int8_t ret;
1775         int16_t c;
1776
1777         rdline_init(&rdl, cmdline_write_char, NULL, NULL);
1778         rdline_newline(&rdl, "> ");
1779
1780         /* XXX bad: we should not block as we do not serve callout */
1781         while (1) {
1782                 c = cmdline_dev_recv(NULL);
1783                 if (c < 0)
1784                         continue;
1785
1786                 ret = rdline_char_in(&rdl, c);
1787                 if (ret == -2) {
1788                         printf_P(PSTR("abort\n"));
1789                         return;
1790                 }
1791                 if (ret == 1)
1792                         break;
1793         }
1794
1795         buffer = rdline_get_buffer(&rdl);
1796         if (data == NULL)
1797                 eeprom_insert_cmd_before(buffer, res->n);
1798         else
1799                 eeprom_append_cmd(buffer);
1800         eeprom_dump_cmds();
1801 }
1802
1803 const char PROGMEM str_eeprom_add_eeprom[] = "eeprom";
1804 const parse_token_string_t PROGMEM cmd_eeprom_add_cmd =
1805         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_add_result, cmd,
1806                                  str_eeprom_add_eeprom);
1807 const char PROGMEM str_eeprom_add_add[] = "add";
1808 const parse_token_string_t PROGMEM cmd_eeprom_add_action =
1809         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_add_result, action,
1810                                  str_eeprom_add_add);
1811 const parse_token_num_t PROGMEM cmd_eeprom_add_num =
1812         TOKEN_NUM_INITIALIZER(struct cmd_eeprom_add_result, n,
1813                               UINT8);
1814
1815 const char PROGMEM help_eeprom_add[] = "insert an eeprom init command";
1816 const parse_inst_t PROGMEM cmd_eeprom_add = {
1817         .f = cmd_eeprom_add_parsed,  /* function to call */
1818         .data = NULL,      /* 2nd arg of func */
1819         .help_str = help_eeprom_add,
1820         .tokens = {        /* token list, NULL terminated */
1821                 (PGM_P)&cmd_eeprom_add_cmd,
1822                 (PGM_P)&cmd_eeprom_add_action,
1823                 (PGM_P)&cmd_eeprom_add_num,
1824                 NULL,
1825         },
1826 };
1827
1828 const char PROGMEM help_eeprom_add2[] = "append an eeprom init command";
1829 const parse_inst_t PROGMEM cmd_eeprom_add2 = {
1830         .f = cmd_eeprom_add_parsed,  /* function to call */
1831         .data = (void *)1,      /* 2nd arg of func */
1832         .help_str = help_eeprom_add2,
1833         .tokens = {        /* token list, NULL terminated */
1834                 (PGM_P)&cmd_eeprom_add_cmd,
1835                 (PGM_P)&cmd_eeprom_add_action,
1836                 NULL,
1837         },
1838 };
1839
1840 /* ************* */
1841
1842 struct cmd_eeprom_list_result {
1843         fixed_string_t cmd;
1844         fixed_string_t action;
1845 };
1846
1847 static void cmd_eeprom_list_parsed(void *parsed_result,
1848                                 void *data)
1849 {
1850         (void)parsed_result;
1851         (void)data;
1852         eeprom_dump_cmds();
1853 }
1854
1855 const char PROGMEM str_eeprom_list_eeprom[] = "eeprom";
1856 const parse_token_string_t PROGMEM cmd_eeprom_list_cmd =
1857         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_list_result, cmd,
1858                                  str_eeprom_list_eeprom);
1859 const char PROGMEM str_eeprom_list_list[] = "list";
1860 const parse_token_string_t PROGMEM cmd_eeprom_list_action =
1861         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_list_result, action,
1862                                  str_eeprom_list_list);
1863
1864 const char PROGMEM help_eeprom_list[] = "list all eeprom init commands";
1865 const parse_inst_t PROGMEM cmd_eeprom_list = {
1866         .f = cmd_eeprom_list_parsed,  /* function to call */
1867         .data = NULL,      /* 2nd arg of func */
1868         .help_str = help_eeprom_list,
1869         .tokens = {        /* token list, NULL terminated */
1870                 (PGM_P)&cmd_eeprom_list_cmd,
1871                 (PGM_P)&cmd_eeprom_list_action,
1872                 NULL,
1873         },
1874 };
1875
1876
1877 /* ************* */
1878
1879 /* in progmem */
1880 const parse_ctx_t PROGMEM main_ctx[] = {
1881
1882         /* commands_gen.c */
1883         &cmd_reset,
1884         &cmd_bootloader,
1885         &cmd_log,
1886         &cmd_log_show,
1887         &cmd_log_type,
1888         &cmd_stack_space,
1889         &cmd_callout,
1890         &cmd_help,
1891         &cmd_neigh_del,
1892         &cmd_neigh_add,
1893         &cmd_neigh_list,
1894         &cmd_read,
1895         &cmd_write_none,
1896         &cmd_write_u8,
1897         &cmd_write_u16,
1898         &cmd_write_u32,
1899         &cmd_sendmsg,
1900         &cmd_send_hello,
1901         &cmd_send_hello_name,
1902         &cmd_sendmsg_name,
1903         &cmd_range,
1904         &cmd_range_period,
1905         &cmd_range_count,
1906         &cmd_range_powermask,
1907         &cmd_range_dstaddr,
1908         &cmd_monitor,
1909         &cmd_monitor_period,
1910         &cmd_monitor_add,
1911         &cmd_monitor_del,
1912         &cmd_ping,
1913         &cmd_raw,
1914         &cmd_baudrate,
1915         &cmd_beep,
1916         &cmd_servo_set,
1917         &cmd_servo_bypassppm,
1918         &cmd_servo_show,
1919         &cmd_test_spi,
1920         &cmd_dump_xbee_stats,
1921         &cmd_test_eeprom_config,
1922         &cmd_eeprom_del,
1923         &cmd_eeprom_add,
1924         &cmd_eeprom_add2,
1925         &cmd_eeprom_list,
1926         NULL,
1927 };