From b9b03aadb219d06fbad9d110e508db93e45461af Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Fri, 5 Jun 2009 07:16:33 +0000 Subject: Move new Class Driver powered demos to a new ClassDriver subdirectory, re-add old low level demos to a LowLevel subdirectory. --- Demos/Device/LowLevel/RNDISEthernet/Descriptors.c | 263 ++++ Demos/Device/LowLevel/RNDISEthernet/Descriptors.h | 98 ++ Demos/Device/LowLevel/RNDISEthernet/Doxygen.conf | 1485 ++++++++++++++++++++ Demos/Device/LowLevel/RNDISEthernet/LUFA RNDIS.inf | 52 + Demos/Device/LowLevel/RNDISEthernet/Lib/ARP.c | 85 ++ Demos/Device/LowLevel/RNDISEthernet/Lib/ARP.h | 76 + Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.c | 118 ++ Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.h | 125 ++ Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.c | 136 ++ Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.h | 116 ++ .../LowLevel/RNDISEthernet/Lib/EthernetProtocols.h | 87 ++ Demos/Device/LowLevel/RNDISEthernet/Lib/ICMP.c | 79 ++ Demos/Device/LowLevel/RNDISEthernet/Lib/ICMP.h | 80 ++ Demos/Device/LowLevel/RNDISEthernet/Lib/IP.c | 111 ++ Demos/Device/LowLevel/RNDISEthernet/Lib/IP.h | 93 ++ .../LowLevel/RNDISEthernet/Lib/ProtocolDecoders.c | 280 ++++ .../LowLevel/RNDISEthernet/Lib/ProtocolDecoders.h | 56 + Demos/Device/LowLevel/RNDISEthernet/Lib/RNDIS.c | 394 ++++++ Demos/Device/LowLevel/RNDISEthernet/Lib/RNDIS.h | 226 +++ .../LowLevel/RNDISEthernet/Lib/RNDISConstants.h | 99 ++ Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.c | 614 ++++++++ Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.h | 253 ++++ Demos/Device/LowLevel/RNDISEthernet/Lib/UDP.c | 80 ++ Demos/Device/LowLevel/RNDISEthernet/Lib/UDP.h | 66 + .../Device/LowLevel/RNDISEthernet/Lib/Webserver.c | 162 +++ .../Device/LowLevel/RNDISEthernet/Lib/Webserver.h | 55 + .../LowLevel/RNDISEthernet/RNDISEthernet.aps | 1 + .../Device/LowLevel/RNDISEthernet/RNDISEthernet.c | 338 +++++ .../Device/LowLevel/RNDISEthernet/RNDISEthernet.h | 100 ++ .../LowLevel/RNDISEthernet/RNDISEthernet.txt | 115 ++ Demos/Device/LowLevel/RNDISEthernet/makefile | 747 ++++++++++ 31 files changed, 6590 insertions(+) create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Descriptors.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Descriptors.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Doxygen.conf create mode 100644 Demos/Device/LowLevel/RNDISEthernet/LUFA RNDIS.inf create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/ARP.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/ARP.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/EthernetProtocols.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/ICMP.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/ICMP.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/IP.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/IP.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/ProtocolDecoders.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/ProtocolDecoders.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/RNDIS.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/RNDIS.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/RNDISConstants.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/UDP.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/UDP.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.aps create mode 100644 Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c create mode 100644 Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.h create mode 100644 Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.txt create mode 100644 Demos/Device/LowLevel/RNDISEthernet/makefile (limited to 'Demos/Device/LowLevel/RNDISEthernet') diff --git a/Demos/Device/LowLevel/RNDISEthernet/Descriptors.c b/Demos/Device/LowLevel/RNDISEthernet/Descriptors.c new file mode 100644 index 000000000..1be5bfd26 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Descriptors.c @@ -0,0 +1,263 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * USB Device Descriptors, for library use when in USB device mode. Descriptors are special + * computer-readable structures which the host requests upon device enumeration, to determine + * the device's capabilities and functions. + */ + +#include "Descriptors.h" + +/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall + * device characteristics, including the supported USB version, control endpoint size and the + * number of device configurations. The descriptor is read out by the USB host when the enumeration + * process begins. + */ +USB_Descriptor_Device_t PROGMEM DeviceDescriptor = +{ + .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, + + .USBSpecification = VERSION_BCD(01.10), + .Class = 0x02, + .SubClass = 0x00, + .Protocol = 0x00, + + .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, + + .VendorID = 0x03EB, + .ProductID = 0x204C, + .ReleaseNumber = 0x0000, + + .ManufacturerStrIndex = 0x01, + .ProductStrIndex = 0x02, + .SerialNumStrIndex = NO_DESCRIPTOR, + + .NumberOfConfigurations = 1 +}; + +/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage + * of the device in one of its supported configurations, including information about any device interfaces + * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting + * a configuration so that the host may correctly communicate with the USB device. + */ +USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = +{ + .Config = + { + .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, + + .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), + .TotalInterfaces = 2, + + .ConfigurationNumber = 1, + .ConfigurationStrIndex = NO_DESCRIPTOR, + + .ConfigAttributes = (USB_CONFIG_ATTR_BUSPOWERED | USB_CONFIG_ATTR_SELFPOWERED), + + .MaxPowerConsumption = USB_CONFIG_POWER_MA(100) + }, + + .CCI_Interface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = 0, + .AlternateSetting = 0, + + .TotalEndpoints = 1, + + .Class = 0x02, + .SubClass = 0x02, + .Protocol = 0xFF, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .CDC_Functional_Header = + { + .Header = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type = 0x24}, + .SubType = 0x00, + + .Data = {0x01, 0x10} + }, + + .CDC_Functional_CallManagement= + { + .Header = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type = 0x24}, + .SubType = 0x01, + + .Data = {0x00, 0x00} + }, + + .CDC_Functional_AbstractControlManagement = + { + .Header = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(1)), .Type = 0x24}, + .SubType = 0x02, + + .Data = {0x00} + }, + + .CDC_Functional_Union = + { + .Header = {.Size = sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), .Type = 0x24}, + .SubType = 0x06, + + .Data = {0x00, 0x01} + }, + + .ManagementEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC_NOTIFICATION_EPNUM), + .Attributes = EP_TYPE_INTERRUPT, + .EndpointSize = CDC_NOTIFICATION_EPSIZE, + .PollingIntervalMS = 0x02 + }, + + .DCI_Interface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = 1, + .AlternateSetting = 0, + + .TotalEndpoints = 2, + + .Class = 0x0A, + .SubClass = 0x00, + .Protocol = 0x00, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .DataOutEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_OUT | CDC_RX_EPNUM), + .Attributes = EP_TYPE_BULK, + .EndpointSize = CDC_TXRX_EPSIZE, + .PollingIntervalMS = 0x00 + }, + + .DataInEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC_TX_EPNUM), + .Attributes = EP_TYPE_BULK, + .EndpointSize = CDC_TXRX_EPSIZE, + .PollingIntervalMS = 0x00 + } +}; + +/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests + * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate + * via the language ID table available at USB.org what languages the device supports for its string descriptors. + */ +USB_Descriptor_String_t PROGMEM LanguageString = +{ + .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String}, + + .UnicodeString = {LANGUAGE_ID_ENG} +}; + +/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable + * form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device + * Descriptor. + */ +USB_Descriptor_String_t PROGMEM ManufacturerString = +{ + .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String}, + + .UnicodeString = L"Dean Camera" +}; + +/** Product descriptor string. This is a Unicode string containing the product's details in human readable form, + * and is read out upon request by the host when the appropriate string ID is requested, listed in the Device + * Descriptor. + */ +USB_Descriptor_String_t PROGMEM ProductString = +{ + .Header = {.Size = USB_STRING_LEN(19), .Type = DTYPE_String}, + + .UnicodeString = L"LUFA RNDIS CDC Demo" +}; + +/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors" + * documentation) by the application code so that the address and size of a requested descriptor can be given + * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function + * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the + * USB host. + */ +uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress) +{ + const uint8_t DescriptorType = (wValue >> 8); + const uint8_t DescriptorNumber = (wValue & 0xFF); + + void* Address = NULL; + uint16_t Size = NO_DESCRIPTOR; + + switch (DescriptorType) + { + case DTYPE_Device: + Address = (void*)&DeviceDescriptor; + Size = sizeof(USB_Descriptor_Device_t); + break; + case DTYPE_Configuration: + Address = (void*)&ConfigurationDescriptor; + Size = sizeof(USB_Descriptor_Configuration_t); + break; + case DTYPE_String: + switch (DescriptorNumber) + { + case 0x00: + Address = (void*)&LanguageString; + Size = pgm_read_byte(&LanguageString.Header.Size); + break; + case 0x01: + Address = (void*)&ManufacturerString; + Size = pgm_read_byte(&ManufacturerString.Header.Size); + break; + case 0x02: + Address = (void*)&ProductString; + Size = pgm_read_byte(&ProductString.Header.Size); + break; + } + + break; + } + + *DescriptorAddress = Address; + return Size; +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Descriptors.h b/Demos/Device/LowLevel/RNDISEthernet/Descriptors.h new file mode 100644 index 000000000..eb4373552 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Descriptors.h @@ -0,0 +1,98 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for Descriptors.c. + */ + +#ifndef _DESCRIPTORS_H_ +#define _DESCRIPTORS_H_ + + /* Includes: */ + #include + + #include + + /* Macros: */ + /** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a + * uniform structure but variable sized data payloads, thus cannot be represented accurately by + * a single typedef struct. A macro is used instead so that functional descriptors can be created + * easily by specifying the size of the payload. This allows sizeof() to work correctly. + * + * \param DataSize Size in bytes of the CDC functional descriptor's data payload + */ + #define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \ + struct \ + { \ + USB_Descriptor_Header_t Header; \ + uint8_t SubType; \ + uint8_t Data[DataSize]; \ + } + + /** Endpoint number of the CDC device-to-host notification IN endpoint. */ + #define CDC_NOTIFICATION_EPNUM 3 + + /** Endpoint number of the CDC device-to-host data IN endpoint. */ + #define CDC_TX_EPNUM 1 + + /** Endpoint number of the CDC host-to-device data OUT endpoint. */ + #define CDC_RX_EPNUM 2 + + /** Size in bytes of the CDC device-to-host notification IN endpoint. */ + #define CDC_NOTIFICATION_EPSIZE 8 + + /** Size in bytes of the CDC data IN and OUT endpoints. */ + #define CDC_TXRX_EPSIZE 64 + + /* Type Defines: */ + /** Type define for the device configuration descriptor structure. This must be defined in the + * application code, as the configuration descriptor contains several sub-descriptors which + * vary between devices, and which describe the device's usage to the host. + */ + typedef struct + { + USB_Descriptor_Configuration_Header_t Config; + USB_Descriptor_Interface_t CCI_Interface; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Header; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_CallManagement; + CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_AbstractControlManagement; + CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union; + USB_Descriptor_Endpoint_t ManagementEndpoint; + USB_Descriptor_Interface_t DCI_Interface; + USB_Descriptor_Endpoint_t DataOutEndpoint; + USB_Descriptor_Endpoint_t DataInEndpoint; + } USB_Descriptor_Configuration_t; + + /* Function Prototypes: */ + uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress) + ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Doxygen.conf b/Demos/Device/LowLevel/RNDISEthernet/Doxygen.conf new file mode 100644 index 000000000..9d7973b78 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Doxygen.conf @@ -0,0 +1,1485 @@ +# Doxyfile 1.5.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "LUFA Library - RNDIS Ethernet Demo" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.0.0 + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./Documentation/ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, +# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, +# Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ./ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = *.h \ + *.c \ + *.txt + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = */LowLevel/USBMode.h + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = __* + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = NO + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = YES + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = YES + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# Qt Help Project / Namespace. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# Qt Help Project / Virtual Folders. + +QHP_VIRTUAL_FOLDER = doc + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file . + +QHG_LOCATION = + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 1 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to FRAME, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. Other possible values +# for this tag are: HIERARCHIES, which will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list; +# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which +# disables this behavior completely. For backwards compatibility with previous +# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE +# respectively. + +GENERATE_TREEVIEW = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = __DOXYGEN__ + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = BUTTLOADTAG + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = NO + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = NO + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = NO + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = NO + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = NO + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = NO + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = NO + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = "C:/Program Files/Graphviz2.18/bin" + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 15 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 2 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/Demos/Device/LowLevel/RNDISEthernet/LUFA RNDIS.inf b/Demos/Device/LowLevel/RNDISEthernet/LUFA RNDIS.inf new file mode 100644 index 000000000..a124afec1 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/LUFA RNDIS.inf @@ -0,0 +1,52 @@ +; Windows LUFA RNDIS Setup File +; Copyright (c) 2000 Microsoft Corporation + +[Version] +Signature = "$Windows NT$" +Class = Net +ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} +Provider = %COMPANY% +DriverVer = 06/21/2006,6.0.6000.16384 +;CatalogFile = device.cat + +[Manufacturer] +%COMPANY% = RndisDevices,NTx86,NTamd64,NTia64 + +; Decoration for x86 architecture +[RndisDevices.NTx86] +%RNDISDEV% = RNDIS.NT.5.1, USB\VID_03EB&PID_204C + +; Decoration for x64 architecture +[RndisDevices.NTamd64] +%RNDISDEV% = RNDIS.NT.5.1, USB\VID_03EB&PID_204C + +; Decoration for ia64 architecture +[RndisDevices.NTia64] +%RNDISDEV% = RNDIS.NT.5.1, USB\VID_03EB&PID_204C + +;@@@ This is the common setting for setup +[ControlFlags] +ExcludeFromSelect=* + +; DDInstall section +; References the in-build Netrndis.inf +[RNDIS.NT.5.1] +Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI +BusType = 15 +; NEVER REMOVE THE FOLLOWING REFERENCE FOR NETRNDIS.INF +include = netrndis.inf +needs = Usb_Rndis.ndi +AddReg = Rndis_AddReg_Vista + +; DDInstal.Services section +[RNDIS.NT.5.1.Services] +include = netrndis.inf +needs = Usb_Rndis.ndi.Services + +; No sys copyfiles - the sys files are already in-build +; (part of the operating system). + +; Modify these strings for your device as needed. +[Strings] +COMPANY="LUFA Library" +RNDISDEV="LUFA USB RNDIS Demo" \ No newline at end of file diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/ARP.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/ARP.c new file mode 100644 index 000000000..0f108c290 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/ARP.c @@ -0,0 +1,85 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Address Resolution Protocol (ARP) packet handling routines. This protocol handles the + * conversion of physical MAC addresses to protocol IP addresses between the host and the + * device. + */ + +#include "ARP.h" + +/** Processes an ARP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if the host is requesting the IP or MAC address of the + * virtual server device on the network. + * + * \param InDataStart Pointer to the start of the incoming packet's ARP header + * \param OutDataStart Pointer to the start of the outgoing packet's ARP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise + */ +int16_t ARP_ProcessARPPacket(void* InDataStart, void* OutDataStart) +{ + DecodeARPHeader(InDataStart); + + ARP_Header_t* ARPHeaderIN = (ARP_Header_t*)InDataStart; + ARP_Header_t* ARPHeaderOUT = (ARP_Header_t*)OutDataStart; + + /* Ensure that the ARP request is a IPv4 request packet */ + if ((SwapEndian_16(ARPHeaderIN->ProtocolType) == ETHERTYPE_IPV4) && + (SwapEndian_16(ARPHeaderIN->Operation) == ARP_OPERATION_REQUEST)) + { + /* If the ARP packet is requesting the MAC or IP of the virtual webserver, return the response */ + if (IP_COMPARE(&ARPHeaderIN->TPA, &ServerIPAddress) || + MAC_COMPARE(&ARPHeaderIN->THA, &ServerMACAddress)) + { + /* Fill out the ARP response header */ + ARPHeaderOUT->HardwareType = ARPHeaderIN->HardwareType; + ARPHeaderOUT->ProtocolType = ARPHeaderIN->ProtocolType; + ARPHeaderOUT->HLEN = ARPHeaderIN->HLEN; + ARPHeaderOUT->PLEN = ARPHeaderIN->PLEN; + ARPHeaderOUT->Operation = SwapEndian_16(ARP_OPERATION_REPLY); + + /* Copy over the sender MAC/IP to the target fields for the response */ + ARPHeaderOUT->THA = ARPHeaderIN->SHA; + ARPHeaderOUT->TPA = ARPHeaderIN->SPA; + + /* Copy over the new sender MAC/IP - MAC and IP addresses of the virtual webserver */ + ARPHeaderOUT->SHA = ServerMACAddress; + ARPHeaderOUT->SPA = ServerIPAddress; + + /* Return the size of the response so far */ + return sizeof(ARP_Header_t); + } + } + + return NO_RESPONSE; +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/ARP.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/ARP.h new file mode 100644 index 000000000..8551df85b --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/ARP.h @@ -0,0 +1,76 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for ARP.c. + */ + +#ifndef _ARP_H_ +#define _ARP_H_ + + /* Includes: */ + #include + #include + + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** ARP header operation constant, indicating a request from a host for an address translation */ + #define ARP_OPERATION_REQUEST 1 + + /** ARP header operation constant, indicating a reply from a host giving an address translation */ + #define ARP_OPERATION_REPLY 2 + + /* Type Defines: */ + /** Type define for an ARP packet inside an Ethernet frame. */ + typedef struct + { + uint16_t HardwareType; /**< Hardware type constant, indicating the hardware used */ + uint16_t ProtocolType; /**< Protocol being resolved, usually ETHERTYPE_IPV4 */ + + uint8_t HLEN; /**< Length in bytes of the source/destination hardware addresses */ + uint8_t PLEN; /**< Length in bytes of the source/destination protocol addresses */ + uint16_t Operation; /**< Type of operation, either ARP_OPERATION_REQUEST or ARP_OPERATION_REPLY */ + + MAC_Address_t SHA; /**< Sender's hardware address */ + IP_Address_t SPA; /**< Sender's protocol address */ + MAC_Address_t THA; /**< Target's hardware address */ + IP_Address_t TPA; /**< Target's protocol address */ + } ARP_Header_t; + + /* Function Prototypes: */ + int16_t ARP_ProcessARPPacket(void* InDataStart, void* OutDataStart); + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.c new file mode 100644 index 000000000..76711fb4f --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.c @@ -0,0 +1,118 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Dynamic Host Configuration Protocol (DHCP) packet handling routines. This protocol + * handles the automatic IP negotiation to the host, so that the host will use the provided + * IP address given to it by the device. + */ + +#include "DHCP.h" + +/** Processes a DHCP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if the host is requesting or accepting an IP address. + * + * \param IPHeaderInStart Pointer to the start of the incoming packet's IP header + * \param DHCPHeaderInStart Pointer to the start of the incoming packet's DHCP header + * \param DHCPHeaderOutStart Pointer to the start of the outgoing packet's DHCP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise + */ +int16_t DHCP_ProcessDHCPPacket(void* IPHeaderInStart, void* DHCPHeaderInStart, void* DHCPHeaderOutStart) +{ + IP_Header_t* IPHeaderIN = (IP_Header_t*)IPHeaderInStart; + DHCP_Header_t* DHCPHeaderIN = (DHCP_Header_t*)DHCPHeaderInStart; + DHCP_Header_t* DHCPHeaderOUT = (DHCP_Header_t*)DHCPHeaderOutStart; + + uint8_t* DHCPOptionsINStart = (uint8_t*)(DHCPHeaderInStart + sizeof(DHCP_Header_t)); + uint8_t* DHCPOptionsOUTStart = (uint8_t*)(DHCPHeaderOutStart + sizeof(DHCP_Header_t)); + + DecodeDHCPHeader(DHCPHeaderInStart); + + /* Zero out the response DHCP packet, as much of it legacy and left at 0 */ + memset(DHCPHeaderOUT, 0, sizeof(DHCP_Header_t)); + + /* Fill out the response DHCP packet */ + DHCPHeaderOUT->HardwareType = DHCPHeaderIN->HardwareType; + DHCPHeaderOUT->Operation = DHCP_OP_BOOTREPLY; + DHCPHeaderOUT->HardwareAddressLength = DHCPHeaderIN->HardwareAddressLength; + DHCPHeaderOUT->Hops = 0; + DHCPHeaderOUT->TransactionID = DHCPHeaderIN->TransactionID; + DHCPHeaderOUT->ElapsedSeconds = 0; + DHCPHeaderOUT->Flags = DHCPHeaderIN->Flags; + DHCPHeaderOUT->YourIP = ClientIPAddress; + memcpy(&DHCPHeaderOUT->ClientHardwareAddress, &DHCPHeaderIN->ClientHardwareAddress, sizeof(MAC_Address_t)); + DHCPHeaderOUT->Cookie = SwapEndian_32(DHCP_MAGIC_COOKIE); + + /* Alter the incoming IP packet header so that the corrected IP source and destinations are used - this means that + when the response IP header is generated, it will use the corrected addresses and not the null/broatcast addresses */ + IPHeaderIN->SourceAddress = ClientIPAddress; + IPHeaderIN->DestinationAddress = ServerIPAddress; + + /* Process the incoming DHCP packet options */ + while (DHCPOptionsINStart[0] != DHCP_OPTION_END) + { + /* Find the Message Type DHCP option, to determine the type of DHCP packet */ + if (DHCPOptionsINStart[0] == DHCP_OPTION_MESSAGETYPE) + { + if ((DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_DISCOVER) || (DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_REQUEST)) + { + /* Fill out the response DHCP packet options for a DHCP OFFER or ACK response */ + + *(DHCPOptionsOUTStart++) = DHCP_OPTION_MESSAGETYPE; + *(DHCPOptionsOUTStart++) = 1; + *(DHCPOptionsOUTStart++) = (DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_DISCOVER) ? DHCP_MESSAGETYPE_OFFER + : DHCP_MESSAGETYPE_ACK; + + *(DHCPOptionsOUTStart++) = DHCP_OPTION_SUBNETMASK; + *(DHCPOptionsOUTStart++) = 4; + *(DHCPOptionsOUTStart++) = 0xFF; + *(DHCPOptionsOUTStart++) = 0xFF; + *(DHCPOptionsOUTStart++) = 0xFF; + *(DHCPOptionsOUTStart++) = 0x00; + + *(DHCPOptionsOUTStart++) = DHCP_OPTION_DHCPSERVER; + *(DHCPOptionsOUTStart++) = sizeof(IP_Address_t); + memcpy(DHCPOptionsOUTStart, &ServerIPAddress, sizeof(IP_Address_t)); + DHCPOptionsOUTStart += sizeof(IP_Address_t); + + *(DHCPOptionsOUTStart++) = DHCP_OPTION_END; + + return (sizeof(DHCP_Header_t) + 12 + sizeof(IP_Address_t)); + } + } + + /* Go to the next DHCP option - skip one byte if option is a padding byte, else skip the complete option's size */ + DHCPOptionsINStart += ((DHCPOptionsINStart[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptionsINStart[1] + 2)); + } + + return NO_RESPONSE; +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.h new file mode 100644 index 000000000..f0e68b994 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.h @@ -0,0 +1,125 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for DHCP.c. + */ + +#ifndef _DHCP_H_ +#define _DHCP_H_ + + /* Includes: */ + #include + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** DHCP operation constant, indicating a request from a host to a DHCP server */ + #define DHCP_OP_BOOTREQUEST 0x01 + + /** DHCP operation constant, indicating a reply from a DHCP server to a host */ + #define DHCP_OP_BOOTREPLY 0x02 + + /** Hardware type constant, indicating Ethernet as a carrier */ + #define DHCP_HTYPE_ETHERNET 0x01 + + /** Magic boot protocol "cookie", inserted into all BOOTP packets (BOOTP is the carrier of DHCP) */ + #define DHCP_MAGIC_COOKIE 0x63825363 + + /** DHCP option list entry header, indicating that a subnet mask will follow */ + #define DHCP_OPTION_SUBNETMASK 1 + + /** DHCP option list entry header, indicating that the DHCP message type constant will follow */ + #define DHCP_OPTION_MESSAGETYPE 53 + + /** DHCP option list entry header, indicating that the IP address of the DHCP server will follow */ + #define DHCP_OPTION_DHCPSERVER 54 + + /** DHCP option list entry header, used to pad out option data */ + #define DHCP_OPTION_PAD 0 + + /** DHCP option list entry header, indicating the end of option data */ + #define DHCP_OPTION_END 255 + + /** Message type constant, used in the DHCP option data field, requesting that a DHCP server offer an IP address */ + #define DHCP_MESSAGETYPE_DISCOVER 1 + + /** Message type constant, used in the DHCP option data field, indicating that a DHCP server is offering an IP address */ + #define DHCP_MESSAGETYPE_OFFER 2 + + /** Message type constant, used in the DHCP option data field, requesting that a DHCP server lease a given IP address */ + #define DHCP_MESSAGETYPE_REQUEST 3 + + /** Message type constant, used in the DHCP option data field, declining an offered DHCP server IP address lease */ + #define DHCP_MESSAGETYPE_DECLINE 4 + + /** Message type constant, used in the DHCP option data field, ACKing a host IP lease request */ + #define DHCP_MESSAGETYPE_ACK 5 + + /** Message type constant, used in the DHCP option data field, NACKing a host IP lease request */ + #define DHCP_MESSAGETYPE_NACK 6 + + /** Message type constant, used in the DHCP option data field, indicating that a host is releasing a leased IP address */ + #define DHCP_MESSAGETYPE_RELEASE 7 + + /* Type Defines: */ + /** Type define for a DHCP packet inside an Ethernet frame. */ + typedef struct + { + uint8_t Operation; /**< DHCP operation, either DHCP_OP_BOOTREQUEST or DHCP_OP_BOOTREPLY */ + uint8_t HardwareType; /**< Hardware carrier type constant */ + uint8_t HardwareAddressLength; /**< Length in bytes of a hardware (MAC) address on the network */ + uint8_t Hops; /**< Number of hops required to reach the server, unused */ + + uint32_t TransactionID; /**< Unique ID of the DHCP packet, for positive matching between sent and received packets */ + + uint16_t ElapsedSeconds; /**< Elapsed seconds since the request was made */ + uint16_t Flags; /**< BOOTP packet flags */ + + IP_Address_t ClientIP; /**< Client IP address, if already leased an IP */ + IP_Address_t YourIP; /**< Client IP address */ + IP_Address_t NextServerIP; /**< Legacy BOOTP protocol field, unused for DHCP */ + IP_Address_t RelayAgentIP; /**< Legacy BOOTP protocol field, unused for DHCP */ + + uint8_t ClientHardwareAddress[16]; /**< Hardware (MAC) address of the client making a request to the DHCP server */ + uint8_t ServerHostnameString[64]; /**< Legacy BOOTP protocol field, unused for DHCP */ + uint8_t BootFileName[128]; /**< Legacy BOOTP protocol field, unused for DHCP */ + + uint32_t Cookie; /**< Magic BOOTP protocol cookie to indicate a valid packet */ + } DHCP_Header_t; + + /* Function Prototypes: */ + int16_t DHCP_ProcessDHCPPacket(void* IPHeaderInStart, void* DHCPHeaderInStart, void* DHCPHeaderOutStart); + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.c new file mode 100644 index 000000000..3d34f716a --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.c @@ -0,0 +1,136 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 subpacket protocols to the appropriate + * protocol handlers, such as DHCP or ARP. + */ + +#include "Ethernet.h" + +/* Global Variables: */ +/** Ethernet Frame buffer structure, to hold the incoming Ethernet frame from the host. */ +Ethernet_Frame_Info_t FrameIN; + +/** Ethernet Frame buffer structure, to hold the outgoing Ethernet frame to the host. */ +Ethernet_Frame_Info_t FrameOUT; + +/** 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(void) +{ + 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.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); + FrameOUT.FrameInBuffer = true; + } + } + + /* Check if the packet was processed */ + if (RetSize != NO_PROCESS) + { + /* Clear the frame buffer */ + FrameIN.FrameInBuffer = false; + } +} + +/** Calculates the appropriate ethernet checksum, consisting of the addition of the one's + * compliment of each word, complimented. + * + * \param Data Pointer to the packet buffer data whose checksum must be calculated + * \param 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 (uint8_t CurrWord = 0; CurrWord < (Bytes >> 1); CurrWord++) + Checksum += Words[CurrWord]; + + while (Checksum & 0xFFFF0000) + Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16)); + + return ~Checksum; +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.h new file mode 100644 index 000000000..b360f07ae --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/Ethernet.h @@ -0,0 +1,116 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for Ethernet.c. + */ + +#ifndef _ETHERNET_H_ +#define _ETHERNET_H_ + + /* Includes: */ + #include + #include + + #include "EthernetProtocols.h" + #include "ProtocolDecoders.h" + #include "ICMP.h" + #include "TCP.h" + #include "UDP.h" + #include "DHCP.h" + #include "ARP.h" + #include "IP.h" + + /* Macros: */ + /** Physical MAC address of the virtual server on the network */ + #define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01} + + /** Physical MAC address of the network broadcast address */ + #define BROADCAST_MAC_ADDRESS {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + + /** Performs a comparison between two MAC addresses, indicating if they are identical. + * + * \param MAC1 First MAC address + * \param MAC2 Second MAC address + * + * \return True if the addresses match, false otherwise + */ + #define MAC_COMPARE(MAC1, MAC2) (memcmp(MAC1, MAC2, sizeof(MAC_Address_t)) == 0) + + /** Maximum size of an incoming or outgoing Ethernet frame in bytes */ + #define ETHERNET_FRAME_SIZE_MAX 1500 + + /** Minimum size of an Ethernet packet in bytes, to conform to the Ethernet V2 packet standard */ + #define ETHERNET_VER2_MINSIZE 0x0600 + + /** Return value for all sub protocol handling routines, indicating that no response packet has been generated */ + #define NO_RESPONSE 0 + + /** Return value for all sub protocol handling routines, indicating that the packet has not yet been handled */ + #define NO_PROCESS -1 + + /* Type Defines: */ + /** Type define for an Ethernet frame buffer. */ + typedef struct + { + uint8_t FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents */ + uint16_t FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer */ + bool FrameInBuffer; /**< Indicates if a frame is currently stored in the buffer */ + } Ethernet_Frame_Info_t; + + /** Type define for an Ethernet frame header */ + typedef struct + { + MAC_Address_t Destination; /**< Physical MAC address of the packet recipient */ + MAC_Address_t Source; /**< Physics MAC address of the packet source */ + + union + { + uint16_t EtherType; /**< Ethernet packet subprotocol type, for Ethernet V2 packets */ + uint16_t Length; /**< Ethernet frame length, for Ethernet V1 packets */ + }; + } Ethernet_Frame_Header_t; + + /* External Variables: */ + extern Ethernet_Frame_Info_t FrameIN; + extern Ethernet_Frame_Info_t FrameOUT; + + extern const MAC_Address_t ServerMACAddress; + extern const IP_Address_t ServerIPAddress; + extern const MAC_Address_t BroadcastMACAddress; + extern const IP_Address_t BroadcastIPAddress; + extern const IP_Address_t ClientIPAddress; + + /* Function Prototypes: */ + void Ethernet_ProcessPacket(void); + uint16_t Ethernet_Checksum16(void* Data, uint16_t Bytes); + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/EthernetProtocols.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/EthernetProtocols.h new file mode 100644 index 000000000..3ff3433ae --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/EthernetProtocols.h @@ -0,0 +1,87 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * General Ethernet protocol constants and type defines, for use by + * all network protocol portions of the TCP/IP stack. + */ + +#ifndef _ETHERNET_PROTOCOLS_H_ +#define _ETHERNET_PROTOCOLS_H_ + + /* Macros: */ + #define ETHERTYPE_IPV4 0x0800 + #define ETHERTYPE_ARP 0x0806 + #define ETHERTYPE_RARP 0x8035 + #define ETHERTYPE_APPLETALK 0x809b + #define ETHERTYPE_APPLETALKARP 0x80f3 + #define ETHERTYPE_IEEE8021Q 0x8100 + #define ETHERTYPE_NOVELLIPX 0x8137 + #define ETHERTYPE_NOVELL 0x8138 + #define ETHERTYPE_IPV6 0x86DD + #define ETHERTYPE_COBRANET 0x8819 + #define ETHERTYPE_PROVIDERBRIDGING 0x88a8 + #define ETHERTYPE_MPLSUNICAST 0x8847 + #define ETHERTYPE_MPLSMULTICAST 0x8848 + #define ETHERTYPE_PPPoEDISCOVERY 0x8863 + #define ETHERTYPE_PPPoESESSION 0x8864 + #define ETHERTYPE_EAPOVERLAN 0x888E + #define ETHERTYPE_HYPERSCSI 0x889A + #define ETHERTYPE_ATAOVERETHERNET 0x88A2 + #define ETHERTYPE_ETHERCAT 0x88A4 + #define ETHERTYPE_SERCOSIII 0x88CD + #define ETHERTYPE_CESoE 0x88D8 + #define ETHERTYPE_MACSECURITY 0x88E5 + #define ETHERTYPE_FIBRECHANNEL 0x8906 + #define ETHERTYPE_QINQ 0x9100 + #define ETHERTYPE_VLLT 0xCAFE + + #define PROTOCOL_ICMP 1 + #define PROTOCOL_IGMP 2 + #define PROTOCOL_TCP 6 + #define PROTOCOL_UDP 17 + #define PROTOCOL_OSPF 89 + #define PROTOCOL_SCTP 132 + + /* Type Defines: */ + /** Type define for a physical MAC address of a device on a network */ + typedef struct + { + uint8_t Octets[6]; /**< Individual bytes of a MAC address */ + } MAC_Address_t; + + /** Type define for a protocol IP address of a device on a network */ + typedef struct + { + uint8_t Octets[4]; /**< Individual bytes of an IP address */ + } IP_Address_t; + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/ICMP.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/ICMP.c new file mode 100644 index 000000000..da4ffcfa1 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/ICMP.c @@ -0,0 +1,79 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Internet Control Message Protocol (ICMP) packet handling routines. This protocol handles + * Echo requests from the host, to indicate a successful network connection between the host + * and the virtual server. + */ + +#include "ICMP.h" + +/** Processes an ICMP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if the host is issuing a ICMP ECHO request. + * + * \param InDataStart Pointer to the start of the incoming packet's ICMP header + * \param OutDataStart Pointer to the start of the outgoing packet's ICMP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise + */ +int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart) +{ + ICMP_Header_t* ICMPHeaderIN = (ICMP_Header_t*)InDataStart; + ICMP_Header_t* ICMPHeaderOUT = (ICMP_Header_t*)OutDataStart; + + DecodeICMPHeader(InDataStart); + + /* Determine if the ICMP packet is an echo request (ping) */ + if (ICMPHeaderIN->Type == ICMP_TYPE_ECHOREQUEST) + { + /* Fill out the ICMP response packet */ + ICMPHeaderOUT->Type = ICMP_TYPE_ECHOREPLY; + ICMPHeaderOUT->Code = 0; + ICMPHeaderOUT->Checksum = 0; + ICMPHeaderOUT->Id = ICMPHeaderIN->Id; + ICMPHeaderOUT->Sequence = ICMPHeaderIN->Sequence; + + uint16_t DataSize = FrameIN.FrameLength - ((((uint16_t)InDataStart + sizeof(ICMP_Header_t)) - (uint16_t)FrameIN.FrameData)); + + /* Copy the remaining payload to the response - echo requests should echo back any sent data */ + memcpy(&((uint8_t*)OutDataStart)[sizeof(ICMP_Header_t)], + &((uint8_t*)InDataStart)[sizeof(ICMP_Header_t)], + DataSize); + + ICMPHeaderOUT->Checksum = Ethernet_Checksum16(ICMPHeaderOUT, (DataSize + sizeof(ICMP_Header_t))); + + /* Return the size of the response so far */ + return (DataSize + sizeof(ICMP_Header_t)); + } + + return NO_RESPONSE; +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/ICMP.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/ICMP.h new file mode 100644 index 000000000..b20a557e9 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/ICMP.h @@ -0,0 +1,80 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for ICMP.c. + */ + +#ifndef _ICMP_H_ +#define _ICMP_H_ + + /* Includes: */ + #include + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** ICMP message type constant, indicating an ICMP ECHO Reply message */ + #define ICMP_TYPE_ECHOREPLY 0 + + /** ICMP message type constant, indicating a packet destination is unreachable */ + #define ICMP_TYPE_DESTINATIONUNREACHABLE 3 + + /** ICMP message type constant, indicating an ICMP Source Quench message */ + #define ICMP_TYPE_SOURCEQUENCH 4 + + /** ICMP message type constant, indicating an ICMP Redirect message */ + #define ICMP_TYPE_REDIRECTMESSAGE 5 + + /** ICMP message type constant, indicating an ICMP ECHO Request message */ + #define ICMP_TYPE_ECHOREQUEST 8 + + /** ICMP message type constant, indicating an ICMP Time Exceeded message */ + #define ICMP_TYPE_TIMEEXCEEDED 11 + + /* Type Defines: */ + /** Type define for an ICMP message header. */ + typedef struct + { + uint8_t Type; /**< ICMP message type, a ICMP_TYPE_* constant */ + uint8_t Code; /**< ICMP message code, indicating the message value */ + uint16_t Checksum; /**< Ethernet checksum of the ICMP message */ + uint16_t Id; /**< Id of the ICMP message */ + uint16_t Sequence; /**< Sequence number of the ICMP message, to link together message responses */ + } ICMP_Header_t; + + /* Function Prototypes: */ + int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart); + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/IP.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/IP.c new file mode 100644 index 000000000..8fb0b446d --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/IP.c @@ -0,0 +1,111 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Internet Protocol (IP) packet handling routines. This protocol handles IP packets from the + * host which typically encapsulate other protocols such as ICMP, UDP and TCP. + */ + +#include "IP.h" + +/** Processes an IP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if one is created by a subprotocol handler. + * + * \param InDataStart Pointer to the start of the incoming packet's IP header + * \param OutDataStart Pointer to the start of the outgoing packet's IP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE if no + * response was generated, NO_PROCESS if the packet processing was deferred until the + * next Ethernet packet handler iteration + */ +int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart) +{ + DecodeIPHeader(InDataStart); + + IP_Header_t* IPHeaderIN = (IP_Header_t*)InDataStart; + IP_Header_t* IPHeaderOUT = (IP_Header_t*)OutDataStart; + + /* Header length is specified in number of longs in the packet header, convert to bytes */ + uint16_t HeaderLengthBytes = (IPHeaderIN->HeaderLength * sizeof(uint32_t)); + + int16_t RetSize = NO_RESPONSE; + + /* Check to ensure the IP packet is addressed to the virtual webserver's IP or the broadcast IP address */ + if (!(IP_COMPARE(&IPHeaderIN->DestinationAddress, &ServerIPAddress)) && + !(IP_COMPARE(&IPHeaderIN->DestinationAddress, &BroadcastIPAddress))) + { + return NO_RESPONSE; + } + + /* Pass off the IP payload to the appropriate protocol processing routine */ + switch (IPHeaderIN->Protocol) + { + case PROTOCOL_ICMP: + RetSize = ICMP_ProcessICMPPacket(&((uint8_t*)InDataStart)[HeaderLengthBytes], + &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]); + break; + case PROTOCOL_TCP: + RetSize = TCP_ProcessTCPPacket(InDataStart, + &((uint8_t*)InDataStart)[HeaderLengthBytes], + &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]); + break; + case PROTOCOL_UDP: + RetSize = UDP_ProcessUDPPacket(InDataStart, + &((uint8_t*)InDataStart)[HeaderLengthBytes], + &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]); + break; + } + + /* Check to see if the protocol processing routine has filled out a response */ + if (RetSize > 0) + { + /* Fill out the response IP packet header */ + IPHeaderOUT->TotalLength = SwapEndian_16(sizeof(IP_Header_t) + RetSize); + IPHeaderOUT->TypeOfService = 0; + IPHeaderOUT->HeaderLength = (sizeof(IP_Header_t) / sizeof(uint32_t)); + IPHeaderOUT->Version = 4; + IPHeaderOUT->Flags = 0; + IPHeaderOUT->FragmentOffset = 0; + IPHeaderOUT->Identification = 0; + IPHeaderOUT->HeaderChecksum = 0; + IPHeaderOUT->Protocol = IPHeaderIN->Protocol; + IPHeaderOUT->TTL = DEFAULT_TTL; + IPHeaderOUT->SourceAddress = IPHeaderIN->DestinationAddress; + IPHeaderOUT->DestinationAddress = IPHeaderIN->SourceAddress; + + IPHeaderOUT->HeaderChecksum = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t)); + + /* Return the size of the response so far */ + return (sizeof(IP_Header_t) + RetSize); + } + + return RetSize; +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/IP.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/IP.h new file mode 100644 index 000000000..fc1a46aef --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/IP.h @@ -0,0 +1,93 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for IP.c. + */ + +#ifndef _IP_H_ +#define _IP_H_ + + /* Includes: */ + #include + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** Protocol IP address of the host (client) machine, once assigned by DHCP */ + #define CLIENT_IP_ADDRESS { 10, 0, 0, 1} + + /** Protocol IP address of the virtual server machine */ + #define SERVER_IP_ADDRESS { 10, 0, 0, 2} + + /** Protocol IP address of the broadcast address */ + #define BROADCAST_IP_ADDRESS {0xFF, 0xFF, 0xFF, 0xFF} + + /** Default Time To Live (TTL) value for sent packets, indicating the maximum allowable hops until their destination is reached */ + #define DEFAULT_TTL 128 + + /** Performs a comparison between two IP addresses, indicating if they are identical. + * + * \param IP1 First IP address + * \param IP2 Second IP address + * + * \return True if the addresses match, false otherwise + */ + #define IP_COMPARE(IP1, IP2) (memcmp(IP1, IP2, sizeof(IP_Address_t)) == 0) + + /* Type Defines: */ + /** Type define of an IP packet header. */ + typedef struct + { + unsigned char HeaderLength : 4; /**< Total length of the packet header, in 4-byte blocks */ + unsigned char Version : 4; /**< IP protocol version */ + uint8_t TypeOfService; /**< Special service type identifier, indicating delay/throughput/reliability levels */ + uint16_t TotalLength; /**< Total length of the IP packet, in bytes */ + + uint16_t Identification; /**< Identification value for identifying fragmented packets */ + unsigned int FragmentOffset : 13; /**< Offset of this IP fragment */ + unsigned int Flags : 3; /**< Fragment flags, to indicate if a packet is fragmented */ + + uint8_t TTL; /**< Maximum allowable number of hops to reach the packet destination */ + uint8_t Protocol; /**< Encapsulated protocol type */ + uint16_t HeaderChecksum; /**< Ethernet checksum of the IP header */ + + IP_Address_t SourceAddress; /**< Source protocol IP address of the packet */ + IP_Address_t DestinationAddress; /**< Destination protocol IP address of the packet */ + } IP_Header_t; + + /* Function Prototypes: */ + int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart); + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/ProtocolDecoders.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/ProtocolDecoders.c new file mode 100644 index 000000000..add0333f2 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/ProtocolDecoders.c @@ -0,0 +1,280 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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. +*/ + +/* Protocol decoders for Ethernet, TCP, IP, ICMP and ARP. Each of these routines + accepts a header to the appropriate protocol and prints out pertinent information + on the packet through the serial port. + + To disable printing of a specific protocol, define the token NO_DECODE_{Protocol} + in the project makefile, and pass it to the compiler using the -D switch. +*/ + +/** \file + * + * Protocol decoding routines, for the plain-text decoding of Ethernet frames for debugging purposes. + * Enabled protocol decoders will print incoming Ethernet frame contents through the USART in a human + * readable format. + * + * Note that the USART is a slow transmission medium, and will slow down packet processing considerably. + * Packet decoding routines can be disabled by defining NO_DECODE_{Protocol Name} in the project makefile + * and passing it to the compiler via the -D switch. + */ + +#include "ProtocolDecoders.h" + +/** Decodes an Ethernet frame header and prints its contents to through the USART in a human readable format. + * + * \param InDataStart Pointer to the start of an Ethernet frame header + */ +void DecodeEthernetFrameHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_ETHERNET) + Ethernet_Frame_Header_t* FrameHeader = (Ethernet_Frame_Header_t*)InDataStart; + + printf_P(PSTR("\r\n")); + + printf_P(PSTR(" ETHERNET\r\n")); + printf_P(PSTR(" + Frame Size: %u\r\n"), FrameIN.FrameLength); + + if (!(MAC_COMPARE(&FrameHeader->Destination, &ServerMACAddress)) && + !(MAC_COMPARE(&FrameHeader->Destination, &BroadcastMACAddress))) + { + printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n")); + return; + } + + printf_P(PSTR(" + MAC Source : %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader->Source.Octets[0], + FrameHeader->Source.Octets[1], + FrameHeader->Source.Octets[2], + FrameHeader->Source.Octets[3], + FrameHeader->Source.Octets[4], + FrameHeader->Source.Octets[5]); + + printf_P(PSTR(" + MAC Dest: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader->Destination.Octets[0], + FrameHeader->Destination.Octets[1], + FrameHeader->Destination.Octets[2], + FrameHeader->Destination.Octets[3], + FrameHeader->Destination.Octets[4], + FrameHeader->Destination.Octets[5]); + + if (SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE) + printf_P(PSTR(" + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader->EtherType)); + else + printf_P(PSTR(" + Protocol: UNKNOWN E1\r\n")); + #endif +} + +/** Decodes an ARP header and prints its contents to through the USART in a human readable format. + * + * \param InDataStart Pointer to the start of an ARP packet header + */ +void DecodeARPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_ARP) + ARP_Header_t* ARPHeader = (ARP_Header_t*)InDataStart; + + printf_P(PSTR(" \\\r\n ARP\r\n")); + + if (!(IP_COMPARE(&ARPHeader->TPA, &ServerIPAddress)) && + !(MAC_COMPARE(&ARPHeader->THA, &ServerMACAddress))) + { + printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n")); + return; + } + + printf_P(PSTR(" + Protocol: %x\r\n"), SwapEndian_16(ARPHeader->ProtocolType)); + printf_P(PSTR(" + Operation: %u\r\n"), SwapEndian_16(ARPHeader->Operation)); + + if (SwapEndian_16(ARPHeader->ProtocolType) == ETHERTYPE_IPV4) + { + printf_P(PSTR(" + SHA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader->SHA.Octets[0], + ARPHeader->SHA.Octets[1], + ARPHeader->SHA.Octets[2], + ARPHeader->SHA.Octets[3], + ARPHeader->SHA.Octets[4], + ARPHeader->SHA.Octets[5]); + + printf_P(PSTR(" + SPA IP: %u.%u.%u.%u\r\n"), ARPHeader->SPA.Octets[0], + ARPHeader->SPA.Octets[1], + ARPHeader->SPA.Octets[2], + ARPHeader->SPA.Octets[3]); + + printf_P(PSTR(" + THA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader->THA.Octets[0], + ARPHeader->THA.Octets[1], + ARPHeader->THA.Octets[2], + ARPHeader->THA.Octets[3], + ARPHeader->THA.Octets[4], + ARPHeader->THA.Octets[5]); + + printf_P(PSTR(" + TPA IP: %u.%u.%u.%u\r\n"), ARPHeader->TPA.Octets[0], + ARPHeader->TPA.Octets[1], + ARPHeader->TPA.Octets[2], + ARPHeader->TPA.Octets[3]); + } + #endif +} + +/** Decodes an IP header and prints its contents to through the USART in a human readable format. + * + * \param InDataStart Pointer to the start of an IP packet header + */ +void DecodeIPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_IP) + IP_Header_t* IPHeader = (IP_Header_t*)InDataStart; + + uint16_t HeaderLengthBytes = (IPHeader->HeaderLength * sizeof(uint32_t)); + + printf_P(PSTR(" \\\r\n IP\r\n")); + + if (!(IP_COMPARE(&IPHeader->DestinationAddress, &ServerIPAddress))) + { + printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n")); + return; + } + + printf_P(PSTR(" + Header Length: %u Bytes\r\n"), HeaderLengthBytes); + printf_P(PSTR(" + Packet Version: %u\r\n"), IPHeader->Version); + printf_P(PSTR(" + Total Length: %u\r\n"), SwapEndian_16(IPHeader->TotalLength)); + + printf_P(PSTR(" + Protocol: %u\r\n"), IPHeader->Protocol); + printf_P(PSTR(" + TTL: %u\r\n"), IPHeader->TTL); + + printf_P(PSTR(" + IP Src: %u.%u.%u.%u\r\n"), IPHeader->SourceAddress.Octets[0], + IPHeader->SourceAddress.Octets[1], + IPHeader->SourceAddress.Octets[2], + IPHeader->SourceAddress.Octets[3]); + + printf_P(PSTR(" + IP Dst: %u.%u.%u.%u\r\n"), IPHeader->DestinationAddress.Octets[0], + IPHeader->DestinationAddress.Octets[1], + IPHeader->DestinationAddress.Octets[2], + IPHeader->DestinationAddress.Octets[3]); + #endif +} + +/** Decodes an ICMP header and prints its contents to through the USART in a human readable format. + * + * \param InDataStart Pointer to the start of an ICMP packet header + */ +void DecodeICMPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_ICMP) + ICMP_Header_t* ICMPHeader = (ICMP_Header_t*)InDataStart; + + printf_P(PSTR(" \\\r\n ICMP\r\n")); + + printf_P(PSTR(" + Type: %u\r\n"), ICMPHeader->Type); + printf_P(PSTR(" + Code: %u\r\n"), ICMPHeader->Code); + #endif +} + +/** Decodes a TCP header and prints its contents to through the USART in a human readable format. + * + * \param InDataStart Pointer to the start of a TCP packet header + */ +void DecodeTCPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_TCP) + TCP_Header_t* TCPHeader = (TCP_Header_t*)InDataStart; + + uint16_t HeaderLengthBytes = (TCPHeader->DataOffset * sizeof(uint32_t)); + + printf_P(PSTR(" \\\r\n TCP\r\n")); + + printf_P(PSTR(" + Header Length: %u Bytes\r\n"), HeaderLengthBytes); + + printf_P(PSTR(" + Source Port: %u\r\n"), SwapEndian_16(TCPHeader->SourcePort)); + printf_P(PSTR(" + Destination Port: %u\r\n"), SwapEndian_16(TCPHeader->DestinationPort)); + + printf_P(PSTR(" + Sequence Number: %lu\r\n"), SwapEndian_32(TCPHeader->SequenceNumber)); + printf_P(PSTR(" + Acknowledgment Number: %lu\r\n"), SwapEndian_32(TCPHeader->AcknowledgmentNumber)); + + printf_P(PSTR(" + Flags: 0x%02X\r\n"), TCPHeader->Flags); + + if (TCP_GetPortState(TCPHeader->DestinationPort) == TCP_Port_Closed) + printf_P(PSTR(" + NOT LISTENING ON DESTINATION PORT\r\n")); + #endif +} + +/** Decodes an UDP header and prints its contents to through the USART in a human readable format. + * + * \param InDataStart Pointer to the start of a UDP packet header + */ +void DecodeUDPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_UDP) + UDP_Header_t* UDPHeader = (UDP_Header_t*)InDataStart; + + printf_P(PSTR(" \\\r\n UDP\r\n")); + + printf_P(PSTR(" + Source Port: %u\r\n"), SwapEndian_16(UDPHeader->SourcePort)); + printf_P(PSTR(" + Destination Port: %u\r\n"), SwapEndian_16(UDPHeader->DestinationPort)); + + printf_P(PSTR(" + Data Length: %d\r\n"), SwapEndian_16(UDPHeader->Length)); + #endif +} + +/** Decodes an DHCP header and prints its contents to through the USART in a human readable format. + * + * \param InDataStart Pointer to the start of a DHCP packet header + */ +void DecodeDHCPHeader(void* InDataStart) +{ + #if !defined(NO_DECODE_DHCP) + uint8_t* DHCPOptions = (InDataStart + sizeof(DHCP_Header_t)); + + printf_P(PSTR(" \\\r\n DHCP\r\n")); + + while (DHCPOptions[0] != DHCP_OPTION_END) + { + if (DHCPOptions[0] == DHCP_OPTION_MESSAGETYPE) + { + switch (DHCPOptions[2]) + { + case DHCP_MESSAGETYPE_DISCOVER: + printf_P(PSTR(" + DISCOVER\r\n")); + break; + case DHCP_MESSAGETYPE_REQUEST: + printf_P(PSTR(" + REQUEST\r\n")); + break; + case DHCP_MESSAGETYPE_RELEASE: + printf_P(PSTR(" + RELEASE\r\n")); + break; + case DHCP_MESSAGETYPE_DECLINE: + printf_P(PSTR(" + DECLINE\r\n")); + break; + } + } + + DHCPOptions += ((DHCPOptions[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptions[1] + 2)); + } + + #endif +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/ProtocolDecoders.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/ProtocolDecoders.h new file mode 100644 index 000000000..fa0a869eb --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/ProtocolDecoders.h @@ -0,0 +1,56 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for ProtocolDecoders.c. + */ + +#ifndef _PROTOCOL_DECODERS_H_ +#define _PROTOCOL_DECODERS_H_ + + /* Includes: */ + #include + + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + + /* Function Prototypes: */ + void DecodeEthernetFrameHeader(void* InDataStart); + void DecodeARPHeader(void* InDataStart); + void DecodeIPHeader(void* InDataStart); + void DecodeICMPHeader(void* InDataStart); + void DecodeTCPHeader(void* InDataStart); + void DecodeUDPHeader(void* InDataStart); + void DecodeDHCPHeader(void* InDataStart); + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/RNDIS.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/RNDIS.c new file mode 100644 index 000000000..c5202bcd1 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/RNDIS.c @@ -0,0 +1,394 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * RNDIS command handler functions. This handles RNDIS commands according to + * the Microsoft RNDIS specification, creating a USB Ethernet network adapter. + */ + +#define INCLUDE_FROM_RNDIS_C +#include "RNDIS.h" + +/* Global Variables: */ +/** Physical MAC address of the network adapter, which becomes the MAC address of the host for packets sent to the adapter. */ +static MAC_Address_t PROGMEM AdapterMACAddress = {ADAPTER_MAC_ADDRESS}; + +/** Vendor description of the adapter. This is overridden by the INF file required to install the appropriate RNDIS drivers for + * the device, but may still be used by the OS in some circumstances. + */ +static char PROGMEM AdapterVendorDescription[] = "LUFA RNDIS Adapter"; + +/** List of RNDIS OID commands supported by this adapter. */ +static const uint32_t PROGMEM AdapterSupportedOIDList[] = + { + OID_GEN_SUPPORTED_LIST, + OID_GEN_PHYSICAL_MEDIUM, + OID_GEN_HARDWARE_STATUS, + OID_GEN_MEDIA_SUPPORTED, + OID_GEN_MEDIA_IN_USE, + OID_GEN_MAXIMUM_FRAME_SIZE, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_LINK_SPEED, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_MEDIA_CONNECT_STATUS, + OID_GEN_XMIT_OK, + OID_GEN_RCV_OK, + OID_GEN_XMIT_ERROR, + OID_GEN_RCV_ERROR, + OID_GEN_RCV_NO_BUFFER, + OID_802_3_PERMANENT_ADDRESS, + OID_802_3_CURRENT_ADDRESS, + OID_802_3_MULTICAST_LIST, + OID_802_3_MAXIMUM_LIST_SIZE, + OID_802_3_RCV_ERROR_ALIGNMENT, + OID_802_3_XMIT_ONE_COLLISION, + OID_802_3_XMIT_MORE_COLLISIONS, + }; + +/** Buffer for RNDIS messages (as distinct from Ethernet frames sent through the adapter. This must be big enough to hold the entire + * Supported OID list, plus the response header. The buffer is half-duplex, and is written to as it is read to save on SRAM - for this + * reason, care must be taken when constructing RNDIS responses that unread data is not overwritten when writing in responses. + */ +uint8_t RNDISMessageBuffer[sizeof(AdapterSupportedOIDList) + sizeof(RNDIS_QUERY_CMPLT_t)]; + +/** Pointer to the RNDIS message header at the top of the RNDIS message buffer, for convenience. */ +RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISMessageBuffer; + +/** Indicates if a RNDIS message response is ready to be sent back to the host. */ +bool ResponseReady = false; + +/** Current RNDIS adapter state, a value from the RNDIS_States_t enum. */ +uint8_t CurrRNDISState = RNDIS_Uninitialized; + +/** Current Ethernet packet filter mask. This is non-zero when the adapter is initialized, or zero when disabled. */ +uint32_t CurrPacketFilter = 0; + + +/** Processes the RNDIS message received by the host and stored in the RNDISMessageBuffer global buffer. If a response is + * created, the ResponseReady global is updated so that the response is written back to the host upon request. + */ +void ProcessRNDISControlMessage(void) +{ + /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of + this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */ + + switch (MessageHeader->MessageType) + { + case REMOTE_NDIS_INITIALIZE_MSG: + /* Initialize the adapter - return information about the supported RNDIS version and buffer sizes */ + + ResponseReady = true; + + RNDIS_INITIALIZE_MSG_t* INITIALIZE_Message = (RNDIS_INITIALIZE_MSG_t*)&RNDISMessageBuffer; + RNDIS_INITIALIZE_CMPLT_t* INITIALIZE_Response = (RNDIS_INITIALIZE_CMPLT_t*)&RNDISMessageBuffer; + + INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; + INITIALIZE_Response->MessageLength = sizeof(RNDIS_INITIALIZE_CMPLT_t); + INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId; + INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS; + + INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR; + INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR; + INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS; + INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3; + INITIALIZE_Response->MaxPacketsPerTransfer = 1; + INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_PACKET_MSG_t) + ETHERNET_FRAME_SIZE_MAX); + INITIALIZE_Response->PacketAlignmentFactor = 0; + INITIALIZE_Response->AFListOffset = 0; + INITIALIZE_Response->AFListSize = 0; + + CurrRNDISState = RNDIS_Initialized; + + break; + case REMOTE_NDIS_HALT_MSG: + /* Halt the adapter, reset the adapter state - note that no response should be returned when completed */ + + ResponseReady = false; + MessageHeader->MessageLength = 0; + + CurrRNDISState = RNDIS_Uninitialized; + + break; + case REMOTE_NDIS_QUERY_MSG: + /* Request for information about a parameter about the adapter, specified as an OID token */ + + ResponseReady = true; + + RNDIS_QUERY_MSG_t* QUERY_Message = (RNDIS_QUERY_MSG_t*)&RNDISMessageBuffer; + RNDIS_QUERY_CMPLT_t* QUERY_Response = (RNDIS_QUERY_CMPLT_t*)&RNDISMessageBuffer; + uint32_t Query_Oid = QUERY_Message->Oid; + + void* QueryData = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) + + QUERY_Message->InformationBufferOffset]; + void* ResponseData = &RNDISMessageBuffer[sizeof(RNDIS_QUERY_CMPLT_t)]; + uint16_t ResponseSize; + + QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT; + QUERY_Response->MessageLength = sizeof(RNDIS_QUERY_CMPLT_t); + + if (ProcessNDISQuery(Query_Oid, QueryData, QUERY_Message->InformationBufferLength, + ResponseData, &ResponseSize)) + { + QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS; + QUERY_Response->MessageLength += ResponseSize; + + QUERY_Response->InformationBufferLength = ResponseSize; + QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_QUERY_CMPLT_t) - sizeof(RNDIS_Message_Header_t)); + } + else + { + QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED; + + QUERY_Response->InformationBufferLength = 0; + QUERY_Response->InformationBufferOffset = 0; + } + + break; + case REMOTE_NDIS_SET_MSG: + /* Request to set a parameter of the adapter, specified as an OID token */ + + ResponseReady = true; + + RNDIS_SET_MSG_t* SET_Message = (RNDIS_SET_MSG_t*)&RNDISMessageBuffer; + RNDIS_SET_CMPLT_t* SET_Response = (RNDIS_SET_CMPLT_t*)&RNDISMessageBuffer; + uint32_t SET_Oid = SET_Message->Oid; + + SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT; + SET_Response->MessageLength = sizeof(RNDIS_SET_CMPLT_t); + SET_Response->RequestId = SET_Message->RequestId; + + void* SetData = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) + + SET_Message->InformationBufferOffset]; + + if (ProcessNDISSet(SET_Oid, SetData, SET_Message->InformationBufferLength)) + SET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS; + else + SET_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED; + + break; + case REMOTE_NDIS_RESET_MSG: + /* Soft reset the adapter */ + + ResponseReady = true; + + RNDIS_RESET_CMPLT_t* RESET_Response = (RNDIS_RESET_CMPLT_t*)&RNDISMessageBuffer; + + RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT; + RESET_Response->MessageLength = sizeof(RNDIS_RESET_CMPLT_t); + RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS; + RESET_Response->AddressingReset = 0; + + break; + case REMOTE_NDIS_KEEPALIVE_MSG: + /* Keep alive message sent to the adapter every 5 seconds when idle to ensure it is still responding */ + + ResponseReady = true; + + RNDIS_KEEPALIVE_MSG_t* KEEPALIVE_Message = (RNDIS_KEEPALIVE_MSG_t*)&RNDISMessageBuffer; + RNDIS_KEEPALIVE_CMPLT_t* KEEPALIVE_Response = (RNDIS_KEEPALIVE_CMPLT_t*)&RNDISMessageBuffer; + + KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; + KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KEEPALIVE_CMPLT_t); + KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId; + KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS; + + break; + } +} + +/** Processes RNDIS query commands, retrieving information from the adapter and reporting it back to the host. The requested + * parameter is given as an OID value. + * + * \param OId OId value of the parameter being queried + * \param QueryData Pointer to any extra query data being sent by the host to the device inside the RNDIS message buffer + * \param QuerySize Size in bytes of the extra query data being sent by the host + * \param ResponseData Pointer to the start of the query response inside the RNDIS message buffer + * \param ResponseSize Pointer to the size in bytes of the response data being sent to the host + * + * \return Boolean true if the query was handled, false otherwise + */ +static bool ProcessNDISQuery(uint32_t OId, void* QueryData, uint16_t QuerySize, + void* ResponseData, uint16_t* ResponseSize) +{ + /* Handler for REMOTE_NDIS_QUERY_MSG messages */ + + switch (OId) + { + case OID_GEN_SUPPORTED_LIST: + *ResponseSize = sizeof(AdapterSupportedOIDList); + + /* Copy the list of supported NDIS OID tokens to the response buffer */ + memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList)); + + return true; + case OID_GEN_PHYSICAL_MEDIUM: + *ResponseSize = sizeof(uint32_t); + + /* Indicate that the device is a true ethernet link */ + *((uint32_t*)ResponseData) = 0; + + return true; + case OID_GEN_HARDWARE_STATUS: + *ResponseSize = sizeof(uint32_t); + + /* Always indicate hardware ready */ + *((uint32_t*)ResponseData) = NdisHardwareStatusReady; + + return true; + case OID_GEN_MEDIA_SUPPORTED: + case OID_GEN_MEDIA_IN_USE: + *ResponseSize = sizeof(uint32_t); + + /* Indicate 802.3 (Ethernet) supported by the adapter */ + *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3; + + return true; + case OID_GEN_VENDOR_ID: + *ResponseSize = sizeof(uint32_t); + + /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */ + *((uint32_t*)ResponseData) = 0x00FFFFFF; + + return true; + case OID_GEN_MAXIMUM_FRAME_SIZE: + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + *ResponseSize = sizeof(uint32_t); + + /* Indicate that the maximum frame size is the size of the ethernet frame buffer */ + *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX; + + return true; + case OID_GEN_VENDOR_DESCRIPTION: + *ResponseSize = sizeof(AdapterVendorDescription); + + /* Copy vendor description string to the response buffer */ + memcpy_P(ResponseData, AdapterVendorDescription, sizeof(AdapterVendorDescription)); + + return true; + case OID_GEN_MEDIA_CONNECT_STATUS: + *ResponseSize = sizeof(uint32_t); + + /* Always indicate that the adapter is connected to a network */ + *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED; + + return true; + case OID_GEN_LINK_SPEED: + *ResponseSize = sizeof(uint32_t); + + /* Indicate 10Mb/s link speed */ + *((uint32_t*)ResponseData) = 100000; + + return true; + case OID_802_3_PERMANENT_ADDRESS: + case OID_802_3_CURRENT_ADDRESS: + *ResponseSize = sizeof(MAC_Address_t); + + /* Copy over the fixed adapter MAC to the response buffer */ + memcpy_P(ResponseData, &AdapterMACAddress, sizeof(MAC_Address_t)); + + return true; + case OID_802_3_MAXIMUM_LIST_SIZE: + *ResponseSize = sizeof(uint32_t); + + /* Indicate only one multicast address supported */ + *((uint32_t*)ResponseData) = 1; + + return true; + case OID_GEN_CURRENT_PACKET_FILTER: + *ResponseSize = sizeof(uint32_t); + + /* Indicate the current packet filter mask */ + *((uint32_t*)ResponseData) = CurrPacketFilter; + + return true; + case OID_GEN_XMIT_OK: + case OID_GEN_RCV_OK: + case OID_GEN_XMIT_ERROR: + case OID_GEN_RCV_ERROR: + case OID_GEN_RCV_NO_BUFFER: + case OID_802_3_RCV_ERROR_ALIGNMENT: + case OID_802_3_XMIT_ONE_COLLISION: + case OID_802_3_XMIT_MORE_COLLISIONS: + *ResponseSize = sizeof(uint32_t); + + /* Unused statistic OIDs - always return 0 for each */ + *((uint32_t*)ResponseData) = 0; + + return true; + case OID_GEN_MAXIMUM_TOTAL_SIZE: + *ResponseSize = sizeof(uint32_t); + + /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */ + *((uint32_t*)ResponseData) = (sizeof(RNDISMessageBuffer) + ETHERNET_FRAME_SIZE_MAX); + + return true; + default: + return false; + } +} + +/** Processes RNDIS set commands, setting adapter parameters to values given by the host. The requested parameter is given + * as an OID value. + * + * \param OId OId value of the parameter being set + * \param SetData Pointer to the parameter value in the RNDIS message buffer + * \param SetSize Size in bytes of the parameter value being sent by the host + * + * \return Boolean true if the set was handled, false otherwise + */ +static bool ProcessNDISSet(uint32_t OId, void* SetData, uint16_t SetSize) +{ + /* Handler for REMOTE_NDIS_SET_MSG messages */ + + switch (OId) + { + case OID_GEN_CURRENT_PACKET_FILTER: + /* Save the packet filter mask in case the host queries it again later */ + CurrPacketFilter = *((uint32_t*)SetData); + + /* Set the RNDIS state to initialized if the packet filter is non-zero */ + CurrRNDISState = ((CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Data_Initialized); + + return true; + case OID_802_3_MULTICAST_LIST: + /* Do nothing - throw away the value from the host as it is unused */ + + return true; + default: + return false; + } +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/RNDIS.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/RNDIS.h new file mode 100644 index 000000000..88c9a9eb9 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/RNDIS.h @@ -0,0 +1,226 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for RNDIS.c. + */ + +#ifndef _RNDIS_H_ +#define _RNDIS_H_ + + /* Includes: */ + #include + #include + + #include "RNDISEthernet.h" + #include "RNDISConstants.h" + #include "Ethernet.h" + + /* Macros: */ + /** Physical MAC Address of the USB network adapter */ + #define ADAPTER_MAC_ADDRESS {0x02, 0x00, 0x02, 0x00, 0x02, 0x00} + + /** Implemented RNDIS Version Major */ + #define REMOTE_NDIS_VERSION_MAJOR 0x01 + + /** Implemented RNDIS Version Minor */ + #define REMOTE_NDIS_VERSION_MINOR 0x00 + + /** RNDIS request to issue a host-to-device NDIS command */ + #define REQ_SendEncapsulatedCommand 0x00 + + /** RNDIS request to issue a device-to-host NDIS response */ + #define REQ_GetEncapsulatedResponse 0x01 + + /* Enums: */ + /** Enum for the possible NDIS adapter states. */ + enum RNDIS_States_t + { + RNDIS_Uninitialized = 0, /**< Adapter currently uninitialized */ + RNDIS_Initialized = 1, /**< Adapter currently initialized but not ready for data transfers */ + RNDIS_Data_Initialized = 2, /**< Adapter currently initialized and ready for data transfers */ + }; + + /** Enum for the NDIS hardware states */ + enum NDIS_Hardware_Status_t + { + NdisHardwareStatusReady, /**< Hardware Ready to accept commands from the host */ + NdisHardwareStatusInitializing, /**< Hardware busy initializing */ + NdisHardwareStatusReset, /**< Hardware reset */ + NdisHardwareStatusClosing, /**< Hardware currently closing */ + NdisHardwareStatusNotReady /**< Hardware not ready to accept commands from the host */ + }; + + /* Type Defines: */ + /** Type define for a RNDIS message header, sent before RNDIS messages */ + typedef struct + { + uint32_t MessageType; /**< RNDIS message type, a REMOTE_NDIS_*_MSG constant */ + uint32_t MessageLength; /**< Total length of the RNDIS message, in bytes */ + } RNDIS_Message_Header_t; + + /** Type define for a RNDIS packet message, used to encapsulate Ethernet packets sent to and from the adapter */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t DataOffset; + uint32_t DataLength; + uint32_t OOBDataOffset; + uint32_t OOBDataLength; + uint32_t NumOOBDataElements; + uint32_t PerPacketInfoOffset; + uint32_t PerPacketInfoLength; + uint32_t VcHandle; + uint32_t Reserved; + } RNDIS_PACKET_MSG_t; + + /** Type define for a RNDIS Initialize command message */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + + uint32_t MajorVersion; + uint32_t MinorVersion; + uint32_t MaxTransferSize; + } RNDIS_INITIALIZE_MSG_t; + + /** Type define for a RNDIS Initialize complete response message */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + uint32_t Status; + + uint32_t MajorVersion; + uint32_t MinorVersion; + uint32_t DeviceFlags; + uint32_t Medium; + uint32_t MaxPacketsPerTransfer; + uint32_t MaxTransferSize; + uint32_t PacketAlignmentFactor; + uint32_t AFListOffset; + uint32_t AFListSize; + } RNDIS_INITIALIZE_CMPLT_t; + + /** Type define for a RNDIS Keepalive command message */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + } RNDIS_KEEPALIVE_MSG_t; + + /** Type define for a RNDIS Keepalive complete message */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + uint32_t Status; + } RNDIS_KEEPALIVE_CMPLT_t; + + /** Type define for a RNDIS Reset complete message */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t Status; + + uint32_t AddressingReset; + } RNDIS_RESET_CMPLT_t; + + /** Type define for a RNDIS Set command message */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + + uint32_t Oid; + uint32_t InformationBufferLength; + uint32_t InformationBufferOffset; + uint32_t DeviceVcHandle; + } RNDIS_SET_MSG_t; + + /** Type define for a RNDIS Set complete response message */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + uint32_t Status; + } RNDIS_SET_CMPLT_t; + + /** Type define for a RNDIS Query command message */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + + uint32_t Oid; + uint32_t InformationBufferLength; + uint32_t InformationBufferOffset; + uint32_t DeviceVcHandle; + } RNDIS_QUERY_MSG_t; + + /** Type define for a RNDIS Query complete response message */ + typedef struct + { + uint32_t MessageType; + uint32_t MessageLength; + uint32_t RequestId; + uint32_t Status; + + uint32_t InformationBufferLength; + uint32_t InformationBufferOffset; + } RNDIS_QUERY_CMPLT_t; + + /* External Variables: */ + extern uint8_t RNDISMessageBuffer[]; + extern RNDIS_Message_Header_t* MessageHeader; + extern bool ResponseReady; + extern uint8_t CurrRNDISState; + + /* Function Prototypes: */ + void ProcessRNDISControlMessage(void); + + #if defined(INCLUDE_FROM_RNDIS_C) + static bool ProcessNDISQuery(uint32_t OId, void* QueryData, uint16_t QuerySize, + void* ResponseData, uint16_t* ResponseSize); + static bool ProcessNDISSet(uint32_t OId, void* SetData, uint16_t SetSize); + #endif + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/RNDISConstants.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/RNDISConstants.h new file mode 100644 index 000000000..ad66f62db --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/RNDISConstants.h @@ -0,0 +1,99 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * RNDIS specification related constants. For more information on these + * constants, please refer to the Microsoft RNDIS specification. + */ + +#ifndef _RNDIS_CONSTANTS_H_ +#define _RNDIS_CONSTANTS_H_ + + /* Macros: */ + #define REMOTE_NDIS_PACKET_MSG 0x00000001UL + #define REMOTE_NDIS_INITIALIZE_MSG 0x00000002UL + #define REMOTE_NDIS_HALT_MSG 0x00000003UL + #define REMOTE_NDIS_QUERY_MSG 0x00000004UL + #define REMOTE_NDIS_SET_MSG 0x00000005UL + #define REMOTE_NDIS_RESET_MSG 0x00000006UL + #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007UL + #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008UL + + #define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002UL + #define REMOTE_NDIS_QUERY_CMPLT 0x80000004UL + #define REMOTE_NDIS_SET_CMPLT 0x80000005UL + #define REMOTE_NDIS_RESET_CMPLT 0x80000006UL + #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008UL + + #define REMOTE_NDIS_STATUS_SUCCESS 0x00000000UL + #define REMOTE_NDIS_STATUS_FAILURE 0xC0000001UL + #define REMOTE_NDIS_STATUS_INVALID_DATA 0xC0010015UL + #define REMOTE_NDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL + #define REMOTE_NDIS_STATUS_MEDIA_CONNECT 0x4001000BUL + #define REMOTE_NDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL + + #define REMOTE_NDIS_MEDIA_STATE_CONNECTED 0x00000000UL + #define REMOTE_NDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL + + #define REMOTE_NDIS_MEDIUM_802_3 0x00000000UL + + #define REMOTE_NDIS_DF_CONNECTIONLESS 0x00000001UL + #define REMOTE_NDIS_DF_CONNECTION_ORIENTED 0x00000002UL + + #define OID_GEN_SUPPORTED_LIST 0x00010101UL + #define OID_GEN_HARDWARE_STATUS 0x00010102UL + #define OID_GEN_MEDIA_SUPPORTED 0x00010103UL + #define OID_GEN_MEDIA_IN_USE 0x00010104UL + #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL + #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL + #define OID_GEN_LINK_SPEED 0x00010107UL + #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL + #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL + #define OID_GEN_VENDOR_ID 0x0001010CUL + #define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL + #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL + #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL + #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL + #define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL + #define OID_GEN_XMIT_OK 0x00020101UL + #define OID_GEN_RCV_OK 0x00020102UL + #define OID_GEN_XMIT_ERROR 0x00020103UL + #define OID_GEN_RCV_ERROR 0x00020104UL + #define OID_GEN_RCV_NO_BUFFER 0x00020105UL + #define OID_802_3_PERMANENT_ADDRESS 0x01010101UL + #define OID_802_3_CURRENT_ADDRESS 0x01010102UL + #define OID_802_3_MULTICAST_LIST 0x01010103UL + #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL + #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL + #define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL + #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.c new file mode 100644 index 000000000..f259aad02 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.c @@ -0,0 +1,614 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Transmission Control Protocol (TCP) packet handling routines. This protocol handles the reliable in-order transmission + * and reception of packets to and from devices on a network, to "ports" on the device. It is used in situations where data + * delivery must be reliable and correct, e.g. HTTP, TELNET and most other non-streaming protocols. + */ + +#define INCLUDE_FROM_TCP_C +#include "TCP.h" + +/* Global Variables: */ +/** Port state table array. This contains the current status of TCP ports in the device. To save on space, only open ports are + * stored - closed ports may be overwritten at any time, and the system will assume any ports not present in the array are closed. This + * allows for MAX_OPEN_TCP_PORTS to be less than the number of ports used by the application if desired. + */ +TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS]; + +/** Connection state table array. This contains the current status of TCP connections in the device. To save on space, only active + * (non-closed) connections are stored - closed connections may be overwritten at any time, and the system will assume any connections + * not present in the array are closed. + */ +TCP_ConnectionState_t ConnectionStateTable[MAX_TCP_CONNECTIONS]; + + +/** Task to handle the calling of each registered application's callback function, to process and generate TCP packets at the application + * level. If an application produces a response, this task constructs the appropriate Ethernet frame and places it into the Ethernet OUT + * buffer for later transmission. + */ +TASK(TCP_Task) +{ + /* Task to hand off TCP packets to and from the listening applications. */ + + /* Run each application in sequence, to process incoming and generate outgoing packets */ + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* Find the corresponding port entry in the port table */ + for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++) + { + /* Run the application handler for the port */ + if ((PortStateTable[PTableEntry].Port == ConnectionStateTable[CSTableEntry].Port) && + (PortStateTable[PTableEntry].State == TCP_Port_Open)) + { + PortStateTable[PTableEntry].ApplicationHandler(&ConnectionStateTable[CSTableEntry], &ConnectionStateTable[CSTableEntry].Info.Buffer); + } + } + } + + /* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */ + if (FrameOUT.FrameInBuffer) + return; + + /* Send response packets from each application as the TCP packet buffers are filled by the applications */ + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* For each completely received packet, pass it along to the listening application */ + if ((ConnectionStateTable[CSTableEntry].Info.Buffer.Direction == TCP_PACKETDIR_OUT) && + (ConnectionStateTable[CSTableEntry].Info.Buffer.Ready)) + { + Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData; + IP_Header_t* IPHeaderOUT = (IP_Header_t*)&FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]; + TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) + + sizeof(IP_Header_t)]; + void* TCPDataOUT = &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) + + sizeof(IP_Header_t) + + sizeof(TCP_Header_t)]; + + uint16_t PacketSize = ConnectionStateTable[CSTableEntry].Info.Buffer.Length; + + /* Fill out the TCP data */ + TCPHeaderOUT->SourcePort = ConnectionStateTable[CSTableEntry].Port; + TCPHeaderOUT->DestinationPort = ConnectionStateTable[CSTableEntry].RemotePort; + TCPHeaderOUT->SequenceNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut); + TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberIn); + TCPHeaderOUT->DataOffset = (sizeof(TCP_Header_t) / sizeof(uint32_t)); + TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE); + + TCPHeaderOUT->Flags = TCP_FLAG_ACK; + TCPHeaderOUT->UrgentPointer = 0; + TCPHeaderOUT->Checksum = 0; + TCPHeaderOUT->Reserved = 0; + + memcpy(TCPDataOUT, ConnectionStateTable[CSTableEntry].Info.Buffer.Data, PacketSize); + + ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut += PacketSize; + + TCPHeaderOUT->Checksum = TCP_Checksum16(TCPHeaderOUT, ServerIPAddress, + ConnectionStateTable[CSTableEntry].RemoteAddress, + (sizeof(TCP_Header_t) + PacketSize)); + + PacketSize += sizeof(TCP_Header_t); + + /* Fill out the response IP header */ + IPHeaderOUT->TotalLength = SwapEndian_16(sizeof(IP_Header_t) + PacketSize); + IPHeaderOUT->TypeOfService = 0; + IPHeaderOUT->HeaderLength = (sizeof(IP_Header_t) / sizeof(uint32_t)); + IPHeaderOUT->Version = 4; + IPHeaderOUT->Flags = 0; + IPHeaderOUT->FragmentOffset = 0; + IPHeaderOUT->Identification = 0; + IPHeaderOUT->HeaderChecksum = 0; + IPHeaderOUT->Protocol = PROTOCOL_TCP; + IPHeaderOUT->TTL = DEFAULT_TTL; + IPHeaderOUT->SourceAddress = ServerIPAddress; + IPHeaderOUT->DestinationAddress = ConnectionStateTable[CSTableEntry].RemoteAddress; + + IPHeaderOUT->HeaderChecksum = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t)); + + PacketSize += sizeof(IP_Header_t); + + /* Fill out the response Ethernet frame header */ + FrameOUTHeader->Source = ServerMACAddress; + FrameOUTHeader->Destination = (MAC_Address_t){{0x02, 0x00, 0x02, 0x00, 0x02, 0x00}}; + FrameOUTHeader->EtherType = SwapEndian_16(ETHERTYPE_IPV4); + + PacketSize += sizeof(Ethernet_Frame_Header_t); + + /* Set the response length in the buffer and indicate that a response is ready to be sent */ + FrameOUT.FrameLength = PacketSize; + FrameOUT.FrameInBuffer = true; + + ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false; + + break; + } + } +} + +/** Initializes the TCP protocol handler, clearing the port and connection state tables. This must be called before TCP packets are + * processed. + */ +void TCP_Init(void) +{ + /* Initialize the port state table with all CLOSED entries */ + for (uint8_t PTableEntry = 0; PTableEntry < MAX_OPEN_TCP_PORTS; PTableEntry++) + PortStateTable[PTableEntry].State = TCP_Port_Closed; + + /* Initialize the connection table with all CLOSED entries */ + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + ConnectionStateTable[CSTableEntry].State = TCP_Connection_Closed; +} + +/** Sets the state and callback handler of the given port, specified in big endian to the given state. + * + * \param Port Port whose state and callback function to set, specified in big endian + * \param State New state of the port, a value from the TCP_PortStates_t enum + * \param Handler Application callback handler for the port + * + * \return Boolean true if the port state was set, false otherwise (no more space in the port state table) + */ +bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*)) +{ + /* Note, Port number should be specified in BIG endian to simplify network code */ + + /* Check to see if the port entry is already in the port state table */ + for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++) + { + /* Find existing entry for the port in the table, update it if found */ + if (PortStateTable[PTableEntry].Port == Port) + { + PortStateTable[PTableEntry].State = State; + PortStateTable[PTableEntry].ApplicationHandler = Handler; + return true; + } + } + + /* Check if trying to open the port -- if so we need to find an unused (closed) entry and replace it */ + if (State == TCP_Port_Open) + { + for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++) + { + /* Find a closed port entry in the table, change it to the given port and state */ + if (PortStateTable[PTableEntry].State == TCP_Port_Closed) + { + PortStateTable[PTableEntry].Port = Port; + PortStateTable[PTableEntry].State = State; + PortStateTable[PTableEntry].ApplicationHandler = Handler; + return true; + } + } + + /* Port not in table and no room to add it, return failure */ + return false; + } + else + { + /* Port not in table but trying to close it, so operation successful */ + return true; + } +} + +/** Retrieves the current state of a given TCP port, specified in big endian. + * + * \param Port TCP port whose state is to be retrieved, given in big-endian + * + * \return A value from the TCP_PortStates_t enum + */ +uint8_t TCP_GetPortState(uint16_t Port) +{ + /* Note, Port number should be specified in BIG endian to simplify network code */ + + for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++) + { + /* Find existing entry for the port in the table, return the port status if found */ + if (PortStateTable[PTableEntry].Port == Port) + return PortStateTable[PTableEntry].State; + } + + /* Port not in table, assume closed */ + return TCP_Port_Closed; +} + +/** Sets the connection state of the given port, remote address and remote port to the given TCP connection state. If the + * connection exists in the connection state table it is updated, otherwise it is created if possible. + * + * \param Port TCP port of the connection on the device, specified in big endian + * \param RemoteAddress Remote protocol IP address of the connected device + * \param RemotePort TCP port of the remote device in the connection, specified in big endian + * \param State TCP connection state, a value from the TCP_ConnectionStates_t enum + * + * \return Boolean true if the connection was updated or created, false otherwise (no more space in the connection state table) + */ +bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State) +{ + /* Note, Port number should be specified in BIG endian to simplify network code */ + + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* Find port entry in the table */ + if ((ConnectionStateTable[CSTableEntry].Port == Port) && + IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) && + ConnectionStateTable[CSTableEntry].RemotePort == RemotePort) + { + ConnectionStateTable[CSTableEntry].State = State; + return true; + } + } + + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* Find empty entry in the table */ + if (ConnectionStateTable[CSTableEntry].State == TCP_Connection_Closed) + { + ConnectionStateTable[CSTableEntry].Port = Port; + ConnectionStateTable[CSTableEntry].RemoteAddress = RemoteAddress; + ConnectionStateTable[CSTableEntry].RemotePort = RemotePort; + ConnectionStateTable[CSTableEntry].State = State; + return true; + } + } + + return false; +} + +/** Retrieves the current state of a given TCP connection to a host. + * + * \param Port TCP port on the device in the connection, specified in big endian + * \param RemoteAddress Remote protocol IP address of the connected host + * \param RemotePort Remote TCP port of the connected host, specified in big endian + * + * \return A value from the TCP_ConnectionStates_t enum + */ +uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort) +{ + /* Note, Port number should be specified in BIG endian to simplify network code */ + + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* Find port entry in the table */ + if ((ConnectionStateTable[CSTableEntry].Port == Port) && + IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) && + ConnectionStateTable[CSTableEntry].RemotePort == RemotePort) + + { + return ConnectionStateTable[CSTableEntry].State; + } + } + + return TCP_Connection_Closed; +} + +/** Retrieves the connection info structure of a given connection to a host. + * + * \param Port TCP port on the device in the connection, specified in big endian + * \param RemoteAddress Remote protocol IP address of the connected host + * \param RemotePort Remote TCP port of the connected host, specified in big endian + * + * \return ConnectionInfo structure of the connection if found, NULL otherwise + */ +TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort) +{ + /* Note, Port number should be specified in BIG endian to simplify network code */ + + for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++) + { + /* Find port entry in the table */ + if ((ConnectionStateTable[CSTableEntry].Port == Port) && + IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) && + ConnectionStateTable[CSTableEntry].RemotePort == RemotePort) + { + return &ConnectionStateTable[CSTableEntry].Info; + } + } + + return NULL; +} + +/** Processes a TCP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if one is created by a application handler. + * + * \param IPHeaderInStart Pointer to the start of the incoming packet's IP header + * \param TCPHeaderInStart Pointer to the start of the incoming packet's TCP header + * \param TCPHeaderOutStart Pointer to the start of the outgoing packet's TCP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE if no + * response was generated, NO_PROCESS if the packet processing was deferred until the + * next Ethernet packet handler iteration + */ +int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart) +{ + IP_Header_t* IPHeaderIN = (IP_Header_t*)IPHeaderInStart; + TCP_Header_t* TCPHeaderIN = (TCP_Header_t*)TCPHeaderInStart; + TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)TCPHeaderOutStart; + + TCP_ConnectionInfo_t* ConnectionInfo; + + DecodeTCPHeader(TCPHeaderInStart); + + bool PacketResponse = false; + + /* Check if the destination port is open and allows incoming connections */ + if (TCP_GetPortState(TCPHeaderIN->DestinationPort) == TCP_Port_Open) + { + /* Detect SYN from host to start a connection */ + if (TCPHeaderIN->Flags & TCP_FLAG_SYN) + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort, TCP_Connection_Listen); + + /* Detect RST from host to abort existing connection */ + if (TCPHeaderIN->Flags & TCP_FLAG_RST) + { + TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK); + PacketResponse = true; + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_Closed); + } + else + { + /* Process the incoming TCP packet based on the current connection state for the sender and port */ + switch (TCP_GetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort)) + { + case TCP_Connection_Listen: + if (TCPHeaderIN->Flags == TCP_FLAG_SYN) + { + /* SYN connection when closed starts a connection with a peer */ + + TCPHeaderOUT->Flags = (TCP_FLAG_SYN | TCP_FLAG_ACK); + PacketResponse = true; + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort, + TCP_Connection_SYNReceived); + + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort); + + ConnectionInfo->SequenceNumberIn = (SwapEndian_32(TCPHeaderIN->SequenceNumber) + 1); + ConnectionInfo->SequenceNumberOut = 0; + ConnectionInfo->Buffer.InUse = false; + } + + break; + case TCP_Connection_SYNReceived: + if (TCPHeaderIN->Flags == TCP_FLAG_ACK) + { + /* ACK during the connection process completes the connection to a peer */ + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_Established); + + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + ConnectionInfo->SequenceNumberOut++; + } + + break; + case TCP_Connection_Established: + if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK)) + { + /* FIN ACK when connected to a peer starts the finalization process */ + + TCPHeaderOUT->Flags = (TCP_FLAG_FIN | TCP_FLAG_ACK); + PacketResponse = true; + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_CloseWait); + + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + ConnectionInfo->SequenceNumberIn++; + ConnectionInfo->SequenceNumberOut++; + } + else if ((TCPHeaderIN->Flags == TCP_FLAG_ACK) || (TCPHeaderIN->Flags == (TCP_FLAG_ACK | TCP_FLAG_PSH))) + { + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + /* Check if the buffer is currently in use either by a buffered data to send, or receive */ + if ((ConnectionInfo->Buffer.InUse == false) && (ConnectionInfo->Buffer.Ready == false)) + { + ConnectionInfo->Buffer.Direction = TCP_PACKETDIR_IN; + ConnectionInfo->Buffer.InUse = true; + ConnectionInfo->Buffer.Length = 0; + } + + /* Check if the buffer has been claimed by us to read in data from the peer */ + if ((ConnectionInfo->Buffer.Direction == TCP_PACKETDIR_IN) && + (ConnectionInfo->Buffer.Length != TCP_WINDOW_SIZE)) + { + uint16_t IPOffset = (IPHeaderIN->HeaderLength * sizeof(uint32_t)); + uint16_t TCPOffset = (TCPHeaderIN->DataOffset * sizeof(uint32_t)); + uint16_t DataLength = (SwapEndian_16(IPHeaderIN->TotalLength) - IPOffset - TCPOffset); + + /* Copy the packet data into the buffer */ + memcpy(&ConnectionInfo->Buffer.Data[ConnectionInfo->Buffer.Length], + &((uint8_t*)TCPHeaderInStart)[TCPOffset], + DataLength); + + ConnectionInfo->SequenceNumberIn += DataLength; + ConnectionInfo->Buffer.Length += DataLength; + + /* Check if the buffer is full or if the PSH flag is set, if so indicate buffer ready */ + if ((!(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length)) || (TCPHeaderIN->Flags & TCP_FLAG_PSH)) + { + ConnectionInfo->Buffer.InUse = false; + ConnectionInfo->Buffer.Ready = true; + + TCPHeaderOUT->Flags = TCP_FLAG_ACK; + PacketResponse = true; + } + } + else + { + /* Buffer is currently in use by the application, defer processing of the incoming packet */ + return NO_PROCESS; + } + } + + break; + case TCP_Connection_Closing: + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + TCPHeaderOUT->Flags = (TCP_FLAG_ACK | TCP_FLAG_FIN); + PacketResponse = true; + + ConnectionInfo->Buffer.InUse = false; + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_FINWait1); + + break; + case TCP_Connection_FINWait1: + if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK)) + { + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + TCPHeaderOUT->Flags = TCP_FLAG_ACK; + PacketResponse = true; + + ConnectionInfo->SequenceNumberIn++; + ConnectionInfo->SequenceNumberOut++; + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_Closed); + } + else if (TCPHeaderIN->Flags == TCP_FLAG_ACK) + { + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_FINWait2); + } + + break; + case TCP_Connection_FINWait2: + if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK)) + { + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + TCPHeaderOUT->Flags = TCP_FLAG_ACK; + PacketResponse = true; + + ConnectionInfo->SequenceNumberIn++; + ConnectionInfo->SequenceNumberOut++; + + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_Closed); + } + + break; + case TCP_Connection_CloseWait: + if (TCPHeaderIN->Flags == TCP_FLAG_ACK) + { + TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort, TCP_Connection_Closed); + } + + break; + } + } + } + else + { + /* Port is not open, indicate via a RST/ACK response to the sender */ + TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK); + PacketResponse = true; + } + + /* Check if we need to respond to the sent packet */ + if (PacketResponse) + { + ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, + TCPHeaderIN->SourcePort); + + TCPHeaderOUT->SourcePort = TCPHeaderIN->DestinationPort; + TCPHeaderOUT->DestinationPort = TCPHeaderIN->SourcePort; + TCPHeaderOUT->SequenceNumber = SwapEndian_32(ConnectionInfo->SequenceNumberOut); + TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionInfo->SequenceNumberIn); + TCPHeaderOUT->DataOffset = (sizeof(TCP_Header_t) / sizeof(uint32_t)); + + if (!(ConnectionInfo->Buffer.InUse)) + TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE); + else + TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length); + + TCPHeaderOUT->UrgentPointer = 0; + TCPHeaderOUT->Checksum = 0; + TCPHeaderOUT->Reserved = 0; + + TCPHeaderOUT->Checksum = TCP_Checksum16(TCPHeaderOUT, IPHeaderIN->DestinationAddress, + IPHeaderIN->SourceAddress, sizeof(TCP_Header_t)); + + return sizeof(TCP_Header_t); + } + + return NO_RESPONSE; +} + +/** Calculates the appropriate TCP checksum, consisting of the addition of the one's compliment of each word, + * complimented. + * + * \param TCPHeaderOutStart Pointer to the start of the packet's outgoing TCP header + * \param SourceAddress Source protocol IP address of the outgoing IP header + * \param SourceAddress DestinationAddress protocol IP address of the outgoing IP header + * \param TCPOutSize Size in bytes of the TCP data header and payload + * + * \return A 16-bit TCP checksum value + */ +static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress, + IP_Address_t DestinationAddress, uint16_t TCPOutSize) +{ + uint32_t Checksum = 0; + + /* TCP/IP checksums are the addition of the one's compliment of each word including the IP pseudo-header, + complimented */ + + Checksum += ((uint16_t*)&SourceAddress)[0]; + Checksum += ((uint16_t*)&SourceAddress)[1]; + Checksum += ((uint16_t*)&DestinationAddress)[0]; + Checksum += ((uint16_t*)&DestinationAddress)[1]; + Checksum += SwapEndian_16(PROTOCOL_TCP); + Checksum += SwapEndian_16(TCPOutSize); + + for (uint8_t CurrWord = 0; CurrWord < (TCPOutSize >> 1); CurrWord++) + Checksum += ((uint16_t*)TCPHeaderOutStart)[CurrWord]; + + if (TCPOutSize & 0x01) + Checksum += (((uint16_t*)TCPHeaderOutStart)[TCPOutSize >> 1] & 0x00FF); + + while (Checksum & 0xFFFF0000) + Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16)); + + return ~Checksum; +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.h new file mode 100644 index 000000000..d4b72a519 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/TCP.h @@ -0,0 +1,253 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for TCP.c. + */ + +#ifndef _TCP_H_ +#define _TCP_H_ + + /* Includes: */ + #include + #include + + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** Maximum number of TCP ports which can be open at the one time */ + #define MAX_OPEN_TCP_PORTS 1 + + /** Maximum number of TCP connections which can be sustained at the one time */ + #define MAX_TCP_CONNECTIONS 1 + + /** TCP window size, giving the maximum number of bytes which can be buffered at the one time */ + #define TCP_WINDOW_SIZE 1024 + + /** Port number for HTTP transmissions */ + #define TCP_PORT_HTTP SwapEndian_16(80) + + /** Data direction indicator for a TCP application buffer, indicating data from host-to-device */ + #define TCP_PACKETDIR_IN false + + /** Data direction indicator for a TCP application buffer, indicating data from device-to-host */ + #define TCP_PACKETDIR_OUT true + + /** Congestion Window Reduced TCP flag mask */ + #define TCP_FLAG_CWR (1 << 7) + + /** Explicit Congestion Notification TCP flag mask */ + #define TCP_FLAG_ECE (1 << 6) + + /** Urgent TCP flag mask */ + #define TCP_FLAG_URG (1 << 5) + + /** Data Acknowledge TCP flag mask */ + #define TCP_FLAG_ACK (1 << 4) + + /** Data Push TCP flag mask */ + #define TCP_FLAG_PSH (1 << 3) + + /** Reset TCP flag mask */ + #define TCP_FLAG_RST (1 << 2) + + /** Synchronize TCP flag mask */ + #define TCP_FLAG_SYN (1 << 1) + + /** Connection Finalize TCP flag mask */ + #define TCP_FLAG_FIN (1 << 0) + + /** Application macro: Determines if the given application buffer contains a packet received from the host + * + * \param Buffer Application buffer to check + * + * \return Boolean true if the buffer contains a packet from the host, false otherwise + */ + #define TCP_APP_HAS_RECEIVED_PACKET(Buffer) (Buffer->Ready && (Buffer->Direction == TCP_PACKETDIR_IN)) + + /** Application macro: Indicates if the application buffer is currently locked by the application for device-to-host transfers. + * + * \param Buffer Application buffer to check + * + * \return Boolean true if the buffer has been captured by the application for device-to-host transmissions, false otherwise + */ + #define TCP_APP_HAVE_CAPTURED_BUFFER(Buffer) (!(Buffer->Ready) && Buffer->InUse && \ + (Buffer->Direction == TCP_PACKETDIR_OUT)) + + /** Application macro: Indicates if the application can lock the buffer for multiple continued device-to-host transmissions. + * + * \param Buffer Application buffer to check + * + * \return Boolean true if the buffer may be captured by the application for device-to-host transmissions, false otherwise + */ + #define TCP_APP_CAN_CAPTURE_BUFFER(Buffer) Buffer->InUse + + /** Application macro: Captures the application buffer, locking it for device-to-host transmissions only. This should be + * performed when the application needs to transmit several packets worth of data in succession with no interruptions from the host. + * + * \note The application must check that the buffer can be locked first using TCP_APP_CAN_CAPTURE_BUFFER(). + * + * \param Buffer Application buffer to lock + */ + #define TCP_APP_CAPTURE_BUFFER(Buffer) MACROS{ Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->InUse = true; }MACROE + + /** Application macro: Releases a captured application buffer, allowing for host-to-device packets to be received. + * + * \param Buffer Application buffer to release + */ + #define TCP_APP_RELEASE_BUFFER(Buffer) MACROS{ Buffer->InUse = false; }MACROE + + /** Application macro: Sends the contents of the given application buffer to the host. + * + * \param Buffer Application buffer to send + * \param Len Length of data contained in the buffer + */ + #define TCP_APP_SEND_BUFFER(Buffer, Len) MACROS{ Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->Length = Len; Buffer->Ready = true; }MACROE + + /** Application macro: Clears the application buffer, ready for a packet to be written to it. + * + * \param Buffer Application buffer to clear + */ + #define TCP_APP_CLEAR_BUFFER(Buffer) MACROS{ Buffer->Ready = false; Buffer->Length = 0; }MACROE + + /** Application macro: Closes an open connection to a host. + * + * \param Connection Open TCP connection to close + */ + #define TCP_APP_CLOSECONNECTION(Connection) MACROS{ Connection->State = TCP_Connection_Closing; }MACROE + + /* Enums: */ + /** Enum for possible TCP port states */ + enum TCP_PortStates_t + { + TCP_Port_Closed = 0, /**< TCP port closed, no connections to a host may be made on this port. */ + TCP_Port_Open = 1, /**< TCP port open, connections to a host may be made on this port. */ + }; + + /** Enum for possible TCP connection states */ + enum TCP_ConnectionStates_t + { + TCP_Connection_Listen = 0, /**< Listening for a connection from a host */ + TCP_Connection_SYNSent = 1, /**< Unused */ + TCP_Connection_SYNReceived = 2, /**< SYN received, waiting for ACK */ + TCP_Connection_Established = 3, /**< Connection established in both directions */ + TCP_Connection_FINWait1 = 4, /**< Closing, waiting for ACK */ + TCP_Connection_FINWait2 = 5, /**< Closing, waiting for FIN ACK */ + TCP_Connection_CloseWait = 6, /**< Closing, waiting for ACK */ + TCP_Connection_Closing = 7, /**< Unused */ + TCP_Connection_LastACK = 8, /**< Unused */ + TCP_Connection_TimeWait = 9, /**< Unused */ + TCP_Connection_Closed = 10, /**< Connection closed in both directions */ + }; + + /* Type Defines: */ + /** Type define for a TCP connection buffer structure, including size, data and direction */ + typedef struct + { + uint16_t Length; /**< Length of data in the TCP application buffer */ + uint8_t Data[TCP_WINDOW_SIZE]; /**< TCP application data buffer */ + bool Direction; /**< Buffer transmission direction, either TCP_PACKETDIR_IN or TCP_PACKETDIR_OUT */ + bool Ready; /**< If data from host, indicates buffer ready to be read, otherwise indicates + * buffer ready to be sent to the host + */ + bool InUse; /** Indicates if the buffer is locked to to the current direction, and cannot be changed */ + } TCP_ConnectionBuffer_t; + + /** Type define for a TCP connection information structure */ + typedef struct + { + uint32_t SequenceNumberIn; /**< Current TCP sequence number for host-to-device */ + uint32_t SequenceNumberOut; /**< Current TCP sequence number for device-to-host */ + TCP_ConnectionBuffer_t Buffer; /**< Connection application data buffer */ + } TCP_ConnectionInfo_t; + + /** Type define for a complete TCP connection state */ + typedef struct + { + uint16_t Port; /**< Connection port number on the device */ + uint16_t RemotePort; /**< Connection port number on the host */ + IP_Address_t RemoteAddress; /**< Connection protocol IP address of the host */ + TCP_ConnectionInfo_t Info; /**< Connection information, including application buffer */ + uint8_t State; /**< Current connection state, a value from the TCP_ConnectionStates_t enum */ + } TCP_ConnectionState_t; + + /** Type define for a TCP port state */ + typedef struct + { + uint16_t Port; /**< TCP port number on the device */ + uint8_t State; /**< Current port state, a value from the TCP_PortStates_t enum */ + void (*ApplicationHandler) (TCP_ConnectionState_t* ConnectionState, + TCP_ConnectionBuffer_t* Buffer); /**< Port application handler */ + } TCP_PortState_t; + + /** Type define for a TCP packet header */ + typedef struct + { + uint16_t SourcePort; /**< Source port of the TCP packet */ + uint16_t DestinationPort; /**< Destination port of the TCP packet */ + + uint32_t SequenceNumber; /**< Data sequence number of the packet */ + uint32_t AcknowledgmentNumber; /**< Data acknowledgment number of the packet */ + + unsigned char Reserved : 4; /**< Reserved, must be all 0 */ + unsigned char DataOffset : 4; /**< Offset of the data from the start of the header, in 4 byte chunks */ + uint8_t Flags; /**< TCP packet flags */ + uint16_t WindowSize; /**< Current data window size (bytes remaining in reception buffer) */ + + uint16_t Checksum; /**< TCP checksum */ + uint16_t UrgentPointer; /**< Urgent data pointer */ + } TCP_Header_t; + + /* Tasks: */ + TASK(TCP_Task); + + /* External Variables: */ + TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS]; + + /* Function Prototypes: */ + void TCP_Init(void); + bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*)); + uint8_t TCP_GetPortState(uint16_t Port); + bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State); + uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort); + TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort); + int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart); + + #if defined(INCLUDE_FROM_TCP_C) + static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress, + IP_Address_t DestinationAddress, uint16_t TCPOutSize); + #endif + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/UDP.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/UDP.c new file mode 100644 index 000000000..1f571c3e9 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/UDP.c @@ -0,0 +1,80 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * User Datagram Protocol (UDP) packet handling routines. This protocol handles high throughput, low + * reliability packets which are typically used to encapsulate streaming data. + */ + +#define INCLUDE_FROM_UDP_C +#include "UDP.h" + +/** Processes a UDP packet inside an Ethernet frame, and writes the appropriate response + * to the output Ethernet frame if a subprotocol handler has created a response packet. + * + * \param IPHeaderInStart Pointer to the start of the incoming packet's IP header + * \param UDPHeaderInStart Pointer to the start of the incoming packet's UDP header + * \param UDPHeaderOutStart Pointer to the start of the outgoing packet's UDP header + * + * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise + */ +int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void* UDPHeaderOutStart) +{ + UDP_Header_t* UDPHeaderIN = (UDP_Header_t*)UDPHeaderInStart; + UDP_Header_t* UDPHeaderOUT = (UDP_Header_t*)UDPHeaderOutStart; + + int16_t RetSize = NO_RESPONSE; + + DecodeUDPHeader(UDPHeaderInStart); + + /* Check to see if the UDP packet is a DHCP packet */ + if (SwapEndian_16(UDPHeaderIN->DestinationPort) == UDP_PORT_DHCP_REQUEST) + { + RetSize = DHCP_ProcessDHCPPacket(IPHeaderInStart, + &((uint8_t*)UDPHeaderInStart)[sizeof(UDP_Header_t)], + &((uint8_t*)UDPHeaderOutStart)[sizeof(UDP_Header_t)]); + } + + /* Check to see if the protocol processing routine has filled out a response */ + if (RetSize > 0) + { + /* Fill out the response UDP packet header */ + UDPHeaderOUT->SourcePort = UDPHeaderIN->DestinationPort; + UDPHeaderOUT->DestinationPort = UDPHeaderIN->SourcePort; + UDPHeaderOUT->Checksum = 0; + UDPHeaderOUT->Length = SwapEndian_16(sizeof(UDP_Header_t) + RetSize); + + /* Return the size of the response so far */ + return (sizeof(UDP_Header_t) + RetSize); + } + + return NO_RESPONSE; +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/UDP.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/UDP.h new file mode 100644 index 000000000..60bbe2185 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/UDP.h @@ -0,0 +1,66 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for IP.c. + */ + +#ifndef _UDP_H_ +#define _UDP_H_ + + /* Includes: */ + #include + + #include "EthernetProtocols.h" + #include "Ethernet.h" + #include "ProtocolDecoders.h" + + /* Macros: */ + /** Source UDP port for a DHCP request */ + #define UDP_PORT_DHCP_REQUEST 67 + + /** Destination UDP port for a DHCP reply */ + #define UDP_PORT_DHCP_REPLY 68 + + /* Type Defines: */ + /** Type define for a UDP packet header */ + typedef struct + { + uint16_t SourcePort; /**< Packet source port */ + uint16_t DestinationPort; /**< Packet destination port */ + uint16_t Length; /**< Total packet length, in bytes */ + uint16_t Checksum; /**< Optional UDP packet checksum */ + } UDP_Header_t; + + /* Function Prototypes: */ + int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void* UDPHeaderOutStart); + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.c new file mode 100644 index 000000000..c07f2c8bd --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.c @@ -0,0 +1,162 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Simple webserver application for demonstrating the RNDIS demo and TCP/IP stack. This + * application will serve up a static HTTP webpage when requested by the host. + */ + +#include "Webserver.h" + +/** HTTP server response header, for transmission before the page contents. This indicates to the host that a page exists at the + * given location, and gives extra connection information. + */ +char PROGMEM HTTPHeader[] = "HTTP/1.1 200 OK\r\n" + "Server: LUFA RNDIS\r\n" + "Content-type: text/html\r\n" + "Connection: close\r\n\r\n"; + +/** HTTP page to serve to the host when a HTTP request is made. This page is too long for a single response, thus it is automatically + * broken up into smaller blocks and sent as a series of packets each time the webserver application callback is run. + */ +char PROGMEM HTTPPage[] = + "" + " " + " " + " LUFA Webserver Demo" + " " + " " + " " + "

Hello from your USB AVR!

" + "

" + " Hello! Welcome to the LUFA RNDIS Demo Webserver test page, running on your USB AVR via the LUFA library. This demonstrates the HTTP webserver, TCP/IP stack and RNDIS demo all running atop the LUFA USB stack." + "

" + " Project Information: http://www.fourwalledcubicle.com/LUFA.php." + "


" + " LUFA Version: " LUFA_VERSION_STRING + "

" + " " + ""; + + +/** Initializes the Webserver application, opening the appropriate HTTP port in the TCP handler and registering the application + * callback routine for packets sent to the HTTP protocol port. + */ +void Webserver_Init(void) +{ + /* Open the HTTP port in the TCP protocol so that HTTP connections to the device can be established */ + TCP_SetPortState(TCP_PORT_HTTP, TCP_Port_Open, Webserver_ApplicationCallback); +} + +/** Indicates if a given request equals the given HTTP command. + * + * \param RequestHeader HTTP request made by the host + * \param Command HTTP command to compare the request to + * + * \return Boolean true if the command matches the request, false otherwise + */ +static bool IsHTTPCommand(uint8_t* RequestHeader, char* Command) +{ + /* Returns true if the non null terminated string in RequestHeader matches the null terminated string Command */ + return (strncmp((char*)RequestHeader, Command, strlen(Command)) == 0); +} + +/** Application callback routine, executed each time the TCP processing task runs. This callback determines what request + * has been made (if any), and serves up appropriate responses. + * + * \param ConnectionState Pointer to a TCP Connection State structure giving connection information + * \param Buffer Pointer to the application's send/receive packet buffer + */ +void Webserver_ApplicationCallback(TCP_ConnectionState_t* ConnectionState, TCP_ConnectionBuffer_t* Buffer) +{ + char* BufferDataStr = (char*)Buffer->Data; + static uint8_t PageBlock = 0; + + /* Check to see if a packet has been received on the HTTP port from a remote host */ + if (TCP_APP_HAS_RECEIVED_PACKET(Buffer)) + { + if (IsHTTPCommand(Buffer->Data, "GET")) + { + PageBlock = 0; + + /* Copy the HTTP response header into the packet buffer */ + strcpy_P(BufferDataStr, HTTPHeader); + + /* Send the buffer contents to the host */ + TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr)); + + /* Lock the buffer to Device->Host transmissions only while we send the page contents */ + TCP_APP_CAPTURE_BUFFER(Buffer); + } + else if (IsHTTPCommand(Buffer->Data, "HEAD")) + { + /* Copy the HTTP response header into the packet buffer */ + strcpy_P(BufferDataStr, HTTPHeader); + + /* Send the buffer contents to the host */ + TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr)); + } + else if (IsHTTPCommand(Buffer->Data, "TRACE")) + { + /* Echo the host's query back to the host */ + TCP_APP_SEND_BUFFER(Buffer, Buffer->Length); + } + else + { + /* Unknown request, just clear the buffer (drop the packet) */ + TCP_APP_CLEAR_BUFFER(Buffer); + } + } + else if (TCP_APP_HAVE_CAPTURED_BUFFER(Buffer)) + { + uint16_t RemLength = strlen_P(&HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE]); + uint16_t Length; + + /* Determine the length of the loaded block */ + Length = ((RemLength > HTTP_REPLY_BLOCK_SIZE) ? HTTP_REPLY_BLOCK_SIZE : RemLength); + + /* Copy the next buffer sized block of the page to the packet buffer */ + strncpy_P(BufferDataStr, &HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE], Length); + + /* Send the buffer contents to the host */ + TCP_APP_SEND_BUFFER(Buffer, Length); + + /* Check to see if the entire page has been sent */ + if (PageBlock++ == (sizeof(HTTPPage) / HTTP_REPLY_BLOCK_SIZE)) + { + /* Unlock the buffer so that the host can fill it with future packets */ + TCP_APP_RELEASE_BUFFER(Buffer); + + /* Close the connection to the host */ + TCP_APP_CLOSECONNECTION(ConnectionState); + } + } +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.h b/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.h new file mode 100644 index 000000000..b2193ad1f --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/Webserver.h @@ -0,0 +1,55 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for Webserver.c. + */ + +#ifndef _WEBSERVER_H_ +#define _WEBSERVER_H_ + + /* Includes: */ + #include + #include + + #include + + #include "TCP.h" + + /* Macros: */ + /** Maximum size of a HTTP response per transmission */ + #define HTTP_REPLY_BLOCK_SIZE 128 + + /* Function Prototypes: */ + void Webserver_Init(void); + void Webserver_ApplicationCallback(TCP_ConnectionState_t* ConnectionState, TCP_ConnectionBuffer_t* Buffer); + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.aps b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.aps new file mode 100644 index 000000000..b5d21c1f9 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.aps @@ -0,0 +1 @@ +RNDISEthernet30-Sep-2008 14:17:0522-Jan-2009 17:52:35241030-Sep-2008 14:17:0544, 14, 0, 589AVR GCCC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\JTAGICE mkIIAT90USB1287.xmlfalseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31Auto000ARP.cDescriptors.cEthernet.cICMP.cIP.cProtocolDecoders.cRNDIS.cRNDISEthernet.cTCP.cWebserver.cARP.hDescriptors.hEthernet.hEthernetProtocols.hICMP.hIP.hProtocolDecoders.hRNDIS.hRNDISEthernet.hTCP.hWebserver.hmakefiledefaultYESmakefileat90usb1287111RNDISEthernet.elfdefault\1-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enumsdefault1C:\WinAVR-20081205\bin\avr-gcc.exeC:\WinAVR-20081205\utils\bin\make.exeC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\ARP.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\Descriptors.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\Ethernet.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\EthernetProtocols.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\ICMP.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\IP.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\ProtocolDecoders.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\RNDIS.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\RNDISEthernet.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\TCP.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\Telnet.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\Webserver.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\ARP.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\Descriptors.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\Ethernet.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\ICMP.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\IP.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\ProtocolDecoders.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\RNDIS.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\RNDISEthernet.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\TCP.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\Telnet.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Demos\RNDISEthernet\Webserver.c diff --git a/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c new file mode 100644 index 000000000..b046f7870 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c @@ -0,0 +1,338 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Main source file for the RNDISEthernet demo. This file contains the main tasks of the demo and + * is responsible for the initial application hardware configuration. + */ + +#include "RNDISEthernet.h" + +/* Scheduler Task List */ +TASK_LIST +{ + { .Task = USB_USBTask , .TaskStatus = TASK_STOP }, + { .Task = Ethernet_Task , .TaskStatus = TASK_STOP }, + { .Task = TCP_Task , .TaskStatus = TASK_STOP }, + { .Task = RNDIS_Task , .TaskStatus = TASK_STOP }, +}; + +/** Main program entry point. This routine configures the hardware required by the application, then + * starts the scheduler to run the USB management task. + */ +int main(void) +{ + /* Disable watchdog if enabled by bootloader/fuses */ + MCUSR &= ~(1 << WDRF); + wdt_disable(); + + /* Disable clock division */ + clock_prescale_set(clock_div_1); + + /* Hardware Initialization */ + LEDs_Init(); + SerialStream_Init(9600, false); + + /* Webserver Initialization */ + TCP_Init(); + Webserver_Init(); + + printf_P(PSTR("\r\n\r\n****** RNDIS Demo running. ******\r\n")); + + /* Indicate USB not ready */ + UpdateStatus(Status_USBNotReady); + + /* Initialize Scheduler so that it can be used */ + Scheduler_Init(); + + /* Initialize USB Subsystem */ + USB_Init(); + + /* Scheduling - routine never returns, so put this last in the main function */ + Scheduler_Start(); +} + +/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and + * starts the library USB task to begin the enumeration and USB management process. + */ +void EVENT_USB_Connect(void) +{ + /* Start USB management task */ + Scheduler_SetTaskMode(USB_USBTask, TASK_RUN); + + /* Indicate USB enumerating */ + UpdateStatus(Status_USBEnumerating); +} + +/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via + * the status LEDs and stops all the relevant tasks. + */ +void EVENT_USB_Disconnect(void) +{ + /* Stop running TCP/IP and USB management tasks */ + Scheduler_SetTaskMode(RNDIS_Task, TASK_STOP); + Scheduler_SetTaskMode(Ethernet_Task, TASK_STOP); + Scheduler_SetTaskMode(TCP_Task, TASK_STOP); + Scheduler_SetTaskMode(USB_USBTask, TASK_STOP); + + /* Indicate USB not ready */ + UpdateStatus(Status_USBNotReady); +} + +/** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration + * of the USB device after enumeration, and configures the RNDIS device endpoints and starts the relevant tasks. + */ +void EVENT_USB_ConfigurationChanged(void) +{ + /* Setup CDC Notification, Rx and Tx Endpoints */ + Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK, + ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE, + ENDPOINT_BANK_SINGLE); + + Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK, + ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE, + ENDPOINT_BANK_SINGLE); + + Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT, + ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE, + ENDPOINT_BANK_SINGLE); + + /* Indicate USB connected and ready */ + UpdateStatus(Status_USBReady); + + /* Start TCP/IP tasks */ + Scheduler_SetTaskMode(RNDIS_Task, TASK_RUN); + Scheduler_SetTaskMode(Ethernet_Task, TASK_RUN); + Scheduler_SetTaskMode(TCP_Task, TASK_RUN); +} + +/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific + * control requests that are not handled internally by the USB library (including the RNDIS control commands, + * which set up the USB RNDIS network adapter), so that they can be handled appropriately for the application. + */ +void EVENT_USB_UnhandledControlPacket(void) +{ + /* Process RNDIS class commands */ + switch (USB_ControlRequest.bRequest) + { + case REQ_SendEncapsulatedCommand: + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) + { + /* Clear the SETUP packet, ready for data transfer */ + Endpoint_ClearSETUP(); + + /* Read in the RNDIS message into the message buffer */ + Endpoint_Read_Control_Stream_LE(RNDISMessageBuffer, USB_ControlRequest.wLength); + + /* Finalize the stream transfer to clear the last packet from the host */ + Endpoint_ClearIN(); + + /* Process the RNDIS message */ + ProcessRNDISControlMessage(); + } + + break; + case REQ_GetEncapsulatedResponse: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) + { + /* Clear the SETUP packet, ready for data transfer */ + Endpoint_ClearSETUP(); + + /* Check if a response to the last message is ready */ + if (!(MessageHeader->MessageLength)) + { + /* Set the response to a single 0x00 byte to indicate that no response is ready */ + RNDISMessageBuffer[0] = 0; + MessageHeader->MessageLength = 1; + } + + /* Write the message response data to the endpoint */ + Endpoint_Write_Control_Stream_LE(RNDISMessageBuffer, MessageHeader->MessageLength); + + /* Finalize the stream transfer to send the last packet or clear the host abort */ + Endpoint_ClearOUT(); + + /* Reset the message header once again after transmission */ + MessageHeader->MessageLength = 0; + } + + break; + } +} + +/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to + * log to a serial port, or anything else that is suitable for status updates. + * + * \param CurrentStatus Current status of the system, from the RNDISEthernet_StatusCodes_t enum + */ +void UpdateStatus(uint8_t CurrentStatus) +{ + uint8_t LEDMask = LEDS_NO_LEDS; + + /* Set the LED mask to the appropriate LED mask based on the given status code */ + switch (CurrentStatus) + { + case Status_USBNotReady: + LEDMask = (LEDS_LED1); + break; + case Status_USBEnumerating: + LEDMask = (LEDS_LED1 | LEDS_LED2); + break; + case Status_USBReady: + LEDMask = (LEDS_LED2 | LEDS_LED4); + break; + case Status_ProcessingEthernetFrame: + LEDMask = (LEDS_LED2 | LEDS_LED3); + break; + } + + /* Set the board LEDs to the new LED mask */ + LEDs_SetAllLEDs(LEDMask); +} + +/** Task to manage the sending and receiving of encapsulated RNDIS data and notifications. This removes the RNDIS + * wrapper from received Ethernet frames and places them in the FrameIN global buffer, or adds the RNDIS wrapper + * to a frame in the FrameOUT global before sending the buffer contents to the host. + */ +TASK(RNDIS_Task) +{ + /* Select the notification endpoint */ + Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM); + + /* Check if a message response is ready for the host */ + if (Endpoint_IsINReady() && ResponseReady) + { + USB_Notification_t Notification = (USB_Notification_t) + { + .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE), + .bNotification = NOTIF_RESPONSE_AVAILABLE, + .wValue = 0, + .wIndex = 0, + .wLength = 0, + }; + + /* Indicate that a message response is ready for the host */ + Endpoint_Write_Stream_LE(&Notification, sizeof(Notification)); + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearIN(); + + /* Indicate a response is no longer ready */ + ResponseReady = false; + } + + /* Don't process the data endpoints until the system is in the data initialized state, and the buffer is free */ + if ((CurrRNDISState == RNDIS_Data_Initialized) && !(MessageHeader->MessageLength)) + { + /* Create a new packet header for reading/writing */ + RNDIS_PACKET_MSG_t RNDISPacketHeader; + + /* Select the data OUT endpoint */ + Endpoint_SelectEndpoint(CDC_RX_EPNUM); + + /* Check if the data OUT endpoint contains data, and that the IN buffer is empty */ + if (Endpoint_IsOUTReceived() && !(FrameIN.FrameInBuffer)) + { + /* Read in the packet message header */ + Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t)); + + /* Stall the request if the data is too large */ + if (RNDISPacketHeader.DataLength > ETHERNET_FRAME_SIZE_MAX) + { + Endpoint_StallTransaction(); + return; + } + + /* Read in the Ethernet frame into the buffer */ + Endpoint_Read_Stream_LE(FrameIN.FrameData, RNDISPacketHeader.DataLength); + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearOUT(); + + /* Store the size of the Ethernet frame */ + FrameIN.FrameLength = RNDISPacketHeader.DataLength; + + /* Indicate Ethernet IN buffer full */ + FrameIN.FrameInBuffer = true; + } + + /* Select the data IN endpoint */ + Endpoint_SelectEndpoint(CDC_TX_EPNUM); + + /* Check if the data IN endpoint is ready for more data, and that the IN buffer is full */ + if (Endpoint_IsINReady() && FrameOUT.FrameInBuffer) + { + /* Clear the packet header with all 0s so that the relevant fields can be filled */ + memset(&RNDISPacketHeader, 0, sizeof(RNDIS_PACKET_MSG_t)); + + /* Construct the required packet header fields in the buffer */ + RNDISPacketHeader.MessageType = REMOTE_NDIS_PACKET_MSG; + RNDISPacketHeader.MessageLength = (sizeof(RNDIS_PACKET_MSG_t) + FrameOUT.FrameLength); + RNDISPacketHeader.DataOffset = (sizeof(RNDIS_PACKET_MSG_t) - sizeof(RNDIS_Message_Header_t)); + RNDISPacketHeader.DataLength = FrameOUT.FrameLength; + + /* Send the packet header to the host */ + Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_PACKET_MSG_t)); + + /* Send the Ethernet frame data to the host */ + Endpoint_Write_Stream_LE(FrameOUT.FrameData, RNDISPacketHeader.DataLength); + + /* Finalize the stream transfer to send the last packet */ + Endpoint_ClearIN(); + + /* Indicate Ethernet OUT buffer no longer full */ + FrameOUT.FrameInBuffer = false; + } + } +} + +/** Ethernet frame processing task. This task checks to see if a frame has been received, and if so hands off the processing + * of the frame to the Ethernet processing routines. + */ +TASK(Ethernet_Task) +{ + /* Task for Ethernet processing. Incoming ethernet frames are loaded into the FrameIN structure, and + outgoing frames should be loaded into the FrameOUT structure. Both structures can only hold a single + Ethernet frame at a time, so the FrameInBuffer bool is used to indicate when the buffers contain data. */ + + /* Check if a frame has been written to the IN frame buffer */ + if (FrameIN.FrameInBuffer) + { + /* Indicate packet processing started */ + UpdateStatus(Status_ProcessingEthernetFrame); + + /* Process the ethernet frame - replace this with your own Ethernet handler code as desired */ + Ethernet_ProcessPacket(); + + /* Indicate packet processing complete */ + UpdateStatus(Status_USBReady); + } +} diff --git a/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.h b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.h new file mode 100644 index 000000000..703af4003 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.h @@ -0,0 +1,100 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, 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 disclaim 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 + * + * Header file for RNDISEthernet.c. + */ + +#ifndef _RNDISETHERNET_H_ +#define _RNDISETHERNET_H_ + + /* Includes: */ + #include + #include + #include + #include + #include + #include + + #include "Descriptors.h" + + #include "Lib/RNDIS.h" + #include "Lib/Ethernet.h" + #include "Lib/TCP.h" + #include "Lib/ARP.h" + #include "Lib/Webserver.h" + + #include // Library Version Information + #include // USB Functionality + #include // LEDs driver + #include // Simple scheduler for task management + #include // Serial stream driver + + /* Macros: */ + /** Notification value to indicate that a frame is ready to be read by the host. */ + #define NOTIF_RESPONSE_AVAILABLE 0x01 + + /* Type Defines: */ + /** Type define for a RNDIS notification message, for transmission to the RNDIS host via the notification + * Endpoint. + */ + typedef struct + { + uint8_t bmRequestType; /**< Notification type, a mask of values from SrdRequestType.h */ + uint8_t bNotification; /**< Notification index, indicating what the RNDIS notification relates to */ + uint16_t wValue; /**< Two byte notification value parameter */ + uint16_t wIndex; /**< Two byte notification index parameter */ + uint16_t wLength; /**< Size of data payload following the notification header */ + } USB_Notification_t; + + /* Enums: */ + /** Enum for the possible status codes for passing to the UpdateStatus() function. */ + enum RNDISEthernet_StatusCodes_t + { + Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */ + Status_USBEnumerating = 1, /**< USB interface is enumerating */ + Status_USBReady = 2, /**< USB interface is connected and ready */ + Status_ProcessingEthernetFrame = 3, /**< Currently processing an ethernet frame from the host */ + }; + + /* Tasks: */ + TASK(RNDIS_Task); + TASK(Ethernet_Task); + + /* Function Prototypes: */ + void EVENT_USB_Connect(void); + void EVENT_USB_Disconnect(void); + void EVENT_USB_ConfigurationChanged(void); + void EVENT_USB_UnhandledControlPacket(void); + + void UpdateStatus(uint8_t CurrentStatus); + +#endif diff --git a/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.txt b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.txt new file mode 100644 index 000000000..306cf8526 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.txt @@ -0,0 +1,115 @@ +/** \file + * + * This file contains special DoxyGen information for the generation of the main page and other special + * documentation pages. It is not a project source file. + */ + +/** \mainpage RNDIS Class Ethernet Demo (with Webserver/Telnet) + * + * \section SSec_Info USB Information: + * + * The following table gives a rundown of the USB utilization of this demo. + * + * Remote Network Driver Interface demonstration application. + * This gives a simple reference application for implementing + * a CDC RNDIS device acting as a simple network interface for + * ethernet packet exchange. RNDIS is a proprietary Microsoft + * standard; this demo will only work on Windows 2000 (manually + * patched with the Microsoft RNDIS hotfix) and above (with no + * manual patches), or on the latest Linux kernels. + * + * Before running, you will need to install the INF file that + * is located in the RNDISEthernet project directory. This will + * enable Windows to use its inbuilt RNDIS drivers, negating the + * need for special Windows drivers for the device. To install, + * right-click the .INF file and choose the Install option. If + * Windows 2000 is used, the Microsoft INF file in the hotfix + * will need to be altered to use the VID/PID of the demo and + * then chosen instead of the LUFA RNDIS INF file when prompted. + * + * When enumerated, this demo will install as a new network + * adapter which ethernet packets can be sent to and received + * from. Running on top of the adapter is a very simple TCP/IP + * stack with a HTTP webserver and TELNET host which can be + * accessed through a web browser at IP address 10.0.0.2:80 or + * through a TELNET client at 10.0.0.2:25. This device also supports + * ping echos via the ICMP protocol. + * + * \note The TCP/IP stack in this demo has a number of limitations + * and should serve as an example only - it is not fully featured nor + * compliant to the TCP/IP specification. For complete projects, it is + * recommended that it be replaced with an external open source TCP/IP + * stack that is feature complete, such as the uIP stack. + * + * \section SSec_Description Project Description: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
USB Mode:Device
USB Class:Communications Device Class (CDC)
USB Subclass:Remote NDIS (Microsoft Proprietary CDC Class Networking Standard)
Relevant Standards:Microsoft RNDIS Specification
Usable Speeds:Full Speed Mode
+ * + * \section SSec_Options Project Options + * + * The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Define Name:Location:Description:
NO_DECODE_ETHERNETMakefile CDEFSWhen defined, received Ethernet headers will not be decoded and printed to the device serial port.
NO_DECODE_ARPMakefile CDEFSWhen defined, received ARP headers will not be decoded and printed to the device serial port.
NO_DECODE_IPMakefile CDEFSWhen defined, received IP headers will not be decoded and printed to the device serial port.
NO_DECODE_ICMPMakefile CDEFSWhen defined, received ICMP headers will not be decoded and printed to the device serial port.
NO_DECODE_TCPMakefile CDEFSWhen defined, received TCP headers will not be decoded and printed to the device serial port.
NO_DECODE_UDPMakefile CDEFSWhen defined, received UDP headers will not be decoded and printed to the device serial port.
NO_DECODE_DHCPMakefile CDEFSWhen defined, received DHCP headers will not be decoded and printed to the device serial port.
+ */ \ No newline at end of file diff --git a/Demos/Device/LowLevel/RNDISEthernet/makefile b/Demos/Device/LowLevel/RNDISEthernet/makefile new file mode 100644 index 000000000..f40c37b05 --- /dev/null +++ b/Demos/Device/LowLevel/RNDISEthernet/makefile @@ -0,0 +1,747 @@ +# Hey Emacs, this is a -*- makefile -*- +#---------------------------------------------------------------------------- +# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al. +# >> Modified for use with the LUFA project. << +# +# Released to the Public Domain +# +# Additional material for this makefile was written by: +# Peter Fleury +# Tim Henigan +# Colin O'Flynn +# Reiner Patommel +# Markus Pfaff +# Sander Pool +# Frederik Rouleau +# Carlos Lamas +# Dean Camera +# Opendous Inc. +# Denver Gingerich +# +#---------------------------------------------------------------------------- +# On command line: +# +# make all = Make software. +# +# make clean = Clean out built project files. +# +# make coff = Convert ELF to AVR COFF. +# +# make extcoff = Convert ELF to AVR Extended COFF. +# +# make program = Download the hex file to the device, using avrdude. +# Please customize the avrdude settings below first! +# +# make dfu = Download the hex file to the device, using dfu-programmer (must +# have dfu-programmer installed). +# +# make flip = Download the hex file to the device, using Atmel FLIP (must +# have Atmel FLIP installed). +# +# make dfu-ee = Download the eeprom file to the device, using dfu-programmer +# (must have dfu-programmer installed). +# +# make flip-ee = Download the eeprom file to the device, using Atmel FLIP +# (must have Atmel FLIP installed). +# +# make doxygen = Generate DoxyGen documentation for the project (must have +# DoxyGen installed) +# +# make debug = Start either simulavr or avarice as specified for debugging, +# with avr-gdb or avr-insight as the front end for debugging. +# +# make filename.s = Just compile filename.c into the assembler code only. +# +# make filename.i = Create a preprocessed source file for use in submitting +# bug reports to the GCC project. +# +# To rebuild project do "make clean" then "make all". +#---------------------------------------------------------------------------- + + +# MCU name +MCU = at90usb1287 + + +# Target board (see library "Board Types" documentation, USER or blank for projects not requiring +# LUFA board drivers). If USER is selected, put custom board drivers in a directory called +# "Board" inside the application directory. +BOARD = USBKEY + + +# Processor frequency. +# This will define a symbol, F_CPU, in all source code files equal to the +# processor frequency. You can then use this symbol in your source code to +# calculate timings. Do NOT tack on a 'UL' at the end, this will be done +# automatically to create a 32-bit value in your source code. +# Typical values are: +# F_CPU = 1000000 +# F_CPU = 1843200 +# F_CPU = 2000000 +# F_CPU = 3686400 +# F_CPU = 4000000 +# F_CPU = 7372800 +# F_CPU = 8000000 +# F_CPU = 11059200 +# F_CPU = 14745600 +# F_CPU = 16000000 +# F_CPU = 18432000 +# F_CPU = 20000000 +F_CPU = 8000000 + + +# Input clock frequency. +# This will define a symbol, F_CLOCK, in all source code files equal to the +# input clock frequency (before any prescaling is performed). This value may +# differ from F_CPU if prescaling is used on the latter, and is required as the +# raw input clock is fed directly to the PLL sections of the AVR for high speed +# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' +# at the end, this will be done automatically to create a 32-bit value in your +# source code. +# +# If no clock division is performed on the input clock inside the AVR (via the +# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. +F_CLOCK = 8000000 + + +# Output format. (can be srec, ihex, binary) +FORMAT = ihex + + +# Target file name (without extension). +TARGET = RNDISEthernet + + +# Object files directory +# To put object files in current directory, use a dot (.), do NOT make +# this an empty or blank macro! +OBJDIR = . + + +# Path to the LUFA library +LUFA_PATH = ../../.. + + +# List C source files here. (C dependencies are automatically generated.) +SRC = $(TARGET).c \ + Descriptors.c \ + Lib/RNDIS.c \ + Lib/Ethernet.c \ + Lib/ProtocolDecoders.c \ + Lib/ICMP.c \ + Lib/TCP.c \ + Lib/UDP.c \ + Lib/DHCP.c \ + Lib/ARP.c \ + Lib/IP.c \ + Lib/Webserver.c \ + $(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \ + $(LUFA_PATH)/LUFA/Drivers/Peripheral/SerialStream.c \ + $(LUFA_PATH)/LUFA/Drivers/Peripheral/Serial.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Host.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/HostChapter9.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/LowLevel.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Pipe.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/Events.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBInterrupt.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/USBTask.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/HighLevel/ConfigDescriptor.c \ + $(LUFA_PATH)/LUFA/Drivers/USB/Class/HIDParser.c \ + + +# List C++ source files here. (C dependencies are automatically generated.) +CPPSRC = + + +# List Assembler source files here. +# Make them always end in a capital .S. Files ending in a lowercase .s +# will not be considered source files but generated files (assembler +# output from the compiler), and will be deleted upon "make clean"! +# Even though the DOS/Win* filesystem matches both .s and .S the same, +# it will preserve the spelling of the filenames, and gcc itself does +# care about how the name is spelled on its command-line. +ASRC = + + +# Optimization level, can be [0, 1, 2, 3, s]. +# 0 = turn off optimization. s = optimize for size. +# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) +OPT = s + + +# Debugging format. +# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs. +# AVR Studio 4.10 requires dwarf-2. +# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run. +DEBUG = dwarf-2 + + +# List any extra directories to look for include files here. +# Each directory must be seperated by a space. +# Use forward slashes for directory separators. +# For a directory that has spaces, enclose it in quotes. +EXTRAINCDIRS = $(LUFA_PATH)/ + + +# Compiler flag to set the C Standard level. +# c89 = "ANSI" C +# gnu89 = c89 plus GCC extensions +# c99 = ISO C99 standard (not yet fully implemented) +# gnu99 = c99 plus GCC extensions +CSTANDARD = -std=gnu99 + + +# Place -D or -U options here for C sources +CDEFS = -DF_CPU=$(F_CPU)UL -DF_CLOCK=$(F_CLOCK)UL -DBOARD=BOARD_$(BOARD) +CDEFS += -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS -DUSB_DEVICE_ONLY +CDEFS += -DFIXED_CONTROL_ENDPOINT_SIZE=8 -DUSE_SINGLE_DEVICE_CONFIGURATION +CDEFS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" +CDEFS += -DNO_DECODE_ETHERNET -DNO_DECODE_ARP -DNO_DECODE_ICMP -DNO_DECODE_IP -DNO_DECODE_TCP -DNO_DECODE_UDP -DNO_DECODE_DHCP + + +# Place -D or -U options here for ASM sources +ADEFS = -DF_CPU=$(F_CPU) + + +# Place -D or -U options here for C++ sources +CPPDEFS = -DF_CPU=$(F_CPU)UL +#CPPDEFS += -D__STDC_LIMIT_MACROS +#CPPDEFS += -D__STDC_CONSTANT_MACROS + + + +#---------------- Compiler Options C ---------------- +# -g*: generate debugging information +# -O*: optimization level +# -f...: tuning, see GCC manual and avr-libc documentation +# -Wall...: warning level +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns...: create assembler listing +CFLAGS = -g$(DEBUG) +CFLAGS += $(CDEFS) +CFLAGS += -O$(OPT) +CFLAGS += -funsigned-char +CFLAGS += -funsigned-bitfields +CFLAGS += -ffunction-sections +CFLAGS += -fpack-struct +CFLAGS += -fshort-enums +CFLAGS += -finline-limit=20 +CFLAGS += -Wall +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wundef +#CFLAGS += -fno-unit-at-a-time +#CFLAGS += -Wunreachable-code +#CFLAGS += -Wsign-compare +CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst) +CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) +CFLAGS += $(CSTANDARD) + + +#---------------- Compiler Options C++ ---------------- +# -g*: generate debugging information +# -O*: optimization level +# -f...: tuning, see GCC manual and avr-libc documentation +# -Wall...: warning level +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns...: create assembler listing +CPPFLAGS = -g$(DEBUG) +CPPFLAGS += $(CPPDEFS) +CPPFLAGS += -O$(OPT) +CPPFLAGS += -funsigned-char +CPPFLAGS += -funsigned-bitfields +CPPFLAGS += -fpack-struct +CPPFLAGS += -fshort-enums +CPPFLAGS += -fno-exceptions +CPPFLAGS += -Wall +CFLAGS += -Wundef +#CPPFLAGS += -mshort-calls +#CPPFLAGS += -fno-unit-at-a-time +#CPPFLAGS += -Wstrict-prototypes +#CPPFLAGS += -Wunreachable-code +#CPPFLAGS += -Wsign-compare +CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst) +CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) +#CPPFLAGS += $(CSTANDARD) + + +#---------------- Assembler Options ---------------- +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns: create listing +# -gstabs: have the assembler create line number information; note that +# for use in COFF files, additional information about filenames +# and function names needs to be present in the assembler source +# files -- see avr-libc docs [FIXME: not yet described there] +# -listing-cont-lines: Sets the maximum number of continuation lines of hex +# dump that will be displayed for a given single line of source input. +ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100 + + +#---------------- Library Options ---------------- +# Minimalistic printf version +PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min + +# Floating point printf version (requires MATH_LIB = -lm below) +PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt + +# If this is left blank, then it will use the Standard printf version. +PRINTF_LIB = +#PRINTF_LIB = $(PRINTF_LIB_MIN) +#PRINTF_LIB = $(PRINTF_LIB_FLOAT) + + +# Minimalistic scanf version +SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min + +# Floating point + %[ scanf version (requires MATH_LIB = -lm below) +SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt + +# If this is left blank, then it will use the Standard scanf version. +SCANF_LIB = +#SCANF_LIB = $(SCANF_LIB_MIN) +#SCANF_LIB = $(SCANF_LIB_FLOAT) + + +MATH_LIB = -lm + + +# List any extra directories to look for libraries here. +# Each directory must be seperated by a space. +# Use forward slashes for directory separators. +# For a directory that has spaces, enclose it in quotes. +EXTRALIBDIRS = + + + +#---------------- External Memory Options ---------------- + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# used for variables (.data/.bss) and heap (malloc()). +#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# only used for heap (malloc()). +#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff + +EXTMEMOPTS = + + + +#---------------- Linker Options ---------------- +# -Wl,...: tell GCC to pass this to linker. +# -Map: create map file +# --cref: add cross reference to map file +LDFLAGS = -Wl,-Map=$(TARGET).map,--cref +LDFLAGS += -Wl,--relax +LDFLAGS += -Wl,--gc-sections +LDFLAGS += $(EXTMEMOPTS) +LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS)) +LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) +#LDFLAGS += -T linker_script.x + + + +#---------------- Programming Options (avrdude) ---------------- + +# Programming hardware: alf avr910 avrisp bascom bsd +# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500 +# +# Type: avrdude -c ? +# to get a full listing. +# +AVRDUDE_PROGRAMMER = jtagmkII + +# com1 = serial port. Use lpt1 to connect to parallel port. +AVRDUDE_PORT = usb + +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +# see avrdude manual. +#AVRDUDE_ERASE_COUNTER = -y + +# Uncomment the following if you do /not/ wish a verification to be +# performed after programming the device. +#AVRDUDE_NO_VERIFY = -V + +# Increase verbosity level. Please use this when submitting bug +# reports about avrdude. See +# to submit bug reports. +#AVRDUDE_VERBOSE = -v -v + +AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) +AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) +AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) + + + +#---------------- Debugging Options ---------------- + +# For simulavr only - target MCU frequency. +DEBUG_MFREQ = $(F_CPU) + +# Set the DEBUG_UI to either gdb or insight. +# DEBUG_UI = gdb +DEBUG_UI = insight + +# Set the debugging back-end to either avarice, simulavr. +DEBUG_BACKEND = avarice +#DEBUG_BACKEND = simulavr + +# GDB Init Filename. +GDBINIT_FILE = __avr_gdbinit + +# When using avarice settings for the JTAG +JTAG_DEV = /dev/com1 + +# Debugging port used to communicate between GDB / avarice / simulavr. +DEBUG_PORT = 4242 + +# Debugging host used to communicate between GDB / avarice / simulavr, normally +# just set to localhost unless doing some sort of crazy debugging when +# avarice is running on a different computer. +DEBUG_HOST = localhost + + + +#============================================================================ + + +# Define programs and commands. +SHELL = sh +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size +AR = avr-ar rcs +NM = avr-nm +AVRDUDE = avrdude +REMOVE = rm -f +REMOVEDIR = rm -rf +COPY = cp +WINSHELL = cmd + +# Define Messages +# English +MSG_ERRORS_NONE = Errors: none +MSG_BEGIN = -------- begin -------- +MSG_END = -------- end -------- +MSG_SIZE_BEFORE = Size before: +MSG_SIZE_AFTER = Size after: +MSG_COFF = Converting to AVR COFF: +MSG_EXTENDED_COFF = Converting to AVR Extended COFF: +MSG_FLASH = Creating load file for Flash: +MSG_EEPROM = Creating load file for EEPROM: +MSG_EXTENDED_LISTING = Creating Extended Listing: +MSG_SYMBOL_TABLE = Creating Symbol Table: +MSG_LINKING = Linking: +MSG_COMPILING = Compiling C: +MSG_COMPILING_CPP = Compiling C++: +MSG_ASSEMBLING = Assembling: +MSG_CLEANING = Cleaning project: +MSG_CREATING_LIBRARY = Creating library: + + + + +# Define all object files. +OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) + +# Define all listing files. +LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) + + +# Compiler flags to generate dependency files. +GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d + + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) +ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) + + + + + +# Default target. +all: begin gccversion sizebefore build checkhooks checklibmode checkboard sizeafter end + +# Change the build target to build a HEX file or a library. +build: elf hex eep lss sym +#build: lib + + +elf: $(TARGET).elf +hex: $(TARGET).hex +eep: $(TARGET).eep +lss: $(TARGET).lss +sym: $(TARGET).sym +LIBNAME=lib$(TARGET).a +lib: $(LIBNAME) + + + +# Eye candy. +# AVR Studio 3.x does not check make's exit code but relies on +# the following magic strings to be generated by the compile job. +begin: + @echo + @echo $(MSG_BEGIN) + +end: + @echo $(MSG_END) + @echo + + +# Display size of file. +HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex +ELFSIZE = $(SIZE) $(MCU_FLAG) $(FORMAT_FLAG) $(TARGET).elf +MCU_FLAG = $(shell $(SIZE) --help | grep -- --mcu > /dev/null && echo --mcu=$(MCU) ) +FORMAT_FLAG = $(shell $(SIZE) --help | grep -- --format=.*avr > /dev/null && echo --format=avr ) + +sizebefore: + @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \ + 2>/dev/null; echo; fi + +sizeafter: + @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \ + 2>/dev/null; echo; fi + +checkhooks: build + @echo + @echo ------- Unhooked LUFA Events ------- + @$(shell) (grep -s '^EVENT_.*LUFA/.*\\.o' $(TARGET).map | \ + cut -d' ' -f1 | cut -d'_' -f2- | grep ".*") || \ + echo "(None)" + @echo ------------------------------------ + +checklibmode: + @echo + @echo ----------- Library Mode ----------- + @$(shell) ($(CC) $(ALL_CFLAGS) -E -dM - < /dev/null \ + | grep 'USB_\(DEVICE\|HOST\)_ONLY' | cut -d' ' -f2 | grep ".*") \ + || echo "No specific mode (both device and host mode allowable)." + @echo ------------------------------------ + +checkboard: + @echo + @echo ---------- Selected Board ---------- + @echo Selected board model is $(BOARD). + @echo ------------------------------------ + +# Display compiler version information. +gccversion : + @$(CC) --version + + + +# Program the device. +program: $(TARGET).hex $(TARGET).eep + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + +flip: $(TARGET).hex + batchisp -hardware usb -device $(MCU) -operation erase f + batchisp -hardware usb -device $(MCU) -operation loadbuffer $(TARGET).hex program + batchisp -hardware usb -device $(MCU) -operation start reset 0 + +dfu: $(TARGET).hex + dfu-programmer $(MCU) erase + dfu-programmer $(MCU) flash --debug 1 $(TARGET).hex + dfu-programmer $(MCU) reset + +flip-ee: $(TARGET).hex $(TARGET).eep + copy $(TARGET).eep $(TARGET)eep.hex + batchisp -hardware usb -device $(MCU) -operation memory EEPROM erase + batchisp -hardware usb -device $(MCU) -operation memory EEPROM loadbuffer $(TARGET)eep.hex program + batchisp -hardware usb -device $(MCU) -operation start reset 0 + +dfu-ee: $(TARGET).hex $(TARGET).eep + dfu-programmer $(MCU) flash-eeprom --debug 1 --suppress-bootloader-mem $(TARGET).eep + dfu-programmer $(MCU) reset + + +# Generate avr-gdb config/init file which does the following: +# define the reset signal, load the target file, connect to target, and set +# a breakpoint at main(). +gdb-config: + @$(REMOVE) $(GDBINIT_FILE) + @echo define reset >> $(GDBINIT_FILE) + @echo SIGNAL SIGHUP >> $(GDBINIT_FILE) + @echo end >> $(GDBINIT_FILE) + @echo file $(TARGET).elf >> $(GDBINIT_FILE) + @echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE) +ifeq ($(DEBUG_BACKEND),simulavr) + @echo load >> $(GDBINIT_FILE) +endif + @echo break main >> $(GDBINIT_FILE) + +debug: gdb-config $(TARGET).elf +ifeq ($(DEBUG_BACKEND), avarice) + @echo Starting AVaRICE - Press enter when "waiting to connect" message displays. + @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \ + $(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT) + @$(WINSHELL) /c pause + +else + @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \ + $(DEBUG_MFREQ) --port $(DEBUG_PORT) +endif + @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE) + + + + +# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. +COFFCONVERT = $(OBJCOPY) --debugging +COFFCONVERT += --change-section-address .data-0x800000 +COFFCONVERT += --change-section-address .bss-0x800000 +COFFCONVERT += --change-section-address .noinit-0x800000 +COFFCONVERT += --change-section-address .eeprom-0x810000 + + + +coff: $(TARGET).elf + @echo + @echo $(MSG_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-avr $< $(TARGET).cof + + +extcoff: $(TARGET).elf + @echo + @echo $(MSG_EXTENDED_COFF) $(TARGET).cof + $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof + + + +# Create final output files (.hex, .eep) from ELF output file. +%.hex: %.elf + @echo + @echo $(MSG_FLASH) $@ + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +%.eep: %.elf + @echo + @echo $(MSG_EEPROM) $@ + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0 + +# Create extended listing file from ELF output file. +%.lss: %.elf + @echo + @echo $(MSG_EXTENDED_LISTING) $@ + $(OBJDUMP) -h -z -S $< > $@ + +# Create a symbol table from ELF output file. +%.sym: %.elf + @echo + @echo $(MSG_SYMBOL_TABLE) $@ + $(NM) -n $< > $@ + + + +# Create library from object files. +.SECONDARY : $(TARGET).a +.PRECIOUS : $(OBJ) +%.a: $(OBJ) + @echo + @echo $(MSG_CREATING_LIBRARY) $@ + $(AR) $@ $(OBJ) + + +# Link: create ELF output file from object files. +.SECONDARY : $(TARGET).elf +.PRECIOUS : $(OBJ) +%.elf: $(OBJ) + @echo + @echo $(MSG_LINKING) $@ + $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS) + + +# Compile: create object files from C source files. +$(OBJDIR)/%.o : %.c + @echo + @echo $(MSG_COMPILING) $< + $(CC) -c $(ALL_CFLAGS) $< -o $@ + + +# Compile: create object files from C++ source files. +$(OBJDIR)/%.o : %.cpp + @echo + @echo $(MSG_COMPILING_CPP) $< + $(CC) -c $(ALL_CPPFLAGS) $< -o $@ + + +# Compile: create assembler files from C source files. +%.s : %.c + $(CC) -S $(ALL_CFLAGS) $< -o $@ + + +# Compile: create assembler files from C++ source files. +%.s : %.cpp + $(CC) -S $(ALL_CPPFLAGS) $< -o $@ + + +# Assemble: create object files from assembler source files. +$(OBJDIR)/%.o : %.S + @echo + @echo $(MSG_ASSEMBLING) $< + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + + +# Create preprocessed source for use in sending a bug report. +%.i : %.c + $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ + + +# Target: clean project. +clean: begin clean_list clean_binary end + +clean_binary: + $(REMOVE) $(TARGET).hex + +clean_list: + @echo $(MSG_CLEANING) + $(REMOVE) $(TARGET).eep + $(REMOVE) $(TARGET)eep.hex + $(REMOVE) $(TARGET).cof + $(REMOVE) $(TARGET).elf + $(REMOVE) $(TARGET).map + $(REMOVE) $(TARGET).sym + $(REMOVE) $(TARGET).lss + $(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o) + $(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst) + $(REMOVE) $(SRC:.c=.s) + $(REMOVE) $(SRC:.c=.d) + $(REMOVE) $(SRC:.c=.i) + $(REMOVEDIR) .dep + + +doxygen: + @echo Generating Project Documentation... + @doxygen Doxygen.conf + @echo Documentation Generation Complete. + +clean_doxygen: + rm -rf Documentation + +# Create object files directory +$(shell mkdir $(OBJDIR) 2>/dev/null) + + +# Include the dependency files. +-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) + + +# Listing of phony targets. +.PHONY : all checkhooks checklibmode checkboard \ +begin finish end sizebefore sizeafter gccversion \ +build elf hex eep lss sym coff extcoff clean \ +clean_list clean_binary program debug gdb-config \ +doxygen dfu flip flip-ee dfu-ee \ No newline at end of file -- cgit v1.2.3