1
0
Fork 0

Squashed 'tmk_core/' changes from caca2c0..dc0e46e

dc0e46e Rename LUFA to LUFA-git
3bfa7fa Remove LUFA-120730
215b764 Merge commit 'afa0f22a9299686fd88f58ce09c5b521ac917e8f' as 'protocol/lufa/LUFA'
afa0f22 Squashed 'protocol/lufa/LUFA/' content from commit def7fca
c0c42fa Remove submodule of LUFA
30f897d Merge commit '87ced33feb74e79c3281dda36eb6d6d153399b41' as 'protocol/usb_hid/USB_Host_Shield_2.0'
87ced33 Squashed 'protocol/usb_hid/USB_Host_Shield_2.0/' content from commit aab4a69
14f6d49 Remove submodule of USB_Host_Shield_2.0

git-subtree-dir: tmk_core
git-subtree-split: dc0e46eaa4367d4e218f8816e3c117895820f07c
This commit is contained in:
tmk 2015-05-13 11:13:10 +09:00
parent 4d116a04e9
commit f6d56675f9
1575 changed files with 421901 additions and 63190 deletions

View file

@ -0,0 +1,208 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* 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"
#if defined(ENABLE_DHCP_CLIENT) || defined(__DOXYGEN__)
/** 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(DHCP_SERVER_PORT));
/* If the connection was successfully created, bind it to the local DHCP client port */
if (Connection != NULL)
{
uip_udp_appstate_t* const AppState = &Connection->appstate;
uip_udp_bind(Connection, HTONS(DHCP_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 += DHCPCommon_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) &&
DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &OfferResponse_MessageType) &&
(OfferResponse_MessageType == DHCP_OFFER))
{
/* Received a DHCP offer for an IP address, copy over values for later request */
memcpy(&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP, &AppData->YourIP, sizeof(uip_ipaddr_t));
DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK, &AppState->DHCPClient.DHCPOffer_Data.Netmask);
DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_ROUTER, &AppState->DHCPClient.DHCPOffer_Data.GatewayIP);
DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_SERVER_ID, &AppState->DHCPClient.DHCPOffer_Data.ServerIP);
timer_reset(&AppState->DHCPClient.Timeout);
AppState->DHCPClient.CurrentState = DHCP_STATE_SendRequest;
}
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 += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_REQ_IPADDR, sizeof(uip_ipaddr_t),
&AppState->DHCPClient.DHCPOffer_Data.AllocatedIP);
/* Add the DHCP SERVER IP ADDRESS option to the packet */
AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SERVER_ID, sizeof(uip_ipaddr_t),
&AppState->DHCPClient.DHCPOffer_Data.ServerIP);
/* Send the DHCP REQUEST packet */
uip_udp_send(AppDataSize);
/* 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) &&
DHCPCommon_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);
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* const 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);
}
#endif

View file

@ -0,0 +1,69 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for DHCPClientApp.c.
*/
#ifndef _DHCPCLIENT_APP_H_
#define _DHCPCLIENT_APP_H_
/* Includes: */
#include <stdio.h>
#include <uip.h>
#include "Config/AppConfig.h"
#include "../Webserver.h"
#include "DHCPCommon.h"
/* Enums: */
/** States for each DHCP connection to a DHCP client. */
enum DHCP_Client_States_t
{
DHCP_STATE_SendDiscover, /**< Send DISCOVER packet to retrieve DHCP lease offers */
DHCP_STATE_WaitForOffer, /**< Waiting for OFFER packet giving available DHCP leases */
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* const AppState);
#endif
#endif

View file

@ -0,0 +1,103 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Common DHCP routines to manage DHCP packet data.
*/
#include "DHCPCommon.h"
#if defined(ENABLE_DHCP_CLIENT) || defined(ENABLE_DHCP_SERVER) || defined(__DOXYGEN__)
/** Sets the given DHCP option in the DHCP packet's option list. This automatically moves the
* end of options terminator past the new option in the options list.
*
* \param[in,out] DHCPOptionList Pointer to the start of the DHCP packet's options list
* \param[in] Option DHCP option to add to the list
* \param[in] DataLen Size in bytes of the option data to add
* \param[in] OptionData Buffer where the option's data is to be sourced from
*
* \return Number of bytes added to the DHCP packet
*/
uint8_t DHCPCommon_SetOption(uint8_t* DHCPOptionList,
const uint8_t Option,
const uint8_t DataLen,
void* const OptionData)
{
/* Skip through the DHCP options list until the terminator option is found */
while (*DHCPOptionList != DHCP_OPTION_END)
DHCPOptionList += (DHCPOptionList[1] + 2);
/* Overwrite the existing terminator with the new option, add a new terminator at the end of the list */
DHCPOptionList[0] = Option;
DHCPOptionList[1] = DataLen;
memcpy(&DHCPOptionList[2], OptionData, DataLen);
DHCPOptionList[2 + DataLen] = DHCP_OPTION_END;
/* Calculate the total number of bytes added to the outgoing packet */
return (2 + DataLen);
}
/** Retrieves the given option's data (if present) from the DHCP packet's options list.
*
* \param[in,out] DHCPOptionList Pointer to the start of the DHCP packet's options list
* \param[in] Option DHCP option to retrieve to the list
* \param[out] Destination Buffer where the option's data is to be written to if found
*
* \return Boolean \c true if the option was found in the DHCP packet's options list, \c false otherwise
*/
bool DHCPCommon_GetOption(const uint8_t* DHCPOptionList,
const uint8_t Option,
void* const Destination)
{
/* Look through the incoming DHCP packet's options list for the requested option */
while (*DHCPOptionList != DHCP_OPTION_END)
{
/* Check if the current DHCP option in the packet is the one requested */
if (DHCPOptionList[0] == Option)
{
/* Copy request option's data to the destination buffer */
memcpy(Destination, &DHCPOptionList[2], DHCPOptionList[1]);
/* Indicate that the requested option data was successfully retrieved */
return true;
}
/* Skip to next DHCP option in the options list */
DHCPOptionList += (DHCPOptionList[1] + 2);
}
/* Requested option not found in the incoming packet's DHCP options list */
return false;
}
#endif

View file

@ -0,0 +1,159 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for common DHCP defines.
*/
#ifndef _DHCP_COMMON_H_
#define _DHCP_COMMON_H_
/* Includes: */
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "Config/AppConfig.h"
#include <uip.h>
/* Macros: */
/** UDP listen port for a BOOTP server. */
#define DHCP_SERVER_PORT 67
/** UDP listen port for a BOOTP client. */
#define DHCP_CLIENT_PORT 68
/** BOOTP message type for a BOOTP REQUEST message. */
#define DHCP_OP_BOOTREQUEST 0x01
/** BOOTP message type for a BOOTP REPLY message. */
#define DHCP_OP_BOOTREPLY 0x02
/** BOOTP flag for a BOOTP broadcast message. */
#define BOOTP_BROADCAST 0x8000
/** Magic DHCP cookie for a BOOTP message to identify it as a DHCP message. */
#define DHCP_MAGIC_COOKIE 0x63538263
/** Unique transaction ID used to identify DHCP responses to the client. */
#define DHCP_TRANSACTION_ID 0x13245466
/** DHCP message type for a DISCOVER message. */
#define DHCP_DISCOVER 1
/** DHCP message type for an OFFER message. */
#define DHCP_OFFER 2
/** DHCP message type for a REQUEST message. */
#define DHCP_REQUEST 3
/** DHCP message type for a DECLINE message. */
#define DHCP_DECLINE 4
/** DHCP message type for an ACK message. */
#define DHCP_ACK 5
/** DHCP message type for a NAK message. */
#define DHCP_NAK 6
/** DHCP message type for a RELEASE message. */
#define DHCP_RELEASE 7
/** DHCP medium type for standard Ethernet. */
#define DHCP_HTYPE_ETHERNET 1
/** DHCP message option for the network subnet mask. */
#define DHCP_OPTION_SUBNET_MASK 1
/** DHCP message option for the network gateway IP. */
#define DHCP_OPTION_ROUTER 3
/** DHCP message option for the network DNS server. */
#define DHCP_OPTION_DNS_SERVER 6
/** DHCP message option for the requested client IP address. */
#define DHCP_OPTION_REQ_IPADDR 50
/** DHCP message option for the IP address lease time. */
#define DHCP_OPTION_LEASE_TIME 51
/** DHCP message option for the DHCP message type. */
#define DHCP_OPTION_MSG_TYPE 53
/** DHCP message option for the DHCP server IP. */
#define DHCP_OPTION_SERVER_ID 54
/** DHCP message option for the list of required options from the server. */
#define DHCP_OPTION_REQ_LIST 55
/** DHCP message option for the options list terminator. */
#define DHCP_OPTION_END 255
/* Type Defines: */
/** Type define for a DHCP packet inside an Ethernet frame. */
typedef struct
{
uint8_t Operation; /**< DHCP operation, either DHCP_OP_BOOTREQUEST or DHCP_OP_BOOTREPLY */
uint8_t HardwareType; /**< Hardware carrier type constant */
uint8_t HardwareAddressLength; /**< Length in bytes of a hardware (MAC) address on the network */
uint8_t Hops; /**< Number of hops required to reach the server, unused */
uint32_t TransactionID; /**< Unique ID of the DHCP packet, for positive matching between sent and received packets */
uint16_t ElapsedSeconds; /**< Elapsed seconds since the request was made */
uint16_t Flags; /**< BOOTP packet flags */
uip_ipaddr_t ClientIP; /**< Client IP address, if already leased an IP */
uip_ipaddr_t YourIP; /**< Client IP address */
uip_ipaddr_t NextServerIP; /**< Legacy BOOTP protocol field, unused for DHCP */
uip_ipaddr_t RelayAgentIP; /**< Legacy BOOTP protocol field, unused for DHCP */
uint8_t ClientHardwareAddress[16]; /**< Hardware (MAC) address of the client making a request to the DHCP server */
uint8_t ServerHostnameString[64]; /**< Legacy BOOTP protocol field, unused for DHCP */
uint8_t BootFileName[128]; /**< Legacy BOOTP protocol field, unused for DHCP */
uint32_t Cookie; /**< Magic BOOTP protocol cookie to indicate a valid packet */
uint8_t Options[]; /**< DHCP message options */
} DHCP_Header_t;
/* Function Prototypes: */
uint8_t DHCPCommon_SetOption(uint8_t* DHCPOptionList,
const uint8_t Option,
const uint8_t DataLen,
void* const OptionData);
bool DHCPCommon_GetOption(const uint8_t* DHCPOptionList,
const uint8_t Option,
void* const Destination);
#endif

