Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers net.c Source File

net.c

Go to the documentation of this file.
00001 /**
00002  * @file net.c
00003  * @brief TCP/IP stack core
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL ETH_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include <stdlib.h>
00034 #include "core/net.h"
00035 #include "core/socket.h"
00036 #include "core/tcp_timer.h"
00037 #include "core/ethernet.h"
00038 #include "ipv4/arp.h"
00039 #include "ipv4/ipv4.h"
00040 #include "ipv4/ipv4_routing.h"
00041 #include "ipv4/igmp.h"
00042 #include "ipv6/ipv6.h"
00043 #include "ipv6/ipv6_routing.h"
00044 #include "ipv6/mld.h"
00045 #include "ipv6/ndp.h"
00046 #include "ipv6/ndp_router_adv.h"
00047 #include "dhcp/dhcp_client.h"
00048 #include "dhcp/dhcp_server.h"
00049 #include "dns/dns_cache.h"
00050 #include "dns/dns_client.h"
00051 #include "mdns/mdns_client.h"
00052 #include "mdns/mdns_responder.h"
00053 #include "mdns/mdns_common.h"
00054 #include "dns_sd/dns_sd.h"
00055 #include "netbios/nbns_client.h"
00056 #include "netbios/nbns_responder.h"
00057 #include "netbios/nbns_common.h"
00058 #include "dns_sd/dns_sd.h"
00059 #include "mibs/mib2_module.h"
00060 #include "str.h"
00061 #include "debug.h"
00062 
00063 #if (WEB_SOCKET_SUPPORT == ENABLED)
00064    #include "web_socket/web_socket.h"
00065 #endif
00066 
00067 //TCP/IP stack handle
00068 OsTask *netTaskHandle;
00069 //Mutex preventing simultaneous access to the TCP/IP stack
00070 OsMutex netMutex;
00071 //Event object to receive notifications from device drivers
00072 OsEvent netEvent;
00073 //Network interfaces
00074 NetInterface netInterface[NET_INTERFACE_COUNT];
00075 
00076 //TCP/IP process state
00077 static bool_t netTaskRunning;
00078 //Timestamp
00079 static systime_t netTimestamp;
00080 //Pseudo-random number generator state
00081 static uint32_t prngState = 0;
00082 
00083 //Mutex to prevent simultaneous access to the callback table
00084 static OsMutex callbackTableMutex;
00085 //Table that holds the registered user callbacks
00086 static LinkChangeCallbackDesc callbackTable[NET_CALLBACK_TABLE_SIZE];
00087 
00088 //Check TCP/IP stack configuration
00089 #if (NET_STATIC_OS_RESOURCES == ENABLED)
00090 
00091 //Task responsible for handling TCP/IP events
00092 static OsTask netTaskInstance;
00093 static uint_t netTaskStack[NET_TASK_STACK_SIZE];
00094 
00095 #endif
00096 
00097 
00098 /**
00099  * @brief TCP/IP stack initialization
00100  * @return Error code
00101  **/
00102 
00103 error_t netInit(void)
00104 {
00105    error_t error;
00106    uint_t i;
00107    NetInterface *interface;
00108 
00109    //The TCP/IP process is currently suspended
00110    netTaskRunning = FALSE;
00111    //Get current time
00112    netTimestamp = osGetSystemTime();
00113 
00114    //Create a mutex to prevent simultaneous access to the TCP/IP stack
00115    if(!osCreateMutex(&netMutex))
00116    {
00117       //Failed to create mutex
00118       return ERROR_OUT_OF_RESOURCES;
00119    }
00120 
00121    //Create a event object to receive notifications from device drivers
00122    if(!osCreateEvent(&netEvent))
00123    {
00124       //Failed to create mutex
00125       return ERROR_OUT_OF_RESOURCES;
00126    }
00127 
00128    //Memory pool initialization
00129    error = memPoolInit();
00130    //Any error to report?
00131    if(error)
00132       return error;
00133 
00134    //Clear configuration data for each interface
00135    memset(netInterface, 0, sizeof(netInterface));
00136 
00137    //Save the number of interfaces
00138    MIB2_SET_INTEGER(mib2Base.ifGroup.ifNumber, NET_INTERFACE_COUNT);
00139 
00140    //Loop through network interfaces
00141    for(i = 0; i < NET_INTERFACE_COUNT; i++)
00142    {
00143       //Point to the current interface
00144       interface = &netInterface[i];
00145 
00146       //Default interface name
00147       sprintf(interface->name, "eth%u", i);
00148       //Default interface identifier
00149       interface->id = i;
00150       //Default PHY address
00151       interface->phyAddr = UINT8_MAX;
00152 
00153 #if (MIB2_SUPPORT == ENABLED)
00154       //MIB ifEntry object
00155       interface->mibIfEntry = &mib2Base.ifGroup.ifTable[i];
00156 #endif
00157 
00158       //Interface identifier
00159       MIB2_SET_INTEGER(interface->mibIfEntry->ifIndex, i + 1);
00160       //Interface name
00161       MIB2_SET_OCTET_STRING(interface->mibIfEntry->ifDescr, interface->name, strlen(interface->name));
00162       MIB2_SET_OCTET_STRING_LEN(interface->mibIfEntry->ifDescrLen, strlen(interface->name));
00163       //Default interface type
00164       MIB2_SET_INTEGER(interface->mibIfEntry->ifType, MIB2_IF_TYPE_OTHER);
00165       //Default interface state
00166       MIB2_SET_INTEGER(interface->mibIfEntry->ifAdminStatus, MIB2_IF_ADMIN_STATUS_DOWN);
00167       MIB2_SET_INTEGER(interface->mibIfEntry->ifOperStatus, MIB2_IF_OPER_STATUS_DOWN);
00168    }
00169 
00170    //Create a mutex to prevent simultaneous access to the callback table
00171    if(!osCreateMutex(&callbackTableMutex))
00172    {
00173       //Failed to create mutex
00174       return ERROR_OUT_OF_RESOURCES;
00175    }
00176 
00177    //Initialize callback table
00178    memset(callbackTable, 0, sizeof(callbackTable));
00179 
00180    //Socket related initialization
00181    error = socketInit();
00182    //Any error to report?
00183    if(error)
00184       return error;
00185 
00186 #if (WEB_SOCKET_SUPPORT == ENABLED)
00187    //WebSocket related initialization
00188    webSocketInit();
00189 #endif
00190 
00191 #if (IPV4_SUPPORT == ENABLED && IPV4_ROUTING_SUPPORT == ENABLED)
00192    //Initialize IPv4 routing table
00193    error = ipv4InitRouting();
00194    //Any error to report?
00195    if(error)
00196       return error;
00197 #endif
00198 
00199 #if (IPV6_SUPPORT == ENABLED && IPV6_ROUTING_SUPPORT == ENABLED)
00200    //Initialize IPv6 routing table
00201    error = ipv6InitRouting();
00202    //Any error to report?
00203    if(error)
00204       return error;
00205 #endif
00206 
00207 #if (UDP_SUPPORT == ENABLED)
00208    //UDP related initialization
00209    error = udpInit();
00210    //Any error to report?
00211    if(error)
00212       return error;
00213 #endif
00214 
00215 #if (TCP_SUPPORT == ENABLED)
00216    //TCP related initialization
00217    error = tcpInit();
00218    //Any error to report?
00219    if(error)
00220       return error;
00221 #endif
00222 
00223 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
00224    NBNS_CLIENT_SUPPORT == ENABLED)
00225    //DNS cache initialization
00226    error = dnsInit();
00227    //Any error to report?
00228    if(error)
00229       return error;
00230 #endif
00231 
00232    //Initialize tick counters
00233    nicTickCounter = 0;
00234 
00235 #if (PPP_SUPPORT == ENABLED)
00236    pppTickCounter = 0;
00237 #endif
00238 #if (IPV4_SUPPORT == ENABLED && ETH_SUPPORT == ENABLED)
00239    arpTickCounter = 0;
00240 #endif
00241 #if (IPV4_SUPPORT == ENABLED && IPV4_FRAG_SUPPORT == ENABLED)
00242    ipv4FragTickCounter = 0;
00243 #endif
00244 #if (IPV4_SUPPORT == ENABLED && IGMP_SUPPORT == ENABLED)
00245    igmpTickCounter = 0;
00246 #endif
00247 #if (IPV4_SUPPORT == ENABLED && AUTO_IP_SUPPORT == ENABLED)
00248    autoIpTickCounter = 0;
00249 #endif
00250 #if (IPV4_SUPPORT == ENABLED && DHCP_CLIENT_SUPPORT == ENABLED)
00251    dhcpClientTickCounter = 0;
00252 #endif
00253 #if (IPV4_SUPPORT == ENABLED && DHCP_SERVER_SUPPORT == ENABLED)
00254    dhcpServerTickCounter = 0;
00255 #endif
00256 #if (IPV6_SUPPORT == ENABLED && IPV6_FRAG_SUPPORT == ENABLED)
00257    ipv6FragTickCounter = 0;
00258 #endif
00259 #if (IPV6_SUPPORT == ENABLED && MLD_SUPPORT == ENABLED)
00260    mldTickCounter = 0;
00261 #endif
00262 #if (IPV6_SUPPORT == ENABLED && NDP_SUPPORT == ENABLED)
00263    ndpTickCounter = 0;
00264 #endif
00265 #if (IPV6_SUPPORT == ENABLED && NDP_ROUTER_ADV_SUPPORT == ENABLED)
00266    ndpRouterAdvTickCounter = 0;
00267 #endif
00268 #if (IPV6_SUPPORT == ENABLED && DHCPV6_CLIENT_SUPPORT == ENABLED)
00269    dhcpv6ClientTickCounter = 0;
00270 #endif
00271 #if (TCP_SUPPORT == ENABLED)
00272    tcpTickCounter = 0;
00273 #endif
00274 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
00275    NBNS_CLIENT_SUPPORT == ENABLED)
00276    dnsTickCounter = 0;
00277 #endif
00278 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
00279    mdnsResponderTickCounter = 0;
00280 #endif
00281 #if (DNS_SD_SUPPORT == ENABLED)
00282    dnsSdTickCounter = 0;
00283 #endif
00284 
00285 #if (NET_STATIC_OS_RESOURCES == ENABLED)
00286    //Create a task to handle TCP/IP events
00287    osCreateStaticTask(&netTaskInstance, "TCP/IP Stack", (OsTaskCode) netTask,
00288       NULL, netTaskStack, NET_TASK_STACK_SIZE, NET_TASK_PRIORITY);
00289 #else
00290    //Create a task to handle TCP/IP events
00291    netTaskHandle = osCreateTask("TCP/IP Stack", (OsTaskCode) netTask,
00292       NULL, NET_TASK_STACK_SIZE, NET_TASK_PRIORITY);
00293 
00294    //Unable to create the task?
00295    if(netTaskHandle == OS_INVALID_HANDLE)
00296       return ERROR_OUT_OF_RESOURCES;
00297 #endif
00298 
00299 #if (NET_RTOS_SUPPORT == DISABLED)
00300    //The TCP/IP process is now running
00301    netTaskRunning = TRUE;
00302 #endif
00303 
00304    //Successful initialization
00305    return NO_ERROR;
00306 }
00307 
00308 
00309 /**
00310  * @brief Set MAC address
00311  * @param[in] interface Pointer to the desired network interface
00312  * @param[in] macAddr MAC address
00313  * @return Error code
00314  **/
00315 
00316 error_t netSetMacAddr(NetInterface *interface, const MacAddr *macAddr)
00317 {
00318    //Check parameters
00319    if(interface == NULL || macAddr == NULL)
00320       return ERROR_INVALID_PARAMETER;
00321 
00322 #if (ETH_SUPPORT == ENABLED)
00323    //Get exclusive access
00324    osAcquireMutex(&netMutex);
00325 
00326    //Set MAC address
00327    interface->macAddr = *macAddr;
00328 
00329    //Generate the 64-bit interface identifier
00330    macAddrToEui64(macAddr, &interface->eui64);
00331 
00332    //Interface's physical address
00333    MIB2_SET_OCTET_STRING(interface->mibIfEntry->ifPhysAddress, &interface->macAddr, 6);
00334    MIB2_SET_OCTET_STRING_LEN(interface->mibIfEntry->ifPhysAddressLen, 6);
00335 
00336    //Release exclusive access
00337    osReleaseMutex(&netMutex);
00338 #endif
00339 
00340    //Successful processing
00341    return NO_ERROR;
00342 }
00343 
00344 
00345 /**
00346  * @brief Retrieve MAC address
00347  * @param[in] interface Pointer to the desired network interface
00348  * @param[out] macAddr MAC address
00349  * @return Error code
00350  **/
00351 
00352 error_t netGetMacAddr(NetInterface *interface, MacAddr *macAddr)
00353 {
00354    //Check parameters
00355    if(interface == NULL || macAddr == NULL)
00356       return ERROR_INVALID_PARAMETER;
00357 
00358 #if (ETH_SUPPORT == ENABLED)
00359    //Get exclusive access
00360    osAcquireMutex(&netMutex);
00361    //Get MAC address
00362    *macAddr = interface->macAddr;
00363    //Release exclusive access
00364    osReleaseMutex(&netMutex);
00365 #endif
00366 
00367    //Successful processing
00368    return NO_ERROR;
00369 }
00370 
00371 
00372 /**
00373  * @brief Set EUI-64 interface identifier
00374  * @param[in] interface Pointer to the desired network interface
00375  * @param[in] eui64 Interface identifier
00376  * @return Error code
00377  **/
00378 
00379 error_t netSetEui64(NetInterface *interface, const Eui64 *eui64)
00380 {
00381    //Check parameters
00382    if(interface == NULL || eui64 == NULL)
00383       return ERROR_INVALID_PARAMETER;
00384 
00385    //Get exclusive access
00386    osAcquireMutex(&netMutex);
00387    //Set interface identifier
00388    interface->eui64 = *eui64;
00389    //Release exclusive access
00390    osReleaseMutex(&netMutex);
00391 
00392    //Successful processing
00393    return NO_ERROR;
00394 }
00395 
00396 
00397 /**
00398  * @brief Retrieve EUI-64 interface identifier
00399  * @param[in] interface Pointer to the desired network interface
00400  * @param[out] eui64 Interface identifier
00401  * @return Error code
00402  **/
00403 
00404 error_t netGetEui64(NetInterface *interface, Eui64 *eui64)
00405 {
00406    //Check parameters
00407    if(interface == NULL || eui64 == NULL)
00408       return ERROR_INVALID_PARAMETER;
00409 
00410    //Get exclusive access
00411    osAcquireMutex(&netMutex);
00412    //Get interface identifier
00413    *eui64 = interface->eui64;
00414    //Release exclusive access
00415    osReleaseMutex(&netMutex);
00416 
00417    //Successful processing
00418    return NO_ERROR;
00419 }
00420 
00421 
00422 /**
00423  * @brief Set interface identifier
00424  * @param[in] interface Pointer to the desired network interface
00425  * @param[in] id Unique number identifying the interface
00426  * @return Error code
00427  **/
00428 
00429 error_t netSetInterfaceId(NetInterface *interface, uint32_t id)
00430 {
00431    //Check parameters
00432    if(interface == NULL)
00433       return ERROR_INVALID_PARAMETER;
00434 
00435    //Get exclusive access
00436    osAcquireMutex(&netMutex);
00437    //Set interface identifier
00438    interface->id = id;
00439    //Release exclusive access
00440    osReleaseMutex(&netMutex);
00441 
00442    //Successful processing
00443    return NO_ERROR;
00444 }
00445 
00446 
00447 /**
00448  * @brief Set interface name
00449  * @param[in] interface Pointer to the desired network interface
00450  * @param[in] name NULL-terminated string that contains the interface name
00451  * @return Error code
00452  **/
00453 
00454 error_t netSetInterfaceName(NetInterface *interface, const char_t *name)
00455 {
00456 #if (MIB2_SUPPORT == ENABLED)
00457    size_t n;
00458 #endif
00459 
00460    //Check parameters
00461    if(interface == NULL || name == NULL)
00462       return ERROR_INVALID_PARAMETER;
00463 
00464    //Get exclusive access
00465    osAcquireMutex(&netMutex);
00466 
00467    //Set interface name
00468    strSafeCopy(interface->name, name, NET_MAX_IF_NAME_LEN);
00469 
00470 #if (MIB2_SUPPORT == ENABLED)
00471    //Get the length of the string
00472    n = strlen(interface->name);
00473 
00474    //Text string containing information about the interface
00475    MIB2_SET_OCTET_STRING(interface->mibIfEntry->ifDescr, interface->name, n);
00476    MIB2_SET_OCTET_STRING_LEN(interface->mibIfEntry->ifDescrLen, n);
00477 #endif
00478 
00479    //Release exclusive access
00480    osReleaseMutex(&netMutex);
00481 
00482    //Successful processing
00483    return NO_ERROR;
00484 }
00485 
00486 
00487 /**
00488  * @brief Set host name
00489  * @param[in] interface Pointer to the desired network interface
00490  * @param[in] name NULL-terminated string that contains the host name
00491  * @return Error code
00492  **/
00493 
00494 error_t netSetHostname(NetInterface *interface, const char_t *name)
00495 {
00496    //Check parameters
00497    if(interface == NULL || name == NULL)
00498       return ERROR_INVALID_PARAMETER;
00499 
00500    //Get exclusive access
00501    osAcquireMutex(&netMutex);
00502 
00503    //Set host name
00504    strSafeCopy(interface->hostname, name, NET_MAX_HOSTNAME_LEN);
00505 
00506    //Release exclusive access
00507    osReleaseMutex(&netMutex);
00508 
00509    //Successful processing
00510    return NO_ERROR;
00511 }
00512 
00513 
00514 /**
00515  * @brief Set proxy server
00516  * @param[in] interface Pointer to the desired network interface
00517  * @param[in] name Proxy server name
00518  * @param[in] port Proxy server port
00519  * @return Error code
00520  **/
00521 
00522 error_t netSetProxy(NetInterface *interface, const char_t *name, uint16_t port)
00523 {
00524    //Check parameters
00525    if(interface == NULL || name == NULL)
00526       return ERROR_INVALID_PARAMETER;
00527 
00528    //Get exclusive access
00529    osAcquireMutex(&netMutex);
00530 
00531    //Set proxy server name
00532    strSafeCopy(interface->proxyName, name, NET_MAX_PROXY_NAME_LEN);
00533    //Set proxy server port
00534    interface->proxyPort = port;
00535 
00536    //Release exclusive access
00537    osReleaseMutex(&netMutex);
00538 
00539    //Successful processing
00540    return NO_ERROR;
00541 }
00542 
00543 
00544 /**
00545  * @brief Set Ethernet MAC driver
00546  * @param[in] interface Pointer to the desired network interface
00547  * @param[in] driver Ethernet MAC driver
00548  * @return Error code
00549  **/
00550 
00551 error_t netSetDriver(NetInterface *interface, const NicDriver *driver)
00552 {
00553    //Check parameters
00554    if(interface == NULL || driver == NULL)
00555       return ERROR_INVALID_PARAMETER;
00556 
00557    //Get exclusive access
00558    osAcquireMutex(&netMutex);
00559 
00560    //Set Ethernet MAC driver
00561    interface->nicDriver = driver;
00562 
00563    //Set interface type
00564    if(driver->type == NIC_TYPE_ETHERNET)
00565    {
00566       //Ethernet interface
00567       MIB2_SET_INTEGER(interface->mibIfEntry->ifType, MIB2_IF_TYPE_ETHERNET_CSMACD);
00568    }
00569    else if(driver->type == NIC_TYPE_PPP)
00570    {
00571       //PPP interface
00572       MIB2_SET_INTEGER(interface->mibIfEntry->ifType, MIB2_IF_TYPE_PPP);
00573    }
00574    else if(driver->type == NIC_TYPE_6LOWPAN)
00575    {
00576       //IEEE 802.15.4 WPAN interface
00577       MIB2_SET_INTEGER(interface->mibIfEntry->ifType, MIB2_IF_TYPE_IEEE_802_15_4);
00578    }
00579    else
00580    {
00581       //Unknown interface type
00582       MIB2_SET_INTEGER(interface->mibIfEntry->ifType, MIB2_IF_TYPE_OTHER);
00583    }
00584 
00585    //Set interface MTU
00586    MIB2_SET_INTEGER(interface->mibIfEntry->ifMtu, driver->mtu);
00587    //Update interface state
00588    MIB2_SET_INTEGER(interface->mibIfEntry->ifAdminStatus, MIB2_IF_ADMIN_STATUS_UP);
00589 
00590    //Release exclusive access
00591    osReleaseMutex(&netMutex);
00592 
00593    //Successful processing
00594    return NO_ERROR;
00595 }
00596 
00597 
00598 /**
00599  * @brief Set Ethernet PHY driver
00600  * @param[in] interface Pointer to the desired network interface
00601  * @param[in] driver Ethernet PHY driver (can be NULL for MAC + PHY controller)
00602  * @return Error code
00603  **/
00604 
00605 error_t netSetPhyDriver(NetInterface *interface, const PhyDriver *driver)
00606 {
00607    //Check parameters
00608    if(interface == NULL || driver == NULL)
00609       return ERROR_INVALID_PARAMETER;
00610 
00611    //Get exclusive access
00612    osAcquireMutex(&netMutex);
00613    //Set Ethernet PHY driver
00614    interface->phyDriver = driver;
00615    //Release exclusive access
00616    osReleaseMutex(&netMutex);
00617 
00618    //Successful processing
00619    return NO_ERROR;
00620 }
00621 
00622 
00623 /**
00624  * @brief Set Ethernet PHY address
00625  * @param[in] interface Pointer to the desired network interface
00626  * @param[in] phyAddr PHY address
00627  * @return Error code
00628  **/
00629 
00630 error_t netSetPhyAddr(NetInterface *interface, uint8_t phyAddr)
00631 {
00632    //Make sure the network interface is valid
00633    if(interface == NULL)
00634       return ERROR_INVALID_PARAMETER;
00635 
00636    //Make sure the PHY address is valid
00637    if(phyAddr >= 32)
00638       return ERROR_OUT_OF_RANGE;
00639 
00640    //Get exclusive access
00641    osAcquireMutex(&netMutex);
00642    //Set PHY address
00643    interface->phyAddr = phyAddr;
00644    //Release exclusive access
00645    osReleaseMutex(&netMutex);
00646 
00647    //Successful processing
00648    return NO_ERROR;
00649 }
00650 
00651 
00652 /**
00653  * @brief Set SPI driver
00654  * @param[in] interface Pointer to the desired network interface
00655  * @param[in] driver Underlying SPI driver
00656  * @return Error code
00657  **/
00658 
00659 error_t netSetSpiDriver(NetInterface *interface, const SpiDriver *driver)
00660 {
00661    //Check parameters
00662    if(interface == NULL || driver == NULL)
00663       return ERROR_INVALID_PARAMETER;
00664 
00665    //Get exclusive access
00666    osAcquireMutex(&netMutex);
00667    //Set SPI driver
00668    interface->spiDriver = driver;
00669    //Release exclusive access
00670    osReleaseMutex(&netMutex);
00671 
00672    //Successful processing
00673    return NO_ERROR;
00674 }
00675 
00676 
00677 /**
00678  * @brief Set UART driver
00679  * @param[in] interface Pointer to the desired network interface
00680  * @param[in] driver Underlying UART driver
00681  * @return Error code
00682  **/
00683 
00684 error_t netSetUartDriver(NetInterface *interface, const UartDriver *driver)
00685 {
00686    //Check parameters
00687    if(interface == NULL || driver == NULL)
00688       return ERROR_INVALID_PARAMETER;
00689 
00690    //Get exclusive access
00691    osAcquireMutex(&netMutex);
00692    //Set UART driver
00693    interface->uartDriver = driver;
00694    //Release exclusive access
00695    osReleaseMutex(&netMutex);
00696 
00697    //Successful processing
00698    return NO_ERROR;
00699 }
00700 
00701 
00702 /**
00703  * @brief Set external interrupt line driver
00704  * @param[in] interface Pointer to the desired network interface
00705  * @param[in] driver Underlying SPI driver
00706  * @return Error code
00707  **/
00708 
00709 error_t netSetExtIntDriver(NetInterface *interface, const ExtIntDriver *driver)
00710 {
00711    //Check parameters
00712    if(interface == NULL || driver == NULL)
00713       return ERROR_INVALID_PARAMETER;
00714 
00715    //Get exclusive access
00716    osAcquireMutex(&netMutex);
00717    //Set external interrupt line driver
00718    interface->extIntDriver = driver;
00719    //Release exclusive access
00720    osReleaseMutex(&netMutex);
00721 
00722    //Successful processing
00723    return NO_ERROR;
00724 }
00725 
00726 
00727 /**
00728  * @brief Set link state (for virtual drivers only)
00729  * @param[in] interface Pointer to the desired network interface
00730  * @param[in] linkState Link state
00731  * @return Error code
00732  **/
00733 
00734 error_t netSetLinkState(NetInterface *interface, NicLinkState linkState)
00735 {
00736    //Make sure the network interface is valid
00737    if(interface == NULL)
00738       return ERROR_INVALID_PARAMETER;
00739 
00740    //Get exclusive access
00741    osAcquireMutex(&netMutex);
00742 
00743    //Link state changed?
00744    if(linkState != interface->linkState)
00745    {
00746       //Update link state
00747       interface->linkState = linkState;
00748       //Process link state change event
00749       nicNotifyLinkChange(interface);
00750    }
00751 
00752    //Release exclusive access
00753    osReleaseMutex(&netMutex);
00754 
00755    //Successful processing
00756    return NO_ERROR;
00757 }
00758 
00759 
00760 /**
00761  * @brief Get link state
00762  * @param[in] interface Pointer to the desired network interface
00763  * @return Link state
00764  **/
00765 
00766 bool_t netGetLinkState(NetInterface *interface)
00767 {
00768    bool_t linkState;
00769 
00770    //Make sure the network interface is valid
00771    if(interface == NULL)
00772       return FALSE;
00773 
00774    //Get exclusive access
00775    osAcquireMutex(&netMutex);
00776    //Retrieve link state
00777    linkState = interface->linkState;
00778    //Release exclusive access
00779    osReleaseMutex(&netMutex);
00780 
00781    //Return link state
00782    return linkState;
00783 }
00784 
00785 
00786 /**
00787  * @brief Configure network interface
00788  * @param[in] interface Network interface to configure
00789  * @return Error code
00790  **/
00791 
00792 error_t netConfigInterface(NetInterface *interface)
00793 {
00794    error_t error;
00795 
00796    //Make sure the network interface is valid
00797    if(interface == NULL)
00798       return ERROR_INVALID_PARAMETER;
00799 
00800    //Get exclusive access
00801    osAcquireMutex(&netMutex);
00802 
00803    //Disable hardware interrupts
00804    interface->nicDriver->disableIrq(interface);
00805 
00806    //Start of exception handling block
00807    do
00808    {
00809       //Receive notifications when the transmitter is ready to send
00810       if(!osCreateEvent(&interface->nicTxEvent))
00811       {
00812          //Failed to create event object
00813          error = ERROR_OUT_OF_RESOURCES;
00814          //Stop immediately
00815          break;
00816       }
00817 
00818       //Network controller initialization
00819       error = interface->nicDriver->init(interface);
00820       //Any error to report?
00821       if(error)
00822          break;
00823 
00824 #if (ETH_SUPPORT == ENABLED)
00825       //Ethernet related initialization
00826       error = ethInit(interface);
00827       //Any error to report?
00828       if(error)
00829          break;
00830 
00831       //Interface's physical address
00832       MIB2_SET_OCTET_STRING(interface->mibIfEntry->ifPhysAddress, &interface->macAddr, 6);
00833       MIB2_SET_OCTET_STRING_LEN(interface->mibIfEntry->ifPhysAddressLen, 6);
00834 #endif
00835 
00836 #if (IPV4_SUPPORT == ENABLED)
00837       //IPv4 initialization
00838       error = ipv4Init(interface);
00839       //Any error to report?
00840       if(error)
00841          break;
00842 
00843 #if (ETH_SUPPORT == ENABLED)
00844       //ARP cache initialization
00845       error = arpInit(interface);
00846       //Any error to report?
00847       if(error)
00848          break;
00849 #endif
00850 
00851 #if (IGMP_SUPPORT == ENABLED)
00852       //IGMP related initialization
00853       error = igmpInit(interface);
00854       //Any error to report?
00855       if(error)
00856          break;
00857 
00858       //Join the all-systems group
00859       error = ipv4JoinMulticastGroup(interface, IGMP_ALL_SYSTEMS_ADDR);
00860       //Any error to report?
00861       if(error)
00862          break;
00863 #endif
00864 
00865 #if (NBNS_CLIENT_SUPPORT == ENABLED || NBNS_RESPONDER_SUPPORT == ENABLED)
00866       //NetBIOS Name Service related initialization
00867       error = nbnsInit(interface);
00868       //Any error to report?
00869       if(error)
00870          break;
00871 #endif
00872 #endif
00873 
00874 #if (IPV6_SUPPORT == ENABLED)
00875       //IPv6 initialization
00876       error = ipv6Init(interface);
00877       //Any error to report?
00878       if(error)
00879          break;
00880 
00881 #if (NDP_SUPPORT == ENABLED)
00882       //NDP related initialization
00883       error = ndpInit(interface);
00884       //Any error to report?
00885       if(error)
00886          break;
00887 #endif
00888 
00889 #if (MLD_SUPPORT == ENABLED)
00890       //MLD related initialization
00891       error = mldInit(interface);
00892       //Any error to report?
00893       if(error)
00894          break;
00895 #endif
00896 
00897       //Join the All-Nodes multicast address
00898       error = ipv6JoinMulticastGroup(interface, &IPV6_LINK_LOCAL_ALL_NODES_ADDR);
00899       //Any error to report?
00900       if(error)
00901          break;
00902 #endif
00903 
00904 #if (MDNS_CLIENT_SUPPORT == ENABLED || MDNS_RESPONDER_SUPPORT == ENABLED)
00905       //mDNS related initialization
00906       error = mdnsInit(interface);
00907       //Any error to report?
00908       if(error)
00909          break;
00910 #endif
00911 
00912       //End of exception handling block
00913    } while(0);
00914 
00915    //Check status code
00916    if(!error)
00917    {
00918       //The network interface is now fully configured
00919       interface->configured = TRUE;
00920 
00921       //Check whether the TCP/IP process is running
00922       if(netTaskRunning)
00923       {
00924          //Interrupts can be safely enabled
00925          interface->nicDriver->enableIrq(interface);
00926       }
00927    }
00928    else
00929    {
00930       //Clean up side effects before returning
00931       osDeleteEvent(&interface->nicTxEvent);
00932    }
00933 
00934    //Release exclusive access
00935    osReleaseMutex(&netMutex);
00936 
00937    //Return status code
00938    return error;
00939 }
00940 
00941 
00942 /**
00943  * @brief TCP/IP events handling
00944  **/
00945 
00946 void netTask(void)
00947 {
00948    uint_t i;
00949    bool_t status;
00950    systime_t time;
00951    systime_t timeout;
00952    NetInterface *interface;
00953 
00954 #if (NET_RTOS_SUPPORT == ENABLED)
00955    //Get exclusive access
00956    osAcquireMutex(&netMutex);
00957 
00958    //The TCP/IP process is now running
00959    netTaskRunning = TRUE;
00960 
00961    //Loop through network interfaces
00962    for(i = 0; i < NET_INTERFACE_COUNT; i++)
00963    {
00964       //Point to the current network interface
00965       interface = &netInterface[i];
00966 
00967       //Check whether the interface is fully configured
00968       if(interface->configured)
00969       {
00970          //Interrupts can be safely enabled
00971          interface->nicDriver->enableIrq(interface);
00972       }
00973    }
00974 
00975    //Release exclusive access
00976    osReleaseMutex(&netMutex);
00977 
00978    //Main loop
00979    while(1)
00980    {
00981 #endif
00982       //Get current time
00983       time = osGetSystemTime();
00984 
00985       //Compute the maximum blocking time when waiting for an event
00986       if(timeCompare(time, netTimestamp) < 0)
00987          timeout = netTimestamp - time;
00988       else
00989          timeout = 0;
00990 
00991       //Receive notifications when a frame has been received, or the
00992       //link state of any network interfaces has changed
00993       status = osWaitForEvent(&netEvent, timeout);
00994 
00995       //Check whether the specified event is in signaled state
00996       if(status)
00997       {
00998          //Get exclusive access
00999          osAcquireMutex(&netMutex);
01000 
01001          //Process events
01002          for(i = 0; i < NET_INTERFACE_COUNT; i++)
01003          {
01004             //Point to the current network interface
01005             interface = &netInterface[i];
01006 
01007             //Check whether a NIC event is pending
01008             if(interface->nicEvent)
01009             {
01010                //Acknowledge the event by clearing the flag
01011                interface->nicEvent = FALSE;
01012 
01013                //Disable hardware interrupts
01014                interface->nicDriver->disableIrq(interface);
01015                //Handle NIC events
01016                interface->nicDriver->eventHandler(interface);
01017                //Re-enable hardware interrupts
01018                interface->nicDriver->enableIrq(interface);
01019             }
01020 
01021             //Check whether a PHY event is pending
01022             if(interface->phyEvent)
01023             {
01024                //Acknowledge the event by clearing the flag
01025                interface->phyEvent = FALSE;
01026 
01027                //Disable hardware interrupts
01028                interface->nicDriver->disableIrq(interface);
01029                //Handle PHY events
01030                interface->phyDriver->eventHandler(interface);
01031                //Re-enable hardware interrupts
01032                interface->nicDriver->enableIrq(interface);
01033             }
01034          }
01035 
01036          //Release exclusive access
01037          osReleaseMutex(&netMutex);
01038       }
01039 
01040       //Check current time
01041       if(timeCompare(time, netTimestamp) > 0)
01042       {
01043          //Get exclusive access
01044          osAcquireMutex(&netMutex);
01045          //Handle periodic operations
01046          netTick();
01047          //Release exclusive access
01048          osReleaseMutex(&netMutex);
01049 
01050          //Next event
01051          netTimestamp = time + NET_TICK_INTERVAL;
01052       }
01053 #if (NET_RTOS_SUPPORT == ENABLED)
01054    }
01055 #endif
01056 }
01057 
01058 
01059 /**
01060  * @brief Manage TCP/IP timers
01061  **/
01062 
01063 void netTick(void)
01064 {
01065    uint_t i;
01066 
01067    //Increment tick counter
01068    nicTickCounter += NET_TICK_INTERVAL;
01069 
01070    //Handle periodic operations such as polling the link state
01071    if(nicTickCounter >= NIC_TICK_INTERVAL)
01072    {
01073       //Loop through network interfaces
01074       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01075       {
01076          //Make sure the interface has been properly configured
01077          if(netInterface[i].configured)
01078             nicTick(&netInterface[i]);
01079       }
01080 
01081       //Reset tick counter
01082       nicTickCounter = 0;
01083    }
01084 
01085 #if (PPP_SUPPORT == ENABLED)
01086    //Increment tick counter
01087    pppTickCounter += NET_TICK_INTERVAL;
01088 
01089    //Manage PPP related timers
01090    if(pppTickCounter >= PPP_TICK_INTERVAL)
01091    {
01092       //Loop through network interfaces
01093       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01094       {
01095          //Make sure the interface has been properly configured
01096          if(netInterface[i].configured)
01097             pppTick(&netInterface[i]);
01098       }
01099 
01100       //Reset tick counter
01101       pppTickCounter = 0;
01102    }
01103 #endif
01104 
01105 #if (IPV4_SUPPORT == ENABLED && ETH_SUPPORT == ENABLED)
01106    //Increment tick counter
01107    arpTickCounter += NET_TICK_INTERVAL;
01108 
01109    //Manage ARP cache
01110    if(arpTickCounter >= ARP_TICK_INTERVAL)
01111    {
01112       //Loop through network interfaces
01113       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01114       {
01115          //Make sure the interface has been properly configured
01116          if(netInterface[i].configured)
01117             arpTick(&netInterface[i]);
01118       }
01119 
01120       //Reset tick counter
01121       arpTickCounter = 0;
01122    }
01123 #endif
01124 
01125 #if (IPV4_SUPPORT == ENABLED && IPV4_FRAG_SUPPORT == ENABLED)
01126    //Increment tick counter
01127    ipv4FragTickCounter += NET_TICK_INTERVAL;
01128 
01129    //Handle IPv4 fragment reassembly timeout
01130    if(ipv4FragTickCounter >= IPV4_FRAG_TICK_INTERVAL)
01131    {
01132       //Loop through network interfaces
01133       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01134       {
01135          //Make sure the interface has been properly configured
01136          if(netInterface[i].configured)
01137             ipv4FragTick(&netInterface[i]);
01138       }
01139 
01140       //Reset tick counter
01141       ipv4FragTickCounter = 0;
01142    }
01143 #endif
01144 
01145 #if (IPV4_SUPPORT == ENABLED && IGMP_SUPPORT == ENABLED)
01146    //Increment tick counter
01147    igmpTickCounter += NET_TICK_INTERVAL;
01148 
01149    //Handle IGMP related timers
01150    if(igmpTickCounter >= IGMP_TICK_INTERVAL)
01151    {
01152       //Loop through network interfaces
01153       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01154       {
01155          //Make sure the interface has been properly configured
01156          if(netInterface[i].configured)
01157             igmpTick(&netInterface[i]);
01158       }
01159 
01160       //Reset tick counter
01161       igmpTickCounter = 0;
01162    }
01163 #endif
01164 
01165 #if (IPV4_SUPPORT == ENABLED && AUTO_IP_SUPPORT == ENABLED)
01166    //Increment tick counter
01167    autoIpTickCounter += NET_TICK_INTERVAL;
01168 
01169    //Handle Auto-IP related timers
01170    if(autoIpTickCounter >= AUTO_IP_TICK_INTERVAL)
01171    {
01172       //Loop through network interfaces
01173       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01174          autoIpTick(netInterface[i].autoIpContext);
01175 
01176       //Reset tick counter
01177       autoIpTickCounter = 0;
01178    }
01179 #endif
01180 
01181 #if (IPV4_SUPPORT == ENABLED && DHCP_CLIENT_SUPPORT == ENABLED)
01182    //Increment tick counter
01183    dhcpClientTickCounter += NET_TICK_INTERVAL;
01184 
01185    //Handle DHCP client related timers
01186    if(dhcpClientTickCounter >= DHCP_CLIENT_TICK_INTERVAL)
01187    {
01188       //Loop through network interfaces
01189       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01190          dhcpClientTick(netInterface[i].dhcpClientContext);
01191 
01192       //Reset tick counter
01193       dhcpClientTickCounter = 0;
01194    }
01195 #endif
01196 
01197 #if (IPV4_SUPPORT == ENABLED && DHCP_SERVER_SUPPORT == ENABLED)
01198    //Increment tick counter
01199    dhcpServerTickCounter += NET_TICK_INTERVAL;
01200 
01201    //Handle DHCP server related timers
01202    if(dhcpServerTickCounter >= DHCP_SERVER_TICK_INTERVAL)
01203    {
01204       //Loop through network interfaces
01205       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01206          dhcpServerTick(netInterface[i].dhcpServerContext);
01207 
01208       //Reset tick counter
01209       dhcpServerTickCounter = 0;
01210    }
01211 #endif
01212 
01213 #if (IPV6_SUPPORT == ENABLED && IPV6_FRAG_SUPPORT == ENABLED)
01214    //Increment tick counter
01215    ipv6FragTickCounter += NET_TICK_INTERVAL;
01216 
01217    //Handle IPv6 fragment reassembly timeout
01218    if(ipv6FragTickCounter >= IPV6_FRAG_TICK_INTERVAL)
01219    {
01220       //Loop through network interfaces
01221       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01222       {
01223          //Make sure the interface has been properly configured
01224          if(netInterface[i].configured)
01225             ipv6FragTick(&netInterface[i]);
01226       }
01227 
01228       //Reset tick counter
01229       ipv6FragTickCounter = 0;
01230    }
01231 #endif
01232 
01233 #if (IPV6_SUPPORT == ENABLED && MLD_SUPPORT == ENABLED)
01234    //Increment tick counter
01235    mldTickCounter += NET_TICK_INTERVAL;
01236 
01237    //Handle MLD related timers
01238    if(mldTickCounter >= MLD_TICK_INTERVAL)
01239    {
01240       //Loop through network interfaces
01241       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01242       {
01243          //Make sure the interface has been properly configured
01244          if(netInterface[i].configured)
01245             mldTick(&netInterface[i]);
01246       }
01247 
01248       //Reset tick counter
01249       mldTickCounter = 0;
01250    }
01251 #endif
01252 
01253 #if (IPV6_SUPPORT == ENABLED && NDP_SUPPORT == ENABLED)
01254    //Increment tick counter
01255    ndpTickCounter += NET_TICK_INTERVAL;
01256 
01257    //Handle NDP related timers
01258    if(ndpTickCounter >= NDP_TICK_INTERVAL)
01259    {
01260       //Loop through network interfaces
01261       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01262       {
01263          //Make sure the interface has been properly configured
01264          if(netInterface[i].configured)
01265             ndpTick(&netInterface[i]);
01266       }
01267 
01268       //Reset tick counter
01269       ndpTickCounter = 0;
01270    }
01271 #endif
01272 
01273 #if (IPV6_SUPPORT == ENABLED && NDP_ROUTER_ADV_SUPPORT == ENABLED)
01274    //Increment tick counter
01275    ndpRouterAdvTickCounter += NET_TICK_INTERVAL;
01276 
01277    //Handle RA service related timers
01278    if(ndpRouterAdvTickCounter >= NDP_ROUTER_ADV_TICK_INTERVAL)
01279    {
01280       //Loop through network interfaces
01281       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01282          ndpRouterAdvTick(netInterface[i].ndpRouterAdvContext);
01283 
01284       //Reset tick counter
01285       ndpRouterAdvTickCounter = 0;
01286    }
01287 #endif
01288 
01289 #if (IPV6_SUPPORT == ENABLED && DHCPV6_CLIENT_SUPPORT == ENABLED)
01290    //Increment tick counter
01291    dhcpv6ClientTickCounter += NET_TICK_INTERVAL;
01292 
01293    //Handle DHCPv6 client related timers
01294    if(dhcpv6ClientTickCounter >= DHCPV6_CLIENT_TICK_INTERVAL)
01295    {
01296       //Loop through network interfaces
01297       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01298          dhcpv6ClientTick(netInterface[i].dhcpv6ClientContext);
01299 
01300       //Reset tick counter
01301       dhcpv6ClientTickCounter = 0;
01302    }
01303 #endif
01304 
01305 #if (TCP_SUPPORT == ENABLED)
01306    //Increment tick counter
01307    tcpTickCounter += NET_TICK_INTERVAL;
01308 
01309    //Manage TCP related timers
01310    if(tcpTickCounter >= TCP_TICK_INTERVAL)
01311    {
01312       //TCP timer handler
01313       tcpTick();
01314       //Reset tick counter
01315       tcpTickCounter = 0;
01316    }
01317 #endif
01318 
01319 #if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
01320 NBNS_CLIENT_SUPPORT == ENABLED)
01321    //Increment tick counter
01322    dnsTickCounter += NET_TICK_INTERVAL;
01323 
01324    //Manage DNS cache
01325    if(dnsTickCounter >= DNS_TICK_INTERVAL)
01326    {
01327       //DNS timer handler
01328       dnsTick();
01329       //Reset tick counter
01330       dnsTickCounter = 0;
01331    }
01332 #endif
01333 
01334 #if (MDNS_RESPONDER_SUPPORT == ENABLED)
01335    //Increment tick counter
01336    mdnsResponderTickCounter += NET_TICK_INTERVAL;
01337 
01338    //Manage mDNS probing and announcing
01339    if(mdnsResponderTickCounter >= MDNS_RESPONDER_TICK_INTERVAL)
01340    {
01341       //Loop through network interfaces
01342       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01343          mdnsResponderTick(netInterface[i].mdnsResponderContext);
01344 
01345       //Reset tick counter
01346       mdnsResponderTickCounter = 0;
01347    }
01348 #endif
01349 
01350 #if (DNS_SD_SUPPORT == ENABLED)
01351    //Increment tick counter
01352    dnsSdTickCounter += NET_TICK_INTERVAL;
01353 
01354    //Manage DNS-SD probing and announcing
01355    if(dnsSdTickCounter >= DNS_SD_TICK_INTERVAL)
01356    {
01357       //Loop through network interfaces
01358       for(i = 0; i < NET_INTERFACE_COUNT; i++)
01359          dnsSdTick(netInterface[i].dnsSdContext);
01360 
01361       //Reset tick counter
01362       dnsSdTickCounter = 0;
01363    }
01364 #endif
01365 }
01366 
01367 
01368 /**
01369  * @brief Get default network interface
01370  * @return Pointer to the default network interface to be used
01371  **/
01372 
01373 NetInterface *netGetDefaultInterface(void)
01374 {
01375    //Default network interface
01376    return &netInterface[0];
01377 }
01378 
01379 
01380 /**
01381  * @brief Seed pseudo-random number generator
01382  * @param[in] seed An integer value to be used as seed by the pseudo-random number generator
01383  * @return Error code
01384  **/
01385 
01386 error_t netInitRand(uint32_t seed)
01387 {
01388    //Seed the pseudo-random number generator
01389    prngState += seed;
01390 
01391    //Successful processing
01392    return NO_ERROR;
01393 }
01394 
01395 
01396 /**
01397  * @brief Get a random value
01398  * @return Error code
01399  **/
01400 
01401 uint32_t netGetRand(void)
01402 {
01403    uint32_t result;
01404 
01405    //Use a linear congruential generator (LCG) to update the state of the PRNG
01406    prngState *= 1103515245;
01407    prngState += 12345;
01408    result = (prngState >> 16) & 0x07FF;
01409 
01410    prngState *= 1103515245;
01411    prngState += 12345;
01412    result <<= 10;
01413    result |= (prngState >> 16) & 0x03FF;
01414 
01415    prngState *= 1103515245;
01416    prngState += 12345;
01417    result <<= 10;
01418    result |= (prngState >> 16) & 0x03FF;
01419 
01420    //Return the resulting value
01421    return result;
01422 }
01423 
01424 
01425 /**
01426  * @brief Get a random value in the specified range
01427  * @param[in] min Lower bound
01428  * @param[in] max Upper bound
01429  * @return Random value in the specified range
01430  **/
01431 
01432 int32_t netGetRandRange(int32_t min, int32_t max)
01433 {
01434    //Return a random value in the given range
01435    return min + netGetRand() % (max - min + 1);
01436 }
01437 
01438 
01439 /**
01440  * @brief Register link change callback
01441  * @param[in] interface Underlying network interface
01442  * @param[in] callback Callback function to be called when the link state changed
01443  * @param[in] params Callback function parameter (optional)
01444  * @param[out] cookie Identifier that can be used to unregister the callback function
01445  * @return Error code
01446  **/
01447 
01448 error_t netAttachLinkChangeCallback(NetInterface *interface,
01449    LinkChangeCallback callback, void *params, uint_t *cookie)
01450 {
01451    uint_t i;
01452    LinkChangeCallbackDesc *entry;
01453 
01454    //Acquire exclusive access to the callback table
01455    osAcquireMutex(&callbackTableMutex);
01456 
01457    //Loop through the table
01458    for(i = 0; i < NET_CALLBACK_TABLE_SIZE; i++)
01459    {
01460       //Point to the current entry
01461       entry = &callbackTable[i];
01462 
01463       //Check whether the entry is currently in used
01464       if(entry->callback == NULL)
01465       {
01466          //Create a new entry
01467          entry->interface = interface;
01468          entry->callback = callback;
01469          entry->params = params;
01470          //We are done
01471          break;
01472       }
01473    }
01474 
01475    //Release exclusive access to the callback table
01476    osReleaseMutex(&callbackTableMutex);
01477 
01478    //Failed to attach the specified user callback?
01479    if(i >= NET_CALLBACK_TABLE_SIZE)
01480       return ERROR_OUT_OF_RESOURCES;
01481 
01482    //Return a cookie that can be used later to unregister the callback
01483    if(cookie != NULL)
01484       *cookie = i;
01485 
01486    //Successful processing
01487    return NO_ERROR;
01488 }
01489 
01490 
01491 /**
01492  * @brief Unregister link change callback
01493  * @param[in] cookie Identifier specifying the callback to be unregistered
01494  * @return Error code
01495  **/
01496 
01497 error_t netDetachLinkChangeCallback(uint_t cookie)
01498 {
01499    //Make sure the cookie is valid
01500    if(cookie >= NET_CALLBACK_TABLE_SIZE)
01501       return ERROR_INVALID_PARAMETER;
01502 
01503    //Acquire exclusive access to the callback table
01504    osAcquireMutex(&callbackTableMutex);
01505    //Unregister user callback
01506    callbackTable[cookie].callback = NULL;
01507    //Release exclusive access to the callback table
01508    osReleaseMutex(&callbackTableMutex);
01509 
01510    //Successful processing
01511    return NO_ERROR;
01512 }
01513 
01514 
01515 /**
01516  * @brief Invoke link change callback
01517  * @param[in] interface Underlying network interface
01518  * @param[in] linkState Link state
01519  **/
01520 
01521 void netInvokeLinkChangeCallback(NetInterface *interface, bool_t linkState)
01522 {
01523    uint_t i;
01524    LinkChangeCallbackDesc *entry;
01525 
01526    //Acquire exclusive access to the callback table
01527    osAcquireMutex(&callbackTableMutex);
01528 
01529    //Loop through the table
01530    for(i = 0; i < NET_CALLBACK_TABLE_SIZE; i++)
01531    {
01532       //Point to the current entry
01533       entry = &callbackTable[i];
01534 
01535       //Any registered callback?
01536       if(entry->callback != NULL)
01537       {
01538          //Check whether the network interface matches the current entry
01539          if(entry->interface == NULL || entry->interface == interface)
01540          {
01541             //Invoke user callback function
01542             entry->callback(interface, linkState, entry->params);
01543          }
01544       }
01545    }
01546 
01547    //Release exclusive access to the callback table
01548    osReleaseMutex(&callbackTableMutex);
01549 }
01550