CDC/ECM driver for mbed, based on USBDevice by mbed-official. Uses PicoTCP to access Ethernet USB device. License: GPLv2
Fork of USB_Ethernet by
pico_device.c
00001 /********************************************************************* 00002 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. 00003 See LICENSE and COPYING for usage. 00004 00005 . 00006 00007 Authors: Daniele Lacamera 00008 *********************************************************************/ 00009 00010 00011 #include "pico_config.h" 00012 #include "pico_device.h" 00013 #include "pico_stack.h" 00014 #include "pico_protocol.h" 00015 #include "pico_tree.h" 00016 00017 00018 static int pico_dev_cmp(void *ka, void *kb) 00019 { 00020 struct pico_device *a = ka, *b = kb; 00021 if (a->hash < b->hash) 00022 return -1; 00023 if (a->hash > b->hash) 00024 return 1; 00025 return 0; 00026 } 00027 00028 PICO_TREE_DECLARE(Device_tree,pico_dev_cmp); 00029 00030 int pico_device_init(struct pico_device *dev, char *name, uint8_t *mac) 00031 { 00032 int len = strlen(name); 00033 if(len>MAX_DEVICE_NAME) 00034 len = MAX_DEVICE_NAME; 00035 memcpy(dev->name, name, len); 00036 dev->hash = pico_hash(dev->name); 00037 00038 pico_tree_insert(&Device_tree,dev); 00039 dev->q_in = pico_zalloc(sizeof(struct pico_queue)); 00040 dev->q_out = pico_zalloc(sizeof(struct pico_queue)); 00041 00042 if (mac) { 00043 dev->eth = pico_zalloc(sizeof(struct pico_ethdev)); 00044 memcpy(dev->eth->mac.addr, mac, PICO_SIZE_ETH); 00045 } else { 00046 dev->eth = NULL; 00047 } 00048 00049 if (!dev->q_in || !dev->q_out || (mac && !dev->eth)) 00050 return -1; 00051 return 0; 00052 } 00053 00054 void pico_device_destroy(struct pico_device *dev) 00055 { 00056 if (dev->destroy) 00057 dev->destroy(dev); 00058 00059 if (dev->q_in) { 00060 pico_queue_empty(dev->q_in); 00061 pico_free(dev->q_in); 00062 } 00063 if (dev->q_out) { 00064 pico_queue_empty(dev->q_out); 00065 pico_free(dev->q_out); 00066 } 00067 00068 if (dev->eth) 00069 pico_free(dev->eth); 00070 00071 pico_tree_delete(&Device_tree,dev); 00072 pico_free(dev); 00073 } 00074 00075 static int devloop(struct pico_device *dev, int loop_score, int direction) 00076 { 00077 struct pico_frame *f; 00078 00079 /* If device supports interrupts, read the value of the condition and trigger the dsr */ 00080 if ((dev->__serving_interrupt) && (dev->dsr)) { 00081 /* call dsr routine */ 00082 loop_score = dev->dsr(dev, loop_score); 00083 } 00084 00085 /* If device supports polling, give control. Loop score is managed internally, 00086 * remaining loop points are returned. */ 00087 if (dev->poll) { 00088 loop_score = dev->poll(dev, loop_score); 00089 } 00090 00091 if (direction == PICO_LOOP_DIR_OUT) { 00092 00093 while(loop_score > 0) { 00094 if (dev->q_out->frames <= 0) 00095 break; 00096 00097 /* Device dequeue + send */ 00098 f = pico_dequeue(dev->q_out); 00099 if (f) { 00100 if (dev->eth) { 00101 int ret = pico_ethernet_send(f); 00102 if (0 == ret) { 00103 loop_score--; 00104 continue; 00105 } if (ret < 0) { 00106 if (!pico_source_is_local(f)) { 00107 dbg("Destination unreachable -------> SEND ICMP\n"); 00108 pico_notify_dest_unreachable(f); 00109 } else { 00110 dbg("Destination unreachable -------> LOCAL\n"); 00111 } 00112 pico_frame_discard(f); 00113 continue; 00114 } 00115 } else { 00116 dev->send(dev, f->start, f->len); 00117 } 00118 pico_frame_discard(f); 00119 loop_score--; 00120 } 00121 } 00122 00123 } else if (direction == PICO_LOOP_DIR_IN) { 00124 00125 while(loop_score > 0) { 00126 if (dev->q_in->frames <= 0) 00127 break; 00128 00129 /* Receive */ 00130 f = pico_dequeue(dev->q_in); 00131 if (f) { 00132 if (dev->eth) { 00133 f->datalink_hdr = f->buffer; 00134 pico_ethernet_receive(f); 00135 } else { 00136 f->net_hdr = f->buffer; 00137 pico_network_receive(f); 00138 } 00139 loop_score--; 00140 } 00141 } 00142 } 00143 00144 return loop_score; 00145 } 00146 00147 00148 #define DEV_LOOP_MIN 16 00149 00150 int pico_devices_loop(int loop_score, int direction) 00151 { 00152 struct pico_device *start; 00153 static struct pico_device *next = NULL, *next_in = NULL, *next_out = NULL; 00154 static struct pico_tree_node * next_node, * in_node, * out_node; 00155 00156 if (next_in == NULL) { 00157 in_node = pico_tree_firstNode(Device_tree.root); 00158 next_in = in_node->keyValue; 00159 } 00160 if (next_out == NULL) { 00161 out_node = pico_tree_firstNode(Device_tree.root); 00162 next_out = out_node->keyValue; 00163 } 00164 00165 if (direction == PICO_LOOP_DIR_IN) 00166 { 00167 next_node = in_node; 00168 next = next_in; 00169 } 00170 else if (direction == PICO_LOOP_DIR_OUT) 00171 { 00172 next_node = out_node; 00173 next = next_out; 00174 } 00175 00176 /* init start node */ 00177 start = next; 00178 00179 /* round-robin all devices, break if traversed all devices */ 00180 while (loop_score > DEV_LOOP_MIN && next != NULL) { 00181 loop_score = devloop(next, loop_score, direction); 00182 00183 next_node = pico_tree_next(next_node); 00184 next = next_node->keyValue; 00185 00186 if (next == NULL) 00187 { 00188 next_node = pico_tree_firstNode(Device_tree.root); 00189 next = next_node->keyValue; 00190 } 00191 if (next == start) 00192 break; 00193 } 00194 00195 if (direction == PICO_LOOP_DIR_IN) 00196 { 00197 in_node = next_node; 00198 next_in = next; 00199 } 00200 else if (direction == PICO_LOOP_DIR_OUT) 00201 { 00202 out_node = next_node; 00203 next_out = next; 00204 } 00205 00206 return loop_score; 00207 } 00208 00209 struct pico_device* pico_get_device(char* name) 00210 { 00211 struct pico_device *dev; 00212 struct pico_tree_node * index; 00213 pico_tree_foreach(index, &Device_tree){ 00214 dev = index->keyValue; 00215 if(strcmp(name, dev->name) == 0) 00216 return dev; 00217 } 00218 return NULL; 00219 } 00220 00221 int pico_device_broadcast(struct pico_frame * f) 00222 { 00223 struct pico_tree_node * index; 00224 int ret = -1; 00225 00226 pico_tree_foreach(index,&Device_tree) 00227 { 00228 struct pico_device * dev = index->keyValue; 00229 if(dev != f->dev) 00230 { 00231 struct pico_frame * copy = pico_frame_copy(f); 00232 00233 if(!copy) 00234 return -1; 00235 copy->dev = dev; 00236 copy->dev->send(copy->dev, copy->start, copy->len); 00237 pico_frame_discard(copy); 00238 } 00239 else 00240 { 00241 ret = f->dev->send(f->dev, f->start, f->len); 00242 } 00243 } 00244 00245 return ret; 00246 }
Generated on Wed Jul 13 2022 02:20:45 by 1.7.2