View file

@ -0,0 +1,265 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* DHCP Server Application. When connected to the uIP stack, this will send IP configuration settings to a
* DHCP client on the network.
*/
#define INCLUDE_FROM_DHCPSERVERAPP_C
#include "DHCPServerApp.h"
#if defined(ENABLE_DHCP_SERVER) || defined(__DOXYGEN__)
struct uip_conn* BroadcastConnection;
uint8_t LeasedIPs[255 / 8];
/** Initialization function for the DHCP server. */
void DHCPServerApp_Init(void)
{
/* Listen on port 67 for DHCP server connections from hosts */
uip_listen(HTONS(DHCP_SERVER_PORT));
/* Create a new UDP connection to the DHCP server port for the DHCP solicitation */
struct uip_udp_conn* BroadcastConnection = uip_udp_new(&uip_broadcast_addr, HTONS(DHCP_CLIENT_PORT));
/* If the connection was successfully created, bind it to the local DHCP client port */
if (BroadcastConnection != NULL)
uip_udp_bind(BroadcastConnection, HTONS(DHCP_SERVER_PORT));
/* Set all IP addresses as unleased */
memset(LeasedIPs, 0x00, sizeof(LeasedIPs));
}
/** uIP stack application callback for the DHCP server. This function must be called each time the TCP/IP stack
* needs a UDP packet to be processed.
*/
void DHCPServerApp_Callback(void)
{
DHCP_Header_t* const AppData = (DHCP_Header_t*)uip_appdata;
uint16_t AppDataSize = 0;
/* Only process when new data arrives - don't retransmit lost packets */
if (uip_newdata())
{
/* Get the DHCP message type (if present), otherwise early-abort */
uint8_t DHCPMessageType;
if (!(DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_MSG_TYPE, &DHCPMessageType)))
return;
uip_ipaddr_t Netmask, GatewayIPAddress, PreferredClientIP;
struct uip_eth_addr RemoteMACAddress;
uint32_t TransactionID;
/* Get configured network mask, gateway IP and extract out DHCP transaction ID and remote IP */
uip_getnetmask(&Netmask);
uip_getdraddr(&GatewayIPAddress);
memcpy(&RemoteMACAddress, &AppData->ClientHardwareAddress, sizeof(struct uip_eth_addr));
TransactionID = AppData->TransactionID;
/* Try to extract out the client's preferred IP address if it is indicated in the packet */
if (!(DHCPCommon_GetOption(AppData->Options, DHCP_OPTION_REQ_IPADDR, &PreferredClientIP)))
memcpy(&PreferredClientIP, &uip_all_zeroes_addr, sizeof(uip_ipaddr_t));
switch (DHCPMessageType)
{
case DHCP_DISCOVER:
/* If no preference was made or the preferred IP is already taken, find a new address */
if (DHCPServerApp_CheckIfIPLeased(&PreferredClientIP))
DHCPServerApp_GetUnleasedIP(&PreferredClientIP);
/* Create a new DHCP OFFER packet with the offered IP address */
AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_OFFER, &RemoteMACAddress, &PreferredClientIP, TransactionID);
/* Add network mask and router information to the list of DHCP OFFER packet options */
AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK,
sizeof(uip_ipaddr_t), &Netmask);
AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_ROUTER,
sizeof(uip_ipaddr_t), &GatewayIPAddress);
/* Send the DHCP OFFER packet */
uip_poll_conn(BroadcastConnection);
memcpy(&uip_udp_conn->ripaddr, &uip_broadcast_addr, sizeof(uip_ipaddr_t));
uip_udp_send(AppDataSize);
break;
case DHCP_REQUEST:
/* Check to see if the requested IP address has already been leased to a client */
if (!(DHCPServerApp_CheckIfIPLeased(&PreferredClientIP)))
{
/* Create a new DHCP ACK packet to accept the IP address lease */
AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_ACK, &RemoteMACAddress, &PreferredClientIP, TransactionID);
/* Add network mask and router information to the list of DHCP ACK packet options */
AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_SUBNET_MASK,
sizeof(uip_ipaddr_t), &Netmask);
AppDataSize += DHCPCommon_SetOption(AppData->Options, DHCP_OPTION_ROUTER,
sizeof(uip_ipaddr_t), &GatewayIPAddress);
/* Mark the requested IP as leased to a client */
DHCPServerApp_LeaseIP(&PreferredClientIP);
}
else
{
/* Create a new DHCP NAK packet to reject the requested allocation */
AppDataSize += DHCPServerApp_FillDHCPHeader(AppData, DHCP_NAK, &RemoteMACAddress, &uip_all_zeroes_addr, TransactionID);
}
/* Send the DHCP ACK or NAK packet */
uip_poll_conn(BroadcastConnection);
memcpy(&uip_udp_conn->ripaddr, &uip_broadcast_addr, sizeof(uip_ipaddr_t));
uip_udp_send(AppDataSize);
break;
case DHCP_RELEASE:
/* Mark the IP address as released in the allocation table */
DHCPServerApp_UnleaseIP(&uip_udp_conn->ripaddr);
break;
}
}
}
/** Fills the DHCP packet response with the appropriate BOOTP header for DHCP. This fills out all the required
* fields, leaving only the additional DHCP options to be added to the packet before it is sent to the DHCP client.
*
* \param[out] DHCPHeader Location in the packet buffer where the BOOTP header should be written to
* \param[in] DHCPMessageType DHCP Message type, such as DHCP_DISCOVER
* \param[in] ClientHardwareAddress Client MAC address the created transaction should be directed to
* \param[in] PreferredClientIP Preferred IP that should be given to the client if it is unallocated
* \param[in] TransactionID Transaction ID the created transaction should be associated with
*
* \return Size in bytes of the created DHCP packet
*/
static uint16_t DHCPServerApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader,
const uint8_t DHCPMessageType,
const struct uip_eth_addr* const ClientHardwareAddress,
const uip_ipaddr_t* const PreferredClientIP,
const uint32_t TransactionID)
{
/* Erase existing packet data so that we start will all 0x00 DHCP header data */
memset(DHCPHeader, 0, sizeof(DHCP_Header_t));
DHCPHeader->Operation = DHCPMessageType;
DHCPHeader->HardwareType = DHCP_HTYPE_ETHERNET;
DHCPHeader->HardwareAddressLength = sizeof(MACAddress);
DHCPHeader->Hops = 0;
DHCPHeader->TransactionID = TransactionID;
DHCPHeader->ElapsedSeconds = 0;
DHCPHeader->Flags = 0;
memcpy(&DHCPHeader->NextServerIP, &uip_hostaddr, sizeof(uip_ipaddr_t));
memcpy(&DHCPHeader->YourIP, PreferredClientIP, sizeof(uip_ipaddr_t));
memcpy(&DHCPHeader->ClientHardwareAddress, ClientHardwareAddress, sizeof(struct uip_eth_addr));
DHCPHeader->Cookie = DHCP_MAGIC_COOKIE;
/* Add a DHCP message type and terminator options to the start of the DHCP options field */
DHCPHeader->Options[0] = DHCP_OPTION_MSG_TYPE;
DHCPHeader->Options[1] = 1;
DHCPHeader->Options[2] = DHCPMessageType;
DHCPHeader->Options[3] = DHCP_OPTION_END;
/* Calculate the total number of bytes added to the outgoing packet */
return (sizeof(DHCP_Header_t) + 4);
}
/** Checks to see if the nominated IP address has already been allocated to a client.
*
* \param[in] IPAddress IP Address whose lease status should be checked
*
* \pre The IP address must be within the same /24 subnet as the virtual webserver.
*
* \return Boolean \c true if the IP has already been leased to a client, \c false otherwise.
*/
static bool DHCPServerApp_CheckIfIPLeased(const uip_ipaddr_t* const IPAddress)
{
uint8_t Byte = (IPAddress->u8[3] / 8);
uint8_t Mask = (1 << (IPAddress->u8[3] % 8));
/* Make sure that the requested IP address isn't already leased to the virtual server or another client */
if (IPAddress->u8[3] && !(IPAddress->u8[3] == uip_hostaddr.u8[3]) && !(LeasedIPs[Byte] & Mask))
return false;
else
return true;
}
/** Retrieves the next unleased IP in the IP address pool.
*
* \param[out] NewIPAddress Location where the generated IP Address should be stored
*/
static void DHCPServerApp_GetUnleasedIP(uip_ipaddr_t* const NewIPAddress)
{
uip_ipaddr_copy(NewIPAddress, &uip_hostaddr);
/** Look through the current subnet, skipping the broadcast and zero IP addresses */
for (uint8_t IP = 1; IP < 254; IP++)
{
/* Update new IP address to lease with the current IP address to test */
NewIPAddress->u8[3] = IP;
/* If we've found an unleased IP, abort with the updated IP stored for the called */
if (!(DHCPServerApp_CheckIfIPLeased(NewIPAddress)))
return;
}
}
/** Marks the given IP Address as leased in the address pool, so that it will not be
* allocated to another client unless it is first released.
*
* \param[in] IPAddress IP Address to mark as leased
*
* \pre The IP address must be within the same /24 subnet as the virtual webserver.
*/
static void DHCPServerApp_LeaseIP(const uip_ipaddr_t* const IPAddress)
{
uint8_t Byte = (IPAddress->u8[3] / 8);
uint8_t Mask = (1 << (IPAddress->u8[3] % 8));
/* Mark the IP address as leased in the allocation table */
LeasedIPs[Byte] |= Mask;
}
/** Marks the given IP Address as not leased in the address pool, so that it can be
* allocated to another client upon request.
*
* \param[in] IPAddress IP Address to mark as not leased
*
* \pre The IP address must be within the same /24 subnet as the virtual webserver.
*/
static void DHCPServerApp_UnleaseIP(const uip_ipaddr_t* const IPAddress)
{
uint8_t Byte = (IPAddress->u8[3] / 8);
uint8_t Mask = (1 << (IPAddress->u8[3] % 8));
/* Mark the IP address as unleased in the allocation table */
LeasedIPs[Byte] &= ~Mask;
}
#endif

