CDC/ECM driver for mbed, based on USBDevice by mbed-official. Uses PicoTCP to access Ethernet USB device. License: GPLv2

Dependents:   USBEthernet_TEST

Fork of USB_Ethernet by Daniele Lacamera

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pico_stack.c Source File

pico_stack.c

00001 /*********************************************************************
00002 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
00003 See LICENSE and COPYING for usage.
00004 
00005 .
00006 
00007 Authors: Daniele Lacamera
00008 *********************************************************************/
00009 
00010 
00011 #include "pico_config.h"
00012 #include "pico_frame.h"
00013 #include "pico_device.h"
00014 #include "pico_protocol.h"
00015 #include "pico_stack.h"
00016 #include "pico_addressing.h"
00017 #include "pico_dns_client.h"
00018 
00019 #include "pico_eth.h"
00020 #include "pico_arp.h"
00021 #include "pico_ipv4.h"
00022 #include "pico_ipv6.h"
00023 #include "pico_icmp4.h"
00024 #include "pico_igmp.h"
00025 #include "pico_udp.h"
00026 #include "pico_tcp.h"
00027 #include "pico_socket.h"
00028 #include "heap.h"
00029 
00030 #define IS_LIMITED_BCAST(f) ( ((struct pico_ipv4_hdr *) f->net_hdr)->dst.addr == PICO_IP4_BCAST )
00031 
00032 #ifdef PICO_SUPPORT_MCAST
00033 # define PICO_SIZE_MCAST 3
00034   const uint8_t PICO_ETHADDR_MCAST[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};
00035 #endif
00036 
00037 volatile unsigned long pico_tick;
00038 volatile pico_err_t pico_err;
00039 
00040 static uint32_t _rand_seed;
00041 
00042 void pico_rand_feed(uint32_t feed)
00043 {
00044   if (!feed)
00045     return;
00046   _rand_seed *= 1664525;
00047   _rand_seed += 1013904223;
00048   _rand_seed ^= ~(feed);
00049 }
00050 
00051 uint32_t pico_rand(void)
00052 {
00053   pico_rand_feed(pico_tick);
00054   return _rand_seed;
00055 }
00056 
00057 /* NOTIFICATIONS: distributed notifications for stack internal errors.
00058  */
00059 
00060 int pico_notify_socket_unreachable(struct pico_frame *f)
00061 {
00062   if (0) {}
00063 #ifdef PICO_SUPPORT_ICMP4 
00064   else if (IS_IPV4(f)) {
00065     pico_icmp4_port_unreachable(f);
00066   }
00067 #endif
00068 #ifdef PICO_SUPPORT_ICMP6 
00069   else if (IS_IPV6(f)) {
00070     pico_icmp6_port_unreachable(f);
00071   }
00072 #endif
00073 
00074   return 0;
00075 }
00076 
00077 int pico_notify_proto_unreachable(struct pico_frame *f)
00078 {
00079   if (0) {}
00080 #ifdef PICO_SUPPORT_ICMP4 
00081   else if (IS_IPV4(f)) {
00082     pico_icmp4_proto_unreachable(f);
00083   }
00084 #endif
00085 #ifdef PICO_SUPPORT_ICMP6 
00086   else if (IS_IPV6(f)) {
00087     pico_icmp6_proto_unreachable(f);
00088   }
00089 #endif
00090   return 0;
00091 }
00092 
00093 int pico_notify_dest_unreachable(struct pico_frame *f)
00094 {
00095   if (0) {}
00096 #ifdef PICO_SUPPORT_ICMP4 
00097   else if (IS_IPV4(f)) {
00098     pico_icmp4_dest_unreachable(f);
00099   }
00100 #endif
00101 #ifdef PICO_SUPPORT_ICMP6 
00102   else if (IS_IPV6(f)) {
00103     pico_icmp6_dest_unreachable(f);
00104   }
00105 #endif
00106   return 0;
00107 }
00108 
00109 int pico_notify_ttl_expired(struct pico_frame *f)
00110 {
00111   if (0) {}
00112 #ifdef PICO_SUPPORT_ICMP4 
00113   else if (IS_IPV4(f)) {
00114     pico_icmp4_ttl_expired(f);
00115   }
00116 #endif
00117 #ifdef PICO_SUPPORT_ICMP6 
00118   else if (IS_IPV6(f)) {
00119     pico_icmp6_ttl_expired(f);
00120   }
00121 #endif
00122   return 0;
00123 }
00124 
00125 
00126 /* Transport layer */
00127 int pico_transport_receive(struct pico_frame *f, uint8_t proto)
00128 {
00129   int ret = -1;
00130   switch (proto) {
00131 
00132 #ifdef PICO_SUPPORT_ICMP4
00133   case PICO_PROTO_ICMP4:
00134     ret = pico_enqueue(pico_proto_icmp4.q_in, f);
00135     break;
00136 #endif
00137 
00138 #ifdef PICO_SUPPORT_IGMP
00139   case PICO_PROTO_IGMP:
00140     ret = pico_enqueue(pico_proto_igmp.q_in, f);
00141     break;
00142 #endif
00143 
00144 #ifdef PICO_SUPPORT_UDP
00145   case PICO_PROTO_UDP:
00146     ret = pico_enqueue(pico_proto_udp.q_in, f);
00147     break;
00148 #endif
00149 
00150 #ifdef PICO_SUPPORT_TCP
00151   case PICO_PROTO_TCP:
00152     ret = pico_enqueue(pico_proto_tcp.q_in, f);
00153     break;
00154 #endif
00155 
00156   default:
00157     /* Protocol not available */
00158     dbg("pkt: no such protocol (%d)\n", proto);
00159     pico_notify_proto_unreachable(f);
00160     pico_frame_discard(f);
00161     ret = -1;
00162  }
00163  return ret;
00164 }
00165 
00166 int pico_transport_send(struct pico_frame *f)
00167 {
00168   if (!f || !f->sock || !f->sock->proto) {
00169     pico_frame_discard(f);
00170     return -1;
00171   }
00172   return f->sock->proto->push(f->sock->net, f);
00173 }
00174 
00175 int pico_network_receive(struct pico_frame *f)
00176 {
00177   if (0) {}
00178 #ifdef PICO_SUPPORT_IPV4
00179   else if (IS_IPV4(f)) {
00180     pico_enqueue(pico_proto_ipv4.q_in, f);
00181   }
00182 #endif
00183 #ifdef PICO_SUPPORT_IPV6
00184   else if (IS_IPV6(f)) {
00185     pico_enqueue(pico_proto_ipv6.q_in, f);
00186   }
00187 #endif
00188   else {
00189     dbg("Network not found.\n");
00190     pico_frame_discard(f);
00191     return -1;
00192   }
00193   return f->buffer_len;
00194 }
00195 
00196 
00197 /* Network layer: interface towards socket for frame sending */
00198 int pico_network_send(struct pico_frame *f)
00199 {
00200   if (!f || !f->sock || !f->sock->net) {
00201     pico_frame_discard(f);
00202     return -1;
00203   }
00204   return f->sock->net->push(f->sock->net, f);
00205 }
00206 
00207 int pico_destination_is_local(struct pico_frame *f)
00208 {
00209   if (0) { }
00210 #ifdef PICO_SUPPORT_IPV4
00211   else if (IS_IPV4(f)) {
00212     struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
00213     if (pico_ipv4_link_find(&hdr->dst))
00214       return 1;
00215   }
00216 #endif
00217 #ifdef PICO_SUPPORT_IPV6
00218   else if (IS_IPV6(f)) {
00219   }
00220 #endif
00221   return 0;
00222 }
00223 
00224 int pico_source_is_local(struct pico_frame *f)
00225 {
00226   if (0) { }
00227 #ifdef PICO_SUPPORT_IPV4
00228   else if (IS_IPV4(f)) {
00229     struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
00230     if (hdr->src.addr == PICO_IPV4_INADDR_ANY)
00231       return 1;
00232     if (pico_ipv4_link_find(&hdr->src))
00233       return 1;
00234   }
00235 #endif
00236 #ifdef PICO_SUPPORT_IPV6
00237   else if (IS_IPV6(f)) {
00238   /* XXX */
00239   }
00240 #endif
00241   return 0;
00242 
00243 
00244 }
00245 
00246 
00247 /* DATALINK LEVEL: interface from network to the device
00248  * and vice versa.
00249  */
00250 
00251 /* The pico_ethernet_receive() function is used by 
00252  * those devices supporting ETH in order to push packets up 
00253  * into the stack. 
00254  */
00255 int pico_ethernet_receive(struct pico_frame *f)
00256 {
00257   struct pico_eth_hdr *hdr;
00258   if (!f || !f->dev || !f->datalink_hdr)
00259     goto discard;
00260   hdr = (struct pico_eth_hdr *) f->datalink_hdr;
00261   if ( (memcmp(hdr->daddr, f->dev->eth->mac.addr, PICO_SIZE_ETH) != 0) && 
00262 #ifdef PICO_SUPPORT_MCAST
00263     (memcmp(hdr->daddr, PICO_ETHADDR_MCAST, PICO_SIZE_MCAST) != 0) &&
00264 #endif
00265     (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) != 0) ) 
00266     goto discard;
00267 
00268   f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
00269   if (hdr->proto == PICO_IDETH_ARP)
00270     return pico_arp_receive(f);
00271   if ((hdr->proto == PICO_IDETH_IPV4) || (hdr->proto == PICO_IDETH_IPV6))
00272     return pico_network_receive(f);
00273 discard:
00274   pico_frame_discard(f);
00275   return -1;
00276 }
00277 
00278 static int destination_is_bcast(struct pico_frame *f)
00279 {
00280   if (!f)
00281     return 0;
00282 
00283   if (IS_IPV6(f))
00284     return 0;
00285 #ifdef PICO_SUPPORT_IPV4
00286   else {
00287     struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
00288     return pico_ipv4_is_broadcast(hdr->dst.addr);
00289   }
00290 #endif
00291   return 0;
00292 }
00293 
00294 #ifdef PICO_SUPPORT_MCAST
00295 static int destination_is_mcast(struct pico_frame *f)
00296 {
00297   if (!f)
00298     return 0;
00299 
00300   if (IS_IPV6(f))
00301     return 0;
00302 #ifdef PICO_SUPPORT_IPV4
00303   else {
00304     struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
00305     return pico_ipv4_is_multicast(hdr->dst.addr);
00306   }
00307 #endif
00308   return 0;
00309 }
00310 
00311 static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint8_t *pico_mcast_mac)
00312 {
00313   struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
00314 
00315   /* place 23 lower bits of IP in lower 23 bits of MAC */
00316   pico_mcast_mac[5] = (long_be(hdr->dst.addr) & 0x000000FF);
00317   pico_mcast_mac[4] = (long_be(hdr->dst.addr) & 0x0000FF00) >> 8; 
00318   pico_mcast_mac[3] = (long_be(hdr->dst.addr) & 0x007F0000) >> 16;
00319 
00320   return (struct pico_eth *)pico_mcast_mac;
00321 }
00322 
00323 
00324 #endif /* PICO_SUPPORT_MCAST */
00325 
00326 /* This is called by dev loop in order to ensure correct ethernet addressing.
00327  * Returns 0 if the destination is unknown, and -1 if the packet is not deliverable
00328  * due to ethernet addressing (i.e., no arp association was possible. 
00329  *
00330  * Only IP packets must pass by this. ARP will always use direct dev->send() function, so
00331  * we assume IP is used.
00332  */
00333 int pico_ethernet_send(struct pico_frame *f)
00334 {
00335   struct pico_eth *dstmac = NULL;
00336   int ret = -1;
00337 
00338   if (IS_IPV6(f)) {
00339     /*TODO: Neighbor solicitation */
00340     dstmac = NULL;
00341   }
00342 
00343   else if (IS_IPV4(f)) {
00344     if (IS_BCAST(f) || destination_is_bcast(f)) {
00345       dstmac = (struct pico_eth *) PICO_ETHADDR_ALL;
00346     } 
00347 #ifdef PICO_SUPPORT_MCAST
00348     else if (destination_is_mcast(f)) {
00349       uint8_t pico_mcast_mac[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};
00350       dstmac = pico_ethernet_mcast_translate(f, pico_mcast_mac);
00351     } 
00352 #endif
00353     else {
00354       dstmac = pico_arp_get(f);
00355       if (!dstmac)
00356         return 0;
00357     }
00358     /* This sets destination and source address, then pushes the packet to the device. */
00359     if (dstmac && (f->start > f->buffer) && ((f->start - f->buffer) >= PICO_SIZE_ETHHDR)) {
00360       struct pico_eth_hdr *hdr;
00361       f->start -= PICO_SIZE_ETHHDR;
00362       f->len += PICO_SIZE_ETHHDR;
00363       f->datalink_hdr = f->start;
00364       hdr = (struct pico_eth_hdr *) f->datalink_hdr;
00365       memcpy(hdr->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH);
00366       memcpy(hdr->daddr, dstmac, PICO_SIZE_ETH);
00367       hdr->proto = PICO_IDETH_IPV4;
00368       if(!memcmp(hdr->daddr, hdr->saddr, PICO_SIZE_ETH)){
00369         dbg("sending out packet destined for our own mac\n");
00370       return pico_ethernet_receive(f);
00371       }else if(IS_LIMITED_BCAST(f)){
00372         ret = pico_device_broadcast(f);
00373       }else {
00374         ret = f->dev->send(f->dev, f->start, f->len);
00375         /* Frame is discarded after this return by the caller */
00376       }
00377 
00378       if(!ret) pico_frame_discard(f);
00379         return ret;
00380     } else {
00381       return -1;
00382     }
00383   } /* End IPV4 ethernet addressing */
00384   return -1;
00385 
00386 }
00387 
00388 void pico_store_network_origin(void *src, struct pico_frame *f)
00389 {
00390   #ifdef PICO_SUPPORT_IPV4
00391   struct pico_ip4 *ip4;
00392   #endif
00393 
00394   #ifdef PICO_SUPPORT_IPV6
00395   struct pico_ip6 *ip6;
00396   #endif
00397 
00398   #ifdef PICO_SUPPORT_IPV4
00399   if (IS_IPV4(f)) {
00400     struct pico_ipv4_hdr *hdr;
00401     hdr = (struct pico_ipv4_hdr *) f->net_hdr;
00402     ip4 = (struct pico_ip4 *) src;
00403     ip4->addr = hdr->src.addr;
00404   }
00405   #endif
00406   #ifdef PICO_SUPPORT_IPV6
00407   if (IS_IPV6(f)) {
00408     struct pico_ipv6_hdr *hdr;
00409     hdr = (struct pico_ipv6_hdr *) f->net_hdr;
00410     ip6 = (struct pico_ip6 *) src;
00411     memcpy(ip6->addr, hdr->src.addr, PICO_SIZE_IP6);
00412   }
00413   #endif
00414 }
00415 
00416 
00417 /* LOWEST LEVEL: interface towards devices. */
00418 /* Device driver will call this function which returns immediately.
00419  * Incoming packet will be processed later on in the dev loop.
00420  */
00421 int pico_stack_recv(struct pico_device *dev, uint8_t *buffer, int len)
00422 {
00423   struct pico_frame *f;
00424   int ret;
00425   if (len <= 0)
00426     return -1;
00427   f = pico_frame_alloc(len);
00428   if (!f)
00429     return -1;
00430 
00431   /* Association to the device that just received the frame. */
00432   f->dev = dev;
00433 
00434   /* Setup the start pointer, lenght. */
00435   f->start = f->buffer;
00436   f->len = f->buffer_len;
00437   if (f->len > 8) {
00438     int mid_frame = (f->buffer_len >> 2)<<1;
00439     mid_frame -= (mid_frame % 4);
00440     pico_rand_feed(*(uint32_t*)(f->buffer + mid_frame));
00441   }
00442   memcpy(f->buffer, buffer, len);
00443   ret = pico_enqueue(dev->q_in, f);
00444   if (ret <= 0) {
00445     pico_frame_discard(f);
00446   }
00447   return ret;
00448 }
00449 
00450 int pico_sendto_dev(struct pico_frame *f)
00451 {
00452   if (!f->dev) {
00453     pico_frame_discard(f);
00454     return -1;
00455   } else {
00456     if (f->len > 8) {
00457       int mid_frame = (f->buffer_len >> 2)<<1;
00458       mid_frame -= (mid_frame % 4);
00459       pico_rand_feed(*(uint32_t*)(f->buffer + mid_frame));
00460     }
00461     return pico_enqueue(f->dev->q_out, f);
00462   }
00463 }
00464 
00465 struct pico_timer
00466 {
00467   unsigned long expire;
00468   void *arg;
00469   void (*timer)(unsigned long timestamp, void *arg);
00470 };
00471 
00472 typedef struct pico_timer pico_timer;
00473 
00474 DECLARE_HEAP(pico_timer, expire);
00475 
00476 static heap_pico_timer *Timers;
00477 
00478 void pico_check_timers(void)
00479 {
00480   struct pico_timer timer;
00481   struct pico_timer *t = heap_first(Timers);
00482   pico_tick = PICO_TIME_MS();
00483   while((t) && (t->expire < pico_tick)) {
00484     t->timer(pico_tick, t->arg);
00485     heap_peek(Timers, &timer);
00486     t = heap_first(Timers);
00487   }
00488 }
00489 
00490 
00491 #define PROTO_DEF_NR      11
00492 #define PROTO_DEF_AVG_NR  4
00493 #define PROTO_DEF_SCORE   32
00494 #define PROTO_MIN_SCORE   32
00495 #define PROTO_MAX_SCORE   128
00496 #define PROTO_LAT_IND     3   /* latecy indication 0-3 (lower is better latency performance), x1, x2, x4, x8 */
00497 #define PROTO_MAX_LOOP    (PROTO_MAX_SCORE<<PROTO_LAT_IND) /* max global loop score, so per tick */
00498 
00499 static int calc_score(int *score, int *index, int avg[][PROTO_DEF_AVG_NR], int *ret)
00500 {
00501   int temp, i, j, sum;
00502   int max_total = PROTO_MAX_LOOP, total = 0;
00503 
00504   //dbg("USED SCORES> "); 
00505 
00506   for (i = 0; i < PROTO_DEF_NR; i++) {
00507 
00508     /* if used looped score */
00509     if (ret[i] < score[i]) {
00510       temp = score[i] - ret[i]; /* remaining loop score */
00511       
00512       //dbg("%3d - ",temp);
00513 
00514       if (index[i] >= PROTO_DEF_AVG_NR)
00515         index[i] = 0;           /* reset index */
00516       j = index[i];
00517       avg[i][j] = temp;
00518 
00519       index[i]++; 
00520 
00521       if (ret[i] == 0 && (score[i]<<1 <= PROTO_MAX_SCORE) && ((total+(score[i]<<1)) < max_total) ) {        /* used all loop score -> increase next score directly */
00522         score[i] <<= 1;
00523         total += score[i];
00524         continue;
00525       }
00526 
00527       sum = 0;
00528       for (j = 0; j < PROTO_DEF_AVG_NR; j++)
00529         sum += avg[i][j];       /* calculate sum */
00530 
00531       sum >>= 2;                /* divide by 4 to get average used score */
00532 
00533       /* criterion to increase next loop score */
00534       if (sum > (score[i] - (score[i]>>2))  && (score[i]<<1 <= PROTO_MAX_SCORE) && ((total+(score[i]<<1)) < max_total)) { /* > 3/4 */
00535         score[i] <<= 1;         /* double loop score */
00536         total += score[i];
00537         continue;
00538       }
00539 
00540       /* criterion to decrease next loop score */
00541       if (sum < (score[i]>>2) && (score[i]>>1 >= PROTO_MIN_SCORE)) { /* < 1/4 */
00542         score[i] >>= 1;         /* half loop score */
00543         total += score[i];
00544         continue;
00545       }
00546 
00547       /* also add non-changed scores */
00548       total += score[i];
00549     }
00550     else if (ret[i] == score[i]) {
00551       /* no used loop score - gradually decrease */
00552       
00553     //  dbg("%3d - ",0);
00554 
00555       if (index[i] >= PROTO_DEF_AVG_NR)
00556         index[i] = 0;           /* reset index */
00557       j = index[i];
00558       avg[i][j] = 0;
00559 
00560       index[i]++; 
00561 
00562       sum = 0;
00563       for (j = 0; j < PROTO_DEF_AVG_NR; j++)
00564         sum += avg[i][j];       /* calculate sum */
00565 
00566       sum >>= 2;                /* divide by 4 to get average used score */
00567 
00568       if ((sum == 0) && (score[i]>>1 >= PROTO_MIN_SCORE)) {
00569         score[i] >>= 1;         /* half loop score */
00570         total += score[i];
00571         for (j = 0; j < PROTO_DEF_AVG_NR; j++)
00572           avg[i][j] = score[i];
00573       }
00574       
00575     }
00576   }
00577 
00578   //dbg("\n");
00579 
00580   return 0;
00581 }
00582 
00583 
00584 
00585 /* 
00586 
00587          .                                                               
00588        .vS.                                                              
00589      <aoSo.                                                              
00590     .XoS22.                                                              
00591     .S2S22.             ._...              ......            ..._.       
00592   :=|2S2X2|=++;      <vSX2XX2z+          |vSSSXSSs>.      :iXXZUZXXe=    
00593   )2SS2SS2S2S2I    =oS2S2S2S2X22;.    _vuXS22S2S2S22i  ._wZZXZZZXZZXZX=  
00594   )22S2S2S2S2Sl    |S2S2S22S2SSSXc:  .S2SS2S2S22S2SS= .]#XZZZXZXZZZZZZ:  
00595   )oSS2SS2S2Sol     |2}!"""!32S22S(. uS2S2Se**12oS2e  ]dXZZXX2?YYXXXZ*   
00596    .:2S2So:..-.      .      :]S2S2e;=X2SS2o     .)oc  ]XZZXZ(     =nX:   
00597     .S2S22.          ___s_i,.)oS2So(;2SS2So,       `  3XZZZZc,      -    
00598     .S2SSo.        =oXXXSSS2XoS2S2o( XS2S2XSos;.      ]ZZZZXXXX|=        
00599     .S2S22.      .)S2S2S22S2S2S2S2o( "X2SS2S2S2Sus,,  +3XZZZZZXZZoos_    
00600     .S2S22.     .]2S2SS22S222S2SS2o(  ]S22S2S2S222So   :3XXZZZZZZZZXXv   
00601     .S2S22.     =u2SS2e"~---"{2S2So(   -"12S2S2SSS2Su.   "?SXXXZXZZZZXo  
00602     .S2SSo.     )SS22z;      :S2S2o(       ={vS2S2S22v      .<vXZZZZZZZ; 
00603     .S2S2S:     ]oSS2c;      =22S2o(          -"S2SS2n          ~4XXZXZ( 
00604     .2S2S2i     )2S2S2[.    .)XS2So(  <;.      .2S2S2o :<.       ]XZZZX( 
00605      nX2S2S,,_s_=3oSS2SoaasuXXS2S2o( .oXoasi_aioSSS22l.]dZoaas_aadXZZXZ' 
00606      vS2SSSXXX2; )S2S2S2SoS2S2S2S2o( iS2S222XSoSS22So.)nXZZXXXZZXXZZXZo  
00607      +32S22S2Sn  -+S2S2S2S2So22S2So( 12S2SS2S2SS22S}- )SXXZZZZZZZZZXX!-  
00608       .)S22222i    .i2S2S2o>;:S2S2o(  .<vSoSoSo2S(;     :nXXXXXZXXX(     
00609        .-~~~~-        --- .   - -        --~~~--           --^^~~-       
00610                                   .                                      
00611                                                                          
00612 
00613  ... curious about our source code? We are hiring! mailto:<recruiting@tass.be>
00614 
00615 
00616 */
00617 
00618 void pico_stack_tick(void)
00619 {
00620     static int score[PROTO_DEF_NR] = {PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE, PROTO_DEF_SCORE};
00621     static int index[PROTO_DEF_NR] = {0,0,0,0,0,0};
00622     static int avg[PROTO_DEF_NR][PROTO_DEF_AVG_NR];
00623     static int ret[PROTO_DEF_NR] = {0};
00624 
00625     pico_check_timers();
00626 
00627     //dbg("LOOP_SCORES> %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d - %3d\n",score[0],score[1],score[2],score[3],score[4],score[5],score[6],score[7],score[8],score[9],score[10]);
00628 
00629     //score = pico_protocols_loop(100);
00630 
00631     ret[0] = pico_devices_loop(score[0],PICO_LOOP_DIR_IN);
00632     pico_rand_feed(ret[0]);
00633 
00634     ret[1] = pico_protocol_datalink_loop(score[1], PICO_LOOP_DIR_IN);
00635     pico_rand_feed(ret[1]);
00636 
00637     ret[2] = pico_protocol_network_loop(score[2], PICO_LOOP_DIR_IN);
00638     pico_rand_feed(ret[2]);
00639 
00640     ret[3] = pico_protocol_transport_loop(score[3], PICO_LOOP_DIR_IN);
00641     pico_rand_feed(ret[3]);
00642 
00643 
00644     ret[5] = score[5];
00645 #if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6)
00646 #if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP)
00647     ret[5] = pico_sockets_loop(score[5]); // swapped
00648     pico_rand_feed(ret[5]);
00649 #endif
00650 #endif
00651 
00652     ret[4] = pico_protocol_socket_loop(score[4], PICO_LOOP_DIR_IN);
00653     pico_rand_feed(ret[4]);
00654 
00655 
00656     ret[6] = pico_protocol_socket_loop(score[6], PICO_LOOP_DIR_OUT);
00657     pico_rand_feed(ret[6]);
00658 
00659     ret[7] = pico_protocol_transport_loop(score[7], PICO_LOOP_DIR_OUT);
00660     pico_rand_feed(ret[7]);
00661 
00662     ret[8] = pico_protocol_network_loop(score[8], PICO_LOOP_DIR_OUT);
00663     pico_rand_feed(ret[8]);
00664 
00665     ret[9] = pico_protocol_datalink_loop(score[9], PICO_LOOP_DIR_OUT);
00666     pico_rand_feed(ret[9]);
00667 
00668     ret[10] = pico_devices_loop(score[10],PICO_LOOP_DIR_OUT);
00669     pico_rand_feed(ret[10]);
00670 
00671     /* calculate new loop scores for next iteration */
00672     calc_score(score, index,(int (*)[]) avg, ret);
00673 }
00674 
00675 void pico_stack_loop(void)
00676 {
00677   while(1) {
00678     pico_stack_tick();
00679     PICO_IDLE();
00680   }
00681 }
00682 
00683 void pico_timer_add(unsigned long expire, void (*timer)(unsigned long, void *), void *arg)
00684 {
00685   pico_timer t;
00686   t.expire = PICO_TIME_MS() + expire;
00687   t.arg = arg;
00688   t.timer = timer;
00689   heap_insert(Timers, &t);
00690   if (Timers->n > PICO_MAX_TIMERS) {
00691     dbg("Warning: I have %d timers\n", Timers->n);
00692   }
00693 }
00694 
00695 void pico_stack_init(void)
00696 {
00697 
00698 #ifdef PICO_SUPPORT_IPV4
00699   pico_protocol_init(&pico_proto_ipv4);
00700 #endif
00701 
00702 #ifdef PICO_SUPPORT_IPV6
00703   pico_protocol_init(&pico_proto_ipv6);
00704 #endif
00705 
00706 #ifdef PICO_SUPPORT_ICMP4
00707   pico_protocol_init(&pico_proto_icmp4);
00708 #endif
00709 
00710 #ifdef PICO_SUPPORT_IGMP
00711   pico_protocol_init(&pico_proto_igmp);
00712 #endif
00713 
00714 #ifdef PICO_SUPPORT_UDP
00715   pico_protocol_init(&pico_proto_udp);
00716 #endif
00717 
00718 #ifdef PICO_SUPPORT_TCP
00719   pico_protocol_init(&pico_proto_tcp);
00720 #endif
00721 
00722 #ifdef PICO_SUPPORT_DNS_CLIENT
00723   pico_dns_client_init();
00724 #endif
00725 
00726   pico_rand_feed(123456);
00727 
00728   /* Initialize timer heap */
00729   Timers = heap_init();
00730   pico_stack_tick();
00731   pico_stack_tick();
00732   pico_stack_tick();
00733 }
00734