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