Daniele Lacamera / PicoTCP-Experimental_CDC_ECM_Branch

Fork of PicoTCP by Daniele Lacamera

Committer:
daniele
Date:
Tue Jun 11 23:28:50 2013 +0000
Revision:
25:d63125298eb3
Parent:
23:884f327c3647
Fixed close

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