Moved out each demos' functionality library files (e.g. Ring Buffer library) to ...
[pub/lufa.git] / Demos / Device / RNDISEthernet / Lib / Ethernet.c
diff --git a/Demos/Device/RNDISEthernet/Lib/Ethernet.c b/Demos/Device/RNDISEthernet/Lib/Ethernet.c
new file mode 100644 (file)
index 0000000..3d34f71
--- /dev/null
@@ -0,0 +1,136 @@
+/*\r
+             LUFA Library\r
+     Copyright (C) Dean Camera, 2009.\r
+              \r
+  dean [at] fourwalledcubicle [dot] com\r
+      www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+  Permission to use, copy, modify, and distribute this software\r
+  and its documentation for any purpose and without fee is hereby\r
+  granted, provided that the above copyright notice appear in all\r
+  copies and that both that the copyright notice and this\r
+  permission notice and warranty disclaimer appear in supporting\r
+  documentation, and that the name of the author not be used in\r
+  advertising or publicity pertaining to distribution of the\r
+  software without specific, written prior permission.\r
+\r
+  The author disclaim all warranties with regard to this\r
+  software, including all implied warranties of merchantability\r
+  and fitness.  In no event shall the author be liable for any\r
+  special, indirect or consequential damages or any damages\r
+  whatsoever resulting from loss of use, data or profits, whether\r
+  in an action of contract, negligence or other tortious action,\r
+  arising out of or in connection with the use or performance of\r
+  this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ *  Ethernet frame packet handling routines. This protocol handles the processing of raw Ethernet\r
+ *  frames sent and received, deferring the processing of subpacket protocols to the appropriate\r
+ *  protocol handlers, such as DHCP or ARP.\r
+ */\r
\r
+#include "Ethernet.h"\r
+\r
+/* Global Variables: */\r
+/** Ethernet Frame buffer structure, to hold the incoming Ethernet frame from the host. */\r
+Ethernet_Frame_Info_t FrameIN;\r
+\r
+/** Ethernet Frame buffer structure, to hold the outgoing Ethernet frame to the host. */\r
+Ethernet_Frame_Info_t FrameOUT;\r
+\r
+/** Constant for convenience when checking against or setting a MAC address to the virtual server MAC address. */\r
+const MAC_Address_t ServerMACAddress    = {SERVER_MAC_ADDRESS};\r
+\r
+/** Constant for convenience when checking against or setting an IP address to the virtual server IP address. */\r
+const IP_Address_t  ServerIPAddress     = {SERVER_IP_ADDRESS};\r
+\r
+/** Constant for convenience when checking against or setting a MAC address to the broadcast MAC address. */\r
+const MAC_Address_t BroadcastMACAddress = {BROADCAST_MAC_ADDRESS};\r
+\r
+/** Constant for convenience when checking against or setting a IP address to the broadcast IP address. */\r
+const IP_Address_t  BroadcastIPAddress  = {BROADCAST_IP_ADDRESS};\r
+\r
+/** Constant for convenience when checking against or setting an IP address to the client (host) IP address. */\r
+const IP_Address_t  ClientIPAddress     = {CLIENT_IP_ADDRESS};\r
+\r
+\r
+/** Processes an incoming Ethernet frame, and writes the appropriate response to the output Ethernet\r
+ *  frame buffer if the sub protocol handlers create a valid response.\r
+ */\r
+void Ethernet_ProcessPacket(void)\r
+{\r
+       DecodeEthernetFrameHeader(FrameIN.FrameData);\r
+\r
+       /* Cast the incoming Ethernet frame to the Ethernet header type */\r
+       Ethernet_Frame_Header_t* FrameINHeader  = (Ethernet_Frame_Header_t*)&FrameIN.FrameData;\r
+       Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData;\r
+       \r
+       int16_t                  RetSize        = NO_RESPONSE;\r
+       \r
+       /* Ensure frame is addressed to either all (broadcast) or the virtual webserver, and is a type II frame */\r
+       if ((MAC_COMPARE(&FrameINHeader->Destination, &ServerMACAddress) ||\r
+            MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress)) &&\r
+               (SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE))\r
+       {\r
+               /* Process the packet depending on its protocol */\r
+               switch (SwapEndian_16(FrameINHeader->EtherType))\r
+               {\r
+                       case ETHERTYPE_ARP:\r
+                               RetSize = ARP_ProcessARPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],\r
+                                                              &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);\r
+                               break;          \r
+                       case ETHERTYPE_IPV4:\r
+                               RetSize = IP_ProcessIPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],\r
+                                                            &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);\r
+                               break;\r
+               }\r
+               \r
+               /* Protocol processing routine has filled a response, complete the ethernet frame header */\r
+               if (RetSize > 0)\r
+               {\r
+                       /* Fill out the response Ethernet frame header */\r
+                       FrameOUTHeader->Source          = ServerMACAddress;\r
+                       FrameOUTHeader->Destination     = FrameINHeader->Source;\r
+                       FrameOUTHeader->EtherType       = FrameINHeader->EtherType;\r
+                       \r
+                       /* Set the response length in the buffer and indicate that a response is ready to be sent */\r
+                       FrameOUT.FrameLength            = (sizeof(Ethernet_Frame_Header_t) + RetSize);\r
+                       FrameOUT.FrameInBuffer          = true;\r
+               }\r
+       }\r
+\r
+       /* Check if the packet was processed */\r
+       if (RetSize != NO_PROCESS)\r
+       {\r
+               /* Clear the frame buffer */\r
+               FrameIN.FrameInBuffer = false;\r
+       }\r
+}\r
+\r
+/** Calculates the appropriate ethernet checksum, consisting of the addition of the one's\r
+ *  compliment of each word, complimented.\r
+ *\r
+ *  \param Data   Pointer to the packet buffer data whose checksum must be calculated\r
+ *  \param Bytes  Number of bytes in the data buffer to process\r
+ *\r
+ *  \return A 16-bit Ethernet checksum value\r
+ */\r
+uint16_t Ethernet_Checksum16(void* Data, uint16_t Bytes)\r
+{\r
+       uint16_t* Words    = (uint16_t*)Data;\r
+       uint32_t  Checksum = 0;\r
+\r
+       for (uint8_t CurrWord = 0; CurrWord < (Bytes >> 1); CurrWord++)\r
+         Checksum += Words[CurrWord];\r
+         \r
+       while (Checksum & 0xFFFF0000)\r
+         Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16));\r
+       \r
+       return ~Checksum;\r
+}\r