Contiki-NG
platform.c
1 /*
2  * Copyright (c) 2002, Adam Dunkels.
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
11  * copyright notice, this list of conditions and the following
12  * disclaimer in the documentation and/or other materials provided
13  * with the distribution.
14  * 3. The name of the author may not be used to endorse or promote
15  * products derived from this software without specific prior
16  * written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * This file is part of the Contiki OS
31  *
32  */
33 
34 /**
35  * \ingroup platform
36  *
37  * \defgroup native_platform Native platform
38  *
39  * Platform running in the host (Windows or Linux) environment.
40  *
41  * Used mainly for development and debugging.
42  * @{
43  */
44 
45 #include <stdio.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <sys/select.h>
49 #include <errno.h>
50 
51 #ifdef __CYGWIN__
52 #include "net/wpcap-drv.h"
53 #endif /* __CYGWIN__ */
54 
55 #include "contiki.h"
56 #include "net/netstack.h"
57 
58 #include "dev/serial-line.h"
59 #include "dev/button-hal.h"
60 #include "dev/gpio-hal.h"
61 #include "dev/leds.h"
62 
63 #include "net/ipv6/uip.h"
64 #include "net/ipv6/uip-debug.h"
65 #include "net/queuebuf.h"
66 
67 #if NETSTACK_CONF_WITH_IPV6
68 #include "net/ipv6/uip-ds6.h"
69 #endif /* NETSTACK_CONF_WITH_IPV6 */
70 
71 /* Log configuration */
72 #include "sys/log.h"
73 #define LOG_MODULE "Native"
74 #define LOG_LEVEL LOG_LEVEL_MAIN
75 
76 /*---------------------------------------------------------------------------*/
77 /**
78  * \name Native Platform Configuration
79  *
80  * @{
81  */
82 
83 /*
84  * Defines the maximum number of file descriptors monitored by the platform
85  * main loop.
86  */
87 #ifdef SELECT_CONF_MAX
88 #define SELECT_MAX SELECT_CONF_MAX
89 #else
90 #define SELECT_MAX 8
91 #endif
92 
93 /*
94  * Defines the timeout (in msec) of the select operation if no monitored file
95  * descriptors becomes ready.
96  */
97 #ifdef SELECT_CONF_TIMEOUT
98 #define SELECT_TIMEOUT SELECT_CONF_TIMEOUT
99 #else
100 #define SELECT_TIMEOUT 1000
101 #endif
102 
103 /*
104  * Adds the STDIN file descriptor to the list of monitored file descriptors.
105  */
106 #ifdef SELECT_CONF_STDIN
107 #define SELECT_STDIN SELECT_CONF_STDIN
108 #else
109 #define SELECT_STDIN 1
110 #endif
111 /** @} */
112 /*---------------------------------------------------------------------------*/
113 
114 static const struct select_callback *select_callback[SELECT_MAX];
115 static int select_max = 0;
116 
117 #ifdef PLATFORM_CONF_MAC_ADDR
118 static uint8_t mac_addr[] = PLATFORM_CONF_MAC_ADDR;
119 #else /* PLATFORM_CONF_MAC_ADDR */
120 static uint8_t mac_addr[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
121 #endif /* PLATFORM_CONF_MAC_ADDR */
122 
123 /*---------------------------------------------------------------------------*/
124 int
125 select_set_callback(int fd, const struct select_callback *callback)
126 {
127  int i;
128  if(fd >= 0 && fd < SELECT_MAX) {
129  /* Check that the callback functions are set */
130  if(callback != NULL &&
131  (callback->set_fd == NULL || callback->handle_fd == NULL)) {
132  callback = NULL;
133  }
134 
135  select_callback[fd] = callback;
136 
137  /* Update fd max */
138  if(callback != NULL) {
139  if(fd > select_max) {
140  select_max = fd;
141  }
142  } else {
143  select_max = 0;
144  for(i = SELECT_MAX - 1; i > 0; i--) {
145  if(select_callback[i] != NULL) {
146  select_max = i;
147  break;
148  }
149  }
150  }
151  return 1;
152  }
153  return 0;
154 }
155 /*---------------------------------------------------------------------------*/
156 #if SELECT_STDIN
157 static int
158 stdin_set_fd(fd_set *rset, fd_set *wset)
159 {
160  FD_SET(STDIN_FILENO, rset);
161  return 1;
162 }
163 
164 static int (*input_handler)(unsigned char c);
165 
166 void native_uart_set_input(int (*input)(unsigned char c)) {
167  input_handler = input;
168 }
169 
170 
171 static void
172 stdin_handle_fd(fd_set *rset, fd_set *wset)
173 {
174  char c;
175  if(FD_ISSET(STDIN_FILENO, rset)) {
176  if(read(STDIN_FILENO, &c, 1) > 0) {
177  input_handler(c);
178  }
179  }
180 }
181 const static struct select_callback stdin_fd = {
182  stdin_set_fd, stdin_handle_fd
183 };
184 #endif /* SELECT_STDIN */
185 /*---------------------------------------------------------------------------*/
186 static void
187 set_lladdr(void)
188 {
189  linkaddr_t addr;
190 
191  memset(&addr, 0, sizeof(linkaddr_t));
192 #if NETSTACK_CONF_WITH_IPV6
193  memcpy(addr.u8, mac_addr, sizeof(addr.u8));
194 #else
195  int i;
196  for(i = 0; i < sizeof(linkaddr_t); ++i) {
197  addr.u8[i] = mac_addr[7 - i];
198  }
199 #endif
200  linkaddr_set_node_addr(&addr);
201 }
202 /*---------------------------------------------------------------------------*/
203 #if NETSTACK_CONF_WITH_IPV6
204 static void
205 set_global_address(void)
206 {
207  uip_ipaddr_t ipaddr;
208  const uip_ipaddr_t *default_prefix = uip_ds6_default_prefix();
209 
210  /* Assign a unique local address (RFC4193,
211  http://tools.ietf.org/html/rfc4193). */
212  uip_ip6addr_copy(&ipaddr, default_prefix);
213 
214  /* Assumes that the uip_lladdr is set */
215  uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
216  uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
217 
218  LOG_INFO("Added global IPv6 address ");
219  LOG_INFO_6ADDR(&ipaddr);
220  LOG_INFO_("\n");
221 
222  /* set the PREFIX::1 address to the IF */
223  uip_ip6addr_copy(&ipaddr, default_prefix);
224  ipaddr.u8[15] = 1;
225  uip_ds6_defrt_add(&ipaddr, 0);
226 }
227 #endif
228 /*---------------------------------------------------------------------------*/
229 int contiki_argc = 0;
230 char **contiki_argv;
231 /*---------------------------------------------------------------------------*/
232 void
233 platform_process_args(int argc, char**argv)
234 {
235  /* crappy way of remembering and accessing argc/v */
236  contiki_argc = argc;
237  contiki_argv = argv;
238 
239  /* native under windows is hardcoded to use the first one or two args */
240  /* for wpcap configuration so this needs to be "removed" from */
241  /* contiki_args (used by the native-border-router) */
242 #ifdef __CYGWIN__
243  contiki_argc--;
244  contiki_argv++;
245 #ifdef UIP_FALLBACK_INTERFACE
246  contiki_argc--;
247  contiki_argv++;
248 #endif
249 #endif
250 }
251 /*---------------------------------------------------------------------------*/
252 void
254 {
255  gpio_hal_init();
256  button_hal_init();
257  leds_init();
258  return;
259 }
260 /*---------------------------------------------------------------------------*/
261 void
263 {
264  set_lladdr();
265  serial_line_init();
266 
267  if (NULL == input_handler) {
268  native_uart_set_input(serial_line_input_byte);
269  }
270 
271 }
272 /*---------------------------------------------------------------------------*/
273 void
275 {
276 #if NETSTACK_CONF_WITH_IPV6
277 #ifdef __CYGWIN__
278  process_start(&wpcap_process, NULL);
279 #endif
280 
281  set_global_address();
282 
283 #endif /* NETSTACK_CONF_WITH_IPV6 */
284 
285  /* Make standard output unbuffered. */
286  setvbuf(stdout, (char *)NULL, _IONBF, 0);
287 }
288 /*---------------------------------------------------------------------------*/
289 void
291 {
292 #if SELECT_STDIN
293  select_set_callback(STDIN_FILENO, &stdin_fd);
294 #endif /* SELECT_STDIN */
295  while(1) {
296  fd_set fdr;
297  fd_set fdw;
298  int maxfd;
299  int i;
300  int retval;
301  struct timeval tv;
302 
303  retval = process_run();
304 
305  tv.tv_sec = 0;
306  tv.tv_usec = retval ? 1 : SELECT_TIMEOUT;
307 
308  FD_ZERO(&fdr);
309  FD_ZERO(&fdw);
310  maxfd = 0;
311  for(i = 0; i <= select_max; i++) {
312  if(select_callback[i] != NULL && select_callback[i]->set_fd(&fdr, &fdw)) {
313  maxfd = i;
314  }
315  }
316 
317  retval = select(maxfd + 1, &fdr, &fdw, NULL, &tv);
318  if(retval < 0) {
319  if(errno != EINTR) {
320  perror("select");
321  }
322  } else if(retval > 0) {
323  /* timeout => retval == 0 */
324  for(i = 0; i <= maxfd; i++) {
325  if(select_callback[i] != NULL) {
326  select_callback[i]->handle_fd(&fdr, &fdw);
327  }
328  }
329  }
330 
332  }
333 
334  return;
335 }
336 /*---------------------------------------------------------------------------*/
337 void
338 log_message(char *m1, char *m2)
339 {
340  fprintf(stderr, "%s%s\n", m1, m2);
341 }
342 /*---------------------------------------------------------------------------*/
343 void
344 uip_log(char *m)
345 {
346  fprintf(stderr, "%s\n", m);
347 }
348 /*---------------------------------------------------------------------------*/
349 /** @} */
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:107
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
void platform_main_loop()
The platform&#39;s main loop, if provided.
Definition: platform.c:195
void platform_init_stage_two()
Stage 2 of platform driver initialisation.
Definition: platform.c:123
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
Definition: etimer.c:145
void leds_init(void)
Initialise the LED HAL.
Definition: minileds.c:44
void uip_log(char *m)
Print out a uIP log message.
Definition: platform.c:344
A set of debugging macros for the IP stack
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
Definition: uip-ds6.c:576
void platform_process_args(int argc, char **argv)
Allow the platform to process main&#39;s command line arguments.
Definition: platform.c:233
void gpio_hal_init()
Initialise the GPIO HAL.
Definition: gpio-hal.c:95
Header file for IPv6-related data structures.
int serial_line_input_byte(unsigned char c)
Get one byte of input from the serial driver.
Definition: serial-line.c:64
const uip_ip6addr_t * uip_ds6_default_prefix()
Retrieve the Default IPv6 prefix.
Definition: uip-ds6.c:104
Header file for the Packet queue buffer management
uip_ds6_addr_t * uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
Add a unicast address to the interface.
Definition: uip-ds6.c:360
void platform_init_stage_three()
Final stage of platform driver initialisation.
Definition: platform.c:169
Header file for the uIP TCP/IP stack.
Generic serial I/O process header filer.
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the GPIO HAL.
void button_hal_init()
Initialise the button HAL.
Definition: button-hal.c:178
Header file for the logging system
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1802
Header file for the LED HAL.
int process_run(void)
Run the system once - call poll handlers and process one event.
Definition: process.c:302
void platform_init_stage_one(void)
Basic (Stage 1) platform driver initialisation.
Definition: platform.c:114
Header file for the button HAL.
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
void linkaddr_set_node_addr(linkaddr_t *t)
Set the address of the current node.
Definition: linkaddr.c:75