/* * 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 */ #if BUILD_WITH_SHELL #include "serial-shell.h" #endif /* BUILD_WITH_SHELL */ #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; int i; memset(&addr, 0, sizeof(linkaddr_t)); #if NETSTACK_CONF_WITH_IPV6 memcpy(addr.u8, serial_id, sizeof(addr.u8)); #else if(node_id == 0) { 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); printf("Contiki started with address "); for(i = 0; i < sizeof(addr.u8) - 1; i++) { printf("%d.", addr.u8[i]); } printf("%d\n", addr.u8[i]); } /*---------------------------------------------------------------------------*/ static void set_global_address(void) { static uip_ipaddr_t ipaddr; static uip_ipaddr_t *prefix = NULL; int i; uint8_t state; /* 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); printf("IPv6 addresses: "); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { state = uip_ds6_if.addr_list[i].state; if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); printf("\n"); } } } /*---------------------------------------------------------------------------*/ int contiki_argc = 0; char **contiki_argv; int main(int argc, char **argv) { #if NETSTACK_CONF_WITH_IPV6 #if UIP_CONF_IPV6_RPL printf(CONTIKI_VERSION_STRING " started with IPV6, RPL\n"); #else printf(CONTIKI_VERSION_STRING " started with IPV6\n"); #endif #else printf(CONTIKI_VERSION_STRING " started\n"); #endif /* 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 process_init(); process_start(&etimer_process, NULL); ctimer_init(); rtimer_init(); set_lladdr(); netstack_init(); printf("MAC %s NETWORK %s\n", NETSTACK_MAC.name, NETSTACK_NETWORK.name); #if NETSTACK_CONF_WITH_IPV6 queuebuf_init(); memcpy(&uip_lladdr.addr, serial_id, sizeof(uip_lladdr.addr)); process_start(&tcpip_process, NULL); #ifdef __CYGWIN__ process_start(&wpcap_process, NULL); #endif printf("Tentative link-local IPv6 address "); { uip_ds6_addr_t *lladdr; int i; lladdr = uip_ds6_get_link_local(-1); for(i = 0; i < 7; ++i) { printf("%02x%02x:", lladdr->ipaddr.u8[i * 2], lladdr->ipaddr.u8[i * 2 + 1]); } /* make it hardcoded... */ lladdr->state = ADDR_AUTOCONF; printf("%02x%02x\n", lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]); } set_global_address(); #endif /* NETSTACK_CONF_WITH_IPV6 */ serial_line_init(); #if BUILD_WITH_SHELL serial_shell_init(); #endif /* BUILD_WITH_SHELL */ autostart_start(autostart_processes); /* Make standard output unbuffered. */ setvbuf(stdout, (char *)NULL, _IONBF, 0); 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 0; } /*---------------------------------------------------------------------------*/ void log_message(char *m1, char *m2) { fprintf(stderr, "%s%s\n", m1, m2); } /*---------------------------------------------------------------------------*/ void uip_log(char *m) { fprintf(stderr, "%s\n", m); } /*---------------------------------------------------------------------------*/ /** @} */