/* * Copyright (c) 2002, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This file is part of the Contiki OS * */ /** * \ingroup platform * * \defgroup native_platform Native platform * * Platform running in the host (Windows or Linux) environment. * * Used mainly for development and debugging. * @{ */ #include #include #include #include #include #ifdef __CYGWIN__ #include "net/wpcap-drv.h" #endif /* __CYGWIN__ */ #include "contiki.h" #include "net/netstack.h" #include "dev/serial-line.h" #include "net/ipv6/uip.h" #include "net/ipv6/uip-debug.h" #include "net/queuebuf.h" #include "dev/button-sensor.h" #include "dev/pir-sensor.h" #include "dev/vib-sensor.h" #if NETSTACK_CONF_WITH_IPV6 #include "net/ipv6/uip-ds6.h" #endif /* NETSTACK_CONF_WITH_IPV6 */ /* Log configuration */ #include "sys/log.h" #define LOG_MODULE "Native" #define LOG_LEVEL LOG_LEVEL_MAIN #ifdef SELECT_CONF_MAX #define SELECT_MAX SELECT_CONF_MAX #else #define SELECT_MAX 8 #endif static const struct select_callback *select_callback[SELECT_MAX]; static int select_max = 0; SENSORS(&pir_sensor, &vib_sensor, &button_sensor); static uint8_t serial_id[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; #if !NETSTACK_CONF_WITH_IPV6 static uint16_t node_id = 0x0102; #endif /* !NETSTACK_CONF_WITH_IPV6 */ /*---------------------------------------------------------------------------*/ int select_set_callback(int fd, const struct select_callback *callback) { int i; if(fd >= 0 && fd < SELECT_MAX) { /* Check that the callback functions are set */ if(callback != NULL && (callback->set_fd == NULL || callback->handle_fd == NULL)) { callback = NULL; } select_callback[fd] = callback; /* Update fd max */ if(callback != NULL) { if(fd > select_max) { select_max = fd; } } else { select_max = 0; for(i = SELECT_MAX - 1; i > 0; i--) { if(select_callback[i] != NULL) { select_max = i; break; } } } return 1; } return 0; } /*---------------------------------------------------------------------------*/ static int stdin_set_fd(fd_set *rset, fd_set *wset) { FD_SET(STDIN_FILENO, rset); return 1; } static void stdin_handle_fd(fd_set *rset, fd_set *wset) { char c; if(FD_ISSET(STDIN_FILENO, rset)) { if(read(STDIN_FILENO, &c, 1) > 0) { serial_line_input_byte(c); } } } const static struct select_callback stdin_fd = { stdin_set_fd, stdin_handle_fd }; /*---------------------------------------------------------------------------*/ static void set_lladdr(void) { linkaddr_t addr; memset(&addr, 0, sizeof(linkaddr_t)); #if NETSTACK_CONF_WITH_IPV6 memcpy(addr.u8, serial_id, sizeof(addr.u8)); #else if(node_id == 0) { int i; for(i = 0; i < sizeof(linkaddr_t); ++i) { addr.u8[i] = serial_id[7 - i]; } } else { addr.u8[0] = node_id & 0xff; addr.u8[1] = node_id >> 8; } #endif linkaddr_set_node_addr(&addr); } /*---------------------------------------------------------------------------*/ static void set_global_address(void) { static uip_ipaddr_t ipaddr; static uip_ipaddr_t *prefix = NULL; /* Assign a unique local address (RFC4193, http://tools.ietf.org/html/rfc4193). */ if(prefix == NULL) { uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); } else { memcpy(&ipaddr, prefix, 8); } /* Assumes that the uip_lladdr is set */ uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); /* set the PREFIX::1 address to the IF */ uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); uip_ds6_defrt_add(&ipaddr, 0); } /*---------------------------------------------------------------------------*/ int contiki_argc = 0; char **contiki_argv; /*---------------------------------------------------------------------------*/ void platform_process_args(int argc, char**argv) { /* crappy way of remembering and accessing argc/v */ contiki_argc = argc; contiki_argv = argv; /* native under windows is hardcoded to use the first one or two args */ /* for wpcap configuration so this needs to be "removed" from */ /* contiki_args (used by the native-border-router) */ #ifdef __CYGWIN__ contiki_argc--; contiki_argv++; #ifdef UIP_FALLBACK_INTERFACE contiki_argc--; contiki_argv++; #endif #endif } /*---------------------------------------------------------------------------*/ void platform_init_stage_one() { return; } /*---------------------------------------------------------------------------*/ void platform_init_stage_two() { set_lladdr(); } /*---------------------------------------------------------------------------*/ void platform_init_stage_three() { #if NETSTACK_CONF_WITH_IPV6 #ifdef __CYGWIN__ process_start(&wpcap_process, NULL); #endif set_global_address(); #endif /* NETSTACK_CONF_WITH_IPV6 */ /* Make standard output unbuffered. */ setvbuf(stdout, (char *)NULL, _IONBF, 0); } /*---------------------------------------------------------------------------*/ void platform_main_loop() { select_set_callback(STDIN_FILENO, &stdin_fd); while(1) { fd_set fdr; fd_set fdw; int maxfd; int i; int retval; struct timeval tv; retval = process_run(); tv.tv_sec = 0; tv.tv_usec = retval ? 1 : 1000; FD_ZERO(&fdr); FD_ZERO(&fdw); maxfd = 0; for(i = 0; i <= select_max; i++) { if(select_callback[i] != NULL && select_callback[i]->set_fd(&fdr, &fdw)) { maxfd = i; } } retval = select(maxfd + 1, &fdr, &fdw, NULL, &tv); if(retval < 0) { if(errno != EINTR) { perror("select"); } } else if(retval > 0) { /* timeout => retval == 0 */ for(i = 0; i <= maxfd; i++) { if(select_callback[i] != NULL) { select_callback[i]->handle_fd(&fdr, &fdw); } } } etimer_request_poll(); } return; } /*---------------------------------------------------------------------------*/ void log_message(char *m1, char *m2) { fprintf(stderr, "%s%s\n", m1, m2); } /*---------------------------------------------------------------------------*/ void uip_log(char *m) { fprintf(stderr, "%s\n", m); } /*---------------------------------------------------------------------------*/ /** @} */