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

Dependents:   USBEthernet_TEST

Fork of USB_Ethernet by Daniele Lacamera

Committer:
daniele
Date:
Sat Aug 03 13:16:14 2013 +0000
Revision:
2:540f6e142d59
Moved to single package

Who changed what in which revision?

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