Daniele Lacamera / PicoTCP Featured

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EthernetInterface.cpp Source File

EthernetInterface.cpp

00001 /* 
00002  *
00003  * PicoTCP Socket interface for mbed.
00004  * Copyright (C) 2013 TASS Belgium NV
00005  * 
00006  * Released under GPL v2
00007  *
00008  * Other licensing models might apply at the sole discretion of the copyright holders.
00009  *
00010  *
00011  * This software is based on the mbed.org EthernetInterface implementation:
00012  * Copyright (C) 2012 mbed.org, MIT License
00013  *
00014  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00015  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00016  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00017  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00018  * furnished to do so, subject to the following conditions:
00019  *
00020  * The above copyright notice and this permission notice shall be included in all copies or
00021  * substantial portions of the Software.
00022  *
00023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00024  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00025  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00026  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00027  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00028  */
00029 
00030 #include "EthernetInterface.h"
00031 #include "Queue.h"
00032 #include "wrapper.h"
00033 #include "proxy_endpoint.h"
00034 #include "pico_dev_mbed_emac.h"
00035 #include "mbed.h"
00036 #include "PicoCondition.h"
00037 extern "C"{
00038 #include "pico_stack.h"
00039 #include "pico_config.h"
00040 #include "cmsis_os.h"
00041 #include "pico_dhcp_client.h"
00042 #include "pico_dns_client.h"
00043 #include "pico_ipfilter.h"
00044 #include "pico_slaacv4.h"
00045 //#define eth_dbg mbed_dbg
00046 #define eth_dbg(...)
00047 
00048 void (*linkCb)(uint32_t link) = NULL;
00049 }
00050 
00051 //DigitalOutput led(LED3);
00052 /* TCP/IP and Network Interface Initialisation */
00053 static struct pico_device *lpc_eth;
00054 
00055 static uint32_t dhcp_xid = 0;
00056 static PicoCondition dhcp_mx;
00057 static int dhcp_retval = -1;
00058 
00059 static char mac_addr[19];
00060 static char ip_addr[17] = "\0";
00061 static char gw_addr[17] = "\0";
00062 static char nm_addr[17] = "\0";
00063 static bool use_dhcp = false;
00064 static bool is_initialized = false;
00065 
00066 void slaacv4_cb(struct pico_ip4 *ip, uint8_t code)
00067 {
00068     struct pico_ip4 nm_ip4;
00069     if(code == 0 && ip)
00070     {
00071         dhcp_retval = 0;
00072         
00073         pico_ipv4_to_string(ip_addr, ip->addr);
00074         nm_ip4.addr = long_be(0xFFFF0000);
00075         pico_ipv4_to_string(nm_addr,nm_ip4.addr);
00076     }
00077     else
00078         dhcp_retval = -1;
00079         
00080     dhcp_mx.unlock();
00081 }
00082 
00083 static void dhcp_cb(void *cli, int code)
00084 {
00085     void *id = NULL;
00086     struct pico_ip4 address, gateway, netmask, zero = {};
00087     
00088     if (PICO_DHCP_ERROR == code)
00089         goto fail;
00090     
00091     if (PICO_DHCP_RESET == code)
00092         goto reset;    
00093     
00094     id = pico_dhcp_get_identifier(dhcp_xid);
00095     if (!id)
00096         goto fail;
00097     address = pico_dhcp_get_address(id);
00098     gateway = pico_dhcp_get_gateway(id);
00099     netmask = pico_dhcp_get_netmask(id);
00100     //if (address) ? // still needed
00101     
00102     pico_ipv4_to_string(ip_addr, address.addr);
00103     pico_ipv4_to_string(gw_addr,gateway.addr);
00104     pico_ipv4_to_string(nm_addr,netmask.addr);
00105     
00106     eth_dbg("IP assigned : %s\n",ip_addr);
00107     
00108     if (gateway.addr != 0) {
00109         pico_ipv4_to_string(gw_addr, gateway.addr);
00110         eth_dbg("Default gateway assigned : %s\n",gw_addr);
00111         pico_ipv4_route_add(zero, zero, gateway, 1, NULL);
00112     }
00113 
00114     dhcp_retval = 0;
00115     dhcp_mx.unlock();
00116     
00117     return;
00118     
00119 fail:
00120     pico_slaacv4_claimip(lpc_eth,slaacv4_cb);
00121     
00122 reset:
00123      eth_dbg("DHCP reset!\n");
00124 }
00125 
00126 static void init_eth(void) 
00127 {
00128    if (!is_initialized) {
00129         pico_stack_init();
00130         picotcp_init();
00131         lpc_eth = pico_emac_create("mbed0");
00132         is_initialized = true;
00133         pico_dns_client_init();
00134     }
00135     if (lpc_eth) {
00136         snprintf(mac_addr, 19, "%02X:%02X:%02X:%02X:%02X:%02X", lpc_eth->eth->mac.addr[0], lpc_eth->eth->mac.addr[1], 
00137             lpc_eth->eth->mac.addr[2], lpc_eth->eth->mac.addr[3], lpc_eth->eth->mac.addr[4], lpc_eth->eth->mac.addr[5]);
00138     }
00139     
00140     if(lpc_eth)
00141         eth_dbg("Ethernet initialized...\n");
00142     else
00143         eth_dbg("Failed to start Ethernet...\n");
00144        
00145 }
00146 
00147 int EthernetInterface::init() 
00148 {
00149     init_eth();    
00150     /* use dhcp to retrieve address and gateway. */
00151     use_dhcp = true;
00152     return 0; 
00153 }
00154 
00155 int EthernetInterface::init(const char* ip, const char* mask, const char* gateway) {
00156     pico_ip4 pico_addr, pico_netmask, pico_gw = {0}, zero = {0};
00157     
00158     if(strcmp(ip,gateway) == 0)
00159         return -1;
00160     
00161     init_eth();
00162     
00163     use_dhcp = false;
00164     strcpy(ip_addr, ip);
00165     strcpy(nm_addr, mask);
00166     strcpy(gw_addr,gateway);
00167     
00168     pico_string_to_ipv4(ip, &pico_addr.addr);
00169     pico_string_to_ipv4(mask, &pico_netmask.addr);
00170     if (gateway) {
00171         pico_string_to_ipv4(gateway, &pico_gw.addr);
00172     }
00173     pico_ipv4_link_add(lpc_eth, pico_addr, pico_netmask);
00174     
00175     if (pico_gw.addr)
00176         pico_ipv4_route_add(zero, zero, pico_gw, 1, NULL);
00177     
00178     return 0;
00179 }
00180 
00181 int EthernetInterface::connect(unsigned int timeout_ms) {
00182      IGNORE_PARAMETER(timeout_ms);
00183     //dhcp_mx.lock(); do we still need this ?
00184     if (use_dhcp) {
00185         if (pico_dhcp_initiate_negotiation(lpc_eth, &dhcp_cb, &dhcp_xid) < 0)
00186             return -1;
00187       
00188         dhcp_mx.lock(); // wait for a sign
00189 //timeout_ms removed because rtos limit lock timeout to approximate 65 seconds.
00190         
00191         return dhcp_retval;
00192         
00193     } else {
00194         return 0;
00195     }
00196 }
00197 
00198 int EthernetInterface::disconnect() {
00199     if (use_dhcp) {
00200     } 
00201     pico_device_destroy(lpc_eth);
00202     lpc_eth = NULL;
00203     return 0;
00204 }
00205 
00206 char* EthernetInterface::getMACAddress() {
00207     return mac_addr;
00208 }
00209 
00210 char* EthernetInterface::getIPAddress() {
00211     return ip_addr;
00212 }
00213 
00214 char* EthernetInterface::getIPGateway() {
00215     return gw_addr;
00216 }
00217 
00218 char* EthernetInterface::getIPNetmask() {
00219     return nm_addr;
00220 }
00221 
00222 int EthernetInterface::registerLinkStatus(void (*cb)(uint32_t linkStatus))
00223 {
00224     ::linkCb = cb;
00225     return 0;
00226 }
00227 
00228 int EthernetInterface::setDnsServer(const char * ip)
00229 {
00230     return picotcp_dns_client_nameserver(ip, PICO_DNS_NS_ADD);
00231 }
00232 
00233 int EthernetInterface::createIpFilter(char *ipAddress, char * netmask, int port, filter_type filter)
00234 {
00235     struct pico_ip4 addr, nm, local;
00236     if(!ipAddress) addr.addr = 0;
00237     else pico_string_to_ipv4(ipAddress,&addr.addr);
00238     
00239     if(!netmask) nm.addr = 0;
00240     else pico_string_to_ipv4(netmask,&nm.addr);
00241     
00242     pico_string_to_ipv4(ip_addr,&local.addr);
00243     
00244     if(filter == INPUT_FILTER)
00245     {
00246         return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&local,&nm,&addr,&nm,0,port,0,0,FILTER_REJECT);
00247     }
00248     else if(filter == OUTPUT_FILTER)
00249     {
00250         return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&addr,&nm,&local,&nm,port,0,0,0,FILTER_DROP);
00251     }
00252     else 
00253         return -1;
00254 }
00255 
00256 int EthernetInterface::createIpFilter(char *src, char * src_netmask, int src_port, char *dst, char * dst_netmask, int dst_port)
00257 {
00258     struct pico_ip4 src4,src_nm4,dst4,dst_nm4;
00259     
00260     if(!src)
00261         src4.addr=0;
00262     else
00263         pico_string_to_ipv4(src,&src4.addr);
00264     
00265     if(!src_netmask)
00266         src_nm4.addr=0;
00267     else
00268         pico_string_to_ipv4(src,&src_nm4.addr);    
00269         
00270     if(!dst)
00271         dst4.addr=0;
00272     else
00273         pico_string_to_ipv4(src,&dst4.addr);
00274     
00275     if(!dst_netmask)
00276         dst_nm4.addr=0;
00277     else
00278         pico_string_to_ipv4(src,&dst_nm4.addr);   
00279         
00280     return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&dst4,&dst_nm4,&src4,&src_nm4,dst_port,src_port,0,0,FILTER_DROP);
00281 }
00282 
00283 int EthernetInterface::destroyIpFilter(int filter_id)
00284 {
00285     return pico_ipv4_filter_del(filter_id);
00286 }