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
114static const struct select_callback *select_callback[SELECT_MAX];
115static int select_max = 0;
116
117#ifdef PLATFORM_CONF_MAC_ADDR
118static uint8_t mac_addr[] = PLATFORM_CONF_MAC_ADDR;
119#else /* PLATFORM_CONF_MAC_ADDR */
120static uint8_t mac_addr[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
121#endif /* PLATFORM_CONF_MAC_ADDR */
122
123/*---------------------------------------------------------------------------*/
124int
125select_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
157static int
158stdin_set_fd(fd_set *rset, fd_set *wset)
159{
160 FD_SET(STDIN_FILENO, rset);
161 return 1;
162}
163static int (*input_handler)(unsigned char c);
164
165void
166native_uart_set_input(int (*input)(unsigned char c))
167{
168 input_handler = input;
169}
170static void
171stdin_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}
180const static struct select_callback stdin_fd = {
181 stdin_set_fd, stdin_handle_fd
182};
183#endif /* SELECT_STDIN */
184/*---------------------------------------------------------------------------*/
185static void
186set_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
200}
201/*---------------------------------------------------------------------------*/
202#if NETSTACK_CONF_WITH_IPV6
203static void
204set_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 */
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/*---------------------------------------------------------------------------*/
228int contiki_argc = 0;
229char **contiki_argv;
230/*---------------------------------------------------------------------------*/
231void
232platform_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/*---------------------------------------------------------------------------*/
251void
253{
256 leds_init();
257 return;
258}
259/*---------------------------------------------------------------------------*/
260void
262{
263 set_lladdr();
264 serial_line_init();
265
266#if SELECT_STDIN
267 if(NULL == input_handler) {
268 native_uart_set_input(serial_line_input_byte);
269 }
270#endif
271}
272/*---------------------------------------------------------------------------*/
273void
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/*---------------------------------------------------------------------------*/
289void
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 = retval ? 0 : SELECT_TIMEOUT / 1000;
306 tv.tv_usec = retval ? 1 : (SELECT_TIMEOUT * 1000) % 1000000;
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/*---------------------------------------------------------------------------*/
335void
336log_message(char *m1, char *m2)
337{
338 fprintf(stderr, "%s%s\n", m1, m2);
339}
340/*---------------------------------------------------------------------------*/
341void
342uip_log(char *m)
343{
344 fprintf(stderr, "%s\n", m);
345}
346/*---------------------------------------------------------------------------*/
347/** @} */
Header file for the button HAL.
Header file for the GPIO HAL.
void button_hal_init()
Initialise the button HAL.
Definition: button-hal.c:213
void platform_init_stage_three()
Final stage of platform driver initialisation.
Definition: platform.c:169
void platform_init_stage_one(void)
Basic (Stage 1) platform driver initialisation.
Definition: platform.c:114
void platform_init_stage_two()
Stage 2 of platform driver initialisation.
Definition: platform.c:123
void leds_init(void)
Initialise the LED HAL.
Definition: minileds.c:44
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
Definition: etimer.c:145
void gpio_hal_init()
Initialise the GPIO HAL.
Definition: gpio-hal.c:95
void linkaddr_set_node_addr(linkaddr_t *t)
Set the address of the current node.
Definition: linkaddr.c:75
void platform_main_loop()
The platform's main loop, if provided.
Definition: platform.c:146
void uip_log(char *m)
Print out a uIP log message.
Definition: platform.c:342
void platform_process_args(int argc, char **argv)
Allow the platform to process main's command line arguments.
Definition: platform.c:232
int process_run(void)
Run the system once - call poll handlers and process one event.
Definition: process.c:302
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1833
const uip_ip6addr_t * uip_ds6_default_prefix()
Retrieve the Default IPv6 prefix.
Definition: uip-ds6.c:104
uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:107
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 uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
Definition: uip-ds6.c:576
Header file for the LED HAL.
Header file for the logging system.
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet queue buffer management.
Generic serial I/O process header filer.
int serial_line_input_byte(unsigned char c)
Get one byte of input from the serial driver.
Definition: serial-line.c:64
A set of debugging macros for the IP stack.
Header file for IPv6-related data structures.
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
Header file for the uIP TCP/IP stack.