View file

@ -0,0 +1,64 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for DHCPServerApp.c.
*/
#ifndef _DHCPSERVER_APP_H_
#define _DHCPSERVER_APP_H_
/* Includes: */
#include <stdio.h>
#include <uip.h>
#include "Config/AppConfig.h"
#include "../Webserver.h"
#include "DHCPCommon.h"
/* Function Prototypes: */
void DHCPServerApp_Init(void);
void DHCPServerApp_Callback(void);
#if defined(INCLUDE_FROM_DHCPSERVERAPP_C)
static uint16_t DHCPServerApp_FillDHCPHeader(DHCP_Header_t* const DHCPHeader,
const uint8_t DHCPMessageType,
const struct uip_eth_addr* const ClientHardwareAddress,
const uip_ipaddr_t* const PreferredClientIP,
const uint32_t TransactionID);
static bool DHCPServerApp_CheckIfIPLeased(const uip_ipaddr_t* const IPAddress);
static void DHCPServerApp_GetUnleasedIP(uip_ipaddr_t* const NewIPAddress);
static void DHCPServerApp_LeaseIP(const uip_ipaddr_t* const IPAddress);
static void DHCPServerApp_UnleaseIP(const uip_ipaddr_t* const IPAddress);
#endif
#endif

View file

@ -0,0 +1,534 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Functions to manage the physical Dataflash media, including reading and writing of
* blocks of data. These functions are called by the SCSI layer when data must be stored
* or retrieved to/from the physical storage media. If a different media is used (such
* as a SD card or EEPROM), functions similar to these will need to be generated.
*/
#define INCLUDE_FROM_DATAFLASHMANAGER_C
#include "DataflashManager.h"
/** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board Dataflash IC(s), from
* the pre-selected data OUT endpoint. This routine reads in OS sized blocks from the endpoint and writes
* them to the Dataflash in Dataflash page sized blocks.
*
* \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
* \param[in] BlockAddress Data block starting address for the write sequence
* \param[in] TotalBlocks Number of blocks of data to write
*/
void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const uint32_t BlockAddress,
uint16_t TotalBlocks)
{
uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
bool UsingSecondBuffer = false;
/* Select the correct starting Dataflash IC for the block requested */
Dataflash_SelectChipFromPage(CurrDFPage);
#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
/* Copy selected dataflash's current page contents to the Dataflash buffer */
Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);
Dataflash_SendAddressBytes(CurrDFPage, 0);
Dataflash_WaitWhileBusy();
#endif
/* Send the Dataflash buffer write command */
Dataflash_SendByte(DF_CMD_BUFF1WRITE);
Dataflash_SendAddressBytes(0, CurrDFPageByte);
/* Wait until endpoint is ready before continuing */
if (Endpoint_WaitUntilReady())
return;
while (TotalBlocks)
{
uint8_t BytesInBlockDiv16 = 0;
/* Write an endpoint packet sized data block to the Dataflash */
while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
{
/* Check if the endpoint is currently empty */
if (!(Endpoint_IsReadWriteAllowed()))
{
/* Clear the current endpoint bank */
Endpoint_ClearOUT();
/* Wait until the host has sent another packet */
if (Endpoint_WaitUntilReady())
return;
}
/* Check if end of Dataflash page reached */
if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
{
/* Write the Dataflash buffer contents back to the Dataflash page */
Dataflash_WaitWhileBusy();
Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
Dataflash_SendAddressBytes(CurrDFPage, 0);
/* Reset the Dataflash buffer counter, increment the page counter */
CurrDFPageByteDiv16 = 0;
CurrDFPage++;
/* Once all the Dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */
if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS))
UsingSecondBuffer = !(UsingSecondBuffer);
/* Select the next Dataflash chip based on the new Dataflash page index */
Dataflash_SelectChipFromPage(CurrDFPage);
#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
/* If less than one Dataflash page remaining, copy over the existing page to preserve trailing data */
if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))
{
/* Copy selected dataflash's current page contents to the Dataflash buffer */
Dataflash_WaitWhileBusy();
Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);
Dataflash_SendAddressBytes(CurrDFPage, 0);
Dataflash_WaitWhileBusy();
}
#endif
/* Send the Dataflash buffer write command */
Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE);
Dataflash_SendAddressBytes(0, 0);
}
/* Write one 16-byte chunk of data to the Dataflash */
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
Dataflash_SendByte(Endpoint_Read_8());
/* Increment the Dataflash page 16 byte block counter */
CurrDFPageByteDiv16++;
/* Increment the block 16 byte block counter */
BytesInBlockDiv16++;
/* Check if the current command is being aborted by the host */
if (MSInterfaceInfo->State.IsMassStoreReset)
return;
}
/* Decrement the blocks remaining counter */
TotalBlocks--;
}
/* Write the Dataflash buffer contents back to the Dataflash page */
Dataflash_WaitWhileBusy();
Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
Dataflash_SendAddressBytes(CurrDFPage, 0x00);
Dataflash_WaitWhileBusy();
/* If the endpoint is empty, clear it ready for the next packet from the host */
if (!(Endpoint_IsReadWriteAllowed()))
Endpoint_ClearOUT();
/* Deselect all Dataflash chips */
Dataflash_DeselectChip();
}
/** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board Dataflash IC(s), into
* the pre-selected data IN endpoint. This routine reads in Dataflash page sized blocks from the Dataflash
* and writes them in OS sized blocks to the endpoint.
*
* \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
* \param[in] BlockAddress Data block starting address for the read sequence
* \param[in] TotalBlocks Number of blocks of data to read
*/
void DataflashManager_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const uint32_t BlockAddress,
uint16_t TotalBlocks)
{
uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
/* Select the correct starting Dataflash IC for the block requested */
Dataflash_SelectChipFromPage(CurrDFPage);
/* Send the Dataflash main memory page read command */
Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
/* Wait until endpoint is ready before continuing */
if (Endpoint_WaitUntilReady())
return;
while (TotalBlocks)
{
uint8_t BytesInBlockDiv16 = 0;
/* Write an endpoint packet sized data block to the Dataflash */
while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
{
/* Check if the endpoint is currently full */
if (!(Endpoint_IsReadWriteAllowed()))
{
/* Clear the endpoint bank to send its contents to the host */
Endpoint_ClearIN();
/* Wait until the endpoint is ready for more data */
if (Endpoint_WaitUntilReady())
return;
}
/* Check if end of Dataflash page reached */
if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
{
/* Reset the Dataflash buffer counter, increment the page counter */
CurrDFPageByteDiv16 = 0;
CurrDFPage++;
/* Select the next Dataflash chip based on the new Dataflash page index */
Dataflash_SelectChipFromPage(CurrDFPage);
/* Send the Dataflash main memory page read command */
Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
Dataflash_SendAddressBytes(CurrDFPage, 0);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
}
/* Read one 16-byte chunk of data from the Dataflash */
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
Endpoint_Write_8(Dataflash_ReceiveByte());
/* Increment the Dataflash page 16 byte block counter */
CurrDFPageByteDiv16++;
/* Increment the block 16 byte block counter */
BytesInBlockDiv16++;
/* Check if the current command is being aborted by the host */
if (MSInterfaceInfo->State.IsMassStoreReset)
return;
}
/* Decrement the blocks remaining counter */
TotalBlocks--;
}
/* If the endpoint is full, send its contents to the host */
if (!(Endpoint_IsReadWriteAllowed()))
Endpoint_ClearIN();
/* Deselect all Dataflash chips */
Dataflash_DeselectChip();
}
/** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board Dataflash IC(s), from
* the given RAM buffer. This routine reads in OS sized blocks from the buffer and writes them to the
* Dataflash in Dataflash page sized blocks. This can be linked to FAT libraries to write files to the
* Dataflash.
*
* \param[in] BlockAddress Data block starting address for the write sequence
* \param[in] TotalBlocks Number of blocks of data to write
* \param[in] BufferPtr Pointer to the data source RAM buffer
*/
void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress,
uint16_t TotalBlocks,
const uint8_t* BufferPtr)
{
uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
bool UsingSecondBuffer = false;
/* Select the correct starting Dataflash IC for the block requested */
Dataflash_SelectChipFromPage(CurrDFPage);
#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
/* Copy selected dataflash's current page contents to the Dataflash buffer */
Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);
Dataflash_SendAddressBytes(CurrDFPage, 0);
Dataflash_WaitWhileBusy();
#endif
/* Send the Dataflash buffer write command */
Dataflash_SendByte(DF_CMD_BUFF1WRITE);
Dataflash_SendAddressBytes(0, CurrDFPageByte);
while (TotalBlocks)
{
uint8_t BytesInBlockDiv16 = 0;
/* Write an endpoint packet sized data block to the Dataflash */
while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
{
/* Check if end of Dataflash page reached */
if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
{
/* Write the Dataflash buffer contents back to the Dataflash page */
Dataflash_WaitWhileBusy();
Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
Dataflash_SendAddressBytes(CurrDFPage, 0);
/* Reset the Dataflash buffer counter, increment the page counter */
CurrDFPageByteDiv16 = 0;
CurrDFPage++;
/* Once all the Dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */
if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS))
UsingSecondBuffer = !(UsingSecondBuffer);
/* Select the next Dataflash chip based on the new Dataflash page index */
Dataflash_SelectChipFromPage(CurrDFPage);
#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
/* If less than one Dataflash page remaining, copy over the existing page to preserve trailing data */
if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))
{
/* Copy selected dataflash's current page contents to the Dataflash buffer */
Dataflash_WaitWhileBusy();
Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);
Dataflash_SendAddressBytes(CurrDFPage, 0);
Dataflash_WaitWhileBusy();
}
#endif
/* Send the Dataflash buffer write command */
Dataflash_ToggleSelectedChipCS();
Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE);
Dataflash_SendAddressBytes(0, 0);
}
/* Write one 16-byte chunk of data to the Dataflash */
for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++)
Dataflash_SendByte(*(BufferPtr++));
/* Increment the Dataflash page 16 byte block counter */
CurrDFPageByteDiv16++;
/* Increment the block 16 byte block counter */
BytesInBlockDiv16++;
}
/* Decrement the blocks remaining counter */
TotalBlocks--;
}
/* Write the Dataflash buffer contents back to the Dataflash page */
Dataflash_WaitWhileBusy();
Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
Dataflash_SendAddressBytes(CurrDFPage, 0x00);
Dataflash_WaitWhileBusy();
/* Deselect all Dataflash chips */
Dataflash_DeselectChip();
}
/** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board Dataflash IC(s), into
* the preallocated RAM buffer. This routine reads in Dataflash page sized blocks from the Dataflash
* and writes them in OS sized blocks to the given buffer. This can be linked to FAT libraries to read
* the files stored on the Dataflash.
*
* \param[in] BlockAddress Data block starting address for the read sequence
* \param[in] TotalBlocks Number of blocks of data to read
* \param[out] BufferPtr Pointer to the data destination RAM buffer
*/
void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress,
uint16_t TotalBlocks,
uint8_t* BufferPtr)
{
uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
/* Select the correct starting Dataflash IC for the block requested */
Dataflash_SelectChipFromPage(CurrDFPage);
/* Send the Dataflash main memory page read command */
Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
while (TotalBlocks)
{
uint8_t BytesInBlockDiv16 = 0;
/* Write an endpoint packet sized data block to the Dataflash */
while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
{
/* Check if end of Dataflash page reached */
if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
{
/* Reset the Dataflash buffer counter, increment the page counter */
CurrDFPageByteDiv16 = 0;
CurrDFPage++;
/* Select the next Dataflash chip based on the new Dataflash page index */
Dataflash_SelectChipFromPage(CurrDFPage);
/* Send the Dataflash main memory page read command */
Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
Dataflash_SendAddressBytes(CurrDFPage, 0);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
Dataflash_SendByte(0x00);
}
/* Read one 16-byte chunk of data from the Dataflash */
for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++)
*(BufferPtr++) = Dataflash_ReceiveByte();
/* Increment the Dataflash page 16 byte block counter */
CurrDFPageByteDiv16++;
/* Increment the block 16 byte block counter */
BytesInBlockDiv16++;
}
/* Decrement the blocks remaining counter */
TotalBlocks--;
}
/* Deselect all Dataflash chips */
Dataflash_DeselectChip();
}
/** Disables the Dataflash memory write protection bits on the board Dataflash ICs, if enabled. */
void DataflashManager_ResetDataflashProtections(void)
{
/* Select first Dataflash chip, send the read status register command */
Dataflash_SelectChip(DATAFLASH_CHIP1);
Dataflash_SendByte(DF_CMD_GETSTATUS);
/* Check if sector protection is enabled */
if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON)
{
Dataflash_ToggleSelectedChipCS();
/* Send the commands to disable sector protection */
Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);
Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);
Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);
Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);
}
/* Select second Dataflash chip (if present on selected board), send read status register command */
#if (DATAFLASH_TOTALCHIPS == 2)
Dataflash_SelectChip(DATAFLASH_CHIP2);
Dataflash_SendByte(DF_CMD_GETSTATUS);
/* Check if sector protection is enabled */
if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON)
{
Dataflash_ToggleSelectedChipCS();
/* Send the commands to disable sector protection */
Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);
Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);
Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);
Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);
}
#endif
/* Deselect current Dataflash chip */
Dataflash_DeselectChip();
}
/** Performs a simple test on the attached Dataflash IC(s) to ensure that they are working.
*
* \return Boolean \c true if all media chips are working, \c false otherwise
*/
bool DataflashManager_CheckDataflashOperation(void)
{
uint8_t ReturnByte;
/* Test first Dataflash IC is present and responding to commands */
Dataflash_SelectChip(DATAFLASH_CHIP1);
Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
ReturnByte = Dataflash_ReceiveByte();
Dataflash_DeselectChip();
/* If returned data is invalid, fail the command */
if (ReturnByte != DF_MANUFACTURER_ATMEL)
return false;
#if (DATAFLASH_TOTALCHIPS == 2)
/* Test second Dataflash IC is present and responding to commands */
Dataflash_SelectChip(DATAFLASH_CHIP2);
Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
ReturnByte = Dataflash_ReceiveByte();
Dataflash_DeselectChip();
/* If returned data is invalid, fail the command */
if (ReturnByte != DF_MANUFACTURER_ATMEL)
return false;
#endif
return true;
}

