Daniele Lacamera / PicoTCP-Experimental_CDC_ECM_Branch

Fork of PicoTCP by Daniele Lacamera

Committer:
daniele
Date:
Thu Jun 06 00:38:54 2013 +0000
Revision:
10:dd7111d4279f
Child:
23:884f327c3647
Child:
40:c8ab0d2bba0b
Update from masterbranch;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 10:dd7111d4279f 1 /*********************************************************************
daniele 10:dd7111d4279f 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 10:dd7111d4279f 3 See LICENSE and COPYING for usage.
daniele 10:dd7111d4279f 4
daniele 10:dd7111d4279f 5 .
daniele 10:dd7111d4279f 6
daniele 10:dd7111d4279f 7 Authors: Daniele Lacamera
daniele 10:dd7111d4279f 8 *********************************************************************/
daniele 10:dd7111d4279f 9
daniele 10:dd7111d4279f 10
daniele 10:dd7111d4279f 11 #include "pico_config.h"
daniele 10:dd7111d4279f 12 #include "pico_frame.h"
daniele 10:dd7111d4279f 13 #include "pico_device.h"
daniele 10:dd7111d4279f 14 #include "pico_protocol.h"
daniele 10:dd7111d4279f 15 #include "pico_stack.h"
daniele 10:dd7111d4279f 16 #include "pico_addressing.h"
daniele 10:dd7111d4279f 17 #include "pico_dns_client.h"
daniele 10:dd7111d4279f 18
daniele 10:dd7111d4279f 19 #include "pico_eth.h"
daniele 10:dd7111d4279f 20 #include "pico_arp.h"
daniele 10:dd7111d4279f 21 #include "pico_ipv4.h"
daniele 10:dd7111d4279f 22 #include "pico_ipv6.h"
daniele 10:dd7111d4279f 23 #include "pico_icmp4.h"
daniele 10:dd7111d4279f 24 #include "pico_igmp.h"
daniele 10:dd7111d4279f 25 #include "pico_udp.h"
daniele 10:dd7111d4279f 26 #include "pico_tcp.h"
daniele 10:dd7111d4279f 27 #include "pico_socket.h"
daniele 10:dd7111d4279f 28 #include "heap.h"
daniele 10:dd7111d4279f 29
daniele 10:dd7111d4279f 30 #define IS_LIMITED_BCAST(f) ( ((struct pico_ipv4_hdr *) f->net_hdr)->dst.addr == PICO_IP4_BCAST )
daniele 10:dd7111d4279f 31
daniele 10:dd7111d4279f 32 #ifdef PICO_SUPPORT_MCAST
daniele 10:dd7111d4279f 33 # define PICO_SIZE_MCAST 3
daniele 10:dd7111d4279f 34 const uint8_t PICO_ETHADDR_MCAST[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};
daniele 10:dd7111d4279f 35 #endif
daniele 10:dd7111d4279f 36
daniele 10:dd7111d4279f 37 volatile unsigned long pico_tick;
daniele 10:dd7111d4279f 38 volatile pico_err_t pico_err;
daniele 10:dd7111d4279f 39
daniele 10:dd7111d4279f 40 static uint32_t _rand_seed;
daniele 10:dd7111d4279f 41
daniele 10:dd7111d4279f 42 void pico_rand_feed(uint32_t feed)
daniele 10:dd7111d4279f 43 {
daniele 10:dd7111d4279f 44 if (!feed)
daniele 10:dd7111d4279f 45 return;
daniele 10:dd7111d4279f 46 _rand_seed *= 1664525;
daniele 10:dd7111d4279f 47 _rand_seed += 1013904223;
daniele 10:dd7111d4279f 48 _rand_seed ^= ~(feed);
daniele 10:dd7111d4279f 49 }
daniele 10:dd7111d4279f 50
daniele 10:dd7111d4279f 51 uint32_t pico_rand(void)
daniele 10:dd7111d4279f 52 {
daniele 10:dd7111d4279f 53 pico_rand_feed(pico_tick);
daniele 10:dd7111d4279f 54 return _rand_seed;
daniele 10:dd7111d4279f 55 }
daniele 10:dd7111d4279f 56
daniele 10:dd7111d4279f 57 /* NOTIFICATIONS: distributed notifications for stack internal errors.
daniele 10:dd7111d4279f 58 */
daniele 10:dd7111d4279f 59
daniele 10:dd7111d4279f 60 int pico_notify_socket_unreachable(struct pico_frame *f)
daniele 10:dd7111d4279f 61 {
daniele 10:dd7111d4279f 62 if (0) {}
daniele 10:dd7111d4279f 63 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 64 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 65 pico_icmp4_port_unreachable(f);
daniele 10:dd7111d4279f 66 }
daniele 10:dd7111d4279f 67 #endif
daniele 10:dd7111d4279f 68 #ifdef PICO_SUPPORT_ICMP6
daniele 10:dd7111d4279f 69 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 70 pico_icmp6_port_unreachable(f);
daniele 10:dd7111d4279f 71 }
daniele 10:dd7111d4279f 72 #endif
daniele 10:dd7111d4279f 73
daniele 10:dd7111d4279f 74 return 0;
daniele 10:dd7111d4279f 75 }
daniele 10:dd7111d4279f 76
daniele 10:dd7111d4279f 77 int pico_notify_proto_unreachable(struct pico_frame *f)
daniele 10:dd7111d4279f 78 {
daniele 10:dd7111d4279f 79 if (0) {}
daniele 10:dd7111d4279f 80 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 81 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 82 pico_icmp4_proto_unreachable(f);
daniele 10:dd7111d4279f 83 }
daniele 10:dd7111d4279f 84 #endif
daniele 10:dd7111d4279f 85 #ifdef PICO_SUPPORT_ICMP6
daniele 10:dd7111d4279f 86 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 87 pico_icmp6_proto_unreachable(f);
daniele 10:dd7111d4279f 88 }
daniele 10:dd7111d4279f 89 #endif
daniele 10:dd7111d4279f 90 return 0;
daniele 10:dd7111d4279f 91 }
daniele 10:dd7111d4279f 92
daniele 10:dd7111d4279f 93 int pico_notify_dest_unreachable(struct pico_frame *f)
daniele 10:dd7111d4279f 94 {
daniele 10:dd7111d4279f 95 if (0) {}
daniele 10:dd7111d4279f 96 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 97 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 98 pico_icmp4_dest_unreachable(f);
daniele 10:dd7111d4279f 99 }
daniele 10:dd7111d4279f 100 #endif
daniele 10:dd7111d4279f 101 #ifdef PICO_SUPPORT_ICMP6
daniele 10:dd7111d4279f 102 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 103 pico_icmp6_dest_unreachable(f);
daniele 10:dd7111d4279f 104 }
daniele 10:dd7111d4279f 105 #endif
daniele 10:dd7111d4279f 106 return 0;
daniele 10:dd7111d4279f 107 }
daniele 10:dd7111d4279f 108
daniele 10:dd7111d4279f 109 int pico_notify_ttl_expired(struct pico_frame *f)
daniele 10:dd7111d4279f 110 {
daniele 10:dd7111d4279f 111 if (0) {}
daniele 10:dd7111d4279f 112 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 113 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 114 pico_icmp4_ttl_expired(f);
daniele 10:dd7111d4279f 115 }
daniele 10:dd7111d4279f 116 #endif
daniele 10:dd7111d4279f 117 #ifdef PICO_SUPPORT_ICMP6
daniele 10:dd7111d4279f 118 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 119 pico_icmp6_ttl_expired(f);
daniele 10:dd7111d4279f 120 }
daniele 10:dd7111d4279f 121 #endif
daniele 10:dd7111d4279f 122 return 0;
daniele 10:dd7111d4279f 123 }
daniele 10:dd7111d4279f 124
daniele 10:dd7111d4279f 125
daniele 10:dd7111d4279f 126 /* Transport layer */
daniele 10:dd7111d4279f 127 int pico_transport_receive(struct pico_frame *f, uint8_t proto)
daniele 10:dd7111d4279f 128 {
daniele 10:dd7111d4279f 129 int ret = -1;
daniele 10:dd7111d4279f 130 switch (proto) {
daniele 10:dd7111d4279f 131
daniele 10:dd7111d4279f 132 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 133 case PICO_PROTO_ICMP4:
daniele 10:dd7111d4279f 134 ret = pico_enqueue(pico_proto_icmp4.q_in, f);
daniele 10:dd7111d4279f 135 break;
daniele 10:dd7111d4279f 136 #endif
daniele 10:dd7111d4279f 137
daniele 10:dd7111d4279f 138 #ifdef PICO_SUPPORT_IGMP
daniele 10:dd7111d4279f 139 case PICO_PROTO_IGMP:
daniele 10:dd7111d4279f 140 ret = pico_enqueue(pico_proto_igmp.q_in, f);
daniele 10:dd7111d4279f 141 break;
daniele 10:dd7111d4279f 142 #endif
daniele 10:dd7111d4279f 143
daniele 10:dd7111d4279f 144 #ifdef PICO_SUPPORT_UDP
daniele 10:dd7111d4279f 145 case PICO_PROTO_UDP:
daniele 10:dd7111d4279f 146 ret = pico_enqueue(pico_proto_udp.q_in, f);
daniele 10:dd7111d4279f 147 break;
daniele 10:dd7111d4279f 148 #endif
daniele 10:dd7111d4279f 149
daniele 10:dd7111d4279f 150 #ifdef PICO_SUPPORT_TCP
daniele 10:dd7111d4279f 151 case PICO_PROTO_TCP:
daniele 10:dd7111d4279f 152 ret = pico_enqueue(pico_proto_tcp.q_in, f);
daniele 10:dd7111d4279f 153 break;
daniele 10:dd7111d4279f 154 #endif
daniele 10:dd7111d4279f 155
daniele 10:dd7111d4279f 156 default:
daniele 10:dd7111d4279f 157 /* Protocol not available */
daniele 10:dd7111d4279f 158 dbg("pkt: no such protocol (%d)\n", proto);
daniele 10:dd7111d4279f 159 pico_notify_proto_unreachable(f);
daniele 10:dd7111d4279f 160 pico_frame_discard(f);
daniele 10:dd7111d4279f 161 ret = -1;
daniele 10:dd7111d4279f 162 }
daniele 10:dd7111d4279f 163 return ret;
daniele 10:dd7111d4279f 164 }
daniele 10:dd7111d4279f 165
daniele 10:dd7111d4279f 166 int pico_transport_send(struct pico_frame *f)
daniele 10:dd7111d4279f 167 {
daniele 10:dd7111d4279f 168 if (!f || !f->sock || !f->sock->proto) {
daniele 10:dd7111d4279f 169 pico_frame_discard(f);
daniele 10:dd7111d4279f 170 return -1;
daniele 10:dd7111d4279f 171 }
daniele 10:dd7111d4279f 172 return f->sock->proto->push(f->sock->net, f);
daniele 10:dd7111d4279f 173 }
daniele 10:dd7111d4279f 174
daniele 10:dd7111d4279f 175 int pico_network_receive(struct pico_frame *f)
daniele 10:dd7111d4279f 176 {
daniele 10:dd7111d4279f 177 if (0) {}
daniele 10:dd7111d4279f 178 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 179 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 180 pico_enqueue(pico_proto_ipv4.q_in, f);
daniele 10:dd7111d4279f 181 }
daniele 10:dd7111d4279f 182 #endif
daniele 10:dd7111d4279f 183 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 184 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 185 pico_enqueue(pico_proto_ipv6.q_in, f);
daniele 10:dd7111d4279f 186 }
daniele 10:dd7111d4279f 187 #endif
daniele 10:dd7111d4279f 188 else {
daniele 10:dd7111d4279f 189 dbg("Network not found.\n");
daniele 10:dd7111d4279f 190 pico_frame_discard(f);
daniele 10:dd7111d4279f 191 return -1;
daniele 10:dd7111d4279f 192 }
daniele 10:dd7111d4279f 193 return f->buffer_len;
daniele 10:dd7111d4279f 194 }
daniele 10:dd7111d4279f 195
daniele 10:dd7111d4279f 196
daniele 10:dd7111d4279f 197 /* Network layer: interface towards socket for frame sending */
daniele 10:dd7111d4279f 198 int pico_network_send(struct pico_frame *f)
daniele 10:dd7111d4279f 199 {
daniele 10:dd7111d4279f 200 if (!f || !f->sock || !f->sock->net) {
daniele 10:dd7111d4279f 201 pico_frame_discard(f);
daniele 10:dd7111d4279f 202 return -1;
daniele 10:dd7111d4279f 203 }
daniele 10:dd7111d4279f 204 return f->sock->net->push(f->sock->net, f);
daniele 10:dd7111d4279f 205 }
daniele 10:dd7111d4279f 206
daniele 10:dd7111d4279f 207 int pico_destination_is_local(struct pico_frame *f)
daniele 10:dd7111d4279f 208 {
daniele 10:dd7111d4279f 209 if (0) { }
daniele 10:dd7111d4279f 210 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 211 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 212 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
daniele 10:dd7111d4279f 213 if (pico_ipv4_link_find(&hdr->dst))
daniele 10:dd7111d4279f 214 return 1;
daniele 10:dd7111d4279f 215 }
daniele 10:dd7111d4279f 216 #endif
daniele 10:dd7111d4279f 217 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 218 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 219 }
daniele 10:dd7111d4279f 220 #endif
daniele 10:dd7111d4279f 221 return 0;
daniele 10:dd7111d4279f 222 }
daniele 10:dd7111d4279f 223
daniele 10:dd7111d4279f 224 int pico_source_is_local(struct pico_frame *f)
daniele 10:dd7111d4279f 225 {
daniele 10:dd7111d4279f 226 if (0) { }
daniele 10:dd7111d4279f 227 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 228 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 229 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
daniele 10:dd7111d4279f 230 if (hdr->src.addr == PICO_IPV4_INADDR_ANY)
daniele 10:dd7111d4279f 231 return 1;
daniele 10:dd7111d4279f 232 if (pico_ipv4_link_find(&hdr->src))
daniele 10:dd7111d4279f 233 return 1;
daniele 10:dd7111d4279f 234 }
daniele 10:dd7111d4279f 235 #endif
daniele 10:dd7111d4279f 236 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 237 else if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 238 /* XXX */
daniele 10:dd7111d4279f 239 }
daniele 10:dd7111d4279f 240 #endif
daniele 10:dd7111d4279f 241 return 0;
daniele 10:dd7111d4279f 242
daniele 10:dd7111d4279f 243
daniele 10:dd7111d4279f 244 }
daniele 10:dd7111d4279f 245
daniele 10:dd7111d4279f 246
daniele 10:dd7111d4279f 247 /* DATALINK LEVEL: interface from network to the device
daniele 10:dd7111d4279f 248 * and vice versa.
daniele 10:dd7111d4279f 249 */
daniele 10:dd7111d4279f 250
daniele 10:dd7111d4279f 251 /* The pico_ethernet_receive() function is used by
daniele 10:dd7111d4279f 252 * those devices supporting ETH in order to push packets up
daniele 10:dd7111d4279f 253 * into the stack.
daniele 10:dd7111d4279f 254 */
daniele 10:dd7111d4279f 255 int pico_ethernet_receive(struct pico_frame *f)
daniele 10:dd7111d4279f 256 {
daniele 10:dd7111d4279f 257 struct pico_eth_hdr *hdr;
daniele 10:dd7111d4279f 258 if (!f || !f->dev || !f->datalink_hdr)
daniele 10:dd7111d4279f 259 goto discard;
daniele 10:dd7111d4279f 260 hdr = (struct pico_eth_hdr *) f->datalink_hdr;
daniele 10:dd7111d4279f 261 if ( (memcmp(hdr->daddr, f->dev->eth->mac.addr, PICO_SIZE_ETH) != 0) &&
daniele 10:dd7111d4279f 262 #ifdef PICO_SUPPORT_MCAST
daniele 10:dd7111d4279f 263 (memcmp(hdr->daddr, PICO_ETHADDR_MCAST, PICO_SIZE_MCAST) != 0) &&
daniele 10:dd7111d4279f 264 #endif
daniele 10:dd7111d4279f 265 (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) != 0) )
daniele 10:dd7111d4279f 266 goto discard;
daniele 10:dd7111d4279f 267
daniele 10:dd7111d4279f 268 f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
daniele 10:dd7111d4279f 269 if (hdr->proto == PICO_IDETH_ARP)
daniele 10:dd7111d4279f 270 return pico_arp_receive(f);
daniele 10:dd7111d4279f 271 if ((hdr->proto == PICO_IDETH_IPV4) || (hdr->proto == PICO_IDETH_IPV6))
daniele 10:dd7111d4279f 272 return pico_network_receive(f);
daniele 10:dd7111d4279f 273 discard:
daniele 10:dd7111d4279f 274 pico_frame_discard(f);
daniele 10:dd7111d4279f 275 return -1;
daniele 10:dd7111d4279f 276 }
daniele 10:dd7111d4279f 277
daniele 10:dd7111d4279f 278 static int destination_is_bcast(struct pico_frame *f)
daniele 10:dd7111d4279f 279 {
daniele 10:dd7111d4279f 280 if (!f)
daniele 10:dd7111d4279f 281 return 0;
daniele 10:dd7111d4279f 282
daniele 10:dd7111d4279f 283 if (IS_IPV6(f))
daniele 10:dd7111d4279f 284 return 0;
daniele 10:dd7111d4279f 285 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 286 else {
daniele 10:dd7111d4279f 287 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 10:dd7111d4279f 288 return pico_ipv4_is_broadcast(hdr->dst.addr);
daniele 10:dd7111d4279f 289 }
daniele 10:dd7111d4279f 290 #endif
daniele 10:dd7111d4279f 291 return 0;
daniele 10:dd7111d4279f 292 }
daniele 10:dd7111d4279f 293
daniele 10:dd7111d4279f 294 #ifdef PICO_SUPPORT_MCAST
daniele 10:dd7111d4279f 295 static int destination_is_mcast(struct pico_frame *f)
daniele 10:dd7111d4279f 296 {
daniele 10:dd7111d4279f 297 if (!f)
daniele 10:dd7111d4279f 298 return 0;
daniele 10:dd7111d4279f 299
daniele 10:dd7111d4279f 300 if (IS_IPV6(f))
daniele 10:dd7111d4279f 301 return 0;
daniele 10:dd7111d4279f 302 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 303 else {
daniele 10:dd7111d4279f 304 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 10:dd7111d4279f 305 return pico_ipv4_is_multicast(hdr->dst.addr);
daniele 10:dd7111d4279f 306 }
daniele 10:dd7111d4279f 307 #endif
daniele 10:dd7111d4279f 308 return 0;
daniele 10:dd7111d4279f 309 }
daniele 10:dd7111d4279f 310
daniele 10:dd7111d4279f 311 static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint8_t *pico_mcast_mac)
daniele 10:dd7111d4279f 312 {
daniele 10:dd7111d4279f 313 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 10:dd7111d4279f 314
daniele 10:dd7111d4279f 315 /* place 23 lower bits of IP in lower 23 bits of MAC */
daniele 10:dd7111d4279f 316 pico_mcast_mac[5] = (long_be(hdr->dst.addr) & 0x000000FF);
daniele 10:dd7111d4279f 317 pico_mcast_mac[4] = (long_be(hdr->dst.addr) & 0x0000FF00) >> 8;
daniele 10:dd7111d4279f 318 pico_mcast_mac[3] = (long_be(hdr->dst.addr) & 0x007F0000) >> 16;
daniele 10:dd7111d4279f 319
daniele 10:dd7111d4279f 320 return (struct pico_eth *)pico_mcast_mac;
daniele 10:dd7111d4279f 321 }
daniele 10:dd7111d4279f 322
daniele 10:dd7111d4279f 323
daniele 10:dd7111d4279f 324 #endif /* PICO_SUPPORT_MCAST */
daniele 10:dd7111d4279f 325
daniele 10:dd7111d4279f 326 /* This is called by dev loop in order to ensure correct ethernet addressing.
daniele 10:dd7111d4279f 327 * Returns 0 if the destination is unknown, and -1 if the packet is not deliverable
daniele 10:dd7111d4279f 328 * due to ethernet addressing (i.e., no arp association was possible.
daniele 10:dd7111d4279f 329 *
daniele 10:dd7111d4279f 330 * Only IP packets must pass by this. ARP will always use direct dev->send() function, so
daniele 10:dd7111d4279f 331 * we assume IP is used.
daniele 10:dd7111d4279f 332 */
daniele 10:dd7111d4279f 333 int pico_ethernet_send(struct pico_frame *f)
daniele 10:dd7111d4279f 334 {
daniele 10:dd7111d4279f 335 struct pico_eth *dstmac = NULL;
daniele 10:dd7111d4279f 336
daniele 10:dd7111d4279f 337 if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 338 /*TODO: Neighbor solicitation */
daniele 10:dd7111d4279f 339 dstmac = NULL;
daniele 10:dd7111d4279f 340 }
daniele 10:dd7111d4279f 341
daniele 10:dd7111d4279f 342 else if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 343 if (IS_BCAST(f) || destination_is_bcast(f)) {
daniele 10:dd7111d4279f 344 dstmac = (struct pico_eth *) PICO_ETHADDR_ALL;
daniele 10:dd7111d4279f 345 }
daniele 10:dd7111d4279f 346 #ifdef PICO_SUPPORT_MCAST
daniele 10:dd7111d4279f 347 else if (destination_is_mcast(f)) {
daniele 10:dd7111d4279f 348 uint8_t pico_mcast_mac[6] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x00};
daniele 10:dd7111d4279f 349 dstmac = pico_ethernet_mcast_translate(f, pico_mcast_mac);
daniele 10:dd7111d4279f 350 }
daniele 10:dd7111d4279f 351 #endif
daniele 10:dd7111d4279f 352 else {
daniele 10:dd7111d4279f 353 dstmac = pico_arp_get(f);
daniele 10:dd7111d4279f 354 if (!dstmac)
daniele 10:dd7111d4279f 355 return 0;
daniele 10:dd7111d4279f 356 }
daniele 10:dd7111d4279f 357 /* This sets destination and source address, then pushes the packet to the device. */
daniele 10:dd7111d4279f 358 if (dstmac && (f->start > f->buffer) && ((f->start - f->buffer) >= PICO_SIZE_ETHHDR)) {
daniele 10:dd7111d4279f 359 struct pico_eth_hdr *hdr;
daniele 10:dd7111d4279f 360 f->start -= PICO_SIZE_ETHHDR;
daniele 10:dd7111d4279f 361 f->len += PICO_SIZE_ETHHDR;
daniele 10:dd7111d4279f 362 f->datalink_hdr = f->start;
daniele 10:dd7111d4279f 363 hdr = (struct pico_eth_hdr *) f->datalink_hdr;
daniele 10:dd7111d4279f 364 memcpy(hdr->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH);
daniele 10:dd7111d4279f 365 memcpy(hdr->daddr, dstmac, PICO_SIZE_ETH);
daniele 10:dd7111d4279f 366 hdr->proto = PICO_IDETH_IPV4;
daniele 10:dd7111d4279f 367 if(!memcmp(hdr->daddr, hdr->saddr, PICO_SIZE_ETH)){
daniele 10:dd7111d4279f 368 dbg("sending out packet destined for our own mac\n");
daniele 10:dd7111d4279f 369 return pico_ethernet_receive(f);
daniele 10:dd7111d4279f 370 }else if(IS_LIMITED_BCAST(f)){
daniele 10:dd7111d4279f 371 return pico_device_broadcast(f);
daniele 10:dd7111d4279f 372 }else {
daniele 10:dd7111d4279f 373 return f->dev->send(f->dev, f->start, f->len);
daniele 10:dd7111d4279f 374 /* Frame is discarded after this return by the caller */
daniele 10:dd7111d4279f 375 }
daniele 10:dd7111d4279f 376 } else {
daniele 10:dd7111d4279f 377 return -1;
daniele 10:dd7111d4279f 378 }
daniele 10:dd7111d4279f 379 } /* End IPV4 ethernet addressing */
daniele 10:dd7111d4279f 380 return -1;
daniele 10:dd7111d4279f 381 }
daniele 10:dd7111d4279f 382
daniele 10:dd7111d4279f 383 void pico_store_network_origin(void *src, struct pico_frame *f)
daniele 10:dd7111d4279f 384 {
daniele 10:dd7111d4279f 385 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 386 struct pico_ip4 *ip4;
daniele 10:dd7111d4279f 387 #endif
daniele 10:dd7111d4279f 388
daniele 10:dd7111d4279f 389 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 390 struct pico_ip6 *ip6;
daniele 10:dd7111d4279f 391 #endif
daniele 10:dd7111d4279f 392
daniele 10:dd7111d4279f 393 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 394 if (IS_IPV4(f)) {
daniele 10:dd7111d4279f 395 struct pico_ipv4_hdr *hdr;
daniele 10:dd7111d4279f 396 hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 10:dd7111d4279f 397 ip4 = (struct pico_ip4 *) src;
daniele 10:dd7111d4279f 398 ip4->addr = hdr->src.addr;
daniele 10:dd7111d4279f 399 }
daniele 10:dd7111d4279f 400 #endif
daniele 10:dd7111d4279f 401 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 402 if (IS_IPV6(f)) {
daniele 10:dd7111d4279f 403 struct pico_ipv6_hdr *hdr;
daniele 10:dd7111d4279f 404 hdr = (struct pico_ipv6_hdr *) f->net_hdr;
daniele 10:dd7111d4279f 405 ip6 = (struct pico_ip6 *) src;
daniele 10:dd7111d4279f 406 memcpy(ip6->addr, hdr->src.addr, PICO_SIZE_IP6);
daniele 10:dd7111d4279f 407 }
daniele 10:dd7111d4279f 408 #endif
daniele 10:dd7111d4279f 409 }
daniele 10:dd7111d4279f 410
daniele 10:dd7111d4279f 411
daniele 10:dd7111d4279f 412 /* LOWEST LEVEL: interface towards devices. */
daniele 10:dd7111d4279f 413 /* Device driver will call this function which returns immediately.
daniele 10:dd7111d4279f 414 * Incoming packet will be processed later on in the dev loop.
daniele 10:dd7111d4279f 415 */
daniele 10:dd7111d4279f 416 int pico_stack_recv(struct pico_device *dev, uint8_t *buffer, int len)
daniele 10:dd7111d4279f 417 {
daniele 10:dd7111d4279f 418 struct pico_frame *f;
daniele 10:dd7111d4279f 419 int ret;
daniele 10:dd7111d4279f 420 if (len <= 0)
daniele 10:dd7111d4279f 421 return -1;
daniele 10:dd7111d4279f 422 f = pico_frame_alloc(len);
daniele 10:dd7111d4279f 423 if (!f)
daniele 10:dd7111d4279f 424 return -1;
daniele 10:dd7111d4279f 425
daniele 10:dd7111d4279f 426 /* Association to the device that just received the frame. */
daniele 10:dd7111d4279f 427 f->dev = dev;
daniele 10:dd7111d4279f 428
daniele 10:dd7111d4279f 429 /* Setup the start pointer, lenght. */
daniele 10:dd7111d4279f 430 f->start = f->buffer;
daniele 10:dd7111d4279f 431 f->len = f->buffer_len;
daniele 10:dd7111d4279f 432 if (f->len > 8) {
daniele 10:dd7111d4279f 433 int mid_frame = (f->buffer_len >> 2)<<1;
daniele 10:dd7111d4279f 434 mid_frame -= (mid_frame % 4);
daniele 10:dd7111d4279f 435 pico_rand_feed(*(uint32_t*)(f->buffer + mid_frame));
daniele 10:dd7111d4279f 436 }
daniele 10:dd7111d4279f 437 memcpy(f->buffer, buffer, len);
daniele 10:dd7111d4279f 438 ret = pico_enqueue(dev->q_in, f);
daniele 10:dd7111d4279f 439 if (ret <= 0) {
daniele 10:dd7111d4279f 440 pico_frame_discard(f);
daniele 10:dd7111d4279f 441 }
daniele 10:dd7111d4279f 442 return ret;
daniele 10:dd7111d4279f 443 }
daniele 10:dd7111d4279f 444
daniele 10:dd7111d4279f 445 int pico_sendto_dev(struct pico_frame *f)
daniele 10:dd7111d4279f 446 {
daniele 10:dd7111d4279f 447 if (!f->dev) {
daniele 10:dd7111d4279f 448 pico_frame_discard(f);
daniele 10:dd7111d4279f 449 return -1;
daniele 10:dd7111d4279f 450 } else {
daniele 10:dd7111d4279f 451 if (f->len > 8) {
daniele 10:dd7111d4279f 452 int mid_frame = (f->buffer_len >> 2)<<1;
daniele 10:dd7111d4279f 453 mid_frame -= (mid_frame % 4);
daniele 10:dd7111d4279f 454 pico_rand_feed(*(uint32_t*)(f->buffer + mid_frame));
daniele 10:dd7111d4279f 455 }
daniele 10:dd7111d4279f 456 return pico_enqueue(f->dev->q_out, f);
daniele 10:dd7111d4279f 457 }
daniele 10:dd7111d4279f 458 }
daniele 10:dd7111d4279f 459
daniele 10:dd7111d4279f 460 struct pico_timer
daniele 10:dd7111d4279f 461 {
daniele 10:dd7111d4279f 462 unsigned long expire;
daniele 10:dd7111d4279f 463 void *arg;
daniele 10:dd7111d4279f 464 void (*timer)(unsigned long timestamp, void *arg);
daniele 10:dd7111d4279f 465 };
daniele 10:dd7111d4279f 466
daniele 10:dd7111d4279f 467 typedef struct pico_timer pico_timer;
daniele 10:dd7111d4279f 468
daniele 10:dd7111d4279f 469 DECLARE_HEAP(pico_timer, expire);
daniele 10:dd7111d4279f 470
daniele 10:dd7111d4279f 471 static heap_pico_timer *Timers;
daniele 10:dd7111d4279f 472
daniele 10:dd7111d4279f 473 void pico_check_timers(void)
daniele 10:dd7111d4279f 474 {
daniele 10:dd7111d4279f 475 struct pico_timer timer;
daniele 10:dd7111d4279f 476 struct pico_timer *t = heap_first(Timers);
daniele 10:dd7111d4279f 477 pico_tick = PICO_TIME_MS();
daniele 10:dd7111d4279f 478 while((t) && (t->expire < pico_tick)) {
daniele 10:dd7111d4279f 479 t->timer(pico_tick, t->arg);
daniele 10:dd7111d4279f 480 heap_peek(Timers, &timer);
daniele 10:dd7111d4279f 481 t = heap_first(Timers);
daniele 10:dd7111d4279f 482 }
daniele 10:dd7111d4279f 483 }
daniele 10:dd7111d4279f 484
daniele 10:dd7111d4279f 485
daniele 10:dd7111d4279f 486 #define PROTO_DEF_NR 11
daniele 10:dd7111d4279f 487 #define PROTO_DEF_AVG_NR 4
daniele 10:dd7111d4279f 488 #define PROTO_DEF_SCORE 32
daniele 10:dd7111d4279f 489 #define PROTO_MIN_SCORE 32
daniele 10:dd7111d4279f 490 #define PROTO_MAX_SCORE 128
daniele 10:dd7111d4279f 491 #define PROTO_LAT_IND 3 /* latecy indication 0-3 (lower is better latency performance), x1, x2, x4, x8 */
daniele 10:dd7111d4279f 492 #define PROTO_MAX_LOOP (PROTO_MAX_SCORE<<PROTO_LAT_IND) /* max global loop score, so per tick */
daniele 10:dd7111d4279f 493
daniele 10:dd7111d4279f 494 static int calc_score(int *score, int *index, int avg[][PROTO_DEF_AVG_NR], int *ret)
daniele 10:dd7111d4279f 495 {
daniele 10:dd7111d4279f 496 int temp, i, j, sum;
daniele 10:dd7111d4279f 497 int max_total = PROTO_MAX_LOOP, total = 0;
daniele 10:dd7111d4279f 498
daniele 10:dd7111d4279f 499 //dbg("USED SCORES> ");
daniele 10:dd7111d4279f 500
daniele 10:dd7111d4279f 501 for (i = 0; i < PROTO_DEF_NR; i++) {
daniele 10:dd7111d4279f 502
daniele 10:dd7111d4279f 503 /* if used looped score */
daniele 10:dd7111d4279f 504 if (ret[i] < score[i]) {
daniele 10:dd7111d4279f 505 temp = score[i] - ret[i]; /* remaining loop score */
daniele 10:dd7111d4279f 506
daniele 10:dd7111d4279f 507 //dbg("%3d - ",temp);
daniele 10:dd7111d4279f 508
daniele 10:dd7111d4279f 509 if (index[i] >= PROTO_DEF_AVG_NR)
daniele 10:dd7111d4279f 510 index[i] = 0; /* reset index */
daniele 10:dd7111d4279f 511 j = index[i];
daniele 10:dd7111d4279f 512 avg[i][j] = temp;
daniele 10:dd7111d4279f 513
daniele 10:dd7111d4279f 514 index[i]++;
daniele 10:dd7111d4279f 515
daniele 10:dd7111d4279f 516 if (ret[i] == 0 && (score[i]<<1 <= PROTO_MAX_SCORE) && ((total+(score[i]<<1)) < max_total) ) { /* used all loop score -> increase next score directly */
daniele 10:dd7111d4279f 517 score[i] <<= 1;
daniele 10:dd7111d4279f 518 total += score[i];
daniele 10:dd7111d4279f 519 continue;
daniele 10:dd7111d4279f 520 }
daniele 10:dd7111d4279f 521
daniele 10:dd7111d4279f 522 sum = 0;
daniele 10:dd7111d4279f 523 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
daniele 10:dd7111d4279f 524 sum += avg[i][j]; /* calculate sum */
daniele 10:dd7111d4279f 525
daniele 10:dd7111d4279f 526 sum >>= 2; /* divide by 4 to get average used score */
daniele 10:dd7111d4279f 527
daniele 10:dd7111d4279f 528 /* criterion to increase next loop score */
daniele 10:dd7111d4279f 529 if (sum > (score[i] - (score[i]>>2)) && (score[i]<<1 <= PROTO_MAX_SCORE) && ((total+(score[i]<<1)) < max_total)) { /* > 3/4 */
daniele 10:dd7111d4279f 530 score[i] <<= 1; /* double loop score */
daniele 10:dd7111d4279f 531 total += score[i];
daniele 10:dd7111d4279f 532 continue;
daniele 10:dd7111d4279f 533 }
daniele 10:dd7111d4279f 534
daniele 10:dd7111d4279f 535 /* criterion to decrease next loop score */
daniele 10:dd7111d4279f 536 if (sum < (score[i]>>2) && (score[i]>>1 >= PROTO_MIN_SCORE)) { /* < 1/4 */
daniele 10:dd7111d4279f 537 score[i] >>= 1; /* half loop score */
daniele 10:dd7111d4279f 538 total += score[i];
daniele 10:dd7111d4279f 539 continue;
daniele 10:dd7111d4279f 540 }
daniele 10:dd7111d4279f 541
daniele 10:dd7111d4279f 542 /* also add non-changed scores */
daniele 10:dd7111d4279f 543 total += score[i];
daniele 10:dd7111d4279f 544 }
daniele 10:dd7111d4279f 545 else if (ret[i] == score[i]) {
daniele 10:dd7111d4279f 546 /* no used loop score - gradually decrease */
daniele 10:dd7111d4279f 547
daniele 10:dd7111d4279f 548 // dbg("%3d - ",0);
daniele 10:dd7111d4279f 549
daniele 10:dd7111d4279f 550 if (index[i] >= PROTO_DEF_AVG_NR)
daniele 10:dd7111d4279f 551 index[i] = 0; /* reset index */
daniele 10:dd7111d4279f 552 j = index[i];
daniele 10:dd7111d4279f 553 avg[i][j] = 0;
daniele 10:dd7111d4279f 554
daniele 10:dd7111d4279f 555 index[i]++;
daniele 10:dd7111d4279f 556
daniele 10:dd7111d4279f 557 sum = 0;
daniele 10:dd7111d4279f 558 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
daniele 10:dd7111d4279f 559 sum += avg[i][j]; /* calculate sum */
daniele 10:dd7111d4279f 560
daniele 10:dd7111d4279f 561 sum >>= 2; /* divide by 4 to get average used score */
daniele 10:dd7111d4279f 562
daniele 10:dd7111d4279f 563 if ((sum == 0) && (score[i]>>1 >= PROTO_MIN_SCORE)) {
daniele 10:dd7111d4279f 564 score[i] >>= 1; /* half loop score */
daniele 10:dd7111d4279f 565 total += score[i];
daniele 10:dd7111d4279f 566 for (j = 0; j < PROTO_DEF_AVG_NR; j++)
daniele 10:dd7111d4279f 567 avg[i][j] = score[i];
daniele 10:dd7111d4279f 568 }
daniele 10:dd7111d4279f 569
daniele 10:dd7111d4279f 570 }
daniele 10:dd7111d4279f 571 }
daniele 10:dd7111d4279f 572
daniele 10:dd7111d4279f 573 //dbg("\n");
daniele 10:dd7111d4279f 574
daniele 10:dd7111d4279f 575 return 0;
daniele 10:dd7111d4279f 576 }
daniele 10:dd7111d4279f 577
daniele 10:dd7111d4279f 578
daniele 10:dd7111d4279f 579
daniele 10:dd7111d4279f 580 /*
daniele 10:dd7111d4279f 581
daniele 10:dd7111d4279f 582 .
daniele 10:dd7111d4279f 583 .vS.
daniele 10:dd7111d4279f 584 <aoSo.
daniele 10:dd7111d4279f 585 .XoS22.
daniele 10:dd7111d4279f 586 .S2S22. ._... ...... ..._.
daniele 10:dd7111d4279f 587 :=|2S2X2|=++; <vSX2XX2z+ |vSSSXSSs>. :iXXZUZXXe=
daniele 10:dd7111d4279f 588 )2SS2SS2S2S2I =oS2S2S2S2X22;. _vuXS22S2S2S22i ._wZZXZZZXZZXZX=
daniele 10:dd7111d4279f 589 )22S2S2S2S2Sl |S2S2S22S2SSSXc: .S2SS2S2S22S2SS= .]#XZZZXZXZZZZZZ:
daniele 10:dd7111d4279f 590 )oSS2SS2S2Sol |2}!"""!32S22S(. uS2S2Se**12oS2e ]dXZZXX2?YYXXXZ*
daniele 10:dd7111d4279f 591 .:2S2So:..-. . :]S2S2e;=X2SS2o .)oc ]XZZXZ( =nX:
daniele 10:dd7111d4279f 592 .S2S22. ___s_i,.)oS2So(;2SS2So, ` 3XZZZZc, -
daniele 10:dd7111d4279f 593 .S2SSo. =oXXXSSS2XoS2S2o( XS2S2XSos;. ]ZZZZXXXX|=
daniele 10:dd7111d4279f 594 .S2S22. .)S2S2S22S2S2S2S2o( "X2SS2S2S2Sus,, +3XZZZZZXZZoos_
daniele 10:dd7111d4279f 595 .S2S22. .]2S2SS22S222S2SS2o( ]S22S2S2S222So :3XXZZZZZZZZXXv
daniele 10:dd7111d4279f 596 .S2S22. =u2SS2e"~---"{2S2So( -"12S2S2SSS2Su. "?SXXXZXZZZZXo
daniele 10:dd7111d4279f 597 .S2SSo. )SS22z; :S2S2o( ={vS2S2S22v .<vXZZZZZZZ;
daniele 10:dd7111d4279f 598 .S2S2S: ]oSS2c; =22S2o( -"S2SS2n ~4XXZXZ(
daniele 10:dd7111d4279f 599 .2S2S2i )2S2S2[. .)XS2So( <;. .2S2S2o :<. ]XZZZX(
daniele 10:dd7111d4279f 600 nX2S2S,,_s_=3oSS2SoaasuXXS2S2o( .oXoasi_aioSSS22l.]dZoaas_aadXZZXZ'
daniele 10:dd7111d4279f 601 vS2SSSXXX2; )S2S2S2SoS2S2S2S2o( iS2S222XSoSS22So.)nXZZXXXZZXXZZXZo
daniele 10:dd7111d4279f 602 +32S22S2Sn -+S2S2S2S2So22S2So( 12S2SS2S2SS22S}- )SXXZZZZZZZZZXX!-
daniele 10:dd7111d4279f 603 .)S22222i .i2S2S2o>;:S2S2o( .<vSoSoSo2S(; :nXXXXXZXXX(
daniele 10:dd7111d4279f 604 .-~~~~- --- . - - --~~~-- --^^~~-
daniele 10:dd7111d4279f 605 .
daniele 10:dd7111d4279f 606
daniele 10:dd7111d4279f 607
daniele 10:dd7111d4279f 608 ... curious about our source code? We are hiring! mailto:<recruiting@tass.be>
daniele 10:dd7111d4279f 609
daniele 10:dd7111d4279f 610
daniele 10:dd7111d4279f 611 */
daniele 10:dd7111d4279f 612
daniele 10:dd7111d4279f 613 void pico_stack_tick(void)
daniele 10:dd7111d4279f 614 {
daniele 10:dd7111d4279f 615 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};
daniele 10:dd7111d4279f 616 static int index[PROTO_DEF_NR] = {0,0,0,0,0,0};
daniele 10:dd7111d4279f 617 static int avg[PROTO_DEF_NR][PROTO_DEF_AVG_NR];
daniele 10:dd7111d4279f 618 static int ret[PROTO_DEF_NR] = {0};
daniele 10:dd7111d4279f 619
daniele 10:dd7111d4279f 620 pico_check_timers();
daniele 10:dd7111d4279f 621
daniele 10:dd7111d4279f 622 //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]);
daniele 10:dd7111d4279f 623
daniele 10:dd7111d4279f 624 //score = pico_protocols_loop(100);
daniele 10:dd7111d4279f 625
daniele 10:dd7111d4279f 626 ret[0] = pico_devices_loop(score[0],PICO_LOOP_DIR_IN);
daniele 10:dd7111d4279f 627 pico_rand_feed(ret[0]);
daniele 10:dd7111d4279f 628
daniele 10:dd7111d4279f 629 ret[1] = pico_protocol_datalink_loop(score[1], PICO_LOOP_DIR_IN);
daniele 10:dd7111d4279f 630 pico_rand_feed(ret[1]);
daniele 10:dd7111d4279f 631
daniele 10:dd7111d4279f 632 ret[2] = pico_protocol_network_loop(score[2], PICO_LOOP_DIR_IN);
daniele 10:dd7111d4279f 633 pico_rand_feed(ret[2]);
daniele 10:dd7111d4279f 634
daniele 10:dd7111d4279f 635 ret[3] = pico_protocol_transport_loop(score[3], PICO_LOOP_DIR_IN);
daniele 10:dd7111d4279f 636 pico_rand_feed(ret[3]);
daniele 10:dd7111d4279f 637
daniele 10:dd7111d4279f 638
daniele 10:dd7111d4279f 639 ret[5] = score[5];
daniele 10:dd7111d4279f 640 #if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6)
daniele 10:dd7111d4279f 641 #if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP)
daniele 10:dd7111d4279f 642 ret[5] = pico_sockets_loop(score[5]); // swapped
daniele 10:dd7111d4279f 643 pico_rand_feed(ret[5]);
daniele 10:dd7111d4279f 644 #endif
daniele 10:dd7111d4279f 645 #endif
daniele 10:dd7111d4279f 646
daniele 10:dd7111d4279f 647 ret[4] = pico_protocol_socket_loop(score[4], PICO_LOOP_DIR_IN);
daniele 10:dd7111d4279f 648 pico_rand_feed(ret[4]);
daniele 10:dd7111d4279f 649
daniele 10:dd7111d4279f 650
daniele 10:dd7111d4279f 651 ret[6] = pico_protocol_socket_loop(score[6], PICO_LOOP_DIR_OUT);
daniele 10:dd7111d4279f 652 pico_rand_feed(ret[6]);
daniele 10:dd7111d4279f 653
daniele 10:dd7111d4279f 654 ret[7] = pico_protocol_transport_loop(score[7], PICO_LOOP_DIR_OUT);
daniele 10:dd7111d4279f 655 pico_rand_feed(ret[7]);
daniele 10:dd7111d4279f 656
daniele 10:dd7111d4279f 657 ret[8] = pico_protocol_network_loop(score[8], PICO_LOOP_DIR_OUT);
daniele 10:dd7111d4279f 658 pico_rand_feed(ret[8]);
daniele 10:dd7111d4279f 659
daniele 10:dd7111d4279f 660 ret[9] = pico_protocol_datalink_loop(score[9], PICO_LOOP_DIR_OUT);
daniele 10:dd7111d4279f 661 pico_rand_feed(ret[9]);
daniele 10:dd7111d4279f 662
daniele 10:dd7111d4279f 663 ret[10] = pico_devices_loop(score[10],PICO_LOOP_DIR_OUT);
daniele 10:dd7111d4279f 664 pico_rand_feed(ret[10]);
daniele 10:dd7111d4279f 665
daniele 10:dd7111d4279f 666 /* calculate new loop scores for next iteration */
daniele 10:dd7111d4279f 667 calc_score(score, index,(int (*)[]) avg, ret);
daniele 10:dd7111d4279f 668 }
daniele 10:dd7111d4279f 669
daniele 10:dd7111d4279f 670 void pico_stack_loop(void)
daniele 10:dd7111d4279f 671 {
daniele 10:dd7111d4279f 672 while(1) {
daniele 10:dd7111d4279f 673 pico_stack_tick();
daniele 10:dd7111d4279f 674 PICO_IDLE();
daniele 10:dd7111d4279f 675 }
daniele 10:dd7111d4279f 676 }
daniele 10:dd7111d4279f 677
daniele 10:dd7111d4279f 678 void pico_timer_add(unsigned long expire, void (*timer)(unsigned long, void *), void *arg)
daniele 10:dd7111d4279f 679 {
daniele 10:dd7111d4279f 680 pico_timer t;
daniele 10:dd7111d4279f 681 t.expire = PICO_TIME_MS() + expire;
daniele 10:dd7111d4279f 682 t.arg = arg;
daniele 10:dd7111d4279f 683 t.timer = timer;
daniele 10:dd7111d4279f 684 heap_insert(Timers, &t);
daniele 10:dd7111d4279f 685 if (Timers->n > PICO_MAX_TIMERS) {
daniele 10:dd7111d4279f 686 dbg("Warning: I have %d timers\n", Timers->n);
daniele 10:dd7111d4279f 687 }
daniele 10:dd7111d4279f 688 }
daniele 10:dd7111d4279f 689
daniele 10:dd7111d4279f 690 void pico_stack_init(void)
daniele 10:dd7111d4279f 691 {
daniele 10:dd7111d4279f 692
daniele 10:dd7111d4279f 693 #ifdef PICO_SUPPORT_IPV4
daniele 10:dd7111d4279f 694 pico_protocol_init(&pico_proto_ipv4);
daniele 10:dd7111d4279f 695 #endif
daniele 10:dd7111d4279f 696
daniele 10:dd7111d4279f 697 #ifdef PICO_SUPPORT_IPV6
daniele 10:dd7111d4279f 698 pico_protocol_init(&pico_proto_ipv6);
daniele 10:dd7111d4279f 699 #endif
daniele 10:dd7111d4279f 700
daniele 10:dd7111d4279f 701 #ifdef PICO_SUPPORT_ICMP4
daniele 10:dd7111d4279f 702 pico_protocol_init(&pico_proto_icmp4);
daniele 10:dd7111d4279f 703 #endif
daniele 10:dd7111d4279f 704
daniele 10:dd7111d4279f 705 #ifdef PICO_SUPPORT_IGMP
daniele 10:dd7111d4279f 706 pico_protocol_init(&pico_proto_igmp);
daniele 10:dd7111d4279f 707 #endif
daniele 10:dd7111d4279f 708
daniele 10:dd7111d4279f 709 #ifdef PICO_SUPPORT_UDP
daniele 10:dd7111d4279f 710 pico_protocol_init(&pico_proto_udp);
daniele 10:dd7111d4279f 711 #endif
daniele 10:dd7111d4279f 712
daniele 10:dd7111d4279f 713 #ifdef PICO_SUPPORT_TCP
daniele 10:dd7111d4279f 714 pico_protocol_init(&pico_proto_tcp);
daniele 10:dd7111d4279f 715 #endif
daniele 10:dd7111d4279f 716
daniele 10:dd7111d4279f 717 #ifdef PICO_SUPPORT_DNS_CLIENT
daniele 10:dd7111d4279f 718 pico_dns_client_init();
daniele 10:dd7111d4279f 719 #endif
daniele 10:dd7111d4279f 720
daniele 10:dd7111d4279f 721 pico_rand_feed(123456);
daniele 10:dd7111d4279f 722
daniele 10:dd7111d4279f 723 /* Initialize timer heap */
daniele 10:dd7111d4279f 724 Timers = heap_init();
daniele 10:dd7111d4279f 725 pico_stack_tick();
daniele 10:dd7111d4279f 726 pico_stack_tick();
daniele 10:dd7111d4279f 727 pico_stack_tick();
daniele 10:dd7111d4279f 728 }
daniele 10:dd7111d4279f 729