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