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