Contiki-NG
border-router-cmds.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011, Swedish Institute of Computer Science.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30/**
31 * \file
32 * Sets up some commands for the border router
33 * \author
34 * Niclas Finne <nfi@sics.se>
35 * Joakim Eriksson <joakime@sics.se>
36 */
37
38#include "contiki.h"
39#include "cmd.h"
40#include "border-router.h"
41#include "border-router-cmds.h"
42#include "dev/serial-line.h"
43#include "net/routing/routing.h"
44#include "net/ipv6/uiplib.h"
45#include <string.h>
46#include "shell.h"
47#include <stdio.h>
48
49/*---------------------------------------------------------------------------*/
50/* Log configuration */
51#include "sys/log.h"
52#define LOG_MODULE "BR"
53#define LOG_LEVEL LOG_LEVEL_NONE
54
55uint8_t command_context;
56
57void packet_sent(uint8_t sessionid, uint8_t status, uint8_t tx);
58void nbr_print_stat(void);
59
60/*---------------------------------------------------------------------------*/
61PROCESS(border_router_cmd_process, "Border router cmd process");
62/*---------------------------------------------------------------------------*/
63static const uint8_t *
64hextoi(const uint8_t *buf, int len, int *v)
65{
66 *v = 0;
67 for(; len > 0; len--, buf++) {
68 if(*buf >= '0' && *buf <= '9') {
69 *v = (*v << 4) + ((*buf - '0') & 0xf);
70 } else if(*buf >= 'a' && *buf <= 'f') {
71 *v = (*v << 4) + ((*buf - 'a' + 10) & 0xf);
72 } else if(*buf >= 'A' && *buf <= 'F') {
73 *v = (*v << 4) + ((*buf - 'A' + 10) & 0xf);
74 } else {
75 break;
76 }
77 }
78 return buf;
79}
80/*---------------------------------------------------------------------------*/
81static const uint8_t *
82dectoi(const uint8_t *buf, int len, int *v)
83{
84 int negative = 0;
85 *v = 0;
86 if(len <= 0) {
87 return buf;
88 }
89 if(*buf == '$') {
90 return hextoi(buf + 1, len - 1, v);
91 }
92 if(*buf == '0' && *(buf + 1) == 'x' && len > 2) {
93 return hextoi(buf + 2, len - 2, v);
94 }
95 if(*buf == '-') {
96 negative = 1;
97 buf++;
98 }
99 for(; len > 0; len--, buf++) {
100 if(*buf < '0' || *buf > '9') {
101 break;
102 }
103 *v = (*v * 10) + ((*buf - '0') & 0xf);
104 }
105 if(negative) {
106 *v = - *v;
107 }
108 return buf;
109}
110/*---------------------------------------------------------------------------*/
111
112/*---------------------------------------------------------------------------*/
113/* TODO: the below code needs some way of identifying from where the command */
114/* comes. In this case it can be from stdin or from SLIP. */
115/*---------------------------------------------------------------------------*/
116int
117border_router_cmd_handler(const uint8_t *data, int len)
118{
119 /* handle global repair, etc here */
120 if(data[0] == '!') {
121 LOG_DBG("Got configuration message of type %c\n", data[1]);
122 if(command_context == CMD_CONTEXT_STDIO) {
123 switch(data[1]) {
124 case 'G':
125 /* This is supposed to be from stdin */
126 printf("Performing Global Repair...\n");
127 NETSTACK_ROUTING.global_repair("Command");
128 return 1;
129 case 'C': {
130 /* send on a set-param thing! */
131 uint8_t set_param[] = {'!', 'V', 0, RADIO_PARAM_CHANNEL, 0, 0 };
132 int channel = -1;
133 dectoi(&data[2], len - 2, &channel);
134 if(channel >= 0) {
135 set_param[5] = channel & 0xff;
136 write_to_slip(set_param, sizeof(set_param));
137 }
138 return 1;
139 }
140 case 'P': {
141 /* send on a set-param thing! */
142 uint8_t set_param[] = {'!', 'V', 0, RADIO_PARAM_PAN_ID, 0, 0 };
143 int pan_id;
144 dectoi(&data[2], len - 2, &pan_id);
145 set_param[4] = (pan_id >> 8) & 0xff;
146 set_param[5] = pan_id & 0xff;
147 write_to_slip(set_param, sizeof(set_param));
148 return 1;
149 }
150 default:
151 return 0;
152 }
153 } else if(command_context == CMD_CONTEXT_RADIO) {
154 /* We need to know that this is from the slip-radio here. */
155 switch(data[1]) {
156 case 'M':
157 LOG_DBG("Setting MAC address\n");
158 border_router_set_mac(&data[2]);
159 return 1;
160 case 'V':
161 if(data[3] == RADIO_PARAM_CHANNEL) {
162 printf("Channel is %d\n", data[5]);
163 }
164 if(data[3] == RADIO_PARAM_PAN_ID) {
165 printf("PAN_ID is 0x%04x\n", (data[4] << 8) + data[5]);
166 }
167 return 1;
168 case 'R':
169 LOG_DBG("Packet data report for sid:%d st:%d tx:%d\n",
170 data[2], data[3], data[4]);
171 packet_sent(data[2], data[3], data[4]);
172 return 1;
173 default:
174 return 0;
175 }
176 }
177 } else if(data[0] == '?') {
178 LOG_DBG("Got request message of type %c\n", data[1]);
179 if(data[1] == 'M' && command_context == CMD_CONTEXT_STDIO) {
180 uint8_t buf[20];
181 char *hexchar = "0123456789abcdef";
182 int j;
183 /* this is just a test so far... just to see if it works */
184 buf[0] = '!';
185 buf[1] = 'M';
186 for(j = 0; j < UIP_LLADDR_LEN; j++) {
187 buf[2 + j * 2] = hexchar[uip_lladdr.addr[j] >> 4];
188 buf[3 + j * 2] = hexchar[uip_lladdr.addr[j] & 15];
189 }
190 cmd_send(buf, 18);
191 return 1;
192 } else if(data[1] == 'C' && command_context == CMD_CONTEXT_STDIO) {
193 /* send on a set-param thing! */
194 uint8_t set_param[] = {'?', 'V', 0, RADIO_PARAM_CHANNEL};
195 write_to_slip(set_param, sizeof(set_param));
196 return 1;
197 } else if(data[1] == 'P' && command_context == CMD_CONTEXT_STDIO) {
198 /* send on a set-param thing! */
199 uint8_t set_param[] = {'?', 'V', 0, RADIO_PARAM_PAN_ID};
200 write_to_slip(set_param, sizeof(set_param));
201 return 1;
202 } else if(data[1] == 'S') {
203 border_router_print_stat();
204 return 1;
205 }
206 }
207 return 0;
208}
209/*---------------------------------------------------------------------------*/
210void
211border_router_cmd_output(const uint8_t *data, int data_len)
212{
213 int i;
214 printf("CMD output: ");
215 for(i = 0; i < data_len; i++) {
216 printf("%c", data[i]);
217 }
218 printf("\n");
219}
220/*---------------------------------------------------------------------------*/
221static void
222serial_shell_output(const char *str)
223{
224 printf("%s", str);
225}
226/*---------------------------------------------------------------------------*/
227
228PROCESS_THREAD(border_router_cmd_process, ev, data)
229{
230 static struct pt shell_input_pt;
232
233 shell_init();
234
235 while(1) {
237 if(ev == serial_line_event_message && data != NULL) {
238 LOG_DBG("Got serial data!!! %s of len: %u\n",
239 (char *)data, (unsigned)strlen((char *)data));
240 command_context = CMD_CONTEXT_STDIO;
241 if(cmd_input(data, strlen((char *)data))) {
242 /* Commnand executed - all is fine */
243 } else {
244 /* did not find command - run shell and see if ... */
245 PROCESS_PT_SPAWN(&shell_input_pt, shell_input(&shell_input_pt, serial_shell_output, data));
246 }
247 }
248 }
249 PROCESS_END();
250}
251/*---------------------------------------------------------------------------*/
Sets up some commands for the border router.
Border router header file.
Simple command handler.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1154
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#define PROCESS_PT_SPAWN(pt, thread)
Spawn a protothread from the process.
Definition: process.h:211
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define PROCESS_YIELD()
Yield the currently running process.
Definition: process.h:164
@ RADIO_PARAM_CHANNEL
Channel used for radio communication.
Definition: radio.h:134
@ RADIO_PARAM_PAN_ID
The personal area network identifier (PAN ID), which is used by the h/w frame filtering functionality...
Definition: radio.h:150
void shell_init(void)
Initializes Shell module.
Definition: shell.c:123
static void packet_sent(void *ptr, int status, int transmissions)
Callback function for the MAC packet sent callback.
Definition: sicslowpan.c:1513
uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:107
#define UIP_LLADDR_LEN
802.15.4 address
Definition: uip.h:145
Header file for the logging system.
Routing driver header file.
Generic serial I/O process header filer.
process_event_t serial_line_event_message
Event posted when a line of input has been received.
Definition: serial-line.c:60
Main header file for the Contiki shell.
void(* global_repair)(const char *str)
Triggers a global topology repair.
Definition: routing.h:120
Header file for the IP address manipulation library.