cmdline: replace printf printf_P
[protos/xbee-avr.git] / commands2.c
1 /*
2  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
3  * All rights reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <stdio.h>
29 #include <stdint.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <errno.h>
34 #include <ctype.h>
35 #include <sys/queue.h>
36 #include <arpa/inet.h>
37 #include <inttypes.h>
38
39 #include <event.h>
40
41 #include <cmdline_parse.h>
42 #include <cmdline_parse_num.h>
43 #include <cmdline_parse_string.h>
44 #include <cmdline_parse_file.h>
45 #include <cmdline.h>
46
47 #include "xbee_neighbor.h"
48 #include "xbee_atcmd.h"
49 #include "xbee_stats.h"
50 #include "xbee_buf.h"
51 #include "xbee_proto.h"
52 #include "xbee.h"
53 #include "parse_atcmd.h"
54 #include "parse_neighbor.h"
55 #include "parse_monitor.h"
56 #include "main.h"
57
58 static struct monitor_reg_list monitor_list = LIST_HEAD_INITIALIZER(x/*XXX*/);
59 static int monitor_period_ms = 1000;
60 static int monitor_running = 0;
61 static int monitor_count = 0;
62 static struct event monitor_event;
63 struct monitor_reg *monitor_current;
64
65 static int range_period_ms = 1000;
66 static int range_powermask = 0x1F;
67 static uint8_t range_power = 0;
68 static int range_running = 0;
69 static uint64_t range_dstaddr = 0xFFFF; /* broadcast by default */
70 static struct event range_event;
71 static int range_count = 100;
72 static int range_cur_count = 0;
73
74 static const char *xbee_logfilename = "/tmp/xbee.log";
75
76 static void monitor_cb(int s, short event, void *arg)
77 {
78         struct timeval tv;
79         struct cmdline *cl = arg;
80
81         if (monitor_current == NULL)
82                 monitor_current = LIST_FIRST(&monitor_list);
83
84         xbeeapp_send_atcmd(monitor_current->atcmd, NULL, 0, 0);
85         monitor_current = LIST_NEXT(monitor_current, next);
86
87         evtimer_set(&monitor_event, monitor_cb, cl);
88         tv.tv_sec = 0;
89         tv.tv_usec = (1000 * monitor_period_ms) / monitor_count;
90         evtimer_add(&monitor_event, &tv);
91 }
92
93 static void range_cb(int s, short event, void *arg)
94 {
95         struct timeval tv;
96         struct cmdline *cl = arg;
97         char buf[16];
98         uint8_t i, mask;
99
100         range_cur_count--;
101
102         /* get new xmit power */
103         for (i = 1; i <= 8; i++) {
104                 mask = 1 << ((range_power + i) & 0x7);
105                 if (mask & range_powermask)
106                         break;
107         }
108         range_power = ((range_power + i) & 0x7);
109
110         xbeeapp_send_atcmd("PL", &range_power, sizeof(range_power), 0, NULL, NULL);
111         snprintf(buf, sizeof(buf), "range%d", range_power);
112         xbeeapp_send_msg(range_dstaddr, buf, strlen(buf), 0);
113
114         if (range_cur_count == 0) {
115                 range_running = 0;
116                 return;
117         }
118
119         evtimer_set(&range_event, range_cb, cl);
120         tv.tv_sec = 0;
121         tv.tv_usec = 1000 * range_period_ms;
122         evtimer_add(&range_event, &tv);
123 }
124
125 /* ************* */
126
127 /* this structure is filled when cmd_stats is parsed successfully */
128 struct cmd_stats_result {
129         fixed_string_t stats;
130         fixed_string_t action;
131 };
132
133 /* function called when cmd_stats is parsed successfully */
134 static void cmd_stats_parsed(void *parsed_result, struct cmdline *cl, void *data)
135 {
136         struct cmd_stats_result *res = parsed_result;
137
138         if (!strcmp(res->action, "show")) {
139                 xbee_dump_stats(stdout, xbee_dev);
140                 if (xbee_logfile != NULL)
141                         xbee_dump_stats(xbee_logfile, xbee_dev);
142         }
143         else if (!strcmp(res->action, "reset"))
144                 xbee_reset_stats(xbee_dev);
145 }
146
147 parse_pgm_token_string_t cmd_stats_stats =
148         TOKEN_STRING_INITIALIZER(struct cmd_stats_result, stats, "stats");
149 parse_pgm_token_string_t cmd_stats_action =
150         TOKEN_STRING_INITIALIZER(struct cmd_stats_result, action, "show#reset");
151
152 parse_pgm_inst_t cmd_stats = {
153         .f = cmd_stats_parsed,  /* function to call */
154         .data = NULL,      /* 2nd arg of func */
155         .help_str = "Send a stats to the xbee device",
156         .tokens = {        /* token list, NULL terminated */
157                 (prog_void *)&cmd_stats_stats,
158                 (prog_void *)&cmd_stats_action,
159                 NULL,
160         },
161 };
162
163 /* ************* */
164
165 /* this structure is filled when cmd_monitor is parsed successfully */
166 struct cmd_monitor_result {
167         fixed_string_t monitor;
168         fixed_string_t action;
169 };
170
171 /* function called when cmd_monitor is parsed successfully */
172 static void cmd_monitor_parsed(void *parsed_result, struct cmdline *cl,
173                                void *data)
174 {
175         struct cmd_monitor_result *res = parsed_result;
176         struct monitor_reg *m;
177
178         if (!strcmp(res->action, "show")) {
179                 printf("monitor period is %d ms, %d regs in list\n",
180                        monitor_period_ms, monitor_count);
181                 LIST_FOREACH(m, &monitor_list, next)
182                         printf(" %s\n", m->desc);
183         }
184         else if (!strcmp(res->action, "start")) {
185                 struct timeval tv;
186                 if (monitor_running) {
187                         printf("already running\n");
188                         return;
189                 }
190                 if (monitor_count == 0) {
191                         printf("no regs to be monitored\n");
192                         return;
193                 }
194                 evtimer_set(&monitor_event, monitor_cb, cl);
195                 tv.tv_sec = 0;
196                 tv.tv_usec = 0;
197                 evtimer_add(&monitor_event, &tv);
198                 monitor_running = 1;
199                 monitor_current = LIST_FIRST(&monitor_list);
200         }
201         else if (!strcmp(res->action, "end")) {
202                 if (monitor_running == 0) {
203                         printf("not running\n");
204                         return;
205                 }
206                 monitor_running = 0;
207                 evtimer_del(&monitor_event);
208         }
209 }
210
211 parse_pgm_token_string_t cmd_monitor_monitor =
212         TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, monitor, "monitor");
213 parse_pgm_token_string_t cmd_monitor_action =
214         TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, action,
215                                  "show#start#end");
216
217 parse_pgm_inst_t cmd_monitor = {
218         .f = cmd_monitor_parsed,  /* function to call */
219         .data = NULL,      /* 2nd arg of func */
220         .help_str = "start/stop/show current monitoring",
221         .tokens = {        /* token list, NULL terminated */
222                 (prog_void *)&cmd_monitor_monitor,
223                 (prog_void *)&cmd_monitor_action,
224                 NULL,
225         },
226 };
227
228 /* ************* */
229
230 /* this structure is filled when cmd_monitor_add is parsed successfully */
231 struct cmd_monitor_add_result {
232         fixed_string_t monitor;
233         fixed_string_t action;
234         struct xbee_atcmd *cmd;
235 };
236
237 /* function called when cmd_monitor_add is parsed successfully */
238 static void cmd_monitor_add_parsed(void *parsed_result, struct cmdline *cl,
239                                    void *data)
240 {
241         struct cmd_monitor_add_result *res = parsed_result;
242         struct monitor_reg *m;
243
244         LIST_FOREACH(m, &monitor_list, next) {
245                 if (!strcmp(m->desc, res->cmd->desc))
246                         break;
247         }
248
249         if (m != NULL) {
250                 printf("already exist\n");
251                 return;
252         }
253
254         m = malloc(sizeof(*m));
255         if (m == NULL) {
256                 printf("no mem\n");
257                 return;
258         }
259
260         m->desc = res->cmd->desc;
261         m->atcmd = res->cmd->name;
262         LIST_INSERT_HEAD(&monitor_list, m, next);
263         monitor_count ++;
264 }
265
266 parse_pgm_token_string_t cmd_monitor_add_monitor_add =
267         TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, monitor,
268                                  "monitor");
269 parse_pgm_token_string_t cmd_monitor_add_action =
270         TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, action,
271                                  "add");
272 parse_pgm_token_atcmd_t cmd_monitor_add_atcmd =
273         TOKEN_ATCMD_INITIALIZER(struct cmd_monitor_add_result, cmd, &xbee_dev,
274                                 XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
275
276
277 parse_pgm_inst_t cmd_monitor_add = {
278         .f = cmd_monitor_add_parsed,  /* function to call */
279         .data = NULL,      /* 2nd arg of func */
280         .help_str = "add a register in monitor list",
281         .tokens = {        /* token list, NULL terminated */
282                 (prog_void *)&cmd_monitor_add_monitor_add,
283                 (prog_void *)&cmd_monitor_add_action,
284                 (prog_void *)&cmd_monitor_add_atcmd,
285                 NULL,
286         },
287 };
288
289 /* ************* */
290
291 /* this structure is filled when cmd_monitor_period is parsed successfully */
292 struct cmd_monitor_period_result {
293         fixed_string_t monitor;
294         fixed_string_t action;
295         uint32_t period;
296 };
297
298 /* function called when cmd_monitor_period is parsed successfully */
299 static void cmd_monitor_period_parsed(void *parsed_result, struct cmdline *cl,
300                                    void *data)
301 {
302         struct cmd_monitor_period_result *res = parsed_result;
303
304         if (res->period < 100) {
305                 printf("error, minimum period is 100 ms\n");
306                 return;
307         }
308
309         monitor_period_ms = res->period;
310 }
311
312 parse_pgm_token_string_t cmd_monitor_period_monitor_period =
313         TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, monitor,
314                                  "monitor");
315 parse_pgm_token_string_t cmd_monitor_period_action =
316         TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, action,
317                                  "period");
318 parse_pgm_token_num_t cmd_monitor_period_period =
319         TOKEN_NUM_INITIALIZER(struct cmd_monitor_period_result, period, UINT32);
320
321
322 parse_pgm_inst_t cmd_monitor_period = {
323         .f = cmd_monitor_period_parsed,  /* function to call */
324         .data = NULL,      /* 2nd arg of func */
325         .help_str = "set register monitoring period",
326         .tokens = {        /* token list, NULL terminated */
327                 (prog_void *)&cmd_monitor_period_monitor_period,
328                 (prog_void *)&cmd_monitor_period_action,
329                 (prog_void *)&cmd_monitor_period_period,
330                 NULL,
331         },
332 };
333
334 /* ************* */
335
336 /* this structure is filled when cmd_monitor_del is parsed successfully */
337 struct cmd_monitor_del_result {
338         fixed_string_t monitor;
339         fixed_string_t action;
340         struct monitor_reg *m;
341 };
342
343 /* function called when cmd_monitor_del is parsed successfully */
344 static void cmd_monitor_del_parsed(void *parsed_result, struct cmdline *cl,
345                                    void *data)
346 {
347         struct cmd_monitor_del_result *res = parsed_result;
348
349         monitor_current = LIST_NEXT(res->m, next);
350         LIST_REMOVE(res->m, next);
351         free(res->m);
352         monitor_count --;
353         if (monitor_count == 0) {
354                 printf("Disable monitoring, no more event\n");
355                 evtimer_del(&monitor_event);
356                 monitor_running = 0;
357                 return;
358         }
359 }
360
361 parse_pgm_token_string_t cmd_monitor_del_monitor_del =
362         TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, monitor,
363                                  "monitor");
364 parse_pgm_token_string_t cmd_monitor_del_action =
365         TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, action,
366                                  "del");
367 parse_pgm_token_monitor_t cmd_monitor_del_atcmd =
368         TOKEN_MONITOR_INITIALIZER(struct cmd_monitor_del_result, m,
369                                   &monitor_list);
370
371
372 parse_pgm_inst_t cmd_monitor_del = {
373         .f = cmd_monitor_del_parsed,  /* function to call */
374         .data = NULL,      /* 2nd arg of func */
375         .help_str = "del a register in monitor list",
376         .tokens = {        /* token list, NULL terminated */
377                 (prog_void *)&cmd_monitor_del_monitor_del,
378                 (prog_void *)&cmd_monitor_del_action,
379                 (prog_void *)&cmd_monitor_del_atcmd,
380                 NULL,
381         },
382 };
383
384 /* ************* */
385
386 /* this structure is filled when cmd_range is parsed successfully */
387 struct cmd_range_result {
388         fixed_string_t range;
389         fixed_string_t action;
390 };
391
392 /* function called when cmd_range is parsed successfully */
393 static void cmd_range_parsed(void *parsed_result, struct cmdline *cl,
394                                void *data)
395 {
396         struct cmd_range_result *res = parsed_result;
397
398         if (!strcmp(res->action, "show")) {
399                 printf("range infos:\n");
400                 printf("  range period %d\n", range_period_ms);
401                 printf("  range count %d\n", range_count);
402                 printf("  range powermask 0x%x\n", range_powermask);
403                 printf("  range dstaddr %"PRIx64"\n", range_dstaddr);
404                 if (range_running)
405                         printf("  range test is running\n");
406                 else
407                         printf("  range test is not running\n");
408         }
409         else if (!strcmp(res->action, "start")) {
410                 struct timeval tv;
411                 if (range_running) {
412                         printf("already running\n");
413                         return;
414                 }
415                 range_cur_count = range_count;
416                 evtimer_set(&range_event, range_cb, cl);
417                 tv.tv_sec = 0;
418                 tv.tv_usec = 0;
419                 evtimer_add(&range_event, &tv);
420                 range_running = 1;
421         }
422         else if (!strcmp(res->action, "end")) {
423                 if (range_running == 0) {
424                         printf("not running\n");
425                         return;
426                 }
427                 range_running = 0;
428                 evtimer_del(&range_event);
429         }
430 }
431
432 parse_pgm_token_string_t cmd_range_range =
433         TOKEN_STRING_INITIALIZER(struct cmd_range_result, range, "range");
434 parse_pgm_token_string_t cmd_range_action =
435         TOKEN_STRING_INITIALIZER(struct cmd_range_result, action,
436                                  "show#start#end");
437
438 parse_pgm_inst_t cmd_range = {
439         .f = cmd_range_parsed,  /* function to call */
440         .data = NULL,      /* 2nd arg of func */
441         .help_str = "start/stop/show current rangeing",
442         .tokens = {        /* token list, NULL terminated */
443                 (prog_void *)&cmd_range_range,
444                 (prog_void *)&cmd_range_action,
445                 NULL,
446         },
447 };
448
449 /* ************* */
450
451 /* this structure is filled when cmd_range_period is parsed successfully */
452 struct cmd_range_period_result {
453         fixed_string_t range;
454         fixed_string_t action;
455         uint32_t period;
456 };
457
458 /* function called when cmd_range_period is parsed successfully */
459 static void cmd_range_period_parsed(void *parsed_result, struct cmdline *cl,
460                                    void *data)
461 {
462         struct cmd_range_period_result *res = parsed_result;
463
464         if (res->period < 10) {
465                 printf("error, minimum period is 10 ms\n");
466                 return;
467         }
468
469         range_period_ms = res->period;
470 }
471
472 parse_pgm_token_string_t cmd_range_period_range_period =
473         TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, range,
474                                  "range");
475 parse_pgm_token_string_t cmd_range_period_action =
476         TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, action,
477                                  "period");
478 parse_pgm_token_num_t cmd_range_period_period =
479         TOKEN_NUM_INITIALIZER(struct cmd_range_period_result, period, UINT32);
480
481
482 parse_pgm_inst_t cmd_range_period = {
483         .f = cmd_range_period_parsed,  /* function to call */
484         .data = NULL,      /* 2nd arg of func */
485         .help_str = "set range test period",
486         .tokens = {        /* token list, NULL terminated */
487                 (prog_void *)&cmd_range_period_range_period,
488                 (prog_void *)&cmd_range_period_action,
489                 (prog_void *)&cmd_range_period_period,
490                 NULL,
491         },
492 };
493
494 /* ************* */
495
496 /* this structure is filled when cmd_range_count is parsed successfully */
497 struct cmd_range_count_result {
498         fixed_string_t range;
499         fixed_string_t action;
500         uint32_t count;
501 };
502
503 /* function called when cmd_range_count is parsed successfully */
504 static void cmd_range_count_parsed(void *parsed_result, struct cmdline *cl,
505                                    void *data)
506 {
507         struct cmd_range_count_result *res = parsed_result;
508         range_count = res->count;
509 }
510
511 parse_pgm_token_string_t cmd_range_count_range_count =
512         TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, range,
513                                  "range");
514 parse_pgm_token_string_t cmd_range_count_action =
515         TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, action,
516                                  "count");
517 parse_pgm_token_num_t cmd_range_count_count =
518         TOKEN_NUM_INITIALIZER(struct cmd_range_count_result, count, UINT32);
519
520
521 parse_pgm_inst_t cmd_range_count = {
522         .f = cmd_range_count_parsed,  /* function to call */
523         .data = NULL,      /* 2nd arg of func */
524         .help_str = "set range test count",
525         .tokens = {        /* token list, NULL terminated */
526                 (prog_void *)&cmd_range_count_range_count,
527                 (prog_void *)&cmd_range_count_action,
528                 (prog_void *)&cmd_range_count_count,
529                 NULL,
530         },
531 };
532
533 /* ************* */
534
535 /* this structure is filled when cmd_range_powermask is parsed successfully */
536 struct cmd_range_powermask_result {
537         fixed_string_t range;
538         fixed_string_t action;
539         uint8_t powermask;
540 };
541
542 /* function called when cmd_range_powermask is parsed successfully */
543 static void cmd_range_powermask_parsed(void *parsed_result, struct cmdline *cl,
544                                    void *data)
545 {
546         struct cmd_range_powermask_result *res = parsed_result;
547         range_powermask = res->powermask;
548 }
549
550 parse_pgm_token_string_t cmd_range_powermask_range_powermask =
551         TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, range,
552                                  "range");
553 parse_pgm_token_string_t cmd_range_powermask_action =
554         TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, action,
555                                  "powermask");
556 parse_pgm_token_num_t cmd_range_powermask_powermask =
557         TOKEN_NUM_INITIALIZER(struct cmd_range_powermask_result, powermask,
558                               UINT8);
559
560
561 parse_pgm_inst_t cmd_range_powermask = {
562         .f = cmd_range_powermask_parsed,  /* function to call */
563         .data = NULL,      /* 2nd arg of func */
564         .help_str = "set range test powermask",
565         .tokens = {        /* token list, NULL terminated */
566                 (prog_void *)&cmd_range_powermask_range_powermask,
567                 (prog_void *)&cmd_range_powermask_action,
568                 (prog_void *)&cmd_range_powermask_powermask,
569                 NULL,
570         },
571 };
572
573 /* ************* */
574
575 /* this structure is filled when cmd_range_dstaddr is parsed successfully */
576 struct cmd_range_dstaddr_result {
577         fixed_string_t range;
578         fixed_string_t action;
579         uint64_t dstaddr;
580 };
581
582 /* function called when cmd_range_dstaddr is parsed successfully */
583 static void cmd_range_dstaddr_parsed(void *parsed_result, struct cmdline *cl,
584                                      void *data)
585 {
586         struct cmd_range_dstaddr_result *res = parsed_result;
587
588         range_dstaddr = res->dstaddr;
589 }
590
591 parse_pgm_token_string_t cmd_range_dstaddr_range_dstaddr =
592         TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, range,
593                                  "range");
594 parse_pgm_token_string_t cmd_range_dstaddr_action =
595         TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, action,
596                                  "dstaddr");
597 parse_pgm_token_num_t cmd_range_dstaddr_dstaddr =
598         TOKEN_NUM_INITIALIZER(struct cmd_range_dstaddr_result, dstaddr, UINT64);
599
600
601 parse_pgm_inst_t cmd_range_dstaddr = {
602         .f = cmd_range_dstaddr_parsed,  /* function to call */
603         .data = NULL,      /* 2nd arg of func */
604         .help_str = "set register rangeing dstaddr",
605         .tokens = {        /* token list, NULL terminated */
606                 (prog_void *)&cmd_range_dstaddr_range_dstaddr,
607                 (prog_void *)&cmd_range_dstaddr_action,
608                 (prog_void *)&cmd_range_dstaddr_dstaddr,
609                 NULL,
610         },
611 };
612
613 /* ************* */
614
615 /* this structure is filled when cmd_ping is parsed successfully */
616 struct cmd_ping_result {
617         fixed_string_t ping;
618 };
619
620 /* function called when cmd_ping is parsed successfully */
621 static void cmd_ping_parsed(void *parsed_result, struct cmdline *cl, void *data)
622 {
623         xbeeapp_send_atcmd("VL", NULL, 0, 1, NULL, NULL);
624 }
625
626 parse_pgm_token_string_t cmd_ping_ping =
627         TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping, "ping");
628
629 parse_pgm_inst_t cmd_ping = {
630         .f = cmd_ping_parsed,  /* function to call */
631         .data = NULL,      /* 2nd arg of func */
632         .help_str = "Send a ping to the xbee device",
633         .tokens = {        /* token list, NULL terminated */
634                 (prog_void *)&cmd_ping_ping,
635                 NULL,
636         },
637 };
638
639 /* ************* */
640
641 /* this structure is filled when cmd_raw is parsed successfully */
642 struct cmd_raw_result {
643         fixed_string_t raw;
644 };
645
646 /* function called when cmd_raw is parsed successfully */
647 static void cmd_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
648 {
649         printf("switched to raw mode, CTRL-D to exit\n");
650         rdline_stop(&cl->rdl); /* don't display prompt when return */
651         xbee_raw = 1;
652 }
653
654 parse_pgm_token_string_t cmd_raw_raw =
655         TOKEN_STRING_INITIALIZER(struct cmd_raw_result, raw, "raw");
656
657 parse_pgm_inst_t cmd_raw = {
658         .f = cmd_raw_parsed,  /* function to call */
659         .data = NULL,      /* 2nd arg of func */
660         .help_str = "Switch to raw mode",
661         .tokens = {        /* token list, NULL terminated */
662                 (prog_void *)&cmd_raw_raw,
663                 NULL,
664         },
665 };
666
667 /* ************* */
668
669 /* this structure is filled when cmd_dump is parsed successfully */
670 struct cmd_dump_result {
671         fixed_string_t dump;
672         fixed_string_t onoff;
673 };
674
675 /* function called when cmd_dump is parsed successfully */
676 static void cmd_dump_parsed(void *parsed_result, struct cmdline *cl, void *data)
677 {
678         struct cmd_dump_result *res = parsed_result;
679         if (!strcmp(res->onoff, "on"))
680                 xbee_hexdump = 1;
681         else
682                 xbee_hexdump = 0;
683 }
684
685 parse_pgm_token_string_t cmd_dump_dump =
686         TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump, "dump");
687
688 parse_pgm_token_string_t cmd_dump_onoff =
689         TOKEN_STRING_INITIALIZER(struct cmd_dump_result, onoff, "on#off");
690
691 parse_pgm_inst_t cmd_dump = {
692         .f = cmd_dump_parsed,  /* function to call */
693         .data = NULL,      /* 2nd arg of func */
694         .help_str = "enable/disable hexdump of received packets",
695         .tokens = {        /* token list, NULL terminated */
696                 (prog_void *)&cmd_dump_dump,
697                 (prog_void *)&cmd_dump_onoff,
698                 NULL,
699         },
700 };
701
702 /* ************* */
703
704 /* this structure is filled when cmd_debug is parsed successfully */
705 struct cmd_debug_result {
706         fixed_string_t debug;
707         fixed_string_t onoff;
708 };
709
710 /* function called when cmd_debug is parsed successfully */
711 static void cmd_debug_parsed(void *parsed_result, struct cmdline *cl, void *data)
712 {
713         struct cmd_debug_result *res = parsed_result;
714         if (!strcmp(res->onoff, "on"))
715                 xbee_debug = 1;
716         else
717                 xbee_debug = 0;
718 }
719
720 parse_pgm_token_string_t cmd_debug_debug =
721         TOKEN_STRING_INITIALIZER(struct cmd_debug_result, debug, "debug");
722
723 parse_pgm_token_string_t cmd_debug_onoff =
724         TOKEN_STRING_INITIALIZER(struct cmd_debug_result, onoff, "on#off");
725
726 parse_pgm_inst_t cmd_debug = {
727         .f = cmd_debug_parsed,  /* function to call */
728         .data = NULL,      /* 2nd arg of func */
729         .help_str = "enable/disable additionnal debug",
730         .tokens = {        /* token list, NULL terminated */
731                 (prog_void *)&cmd_debug_debug,
732                 (prog_void *)&cmd_debug_onoff,
733                 NULL,
734         },
735 };
736
737 /* ************* */
738
739 /* this structure is filled when cmd_help is parsed successfully */
740 struct cmd_help_result {
741         fixed_string_t help;
742         struct xbee_atcmd *cmd;
743 };
744
745 /* function called when cmd_help is parsed successfully */
746 static void cmd_help_parsed(void *parsed_result, struct cmdline *cl,
747                             void *data)
748 {
749         struct cmd_help_result *res = parsed_result;
750         int type;
751
752         type = (res->cmd->flags & (XBEE_ATCMD_F_READ | XBEE_ATCMD_F_WRITE));
753         switch (type) {
754                 case XBEE_ATCMD_F_READ:
755                         printf("Read-only\n");
756                         break;
757                 case XBEE_ATCMD_F_WRITE:
758                         printf("Write-only\n");
759                         break;
760                 default:
761                         printf("Read-write\n");
762                         break;
763         }
764         if (res->cmd->flags & XBEE_ATCMD_F_PARAM_NONE)
765                 printf("No argument\n");
766         else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U8)
767                 printf("Register is unsigned 8 bits\n");
768         else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U16)
769                 printf("Register is unsigned 16 bits\n");
770         else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U32)
771                 printf("Register is unsigned 32 bits\n");
772         else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_S16)
773                 printf("Register is signed 16 bits\n");
774         else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_STRING_20B)
775                 printf("Register is a 20 bytes string\n");
776         else
777                 printf("Unknown argument\n");
778
779         printf("%s\n", res->cmd->help);
780 }
781
782 parse_pgm_token_string_t cmd_help_help =
783         TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help");
784
785 parse_pgm_token_atcmd_t cmd_help_atcmd =
786         TOKEN_ATCMD_INITIALIZER(struct cmd_help_result, cmd, &xbee_dev,
787                                 0, 0);
788
789 parse_pgm_inst_t cmd_help = {
790         .f = cmd_help_parsed,  /* function to call */
791         .data = NULL,      /* 2nd arg of func */
792         .help_str = "Help a register using an AT command",
793         .tokens = {        /* token list, NULL terminated */
794                 (prog_void *)&cmd_help_help,
795                 (prog_void *)&cmd_help_atcmd,
796                 NULL,
797         },
798 };
799
800 /* ************* */
801
802 /* this structure is filled when cmd_read is parsed successfully */
803 struct cmd_read_result {
804         fixed_string_t read;
805         struct xbee_atcmd *cmd;
806 };
807
808 /* function called when cmd_read is parsed successfully */
809 static void cmd_read_parsed(void *parsed_result, struct cmdline *cl,
810                             void *data)
811 {
812         struct cmd_read_result *res = parsed_result;
813         xbeeapp_send_atcmd(res->cmd->name, NULL, 0, 1, NULL, NULL);
814 }
815
816 parse_pgm_token_string_t cmd_read_read =
817         TOKEN_STRING_INITIALIZER(struct cmd_read_result, read, "read");
818
819 parse_pgm_token_atcmd_t cmd_read_atcmd =
820         TOKEN_ATCMD_INITIALIZER(struct cmd_read_result, cmd, &xbee_dev,
821                                 XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
822
823 parse_pgm_inst_t cmd_read = {
824         .f = cmd_read_parsed,  /* function to call */
825         .data = NULL,      /* 2nd arg of func */
826         .help_str = "Read a register using an AT command",
827         .tokens = {        /* token list, NULL terminated */
828                 (prog_void *)&cmd_read_read,
829                 (prog_void *)&cmd_read_atcmd,
830                 NULL,
831         },
832 };
833
834 /* ************* */
835
836 /* this structure is filled when cmd_write is parsed successfully */
837 struct cmd_write_result {
838         fixed_string_t write;
839         struct xbee_atcmd *cmd;
840         union {
841                 uint8_t u8;
842                 uint16_t u16;
843                 uint32_t u32;
844         };
845 };
846
847 /* function called when cmd_write is parsed successfully */
848 static void cmd_write_parsed(void *parsed_result, struct cmdline *cl,
849                              void *data)
850 {
851         struct cmd_write_result *res = parsed_result;
852         int len;
853         void *param;
854
855         if (res->cmd->flags & XBEE_ATCMD_F_PARAM_NONE) {
856                 len = 0;
857                 param = NULL;
858         }
859         else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U8) {
860                 len = sizeof(res->u8);
861                 param = &res->u8;
862         }
863         else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U16) {
864                 len = sizeof(res->u16);
865                 res->u16 = htons(res->u16);
866                 param = &res->u16;
867         }
868         else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U32) {
869                 len = sizeof(res->u32);
870                 res->u32 = htonl(res->u32);
871                 param = &res->u32;
872         }
873         else {
874                 printf("Unknown argument type\n");
875                 return;
876         }
877         xbeeapp_send_atcmd(res->cmd->name, param, len, 1, NULL, NULL);
878 }
879
880 parse_pgm_token_string_t cmd_write_write =
881         TOKEN_STRING_INITIALIZER(struct cmd_write_result, write,
882                                  "write");
883
884 parse_pgm_token_atcmd_t cmd_write_none_atcmd =
885         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
886                                 &xbee_dev,
887                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE,
888                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE);
889
890 parse_pgm_inst_t cmd_write_none = {
891         .f = cmd_write_parsed,  /* function to call */
892         .data = NULL,      /* 2nd arg of func */
893         .help_str = "Send an AT command (no argument)",
894         .tokens = {        /* token list, NULL terminated */
895                 (prog_void *)&cmd_write_write,
896                 (prog_void *)&cmd_write_none_atcmd,
897                 NULL,
898         },
899 };
900
901 parse_pgm_token_atcmd_t cmd_write_u8_atcmd =
902         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
903                                 &xbee_dev,
904                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8,
905                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8);
906
907 parse_pgm_token_num_t cmd_write_u8_u8 =
908         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u8, UINT8);
909
910 parse_pgm_inst_t cmd_write_u8 = {
911         .f = cmd_write_parsed,  /* function to call */
912         .data = NULL,      /* 2nd arg of func */
913         .help_str = "Write a 8 bits register using an AT command",
914         .tokens = {        /* token list, NULL terminated */
915                 (prog_void *)&cmd_write_write,
916                 (prog_void *)&cmd_write_u8_atcmd,
917                 (prog_void *)&cmd_write_u8_u8,
918                 NULL,
919         },
920 };
921
922 parse_pgm_token_atcmd_t cmd_write_u16_atcmd =
923         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
924                                 &xbee_dev,
925                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16,
926                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16);
927
928 parse_pgm_token_num_t cmd_write_u16_u16 =
929         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u16, UINT16);
930
931 parse_pgm_inst_t cmd_write_u16 = {
932         .f = cmd_write_parsed,  /* function to call */
933         .data = NULL,      /* 2nd arg of func */
934         .help_str = "Write a 16 bits register using an AT command",
935         .tokens = {        /* token list, NULL terminated */
936                 (prog_void *)&cmd_write_write,
937                 (prog_void *)&cmd_write_u16_atcmd,
938                 (prog_void *)&cmd_write_u16_u16,
939                 NULL,
940         },
941 };
942
943 parse_pgm_token_atcmd_t cmd_write_u32_atcmd =
944         TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
945                                 &xbee_dev,
946                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32,
947                                 XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32);
948
949 parse_pgm_token_num_t cmd_write_u32_u32 =
950         TOKEN_NUM_INITIALIZER(struct cmd_write_result, u32, UINT32);
951
952 parse_pgm_inst_t cmd_write_u32 = {
953         .f = cmd_write_parsed,  /* function to call */
954         .data = NULL,      /* 2nd arg of func */
955         .help_str = "Write a 32 bits register using an AT command",
956         .tokens = {        /* token list, NULL terminated */
957                 (prog_void *)&cmd_write_write,
958                 (prog_void *)&cmd_write_u32_atcmd,
959                 (prog_void *)&cmd_write_u32_u32,
960                 NULL,
961         },
962 };
963
964 /* ************* */
965
966 /* this structure is filled when cmd_sendmsg is parsed successfully */
967 struct cmd_sendmsg_result {
968         fixed_string_t sendmsg;
969         uint64_t addr;
970         fixed_string_t data;
971 };
972
973 /* function called when cmd_sendmsg is parsed successfully */
974 static void cmd_sendmsg_parsed(void *parsed_result, struct cmdline *cl,
975                             void *data)
976 {
977         struct cmd_sendmsg_result *res = parsed_result;
978         xbeeapp_send_msg(res->addr, res->data, strlen(res->data), 1);
979 }
980
981 parse_pgm_token_string_t cmd_sendmsg_sendmsg =
982         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, sendmsg, "sendmsg");
983
984 parse_pgm_token_num_t cmd_sendmsg_addr =
985         TOKEN_NUM_INITIALIZER(struct cmd_sendmsg_result, addr, UINT64);
986
987 parse_pgm_token_string_t cmd_sendmsg_data =
988         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, data, NULL);
989
990 parse_pgm_inst_t cmd_sendmsg = {
991         .f = cmd_sendmsg_parsed,  /* function to call */
992         .data = NULL,      /* 2nd arg of func */
993         .help_str = "Send data to a node using its address",
994         .tokens = {        /* token list, NULL terminated */
995                 (prog_void *)&cmd_sendmsg_sendmsg,
996                 (prog_void *)&cmd_sendmsg_addr,
997                 (prog_void *)&cmd_sendmsg_data,
998                 NULL,
999         },
1000 };
1001
1002 /* ************* */
1003
1004 /* this structure is filled when cmd_sendmsg_name is parsed successfully */
1005 struct cmd_sendmsg_name_result {
1006         fixed_string_t sendmsg_name;
1007         struct xbee_neigh *neigh;
1008         fixed_string_t data;
1009 };
1010
1011 /* function called when cmd_sendmsg_name is parsed successfully */
1012 static void cmd_sendmsg_name_parsed(void *parsed_result, struct cmdline *cl,
1013                             void *data)
1014 {
1015         struct cmd_sendmsg_name_result *res = parsed_result;
1016         xbeeapp_send_msg(res->neigh->addr, res->data, strlen(res->data), 1);
1017 }
1018
1019 parse_pgm_token_string_t cmd_sendmsg_name_sendmsg_name =
1020         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, sendmsg_name,
1021                                  "sendmsg");
1022
1023 parse_pgm_token_neighbor_t cmd_sendmsg_name_neigh =
1024         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_sendmsg_name_result, neigh,
1025                                    &xbee_dev);
1026
1027 parse_pgm_token_string_t cmd_sendmsg_name_data =
1028         TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, data, NULL);
1029
1030 parse_pgm_inst_t cmd_sendmsg_name = {
1031         .f = cmd_sendmsg_name_parsed,  /* function to call */
1032         .data = NULL,      /* 2nd arg of func */
1033         .help_str = "Send data to a node using its name",
1034         .tokens = {        /* token list, NULL terminated */
1035                 (prog_void *)&cmd_sendmsg_name_sendmsg_name,
1036                 (prog_void *)&cmd_sendmsg_name_neigh,
1037                 (prog_void *)&cmd_sendmsg_name_data,
1038                 NULL,
1039         },
1040 };
1041
1042 /* ************* */
1043
1044 struct cmd_neigh_del_result {
1045         fixed_string_t cmd;
1046         fixed_string_t action;
1047         struct xbee_neigh *neigh;
1048 };
1049
1050 static void cmd_neigh_del_parsed(void *parsed_result,
1051                                 struct cmdline *cl,
1052                                 void *data)
1053 {
1054         struct cmd_neigh_del_result *res = parsed_result;
1055         xbee_neigh_del(xbee_dev, res->neigh);
1056 }
1057
1058 parse_pgm_token_string_t cmd_neigh_del_cmd =
1059         TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, cmd, "neigh");
1060 parse_pgm_token_string_t cmd_neigh_del_action =
1061         TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, action, "del");
1062 parse_pgm_token_neighbor_t cmd_neigh_del_neigh =
1063         TOKEN_NEIGHBOR_INITIALIZER(struct cmd_neigh_del_result, neigh,
1064                                    &xbee_dev);
1065
1066 parse_pgm_inst_t cmd_neigh_del = {
1067         .f = cmd_neigh_del_parsed,  /* function to call */
1068         .data = NULL,      /* 2nd arg of func */
1069         .help_str = "delete a neighbor",
1070         .tokens = {        /* token list, NULL terminated */
1071                 (prog_void *)&cmd_neigh_del_cmd,
1072                 (prog_void *)&cmd_neigh_del_action,
1073                 (prog_void *)&cmd_neigh_del_neigh,
1074                 NULL,
1075         },
1076 };
1077
1078 /* ************* */
1079
1080 struct cmd_neigh_add_result {
1081         fixed_string_t cmd;
1082         fixed_string_t action;
1083         fixed_string_t name;
1084         uint64_t addr;
1085 };
1086
1087 static void cmd_neigh_add_parsed(void *parsed_result,
1088                                 struct cmdline *cl,
1089                                 void *data)
1090 {
1091         struct cmd_neigh_add_result *res = parsed_result;
1092         if (xbee_neigh_add(xbee_dev, res->name, res->addr) == NULL)
1093                 printf("name or addr already exist\n");
1094 }
1095
1096 parse_pgm_token_string_t cmd_neigh_add_cmd =
1097         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, cmd, "neigh");
1098 parse_pgm_token_string_t cmd_neigh_add_action =
1099         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, action, "add");
1100 parse_pgm_token_string_t cmd_neigh_add_name =
1101         TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, name, NULL);
1102 parse_pgm_token_num_t cmd_neigh_add_addr =
1103         TOKEN_NUM_INITIALIZER(struct cmd_neigh_add_result, addr, UINT64);
1104
1105 parse_pgm_inst_t cmd_neigh_add = {
1106         .f = cmd_neigh_add_parsed,  /* function to call */
1107         .data = NULL,      /* 2nd arg of func */
1108         .help_str = "add a neighbor",
1109         .tokens = {        /* token list, NULL terminated */
1110                 (prog_void *)&cmd_neigh_add_cmd,
1111                 (prog_void *)&cmd_neigh_add_action,
1112                 (prog_void *)&cmd_neigh_add_name,
1113                 (prog_void *)&cmd_neigh_add_addr,
1114                 NULL,
1115         },
1116 };
1117
1118 /* ************* */
1119
1120 struct cmd_neigh_list_result {
1121         fixed_string_t cmd;
1122         fixed_string_t action;
1123 };
1124
1125 static void cmd_neigh_list_parsed(void *parsed_result,
1126                                 struct cmdline *cl,
1127                                 void *data)
1128 {
1129         struct xbee_neigh *neigh;
1130
1131         LIST_FOREACH(neigh, &xbee_dev->neigh_list, next) {
1132                 printf(" %s: 0x%"PRIx64"\n", neigh->name, neigh->addr);
1133         }
1134 }
1135
1136 parse_pgm_token_string_t cmd_neigh_list_cmd =
1137         TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, cmd, "neigh");
1138 parse_pgm_token_string_t cmd_neigh_list_action =
1139         TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, action, "list");
1140
1141 parse_pgm_inst_t cmd_neigh_list = {
1142         .f = cmd_neigh_list_parsed,  /* function to call */
1143         .data = NULL,      /* 2nd arg of func */
1144         .help_str = "list all known neighbors",
1145         .tokens = {        /* token list, NULL terminated */
1146                 (prog_void *)&cmd_neigh_list_cmd,
1147                 (prog_void *)&cmd_neigh_list_action,
1148                 NULL,
1149         },
1150 };
1151
1152 /*******************/
1153
1154 struct cmd_logfile_result {
1155         fixed_string_t logfile;
1156         filename_t file;
1157 };
1158
1159 static void cmd_logfile_parsed(void *parsed_result,
1160                                struct cmdline *cl,
1161                                void *data)
1162 {
1163         if (xbee_logfile != NULL)
1164                 fclose(xbee_logfile);
1165         xbee_logfile = fopen(xbee_logfilename, "a");
1166         if (xbee_logfile == NULL)
1167                 printf("cannot open file: %s\n", strerror(errno));
1168         fprintf(xbee_logfile, "-------------------start\n");
1169         printf("enabling log\n");
1170 }
1171
1172 parse_pgm_token_string_t cmd_logfile_logfile =
1173         TOKEN_STRING_INITIALIZER(struct cmd_logfile_result, logfile, "logfile");
1174
1175 parse_pgm_token_file_t cmd_logfile_file =
1176         TOKEN_FILE_INITIALIZER(struct cmd_logfile_result, file,
1177                                PARSE_FILE_F_CREATE);
1178
1179 parse_pgm_inst_t cmd_logfile = {
1180         .f = cmd_logfile_parsed,  /* function to call */
1181         .data = NULL,      /* 2nd arg of func */
1182         .help_str = "<logfile FILE> set log file",
1183         .tokens = {        /* token list, NULL terminated */
1184                 (prog_void *)&cmd_logfile_logfile,
1185                 (prog_void *)&cmd_logfile_file,
1186                 NULL,
1187         },
1188 };
1189
1190 /* ************* */
1191
1192 /* this structure is filled when cmd_log is parsed successfully */
1193 struct cmd_log_result {
1194         fixed_string_t log;
1195         fixed_string_t onoff;
1196 };
1197
1198 /* function called when cmd_log is parsed successfully */
1199 static void cmd_log_parsed(void *parsed_result, struct cmdline *cl, void *data)
1200 {
1201         struct cmd_log_result *res = parsed_result;
1202         if (!strcmp(res->onoff, "on") && xbee_logfile == NULL) {
1203                 xbee_logfile = fopen(xbee_logfilename, "a");
1204                 if (xbee_logfile == NULL)
1205                         printf("cannot open file: %s\n", strerror(errno));
1206                 fprintf(xbee_logfile, "-------------------start\n");
1207         }
1208         else if (!strcmp(res->onoff, "off") && xbee_logfile != NULL) {
1209                 fclose(xbee_logfile);
1210                 xbee_logfile = NULL;
1211         }
1212 }
1213
1214 parse_pgm_token_string_t cmd_log_log =
1215         TOKEN_STRING_INITIALIZER(struct cmd_log_result, log, "log");
1216
1217 parse_pgm_token_string_t cmd_log_onoff =
1218         TOKEN_STRING_INITIALIZER(struct cmd_log_result, onoff, "on#off");
1219
1220 parse_pgm_inst_t cmd_log = {
1221         .f = cmd_log_parsed,  /* function to call */
1222         .data = NULL,      /* 2nd arg of func */
1223         .help_str = "enable/disable hexlog of received packets",
1224         .tokens = {        /* token list, NULL terminated */
1225                 (prog_void *)&cmd_log_log,
1226                 (prog_void *)&cmd_log_onoff,
1227                 NULL,
1228         },
1229 };
1230
1231
1232 /*******************/
1233
1234 struct cmd_saveconfig_result {
1235         fixed_string_t saveconfig;
1236         filename_t file;
1237 };
1238
1239 static void cmd_saveconfig_parsed(void *parsed_result,
1240                                struct cmdline *cl,
1241                                void *data)
1242 {
1243         struct cmd_saveconfig_result *res = parsed_result;
1244
1245         if (xbeeapp_dump_config(res->file) < 0)
1246                 printf("cannot save config\n");
1247 }
1248
1249 parse_pgm_token_string_t cmd_saveconfig_saveconfig =
1250         TOKEN_STRING_INITIALIZER(struct cmd_saveconfig_result, saveconfig,
1251                                  "saveconfig");
1252
1253 parse_pgm_token_file_t cmd_saveconfig_file =
1254         TOKEN_FILE_INITIALIZER(struct cmd_saveconfig_result, file,
1255                                PARSE_FILE_F_CREATE);
1256
1257 parse_pgm_inst_t cmd_saveconfig = {
1258         .f = cmd_saveconfig_parsed,  /* function to call */
1259         .data = NULL,      /* 2nd arg of func */
1260         .help_str = "<saveconfig FILE> set log file",
1261         .tokens = {        /* token list, NULL terminated */
1262                 (prog_void *)&cmd_saveconfig_saveconfig,
1263                 (prog_void *)&cmd_saveconfig_file,
1264                 NULL,
1265         },
1266 };
1267
1268 /*******************/
1269
1270 struct cmd_loadconfig_result {
1271         fixed_string_t loadconfig;
1272         filename_t file;
1273 };
1274
1275 static void cmd_loadconfig_parsed(void *parsed_result,
1276                                struct cmdline *cl,
1277                                void *data)
1278 {
1279 }
1280
1281 parse_pgm_token_string_t cmd_loadconfig_loadconfig =
1282         TOKEN_STRING_INITIALIZER(struct cmd_loadconfig_result, loadconfig,
1283                                  "loadconfig");
1284
1285 parse_pgm_token_file_t cmd_loadconfig_file =
1286         TOKEN_FILE_INITIALIZER(struct cmd_loadconfig_result, file,
1287                                PARSE_FILE_F_CREATE);
1288
1289 parse_pgm_inst_t cmd_loadconfig = {
1290         .f = cmd_loadconfig_parsed,  /* function to call */
1291         .data = NULL,      /* 2nd arg of func */
1292         .help_str = "<loadconfig FILE> set log file",
1293         .tokens = {        /* token list, NULL terminated */
1294                 (prog_void *)&cmd_loadconfig_loadconfig,
1295                 (prog_void *)&cmd_loadconfig_file,
1296                 NULL,
1297         },
1298 };
1299
1300 /**********************************************************/
1301 /**********************************************************/
1302 /****** CONTEXT (list of instruction) */
1303
1304 /* in progmem */
1305 parse_ctx_t main_ctx = {
1306         .name = "main",
1307         .insts = {
1308                 (parse_pgm_inst_t *)&cmd_stats,
1309                 (parse_pgm_inst_t *)&cmd_monitor,
1310                 (parse_pgm_inst_t *)&cmd_monitor_period,
1311                 (parse_pgm_inst_t *)&cmd_monitor_add,
1312                 (parse_pgm_inst_t *)&cmd_monitor_del,
1313                 (parse_pgm_inst_t *)&cmd_range,
1314                 (parse_pgm_inst_t *)&cmd_range_period,
1315                 (parse_pgm_inst_t *)&cmd_range_count,
1316                 (parse_pgm_inst_t *)&cmd_range_powermask,
1317                 (parse_pgm_inst_t *)&cmd_range_dstaddr,
1318                 (parse_pgm_inst_t *)&cmd_ping,
1319                 (parse_pgm_inst_t *)&cmd_raw,
1320                 (parse_pgm_inst_t *)&cmd_dump,
1321                 (parse_pgm_inst_t *)&cmd_debug,
1322                 (parse_pgm_inst_t *)&cmd_help,
1323                 (parse_pgm_inst_t *)&cmd_read,
1324                 (parse_pgm_inst_t *)&cmd_write_none,
1325                 (parse_pgm_inst_t *)&cmd_write_u8,
1326                 (parse_pgm_inst_t *)&cmd_write_u16,
1327                 (parse_pgm_inst_t *)&cmd_write_u32,
1328                 (parse_pgm_inst_t *)&cmd_sendmsg,
1329                 (parse_pgm_inst_t *)&cmd_sendmsg_name,
1330                 (parse_pgm_inst_t *)&cmd_neigh_del,
1331                 (parse_pgm_inst_t *)&cmd_neigh_add,
1332                 (parse_pgm_inst_t *)&cmd_neigh_list,
1333                 (parse_pgm_inst_t *)&cmd_logfile,
1334                 (parse_pgm_inst_t *)&cmd_log,
1335                 (parse_pgm_inst_t *)&cmd_saveconfig,
1336                 (parse_pgm_inst_t *)&cmd_loadconfig,
1337                 NULL,
1338         },
1339 };