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 static int (*input_handler)(unsigned char c);
164 
165 void
166 native_uart_set_input(int (*input)(unsigned char c))
167 {
168  input_handler = input;
169 }
170 static void
171 stdin_handle_fd(fd_set *rset, fd_set *wset)
172 {
173  char c;
174  if(FD_ISSET(STDIN_FILENO, rset)) {
175  if(read(STDIN_FILENO, &c, 1) > 0) {
176  input_handler(c);
177  }
178  }
179 }
180 const static struct select_callback stdin_fd = {
181  stdin_set_fd, stdin_handle_fd
182 };
183 #endif /* SELECT_STDIN */
184 /*---------------------------------------------------------------------------*/
185 static void
186 set_lladdr(void)
187 {
188  linkaddr_t addr;
189 
190  memset(&addr, 0, sizeof(linkaddr_t));
191 #if NETSTACK_CONF_WITH_IPV6
192  memcpy(addr.u8, mac_addr, sizeof(addr.u8));
193 #else
194  int i;
195  for(i = 0; i < sizeof(linkaddr_t); ++i) {
196  addr.u8[i] = mac_addr[7 - i];
197  }
198 #endif
199  linkaddr_set_node_addr(&addr);
200 }
201 /*---------------------------------------------------------------------------*/
202 #if NETSTACK_CONF_WITH_IPV6
203 static void
204 set_global_address(void)
205 {
206  uip_ipaddr_t ipaddr;
207  const uip_ipaddr_t *default_prefix = uip_ds6_default_prefix();
208 
209  /* Assign a unique local address (RFC4193,
210  http://tools.ietf.org/html/rfc4193). */
211  uip_ip6addr_copy(&ipaddr, default_prefix);
212 
213  /* Assumes that the uip_lladdr is set */
214  uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
215  uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
216 
217  LOG_INFO("Added global IPv6 address ");
218  LOG_INFO_6ADDR(&ipaddr);
219  LOG_INFO_("\n");
220 
221  /* set the PREFIX::1 address to the IF */
222  uip_ip6addr_copy(&ipaddr, default_prefix);
223  ipaddr.u8[15] = 1;
224  uip_ds6_defrt_add(&ipaddr, 0);
225 }
226 #endif
227 /*---------------------------------------------------------------------------*/
228 int contiki_argc = 0;
229 char **contiki_argv;
230 /*---------------------------------------------------------------------------*/
231 void
232 platform_process_args(int argc, char **argv)
233 {
234  /* crappy way of remembering and accessing argc/v */
235  contiki_argc = argc;
236  contiki_argv = argv;
237 
238  /* native under windows is hardcoded to use the first one or two args */
239  /* for wpcap configuration so this needs to be "removed" from */
240  /* contiki_args (used by the native-border-router) */
241 #ifdef __CYGWIN__
242  contiki_argc--;
243  contiki_argv++;
244 #ifdef UIP_FALLBACK_INTERFACE
245  contiki_argc--;
246  contiki_argv++;
247 #endif
248 #endif
249 }
250 /*---------------------------------------------------------------------------*/
251 void
253 {
254  gpio_hal_init();
255  button_hal_init();
256  leds_init();
257  return;
258 }
259 /*---------------------------------------------------------------------------*/
260 void
262 {
263  set_lladdr();
264  serial_line_init();
265 
266  if(NULL == input_handler) {
267  native_uart_set_input(serial_line_input_byte);
268  }
269 }
270 /*---------------------------------------------------------------------------*/
271 void
273 {
274 #if NETSTACK_CONF_WITH_IPV6
275 #ifdef __CYGWIN__
276  process_start(&wpcap_process, NULL);
277 #endif
278 
279  set_global_address();
280 
281 #endif /* NETSTACK_CONF_WITH_IPV6 */
282 
283  /* Make standard output unbuffered. */
284  setvbuf(stdout, (char *)NULL, _IONBF, 0);
285 }
286 /*---------------------------------------------------------------------------*/
287 void
289 {
290 #if SELECT_STDIN
291  select_set_callback(STDIN_FILENO, &stdin_fd);
292 #endif /* SELECT_STDIN */
293  while(1) {
294  fd_set fdr;
295  fd_set fdw;
296  int maxfd;
297  int i;
298  int retval;
299  struct timeval tv;
300 
301  retval = process_run();
302 
303  tv.tv_sec = retval ? 0 : SELECT_TIMEOUT / 1000;
304  tv.tv_usec = retval ? 1 : (SELECT_TIMEOUT * 1000) % 1000000;
305 
306  FD_ZERO(&fdr);
307  FD_ZERO(&fdw);
308  maxfd = 0;
309  for(i = 0; i <= select_max; i++) {
310  if(select_callback[i] != NULL && select_callback[i]->set_fd(&fdr, &fdw)) {
311  maxfd = i;
312  }
313  }
314 
315  retval = select(maxfd + 1, &fdr, &fdw, NULL, &tv);
316  if(retval < 0) {
317  if(errno != EINTR) {
318  perror("select");
319  }
320  } else if(retval > 0) {
321  /* timeout => retval == 0 */
322  for(i = 0; i <= maxfd; i++) {
323  if(select_callback[i] != NULL) {
324  select_callback[i]->handle_fd(&fdr, &fdw);
325  }
326  }
327  }
328 
330  }
331 
332  return;
333 }
334 /*---------------------------------------------------------------------------*/
335 void
336 log_message(char *m1, char *m2)
337 {
338  fprintf(stderr, "%s%s\n", m1, m2);
339 }
340 /*---------------------------------------------------------------------------*/
341 void
342 uip_log(char *m)
343 {
344  fprintf(stderr, "%s\n", m);
345 }
346 /*---------------------------------------------------------------------------*/
347 /** @} */
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:342
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:232
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:213
Header file for the logging system
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1813
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