From 3cba88e4c05d6a3c25ffa9c7185d41a84b7f72b1 Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Sun, 22 May 2011 08:28:40 +0000 Subject: [PATCH] Add RNDIS Device support to the Webserver project, so that the files stored on the device can be viewed from a web-browser while the board is plugged into a host machine. --- .../ClassDriver/RNDISEthernet/Lib/DHCP.c | 2 +- .../ClassDriver/RNDISEthernet/RNDISEthernet.c | 3 + .../Device/LowLevel/RNDISEthernet/Lib/DHCP.c | 2 +- LUFA.pnproj | 2 +- LUFA/ManPages/ChangeLog.txt | 1 + LUFA/ManPages/FutureChanges.txt | 1 - Projects/Webserver/Descriptors.c | 115 ++++++++- Projects/Webserver/Descriptors.h | 32 ++- Projects/Webserver/LUFA Webserver RNDIS.inf | 52 ++++ Projects/Webserver/Lib/DHCPClientApp.c | 87 +------ Projects/Webserver/Lib/DHCPClientApp.h | 111 +------- Projects/Webserver/Lib/DHCPCommon.c | 102 ++++++++ Projects/Webserver/Lib/DHCPCommon.h | 157 ++++++++++++ Projects/Webserver/Lib/DHCPServerApp.c | 237 ++++++++++++++++++ Projects/Webserver/Lib/DHCPServerApp.h | 62 +++++ Projects/Webserver/Lib/HTTPServerApp.c | 6 +- Projects/Webserver/Lib/uIPManagement.c | 96 +++++-- Projects/Webserver/Lib/uIPManagement.h | 11 +- Projects/Webserver/Lib/uip/uip-split.c | 15 +- Projects/Webserver/Lib/uip/uip.c | 10 +- Projects/Webserver/USBDeviceMode.c | 40 ++- Projects/Webserver/USBDeviceMode.h | 4 + Projects/Webserver/USBHostMode.c | 12 +- Projects/Webserver/USBHostMode.h | 2 +- Projects/Webserver/Webserver.aps | 2 +- Projects/Webserver/Webserver.txt | 13 +- Projects/Webserver/makefile | 13 +- 27 files changed, 939 insertions(+), 251 deletions(-) create mode 100644 Projects/Webserver/LUFA Webserver RNDIS.inf create mode 100644 Projects/Webserver/Lib/DHCPCommon.c create mode 100644 Projects/Webserver/Lib/DHCPCommon.h create mode 100644 Projects/Webserver/Lib/DHCPServerApp.c create mode 100644 Projects/Webserver/Lib/DHCPServerApp.h diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c b/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c index 6bd920fd0e..cc8861736d 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/Lib/DHCP.c @@ -59,7 +59,7 @@ int16_t DHCP_ProcessDHCPPacket(void* IPHeaderInStart, DecodeDHCPHeader(DHCPHeaderInStart); - /* Zero out the response DHCP packet, as much of it legacy and left at 0 */ + /* Zero out the response DHCP packet, as much of it is legacy and left at 0 */ memset(DHCPHeaderOUT, 0, sizeof(DHCP_Header_t)); /* Fill out the response DHCP packet */ diff --git a/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c b/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c index dc9682a05f..adcb2939ae 100644 --- a/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c +++ b/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c @@ -63,7 +63,10 @@ USB_ClassInfo_RNDIS_Device_t Ethernet_RNDIS_Interface = }, }; +/** Global to store the incoming frame from the host before it is processed by the device. */ static Ethernet_Frame_Info_t FrameIN; + +/** Global to store the outgoing frame created in the device before it is sent to the host. */ static Ethernet_Frame_Info_t FrameOUT; /** Main program entry point. This routine contains the overall program flow, including initial diff --git a/Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.c b/Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.c index 56668112ed..5fce88a6f7 100644 --- a/Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.c +++ b/Demos/Device/LowLevel/RNDISEthernet/Lib/DHCP.c @@ -59,7 +59,7 @@ int16_t DHCP_ProcessDHCPPacket(void* IPHeaderInStart, DecodeDHCPHeader(DHCPHeaderInStart); - /* Zero out the response DHCP packet, as much of it legacy and left at 0 */ + /* Zero out the response DHCP packet, as much of it is legacy and left at 0 */ memset(DHCPHeaderOUT, 0, sizeof(DHCP_Header_t)); /* Fill out the response DHCP packet */ diff --git a/LUFA.pnproj b/LUFA.pnproj index 0d335d0e70..5ed8db5afd 100644 --- a/LUFA.pnproj +++ b/LUFA.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt index dd58c24dd6..12352129cc 100644 --- a/LUFA/ManPages/ChangeLog.txt +++ b/LUFA/ManPages/ChangeLog.txt @@ -38,6 +38,7 @@ * - Added HID class bootloader, compatible with a modified version of the command line Teensy loader from PJRC.com * - Added LED flashing to the CDC and DFU class bootloaders to indicate when they are running * - Added new incomplete AndroidAccessoryHost Host LowLevel demo + * - Added RNDIS device mode to the Webserver project * * Changed: * - Core: diff --git a/LUFA/ManPages/FutureChanges.txt b/LUFA/ManPages/FutureChanges.txt index 6db27d1644..b1cc3a78f5 100644 --- a/LUFA/ManPages/FutureChanges.txt +++ b/LUFA/ManPages/FutureChanges.txt @@ -33,7 +33,6 @@ * -# Finish SideShow demo * -# Finish StandaloneProgrammer project * -# Arduino Uno compatible USB-MIDI, USB-HID - * -# Make Webserver project work in RNDIS device mode * - Ports * -# Atmel ARM7 series microcontrollers * -# Other (commercial) C compilers diff --git a/Projects/Webserver/Descriptors.c b/Projects/Webserver/Descriptors.c index ba20f070a8..63c43d763a 100644 --- a/Projects/Webserver/Descriptors.c +++ b/Projects/Webserver/Descriptors.c @@ -59,15 +59,15 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, .USBSpecification = VERSION_BCD(01.10), - .Class = USB_CSCP_NoDeviceClass, - .SubClass = USB_CSCP_NoDeviceSubclass, - .Protocol = USB_CSCP_NoDeviceProtocol, + .Class = USB_CSCP_IADDeviceClass, + .SubClass = USB_CSCP_IADDeviceSubclass, + .Protocol = USB_CSCP_IADDeviceProtocol, .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, .VendorID = 0x03EB, - .ProductID = 0x2045, - .ReleaseNumber = VERSION_BCD(00.01), + .ProductID = 0x2069, + .ReleaseNumber = VERSION_BCD(00.10), .ManufacturerStrIndex = 0x01, .ProductStrIndex = 0x02, @@ -88,7 +88,7 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), - .TotalInterfaces = 1, + .TotalInterfaces = 3, .ConfigurationNumber = 1, .ConfigurationStrIndex = NO_DESCRIPTOR, @@ -98,13 +98,114 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = .MaxPowerConsumption = USB_CONFIG_POWER_MA(100) }, - .MS_Interface = + .CDC_IAD = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation}, + + .FirstInterfaceIndex = 0, + .TotalInterfaces = 2, + + .Class = CDC_CSCP_CDCClass, + .SubClass = CDC_CSCP_ACMSubclass, + .Protocol = CDC_CSCP_VendorSpecificProtocol, + + .IADStrIndex = NO_DESCRIPTOR + }, + + .CDC_CCI_Interface = { .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, .InterfaceNumber = 0, .AlternateSetting = 0, + .TotalEndpoints = 1, + + .Class = CDC_CSCP_CDCClass, + .SubClass = CDC_CSCP_ACMSubclass, + .Protocol = CDC_CSCP_VendorSpecificProtocol, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .CDC_Functional_Header = + { + .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface}, + .Subtype = CDC_DSUBTYPE_CSInterface_Header, + + .CDCSpecification = VERSION_BCD(01.10), + }, + + .CDC_Functional_ACM = + { + .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface}, + .Subtype = CDC_DSUBTYPE_CSInterface_ACM, + + .Capabilities = 0x00, + }, + + .CDC_Functional_Union = + { + .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface}, + .Subtype = CDC_DSUBTYPE_CSInterface_Union, + + .MasterInterfaceNumber = 0, + .SlaveInterfaceNumber = 1, + }, + + .CDC_NotificationEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC_NOTIFICATION_EPNUM), + .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CDC_NOTIFICATION_EPSIZE, + .PollingIntervalMS = 0xFF + }, + + .CDC_DCI_Interface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = 1, + .AlternateSetting = 0, + + .TotalEndpoints = 2, + + .Class = CDC_CSCP_CDCDataClass, + .SubClass = CDC_CSCP_NoDataSubclass, + .Protocol = CDC_CSCP_NoDataProtocol, + + .InterfaceStrIndex = NO_DESCRIPTOR + }, + + .RNDIS_DataOutEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_OUT | CDC_RX_EPNUM), + .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CDC_TXRX_EPSIZE, + .PollingIntervalMS = 0x01 + }, + + .RNDIS_DataInEndpoint = + { + .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, + + .EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | CDC_TX_EPNUM), + .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + .EndpointSize = CDC_TXRX_EPSIZE, + .PollingIntervalMS = 0x01 + }, + + .MS_Interface = + { + .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, + + .InterfaceNumber = 2, + .AlternateSetting = 0, + .TotalEndpoints = 2, .Class = MS_CSCP_MassStorageClass, diff --git a/Projects/Webserver/Descriptors.h b/Projects/Webserver/Descriptors.h index 38cb23131c..e285dfba51 100644 --- a/Projects/Webserver/Descriptors.h +++ b/Projects/Webserver/Descriptors.h @@ -51,6 +51,21 @@ /** Size in bytes of the Mass Storage data endpoints. */ #define MASS_STORAGE_IO_EPSIZE 64 + /** Endpoint number of the CDC device-to-host notification IN endpoint. */ + #define CDC_NOTIFICATION_EPNUM 5 + + /** 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 @@ -58,10 +73,19 @@ */ typedef struct { - USB_Descriptor_Configuration_Header_t Config; - USB_Descriptor_Interface_t MS_Interface; - USB_Descriptor_Endpoint_t MS_DataInEndpoint; - USB_Descriptor_Endpoint_t MS_DataOutEndpoint; + USB_Descriptor_Configuration_Header_t Config; + USB_Descriptor_Interface_Association_t CDC_IAD; + USB_Descriptor_Interface_t CDC_CCI_Interface; + USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header; + USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM; + USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union; + USB_Descriptor_Endpoint_t CDC_NotificationEndpoint; + USB_Descriptor_Interface_t CDC_DCI_Interface; + USB_Descriptor_Endpoint_t RNDIS_DataOutEndpoint; + USB_Descriptor_Endpoint_t RNDIS_DataInEndpoint; + USB_Descriptor_Interface_t MS_Interface; + USB_Descriptor_Endpoint_t MS_DataInEndpoint; + USB_Descriptor_Endpoint_t MS_DataOutEndpoint; } USB_Descriptor_Configuration_t; /* Function Prototypes: */ diff --git a/Projects/Webserver/LUFA Webserver RNDIS.inf b/Projects/Webserver/LUFA Webserver RNDIS.inf new file mode 100644 index 0000000000..6ed9cc74da --- /dev/null +++ b/Projects/Webserver/LUFA Webserver RNDIS.inf @@ -0,0 +1,52 @@ +; Windows LUFA RNDIS Setup File +; Copyright (c) 2000 Microsoft Corporation + +[Version] +Signature = "$Windows NT$" +Class = Net +ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} +Provider = %COMPANY% +DriverVer = 06/21/2006,6.0.6000.16384 +;CatalogFile = device.cat + +[Manufacturer] +%COMPANY% = RndisDevices,NTx86,NTamd64,NTia64 + +; Decoration for x86 architecture +[RndisDevices.NTx86] +%RNDISDEV% = RNDIS.NT.5.1, USB\VID_03EB&PID_2069&MI_00 + +; Decoration for x64 architecture +[RndisDevices.NTamd64] +%RNDISDEV% = RNDIS.NT.5.1, USB\VID_03EB&PID_2069&MI_00 + +; Decoration for ia64 architecture +[RndisDevices.NTia64] +%RNDISDEV% = RNDIS.NT.5.1, USB\VID_03EB&PID_2069&MI_00 + +;@@@ 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 Webserver" \ No newline at end of file diff --git a/Projects/Webserver/Lib/DHCPClientApp.c b/Projects/Webserver/Lib/DHCPClientApp.c index 4afe6bfe25..6a2f029387 100644 --- a/Projects/Webserver/Lib/DHCPClientApp.c +++ b/Projects/Webserver/Lib/DHCPClientApp.c @@ -43,13 +43,13 @@ void DHCPClientApp_Init(void) { /* Create a new UDP connection to the DHCP server port for the DHCP solicitation */ - struct uip_udp_conn* Connection = uip_udp_new(&uip_broadcast_addr, HTONS(DHCPC_SERVER_PORT)); + struct uip_udp_conn* Connection = uip_udp_new(&uip_broadcast_addr, HTONS(DHCP_SERVER_PORT)); /* If the connection was successfully created, bind it to the local DHCP client port */ if (Connection != NULL) { uip_udp_appstate_t* const AppState = &Connection->appstate; - uip_udp_bind(Connection, HTONS(DHCPC_CLIENT_PORT)); + uip_udp_bind(Connection, HTONS(DHCP_CLIENT_PORT)); /* Set the initial client state */ AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover; @@ -80,8 +80,8 @@ void DHCPClientApp_Callback(void) /* Add the required DHCP options list to the packet */ uint8_t RequiredOptionList[] = {DHCP_OPTION_SUBNET_MASK, DHCP_OPTION_ROUTER, DHCP_OPTION_DNS_SERVER}; - AppDataSize += DHCPClientApp_SetOption(AppData->Options, DHCP_OPTION_REQ_LIST, sizeof(RequiredOptionList), - RequiredOptionList); + AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_REQ_LIST, sizeof(RequiredOptionList), + RequiredOptionList); /* Send the DHCP DISCOVER packet */ uip_udp_send(AppDataSize); @@ -103,14 +103,14 @@ void DHCPClientApp_Callback(void) uint8_t OfferResponse_MessageType; if ((AppData->TransactionID == DHCP_TRANSACTION_ID) && - DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &OfferResponse_MessageType) && + DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &OfferResponse_MessageType) && (OfferResponse_MessageType == DHCP_OFFER)) { /* Received a DHCP offer for an IP address, copy over values for later request */ memcpy(&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP, &AppData->YourIP, sizeof(uip_ipaddr_t)); - DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK, &AppState->DHCPClient.DHCPOffer_Data.Netmask); - DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_ROUTER, &AppState->DHCPClient.DHCPOffer_Data.GatewayIP); - DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_SERVER_ID, &AppState->DHCPClient.DHCPOffer_Data.ServerIP); + DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK, &AppState->DHCPClient.DHCPOffer_Data.Netmask); + DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_ROUTER, &AppState->DHCPClient.DHCPOffer_Data.GatewayIP); + DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_SERVER_ID, &AppState->DHCPClient.DHCPOffer_Data.ServerIP); timer_reset(&AppState->DHCPClient.Timeout); AppState->DHCPClient.CurrentState = DHCP_STATE_SendRequest; @@ -122,12 +122,12 @@ void DHCPClientApp_Callback(void) AppDataSize += DHCPClientApp_FillDHCPHeader(AppData, DHCP_REQUEST, AppState); /* Add the DHCP REQUESTED IP ADDRESS option to the packet */ - AppDataSize += DHCPClientApp_SetOption(AppData->Options, DHCP_OPTION_REQ_IPADDR, sizeof(uip_ipaddr_t), - &AppState->DHCPClient.DHCPOffer_Data.AllocatedIP); + AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_REQ_IPADDR, sizeof(uip_ipaddr_t), + &AppState->DHCPClient.DHCPOffer_Data.AllocatedIP); /* Add the DHCP SERVER IP ADDRESS option to the packet */ - AppDataSize += DHCPClientApp_SetOption(AppData->Options, DHCP_OPTION_SERVER_ID, sizeof(uip_ipaddr_t), - &AppState->DHCPClient.DHCPOffer_Data.ServerIP); + AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SERVER_ID, sizeof(uip_ipaddr_t), + &AppState->DHCPClient.DHCPOffer_Data.ServerIP); /* Send the DHCP REQUEST packet */ uip_udp_send(AppDataSize); @@ -149,7 +149,7 @@ void DHCPClientApp_Callback(void) uint8_t RequestResponse_MessageType; if ((AppData->TransactionID == DHCP_TRANSACTION_ID) && - DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &RequestResponse_MessageType) && + DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &RequestResponse_MessageType) && (RequestResponse_MessageType == DHCP_ACK)) { /* Set the new network parameters from the DHCP server */ @@ -207,66 +207,5 @@ static uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader, return (sizeof(DHCP_Header_t) + 4); } -/** Sets the given DHCP option in the DHCP packet's option list. This automatically moves the - * end of options terminator past the new option in the options list. - * - * \param[in,out] DHCPOptionList Pointer to the start of the DHCP packet's options list - * \param[in] Option DHCP option to add to the list - * \param[in] DataLen Size in bytes of the option data to add - * \param[in] OptionData Buffer where the option's data is to be sourced from - * - * \return Number of bytes added to the DHCP packet - */ -static uint8_t DHCPClientApp_SetOption(uint8_t* DHCPOptionList, - const uint8_t Option, - const uint8_t DataLen, - void* const OptionData) -{ - /* Skip through the DHCP options list until the terminator option is found */ - while (*DHCPOptionList != DHCP_OPTION_END) - DHCPOptionList += (DHCPOptionList[1] + 2); - - /* Overwrite the existing terminator with the new option, add a new terminator at the end of the list */ - DHCPOptionList[0] = Option; - DHCPOptionList[1] = DataLen; - memcpy(&DHCPOptionList[2], OptionData, DataLen); - DHCPOptionList[2 + DataLen] = DHCP_OPTION_END; - - /* Calculate the total number of bytes added to the outgoing packet */ - return (2 + DataLen); -} - -/** Retrieves the given option's data (if present) from the DHCP packet's options list. - * - * \param[in,out] DHCPOptionList Pointer to the start of the DHCP packet's options list - * \param[in] Option DHCP option to retrieve to the list - * \param[out] Destination Buffer where the option's data is to be written to if found - * - * \return Boolean true if the option was found in the DHCP packet's options list, false otherwise - */ -static bool DHCPClientApp_GetOption(const uint8_t* DHCPOptionList, - const uint8_t Option, - void* const Destination) -{ - /* Look through the incoming DHCP packet's options list for the requested option */ - while (*DHCPOptionList != DHCP_OPTION_END) - { - /* Check if the current DHCP option in the packet is the one requested */ - if (DHCPOptionList[0] == Option) - { - /* Copy request option's data to the destination buffer */ - memcpy(Destination, &DHCPOptionList[2], DHCPOptionList[1]); - - /* Indicate that the requested option data was successfully retrieved */ - return true; - } - - /* Skip to next DHCP option in the options list */ - DHCPOptionList += (DHCPOptionList[1] + 2); - } - - /* Requested option not found in the incoming packet's DHCP options list */ - return false; -} #endif diff --git a/Projects/Webserver/Lib/DHCPClientApp.h b/Projects/Webserver/Lib/DHCPClientApp.h index cb4014fbc2..1f3104c6f9 100644 --- a/Projects/Webserver/Lib/DHCPClientApp.h +++ b/Projects/Webserver/Lib/DHCPClientApp.h @@ -42,111 +42,11 @@ #include #include "../Webserver.h" - - /* Macros: */ - /** UDP listen port for a BOOTP server. */ - #define DHCPC_SERVER_PORT 67 - - /** UDP listen port for a BOOTP client. */ - #define DHCPC_CLIENT_PORT 68 - - /** BOOTP message type for a BOOTP REQUEST message. */ - #define DHCP_OP_BOOTREQUEST 0x01 - - /** BOOTP message type for a BOOTP REPLY message. */ - #define DHCP_OP_BOOTREPLY 0x02 - - /** BOOTP flag for a BOOTP broadcast message. */ - #define BOOTP_BROADCAST 0x8000 - - /** Magic DHCP cookie for a BOOTP message to identify it as a DHCP message. */ - #define DHCP_MAGIC_COOKIE 0x63538263 - - /** Unique transaction ID used to identify DHCP responses to the client. */ - #define DHCP_TRANSACTION_ID 0x13245466 - - /** DHCP message type for a DISCOVER message. */ - #define DHCP_DISCOVER 1 - - /** DHCP message type for an OFFER message. */ - #define DHCP_OFFER 2 - - /** DHCP message type for a REQUEST message. */ - #define DHCP_REQUEST 3 - - /** DHCP message type for a DECLINE message. */ - #define DHCP_DECLINE 4 - - /** DHCP message type for an ACK message. */ - #define DHCP_ACK 5 - - /** DHCP message type for a NAK message. */ - #define DHCP_NAK 6 - - /** DHCP message type for a RELEASE message. */ - #define DHCP_RELEASE 7 - - /** DHCP medium type for standard Ethernet. */ - #define DHCP_HTYPE_ETHERNET 1 - - /** DHCP message option for the network subnet mask. */ - #define DHCP_OPTION_SUBNET_MASK 1 - - /** DHCP message option for the network gateway IP. */ - #define DHCP_OPTION_ROUTER 3 - - /** DHCP message option for the network DNS server. */ - #define DHCP_OPTION_DNS_SERVER 6 - - /** DHCP message option for the requested client IP address. */ - #define DHCP_OPTION_REQ_IPADDR 50 - - /** DHCP message option for the IP address lease time. */ - #define DHCP_OPTION_LEASE_TIME 51 - - /** DHCP message option for the DHCP message type. */ - #define DHCP_OPTION_MSG_TYPE 53 - - /** DHCP message option for the DHCP server IP. */ - #define DHCP_OPTION_SERVER_ID 54 - - /** DHCP message option for the list of required options from the server. */ - #define DHCP_OPTION_REQ_LIST 55 - - /** DHCP message option for the options list terminator. */ - #define DHCP_OPTION_END 255 - - /* 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 */ - - uip_ipaddr_t ClientIP; /**< Client IP address, if already leased an IP */ - uip_ipaddr_t YourIP; /**< Client IP address */ - uip_ipaddr_t NextServerIP; /**< Legacy BOOTP protocol field, unused for DHCP */ - uip_ipaddr_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 */ - - uint8_t Options[]; /**< DHCP message options */ - } DHCP_Header_t; + #include "DHCPCommon.h" /* Enums: */ /** States for each DHCP connection to a DHCP client. */ - enum DHCP_States_t + enum DHCP_Client_States_t { DHCP_STATE_SendDiscover, /**< Send DISCOVER packet to retrieve DHCP lease offers */ DHCP_STATE_WaitForOffer, /**< Waiting for OFFER packet giving available DHCP leases */ @@ -163,13 +63,6 @@ static uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader, const uint8_t DHCPMessageType, uip_udp_appstate_t* const AppState); - static uint8_t DHCPClientApp_SetOption(uint8_t* DHCPOptionList, - const uint8_t Option, - const uint8_t DataLen, - void* const OptionData); - static bool DHCPClientApp_GetOption(const uint8_t* DHCPOptionList, - const uint8_t Option, - void* const Destination); #endif #endif diff --git a/Projects/Webserver/Lib/DHCPCommon.c b/Projects/Webserver/Lib/DHCPCommon.c new file mode 100644 index 0000000000..dac5fa7976 --- /dev/null +++ b/Projects/Webserver/Lib/DHCPCommon.c @@ -0,0 +1,102 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author 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. +*/ + +#if defined(ENABLE_DHCP_CLIENT) || defined(ENABLE_DHCP_SERVER) || defined(__DOXYGEN__) + +/** \file + * + * Common DHCP routines to manage DHCP packet data. + */ + +#include "DHCPCommon.h" + +/** Sets the given DHCP option in the DHCP packet's option list. This automatically moves the + * end of options terminator past the new option in the options list. + * + * \param[in,out] DHCPOptionList Pointer to the start of the DHCP packet's options list + * \param[in] Option DHCP option to add to the list + * \param[in] DataLen Size in bytes of the option data to add + * \param[in] OptionData Buffer where the option's data is to be sourced from + * + * \return Number of bytes added to the DHCP packet + */ +uint8_t DHCPCommon_SetOption(uint8_t* DHCPOptionList, + const uint8_t Option, + const uint8_t DataLen, + void* const OptionData) +{ + /* Skip through the DHCP options list until the terminator option is found */ + while (*DHCPOptionList != DHCP_OPTION_END) + DHCPOptionList += (DHCPOptionList[1] + 2); + + /* Overwrite the existing terminator with the new option, add a new terminator at the end of the list */ + DHCPOptionList[0] = Option; + DHCPOptionList[1] = DataLen; + memcpy(&DHCPOptionList[2], OptionData, DataLen); + DHCPOptionList[2 + DataLen] = DHCP_OPTION_END; + + /* Calculate the total number of bytes added to the outgoing packet */ + return (2 + DataLen); +} + +/** Retrieves the given option's data (if present) from the DHCP packet's options list. + * + * \param[in,out] DHCPOptionList Pointer to the start of the DHCP packet's options list + * \param[in] Option DHCP option to retrieve to the list + * \param[out] Destination Buffer where the option's data is to be written to if found + * + * \return Boolean true if the option was found in the DHCP packet's options list, false otherwise + */ +bool DHCPCommon_GetOption(const uint8_t* DHCPOptionList, + const uint8_t Option, + void* const Destination) +{ + /* Look through the incoming DHCP packet's options list for the requested option */ + while (*DHCPOptionList != DHCP_OPTION_END) + { + /* Check if the current DHCP option in the packet is the one requested */ + if (DHCPOptionList[0] == Option) + { + /* Copy request option's data to the destination buffer */ + memcpy(Destination, &DHCPOptionList[2], DHCPOptionList[1]); + + /* Indicate that the requested option data was successfully retrieved */ + return true; + } + + /* Skip to next DHCP option in the options list */ + DHCPOptionList += (DHCPOptionList[1] + 2); + } + + /* Requested option not found in the incoming packet's DHCP options list */ + return false; +} + +#endif diff --git a/Projects/Webserver/Lib/DHCPCommon.h b/Projects/Webserver/Lib/DHCPCommon.h new file mode 100644 index 0000000000..652db683cd --- /dev/null +++ b/Projects/Webserver/Lib/DHCPCommon.h @@ -0,0 +1,157 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author 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 common DHCP defines. + */ + +#ifndef _DHCP_COMMON_H_ +#define _DHCP_COMMON_H_ + + /* Includes: */ + #include + #include + #include + + #include + + /* Macros: */ + /** UDP listen port for a BOOTP server. */ + #define DHCP_SERVER_PORT 67 + + /** UDP listen port for a BOOTP client. */ + #define DHCP_CLIENT_PORT 68 + + /** BOOTP message type for a BOOTP REQUEST message. */ + #define DHCP_OP_BOOTREQUEST 0x01 + + /** BOOTP message type for a BOOTP REPLY message. */ + #define DHCP_OP_BOOTREPLY 0x02 + + /** BOOTP flag for a BOOTP broadcast message. */ + #define BOOTP_BROADCAST 0x8000 + + /** Magic DHCP cookie for a BOOTP message to identify it as a DHCP message. */ + #define DHCP_MAGIC_COOKIE 0x63538263 + + /** Unique transaction ID used to identify DHCP responses to the client. */ + #define DHCP_TRANSACTION_ID 0x13245466 + + /** DHCP message type for a DISCOVER message. */ + #define DHCP_DISCOVER 1 + + /** DHCP message type for an OFFER message. */ + #define DHCP_OFFER 2 + + /** DHCP message type for a REQUEST message. */ + #define DHCP_REQUEST 3 + + /** DHCP message type for a DECLINE message. */ + #define DHCP_DECLINE 4 + + /** DHCP message type for an ACK message. */ + #define DHCP_ACK 5 + + /** DHCP message type for a NAK message. */ + #define DHCP_NAK 6 + + /** DHCP message type for a RELEASE message. */ + #define DHCP_RELEASE 7 + + /** DHCP medium type for standard Ethernet. */ + #define DHCP_HTYPE_ETHERNET 1 + + /** DHCP message option for the network subnet mask. */ + #define DHCP_OPTION_SUBNET_MASK 1 + + /** DHCP message option for the network gateway IP. */ + #define DHCP_OPTION_ROUTER 3 + + /** DHCP message option for the network DNS server. */ + #define DHCP_OPTION_DNS_SERVER 6 + + /** DHCP message option for the requested client IP address. */ + #define DHCP_OPTION_REQ_IPADDR 50 + + /** DHCP message option for the IP address lease time. */ + #define DHCP_OPTION_LEASE_TIME 51 + + /** DHCP message option for the DHCP message type. */ + #define DHCP_OPTION_MSG_TYPE 53 + + /** DHCP message option for the DHCP server IP. */ + #define DHCP_OPTION_SERVER_ID 54 + + /** DHCP message option for the list of required options from the server. */ + #define DHCP_OPTION_REQ_LIST 55 + + /** DHCP message option for the options list terminator. */ + #define DHCP_OPTION_END 255 + + /* 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 */ + + uip_ipaddr_t ClientIP; /**< Client IP address, if already leased an IP */ + uip_ipaddr_t YourIP; /**< Client IP address */ + uip_ipaddr_t NextServerIP; /**< Legacy BOOTP protocol field, unused for DHCP */ + uip_ipaddr_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 */ + + uint8_t Options[]; /**< DHCP message options */ + } DHCP_Header_t; + + /* Function Prototypes: */ + uint8_t DHCPCommon_SetOption(uint8_t* DHCPOptionList, + const uint8_t Option, + const uint8_t DataLen, + void* const OptionData); + bool DHCPCommon_GetOption(const uint8_t* DHCPOptionList, + const uint8_t Option, + void* const Destination); + +#endif + diff --git a/Projects/Webserver/Lib/DHCPServerApp.c b/Projects/Webserver/Lib/DHCPServerApp.c new file mode 100644 index 0000000000..84c57d0a2e --- /dev/null +++ b/Projects/Webserver/Lib/DHCPServerApp.c @@ -0,0 +1,237 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author 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. +*/ + +#if defined(ENABLE_DHCP_SERVER) || defined(__DOXYGEN__) + +/** \file + * + * DHCP Server Application. When connected to the uIP stack, this will send IP configuration settings to a + * DHCP client on the network. + */ + +#define INCLUDE_FROM_DHCPSERVERAPP_C +#include "DHCPServerApp.h" + +struct uip_conn* BroadcastConnection; + +uint8_t LeasedIPs[255 / 8]; + +/** Initialization function for the DHCP server. */ +void DHCPServerApp_Init(void) +{ + /* Listen on port 67 for DHCP server connections from hosts */ + uip_listen(HTONS(DHCP_SERVER_PORT)); + + /* Create a new UDP connection to the DHCP server port for the DHCP solicitation */ + struct uip_udp_conn* BroadcastConnection = uip_udp_new(&uip_broadcast_addr, HTONS(DHCP_CLIENT_PORT)); + + /* If the connection was successfully created, bind it to the local DHCP client port */ + if (BroadcastConnection != NULL) + uip_udp_bind(BroadcastConnection, HTONS(DHCP_SERVER_PORT)); + + /* Set all IP addresses as unleased */ + memset(LeasedIPs, 0x00, sizeof(LeasedIPs)); +} + +/** uIP stack application callback for the DHCP server. This function must be called each time the TCP/IP stack + * needs a UDP packet to be processed. + */ +void DHCPServerApp_Callback(void) +{ + DHCP_Header_t* const AppData = (DHCP_Header_t*)uip_appdata; + uint16_t AppDataSize = 0; + + uint8_t DHCPMessageType; + if (!(DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &DHCPMessageType))) + return; + + uip_ipaddr_t Netmask, GatewayIPAddress; + struct uip_eth_addr RemoteMACAddress; + uint32_t TransactionID; + + memcpy(&RemoteMACAddress, &AppData->ClientHardwareAddress, sizeof(struct uip_eth_addr)); + uip_getnetmask(&Netmask); + uip_getdraddr(&GatewayIPAddress); + TransactionID = AppData->TransactionID; + + switch (DHCPMessageType) + { + case DHCP_DISCOVER: + AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_OFFER, &RemoteMACAddress, TransactionID); + + AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK, + sizeof(uip_ipaddr_t), &Netmask); + AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_ROUTER, + sizeof(uip_ipaddr_t), &GatewayIPAddress); + + /* Send the DHCP OFFER packet */ + uip_poll_conn(BroadcastConnection); + memcpy(&uip_udp_conn->ripaddr, &uip_broadcast_addr, sizeof(uip_ipaddr_t)); + uip_udp_send(AppDataSize); + + break; + case DHCP_REQUEST: + if (!(DHCPServerApp_CheckIfIPLeased(&AppData->YourIP))) + { + AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_ACK, &RemoteMACAddress, TransactionID); + + AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK, + sizeof(uip_ipaddr_t), &Netmask); + AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_ROUTER, + sizeof(uip_ipaddr_t), &GatewayIPAddress); + + DHCPServerApp_LeaseIP(&AppData->YourIP); + } + else + { + AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_NAK, &RemoteMACAddress, TransactionID); + } + + /* Send the DHCP ACK or NAK packet */ + uip_poll_conn(BroadcastConnection); + memcpy(&uip_udp_conn->ripaddr, &uip_broadcast_addr, sizeof(uip_ipaddr_t)); + uip_udp_send(AppDataSize); + + break; + case DHCP_RELEASE: + /* Mark the IP address as released in the allocation table */ + DHCPServerApp_UnleaseIP(&uip_udp_conn->ripaddr); + break; + } +} + +/** Fills the DHCP packet response with the appropriate BOOTP header for DHCP. This fills out all the required + * fields, leaving only the additional DHCP options to be added to the packet before it is sent to the DHCP client. + * + * \param[out] DHCPHeader Location in the packet buffer where the BOOTP header should be written to + * \param[in] DHCPMessageType DHCP Message type, such as DHCP_DISCOVER + * \param[in] ClientHardwareAddress Client MAC address the created transaction should be directed to + * \param[in] TransactionID Transaction ID the created transaction should be associated with + * + * \return Size in bytes of the created DHCP packet + */ +static uint16_t DHCPServerApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader, + const uint8_t DHCPMessageType, + struct uip_eth_addr* ClientHardwareAddress, + uint32_t TransactionID) +{ + /* Erase existing packet data so that we start will all 0x00 DHCP header data */ + memset(DHCPHeader, 0, sizeof(DHCP_Header_t)); + + DHCPHeader->Operation = DHCPMessageType; + DHCPHeader->HardwareType = DHCP_HTYPE_ETHERNET; + DHCPHeader->HardwareAddressLength = sizeof(MACAddress); + DHCPHeader->Hops = 0; + DHCPHeader->TransactionID = TransactionID; + DHCPHeader->ElapsedSeconds = 0; + DHCPHeader->Flags = 0; + memcpy(&DHCPHeader->NextServerIP, &uip_hostaddr, sizeof(uip_ipaddr_t)); + if (uip_ipaddr_cmp(&DHCPHeader->YourIP, &uip_all_zeroes_addr)) + DHCPServerApp_GetUnleasedIP(&DHCPHeader->YourIP); + memcpy(&DHCPHeader->ClientHardwareAddress, ClientHardwareAddress, sizeof(struct uip_eth_addr)); + DHCPHeader->Cookie = DHCP_MAGIC_COOKIE; + + /* Add a DHCP message type and terminator options to the start of the DHCP options field */ + DHCPHeader->Options[0] = DHCP_OPTION_MSG_TYPE; + DHCPHeader->Options[1] = 1; + DHCPHeader->Options[2] = DHCPMessageType; + DHCPHeader->Options[3] = DHCP_OPTION_END; + + /* Calculate the total number of bytes added to the outgoing packet */ + return (sizeof(DHCP_Header_t) + 4); +} + +/** Checks to see if the nominated IP address has already been allocated to a client. + * + * \param[in] IPAddress IP Address whose lease status should be checked + * + * \pre The IP address must be within the same /24 subnet as the virtual webserver. + * + * \return Boolean true if the IP has already been leased to a client, false otherwise. + */ +static bool DHCPServerApp_CheckIfIPLeased(uip_ipaddr_t* IPAddress) +{ + uint8_t Byte = (IPAddress->u8[3] / 8); + uint8_t Mask = (1 << (IPAddress->u8[3] % 8)); + + if (!(IPAddress->u8[3] == uip_hostaddr.u8[3]) && !(LeasedIPs[Byte] & Mask)) + return false; + else + return true; +} + +/** Retrieves the next unleased IP in the IP address pool. + * + * \param[out] NewIPAddress Location where the generated IP Address should be stored + */ +static void DHCPServerApp_GetUnleasedIP(uip_ipaddr_t* NewIPAddress) +{ + uip_ipaddr_copy(NewIPAddress, &uip_hostaddr); + + for (uint8_t IP = 1; IP < 254; IP++) + { + NewIPAddress->u8[3] = IP; + + if (!(DHCPServerApp_CheckIfIPLeased(NewIPAddress))) + return; + } +} + +/** Marks the given IP Address as leased in the address pool, so that it will not be + * allocated to another client unless it is first released. + * + * \param[in] IPAddress IP Address to mark as leased + * + * \pre The IP address must be within the same /24 subnet as the virtual webserver. + */ +static void DHCPServerApp_LeaseIP(uip_ipaddr_t* IPAddress) +{ + uint8_t Byte = (IPAddress->u8[3] / 8); + uint8_t Mask = (1 << (IPAddress->u8[3] % 8)); + + LeasedIPs[Byte] |= Mask; +} + +/** Marks the given IP Address as not leased in the address pool, so that it can be + * allocated to another client upon request. + * + * \param[in] IPAddress IP Address to mark as not leased + * + * \pre The IP address must be within the same /24 subnet as the virtual webserver. + */ +static void DHCPServerApp_UnleaseIP(uip_ipaddr_t* IPAddress) +{ + uint8_t Byte = (IPAddress->u8[3] / 8); + uint8_t Mask = (1 << (IPAddress->u8[3] % 8)); + + LeasedIPs[Byte] &= ~Mask; +} +#endif + diff --git a/Projects/Webserver/Lib/DHCPServerApp.h b/Projects/Webserver/Lib/DHCPServerApp.h new file mode 100644 index 0000000000..e70869588f --- /dev/null +++ b/Projects/Webserver/Lib/DHCPServerApp.h @@ -0,0 +1,62 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2011. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author 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 DHCPServerApp.c. + */ + +#ifndef _DHCPSERVER_APP_H_ +#define _DHCPSERVER_APP_H_ + + /* Includes: */ + #include + + #include + + #include "../Webserver.h" + #include "DHCPCommon.h" + + /* Function Prototypes: */ + void DHCPServerApp_Init(void); + void DHCPServerApp_Callback(void); + + #if defined(INCLUDE_FROM_DHCPSERVERAPP_C) + static uint16_t DHCPServerApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader, + const uint8_t DHCPMessageType, + struct uip_eth_addr* ClientHardwareAddress, + uint32_t TransactionID); + static bool DHCPServerApp_CheckIfIPLeased(uip_ipaddr_t* IPAddress); + static void DHCPServerApp_GetUnleasedIP(uip_ipaddr_t* NewIPAddress); + static void DHCPServerApp_LeaseIP(uip_ipaddr_t* IPAddress); + static void DHCPServerApp_UnleaseIP(uip_ipaddr_t* IPAddress); + #endif +#endif + diff --git a/Projects/Webserver/Lib/HTTPServerApp.c b/Projects/Webserver/Lib/HTTPServerApp.c index 8548045dfc..6822b270d6 100644 --- a/Projects/Webserver/Lib/HTTPServerApp.c +++ b/Projects/Webserver/Lib/HTTPServerApp.c @@ -181,7 +181,7 @@ static void HTTPServerApp_OpenRequestedFile(void) } /* Copy over the requested filename */ - strncpy(AppState->HTTPServer.FileName, &RequestedFileName[1], (sizeof(AppState->HTTPServer.FileName) - 1)); + strncpy(AppState->HTTPServer.FileName, &RequestedFileName[1], sizeof(AppState->HTTPServer.FileName)); /* Ensure filename is null-terminated */ AppState->HTTPServer.FileName[sizeof(AppState->HTTPServer.FileName) - 1] = 0x00; @@ -190,11 +190,11 @@ static void HTTPServerApp_OpenRequestedFile(void) uint8_t FileNameLen = strlen(AppState->HTTPServer.FileName); /* If the URI is a directory, append the default filename */ - if (AppState->HTTPServer.FileName[FileNameLen - 1] == '/') + if ((AppState->HTTPServer.FileName[FileNameLen - 1] == '/') || !(FileNameLen)) { strncpy_P(&AppState->HTTPServer.FileName[FileNameLen], DefaultDirFileName, (sizeof(AppState->HTTPServer.FileName) - FileNameLen)); - + /* Ensure altered filename is still null-terminated */ AppState->HTTPServer.FileName[sizeof(AppState->HTTPServer.FileName) - 1] = 0x00; } diff --git a/Projects/Webserver/Lib/uIPManagement.c b/Projects/Webserver/Lib/uIPManagement.c index a99e8be938..59045c06a3 100644 --- a/Projects/Webserver/Lib/uIPManagement.c +++ b/Projects/Webserver/Lib/uIPManagement.c @@ -61,22 +61,49 @@ void uIPManagement_Init(void) /* uIP Stack Initialization */ uip_init(); uip_arp_init(); - uip_setethaddr(MACAddress); /* DHCP/Server IP Settings Initialization */ - #if defined(ENABLE_DHCP_CLIENT) - HaveIPConfiguration = false; - DHCPClientApp_Init(); - #else - HaveIPConfiguration = true; - uip_ipaddr_t IPAddress, Netmask, GatewayIPAddress; - uip_ipaddr(&IPAddress, DEVICE_IP_ADDRESS[0], DEVICE_IP_ADDRESS[1], DEVICE_IP_ADDRESS[2], DEVICE_IP_ADDRESS[3]); - uip_ipaddr(&Netmask, DEVICE_NETMASK[0], DEVICE_NETMASK[1], DEVICE_NETMASK[2], DEVICE_NETMASK[3]); - uip_ipaddr(&GatewayIPAddress, DEVICE_GATEWAY[0], DEVICE_GATEWAY[1], DEVICE_GATEWAY[2], DEVICE_GATEWAY[3]); - uip_sethostaddr(&IPAddress); - uip_setnetmask(&Netmask); - uip_setdraddr(&GatewayIPAddress); - #endif + if (USB_CurrentMode == USB_MODE_Device) + { + MACAddress.addr[0] = SERVER_MAC_ADDRESS[0]; + MACAddress.addr[1] = SERVER_MAC_ADDRESS[1]; + MACAddress.addr[2] = SERVER_MAC_ADDRESS[2]; + MACAddress.addr[3] = SERVER_MAC_ADDRESS[3]; + MACAddress.addr[4] = SERVER_MAC_ADDRESS[4]; + MACAddress.addr[5] = SERVER_MAC_ADDRESS[5]; + + #if defined(ENABLE_DHCP_SERVER) + DHCPServerApp_Init(); + #endif + + HaveIPConfiguration = true; + uip_ipaddr_t IPAddress, Netmask, GatewayIPAddress; + uip_ipaddr(&IPAddress, DEVICE_IP_ADDRESS[0], DEVICE_IP_ADDRESS[1], DEVICE_IP_ADDRESS[2], DEVICE_IP_ADDRESS[3]); + uip_ipaddr(&Netmask, DEVICE_NETMASK[0], DEVICE_NETMASK[1], DEVICE_NETMASK[2], DEVICE_NETMASK[3]); + uip_ipaddr(&GatewayIPAddress, DEVICE_GATEWAY[0], DEVICE_GATEWAY[1], DEVICE_GATEWAY[2], DEVICE_GATEWAY[3]); + uip_sethostaddr(&IPAddress); + uip_setnetmask(&Netmask); + uip_setdraddr(&GatewayIPAddress); + } + else + { + #if defined(ENABLE_DHCP_CLIENT) + HaveIPConfiguration = false; + DHCPClientApp_Init(); + #else + HaveIPConfiguration = true; + uip_ipaddr_t IPAddress, Netmask, GatewayIPAddress; + uip_ipaddr(&IPAddress, DEVICE_IP_ADDRESS[0], DEVICE_IP_ADDRESS[1], DEVICE_IP_ADDRESS[2], DEVICE_IP_ADDRESS[3]); + uip_ipaddr(&Netmask, DEVICE_NETMASK[0], DEVICE_NETMASK[1], DEVICE_NETMASK[2], DEVICE_NETMASK[3]); + uip_ipaddr(&GatewayIPAddress, DEVICE_GATEWAY[0], DEVICE_GATEWAY[1], DEVICE_GATEWAY[2], DEVICE_GATEWAY[3]); + uip_sethostaddr(&IPAddress); + uip_setnetmask(&Netmask); + uip_setdraddr(&GatewayIPAddress); + #endif + } + + /* Virtual Webserver Ethernet Address Configuration */ + uip_setethaddr(MACAddress); /* HTTP Webserver Initialization */ HTTPServerApp_Init(); @@ -92,7 +119,8 @@ void uIPManagement_Init(void) */ void uIPManagement_ManageNetwork(void) { - if ((USB_CurrentMode == USB_MODE_Host) && (USB_HostState == HOST_STATE_Configured)) + if (((USB_CurrentMode == USB_MODE_Host) && (USB_HostState == HOST_STATE_Configured)) || + ((USB_CurrentMode == USB_MODE_Device) && (USB_DeviceState == DEVICE_STATE_Configured))) { uIPManagement_ProcessIncomingPacket(); uIPManagement_ManageConnections(); @@ -126,24 +154,46 @@ void uIPManagement_UDPCallback(void) /* Call the correct UDP application based on the port number the connection is listening on */ switch (uip_udp_conn->lport) { - case HTONS(DHCPC_CLIENT_PORT): + #if defined(ENABLE_DHCP_CLIENT) + case HTONS(DHCP_CLIENT_PORT): DHCPClientApp_Callback(); break; + #endif + #if defined(ENABLE_DHCP_SERVER) + case HTONS(DHCP_SERVER_PORT): + DHCPServerApp_Callback(); + break; + #endif } } /** Processes Incoming packets to the server from the connected RNDIS device, creating responses as needed. */ static void uIPManagement_ProcessIncomingPacket(void) { - /* If no packet received, exit processing routine */ - if (!(RNDIS_Host_IsPacketReceived(&Ethernet_RNDIS_Interface))) - return; - - LEDs_SetAllLEDs(LEDMASK_USB_BUSY); + /* Determine which USB mode the system is currently initialised in */ + if (USB_CurrentMode == USB_MODE_Device) + { + /* If no packet received, exit processing routine */ + if (!(RNDIS_Device_IsPacketReceived(&Ethernet_RNDIS_Interface_Device))) + return; + + LEDs_SetAllLEDs(LEDMASK_USB_BUSY); - /* Read the Incoming packet straight into the UIP packet buffer */ - RNDIS_Host_ReadPacket(&Ethernet_RNDIS_Interface, uip_buf, &uip_len); + /* Read the Incoming packet straight into the UIP packet buffer */ + RNDIS_Device_ReadPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, &uip_len); + } + else + { + /* If no packet received, exit processing routine */ + if (!(RNDIS_Host_IsPacketReceived(&Ethernet_RNDIS_Interface_Host))) + return; + + LEDs_SetAllLEDs(LEDMASK_USB_BUSY); + /* Read the Incoming packet straight into the UIP packet buffer */ + RNDIS_Host_ReadPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, &uip_len); + } + /* If the packet contains an Ethernet frame, process it */ if (uip_len > 0) { diff --git a/Projects/Webserver/Lib/uIPManagement.h b/Projects/Webserver/Lib/uIPManagement.h index 7409eab90c..c42e132253 100644 --- a/Projects/Webserver/Lib/uIPManagement.h +++ b/Projects/Webserver/Lib/uIPManagement.h @@ -45,12 +45,13 @@ #include #include "Lib/DHCPClientApp.h" + #include "Lib/DHCPServerApp.h" #include "Lib/HTTPServerApp.h" #include "Lib/TELNETServerApp.h" /* Macros: */ /** IP address that the webserver should use once connected to a RNDIS device (when DHCP is disabled). */ - #define DEVICE_IP_ADDRESS (uint8_t[]){192, 168, 1, 10} + #define DEVICE_IP_ADDRESS (uint8_t[]){10, 0, 0, 2} /** Netmask that the webserver should once connected to a RNDIS device (when DHCP is disabled). */ #define DEVICE_NETMASK (uint8_t[]){255, 255, 255, 0} @@ -58,7 +59,13 @@ /** IP address of the default gateway the webserver should use when routing outside the local subnet * (when DHCP is disabled). */ - #define DEVICE_GATEWAY (uint8_t[]){192, 168, 1, 1} + #define DEVICE_GATEWAY (uint8_t[]){10, 0, 0, 1} + + /** Ethernet MAC address of the virtual webserver. When in device RNDIS mode, the virtual webserver requires + * a unique MAC address that it can use when sending packets to the RNDIS adapter, which contains a seperate + * MAC address as set in the RNDIS class driver configuration structure. + */ + #define SERVER_MAC_ADDRESS (uint8_t[]){1, 0, 1, 0, 1, 0} /* External Variables: */ extern struct uip_eth_addr MACAddress; diff --git a/Projects/Webserver/Lib/uip/uip-split.c b/Projects/Webserver/Lib/uip/uip-split.c index 87dbd7e1f2..5222a05b63 100644 --- a/Projects/Webserver/Lib/uip/uip-split.c +++ b/Projects/Webserver/Lib/uip/uip-split.c @@ -83,7 +83,10 @@ uip_split_output(void) #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else - RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len); + if (USB_CurrentMode == USB_MODE_Device) + RNDIS_Device_SendPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, uip_len); + else + RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, uip_len); #endif /* UIP_CONF_IPV6 */ /* Now, create the second packet. To do this, it is not enough to @@ -124,7 +127,10 @@ uip_split_output(void) #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else - RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len); + if (USB_CurrentMode == USB_MODE_Device) + RNDIS_Device_SendPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, uip_len); + else + RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, uip_len); #endif /* UIP_CONF_IPV6 */ return; } @@ -134,7 +140,10 @@ uip_split_output(void) #if UIP_CONF_IPV6 tcpip_ipv6_output(); #else - RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len); + if (USB_CurrentMode == USB_MODE_Device) + RNDIS_Device_SendPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, uip_len); + else + RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, uip_len); #endif /* UIP_CONF_IPV6 */ } diff --git a/Projects/Webserver/Lib/uip/uip.c b/Projects/Webserver/Lib/uip/uip.c index afa19f750d..94171adad5 100644 --- a/Projects/Webserver/Lib/uip/uip.c +++ b/Projects/Webserver/Lib/uip/uip.c @@ -904,10 +904,12 @@ uip_process(u8_t flag) #if UIP_BROADCAST DEBUG_PRINTF("UDP IP checksum 0x%04x\n", uip_ipchksum()); if(BUF->proto == UIP_PROTO_UDP && - uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr) - /*&& - uip_ipchksum() == 0xffff*/) { - goto udp_input; + uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr)) + { + if (uip_ipaddr_cmp(&BUF->srcipaddr, &uip_all_zeroes_addr)) + uip_ipaddr_copy(&BUF->srcipaddr, &uip_broadcast_addr); + + goto udp_input; } #endif /* UIP_BROADCAST */ diff --git a/Projects/Webserver/USBDeviceMode.c b/Projects/Webserver/USBDeviceMode.c index 44bae33d20..f5856ebbdc 100644 --- a/Projects/Webserver/USBDeviceMode.c +++ b/Projects/Webserver/USBDeviceMode.c @@ -36,6 +36,33 @@ #include "USBDeviceMode.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_Device_t Ethernet_RNDIS_Interface_Device = + { + .Config = + { + .ControlInterfaceNumber = 0, + + .DataINEndpointNumber = CDC_TX_EPNUM, + .DataINEndpointSize = CDC_TXRX_EPSIZE, + .DataINEndpointDoubleBank = false, + + .DataOUTEndpointNumber = CDC_RX_EPNUM, + .DataOUTEndpointSize = CDC_TXRX_EPSIZE, + .DataOUTEndpointDoubleBank = false, + + .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM, + .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE, + .NotificationEndpointDoubleBank = false, + + .AdapterVendorDescription = "LUFA RNDIS Adapter", + .AdapterMACAddress = {{0x02, 0x00, 0x02, 0x00, 0x02, 0x00}}, + }, + }; + /** LUFA Mass Storage Class driver interface configuration and state information. This structure is * passed to all Mass Storage Class driver functions, so that multiple instances of the same class * within a device can be differentiated from one another. @@ -44,15 +71,15 @@ USB_ClassInfo_MS_Device_t Disk_MS_Interface = { .Config = { - .InterfaceNumber = 0, + .InterfaceNumber = 2, .DataINEndpointNumber = MASS_STORAGE_IN_EPNUM, .DataINEndpointSize = MASS_STORAGE_IO_EPSIZE, - .DataINEndpointDoubleBank = true, + .DataINEndpointDoubleBank = false, .DataOUTEndpointNumber = MASS_STORAGE_OUT_EPNUM, .DataOUTEndpointSize = MASS_STORAGE_IO_EPSIZE, - .DataOUTEndpointDoubleBank = true, + .DataOUTEndpointDoubleBank = false, .TotalLUNs = 1, }, @@ -67,6 +94,9 @@ void USBDeviceMode_USBTask(void) if (USB_CurrentMode != USB_MODE_Device) return; + uIPManagement_ManageNetwork(); + + RNDIS_Device_USBTask(&Ethernet_RNDIS_Interface_Device); MS_Device_USBTask(&Disk_MS_Interface); } @@ -74,6 +104,8 @@ void USBDeviceMode_USBTask(void) void EVENT_USB_Device_Connect(void) { LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); + + uIPManagement_Init(); } /** Event handler for the library USB Disconnection event. */ @@ -87,6 +119,7 @@ void EVENT_USB_Device_ConfigurationChanged(void) { bool ConfigSuccess = true; + ConfigSuccess &= RNDIS_Device_ConfigureEndpoints(&Ethernet_RNDIS_Interface_Device); ConfigSuccess &= MS_Device_ConfigureEndpoints(&Disk_MS_Interface); LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR); @@ -95,6 +128,7 @@ void EVENT_USB_Device_ConfigurationChanged(void) /** Event handler for the library USB Control Request reception event. */ void EVENT_USB_Device_ControlRequest(void) { + RNDIS_Device_ProcessControlRequest(&Ethernet_RNDIS_Interface_Device); MS_Device_ProcessControlRequest(&Disk_MS_Interface); } diff --git a/Projects/Webserver/USBDeviceMode.h b/Projects/Webserver/USBDeviceMode.h index 910dee0e71..02d522d658 100644 --- a/Projects/Webserver/USBDeviceMode.h +++ b/Projects/Webserver/USBDeviceMode.h @@ -40,9 +40,13 @@ #include #include "Webserver.h" + #include "Lib/uIPManagement.h" #include "Descriptors.h" #include "Lib/SCSI.h" + /* External Variables: */ + extern USB_ClassInfo_RNDIS_Device_t Ethernet_RNDIS_Interface_Device; + /* Function Prototypes: */ void USBDeviceMode_USBTask(void); diff --git a/Projects/Webserver/USBHostMode.c b/Projects/Webserver/USBHostMode.c index 941ebba8df..1fcec3491b 100644 --- a/Projects/Webserver/USBHostMode.c +++ b/Projects/Webserver/USBHostMode.c @@ -40,7 +40,7 @@ * 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_Host_t Ethernet_RNDIS_Interface = +USB_ClassInfo_RNDIS_Host_t Ethernet_RNDIS_Interface_Host = { .Config = { @@ -82,7 +82,7 @@ void USBHostMode_USBTask(void) break; } - if (RNDIS_Host_ConfigurePipes(&Ethernet_RNDIS_Interface, + if (RNDIS_Host_ConfigurePipes(&Ethernet_RNDIS_Interface_Host, ConfigDescriptorSize, ConfigDescriptorData) != RNDIS_ENUMERROR_NoError) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); @@ -97,7 +97,7 @@ void USBHostMode_USBTask(void) break; } - if (RNDIS_Host_InitializeDevice(&Ethernet_RNDIS_Interface) != HOST_SENDCONTROL_Successful) + if (RNDIS_Host_InitializeDevice(&Ethernet_RNDIS_Interface_Host) != HOST_SENDCONTROL_Successful) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; @@ -105,7 +105,7 @@ void USBHostMode_USBTask(void) } uint32_t PacketFilter = (REMOTE_NDIS_PACKET_DIRECTED | REMOTE_NDIS_PACKET_BROADCAST); - if (RNDIS_Host_SetRNDISProperty(&Ethernet_RNDIS_Interface, OID_GEN_CURRENT_PACKET_FILTER, + if (RNDIS_Host_SetRNDISProperty(&Ethernet_RNDIS_Interface_Host, OID_GEN_CURRENT_PACKET_FILTER, &PacketFilter, sizeof(PacketFilter)) != HOST_SENDCONTROL_Successful) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); @@ -113,7 +113,7 @@ void USBHostMode_USBTask(void) break; } - if (RNDIS_Host_QueryRNDISProperty(&Ethernet_RNDIS_Interface, OID_802_3_CURRENT_ADDRESS, + if (RNDIS_Host_QueryRNDISProperty(&Ethernet_RNDIS_Interface_Host, OID_802_3_CURRENT_ADDRESS, &MACAddress, sizeof(MACAddress)) != HOST_SENDCONTROL_Successful) { LEDs_SetAllLEDs(LEDMASK_USB_ERROR); @@ -133,7 +133,7 @@ void USBHostMode_USBTask(void) break; } - RNDIS_Host_USBTask(&Ethernet_RNDIS_Interface); + RNDIS_Host_USBTask(&Ethernet_RNDIS_Interface_Host); } /** Event handler for the USB_DeviceAttached event. This indicates that a device has been attached to the host, and diff --git a/Projects/Webserver/USBHostMode.h b/Projects/Webserver/USBHostMode.h index fa914013fc..bb71070735 100644 --- a/Projects/Webserver/USBHostMode.h +++ b/Projects/Webserver/USBHostMode.h @@ -43,7 +43,7 @@ #include "Lib/uIPManagement.h" /* External Variables: */ - extern USB_ClassInfo_RNDIS_Host_t Ethernet_RNDIS_Interface; + extern USB_ClassInfo_RNDIS_Host_t Ethernet_RNDIS_Interface_Host; /* Function Prototypes: */ void USBHostMode_USBTask(void); diff --git a/Projects/Webserver/Webserver.aps b/Projects/Webserver/Webserver.aps index aaf3114f98..4c47287d03 100644 --- a/Projects/Webserver/Webserver.aps +++ b/Projects/Webserver/Webserver.aps @@ -1 +1 @@ -Webserver13-Jul-2010 14:36:1913-Jul-2010 14:37:18241013-Jul-2010 14:36:1944, 18, 0, 685AVR GCCWebserver.elfC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\falseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31000Descriptors.cUSBDeviceMode.cUSBHostMode.cWebserver.cLib\DataflashManager.cLib\DHCPClientApp.cLib\HTTPServerApp.cLib\SCSI.cLib\TELNETServerApp.cLib\uIPManagement.cDescriptors.hUSBDeviceMode.hUSBHostMode.hWebserver.hLib\DataflashManager.hLib\DHCPClientApp.hLib\HTTPServerApp.hLib\SCSI.hLib\TELNETServerApp.hLib\uIPManagement.hmakefiledefaultYESmakefileatmega128111Webserver.elfdefault\1-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enumsdefault1C:\WinAVR-20100110\bin\avr-gcc.exeC:\WinAVR-20100110\utils\bin\make.exeC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Descriptors.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\USBDeviceMode.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\USBHostMode.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Webserver.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\DataflashManager.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\DHCPClientApp.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\HTTPServerApp.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\SCSI.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\TELNETServerApp.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\uIPManagement.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Descriptors.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\USBDeviceMode.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\USBHostMode.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Webserver.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\DataflashManager.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\DHCPClientApp.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\HTTPServerApp.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\SCSI.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\TELNETServerApp.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\uIPManagement.c +Webserver13-Jul-2010 14:36:1913-Jul-2010 14:37:18241013-Jul-2010 14:36:1944, 18, 0, 685AVR GCCWebserver.elfC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\falseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31000Descriptors.cUSBDeviceMode.cUSBHostMode.cWebserver.cLib\DataflashManager.cLib\DHCPClientApp.cLib\DHCPServerApp.cLib\DHCPCommon.cLib\HTTPServerApp.cLib\SCSI.cLib\TELNETServerApp.cLib\uIPManagement.cDescriptors.hUSBDeviceMode.hUSBHostMode.hWebserver.hLib\DataflashManager.hLib\DHCPClientApp.hLib\DHCPServerApp.hLib\DHCPCommon.hLib\HTTPServerApp.hLib\SCSI.hLib\TELNETServerApp.hLib\uIPManagement.hmakefiledefaultYESmakefileatmega128111Webserver.elfdefault\1-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enumsdefault1C:\WinAVR-20100110\bin\avr-gcc.exeC:\WinAVR-20100110\utils\bin\make.exeC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Descriptors.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\USBDeviceMode.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\USBHostMode.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Webserver.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\DataflashManager.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\DHCPClientApp.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\HTTPServerApp.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\SCSI.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\TELNETServerApp.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\uIPManagement.hC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Descriptors.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\USBDeviceMode.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\USBHostMode.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Webserver.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\DataflashManager.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\DHCPClientApp.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\HTTPServerApp.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\SCSI.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\TELNETServerApp.cC:\Users\Dean\Documents\Electronics\Projects\WORK\LUFAWORK\Projects\Webserver\Lib\uIPManagement.c diff --git a/Projects/Webserver/Webserver.txt b/Projects/Webserver/Webserver.txt index ddb06590aa..32bdb597a3 100644 --- a/Projects/Webserver/Webserver.txt +++ b/Projects/Webserver/Webserver.txt @@ -52,10 +52,12 @@ * demonstrates how the libraries can be combined into a robust network enabled application, with the addition of a RNDIS * network device. * - * To use this project, plug the USB AVR into a computer, so that it enumerates as a standard Mass Storage device. Load - * HTML files onto the disk, so that they can be served out to clients -- the default file to serve should be called + * To use this project, plug the USB AVR into a computer, so that it enumerates as a standard Mass Storage and RNDIS composite + * device. Load HTML files onto the disk, so that they can be served out to clients -- the default file to serve should be called * index.htm. Filenames must be in 8.3 format for them to be retrieved correctly by the webserver, and the total - * requested file path must be equal to or less than the maximum URI length (\see \ref Sec_Options). + * requested file path must be equal to or less than the maximum URI length (\see \ref Sec_Options). Supply the included INF + * file when requested on Windows machines to enable the RNDIS interface, and allow the files to be viewed on a standard web-browser + * using the IP address 10.0.0.2. * * When attached to a RNDIS class device, such as a USB (desktop) modem, the system will enumerate the device, set the * appropriate parameters needed for connectivity and begin listening for new HTTP connections on port 80 and TELNET @@ -89,6 +91,11 @@ * When defined, this enables the DHCP client for dynamic IP allocation of the network settings from a DHCP server. * * + * ENABLE_DHCP_SERVER + * Makefile LUFA_OPTS + * When defined, this enables the DHCP server for dynamic IP allocation of the network settings to a DHCP client. + * + * * DEVICE_IP_ADDRESS * Lib/uIPManagement.h * IP address that the webserver should use when connected to a RNDIS device (when ENABLE_DHCP_CLIENT is not defined). diff --git a/Projects/Webserver/makefile b/Projects/Webserver/makefile index bba6d057b2..1602b2ff48 100644 --- a/Projects/Webserver/makefile +++ b/Projects/Webserver/makefile @@ -128,22 +128,25 @@ LUFA_OPTS += -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENAB LUFA_OPTS += -D INTERRUPT_CONTROL_ENDPOINT LUFA_OPTS += -D ENABLE_DHCP_CLIENT +LUFA_OPTS += -D ENABLE_DHCP_SERVER LUFA_OPTS += -D ENABLE_TELNET_SERVER LUFA_OPTS += -D MAX_URI_LENGTH=50 -LUFA_OPTS += -D UIP_CONF_UDP="defined(ENABLE_DHCP_CLIENT)" + +LUFA_OPTS += -D UIP_CONF_UDP="defined(ENABLE_DHCP_CLIENT) || defined(ENABLE_DHCP_SERVER)" +LUFA_OPTS += -D UIP_CONF_BROADCAST=1 LUFA_OPTS += -D UIP_CONF_TCP=1 LUFA_OPTS += -D UIP_CONF_UDP_CONNS=1 LUFA_OPTS += -D UIP_CONF_MAX_CONNECTIONS=3 LUFA_OPTS += -D UIP_CONF_MAX_LISTENPORTS=5 -LUFA_OPTS += -D UIP_URGDATA=0 LUFA_OPTS += -D UIP_CONF_BUFFER_SIZE=1514 -LUFA_OPTS += -D UIP_ARCH_CHKSUM=0 LUFA_OPTS += -D UIP_CONF_LL_802154=0 LUFA_OPTS += -D UIP_CONF_LL_80211=0 LUFA_OPTS += -D UIP_CONF_ROUTER=0 LUFA_OPTS += -D UIP_CONF_ICMP6=0 -LUFA_OPTS += -D UIP_ARCH_ADD32=0 LUFA_OPTS += -D UIP_CONF_ICMP_DEST_UNREACH=1 +LUFA_OPTS += -D UIP_URGDATA=0 +LUFA_OPTS += -D UIP_ARCH_CHKSUM=0 +LUFA_OPTS += -D UIP_ARCH_ADD32=0 LUFA_OPTS += -D UIP_NEIGHBOR_CONF_ADDRTYPE=0 @@ -159,7 +162,9 @@ SRC = $(TARGET).c \ Lib/SCSI.c \ Lib/DataflashManager.c \ Lib/uIPManagement.c \ + Lib/DHCPCommon.c \ Lib/DHCPClientApp.c \ + Lib/DHCPServerApp.c \ Lib/HTTPServerApp.c \ Lib/TELNETServerApp.c \ Lib/uip/uip.c \