parse rx hello frames
[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         struct xbee_neigh *neigh;
577         uint16_t period;
578         uint16_t count;
579         fixed_string_t data;
580 };
581
582 /* function called when cmd_send_hello is parsed successfully */
583 static void cmd_send_hello_parsed(void *parsed_result, void *use_neigh)
584 {
585         struct cmd_send_hello_result *res = parsed_result;
586         uint16_t now, next, diff;
587         uint8_t flags;
588         uint64_t addr;
589
590         if (use_neigh)
591                 addr = res->neigh->addr;
592         else
593                 addr = res->addr;
594
595         IRQ_LOCK(flags);
596         now = global_ms;
597         IRQ_UNLOCK(flags);
598
599         next = now;
600
601         while (!cmdline_keypressed() && res->count != 0) {
602                 IRQ_LOCK(flags);
603                 now = global_ms;
604                 IRQ_UNLOCK(flags);
605
606                 diff = now - next;
607                 if (diff < res->period)
608                         continue;
609
610                 rc_proto_send_hello(addr, res->data, strlen(res->data));
611                 next += res->period;
612                 res->count--;
613         }
614 }
615
616 const char PROGMEM str_send_hello[] = "send_hello";
617
618 const parse_token_string_t PROGMEM cmd_send_hello_send_hello =
619         TOKEN_STRING_INITIALIZER(struct cmd_send_hello_result, send_hello,
620                                  str_send_hello);
621
622 const parse_token_num_t PROGMEM cmd_send_hello_addr =
623         TOKEN_NUM_INITIALIZER(struct cmd_send_hello_result, addr, UINT64);
624
625 const parse_token_num_t PROGMEM cmd_send_hello_period =
626         TOKEN_NUM_INITIALIZER(struct cmd_send_hello_result, period, UINT16);
627
628 const parse_token_num_t PROGMEM cmd_send_hello_count =
629         TOKEN_NUM_INITIALIZER(struct cmd_send_hello_result, count, UINT16);
630
631 const parse_token_string_t PROGMEM cmd_send_hello_data =
632         TOKEN_STRING_INITIALIZER(struct cmd_send_hello_result, data, NULL);
633
634 const char PROGMEM help_send_hello[] =
635         "Send hello msg to a node: addr, period_ms, count, str";
636
637 const parse_inst_t PROGMEM cmd_send_hello = {
638         .f = cmd_send_hello_parsed,  /* function to call */
639         .data = NULL,      /* 2nd arg of func */
640         .help_str = help_send_hello,
641         .tokens = {        /* token list, NULL terminated */
642                 (PGM_P)&cmd_send_hello_send_hello,
643                 (PGM_P)&cmd_send_hello_addr,
644                 (PGM_P)&cmd_send_hello_period,
645                 (PGM_P)&cmd_send_hello_count,
646                 (PGM_P)&cmd_send_hello_data,
647                 NULL,
648         },
649 };
650
651 const parse_token_neighbor_t PROGMEM cmd_send_hello_neigh =
652         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_send_hello_result, neigh,
653                                    &xbee_dev);
654
655 const parse_inst_t PROGMEM cmd_send_hello_name = {
656         .f = cmd_send_hello_parsed,  /* function to call */
657         .data = (void *)1,      /* 2nd arg of func */
658         .help_str = help_send_hello,
659         .tokens = {        /* token list, NULL terminated */
660                 (PGM_P)&cmd_send_hello_send_hello,
661                 (PGM_P)&cmd_send_hello_neigh,
662                 (PGM_P)&cmd_send_hello_period,
663                 (PGM_P)&cmd_send_hello_count,
664                 (PGM_P)&cmd_send_hello_data,
665                 NULL,
666         },
667 };
668
669 /* ************* */
670
671 /* this structure is filled when cmd_sendmsg_name is parsed successfully */
672 struct cmd_sendmsg_name_result {
673         fixed_string_t sendmsg_name;
674         struct xbee_neigh *neigh;
675         fixed_string_t data;
676 };
677
678 /* function called when cmd_sendmsg_name is parsed successfully */
679 static void cmd_sendmsg_name_parsed(void *parsed_result, void *data)
680 {
681         struct cmd_sendmsg_name_result *res = parsed_result;
682
683         (void)data;
684         xbeeapp_send_msg(res->neigh->addr, res->data, strlen(res->data), 1);
685 }
686
687 const parse_token_string_t PROGMEM cmd_sendmsg_name_sendmsg_name =
688         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, sendmsg_name,
689                                  str_sendmsg);
690
691 const parse_token_neighbor_t PROGMEM cmd_sendmsg_name_neigh =
692         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_sendmsg_name_result, neigh,
693                                    &xbee_dev);
694
695 const parse_token_string_t PROGMEM cmd_sendmsg_name_data =
696         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, data, NULL);
697
698 const char PROGMEM help_sendmsg_name[] = "Send data to a node using its name";
699
700 const parse_inst_t PROGMEM cmd_sendmsg_name = {
701         .f = cmd_sendmsg_name_parsed,  /* function to call */
702         .data = NULL,      /* 2nd arg of func */
703         .help_str = help_sendmsg_name,
704         .tokens = {        /* token list, NULL terminated */
705                 (PGM_P)&cmd_sendmsg_name_sendmsg_name,
706                 (PGM_P)&cmd_sendmsg_name_neigh,
707                 (PGM_P)&cmd_sendmsg_name_data,
708                 NULL,
709         },
710 };
711
712
713 /* ************* */
714
715 /* this structure is filled when cmd_range is parsed successfully */
716 struct cmd_range_result {
717         fixed_string_t range;
718         fixed_string_t action;
719 };
720
721 /* function called when cmd_range is parsed successfully */
722 static void cmd_range_parsed(void *parsed_result, void *data)
723 {
724         struct cmd_range_result *res = parsed_result;
725
726         (void)data;
727         if (!strcmp_P(res->action, PSTR("show"))) {
728                 printf_P(PSTR("range infos:\r\n"));
729                 printf_P(PSTR("  range period %d\r\n"), range_period_ms);
730                 printf_P(PSTR("  range count %d\r\n"), range_count);
731                 printf_P(PSTR("  range powermask 0x%x\r\n"), range_powermask);
732                 printf_P(PSTR("  range dstaddr 0x%.8"PRIx32"%.8"PRIx32"\r\n"),
733                          (uint32_t)(range_dstaddr >> 32ULL),
734                          (uint32_t)(range_dstaddr & 0xFFFFFFFF));
735
736                 if (range_running)
737                         printf_P(PSTR("  range test is running\r\n"));
738                 else
739                         printf_P(PSTR("  range test is not running\r\n"));
740         }
741         else if (!strcmp(res->action, "start")) {
742                 if (range_running) {
743                         printf_P(PSTR("already running\r\n"));
744                         return;
745                 }
746                 range_cur_count = range_count;
747                 callout_init(&range_event);
748                 callout_reset(&cm, &range_event, 0,
749                               SINGLE, range_cb, NULL);
750                 range_running = 1;
751         }
752         else if (!strcmp(res->action, "end")) {
753                 if (range_running == 0) {
754                         printf_P(PSTR("not running\r\n"));
755                         return;
756                 }
757                 range_running = 0;
758                 callout_stop(&cm, &range_event);
759         }
760 }
761
762 const char PROGMEM str_range[] = "range";
763 const char PROGMEM str_range_tokens[] = "show#start#end";
764
765 const parse_token_string_t PROGMEM cmd_range_range =
766         TOKEN_STRING_INITIALIZER(struct cmd_range_result, range,
767                                  str_range);
768 const parse_token_string_t PROGMEM cmd_range_action =
769         TOKEN_STRING_INITIALIZER(struct cmd_range_result, action,
770                                  str_range_tokens);
771
772 const char PROGMEM help_range[] = "start/stop/show current rangeing";
773
774 const parse_inst_t PROGMEM cmd_range = {
775         .f = cmd_range_parsed,  /* function to call */
776         .data = NULL,      /* 2nd arg of func */
777         .help_str = help_range,
778         .tokens = {        /* token list, NULL terminated */
779                 (PGM_P)&cmd_range_range,
780                 (PGM_P)&cmd_range_action,
781                 NULL,
782         },
783 };
784
785 /* ************* */
786
787 /* this structure is filled when cmd_range_period is parsed successfully */
788 struct cmd_range_period_result {
789         fixed_string_t range;
790         fixed_string_t action;
791         uint32_t period;
792 };
793
794 /* function called when cmd_range_period is parsed successfully */
795 static void cmd_range_period_parsed(void *parsed_result, void *data)
796 {
797         struct cmd_range_period_result *res = parsed_result;
798
799         (void)data;
800         if (res->period < 10) {
801                 printf_P(PSTR("error, minimum period is 10 ms\r\n"));
802                 return;
803         }
804
805         range_period_ms = res->period;
806 }
807
808 const char PROGMEM str_period[] = "period";
809
810 const parse_token_string_t PROGMEM cmd_range_period_range_period =
811         TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, range,
812                                  str_range);
813 const parse_token_string_t PROGMEM cmd_range_period_action =
814         TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, action,
815                                  str_period);
816 const parse_token_num_t PROGMEM cmd_range_period_period =
817         TOKEN_NUM_INITIALIZER(struct cmd_range_period_result, period, UINT32);
818
819 const char PROGMEM help_range_period[] = "set range test period";
820
821 const parse_inst_t PROGMEM cmd_range_period = {
822         .f = cmd_range_period_parsed,  /* function to call */
823         .data = NULL,      /* 2nd arg of func */
824         .help_str = help_range_period,
825         .tokens = {        /* token list, NULL terminated */
826                 (PGM_P)&cmd_range_period_range_period,
827                 (PGM_P)&cmd_range_period_action,
828                 (PGM_P)&cmd_range_period_period,
829                 NULL,
830         },
831 };
832
833 /* ************* */
834
835 /* this structure is filled when cmd_range_count is parsed successfully */
836 struct cmd_range_count_result {
837         fixed_string_t range;
838         fixed_string_t action;
839         uint32_t count;
840 };
841
842 /* function called when cmd_range_count is parsed successfully */
843 static void cmd_range_count_parsed(void *parsed_result, void *data)
844 {
845         struct cmd_range_count_result *res = parsed_result;
846
847         (void)data;
848         range_count = res->count;
849 }
850
851 const char PROGMEM str_count[] = "count";
852
853 const parse_token_string_t PROGMEM cmd_range_count_range_count =
854         TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, range,
855                                  str_range);
856 const parse_token_string_t PROGMEM cmd_range_count_action =
857         TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, action,
858                                  str_count);
859 const parse_token_num_t PROGMEM cmd_range_count_count =
860         TOKEN_NUM_INITIALIZER(struct cmd_range_count_result, count, UINT32);
861
862
863 const char PROGMEM help_range_count[] = "set range test count";
864
865 const parse_inst_t PROGMEM cmd_range_count = {
866         .f = cmd_range_count_parsed,  /* function to call */
867         .data = NULL,      /* 2nd arg of func */
868         .help_str = help_range_count,
869         .tokens = {        /* token list, NULL terminated */
870                 (PGM_P)&cmd_range_count_range_count,
871                 (PGM_P)&cmd_range_count_action,
872                 (PGM_P)&cmd_range_count_count,
873                 NULL,
874         },
875 };
876
877 /* ************* */
878
879 /* this structure is filled when cmd_range_powermask is parsed successfully */
880 struct cmd_range_powermask_result {
881         fixed_string_t range;
882         fixed_string_t action;
883         uint8_t powermask;
884 };
885
886 /* function called when cmd_range_powermask is parsed successfully */
887 static void cmd_range_powermask_parsed(void *parsed_result, void *data)
888 {
889         struct cmd_range_powermask_result *res = parsed_result;
890
891         (void)data;
892         range_powermask = res->powermask;
893 }
894
895 const char PROGMEM str_powermask[] = "powermask";
896
897 const parse_token_string_t PROGMEM cmd_range_powermask_range_powermask =
898         TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, range,
899                                  str_range);
900 const parse_token_string_t PROGMEM cmd_range_powermask_action =
901         TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, action,
902                                  str_powermask);
903 const parse_token_num_t PROGMEM cmd_range_powermask_powermask =
904         TOKEN_NUM_INITIALIZER(struct cmd_range_powermask_result, powermask,
905                               UINT8);
906
907
908 const char PROGMEM help_range_powermask[] = "set range test powermask";
909
910 const parse_inst_t PROGMEM cmd_range_powermask = {
911         .f = cmd_range_powermask_parsed,  /* function to call */
912         .data = NULL,      /* 2nd arg of func */
913         .help_str = help_range_powermask,
914         .tokens = {        /* token list, NULL terminated */
915                 (PGM_P)&cmd_range_powermask_range_powermask,
916                 (PGM_P)&cmd_range_powermask_action,
917                 (PGM_P)&cmd_range_powermask_powermask,
918                 NULL,
919         },
920 };
921
922 /* ************* */
923
924 /* this structure is filled when cmd_range_dstaddr is parsed successfully */
925 struct cmd_range_dstaddr_result {
926         fixed_string_t range;
927         fixed_string_t action;
928         uint64_t dstaddr;
929 };
930
931 /* function called when cmd_range_dstaddr is parsed successfully */
932 static void cmd_range_dstaddr_parsed(void *parsed_result, void *data)
933 {
934         struct cmd_range_dstaddr_result *res = parsed_result;
935
936         (void)data;
937         range_dstaddr = res->dstaddr;
938 }
939
940 const char PROGMEM str_dstaddr[] = "dstaddr";
941
942 const parse_token_string_t PROGMEM cmd_range_dstaddr_range_dstaddr =
943         TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, range,
944                                  str_range);
945 const parse_token_string_t PROGMEM cmd_range_dstaddr_action =
946         TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, action,
947                                  str_dstaddr);
948 const parse_token_num_t PROGMEM cmd_range_dstaddr_dstaddr =
949         TOKEN_NUM_INITIALIZER(struct cmd_range_dstaddr_result, dstaddr, UINT64);
950
951
952 const char PROGMEM help_range_dstaddr[] = "set register rangeing dstaddr";
953
954 const parse_inst_t PROGMEM cmd_range_dstaddr = {
955         .f = cmd_range_dstaddr_parsed,  /* function to call */
956         .data = NULL,      /* 2nd arg of func */
957         .help_str = help_range_dstaddr,
958         .tokens = {        /* token list, NULL terminated */
959                 (PGM_P)&cmd_range_dstaddr_range_dstaddr,
960                 (PGM_P)&cmd_range_dstaddr_action,
961                 (PGM_P)&cmd_range_dstaddr_dstaddr,
962                 NULL,
963         },
964 };
965
966
967 /* ************* */
968
969 /* this structure is filled when cmd_monitor is parsed successfully */
970 struct cmd_monitor_result {
971         fixed_string_t monitor;
972         fixed_string_t action;
973 };
974
975 /* function called when cmd_monitor is parsed successfully */
976 static void cmd_monitor_parsed(void *parsed_result, void *data)
977 {
978         struct cmd_monitor_result *res = parsed_result;
979         struct monitor_reg *m;
980
981         (void)data;
982         if (!strcmp_P(res->action, PSTR("show"))) {
983                 printf_P(PSTR("monitor period is %d ms, %d regs in list\r\n"),
984                        monitor_period_ms, monitor_count);
985                 LIST_FOREACH(m, &xbee_monitor_list, next)
986                         printf_P(PSTR(" %S\r\n"), m->desc);
987         }
988         else if (!strcmp_P(res->action, PSTR("start"))) {
989                 if (monitor_running) {
990                         printf_P(PSTR("already running\r\n"));
991                         return;
992                 }
993                 if (monitor_count == 0) {
994                         printf_P(PSTR("no regs to be monitored\r\n"));
995                         return;
996                 }
997                 callout_init(&monitor_event);
998                 callout_reset(&cm, &monitor_event, 0, SINGLE, monitor_cb, NULL);
999                 monitor_running = 1;
1000                 monitor_current = LIST_FIRST(&xbee_monitor_list);
1001                 printf_P(PSTR("monitor cb: %S %s\r\n"),
1002                          monitor_current->desc,
1003                          monitor_current->atcmd);
1004
1005         }
1006         else if (!strcmp_P(res->action, PSTR("end"))) {
1007                 if (monitor_running == 0) {
1008                         printf_P(PSTR("not running\r\n"));
1009                         return;
1010                 }
1011                 monitor_running = 0;
1012                 callout_stop(&cm, &monitor_event);
1013         }
1014 }
1015
1016 const char PROGMEM str_monitor[] = "monitor";
1017 const char PROGMEM str_monitor_tokens[] = "show#start#end";
1018
1019 const parse_token_string_t PROGMEM cmd_monitor_monitor =
1020         TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, monitor,
1021                                  str_monitor);
1022 const parse_token_string_t PROGMEM cmd_monitor_action =
1023         TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, action,
1024                                  str_monitor_tokens);
1025
1026 const char PROGMEM help_monitor[] = "start/stop/show current monitoring";
1027
1028 const parse_inst_t PROGMEM cmd_monitor = {
1029         .f = cmd_monitor_parsed,  /* function to call */
1030         .data = NULL,      /* 2nd arg of func */
1031         .help_str = help_monitor,
1032         .tokens = {        /* token list, NULL terminated */
1033                 (PGM_P)&cmd_monitor_monitor,
1034                 (PGM_P)&cmd_monitor_action,
1035                 NULL,
1036         },
1037 };
1038
1039 /* ************* */
1040
1041 /* this structure is filled when cmd_monitor_add is parsed successfully */
1042 struct cmd_monitor_add_result {
1043         fixed_string_t monitor;
1044         fixed_string_t action;
1045         struct xbee_atcmd *cmd;
1046 };
1047
1048 /* function called when cmd_monitor_add is parsed successfully */
1049 static void cmd_monitor_add_parsed(void *parsed_result, void *data)
1050 {
1051         struct cmd_monitor_add_result *res = parsed_result;
1052         struct monitor_reg *m;
1053         struct xbee_atcmd copy;
1054
1055         (void)data;
1056         memcpy_P(&copy, res->cmd, sizeof(copy));
1057         LIST_FOREACH(m, &xbee_monitor_list, next) {
1058                 if (!strcmp_P(m->atcmd, copy.name))
1059                         break;
1060         }
1061
1062         if (m != NULL) {
1063                 printf_P(PSTR("already exist\r\n"));
1064                 return;
1065         }
1066
1067         m = malloc(sizeof(*m));
1068         if (m == NULL) {
1069                 printf_P(PSTR("no mem\r\n"));
1070                 return;
1071         }
1072         m->desc = copy.desc;
1073         strcpy_P(m->atcmd, copy.name);
1074         LIST_INSERT_HEAD(&xbee_monitor_list, m, next);
1075         monitor_count ++;
1076 }
1077
1078 const char PROGMEM str_monitor_add[] = "add";
1079
1080 const parse_token_string_t PROGMEM cmd_monitor_add_monitor_add =
1081         TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, monitor,
1082                                  str_monitor);
1083 const parse_token_string_t PROGMEM cmd_monitor_add_action =
1084         TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, action,
1085                                  str_monitor_add);
1086 const parse_token_atcmd_t PROGMEM cmd_monitor_add_atcmd =
1087         TOKEN_ATCMD_INITIALIZER(struct cmd_monitor_add_result, cmd, &xbee_dev,
1088                                 XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
1089
1090
1091 const char PROGMEM help_monitor_add[] = "add a register in monitor list";
1092
1093 const parse_inst_t PROGMEM cmd_monitor_add = {
1094         .f = cmd_monitor_add_parsed,  /* function to call */
1095         .data = NULL,      /* 2nd arg of func */
1096         .help_str = help_monitor_add,
1097         .tokens = {        /* token list, NULL terminated */
1098                 (PGM_P)&cmd_monitor_add_monitor_add,
1099                 (PGM_P)&cmd_monitor_add_action,
1100                 (PGM_P)&cmd_monitor_add_atcmd,
1101                 NULL,
1102         },
1103 };
1104
1105 /* ************* */
1106
1107 /* this structure is filled when cmd_monitor_period is parsed successfully */
1108 struct cmd_monitor_period_result {
1109         fixed_string_t monitor;
1110         fixed_string_t action;
1111         uint32_t period;
1112 };
1113
1114 /* function called when cmd_monitor_period is parsed successfully */
1115 static void cmd_monitor_period_parsed(void *parsed_result, void *data)
1116 {
1117         struct cmd_monitor_period_result *res = parsed_result;
1118
1119         (void)data;
1120         if (res->period < 100) {
1121                 printf_P(PSTR("error, minimum period is 100 ms\r\n"));
1122                 return;
1123         }
1124
1125         monitor_period_ms = res->period;
1126 }
1127
1128 const char PROGMEM str_monitor_period[] = "period";
1129
1130 const parse_token_string_t PROGMEM cmd_monitor_period_monitor_period =
1131         TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, monitor,
1132                                  str_monitor);
1133 const parse_token_string_t PROGMEM cmd_monitor_period_action =
1134         TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, action,
1135                                  str_monitor_period);
1136 const parse_token_num_t PROGMEM cmd_monitor_period_period =
1137         TOKEN_NUM_INITIALIZER(struct cmd_monitor_period_result, period, UINT32);
1138
1139
1140 const char PROGMEM help_monitor_period[] = "set register monitoring period";
1141
1142 const parse_inst_t PROGMEM cmd_monitor_period = {
1143         .f = cmd_monitor_period_parsed,  /* function to call */
1144         .data = NULL,      /* 2nd arg of func */
1145         .help_str = help_monitor_period,
1146         .tokens = {        /* token list, NULL terminated */
1147                 (PGM_P)&cmd_monitor_period_monitor_period,
1148                 (PGM_P)&cmd_monitor_period_action,
1149                 (PGM_P)&cmd_monitor_period_period,
1150                 NULL,
1151         },
1152 };
1153
1154 /* ************* */
1155
1156 /* this structure is filled when cmd_monitor_del is parsed successfully */
1157 struct cmd_monitor_del_result {
1158         fixed_string_t monitor;
1159         fixed_string_t action;
1160         struct monitor_reg *m;
1161 };
1162
1163 /* function called when cmd_monitor_del is parsed successfully */
1164 static void cmd_monitor_del_parsed(void *parsed_result, void *data)
1165 {
1166         struct cmd_monitor_del_result *res = parsed_result;
1167
1168         (void)data;
1169         monitor_current = LIST_NEXT(res->m, next);
1170         LIST_REMOVE(res->m, next);
1171         free(res->m);
1172         monitor_count --;
1173         if (monitor_count == 0) {
1174                 printf_P(PSTR("Disable monitoring, no more event\r\n"));
1175                 callout_stop(&cm, &monitor_event);
1176                 monitor_running = 0;
1177                 return;
1178         }
1179 }
1180
1181 const char PROGMEM str_monitor_del[] = "del";
1182
1183 const parse_token_string_t PROGMEM cmd_monitor_del_monitor_del =
1184         TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, monitor,
1185                                  str_monitor);
1186 const parse_token_string_t PROGMEM cmd_monitor_del_action =
1187         TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, action,
1188                                  str_monitor_del);
1189 const parse_token_monitor_t PROGMEM cmd_monitor_del_atcmd =
1190         TOKEN_MONITOR_INITIALIZER(struct cmd_monitor_del_result, m);
1191
1192
1193 const char PROGMEM help_monitor_del[] = "del a register in monitor list";
1194
1195 const parse_inst_t PROGMEM cmd_monitor_del = {
1196         .f = cmd_monitor_del_parsed,  /* function to call */
1197         .data = NULL,      /* 2nd arg of func */
1198         .help_str = help_monitor_del,
1199         .tokens = {        /* token list, NULL terminated */
1200                 (PGM_P)&cmd_monitor_del_monitor_del,
1201                 (PGM_P)&cmd_monitor_del_action,
1202                 (PGM_P)&cmd_monitor_del_atcmd,
1203                 NULL,
1204         },
1205 };
1206
1207
1208 /* ************* */
1209
1210 /* this structure is filled when cmd_ping is parsed successfully */
1211 struct cmd_ping_result {
1212         fixed_string_t ping;
1213 };
1214
1215 /* function called when cmd_ping is parsed successfully */
1216 static void cmd_ping_parsed(void *parsed_result, void *data)
1217 {
1218         (void)parsed_result;
1219         (void)data;
1220         xbeeapp_send_atcmd("VL", NULL, 0, 1, NULL, NULL);
1221 }
1222
1223 const char PROGMEM str_ping[] = "ping";
1224
1225 const parse_token_string_t PROGMEM cmd_ping_ping =
1226         TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping,
1227                                  str_ping);
1228
1229 const char PROGMEM help_ping[] = "Send a ping to the xbee device";
1230
1231 const parse_inst_t PROGMEM cmd_ping = {
1232         .f = cmd_ping_parsed,  /* function to call */
1233         .data = NULL,      /* 2nd arg of func */
1234         .help_str = help_ping,
1235         .tokens = {        /* token list, NULL terminated */
1236                 (PGM_P)&cmd_ping_ping,
1237                 NULL,
1238         },
1239 };
1240
1241 /* ************* */
1242
1243 /* this structure is filled when cmd_raw is parsed successfully */
1244 struct cmd_raw_result {
1245         fixed_string_t raw;
1246 };
1247
1248 /* function called when cmd_raw is parsed successfully */
1249 static void cmd_raw_parsed(void *parsed_result, void *data)
1250 {
1251         (void)parsed_result;
1252         (void)data;
1253         printf_P(PSTR("switched to raw mode, CTRL-D to exit\r\n"));
1254         rdline_stop(&xbeeboard.rdl); /* don't display prompt when return */
1255         xbee_raw = 1;
1256 }
1257
1258 const char PROGMEM str_raw[] = "raw";
1259
1260 const parse_token_string_t PROGMEM cmd_raw_raw =
1261         TOKEN_STRING_INITIALIZER(struct cmd_raw_result, raw,
1262                                  str_raw);
1263
1264 const char PROGMEM help_raw[] = "Switch to raw mode";
1265
1266 const parse_inst_t PROGMEM cmd_raw = {
1267         .f = cmd_raw_parsed,  /* function to call */
1268         .data = NULL,      /* 2nd arg of func */
1269         .help_str = help_raw,
1270         .tokens = {        /* token list, NULL terminated */
1271                 (PGM_P)&cmd_raw_raw,
1272                 NULL,
1273         },
1274 };
1275
1276 /* ************* */
1277
1278 /* this structure is filled when cmd_dump is parsed successfully */
1279 struct cmd_dump_result {
1280         fixed_string_t dump;
1281         fixed_string_t onoff;
1282 };
1283
1284 /* function called when cmd_dump is parsed successfully */
1285 static void cmd_dump_parsed(void *parsed_result, void *data)
1286 {
1287         struct cmd_dump_result *res = parsed_result;
1288
1289         (void)data;
1290         if (!strcmp(res->onoff, "on"))
1291                 xbee_hexdump = 1;
1292         else
1293                 xbee_hexdump = 0;
1294 }
1295
1296 const char PROGMEM str_dump[] = "dump";
1297 const char PROGMEM str_dump_onoff[] = "on#off";
1298
1299 const parse_token_string_t PROGMEM cmd_dump_dump =
1300         TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump,
1301                                  str_dump);
1302
1303 const parse_token_string_t PROGMEM cmd_dump_onoff =
1304         TOKEN_STRING_INITIALIZER(struct cmd_dump_result, onoff,
1305                                  str_dump_onoff);
1306
1307 const char PROGMEM help_dump[] = "enable/disable hexdump of received packets";
1308
1309 const parse_inst_t PROGMEM cmd_dump = {
1310         .f = cmd_dump_parsed,  /* function to call */
1311         .data = NULL,      /* 2nd arg of func */
1312         .help_str = help_dump,
1313         .tokens = {        /* token list, NULL terminated */
1314                 (PGM_P)&cmd_dump_dump,
1315                 (PGM_P)&cmd_dump_onoff,
1316                 NULL,
1317         },
1318 };
1319
1320 /* ************* */
1321
1322 /* this structure is filled when cmd_debug is parsed successfully */
1323 struct cmd_debug_result {
1324         fixed_string_t debug;
1325         fixed_string_t onoff;
1326 };
1327
1328 /* function called when cmd_debug is parsed successfully */
1329 static void cmd_debug_parsed(void *parsed_result, void *data)
1330 {
1331         struct cmd_debug_result *res = parsed_result;
1332
1333         (void)data;
1334         if (!strcmp(res->onoff, "on"))
1335                 xbee_debug = 1;
1336         else
1337                 xbee_debug = 0;
1338 }
1339
1340 const char PROGMEM str_debug[] = "debug";
1341 const char PROGMEM str_debug_onoff[] = "on#off";
1342
1343 const parse_token_string_t PROGMEM cmd_debug_debug =
1344         TOKEN_STRING_INITIALIZER(struct cmd_debug_result, debug,
1345                                  str_debug);
1346
1347 const parse_token_string_t PROGMEM cmd_debug_onoff =
1348         TOKEN_STRING_INITIALIZER(struct cmd_debug_result, onoff,
1349                                  str_debug_onoff);
1350
1351 const char PROGMEM help_debug[] = "enable/disable additionnal debug";
1352
1353 const parse_inst_t PROGMEM cmd_debug = {
1354         .f = cmd_debug_parsed,  /* function to call */
1355         .data = NULL,      /* 2nd arg of func */
1356         .help_str = help_debug,
1357         .tokens = {        /* token list, NULL terminated */
1358                 (PGM_P)&cmd_debug_debug,
1359                 (PGM_P)&cmd_debug_onoff,
1360                 NULL,
1361         },
1362 };
1363
1364 /**********************************************************/
1365
1366 /* this structure is filled when cmd_baudrate is parsed successfully */
1367 struct cmd_baudrate_result {
1368         fixed_string_t arg0;
1369         uint32_t arg1;
1370 };
1371
1372 /* function called when cmd_baudrate is parsed successfully */
1373 static void cmd_baudrate_parsed(void * parsed_result, __attribute__((unused)) void *data)
1374 {
1375         struct cmd_baudrate_result *res = parsed_result;
1376         struct uart_config c;
1377
1378         uart_getconf(XBEE_UART, &c);
1379         c.baudrate = res->arg1;
1380         uart_setconf(XBEE_UART, &c);
1381 }
1382
1383 const char PROGMEM str_baudrate_arg0[] = "baudrate";
1384 const parse_token_string_t PROGMEM cmd_baudrate_arg0 =
1385         TOKEN_STRING_INITIALIZER(struct cmd_baudrate_result, arg0,
1386                                  str_baudrate_arg0);
1387 const parse_token_num_t PROGMEM cmd_baudrate_arg1 =
1388         TOKEN_NUM_INITIALIZER(struct cmd_baudrate_result, arg1,
1389                               UINT32);
1390
1391 const char PROGMEM help_baudrate[] = "Change xbee baudrate";
1392 const parse_inst_t PROGMEM cmd_baudrate = {
1393         .f = cmd_baudrate_parsed,  /* function to call */
1394         .data = NULL,      /* 2nd arg of func */
1395         .help_str = help_baudrate,
1396         .tokens = {        /* token list, NULL terminated */
1397                 (PGM_P)&cmd_baudrate_arg0,
1398                 (PGM_P)&cmd_baudrate_arg1,
1399                 NULL,
1400         },
1401 };
1402
1403
1404 /**********************************************************/
1405
1406 /* this structure is filled when cmd_beep is parsed successfully */
1407 struct cmd_beep_result {
1408         fixed_string_t beep;
1409 };
1410
1411 /* function called when cmd_beep is parsed successfully */
1412 static void cmd_beep_parsed(void *parsed_result, void *data)
1413 {
1414         (void)parsed_result;
1415         (void)data;
1416
1417         beep(0, 3, 3);
1418         beep(1, 3, 3);
1419         beep(2, 3, 3);
1420         beep(0, 1, 1);
1421         beep(1, 1, 1);
1422         beep(2, 1, 1);
1423 }
1424
1425 const char PROGMEM str_beep[] = "beep";
1426 const parse_token_string_t PROGMEM cmd_beep_beep =
1427         TOKEN_STRING_INITIALIZER(struct cmd_beep_result, beep,
1428                                  str_beep);
1429
1430 const char PROGMEM help_beep[] = "Send a beep";
1431
1432 const parse_inst_t PROGMEM cmd_beep = {
1433         .f = cmd_beep_parsed,  /* function to call */
1434         .data = NULL,      /* 2nd arg of func */
1435         .help_str = help_beep,
1436         .tokens = {        /* token list, NULL terminated */
1437                 (PGM_P)&cmd_beep_beep,
1438                 NULL,
1439         },
1440 };
1441
1442 /**********************************************************/
1443
1444 /* this structure is filled when cmd_servo is parsed successfully */
1445 struct cmd_servo_result {
1446         fixed_string_t arg0;
1447         fixed_string_t arg1;
1448         uint16_t num;
1449         uint16_t val;
1450 };
1451
1452 /* function called when cmd_servo is parsed successfully */
1453 static void cmd_servo_parsed(void * parsed_result, void *data)
1454 {
1455         struct cmd_servo_result *res = parsed_result;
1456
1457         (void)data;
1458
1459         if (!strcmp_P(res->arg1, PSTR("set"))) {
1460                 if (res->num >= N_SERVO) {
1461                         printf_P(PSTR("bad servo num\n"));
1462                         return;
1463                 }
1464                 if (res->val >= 1024) {
1465                         printf_P(PSTR("bad servo val\n"));
1466                         return;
1467                 }
1468                 spi_servo_set(res->num, res->val);
1469         }
1470         else if (!strcmp_P(res->arg1, PSTR("bypass"))) {
1471                 spi_servo_set_bypass(!!res->val);
1472         }
1473         else if (!strcmp_P(res->arg1, PSTR("ppm"))) {
1474                 spi_servo_set_ppm(!!res->val);
1475         }
1476         else if (!strcmp_P(res->arg1, PSTR("show"))) {
1477                 spi_servo_dump();
1478         }
1479 }
1480
1481 const char PROGMEM str_servo_arg0[] = "servo";
1482 const parse_token_string_t PROGMEM cmd_servo_arg0 =
1483         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg0,
1484                                  str_servo_arg0);
1485 const char PROGMEM str_servo_arg1_set[] = "set";
1486 const parse_token_string_t PROGMEM cmd_servo_arg1_set =
1487         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1488                                  str_servo_arg1_set);
1489 const parse_token_num_t PROGMEM cmd_servo_num =
1490         TOKEN_NUM_INITIALIZER(struct cmd_servo_result, num,
1491                               UINT16);
1492 const parse_token_num_t PROGMEM cmd_servo_val =
1493         TOKEN_NUM_INITIALIZER(struct cmd_servo_result, val,
1494                               UINT16);
1495
1496 const char PROGMEM help_servo_set[] = "set servo value";
1497 const parse_inst_t PROGMEM cmd_servo_set = {
1498         .f = cmd_servo_parsed,  /* function to call */
1499         .data = NULL,      /* 2nd arg of func */
1500         .help_str = help_servo_set,
1501         .tokens = {        /* token list, NULL terminated */
1502                 (PGM_P)&cmd_servo_arg0,
1503                 (PGM_P)&cmd_servo_arg1_set,
1504                 (PGM_P)&cmd_servo_num,
1505                 (PGM_P)&cmd_servo_val,
1506                 NULL,
1507         },
1508 };
1509
1510 const char PROGMEM str_servo_arg1_show[] = "show";
1511 const parse_token_string_t PROGMEM cmd_servo_arg1_show =
1512         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1513                                  str_servo_arg1_show);
1514
1515 const char PROGMEM help_servo_show[] = "read servo and config";
1516 const parse_inst_t PROGMEM cmd_servo_show = {
1517         .f = cmd_servo_parsed,  /* function to call */
1518         .data = NULL,      /* 2nd arg of func */
1519         .help_str = help_servo_show,
1520         .tokens = {        /* token list, NULL terminated */
1521                 (PGM_P)&cmd_servo_arg0,
1522                 (PGM_P)&cmd_servo_arg1_show,
1523                 NULL,
1524         },
1525 };
1526
1527 const char PROGMEM str_servo_arg1_bypassppm[] = "bypass#ppm";
1528 const parse_token_string_t PROGMEM cmd_servo_arg1_bypassppm =
1529         TOKEN_STRING_INITIALIZER(struct cmd_servo_result, arg1,
1530                                  str_servo_arg1_bypassppm);
1531
1532 const char PROGMEM help_servo_bypassppm[] = "change bypass/ppm";
1533 const parse_inst_t PROGMEM cmd_servo_bypassppm = {
1534         .f = cmd_servo_parsed,  /* function to call */
1535         .data = NULL,      /* 2nd arg of func */
1536         .help_str = help_servo_bypassppm,
1537         .tokens = {        /* token list, NULL terminated */
1538                 (PGM_P)&cmd_servo_arg0,
1539                 (PGM_P)&cmd_servo_arg1_bypassppm,
1540                 (PGM_P)&cmd_servo_val,
1541                 NULL,
1542         },
1543 };
1544
1545 /**********************************************************/
1546
1547 /* this structure is filled when cmd_test_spi is parsed successfully */
1548 struct cmd_test_spi_result {
1549         fixed_string_t arg0;
1550 };
1551
1552 static void cmd_test_spi_parsed(void * parsed_result, void *data)
1553 {
1554         uint8_t i, flags, wait_time = 0;
1555         uint16_t val = 0;
1556
1557         (void)parsed_result;
1558         (void)data;
1559
1560         spi_servo_set_bypass(0);
1561         spi_servo_set_ppm(0);
1562
1563         /* stress test: send many commands, no wait between each servo
1564          * of a series, and a variable delay between series */
1565         printf_P(PSTR("stress test\r\n"));
1566         while (!cmdline_keypressed()) {
1567
1568                 wait_time++;
1569                 if (wait_time > 20)
1570                         wait_time = 0;
1571
1572                 IRQ_LOCK(flags);
1573                 val = global_ms;
1574                 IRQ_UNLOCK(flags);
1575                 val >>= 3;
1576                 val &= 1023;
1577
1578                 for (i = 0; i < 6; i++)
1579                         spi_servo_set(i, val);
1580
1581                 wait_ms(wait_time);
1582                 printf_P(PSTR("%4.4d %4.4d %4.4d %4.4d %4.4d %4.4d\r\n"),
1583                          spi_servo_get(0), spi_servo_get(1), spi_servo_get(2),
1584                          spi_servo_get(3), spi_servo_get(4), spi_servo_get(5));
1585         }
1586
1587         printf_P(PSTR("bypass mode, with spi commands in background\r\n"));
1588         spi_servo_set_bypass(1);
1589
1590         /* test bypass mode */
1591         while (!cmdline_keypressed()) {
1592
1593                 wait_time++;
1594                 if (wait_time > 20)
1595                         wait_time = 0;
1596
1597                 IRQ_LOCK(flags);
1598                 val = global_ms;
1599                 IRQ_UNLOCK(flags);
1600                 val >>= 3;
1601                 val &= 1023;
1602
1603                 for (i = 0; i < 6; i++)
1604                         spi_servo_set(i, val);
1605
1606                 wait_ms(wait_time);
1607                 printf_P(PSTR("%4.4d %4.4d %4.4d %4.4d %4.4d %4.4d\r\n"),
1608                          spi_servo_get(0), spi_servo_get(1), spi_servo_get(2),
1609                          spi_servo_get(3), spi_servo_get(4), spi_servo_get(5));
1610         }
1611
1612         printf_P(PSTR("PPM to servo\r\n"));
1613         spi_servo_set_bypass(0);
1614         spi_servo_set_ppm(0);
1615
1616         /* test PPM to servo (bypass) mode */
1617         while (!cmdline_keypressed()) {
1618                 for (i = 0; i < 6; i++) {
1619                         val = spi_servo_get(i);
1620                         spi_servo_set(i, val);
1621                 }
1622         }
1623
1624         printf_P(PSTR("PPM to (servo + PPM)\r\n"));
1625         spi_servo_set_bypass(0);
1626         spi_servo_set_ppm(1);
1627
1628         /* test PPM to servo (bypass) mode */
1629         while (!cmdline_keypressed()) {
1630                 for (i = 0; i < 6; i++) {
1631                         val = spi_servo_get(i);
1632                         spi_servo_set(i, val);
1633                 }
1634         }
1635 }
1636
1637 const char PROGMEM str_test_spi_arg0[] = "test_spi";
1638 const parse_token_string_t PROGMEM cmd_test_spi_arg0 =
1639         TOKEN_STRING_INITIALIZER(struct cmd_test_spi_result, arg0,
1640                                  str_test_spi_arg0);
1641
1642 const char PROGMEM help_test_spi[] = "Test the spi";
1643 const parse_inst_t PROGMEM cmd_test_spi = {
1644         .f = cmd_test_spi_parsed,  /* function to call */
1645         .data = NULL,      /* 2nd arg of func */
1646         .help_str = help_test_spi,
1647         .tokens = {        /* token list, NULL terminated */
1648                 (PGM_P)&cmd_test_spi_arg0,
1649                 NULL,
1650         },
1651 };
1652
1653 /**********************************************************/
1654
1655 /* this structure is filled when cmd_dump_xbee_stats is parsed successfully */
1656 struct cmd_dump_xbee_stats_result {
1657         fixed_string_t arg0;
1658 };
1659
1660 static void cmd_dump_xbee_stats_parsed(void *parsed_result, void *data)
1661 {
1662         (void)parsed_result;
1663         (void)data;
1664
1665         xbee_dump_stats(xbee_dev);
1666 }
1667
1668 const char PROGMEM str_dump_xbee_stats_arg0[] = "dump_xbee_stats";
1669 const parse_token_string_t PROGMEM cmd_dump_xbee_stats_arg0 =
1670         TOKEN_STRING_INITIALIZER(struct cmd_dump_xbee_stats_result, arg0,
1671                                  str_dump_xbee_stats_arg0);
1672
1673 const char PROGMEM help_dump_xbee_stats[] = "Test the spi";
1674 const parse_inst_t PROGMEM cmd_dump_xbee_stats = {
1675         .f = cmd_dump_xbee_stats_parsed,  /* function to call */
1676         .data = NULL,      /* 2nd arg of func */
1677         .help_str = help_dump_xbee_stats,
1678         .tokens = {        /* token list, NULL terminated */
1679                 (PGM_P)&cmd_dump_xbee_stats_arg0,
1680                 NULL,
1681         },
1682 };
1683
1684 /**********************************************************/
1685
1686 /* this structure is filled when cmd_test_eeprom_config is parsed successfully */
1687 struct cmd_test_eeprom_config_result {
1688         fixed_string_t arg0;
1689 };
1690
1691 static void cmd_test_eeprom_config_parsed(void *parsed_result, void *data)
1692 {
1693         (void)parsed_result;
1694         (void)data;
1695
1696         eeprom_dump_cmds();
1697         eeprom_append_cmd("salut1\n");
1698         eeprom_dump_cmds();
1699         eeprom_append_cmd("salut2\n");
1700         eeprom_append_cmd("salut3\n");
1701         eeprom_append_cmd("salut4\n");
1702         eeprom_dump_cmds();
1703         eeprom_insert_cmd_before("coin\n", 0);
1704         eeprom_insert_cmd_before("coin2\n", 2);
1705         eeprom_dump_cmds();
1706         eeprom_delete_cmd(2);
1707         eeprom_delete_cmd(0);
1708         eeprom_dump_cmds();
1709 }
1710
1711 const char PROGMEM str_test_eeprom_config_arg0[] = "test_eeprom_config";
1712 const parse_token_string_t PROGMEM cmd_test_eeprom_config_arg0 =
1713         TOKEN_STRING_INITIALIZER(struct cmd_test_eeprom_config_result, arg0,
1714                                  str_test_eeprom_config_arg0);
1715
1716 const char PROGMEM help_test_eeprom_config[] = "Test the eeprom configuration";
1717 const parse_inst_t PROGMEM cmd_test_eeprom_config = {
1718         .f = cmd_test_eeprom_config_parsed,  /* function to call */
1719         .data = NULL,      /* 2nd arg of func */
1720         .help_str = help_test_eeprom_config,
1721         .tokens = {        /* token list, NULL terminated */
1722                 (PGM_P)&cmd_test_eeprom_config_arg0,
1723                 NULL,
1724         },
1725 };
1726
1727 /* ************* */
1728
1729 struct cmd_eeprom_del_result {
1730         fixed_string_t cmd;
1731         fixed_string_t action;
1732         uint8_t n;
1733 };
1734
1735 static void cmd_eeprom_del_parsed(void *parsed_result,
1736                                 void *data)
1737 {
1738         struct cmd_eeprom_del_result *res = parsed_result;
1739
1740         (void)data;
1741         if (eeprom_delete_cmd(res->n) < 0)
1742                 printf_P(PSTR("cannot delete command\n"));
1743         eeprom_dump_cmds();
1744 }
1745
1746 const char PROGMEM str_eeprom_del_eeprom[] = "eeprom";
1747 const parse_token_string_t PROGMEM cmd_eeprom_del_cmd =
1748         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_del_result, cmd,
1749                                  str_eeprom_del_eeprom);
1750 const char PROGMEM str_eeprom_del_del[] = "del";
1751 const parse_token_string_t PROGMEM cmd_eeprom_del_action =
1752         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_del_result, action,
1753                                  str_eeprom_del_del);
1754 const parse_token_num_t PROGMEM cmd_eeprom_del_num =
1755         TOKEN_NUM_INITIALIZER(struct cmd_eeprom_del_result, n,
1756                               UINT8);
1757
1758 const char PROGMEM help_eeprom_del[] = "delete an eeprom init command";
1759 const parse_inst_t PROGMEM cmd_eeprom_del = {
1760         .f = cmd_eeprom_del_parsed,  /* function to call */
1761         .data = NULL,      /* 2nd arg of func */
1762         .help_str = help_eeprom_del,
1763         .tokens = {        /* token list, NULL terminated */
1764                 (PGM_P)&cmd_eeprom_del_cmd,
1765                 (PGM_P)&cmd_eeprom_del_action,
1766                 (PGM_P)&cmd_eeprom_del_num,
1767                 NULL,
1768         },
1769 };
1770
1771 /* ************* */
1772
1773 struct cmd_eeprom_add_result {
1774         fixed_string_t cmd;
1775         fixed_string_t action;
1776         uint8_t n;
1777 };
1778
1779 static void cmd_eeprom_add_parsed(void *parsed_result,
1780                                  void *data)
1781 {
1782         struct cmd_eeprom_add_result *res = parsed_result;
1783         struct rdline rdl;
1784         const char *buffer;
1785         int8_t ret;
1786         int16_t c;
1787
1788         rdline_init(&rdl, cmdline_write_char, NULL, NULL);
1789         rdline_newline(&rdl, "> ");
1790
1791         /* XXX bad: we should not block as we do not serve callout */
1792         while (1) {
1793                 c = cmdline_dev_recv(NULL);
1794                 if (c < 0)
1795                         continue;
1796
1797                 ret = rdline_char_in(&rdl, c);
1798                 if (ret == -2) {
1799                         printf_P(PSTR("abort\n"));
1800                         return;
1801                 }
1802                 if (ret == 1)
1803                         break;
1804         }
1805
1806         buffer = rdline_get_buffer(&rdl);
1807         if (data == NULL)
1808                 eeprom_insert_cmd_before(buffer, res->n);
1809         else
1810                 eeprom_append_cmd(buffer);
1811         eeprom_dump_cmds();
1812 }
1813
1814 const char PROGMEM str_eeprom_add_eeprom[] = "eeprom";
1815 const parse_token_string_t PROGMEM cmd_eeprom_add_cmd =
1816         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_add_result, cmd,
1817                                  str_eeprom_add_eeprom);
1818 const char PROGMEM str_eeprom_add_add[] = "add";
1819 const parse_token_string_t PROGMEM cmd_eeprom_add_action =
1820         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_add_result, action,
1821                                  str_eeprom_add_add);
1822 const parse_token_num_t PROGMEM cmd_eeprom_add_num =
1823         TOKEN_NUM_INITIALIZER(struct cmd_eeprom_add_result, n,
1824                               UINT8);
1825
1826 const char PROGMEM help_eeprom_add[] = "insert an eeprom init command";
1827 const parse_inst_t PROGMEM cmd_eeprom_add = {
1828         .f = cmd_eeprom_add_parsed,  /* function to call */
1829         .data = NULL,      /* 2nd arg of func */
1830         .help_str = help_eeprom_add,
1831         .tokens = {        /* token list, NULL terminated */
1832                 (PGM_P)&cmd_eeprom_add_cmd,
1833                 (PGM_P)&cmd_eeprom_add_action,
1834                 (PGM_P)&cmd_eeprom_add_num,
1835                 NULL,
1836         },
1837 };
1838
1839 const char PROGMEM help_eeprom_add2[] = "append an eeprom init command";
1840 const parse_inst_t PROGMEM cmd_eeprom_add2 = {
1841         .f = cmd_eeprom_add_parsed,  /* function to call */
1842         .data = (void *)1,      /* 2nd arg of func */
1843         .help_str = help_eeprom_add2,
1844         .tokens = {        /* token list, NULL terminated */
1845                 (PGM_P)&cmd_eeprom_add_cmd,
1846                 (PGM_P)&cmd_eeprom_add_action,
1847                 NULL,
1848         },
1849 };
1850
1851 /* ************* */
1852
1853 struct cmd_eeprom_list_result {
1854         fixed_string_t cmd;
1855         fixed_string_t action;
1856 };
1857
1858 static void cmd_eeprom_list_parsed(void *parsed_result,
1859                                 void *data)
1860 {
1861         (void)parsed_result;
1862         (void)data;
1863         eeprom_dump_cmds();
1864 }
1865
1866 const char PROGMEM str_eeprom_list_eeprom[] = "eeprom";
1867 const parse_token_string_t PROGMEM cmd_eeprom_list_cmd =
1868         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_list_result, cmd,
1869                                  str_eeprom_list_eeprom);
1870 const char PROGMEM str_eeprom_list_list[] = "list";
1871 const parse_token_string_t PROGMEM cmd_eeprom_list_action =
1872         TOKEN_STRING_INITIALIZER(struct cmd_eeprom_list_result, action,
1873                                  str_eeprom_list_list);
1874
1875 const char PROGMEM help_eeprom_list[] = "list all eeprom init commands";
1876 const parse_inst_t PROGMEM cmd_eeprom_list = {
1877         .f = cmd_eeprom_list_parsed,  /* function to call */
1878         .data = NULL,      /* 2nd arg of func */
1879         .help_str = help_eeprom_list,
1880         .tokens = {        /* token list, NULL terminated */
1881                 (PGM_P)&cmd_eeprom_list_cmd,
1882                 (PGM_P)&cmd_eeprom_list_action,
1883                 NULL,
1884         },
1885 };
1886
1887
1888 /* ************* */
1889
1890 /* in progmem */
1891 const parse_ctx_t PROGMEM main_ctx[] = {
1892
1893         /* commands_gen.c */
1894         &cmd_reset,
1895         &cmd_bootloader,
1896         &cmd_log,
1897         &cmd_log_show,
1898         &cmd_log_type,
1899         &cmd_stack_space,
1900         &cmd_scheduler,
1901         &cmd_help,
1902         &cmd_neigh_del,
1903         &cmd_neigh_add,
1904         &cmd_neigh_list,
1905         &cmd_read,
1906         &cmd_write_none,
1907         &cmd_write_u8,
1908         &cmd_write_u16,
1909         &cmd_write_u32,
1910         &cmd_sendmsg,
1911         &cmd_send_hello,
1912         &cmd_send_hello_name,
1913         &cmd_sendmsg_name,
1914         &cmd_range,
1915         &cmd_range_period,
1916         &cmd_range_count,
1917         &cmd_range_powermask,
1918         &cmd_range_dstaddr,
1919         &cmd_monitor,
1920         &cmd_monitor_period,
1921         &cmd_monitor_add,
1922         &cmd_monitor_del,
1923         &cmd_ping,
1924         &cmd_raw,
1925         &cmd_dump,
1926         &cmd_debug,
1927         &cmd_baudrate,
1928         &cmd_beep,
1929         &cmd_servo_set,
1930         &cmd_servo_bypassppm,
1931         &cmd_servo_show,
1932         &cmd_test_spi,
1933         &cmd_dump_xbee_stats,
1934         &cmd_test_eeprom_config,
1935         &cmd_eeprom_del,
1936         &cmd_eeprom_add,
1937         &cmd_eeprom_add2,
1938         &cmd_eeprom_list,
1939         NULL,
1940 };