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