Daniele Lacamera / PicoTCP-Experimental_CDC_ECM_Branch

Fork of PicoTCP by Daniele Lacamera

Committer:
daniele
Date:
Fri May 24 15:25:25 2013 +0000
Revision:
3:b4047e8a0123
Updated from main repo + fixed Mutexes;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 3:b4047e8a0123 1 /*********************************************************************
daniele 3:b4047e8a0123 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 3:b4047e8a0123 3 See LICENSE and COPYING for usage.
daniele 3:b4047e8a0123 4
daniele 3:b4047e8a0123 5 .
daniele 3:b4047e8a0123 6
daniele 3:b4047e8a0123 7 Authors: Daniele Lacamera
daniele 3:b4047e8a0123 8 *********************************************************************/
daniele 3:b4047e8a0123 9
daniele 3:b4047e8a0123 10
daniele 3:b4047e8a0123 11 #include "pico_config.h"
daniele 3:b4047e8a0123 12 #include "pico_device.h"
daniele 3:b4047e8a0123 13 #include "pico_stack.h"
daniele 3:b4047e8a0123 14 #include "pico_protocol.h"
daniele 3:b4047e8a0123 15 #include "pico_tree.h"
daniele 3:b4047e8a0123 16
daniele 3:b4047e8a0123 17
daniele 3:b4047e8a0123 18 static int pico_dev_cmp(void *ka, void *kb)
daniele 3:b4047e8a0123 19 {
daniele 3:b4047e8a0123 20 struct pico_device *a = ka, *b = kb;
daniele 3:b4047e8a0123 21 if (a->hash < b->hash)
daniele 3:b4047e8a0123 22 return -1;
daniele 3:b4047e8a0123 23 if (a->hash > b->hash)
daniele 3:b4047e8a0123 24 return 1;
daniele 3:b4047e8a0123 25 return 0;
daniele 3:b4047e8a0123 26 }
daniele 3:b4047e8a0123 27
daniele 3:b4047e8a0123 28 PICO_TREE_DECLARE(Device_tree,pico_dev_cmp);
daniele 3:b4047e8a0123 29
daniele 3:b4047e8a0123 30 int pico_device_init(struct pico_device *dev, char *name, uint8_t *mac)
daniele 3:b4047e8a0123 31 {
daniele 3:b4047e8a0123 32 int len = strlen(name);
daniele 3:b4047e8a0123 33 if(len>MAX_DEVICE_NAME)
daniele 3:b4047e8a0123 34 len = MAX_DEVICE_NAME;
daniele 3:b4047e8a0123 35 memcpy(dev->name, name, len);
daniele 3:b4047e8a0123 36 dev->hash = pico_hash(dev->name);
daniele 3:b4047e8a0123 37
daniele 3:b4047e8a0123 38 pico_tree_insert(&Device_tree,dev);
daniele 3:b4047e8a0123 39 dev->q_in = pico_zalloc(sizeof(struct pico_queue));
daniele 3:b4047e8a0123 40 dev->q_out = pico_zalloc(sizeof(struct pico_queue));
daniele 3:b4047e8a0123 41
daniele 3:b4047e8a0123 42 if (mac) {
daniele 3:b4047e8a0123 43 dev->eth = pico_zalloc(sizeof(struct pico_ethdev));
daniele 3:b4047e8a0123 44 memcpy(dev->eth->mac.addr, mac, PICO_SIZE_ETH);
daniele 3:b4047e8a0123 45 } else {
daniele 3:b4047e8a0123 46 dev->eth = NULL;
daniele 3:b4047e8a0123 47 }
daniele 3:b4047e8a0123 48
daniele 3:b4047e8a0123 49 if (!dev->q_in || !dev->q_out || (mac && !dev->eth))
daniele 3:b4047e8a0123 50 return -1;
daniele 3:b4047e8a0123 51 return 0;
daniele 3:b4047e8a0123 52 }
daniele 3:b4047e8a0123 53
daniele 3:b4047e8a0123 54 void pico_device_destroy(struct pico_device *dev)
daniele 3:b4047e8a0123 55 {
daniele 3:b4047e8a0123 56 if (dev->destroy)
daniele 3:b4047e8a0123 57 dev->destroy(dev);
daniele 3:b4047e8a0123 58
daniele 3:b4047e8a0123 59 if (dev->q_in) {
daniele 3:b4047e8a0123 60 pico_queue_empty(dev->q_in);
daniele 3:b4047e8a0123 61 pico_free(dev->q_in);
daniele 3:b4047e8a0123 62 }
daniele 3:b4047e8a0123 63 if (dev->q_out) {
daniele 3:b4047e8a0123 64 pico_queue_empty(dev->q_out);
daniele 3:b4047e8a0123 65 pico_free(dev->q_out);
daniele 3:b4047e8a0123 66 }
daniele 3:b4047e8a0123 67
daniele 3:b4047e8a0123 68 if (dev->eth)
daniele 3:b4047e8a0123 69 pico_free(dev->eth);
daniele 3:b4047e8a0123 70
daniele 3:b4047e8a0123 71 pico_tree_delete(&Device_tree,dev);
daniele 3:b4047e8a0123 72 pico_free(dev);
daniele 3:b4047e8a0123 73 }
daniele 3:b4047e8a0123 74
daniele 3:b4047e8a0123 75 static int devloop(struct pico_device *dev, int loop_score, int direction)
daniele 3:b4047e8a0123 76 {
daniele 3:b4047e8a0123 77 struct pico_frame *f;
daniele 3:b4047e8a0123 78
daniele 3:b4047e8a0123 79 /* If device supports polling, give control. Loop score is managed internally,
daniele 3:b4047e8a0123 80 * remaining loop points are returned. */
daniele 3:b4047e8a0123 81 if (dev->poll) {
daniele 3:b4047e8a0123 82 loop_score = dev->poll(dev, loop_score);
daniele 3:b4047e8a0123 83 }
daniele 3:b4047e8a0123 84
daniele 3:b4047e8a0123 85 if (direction == PICO_LOOP_DIR_OUT) {
daniele 3:b4047e8a0123 86
daniele 3:b4047e8a0123 87 while(loop_score > 0) {
daniele 3:b4047e8a0123 88 if (dev->q_out->frames <= 0)
daniele 3:b4047e8a0123 89 break;
daniele 3:b4047e8a0123 90
daniele 3:b4047e8a0123 91 /* Device dequeue + send */
daniele 3:b4047e8a0123 92 f = pico_dequeue(dev->q_out);
daniele 3:b4047e8a0123 93 if (f) {
daniele 3:b4047e8a0123 94 if (dev->eth) {
daniele 3:b4047e8a0123 95 int ret = pico_ethernet_send(f);
daniele 3:b4047e8a0123 96 if (0 == ret) {
daniele 3:b4047e8a0123 97 loop_score--;
daniele 3:b4047e8a0123 98 continue;
daniele 3:b4047e8a0123 99 } if (ret < 0) {
daniele 3:b4047e8a0123 100 if (!pico_source_is_local(f)) {
daniele 3:b4047e8a0123 101 dbg("Destination unreachable -------> SEND ICMP\n");
daniele 3:b4047e8a0123 102 pico_notify_dest_unreachable(f);
daniele 3:b4047e8a0123 103 } else {
daniele 3:b4047e8a0123 104 dbg("Destination unreachable -------> LOCAL\n");
daniele 3:b4047e8a0123 105 }
daniele 3:b4047e8a0123 106 pico_frame_discard(f);
daniele 3:b4047e8a0123 107 continue;
daniele 3:b4047e8a0123 108 }
daniele 3:b4047e8a0123 109 } else {
daniele 3:b4047e8a0123 110 dev->send(dev, f->start, f->len);
daniele 3:b4047e8a0123 111 }
daniele 3:b4047e8a0123 112 pico_frame_discard(f);
daniele 3:b4047e8a0123 113 loop_score--;
daniele 3:b4047e8a0123 114 }
daniele 3:b4047e8a0123 115 }
daniele 3:b4047e8a0123 116
daniele 3:b4047e8a0123 117 } else if (direction == PICO_LOOP_DIR_IN) {
daniele 3:b4047e8a0123 118
daniele 3:b4047e8a0123 119 while(loop_score > 0) {
daniele 3:b4047e8a0123 120 if (dev->q_in->frames <= 0)
daniele 3:b4047e8a0123 121 break;
daniele 3:b4047e8a0123 122
daniele 3:b4047e8a0123 123 /* Receive */
daniele 3:b4047e8a0123 124 f = pico_dequeue(dev->q_in);
daniele 3:b4047e8a0123 125 if (f) {
daniele 3:b4047e8a0123 126 if (dev->eth) {
daniele 3:b4047e8a0123 127 f->datalink_hdr = f->buffer;
daniele 3:b4047e8a0123 128 pico_ethernet_receive(f);
daniele 3:b4047e8a0123 129 } else {
daniele 3:b4047e8a0123 130 f->net_hdr = f->buffer;
daniele 3:b4047e8a0123 131 pico_network_receive(f);
daniele 3:b4047e8a0123 132 }
daniele 3:b4047e8a0123 133 loop_score--;
daniele 3:b4047e8a0123 134 }
daniele 3:b4047e8a0123 135 }
daniele 3:b4047e8a0123 136 }
daniele 3:b4047e8a0123 137
daniele 3:b4047e8a0123 138 return loop_score;
daniele 3:b4047e8a0123 139 }
daniele 3:b4047e8a0123 140
daniele 3:b4047e8a0123 141
daniele 3:b4047e8a0123 142 #define DEV_LOOP_MIN 16
daniele 3:b4047e8a0123 143
daniele 3:b4047e8a0123 144 int pico_devices_loop(int loop_score, int direction)
daniele 3:b4047e8a0123 145 {
daniele 3:b4047e8a0123 146 struct pico_device *start;
daniele 3:b4047e8a0123 147 static struct pico_device *next = NULL, *next_in = NULL, *next_out = NULL;
daniele 3:b4047e8a0123 148 static struct pico_tree_node * next_node, * in_node, * out_node;
daniele 3:b4047e8a0123 149
daniele 3:b4047e8a0123 150 if (next_in == NULL) {
daniele 3:b4047e8a0123 151 in_node = pico_tree_firstNode(Device_tree.root);
daniele 3:b4047e8a0123 152 next_in = in_node->keyValue;
daniele 3:b4047e8a0123 153 }
daniele 3:b4047e8a0123 154 if (next_out == NULL) {
daniele 3:b4047e8a0123 155 out_node = pico_tree_firstNode(Device_tree.root);
daniele 3:b4047e8a0123 156 next_out = out_node->keyValue;
daniele 3:b4047e8a0123 157 }
daniele 3:b4047e8a0123 158
daniele 3:b4047e8a0123 159 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 160 {
daniele 3:b4047e8a0123 161 next_node = in_node;
daniele 3:b4047e8a0123 162 next = next_in;
daniele 3:b4047e8a0123 163 }
daniele 3:b4047e8a0123 164 else if (direction == PICO_LOOP_DIR_OUT)
daniele 3:b4047e8a0123 165 {
daniele 3:b4047e8a0123 166 next_node = out_node;
daniele 3:b4047e8a0123 167 next = next_out;
daniele 3:b4047e8a0123 168 }
daniele 3:b4047e8a0123 169
daniele 3:b4047e8a0123 170 /* init start node */
daniele 3:b4047e8a0123 171 start = next;
daniele 3:b4047e8a0123 172
daniele 3:b4047e8a0123 173 /* round-robin all devices, break if traversed all devices */
daniele 3:b4047e8a0123 174 while (loop_score > DEV_LOOP_MIN && next != NULL) {
daniele 3:b4047e8a0123 175 loop_score = devloop(next, loop_score, direction);
daniele 3:b4047e8a0123 176
daniele 3:b4047e8a0123 177 next_node = pico_tree_next(next_node);
daniele 3:b4047e8a0123 178 next = next_node->keyValue;
daniele 3:b4047e8a0123 179
daniele 3:b4047e8a0123 180 if (next == NULL)
daniele 3:b4047e8a0123 181 {
daniele 3:b4047e8a0123 182 next_node = pico_tree_firstNode(Device_tree.root);
daniele 3:b4047e8a0123 183 next = next_node->keyValue;
daniele 3:b4047e8a0123 184 }
daniele 3:b4047e8a0123 185 if (next == start)
daniele 3:b4047e8a0123 186 break;
daniele 3:b4047e8a0123 187 }
daniele 3:b4047e8a0123 188
daniele 3:b4047e8a0123 189 if (direction == PICO_LOOP_DIR_IN)
daniele 3:b4047e8a0123 190 {
daniele 3:b4047e8a0123 191 in_node = next_node;
daniele 3:b4047e8a0123 192 next_in = next;
daniele 3:b4047e8a0123 193 }
daniele 3:b4047e8a0123 194 else if (direction == PICO_LOOP_DIR_OUT)
daniele 3:b4047e8a0123 195 {
daniele 3:b4047e8a0123 196 out_node = next_node;
daniele 3:b4047e8a0123 197 next_out = next;
daniele 3:b4047e8a0123 198 }
daniele 3:b4047e8a0123 199
daniele 3:b4047e8a0123 200 return loop_score;
daniele 3:b4047e8a0123 201 }
daniele 3:b4047e8a0123 202
daniele 3:b4047e8a0123 203 struct pico_device* pico_get_device(char* name)
daniele 3:b4047e8a0123 204 {
daniele 3:b4047e8a0123 205 struct pico_device *dev;
daniele 3:b4047e8a0123 206 struct pico_tree_node * index;
daniele 3:b4047e8a0123 207 pico_tree_foreach(index, &Device_tree){
daniele 3:b4047e8a0123 208 dev = index->keyValue;
daniele 3:b4047e8a0123 209 if(strcmp(name, dev->name) == 0)
daniele 3:b4047e8a0123 210 return dev;
daniele 3:b4047e8a0123 211 }
daniele 3:b4047e8a0123 212 return NULL;
daniele 3:b4047e8a0123 213 }
daniele 3:b4047e8a0123 214
daniele 3:b4047e8a0123 215 int pico_device_broadcast(struct pico_frame * f)
daniele 3:b4047e8a0123 216 {
daniele 3:b4047e8a0123 217 struct pico_tree_node * index;
daniele 3:b4047e8a0123 218 int ret = -1;
daniele 3:b4047e8a0123 219
daniele 3:b4047e8a0123 220 pico_tree_foreach(index,&Device_tree)
daniele 3:b4047e8a0123 221 {
daniele 3:b4047e8a0123 222 struct pico_device * dev = index->keyValue;
daniele 3:b4047e8a0123 223 if(dev != f->dev)
daniele 3:b4047e8a0123 224 {
daniele 3:b4047e8a0123 225 struct pico_frame * copy = pico_frame_copy(f);
daniele 3:b4047e8a0123 226
daniele 3:b4047e8a0123 227 if(!copy)
daniele 3:b4047e8a0123 228 return -1;
daniele 3:b4047e8a0123 229 copy->dev = dev;
daniele 3:b4047e8a0123 230 copy->dev->send(copy->dev, copy->start, copy->len);
daniele 3:b4047e8a0123 231 pico_frame_discard(copy);
daniele 3:b4047e8a0123 232 }
daniele 3:b4047e8a0123 233 else
daniele 3:b4047e8a0123 234 {
daniele 3:b4047e8a0123 235 ret = f->dev->send(f->dev, f->start, f->len);
daniele 3:b4047e8a0123 236 }
daniele 3:b4047e8a0123 237 }
daniele 3:b4047e8a0123 238
daniele 3:b4047e8a0123 239 return ret;
daniele 3:b4047e8a0123 240 }