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