ether.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004, Swedish Institute of Computer Science.
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 copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  *
00031  * Author: Adam Dunkels <adam@sics.se>
00032  *
00033  * $Id: ether.c,v 1.17 2010/10/19 18:29:05 adamdunkels Exp $
00034  */
00035 /**
00036  * \file
00037  * This module implements a simple "ether", into which datapackets can
00038  * be injected. The packets are delivered to all nodes that are in
00039  * transmission range.
00040  *
00041  * \author Adam Dunkels <adam@sics.se>
00042  *
00043  */
00044 
00045 #include <sys/types.h>
00046 #include <sys/socket.h>
00047 #include <sys/time.h>
00048 #include <unistd.h>
00049 #include <stdlib.h>
00050 #include <stdio.h>
00051 #include <string.h>
00052 #include <netinet/in.h>
00053 #include <arpa/inet.h>
00054 
00055 #include <errno.h>
00056 
00057 #include "ether.h"
00058 #include "lib/memb.h"
00059 #include "lib/list.h"
00060 #include "nodes.h"
00061 
00062 #include "dev/radio-sensor.h"
00063 
00064 #include "dev/serial-line.h"
00065 
00066 #include "sensor.h"
00067 
00068 #include "node.h"
00069 #include "net/uip.h"
00070 #include "net/uip-fw.h"
00071 
00072 #ifndef NULL
00073 #define NULL 0
00074 #endif /* NULL */
00075 
00076 MEMB(packets, struct ether_packet, 20000);
00077 LIST(active_packets);
00078 
00079 static u8_t rxbuffer[2048];
00080 static clock_time_t timer;
00081 
00082 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
00083 
00084 #define PRINTF(...)
00085 /*#define PRINTF(x) printf x*/
00086 
00087 static int s, sc;
00088 
00089 #define PTYPE_NONE   0
00090 #define PTYPE_CLOCK  1
00091 #define PTYPE_DATA   2
00092 #define PTYPE_SENSOR 3
00093 #define PTYPE_LEDS   4
00094 #define PTYPE_TEXT   5
00095 #define PTYPE_DONE   6
00096 #define PTYPE_SERIAL 7
00097 #define PTYPE_RADIO_STATUS 8
00098 
00099 #define SERIAL_LEN 80
00100 
00101 struct ether_hdr {
00102   int type;
00103   struct sensor_data sensor_data;
00104   clock_time_t clock;
00105   int linex, liney;
00106   int signal;
00107   int srcx, srcy;
00108   int srcpid;
00109   int srcid;
00110   int srcnodetype;
00111   int leds;
00112   int radio_status;
00113   char text[NODES_TEXTLEN + SERIAL_LEN];
00114 };
00115 
00116 static int strength;
00117 
00118 static int collisions = 1;
00119 static int num_collisions = 0;
00120 static int num_sent = 0;
00121 static int num_received = 0;
00122 static int drop_probability = 0;
00123 static int num_drops = 0;
00124 
00125 #include <sys/time.h>
00126 
00127 static struct timeval t1;
00128 
00129 static int linex, liney;
00130 
00131 /*-----------------------------------------------------------------------------------*/
00132 void
00133 ether_print_stats(void)
00134 {
00135   unsigned long time;
00136   struct timeval t2;
00137   gettimeofday(&t2, NULL);
00138 
00139   time = (t2.tv_sec * 1000 + t2.tv_usec / 1000) -
00140     (t1.tv_sec * 1000 + t1.tv_usec / 1000);
00141   /*  printf("%d, %d, %f\n", num_packets, num_collisions, time/1000.0);*/
00142   printf("Time: %f\n", time/1000.0);
00143   printf("Total packets sent: %d\n", num_sent);
00144   printf("Total collisions: %d\n", num_collisions);
00145   printf("Total packets receptions: %d\n", num_received);
00146   printf("Total randomly dropped packets: %d\n", num_drops);
00147 }
00148 /*-----------------------------------------------------------------------------------*/
00149 void
00150 ether_set_drop_probability(double p)
00151 {
00152   drop_probability = p * 65536;
00153 }
00154 /*-----------------------------------------------------------------------------------*/
00155 void
00156 ether_set_collisions(int c)
00157 {
00158   collisions = c;
00159 }
00160 /*-----------------------------------------------------------------------------------*/
00161 void
00162 ether_set_strength(int s)
00163 {
00164   strength = s;
00165 }
00166 /*-----------------------------------------------------------------------------------*/
00167 int
00168 ether_strength(void)
00169 {
00170   return strength;
00171 }
00172 /*-----------------------------------------------------------------------------------*/
00173 void
00174 ether_server_init(void)
00175 {
00176   struct sockaddr_in sa;
00177 
00178   gettimeofday(&t1, NULL);
00179   
00180   memb_init(&packets);
00181   list_init(active_packets);
00182 
00183   timer = 0;
00184 
00185   s = socket(AF_INET,SOCK_DGRAM,0);
00186 
00187   if(s < 0) {
00188     perror("ether_server_init: socket");
00189   }
00190   
00191   memset((char *)&sa, 0, sizeof(sa));
00192   
00193   sa.sin_family = AF_INET;
00194   sa.sin_addr.s_addr = inet_addr("127.0.0.1");/*uip_htonl(INADDR_ANY);*/
00195 
00196   sa.sin_port = uip_htons(ETHER_PORT);
00197 
00198   /*  printf("Binding to port %d\n", ETHER_PORT);*/
00199   
00200   if(bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
00201     printf("Bind to port %d\n", ETHER_PORT);
00202     perror("bind");
00203     exit(1);
00204   }
00205 
00206 }
00207 /*-----------------------------------------------------------------------------------*/
00208 void
00209 ether_client_init(int port)
00210 {
00211   struct sockaddr_in sa;
00212     
00213   sc = socket(AF_INET,SOCK_DGRAM,0);
00214   
00215   if(sc < 0) {
00216     perror("socket");
00217   }
00218   
00219   memset((char *)&sa, 0, sizeof(sa));
00220   
00221   sa.sin_family = AF_INET;
00222   sa.sin_addr.s_addr = inet_addr("127.0.0.1");/*uip_htonl(INADDR_ANY);*/
00223 
00224   sa.sin_port = uip_htons(port);
00225 
00226   /*  printf("ether_client_init: binding to port %d\n", port);*/
00227   if(bind(sc, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
00228     printf("Bind to port %d\n", port);
00229     perror("bind");
00230     exit(1);
00231   }
00232 }
00233 /*-----------------------------------------------------------------------------------*/
00234 int
00235 ether_client_poll(void)
00236 {
00237   fd_set fdset;
00238   struct timeval tv;
00239   int ret;
00240 
00241   FD_ZERO(&fdset);
00242   FD_SET(sc, &fdset);
00243 
00244   tv.tv_sec = 0;
00245   tv.tv_usec = 1000;
00246   
00247   ret = select(sc + 1, &fdset, NULL, NULL, &tv);
00248 
00249   if(ret < 0) {
00250     perror("ether_client_poll: select");
00251   }
00252   return ret == 1;
00253 }
00254 /*-----------------------------------------------------------------------------------*/
00255 u16_t
00256 ether_client_read(u8_t *buf, int bufsize)
00257 {
00258   int ret, len;
00259   fd_set fdset;
00260   struct timeval tv;
00261   struct ether_hdr *hdr = (struct ether_hdr *)rxbuffer;
00262 
00263   FD_ZERO(&fdset);
00264   FD_SET(sc, &fdset);
00265 
00266   tv.tv_sec = 0;
00267   tv.tv_usec = 10000;
00268 
00269   ret = select(sc + 1, &fdset, NULL, NULL, &tv);
00270   
00271   if(ret == 0) {
00272     /*    printf("ret 0\n");*/
00273     return 0;
00274   }
00275   if(FD_ISSET(sc, &fdset)) {
00276     ret = recv(sc, &rxbuffer[0], sizeof(rxbuffer), 0);
00277     if(ret == -1) {
00278       perror("ether_client_poll: recv");
00279       return 0;
00280     }
00281     len = ret;
00282 
00283     if(len > bufsize) {
00284       PRINTF("ether_client_read: packet truncated from %d to %d\n",
00285              len, bufsize);
00286       len = bufsize;
00287     }
00288 
00289     /*    printf("Incoming len %d\n", len);*/
00290     memcpy(buf, &rxbuffer[sizeof(struct ether_hdr)], len);
00291     radio_sensor_signal = hdr->signal;
00292 
00293     if(hdr->type == PTYPE_DATA && hdr->srcid != node.id) {
00294       return len - sizeof(struct ether_hdr);
00295     } else if(hdr->type == PTYPE_CLOCK) {
00296       node_set_time(hdr->clock);
00297     } else if(hdr->type == PTYPE_SENSOR) {
00298       int strength = sensor_strength() -
00299         ((hdr->srcx - node_x()) * (hdr->srcx - node_x()) +
00300          (hdr->srcy - node_y()) * (hdr->srcy - node_y())) / sensor_strength();
00301       /*      printf("Dist %d \n", strength);*/
00302       if(strength > 0) {
00303         sensor_input(&hdr->sensor_data, strength);
00304       }
00305     } else if(hdr->type == PTYPE_SERIAL) {
00306       char *ptr = hdr->text;
00307       printf("serial input %s\n", ptr);
00308       for(ptr = hdr->text; *ptr != 0; ++ptr) {
00309         serial_line_input_byte(*ptr);
00310       }
00311     }
00312   }
00313   return 0;
00314 }
00315 /*-----------------------------------------------------------------------------------*/
00316 void
00317 ether_server_poll(void)
00318 {
00319   int ret;
00320   fd_set fdset;
00321   struct timeval tv;
00322   struct ether_hdr *hdr = (struct ether_hdr *)rxbuffer;
00323   /*  struct timeval rtime1, rtime2;
00324   struct timespec ts;
00325   struct timezone tz;*/
00326 
00327   
00328   tv.tv_sec = 0;
00329   tv.tv_usec = 100;
00330 
00331   
00332   do {
00333     FD_ZERO(&fdset);
00334     FD_SET(s, &fdset);
00335 
00336     ret = select(s + 1, &fdset, NULL, NULL, &tv);
00337     if(ret == 0) {
00338       return;
00339     }
00340     if(FD_ISSET(s, &fdset)) {
00341       ret = recv(s, &rxbuffer[0], sizeof(rxbuffer), 0);
00342       if(ret == -1) {
00343         perror("ether_poll: read");
00344         return;
00345       }
00346       nodes_set_line(hdr->srcx, hdr->srcy, hdr->linex, hdr->liney);
00347       switch(hdr->type) {
00348       case PTYPE_DATA:
00349         PRINTF("ether_poll: read %d bytes from (%d, %d)\n",
00350                ret, hdr->srcx, hdr->srcy);
00351         ether_put((char *)rxbuffer, ret, hdr->srcx, hdr->srcy);
00352         break;
00353       case PTYPE_LEDS:
00354         nodes_set_leds(hdr->srcx, hdr->srcy, hdr->leds);
00355         break;
00356       case PTYPE_TEXT:
00357         nodes_set_text(hdr->srcx, hdr->srcy, hdr->text);
00358         break;
00359       case PTYPE_DONE:
00360         nodes_done(hdr->srcid);
00361         break;
00362       case PTYPE_SERIAL:
00363         break;
00364       case PTYPE_RADIO_STATUS:
00365         nodes_set_radio_status(hdr->srcx, hdr->srcy, hdr->radio_status);
00366         break;
00367       }
00368     }
00369     /*    tv.tv_sec = 0;
00370           tv.tv_usec = 1;*/
00371 
00372   } while(1/*ret > 0*/);
00373 }
00374 /*-----------------------------------------------------------------------------------*/
00375 void
00376 ether_put(char *data, int len, int x, int y)
00377 {
00378   struct ether_packet *p;
00379 
00380   /*  printf("ether_put: packet len %d at (%d, %d)\n", len, x, y);*/
00381   
00382   p = (struct ether_packet *)memb_alloc(&packets);
00383 
00384   if(p != NULL) {
00385     if(len > 1500) {
00386       len = 1500;
00387     }
00388     memcpy(p->data, data, len);
00389     p->len = len;
00390     p->x = x;
00391     p->y = y;
00392     list_push(active_packets, p);
00393 
00394 
00395   }
00396 }
00397 /*-----------------------------------------------------------------------------------*/
00398 static void
00399 send_packet(char *data, int len, int port)
00400 {
00401   struct sockaddr_in sa;
00402   
00403   memset((char *)&sa, 0, sizeof(sa));
00404   sa.sin_family = AF_INET;
00405   sa.sin_addr.s_addr = inet_addr("127.0.0.1");
00406   sa.sin_port = uip_htons(port);
00407   
00408   if(sendto(s, data, len, 0, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
00409     perror("ether: send_packet: sendto");
00410   }
00411 }
00412 /*-----------------------------------------------------------------------------------*/
00413 void
00414 ether_tick(void)
00415 {
00416   struct ether_packet *p, *q;
00417   struct ether_hdr *hdr;
00418   int port;
00419   int x, y;
00420   int i;
00421   int interference;
00422 
00423   /* Go through every node and see if there are any packets destined
00424      to them. If two or more packets are sent in the vicinity of the
00425      node, they interfere with each otehr and none reaches the
00426      node. */
00427   for(i = 0; i < nodes_num(); ++i) {
00428 
00429     x = nodes_node(i)->x;
00430     y = nodes_node(i)->y;
00431     port = nodes_node(i)->port;
00432 
00433     /* Go through all active packets to see if anyone is sent within
00434        range of this node. */
00435     for(p = list_head(active_packets); p != NULL; p = p->next) {
00436       
00437       num_sent++;
00438       
00439       /* Update the node type. */
00440       hdr = (struct ether_hdr *)p->data;
00441       /*      nodes_node(hdr->srcid)->type = hdr->srcnodetype;*/
00442       
00443       if(!(p->x == x && p->y == y) && /* Don't send packets back to
00444                                          the sender. */
00445          (p->x - x) * (p->x - x) +
00446          (p->y - y) * (p->y - y) <=
00447          ether_strength() * ether_strength()) {
00448 
00449         hdr->signal = ether_strength() * ether_strength() -
00450           (p->x - x) * (p->x - x) -
00451           (p->y - y) * (p->y - y);
00452         /* This packet was sent in the reception range of this node,
00453            so we check against all other packets to see if there is
00454            more than one packet sent towards this node. If so, we have
00455            interference and the node will not be able to receive any
00456            data. */
00457         interference = 0;
00458         if(collisions) {
00459           for(q = list_head(active_packets); q != NULL; q = q->next) {
00460             
00461             /* Compute the distance^2 and check against signal strength. */
00462             if(p != q &&
00463                ((q->x - x) * (q->x - x) +
00464                 (q->y - y) * (q->y - y) <=
00465                 ether_strength() * ether_strength())) {
00466 
00467               /* If the potentially interfering packets were sent from
00468                  the same node, then they don't interfere with each
00469                  other. Otherwise they interfere and we sent the
00470                  interference flag to 1. */
00471               if(p->x != q->x ||
00472                  p->y != q->y) {
00473                 interference = 1;
00474               }
00475               break;
00476             }
00477           }
00478         }
00479 
00480         if(interference) {
00481           num_collisions++;
00482           /*      printf("Collisions %d\n", num_collisions);*/
00483         }
00484         
00485         if(!interference) {
00486           /*      printf("ether: delivering packet from %d to %d\n",
00487                   hdr->srcid, port);*/
00488           if((unsigned int)((rand() * 17) % 65536) >= drop_probability) {
00489             send_packet(p->data, p->len, port);
00490             num_received++;
00491           } else {
00492             num_drops++;
00493           }
00494         }
00495       }
00496 
00497 
00498     }
00499   }
00500 
00501   /* Remove all packets from the active packets list. */
00502   while((p = list_pop(active_packets)) != NULL) {
00503     memb_free(&packets, (void *) p);
00504   }
00505 
00506   ++timer;
00507 }
00508 /*-----------------------------------------------------------------------------------*/
00509 struct ether_packet *
00510 ether_packets(void)
00511 {
00512   return list_head(active_packets);
00513 }
00514 /*-----------------------------------------------------------------------------------*/
00515 clock_time_t
00516 ether_time(void)
00517 {
00518   return timer;
00519 }
00520 /*-----------------------------------------------------------------------------------*/
00521 static void
00522 node_send_packet(char *data, int len)
00523 {
00524   struct sockaddr_in sa;
00525   
00526   memset((char *)&sa, 0, sizeof(sa));
00527   sa.sin_family = AF_INET;
00528   sa.sin_addr.s_addr = inet_addr("127.0.0.1");
00529   sa.sin_port = uip_htons(ETHER_PORT);
00530         
00531   if(sendto(sc, data, len, 0,
00532             (struct sockaddr *)&sa, sizeof(sa)) == -1) {
00533     perror("ether.c node_send_packet: sendto");
00534   }
00535 }
00536 /*-----------------------------------------------------------------------------------*/
00537 u8_t
00538 ether_send(char *data, int len)
00539 {
00540   char tmpbuf[2048];
00541   struct ether_hdr *hdr = (struct ether_hdr *)tmpbuf;
00542    
00543 
00544   memcpy(&tmpbuf[sizeof(struct ether_hdr)], data, len);
00545   
00546   hdr->srcx = node.x;
00547   hdr->srcy = node.y;
00548   hdr->type = PTYPE_DATA;
00549   /*  hdr->srcnodetype = node.type;*/
00550   hdr->srcid = node.id;
00551 
00552   hdr->linex = linex;
00553   hdr->liney = liney;
00554   node_send_packet(tmpbuf, len + sizeof(struct ether_hdr));
00555   
00556   return UIP_FW_OK;
00557 }
00558 /*-----------------------------------------------------------------------------------*/
00559 void
00560 ether_set_leds(int leds)
00561 {
00562   struct ether_hdr hdr;
00563 
00564   memset(&hdr, 0, sizeof (hdr));  
00565   hdr.srcx = node.x;
00566   hdr.srcy = node.y;
00567   hdr.type = PTYPE_LEDS;
00568   hdr.leds = leds;
00569   /*  hdr.srcnodetype = node.type;*/
00570   hdr.srcid = node.id;
00571   hdr.linex = linex;
00572   hdr.liney = liney;
00573 
00574   node_send_packet((char *)&hdr, sizeof(struct ether_hdr));
00575 
00576 }
00577 /*-----------------------------------------------------------------------------------*/
00578 void
00579 ether_set_text(char *text)
00580 {
00581   struct ether_hdr hdr;
00582   
00583   hdr.srcx = node.x;
00584   hdr.srcy = node.y;
00585   hdr.type = PTYPE_TEXT;
00586   strncpy(hdr.text, text, NODES_TEXTLEN);
00587   /*  hdr.srcnodetype = node.type;*/
00588   hdr.srcid = node.id;
00589   hdr.linex = linex;
00590   hdr.liney = liney;
00591 
00592   node_send_packet((char *)&hdr, sizeof(struct ether_hdr));
00593 
00594 }
00595 /*-----------------------------------------------------------------------------------*/
00596 void
00597 ether_set_radio_status(int onoroff)
00598 {
00599   struct ether_hdr hdr;
00600   
00601   hdr.srcx = node.x;
00602   hdr.srcy = node.y;
00603   hdr.type = PTYPE_RADIO_STATUS;
00604   hdr.radio_status = onoroff;
00605   hdr.srcid = node.id;
00606   hdr.linex = linex;
00607   hdr.liney = liney;
00608 
00609   node_send_packet((char *)&hdr, sizeof(struct ether_hdr));
00610 
00611 }
00612 /*-----------------------------------------------------------------------------------*/
00613 void
00614 ether_send_sensor_data(struct sensor_data *d, int srcx, int srcy, int strength)
00615 {
00616   int port;
00617   int x, y;
00618   int i;
00619   struct ether_hdr hdr;
00620 
00621   /*  printf("Sensor data at (%d, %d)\n", srcx, srcy);*/
00622   
00623   for(i = 0; i < nodes_num(); ++i) {
00624 
00625     x = nodes_node(i)->x;
00626     y = nodes_node(i)->y;
00627     port = nodes_node(i)->port;
00628 
00629     if((srcx - x) * (srcx - x) +
00630        (srcy - y) * (srcy - y) <=
00631        strength * strength) {
00632       
00633       hdr.srcx = srcx;
00634       hdr.srcy = srcy;
00635       hdr.type = PTYPE_SENSOR;
00636       hdr.sensor_data = *d;
00637       send_packet((char *)&hdr, sizeof(hdr), port);
00638     }
00639   }
00640 
00641 }
00642 /*-----------------------------------------------------------------------------------*/
00643 void
00644 ether_send_done(void)
00645 {
00646   struct ether_hdr hdr;
00647   
00648   hdr.srcx = node.x;
00649   hdr.srcy = node.y;
00650   hdr.type = PTYPE_DONE;
00651   hdr.srcid = node.id;
00652 
00653   node_send_packet((char *)&hdr, sizeof(struct ether_hdr));
00654 
00655 }
00656 /*-----------------------------------------------------------------------------------*/
00657 void
00658 ether_send_serial(char *str)
00659 {
00660   struct ether_hdr hdr;
00661   int len;
00662 
00663   
00664   hdr.srcx = node.x;
00665   hdr.srcy = node.y;
00666   hdr.type = PTYPE_SERIAL;
00667   hdr.srcid = node.id;
00668   len = strlen(str) + 1;
00669   if(len > sizeof(hdr.text)) {
00670     len = sizeof(hdr.text);
00671   }
00672   memcpy(&hdr.text, str, len);
00673   hdr.text[len] = 0;
00674 
00675   /*  printf("ether_send_serial '%s' to %d len %d\n", str, nodes_base_node_port, sizeof(struct ether_hdr));*/
00676   
00677   send_packet((char *)&hdr, sizeof(struct ether_hdr), nodes_base_node_port);
00678 }
00679 /*-----------------------------------------------------------------------------------*/
00680 void
00681 ether_set_line(int x, int y)
00682 {
00683   struct ether_hdr hdr;
00684   
00685   linex = x;
00686   liney = y;
00687 
00688   
00689   hdr.srcx = node.x;
00690   hdr.srcy = node.y;
00691   hdr.type = PTYPE_NONE;
00692   hdr.srcid = node.id;
00693   hdr.linex = linex;
00694   hdr.liney = liney;
00695 
00696   node_send_packet((char *)&hdr, sizeof(struct ether_hdr));
00697 }
00698 /*-----------------------------------------------------------------------------------*/

Generated on Mon Apr 11 14:23:44 2011 for Contiki 2.5 by  doxygen 1.6.1