Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers wilc1000_driver.c Source File

wilc1000_driver.c

Go to the documentation of this file.
00001 /**
00002  * @file wilc1000_driver.c
00003  * @brief WILC1000 Wi-Fi controller
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 NIC_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include "driver/include/m2m_wifi.h"
00034 #include "core/net.h"
00035 #include "wilc1000_driver.h"
00036 #include "wilc1000_config.h"
00037 #include "debug.h"
00038 
00039 //Underlying network interface
00040 static NetInterface *wilc1000StaInterface = NULL;
00041 static NetInterface *wilc1000ApInterface = NULL;
00042 
00043 //Transmit buffer
00044 static uint8_t txBuffer[WILC1000_TX_BUFFER_SIZE];
00045 //Receive buffer
00046 static uint8_t rxBuffer[WILC1000_RX_BUFFER_SIZE];
00047 
00048 
00049 /**
00050  * @brief WILC1000 driver (STA mode)
00051  **/
00052 
00053 const NicDriver wilc1000StaDriver =
00054 {
00055    NIC_TYPE_ETHERNET,
00056    ETH_MTU,
00057    wilc1000Init,
00058    wilc1000Tick,
00059    wilc1000EnableIrq,
00060    wilc1000DisableIrq,
00061    wilc1000EventHandler,
00062    wilc1000SendPacket,
00063    wilc1000SetMulticastFilter,
00064    NULL,
00065    NULL,
00066    NULL,
00067    TRUE,
00068    TRUE,
00069    TRUE,
00070    TRUE
00071 };
00072 
00073 
00074 /**
00075  * @brief WILC1000 driver (AP mode)
00076  **/
00077 
00078 const NicDriver wilc1000ApDriver =
00079 {
00080    NIC_TYPE_ETHERNET,
00081    ETH_MTU,
00082    wilc1000Init,
00083    wilc1000Tick,
00084    wilc1000EnableIrq,
00085    wilc1000DisableIrq,
00086    wilc1000EventHandler,
00087    wilc1000SendPacket,
00088    wilc1000SetMulticastFilter,
00089    NULL,
00090    NULL,
00091    NULL,
00092    TRUE,
00093    TRUE,
00094    TRUE,
00095    TRUE
00096 };
00097 
00098 
00099 /**
00100  * @brief WILC1000 initialization
00101  * @param[in] interface Underlying network interface
00102  * @return Error code
00103  **/
00104 
00105 error_t wilc1000Init(NetInterface *interface)
00106 {
00107    int8_t status;
00108    tstrWifiInitParam param;
00109    MacAddr staMacAddr;
00110    MacAddr apMacAddr;
00111 
00112    //STA or AP mode?
00113    if(interface->nicDriver == &wilc1000StaDriver)
00114    {
00115       //Debug message
00116       TRACE_INFO("Initializing WILC1000 (STA mode)...\r\n");
00117       //Save underlying network interface
00118       wilc1000StaInterface = interface;
00119    }
00120    else
00121    {
00122       //Debug message
00123       TRACE_INFO("Initializing WILC1000 (AP mode)...\r\n");
00124       //Save underlying network interface
00125       wilc1000ApInterface = interface;
00126    }
00127 
00128    //Start of exception handling block
00129    do
00130    {
00131       //Initialization sequence is performed once
00132       if(wilc1000StaInterface == NULL || wilc1000ApInterface == NULL)
00133       {
00134          //Low-level initialization
00135          status = nm_bsp_init();
00136 
00137          //Check status code
00138          if(status != M2M_SUCCESS)
00139             break;
00140 
00141          //Set default parameters
00142          memset(&param, 0, sizeof(param));
00143 
00144          //Register callback functions
00145          param.pfAppWifiCb = wilc1000AppWifiEvent;
00146          param.pfAppMonCb = NULL;
00147          param.strEthInitParam.pfAppWifiCb = NULL;
00148          param.strEthInitParam.pfAppEthCb = wilc1000AppEthEvent;
00149 
00150          //Set receive buffer
00151          param.strEthInitParam.au8ethRcvBuf = rxBuffer;
00152          param.strEthInitParam.u16ethRcvBufSize = WILC1000_RX_BUFFER_SIZE;
00153 
00154          //Initialize WILC1000 controller
00155          status = m2m_wifi_init(&param);
00156 
00157          //Check status code
00158          if(status != M2M_SUCCESS)
00159             break;
00160       }
00161 
00162       //Retrieve current MAC addresses
00163       status = m2m_wifi_get_mac_address(staMacAddr.b, apMacAddr.b);
00164 
00165       //Check status code
00166       if(status != M2M_SUCCESS)
00167          break;
00168 
00169       //Optionally set the MAC address
00170       if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
00171       {
00172          //Use the factory preprogrammed MAC address
00173          if(interface == wilc1000StaInterface)
00174             interface->macAddr = staMacAddr;
00175          else
00176             interface->macAddr = apMacAddr;
00177 
00178          //Generate the 64-bit interface identifier
00179          macAddrToEui64(&interface->macAddr, &interface->eui64);
00180       }
00181       else
00182       {
00183          //Override the factory preprogrammed address
00184          if(interface == wilc1000StaInterface)
00185             staMacAddr = interface->macAddr;
00186          else
00187             apMacAddr = interface->macAddr;
00188 
00189          //Assign MAC addresses
00190          status = m2m_wifi_set_mac_address(apMacAddr.b, staMacAddr.b);
00191 
00192          //Check status code
00193          if(status != M2M_SUCCESS)
00194             break;
00195       }
00196 
00197       //End of exception handling block
00198    } while(0);
00199 
00200    //WILC1000 is now ready to send
00201    osSetEvent(&interface->nicTxEvent);
00202 
00203    //Return status code
00204    if(status == M2M_SUCCESS)
00205       return NO_ERROR;
00206    else
00207       return ERROR_FAILURE;
00208 }
00209 
00210 
00211 /**
00212  * @brief WILC1000 timer handler
00213  *
00214  * This routine is periodically called by the TCP/IP stack to
00215  * handle periodic operations such as polling the link state
00216  *
00217  * @param[in] interface Underlying network interface
00218  **/
00219 
00220 void wilc1000Tick(NetInterface *interface)
00221 {
00222 }
00223 
00224 
00225 /**
00226  * @brief Enable interrupts
00227  * @param[in] interface Underlying network interface
00228  **/
00229 
00230 void wilc1000EnableIrq(NetInterface *interface)
00231 {
00232 }
00233 
00234 
00235 /**
00236  * @brief Disable interrupts
00237  * @param[in] interface Underlying network interface
00238  **/
00239 
00240 void wilc1000DisableIrq(NetInterface *interface)
00241 {
00242 }
00243 
00244 
00245 /**
00246  * @brief WILC1000 interrupt service routine
00247  * @return TRUE if a higher priority task must be woken. Else FALSE is returned
00248  **/
00249 
00250 bool_t wilc1000IrqHandler(void)
00251 {
00252    bool_t flag;
00253 
00254    //This flag will be set if a higher priority task must be woken
00255    flag = FALSE;
00256 
00257    //STA and/or AP mode?
00258    if(wilc1000StaInterface != NULL)
00259       wilc1000StaInterface->nicEvent = TRUE;
00260    else if(wilc1000ApInterface != NULL)
00261       wilc1000ApInterface->nicEvent = TRUE;
00262 
00263    //Notify the TCP/IP stack of the event
00264    flag = osSetEventFromIsr(&netEvent);
00265 
00266    //A higher priority task must be woken?
00267    return flag;
00268 }
00269 
00270 
00271 /**
00272  * @brief WILC1000 event handler
00273  * @param[in] interface Underlying network interface
00274  **/
00275 
00276 void wilc1000EventHandler(NetInterface *interface)
00277 {
00278    //Process Wi-Fi events
00279    m2m_wifi_handle_events(NULL);
00280 }
00281 
00282 
00283 /**
00284  * @brief Send a packet
00285  * @param[in] interface Underlying network interface
00286  * @param[in] buffer Multi-part buffer containing the data to send
00287  * @param[in] offset Offset to the first data byte
00288  * @return Error code
00289  **/
00290 
00291 error_t wilc1000SendPacket(NetInterface *interface,
00292    const NetBuffer *buffer, size_t offset)
00293 {
00294    int8_t status;
00295    size_t length;
00296 
00297    //Retrieve the length of the packet
00298    length = netBufferGetLength(buffer) - offset;
00299 
00300    //Check the frame length
00301    if(length > WILC1000_TX_BUFFER_SIZE)
00302    {
00303       //The transmitter can accept another packet
00304       osSetEvent(&interface->nicTxEvent);
00305       //Report an error
00306       return ERROR_INVALID_LENGTH;
00307    }
00308 
00309    //Make sure the link is up before transmitting the frame
00310    if(!interface->linkState)
00311    {
00312       //The transmitter can accept another packet
00313       osSetEventFromIsr(&interface->nicTxEvent);
00314       //Drop current packet
00315       return NO_ERROR;
00316    }
00317 
00318    //Copy user data to the transmit buffer
00319    netBufferRead(txBuffer + M2M_ETHERNET_HDR_OFFSET + M2M_ETH_PAD_SIZE,
00320       buffer, offset, length);
00321 
00322    //STA or AP mode?
00323    if(interface == wilc1000StaInterface)
00324    {
00325       //Send packet
00326       status = m2m_wifi_send_ethernet_pkt(txBuffer, length);
00327    }
00328    else
00329    {
00330       //Send packet
00331       status = m2m_wifi_send_ethernet_pkt_ifc1(txBuffer, length);
00332    }
00333 
00334    //The transmitter can accept another packet
00335    osSetEvent(&interface->nicTxEvent);
00336 
00337    //Return status code
00338    if(status == M2M_SUCCESS)
00339       return NO_ERROR;
00340    else
00341       return ERROR_FAILURE;
00342 }
00343 
00344 
00345 /**
00346  * @brief Configure multicast MAC address filtering
00347  * @param[in] interface Underlying network interface
00348  * @return Error code
00349  **/
00350 
00351 error_t wilc1000SetMulticastFilter(NetInterface *interface)
00352 {
00353    uint_t i;
00354    uint_t refCount;
00355    MacFilterEntry *entry;
00356 
00357    //Debug message
00358    TRACE_INFO("Updating WILC1000 multicast filter...\r\n");
00359 
00360    //The MAC filter table contains the multicast MAC addresses
00361    //to accept when receiving an Ethernet frame
00362    for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00363    {
00364       //Point to the current entry
00365       entry = &interface->macMulticastFilter[i];
00366 
00367       //Valid entry?
00368       if(!macCompAddr(&entry->addr, &MAC_UNSPECIFIED_ADDR))
00369       {
00370          //Check whether the multicast MAC address has already been registered
00371          //on the alternate interface
00372          if(interface == wilc1000StaInterface)
00373             refCount = wilc1000GetAddrRefCount(wilc1000ApInterface, &entry->addr);
00374          else
00375             refCount = wilc1000GetAddrRefCount(wilc1000StaInterface, &entry->addr);
00376 
00377          //Ensure that there are not duplicate address entries in the table
00378          if(refCount == 0)
00379          {
00380             //Update MAC filter table only if necessary
00381             if(entry->addFlag)
00382             {
00383                //Add a new entry to the MAC filter table
00384                m2m_wifi_enable_mac_mcast(entry->addr.b, TRUE);
00385             }
00386             else if(entry->deleteFlag)
00387             {
00388                //Remove the current entry from the MAC filter table
00389                m2m_wifi_enable_mac_mcast(entry->addr.b, FALSE);
00390             }
00391          }
00392       }
00393    }
00394 
00395    //Successful processing
00396    return NO_ERROR;
00397 }
00398 
00399 
00400 /**
00401  * @brief Get reference count for the specified multicast MAC address
00402  * @param[in] interface Underlying network interface
00403  * @param[in] macAddr MAC address
00404  * @return Reference count
00405  **/
00406 
00407 bool_t wilc1000GetAddrRefCount(NetInterface *interface, const MacAddr *macAddr)
00408 {
00409    uint_t i;
00410    uint_t refCount;
00411    MacFilterEntry *entry;
00412 
00413    //Clear reference count
00414    refCount = 0;
00415 
00416    //Valid network interface?
00417    if(interface != NULL)
00418    {
00419       //Go through the multicast filter table
00420       for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
00421       {
00422          //Point to the current entry
00423          entry = &interface->macMulticastFilter[i];
00424 
00425          //Valid entry?
00426          if(entry->refCount > 0)
00427          {
00428             //Check whether the specified MAC address matches
00429             //a multicast address in the table
00430             if(macCompAddr(&entry->addr, macAddr))
00431             {
00432                //Get reference count
00433                refCount = entry->refCount;
00434                //We are done
00435                break;
00436             }
00437          }
00438       }
00439    }
00440 
00441    //Return reference count
00442    return refCount;
00443 }
00444 
00445 
00446 /**
00447  * @brief Callback function that handles Wi-Fi events
00448  * @param[in] msgType Type of notification
00449  * @param[in] msg Pointer to the buffer containing the notification parameters
00450  **/
00451 
00452 void wilc1000AppWifiEvent(uint8_t msgType, void *msg)
00453 {
00454    tstrM2mWifiStateChanged *stateChangedMsg;
00455 
00456    //Debug message
00457    TRACE_INFO("WILC1000 Wi-Fi event callback\r\n");
00458 
00459    //Check message type
00460    if(msgType == M2M_WIFI_RESP_FIRMWARE_STRTED)
00461    {
00462       //Debug message
00463       TRACE_INFO("  M2M_WIFI_RESP_FIRMWARE_STRTED\r\n");
00464    }
00465    else if(msgType == M2M_WIFI_RESP_CON_STATE_CHANGED)
00466    {
00467       //Debug message
00468       TRACE_INFO("  M2M_WIFI_RESP_CON_STATE_CHANGED\r\n");
00469 
00470       //Connection state
00471       stateChangedMsg = (tstrM2mWifiStateChanged*) msg;
00472 
00473       //Check interface identifier
00474       if(stateChangedMsg->u8IfcId == INTERFACE_1)
00475       {
00476          //Check whether STA mode is enabled
00477          if(wilc1000StaInterface != NULL)
00478          {
00479             //Check link state
00480             if(stateChangedMsg->u8CurrState == M2M_WIFI_CONNECTED)
00481             {
00482                //Link is up
00483                wilc1000StaInterface->linkState = TRUE;
00484             }
00485             else
00486             {
00487                //Link is down
00488                wilc1000StaInterface->linkState = FALSE;
00489             }
00490 
00491             //Process link state change event
00492             nicNotifyLinkChange(wilc1000StaInterface);
00493          }
00494       }
00495       else if(stateChangedMsg->u8IfcId == INTERFACE_2)
00496       {
00497          //Check whether AP mode is enabled
00498          if(wilc1000ApInterface != NULL)
00499          {
00500             //Check link state
00501             if(stateChangedMsg->u8CurrState == M2M_WIFI_CONNECTED)
00502             {
00503                //Link is up
00504                wilc1000ApInterface->linkState = TRUE;
00505             }
00506             else
00507             {
00508                //Link is down
00509                wilc1000ApInterface->linkState = FALSE;
00510             }
00511 
00512             //Process link state change event
00513             nicNotifyLinkChange(wilc1000ApInterface);
00514          }
00515       }
00516    }
00517 
00518 #if defined(CONF_WILC_EVENT_HOOK)
00519    //Release exclusive access
00520    osReleaseMutex(&netMutex);
00521    //Invoke user callback function
00522    CONF_WILC_EVENT_HOOK(msgType, msg);
00523    //Get exclusive access
00524    osAcquireMutex(&netMutex);
00525 #endif
00526 }
00527 
00528 
00529 /**
00530  * @brief Callback function that handles events in bypass mode
00531  * @param[in] msgType Type of notification
00532  * @param[in] msg Pointer to the buffer containing the notification parameters
00533  * @param[in] ctrlBuf Pointer to the control buffer
00534  **/
00535 
00536 void wilc1000AppEthEvent(uint8_t msgType, void *msg, void *ctrlBuf)
00537 {
00538    size_t length;
00539    uint8_t *packet;
00540    tstrM2mIpCtrlBuf *ctrl;
00541 
00542    //Debug message
00543    TRACE_DEBUG("WILC1000 RX event callback\r\n");
00544 
00545    //Point to the control buffer
00546    ctrl = (tstrM2mIpCtrlBuf *) ctrlBuf;
00547 
00548    //Check message type
00549    if(msgType == M2M_WIFI_RESP_ETHERNET_RX_PACKET)
00550    {
00551       //Debug message
00552       TRACE_DEBUG("  M2M_WIFI_RESP_ETHERNET_RX_PACKET\r\n");
00553 
00554       //Point to the beginning of the packet
00555       packet = rxBuffer + ctrl->u8DataOffset;
00556       //Retrieve the length of the packet
00557       length = ctrl->u16DataSize;
00558 
00559       //Check interface identifier
00560       if(ctrl->u8IfcId == INTERFACE_1)
00561       {
00562          //Valid interface?
00563          if(wilc1000StaInterface != NULL)
00564          {
00565             //Check destination MAC address
00566             if(wilc1000ApInterface != NULL)
00567             {
00568                if(macCompAddr(packet, wilc1000ApInterface->macAddr.b))
00569                   macCopyAddr(packet, wilc1000StaInterface->macAddr.b);
00570             }
00571 
00572             //Pass the packet to the upper layer (STA mode)
00573             nicProcessPacket(wilc1000StaInterface, packet, length);
00574          }
00575       }
00576       else if(ctrl->u8IfcId == INTERFACE_2)
00577       {
00578          //Valid interface?
00579          if(wilc1000ApInterface != NULL)
00580          {
00581             //Check destination MAC address
00582             if(wilc1000StaInterface != NULL)
00583             {
00584                if(macCompAddr(packet, wilc1000StaInterface->macAddr.b))
00585                   macCopyAddr(packet, wilc1000ApInterface->macAddr.b);
00586             }
00587 
00588             //Pass the packet to the upper layer (STA mode)
00589             nicProcessPacket(wilc1000ApInterface, packet, length);
00590          }
00591       }
00592    }
00593 }
00594