View file

@ -0,0 +1,87 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* 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/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)
/** Indicates if the disk is write protected or not. */
#define DISK_READ_ONLY false
/* 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

View file

@ -0,0 +1,135 @@
FatFs Module Source Files R0.09a (C)ChaN, 2012
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 An example of glue function to attach existing disk I/O module to FatFs.
integer.h Integer type definitions for FatFs.
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) 2012, 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, 2009, 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, 2009, R0.07a Separated out OS dependent code on reentrant cfg.
Added multiple sector size support.
Jun 21, 2009, 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, 2009 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.
May 15, 2010, R0.08 Added a memory configuration option. (_USE_LFN)
Added file lock feature. (_FS_SHARE)
Added fast seek feature. (_USE_FASTSEEK)
Changed some types on the API, XCHAR->TCHAR.
Changed fname member in the FILINFO structure on Unicode cfg.
String functions support UTF-8 encoding files on Unicode cfg.
Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2)
Added sector erase feature. (_USE_ERASE)
Moved file lock semaphore table from fs object to the bss.
Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'.
Fixed f_mkfs() creates wrong FAT32 volume.
Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf function.
Ignores duplicated directory separators in given path names.
Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
Added f_fdisk(). (_MULTI_PARTITION = 2)
Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16.
Changed API rejects null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.

View file

@ -0,0 +1,65 @@
/*-----------------------------------------------------------------------*/
/* 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"
/*-----------------------------------------------------------------------*/
/* Initialize a Drive */
DSTATUS disk_initialize (
BYTE drv /* Physical drive number (0..) */
)
{
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* Return Disk Status */
DSTATUS disk_status (
BYTE drv /* Physical drive number (0..) */
)
{
return FR_OK;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
DRESULT disk_read (
BYTE drv, /* Physical drive number (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..128) */
)
{
DataflashManager_ReadBlocks_RAM(sector, count, buff);
return RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive number (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..128) */
)
{
DataflashManager_WriteBlocks_RAM(sector, count, buff);
return RES_OK;
}
#endif /* _READONLY */

View file

@ -0,0 +1,52 @@
/*-----------------------------------------------------------------------
/ Low level disk interface module include file
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#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 */
DSTATUS disk_initialize (BYTE);
DSTATUS disk_status (BYTE);
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
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 */
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,337 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.09a (C)ChaN, 2012
/----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 2012, 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.
/
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 4004 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h" /* Basic integer types */
#include "ffconf.h" /* FatFs configuration options */
#if _FATFS != _FFCONF
#error Wrong configuration file (ffconf.h).
#endif
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
#else /* Single partition configuration */
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */
#endif
/* Type of path name strings on FatFs API */
#if _LFN_UNICODE /* Unicode string */
#if !_USE_LFN
#error _LFN_UNICODE must be 0 in non-LFN cfg.
#endif
#ifndef _INC_TCHAR
typedef WCHAR TCHAR;
#define _T(x) L ## x
#define _TEXT(x) L ## x
#endif
#else /* ANSI/OEM string */
#ifndef _INC_TCHAR
typedef char TCHAR;
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
/* File system object structure (FATFS) */
typedef struct {
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
BYTE drv; /* Physical drive number */
BYTE csize; /* Sectors per cluster (1,2,4...128) */
BYTE n_fats; /* Number of FAT copies (1,2) */
BYTE wflag; /* win[] dirty flag (1:must be written back) */
BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != 512
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
#endif
#if !_FS_READONLY
DWORD last_clust; /* Last allocated cluster */
DWORD free_clust; /* Number of free clusters */
DWORD fsi_sector; /* fsinfo sector (FAT32) */
#endif
#if _FS_RPATH
DWORD cdir; /* Current directory start cluster (0:root) */
#endif
DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */
DWORD fsize; /* Sectors per FAT */
DWORD fatbase; /* FAT start sector */
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
DWORD database; /* Data start sector */
DWORD winsect; /* Current sector appearing in the win[] */
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */
} FATFS;
/* File object structure (FIL) */
typedef struct {
FATFS* fs; /* Pointer to the related file system object */
WORD id; /* File system mount ID of the related file system object */
BYTE flag; /* File status flags */
BYTE pad1;
DWORD fptr; /* File read/write pointer (0ed on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */
DWORD clust; /* Current cluster of fpter */
DWORD dsect; /* Current data sector of fpter */
#if !_FS_READONLY
DWORD dir_sect; /* Sector containing the directory entry */
BYTE* dir_ptr; /* Pointer to the directory entry in the window */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */
#endif
#if _FS_LOCK
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File data read/write buffer */
#endif
} FIL;
/* Directory object structure (DIR) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
WORD index; /* Current read/write index number */
DWORD sclust; /* Table start cluster (0:Root dir) */
DWORD clust; /* Current cluster */
DWORD sect; /* Current sector */
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _USE_LFN
WCHAR* lfn; /* Pointer to the LFN working buffer */
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
} DIR;
/* File status structure (FILINFO) */
typedef struct {
DWORD fsize; /* File size */
WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */
BYTE fattrib; /* Attribute */
TCHAR fname[13]; /* Short file name (8.3 format) */
#if _USE_LFN
TCHAR* lfname; /* Pointer to the LFN buffer */
UINT lfsize; /* Size of LFN buffer in TCHAR */
#endif
} FILINFO;
/* File function return code (FRESULT) */
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
/*--------------------------------------------------------------*/
/* FatFs module application interface */
FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */
FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
FRESULT f_close (FIL*); /* Close an open file object */
FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */
FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */
FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
FRESULT f_truncate (FIL*); /* Truncate file */
FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */
FRESULT f_mkdir (const TCHAR*); /* Create a new directory */
FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attribute of the file/dir */
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change times-tamp of the file/dir */
FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */
FRESULT f_chdrive (BYTE); /* Change current drive */
FRESULT f_chdir (const TCHAR*); /* Change current directory */
FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */
FRESULT f_fdisk (BYTE, const DWORD[], void*); /* Divide a physical drive into some partitions */
int f_putc (TCHAR, FIL*); /* Put a character to the file */
int f_puts (const TCHAR*, FIL*); /* Put a string to the file */
int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->fsize)
#ifndef EOF
#define EOF (-1)
#endif
/*--------------------------------------------------------------*/
/* Additional user defined functions */
/* RTC function */
#if !_FS_READONLY
DWORD get_fattime (void);
#endif
/* Unicode support functions */
#if _USE_LFN /* Unicode - OEM code conversion */
WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */
WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */
#if _USE_LFN == 3 /* Memory functions */
void* ff_memalloc (UINT); /* Allocate memory block */
void ff_memfree (void*); /* Free memory block */
#endif
#endif
/* Sync functions */
#if _FS_REENTRANT
int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */
int ff_req_grant (_SYNC_t); /* Lock sync object */
void ff_rel_grant (_SYNC_t); /* Unlock sync object */
int ff_del_syncobj (_SYNC_t); /* Delete a sync object */
#endif
/*--------------------------------------------------------------*/
/* Flags and offset address */
/* File access control and file status flags (FIL.flag) */
#define FA_READ 0x01
#define FA_OPEN_EXISTING 0x00
#define FA__ERROR 0x80
#if !_FS_READONLY
#define FA_WRITE 0x02
#define FA_CREATE_NEW 0x04
#define FA_CREATE_ALWAYS 0x08
#define FA_OPEN_ALWAYS 0x10
#define FA__WRITTEN 0x20
#define FA__DIRTY 0x40
#endif
/* FAT sub type (FATFS.fs_type) */
#define FS_FAT12 1
#define FS_FAT16 2
#define FS_FAT32 3
/* File attribute bits for directory entry */
#define AM_RDO 0x01 /* Read only */
#define AM_HID 0x02 /* Hidden */
#define AM_SYS 0x04 /* System */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_DIR 0x10 /* Directory */
#define AM_ARC 0x20 /* Archive */
#define AM_MASK 0x3F /* Mask of defined bits */
/* Fast seek feature */
#define CREATE_LINKMAP 0xFFFFFFFF
/*--------------------------------*/
/* Multi-byte word access macros */
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
#else /* Use byte-by-byte access to the FAT structure */
#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
#endif
#ifdef __cplusplus
}
#endif
#endif /* _FATFS */

