+/*
+ * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the University of California, Berkeley nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/queue.h>
+#include <arpa/inet.h>
+#include <inttypes.h>
+
+#include <event.h>
+
+#include <cmdline_parse.h>
+#include <cmdline_parse_num.h>
+#include <cmdline_parse_string.h>
+#include <cmdline_parse_file.h>
+#include <cmdline.h>
+
+#include "xbee_neighbor.h"
+#include "xbee_atcmd.h"
+#include "xbee_stats.h"
+#include "xbee_buf.h"
+#include "xbee_proto.h"
+#include "xbee.h"
+#include "parse_atcmd.h"
+#include "parse_neighbor.h"
+#include "parse_monitor.h"
+#include "main.h"
+
+static struct monitor_reg_list monitor_list = LIST_HEAD_INITIALIZER(x/*XXX*/);
+static int monitor_period_ms = 1000;
+static int monitor_running = 0;
+static int monitor_count = 0;
+static struct event monitor_event;
+struct monitor_reg *monitor_current;
+
+static int range_period_ms = 1000;
+static int range_powermask = 0x1F;
+static uint8_t range_power = 0;
+static int range_running = 0;
+static uint64_t range_dstaddr = 0xFFFF; /* broadcast by default */
+static struct event range_event;
+static int range_count = 100;
+static int range_cur_count = 0;
+
+static const char *xbee_logfilename = "/tmp/xbee.log";
+
+static void monitor_cb(int s, short event, void *arg)
+{
+ struct timeval tv;
+ struct cmdline *cl = arg;
+
+ if (monitor_current == NULL)
+ monitor_current = LIST_FIRST(&monitor_list);
+
+ xbeeapp_send_atcmd(monitor_current->atcmd, NULL, 0, 0);
+ monitor_current = LIST_NEXT(monitor_current, next);
+
+ evtimer_set(&monitor_event, monitor_cb, cl);
+ tv.tv_sec = 0;
+ tv.tv_usec = (1000 * monitor_period_ms) / monitor_count;
+ evtimer_add(&monitor_event, &tv);
+}
+
+static void range_cb(int s, short event, void *arg)
+{
+ struct timeval tv;
+ struct cmdline *cl = arg;
+ char buf[16];
+ uint8_t i, mask;
+
+ range_cur_count--;
+
+ /* get new xmit power */
+ for (i = 1; i <= 8; i++) {
+ mask = 1 << ((range_power + i) & 0x7);
+ if (mask & range_powermask)
+ break;
+ }
+ range_power = ((range_power + i) & 0x7);
+
+ xbeeapp_send_atcmd("PL", &range_power, sizeof(range_power), 0);
+ snprintf(buf, sizeof(buf), "range%d", range_power);
+ xbeeapp_send_msg(range_dstaddr, buf, strlen(buf), 0);
+
+ if (range_cur_count == 0) {
+ range_running = 0;
+ return;
+ }
+
+ evtimer_set(&range_event, range_cb, cl);
+ tv.tv_sec = 0;
+ tv.tv_usec = 1000 * range_period_ms;
+ evtimer_add(&range_event, &tv);
+}
+
+/* ************* */
+
+/* this structure is filled when cmd_stats is parsed successfully */
+struct cmd_stats_result {
+ cmdline_fixed_string_t stats;
+ cmdline_fixed_string_t action;
+};
+
+/* function called when cmd_stats is parsed successfully */
+static void cmd_stats_parsed(void *parsed_result, struct cmdline *cl, void *data)
+{
+ struct cmd_stats_result *res = parsed_result;
+
+ if (!strcmp(res->action, "show")) {
+ xbee_dump_stats(stdout, xbee_dev);
+ if (xbee_logfile != NULL)
+ xbee_dump_stats(xbee_logfile, xbee_dev);
+ }
+ else if (!strcmp(res->action, "reset"))
+ xbee_reset_stats(xbee_dev);
+}
+
+cmdline_parse_token_string_t cmd_stats_stats =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_result, stats, "stats");
+cmdline_parse_token_string_t cmd_stats_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_stats_result, action, "show#reset");
+
+cmdline_parse_inst_t cmd_stats = {
+ .f = cmd_stats_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Send a stats to the xbee device",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_stats_stats,
+ (void *)&cmd_stats_action,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_monitor is parsed successfully */
+struct cmd_monitor_result {
+ cmdline_fixed_string_t monitor;
+ cmdline_fixed_string_t action;
+};
+
+/* function called when cmd_monitor is parsed successfully */
+static void cmd_monitor_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_monitor_result *res = parsed_result;
+ struct monitor_reg *m;
+
+ if (!strcmp(res->action, "show")) {
+ printf("monitor period is %d ms, %d regs in list\n",
+ monitor_period_ms, monitor_count);
+ LIST_FOREACH(m, &monitor_list, next)
+ printf(" %s\n", m->desc);
+ }
+ else if (!strcmp(res->action, "start")) {
+ struct timeval tv;
+ if (monitor_running) {
+ printf("already running\n");
+ return;
+ }
+ if (monitor_count == 0) {
+ printf("no regs to be monitored\n");
+ return;
+ }
+ evtimer_set(&monitor_event, monitor_cb, cl);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ evtimer_add(&monitor_event, &tv);
+ monitor_running = 1;
+ monitor_current = LIST_FIRST(&monitor_list);
+ }
+ else if (!strcmp(res->action, "end")) {
+ if (monitor_running == 0) {
+ printf("not running\n");
+ return;
+ }
+ monitor_running = 0;
+ evtimer_del(&monitor_event);
+ }
+}
+
+cmdline_parse_token_string_t cmd_monitor_monitor =
+ TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, monitor, "monitor");
+cmdline_parse_token_string_t cmd_monitor_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_monitor_result, action,
+ "show#start#end");
+
+cmdline_parse_inst_t cmd_monitor = {
+ .f = cmd_monitor_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "start/stop/show current monitoring",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_monitor_monitor,
+ (void *)&cmd_monitor_action,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_monitor_add is parsed successfully */
+struct cmd_monitor_add_result {
+ cmdline_fixed_string_t monitor;
+ cmdline_fixed_string_t action;
+ struct xbee_atcmd *cmd;
+};
+
+/* function called when cmd_monitor_add is parsed successfully */
+static void cmd_monitor_add_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_monitor_add_result *res = parsed_result;
+ struct monitor_reg *m;
+
+ LIST_FOREACH(m, &monitor_list, next) {
+ if (!strcmp(m->desc, res->cmd->desc))
+ break;
+ }
+
+ if (m != NULL) {
+ printf("already exist\n");
+ return;
+ }
+
+ m = malloc(sizeof(*m));
+ if (m == NULL) {
+ printf("no mem\n");
+ return;
+ }
+
+ m->desc = res->cmd->desc;
+ m->atcmd = res->cmd->name;
+ LIST_INSERT_HEAD(&monitor_list, m, next);
+ monitor_count ++;
+}
+
+cmdline_parse_token_string_t cmd_monitor_add_monitor_add =
+ TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, monitor,
+ "monitor");
+cmdline_parse_token_string_t cmd_monitor_add_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_monitor_add_result, action,
+ "add");
+parse_token_atcmd_t cmd_monitor_add_atcmd =
+ TOKEN_ATCMD_INITIALIZER(struct cmd_monitor_add_result, cmd, &xbee_dev,
+ XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
+
+
+cmdline_parse_inst_t cmd_monitor_add = {
+ .f = cmd_monitor_add_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "add a register in monitor list",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_monitor_add_monitor_add,
+ (void *)&cmd_monitor_add_action,
+ (void *)&cmd_monitor_add_atcmd,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_monitor_period is parsed successfully */
+struct cmd_monitor_period_result {
+ cmdline_fixed_string_t monitor;
+ cmdline_fixed_string_t action;
+ uint32_t period;
+};
+
+/* function called when cmd_monitor_period is parsed successfully */
+static void cmd_monitor_period_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_monitor_period_result *res = parsed_result;
+
+ if (res->period < 100) {
+ printf("error, minimum period is 100 ms\n");
+ return;
+ }
+
+ monitor_period_ms = res->period;
+}
+
+cmdline_parse_token_string_t cmd_monitor_period_monitor_period =
+ TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, monitor,
+ "monitor");
+cmdline_parse_token_string_t cmd_monitor_period_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_monitor_period_result, action,
+ "period");
+cmdline_parse_token_num_t cmd_monitor_period_period =
+ TOKEN_NUM_INITIALIZER(struct cmd_monitor_period_result, period, UINT32);
+
+
+cmdline_parse_inst_t cmd_monitor_period = {
+ .f = cmd_monitor_period_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "set register monitoring period",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_monitor_period_monitor_period,
+ (void *)&cmd_monitor_period_action,
+ (void *)&cmd_monitor_period_period,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_monitor_del is parsed successfully */
+struct cmd_monitor_del_result {
+ cmdline_fixed_string_t monitor;
+ cmdline_fixed_string_t action;
+ struct monitor_reg *m;
+};
+
+/* function called when cmd_monitor_del is parsed successfully */
+static void cmd_monitor_del_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_monitor_del_result *res = parsed_result;
+
+ monitor_current = LIST_NEXT(res->m, next);
+ LIST_REMOVE(res->m, next);
+ free(res->m);
+ monitor_count --;
+ if (monitor_count == 0) {
+ printf("Disable monitoring, no more event\n");
+ evtimer_del(&monitor_event);
+ monitor_running = 0;
+ return;
+ }
+}
+
+cmdline_parse_token_string_t cmd_monitor_del_monitor_del =
+ TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, monitor,
+ "monitor");
+cmdline_parse_token_string_t cmd_monitor_del_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_monitor_del_result, action,
+ "del");
+parse_token_monitor_t cmd_monitor_del_atcmd =
+ TOKEN_MONITOR_INITIALIZER(struct cmd_monitor_del_result, m,
+ &monitor_list);
+
+
+cmdline_parse_inst_t cmd_monitor_del = {
+ .f = cmd_monitor_del_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "del a register in monitor list",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_monitor_del_monitor_del,
+ (void *)&cmd_monitor_del_action,
+ (void *)&cmd_monitor_del_atcmd,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_range is parsed successfully */
+struct cmd_range_result {
+ cmdline_fixed_string_t range;
+ cmdline_fixed_string_t action;
+};
+
+/* function called when cmd_range is parsed successfully */
+static void cmd_range_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_range_result *res = parsed_result;
+
+ if (!strcmp(res->action, "show")) {
+ printf("range infos:\n");
+ printf(" range period %d\n", range_period_ms);
+ printf(" range count %d\n", range_count);
+ printf(" range powermask 0x%x\n", range_powermask);
+ printf(" range dstaddr %"PRIx64"\n", range_dstaddr);
+ if (range_running)
+ printf(" range test is running\n");
+ else
+ printf(" range test is not running\n");
+ }
+ else if (!strcmp(res->action, "start")) {
+ struct timeval tv;
+ if (range_running) {
+ printf("already running\n");
+ return;
+ }
+ range_cur_count = range_count;
+ evtimer_set(&range_event, range_cb, cl);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ evtimer_add(&range_event, &tv);
+ range_running = 1;
+ }
+ else if (!strcmp(res->action, "end")) {
+ if (range_running == 0) {
+ printf("not running\n");
+ return;
+ }
+ range_running = 0;
+ evtimer_del(&range_event);
+ }
+}
+
+cmdline_parse_token_string_t cmd_range_range =
+ TOKEN_STRING_INITIALIZER(struct cmd_range_result, range, "range");
+cmdline_parse_token_string_t cmd_range_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_range_result, action,
+ "show#start#end");
+
+cmdline_parse_inst_t cmd_range = {
+ .f = cmd_range_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "start/stop/show current rangeing",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_range_range,
+ (void *)&cmd_range_action,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_range_period is parsed successfully */
+struct cmd_range_period_result {
+ cmdline_fixed_string_t range;
+ cmdline_fixed_string_t action;
+ uint32_t period;
+};
+
+/* function called when cmd_range_period is parsed successfully */
+static void cmd_range_period_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_range_period_result *res = parsed_result;
+
+ if (res->period < 10) {
+ printf("error, minimum period is 10 ms\n");
+ return;
+ }
+
+ range_period_ms = res->period;
+}
+
+cmdline_parse_token_string_t cmd_range_period_range_period =
+ TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, range,
+ "range");
+cmdline_parse_token_string_t cmd_range_period_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_range_period_result, action,
+ "period");
+cmdline_parse_token_num_t cmd_range_period_period =
+ TOKEN_NUM_INITIALIZER(struct cmd_range_period_result, period, UINT32);
+
+
+cmdline_parse_inst_t cmd_range_period = {
+ .f = cmd_range_period_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "set range test period",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_range_period_range_period,
+ (void *)&cmd_range_period_action,
+ (void *)&cmd_range_period_period,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_range_count is parsed successfully */
+struct cmd_range_count_result {
+ cmdline_fixed_string_t range;
+ cmdline_fixed_string_t action;
+ uint32_t count;
+};
+
+/* function called when cmd_range_count is parsed successfully */
+static void cmd_range_count_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_range_count_result *res = parsed_result;
+ range_count = res->count;
+}
+
+cmdline_parse_token_string_t cmd_range_count_range_count =
+ TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, range,
+ "range");
+cmdline_parse_token_string_t cmd_range_count_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_range_count_result, action,
+ "count");
+cmdline_parse_token_num_t cmd_range_count_count =
+ TOKEN_NUM_INITIALIZER(struct cmd_range_count_result, count, UINT32);
+
+
+cmdline_parse_inst_t cmd_range_count = {
+ .f = cmd_range_count_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "set range test count",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_range_count_range_count,
+ (void *)&cmd_range_count_action,
+ (void *)&cmd_range_count_count,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_range_powermask is parsed successfully */
+struct cmd_range_powermask_result {
+ cmdline_fixed_string_t range;
+ cmdline_fixed_string_t action;
+ uint8_t powermask;
+};
+
+/* function called when cmd_range_powermask is parsed successfully */
+static void cmd_range_powermask_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_range_powermask_result *res = parsed_result;
+ range_powermask = res->powermask;
+}
+
+cmdline_parse_token_string_t cmd_range_powermask_range_powermask =
+ TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, range,
+ "range");
+cmdline_parse_token_string_t cmd_range_powermask_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_range_powermask_result, action,
+ "powermask");
+cmdline_parse_token_num_t cmd_range_powermask_powermask =
+ TOKEN_NUM_INITIALIZER(struct cmd_range_powermask_result, powermask,
+ UINT8);
+
+
+cmdline_parse_inst_t cmd_range_powermask = {
+ .f = cmd_range_powermask_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "set range test powermask",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_range_powermask_range_powermask,
+ (void *)&cmd_range_powermask_action,
+ (void *)&cmd_range_powermask_powermask,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_range_dstaddr is parsed successfully */
+struct cmd_range_dstaddr_result {
+ cmdline_fixed_string_t range;
+ cmdline_fixed_string_t action;
+ uint64_t dstaddr;
+};
+
+/* function called when cmd_range_dstaddr is parsed successfully */
+static void cmd_range_dstaddr_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_range_dstaddr_result *res = parsed_result;
+
+ range_dstaddr = res->dstaddr;
+}
+
+cmdline_parse_token_string_t cmd_range_dstaddr_range_dstaddr =
+ TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, range,
+ "range");
+cmdline_parse_token_string_t cmd_range_dstaddr_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_range_dstaddr_result, action,
+ "dstaddr");
+cmdline_parse_token_num_t cmd_range_dstaddr_dstaddr =
+ TOKEN_NUM_INITIALIZER(struct cmd_range_dstaddr_result, dstaddr, UINT64);
+
+
+cmdline_parse_inst_t cmd_range_dstaddr = {
+ .f = cmd_range_dstaddr_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "set register rangeing dstaddr",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_range_dstaddr_range_dstaddr,
+ (void *)&cmd_range_dstaddr_action,
+ (void *)&cmd_range_dstaddr_dstaddr,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_ping is parsed successfully */
+struct cmd_ping_result {
+ cmdline_fixed_string_t ping;
+};
+
+/* function called when cmd_ping is parsed successfully */
+static void cmd_ping_parsed(void *parsed_result, struct cmdline *cl, void *data)
+{
+ xbeeapp_send_atcmd("VL", NULL, 0, 1);
+}
+
+cmdline_parse_token_string_t cmd_ping_ping =
+ TOKEN_STRING_INITIALIZER(struct cmd_ping_result, ping, "ping");
+
+cmdline_parse_inst_t cmd_ping = {
+ .f = cmd_ping_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Send a ping to the xbee device",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_ping_ping,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_raw is parsed successfully */
+struct cmd_raw_result {
+ cmdline_fixed_string_t raw;
+};
+
+/* function called when cmd_raw is parsed successfully */
+static void cmd_raw_parsed(void *parsed_result, struct cmdline *cl, void *data)
+{
+ printf("switched to raw mode, CTRL-D to exit\n");
+ rdline_stop(&cl->rdl); /* don't display prompt when return */
+ xbee_raw = 1;
+}
+
+cmdline_parse_token_string_t cmd_raw_raw =
+ TOKEN_STRING_INITIALIZER(struct cmd_raw_result, raw, "raw");
+
+cmdline_parse_inst_t cmd_raw = {
+ .f = cmd_raw_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Switch to raw mode",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_raw_raw,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_dump is parsed successfully */
+struct cmd_dump_result {
+ cmdline_fixed_string_t dump;
+ cmdline_fixed_string_t onoff;
+};
+
+/* function called when cmd_dump is parsed successfully */
+static void cmd_dump_parsed(void *parsed_result, struct cmdline *cl, void *data)
+{
+ struct cmd_dump_result *res = parsed_result;
+ if (!strcmp(res->onoff, "on"))
+ xbee_hexdump = 1;
+ else
+ xbee_hexdump = 0;
+}
+
+cmdline_parse_token_string_t cmd_dump_dump =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_result, dump, "dump");
+
+cmdline_parse_token_string_t cmd_dump_onoff =
+ TOKEN_STRING_INITIALIZER(struct cmd_dump_result, onoff, "on#off");
+
+cmdline_parse_inst_t cmd_dump = {
+ .f = cmd_dump_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "enable/disable hexdump of received packets",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_dump_dump,
+ (void *)&cmd_dump_onoff,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_debug is parsed successfully */
+struct cmd_debug_result {
+ cmdline_fixed_string_t debug;
+ cmdline_fixed_string_t onoff;
+};
+
+/* function called when cmd_debug is parsed successfully */
+static void cmd_debug_parsed(void *parsed_result, struct cmdline *cl, void *data)
+{
+ struct cmd_debug_result *res = parsed_result;
+ if (!strcmp(res->onoff, "on"))
+ xbee_debug = 1;
+ else
+ xbee_debug = 0;
+}
+
+cmdline_parse_token_string_t cmd_debug_debug =
+ TOKEN_STRING_INITIALIZER(struct cmd_debug_result, debug, "debug");
+
+cmdline_parse_token_string_t cmd_debug_onoff =
+ TOKEN_STRING_INITIALIZER(struct cmd_debug_result, onoff, "on#off");
+
+cmdline_parse_inst_t cmd_debug = {
+ .f = cmd_debug_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "enable/disable additionnal debug",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_debug_debug,
+ (void *)&cmd_debug_onoff,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_help is parsed successfully */
+struct cmd_help_result {
+ cmdline_fixed_string_t help;
+ struct xbee_atcmd *cmd;
+};
+
+/* function called when cmd_help is parsed successfully */
+static void cmd_help_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_help_result *res = parsed_result;
+ int type;
+
+ type = (res->cmd->flags & (XBEE_ATCMD_F_READ | XBEE_ATCMD_F_WRITE));
+ switch (type) {
+ case XBEE_ATCMD_F_READ:
+ printf("Read-only\n");
+ break;
+ case XBEE_ATCMD_F_WRITE:
+ printf("Write-only\n");
+ break;
+ default:
+ printf("Read-write\n");
+ break;
+ }
+ if (res->cmd->flags & XBEE_ATCMD_F_PARAM_NONE)
+ printf("No argument\n");
+ else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U8)
+ printf("Register is unsigned 8 bits\n");
+ else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U16)
+ printf("Register is unsigned 16 bits\n");
+ else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U32)
+ printf("Register is unsigned 32 bits\n");
+ else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_S16)
+ printf("Register is signed 16 bits\n");
+ else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_STRING_20B)
+ printf("Register is a 20 bytes string\n");
+ else
+ printf("Unknown argument\n");
+
+ printf("%s\n", res->cmd->help);
+}
+
+cmdline_parse_token_string_t cmd_help_help =
+ TOKEN_STRING_INITIALIZER(struct cmd_help_result, help, "help");
+
+parse_token_atcmd_t cmd_help_atcmd =
+ TOKEN_ATCMD_INITIALIZER(struct cmd_help_result, cmd, &xbee_dev,
+ 0, 0);
+
+cmdline_parse_inst_t cmd_help = {
+ .f = cmd_help_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Help a register using an AT command",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_help_help,
+ (void *)&cmd_help_atcmd,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_read is parsed successfully */
+struct cmd_read_result {
+ cmdline_fixed_string_t read;
+ struct xbee_atcmd *cmd;
+};
+
+/* function called when cmd_read is parsed successfully */
+static void cmd_read_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_read_result *res = parsed_result;
+ xbeeapp_send_atcmd(res->cmd->name, NULL, 0, 1);
+}
+
+cmdline_parse_token_string_t cmd_read_read =
+ TOKEN_STRING_INITIALIZER(struct cmd_read_result, read, "read");
+
+parse_token_atcmd_t cmd_read_atcmd =
+ TOKEN_ATCMD_INITIALIZER(struct cmd_read_result, cmd, &xbee_dev,
+ XBEE_ATCMD_F_READ, XBEE_ATCMD_F_READ);
+
+cmdline_parse_inst_t cmd_read = {
+ .f = cmd_read_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Read a register using an AT command",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_read_read,
+ (void *)&cmd_read_atcmd,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_write is parsed successfully */
+struct cmd_write_result {
+ cmdline_fixed_string_t write;
+ struct xbee_atcmd *cmd;
+ union {
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ };
+};
+
+/* function called when cmd_write is parsed successfully */
+static void cmd_write_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_write_result *res = parsed_result;
+ int len;
+ void *param;
+
+ if (res->cmd->flags & XBEE_ATCMD_F_PARAM_NONE) {
+ len = 0;
+ param = NULL;
+ }
+ else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U8) {
+ len = sizeof(res->u8);
+ param = &res->u8;
+ }
+ else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U16) {
+ len = sizeof(res->u16);
+ res->u16 = htons(res->u16);
+ param = &res->u16;
+ }
+ else if (res->cmd->flags & XBEE_ATCMD_F_PARAM_U32) {
+ len = sizeof(res->u32);
+ res->u32 = htonl(res->u32);
+ param = &res->u32;
+ }
+ else {
+ printf("Unknown argument type\n");
+ return;
+ }
+ xbeeapp_send_atcmd(res->cmd->name, param, len, 1);
+}
+
+cmdline_parse_token_string_t cmd_write_write =
+ TOKEN_STRING_INITIALIZER(struct cmd_write_result, write,
+ "write");
+
+parse_token_atcmd_t cmd_write_none_atcmd =
+ TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
+ &xbee_dev,
+ XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE,
+ XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_NONE);
+
+cmdline_parse_inst_t cmd_write_none = {
+ .f = cmd_write_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Send an AT command (no argument)",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_write_write,
+ (void *)&cmd_write_none_atcmd,
+ NULL,
+ },
+};
+
+parse_token_atcmd_t cmd_write_u8_atcmd =
+ TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
+ &xbee_dev,
+ XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8,
+ XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U8);
+
+cmdline_parse_token_num_t cmd_write_u8_u8 =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_result, u8, UINT8);
+
+cmdline_parse_inst_t cmd_write_u8 = {
+ .f = cmd_write_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Write a 8 bits register using an AT command",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_write_write,
+ (void *)&cmd_write_u8_atcmd,
+ (void *)&cmd_write_u8_u8,
+ NULL,
+ },
+};
+
+parse_token_atcmd_t cmd_write_u16_atcmd =
+ TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
+ &xbee_dev,
+ XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16,
+ XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U16);
+
+cmdline_parse_token_num_t cmd_write_u16_u16 =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_result, u16, UINT16);
+
+cmdline_parse_inst_t cmd_write_u16 = {
+ .f = cmd_write_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Write a 16 bits register using an AT command",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_write_write,
+ (void *)&cmd_write_u16_atcmd,
+ (void *)&cmd_write_u16_u16,
+ NULL,
+ },
+};
+
+parse_token_atcmd_t cmd_write_u32_atcmd =
+ TOKEN_ATCMD_INITIALIZER(struct cmd_write_result, cmd,
+ &xbee_dev,
+ XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32,
+ XBEE_ATCMD_F_WRITE | XBEE_ATCMD_F_PARAM_U32);
+
+cmdline_parse_token_num_t cmd_write_u32_u32 =
+ TOKEN_NUM_INITIALIZER(struct cmd_write_result, u32, UINT32);
+
+cmdline_parse_inst_t cmd_write_u32 = {
+ .f = cmd_write_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Write a 32 bits register using an AT command",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_write_write,
+ (void *)&cmd_write_u32_atcmd,
+ (void *)&cmd_write_u32_u32,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_sendmsg is parsed successfully */
+struct cmd_sendmsg_result {
+ cmdline_fixed_string_t sendmsg;
+ uint64_t addr;
+ cmdline_fixed_string_t data;
+};
+
+/* function called when cmd_sendmsg is parsed successfully */
+static void cmd_sendmsg_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_sendmsg_result *res = parsed_result;
+ xbeeapp_send_msg(res->addr, res->data, strlen(res->data), 1);
+}
+
+cmdline_parse_token_string_t cmd_sendmsg_sendmsg =
+ TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, sendmsg, "sendmsg");
+
+cmdline_parse_token_num_t cmd_sendmsg_addr =
+ TOKEN_NUM_INITIALIZER(struct cmd_sendmsg_result, addr, UINT64);
+
+cmdline_parse_token_string_t cmd_sendmsg_data =
+ TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_result, data, NULL);
+
+cmdline_parse_inst_t cmd_sendmsg = {
+ .f = cmd_sendmsg_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Send data to a node using its address",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_sendmsg_sendmsg,
+ (void *)&cmd_sendmsg_addr,
+ (void *)&cmd_sendmsg_data,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_sendmsg_name is parsed successfully */
+struct cmd_sendmsg_name_result {
+ cmdline_fixed_string_t sendmsg_name;
+ struct xbee_neigh *neigh;
+ cmdline_fixed_string_t data;
+};
+
+/* function called when cmd_sendmsg_name is parsed successfully */
+static void cmd_sendmsg_name_parsed(void *parsed_result, struct cmdline *cl,
+ void *data)
+{
+ struct cmd_sendmsg_name_result *res = parsed_result;
+ xbeeapp_send_msg(res->neigh->addr, res->data, strlen(res->data), 1);
+}
+
+cmdline_parse_token_string_t cmd_sendmsg_name_sendmsg_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, sendmsg_name,
+ "sendmsg");
+
+parse_token_neighbor_t cmd_sendmsg_name_neigh =
+ TOKEN_NEIGHBOR_INITIALIZER(struct cmd_sendmsg_name_result, neigh,
+ &xbee_dev);
+
+cmdline_parse_token_string_t cmd_sendmsg_name_data =
+ TOKEN_STRING_INITIALIZER(struct cmd_sendmsg_name_result, data, NULL);
+
+cmdline_parse_inst_t cmd_sendmsg_name = {
+ .f = cmd_sendmsg_name_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "Send data to a node using its name",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_sendmsg_name_sendmsg_name,
+ (void *)&cmd_sendmsg_name_neigh,
+ (void *)&cmd_sendmsg_name_data,
+ NULL,
+ },
+};
+
+/* ************* */
+
+struct cmd_neigh_del_result {
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t action;
+ struct xbee_neigh *neigh;
+};
+
+static void cmd_neigh_del_parsed(void *parsed_result,
+ struct cmdline *cl,
+ void *data)
+{
+ struct cmd_neigh_del_result *res = parsed_result;
+ xbee_neigh_del(xbee_dev, res->neigh);
+}
+
+cmdline_parse_token_string_t cmd_neigh_del_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, cmd, "neigh");
+cmdline_parse_token_string_t cmd_neigh_del_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_neigh_del_result, action, "del");
+parse_token_neighbor_t cmd_neigh_del_neigh =
+ TOKEN_NEIGHBOR_INITIALIZER(struct cmd_neigh_del_result, neigh,
+ &xbee_dev);
+
+cmdline_parse_inst_t cmd_neigh_del = {
+ .f = cmd_neigh_del_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "delete a neighbor",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_neigh_del_cmd,
+ (void *)&cmd_neigh_del_action,
+ (void *)&cmd_neigh_del_neigh,
+ NULL,
+ },
+};
+
+/* ************* */
+
+struct cmd_neigh_add_result {
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t action;
+ cmdline_fixed_string_t name;
+ uint64_t addr;
+};
+
+static void cmd_neigh_add_parsed(void *parsed_result,
+ struct cmdline *cl,
+ void *data)
+{
+ struct cmd_neigh_add_result *res = parsed_result;
+ if (xbee_neigh_add(xbee_dev, res->name, res->addr) == NULL)
+ printf("name or addr already exist\n");
+}
+
+cmdline_parse_token_string_t cmd_neigh_add_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, cmd, "neigh");
+cmdline_parse_token_string_t cmd_neigh_add_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, action, "add");
+cmdline_parse_token_string_t cmd_neigh_add_name =
+ TOKEN_STRING_INITIALIZER(struct cmd_neigh_add_result, name, NULL);
+cmdline_parse_token_num_t cmd_neigh_add_addr =
+ TOKEN_NUM_INITIALIZER(struct cmd_neigh_add_result, addr, UINT64);
+
+cmdline_parse_inst_t cmd_neigh_add = {
+ .f = cmd_neigh_add_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "add a neighbor",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_neigh_add_cmd,
+ (void *)&cmd_neigh_add_action,
+ (void *)&cmd_neigh_add_name,
+ (void *)&cmd_neigh_add_addr,
+ NULL,
+ },
+};
+
+/* ************* */
+
+struct cmd_neigh_list_result {
+ cmdline_fixed_string_t cmd;
+ cmdline_fixed_string_t action;
+};
+
+static void cmd_neigh_list_parsed(void *parsed_result,
+ struct cmdline *cl,
+ void *data)
+{
+ struct xbee_neigh *neigh;
+
+ LIST_FOREACH(neigh, &xbee_dev->neigh_list, next) {
+ printf(" %s: 0x%"PRIx64"\n", neigh->name, neigh->addr);
+ }
+}
+
+cmdline_parse_token_string_t cmd_neigh_list_cmd =
+ TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, cmd, "neigh");
+cmdline_parse_token_string_t cmd_neigh_list_action =
+ TOKEN_STRING_INITIALIZER(struct cmd_neigh_list_result, action, "list");
+
+cmdline_parse_inst_t cmd_neigh_list = {
+ .f = cmd_neigh_list_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "list all known neighbors",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_neigh_list_cmd,
+ (void *)&cmd_neigh_list_action,
+ NULL,
+ },
+};
+
+/*******************/
+
+struct cmd_logfile_result {
+ cmdline_fixed_string_t logfile;
+ cmdline_filename_t file;
+};
+
+static void cmd_logfile_parsed(void *parsed_result,
+ struct cmdline *cl,
+ void *data)
+{
+ if (xbee_logfile != NULL)
+ fclose(xbee_logfile);
+ xbee_logfile = fopen(xbee_logfilename, "a");
+ if (xbee_logfile == NULL)
+ printf("cannot open file: %s\n", strerror(errno));
+ fprintf(xbee_logfile, "-------------------start\n");
+ printf("enabling log\n");
+}
+
+cmdline_parse_token_string_t cmd_logfile_logfile =
+ TOKEN_STRING_INITIALIZER(struct cmd_logfile_result, logfile, "logfile");
+
+cmdline_parse_token_file_t cmd_logfile_file =
+ TOKEN_FILE_INITIALIZER(struct cmd_logfile_result, file,
+ PARSE_FILE_F_CREATE);
+
+cmdline_parse_inst_t cmd_logfile = {
+ .f = cmd_logfile_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "<logfile FILE> set log file",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_logfile_logfile,
+ (void *)&cmd_logfile_file,
+ NULL,
+ },
+};
+
+/* ************* */
+
+/* this structure is filled when cmd_log is parsed successfully */
+struct cmd_log_result {
+ cmdline_fixed_string_t log;
+ cmdline_fixed_string_t onoff;
+};
+
+/* function called when cmd_log is parsed successfully */
+static void cmd_log_parsed(void *parsed_result, struct cmdline *cl, void *data)
+{
+ struct cmd_log_result *res = parsed_result;
+ if (!strcmp(res->onoff, "on") && xbee_logfile == NULL) {
+ xbee_logfile = fopen(xbee_logfilename, "a");
+ if (xbee_logfile == NULL)
+ printf("cannot open file: %s\n", strerror(errno));
+ fprintf(xbee_logfile, "-------------------start\n");
+ }
+ else if (!strcmp(res->onoff, "off") && xbee_logfile != NULL) {
+ fclose(xbee_logfile);
+ xbee_logfile = NULL;
+ }
+}
+
+cmdline_parse_token_string_t cmd_log_log =
+ TOKEN_STRING_INITIALIZER(struct cmd_log_result, log, "log");
+
+cmdline_parse_token_string_t cmd_log_onoff =
+ TOKEN_STRING_INITIALIZER(struct cmd_log_result, onoff, "on#off");
+
+cmdline_parse_inst_t cmd_log = {
+ .f = cmd_log_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "enable/disable hexlog of received packets",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_log_log,
+ (void *)&cmd_log_onoff,
+ NULL,
+ },
+};
+
+
+/*******************/
+
+struct cmd_saveconfig_result {
+ cmdline_fixed_string_t saveconfig;
+ cmdline_filename_t file;
+};
+
+static void cmd_saveconfig_parsed(void *parsed_result,
+ struct cmdline *cl,
+ void *data)
+{
+ struct cmd_saveconfig_result *res = parsed_result;
+
+ if (xbeeapp_dump_config(res->file) < 0)
+ printf("cannot save config\n");
+}
+
+cmdline_parse_token_string_t cmd_saveconfig_saveconfig =
+ TOKEN_STRING_INITIALIZER(struct cmd_saveconfig_result, saveconfig,
+ "saveconfig");
+
+cmdline_parse_token_file_t cmd_saveconfig_file =
+ TOKEN_FILE_INITIALIZER(struct cmd_saveconfig_result, file,
+ PARSE_FILE_F_CREATE);
+
+cmdline_parse_inst_t cmd_saveconfig = {
+ .f = cmd_saveconfig_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "<saveconfig FILE> set log file",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_saveconfig_saveconfig,
+ (void *)&cmd_saveconfig_file,
+ NULL,
+ },
+};
+
+/*******************/
+
+struct cmd_loadconfig_result {
+ cmdline_fixed_string_t loadconfig;
+ cmdline_filename_t file;
+};
+
+static void cmd_loadconfig_parsed(void *parsed_result,
+ struct cmdline *cl,
+ void *data)
+{
+}
+
+cmdline_parse_token_string_t cmd_loadconfig_loadconfig =
+ TOKEN_STRING_INITIALIZER(struct cmd_loadconfig_result, loadconfig,
+ "loadconfig");
+
+cmdline_parse_token_file_t cmd_loadconfig_file =
+ TOKEN_FILE_INITIALIZER(struct cmd_loadconfig_result, file,
+ PARSE_FILE_F_CREATE);
+
+cmdline_parse_inst_t cmd_loadconfig = {
+ .f = cmd_loadconfig_parsed, /* function to call */
+ .data = NULL, /* 2nd arg of func */
+ .help_str = "<loadconfig FILE> set log file",
+ .tokens = { /* token list, NULL terminated */
+ (void *)&cmd_loadconfig_loadconfig,
+ (void *)&cmd_loadconfig_file,
+ NULL,
+ },
+};
+
+/**********************************************************/
+/**********************************************************/
+/****** CONTEXT (list of instruction) */
+
+/* in progmem */
+cmdline_parse_ctx_t main_ctx = {
+ .name = "main",
+ .insts = {
+ &cmd_stats,
+ &cmd_monitor,
+ &cmd_monitor_period,
+ &cmd_monitor_add,
+ &cmd_monitor_del,
+ &cmd_range,
+ &cmd_range_period,
+ &cmd_range_count,
+ &cmd_range_powermask,
+ &cmd_range_dstaddr,
+ &cmd_ping,
+ &cmd_raw,
+ &cmd_dump,
+ &cmd_debug,
+ &cmd_help,
+ &cmd_read,
+ &cmd_write_none,
+ &cmd_write_u8,
+ &cmd_write_u16,
+ &cmd_write_u32,
+ &cmd_sendmsg,
+ &cmd_sendmsg_name,
+ &cmd_neigh_del,
+ &cmd_neigh_add,
+ &cmd_neigh_list,
+ &cmd_logfile,
+ &cmd_log,
+ &cmd_saveconfig,
+ &cmd_loadconfig,
+ NULL,
+ },
+};