Webserver+3d print

Dependents:   Nucleo

Revision:
0:8918a71cdbe9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cyclone_tcp/core/nic.c	Sat Feb 04 18:15:49 2017 +0000
@@ -0,0 +1,345 @@
+/**
+ * @file nic.c
+ * @brief Network interface controller abstraction layer
+ *
+ * @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 "core/net.h"
+#include "core/nic.h"
+#include "core/socket.h"
+#include "core/raw_socket.h"
+#include "core/tcp_misc.h"
+#include "core/udp.h"
+#include "ipv4/ipv4.h"
+#include "ipv6/ipv6.h"
+#include "dns/dns_cache.h"
+#include "dns/dns_client.h"
+#include "mdns/mdns_client.h"
+#include "mdns/mdns_responder.h"
+#include "dns_sd/dns_sd.h"
+#include "mibs/mib2_module.h"
+#include "debug.h"
+
+//Tick counter to handle periodic operations
+systime_t nicTickCounter;
+
+
+/**
+ * @brief Network controller 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 nicTick(NetInterface *interface)
+{
+   //Disable interrupts
+   interface->nicDriver->disableIrq(interface);
+
+   //Handle periodic operations
+   interface->nicDriver->tick(interface);
+
+   //Re-enable interrupts if necessary
+   if(interface->configured)
+      interface->nicDriver->enableIrq(interface);
+}
+
+
+/**
+ * @brief Send a packet to the network controller
+ * @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 nicSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
+{
+   error_t error;
+   bool_t status;
+
+#if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
+   //Retrieve the length of the packet
+   size_t length = netBufferGetLength(buffer) - offset;
+
+   //Debug message
+   TRACE_DEBUG("Sending packet (%" PRIuSIZE " bytes)...\r\n", length);
+   TRACE_DEBUG_NET_BUFFER("  ", buffer, offset, length);
+#endif
+
+   //Wait for the transmitter to be ready to send
+   status = osWaitForEvent(&interface->nicTxEvent, NIC_MAX_BLOCKING_TIME);
+
+   //Check whether the specified event is in signaled state
+   if(status)
+   {
+      //Disable interrupts
+      interface->nicDriver->disableIrq(interface);
+
+      //Send Ethernet frame
+      error = interface->nicDriver->sendPacket(interface, buffer, offset);
+
+      //Re-enable interrupts if necessary
+      if(interface->configured)
+         interface->nicDriver->enableIrq(interface);
+   }
+   else
+   {
+      //The transmitter is busy...
+      return ERROR_TRANSMITTER_BUSY;
+   }
+
+   //Return status code
+   return error;
+}
+
+
+/**
+ * @brief Configure multicast MAC address filtering
+ * @param[in] interface Underlying network interface
+ * @return Error code
+ **/
+
+error_t nicSetMulticastFilter(NetInterface *interface)
+{
+   error_t error;
+
+   //Disable interrupts
+   interface->nicDriver->disableIrq(interface);
+
+   //Update MAC filter table
+   error = interface->nicDriver->setMulticastFilter(interface);
+
+   //Re-enable interrupts if necessary
+   if(interface->configured)
+      interface->nicDriver->enableIrq(interface);
+
+   //Return status code
+   return error;
+}
+
+
+/**
+ * @brief Handle a packet received by the network controller
+ * @param[in] interface Underlying network interface
+ * @param[in] packet Incoming packet to process
+ * @param[in] length Total packet length
+ **/
+
+void nicProcessPacket(NetInterface *interface, void *packet, size_t length)
+{
+   NicType type;
+
+   //Re-enable interrupts if necessary
+   if(interface->configured)
+      interface->nicDriver->enableIrq(interface);
+
+   //Debug message
+   TRACE_DEBUG("Packet received (%" PRIuSIZE " bytes)...\r\n", length);
+   TRACE_DEBUG_ARRAY("  ", packet, length);
+
+   //Retrieve network interface type
+   type = interface->nicDriver->type;
+
+   //Ethernet interface?
+   if(type == NIC_TYPE_ETHERNET)
+   {
+#if (ETH_SUPPORT == ENABLED)
+      //Process incoming Ethernet frame
+      ethProcessFrame(interface, packet, length);
+#endif
+   }
+   //PPP interface?
+   else if(type == NIC_TYPE_PPP)
+   {
+#if (PPP_SUPPORT == ENABLED)
+      //Process incoming PPP frame
+      pppProcessFrame(interface, packet, length);
+#endif
+   }
+   //6LoWPAN interface?
+   else if(type == NIC_TYPE_6LOWPAN)
+   {
+#if (IPV6_SUPPORT == ENABLED)
+      NetBuffer1 buffer;
+
+      //The incoming packet fits in a single chunk
+      buffer.chunkCount = 1;
+      buffer.maxChunkCount = 1;
+      buffer.chunk[0].address = packet;
+      buffer.chunk[0].length = length;
+      buffer.chunk[0].size = 0;
+
+      //Process incoming IPv6 packet
+      ipv6ProcessPacket(interface, (NetBuffer *) &buffer, 0);
+#endif
+   }
+
+   //Disable interrupts
+   interface->nicDriver->disableIrq(interface);
+}
+
+
+/**
+ * @brief Process link state change event
+ * @param[in] interface Underlying network interface
+ **/
+
+void nicNotifyLinkChange(NetInterface *interface)
+{
+   uint_t i;
+   Socket *socket;
+
+   //Re-enable interrupts if necessary
+   if(interface->configured)
+      interface->nicDriver->enableIrq(interface);
+
+   //Check link state
+   if(interface->linkState)
+   {
+      //Display link state
+      TRACE_INFO("Link is up (%s)...\r\n", interface->name);
+
+      //Display link speed
+      if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
+      {
+         //1000BASE-T
+         TRACE_INFO("  Link speed = 1000 Mbps\r\n");
+      }
+      else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
+      {
+         //100BASE-TX
+         TRACE_INFO("  Link speed = 100 Mbps\r\n");
+      }
+      else if(interface->linkSpeed == NIC_LINK_SPEED_10MBPS)
+      {
+         //10BASE-T
+         TRACE_INFO("  Link speed = 10 Mbps\r\n");
+      }
+      else if(interface->linkSpeed != NIC_LINK_SPEED_UNKNOWN)
+      {
+         //10BASE-T
+         TRACE_INFO("  Link speed = %" PRIu32 " bps\r\n", interface->linkSpeed);
+      }
+
+      //Display duplex mode
+      if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
+      {
+         //1000BASE-T
+         TRACE_INFO("  Duplex mode = Full-Duplex\r\n");
+      }
+      else if(interface->duplexMode == NIC_HALF_DUPLEX_MODE)
+      {
+         //100BASE-TX
+         TRACE_INFO("  Duplex mode = Half-Duplex\r\n");
+      }
+   }
+   else
+   {
+      //Display link state
+      TRACE_INFO("Link is down (%s)...\r\n", interface->name);
+   }
+
+   //Interface's current bandwidth
+   MIB2_SET_GAUGE32(interface->mibIfEntry->ifSpeed, interface->linkSpeed);
+
+   //The current operational state of the interface
+   if(interface->linkState)
+      MIB2_SET_INTEGER(interface->mibIfEntry->ifOperStatus, MIB2_IF_OPER_STATUS_UP);
+   else
+      MIB2_SET_INTEGER(interface->mibIfEntry->ifOperStatus, MIB2_IF_OPER_STATUS_DOWN);
+
+   //The time at which the interface entered its current operational state
+   MIB2_SET_TIME_TICKS(interface->mibIfEntry->ifLastChange, osGetSystemTime() / 10);
+
+#if (IPV4_SUPPORT == ENABLED)
+   //Notify IPv4 of link state changes
+   ipv4LinkChangeEvent(interface);
+#endif
+
+#if (IPV6_SUPPORT == ENABLED)
+   //Notify IPv6 of link state changes
+   ipv6LinkChangeEvent(interface);
+#endif
+
+#if (DNS_CLIENT_SUPPORT == ENABLED || MDNS_CLIENT_SUPPORT == ENABLED || \
+   NBNS_CLIENT_SUPPORT == ENABLED)
+   //Flush DNS cache
+   dnsFlushCache(interface);
+#endif
+
+#if (MDNS_RESPONDER_SUPPORT == ENABLED)
+   //Perform probing and announcing
+   mdnsResponderLinkChangeEvent(interface->mdnsResponderContext);
+#endif
+
+#if (DNS_SD_SUPPORT == ENABLED)
+   //Perform probing and announcing
+   dnsSdLinkChangeEvent(interface->dnsSdContext);
+#endif
+
+   //Notify registered users of link state changes
+   netInvokeLinkChangeCallback(interface, interface->linkState);
+
+   //Loop through opened sockets
+   for(i = 0; i < SOCKET_MAX_COUNT; i++)
+   {
+      //Point to the current socket
+      socket = socketTable + i;
+
+#if (TCP_SUPPORT == ENABLED)
+      //Connection-oriented socket?
+      if(socket->type == SOCKET_TYPE_STREAM)
+      {
+         tcpUpdateEvents(socket);
+      }
+#endif
+#if (UDP_SUPPORT == ENABLED)
+      //Connectionless socket?
+      if(socket->type == SOCKET_TYPE_DGRAM)
+      {
+         udpUpdateEvents(socket);
+      }
+#endif
+#if (RAW_SOCKET_SUPPORT == ENABLED)
+      //Raw socket?
+      if(socket->type == SOCKET_TYPE_RAW_IP ||
+         socket->type == SOCKET_TYPE_RAW_ETH)
+      {
+         rawSocketUpdateEvents(socket);
+      }
+#endif
+   }
+
+   //Disable interrupts
+   interface->nicDriver->disableIrq(interface);
+}
+