View file

@ -0,0 +1,190 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.09a (C)ChaN, 2012
/----------------------------------------------------------------------------/
/
/ CAUTION! Do not forget to make clean the project after any changes to
/ the configuration options.
/
/----------------------------------------------------------------------------*/
#ifndef _FFCONF
#define _FFCONF 4004 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function and Buffer Configurations
/----------------------------------------------------------------------------*/
#define _FS_TINY 1 /* 0:Normal or 1:Tiny */
/* 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:Read/Write or 1:Read only */
/* 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 to 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 1.
/ 3: f_lseek is removed in addition to 2. */
#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
#define _USE_MKFS 0 /* 0:Disable or 1:Enable */
/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
/* To enable fast seek feature, set _USE_FASTSEEK 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 to 3 */
#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
/* The _USE_LFN option switches the LFN support.
/
/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
/ 2: Enable LFN with dynamic working buffer on the STACK.
/ 3: Enable LFN with dynamic working buffer on the HEAP.
/
/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
/ Unicode handling functions ff_convert() and ff_wtoupper() must be added
/ to the project. When enable to use heap, memory control functions
/ ff_memalloc() and ff_memfree() must be added to the project. */
#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
/* 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 to 2 */
/* The _FS_RPATH option configures relative path feature.
/
/ 0: Disable relative path feature and remove related functions.
/ 1: Enable relative path. f_chdrive() and f_chdir() are available.
/ 2: f_getcwd() is available in addition to 1.
/
/ Note that output of the f_readdir function is affected by this option. */
/*---------------------------------------------------------------------------/
/ Physical Drive Configurations
/----------------------------------------------------------------------------*/
#define _VOLUMES 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 on-board flash memory, floppy disk and optical disk.
/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size
/ and GET_SECTOR_SIZE command must be implemented to the disk_ioctl function. */
#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */
/* When set to 0, each volume is bound to the same physical drive number and
/ it can mount only first primary partition. When it is set to 1, each volume
/ is tied to the partitions listed in VolToPart[]. */
#define _USE_ERASE 0 /* 0:Disable or 1:Enable */
/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command
/ should be added to the disk_ioctl function. */
/*---------------------------------------------------------------------------/
/ System Configurations
/----------------------------------------------------------------------------*/
#define _WORD_ACCESS 1 /* 0 or 1 */
/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS
/ option defines which access method is used to the word data on the FAT volume.
/
/ 0: Byte-by-byte access.
/ 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. */
/* A header file that defines sync object types on the O/S, such as
/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */
#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */
#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 (thread safe) 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. */
#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */
/* To enable file lock control feature, set _FS_LOCK to 1 or greater.
The value defines how many files can be opened simultaneously. */
#endif /* _FFCONFIG */

View file

@ -0,0 +1,38 @@
/*-------------------------------------------*/
/* Integer type definitions for FatFs module */
/*-------------------------------------------*/
#ifndef _INTEGER
#define _INTEGER
#ifdef _WIN32 /* FatFs development platform */
#include <windows.h>
#include <tchar.h>
#else /* Embedded platform */
/* 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 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;
#endif
#endif

View file

@ -0,0 +1,284 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* 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
* 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 */
strlcpy(AppState->HTTPServer.FileName, &RequestedFileName[1], sizeof(AppState->HTTPServer.FileName));
/* 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] == '/') || !(FileNameLen))
{
strlcpy_P(&AppState->HTTPServer.FileName[FileNameLen], DefaultDirFileName,
(sizeof(AppState->HTTPServer.FileName) - FileNameLen));
}
/* 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);
strcat(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)
{
strcat(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 */
strcat_P(AppData, DefaultMIMEType);
}
/* Add the end-of-line terminator and end-of-headers terminator after the MIME type */
strcat_P(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;
}

View file

@ -0,0 +1,84 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* 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 "Config/AppConfig.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

View file

