Move new Class Driver powered demos to a new ClassDriver subdirectory, re-add old low level demos to a LowLevel subdirectory.
This commit is contained in:
parent
6a7c298c0f
commit
b9b03aadb2
273 changed files with 46078 additions and 0 deletions
263
Demos/Device/ClassDriver/RNDISEthernet/Descriptors.c
Normal file
263
Demos/Device/ClassDriver/RNDISEthernet/Descriptors.c
Normal file
|
@ -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;
|
||||
}
|
98
Demos/Device/ClassDriver/RNDISEthernet/Descriptors.h
Normal file
98
Demos/Device/ClassDriver/RNDISEthernet/Descriptors.h
Normal file
|
@ -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 <LUFA/Drivers/USB/USB.h>
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
/* 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
|
1485
Demos/Device/ClassDriver/RNDISEthernet/Doxygen.conf
Normal file
1485
Demos/Device/ClassDriver/RNDISEthernet/Doxygen.conf
Normal file
File diff suppressed because it is too large
Load diff
52
Demos/Device/ClassDriver/RNDISEthernet/LUFA RNDIS.inf
Normal file
52
Demos/Device/ClassDriver/RNDISEthernet/LUFA RNDIS.inf
Normal file
|
@ -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"
|
85
Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c
Normal file
85
Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.c
Normal file
|
@ -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;
|
||||
}
|
74
Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.h
Normal file
74
Demos/Device/ClassDriver/RNDISEthernet/Lib/ARP.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
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 <avr/io.h>
|
||||
#include <string.h>
|
||||
|
||||
#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
|
118
Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c
Normal file
118
Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c
Normal file
|
@ -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;
|
||||
}
|
125
Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.h
Normal file
125
Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.h
Normal file
|
@ -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 <avr/io.h>
|
||||
#include <string.h>
|
||||
|
||||
#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
|
130
Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c
Normal file
130
Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
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: */
|
||||
/** Constant for convenience when checking against or setting a MAC address to the virtual server MAC address. */
|
||||
const MAC_Address_t ServerMACAddress = {SERVER_MAC_ADDRESS};
|
||||
|
||||
/** Constant for convenience when checking against or setting an IP address to the virtual server IP address. */
|
||||
const IP_Address_t ServerIPAddress = {SERVER_IP_ADDRESS};
|
||||
|
||||
/** Constant for convenience when checking against or setting a MAC address to the broadcast MAC address. */
|
||||
const MAC_Address_t BroadcastMACAddress = {BROADCAST_MAC_ADDRESS};
|
||||
|
||||
/** Constant for convenience when checking against or setting a IP address to the broadcast IP address. */
|
||||
const IP_Address_t BroadcastIPAddress = {BROADCAST_IP_ADDRESS};
|
||||
|
||||
/** Constant for convenience when checking against or setting an IP address to the client (host) IP address. */
|
||||
const IP_Address_t ClientIPAddress = {CLIENT_IP_ADDRESS};
|
||||
|
||||
|
||||
/** Processes an incoming Ethernet frame, and writes the appropriate response to the output Ethernet
|
||||
* frame buffer if the sub protocol handlers create a valid response.
|
||||
*/
|
||||
void Ethernet_ProcessPacket(Ethernet_Frame_Info_t* FrameIN, Ethernet_Frame_Info_t* FrameOUT)
|
||||
{
|
||||
DecodeEthernetFrameHeader(FrameIN->FrameData);
|
||||
|
||||
/* Cast the incoming Ethernet frame to the Ethernet header type */
|
||||
Ethernet_Frame_Header_t* FrameINHeader = (Ethernet_Frame_Header_t*)&FrameIN->FrameData;
|
||||
Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT->FrameData;
|
||||
|
||||
int16_t RetSize = NO_RESPONSE;
|
||||
|
||||
/* Ensure frame is addressed to either all (broadcast) or the virtual webserver, and is a type II frame */
|
||||
if ((MAC_COMPARE(&FrameINHeader->Destination, &ServerMACAddress) ||
|
||||
MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress)))
|
||||
{
|
||||
/* Process the packet depending on its protocol */
|
||||
switch (SwapEndian_16(FrameINHeader->EtherType))
|
||||
{
|
||||
case ETHERTYPE_ARP:
|
||||
RetSize = ARP_ProcessARPPacket(&FrameIN->FrameData[sizeof(Ethernet_Frame_Header_t)],
|
||||
&FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t)]);
|
||||
break;
|
||||
case ETHERTYPE_IPV4:
|
||||
RetSize = IP_ProcessIPPacket(FrameIN,
|
||||
&FrameIN->FrameData[sizeof(Ethernet_Frame_Header_t)],
|
||||
&FrameOUT->FrameData[sizeof(Ethernet_Frame_Header_t)]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Protocol processing routine has filled a response, complete the ethernet frame header */
|
||||
if (RetSize > 0)
|
||||
{
|
||||
/* Fill out the response Ethernet frame header */
|
||||
FrameOUTHeader->Source = ServerMACAddress;
|
||||
FrameOUTHeader->Destination = FrameINHeader->Source;
|
||||
FrameOUTHeader->EtherType = FrameINHeader->EtherType;
|
||||
|
||||
/* Set the response length in the buffer and indicate that a response is ready to be sent */
|
||||
FrameOUT->FrameLength = (sizeof(Ethernet_Frame_Header_t) + RetSize);
|
||||
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;
|
||||
}
|
104
Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.h
Normal file
104
Demos/Device/ClassDriver/RNDISEthernet/Lib/Ethernet.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
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 <avr/io.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <LUFA/Drivers/USB/Class/Device/RNDIS.h>
|
||||
|
||||
#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 USB RNDIS network adapter */
|
||||
#define ADAPTER_MAC_ADDRESS {0x00, 0x02, 0x00, 0x02, 0x00, 0x02}
|
||||
|
||||
/** 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)
|
||||
|
||||
/** 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 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 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(Ethernet_Frame_Info_t* FrameIN, Ethernet_Frame_Info_t* FrameOUT);
|
||||
uint16_t Ethernet_Checksum16(void* Data, uint16_t Bytes);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
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 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
|
80
Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.c
Normal file
80
Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.c
Normal file
|
@ -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
|
||||
*
|
||||
* 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 FrameIN Pointer to the incomming Ethernet frame information structure
|
||||
* \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(Ethernet_Frame_Info_t* FrameIN, 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;
|
||||
}
|
80
Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.h
Normal file
80
Demos/Device/ClassDriver/RNDISEthernet/Lib/ICMP.h
Normal file
|
@ -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 <avr/io.h>
|
||||
#include <string.h>
|
||||
|
||||
#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(Ethernet_Frame_Info_t* FrameIN, void* InDataStart, void* OutDataStart);
|
||||
|
||||
#endif
|
113
Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c
Normal file
113
Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
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 FrameIN Pointer to the incomming Ethernet frame information structure
|
||||
* \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(Ethernet_Frame_Info_t* FrameIN, 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(FrameIN,
|
||||
&((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;
|
||||
}
|
93
Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.h
Normal file
93
Demos/Device/ClassDriver/RNDISEthernet/Lib/IP.h
Normal file
|
@ -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 <avr/io.h>
|
||||
#include <string.h>
|
||||
|
||||
#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(Ethernet_Frame_Info_t* FrameIN, void* InDataStart, void* OutDataStart);
|
||||
|
||||
#endif
|
280
Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c
Normal file
280
Demos/Device/ClassDriver/RNDISEthernet/Lib/ProtocolDecoders.c
Normal file
|
@ -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
|
||||
}
|
|
@ -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 <avr/io.h>
|
||||
|
||||
#include <LUFA/Drivers/Peripheral/SerialStream.h>
|
||||
|
||||
#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
|
614
Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c
Normal file
614
Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.c
Normal file
|
@ -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.
|
||||
*/
|
||||
void TCP_TCPTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo)
|
||||
{
|
||||
/* 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 (RNDISInterfaceInfo->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*)&RNDISInterfaceInfo->FrameOUT.FrameData;
|
||||
IP_Header_t* IPHeaderOUT = (IP_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)];
|
||||
TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&RNDISInterfaceInfo->FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +
|
||||
sizeof(IP_Header_t)];
|
||||
void* TCPDataOUT = &RNDISInterfaceInfo->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 */
|
||||
RNDISInterfaceInfo->FrameOUT.FrameLength = PacketSize;
|
||||
RNDISInterfaceInfo->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 DestinationAddress 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;
|
||||
}
|
249
Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h
Normal file
249
Demos/Device/ClassDriver/RNDISEthernet/Lib/TCP.h
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
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 <avr/io.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#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;
|
||||
|
||||
/* External Variables: */
|
||||
TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS];
|
||||
|
||||
/* Function Prototypes: */
|
||||
void TCP_TCPTask(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);
|
||||
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
|
80
Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.c
Normal file
80
Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.c
Normal file
|
@ -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;
|
||||
}
|
66
Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.h
Normal file
66
Demos/Device/ClassDriver/RNDISEthernet/Lib/UDP.h
Normal file
|
@ -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 <avr/io.h>
|
||||
|
||||
#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
|
162
Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.c
Normal file
162
Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.c
Normal file
|
@ -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[] =
|
||||
"<html>"
|
||||
" <head>"
|
||||
" <title>"
|
||||
" LUFA Webserver Demo"
|
||||
" </title>"
|
||||
" </head>"
|
||||
" <body>"
|
||||
" <h1>Hello from your USB AVR!</h1>"
|
||||
" <p>"
|
||||
" 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."
|
||||
" <br /><br />"
|
||||
" <small>Project Information: <a href=\"http://www.fourwalledcubicle.com/LUFA.php\">http://www.fourwalledcubicle.com/LUFA.php</a>.</small>"
|
||||
" <hr />"
|
||||
" <i>LUFA Version: </i>" LUFA_VERSION_STRING
|
||||
" </p>"
|
||||
" </body>"
|
||||
"</html>";
|
||||
|
||||
|
||||
/** 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);
|
||||
}
|
||||
}
|
||||
}
|
55
Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.h
Normal file
55
Demos/Device/ClassDriver/RNDISEthernet/Lib/Webserver.h
Normal file
|
@ -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 <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include <LUFA/Version.h>
|
||||
|
||||
#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
|
1
Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.aps
Normal file
1
Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.aps
Normal file
File diff suppressed because one or more lines are too long
131
Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c
Normal file
131
Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
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"
|
||||
|
||||
/** LUFA RNDIS Class driver interface configuration and state information. This structure is
|
||||
* passed to all RNDIS Class driver functions, so that multiple instances of the same class
|
||||
* within a device can be differentiated from one another.
|
||||
*/
|
||||
USB_ClassInfo_RNDIS_t Ethernet_RNDIS_Interface =
|
||||
{
|
||||
.ControlInterfaceNumber = 0,
|
||||
|
||||
.DataINEndpointNumber = CDC_TX_EPNUM,
|
||||
.DataINEndpointSize = CDC_TXRX_EPSIZE,
|
||||
|
||||
.DataOUTEndpointNumber = CDC_RX_EPNUM,
|
||||
.DataOUTEndpointSize = CDC_TXRX_EPSIZE,
|
||||
|
||||
.NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM,
|
||||
.NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE,
|
||||
|
||||
.AdapterVendorDescription = "LUFA RNDIS Demo Adapter",
|
||||
.AdapterMACAddress = {ADAPTER_MAC_ADDRESS},
|
||||
};
|
||||
|
||||
/** Main program entry point. This routine contains the overall program flow, including initial
|
||||
* setup of all components and the main program loop.
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
SetupHardware();
|
||||
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
|
||||
|
||||
TCP_Init();
|
||||
Webserver_Init();
|
||||
|
||||
printf_P(PSTR("\r\n\r\n****** RNDIS Demo running. ******\r\n"));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (Ethernet_RNDIS_Interface.FrameIN.FrameInBuffer)
|
||||
{
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
|
||||
Ethernet_ProcessPacket(&Ethernet_RNDIS_Interface.FrameIN, &Ethernet_RNDIS_Interface.FrameOUT);
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_READY);
|
||||
}
|
||||
|
||||
TCP_TCPTask(&Ethernet_RNDIS_Interface);
|
||||
|
||||
USB_RNDIS_USBTask(&Ethernet_RNDIS_Interface);
|
||||
USB_USBTask();
|
||||
}
|
||||
}
|
||||
|
||||
/** Configures the board hardware and chip peripherals for the demo's functionality. */
|
||||
void SetupHardware(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);
|
||||
USB_Init();
|
||||
}
|
||||
|
||||
/** Event handler for the library USB Connection event. */
|
||||
void EVENT_USB_Connect(void)
|
||||
{
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
|
||||
}
|
||||
|
||||
/** Event handler for the library USB Disconnection event. */
|
||||
void EVENT_USB_Disconnect(void)
|
||||
{
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
|
||||
}
|
||||
|
||||
/** Event handler for the library USB Configuration Changed event. */
|
||||
void EVENT_USB_ConfigurationChanged(void)
|
||||
{
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_READY);
|
||||
|
||||
if (!(USB_RNDIS_ConfigureEndpoints(&Ethernet_RNDIS_Interface)))
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
|
||||
}
|
||||
|
||||
/** Event handler for the library USB Unhandled Control Packet event. */
|
||||
void EVENT_USB_UnhandledControlPacket(void)
|
||||
{
|
||||
USB_RNDIS_ProcessControlPacket(&Ethernet_RNDIS_Interface);
|
||||
}
|
86
Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.h
Normal file
86
Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
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 <avr/io.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/power.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Descriptors.h"
|
||||
|
||||
#include "Lib/Ethernet.h"
|
||||
#include "Lib/TCP.h"
|
||||
#include "Lib/ARP.h"
|
||||
#include "Lib/Webserver.h"
|
||||
|
||||
#include <LUFA/Version.h>
|
||||
#include <LUFA/Drivers/Board/LEDs.h>
|
||||
#include <LUFA/Drivers/Board/Joystick.h>
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
#include <LUFA/Drivers/USB/Class/Device/RNDIS.h>
|
||||
|
||||
/* Macros: */
|
||||
/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
|
||||
#define LEDMASK_USB_NOTREADY LEDS_LED1
|
||||
|
||||
/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
|
||||
#define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
|
||||
|
||||
/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
|
||||
#define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
|
||||
|
||||
/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
|
||||
#define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
|
||||
|
||||
/** LED mask for the library LED driver, to indicate that the USB interface is busy. */
|
||||
#define LEDMASK_USB_BUSY (LEDS_LED2)
|
||||
|
||||
/* Function Prototypes: */
|
||||
void SetupHardware(void);
|
||||
|
||||
void EVENT_USB_Connect(void);
|
||||
void EVENT_USB_Disconnect(void);
|
||||
void EVENT_USB_ConfigurationChanged(void);
|
||||
void EVENT_USB_UnhandledControlPacket(void);
|
||||
|
||||
void CALLBACK_USB_RNDIS_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_t* RNDISInterfaceInfo);
|
||||
|
||||
#endif
|
115
Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.txt
Normal file
115
Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.txt
Normal file
|
@ -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:
|
||||
*
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td><b>USB Mode:</b></td>
|
||||
* <td>Device</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>USB Class:</b></td>
|
||||
* <td>Communications Device Class (CDC)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>USB Subclass:</b></td>
|
||||
* <td>Remote NDIS (Microsoft Proprietary CDC Class Networking Standard)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Relevant Standards:</b></td>
|
||||
* <td>Microsoft RNDIS Specification</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Usable Speeds:</b></td>
|
||||
* <td>Full Speed Mode</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* \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.
|
||||
*
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td><b>Define Name:</b></td>
|
||||
* <td><b>Location:</b></td>
|
||||
* <td><b>Description:</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>NO_DECODE_ETHERNET</td>
|
||||
* <td>Makefile CDEFS</td>
|
||||
* <td>When defined, received Ethernet headers will not be decoded and printed to the device serial port.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>NO_DECODE_ARP</td>
|
||||
* <td>Makefile CDEFS</td>
|
||||
* <td>When defined, received ARP headers will not be decoded and printed to the device serial port.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>NO_DECODE_IP</td>
|
||||
* <td>Makefile CDEFS</td>
|
||||
* <td>When defined, received IP headers will not be decoded and printed to the device serial port.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>NO_DECODE_ICMP</td>
|
||||
* <td>Makefile CDEFS</td>
|
||||
* <td>When defined, received ICMP headers will not be decoded and printed to the device serial port.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>NO_DECODE_TCP</td>
|
||||
* <td>Makefile CDEFS</td>
|
||||
* <td>When defined, received TCP headers will not be decoded and printed to the device serial port.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>NO_DECODE_UDP</td>
|
||||
* <td>Makefile CDEFS</td>
|
||||
* <td>When defined, received UDP headers will not be decoded and printed to the device serial port.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>NO_DECODE_DHCP</td>
|
||||
* <td>Makefile CDEFS</td>
|
||||
* <td>When defined, received DHCP headers will not be decoded and printed to the device serial port.</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*/
|
745
Demos/Device/ClassDriver/RNDISEthernet/makefile
Normal file
745
Demos/Device/ClassDriver/RNDISEthernet/makefile
Normal file
|
@ -0,0 +1,745 @@
|
|||
# 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/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/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/Device/RNDIS.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 -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 <http://savannah.nongnu.org/projects/avrdude>
|
||||
# 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
|
Loading…
Add table
Add a link
Reference in a new issue