Daniele Lacamera / PicoTCP-Experimental_CDC_ECM_Branch

Fork of PicoTCP by Daniele Lacamera

Committer:
tass
Date:
Fri May 17 12:09:59 2013 +0000
Revision:
1:cfe8984a32b4
Parent:
libraries/picotcp/stack/pico_device.c@0:d7f2341ab245
Update for smaller SOCKETQ

Who changed what in which revision?

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