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