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