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 
55 uint8_t command_context;
56 
57 void packet_sent(uint8_t sessionid, uint8_t status, uint8_t tx);
58 void nbr_print_stat(void);
59 
60 /*---------------------------------------------------------------------------*/
61 PROCESS(border_router_cmd_process, "Border router cmd process");
62 /*---------------------------------------------------------------------------*/
63 static const uint8_t *
64 hextoi(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 /*---------------------------------------------------------------------------*/
81 static const uint8_t *
82 dectoi(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 /*---------------------------------------------------------------------------*/
116 int
117 border_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 /*---------------------------------------------------------------------------*/
210 void
211 border_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 /*---------------------------------------------------------------------------*/
221 static void
222 serial_shell_output(const char *str)
223 {
224  printf("%s", str);
225 }
226 /*---------------------------------------------------------------------------*/
227 
228 PROCESS_THREAD(border_router_cmd_process, ev, data)
229 {
230  static struct pt shell_input_pt;
231  PROCESS_BEGIN();
232 
233  shell_init();
234 
235  while(1) {
236  PROCESS_YIELD();
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 /*---------------------------------------------------------------------------*/
uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:107
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
Main header file for the Contiki shell
Border router header file
#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
static void packet_sent(void *ptr, int status, int transmissions)
Callback function for the MAC packet sent callback.
Definition: sicslowpan.c:1422
Simple command handler
void(* global_repair)(const char *str)
Triggers a global topology repair.
Definition: routing.h:120
#define UIP_LLADDR_LEN
802.15.4 address
Definition: uip.h:145
Header file for the IP address manipulation library.
Routing driver header file
#define PROCESS_YIELD()
Yield the currently running process.
Definition: process.h:164
void shell_init(void)
Initializes Shell module.
Definition: shell.c:123
Sets up some commands for the border router
process_event_t serial_line_event_message
Event posted when a line of input has been received.
Definition: serial-line.c:61
Generic serial I/O process header filer.
#define PROCESS_PT_SPAWN(pt, thread)
Spawn a protothread from the process.
Definition: process.h:211
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1097
Header file for the logging system