Contiki 2.6

contiki-main.c

00001 /*
00002  * Copyright (c) 2002, Adam Dunkels.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above
00011  *    copyright notice, this list of conditions and the following
00012  *    disclaimer in the documentation and/or other materials provided
00013  *    with the distribution.
00014  * 3. The name of the author may not be used to endorse or promote
00015  *    products derived from this software without specific prior
00016  *    written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00019  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00022  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00024  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00027  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  * This file is part of the Contiki OS
00031  *
00032  *
00033  */
00034 
00035 #include <stdio.h>
00036 #include <time.h>
00037 #include <sys/select.h>
00038 #include <unistd.h>
00039 #include <memory.h>
00040 
00041 #include "contiki.h"
00042 #include "contiki-net.h"
00043 
00044 #include "dev/serial-line.h"
00045 
00046 #include "net/uip.h"
00047 #ifdef __CYGWIN__
00048 #include "net/wpcap-drv.h"
00049 #else /* __CYGWIN__ */
00050 #include "net/tapdev-drv.h"
00051 #endif /* __CYGWIN__ */
00052 
00053 #ifdef __CYGWIN__
00054 PROCINIT(&etimer_process, &tcpip_process, &wpcap_process, &serial_line_process);
00055 #else /* __CYGWIN__ */
00056 PROCINIT(&etimer_process, &tapdev_process, &tcpip_process, &serial_line_process);
00057 #endif /* __CYGWIN__ */
00058 
00059 #if RPL_BORDER_ROUTER
00060 #include "net/rpl/rpl.h"
00061 
00062 static uint16_t dag_id[] = {0x1111, 0x1100, 0, 0, 0, 0, 0, 0x0011};
00063 
00064 PROCESS(border_router_process, "RPL Border Router");
00065 PROCESS_THREAD(border_router_process, ev, data)
00066 {
00067 
00068   PROCESS_BEGIN();
00069 
00070   PROCESS_PAUSE();
00071 
00072   {
00073     rpl_dag_t *dag;
00074     char buf[sizeof(dag_id)];
00075     memcpy(buf,dag_id,sizeof(dag_id));
00076     dag = rpl_set_root((uip_ip6addr_t *)buf);
00077     
00078     /* Assign separate addresses to the uip stack and the host network
00079         interface, but with the same prefix E.g. bbbb::ff:fe00:200 to
00080         the stack and bbbb::1 to the host *fallback* network interface
00081         Otherwise the host will trap packets intended for the stack,
00082         just as the stack will trap packets intended for the host
00083         $ifconfig usb0 -arp on Ubuntu to skip the neighbor
00084         solicitations. Add explicit neighbors on other OSs */
00085 
00086     if(dag != NULL) {
00087       printf("Created a new RPL dag\n");
00088       
00089 #if UIP_CONF_ROUTER_RECEIVE_RA
00090       /* Contiki stack will shut down until assigned an address from the
00091          interface RA Currently this requires changes in the core
00092          rpl-icmp6.c to pass the link-local RA broadcast.
00093       */
00094       
00095 #else
00096       {
00097         static void sprint_ip6(uip_ip6addr_t addr);
00098         int i;
00099         uip_ip6addr_t ipaddr;
00100 #ifdef HARD_CODED_ADDRESS
00101         uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr);
00102 #else
00103         uip_ip6addr(&ipaddr, 0xbbbb, 0, 0, 0, 0, 0, 0, 0x1);
00104 #endif
00105         uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
00106         uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
00107         rpl_set_prefix(dag, &ipaddr, 64);
00108 
00109         for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
00110           if(uip_ds6_if.addr_list[i].isused) {
00111             printf("IPV6 Address: ");
00112             sprint_ip6(uip_ds6_if.addr_list[i].ipaddr);
00113             printf("\n");
00114           }
00115         }
00116       }
00117 #endif
00118     }
00119   }
00120   /* The border router runs with a 100% duty cycle in order to ensure high
00121      packet reception rates. */
00122   /* NETSTACK_MAC.off(1); */
00123 
00124   while(1) {
00125     PROCESS_YIELD();
00126     /* Local and global dag repair can be done from ? */
00127     /*  rpl_set_prefix(rpl_get_dag(RPL_ANY_INSTANCE), &ipaddr, 64);
00128         rpl_repair_dag(rpl_get_dag(RPL_ANY_INSTANCE)); */
00129   }
00130 
00131   PROCESS_END();
00132 }
00133 #endif /* RPL_BORDER_ROUTER */
00134 
00135 #if UIP_CONF_IPV6
00136 /*---------------------------------------------------------------------------*/
00137 static void
00138 sprint_ip6(uip_ip6addr_t addr)
00139 {
00140   unsigned char i = 0;
00141   unsigned char zerocnt = 0;
00142   unsigned char numprinted = 0;
00143   unsigned char notskipped = 0;
00144   char thestring[40];
00145   char *result = thestring;
00146 
00147   *result++ = '[';
00148   while(numprinted < 8) {
00149     if((addr.u16[i] == 0) && (zerocnt == 0)) {
00150       while(addr.u16[zerocnt + i] == 0) {
00151         zerocnt++;
00152       }
00153       if(zerocnt == 1 && notskipped) {
00154         *result++ = '0';
00155          numprinted++;
00156          notskipped = 1;
00157          continue;
00158       }
00159       i += zerocnt;
00160       numprinted += zerocnt;
00161     } else {
00162       result += sprintf(result, "%x", (unsigned int)(uip_ntohs(addr.u16[i])));
00163       i++;
00164       numprinted++;
00165     }
00166     if(numprinted != 8) {
00167       *result++ = ':';
00168     }
00169   }
00170   *result++=']';
00171   *result=0;
00172   printf("%s", thestring);
00173 }
00174 #endif /* UIP_CONF_IPV6 */
00175 /*---------------------------------------------------------------------------*/
00176 int
00177 main(void)
00178 {
00179   clock_init();
00180 #if UIP_CONF_IPV6
00181 /* A hard coded address overrides the stack default MAC address to
00182    allow multiple instances. uip6.c defines it as
00183    {0x00,0x06,0x98,0x00,0x02,0x32} giving an ipv6 address of
00184    [fe80::206:98ff:fe00:232] We make it simpler, {0x02,0x00,0x00 + the
00185    last three bytes of the hard coded address (if any are nonzero).
00186    HARD_CODED_ADDRESS can be defined in the contiki-conf.h file, or
00187    here to allow quick builds using different addresses.  If
00188    HARD_CODED_ADDRESS has a prefix it also applied, unless built as a
00189    RPL end node.  E.g. bbbb::12:3456 becomes fe80::ff:fe12:3456 and
00190    prefix bbbb::/64 if non-RPL ::10 becomes fe80::ff:fe00:10 and
00191    prefix awaits RA or RPL formation bbbb:: gives an address of
00192    bbbb::206:98ff:fe00:232 if non-RPL */
00193 #ifdef HARD_CODED_ADDRESS
00194   {
00195   uip_ipaddr_t ipaddr;
00196   uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr);
00197   if((ipaddr.u8[13] != 0) ||
00198      (ipaddr.u8[14] != 0) ||
00199      (ipaddr.u8[15] != 0)) {
00200     if(sizeof(uip_lladdr) == 6) {  /* Minimal-net uses ethernet MAC */
00201       uip_lladdr.addr[0] = 0x02;
00202       uip_lladdr.addr[1] = 0;
00203       uip_lladdr.addr[2] = 0;
00204       uip_lladdr.addr[3] = ipaddr.u8[13];
00205       uip_lladdr.addr[4] = ipaddr.u8[14];
00206       uip_lladdr.addr[5] = ipaddr.u8[15];
00207     }
00208   }
00209  }
00210 #endif /* HARD_CODED_ADDRESS */
00211 #endif /* UIP_CONF_IPV6 */
00212 
00213   process_init();
00214 /* procinit_init initializes RPL which sets a ctimer for the first DIS */
00215 /* We must start etimers and ctimers,before calling it */
00216   process_start(&etimer_process, NULL);
00217   ctimer_init();
00218 
00219 #if RPL_BORDER_ROUTER
00220   process_start(&border_router_process, NULL);
00221   printf("Border Router Process started\n");
00222 #elif UIP_CONF_IPV6_RPL
00223   printf("RPL enabled\n");
00224 #endif
00225 
00226   procinit_init();
00227   autostart_start(autostart_processes); 
00228 
00229   /* Set default IP addresses if not specified */
00230 #if !UIP_CONF_IPV6
00231   {
00232     uip_ipaddr_t addr;
00233 
00234     uip_gethostaddr(&addr);
00235     if(addr.u8[0] == 0) {
00236       uip_ipaddr(&addr, 10,1,1,1);
00237     }
00238     printf("IP Address:  %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr));
00239     uip_sethostaddr(&addr);
00240     
00241     uip_getnetmask(&addr);
00242     if(addr.u8[0] == 0) {
00243       uip_ipaddr(&addr, 255,0,0,0);
00244       uip_setnetmask(&addr);
00245     }
00246     printf("Subnet Mask: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr));
00247     
00248     uip_getdraddr(&addr);
00249     if(addr.u8[0] == 0) {
00250       uip_ipaddr(&addr, 10,1,1,100);
00251       uip_setdraddr(&addr);
00252     }
00253     printf("Def. Router: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr));
00254   }
00255 #else /* UIP_CONF_IPV6 */
00256 
00257 #if !UIP_CONF_IPV6_RPL
00258   {
00259     uip_ipaddr_t ipaddr;
00260 #ifdef HARD_CODED_ADDRESS
00261     uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr);
00262 #else
00263     uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
00264 #endif
00265     if((ipaddr.u16[0] != 0) ||
00266        (ipaddr.u16[1] != 0) ||
00267        (ipaddr.u16[2] != 0) ||
00268        (ipaddr.u16[3] != 0)) {
00269 #if UIP_CONF_ROUTER
00270       uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0);
00271 #else /* UIP_CONF_ROUTER */
00272       uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0);
00273 #endif /* UIP_CONF_ROUTER */
00274 
00275       uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
00276       uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
00277     }
00278   }
00279 #endif /* !UIP_CONF_IPV6_RPL */
00280 
00281 #endif /* !UIP_CONF_IPV6 */
00282 
00283  // procinit_init();
00284  // autostart_start(autostart_processes); 
00285 
00286   /* Make standard output unbuffered. */
00287   setvbuf(stdout, (char *)NULL, _IONBF, 0);
00288 
00289   printf("\n*******%s online*******\n",CONTIKI_VERSION_STRING);
00290 
00291 #if UIP_CONF_IPV6 && !RPL_BORDER_ROUTER  /* Border router process prints addresses later */
00292   {
00293     uint8_t i;
00294     for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
00295       if(uip_ds6_if.addr_list[i].isused) {
00296         printf("IPV6 Addresss: ");
00297         sprint_ip6(uip_ds6_if.addr_list[i].ipaddr);
00298         printf("\n");
00299       }
00300     }
00301   }
00302 #endif
00303 
00304   while(1) {
00305     fd_set fds;
00306     int n;
00307     struct timeval tv;
00308     
00309     n = process_run();
00310 
00311     tv.tv_sec = 0;
00312     tv.tv_usec = 1000;
00313     FD_ZERO(&fds);
00314     FD_SET(STDIN_FILENO, &fds);
00315     select(1, &fds, NULL, NULL, &tv);
00316 
00317     if(FD_ISSET(STDIN_FILENO, &fds)) {
00318       char c;
00319       if(read(STDIN_FILENO, &c, 1) > 0) {
00320         serial_line_input_byte(c);
00321       }
00322     }
00323     etimer_request_poll();
00324   }
00325   
00326   return 0;
00327 }
00328 /*---------------------------------------------------------------------------*/
00329 void
00330 log_message(char *m1, char *m2)
00331 {
00332   printf("%s%s\n", m1, m2);
00333 }
00334 /*---------------------------------------------------------------------------*/
00335 void
00336 uip_log(char *m)
00337 {
00338   printf("uIP: '%s'\n", m);
00339 }
00340 /*---------------------------------------------------------------------------*/
00341 unsigned short
00342 sensors_light1(void)
00343 {
00344   static unsigned short count;
00345   return count++;
00346 }
00347 /*---------------------------------------------------------------------------*/