@ -0,0 +1,344 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* 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.
*/
static const 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.
*/
static 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
*
* \return Boolean \c true if the command completed successfully, \c false otherwise
*/
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
bool CommandSuccess = false;
/* Run the appropriate SCSI command hander function based on the passed command */
switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
{
case SCSI_CMD_INQUIRY:
CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);
break;
case SCSI_CMD_REQUEST_SENSE:
CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
break;
case SCSI_CMD_READ_CAPACITY_10:
CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
break;
case SCSI_CMD_SEND_DIAGNOSTIC:
CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
break;
case SCSI_CMD_WRITE_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
break;
case SCSI_CMD_READ_10:
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
break;
case SCSI_CMD_MODE_SENSE_6:
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
break;
case SCSI_CMD_START_STOP_UNIT:
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 */
CommandSuccess = true;
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;
}
/* Check if command was successfully processed */
if (CommandSuccess)
{
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
SCSI_ASENSEQ_NO_QUALIFIER);
return true;
}
return false;
}
/** 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
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
uint16_t AllocationLength = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]);
uint16_t BytesTransferred = MIN(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 false;
}
Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NULL);
/* Pad out remaining bytes with 0x00 */
Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
/* 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;
return true;
}
/** 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
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
uint8_t AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
uint8_t BytesTransferred = MIN(AllocationLength, sizeof(SenseData));
Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NULL);
Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
return true;
}
/** 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
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool 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), NULL);
Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NULL);
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
return true;
}
/** 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
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool 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 false;
}
/* 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 false;
}
/* Succeed the command and update the bytes transferred counter */
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
return true;
}
/** 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)
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead)
{
uint32_t BlockAddress;
uint16_t TotalBlocks;
/* Check if the disk is write protected or not */
if ((IsDataRead == DATA_WRITE) && DISK_READ_ONLY)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_DATA_PROTECT,
SCSI_ASENSE_WRITE_PROTECTED,
SCSI_ASENSEQ_NO_QUALIFIER);
return false;
}
/* 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(*(uint16_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 false;
}
/* 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);
return true;
}
/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
* the SCSI device, as well as the device's Write Protect status.
*
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
*
* \return Boolean \c true if the command completed successfully, \c false otherwise.
*/
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
{
/* Send an empty header response with the Write Protect flag status */
Endpoint_Write_8(0x00);
Endpoint_Write_8(0x00);
Endpoint_Write_8(DISK_READ_ONLY ? 0x80 : 0x00);
Endpoint_Write_8(0x00);
Endpoint_ClearIN();
/* Update the bytes transferred counter and succeed the command */
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
return true;
}

View file

@ -0,0 +1,87 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* 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 "../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) do { SenseData.SenseKey = (Key); \
SenseData.AdditionalSenseCode = (Acode); \
SenseData.AdditionalSenseQualifier = (Aqual); } while (0)
/** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
#define DATA_READ true
/** Macro for the \ref 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 bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
const bool IsDataRead);
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
#endif
#endif

View file

@ -0,0 +1,163 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* 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"
#if defined(ENABLE_TELNET_SERVER) || defined(__DOXYGEN__)
/** 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 TELNET 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) %d.%d.%d.%d (Local Port %u <=> Remote Port %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

View file

@ -0,0 +1,71 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* 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>
#include "Config/AppConfig.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

View file

@ -0,0 +1,298 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* 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. */
static struct timer ConnectionTimer;
/** ARP timer, to retain the time elapsed since the ARP cache was last updated. */
static struct timer ARPTimer;
/** MAC address of the RNDIS device, when enumerated. */
struct uip_eth_addr MACAddress;
/** Configures the uIP stack ready for network traffic processing. */
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();
/* DHCP/Server IP Settings Initialization */
if (USB_CurrentMode == USB_MODE_Device)
{
MACAddress.addr[0] = SERVER_MAC_ADDRESS[0];
MACAddress.addr[1] = SERVER_MAC_ADDRESS[1];
MACAddress.addr[2] = SERVER_MAC_ADDRESS[2];
MACAddress.addr[3] = SERVER_MAC_ADDRESS[3];
MACAddress.addr[4] = SERVER_MAC_ADDRESS[4];
MACAddress.addr[5] = SERVER_MAC_ADDRESS[5];
#if defined(ENABLE_DHCP_SERVER)
DHCPServerApp_Init();
#endif
uip_ipaddr_t IPAddress, Netmask, GatewayIPAddress;
uip_ipaddr(&IPAddress, DEVICE_IP_ADDRESS[0], DEVICE_IP_ADDRESS[1], DEVICE_IP_ADDRESS[2], DEVICE_IP_ADDRESS[3]);
uip_ipaddr(&Netmask, DEVICE_NETMASK[0], DEVICE_NETMASK[1], DEVICE_NETMASK[2], DEVICE_NETMASK[3]);
uip_ipaddr(&GatewayIPAddress, DEVICE_GATEWAY[0], DEVICE_GATEWAY[1], DEVICE_GATEWAY[2], DEVICE_GATEWAY[3]);
uip_sethostaddr(&IPAddress);
uip_setnetmask(&Netmask);
uip_setdraddr(&GatewayIPAddress);
}
else
{
#if defined(ENABLE_DHCP_CLIENT)
DHCPClientApp_Init();
#else
uip_ipaddr_t IPAddress, Netmask, GatewayIPAddress;
uip_ipaddr(&IPAddress, DEVICE_IP_ADDRESS[0], DEVICE_IP_ADDRESS[1], DEVICE_IP_ADDRESS[2], DEVICE_IP_ADDRESS[3]);
uip_ipaddr(&Netmask, DEVICE_NETMASK[0], DEVICE_NETMASK[1], DEVICE_NETMASK[2], DEVICE_NETMASK[3]);
uip_ipaddr(&GatewayIPAddress, DEVICE_GATEWAY[0], DEVICE_GATEWAY[1], DEVICE_GATEWAY[2], DEVICE_GATEWAY[3]);
uip_sethostaddr(&IPAddress);
uip_setnetmask(&Netmask);
uip_setdraddr(&GatewayIPAddress);
#endif
}
/* Virtual Webserver Ethernet Address Configuration */
uip_setethaddr(MACAddress);
/* HTTP Webserver Initialization */
HTTPServerApp_Init();
/* 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)) ||
((USB_CurrentMode == USB_MODE_Device) && (USB_DeviceState == DEVICE_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)
{
#if defined(ENABLE_DHCP_CLIENT)
case HTONS(DHCP_CLIENT_PORT):
DHCPClientApp_Callback();
break;
#endif
#if defined(ENABLE_DHCP_SERVER)
case HTONS(DHCP_SERVER_PORT):
DHCPServerApp_Callback();
break;
#endif
}
}
/** Processes Incoming packets to the server from the connected RNDIS device, creating responses as needed. */
static void uIPManagement_ProcessIncomingPacket(void)
{
/* Determine which USB mode the system is currently initialized in */
if (USB_CurrentMode == USB_MODE_Device)
{
/* If no packet received, exit processing routine */
if (!(RNDIS_Device_IsPacketReceived(&Ethernet_RNDIS_Interface_Device)))
return;
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
/* Read the Incoming packet straight into the UIP packet buffer */
RNDIS_Device_ReadPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, &uip_len);
}
else
{
/* If no packet received, exit processing routine */
if (!(RNDIS_Host_IsPacketReceived(&Ethernet_RNDIS_Interface_Host)))
return;
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
/* Read the Incoming packet straight into the UIP packet buffer */
RNDIS_Host_ReadPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, &uip_len);
}
/* If the packet contains an Ethernet frame, process it */
if (uip_len > 0)
{
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);
}
/** 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();
}
}

View file

@ -0,0 +1,69 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2014.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaims all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for uIPManagement.c.
*/
#ifndef _UIP_MANAGEMENT_H_
#define _UIP_MANAGEMENT_H_
/* Includes: */
#include <LUFA/Drivers/USB/USB.h>
#include <uip.h>
#include <uip_arp.h>
#include <uip-split.h>
#include <timer.h>
#include "Config/AppConfig.h"
#include "DHCPClientApp.h"
#include "DHCPServerApp.h"
#include "HTTPServerApp.h"
#include "TELNETServerApp.h"
/* External Variables: */
extern struct uip_eth_addr MACAddress;
/* 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

View file

@ -0,0 +1,37 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <LUFA/Common/Common.h>
#include "clock.h"
//Counted time
volatile clock_time_t clock_datetime = 0;
//Overflow interrupt
ISR(TIMER1_COMPA_vect, ISR_BLOCK)
{
clock_datetime += 1;
}
//Initialise the clock
void clock_init()
{
OCR1A = (((F_CPU / 1024) / 100) - 1);
TCCR1B = ((1 << WGM12) | (1 << CS12) | (1 << CS10));
TIMSK1 = (1 << OCIE1A);
}
//Return time
clock_time_t clock_time()
{
clock_time_t time;
GlobalInterruptDisable();
time = clock_datetime;
GlobalInterruptEnable();
return time;
}

View file

@ -0,0 +1,13 @@
#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__ */

View file

@ -0,0 +1,128 @@
/**
* \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_restart() 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 periodic 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;
}
/*---------------------------------------------------------------------------*/
/** @} */

View file

@ -0,0 +1,87 @@
/**
* \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__ */
/** @} */

View file

@ -0,0 +1,151 @@
/*
* 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
if (USB_CurrentMode == USB_MODE_Device)
RNDIS_Device_SendPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, uip_len);
else
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, uip_len);
#endif /* UIP_CONF_IPV6 */
/* Now, create the second packet. To do this, it is not enough to
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 determined 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
if (USB_CurrentMode == USB_MODE_Device)
RNDIS_Device_SendPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, uip_len);
else
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, uip_len);
#endif /* UIP_CONF_IPV6 */
return;
}
#endif /* UIP_TCP */
/* uip_fw_output();*/
#if UIP_CONF_IPV6
tcpip_ipv6_output();
#else
if (USB_CurrentMode == USB_MODE_Device)
RNDIS_Device_SendPacket(&Ethernet_RNDIS_Interface_Device, uip_buf, uip_len);
else
RNDIS_Host_SendPacket(&Ethernet_RNDIS_Interface_Host, uip_buf, uip_len);
#endif /* UIP_CONF_IPV6 */
}
/*-----------------------------------------------------------------------------*/

View file

@ -0,0 +1,104 @@
/*
* 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/USB.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

View file

@ -0,0 +1,432 @@
/**
* \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 address 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);
}
/*-----------------------------------------------------------------------------------*/
/** @} */
/** @} */

