Webserver+3d print

Dependents:   Nucleo

Revision:
0:8918a71cdbe9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cyclone_tcp/drivers/wilc1000_driver.c	Sat Feb 04 18:15:49 2017 +0000
@@ -0,0 +1,594 @@
+/**
+ * @file wilc1000_driver.c
+ * @brief WILC1000 Wi-Fi controller
+ *
+ * @section License
+ *
+ * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
+ *
+ * This file is part of CycloneTCP Open.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * @author Oryx Embedded SARL (www.oryx-embedded.com)
+ * @version 1.7.6
+ **/
+
+//Switch to the appropriate trace level
+#define TRACE_LEVEL NIC_TRACE_LEVEL
+
+//Dependencies
+#include "driver/include/m2m_wifi.h"
+#include "core/net.h"
+#include "wilc1000_driver.h"
+#include "wilc1000_config.h"
+#include "debug.h"
+
+//Underlying network interface
+static NetInterface *wilc1000StaInterface = NULL;
+static NetInterface *wilc1000ApInterface = NULL;
+
+//Transmit buffer
+static uint8_t txBuffer[WILC1000_TX_BUFFER_SIZE];
+//Receive buffer
+static uint8_t rxBuffer[WILC1000_RX_BUFFER_SIZE];
+
+
+/**
+ * @brief WILC1000 driver (STA mode)
+ **/
+
+const NicDriver wilc1000StaDriver =
+{
+   NIC_TYPE_ETHERNET,
+   ETH_MTU,
+   wilc1000Init,
+   wilc1000Tick,
+   wilc1000EnableIrq,
+   wilc1000DisableIrq,
+   wilc1000EventHandler,
+   wilc1000SendPacket,
+   wilc1000SetMulticastFilter,
+   NULL,
+   NULL,
+   NULL,
+   TRUE,
+   TRUE,
+   TRUE,
+   TRUE
+};
+
+
+/**
+ * @brief WILC1000 driver (AP mode)
+ **/
+
+const NicDriver wilc1000ApDriver =
+{
+   NIC_TYPE_ETHERNET,
+   ETH_MTU,
+   wilc1000Init,
+   wilc1000Tick,
+   wilc1000EnableIrq,
+   wilc1000DisableIrq,
+   wilc1000EventHandler,
+   wilc1000SendPacket,
+   wilc1000SetMulticastFilter,
+   NULL,
+   NULL,
+   NULL,
+   TRUE,
+   TRUE,
+   TRUE,
+   TRUE
+};
+
+
+/**
+ * @brief WILC1000 initialization
+ * @param[in] interface Underlying network interface
+ * @return Error code
+ **/
+
+error_t wilc1000Init(NetInterface *interface)
+{
+   int8_t status;
+   tstrWifiInitParam param;
+   MacAddr staMacAddr;
+   MacAddr apMacAddr;
+
+   //STA or AP mode?
+   if(interface->nicDriver == &wilc1000StaDriver)
+   {
+      //Debug message
+      TRACE_INFO("Initializing WILC1000 (STA mode)...\r\n");
+      //Save underlying network interface
+      wilc1000StaInterface = interface;
+   }
+   else
+   {
+      //Debug message
+      TRACE_INFO("Initializing WILC1000 (AP mode)...\r\n");
+      //Save underlying network interface
+      wilc1000ApInterface = interface;
+   }
+
+   //Start of exception handling block
+   do
+   {
+      //Initialization sequence is performed once
+      if(wilc1000StaInterface == NULL || wilc1000ApInterface == NULL)
+      {
+         //Low-level initialization
+         status = nm_bsp_init();
+
+         //Check status code
+         if(status != M2M_SUCCESS)
+            break;
+
+         //Set default parameters
+         memset(&param, 0, sizeof(param));
+
+         //Register callback functions
+         param.pfAppWifiCb = wilc1000AppWifiEvent;
+         param.pfAppMonCb = NULL;
+         param.strEthInitParam.pfAppWifiCb = NULL;
+         param.strEthInitParam.pfAppEthCb = wilc1000AppEthEvent;
+
+         //Set receive buffer
+         param.strEthInitParam.au8ethRcvBuf = rxBuffer;
+         param.strEthInitParam.u16ethRcvBufSize = WILC1000_RX_BUFFER_SIZE;
+
+         //Initialize WILC1000 controller
+         status = m2m_wifi_init(&param);
+
+         //Check status code
+         if(status != M2M_SUCCESS)
+            break;
+      }
+
+      //Retrieve current MAC addresses
+      status = m2m_wifi_get_mac_address(staMacAddr.b, apMacAddr.b);
+
+      //Check status code
+      if(status != M2M_SUCCESS)
+         break;
+
+      //Optionally set the MAC address
+      if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR))
+      {
+         //Use the factory preprogrammed MAC address
+         if(interface == wilc1000StaInterface)
+            interface->macAddr = staMacAddr;
+         else
+            interface->macAddr = apMacAddr;
+
+         //Generate the 64-bit interface identifier
+         macAddrToEui64(&interface->macAddr, &interface->eui64);
+      }
+      else
+      {
+         //Override the factory preprogrammed address
+         if(interface == wilc1000StaInterface)
+            staMacAddr = interface->macAddr;
+         else
+            apMacAddr = interface->macAddr;
+
+         //Assign MAC addresses
+         status = m2m_wifi_set_mac_address(apMacAddr.b, staMacAddr.b);
+
+         //Check status code
+         if(status != M2M_SUCCESS)
+            break;
+      }
+
+      //End of exception handling block
+   } while(0);
+
+   //WILC1000 is now ready to send
+   osSetEvent(&interface->nicTxEvent);
+
+   //Return status code
+   if(status == M2M_SUCCESS)
+      return NO_ERROR;
+   else
+      return ERROR_FAILURE;
+}
+
+
+/**
+ * @brief WILC1000 timer handler
+ *
+ * This routine is periodically called by the TCP/IP stack to
+ * handle periodic operations such as polling the link state
+ *
+ * @param[in] interface Underlying network interface
+ **/
+
+void wilc1000Tick(NetInterface *interface)
+{
+}
+
+
+/**
+ * @brief Enable interrupts
+ * @param[in] interface Underlying network interface
+ **/
+
+void wilc1000EnableIrq(NetInterface *interface)
+{
+}
+
+
+/**
+ * @brief Disable interrupts
+ * @param[in] interface Underlying network interface
+ **/
+
+void wilc1000DisableIrq(NetInterface *interface)
+{
+}
+
+
+/**
+ * @brief WILC1000 interrupt service routine
+ * @return TRUE if a higher priority task must be woken. Else FALSE is returned
+ **/
+
+bool_t wilc1000IrqHandler(void)
+{
+   bool_t flag;
+
+   //This flag will be set if a higher priority task must be woken
+   flag = FALSE;
+
+   //STA and/or AP mode?
+   if(wilc1000StaInterface != NULL)
+      wilc1000StaInterface->nicEvent = TRUE;
+   else if(wilc1000ApInterface != NULL)
+      wilc1000ApInterface->nicEvent = TRUE;
+
+   //Notify the TCP/IP stack of the event
+   flag = osSetEventFromIsr(&netEvent);
+
+   //A higher priority task must be woken?
+   return flag;
+}
+
+
+/**
+ * @brief WILC1000 event handler
+ * @param[in] interface Underlying network interface
+ **/
+
+void wilc1000EventHandler(NetInterface *interface)
+{
+   //Process Wi-Fi events
+   m2m_wifi_handle_events(NULL);
+}
+
+
+/**
+ * @brief Send a packet
+ * @param[in] interface Underlying network interface
+ * @param[in] buffer Multi-part buffer containing the data to send
+ * @param[in] offset Offset to the first data byte
+ * @return Error code
+ **/
+
+error_t wilc1000SendPacket(NetInterface *interface,
+   const NetBuffer *buffer, size_t offset)
+{
+   int8_t status;
+   size_t length;
+
+   //Retrieve the length of the packet
+   length = netBufferGetLength(buffer) - offset;
+
+   //Check the frame length
+   if(length > WILC1000_TX_BUFFER_SIZE)
+   {
+      //The transmitter can accept another packet
+      osSetEvent(&interface->nicTxEvent);
+      //Report an error
+      return ERROR_INVALID_LENGTH;
+   }
+
+   //Make sure the link is up before transmitting the frame
+   if(!interface->linkState)
+   {
+      //The transmitter can accept another packet
+      osSetEventFromIsr(&interface->nicTxEvent);
+      //Drop current packet
+      return NO_ERROR;
+   }
+
+   //Copy user data to the transmit buffer
+   netBufferRead(txBuffer + M2M_ETHERNET_HDR_OFFSET + M2M_ETH_PAD_SIZE,
+      buffer, offset, length);
+
+   //STA or AP mode?
+   if(interface == wilc1000StaInterface)
+   {
+      //Send packet
+      status = m2m_wifi_send_ethernet_pkt(txBuffer, length);
+   }
+   else
+   {
+      //Send packet
+      status = m2m_wifi_send_ethernet_pkt_ifc1(txBuffer, length);
+   }
+
+   //The transmitter can accept another packet
+   osSetEvent(&interface->nicTxEvent);
+
+   //Return status code
+   if(status == M2M_SUCCESS)
+      return NO_ERROR;
+   else
+      return ERROR_FAILURE;
+}
+
+
+/**
+ * @brief Configure multicast MAC address filtering
+ * @param[in] interface Underlying network interface
+ * @return Error code
+ **/
+
+error_t wilc1000SetMulticastFilter(NetInterface *interface)
+{
+   uint_t i;
+   uint_t refCount;
+   MacFilterEntry *entry;
+
+   //Debug message
+   TRACE_INFO("Updating WILC1000 multicast filter...\r\n");
+
+   //The MAC filter table contains the multicast MAC addresses
+   //to accept when receiving an Ethernet frame
+   for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
+   {
+      //Point to the current entry
+      entry = &interface->macMulticastFilter[i];
+
+      //Valid entry?
+      if(!macCompAddr(&entry->addr, &MAC_UNSPECIFIED_ADDR))
+      {
+         //Check whether the multicast MAC address has already been registered
+         //on the alternate interface
+         if(interface == wilc1000StaInterface)
+            refCount = wilc1000GetAddrRefCount(wilc1000ApInterface, &entry->addr);
+         else
+            refCount = wilc1000GetAddrRefCount(wilc1000StaInterface, &entry->addr);
+
+         //Ensure that there are not duplicate address entries in the table
+         if(refCount == 0)
+         {
+            //Update MAC filter table only if necessary
+            if(entry->addFlag)
+            {
+               //Add a new entry to the MAC filter table
+               m2m_wifi_enable_mac_mcast(entry->addr.b, TRUE);
+            }
+            else if(entry->deleteFlag)
+            {
+               //Remove the current entry from the MAC filter table
+               m2m_wifi_enable_mac_mcast(entry->addr.b, FALSE);
+            }
+         }
+      }
+   }
+
+   //Successful processing
+   return NO_ERROR;
+}
+
+
+/**
+ * @brief Get reference count for the specified multicast MAC address
+ * @param[in] interface Underlying network interface
+ * @param[in] macAddr MAC address
+ * @return Reference count
+ **/
+
+bool_t wilc1000GetAddrRefCount(NetInterface *interface, const MacAddr *macAddr)
+{
+   uint_t i;
+   uint_t refCount;
+   MacFilterEntry *entry;
+
+   //Clear reference count
+   refCount = 0;
+
+   //Valid network interface?
+   if(interface != NULL)
+   {
+      //Go through the multicast filter table
+      for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
+      {
+         //Point to the current entry
+         entry = &interface->macMulticastFilter[i];
+
+         //Valid entry?
+         if(entry->refCount > 0)
+         {
+            //Check whether the specified MAC address matches
+            //a multicast address in the table
+            if(macCompAddr(&entry->addr, macAddr))
+            {
+               //Get reference count
+               refCount = entry->refCount;
+               //We are done
+               break;
+            }
+         }
+      }
+   }
+
+   //Return reference count
+   return refCount;
+}
+
+
+/**
+ * @brief Callback function that handles Wi-Fi events
+ * @param[in] msgType Type of notification
+ * @param[in] msg Pointer to the buffer containing the notification parameters
+ **/
+
+void wilc1000AppWifiEvent(uint8_t msgType, void *msg)
+{
+   tstrM2mWifiStateChanged *stateChangedMsg;
+
+   //Debug message
+   TRACE_INFO("WILC1000 Wi-Fi event callback\r\n");
+
+   //Check message type
+   if(msgType == M2M_WIFI_RESP_FIRMWARE_STRTED)
+   {
+      //Debug message
+      TRACE_INFO("  M2M_WIFI_RESP_FIRMWARE_STRTED\r\n");
+   }
+   else if(msgType == M2M_WIFI_RESP_CON_STATE_CHANGED)
+   {
+      //Debug message
+      TRACE_INFO("  M2M_WIFI_RESP_CON_STATE_CHANGED\r\n");
+
+      //Connection state
+      stateChangedMsg = (tstrM2mWifiStateChanged*) msg;
+
+      //Check interface identifier
+      if(stateChangedMsg->u8IfcId == INTERFACE_1)
+      {
+         //Check whether STA mode is enabled
+         if(wilc1000StaInterface != NULL)
+         {
+            //Check link state
+            if(stateChangedMsg->u8CurrState == M2M_WIFI_CONNECTED)
+            {
+               //Link is up
+               wilc1000StaInterface->linkState = TRUE;
+            }
+            else
+            {
+               //Link is down
+               wilc1000StaInterface->linkState = FALSE;
+            }
+
+            //Process link state change event
+            nicNotifyLinkChange(wilc1000StaInterface);
+         }
+      }
+      else if(stateChangedMsg->u8IfcId == INTERFACE_2)
+      {
+         //Check whether AP mode is enabled
+         if(wilc1000ApInterface != NULL)
+         {
+            //Check link state
+            if(stateChangedMsg->u8CurrState == M2M_WIFI_CONNECTED)
+            {
+               //Link is up
+               wilc1000ApInterface->linkState = TRUE;
+            }
+            else
+            {
+               //Link is down
+               wilc1000ApInterface->linkState = FALSE;
+            }
+
+            //Process link state change event
+            nicNotifyLinkChange(wilc1000ApInterface);
+         }
+      }
+   }
+
+#if defined(CONF_WILC_EVENT_HOOK)
+   //Release exclusive access
+   osReleaseMutex(&netMutex);
+   //Invoke user callback function
+   CONF_WILC_EVENT_HOOK(msgType, msg);
+   //Get exclusive access
+   osAcquireMutex(&netMutex);
+#endif
+}
+
+
+/**
+ * @brief Callback function that handles events in bypass mode
+ * @param[in] msgType Type of notification
+ * @param[in] msg Pointer to the buffer containing the notification parameters
+ * @param[in] ctrlBuf Pointer to the control buffer
+ **/
+
+void wilc1000AppEthEvent(uint8_t msgType, void *msg, void *ctrlBuf)
+{
+   size_t length;
+   uint8_t *packet;
+   tstrM2mIpCtrlBuf *ctrl;
+
+   //Debug message
+   TRACE_DEBUG("WILC1000 RX event callback\r\n");
+
+   //Point to the control buffer
+   ctrl = (tstrM2mIpCtrlBuf *) ctrlBuf;
+
+   //Check message type
+   if(msgType == M2M_WIFI_RESP_ETHERNET_RX_PACKET)
+   {
+      //Debug message
+      TRACE_DEBUG("  M2M_WIFI_RESP_ETHERNET_RX_PACKET\r\n");
+
+      //Point to the beginning of the packet
+      packet = rxBuffer + ctrl->u8DataOffset;
+      //Retrieve the length of the packet
+      length = ctrl->u16DataSize;
+
+      //Check interface identifier
+      if(ctrl->u8IfcId == INTERFACE_1)
+      {
+         //Valid interface?
+         if(wilc1000StaInterface != NULL)
+         {
+            //Check destination MAC address
+            if(wilc1000ApInterface != NULL)
+            {
+               if(macCompAddr(packet, wilc1000ApInterface->macAddr.b))
+                  macCopyAddr(packet, wilc1000StaInterface->macAddr.b);
+            }
+
+            //Pass the packet to the upper layer (STA mode)
+            nicProcessPacket(wilc1000StaInterface, packet, length);
+         }
+      }
+      else if(ctrl->u8IfcId == INTERFACE_2)
+      {
+         //Valid interface?
+         if(wilc1000ApInterface != NULL)
+         {
+            //Check destination MAC address
+            if(wilc1000StaInterface != NULL)
+            {
+               if(macCompAddr(packet, wilc1000StaInterface->macAddr.b))
+                  macCopyAddr(packet, wilc1000ApInterface->macAddr.b);
+            }
+
+            //Pass the packet to the upper layer (STA mode)
+            nicProcessPacket(wilc1000ApInterface, packet, length);
+         }
+      }
+   }
+}
+