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
Diff: stack/pico_protocol.c
- Revision:
- 2:540f6e142d59
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stack/pico_protocol.c Sat Aug 03 13:16:14 2013 +0000 @@ -0,0 +1,350 @@ +/********************************************************************* +PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. +See LICENSE and COPYING for usage. + +. + +Authors: Daniele Lacamera +*********************************************************************/ + + +#include "pico_protocol.h" +#include "pico_tree.h" + +static int pico_proto_cmp(void *ka, void *kb) +{ + struct pico_protocol *a = ka, *b=kb; + if (a->hash < b->hash) + return -1; + if (a->hash > b->hash) + return 1; + return 0; +} + +PICO_TREE_DECLARE(Datalink_proto_tree,pico_proto_cmp); +PICO_TREE_DECLARE(Network_proto_tree,pico_proto_cmp); +PICO_TREE_DECLARE(Transport_proto_tree,pico_proto_cmp); +PICO_TREE_DECLARE(Socket_proto_tree,pico_proto_cmp); + +static int proto_loop(struct pico_protocol *proto, int loop_score, int direction) +{ + struct pico_frame *f; + + if (direction == PICO_LOOP_DIR_IN) { + + while(loop_score >0) { + if (proto->q_in->frames <= 0) + break; + + f = pico_dequeue(proto->q_in); + if ((f) &&(proto->process_in(proto, f) > 0)) { + loop_score--; + } + } + + } else if (direction == PICO_LOOP_DIR_OUT) { + + while(loop_score >0) { + if (proto->q_out->frames <= 0) + break; + + f = pico_dequeue(proto->q_out); + if ((f) &&(proto->process_out(proto, f) > 0)) { + loop_score--; + } + } + } + + return loop_score; +} + +#define DL_LOOP_MIN 1 + +int pico_protocol_datalink_loop(int loop_score, int direction) +{ + struct pico_protocol *start; + static struct pico_protocol *next = NULL, *next_in = NULL, *next_out = NULL; + static struct pico_tree_node * next_node, * in_node, * out_node; + + if (next_in == NULL) { + in_node = pico_tree_firstNode(Datalink_proto_tree.root); + if (in_node) + next_in = in_node->keyValue; + } + if (next_out == NULL) { + out_node = pico_tree_firstNode(Datalink_proto_tree.root); + if (out_node) + next_out = out_node->keyValue; + } + + if (direction == PICO_LOOP_DIR_IN) + { + next_node = in_node; + next = next_in; + } + else if (direction == PICO_LOOP_DIR_OUT) + { + next_node = out_node; + next = next_out; + } + + /* init start node */ + start = next; + + /* round-robin all datalink protocols, break if traversed all protocols */ + while (loop_score > DL_LOOP_MIN && next != NULL) { + loop_score = proto_loop(next, loop_score, direction); + + //next = RB_NEXT(pico_protocol_tree, &Datalink_proto_tree, next); + next_node = pico_tree_next(next_node); + next = next_node->keyValue; + + if (next == NULL) + { + next_node = pico_tree_firstNode(Datalink_proto_tree.root); + next = next_node->keyValue; + } + if (next == start) + break; + } + + if (direction == PICO_LOOP_DIR_IN) + { + in_node = next_node; + next_in = next; + } + else if (direction == PICO_LOOP_DIR_OUT) + { + out_node = next_node; + next_out = next; + } + + return loop_score; +} + + +#define NW_LOOP_MIN 1 + +int pico_protocol_network_loop(int loop_score, int direction) +{ + struct pico_protocol *start; + static struct pico_protocol *next = NULL, *next_in = NULL, *next_out = NULL; + static struct pico_tree_node * next_node, * in_node, * out_node; + + if (next_in == NULL) { + in_node = pico_tree_firstNode(Network_proto_tree.root); + if (in_node) + next_in = in_node->keyValue; + } + if (next_out == NULL) { + out_node = pico_tree_firstNode(Network_proto_tree.root); + if (out_node) + next_out = out_node->keyValue; + } + if (direction == PICO_LOOP_DIR_IN) + { + next_node = in_node; + next = next_in; + } + else if (direction == PICO_LOOP_DIR_OUT) + { + next_node = out_node; + next = next_out; + } + + /* init start node */ + start = next; + + /* round-robin all network protocols, break if traversed all protocols */ + while (loop_score > NW_LOOP_MIN && next != NULL) { + loop_score = proto_loop(next, loop_score, direction); + + next_node = pico_tree_next(next_node); + next = next_node->keyValue; + + if (next == NULL) + { + next_node = pico_tree_firstNode(Network_proto_tree.root); + next = next_node->keyValue; + } + if (next == start) + break; + } + + if (direction == PICO_LOOP_DIR_IN) + { + in_node = next_node; + next_in = next; + } + else if (direction == PICO_LOOP_DIR_OUT) + { + out_node = next_node; + next_out = next; + } + + return loop_score; +} + +#define TP_LOOP_MIN 1 + +int pico_protocol_transport_loop(int loop_score, int direction) +{ + struct pico_protocol *start; + static struct pico_protocol *next = NULL, *next_in = NULL, *next_out = NULL; + static struct pico_tree_node * next_node, * in_node, * out_node; + + if (next_in == NULL) { + in_node = pico_tree_firstNode(Transport_proto_tree.root); + if (in_node) + next_in = in_node->keyValue; + } + if (next_out == NULL) { + out_node = pico_tree_firstNode(Transport_proto_tree.root); + if (out_node) + next_out = out_node->keyValue; + } + + if (direction == PICO_LOOP_DIR_IN) + { + next_node = in_node; + next = next_in; + } + else if (direction == PICO_LOOP_DIR_OUT) + { + next_node = out_node; + next = next_out; + } + + /* init start node */ + start = next; + + /* round-robin all transport protocols, break if traversed all protocols */ + while (loop_score > DL_LOOP_MIN && next != NULL) { + loop_score = proto_loop(next, loop_score, direction); + + //next = RB_NEXT(pico_protocol_tree, &Transport_proto_tree, next); + next_node = pico_tree_next(next_node); + next = next_node->keyValue; + + if (next == NULL) + { + next_node = pico_tree_firstNode(Transport_proto_tree.root); + next = next_node->keyValue; + } + if (next == start) + break; + } + + if (direction == PICO_LOOP_DIR_IN) + { + in_node = next_node; + next_in = next; + } + else if (direction == PICO_LOOP_DIR_OUT) + { + out_node = next_node; + next_out = next; + } + + return loop_score; +} + + +#define SOCK_LOOP_MIN 1 + +int pico_protocol_socket_loop(int loop_score, int direction) +{ + struct pico_protocol *start; + static struct pico_protocol *next = NULL, *next_in = NULL, *next_out = NULL; + static struct pico_tree_node * next_node, * in_node, * out_node; + + if (next_in == NULL) { + in_node = pico_tree_firstNode(Socket_proto_tree.root); + if(in_node) + next_in = in_node->keyValue; + } + if (next_out == NULL) { + out_node = pico_tree_firstNode(Socket_proto_tree.root); + if(out_node) + next_out = out_node->keyValue; + } + + if (direction == PICO_LOOP_DIR_IN) + { + next_node = in_node; + next = next_in; + } + else if (direction == PICO_LOOP_DIR_OUT) + { + next_node = out_node; + next = next_out; + } + + /* init start node */ + start = next; + + /* round-robin all transport protocols, break if traversed all protocols */ + while (loop_score > SOCK_LOOP_MIN && next != NULL) { + loop_score = proto_loop(next, loop_score,direction); + + next_node = pico_tree_next(next_node); + next = next_node->keyValue; + + if (next == NULL) + { + next_node = pico_tree_firstNode(next_node); + next = next_node->keyValue; + } + if (next == start) + break; + } + + if (direction == PICO_LOOP_DIR_IN) + { + in_node = next_node; + next_in = next; + } + else if (direction == PICO_LOOP_DIR_OUT) + { + out_node = next_node; + next_out = next; + } + + return loop_score; +} + +int pico_protocols_loop(int loop_score) +{ +/* + loop_score = pico_protocol_datalink_loop(loop_score); + loop_score = pico_protocol_network_loop(loop_score); + loop_score = pico_protocol_transport_loop(loop_score); + loop_score = pico_protocol_socket_loop(loop_score); +*/ + return loop_score; +} + +void pico_protocol_init(struct pico_protocol *p) +{ + if (!p) + return; + + p->hash = pico_hash(p->name); + switch (p->layer) { + case PICO_LAYER_DATALINK: + pico_tree_insert(&Datalink_proto_tree, p); + break; + case PICO_LAYER_NETWORK: + pico_tree_insert(&Network_proto_tree,p); + break; + case PICO_LAYER_TRANSPORT: + pico_tree_insert(&Transport_proto_tree,p); + break; + case PICO_LAYER_SOCKET: + pico_tree_insert(&Socket_proto_tree,p); + break; + } + dbg("Protocol %s registered (layer: %d).\n", p->name, p->layer); + +} +