View file

@ -0,0 +1,146 @@
/**
* \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__ */
/** @} */

View file

@ -0,0 +1,740 @@
/**
* \addtogroup uip
* @{
*/
/**
* \defgroup uipopt Configuration options for uIP
* @{
*
* uIP is configured using the per-project configuration file
* "uipopt.h". This file contains all compile-time options for uIP and
* should be tweaked to match each specific project. The uIP
* distribution contains a documented example "uipopt.h" that can be
* copied and modified for each project.
*/
/**
* \file
* Configuration options for uIP.
* \author Adam Dunkels <adam@dunkels.com>
*
* This file is used for tweaking various configuration options for
* uIP. You should make a copy of this file into one of your project's
* directories instead of editing this example "uipopt.h" file that
* comes with the uIP distribution.
*/
/*
* 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: uipopt.h,v 1.11 2009/04/10 00:37:48 adamdunkels Exp $
*
*/
#ifndef __UIPOPT_H__
#define __UIPOPT_H__
#include "Config/AppConfig.h"
#ifndef UIP_LITTLE_ENDIAN
#define UIP_LITTLE_ENDIAN 3412
#endif /* UIP_LITTLE_ENDIAN */
#ifndef UIP_BIG_ENDIAN
#define UIP_BIG_ENDIAN 1234
#endif /* UIP_BIG_ENDIAN */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptstaticconf Static configuration options
* @{
*
* These configuration options can be used for setting the IP address
* settings statically, but only if UIP_FIXEDADDR is set to 1. The
* configuration options for a specific node includes IP address,
* netmask and default router as well as the Ethernet address. The
* netmask, default router and Ethernet address are applicable only
* if uIP should be run over Ethernet.
*
* This options are meaningful only for the IPv4 code.
*
* All of these should be changed to suit your project.
*/
/**
* Determines if uIP should use a fixed IP address or not.
*
* If uIP should use a fixed IP address, the settings are set in the
* uipopt.h file. If not, the macros uip_sethostaddr(),
* uip_setdraddr() and uip_setnetmask() should be used instead.
*
* \hideinitializer
*/
#define UIP_FIXEDADDR 0
/**
* Ping IP address assignment.
*
* uIP uses a "ping" packets for setting its own IP address if this
* option is set. If so, uIP will start with an empty IP address and
* the destination IP address of the first incoming "ping" (ICMP echo)
* packet will be used for setting the hosts IP address.
*
* \note This works only if UIP_FIXEDADDR is 0.
*
* \hideinitializer
*/
#ifdef UIP_CONF_PINGADDRCONF
#define UIP_PINGADDRCONF UIP_CONF_PINGADDRCONF
#else /* UIP_CONF_PINGADDRCONF */
#define UIP_PINGADDRCONF 0
#endif /* UIP_CONF_PINGADDRCONF */
/**
* Specifies if the uIP ARP module should be compiled with a fixed
* Ethernet MAC address or not.
*
* If this configuration option is 0, the macro uip_setethaddr() can
* be used to specify the Ethernet address at run-time.
*
* \hideinitializer
*/
#define UIP_FIXEDETHADDR 0
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptip IP configuration options
* @{
*
*/
/**
* The IP TTL (time to live) of IP packets sent by uIP.
*
* This should normally not be changed.
*/
#define UIP_TTL 64
/**
* The maximum time an IP fragment should wait in the reassembly
* buffer before it is dropped.
*
*/
#define UIP_REASS_MAXAGE 60 /*60s*/
/**
* Turn on support for IP packet reassembly.
*
* uIP supports reassembly of fragmented IP packets. This features
* requires an additional amount of RAM to hold the reassembly buffer
* and the reassembly code size is approximately 700 bytes. The
* reassembly buffer is of the same size as the uip_buf buffer
* (configured by UIP_BUFSIZE).
*
* \note IP packet reassembly is not heavily tested.
*
* \hideinitializer
*/
#ifdef UIP_CONF_REASSEMBLY
#define UIP_REASSEMBLY UIP_CONF_REASSEMBLY
#else /* UIP_CONF_REASSEMBLY */
#define UIP_REASSEMBLY 0
#endif /* UIP_CONF_REASSEMBLY */
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptipv6 IPv6 configuration options
* @{
*
*/
/** The maximum transmission unit at the IP Layer*/
#define UIP_LINK_MTU 1280
#ifndef UIP_CONF_IPV6
/** Do we use IPv6 or not (default: no) */
#define UIP_CONF_IPV6 0
#endif
#ifndef UIP_CONF_IPV6_QUEUE_PKT
/** Do we do per %neighbor queuing during address resolution (default: no) */
#define UIP_CONF_IPV6_QUEUE_PKT 0
#endif
#ifndef UIP_CONF_IPV6_CHECKS
/** Do we do IPv6 consistency checks (highly recommended, default: yes) */
#define UIP_CONF_IPV6_CHECKS 1
#endif
#ifndef UIP_CONF_IPV6_REASSEMBLY
/** Do we do IPv6 fragmentation (default: no) */
#define UIP_CONF_IPV6_REASSEMBLY 0
#endif
#ifndef UIP_CONF_NETIF_MAX_ADDRESSES
/** Default number of IPv6 addresses associated to the node's interface */
#define UIP_CONF_NETIF_MAX_ADDRESSES 3
#endif
#ifndef UIP_CONF_ND6_MAX_PREFIXES
/** Default number of IPv6 prefixes associated to the node's interface */
#define UIP_CONF_ND6_MAX_PREFIXES 3
#endif
#ifndef UIP_CONF_ND6_MAX_NEIGHBORS
/** Default number of neighbors that can be stored in the %neighbor cache */
#define UIP_CONF_ND6_MAX_NEIGHBORS 4
#endif
#ifndef UIP_CONF_ND6_MAX_DEFROUTERS
/** Minimum number of default routers */
#define UIP_CONF_ND6_MAX_DEFROUTERS 2
#endif
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptudp UDP configuration options
* @{
*
* \note The UDP support in uIP is still not entirely complete; there
* is no support for sending or receiving broadcast or multicast
* packets, but it works well enough to support a number of vital
* applications such as DNS queries, though
*/
/**
* Toggles whether UDP support should be compiled in or not.
*
* \hideinitializer
*/
#ifdef UIP_CONF_UDP
#define UIP_UDP UIP_CONF_UDP
#else /* UIP_CONF_UDP */
#define UIP_UDP 1
#endif /* UIP_CONF_UDP */
/**
* Toggles if UDP checksums should be used or not.
*
* \note Support for UDP checksums is currently not included in uIP,
* so this option has no function.
*
* \hideinitializer
*/
#ifdef UIP_CONF_UDP_CHECKSUMS
#define UIP_UDP_CHECKSUMS UIP_CONF_UDP_CHECKSUMS
#else
#define UIP_UDP_CHECKSUMS 0
#endif
/**
* The maximum amount of concurrent UDP connections.
*
* \hideinitializer
*/
#ifdef UIP_CONF_UDP_CONNS
#define UIP_UDP_CONNS UIP_CONF_UDP_CONNS
#else /* UIP_CONF_UDP_CONNS */
#define UIP_UDP_CONNS 10
#endif /* UIP_CONF_UDP_CONNS */
/**
* The name of the function that should be called when UDP datagrams arrive.
*
* \hideinitializer
*/
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipopttcp TCP configuration options
* @{
*/
/**
* Toggles whether TCP support should be compiled in or not.
*
* \hideinitializer
*/
#ifdef UIP_CONF_TCP
#define UIP_TCP UIP_CONF_TCP
#else /* UIP_CONF_TCP */
#define UIP_TCP 1
#endif /* UIP_CONF_TCP */
/**
* Determines if support for opening connections from uIP should be
* compiled in.
*
* If the applications that are running on top of uIP for this project
* do not need to open outgoing TCP connections, this configuration
* option can be turned off to reduce the code size of uIP.
*
* \hideinitializer
*/
#ifndef UIP_CONF_ACTIVE_OPEN
#define UIP_ACTIVE_OPEN 1
#else /* UIP_CONF_ACTIVE_OPEN */
#define UIP_ACTIVE_OPEN UIP_CONF_ACTIVE_OPEN
#endif /* UIP_CONF_ACTIVE_OPEN */
/**
* The maximum number of simultaneously open TCP connections.
*
* Since the TCP connections are statically allocated, turning this
* configuration knob down results in less RAM used. Each TCP
* connection requires approximately 30 bytes of memory.
*
* \hideinitializer
*/
#ifndef UIP_CONF_MAX_CONNECTIONS
#define UIP_CONNS 10
#else /* UIP_CONF_MAX_CONNECTIONS */
#define UIP_CONNS UIP_CONF_MAX_CONNECTIONS
#endif /* UIP_CONF_MAX_CONNECTIONS */
/**
* The maximum number of simultaneously listening TCP ports.
*
* Each listening TCP port requires 2 bytes of memory.
*
* \hideinitializer
*/
#ifndef UIP_CONF_MAX_LISTENPORTS
#define UIP_LISTENPORTS 20
#else /* UIP_CONF_MAX_LISTENPORTS */
#define UIP_LISTENPORTS UIP_CONF_MAX_LISTENPORTS
#endif /* UIP_CONF_MAX_LISTENPORTS */
/**
* Determines if support for TCP urgent data notification should be
* compiled in.
*
* Urgent data (out-of-band data) is a rarely used TCP feature that
* very seldom would be required.
*
* \hideinitializer
*/
#if !defined(UIP_URGDATA)
#define UIP_URGDATA 0
#endif
/**
* The initial retransmission timeout counted in timer pulses.
*
* This should not be changed.
*/
#if !defined(UIP_RTO)
#define UIP_RTO 3
#endif
/**
* The maximum number of times a segment should be retransmitted
* before the connection should be aborted.
*
* This should not be changed.
*/
#if !defined(UIP_MAXRTX)
#define UIP_MAXRTX 8
#endif
/**
* The maximum number of times a SYN segment should be retransmitted
* before a connection request should be deemed to have been
* unsuccessful.
*
* This should not need to be changed.
*/
#if !defined(UIP_MAXSYNRTX)
#define UIP_MAXSYNRTX 5
#endif
/**
* The TCP maximum segment size.
*
* This is should not be to set to more than
* UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
*/
#ifdef UIP_CONF_TCP_MSS
#define UIP_TCP_MSS UIP_CONF_TCP_MSS
#else
#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
#endif
/**
* The size of the advertised receiver's window.
*
* Should be set low (i.e., to the size of the uip_buf buffer) if the
* application is slow to process incoming data, or high (32768 bytes)
* if the application processes data quickly.
*
* \hideinitializer
*/
#ifndef UIP_CONF_RECEIVE_WINDOW
#define UIP_RECEIVE_WINDOW UIP_TCP_MSS
#else
#define UIP_RECEIVE_WINDOW UIP_CONF_RECEIVE_WINDOW
#endif
/**
* How long a connection should stay in the TIME_WAIT state.
*
* This configuration option has no real implication, and it should be
* left untouched.
*/
#define UIP_TIME_WAIT_TIMEOUT 120
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptarp ARP configuration options
* @{
*/
/**
* The size of the ARP table.
*
* This option should be set to a larger value if this uIP node will
* have many connections from the local network.
*
* \hideinitializer
*/
#ifdef UIP_CONF_ARPTAB_SIZE
#define UIP_ARPTAB_SIZE UIP_CONF_ARPTAB_SIZE
#else
#define UIP_ARPTAB_SIZE 8
#endif
/**
* The maximum age of ARP table entries measured in 10ths of seconds.
*
* An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD
* default).
*/
#define UIP_ARP_MAXAGE 120
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptmac layer 2 options (for ipv6)
* @{
*/
#define UIP_DEFAULT_PREFIX_LEN 64
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptsics 6lowpan options (for ipv6)
* @{
*/
/**
* Timeout for packet reassembly at the 6lowpan layer
* (should be < 60s)
*/
#ifdef SICSLOWPAN_CONF_MAXAGE
#define SICSLOWPAN_REASS_MAXAGE SICSLOWPAN_CONF_MAXAGE
#else
#define SICSLOWPAN_REASS_MAXAGE 20
#endif
/**
* Do we compress the IP header or not (default: no)
*/
#ifndef SICSLOWPAN_CONF_COMPRESSION
#define SICSLOWPAN_CONF_COMPRESSION 0
#endif
/**
* If we use IPHC compression, how many address contexts do we support
*/
#ifndef SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS
#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1
#endif
/**
* Do we support 6lowpan fragmentation
*/
#ifndef SICSLOWPAN_CONF_FRAG
#define SICSLOWPAN_CONF_FRAG 0
#endif
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptgeneral General configuration options
* @{
*/
/**
* The size of the uIP packet buffer.
*
* The uIP packet buffer should not be smaller than 60 bytes, and does
* not need to be larger than 1514 bytes. Lower size results in lower
* TCP throughput, larger size results in higher TCP throughput.
*
* \hideinitializer
*/
#ifndef UIP_CONF_BUFFER_SIZE
#define UIP_BUFSIZE UIP_LINK_MTU + UIP_LLH_LEN
#else /* UIP_CONF_BUFFER_SIZE */
#define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE
#endif /* UIP_CONF_BUFFER_SIZE */
/**
* Determines if statistics support should be compiled in.
*
* The statistics is useful for debugging and to show the user.
*
* \hideinitializer
*/
#ifndef UIP_CONF_STATISTICS
#define UIP_STATISTICS 0
#else /* UIP_CONF_STATISTICS */
#define UIP_STATISTICS UIP_CONF_STATISTICS
#endif /* UIP_CONF_STATISTICS */
/**
* Determines if logging of certain events should be compiled in.
*
* This is useful mostly for debugging. The function uip_log()
* must be implemented to suit the architecture of the project, if
* logging is turned on.
*
* \hideinitializer
*/
#ifndef UIP_CONF_LOGGING
#define UIP_LOGGING 0
#else /* UIP_CONF_LOGGING */
#define UIP_LOGGING UIP_CONF_LOGGING
#endif /* UIP_CONF_LOGGING */
/**
* Broadcast support.
*
* This flag configures IP broadcast support. This is useful only
* together with UDP.
*
* \hideinitializer
*
*/
#ifndef UIP_CONF_BROADCAST
#define UIP_BROADCAST 0
#else /* UIP_CONF_BROADCAST */
#define UIP_BROADCAST UIP_CONF_BROADCAST
#endif /* UIP_CONF_BROADCAST */
/**
* Print out a uIP log message.
*
* This function must be implemented by the module that uses uIP, and
* is called by uIP whenever a log message is generated.
*/
void uip_log(char *msg);
/**
* The link level header length.
*
* This is the offset into the uip_buf where the IP header can be
* found. For Ethernet, this should be set to 14. For SLIP, this
* should be set to 0.
*
* \note we probably won't use this constant for other link layers than
* ethernet as they have variable header length (this is due to variable
* number and type of address fields and to optional security features)
* E.g.: 802.15.4 -> 2 + (1/2*4/8) + 0/5/6/10/14
* 802.11 -> 4 + (6*3/4) + 2
* \hideinitializer
*/
#ifdef UIP_CONF_LLH_LEN
#define UIP_LLH_LEN UIP_CONF_LLH_LEN
#else /* UIP_LLH_LEN */
#define UIP_LLH_LEN 14
#endif /* UIP_CONF_LLH_LEN */
/** @} */
/*------------------------------------------------------------------------------*/
/**
* \defgroup uipoptcpu CPU architecture configuration
* @{
*
* The CPU architecture configuration is where the endianess of the
* CPU on which uIP is to be run is specified. Most CPUs today are
* little endian, and the most notable exception are the Motorolas
* which are big endian. The BYTE_ORDER macro should be changed to
* reflect the CPU architecture on which uIP is to be run.
*/
/**
* The byte order of the CPU architecture on which uIP is to be run.
*
* This option can be either UIP_BIG_ENDIAN (Motorola byte order) or
* UIP_LITTLE_ENDIAN (Intel byte order).
*
* \hideinitializer
*/
#ifdef UIP_CONF_BYTE_ORDER
#define UIP_BYTE_ORDER UIP_CONF_BYTE_ORDER
#else /* UIP_CONF_BYTE_ORDER */
#define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN
#endif /* UIP_CONF_BYTE_ORDER */
/** @} */
/*------------------------------------------------------------------------------*/
#include <ff.h>
#include <stdbool.h>
#include <stdint.h>
#include "timer.h"
typedef uint8_t u8_t;
typedef uint16_t u16_t;
typedef uint32_t u32_t;
typedef uint32_t uip_stats_t;
/**
* \defgroup uipoptapp Application specific configurations
* @{
*
* An uIP application is implemented using a single application
* function that is called by uIP whenever a TCP/IP event occurs. The
* name of this function must be registered with uIP at compile time
* using the UIP_APPCALL definition.
*
* uIP applications can store the application state within the
* uip_conn structure by specifying the type of the application
* structure by typedef:ing the type uip_tcp_appstate_t and uip_udp_appstate_t.
*
* The file containing the definitions must be included in the
* uipopt.h file.
*
* The following example illustrates how this can look.
\code
void httpd_appcall(void);
#define UIP_APPCALL httpd_appcall
struct httpd_state {
u8_t state;
u16_t count;
char *dataptr;
char *script;
};
typedef struct httpd_state uip_tcp_appstate_t
\endcode
*/
#define UIP_UDP_APPCALL uIPManagement_UDPCallback
void UIP_UDP_APPCALL(void);
/**
* \var #define UIP_APPCALL
*
* The name of the application function that uIP should call in
* response to TCP/IP events.
*
*/
#define UIP_APPCALL uIPManagement_TCPCallback
void UIP_APPCALL(void);
/**
* \var typedef uip_tcp_appstate_t
*
* The type of the application state that is to be stored in the
* uip_conn structure. This usually is typedef:ed to a struct holding
* application state information.
*/
typedef union
{
struct
{
uint8_t CurrentState;
uint8_t NextState;
char FileName[MAX_URI_LENGTH];
FIL FileHandle;
bool FileOpen;
uint32_t ACKedFilePos;
uint16_t SentChunkSize;
} HTTPServer;
struct
{
uint8_t CurrentState;
uint8_t NextState;
uint8_t IssuedCommand;
} TELNETServer;
} uip_tcp_appstate_t;
/**
* \var typedef uip_udp_appstate_t
*
* The type of the application state that is to be stored in the
* uip_conn structure. This usually is typedef:ed to a struct holding
* application state information.
*/
typedef union
{
struct
{
uint8_t CurrentState;
struct timer Timeout;
struct
{
uint8_t AllocatedIP[4];
uint8_t Netmask[4];
uint8_t GatewayIP[4];
uint8_t ServerIP[4];
} DHCPOffer_Data;
} DHCPClient;
} uip_udp_appstate_t;
/** @} */
#endif /* __UIPOPT_H__ */
/** @} */
/** @} */