Add svn:eol-style property to source files, so that the line endings are correctly converted to the target system's native end of line style.
This commit is contained in:
parent
e331b531c6
commit
071e02c6b6
839 changed files with 274562 additions and 274562 deletions
|
@ -1,264 +1,264 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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(__DOXYGEN__)
|
||||
|
||||
/** \file
|
||||
*
|
||||
* DHCP Client Application. When connected to the uIP stack, this will retrieve IP configuration settings from the
|
||||
* DHCP server on the network.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_DHCPCLIENTAPP_C
|
||||
#include "DHCPClientApp.h"
|
||||
|
||||
/** Initialization function for the DHCP client. */
|
||||
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));
|
||||
|
||||
/* 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));
|
||||
|
||||
/* Set the initial client state */
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;
|
||||
|
||||
/* Set timeout period to half a second for a DHCP server to respond */
|
||||
timer_set(&AppState->DHCPClient.Timeout, CLOCK_SECOND / 2);
|
||||
}
|
||||
}
|
||||
|
||||
/** uIP stack application callback for the DHCP client. This function must be called each time the TCP/IP stack
|
||||
* needs a UDP packet to be processed.
|
||||
*/
|
||||
void DHCPClientApp_Callback(void)
|
||||
{
|
||||
uip_udp_appstate_t* const AppState = &uip_udp_conn->appstate;
|
||||
DHCP_Header_t* const AppData = (DHCP_Header_t*)uip_appdata;
|
||||
uint16_t AppDataSize = 0;
|
||||
|
||||
switch (AppState->DHCPClient.CurrentState)
|
||||
{
|
||||
case DHCP_STATE_SendDiscover:
|
||||
/* Clear all DHCP settings, reset client IP address */
|
||||
memset(&AppState->DHCPClient.DHCPOffer_Data, 0x00, sizeof(AppState->DHCPClient.DHCPOffer_Data));
|
||||
uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);
|
||||
|
||||
/* Fill out the DHCP response header */
|
||||
AppDataSize += DHCPClientApp_FillDHCPHeader(AppData, DHCP_DISCOVER, AppState);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Send the DHCP DISCOVER packet */
|
||||
uip_udp_send(AppDataSize);
|
||||
|
||||
/* Reset the timeout timer, progress to next state */
|
||||
timer_reset(&AppState->DHCPClient.Timeout);
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_WaitForOffer;
|
||||
|
||||
break;
|
||||
case DHCP_STATE_WaitForOffer:
|
||||
if (!(uip_newdata()))
|
||||
{
|
||||
/* Check if the DHCP timeout period has expired while waiting for a response */
|
||||
if (timer_expired(&AppState->DHCPClient.Timeout))
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t OfferResponse_MessageType;
|
||||
if ((AppData->TransactionID == DHCP_TRANSACTION_ID) &&
|
||||
DHCPClientApp_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);
|
||||
|
||||
timer_reset(&AppState->DHCPClient.Timeout);
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_SendRequest;
|
||||
}
|
||||
|
||||
break;
|
||||
case DHCP_STATE_SendRequest:
|
||||
/* Fill out the DHCP response header */
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Send the DHCP REQUEST packet */
|
||||
uip_udp_send(AppDataSize);
|
||||
|
||||
/* Reset the timeout timer, progress to next state */
|
||||
timer_reset(&AppState->DHCPClient.Timeout);
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_WaitForACK;
|
||||
|
||||
break;
|
||||
case DHCP_STATE_WaitForACK:
|
||||
if (!(uip_newdata()))
|
||||
{
|
||||
/* Check if the DHCP timeout period has expired while waiting for a response */
|
||||
if (timer_expired(&AppState->DHCPClient.Timeout))
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t RequestResponse_MessageType;
|
||||
if ((AppData->TransactionID == DHCP_TRANSACTION_ID) &&
|
||||
DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &RequestResponse_MessageType) &&
|
||||
(RequestResponse_MessageType == DHCP_ACK))
|
||||
{
|
||||
/* Set the new network parameters from the DHCP server */
|
||||
uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);
|
||||
uip_setnetmask((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.Netmask);
|
||||
uip_setdraddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.GatewayIP);
|
||||
|
||||
/* Indicate to the user that we now have a valid IP configuration */
|
||||
HaveIPConfiguration = true;
|
||||
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_AddressLeased;
|
||||
}
|
||||
|
||||
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 server.
|
||||
*
|
||||
* \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] AppState Application state of the current UDP connection
|
||||
*
|
||||
* \return Size in bytes of the created DHCP packet
|
||||
*/
|
||||
static uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader, const uint8_t DHCPMessageType, uip_udp_appstate_t* AppState)
|
||||
{
|
||||
/* Erase existing packet data so that we start will all 0x00 DHCP header data */
|
||||
memset(DHCPHeader, 0, sizeof(DHCP_Header_t));
|
||||
|
||||
/* Fill out the DHCP packet header */
|
||||
DHCPHeader->Operation = DHCP_OP_BOOTREQUEST;
|
||||
DHCPHeader->HardwareType = DHCP_HTYPE_ETHERNET;
|
||||
DHCPHeader->HardwareAddressLength = sizeof(MACAddress);
|
||||
DHCPHeader->Hops = 0;
|
||||
DHCPHeader->TransactionID = DHCP_TRANSACTION_ID;
|
||||
DHCPHeader->ElapsedSeconds = 0;
|
||||
DHCPHeader->Flags = HTONS(BOOTP_BROADCAST);
|
||||
memcpy(&DHCPHeader->ClientIP, &uip_hostaddr, sizeof(uip_ipaddr_t));
|
||||
memcpy(&DHCPHeader->YourIP, &AppState->DHCPClient.DHCPOffer_Data.AllocatedIP, sizeof(uip_ipaddr_t));
|
||||
memcpy(&DHCPHeader->NextServerIP, &AppState->DHCPClient.DHCPOffer_Data.ServerIP, sizeof(uip_ipaddr_t));
|
||||
memcpy(&DHCPHeader->ClientHardwareAddress, &MACAddress, 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);
|
||||
}
|
||||
|
||||
/** 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, uint8_t Option, uint8_t DataLen, void* 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
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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(__DOXYGEN__)
|
||||
|
||||
/** \file
|
||||
*
|
||||
* DHCP Client Application. When connected to the uIP stack, this will retrieve IP configuration settings from the
|
||||
* DHCP server on the network.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_DHCPCLIENTAPP_C
|
||||
#include "DHCPClientApp.h"
|
||||
|
||||
/** Initialization function for the DHCP client. */
|
||||
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));
|
||||
|
||||
/* 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));
|
||||
|
||||
/* Set the initial client state */
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;
|
||||
|
||||
/* Set timeout period to half a second for a DHCP server to respond */
|
||||
timer_set(&AppState->DHCPClient.Timeout, CLOCK_SECOND / 2);
|
||||
}
|
||||
}
|
||||
|
||||
/** uIP stack application callback for the DHCP client. This function must be called each time the TCP/IP stack
|
||||
* needs a UDP packet to be processed.
|
||||
*/
|
||||
void DHCPClientApp_Callback(void)
|
||||
{
|
||||
uip_udp_appstate_t* const AppState = &uip_udp_conn->appstate;
|
||||
DHCP_Header_t* const AppData = (DHCP_Header_t*)uip_appdata;
|
||||
uint16_t AppDataSize = 0;
|
||||
|
||||
switch (AppState->DHCPClient.CurrentState)
|
||||
{
|
||||
case DHCP_STATE_SendDiscover:
|
||||
/* Clear all DHCP settings, reset client IP address */
|
||||
memset(&AppState->DHCPClient.DHCPOffer_Data, 0x00, sizeof(AppState->DHCPClient.DHCPOffer_Data));
|
||||
uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);
|
||||
|
||||
/* Fill out the DHCP response header */
|
||||
AppDataSize += DHCPClientApp_FillDHCPHeader(AppData, DHCP_DISCOVER, AppState);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Send the DHCP DISCOVER packet */
|
||||
uip_udp_send(AppDataSize);
|
||||
|
||||
/* Reset the timeout timer, progress to next state */
|
||||
timer_reset(&AppState->DHCPClient.Timeout);
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_WaitForOffer;
|
||||
|
||||
break;
|
||||
case DHCP_STATE_WaitForOffer:
|
||||
if (!(uip_newdata()))
|
||||
{
|
||||
/* Check if the DHCP timeout period has expired while waiting for a response */
|
||||
if (timer_expired(&AppState->DHCPClient.Timeout))
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t OfferResponse_MessageType;
|
||||
if ((AppData->TransactionID == DHCP_TRANSACTION_ID) &&
|
||||
DHCPClientApp_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);
|
||||
|
||||
timer_reset(&AppState->DHCPClient.Timeout);
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_SendRequest;
|
||||
}
|
||||
|
||||
break;
|
||||
case DHCP_STATE_SendRequest:
|
||||
/* Fill out the DHCP response header */
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Send the DHCP REQUEST packet */
|
||||
uip_udp_send(AppDataSize);
|
||||
|
||||
/* Reset the timeout timer, progress to next state */
|
||||
timer_reset(&AppState->DHCPClient.Timeout);
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_WaitForACK;
|
||||
|
||||
break;
|
||||
case DHCP_STATE_WaitForACK:
|
||||
if (!(uip_newdata()))
|
||||
{
|
||||
/* Check if the DHCP timeout period has expired while waiting for a response */
|
||||
if (timer_expired(&AppState->DHCPClient.Timeout))
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_SendDiscover;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t RequestResponse_MessageType;
|
||||
if ((AppData->TransactionID == DHCP_TRANSACTION_ID) &&
|
||||
DHCPClientApp_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &RequestResponse_MessageType) &&
|
||||
(RequestResponse_MessageType == DHCP_ACK))
|
||||
{
|
||||
/* Set the new network parameters from the DHCP server */
|
||||
uip_sethostaddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);
|
||||
uip_setnetmask((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.Netmask);
|
||||
uip_setdraddr((uip_ipaddr_t*)&AppState->DHCPClient.DHCPOffer_Data.GatewayIP);
|
||||
|
||||
/* Indicate to the user that we now have a valid IP configuration */
|
||||
HaveIPConfiguration = true;
|
||||
|
||||
AppState->DHCPClient.CurrentState = DHCP_STATE_AddressLeased;
|
||||
}
|
||||
|
||||
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 server.
|
||||
*
|
||||
* \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] AppState Application state of the current UDP connection
|
||||
*
|
||||
* \return Size in bytes of the created DHCP packet
|
||||
*/
|
||||
static uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader, const uint8_t DHCPMessageType, uip_udp_appstate_t* AppState)
|
||||
{
|
||||
/* Erase existing packet data so that we start will all 0x00 DHCP header data */
|
||||
memset(DHCPHeader, 0, sizeof(DHCP_Header_t));
|
||||
|
||||
/* Fill out the DHCP packet header */
|
||||
DHCPHeader->Operation = DHCP_OP_BOOTREQUEST;
|
||||
DHCPHeader->HardwareType = DHCP_HTYPE_ETHERNET;
|
||||
DHCPHeader->HardwareAddressLength = sizeof(MACAddress);
|
||||
DHCPHeader->Hops = 0;
|
||||
DHCPHeader->TransactionID = DHCP_TRANSACTION_ID;
|
||||
DHCPHeader->ElapsedSeconds = 0;
|
||||
DHCPHeader->Flags = HTONS(BOOTP_BROADCAST);
|
||||
memcpy(&DHCPHeader->ClientIP, &uip_hostaddr, sizeof(uip_ipaddr_t));
|
||||
memcpy(&DHCPHeader->YourIP, &AppState->DHCPClient.DHCPOffer_Data.AllocatedIP, sizeof(uip_ipaddr_t));
|
||||
memcpy(&DHCPHeader->NextServerIP, &AppState->DHCPClient.DHCPOffer_Data.ServerIP, sizeof(uip_ipaddr_t));
|
||||
memcpy(&DHCPHeader->ClientHardwareAddress, &MACAddress, 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);
|
||||
}
|
||||
|
||||
/** 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, uint8_t Option, uint8_t DataLen, void* 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
|
||||
|
|
|
@ -1,169 +1,169 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 DHCPClientApp.c.
|
||||
*/
|
||||
|
||||
#ifndef _DHCPCLIENT_APP_H_
|
||||
#define _DHCPCLIENT_APP_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <stdio.h>
|
||||
|
||||
#include <uip.h>
|
||||
|
||||
#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;
|
||||
|
||||
/* Enums: */
|
||||
/** States for each DHCP connection to a DHCP client. */
|
||||
enum DHCP_States_t
|
||||
{
|
||||
DHCP_STATE_SendDiscover, /**< Send DISCOVER packet to retrieve DHCP lease offers */
|
||||
DHCP_STATE_WaitForOffer, /**< Waiting for OFFER packet giving available DHCP leases */
|
||||
DHCP_STATE_SendRequest, /**< Send REQUEST packet to request a DHCP lease */
|
||||
DHCP_STATE_WaitForACK, /**< Wait for ACK packet to complete the DHCP lease */
|
||||
DHCP_STATE_AddressLeased, /**< DHCP address has been leased from a DHCP server */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
void DHCPClientApp_Init(void);
|
||||
void DHCPClientApp_Callback(void);
|
||||
|
||||
#if defined(INCLUDE_FROM_DHCPCLIENTAPP_C)
|
||||
static uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader, const uint8_t DHCPMessageType,
|
||||
uip_udp_appstate_t* AppState);
|
||||
static uint8_t DHCPClientApp_SetOption(uint8_t* DHCPOptionList, uint8_t Option, uint8_t DataLen,
|
||||
void* OptionData);
|
||||
static bool DHCPClientApp_GetOption(const uint8_t* DHCPOptionList, const uint8_t Option, void* const Destination);
|
||||
#endif
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 DHCPClientApp.c.
|
||||
*/
|
||||
|
||||
#ifndef _DHCPCLIENT_APP_H_
|
||||
#define _DHCPCLIENT_APP_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <stdio.h>
|
||||
|
||||
#include <uip.h>
|
||||
|
||||
#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;
|
||||
|
||||
/* Enums: */
|
||||
/** States for each DHCP connection to a DHCP client. */
|
||||
enum DHCP_States_t
|
||||
{
|
||||
DHCP_STATE_SendDiscover, /**< Send DISCOVER packet to retrieve DHCP lease offers */
|
||||
DHCP_STATE_WaitForOffer, /**< Waiting for OFFER packet giving available DHCP leases */
|
||||
DHCP_STATE_SendRequest, /**< Send REQUEST packet to request a DHCP lease */
|
||||
DHCP_STATE_WaitForACK, /**< Wait for ACK packet to complete the DHCP lease */
|
||||
DHCP_STATE_AddressLeased, /**< DHCP address has been leased from a DHCP server */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
void DHCPClientApp_Init(void);
|
||||
void DHCPClientApp_Callback(void);
|
||||
|
||||
#if defined(INCLUDE_FROM_DHCPCLIENTAPP_C)
|
||||
static uint16_t DHCPClientApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader, const uint8_t DHCPMessageType,
|
||||
uip_udp_appstate_t* AppState);
|
||||
static uint8_t DHCPClientApp_SetOption(uint8_t* DHCPOptionList, uint8_t Option, uint8_t DataLen,
|
||||
void* OptionData);
|
||||
static bool DHCPClientApp_GetOption(const uint8_t* DHCPOptionList, const uint8_t Option, void* const Destination);
|
||||
#endif
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,80 +1,80 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 DataflashManager.c.
|
||||
*/
|
||||
|
||||
#ifndef _DATAFLASH_MANAGER_H_
|
||||
#define _DATAFLASH_MANAGER_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "Descriptors.h"
|
||||
|
||||
#include <LUFA/Common/Common.h>
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
#include <LUFA/Drivers/USB/Class/MassStorage.h>
|
||||
#include <LUFA/Drivers/Board/Dataflash.h>
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if (DATAFLASH_PAGE_SIZE % 16)
|
||||
#error Dataflash page size must be a multiple of 16 bytes.
|
||||
#endif
|
||||
|
||||
/* Defines: */
|
||||
/** Total number of bytes of the storage medium, comprised of one or more dataflash ICs. */
|
||||
#define VIRTUAL_MEMORY_BYTES ((uint32_t)DATAFLASH_PAGES * DATAFLASH_PAGE_SIZE * DATAFLASH_TOTALCHIPS)
|
||||
|
||||
/** Block size of the device. This is kept at 512 to remain compatible with the OS despite the underlying
|
||||
* storage media (Dataflash) using a different native block size. Do not change this value.
|
||||
*/
|
||||
#define VIRTUAL_MEMORY_BLOCK_SIZE 512
|
||||
|
||||
/** Total number of blocks of the virtual memory for reporting to the host as the device's total capacity. Do not
|
||||
* change this value; change VIRTUAL_MEMORY_BYTES instead to alter the media size.
|
||||
*/
|
||||
#define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)
|
||||
|
||||
/* Function Prototypes: */
|
||||
void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const uint32_t BlockAddress,
|
||||
uint16_t TotalBlocks);
|
||||
void DataflashManager_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const uint32_t BlockAddress,
|
||||
uint16_t TotalBlocks);
|
||||
void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,
|
||||
const uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
|
||||
void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,
|
||||
uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
|
||||
void DataflashManager_ResetDataflashProtections(void);
|
||||
bool DataflashManager_CheckDataflashOperation(void);
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 DataflashManager.c.
|
||||
*/
|
||||
|
||||
#ifndef _DATAFLASH_MANAGER_H_
|
||||
#define _DATAFLASH_MANAGER_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "Descriptors.h"
|
||||
|
||||
#include <LUFA/Common/Common.h>
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
#include <LUFA/Drivers/USB/Class/MassStorage.h>
|
||||
#include <LUFA/Drivers/Board/Dataflash.h>
|
||||
|
||||
/* Preprocessor Checks: */
|
||||
#if (DATAFLASH_PAGE_SIZE % 16)
|
||||
#error Dataflash page size must be a multiple of 16 bytes.
|
||||
#endif
|
||||
|
||||
/* Defines: */
|
||||
/** Total number of bytes of the storage medium, comprised of one or more dataflash ICs. */
|
||||
#define VIRTUAL_MEMORY_BYTES ((uint32_t)DATAFLASH_PAGES * DATAFLASH_PAGE_SIZE * DATAFLASH_TOTALCHIPS)
|
||||
|
||||
/** Block size of the device. This is kept at 512 to remain compatible with the OS despite the underlying
|
||||
* storage media (Dataflash) using a different native block size. Do not change this value.
|
||||
*/
|
||||
#define VIRTUAL_MEMORY_BLOCK_SIZE 512
|
||||
|
||||
/** Total number of blocks of the virtual memory for reporting to the host as the device's total capacity. Do not
|
||||
* change this value; change VIRTUAL_MEMORY_BYTES instead to alter the media size.
|
||||
*/
|
||||
#define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)
|
||||
|
||||
/* Function Prototypes: */
|
||||
void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const uint32_t BlockAddress,
|
||||
uint16_t TotalBlocks);
|
||||
void DataflashManager_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const uint32_t BlockAddress,
|
||||
uint16_t TotalBlocks);
|
||||
void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,
|
||||
const uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
|
||||
void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,
|
||||
uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
|
||||
void DataflashManager_ResetDataflashProtections(void);
|
||||
bool DataflashManager_CheckDataflashOperation(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,110 +1,110 @@
|
|||
FatFs Module Source Files R0.07e (C)ChaN, 2010
|
||||
|
||||
|
||||
FILES
|
||||
|
||||
ffconf.h Configuration file for FatFs module.
|
||||
ff.h Common include file for FatFs and application module.
|
||||
ff.c FatFs module.
|
||||
diskio.h Common include file for FatFs and disk I/O module.
|
||||
diskio.c Skeleton of low level disk I/O module.
|
||||
integer.h Alternative type definitions for integer variables.
|
||||
option Optional external functions.
|
||||
|
||||
Low level disk I/O module is not included in this archive because the FatFs
|
||||
module is only a generic file system layer and not depend on any specific
|
||||
storage device. You have to provide a low level disk I/O module that written
|
||||
to control your storage device.
|
||||
|
||||
|
||||
|
||||
AGREEMENTS
|
||||
|
||||
FatFs module is an open source software to implement FAT file system to
|
||||
small embedded systems. This is a free software and is opened for education,
|
||||
research and commercial developments under license policy of following trems.
|
||||
|
||||
Copyright (C) 2010, ChaN, all right reserved.
|
||||
|
||||
* The FatFs module is a free software and there is NO WARRANTY.
|
||||
* No restriction on use. You can use, modify and redistribute it for
|
||||
personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
|
||||
* Redistributions of source code must retain the above copyright notice.
|
||||
|
||||
|
||||
|
||||
REVISION HISTORY
|
||||
|
||||
Feb 26, 2006 R0.00 Prototype
|
||||
|
||||
Apr 29, 2006 R0.01 First release.
|
||||
|
||||
Jun 01, 2006 R0.02 Added FAT12.
|
||||
Removed unbuffered mode.
|
||||
Fixed a problem on small (<32M) patition.
|
||||
|
||||
Jun 10, 2006 R0.02a Added a configuration option _FS_MINIMUM.
|
||||
|
||||
Sep 22, 2006 R0.03 Added f_rename.
|
||||
Changed option _FS_MINIMUM to _FS_MINIMIZE.
|
||||
|
||||
Dec 11, 2006 R0.03a Improved cluster scan algolithm to write files fast.
|
||||
Fixed f_mkdir creates incorrect directory on FAT32.
|
||||
|
||||
Feb 04, 2007 R0.04 Supported multiple drive system. (FatFs)
|
||||
Changed some APIs for multiple drive system.
|
||||
Added f_mkfs. (FatFs)
|
||||
Added _USE_FAT32 option. (Tiny-FatFs)
|
||||
|
||||
Apr 01, 2007 R0.04a Supported multiple partitions on a plysical drive. (FatFs)
|
||||
Fixed an endian sensitive code in f_mkfs. (FatFs)
|
||||
Added a capability of extending the file size to f_lseek.
|
||||
Added minimization level 3.
|
||||
Fixed a problem that can collapse a sector when recreate an
|
||||
existing file in any sub-directory at non FAT32 cfg. (Tiny-FatFs)
|
||||
|
||||
May 05, 2007 R0.04b Added _USE_NTFLAG option.
|
||||
Added FSInfo support.
|
||||
Fixed some problems corresponds to FAT32. (Tiny-FatFs)
|
||||
Fixed DBCS name can result FR_INVALID_NAME.
|
||||
Fixed short seek (0 < ofs <= csize) collapses the file object.
|
||||
|
||||
Aug 25, 2007 R0.05 Changed arguments of f_read, f_write.
|
||||
Changed arguments of f_mkfs. (FatFs)
|
||||
Fixed f_mkfs on FAT32 creates incorrect FSInfo. (FatFs)
|
||||
Fixed f_mkdir on FAT32 creates incorrect directory. (FatFs)
|
||||
|
||||
Feb 03, 2008 R0.05a Added f_truncate().
|
||||
Added f_utime().
|
||||
Fixed off by one error at FAT sub-type determination.
|
||||
Fixed btr in f_read() can be mistruncated.
|
||||
Fixed cached sector is not flushed when create and close without write.
|
||||
|
||||
Apr 01, 2008 R0.06 Added f_forward(). (Tiny-FatFs)
|
||||
Added string functions: fputc(), fputs(), fprintf() and fgets().
|
||||
Improved performance of f_lseek() on move to the same or following cluster.
|
||||
|
||||
Apr 01, 2010, R0.07 Merged Tiny-FatFs as a buffer configuration option.
|
||||
Added long file name support.
|
||||
Added multiple code page support.
|
||||
Added re-entrancy for multitask operation.
|
||||
Added auto cluster size selection to f_mkfs().
|
||||
Added rewind option to f_readdir().
|
||||
Changed result code of critical errors.
|
||||
Renamed string functions to avoid name collision.
|
||||
|
||||
Apr 14, 2010, R0.07a Separated out OS dependent code on reentrant cfg.
|
||||
Added multiple sector size support.
|
||||
|
||||
Jun 21, 2010, R0.07c Fixed f_unlink() may return FR_OK on error.
|
||||
Fixed wrong cache control in f_lseek().
|
||||
Added relative path feature.
|
||||
Added f_chdir().
|
||||
Added f_chdrive().
|
||||
Added proper case conversion for extended characters.
|
||||
|
||||
Nov 03,'2010 R0.07e Separated out configuration options from ff.h to ffconf.h.
|
||||
Added a configuration option, _LFN_UNICODE.
|
||||
Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
|
||||
Fixed name matching error on the 13 char boundary.
|
||||
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
|
||||
FatFs Module Source Files R0.07e (C)ChaN, 2010
|
||||
|
||||
|
||||
FILES
|
||||
|
||||
ffconf.h Configuration file for FatFs module.
|
||||
ff.h Common include file for FatFs and application module.
|
||||
ff.c FatFs module.
|
||||
diskio.h Common include file for FatFs and disk I/O module.
|
||||
diskio.c Skeleton of low level disk I/O module.
|
||||
integer.h Alternative type definitions for integer variables.
|
||||
option Optional external functions.
|
||||
|
||||
Low level disk I/O module is not included in this archive because the FatFs
|
||||
module is only a generic file system layer and not depend on any specific
|
||||
storage device. You have to provide a low level disk I/O module that written
|
||||
to control your storage device.
|
||||
|
||||
|
||||
|
||||
AGREEMENTS
|
||||
|
||||
FatFs module is an open source software to implement FAT file system to
|
||||
small embedded systems. This is a free software and is opened for education,
|
||||
research and commercial developments under license policy of following trems.
|
||||
|
||||
Copyright (C) 2010, ChaN, all right reserved.
|
||||
|
||||
* The FatFs module is a free software and there is NO WARRANTY.
|
||||
* No restriction on use. You can use, modify and redistribute it for
|
||||
personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
|
||||
* Redistributions of source code must retain the above copyright notice.
|
||||
|
||||
|
||||
|
||||
REVISION HISTORY
|
||||
|
||||
Feb 26, 2006 R0.00 Prototype
|
||||
|
||||
Apr 29, 2006 R0.01 First release.
|
||||
|
||||
Jun 01, 2006 R0.02 Added FAT12.
|
||||
Removed unbuffered mode.
|
||||
Fixed a problem on small (<32M) patition.
|
||||
|
||||
Jun 10, 2006 R0.02a Added a configuration option _FS_MINIMUM.
|
||||
|
||||
Sep 22, 2006 R0.03 Added f_rename.
|
||||
Changed option _FS_MINIMUM to _FS_MINIMIZE.
|
||||
|
||||
Dec 11, 2006 R0.03a Improved cluster scan algolithm to write files fast.
|
||||
Fixed f_mkdir creates incorrect directory on FAT32.
|
||||
|
||||
Feb 04, 2007 R0.04 Supported multiple drive system. (FatFs)
|
||||
Changed some APIs for multiple drive system.
|
||||
Added f_mkfs. (FatFs)
|
||||
Added _USE_FAT32 option. (Tiny-FatFs)
|
||||
|
||||
Apr 01, 2007 R0.04a Supported multiple partitions on a plysical drive. (FatFs)
|
||||
Fixed an endian sensitive code in f_mkfs. (FatFs)
|
||||
Added a capability of extending the file size to f_lseek.
|
||||
Added minimization level 3.
|
||||
Fixed a problem that can collapse a sector when recreate an
|
||||
existing file in any sub-directory at non FAT32 cfg. (Tiny-FatFs)
|
||||
|
||||
May 05, 2007 R0.04b Added _USE_NTFLAG option.
|
||||
Added FSInfo support.
|
||||
Fixed some problems corresponds to FAT32. (Tiny-FatFs)
|
||||
Fixed DBCS name can result FR_INVALID_NAME.
|
||||
Fixed short seek (0 < ofs <= csize) collapses the file object.
|
||||
|
||||
Aug 25, 2007 R0.05 Changed arguments of f_read, f_write.
|
||||
Changed arguments of f_mkfs. (FatFs)
|
||||
Fixed f_mkfs on FAT32 creates incorrect FSInfo. (FatFs)
|
||||
Fixed f_mkdir on FAT32 creates incorrect directory. (FatFs)
|
||||
|
||||
Feb 03, 2008 R0.05a Added f_truncate().
|
||||
Added f_utime().
|
||||
Fixed off by one error at FAT sub-type determination.
|
||||
Fixed btr in f_read() can be mistruncated.
|
||||
Fixed cached sector is not flushed when create and close without write.
|
||||
|
||||
Apr 01, 2008 R0.06 Added f_forward(). (Tiny-FatFs)
|
||||
Added string functions: fputc(), fputs(), fprintf() and fgets().
|
||||
Improved performance of f_lseek() on move to the same or following cluster.
|
||||
|
||||
Apr 01, 2010, R0.07 Merged Tiny-FatFs as a buffer configuration option.
|
||||
Added long file name support.
|
||||
Added multiple code page support.
|
||||
Added re-entrancy for multitask operation.
|
||||
Added auto cluster size selection to f_mkfs().
|
||||
Added rewind option to f_readdir().
|
||||
Changed result code of critical errors.
|
||||
Renamed string functions to avoid name collision.
|
||||
|
||||
Apr 14, 2010, R0.07a Separated out OS dependent code on reentrant cfg.
|
||||
Added multiple sector size support.
|
||||
|
||||
Jun 21, 2010, R0.07c Fixed f_unlink() may return FR_OK on error.
|
||||
Fixed wrong cache control in f_lseek().
|
||||
Added relative path feature.
|
||||
Added f_chdir().
|
||||
Added f_chdrive().
|
||||
Added proper case conversion for extended characters.
|
||||
|
||||
Nov 03,'2010 R0.07e Separated out configuration options from ff.h to ffconf.h.
|
||||
Added a configuration option, _LFN_UNICODE.
|
||||
Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
|
||||
Fixed name matching error on the 13 char boundary.
|
||||
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
|
||||
|
|
|
@ -1,64 +1,64 @@
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* This is a stub disk I/O module that acts as front end of the existing */
|
||||
/* disk I/O modules and attach it to FatFs module with common interface. */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#include "diskio.h"
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Inidialize a Drive */
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
BYTE drv /* Physical drive nmuber (0..) */
|
||||
)
|
||||
{
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Return Disk Status */
|
||||
|
||||
DSTATUS disk_status (
|
||||
BYTE drv /* Physical drive nmuber (0..) */
|
||||
)
|
||||
{
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Read Sector(s) */
|
||||
|
||||
DRESULT disk_read (
|
||||
BYTE drv, /* Physical drive nmuber (0..) */
|
||||
BYTE *buff, /* Data buffer to store read data */
|
||||
DWORD sector, /* Sector address (LBA) */
|
||||
BYTE count /* Number of sectors to read (1..255) */
|
||||
)
|
||||
{
|
||||
DataflashManager_ReadBlocks_RAM(sector, count, buff);
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Write Sector(s) */
|
||||
|
||||
#if _READONLY == 0
|
||||
DRESULT disk_write (
|
||||
BYTE drv, /* Physical drive nmuber (0..) */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
DWORD sector, /* Sector address (LBA) */
|
||||
BYTE count /* Number of sectors to write (1..255) */
|
||||
)
|
||||
{
|
||||
DataflashManager_WriteBlocks_RAM(sector, count, buff);
|
||||
return RES_OK;
|
||||
}
|
||||
#endif /* _READONLY */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* This is a stub disk I/O module that acts as front end of the existing */
|
||||
/* disk I/O modules and attach it to FatFs module with common interface. */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#include "diskio.h"
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Inidialize a Drive */
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
BYTE drv /* Physical drive nmuber (0..) */
|
||||
)
|
||||
{
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Return Disk Status */
|
||||
|
||||
DSTATUS disk_status (
|
||||
BYTE drv /* Physical drive nmuber (0..) */
|
||||
)
|
||||
{
|
||||
return FR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Read Sector(s) */
|
||||
|
||||
DRESULT disk_read (
|
||||
BYTE drv, /* Physical drive nmuber (0..) */
|
||||
BYTE *buff, /* Data buffer to store read data */
|
||||
DWORD sector, /* Sector address (LBA) */
|
||||
BYTE count /* Number of sectors to read (1..255) */
|
||||
)
|
||||
{
|
||||
DataflashManager_ReadBlocks_RAM(sector, count, buff);
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Write Sector(s) */
|
||||
|
||||
#if _READONLY == 0
|
||||
DRESULT disk_write (
|
||||
BYTE drv, /* Physical drive nmuber (0..) */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
DWORD sector, /* Sector address (LBA) */
|
||||
BYTE count /* Number of sectors to write (1..255) */
|
||||
)
|
||||
{
|
||||
DataflashManager_WriteBlocks_RAM(sector, count, buff);
|
||||
return RES_OK;
|
||||
}
|
||||
#endif /* _READONLY */
|
||||
|
|
|
@ -1,72 +1,72 @@
|
|||
/*-----------------------------------------------------------------------
|
||||
/ Low level disk interface modlue include file R0.07 (C)ChaN, 2010
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _DISKIO
|
||||
|
||||
#define _READONLY 0 /* 1: Read-only mode */
|
||||
#define _USE_IOCTL 0
|
||||
|
||||
#include "integer.h"
|
||||
#include "ff.h"
|
||||
|
||||
#include "../DataflashManager.h"
|
||||
|
||||
|
||||
/* Status of Disk Functions */
|
||||
typedef BYTE DSTATUS;
|
||||
|
||||
/* Results of Disk Functions */
|
||||
typedef enum {
|
||||
RES_OK = 0, /* 0: Successful */
|
||||
RES_ERROR, /* 1: R/W Error */
|
||||
RES_WRPRT, /* 2: Write Protected */
|
||||
RES_NOTRDY, /* 3: Not Ready */
|
||||
RES_PARERR /* 4: Invalid Parameter */
|
||||
} DRESULT;
|
||||
|
||||
|
||||
/*---------------------------------------*/
|
||||
/* Prototypes for disk control functions */
|
||||
|
||||
BOOL assign_drives (int argc, char *argv[]);
|
||||
DSTATUS disk_initialize (BYTE);
|
||||
DSTATUS disk_status (BYTE);
|
||||
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
|
||||
#if _READONLY == 0
|
||||
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
|
||||
#endif
|
||||
DRESULT disk_ioctl (BYTE, BYTE, void*);
|
||||
|
||||
|
||||
/* Disk Status Bits (DSTATUS) */
|
||||
|
||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
||||
#define STA_PROTECT 0x04 /* Write protected */
|
||||
|
||||
|
||||
/* Command code for disk_ioctrl() */
|
||||
|
||||
/* Generic command */
|
||||
#define CTRL_SYNC 0 /* Mandatory for write functions */
|
||||
#define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */
|
||||
#define GET_SECTOR_SIZE 2 /* Mandatory for multiple sector size cfg */
|
||||
#define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */
|
||||
#define CTRL_POWER 4
|
||||
#define CTRL_LOCK 5
|
||||
#define CTRL_EJECT 6
|
||||
/* MMC/SDC command */
|
||||
#define MMC_GET_TYPE 10
|
||||
#define MMC_GET_CSD 11
|
||||
#define MMC_GET_CID 12
|
||||
#define MMC_GET_OCR 13
|
||||
#define MMC_GET_SDSTAT 14
|
||||
/* ATA/CF command */
|
||||
#define ATA_GET_REV 20
|
||||
#define ATA_GET_MODEL 21
|
||||
#define ATA_GET_SN 22
|
||||
|
||||
|
||||
#define _DISKIO
|
||||
#endif
|
||||
/*-----------------------------------------------------------------------
|
||||
/ Low level disk interface modlue include file R0.07 (C)ChaN, 2010
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _DISKIO
|
||||
|
||||
#define _READONLY 0 /* 1: Read-only mode */
|
||||
#define _USE_IOCTL 0
|
||||
|
||||
#include "integer.h"
|
||||
#include "ff.h"
|
||||
|
||||
#include "../DataflashManager.h"
|
||||
|
||||
|
||||
/* Status of Disk Functions */
|
||||
typedef BYTE DSTATUS;
|
||||
|
||||
/* Results of Disk Functions */
|
||||
typedef enum {
|
||||
RES_OK = 0, /* 0: Successful */
|
||||
RES_ERROR, /* 1: R/W Error */
|
||||
RES_WRPRT, /* 2: Write Protected */
|
||||
RES_NOTRDY, /* 3: Not Ready */
|
||||
RES_PARERR /* 4: Invalid Parameter */
|
||||
} DRESULT;
|
||||
|
||||
|
||||
/*---------------------------------------*/
|
||||
/* Prototypes for disk control functions */
|
||||
|
||||
BOOL assign_drives (int argc, char *argv[]);
|
||||
DSTATUS disk_initialize (BYTE);
|
||||
DSTATUS disk_status (BYTE);
|
||||
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
|
||||
#if _READONLY == 0
|
||||
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
|
||||
#endif
|
||||
DRESULT disk_ioctl (BYTE, BYTE, void*);
|
||||
|
||||
|
||||
/* Disk Status Bits (DSTATUS) */
|
||||
|
||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
||||
#define STA_PROTECT 0x04 /* Write protected */
|
||||
|
||||
|
||||
/* Command code for disk_ioctrl() */
|
||||
|
||||
/* Generic command */
|
||||
#define CTRL_SYNC 0 /* Mandatory for write functions */
|
||||
#define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */
|
||||
#define GET_SECTOR_SIZE 2 /* Mandatory for multiple sector size cfg */
|
||||
#define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */
|
||||
#define CTRL_POWER 4
|
||||
#define CTRL_LOCK 5
|
||||
#define CTRL_EJECT 6
|
||||
/* MMC/SDC command */
|
||||
#define MMC_GET_TYPE 10
|
||||
#define MMC_GET_CSD 11
|
||||
#define MMC_GET_CID 12
|
||||
#define MMC_GET_OCR 13
|
||||
#define MMC_GET_SDSTAT 14
|
||||
/* ATA/CF command */
|
||||
#define ATA_GET_REV 20
|
||||
#define ATA_GET_MODEL 21
|
||||
#define ATA_GET_SN 22
|
||||
|
||||
|
||||
#define _DISKIO
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,166 +1,166 @@
|
|||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module configuration file R0.07e (C)ChaN, 2010
|
||||
/----------------------------------------------------------------------------/
|
||||
/
|
||||
/ CAUTION! Do not forget to make clean the project after any changes to
|
||||
/ the configuration options.
|
||||
/
|
||||
/----------------------------------------------------------------------------*/
|
||||
#ifndef _FFCONFIG
|
||||
#define _FFCONFIG 0x007E
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function and Buffer Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _FS_TINY 1 /* 0 or 1 */
|
||||
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
|
||||
/ object instead of the sector buffer in the individual file object for file
|
||||
/ data transfer. This reduces memory consumption 512 bytes each file object. */
|
||||
|
||||
|
||||
#define _FS_READONLY 1 /* 0 or 1 */
|
||||
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
|
||||
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
|
||||
/ f_truncate and useless f_getfree. */
|
||||
|
||||
|
||||
#define _FS_MINIMIZE 2 /* 0, 1, 2 or 3 */
|
||||
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
||||
/
|
||||
/ 0: Full function.
|
||||
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
|
||||
/ are removed.
|
||||
/ 2: f_opendir and f_readdir are removed in addition to level 1.
|
||||
/ 3: f_lseek is removed in addition to level 2. */
|
||||
|
||||
|
||||
#define _USE_STRFUNC 0 /* 0, 1 or 2 */
|
||||
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
||||
|
||||
|
||||
#define _USE_MKFS 0 /* 0 or 1 */
|
||||
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
|
||||
|
||||
|
||||
#define _USE_FORWARD 0 /* 0 or 1 */
|
||||
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Locale and Namespace Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _CODE_PAGE 932
|
||||
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect setting of the code page can cause a file open failure.
|
||||
/
|
||||
/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
|
||||
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
|
||||
/ 949 - Korean (DBCS, OEM, Windows)
|
||||
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
|
||||
/ 1250 - Central Europe (Windows)
|
||||
/ 1251 - Cyrillic (Windows)
|
||||
/ 1252 - Latin 1 (Windows)
|
||||
/ 1253 - Greek (Windows)
|
||||
/ 1254 - Turkish (Windows)
|
||||
/ 1255 - Hebrew (Windows)
|
||||
/ 1256 - Arabic (Windows)
|
||||
/ 1257 - Baltic (Windows)
|
||||
/ 1258 - Vietnam (OEM, Windows)
|
||||
/ 437 - U.S. (OEM)
|
||||
/ 720 - Arabic (OEM)
|
||||
/ 737 - Greek (OEM)
|
||||
/ 775 - Baltic (OEM)
|
||||
/ 850 - Multilingual Latin 1 (OEM)
|
||||
/ 858 - Multilingual Latin 1 + Euro (OEM)
|
||||
/ 852 - Latin 2 (OEM)
|
||||
/ 855 - Cyrillic (OEM)
|
||||
/ 866 - Russian (OEM)
|
||||
/ 857 - Turkish (OEM)
|
||||
/ 862 - Hebrew (OEM)
|
||||
/ 874 - Thai (OEM, Windows)
|
||||
/ 1 - ASCII only (Valid for non LFN cfg.)
|
||||
*/
|
||||
|
||||
|
||||
#define _USE_LFN 0 /* 0, 1 or 2 */
|
||||
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
|
||||
/* The _USE_LFN option switches the LFN support.
|
||||
/
|
||||
/ 0: Disable LFN. _MAX_LFN and _LFN_UNICODE have no effect.
|
||||
/ 1: Enable LFN with static working buffer on the bss. NOT REENTRANT.
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/
|
||||
/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN,
|
||||
/ two Unicode handling functions ff_convert() and ff_wtoupper() must be added
|
||||
/ to the project. */
|
||||
|
||||
|
||||
#define _LFN_UNICODE 0 /* 0 or 1 */
|
||||
/* To switch the character code set on FatFs API to Unicode,
|
||||
/ enable LFN feature and set _LFN_UNICODE to 1.
|
||||
*/
|
||||
|
||||
|
||||
#define _FS_RPATH 0 /* 0 or 1 */
|
||||
/* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir,
|
||||
/ f_chdrive function are available.
|
||||
/ Note that output of the f_readdir fnction is affected by this option. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Physical Drive Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _DRIVES 1
|
||||
/* Number of volumes (logical drives) to be used. */
|
||||
|
||||
|
||||
#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
|
||||
/* Maximum sector size to be handled.
|
||||
/ Always set 512 for memory card and hard disk but a larger value may be
|
||||
/ required for floppy disk (512/1024) and optical disk (512/2048).
|
||||
/ When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implememted
|
||||
/ to the disk_ioctl function. */
|
||||
|
||||
|
||||
#define _MULTI_PARTITION 0 /* 0 or 1 */
|
||||
/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical
|
||||
/ drive number and can mount only first primaly partition. When it is set to 1,
|
||||
/ each volume is tied to the partitions listed in Drives[]. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ System Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _WORD_ACCESS 1 /* 0 or 1 */
|
||||
/* The _WORD_ACCESS option defines which access method is used to the word
|
||||
/ data on the FAT volume.
|
||||
/
|
||||
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
||||
/ 1: Word access. Do not choose this unless following condition is met.
|
||||
/
|
||||
/ When the byte order on the memory is big-endian or address miss-aligned
|
||||
/ word access results incorrect behavior, the _WORD_ACCESS must be set to 0.
|
||||
/ If it is not the case, the value can also be set to 1 to improve the
|
||||
/ performance and code size. */
|
||||
|
||||
|
||||
#define _FS_REENTRANT 0 /* 0 or 1 */
|
||||
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
|
||||
#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
|
||||
/* The _FS_REENTRANT option switches the reentrancy of the FatFs module.
|
||||
/
|
||||
/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
|
||||
/ 1: Enable reentrancy. Also user provided synchronization handlers,
|
||||
/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
|
||||
/ function must be added to the project. */
|
||||
|
||||
|
||||
#endif /* _FFCONFIG */
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs - FAT file system module configuration file R0.07e (C)ChaN, 2010
|
||||
/----------------------------------------------------------------------------/
|
||||
/
|
||||
/ CAUTION! Do not forget to make clean the project after any changes to
|
||||
/ the configuration options.
|
||||
/
|
||||
/----------------------------------------------------------------------------*/
|
||||
#ifndef _FFCONFIG
|
||||
#define _FFCONFIG 0x007E
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function and Buffer Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _FS_TINY 1 /* 0 or 1 */
|
||||
/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
|
||||
/ object instead of the sector buffer in the individual file object for file
|
||||
/ data transfer. This reduces memory consumption 512 bytes each file object. */
|
||||
|
||||
|
||||
#define _FS_READONLY 1 /* 0 or 1 */
|
||||
/* Setting _FS_READONLY to 1 defines read only configuration. This removes
|
||||
/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
|
||||
/ f_truncate and useless f_getfree. */
|
||||
|
||||
|
||||
#define _FS_MINIMIZE 2 /* 0, 1, 2 or 3 */
|
||||
/* The _FS_MINIMIZE option defines minimization level to remove some functions.
|
||||
/
|
||||
/ 0: Full function.
|
||||
/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
|
||||
/ are removed.
|
||||
/ 2: f_opendir and f_readdir are removed in addition to level 1.
|
||||
/ 3: f_lseek is removed in addition to level 2. */
|
||||
|
||||
|
||||
#define _USE_STRFUNC 0 /* 0, 1 or 2 */
|
||||
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
|
||||
|
||||
|
||||
#define _USE_MKFS 0 /* 0 or 1 */
|
||||
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
|
||||
|
||||
|
||||
#define _USE_FORWARD 0 /* 0 or 1 */
|
||||
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Locale and Namespace Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _CODE_PAGE 932
|
||||
/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect setting of the code page can cause a file open failure.
|
||||
/
|
||||
/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
|
||||
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
|
||||
/ 949 - Korean (DBCS, OEM, Windows)
|
||||
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
|
||||
/ 1250 - Central Europe (Windows)
|
||||
/ 1251 - Cyrillic (Windows)
|
||||
/ 1252 - Latin 1 (Windows)
|
||||
/ 1253 - Greek (Windows)
|
||||
/ 1254 - Turkish (Windows)
|
||||
/ 1255 - Hebrew (Windows)
|
||||
/ 1256 - Arabic (Windows)
|
||||
/ 1257 - Baltic (Windows)
|
||||
/ 1258 - Vietnam (OEM, Windows)
|
||||
/ 437 - U.S. (OEM)
|
||||
/ 720 - Arabic (OEM)
|
||||
/ 737 - Greek (OEM)
|
||||
/ 775 - Baltic (OEM)
|
||||
/ 850 - Multilingual Latin 1 (OEM)
|
||||
/ 858 - Multilingual Latin 1 + Euro (OEM)
|
||||
/ 852 - Latin 2 (OEM)
|
||||
/ 855 - Cyrillic (OEM)
|
||||
/ 866 - Russian (OEM)
|
||||
/ 857 - Turkish (OEM)
|
||||
/ 862 - Hebrew (OEM)
|
||||
/ 874 - Thai (OEM, Windows)
|
||||
/ 1 - ASCII only (Valid for non LFN cfg.)
|
||||
*/
|
||||
|
||||
|
||||
#define _USE_LFN 0 /* 0, 1 or 2 */
|
||||
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
|
||||
/* The _USE_LFN option switches the LFN support.
|
||||
/
|
||||
/ 0: Disable LFN. _MAX_LFN and _LFN_UNICODE have no effect.
|
||||
/ 1: Enable LFN with static working buffer on the bss. NOT REENTRANT.
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/
|
||||
/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN,
|
||||
/ two Unicode handling functions ff_convert() and ff_wtoupper() must be added
|
||||
/ to the project. */
|
||||
|
||||
|
||||
#define _LFN_UNICODE 0 /* 0 or 1 */
|
||||
/* To switch the character code set on FatFs API to Unicode,
|
||||
/ enable LFN feature and set _LFN_UNICODE to 1.
|
||||
*/
|
||||
|
||||
|
||||
#define _FS_RPATH 0 /* 0 or 1 */
|
||||
/* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir,
|
||||
/ f_chdrive function are available.
|
||||
/ Note that output of the f_readdir fnction is affected by this option. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Physical Drive Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _DRIVES 1
|
||||
/* Number of volumes (logical drives) to be used. */
|
||||
|
||||
|
||||
#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
|
||||
/* Maximum sector size to be handled.
|
||||
/ Always set 512 for memory card and hard disk but a larger value may be
|
||||
/ required for floppy disk (512/1024) and optical disk (512/2048).
|
||||
/ When _MAX_SS is larger than 512, GET_SECTOR_SIZE command must be implememted
|
||||
/ to the disk_ioctl function. */
|
||||
|
||||
|
||||
#define _MULTI_PARTITION 0 /* 0 or 1 */
|
||||
/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical
|
||||
/ drive number and can mount only first primaly partition. When it is set to 1,
|
||||
/ each volume is tied to the partitions listed in Drives[]. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ System Configurations
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
#define _WORD_ACCESS 1 /* 0 or 1 */
|
||||
/* The _WORD_ACCESS option defines which access method is used to the word
|
||||
/ data on the FAT volume.
|
||||
/
|
||||
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
||||
/ 1: Word access. Do not choose this unless following condition is met.
|
||||
/
|
||||
/ When the byte order on the memory is big-endian or address miss-aligned
|
||||
/ word access results incorrect behavior, the _WORD_ACCESS must be set to 0.
|
||||
/ If it is not the case, the value can also be set to 1 to improve the
|
||||
/ performance and code size. */
|
||||
|
||||
|
||||
#define _FS_REENTRANT 0 /* 0 or 1 */
|
||||
#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
|
||||
#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
|
||||
/* The _FS_REENTRANT option switches the reentrancy of the FatFs module.
|
||||
/
|
||||
/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
|
||||
/ 1: Enable reentrancy. Also user provided synchronization handlers,
|
||||
/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
|
||||
/ function must be added to the project. */
|
||||
|
||||
|
||||
#endif /* _FFCONFIG */
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
/*-------------------------------------------*/
|
||||
/* Integer type definitions for FatFs module */
|
||||
/*-------------------------------------------*/
|
||||
|
||||
#ifndef _INTEGER
|
||||
|
||||
#if 0
|
||||
#include <windows.h>
|
||||
#else
|
||||
|
||||
/* These types must be 16-bit, 32-bit or larger integer */
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
/* These types must be 8-bit integer */
|
||||
typedef signed char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
/* These types must be 16-bit integer */
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned short WCHAR;
|
||||
|
||||
/* These types must be 32-bit integer */
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
/* Boolean type */
|
||||
typedef enum { FALSE = 0, TRUE } BOOL;
|
||||
|
||||
#endif
|
||||
|
||||
#define _INTEGER
|
||||
#endif
|
||||
/*-------------------------------------------*/
|
||||
/* Integer type definitions for FatFs module */
|
||||
/*-------------------------------------------*/
|
||||
|
||||
#ifndef _INTEGER
|
||||
|
||||
#if 0
|
||||
#include <windows.h>
|
||||
#else
|
||||
|
||||
/* These types must be 16-bit, 32-bit or larger integer */
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
|
||||
/* These types must be 8-bit integer */
|
||||
typedef signed char CHAR;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
/* These types must be 16-bit integer */
|
||||
typedef short SHORT;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned short WCHAR;
|
||||
|
||||
/* These types must be 32-bit integer */
|
||||
typedef long LONG;
|
||||
typedef unsigned long ULONG;
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
/* Boolean type */
|
||||
typedef enum { FALSE = 0, TRUE } BOOL;
|
||||
|
||||
#endif
|
||||
|
||||
#define _INTEGER
|
||||
#endif
|
||||
|
|
|
@ -1,289 +1,289 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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
|
||||
*
|
||||
* Simple HTTP Webserver Application. When connected to the uIP stack,
|
||||
* this will serve out files to HTTP clients on port 80.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_HTTPSERVERAPP_C
|
||||
#include "HTTPServerApp.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.
|
||||
*/
|
||||
const char PROGMEM HTTP200Header[] = "HTTP/1.1 200 OK\r\n"
|
||||
"Server: LUFA " LUFA_VERSION_STRING "\r\n"
|
||||
"Connection: close\r\n"
|
||||
"MIME-version: 1.0\r\n"
|
||||
"Content-Type: ";
|
||||
|
||||
/** HTTP server response header, for transmission before a resource not found error. This indicates to the host that the given
|
||||
* given URL is invalid, and gives extra error information.
|
||||
*/
|
||||
const char PROGMEM HTTP404Header[] = "HTTP/1.1 404 Not Found\r\n"
|
||||
"Server: LUFA " LUFA_VERSION_STRING "\r\n"
|
||||
"Connection: close\r\n"
|
||||
"MIME-version: 1.0\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n"
|
||||
"Error 404: File Not Found: /";
|
||||
|
||||
/** Default filename to fetch when a directory is requested */
|
||||
const char PROGMEM DefaultDirFileName[] = "index.htm";
|
||||
|
||||
/** Default MIME type sent if no other MIME type can be determined. */
|
||||
const char PROGMEM DefaultMIMEType[] = "text/plain";
|
||||
|
||||
/** List of MIME types for each supported file extension. */
|
||||
const MIME_Type_t MIMETypes[] =
|
||||
{
|
||||
{.Extension = "htm", .MIMEType = "text/html"},
|
||||
{.Extension = "jpg", .MIMEType = "image/jpeg"},
|
||||
{.Extension = "gif", .MIMEType = "image/gif"},
|
||||
{.Extension = "bmp", .MIMEType = "image/bmp"},
|
||||
{.Extension = "png", .MIMEType = "image/png"},
|
||||
{.Extension = "ico", .MIMEType = "image/x-icon"},
|
||||
{.Extension = "exe", .MIMEType = "application/octet-stream"},
|
||||
{.Extension = "gz", .MIMEType = "application/x-gzip"},
|
||||
{.Extension = "zip", .MIMEType = "application/zip"},
|
||||
{.Extension = "pdf", .MIMEType = "application/pdf"},
|
||||
};
|
||||
|
||||
/** FATFs structure to hold the internal state of the FAT driver for the dataflash contents. */
|
||||
FATFS DiskFATState;
|
||||
|
||||
|
||||
/** Initialization function for the simple HTTP webserver. */
|
||||
void HTTPServerApp_Init(void)
|
||||
{
|
||||
/* Listen on port 80 for HTTP connections from hosts */
|
||||
uip_listen(HTONS(HTTP_SERVER_PORT));
|
||||
|
||||
/* Mount the dataflash disk via FatFS */
|
||||
f_mount(0, &DiskFATState);
|
||||
}
|
||||
|
||||
/** uIP stack application callback for the simple HTTP webserver. This function must be called each time the
|
||||
* TCP/IP stack needs a TCP packet to be processed.
|
||||
*/
|
||||
void HTTPServerApp_Callback(void)
|
||||
{
|
||||
uip_tcp_appstate_t* const AppState = &uip_conn->appstate;
|
||||
|
||||
if (uip_aborted() || uip_timedout() || uip_closed())
|
||||
{
|
||||
/* Lock to the closed state so that no further processing will occur on the connection */
|
||||
AppState->HTTPServer.CurrentState = WEBSERVER_STATE_Closing;
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_Closing;
|
||||
}
|
||||
|
||||
if (uip_connected())
|
||||
{
|
||||
/* New connection - initialize connection state values */
|
||||
AppState->HTTPServer.CurrentState = WEBSERVER_STATE_OpenRequestedFile;
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_OpenRequestedFile;
|
||||
AppState->HTTPServer.FileOpen = false;
|
||||
AppState->HTTPServer.ACKedFilePos = 0;
|
||||
AppState->HTTPServer.SentChunkSize = 0;
|
||||
}
|
||||
|
||||
if (uip_acked())
|
||||
{
|
||||
/* Add the amount of ACKed file data to the total sent file bytes counter */
|
||||
AppState->HTTPServer.ACKedFilePos += AppState->HTTPServer.SentChunkSize;
|
||||
|
||||
/* Progress to the next state once the current state's data has been ACKed */
|
||||
AppState->HTTPServer.CurrentState = AppState->HTTPServer.NextState;
|
||||
}
|
||||
|
||||
if (uip_rexmit())
|
||||
{
|
||||
/* Return file pointer to the last ACKed position */
|
||||
f_lseek(&AppState->HTTPServer.FileHandle, AppState->HTTPServer.ACKedFilePos);
|
||||
}
|
||||
|
||||
if (uip_rexmit() || uip_acked() || uip_newdata() || uip_connected() || uip_poll())
|
||||
{
|
||||
switch (AppState->HTTPServer.CurrentState)
|
||||
{
|
||||
case WEBSERVER_STATE_OpenRequestedFile:
|
||||
HTTPServerApp_OpenRequestedFile();
|
||||
break;
|
||||
case WEBSERVER_STATE_SendResponseHeader:
|
||||
HTTPServerApp_SendResponseHeader();
|
||||
break;
|
||||
case WEBSERVER_STATE_SendData:
|
||||
HTTPServerApp_SendData();
|
||||
break;
|
||||
case WEBSERVER_STATE_Closing:
|
||||
/* Connection is being terminated for some reason - close file handle */
|
||||
f_close(&AppState->HTTPServer.FileHandle);
|
||||
AppState->HTTPServer.FileOpen = false;
|
||||
|
||||
/* If connection is not already closed, close it */
|
||||
uip_close();
|
||||
|
||||
AppState->HTTPServer.CurrentState = WEBSERVER_STATE_Closed;
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_Closed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** HTTP Server State handler for the Request Process state. This state manages the processing of incoming HTTP
|
||||
* GET requests to the server from the receiving HTTP client.
|
||||
*/
|
||||
static void HTTPServerApp_OpenRequestedFile(void)
|
||||
{
|
||||
uip_tcp_appstate_t* const AppState = &uip_conn->appstate;
|
||||
char* const AppData = (char*)uip_appdata;
|
||||
|
||||
/* No HTTP header received from the client, abort processing */
|
||||
if (!(uip_newdata()))
|
||||
return;
|
||||
|
||||
char* RequestToken = strtok(AppData, " ");
|
||||
char* RequestedFileName = strtok(NULL, " ");
|
||||
|
||||
/* Must be a GET request, abort otherwise */
|
||||
if (strcmp_P(RequestToken, PSTR("GET")) != 0)
|
||||
{
|
||||
uip_abort();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy over the requested filename */
|
||||
strncpy(AppState->HTTPServer.FileName, &RequestedFileName[1], (sizeof(AppState->HTTPServer.FileName) - 1));
|
||||
|
||||
/* Ensure filename is null-terminated */
|
||||
AppState->HTTPServer.FileName[sizeof(AppState->HTTPServer.FileName) - 1] = 0x00;
|
||||
|
||||
/* Determine the length of the URI so that it can be checked to see if it is a directory */
|
||||
uint8_t FileNameLen = strlen(AppState->HTTPServer.FileName);
|
||||
|
||||
/* If the URI is a directory, append the default filename */
|
||||
if (AppState->HTTPServer.FileName[FileNameLen - 1] == '/')
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* Try to open the file from the Dataflash disk */
|
||||
AppState->HTTPServer.FileOpen = (f_open(&AppState->HTTPServer.FileHandle, AppState->HTTPServer.FileName,
|
||||
(FA_OPEN_EXISTING | FA_READ)) == FR_OK);
|
||||
|
||||
/* Lock to the SendResponseHeader state until connection terminated */
|
||||
AppState->HTTPServer.CurrentState = WEBSERVER_STATE_SendResponseHeader;
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_SendResponseHeader;
|
||||
}
|
||||
|
||||
/** HTTP Server State handler for the HTTP Response Header Send state. This state manages the transmission of
|
||||
* the HTTP response header to the receiving HTTP client.
|
||||
*/
|
||||
static void HTTPServerApp_SendResponseHeader(void)
|
||||
{
|
||||
uip_tcp_appstate_t* const AppState = &uip_conn->appstate;
|
||||
char* const AppData = (char*)uip_appdata;
|
||||
|
||||
char* Extension = strpbrk(AppState->HTTPServer.FileName, ".");
|
||||
bool FoundMIMEType = false;
|
||||
|
||||
/* If the file isn't already open, it wasn't found - send back a 404 error response and abort */
|
||||
if (!(AppState->HTTPServer.FileOpen))
|
||||
{
|
||||
/* Copy over the HTTP 404 response header and send it to the receiving client */
|
||||
strcpy_P(AppData, HTTP404Header);
|
||||
strcpy(&AppData[strlen(AppData)], AppState->HTTPServer.FileName);
|
||||
uip_send(AppData, strlen(AppData));
|
||||
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_Closing;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy over the HTTP 200 response header and send it to the receiving client */
|
||||
strcpy_P(AppData, HTTP200Header);
|
||||
|
||||
/* Check to see if a MIME type for the requested file's extension was found */
|
||||
if (Extension != NULL)
|
||||
{
|
||||
/* Look through the MIME type list, copy over the required MIME type if found */
|
||||
for (uint8_t i = 0; i < (sizeof(MIMETypes) / sizeof(MIMETypes[0])); i++)
|
||||
{
|
||||
if (strcmp(&Extension[1], MIMETypes[i].Extension) == 0)
|
||||
{
|
||||
strcpy(&AppData[strlen(AppData)], MIMETypes[i].MIMEType);
|
||||
FoundMIMEType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if a MIME type was found and copied to the output buffer */
|
||||
if (!(FoundMIMEType))
|
||||
{
|
||||
/* MIME type not found - copy over the default MIME type */
|
||||
strcpy_P(&AppData[strlen(AppData)], DefaultMIMEType);
|
||||
}
|
||||
|
||||
/* Add the end-of-line terminator and end-of-headers terminator after the MIME type */
|
||||
strcpy_P(&AppData[strlen(AppData)], PSTR("\r\n\r\n"));
|
||||
|
||||
/* Send the MIME header to the receiving client */
|
||||
uip_send(AppData, strlen(AppData));
|
||||
|
||||
/* When the MIME header is ACKed, progress to the data send stage */
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_SendData;
|
||||
}
|
||||
|
||||
/** HTTP Server State handler for the Data Send state. This state manages the transmission of file chunks
|
||||
* to the receiving HTTP client.
|
||||
*/
|
||||
static void HTTPServerApp_SendData(void)
|
||||
{
|
||||
uip_tcp_appstate_t* const AppState = &uip_conn->appstate;
|
||||
char* const AppData = (char*)uip_appdata;
|
||||
|
||||
/* Get the maximum segment size for the current packet */
|
||||
uint16_t MaxChunkSize = uip_mss();
|
||||
|
||||
/* Read the next chunk of data from the open file */
|
||||
f_read(&AppState->HTTPServer.FileHandle, AppData, MaxChunkSize, &AppState->HTTPServer.SentChunkSize);
|
||||
|
||||
/* Send the next file chunk to the receiving client */
|
||||
uip_send(AppData, AppState->HTTPServer.SentChunkSize);
|
||||
|
||||
/* Check if we are at the last chunk of the file, if so next ACK should close the connection */
|
||||
if (MaxChunkSize != AppState->HTTPServer.SentChunkSize)
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_Closing;
|
||||
}
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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
|
||||
*
|
||||
* Simple HTTP Webserver Application. When connected to the uIP stack,
|
||||
* this will serve out files to HTTP clients on port 80.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_HTTPSERVERAPP_C
|
||||
#include "HTTPServerApp.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.
|
||||
*/
|
||||
const char PROGMEM HTTP200Header[] = "HTTP/1.1 200 OK\r\n"
|
||||
"Server: LUFA " LUFA_VERSION_STRING "\r\n"
|
||||
"Connection: close\r\n"
|
||||
"MIME-version: 1.0\r\n"
|
||||
"Content-Type: ";
|
||||
|
||||
/** HTTP server response header, for transmission before a resource not found error. This indicates to the host that the given
|
||||
* given URL is invalid, and gives extra error information.
|
||||
*/
|
||||
const char PROGMEM HTTP404Header[] = "HTTP/1.1 404 Not Found\r\n"
|
||||
"Server: LUFA " LUFA_VERSION_STRING "\r\n"
|
||||
"Connection: close\r\n"
|
||||
"MIME-version: 1.0\r\n"
|
||||
"Content-Type: text/plain\r\n\r\n"
|
||||
"Error 404: File Not Found: /";
|
||||
|
||||
/** Default filename to fetch when a directory is requested */
|
||||
const char PROGMEM DefaultDirFileName[] = "index.htm";
|
||||
|
||||
/** Default MIME type sent if no other MIME type can be determined. */
|
||||
const char PROGMEM DefaultMIMEType[] = "text/plain";
|
||||
|
||||
/** List of MIME types for each supported file extension. */
|
||||
const MIME_Type_t MIMETypes[] =
|
||||
{
|
||||
{.Extension = "htm", .MIMEType = "text/html"},
|
||||
{.Extension = "jpg", .MIMEType = "image/jpeg"},
|
||||
{.Extension = "gif", .MIMEType = "image/gif"},
|
||||
{.Extension = "bmp", .MIMEType = "image/bmp"},
|
||||
{.Extension = "png", .MIMEType = "image/png"},
|
||||
{.Extension = "ico", .MIMEType = "image/x-icon"},
|
||||
{.Extension = "exe", .MIMEType = "application/octet-stream"},
|
||||
{.Extension = "gz", .MIMEType = "application/x-gzip"},
|
||||
{.Extension = "zip", .MIMEType = "application/zip"},
|
||||
{.Extension = "pdf", .MIMEType = "application/pdf"},
|
||||
};
|
||||
|
||||
/** FATFs structure to hold the internal state of the FAT driver for the dataflash contents. */
|
||||
FATFS DiskFATState;
|
||||
|
||||
|
||||
/** Initialization function for the simple HTTP webserver. */
|
||||
void HTTPServerApp_Init(void)
|
||||
{
|
||||
/* Listen on port 80 for HTTP connections from hosts */
|
||||
uip_listen(HTONS(HTTP_SERVER_PORT));
|
||||
|
||||
/* Mount the dataflash disk via FatFS */
|
||||
f_mount(0, &DiskFATState);
|
||||
}
|
||||
|
||||
/** uIP stack application callback for the simple HTTP webserver. This function must be called each time the
|
||||
* TCP/IP stack needs a TCP packet to be processed.
|
||||
*/
|
||||
void HTTPServerApp_Callback(void)
|
||||
{
|
||||
uip_tcp_appstate_t* const AppState = &uip_conn->appstate;
|
||||
|
||||
if (uip_aborted() || uip_timedout() || uip_closed())
|
||||
{
|
||||
/* Lock to the closed state so that no further processing will occur on the connection */
|
||||
AppState->HTTPServer.CurrentState = WEBSERVER_STATE_Closing;
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_Closing;
|
||||
}
|
||||
|
||||
if (uip_connected())
|
||||
{
|
||||
/* New connection - initialize connection state values */
|
||||
AppState->HTTPServer.CurrentState = WEBSERVER_STATE_OpenRequestedFile;
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_OpenRequestedFile;
|
||||
AppState->HTTPServer.FileOpen = false;
|
||||
AppState->HTTPServer.ACKedFilePos = 0;
|
||||
AppState->HTTPServer.SentChunkSize = 0;
|
||||
}
|
||||
|
||||
if (uip_acked())
|
||||
{
|
||||
/* Add the amount of ACKed file data to the total sent file bytes counter */
|
||||
AppState->HTTPServer.ACKedFilePos += AppState->HTTPServer.SentChunkSize;
|
||||
|
||||
/* Progress to the next state once the current state's data has been ACKed */
|
||||
AppState->HTTPServer.CurrentState = AppState->HTTPServer.NextState;
|
||||
}
|
||||
|
||||
if (uip_rexmit())
|
||||
{
|
||||
/* Return file pointer to the last ACKed position */
|
||||
f_lseek(&AppState->HTTPServer.FileHandle, AppState->HTTPServer.ACKedFilePos);
|
||||
}
|
||||
|
||||
if (uip_rexmit() || uip_acked() || uip_newdata() || uip_connected() || uip_poll())
|
||||
{
|
||||
switch (AppState->HTTPServer.CurrentState)
|
||||
{
|
||||
case WEBSERVER_STATE_OpenRequestedFile:
|
||||
HTTPServerApp_OpenRequestedFile();
|
||||
break;
|
||||
case WEBSERVER_STATE_SendResponseHeader:
|
||||
HTTPServerApp_SendResponseHeader();
|
||||
break;
|
||||
case WEBSERVER_STATE_SendData:
|
||||
HTTPServerApp_SendData();
|
||||
break;
|
||||
case WEBSERVER_STATE_Closing:
|
||||
/* Connection is being terminated for some reason - close file handle */
|
||||
f_close(&AppState->HTTPServer.FileHandle);
|
||||
AppState->HTTPServer.FileOpen = false;
|
||||
|
||||
/* If connection is not already closed, close it */
|
||||
uip_close();
|
||||
|
||||
AppState->HTTPServer.CurrentState = WEBSERVER_STATE_Closed;
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_Closed;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** HTTP Server State handler for the Request Process state. This state manages the processing of incoming HTTP
|
||||
* GET requests to the server from the receiving HTTP client.
|
||||
*/
|
||||
static void HTTPServerApp_OpenRequestedFile(void)
|
||||
{
|
||||
uip_tcp_appstate_t* const AppState = &uip_conn->appstate;
|
||||
char* const AppData = (char*)uip_appdata;
|
||||
|
||||
/* No HTTP header received from the client, abort processing */
|
||||
if (!(uip_newdata()))
|
||||
return;
|
||||
|
||||
char* RequestToken = strtok(AppData, " ");
|
||||
char* RequestedFileName = strtok(NULL, " ");
|
||||
|
||||
/* Must be a GET request, abort otherwise */
|
||||
if (strcmp_P(RequestToken, PSTR("GET")) != 0)
|
||||
{
|
||||
uip_abort();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy over the requested filename */
|
||||
strncpy(AppState->HTTPServer.FileName, &RequestedFileName[1], (sizeof(AppState->HTTPServer.FileName) - 1));
|
||||
|
||||
/* Ensure filename is null-terminated */
|
||||
AppState->HTTPServer.FileName[sizeof(AppState->HTTPServer.FileName) - 1] = 0x00;
|
||||
|
||||
/* Determine the length of the URI so that it can be checked to see if it is a directory */
|
||||
uint8_t FileNameLen = strlen(AppState->HTTPServer.FileName);
|
||||
|
||||
/* If the URI is a directory, append the default filename */
|
||||
if (AppState->HTTPServer.FileName[FileNameLen - 1] == '/')
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* Try to open the file from the Dataflash disk */
|
||||
AppState->HTTPServer.FileOpen = (f_open(&AppState->HTTPServer.FileHandle, AppState->HTTPServer.FileName,
|
||||
(FA_OPEN_EXISTING | FA_READ)) == FR_OK);
|
||||
|
||||
/* Lock to the SendResponseHeader state until connection terminated */
|
||||
AppState->HTTPServer.CurrentState = WEBSERVER_STATE_SendResponseHeader;
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_SendResponseHeader;
|
||||
}
|
||||
|
||||
/** HTTP Server State handler for the HTTP Response Header Send state. This state manages the transmission of
|
||||
* the HTTP response header to the receiving HTTP client.
|
||||
*/
|
||||
static void HTTPServerApp_SendResponseHeader(void)
|
||||
{
|
||||
uip_tcp_appstate_t* const AppState = &uip_conn->appstate;
|
||||
char* const AppData = (char*)uip_appdata;
|
||||
|
||||
char* Extension = strpbrk(AppState->HTTPServer.FileName, ".");
|
||||
bool FoundMIMEType = false;
|
||||
|
||||
/* If the file isn't already open, it wasn't found - send back a 404 error response and abort */
|
||||
if (!(AppState->HTTPServer.FileOpen))
|
||||
{
|
||||
/* Copy over the HTTP 404 response header and send it to the receiving client */
|
||||
strcpy_P(AppData, HTTP404Header);
|
||||
strcpy(&AppData[strlen(AppData)], AppState->HTTPServer.FileName);
|
||||
uip_send(AppData, strlen(AppData));
|
||||
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_Closing;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy over the HTTP 200 response header and send it to the receiving client */
|
||||
strcpy_P(AppData, HTTP200Header);
|
||||
|
||||
/* Check to see if a MIME type for the requested file's extension was found */
|
||||
if (Extension != NULL)
|
||||
{
|
||||
/* Look through the MIME type list, copy over the required MIME type if found */
|
||||
for (uint8_t i = 0; i < (sizeof(MIMETypes) / sizeof(MIMETypes[0])); i++)
|
||||
{
|
||||
if (strcmp(&Extension[1], MIMETypes[i].Extension) == 0)
|
||||
{
|
||||
strcpy(&AppData[strlen(AppData)], MIMETypes[i].MIMEType);
|
||||
FoundMIMEType = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if a MIME type was found and copied to the output buffer */
|
||||
if (!(FoundMIMEType))
|
||||
{
|
||||
/* MIME type not found - copy over the default MIME type */
|
||||
strcpy_P(&AppData[strlen(AppData)], DefaultMIMEType);
|
||||
}
|
||||
|
||||
/* Add the end-of-line terminator and end-of-headers terminator after the MIME type */
|
||||
strcpy_P(&AppData[strlen(AppData)], PSTR("\r\n\r\n"));
|
||||
|
||||
/* Send the MIME header to the receiving client */
|
||||
uip_send(AppData, strlen(AppData));
|
||||
|
||||
/* When the MIME header is ACKed, progress to the data send stage */
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_SendData;
|
||||
}
|
||||
|
||||
/** HTTP Server State handler for the Data Send state. This state manages the transmission of file chunks
|
||||
* to the receiving HTTP client.
|
||||
*/
|
||||
static void HTTPServerApp_SendData(void)
|
||||
{
|
||||
uip_tcp_appstate_t* const AppState = &uip_conn->appstate;
|
||||
char* const AppData = (char*)uip_appdata;
|
||||
|
||||
/* Get the maximum segment size for the current packet */
|
||||
uint16_t MaxChunkSize = uip_mss();
|
||||
|
||||
/* Read the next chunk of data from the open file */
|
||||
f_read(&AppState->HTTPServer.FileHandle, AppData, MaxChunkSize, &AppState->HTTPServer.SentChunkSize);
|
||||
|
||||
/* Send the next file chunk to the receiving client */
|
||||
uip_send(AppData, AppState->HTTPServer.SentChunkSize);
|
||||
|
||||
/* Check if we are at the last chunk of the file, if so next ACK should close the connection */
|
||||
if (MaxChunkSize != AppState->HTTPServer.SentChunkSize)
|
||||
AppState->HTTPServer.NextState = WEBSERVER_STATE_Closing;
|
||||
}
|
||||
|
|
|
@ -1,81 +1,81 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 HTTPServerApp.c.
|
||||
*/
|
||||
|
||||
#ifndef _HTTPSERVER_APP_H_
|
||||
#define _HTTPSERVER_APP_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/pgmspace.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <LUFA/Version.h>
|
||||
|
||||
#include <uip.h>
|
||||
#include <ff.h>
|
||||
|
||||
/* Enums: */
|
||||
/** States for each HTTP connection to the webserver. */
|
||||
enum Webserver_States_t
|
||||
{
|
||||
WEBSERVER_STATE_OpenRequestedFile, /**< Currently opening requested file */
|
||||
WEBSERVER_STATE_SendResponseHeader, /**< Currently sending HTTP response headers to the client */
|
||||
WEBSERVER_STATE_SendData, /**< Currently sending HTTP page data to the client */
|
||||
WEBSERVER_STATE_Closing, /**< Ready to close the connection to the client */
|
||||
WEBSERVER_STATE_Closed, /**< Connection closed after all data sent */
|
||||
};
|
||||
|
||||
/* Type Defines: */
|
||||
/** Type define for a MIME type handler. */
|
||||
typedef struct
|
||||
{
|
||||
char* Extension; /**< File extension (no leading '.' character) */
|
||||
char* MIMEType; /**< Appropriate MIME type to send when the extension is encountered */
|
||||
} MIME_Type_t;
|
||||
|
||||
/* Macros: */
|
||||
/** TCP listen port for incoming HTTP traffic */
|
||||
#define HTTP_SERVER_PORT 80
|
||||
|
||||
/* Function Prototypes: */
|
||||
void HTTPServerApp_Init(void);
|
||||
void HTTPServerApp_Callback(void);
|
||||
|
||||
#if defined(INCLUDE_FROM_HTTPSERVERAPP_C)
|
||||
static void HTTPServerApp_OpenRequestedFile(void);
|
||||
static void HTTPServerApp_SendResponseHeader(void);
|
||||
static void HTTPServerApp_SendData(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 HTTPServerApp.c.
|
||||
*/
|
||||
|
||||
#ifndef _HTTPSERVER_APP_H_
|
||||
#define _HTTPSERVER_APP_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/pgmspace.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <LUFA/Version.h>
|
||||
|
||||
#include <uip.h>
|
||||
#include <ff.h>
|
||||
|
||||
/* Enums: */
|
||||
/** States for each HTTP connection to the webserver. */
|
||||
enum Webserver_States_t
|
||||
{
|
||||
WEBSERVER_STATE_OpenRequestedFile, /**< Currently opening requested file */
|
||||
WEBSERVER_STATE_SendResponseHeader, /**< Currently sending HTTP response headers to the client */
|
||||
WEBSERVER_STATE_SendData, /**< Currently sending HTTP page data to the client */
|
||||
WEBSERVER_STATE_Closing, /**< Ready to close the connection to the client */
|
||||
WEBSERVER_STATE_Closed, /**< Connection closed after all data sent */
|
||||
};
|
||||
|
||||
/* Type Defines: */
|
||||
/** Type define for a MIME type handler. */
|
||||
typedef struct
|
||||
{
|
||||
char* Extension; /**< File extension (no leading '.' character) */
|
||||
char* MIMEType; /**< Appropriate MIME type to send when the extension is encountered */
|
||||
} MIME_Type_t;
|
||||
|
||||
/* Macros: */
|
||||
/** TCP listen port for incoming HTTP traffic */
|
||||
#define HTTP_SERVER_PORT 80
|
||||
|
||||
/* Function Prototypes: */
|
||||
void HTTPServerApp_Init(void);
|
||||
void HTTPServerApp_Callback(void);
|
||||
|
||||
#if defined(INCLUDE_FROM_HTTPSERVERAPP_C)
|
||||
static void HTTPServerApp_OpenRequestedFile(void);
|
||||
static void HTTPServerApp_SendResponseHeader(void);
|
||||
static void HTTPServerApp_SendData(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,281 +1,281 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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
|
||||
*
|
||||
* SCSI command processing routines, for SCSI commands issued by the host. Mass Storage
|
||||
* devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,
|
||||
* which wrap around standard SCSI device commands for controlling the actual storage medium.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_SCSI_C
|
||||
#include "SCSI.h"
|
||||
|
||||
/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's
|
||||
* features and capabilities.
|
||||
*/
|
||||
SCSI_Inquiry_Response_t InquiryData =
|
||||
{
|
||||
.DeviceType = DEVICE_TYPE_BLOCK,
|
||||
.PeripheralQualifier = 0,
|
||||
|
||||
.Removable = true,
|
||||
|
||||
.Version = 0,
|
||||
|
||||
.ResponseDataFormat = 2,
|
||||
.NormACA = false,
|
||||
.TrmTsk = false,
|
||||
.AERC = false,
|
||||
|
||||
.AdditionalLength = 0x1F,
|
||||
|
||||
.SoftReset = false,
|
||||
.CmdQue = false,
|
||||
.Linked = false,
|
||||
.Sync = false,
|
||||
.WideBus16Bit = false,
|
||||
.WideBus32Bit = false,
|
||||
.RelAddr = false,
|
||||
|
||||
.VendorID = "LUFA",
|
||||
.ProductID = "Dataflash Disk",
|
||||
.RevisionID = {'0','.','0','0'},
|
||||
};
|
||||
|
||||
/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE
|
||||
* command is issued. This gives information on exactly why the last command failed to complete.
|
||||
*/
|
||||
SCSI_Request_Sense_Response_t SenseData =
|
||||
{
|
||||
.ResponseCode = 0x70,
|
||||
.AdditionalLength = 0x0A,
|
||||
};
|
||||
|
||||
|
||||
/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches
|
||||
* to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns
|
||||
* a command failure due to a ILLEGAL REQUEST.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
*/
|
||||
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
/* Set initial sense data, before the requested command is processed */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
|
||||
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
|
||||
/* Run the appropriate SCSI command hander function based on the passed command */
|
||||
switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
|
||||
{
|
||||
case SCSI_CMD_INQUIRY:
|
||||
SCSI_Command_Inquiry(MSInterfaceInfo);
|
||||
break;
|
||||
case SCSI_CMD_REQUEST_SENSE:
|
||||
SCSI_Command_Request_Sense(MSInterfaceInfo);
|
||||
break;
|
||||
case SCSI_CMD_READ_CAPACITY_10:
|
||||
SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
|
||||
break;
|
||||
case SCSI_CMD_SEND_DIAGNOSTIC:
|
||||
SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
|
||||
break;
|
||||
case SCSI_CMD_WRITE_10:
|
||||
SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
|
||||
break;
|
||||
case SCSI_CMD_READ_10:
|
||||
SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
|
||||
break;
|
||||
case SCSI_CMD_TEST_UNIT_READY:
|
||||
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
|
||||
case SCSI_CMD_VERIFY_10:
|
||||
/* These commands should just succeed, no handling required */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
|
||||
break;
|
||||
default:
|
||||
/* Update the SENSE key to reflect the invalid command */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||
SCSI_ASENSE_INVALID_COMMAND,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
break;
|
||||
}
|
||||
|
||||
return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD);
|
||||
}
|
||||
|
||||
/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
|
||||
* and capabilities to the host.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
*/
|
||||
static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
uint16_t AllocationLength = (((uint16_t)MSInterfaceInfo->State.CommandBlock.SCSICommandData[3] << 8) |
|
||||
MSInterfaceInfo->State.CommandBlock.SCSICommandData[4]);
|
||||
uint16_t BytesTransferred = (AllocationLength < sizeof(InquiryData))? AllocationLength :
|
||||
sizeof(InquiryData);
|
||||
|
||||
/* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */
|
||||
if ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
|
||||
MSInterfaceInfo->State.CommandBlock.SCSICommandData[2])
|
||||
{
|
||||
/* Optional but unsupported bits set - update the SENSE key and fail the request */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK);
|
||||
|
||||
uint8_t PadBytes[AllocationLength - BytesTransferred];
|
||||
|
||||
/* Pad out remaining bytes with 0x00 */
|
||||
Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), NO_STREAM_CALLBACK);
|
||||
|
||||
/* Finalize the stream transfer to send the last packet */
|
||||
Endpoint_ClearIN();
|
||||
|
||||
/* Succeed the command and update the bytes transferred counter */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
|
||||
}
|
||||
|
||||
/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
|
||||
* including the error code and additional error information so that the host can determine why a command failed to complete.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
*/
|
||||
static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
uint8_t AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
|
||||
uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
|
||||
|
||||
uint8_t PadBytes[AllocationLength - BytesTransferred];
|
||||
|
||||
Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NO_STREAM_CALLBACK);
|
||||
Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), NO_STREAM_CALLBACK);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
/* Succeed the command and update the bytes transferred counter */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
|
||||
}
|
||||
|
||||
/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
|
||||
* on the selected Logical Unit (drive), as a number of OS-sized blocks.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
*/
|
||||
static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
uint32_t LastBlockAddressInLUN = (VIRTUAL_MEMORY_BLOCKS - 1);
|
||||
uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE;
|
||||
|
||||
Endpoint_Write_Stream_BE(&LastBlockAddressInLUN, sizeof(LastBlockAddressInLUN), NO_STREAM_CALLBACK);
|
||||
Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NO_STREAM_CALLBACK);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
/* Succeed the command and update the bytes transferred counter */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
|
||||
}
|
||||
|
||||
/** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
|
||||
* board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is
|
||||
* supported.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
*/
|
||||
static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
/* Check to see if the SELF TEST bit is not set */
|
||||
if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
|
||||
{
|
||||
/* Only self-test supported - update SENSE key and fail the command */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check to see if all attached Dataflash ICs are functional */
|
||||
if (!(DataflashManager_CheckDataflashOperation()))
|
||||
{
|
||||
/* Update SENSE key with a hardware error condition and return command fail */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,
|
||||
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Succeed the command and update the bytes transferred counter */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
|
||||
}
|
||||
|
||||
/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
|
||||
* and total number of blocks to process, then calls the appropriate low-level dataflash routine to handle the actual
|
||||
* reading and writing of the data.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
* \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
|
||||
*/
|
||||
static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead)
|
||||
{
|
||||
uint32_t BlockAddress;
|
||||
uint16_t TotalBlocks;
|
||||
|
||||
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
|
||||
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
|
||||
|
||||
/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
|
||||
TotalBlocks = SwapEndian_16(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
|
||||
|
||||
/* Check if the block address is outside the maximum allowable value for the LUN */
|
||||
if (BlockAddress >= VIRTUAL_MEMORY_BLOCKS)
|
||||
{
|
||||
/* Block address is invalid, update SENSE key and return command fail */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||
SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
||||
if (IsDataRead == DATA_READ)
|
||||
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
||||
else
|
||||
DataflashManager_WriteBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
||||
|
||||
/* Update the bytes transferred counter and succeed the command */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
|
||||
}
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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
|
||||
*
|
||||
* SCSI command processing routines, for SCSI commands issued by the host. Mass Storage
|
||||
* devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,
|
||||
* which wrap around standard SCSI device commands for controlling the actual storage medium.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_SCSI_C
|
||||
#include "SCSI.h"
|
||||
|
||||
/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's
|
||||
* features and capabilities.
|
||||
*/
|
||||
SCSI_Inquiry_Response_t InquiryData =
|
||||
{
|
||||
.DeviceType = DEVICE_TYPE_BLOCK,
|
||||
.PeripheralQualifier = 0,
|
||||
|
||||
.Removable = true,
|
||||
|
||||
.Version = 0,
|
||||
|
||||
.ResponseDataFormat = 2,
|
||||
.NormACA = false,
|
||||
.TrmTsk = false,
|
||||
.AERC = false,
|
||||
|
||||
.AdditionalLength = 0x1F,
|
||||
|
||||
.SoftReset = false,
|
||||
.CmdQue = false,
|
||||
.Linked = false,
|
||||
.Sync = false,
|
||||
.WideBus16Bit = false,
|
||||
.WideBus32Bit = false,
|
||||
.RelAddr = false,
|
||||
|
||||
.VendorID = "LUFA",
|
||||
.ProductID = "Dataflash Disk",
|
||||
.RevisionID = {'0','.','0','0'},
|
||||
};
|
||||
|
||||
/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE
|
||||
* command is issued. This gives information on exactly why the last command failed to complete.
|
||||
*/
|
||||
SCSI_Request_Sense_Response_t SenseData =
|
||||
{
|
||||
.ResponseCode = 0x70,
|
||||
.AdditionalLength = 0x0A,
|
||||
};
|
||||
|
||||
|
||||
/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches
|
||||
* to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns
|
||||
* a command failure due to a ILLEGAL REQUEST.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
*/
|
||||
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
/* Set initial sense data, before the requested command is processed */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
|
||||
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
|
||||
/* Run the appropriate SCSI command hander function based on the passed command */
|
||||
switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
|
||||
{
|
||||
case SCSI_CMD_INQUIRY:
|
||||
SCSI_Command_Inquiry(MSInterfaceInfo);
|
||||
break;
|
||||
case SCSI_CMD_REQUEST_SENSE:
|
||||
SCSI_Command_Request_Sense(MSInterfaceInfo);
|
||||
break;
|
||||
case SCSI_CMD_READ_CAPACITY_10:
|
||||
SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
|
||||
break;
|
||||
case SCSI_CMD_SEND_DIAGNOSTIC:
|
||||
SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
|
||||
break;
|
||||
case SCSI_CMD_WRITE_10:
|
||||
SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
|
||||
break;
|
||||
case SCSI_CMD_READ_10:
|
||||
SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
|
||||
break;
|
||||
case SCSI_CMD_TEST_UNIT_READY:
|
||||
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
|
||||
case SCSI_CMD_VERIFY_10:
|
||||
/* These commands should just succeed, no handling required */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
|
||||
break;
|
||||
default:
|
||||
/* Update the SENSE key to reflect the invalid command */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||
SCSI_ASENSE_INVALID_COMMAND,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
break;
|
||||
}
|
||||
|
||||
return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD);
|
||||
}
|
||||
|
||||
/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
|
||||
* and capabilities to the host.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
*/
|
||||
static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
uint16_t AllocationLength = (((uint16_t)MSInterfaceInfo->State.CommandBlock.SCSICommandData[3] << 8) |
|
||||
MSInterfaceInfo->State.CommandBlock.SCSICommandData[4]);
|
||||
uint16_t BytesTransferred = (AllocationLength < sizeof(InquiryData))? AllocationLength :
|
||||
sizeof(InquiryData);
|
||||
|
||||
/* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */
|
||||
if ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
|
||||
MSInterfaceInfo->State.CommandBlock.SCSICommandData[2])
|
||||
{
|
||||
/* Optional but unsupported bits set - update the SENSE key and fail the request */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK);
|
||||
|
||||
uint8_t PadBytes[AllocationLength - BytesTransferred];
|
||||
|
||||
/* Pad out remaining bytes with 0x00 */
|
||||
Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), NO_STREAM_CALLBACK);
|
||||
|
||||
/* Finalize the stream transfer to send the last packet */
|
||||
Endpoint_ClearIN();
|
||||
|
||||
/* Succeed the command and update the bytes transferred counter */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
|
||||
}
|
||||
|
||||
/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
|
||||
* including the error code and additional error information so that the host can determine why a command failed to complete.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
*/
|
||||
static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
uint8_t AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
|
||||
uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
|
||||
|
||||
uint8_t PadBytes[AllocationLength - BytesTransferred];
|
||||
|
||||
Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NO_STREAM_CALLBACK);
|
||||
Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), NO_STREAM_CALLBACK);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
/* Succeed the command and update the bytes transferred counter */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
|
||||
}
|
||||
|
||||
/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
|
||||
* on the selected Logical Unit (drive), as a number of OS-sized blocks.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
*/
|
||||
static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
uint32_t LastBlockAddressInLUN = (VIRTUAL_MEMORY_BLOCKS - 1);
|
||||
uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE;
|
||||
|
||||
Endpoint_Write_Stream_BE(&LastBlockAddressInLUN, sizeof(LastBlockAddressInLUN), NO_STREAM_CALLBACK);
|
||||
Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NO_STREAM_CALLBACK);
|
||||
Endpoint_ClearIN();
|
||||
|
||||
/* Succeed the command and update the bytes transferred counter */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
|
||||
}
|
||||
|
||||
/** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
|
||||
* board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is
|
||||
* supported.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
*/
|
||||
static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||
{
|
||||
/* Check to see if the SELF TEST bit is not set */
|
||||
if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
|
||||
{
|
||||
/* Only self-test supported - update SENSE key and fail the command */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check to see if all attached Dataflash ICs are functional */
|
||||
if (!(DataflashManager_CheckDataflashOperation()))
|
||||
{
|
||||
/* Update SENSE key with a hardware error condition and return command fail */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,
|
||||
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Succeed the command and update the bytes transferred counter */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
|
||||
}
|
||||
|
||||
/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
|
||||
* and total number of blocks to process, then calls the appropriate low-level dataflash routine to handle the actual
|
||||
* reading and writing of the data.
|
||||
*
|
||||
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||
* \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
|
||||
*/
|
||||
static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead)
|
||||
{
|
||||
uint32_t BlockAddress;
|
||||
uint16_t TotalBlocks;
|
||||
|
||||
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
|
||||
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
|
||||
|
||||
/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
|
||||
TotalBlocks = SwapEndian_16(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
|
||||
|
||||
/* Check if the block address is outside the maximum allowable value for the LUN */
|
||||
if (BlockAddress >= VIRTUAL_MEMORY_BLOCKS)
|
||||
{
|
||||
/* Block address is invalid, update SENSE key and return command fail */
|
||||
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||
SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
|
||||
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
||||
if (IsDataRead == DATA_READ)
|
||||
DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
||||
else
|
||||
DataflashManager_WriteBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
||||
|
||||
/* Update the bytes transferred counter and succeed the command */
|
||||
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
|
||||
}
|
||||
|
|
|
@ -1,85 +1,85 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 SCSI.c.
|
||||
*/
|
||||
|
||||
#ifndef _SCSI_H_
|
||||
#define _SCSI_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
#include <LUFA/Drivers/USB/Class/MassStorage.h>
|
||||
|
||||
#include "../Descriptors.h"
|
||||
#include "DataflashManager.h"
|
||||
|
||||
/* Macros: */
|
||||
/** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This
|
||||
* is for convenience, as it allows for all three sense values (returned upon request to the host to give information about
|
||||
* the last command failure) in a quick and easy manner.
|
||||
*
|
||||
* \param[in] key New SCSI sense key to set the sense code to
|
||||
* \param[in] acode New SCSI additional sense key to set the additional sense code to
|
||||
* \param[in] aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to
|
||||
*/
|
||||
#define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = (key); \
|
||||
SenseData.AdditionalSenseCode = (acode); \
|
||||
SenseData.AdditionalSenseQualifier = (aqual); }MACROE
|
||||
|
||||
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
|
||||
#define DATA_READ true
|
||||
|
||||
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */
|
||||
#define DATA_WRITE false
|
||||
|
||||
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */
|
||||
#define DEVICE_TYPE_BLOCK 0x00
|
||||
|
||||
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a CD-ROM device. */
|
||||
#define DEVICE_TYPE_CDROM 0x05
|
||||
|
||||
/* Function Prototypes: */
|
||||
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||
|
||||
#if defined(INCLUDE_FROM_SCSI_C)
|
||||
static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||
static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||
static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||
static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||
static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 SCSI.c.
|
||||
*/
|
||||
|
||||
#ifndef _SCSI_H_
|
||||
#define _SCSI_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
#include <LUFA/Drivers/USB/Class/MassStorage.h>
|
||||
|
||||
#include "../Descriptors.h"
|
||||
#include "DataflashManager.h"
|
||||
|
||||
/* Macros: */
|
||||
/** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This
|
||||
* is for convenience, as it allows for all three sense values (returned upon request to the host to give information about
|
||||
* the last command failure) in a quick and easy manner.
|
||||
*
|
||||
* \param[in] key New SCSI sense key to set the sense code to
|
||||
* \param[in] acode New SCSI additional sense key to set the additional sense code to
|
||||
* \param[in] aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to
|
||||
*/
|
||||
#define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = (key); \
|
||||
SenseData.AdditionalSenseCode = (acode); \
|
||||
SenseData.AdditionalSenseQualifier = (aqual); }MACROE
|
||||
|
||||
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
|
||||
#define DATA_READ true
|
||||
|
||||
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */
|
||||
#define DATA_WRITE false
|
||||
|
||||
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */
|
||||
#define DEVICE_TYPE_BLOCK 0x00
|
||||
|
||||
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a CD-ROM device. */
|
||||
#define DEVICE_TYPE_CDROM 0x05
|
||||
|
||||
/* Function Prototypes: */
|
||||
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||
|
||||
#if defined(INCLUDE_FROM_SCSI_C)
|
||||
static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||
static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||
static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||
static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||
static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, const bool IsDataRead);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,162 +1,162 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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_TELNET_SERVER) || defined(__DOXYGEN__)
|
||||
|
||||
/** \file
|
||||
*
|
||||
* TELNET Webserver Application. When connected to the uIP stack,
|
||||
* this will serve out raw TELNET to the client on port 23.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_TELNETSERVERAPP_C
|
||||
#include "TELNETServerApp.h"
|
||||
|
||||
/** Welcome message to send to a TELNET client when a connection is first made. */
|
||||
const char PROGMEM WelcomeHeader[] = "********************************************\r\n"
|
||||
"* LUFA uIP Webserver (TELNET) *\r\n"
|
||||
"********************************************\r\n";
|
||||
|
||||
/** Main TELNET menu, giving the user the list of available commands they may issue */
|
||||
const char PROGMEM TELNETMenu[] = "\r\n"
|
||||
" == Available Commands: ==\r\n"
|
||||
" c) List Active TCP Connections\r\n"
|
||||
" =========================\r\n"
|
||||
"\r\n>";
|
||||
|
||||
/** Header to print before the current connections are printed to the client */
|
||||
const char PROGMEM CurrentConnectionsHeader[] = "\r\n* Current TCP Connections: *\r\n";
|
||||
|
||||
/** Initialization function for the simple HTTP webserver. */
|
||||
void TELNETServerApp_Init(void)
|
||||
{
|
||||
/* Listen on port 23 for TELNET connections from hosts */
|
||||
uip_listen(HTONS(TELNET_SERVER_PORT));
|
||||
}
|
||||
|
||||
/** uIP stack application callback for the TELNET server. This function must be called each time the
|
||||
* TCP/IP stack needs a TCP packet to be processed.
|
||||
*/
|
||||
void TELNETServerApp_Callback(void)
|
||||
{
|
||||
uip_tcp_appstate_t* const AppState = &uip_conn->appstate;
|
||||
char* const AppData = (char*)uip_appdata;
|
||||
|
||||
if (uip_connected())
|
||||
{
|
||||
/* New connection - initialize connection state values */
|
||||
AppState->TELNETServer.CurrentState = TELNET_STATE_SendHeader;
|
||||
}
|
||||
|
||||
if (uip_acked())
|
||||
{
|
||||
/* Progress to the next state once the current state's data has been ACKed */
|
||||
AppState->TELNETServer.CurrentState = AppState->TELNETServer.NextState;
|
||||
}
|
||||
|
||||
if (uip_rexmit() || uip_acked() || uip_newdata() || uip_connected() || uip_poll())
|
||||
{
|
||||
switch (AppState->TELNETServer.CurrentState)
|
||||
{
|
||||
case TELNET_STATE_SendHeader:
|
||||
/* Copy over and send the TELNET welcome message upon first connection */
|
||||
strcpy_P(AppData, WelcomeHeader);
|
||||
uip_send(AppData, strlen(AppData));
|
||||
|
||||
AppState->TELNETServer.NextState = TELNET_STATE_SendMenu;
|
||||
break;
|
||||
case TELNET_STATE_SendMenu:
|
||||
/* Copy over and send the TELNET menu to the client */
|
||||
strcpy_P(AppData, TELNETMenu);
|
||||
uip_send(AppData, strlen(AppData));
|
||||
|
||||
AppState->TELNETServer.NextState = TELNET_STATE_GetCommand;
|
||||
break;
|
||||
case TELNET_STATE_GetCommand:
|
||||
if (!(uip_datalen()))
|
||||
break;
|
||||
|
||||
/* Save the issued command for later processing */
|
||||
AppState->TELNETServer.IssuedCommand = AppData[0];
|
||||
|
||||
AppState->TELNETServer.CurrentState = TELNET_STATE_SendResponse;
|
||||
break;
|
||||
case TELNET_STATE_SendResponse:
|
||||
/* Determine which command was issued, perform command processing */
|
||||
switch (AppState->TELNETServer.IssuedCommand)
|
||||
{
|
||||
case 'c':
|
||||
TELNETServerApp_DisplayTCPConnections();
|
||||
break;
|
||||
default:
|
||||
strcpy_P(AppData, PSTR("Invalid Command.\r\n"));
|
||||
uip_send(AppData, strlen(AppData));
|
||||
break;
|
||||
}
|
||||
|
||||
AppState->TELNETServer.NextState = TELNET_STATE_SendMenu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Sends a list of active TCP connections to the TELNET client. */
|
||||
static void TELNETServerApp_DisplayTCPConnections(void)
|
||||
{
|
||||
char* const AppData = (char*)uip_appdata;
|
||||
|
||||
strcpy_P(AppData, CurrentConnectionsHeader);
|
||||
|
||||
uint16_t ResponseLen = strlen(AppData);
|
||||
uint8_t ActiveConnCount = 0;
|
||||
|
||||
/* Loop through the complete uIP TCP connections list, looking for active connections */
|
||||
for (uint8_t i = 0; i < UIP_CONNS; i++)
|
||||
{
|
||||
struct uip_conn* CurrConnection = &uip_conns[i];
|
||||
|
||||
/* If the connection is not closed, it is active and must be added to the out buffer */
|
||||
if (CurrConnection->tcpstateflags != UIP_CLOSED)
|
||||
{
|
||||
/* Add the current connection's details to the out buffer */
|
||||
ResponseLen += sprintf_P(&AppData[ResponseLen], PSTR("%u) %02d.%02d.%02d.%02d (Local %u, Remote %u)\r\n"),
|
||||
++ActiveConnCount,
|
||||
CurrConnection->ripaddr.u8[0],
|
||||
CurrConnection->ripaddr.u8[1],
|
||||
CurrConnection->ripaddr.u8[2],
|
||||
CurrConnection->ripaddr.u8[3],
|
||||
HTONS(CurrConnection->lport), HTONS(CurrConnection->rport));
|
||||
}
|
||||
}
|
||||
|
||||
uip_send(AppData, ResponseLen);
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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_TELNET_SERVER) || defined(__DOXYGEN__)
|
||||
|
||||
/** \file
|
||||
*
|
||||
* TELNET Webserver Application. When connected to the uIP stack,
|
||||
* this will serve out raw TELNET to the client on port 23.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_TELNETSERVERAPP_C
|
||||
#include "TELNETServerApp.h"
|
||||
|
||||
/** Welcome message to send to a TELNET client when a connection is first made. */
|
||||
const char PROGMEM WelcomeHeader[] = "********************************************\r\n"
|
||||
"* LUFA uIP Webserver (TELNET) *\r\n"
|
||||
"********************************************\r\n";
|
||||
|
||||
/** Main TELNET menu, giving the user the list of available commands they may issue */
|
||||
const char PROGMEM TELNETMenu[] = "\r\n"
|
||||
" == Available Commands: ==\r\n"
|
||||
" c) List Active TCP Connections\r\n"
|
||||
" =========================\r\n"
|
||||
"\r\n>";
|
||||
|
||||
/** Header to print before the current connections are printed to the client */
|
||||
const char PROGMEM CurrentConnectionsHeader[] = "\r\n* Current TCP Connections: *\r\n";
|
||||
|
||||
/** Initialization function for the simple HTTP webserver. */
|
||||
void TELNETServerApp_Init(void)
|
||||
{
|
||||
/* Listen on port 23 for TELNET connections from hosts */
|
||||
uip_listen(HTONS(TELNET_SERVER_PORT));
|
||||
}
|
||||
|
||||
/** uIP stack application callback for the TELNET server. This function must be called each time the
|
||||
* TCP/IP stack needs a TCP packet to be processed.
|
||||
*/
|
||||
void TELNETServerApp_Callback(void)
|
||||
{
|
||||
uip_tcp_appstate_t* const AppState = &uip_conn->appstate;
|
||||
char* const AppData = (char*)uip_appdata;
|
||||
|
||||
if (uip_connected())
|
||||
{
|
||||
/* New connection - initialize connection state values */
|
||||
AppState->TELNETServer.CurrentState = TELNET_STATE_SendHeader;
|
||||
}
|
||||
|
||||
if (uip_acked())
|
||||
{
|
||||
/* Progress to the next state once the current state's data has been ACKed */
|
||||
AppState->TELNETServer.CurrentState = AppState->TELNETServer.NextState;
|
||||
}
|
||||
|
||||
if (uip_rexmit() || uip_acked() || uip_newdata() || uip_connected() || uip_poll())
|
||||
{
|
||||
switch (AppState->TELNETServer.CurrentState)
|
||||
{
|
||||
case TELNET_STATE_SendHeader:
|
||||
/* Copy over and send the TELNET welcome message upon first connection */
|
||||
strcpy_P(AppData, WelcomeHeader);
|
||||
uip_send(AppData, strlen(AppData));
|
||||
|
||||
AppState->TELNETServer.NextState = TELNET_STATE_SendMenu;
|
||||
break;
|
||||
case TELNET_STATE_SendMenu:
|
||||
/* Copy over and send the TELNET menu to the client */
|
||||
strcpy_P(AppData, TELNETMenu);
|
||||
uip_send(AppData, strlen(AppData));
|
||||
|
||||
AppState->TELNETServer.NextState = TELNET_STATE_GetCommand;
|
||||
break;
|
||||
case TELNET_STATE_GetCommand:
|
||||
if (!(uip_datalen()))
|
||||
break;
|
||||
|
||||
/* Save the issued command for later processing */
|
||||
AppState->TELNETServer.IssuedCommand = AppData[0];
|
||||
|
||||
AppState->TELNETServer.CurrentState = TELNET_STATE_SendResponse;
|
||||
break;
|
||||
case TELNET_STATE_SendResponse:
|
||||
/* Determine which command was issued, perform command processing */
|
||||
switch (AppState->TELNETServer.IssuedCommand)
|
||||
{
|
||||
case 'c':
|
||||
TELNETServerApp_DisplayTCPConnections();
|
||||
break;
|
||||
default:
|
||||
strcpy_P(AppData, PSTR("Invalid Command.\r\n"));
|
||||
uip_send(AppData, strlen(AppData));
|
||||
break;
|
||||
}
|
||||
|
||||
AppState->TELNETServer.NextState = TELNET_STATE_SendMenu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Sends a list of active TCP connections to the TELNET client. */
|
||||
static void TELNETServerApp_DisplayTCPConnections(void)
|
||||
{
|
||||
char* const AppData = (char*)uip_appdata;
|
||||
|
||||
strcpy_P(AppData, CurrentConnectionsHeader);
|
||||
|
||||
uint16_t ResponseLen = strlen(AppData);
|
||||
uint8_t ActiveConnCount = 0;
|
||||
|
||||
/* Loop through the complete uIP TCP connections list, looking for active connections */
|
||||
for (uint8_t i = 0; i < UIP_CONNS; i++)
|
||||
{
|
||||
struct uip_conn* CurrConnection = &uip_conns[i];
|
||||
|
||||
/* If the connection is not closed, it is active and must be added to the out buffer */
|
||||
if (CurrConnection->tcpstateflags != UIP_CLOSED)
|
||||
{
|
||||
/* Add the current connection's details to the out buffer */
|
||||
ResponseLen += sprintf_P(&AppData[ResponseLen], PSTR("%u) %02d.%02d.%02d.%02d (Local %u, Remote %u)\r\n"),
|
||||
++ActiveConnCount,
|
||||
CurrConnection->ripaddr.u8[0],
|
||||
CurrConnection->ripaddr.u8[1],
|
||||
CurrConnection->ripaddr.u8[2],
|
||||
CurrConnection->ripaddr.u8[3],
|
||||
HTONS(CurrConnection->lport), HTONS(CurrConnection->rport));
|
||||
}
|
||||
}
|
||||
|
||||
uip_send(AppData, ResponseLen);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,68 +1,68 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 TELNETServerApp.c.
|
||||
*/
|
||||
|
||||
#ifndef _TELNETSERVER_APP_H_
|
||||
#define _TELNETSERVER_APP_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/pgmspace.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <uip.h>
|
||||
|
||||
/* Macros: */
|
||||
/** TCP listen port for incoming TELNET traffic */
|
||||
#define TELNET_SERVER_PORT 23
|
||||
|
||||
/* Enums: */
|
||||
/** States for each TELNET connection to the server. */
|
||||
enum TELNET_States_t
|
||||
{
|
||||
TELNET_STATE_SendHeader, /**< Currently sending welcome header to the client */
|
||||
TELNET_STATE_SendMenu, /**< Currently sending the command list menu to the client */
|
||||
TELNET_STATE_GetCommand, /**< Currently waiting for a command from the client */
|
||||
TELNET_STATE_SendResponse, /**< Processing the issued command and sending a response */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
void TELNETServerApp_Init(void);
|
||||
void TELNETServerApp_Callback(void);
|
||||
|
||||
#if defined(INCLUDE_FROM_TELNETSERVERAPP_C)
|
||||
static void TELNETServerApp_DisplayTCPConnections(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 TELNETServerApp.c.
|
||||
*/
|
||||
|
||||
#ifndef _TELNETSERVER_APP_H_
|
||||
#define _TELNETSERVER_APP_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/pgmspace.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <uip.h>
|
||||
|
||||
/* Macros: */
|
||||
/** TCP listen port for incoming TELNET traffic */
|
||||
#define TELNET_SERVER_PORT 23
|
||||
|
||||
/* Enums: */
|
||||
/** States for each TELNET connection to the server. */
|
||||
enum TELNET_States_t
|
||||
{
|
||||
TELNET_STATE_SendHeader, /**< Currently sending welcome header to the client */
|
||||
TELNET_STATE_SendMenu, /**< Currently sending the command list menu to the client */
|
||||
TELNET_STATE_GetCommand, /**< Currently waiting for a command from the client */
|
||||
TELNET_STATE_SendResponse, /**< Processing the issued command and sending a response */
|
||||
};
|
||||
|
||||
/* Function Prototypes: */
|
||||
void TELNETServerApp_Init(void);
|
||||
void TELNETServerApp_Callback(void);
|
||||
|
||||
#if defined(INCLUDE_FROM_TELNETSERVERAPP_C)
|
||||
static void TELNETServerApp_DisplayTCPConnections(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,251 +1,251 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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
|
||||
*
|
||||
* uIP Management functions. This file contains the functions and globals needed to maintain the uIP
|
||||
* stack once an RNDIS device has been attached to the system.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_UIPMANAGEMENT_C
|
||||
#include "uIPManagement.h"
|
||||
|
||||
/** Connection timer, to retain the time elapsed since the last time the uIP connections were managed. */
|
||||
struct timer ConnectionTimer;
|
||||
|
||||
/** ARP timer, to retain the time elapsed since the ARP cache was last updated. */
|
||||
struct timer ARPTimer;
|
||||
|
||||
/** MAC address of the RNDIS device, when enumerated */
|
||||
struct uip_eth_addr MACAddress;
|
||||
|
||||
bool HaveIPConfiguration;
|
||||
|
||||
/** Configures the uIP stack ready for network traffic. */
|
||||
void uIPManagement_Init(void)
|
||||
{
|
||||
/* uIP Timing Initialization */
|
||||
clock_init();
|
||||
timer_set(&ConnectionTimer, CLOCK_SECOND / 2);
|
||||
timer_set(&ARPTimer, CLOCK_SECOND * 10);
|
||||
|
||||
/* 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
|
||||
|
||||
/* HTTP Webserver Initialization */
|
||||
HTTPServerApp_Init();
|
||||
|
||||
/* TELNET Server Initialization */
|
||||
#if defined(ENABLE_TELNET_SERVER)
|
||||
TELNETServerApp_Init();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** uIP Management function. This function manages the uIP stack when called while an RNDIS device has been
|
||||
* attached to the system.
|
||||
*/
|
||||
void uIPManagement_ManageNetwork(void)
|
||||
{
|
||||
if ((USB_CurrentMode == USB_MODE_HOST) && (USB_HostState == HOST_STATE_Configured))
|
||||
{
|
||||
uIPManagement_ProcessIncomingPacket();
|
||||
uIPManagement_ManageConnections();
|
||||
}
|
||||
}
|
||||
|
||||
/** uIP TCP/IP network stack callback function for the processing of a given TCP connection. This routine dispatches
|
||||
* to the appropriate TCP protocol application based on the connection's listen port number.
|
||||
*/
|
||||
void uIPManagement_TCPCallback(void)
|
||||
{
|
||||
/* Call the correct TCP application based on the port number the connection is listening on */
|
||||
switch (uip_conn->lport)
|
||||
{
|
||||
case HTONS(HTTP_SERVER_PORT):
|
||||
HTTPServerApp_Callback();
|
||||
break;
|
||||
#if defined(ENABLE_TELNET_SERVER)
|
||||
case HTONS(TELNET_SERVER_PORT):
|
||||
TELNETServerApp_Callback();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/** uIP TCP/IP network stack callback function for the processing of a given UDP connection. This routine dispatches
|
||||
* to the appropriate UDP protocol application based on the connection's listen port number.
|
||||
*/
|
||||
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):
|
||||
DHCPClientApp_Callback();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** 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);
|
||||
|
||||
/* Read the Incoming packet straight into the UIP packet buffer */
|
||||
RNDIS_Host_ReadPacket(&Ethernet_RNDIS_Interface, uip_buf, &uip_len);
|
||||
|
||||
/* If the packet contains an Ethernet frame, process it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
switch (((struct uip_eth_hdr*)uip_buf)->type)
|
||||
{
|
||||
case HTONS(UIP_ETHTYPE_IP):
|
||||
/* Filter packet by MAC destination */
|
||||
uip_arp_ipin();
|
||||
|
||||
/* Process Incoming packet */
|
||||
uip_input();
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
uip_split_output();
|
||||
}
|
||||
|
||||
break;
|
||||
case HTONS(UIP_ETHTYPE_ARP):
|
||||
/* Process ARP packet */
|
||||
uip_arp_arpin();
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
uip_split_output();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_READY | ((HaveIPConfiguration) ? LEDMASK_UIP_READY_CONFIG : LEDMASK_UIP_READY_NOCONFIG));
|
||||
}
|
||||
|
||||
/** Manages the currently open network connections, including TCP and (if enabled) UDP. */
|
||||
static void uIPManagement_ManageConnections(void)
|
||||
{
|
||||
/* Poll TCP connections for more data to send back to the host */
|
||||
for (uint8_t i = 0; i < UIP_CONNS; i++)
|
||||
{
|
||||
uip_poll_conn(&uip_conns[i]);
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
/* Split and send the outgoing packet */
|
||||
uip_split_output();
|
||||
}
|
||||
}
|
||||
|
||||
/* Manage open connections for timeouts */
|
||||
if (timer_expired(&ConnectionTimer))
|
||||
{
|
||||
timer_reset(&ConnectionTimer);
|
||||
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
|
||||
|
||||
for (uint8_t i = 0; i < UIP_CONNS; i++)
|
||||
{
|
||||
/* Run periodic connection management for each TCP connection */
|
||||
uip_periodic(i);
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
/* Split and send the outgoing packet */
|
||||
uip_split_output();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ENABLE_DHCP_CLIENT)
|
||||
for (uint8_t i = 0; i < UIP_UDP_CONNS; i++)
|
||||
{
|
||||
/* Run periodic connection management for each UDP connection */
|
||||
uip_udp_periodic(i);
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
/* Split and send the outgoing packet */
|
||||
uip_split_output();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_READY);
|
||||
}
|
||||
|
||||
/* Manage ARP cache refreshing */
|
||||
if (timer_expired(&ARPTimer))
|
||||
{
|
||||
timer_reset(&ARPTimer);
|
||||
uip_arp_timer();
|
||||
}
|
||||
}
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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
|
||||
*
|
||||
* uIP Management functions. This file contains the functions and globals needed to maintain the uIP
|
||||
* stack once an RNDIS device has been attached to the system.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_UIPMANAGEMENT_C
|
||||
#include "uIPManagement.h"
|
||||
|
||||
/** Connection timer, to retain the time elapsed since the last time the uIP connections were managed. */
|
||||
struct timer ConnectionTimer;
|
||||
|
||||
/** ARP timer, to retain the time elapsed since the ARP cache was last updated. */
|
||||
struct timer ARPTimer;
|
||||
|
||||
/** MAC address of the RNDIS device, when enumerated */
|
||||
struct uip_eth_addr MACAddress;
|
||||
|
||||
bool HaveIPConfiguration;
|
||||
|
||||
/** Configures the uIP stack ready for network traffic. */
|
||||
void uIPManagement_Init(void)
|
||||
{
|
||||
/* uIP Timing Initialization */
|
||||
clock_init();
|
||||
timer_set(&ConnectionTimer, CLOCK_SECOND / 2);
|
||||
timer_set(&ARPTimer, CLOCK_SECOND * 10);
|
||||
|
||||
/* 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
|
||||
|
||||
/* HTTP Webserver Initialization */
|
||||
HTTPServerApp_Init();
|
||||
|
||||
/* TELNET Server Initialization */
|
||||
#if defined(ENABLE_TELNET_SERVER)
|
||||
TELNETServerApp_Init();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** uIP Management function. This function manages the uIP stack when called while an RNDIS device has been
|
||||
* attached to the system.
|
||||
*/
|
||||
void uIPManagement_ManageNetwork(void)
|
||||
{
|
||||
if ((USB_CurrentMode == USB_MODE_HOST) && (USB_HostState == HOST_STATE_Configured))
|
||||
{
|
||||
uIPManagement_ProcessIncomingPacket();
|
||||
uIPManagement_ManageConnections();
|
||||
}
|
||||
}
|
||||
|
||||
/** uIP TCP/IP network stack callback function for the processing of a given TCP connection. This routine dispatches
|
||||
* to the appropriate TCP protocol application based on the connection's listen port number.
|
||||
*/
|
||||
void uIPManagement_TCPCallback(void)
|
||||
{
|
||||
/* Call the correct TCP application based on the port number the connection is listening on */
|
||||
switch (uip_conn->lport)
|
||||
{
|
||||
case HTONS(HTTP_SERVER_PORT):
|
||||
HTTPServerApp_Callback();
|
||||
break;
|
||||
#if defined(ENABLE_TELNET_SERVER)
|
||||
case HTONS(TELNET_SERVER_PORT):
|
||||
TELNETServerApp_Callback();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/** uIP TCP/IP network stack callback function for the processing of a given UDP connection. This routine dispatches
|
||||
* to the appropriate UDP protocol application based on the connection's listen port number.
|
||||
*/
|
||||
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):
|
||||
DHCPClientApp_Callback();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** 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);
|
||||
|
||||
/* Read the Incoming packet straight into the UIP packet buffer */
|
||||
RNDIS_Host_ReadPacket(&Ethernet_RNDIS_Interface, uip_buf, &uip_len);
|
||||
|
||||
/* If the packet contains an Ethernet frame, process it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
switch (((struct uip_eth_hdr*)uip_buf)->type)
|
||||
{
|
||||
case HTONS(UIP_ETHTYPE_IP):
|
||||
/* Filter packet by MAC destination */
|
||||
uip_arp_ipin();
|
||||
|
||||
/* Process Incoming packet */
|
||||
uip_input();
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
uip_split_output();
|
||||
}
|
||||
|
||||
break;
|
||||
case HTONS(UIP_ETHTYPE_ARP):
|
||||
/* Process ARP packet */
|
||||
uip_arp_arpin();
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
uip_split_output();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_READY | ((HaveIPConfiguration) ? LEDMASK_UIP_READY_CONFIG : LEDMASK_UIP_READY_NOCONFIG));
|
||||
}
|
||||
|
||||
/** Manages the currently open network connections, including TCP and (if enabled) UDP. */
|
||||
static void uIPManagement_ManageConnections(void)
|
||||
{
|
||||
/* Poll TCP connections for more data to send back to the host */
|
||||
for (uint8_t i = 0; i < UIP_CONNS; i++)
|
||||
{
|
||||
uip_poll_conn(&uip_conns[i]);
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
/* Split and send the outgoing packet */
|
||||
uip_split_output();
|
||||
}
|
||||
}
|
||||
|
||||
/* Manage open connections for timeouts */
|
||||
if (timer_expired(&ConnectionTimer))
|
||||
{
|
||||
timer_reset(&ConnectionTimer);
|
||||
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
|
||||
|
||||
for (uint8_t i = 0; i < UIP_CONNS; i++)
|
||||
{
|
||||
/* Run periodic connection management for each TCP connection */
|
||||
uip_periodic(i);
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
/* Split and send the outgoing packet */
|
||||
uip_split_output();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ENABLE_DHCP_CLIENT)
|
||||
for (uint8_t i = 0; i < UIP_UDP_CONNS; i++)
|
||||
{
|
||||
/* Run periodic connection management for each UDP connection */
|
||||
uip_udp_periodic(i);
|
||||
|
||||
/* If a response was generated, send it */
|
||||
if (uip_len > 0)
|
||||
{
|
||||
/* Add destination MAC to outgoing packet */
|
||||
uip_arp_out();
|
||||
|
||||
/* Split and send the outgoing packet */
|
||||
uip_split_output();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LEDs_SetAllLEDs(LEDMASK_USB_READY);
|
||||
}
|
||||
|
||||
/* Manage ARP cache refreshing */
|
||||
if (timer_expired(&ARPTimer))
|
||||
{
|
||||
timer_reset(&ARPTimer);
|
||||
uip_arp_timer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,79 +1,79 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 uIPManagement.c.
|
||||
*/
|
||||
|
||||
#ifndef _UIP_MANAGEMENT_H_
|
||||
#define _UIP_MANAGEMENT_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <LUFA/Drivers/USB/Class/RNDIS.h>
|
||||
|
||||
#include <uip.h>
|
||||
#include <uip_arp.h>
|
||||
#include <uip-split.h>
|
||||
#include <timer.h>
|
||||
|
||||
#include "Lib/DHCPClientApp.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}
|
||||
|
||||
/** Netmask that the webserver should once connected to a RNDIS device (when DHCP is disabled). */
|
||||
#define DEVICE_NETMASK (uint8_t[]){255, 255, 255, 0}
|
||||
|
||||
/** 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}
|
||||
|
||||
/* External Variables: */
|
||||
extern struct uip_eth_addr MACAddress;
|
||||
|
||||
extern bool HaveIPConfiguration;
|
||||
|
||||
/* Function Prototypes: */
|
||||
void uIPManagement_Init(void);
|
||||
void uIPManagement_ManageNetwork(void);
|
||||
void uIPManagement_TCPCallback(void);
|
||||
void uIPManagement_UDPCallback(void);
|
||||
|
||||
#if defined(INCLUDE_FROM_UIPMANAGEMENT_C)
|
||||
static void uIPManagement_ProcessIncomingPacket(void);
|
||||
static void uIPManagement_ManageConnections(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2010.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2010 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 uIPManagement.c.
|
||||
*/
|
||||
|
||||
#ifndef _UIP_MANAGEMENT_H_
|
||||
#define _UIP_MANAGEMENT_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <LUFA/Drivers/USB/Class/RNDIS.h>
|
||||
|
||||
#include <uip.h>
|
||||
#include <uip_arp.h>
|
||||
#include <uip-split.h>
|
||||
#include <timer.h>
|
||||
|
||||
#include "Lib/DHCPClientApp.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}
|
||||
|
||||
/** Netmask that the webserver should once connected to a RNDIS device (when DHCP is disabled). */
|
||||
#define DEVICE_NETMASK (uint8_t[]){255, 255, 255, 0}
|
||||
|
||||
/** 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}
|
||||
|
||||
/* External Variables: */
|
||||
extern struct uip_eth_addr MACAddress;
|
||||
|
||||
extern bool HaveIPConfiguration;
|
||||
|
||||
/* Function Prototypes: */
|
||||
void uIPManagement_Init(void);
|
||||
void uIPManagement_ManageNetwork(void);
|
||||
void uIPManagement_TCPCallback(void);
|
||||
void uIPManagement_UDPCallback(void);
|
||||
|
||||
#if defined(INCLUDE_FROM_UIPMANAGEMENT_C)
|
||||
static void uIPManagement_ProcessIncomingPacket(void);
|
||||
static void uIPManagement_ManageConnections(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/sfr_defs.h>
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
//Counted time
|
||||
volatile clock_time_t clock_datetime = 0;
|
||||
|
||||
//Overflow interrupt
|
||||
ISR(TIMER1_COMPA_vect)
|
||||
{
|
||||
clock_datetime += 1;
|
||||
}
|
||||
|
||||
//Initialise the clock
|
||||
void clock_init()
|
||||
{
|
||||
OCR1A = ((F_CPU / 1024) / 100);
|
||||
TCCR1B = ((1 << WGM12) | (1 << CS12) | (1 << CS10));
|
||||
TIMSK1 = (1 << OCIE1A);
|
||||
}
|
||||
|
||||
//Return time
|
||||
clock_time_t clock_time()
|
||||
{
|
||||
clock_time_t time;
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_FORCEON)
|
||||
{
|
||||
time = clock_datetime;
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/sfr_defs.h>
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
//Counted time
|
||||
volatile clock_time_t clock_datetime = 0;
|
||||
|
||||
//Overflow interrupt
|
||||
ISR(TIMER1_COMPA_vect)
|
||||
{
|
||||
clock_datetime += 1;
|
||||
}
|
||||
|
||||
//Initialise the clock
|
||||
void clock_init()
|
||||
{
|
||||
OCR1A = ((F_CPU / 1024) / 100);
|
||||
TCCR1B = ((1 << WGM12) | (1 << CS12) | (1 << CS10));
|
||||
TIMSK1 = (1 << OCIE1A);
|
||||
}
|
||||
|
||||
//Return time
|
||||
clock_time_t clock_time()
|
||||
{
|
||||
clock_time_t time;
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_FORCEON)
|
||||
{
|
||||
time = clock_datetime;
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#ifndef __CLOCK_ARCH_H__
|
||||
#define __CLOCK_ARCH_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <util/atomic.h>
|
||||
|
||||
typedef uint16_t clock_time_t;
|
||||
#define CLOCK_SECOND 100
|
||||
void clock_init(void);
|
||||
clock_time_t clock_time(void);
|
||||
|
||||
#endif /* __CLOCK_ARCH_H__ */
|
||||
#ifndef __CLOCK_ARCH_H__
|
||||
#define __CLOCK_ARCH_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <util/atomic.h>
|
||||
|
||||
typedef uint16_t clock_time_t;
|
||||
#define CLOCK_SECOND 100
|
||||
void clock_init(void);
|
||||
clock_time_t clock_time(void);
|
||||
|
||||
#endif /* __CLOCK_ARCH_H__ */
|
||||
|
|
|
@ -1,127 +1,127 @@
|
|||
/**
|
||||
* \addtogroup timer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Timer library implementation.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $
|
||||
*/
|
||||
|
||||
#include "clock.h"
|
||||
#include "timer.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Set a timer.
|
||||
*
|
||||
* This function is used to set a timer for a time sometime in the
|
||||
* future. The function timer_expired() will evaluate to true after
|
||||
* the timer has expired.
|
||||
*
|
||||
* \param t A pointer to the timer
|
||||
* \param interval The interval before the timer expires.
|
||||
*
|
||||
*/
|
||||
void
|
||||
timer_set(struct timer *t, clock_time_t interval)
|
||||
{
|
||||
t->interval = interval;
|
||||
t->start = clock_time();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Reset the timer with the same interval.
|
||||
*
|
||||
* This function resets the timer with the same interval that was
|
||||
* given to the timer_set() function. The start point of the interval
|
||||
* is the exact time that the timer last expired. Therefore, this
|
||||
* function will cause the timer to be stable over time, unlike the
|
||||
* timer_rester() function.
|
||||
*
|
||||
* \param t A pointer to the timer.
|
||||
*
|
||||
* \sa timer_restart()
|
||||
*/
|
||||
void
|
||||
timer_reset(struct timer *t)
|
||||
{
|
||||
t->start += t->interval;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Restart the timer from the current point in time
|
||||
*
|
||||
* This function restarts a timer with the same interval that was
|
||||
* given to the timer_set() function. The timer will start at the
|
||||
* current time.
|
||||
*
|
||||
* \note A periodic timer will drift if this function is used to reset
|
||||
* it. For preioric timers, use the timer_reset() function instead.
|
||||
*
|
||||
* \param t A pointer to the timer.
|
||||
*
|
||||
* \sa timer_reset()
|
||||
*/
|
||||
void
|
||||
timer_restart(struct timer *t)
|
||||
{
|
||||
t->start = clock_time();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Check if a timer has expired.
|
||||
*
|
||||
* This function tests if a timer has expired and returns true or
|
||||
* false depending on its status.
|
||||
*
|
||||
* \param t A pointer to the timer
|
||||
*
|
||||
* \return Non-zero if the timer has expired, zero otherwise.
|
||||
*
|
||||
*/
|
||||
int
|
||||
timer_expired(struct timer *t)
|
||||
{
|
||||
return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** @} */
|
||||
/**
|
||||
* \addtogroup timer
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Timer library implementation.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $
|
||||
*/
|
||||
|
||||
#include "clock.h"
|
||||
#include "timer.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Set a timer.
|
||||
*
|
||||
* This function is used to set a timer for a time sometime in the
|
||||
* future. The function timer_expired() will evaluate to true after
|
||||
* the timer has expired.
|
||||
*
|
||||
* \param t A pointer to the timer
|
||||
* \param interval The interval before the timer expires.
|
||||
*
|
||||
*/
|
||||
void
|
||||
timer_set(struct timer *t, clock_time_t interval)
|
||||
{
|
||||
t->interval = interval;
|
||||
t->start = clock_time();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Reset the timer with the same interval.
|
||||
*
|
||||
* This function resets the timer with the same interval that was
|
||||
* given to the timer_set() function. The start point of the interval
|
||||
* is the exact time that the timer last expired. Therefore, this
|
||||
* function will cause the timer to be stable over time, unlike the
|
||||
* timer_rester() function.
|
||||
*
|
||||
* \param t A pointer to the timer.
|
||||
*
|
||||
* \sa timer_restart()
|
||||
*/
|
||||
void
|
||||
timer_reset(struct timer *t)
|
||||
{
|
||||
t->start += t->interval;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Restart the timer from the current point in time
|
||||
*
|
||||
* This function restarts a timer with the same interval that was
|
||||
* given to the timer_set() function. The timer will start at the
|
||||
* current time.
|
||||
*
|
||||
* \note A periodic timer will drift if this function is used to reset
|
||||
* it. For preioric timers, use the timer_reset() function instead.
|
||||
*
|
||||
* \param t A pointer to the timer.
|
||||
*
|
||||
* \sa timer_reset()
|
||||
*/
|
||||
void
|
||||
timer_restart(struct timer *t)
|
||||
{
|
||||
t->start = clock_time();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Check if a timer has expired.
|
||||
*
|
||||
* This function tests if a timer has expired and returns true or
|
||||
* false depending on its status.
|
||||
*
|
||||
* \param t A pointer to the timer
|
||||
*
|
||||
* \return Non-zero if the timer has expired, zero otherwise.
|
||||
*
|
||||
*/
|
||||
int
|
||||
timer_expired(struct timer *t)
|
||||
{
|
||||
return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,86 +1,86 @@
|
|||
/**
|
||||
* \defgroup timer Timer library
|
||||
*
|
||||
* The timer library provides functions for setting, resetting and
|
||||
* restarting timers, and for checking if a timer has expired. An
|
||||
* application must "manually" check if its timers have expired; this
|
||||
* is not done automatically.
|
||||
*
|
||||
* A timer is declared as a \c struct \c timer and all access to the
|
||||
* timer is made by a pointer to the declared timer.
|
||||
*
|
||||
* \note The timer library uses the \ref clock "Clock library" to
|
||||
* measure time. Intervals should be specified in the format used by
|
||||
* the clock library.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Timer library header file.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $
|
||||
*/
|
||||
#ifndef __TIMER_H__
|
||||
#define __TIMER_H__
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
/**
|
||||
* A timer.
|
||||
*
|
||||
* This structure is used for declaring a timer. The timer must be set
|
||||
* with timer_set() before it can be used.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
struct timer {
|
||||
clock_time_t start;
|
||||
clock_time_t interval;
|
||||
};
|
||||
|
||||
void timer_set(struct timer *t, clock_time_t interval);
|
||||
void timer_reset(struct timer *t);
|
||||
void timer_restart(struct timer *t);
|
||||
int timer_expired(struct timer *t);
|
||||
|
||||
#endif /* __TIMER_H__ */
|
||||
|
||||
/** @} */
|
||||
/**
|
||||
* \defgroup timer Timer library
|
||||
*
|
||||
* The timer library provides functions for setting, resetting and
|
||||
* restarting timers, and for checking if a timer has expired. An
|
||||
* application must "manually" check if its timers have expired; this
|
||||
* is not done automatically.
|
||||
*
|
||||
* A timer is declared as a \c struct \c timer and all access to the
|
||||
* timer is made by a pointer to the declared timer.
|
||||
*
|
||||
* \note The timer library uses the \ref clock "Clock library" to
|
||||
* measure time. Intervals should be specified in the format used by
|
||||
* the clock library.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Timer library header file.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $
|
||||
*/
|
||||
#ifndef __TIMER_H__
|
||||
#define __TIMER_H__
|
||||
|
||||
#include "clock.h"
|
||||
|
||||
/**
|
||||
* A timer.
|
||||
*
|
||||
* This structure is used for declaring a timer. The timer must be set
|
||||
* with timer_set() before it can be used.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
struct timer {
|
||||
clock_time_t start;
|
||||
clock_time_t interval;
|
||||
};
|
||||
|
||||
void timer_set(struct timer *t, clock_time_t interval);
|
||||
void timer_reset(struct timer *t);
|
||||
void timer_restart(struct timer *t);
|
||||
int timer_expired(struct timer *t);
|
||||
|
||||
#endif /* __TIMER_H__ */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -1,141 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: uip-split.c,v 1.2 2008/10/14 13:39:12 julienabeille Exp $
|
||||
*/
|
||||
|
||||
#include "uip-split.h"
|
||||
|
||||
|
||||
#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_split_output(void)
|
||||
{
|
||||
#if UIP_TCP
|
||||
u16_t tcplen, len1, len2;
|
||||
|
||||
/* We only try to split maximum sized TCP segments. */
|
||||
if(BUF->proto == UIP_PROTO_TCP && uip_len == UIP_BUFSIZE) {
|
||||
|
||||
tcplen = uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN;
|
||||
/* Split the segment in two. If the original packet length was
|
||||
odd, we make the second packet one byte larger. */
|
||||
len1 = len2 = tcplen / 2;
|
||||
if(len1 + len2 < tcplen) {
|
||||
++len2;
|
||||
}
|
||||
|
||||
/* Create the first packet. This is done by altering the length
|
||||
field of the IP header and updating the checksums. */
|
||||
uip_len = len1 + UIP_TCPIP_HLEN + UIP_LLH_LEN;
|
||||
#if UIP_CONF_IPV6
|
||||
/* For IPv6, the IP length field does not include the IPv6 IP header
|
||||
length. */
|
||||
BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
|
||||
BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
|
||||
#else /* UIP_CONF_IPV6 */
|
||||
BUF->len[0] = (uip_len - UIP_LLH_LEN) >> 8;
|
||||
BUF->len[1] = (uip_len - UIP_LLH_LEN) & 0xff;
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
/* Recalculate the TCP checksum. */
|
||||
BUF->tcpchksum = 0;
|
||||
BUF->tcpchksum = ~(uip_tcpchksum());
|
||||
|
||||
#if !UIP_CONF_IPV6
|
||||
/* Recalculate the IP checksum. */
|
||||
BUF->ipchksum = 0;
|
||||
BUF->ipchksum = ~(uip_ipchksum());
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
/* Transmit the first packet. */
|
||||
#if UIP_CONF_IPV6
|
||||
tcpip_ipv6_output();
|
||||
#else
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len);
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
/* Now, create the second packet. To do this, it is not enough to
|
||||
just alter the length field, but we must also update the TCP
|
||||
sequence number and point the uip_appdata to a new place in
|
||||
memory. This place is detemined by the length of the first
|
||||
packet (len1). */
|
||||
uip_len = len2 + UIP_TCPIP_HLEN + UIP_LLH_LEN;
|
||||
#if UIP_CONF_IPV6
|
||||
/* For IPv6, the IP length field does not include the IPv6 IP header
|
||||
length. */
|
||||
BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
|
||||
BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
|
||||
#else /* UIP_CONF_IPV6 */
|
||||
BUF->len[0] = (uip_len - UIP_LLH_LEN) >> 8;
|
||||
BUF->len[1] = (uip_len - UIP_LLH_LEN) & 0xff;
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2);
|
||||
|
||||
uip_add32(BUF->seqno, len1);
|
||||
BUF->seqno[0] = uip_acc32[0];
|
||||
BUF->seqno[1] = uip_acc32[1];
|
||||
BUF->seqno[2] = uip_acc32[2];
|
||||
BUF->seqno[3] = uip_acc32[3];
|
||||
|
||||
/* Recalculate the TCP checksum. */
|
||||
BUF->tcpchksum = 0;
|
||||
BUF->tcpchksum = ~(uip_tcpchksum());
|
||||
|
||||
#if !UIP_CONF_IPV6
|
||||
/* Recalculate the IP checksum. */
|
||||
BUF->ipchksum = 0;
|
||||
BUF->ipchksum = ~(uip_ipchksum());
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
/* Transmit the second packet. */
|
||||
#if UIP_CONF_IPV6
|
||||
tcpip_ipv6_output();
|
||||
#else
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len);
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
return;
|
||||
}
|
||||
#endif /* UIP_TCP */
|
||||
|
||||
/* uip_fw_output();*/
|
||||
#if UIP_CONF_IPV6
|
||||
tcpip_ipv6_output();
|
||||
#else
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len);
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: uip-split.c,v 1.2 2008/10/14 13:39:12 julienabeille Exp $
|
||||
*/
|
||||
|
||||
#include "uip-split.h"
|
||||
|
||||
|
||||
#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_split_output(void)
|
||||
{
|
||||
#if UIP_TCP
|
||||
u16_t tcplen, len1, len2;
|
||||
|
||||
/* We only try to split maximum sized TCP segments. */
|
||||
if(BUF->proto == UIP_PROTO_TCP && uip_len == UIP_BUFSIZE) {
|
||||
|
||||
tcplen = uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN;
|
||||
/* Split the segment in two. If the original packet length was
|
||||
odd, we make the second packet one byte larger. */
|
||||
len1 = len2 = tcplen / 2;
|
||||
if(len1 + len2 < tcplen) {
|
||||
++len2;
|
||||
}
|
||||
|
||||
/* Create the first packet. This is done by altering the length
|
||||
field of the IP header and updating the checksums. */
|
||||
uip_len = len1 + UIP_TCPIP_HLEN + UIP_LLH_LEN;
|
||||
#if UIP_CONF_IPV6
|
||||
/* For IPv6, the IP length field does not include the IPv6 IP header
|
||||
length. */
|
||||
BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
|
||||
BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
|
||||
#else /* UIP_CONF_IPV6 */
|
||||
BUF->len[0] = (uip_len - UIP_LLH_LEN) >> 8;
|
||||
BUF->len[1] = (uip_len - UIP_LLH_LEN) & 0xff;
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
/* Recalculate the TCP checksum. */
|
||||
BUF->tcpchksum = 0;
|
||||
BUF->tcpchksum = ~(uip_tcpchksum());
|
||||
|
||||
#if !UIP_CONF_IPV6
|
||||
/* Recalculate the IP checksum. */
|
||||
BUF->ipchksum = 0;
|
||||
BUF->ipchksum = ~(uip_ipchksum());
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
/* Transmit the first packet. */
|
||||
#if UIP_CONF_IPV6
|
||||
tcpip_ipv6_output();
|
||||
#else
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len);
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
/* Now, create the second packet. To do this, it is not enough to
|
||||
just alter the length field, but we must also update the TCP
|
||||
sequence number and point the uip_appdata to a new place in
|
||||
memory. This place is detemined by the length of the first
|
||||
packet (len1). */
|
||||
uip_len = len2 + UIP_TCPIP_HLEN + UIP_LLH_LEN;
|
||||
#if UIP_CONF_IPV6
|
||||
/* For IPv6, the IP length field does not include the IPv6 IP header
|
||||
length. */
|
||||
BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
|
||||
BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
|
||||
#else /* UIP_CONF_IPV6 */
|
||||
BUF->len[0] = (uip_len - UIP_LLH_LEN) >> 8;
|
||||
BUF->len[1] = (uip_len - UIP_LLH_LEN) & 0xff;
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2);
|
||||
|
||||
uip_add32(BUF->seqno, len1);
|
||||
BUF->seqno[0] = uip_acc32[0];
|
||||
BUF->seqno[1] = uip_acc32[1];
|
||||
BUF->seqno[2] = uip_acc32[2];
|
||||
BUF->seqno[3] = uip_acc32[3];
|
||||
|
||||
/* Recalculate the TCP checksum. */
|
||||
BUF->tcpchksum = 0;
|
||||
BUF->tcpchksum = ~(uip_tcpchksum());
|
||||
|
||||
#if !UIP_CONF_IPV6
|
||||
/* Recalculate the IP checksum. */
|
||||
BUF->ipchksum = 0;
|
||||
BUF->ipchksum = ~(uip_ipchksum());
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
|
||||
/* Transmit the second packet. */
|
||||
#if UIP_CONF_IPV6
|
||||
tcpip_ipv6_output();
|
||||
#else
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len);
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
return;
|
||||
}
|
||||
#endif /* UIP_TCP */
|
||||
|
||||
/* uip_fw_output();*/
|
||||
#if UIP_CONF_IPV6
|
||||
tcpip_ipv6_output();
|
||||
#else
|
||||
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface, uip_buf, uip_len);
|
||||
#endif /* UIP_CONF_IPV6 */
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -1,103 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: uip-split.h,v 1.1 2006/06/17 22:41:19 adamdunkels Exp $
|
||||
*/
|
||||
/**
|
||||
* \addtogroup uip
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup uipsplit uIP TCP throughput booster hack
|
||||
* @{
|
||||
*
|
||||
* The basic uIP TCP implementation only allows each TCP connection to
|
||||
* have a single TCP segment in flight at any given time. Because of
|
||||
* the delayed ACK algorithm employed by most TCP receivers, uIP's
|
||||
* limit on the amount of in-flight TCP segments seriously reduces the
|
||||
* maximum achievable throughput for sending data from uIP.
|
||||
*
|
||||
* The uip-split module is a hack which tries to remedy this
|
||||
* situation. By splitting maximum sized outgoing TCP segments into
|
||||
* two, the delayed ACK algorithm is not invoked at TCP
|
||||
* receivers. This improves the throughput when sending data from uIP
|
||||
* by orders of magnitude.
|
||||
*
|
||||
* The uip-split module uses the uip-fw module (uIP IP packet
|
||||
* forwarding) for sending packets. Therefore, the uip-fw module must
|
||||
* be set up with the appropriate network interfaces for this module
|
||||
* to work.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Module for splitting outbound TCP segments in two to avoid the
|
||||
* delayed ACK throughput degradation.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UIP_SPLIT_H__
|
||||
#define __UIP_SPLIT_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <uip.h>
|
||||
|
||||
#include "../../USBHostMode.h"
|
||||
|
||||
#include <LUFA/Drivers/USB/Class/RNDIS.h>
|
||||
|
||||
/**
|
||||
* Handle outgoing packets.
|
||||
*
|
||||
* This function inspects an outgoing packet in the uip_buf buffer and
|
||||
* sends it out using the uip_fw_output() function. If the packet is a
|
||||
* full-sized TCP segment it will be split into two segments and
|
||||
* transmitted separately. This function should be called instead of
|
||||
* the actual device driver output function, or the uip_fw_output()
|
||||
* function.
|
||||
*
|
||||
* The headers of the outgoing packet is assumed to be in the uip_buf
|
||||
* buffer and the payload is assumed to be wherever uip_appdata
|
||||
* points. The length of the outgoing packet is assumed to be in the
|
||||
* uip_len variable.
|
||||
*
|
||||
*/
|
||||
void uip_split_output(void);
|
||||
void uip_add32(u8_t *op32, u16_t op16);
|
||||
#endif /* __UIP_SPLIT_H__ */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
/*
|
||||
* Copyright (c) 2004, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
* $Id: uip-split.h,v 1.1 2006/06/17 22:41:19 adamdunkels Exp $
|
||||
*/
|
||||
/**
|
||||
* \addtogroup uip
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup uipsplit uIP TCP throughput booster hack
|
||||
* @{
|
||||
*
|
||||
* The basic uIP TCP implementation only allows each TCP connection to
|
||||
* have a single TCP segment in flight at any given time. Because of
|
||||
* the delayed ACK algorithm employed by most TCP receivers, uIP's
|
||||
* limit on the amount of in-flight TCP segments seriously reduces the
|
||||
* maximum achievable throughput for sending data from uIP.
|
||||
*
|
||||
* The uip-split module is a hack which tries to remedy this
|
||||
* situation. By splitting maximum sized outgoing TCP segments into
|
||||
* two, the delayed ACK algorithm is not invoked at TCP
|
||||
* receivers. This improves the throughput when sending data from uIP
|
||||
* by orders of magnitude.
|
||||
*
|
||||
* The uip-split module uses the uip-fw module (uIP IP packet
|
||||
* forwarding) for sending packets. Therefore, the uip-fw module must
|
||||
* be set up with the appropriate network interfaces for this module
|
||||
* to work.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Module for splitting outbound TCP segments in two to avoid the
|
||||
* delayed ACK throughput degradation.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UIP_SPLIT_H__
|
||||
#define __UIP_SPLIT_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <uip.h>
|
||||
|
||||
#include "../../USBHostMode.h"
|
||||
|
||||
#include <LUFA/Drivers/USB/Class/RNDIS.h>
|
||||
|
||||
/**
|
||||
* Handle outgoing packets.
|
||||
*
|
||||
* This function inspects an outgoing packet in the uip_buf buffer and
|
||||
* sends it out using the uip_fw_output() function. If the packet is a
|
||||
* full-sized TCP segment it will be split into two segments and
|
||||
* transmitted separately. This function should be called instead of
|
||||
* the actual device driver output function, or the uip_fw_output()
|
||||
* function.
|
||||
*
|
||||
* The headers of the outgoing packet is assumed to be in the uip_buf
|
||||
* buffer and the payload is assumed to be wherever uip_appdata
|
||||
* points. The length of the outgoing packet is assumed to be in the
|
||||
* uip_len variable.
|
||||
*
|
||||
*/
|
||||
void uip_split_output(void);
|
||||
void uip_add32(u8_t *op32, u16_t op16);
|
||||
#endif /* __UIP_SPLIT_H__ */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,431 +1,431 @@
|
|||
/**
|
||||
* \addtogroup uip
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup uiparp uIP Address Resolution Protocol
|
||||
* @{
|
||||
*
|
||||
* The Address Resolution Protocol ARP is used for mapping between IP
|
||||
* addresses and link level addresses such as the Ethernet MAC
|
||||
* addresses. ARP uses broadcast queries to ask for the link level
|
||||
* address of a known IP address and the host which is configured with
|
||||
* the IP address for which the query was meant, will respond with its
|
||||
* link level address.
|
||||
*
|
||||
* \note This ARP implementation only supports Ethernet.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Implementation of the ARP Address Resolution Protocol.
|
||||
* \author Adam Dunkels <adam@dunkels.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: uip_arp.c,v 1.5 2008/02/07 01:35:00 adamdunkels Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "uip_arp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct arp_hdr {
|
||||
struct uip_eth_hdr ethhdr;
|
||||
u16_t hwtype;
|
||||
u16_t protocol;
|
||||
u8_t hwlen;
|
||||
u8_t protolen;
|
||||
u16_t opcode;
|
||||
struct uip_eth_addr shwaddr;
|
||||
uip_ipaddr_t sipaddr;
|
||||
struct uip_eth_addr dhwaddr;
|
||||
uip_ipaddr_t dipaddr;
|
||||
};
|
||||
|
||||
struct ethip_hdr {
|
||||
struct uip_eth_hdr ethhdr;
|
||||
/* IP header. */
|
||||
u8_t vhl,
|
||||
tos,
|
||||
len[2],
|
||||
ipid[2],
|
||||
ipoffset[2],
|
||||
ttl,
|
||||
proto;
|
||||
u16_t ipchksum;
|
||||
uip_ipaddr_t srcipaddr, destipaddr;
|
||||
};
|
||||
|
||||
#define ARP_REQUEST 1
|
||||
#define ARP_REPLY 2
|
||||
|
||||
#define ARP_HWTYPE_ETH 1
|
||||
|
||||
struct arp_entry {
|
||||
uip_ipaddr_t ipaddr;
|
||||
struct uip_eth_addr ethaddr;
|
||||
u8_t time;
|
||||
};
|
||||
|
||||
static const struct uip_eth_addr broadcast_ethaddr =
|
||||
{{0xff,0xff,0xff,0xff,0xff,0xff}};
|
||||
static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff};
|
||||
|
||||
static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
|
||||
static uip_ipaddr_t ipaddr;
|
||||
static u8_t i, c;
|
||||
|
||||
static u8_t arptime;
|
||||
static u8_t tmpage;
|
||||
|
||||
#define BUF ((struct arp_hdr *)&uip_buf[0])
|
||||
#define IPBUF ((struct ethip_hdr *)&uip_buf[0])
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Initialize the ARP module.
|
||||
*
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_init(void)
|
||||
{
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
memset(&arp_table[i].ipaddr, 0, 4);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Periodic ARP processing function.
|
||||
*
|
||||
* This function performs periodic timer processing in the ARP module
|
||||
* and should be called at regular intervals. The recommended interval
|
||||
* is 10 seconds between the calls.
|
||||
*
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_timer(void)
|
||||
{
|
||||
struct arp_entry *tabptr = NULL;
|
||||
|
||||
++arptime;
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(uip_ipaddr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr) &&
|
||||
arptime - tabptr->time >= UIP_ARP_MAXAGE) {
|
||||
memset(&tabptr->ipaddr, 0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void
|
||||
uip_arp_update(uip_ipaddr_t *ipaddr, struct uip_eth_addr *ethaddr)
|
||||
{
|
||||
register struct arp_entry *tabptr = NULL;
|
||||
/* Walk through the ARP mapping table and try to find an entry to
|
||||
update. If none is found, the IP -> MAC address mapping is
|
||||
inserted in the ARP table. */
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
|
||||
tabptr = &arp_table[i];
|
||||
/* Only check those entries that are actually in use. */
|
||||
if(!uip_ipaddr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr)) {
|
||||
|
||||
/* Check if the source IP address of the incoming packet matches
|
||||
the IP address in this ARP table entry. */
|
||||
if(uip_ipaddr_cmp(ipaddr, &tabptr->ipaddr)) {
|
||||
|
||||
/* An old entry found, update this and return. */
|
||||
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
|
||||
tabptr->time = arptime;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we get here, no existing ARP table entry was found, so we
|
||||
create one. */
|
||||
|
||||
/* First, we try to find an unused entry in the ARP table. */
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(uip_ipaddr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no unused entry is found, we try to find the oldest entry and
|
||||
throw it away. */
|
||||
if(i == UIP_ARPTAB_SIZE) {
|
||||
tmpage = 0;
|
||||
c = 0;
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(arptime - tabptr->time > tmpage) {
|
||||
tmpage = arptime - tabptr->time;
|
||||
c = i;
|
||||
}
|
||||
}
|
||||
i = c;
|
||||
tabptr = &arp_table[i];
|
||||
}
|
||||
|
||||
/* Now, i is the ARP table entry which we will fill with the new
|
||||
information. */
|
||||
uip_ipaddr_copy(&tabptr->ipaddr, ipaddr);
|
||||
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
|
||||
tabptr->time = arptime;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* ARP processing for incoming IP packets
|
||||
*
|
||||
* This function should be called by the device driver when an IP
|
||||
* packet has been received. The function will check if the address is
|
||||
* in the ARP cache, and if so the ARP cache entry will be
|
||||
* refreshed. If no ARP cache entry was found, a new one is created.
|
||||
*
|
||||
* This function expects an IP packet with a prepended Ethernet header
|
||||
* in the uip_buf[] buffer, and the length of the packet in the global
|
||||
* variable uip_len.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
#if 0
|
||||
void
|
||||
uip_arp_ipin(void)
|
||||
{
|
||||
uip_len -= sizeof(struct uip_eth_hdr);
|
||||
|
||||
/* Only insert/update an entry if the source IP address of the
|
||||
incoming IP packet comes from a host on the local network. */
|
||||
if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
|
||||
(uip_hostaddr[0] & uip_netmask[0])) {
|
||||
return;
|
||||
}
|
||||
if((IPBUF->srcipaddr[1] & uip_netmask[1]) !=
|
||||
(uip_hostaddr[1] & uip_netmask[1])) {
|
||||
return;
|
||||
}
|
||||
uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* 0 */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* ARP processing for incoming ARP packets.
|
||||
*
|
||||
* This function should be called by the device driver when an ARP
|
||||
* packet has been received. The function will act differently
|
||||
* depending on the ARP packet type: if it is a reply for a request
|
||||
* that we previously sent out, the ARP cache will be filled in with
|
||||
* the values from the ARP reply. If the incoming ARP packet is an ARP
|
||||
* request for our IP address, an ARP reply packet is created and put
|
||||
* into the uip_buf[] buffer.
|
||||
*
|
||||
* When the function returns, the value of the global variable uip_len
|
||||
* indicates whether the device driver should send out a packet or
|
||||
* not. If uip_len is zero, no packet should be sent. If uip_len is
|
||||
* non-zero, it contains the length of the outbound packet that is
|
||||
* present in the uip_buf[] buffer.
|
||||
*
|
||||
* This function expects an ARP packet with a prepended Ethernet
|
||||
* header in the uip_buf[] buffer, and the length of the packet in the
|
||||
* global variable uip_len.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_arpin(void)
|
||||
{
|
||||
if(uip_len < sizeof(struct arp_hdr)) {
|
||||
uip_len = 0;
|
||||
return;
|
||||
}
|
||||
uip_len = 0;
|
||||
|
||||
switch(BUF->opcode) {
|
||||
case HTONS(ARP_REQUEST):
|
||||
/* ARP request. If it asked for our address, we send out a
|
||||
reply. */
|
||||
/* if(BUF->dipaddr[0] == uip_hostaddr[0] &&
|
||||
BUF->dipaddr[1] == uip_hostaddr[1]) {*/
|
||||
PRINTF("uip_arp_arpin: request for %d.%d.%d.%d (we are %d.%d.%d.%d)\n",
|
||||
BUF->dipaddr.u8[0], BUF->dipaddr.u8[1],
|
||||
BUF->dipaddr.u8[2], BUF->dipaddr.u8[3],
|
||||
uip_hostaddr.u8[0], uip_hostaddr.u8[1],
|
||||
uip_hostaddr.u8[2], uip_hostaddr.u8[3]);
|
||||
if(uip_ipaddr_cmp(&BUF->dipaddr, &uip_hostaddr)) {
|
||||
/* First, we register the one who made the request in our ARP
|
||||
table, since it is likely that we will do more communication
|
||||
with this host in the future. */
|
||||
uip_arp_update(&BUF->sipaddr, &BUF->shwaddr);
|
||||
|
||||
BUF->opcode = HTONS(ARP_REPLY);
|
||||
|
||||
memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
|
||||
memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
|
||||
memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||
memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
|
||||
|
||||
uip_ipaddr_copy(&BUF->dipaddr, &BUF->sipaddr);
|
||||
uip_ipaddr_copy(&BUF->sipaddr, &uip_hostaddr);
|
||||
|
||||
BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
|
||||
uip_len = sizeof(struct arp_hdr);
|
||||
}
|
||||
break;
|
||||
case HTONS(ARP_REPLY):
|
||||
/* ARP reply. We insert or update the ARP table if it was meant
|
||||
for us. */
|
||||
if(uip_ipaddr_cmp(&BUF->dipaddr, &uip_hostaddr)) {
|
||||
uip_arp_update(&BUF->sipaddr, &BUF->shwaddr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Prepend Ethernet header to an outbound IP packet and see if we need
|
||||
* to send out an ARP request.
|
||||
*
|
||||
* This function should be called before sending out an IP packet. The
|
||||
* function checks the destination IP address of the IP packet to see
|
||||
* what Ethernet MAC address that should be used as a destination MAC
|
||||
* address on the Ethernet.
|
||||
*
|
||||
* If the destination IP address is in the local network (determined
|
||||
* by logical ANDing of netmask and our IP address), the function
|
||||
* checks the ARP cache to see if an entry for the destination IP
|
||||
* address is found. If so, an Ethernet header is prepended and the
|
||||
* function returns. If no ARP cache entry is found for the
|
||||
* destination IP address, the packet in the uip_buf[] is replaced by
|
||||
* an ARP request packet for the IP address. The IP packet is dropped
|
||||
* and it is assumed that they higher level protocols (e.g., TCP)
|
||||
* eventually will retransmit the dropped packet.
|
||||
*
|
||||
* If the destination IP address is not on the local network, the IP
|
||||
* address of the default router is used instead.
|
||||
*
|
||||
* When the function returns, a packet is present in the uip_buf[]
|
||||
* buffer, and the length of the packet is in the global variable
|
||||
* uip_len.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_out(void)
|
||||
{
|
||||
struct arp_entry *tabptr = NULL;
|
||||
|
||||
/* Find the destination IP address in the ARP table and construct
|
||||
the Ethernet header. If the destination IP addres isn't on the
|
||||
local network, we use the default router's IP address instead.
|
||||
|
||||
If not ARP table entry is found, we overwrite the original IP
|
||||
packet with an ARP request for the IP address. */
|
||||
|
||||
/* First check if destination is a local broadcast. */
|
||||
if(uip_ipaddr_cmp(&IPBUF->destipaddr, &uip_broadcast_addr)) {
|
||||
memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
|
||||
} else {
|
||||
/* Check if the destination address is on the local network. */
|
||||
if(!uip_ipaddr_maskcmp(&IPBUF->destipaddr, &uip_hostaddr, &uip_netmask)) {
|
||||
/* Destination address was not on the local network, so we need to
|
||||
use the default router's IP address instead of the destination
|
||||
address when determining the MAC address. */
|
||||
uip_ipaddr_copy(&ipaddr, &uip_draddr);
|
||||
} else {
|
||||
/* Else, we use the destination IP address. */
|
||||
uip_ipaddr_copy(&ipaddr, &IPBUF->destipaddr);
|
||||
}
|
||||
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(uip_ipaddr_cmp(&ipaddr, &tabptr->ipaddr)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == UIP_ARPTAB_SIZE) {
|
||||
/* The destination address was not in our ARP table, so we
|
||||
overwrite the IP packet with an ARP request. */
|
||||
|
||||
memset(BUF->ethhdr.dest.addr, 0xff, 6);
|
||||
memset(BUF->dhwaddr.addr, 0x00, 6);
|
||||
memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||
memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
|
||||
|
||||
uip_ipaddr_copy(&BUF->dipaddr, &ipaddr);
|
||||
uip_ipaddr_copy(&BUF->sipaddr, &uip_hostaddr);
|
||||
BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
|
||||
BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
|
||||
BUF->protocol = HTONS(UIP_ETHTYPE_IP);
|
||||
BUF->hwlen = 6;
|
||||
BUF->protolen = 4;
|
||||
BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
|
||||
|
||||
uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
|
||||
|
||||
uip_len = sizeof(struct arp_hdr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build an ethernet header. */
|
||||
memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
|
||||
}
|
||||
memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||
|
||||
IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
|
||||
|
||||
uip_len += sizeof(struct uip_eth_hdr);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
/**
|
||||
* \addtogroup uip
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup uiparp uIP Address Resolution Protocol
|
||||
* @{
|
||||
*
|
||||
* The Address Resolution Protocol ARP is used for mapping between IP
|
||||
* addresses and link level addresses such as the Ethernet MAC
|
||||
* addresses. ARP uses broadcast queries to ask for the link level
|
||||
* address of a known IP address and the host which is configured with
|
||||
* the IP address for which the query was meant, will respond with its
|
||||
* link level address.
|
||||
*
|
||||
* \note This ARP implementation only supports Ethernet.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Implementation of the ARP Address Resolution Protocol.
|
||||
* \author Adam Dunkels <adam@dunkels.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: uip_arp.c,v 1.5 2008/02/07 01:35:00 adamdunkels Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "uip_arp.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct arp_hdr {
|
||||
struct uip_eth_hdr ethhdr;
|
||||
u16_t hwtype;
|
||||
u16_t protocol;
|
||||
u8_t hwlen;
|
||||
u8_t protolen;
|
||||
u16_t opcode;
|
||||
struct uip_eth_addr shwaddr;
|
||||
uip_ipaddr_t sipaddr;
|
||||
struct uip_eth_addr dhwaddr;
|
||||
uip_ipaddr_t dipaddr;
|
||||
};
|
||||
|
||||
struct ethip_hdr {
|
||||
struct uip_eth_hdr ethhdr;
|
||||
/* IP header. */
|
||||
u8_t vhl,
|
||||
tos,
|
||||
len[2],
|
||||
ipid[2],
|
||||
ipoffset[2],
|
||||
ttl,
|
||||
proto;
|
||||
u16_t ipchksum;
|
||||
uip_ipaddr_t srcipaddr, destipaddr;
|
||||
};
|
||||
|
||||
#define ARP_REQUEST 1
|
||||
#define ARP_REPLY 2
|
||||
|
||||
#define ARP_HWTYPE_ETH 1
|
||||
|
||||
struct arp_entry {
|
||||
uip_ipaddr_t ipaddr;
|
||||
struct uip_eth_addr ethaddr;
|
||||
u8_t time;
|
||||
};
|
||||
|
||||
static const struct uip_eth_addr broadcast_ethaddr =
|
||||
{{0xff,0xff,0xff,0xff,0xff,0xff}};
|
||||
static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff};
|
||||
|
||||
static struct arp_entry arp_table[UIP_ARPTAB_SIZE];
|
||||
static uip_ipaddr_t ipaddr;
|
||||
static u8_t i, c;
|
||||
|
||||
static u8_t arptime;
|
||||
static u8_t tmpage;
|
||||
|
||||
#define BUF ((struct arp_hdr *)&uip_buf[0])
|
||||
#define IPBUF ((struct ethip_hdr *)&uip_buf[0])
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
#include <stdio.h>
|
||||
#define PRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Initialize the ARP module.
|
||||
*
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_init(void)
|
||||
{
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
memset(&arp_table[i].ipaddr, 0, 4);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Periodic ARP processing function.
|
||||
*
|
||||
* This function performs periodic timer processing in the ARP module
|
||||
* and should be called at regular intervals. The recommended interval
|
||||
* is 10 seconds between the calls.
|
||||
*
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_timer(void)
|
||||
{
|
||||
struct arp_entry *tabptr = NULL;
|
||||
|
||||
++arptime;
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(uip_ipaddr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr) &&
|
||||
arptime - tabptr->time >= UIP_ARP_MAXAGE) {
|
||||
memset(&tabptr->ipaddr, 0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void
|
||||
uip_arp_update(uip_ipaddr_t *ipaddr, struct uip_eth_addr *ethaddr)
|
||||
{
|
||||
register struct arp_entry *tabptr = NULL;
|
||||
/* Walk through the ARP mapping table and try to find an entry to
|
||||
update. If none is found, the IP -> MAC address mapping is
|
||||
inserted in the ARP table. */
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
|
||||
tabptr = &arp_table[i];
|
||||
/* Only check those entries that are actually in use. */
|
||||
if(!uip_ipaddr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr)) {
|
||||
|
||||
/* Check if the source IP address of the incoming packet matches
|
||||
the IP address in this ARP table entry. */
|
||||
if(uip_ipaddr_cmp(ipaddr, &tabptr->ipaddr)) {
|
||||
|
||||
/* An old entry found, update this and return. */
|
||||
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
|
||||
tabptr->time = arptime;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we get here, no existing ARP table entry was found, so we
|
||||
create one. */
|
||||
|
||||
/* First, we try to find an unused entry in the ARP table. */
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(uip_ipaddr_cmp(&tabptr->ipaddr, &uip_all_zeroes_addr)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no unused entry is found, we try to find the oldest entry and
|
||||
throw it away. */
|
||||
if(i == UIP_ARPTAB_SIZE) {
|
||||
tmpage = 0;
|
||||
c = 0;
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(arptime - tabptr->time > tmpage) {
|
||||
tmpage = arptime - tabptr->time;
|
||||
c = i;
|
||||
}
|
||||
}
|
||||
i = c;
|
||||
tabptr = &arp_table[i];
|
||||
}
|
||||
|
||||
/* Now, i is the ARP table entry which we will fill with the new
|
||||
information. */
|
||||
uip_ipaddr_copy(&tabptr->ipaddr, ipaddr);
|
||||
memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
|
||||
tabptr->time = arptime;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* ARP processing for incoming IP packets
|
||||
*
|
||||
* This function should be called by the device driver when an IP
|
||||
* packet has been received. The function will check if the address is
|
||||
* in the ARP cache, and if so the ARP cache entry will be
|
||||
* refreshed. If no ARP cache entry was found, a new one is created.
|
||||
*
|
||||
* This function expects an IP packet with a prepended Ethernet header
|
||||
* in the uip_buf[] buffer, and the length of the packet in the global
|
||||
* variable uip_len.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
#if 0
|
||||
void
|
||||
uip_arp_ipin(void)
|
||||
{
|
||||
uip_len -= sizeof(struct uip_eth_hdr);
|
||||
|
||||
/* Only insert/update an entry if the source IP address of the
|
||||
incoming IP packet comes from a host on the local network. */
|
||||
if((IPBUF->srcipaddr[0] & uip_netmask[0]) !=
|
||||
(uip_hostaddr[0] & uip_netmask[0])) {
|
||||
return;
|
||||
}
|
||||
if((IPBUF->srcipaddr[1] & uip_netmask[1]) !=
|
||||
(uip_hostaddr[1] & uip_netmask[1])) {
|
||||
return;
|
||||
}
|
||||
uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* 0 */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* ARP processing for incoming ARP packets.
|
||||
*
|
||||
* This function should be called by the device driver when an ARP
|
||||
* packet has been received. The function will act differently
|
||||
* depending on the ARP packet type: if it is a reply for a request
|
||||
* that we previously sent out, the ARP cache will be filled in with
|
||||
* the values from the ARP reply. If the incoming ARP packet is an ARP
|
||||
* request for our IP address, an ARP reply packet is created and put
|
||||
* into the uip_buf[] buffer.
|
||||
*
|
||||
* When the function returns, the value of the global variable uip_len
|
||||
* indicates whether the device driver should send out a packet or
|
||||
* not. If uip_len is zero, no packet should be sent. If uip_len is
|
||||
* non-zero, it contains the length of the outbound packet that is
|
||||
* present in the uip_buf[] buffer.
|
||||
*
|
||||
* This function expects an ARP packet with a prepended Ethernet
|
||||
* header in the uip_buf[] buffer, and the length of the packet in the
|
||||
* global variable uip_len.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_arpin(void)
|
||||
{
|
||||
if(uip_len < sizeof(struct arp_hdr)) {
|
||||
uip_len = 0;
|
||||
return;
|
||||
}
|
||||
uip_len = 0;
|
||||
|
||||
switch(BUF->opcode) {
|
||||
case HTONS(ARP_REQUEST):
|
||||
/* ARP request. If it asked for our address, we send out a
|
||||
reply. */
|
||||
/* if(BUF->dipaddr[0] == uip_hostaddr[0] &&
|
||||
BUF->dipaddr[1] == uip_hostaddr[1]) {*/
|
||||
PRINTF("uip_arp_arpin: request for %d.%d.%d.%d (we are %d.%d.%d.%d)\n",
|
||||
BUF->dipaddr.u8[0], BUF->dipaddr.u8[1],
|
||||
BUF->dipaddr.u8[2], BUF->dipaddr.u8[3],
|
||||
uip_hostaddr.u8[0], uip_hostaddr.u8[1],
|
||||
uip_hostaddr.u8[2], uip_hostaddr.u8[3]);
|
||||
if(uip_ipaddr_cmp(&BUF->dipaddr, &uip_hostaddr)) {
|
||||
/* First, we register the one who made the request in our ARP
|
||||
table, since it is likely that we will do more communication
|
||||
with this host in the future. */
|
||||
uip_arp_update(&BUF->sipaddr, &BUF->shwaddr);
|
||||
|
||||
BUF->opcode = HTONS(ARP_REPLY);
|
||||
|
||||
memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6);
|
||||
memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
|
||||
memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||
memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6);
|
||||
|
||||
uip_ipaddr_copy(&BUF->dipaddr, &BUF->sipaddr);
|
||||
uip_ipaddr_copy(&BUF->sipaddr, &uip_hostaddr);
|
||||
|
||||
BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
|
||||
uip_len = sizeof(struct arp_hdr);
|
||||
}
|
||||
break;
|
||||
case HTONS(ARP_REPLY):
|
||||
/* ARP reply. We insert or update the ARP table if it was meant
|
||||
for us. */
|
||||
if(uip_ipaddr_cmp(&BUF->dipaddr, &uip_hostaddr)) {
|
||||
uip_arp_update(&BUF->sipaddr, &BUF->shwaddr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Prepend Ethernet header to an outbound IP packet and see if we need
|
||||
* to send out an ARP request.
|
||||
*
|
||||
* This function should be called before sending out an IP packet. The
|
||||
* function checks the destination IP address of the IP packet to see
|
||||
* what Ethernet MAC address that should be used as a destination MAC
|
||||
* address on the Ethernet.
|
||||
*
|
||||
* If the destination IP address is in the local network (determined
|
||||
* by logical ANDing of netmask and our IP address), the function
|
||||
* checks the ARP cache to see if an entry for the destination IP
|
||||
* address is found. If so, an Ethernet header is prepended and the
|
||||
* function returns. If no ARP cache entry is found for the
|
||||
* destination IP address, the packet in the uip_buf[] is replaced by
|
||||
* an ARP request packet for the IP address. The IP packet is dropped
|
||||
* and it is assumed that they higher level protocols (e.g., TCP)
|
||||
* eventually will retransmit the dropped packet.
|
||||
*
|
||||
* If the destination IP address is not on the local network, the IP
|
||||
* address of the default router is used instead.
|
||||
*
|
||||
* When the function returns, a packet is present in the uip_buf[]
|
||||
* buffer, and the length of the packet is in the global variable
|
||||
* uip_len.
|
||||
*/
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void
|
||||
uip_arp_out(void)
|
||||
{
|
||||
struct arp_entry *tabptr = NULL;
|
||||
|
||||
/* Find the destination IP address in the ARP table and construct
|
||||
the Ethernet header. If the destination IP addres isn't on the
|
||||
local network, we use the default router's IP address instead.
|
||||
|
||||
If not ARP table entry is found, we overwrite the original IP
|
||||
packet with an ARP request for the IP address. */
|
||||
|
||||
/* First check if destination is a local broadcast. */
|
||||
if(uip_ipaddr_cmp(&IPBUF->destipaddr, &uip_broadcast_addr)) {
|
||||
memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6);
|
||||
} else {
|
||||
/* Check if the destination address is on the local network. */
|
||||
if(!uip_ipaddr_maskcmp(&IPBUF->destipaddr, &uip_hostaddr, &uip_netmask)) {
|
||||
/* Destination address was not on the local network, so we need to
|
||||
use the default router's IP address instead of the destination
|
||||
address when determining the MAC address. */
|
||||
uip_ipaddr_copy(&ipaddr, &uip_draddr);
|
||||
} else {
|
||||
/* Else, we use the destination IP address. */
|
||||
uip_ipaddr_copy(&ipaddr, &IPBUF->destipaddr);
|
||||
}
|
||||
|
||||
for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
|
||||
tabptr = &arp_table[i];
|
||||
if(uip_ipaddr_cmp(&ipaddr, &tabptr->ipaddr)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == UIP_ARPTAB_SIZE) {
|
||||
/* The destination address was not in our ARP table, so we
|
||||
overwrite the IP packet with an ARP request. */
|
||||
|
||||
memset(BUF->ethhdr.dest.addr, 0xff, 6);
|
||||
memset(BUF->dhwaddr.addr, 0x00, 6);
|
||||
memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||
memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6);
|
||||
|
||||
uip_ipaddr_copy(&BUF->dipaddr, &ipaddr);
|
||||
uip_ipaddr_copy(&BUF->sipaddr, &uip_hostaddr);
|
||||
BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */
|
||||
BUF->hwtype = HTONS(ARP_HWTYPE_ETH);
|
||||
BUF->protocol = HTONS(UIP_ETHTYPE_IP);
|
||||
BUF->hwlen = 6;
|
||||
BUF->protolen = 4;
|
||||
BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP);
|
||||
|
||||
uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
|
||||
|
||||
uip_len = sizeof(struct arp_hdr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build an ethernet header. */
|
||||
memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6);
|
||||
}
|
||||
memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6);
|
||||
|
||||
IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP);
|
||||
|
||||
uip_len += sizeof(struct uip_eth_hdr);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
|
|
@ -1,145 +1,145 @@
|
|||
/**
|
||||
* \addtogroup uip
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uiparp
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Macros and definitions for the ARP module.
|
||||
* \author Adam Dunkels <adam@dunkels.com>
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: uip_arp.h,v 1.2 2006/08/26 23:58:45 oliverschmidt Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UIP_ARP_H__
|
||||
#define __UIP_ARP_H__
|
||||
|
||||
#include "uip.h"
|
||||
|
||||
|
||||
extern struct uip_eth_addr uip_ethaddr;
|
||||
|
||||
/**
|
||||
* The Ethernet header.
|
||||
*/
|
||||
struct uip_eth_hdr {
|
||||
struct uip_eth_addr dest;
|
||||
struct uip_eth_addr src;
|
||||
u16_t type;
|
||||
};
|
||||
|
||||
#define UIP_ETHTYPE_ARP 0x0806
|
||||
#define UIP_ETHTYPE_IP 0x0800
|
||||
#define UIP_ETHTYPE_IPV6 0x86dd
|
||||
|
||||
|
||||
/* The uip_arp_init() function must be called before any of the other
|
||||
ARP functions. */
|
||||
void uip_arp_init(void);
|
||||
|
||||
/* The uip_arp_ipin() function should be called whenever an IP packet
|
||||
arrives from the Ethernet. This function refreshes the ARP table or
|
||||
inserts a new mapping if none exists. The function assumes that an
|
||||
IP packet with an Ethernet header is present in the uip_buf buffer
|
||||
and that the length of the packet is in the uip_len variable. */
|
||||
/*void uip_arp_ipin(void);*/
|
||||
#define uip_arp_ipin()
|
||||
|
||||
/* The uip_arp_arpin() should be called when an ARP packet is received
|
||||
by the Ethernet driver. This function also assumes that the
|
||||
Ethernet frame is present in the uip_buf buffer. When the
|
||||
uip_arp_arpin() function returns, the contents of the uip_buf
|
||||
buffer should be sent out on the Ethernet if the uip_len variable
|
||||
is > 0. */
|
||||
void uip_arp_arpin(void);
|
||||
|
||||
/* The uip_arp_out() function should be called when an IP packet
|
||||
should be sent out on the Ethernet. This function creates an
|
||||
Ethernet header before the IP header in the uip_buf buffer. The
|
||||
Ethernet header will have the correct Ethernet MAC destination
|
||||
address filled in if an ARP table entry for the destination IP
|
||||
address (or the IP address of the default router) is present. If no
|
||||
such table entry is found, the IP packet is overwritten with an ARP
|
||||
request and we rely on TCP to retransmit the packet that was
|
||||
overwritten. In any case, the uip_len variable holds the length of
|
||||
the Ethernet frame that should be transmitted. */
|
||||
void uip_arp_out(void);
|
||||
|
||||
/* The uip_arp_timer() function should be called every ten seconds. It
|
||||
is responsible for flushing old entries in the ARP table. */
|
||||
void uip_arp_timer(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \addtogroup uipconffunc
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Specifiy the Ethernet MAC address.
|
||||
*
|
||||
* The ARP code needs to know the MAC address of the Ethernet card in
|
||||
* order to be able to respond to ARP queries and to generate working
|
||||
* Ethernet headers.
|
||||
*
|
||||
* \note This macro only specifies the Ethernet MAC address to the ARP
|
||||
* code. It cannot be used to change the MAC address of the Ethernet
|
||||
* card.
|
||||
*
|
||||
* \param eaddr A pointer to a struct uip_eth_addr containing the
|
||||
* Ethernet MAC address of the Ethernet card.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \
|
||||
uip_ethaddr.addr[1] = eaddr.addr[1];\
|
||||
uip_ethaddr.addr[2] = eaddr.addr[2];\
|
||||
uip_ethaddr.addr[3] = eaddr.addr[3];\
|
||||
uip_ethaddr.addr[4] = eaddr.addr[4];\
|
||||
uip_ethaddr.addr[5] = eaddr.addr[5];} while(0)
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#endif /* __UIP_ARP_H__ */
|
||||
/** @} */
|
||||
/**
|
||||
* \addtogroup uip
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup uiparp
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Macros and definitions for the ARP module.
|
||||
* \author Adam Dunkels <adam@dunkels.com>
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the uIP TCP/IP stack.
|
||||
*
|
||||
* $Id: uip_arp.h,v 1.2 2006/08/26 23:58:45 oliverschmidt Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __UIP_ARP_H__
|
||||
#define __UIP_ARP_H__
|
||||
|
||||
#include "uip.h"
|
||||
|
||||
|
||||
extern struct uip_eth_addr uip_ethaddr;
|
||||
|
||||
/**
|
||||
* The Ethernet header.
|
||||
*/
|
||||
struct uip_eth_hdr {
|
||||
struct uip_eth_addr dest;
|
||||
struct uip_eth_addr src;
|
||||
u16_t type;
|
||||
};
|
||||
|
||||
#define UIP_ETHTYPE_ARP 0x0806
|
||||
#define UIP_ETHTYPE_IP 0x0800
|
||||
#define UIP_ETHTYPE_IPV6 0x86dd
|
||||
|
||||
|
||||
/* The uip_arp_init() function must be called before any of the other
|
||||
ARP functions. */
|
||||
void uip_arp_init(void);
|
||||
|
||||
/* The uip_arp_ipin() function should be called whenever an IP packet
|
||||
arrives from the Ethernet. This function refreshes the ARP table or
|
||||
inserts a new mapping if none exists. The function assumes that an
|
||||
IP packet with an Ethernet header is present in the uip_buf buffer
|
||||
and that the length of the packet is in the uip_len variable. */
|
||||
/*void uip_arp_ipin(void);*/
|
||||
#define uip_arp_ipin()
|
||||
|
||||
/* The uip_arp_arpin() should be called when an ARP packet is received
|
||||
by the Ethernet driver. This function also assumes that the
|
||||
Ethernet frame is present in the uip_buf buffer. When the
|
||||
uip_arp_arpin() function returns, the contents of the uip_buf
|
||||
buffer should be sent out on the Ethernet if the uip_len variable
|
||||
is > 0. */
|
||||
void uip_arp_arpin(void);
|
||||
|
||||
/* The uip_arp_out() function should be called when an IP packet
|
||||
should be sent out on the Ethernet. This function creates an
|
||||
Ethernet header before the IP header in the uip_buf buffer. The
|
||||
Ethernet header will have the correct Ethernet MAC destination
|
||||
address filled in if an ARP table entry for the destination IP
|
||||
address (or the IP address of the default router) is present. If no
|
||||
such table entry is found, the IP packet is overwritten with an ARP
|
||||
request and we rely on TCP to retransmit the packet that was
|
||||
overwritten. In any case, the uip_len variable holds the length of
|
||||
the Ethernet frame that should be transmitted. */
|
||||
void uip_arp_out(void);
|
||||
|
||||
/* The uip_arp_timer() function should be called every ten seconds. It
|
||||
is responsible for flushing old entries in the ARP table. */
|
||||
void uip_arp_timer(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \addtogroup uipconffunc
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Specifiy the Ethernet MAC address.
|
||||
*
|
||||
* The ARP code needs to know the MAC address of the Ethernet card in
|
||||
* order to be able to respond to ARP queries and to generate working
|
||||
* Ethernet headers.
|
||||
*
|
||||
* \note This macro only specifies the Ethernet MAC address to the ARP
|
||||
* code. It cannot be used to change the MAC address of the Ethernet
|
||||
* card.
|
||||
*
|
||||
* \param eaddr A pointer to a struct uip_eth_addr containing the
|
||||
* Ethernet MAC address of the Ethernet card.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \
|
||||
uip_ethaddr.addr[1] = eaddr.addr[1];\
|
||||
uip_ethaddr.addr[2] = eaddr.addr[2];\
|
||||
uip_ethaddr.addr[3] = eaddr.addr[3];\
|
||||
uip_ethaddr.addr[4] = eaddr.addr[4];\
|
||||
uip_ethaddr.addr[5] = eaddr.addr[5];} while(0)
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#endif /* __UIP_ARP_H__ */
|
||||
/** @} */
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue