+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Functions to manage the physical dataflash media, including reading and writing of\r
- * blocks of data. These functions are called by the SCSI layer when data must be stored\r
- * or retrieved to/from the physical storage media. If a different media is used (such\r
- * as a SD card or EEPROM), functions similar to these will need to be generated.\r
- */\r
-\r
-#define INCLUDE_FROM_DATAFLASHMANAGER_C\r
-#include "DataflashManager.h"\r
-\r
-/** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board dataflash IC(s), from\r
- * the pre-selected data OUT endpoint. This routine reads in OS sized blocks from the endpoint and writes\r
- * them to the dataflash in Dataflash page sized blocks.\r
- *\r
- * \param BlockAddress Data block starting address for the write sequence\r
- * \param TotalBlocks Number of blocks of data to write\r
- */\r
-void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks)\r
-{\r
- uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
- uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
- uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
-\r
- /* Copy selected dataflash's current page contents to the dataflash buffer */\r
- Dataflash_SelectChipFromPage(CurrDFPage);\r
- Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
- Dataflash_SendAddressBytes(CurrDFPage, 0);\r
- Dataflash_WaitWhileBusy();\r
-\r
- /* Send the dataflash buffer write command */\r
- Dataflash_ToggleSelectedChipCS();\r
- Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
- Dataflash_SendAddressBytes(0, CurrDFPageByte);\r
-\r
- /* Wait until endpoint is ready before continuing */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
-\r
- while (TotalBlocks)\r
- {\r
- uint8_t BytesInBlockDiv16 = 0;\r
- \r
- /* Write an endpoint packet sized data block to the dataflash */\r
- while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))\r
- {\r
- /* Check if the endpoint is currently empty */\r
- if (!(Endpoint_IsReadWriteAllowed()))\r
- {\r
- /* Clear the current endpoint bank */\r
- Endpoint_ClearOUT();\r
- \r
- /* Wait until the host has sent another packet */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
- }\r
-\r
- /* Check if end of dataflash page reached */\r
- if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
- {\r
- /* Write the dataflash buffer contents back to the dataflash page */\r
- Dataflash_ToggleSelectedChipCS();\r
- Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
- Dataflash_SendAddressBytes(CurrDFPage, 0);\r
-\r
- /* Reset the dataflash buffer counter, increment the page counter */\r
- CurrDFPageByteDiv16 = 0;\r
- CurrDFPage++;\r
-\r
- /* Select the next dataflash chip based on the new dataflash page index */\r
- Dataflash_SelectChipFromPage(CurrDFPage);\r
- Dataflash_WaitWhileBusy();\r
-\r
-#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
- /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
- if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
- {\r
- /* Copy selected dataflash's current page contents to the dataflash buffer */\r
- Dataflash_ToggleSelectedChipCS();\r
- Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
- Dataflash_SendAddressBytes(CurrDFPage, 0);\r
- Dataflash_WaitWhileBusy();\r
- }\r
-#endif\r
-\r
- /* Send the dataflash buffer write command */\r
- Dataflash_ToggleSelectedChipCS();\r
- Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
- Dataflash_SendAddressBytes(0, 0);\r
- }\r
-\r
- /* Write one 16-byte chunk of data to the dataflash */\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- Dataflash_SendByte(Endpoint_Read_Byte());\r
- \r
- /* Increment the dataflash page 16 byte block counter */\r
- CurrDFPageByteDiv16++;\r
-\r
- /* Increment the block 16 byte block counter */\r
- BytesInBlockDiv16++;\r
-\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return; \r
- }\r
- \r
- /* Decrement the blocks remaining counter and reset the sub block counter */\r
- TotalBlocks--;\r
- }\r
-\r
- /* Write the dataflash buffer contents back to the dataflash page */\r
- Dataflash_ToggleSelectedChipCS();\r
- Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
- Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
- Dataflash_WaitWhileBusy();\r
-\r
- /* If the endpoint is empty, clear it ready for the next packet from the host */\r
- if (!(Endpoint_IsReadWriteAllowed()))\r
- Endpoint_ClearOUT();\r
-\r
- /* Deselect all dataflash chips */\r
- Dataflash_DeselectChip();\r
-}\r
-\r
-/** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board dataflash IC(s), into\r
- * the pre-selected data IN endpoint. This routine reads in Dataflash page sized blocks from the Dataflash\r
- * and writes them in OS sized blocks to the endpoint.\r
- *\r
- * \param BlockAddress Data block starting address for the read sequence\r
- * \param TotalBlocks Number of blocks of data to read\r
- */\r
-void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks)\r
-{\r
- uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
- uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
- uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
-\r
- /* Send the dataflash main memory page read command */\r
- Dataflash_SelectChipFromPage(CurrDFPage);\r
- Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);\r
- Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- \r
- /* Wait until endpoint is ready before continuing */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
- \r
- while (TotalBlocks)\r
- {\r
- uint8_t BytesInBlockDiv16 = 0;\r
- \r
- /* Write an endpoint packet sized data block to the dataflash */\r
- while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))\r
- {\r
- /* Check if the endpoint is currently full */\r
- if (!(Endpoint_IsReadWriteAllowed()))\r
- {\r
- /* Clear the endpoint bank to send its contents to the host */\r
- Endpoint_ClearIN();\r
- \r
- /* Wait until the endpoint is ready for more data */\r
- while (!(Endpoint_IsReadWriteAllowed()));\r
- }\r
- \r
- /* Check if end of dataflash page reached */\r
- if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
- {\r
- /* Reset the dataflash buffer counter, increment the page counter */\r
- CurrDFPageByteDiv16 = 0;\r
- CurrDFPage++;\r
-\r
- /* Select the next dataflash chip based on the new dataflash page index */\r
- Dataflash_SelectChipFromPage(CurrDFPage);\r
- \r
- /* Send the dataflash main memory page read command */\r
- Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);\r
- Dataflash_SendAddressBytes(CurrDFPage, 0);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- } \r
-\r
- /* Read one 16-byte chunk of data from the dataflash */\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
- \r
- /* Increment the dataflash page 16 byte block counter */\r
- CurrDFPageByteDiv16++;\r
- \r
- /* Increment the block 16 byte block counter */\r
- BytesInBlockDiv16++;\r
-\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return;\r
- }\r
- \r
- /* Decrement the blocks remaining counter */\r
- TotalBlocks--;\r
- }\r
- \r
- /* If the endpoint is full, send its contents to the host */\r
- if (!(Endpoint_IsReadWriteAllowed()))\r
- Endpoint_ClearIN();\r
-\r
- /* Deselect all dataflash chips */\r
- Dataflash_DeselectChip();\r
-}\r
-\r
-/** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board dataflash IC(s), from\r
- * the a given RAM buffer. This routine reads in OS sized blocks from the buffer and writes them to the\r
- * dataflash in Dataflash page sized blocks. This can be linked to FAT libraries to write files to the\r
- * dataflash.\r
- *\r
- * \param BlockAddress Data block starting address for the write sequence\r
- * \param TotalBlocks Number of blocks of data to write\r
- * \param BufferPtr Pointer to the data source RAM buffer\r
- */\r
-void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks, uint8_t* BufferPtr)\r
-{\r
- uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
- uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
- uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
-\r
- /* Copy selected dataflash's current page contents to the dataflash buffer */\r
- Dataflash_SelectChipFromPage(CurrDFPage);\r
- Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
- Dataflash_SendAddressBytes(CurrDFPage, 0);\r
- Dataflash_WaitWhileBusy();\r
-\r
- /* Send the dataflash buffer write command */\r
- Dataflash_ToggleSelectedChipCS();\r
- Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
- Dataflash_SendAddressBytes(0, CurrDFPageByte);\r
-\r
- while (TotalBlocks)\r
- {\r
- uint8_t BytesInBlockDiv16 = 0;\r
- \r
- /* Write an endpoint packet sized data block to the dataflash */\r
- while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))\r
- {\r
- /* Check if end of dataflash page reached */\r
- if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
- {\r
- /* Write the dataflash buffer contents back to the dataflash page */\r
- Dataflash_ToggleSelectedChipCS();\r
- Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
- Dataflash_SendAddressBytes(CurrDFPage, 0);\r
-\r
- /* Reset the dataflash buffer counter, increment the page counter */\r
- CurrDFPageByteDiv16 = 0;\r
- CurrDFPage++;\r
-\r
- /* Select the next dataflash chip based on the new dataflash page index */\r
- Dataflash_SelectChipFromPage(CurrDFPage);\r
- Dataflash_WaitWhileBusy();\r
-\r
-#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
- /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
- if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
- {\r
- /* Copy selected dataflash's current page contents to the dataflash buffer */\r
- Dataflash_ToggleSelectedChipCS();\r
- Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
- Dataflash_SendAddressBytes(CurrDFPage, 0);\r
- Dataflash_WaitWhileBusy();\r
- }\r
-#endif\r
-\r
- /* Send the dataflash buffer write command */\r
- Dataflash_ToggleSelectedChipCS();\r
- Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
- Dataflash_SendAddressBytes(0, 0);\r
- }\r
- \r
- /* Write one 16-byte chunk of data to the dataflash */\r
- for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++)\r
- Dataflash_SendByte(*(BufferPtr++));\r
- \r
- /* Increment the dataflash page 16 byte block counter */\r
- CurrDFPageByteDiv16++;\r
-\r
- /* Increment the block 16 byte block counter */\r
- BytesInBlockDiv16++;\r
-\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return; \r
- }\r
- \r
- /* Decrement the blocks remaining counter and reset the sub block counter */\r
- TotalBlocks--;\r
- }\r
-\r
- /* Write the dataflash buffer contents back to the dataflash page */\r
- Dataflash_ToggleSelectedChipCS();\r
- Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
- Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
- Dataflash_WaitWhileBusy();\r
-\r
- /* Deselect all dataflash chips */\r
- Dataflash_DeselectChip();\r
-}\r
-\r
-/** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board dataflash IC(s), into\r
- * the a preallocated RAM buffer. This routine reads in Dataflash page sized blocks from the Dataflash\r
- * and writes them in OS sized blocks to the given buffer. This can be linked to FAT libraries to read\r
- * the files stored on the dataflash.\r
- *\r
- * \param BlockAddress Data block starting address for the read sequence\r
- * \param TotalBlocks Number of blocks of data to read\r
- * \param BufferPtr Pointer to the data destination RAM buffer\r
- */\r
-void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks, uint8_t* BufferPtr)\r
-{\r
- uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
- uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
- uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
-\r
- /* Send the dataflash main memory page read command */\r
- Dataflash_SelectChipFromPage(CurrDFPage);\r
- Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);\r
- Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
-\r
- while (TotalBlocks)\r
- {\r
- uint8_t BytesInBlockDiv16 = 0;\r
- \r
- /* Write an endpoint packet sized data block to the dataflash */\r
- while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))\r
- {\r
- /* Check if end of dataflash page reached */\r
- if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
- {\r
- /* Reset the dataflash buffer counter, increment the page counter */\r
- CurrDFPageByteDiv16 = 0;\r
- CurrDFPage++;\r
-\r
- /* Select the next dataflash chip based on the new dataflash page index */\r
- Dataflash_SelectChipFromPage(CurrDFPage);\r
- \r
- /* Send the dataflash main memory page read command */\r
- Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);\r
- Dataflash_SendAddressBytes(CurrDFPage, 0);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- Dataflash_SendByte(0x00);\r
- } \r
-\r
- /* Read one 16-byte chunk of data from the dataflash */\r
- for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++)\r
- *(BufferPtr++) = Dataflash_ReceiveByte();\r
- \r
- /* Increment the dataflash page 16 byte block counter */\r
- CurrDFPageByteDiv16++;\r
- \r
- /* Increment the block 16 byte block counter */\r
- BytesInBlockDiv16++;\r
-\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return;\r
- }\r
- \r
- /* Decrement the blocks remaining counter */\r
- TotalBlocks--;\r
- }\r
-\r
- /* Deselect all dataflash chips */\r
- Dataflash_DeselectChip();\r
-}\r
-\r
-/** Disables the dataflash memory write protection bits on the board Dataflash ICs, if enabled. */\r
-void DataflashManager_ResetDataflashProtections(void)\r
-{\r
- /* Select first dataflash chip, send the read status register command */\r
- Dataflash_SelectChip(DATAFLASH_CHIP1);\r
- Dataflash_SendByte(DF_CMD_GETSTATUS);\r
- \r
- /* Check if sector protection is enabled */\r
- if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON)\r
- {\r
- Dataflash_ToggleSelectedChipCS();\r
-\r
- /* Send the commands to disable sector protection */\r
- Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);\r
- Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);\r
- Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);\r
- Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);\r
- }\r
- \r
- /* Select second dataflash chip (if present on selected board), send read status register command */\r
- #if (DATAFLASH_TOTALCHIPS == 2)\r
- Dataflash_SelectChip(DATAFLASH_CHIP2);\r
- Dataflash_SendByte(DF_CMD_GETSTATUS);\r
- \r
- /* Check if sector protection is enabled */\r
- if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON)\r
- {\r
- Dataflash_ToggleSelectedChipCS();\r
-\r
- /* Send the commands to disable sector protection */\r
- Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);\r
- Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);\r
- Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);\r
- Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);\r
- }\r
- #endif\r
- \r
- /* Deselect current dataflash chip */\r
- Dataflash_DeselectChip();\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for DataflashManager.c.\r
- */\r
- \r
-#ifndef _DATAFLASH_MANAGER_H\r
-#define _DATAFLASH_MANAGER_H\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- \r
- #include "MassStorage.h"\r
- #include "Descriptors.h"\r
-\r
- #include <LUFA/Common/Common.h> // Function Attribute, Atomic, Debug and ISR Macros\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/Dataflash.h> // Dataflash chip driver\r
-\r
- /* Preprocessor Checks: */\r
- #if (DATAFLASH_PAGE_SIZE % 16)\r
- #error Dataflash page size must be a multiple of 16 bytes.\r
- #endif\r
-\r
- /* Defines: */\r
- /** Total number of bytes of the storage medium, comprised of one or more dataflash ICs. */\r
- #define VIRTUAL_MEMORY_BYTES ((uint32_t)DATAFLASH_PAGES * DATAFLASH_PAGE_SIZE * DATAFLASH_TOTALCHIPS)\r
-\r
- /** Block size of the device. This is kept at 512 to remain compatible with the OS despite the underlying\r
- * storage media (Dataflash) using a different native block size.\r
- */\r
- #define VIRTUAL_MEMORY_BLOCK_SIZE 512\r
- \r
- /** Total number of blocks of the virtual memory for reporting to the host as the device's total capacity. */\r
- #define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)\r
- \r
- /* Function Prototypes: */\r
- void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);\r
- void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);\r
- void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,\r
- uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);\r
- void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,\r
- uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);\r
- void DataflashManager_ResetDataflashProtections(void);\r
- \r
-#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Functions to manage the physical dataflash media, including reading and writing of\r
+ * blocks of data. These functions are called by the SCSI layer when data must be stored\r
+ * or retrieved to/from the physical storage media. If a different media is used (such\r
+ * as a SD card or EEPROM), functions similar to these will need to be generated.\r
+ */\r
+\r
+#define INCLUDE_FROM_DATAFLASHMANAGER_C\r
+#include "DataflashManager.h"\r
+\r
+/** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board dataflash IC(s), from\r
+ * the pre-selected data OUT endpoint. This routine reads in OS sized blocks from the endpoint and writes\r
+ * them to the dataflash in Dataflash page sized blocks.\r
+ *\r
+ * \param BlockAddress Data block starting address for the write sequence\r
+ * \param TotalBlocks Number of blocks of data to write\r
+ */\r
+void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks)\r
+{\r
+ uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
+ uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
+ uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
+\r
+ /* Copy selected dataflash's current page contents to the dataflash buffer */\r
+ Dataflash_SelectChipFromPage(CurrDFPage);\r
+ Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
+ Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+ Dataflash_WaitWhileBusy();\r
+\r
+ /* Send the dataflash buffer write command */\r
+ Dataflash_ToggleSelectedChipCS();\r
+ Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
+ Dataflash_SendAddressBytes(0, CurrDFPageByte);\r
+\r
+ /* Wait until endpoint is ready before continuing */\r
+ while (!(Endpoint_IsReadWriteAllowed()));\r
+\r
+ while (TotalBlocks)\r
+ {\r
+ uint8_t BytesInBlockDiv16 = 0;\r
+ \r
+ /* Write an endpoint packet sized data block to the dataflash */\r
+ while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))\r
+ {\r
+ /* Check if the endpoint is currently empty */\r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ /* Clear the current endpoint bank */\r
+ Endpoint_ClearOUT();\r
+ \r
+ /* Wait until the host has sent another packet */\r
+ while (!(Endpoint_IsReadWriteAllowed()));\r
+ }\r
+\r
+ /* Check if end of dataflash page reached */\r
+ if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
+ {\r
+ /* Write the dataflash buffer contents back to the dataflash page */\r
+ Dataflash_ToggleSelectedChipCS();\r
+ Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+ Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+\r
+ /* Reset the dataflash buffer counter, increment the page counter */\r
+ CurrDFPageByteDiv16 = 0;\r
+ CurrDFPage++;\r
+\r
+ /* Select the next dataflash chip based on the new dataflash page index */\r
+ Dataflash_SelectChipFromPage(CurrDFPage);\r
+ Dataflash_WaitWhileBusy();\r
+\r
+#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
+ /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
+ if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
+ {\r
+ /* Copy selected dataflash's current page contents to the dataflash buffer */\r
+ Dataflash_ToggleSelectedChipCS();\r
+ Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
+ Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+ Dataflash_WaitWhileBusy();\r
+ }\r
+#endif\r
+\r
+ /* Send the dataflash buffer write command */\r
+ Dataflash_ToggleSelectedChipCS();\r
+ Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
+ Dataflash_SendAddressBytes(0, 0);\r
+ }\r
+\r
+ /* Write one 16-byte chunk of data to the dataflash */\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ Dataflash_SendByte(Endpoint_Read_Byte());\r
+ \r
+ /* Increment the dataflash page 16 byte block counter */\r
+ CurrDFPageByteDiv16++;\r
+\r
+ /* Increment the block 16 byte block counter */\r
+ BytesInBlockDiv16++;\r
+\r
+ /* Check if the current command is being aborted by the host */\r
+ if (IsMassStoreReset)\r
+ return; \r
+ }\r
+ \r
+ /* Decrement the blocks remaining counter and reset the sub block counter */\r
+ TotalBlocks--;\r
+ }\r
+\r
+ /* Write the dataflash buffer contents back to the dataflash page */\r
+ Dataflash_ToggleSelectedChipCS();\r
+ Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+ Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
+ Dataflash_WaitWhileBusy();\r
+\r
+ /* If the endpoint is empty, clear it ready for the next packet from the host */\r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ Endpoint_ClearOUT();\r
+\r
+ /* Deselect all dataflash chips */\r
+ Dataflash_DeselectChip();\r
+}\r
+\r
+/** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board dataflash IC(s), into\r
+ * the pre-selected data IN endpoint. This routine reads in Dataflash page sized blocks from the Dataflash\r
+ * and writes them in OS sized blocks to the endpoint.\r
+ *\r
+ * \param BlockAddress Data block starting address for the read sequence\r
+ * \param TotalBlocks Number of blocks of data to read\r
+ */\r
+void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks)\r
+{\r
+ uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
+ uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
+ uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
+\r
+ /* Send the dataflash main memory page read command */\r
+ Dataflash_SelectChipFromPage(CurrDFPage);\r
+ Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);\r
+ Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ \r
+ /* Wait until endpoint is ready before continuing */\r
+ while (!(Endpoint_IsReadWriteAllowed()));\r
+ \r
+ while (TotalBlocks)\r
+ {\r
+ uint8_t BytesInBlockDiv16 = 0;\r
+ \r
+ /* Write an endpoint packet sized data block to the dataflash */\r
+ while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))\r
+ {\r
+ /* Check if the endpoint is currently full */\r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ {\r
+ /* Clear the endpoint bank to send its contents to the host */\r
+ Endpoint_ClearIN();\r
+ \r
+ /* Wait until the endpoint is ready for more data */\r
+ while (!(Endpoint_IsReadWriteAllowed()));\r
+ }\r
+ \r
+ /* Check if end of dataflash page reached */\r
+ if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
+ {\r
+ /* Reset the dataflash buffer counter, increment the page counter */\r
+ CurrDFPageByteDiv16 = 0;\r
+ CurrDFPage++;\r
+\r
+ /* Select the next dataflash chip based on the new dataflash page index */\r
+ Dataflash_SelectChipFromPage(CurrDFPage);\r
+ \r
+ /* Send the dataflash main memory page read command */\r
+ Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);\r
+ Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ } \r
+\r
+ /* Read one 16-byte chunk of data from the dataflash */\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ Endpoint_Write_Byte(Dataflash_ReceiveByte());\r
+ \r
+ /* Increment the dataflash page 16 byte block counter */\r
+ CurrDFPageByteDiv16++;\r
+ \r
+ /* Increment the block 16 byte block counter */\r
+ BytesInBlockDiv16++;\r
+\r
+ /* Check if the current command is being aborted by the host */\r
+ if (IsMassStoreReset)\r
+ return;\r
+ }\r
+ \r
+ /* Decrement the blocks remaining counter */\r
+ TotalBlocks--;\r
+ }\r
+ \r
+ /* If the endpoint is full, send its contents to the host */\r
+ if (!(Endpoint_IsReadWriteAllowed()))\r
+ Endpoint_ClearIN();\r
+\r
+ /* Deselect all dataflash chips */\r
+ Dataflash_DeselectChip();\r
+}\r
+\r
+/** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board dataflash IC(s), from\r
+ * the a given RAM buffer. This routine reads in OS sized blocks from the buffer and writes them to the\r
+ * dataflash in Dataflash page sized blocks. This can be linked to FAT libraries to write files to the\r
+ * dataflash.\r
+ *\r
+ * \param BlockAddress Data block starting address for the write sequence\r
+ * \param TotalBlocks Number of blocks of data to write\r
+ * \param BufferPtr Pointer to the data source RAM buffer\r
+ */\r
+void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks, uint8_t* BufferPtr)\r
+{\r
+ uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
+ uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
+ uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
+\r
+ /* Copy selected dataflash's current page contents to the dataflash buffer */\r
+ Dataflash_SelectChipFromPage(CurrDFPage);\r
+ Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
+ Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+ Dataflash_WaitWhileBusy();\r
+\r
+ /* Send the dataflash buffer write command */\r
+ Dataflash_ToggleSelectedChipCS();\r
+ Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
+ Dataflash_SendAddressBytes(0, CurrDFPageByte);\r
+\r
+ while (TotalBlocks)\r
+ {\r
+ uint8_t BytesInBlockDiv16 = 0;\r
+ \r
+ /* Write an endpoint packet sized data block to the dataflash */\r
+ while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))\r
+ {\r
+ /* Check if end of dataflash page reached */\r
+ if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
+ {\r
+ /* Write the dataflash buffer contents back to the dataflash page */\r
+ Dataflash_ToggleSelectedChipCS();\r
+ Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+ Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+\r
+ /* Reset the dataflash buffer counter, increment the page counter */\r
+ CurrDFPageByteDiv16 = 0;\r
+ CurrDFPage++;\r
+\r
+ /* Select the next dataflash chip based on the new dataflash page index */\r
+ Dataflash_SelectChipFromPage(CurrDFPage);\r
+ Dataflash_WaitWhileBusy();\r
+\r
+#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)\r
+ /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */\r
+ if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))\r
+ {\r
+ /* Copy selected dataflash's current page contents to the dataflash buffer */\r
+ Dataflash_ToggleSelectedChipCS();\r
+ Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);\r
+ Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+ Dataflash_WaitWhileBusy();\r
+ }\r
+#endif\r
+\r
+ /* Send the dataflash buffer write command */\r
+ Dataflash_ToggleSelectedChipCS();\r
+ Dataflash_SendByte(DF_CMD_BUFF1WRITE);\r
+ Dataflash_SendAddressBytes(0, 0);\r
+ }\r
+ \r
+ /* Write one 16-byte chunk of data to the dataflash */\r
+ for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++)\r
+ Dataflash_SendByte(*(BufferPtr++));\r
+ \r
+ /* Increment the dataflash page 16 byte block counter */\r
+ CurrDFPageByteDiv16++;\r
+\r
+ /* Increment the block 16 byte block counter */\r
+ BytesInBlockDiv16++;\r
+\r
+ /* Check if the current command is being aborted by the host */\r
+ if (IsMassStoreReset)\r
+ return; \r
+ }\r
+ \r
+ /* Decrement the blocks remaining counter and reset the sub block counter */\r
+ TotalBlocks--;\r
+ }\r
+\r
+ /* Write the dataflash buffer contents back to the dataflash page */\r
+ Dataflash_ToggleSelectedChipCS();\r
+ Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);\r
+ Dataflash_SendAddressBytes(CurrDFPage, 0x00);\r
+ Dataflash_WaitWhileBusy();\r
+\r
+ /* Deselect all dataflash chips */\r
+ Dataflash_DeselectChip();\r
+}\r
+\r
+/** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board dataflash IC(s), into\r
+ * the a preallocated RAM buffer. This routine reads in Dataflash page sized blocks from the Dataflash\r
+ * and writes them in OS sized blocks to the given buffer. This can be linked to FAT libraries to read\r
+ * the files stored on the dataflash.\r
+ *\r
+ * \param BlockAddress Data block starting address for the read sequence\r
+ * \param TotalBlocks Number of blocks of data to read\r
+ * \param BufferPtr Pointer to the data destination RAM buffer\r
+ */\r
+void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks, uint8_t* BufferPtr)\r
+{\r
+ uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);\r
+ uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);\r
+ uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);\r
+\r
+ /* Send the dataflash main memory page read command */\r
+ Dataflash_SelectChipFromPage(CurrDFPage);\r
+ Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);\r
+ Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+\r
+ while (TotalBlocks)\r
+ {\r
+ uint8_t BytesInBlockDiv16 = 0;\r
+ \r
+ /* Write an endpoint packet sized data block to the dataflash */\r
+ while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))\r
+ {\r
+ /* Check if end of dataflash page reached */\r
+ if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))\r
+ {\r
+ /* Reset the dataflash buffer counter, increment the page counter */\r
+ CurrDFPageByteDiv16 = 0;\r
+ CurrDFPage++;\r
+\r
+ /* Select the next dataflash chip based on the new dataflash page index */\r
+ Dataflash_SelectChipFromPage(CurrDFPage);\r
+ \r
+ /* Send the dataflash main memory page read command */\r
+ Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);\r
+ Dataflash_SendAddressBytes(CurrDFPage, 0);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ Dataflash_SendByte(0x00);\r
+ } \r
+\r
+ /* Read one 16-byte chunk of data from the dataflash */\r
+ for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++)\r
+ *(BufferPtr++) = Dataflash_ReceiveByte();\r
+ \r
+ /* Increment the dataflash page 16 byte block counter */\r
+ CurrDFPageByteDiv16++;\r
+ \r
+ /* Increment the block 16 byte block counter */\r
+ BytesInBlockDiv16++;\r
+\r
+ /* Check if the current command is being aborted by the host */\r
+ if (IsMassStoreReset)\r
+ return;\r
+ }\r
+ \r
+ /* Decrement the blocks remaining counter */\r
+ TotalBlocks--;\r
+ }\r
+\r
+ /* Deselect all dataflash chips */\r
+ Dataflash_DeselectChip();\r
+}\r
+\r
+/** Disables the dataflash memory write protection bits on the board Dataflash ICs, if enabled. */\r
+void DataflashManager_ResetDataflashProtections(void)\r
+{\r
+ /* Select first dataflash chip, send the read status register command */\r
+ Dataflash_SelectChip(DATAFLASH_CHIP1);\r
+ Dataflash_SendByte(DF_CMD_GETSTATUS);\r
+ \r
+ /* Check if sector protection is enabled */\r
+ if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON)\r
+ {\r
+ Dataflash_ToggleSelectedChipCS();\r
+\r
+ /* Send the commands to disable sector protection */\r
+ Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);\r
+ Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);\r
+ Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);\r
+ Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);\r
+ }\r
+ \r
+ /* Select second dataflash chip (if present on selected board), send read status register command */\r
+ #if (DATAFLASH_TOTALCHIPS == 2)\r
+ Dataflash_SelectChip(DATAFLASH_CHIP2);\r
+ Dataflash_SendByte(DF_CMD_GETSTATUS);\r
+ \r
+ /* Check if sector protection is enabled */\r
+ if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON)\r
+ {\r
+ Dataflash_ToggleSelectedChipCS();\r
+\r
+ /* Send the commands to disable sector protection */\r
+ Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);\r
+ Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);\r
+ Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);\r
+ Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);\r
+ }\r
+ #endif\r
+ \r
+ /* Deselect current dataflash chip */\r
+ Dataflash_DeselectChip();\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for DataflashManager.c.\r
+ */\r
+ \r
+#ifndef _DATAFLASH_MANAGER_H\r
+#define _DATAFLASH_MANAGER_H\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ \r
+ #include "MassStorage.h"\r
+ #include "Descriptors.h"\r
+\r
+ #include <LUFA/Common/Common.h> // Function Attribute, Atomic, Debug and ISR Macros\r
+ #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
+ #include <LUFA/Drivers/Board/Dataflash.h> // Dataflash chip driver\r
+\r
+ /* Preprocessor Checks: */\r
+ #if (DATAFLASH_PAGE_SIZE % 16)\r
+ #error Dataflash page size must be a multiple of 16 bytes.\r
+ #endif\r
+\r
+ /* Defines: */\r
+ /** Total number of bytes of the storage medium, comprised of one or more dataflash ICs. */\r
+ #define VIRTUAL_MEMORY_BYTES ((uint32_t)DATAFLASH_PAGES * DATAFLASH_PAGE_SIZE * DATAFLASH_TOTALCHIPS)\r
+\r
+ /** Block size of the device. This is kept at 512 to remain compatible with the OS despite the underlying\r
+ * storage media (Dataflash) using a different native block size.\r
+ */\r
+ #define VIRTUAL_MEMORY_BLOCK_SIZE 512\r
+ \r
+ /** Total number of blocks of the virtual memory for reporting to the host as the device's total capacity. */\r
+ #define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)\r
+ \r
+ /* Function Prototypes: */\r
+ void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);\r
+ void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);\r
+ void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,\r
+ uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);\r
+ void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,\r
+ uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);\r
+ void DataflashManager_ResetDataflashProtections(void);\r
+ \r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * SCSI command processing routines, for SCSI commands issued by the host. Mass Storage\r
+ * devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,\r
+ * which wrap around standard SCSI device commands for controlling the actual storage medium.\r
+ */\r
+ \r
+#define INCLUDE_FROM_SCSI_C\r
+#include "SCSI.h"\r
+\r
+/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's\r
+ * features and capabilities.\r
+ */\r
+SCSI_Inquiry_Response_t InquiryData = \r
+ {\r
+ .DeviceType = DEVICE_TYPE_BLOCK,\r
+ .PeripheralQualifier = 0,\r
+ \r
+ .Removable = true,\r
+ \r
+ .Version = 0,\r
+ \r
+ .ResponseDataFormat = 2,\r
+ .NormACA = false,\r
+ .TrmTsk = false,\r
+ .AERC = false,\r
+\r
+ .AdditionalLength = 0x1F,\r
+ \r
+ .SoftReset = false,\r
+ .CmdQue = false,\r
+ .Linked = false,\r
+ .Sync = false,\r
+ .WideBus16Bit = false,\r
+ .WideBus32Bit = false,\r
+ .RelAddr = false,\r
+ \r
+ .VendorID = "LUFA",\r
+ .ProductID = "Dataflash Disk",\r
+ .RevisionID = {'0','.','0','0'},\r
+ };\r
+\r
+/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE\r
+ * command is issued. This gives information on exactly why the last command failed to complete.\r
+ */\r
+SCSI_Request_Sense_Response_t SenseData =\r
+ {\r
+ .ResponseCode = 0x70,\r
+ .AdditionalLength = 0x0A,\r
+ };\r
+\r
+\r
+/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches\r
+ * to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns\r
+ * a command failure due to a ILLEGAL REQUEST.\r
+ */\r
+void SCSI_DecodeSCSICommand(void)\r
+{\r
+ bool CommandSuccess = false;\r
+\r
+ /* Run the appropriate SCSI command hander function based on the passed command */\r
+ switch (CommandBlock.SCSICommandData[0])\r
+ {\r
+ case SCSI_CMD_INQUIRY:\r
+ CommandSuccess = SCSI_Command_Inquiry(); \r
+ break;\r
+ case SCSI_CMD_REQUEST_SENSE:\r
+ CommandSuccess = SCSI_Command_Request_Sense();\r
+ break;\r
+ case SCSI_CMD_READ_CAPACITY_10:\r
+ CommandSuccess = SCSI_Command_Read_Capacity_10(); \r
+ break;\r
+ case SCSI_CMD_SEND_DIAGNOSTIC:\r
+ CommandSuccess = SCSI_Command_Send_Diagnostic();\r
+ break;\r
+ case SCSI_CMD_WRITE_10:\r
+ CommandSuccess = SCSI_Command_ReadWrite_10(DATA_WRITE);\r
+ break;\r
+ case SCSI_CMD_READ_10:\r
+ CommandSuccess = SCSI_Command_ReadWrite_10(DATA_READ);\r
+ break;\r
+ case SCSI_CMD_TEST_UNIT_READY:\r
+ case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:\r
+ case SCSI_CMD_VERIFY_10:\r
+ /* These commands should just succeed, no handling required */\r
+ CommandSuccess = true;\r
+ CommandBlock.DataTransferLength = 0;\r
+ break;\r
+ default:\r
+ /* Update the SENSE key to reflect the invalid command */\r
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,\r
+ SCSI_ASENSE_INVALID_COMMAND,\r
+ SCSI_ASENSEQ_NO_QUALIFIER);\r
+ break;\r
+ }\r
+ \r
+ /* Check if command was successfully processed */\r
+ if (CommandSuccess)\r
+ {\r
+ /* Command succeeded - set the CSW status and update the SENSE key */\r
+ CommandStatus.Status = Command_Pass;\r
+ \r
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,\r
+ SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,\r
+ SCSI_ASENSEQ_NO_QUALIFIER); \r
+ }\r
+ else\r
+ {\r
+ /* Command failed - set the CSW status - failed command function updates the SENSE key */\r
+ CommandStatus.Status = Command_Fail;\r
+ }\r
+}\r
+\r
+/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features\r
+ * and capabilities to the host.\r
+ *\r
+ * \return Boolean true if the command completed successfully, false otherwise.\r
+ */\r
+static bool SCSI_Command_Inquiry(void)\r
+{\r
+ uint16_t AllocationLength = (((uint16_t)CommandBlock.SCSICommandData[3] << 8) |\r
+ CommandBlock.SCSICommandData[4]);\r
+ uint16_t BytesTransferred = (AllocationLength < sizeof(InquiryData))? AllocationLength :\r
+ sizeof(InquiryData);\r
+\r
+ /* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */\r
+ if ((CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||\r
+ CommandBlock.SCSICommandData[2])\r
+ {\r
+ /* Optional but unsupported bits set - update the SENSE key and fail the request */\r
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,\r
+ SCSI_ASENSE_INVALID_FIELD_IN_CDB,\r
+ SCSI_ASENSEQ_NO_QUALIFIER);\r
+\r
+ return false;\r
+ }\r
+\r
+ /* Write the INQUIRY data to the endpoint */\r
+ Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);\r
+\r
+ uint8_t PadBytes[AllocationLength - BytesTransferred];\r
+ \r
+ /* Pad out remaining bytes with 0x00 */\r
+ Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);\r
+\r
+ /* Finalize the stream transfer to send the last packet */\r
+ Endpoint_ClearIN();\r
+\r
+ /* Succeed the command and update the bytes transferred counter */\r
+ CommandBlock.DataTransferLength -= BytesTransferred;\r
+ \r
+ return true;\r
+}\r
+\r
+/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,\r
+ * including the error code and additional error information so that the host can determine why a command failed to complete.\r
+ *\r
+ * \return Boolean true if the command completed successfully, false otherwise.\r
+ */\r
+static bool SCSI_Command_Request_Sense(void)\r
+{\r
+ uint8_t AllocationLength = CommandBlock.SCSICommandData[4];\r
+ uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);\r
+ \r
+ /* Send the SENSE data - this indicates to the host the status of the last command */\r
+ Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);\r
+ \r
+ uint8_t PadBytes[AllocationLength - BytesTransferred];\r
+ \r
+ /* Pad out remaining bytes with 0x00 */\r
+ Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);\r
+\r
+ /* Finalize the stream transfer to send the last packet */\r
+ Endpoint_ClearIN();\r
+\r
+ /* Succeed the command and update the bytes transferred counter */\r
+ CommandBlock.DataTransferLength -= BytesTransferred;\r
+\r
+ return true;\r
+}\r
+\r
+/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity\r
+ * on the selected Logical Unit (drive), as a number of OS-sized blocks.\r
+ *\r
+ * \return Boolean true if the command completed successfully, false otherwise.\r
+ */\r
+static bool SCSI_Command_Read_Capacity_10(void)\r
+{\r
+ /* Send the total number of logical blocks in the current LUN */\r
+ Endpoint_Write_DWord_BE(LUN_MEDIA_BLOCKS - 1);\r
+\r
+ /* Send the logical block size of the device (must be 512 bytes) */\r
+ Endpoint_Write_DWord_BE(VIRTUAL_MEMORY_BLOCK_SIZE);\r
+\r
+ /* Check if the current command is being aborted by the host */\r
+ if (IsMassStoreReset)\r
+ return false;\r
+\r
+ /* Send the endpoint data packet to the host */\r
+ Endpoint_ClearIN();\r
+\r
+ /* Succeed the command and update the bytes transferred counter */\r
+ CommandBlock.DataTransferLength -= 8;\r
+ \r
+ return true;\r
+}\r
+\r
+/** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the\r
+ * board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is\r
+ * supported.\r
+ *\r
+ * \return Boolean true if the command completed successfully, false otherwise.\r
+ */\r
+static bool SCSI_Command_Send_Diagnostic(void)\r
+{\r
+ uint8_t ReturnByte;\r
+\r
+ /* Check to see if the SELF TEST bit is not set */\r
+ if (!(CommandBlock.SCSICommandData[1] & (1 << 2)))\r
+ {\r
+ /* Only self-test supported - update SENSE key and fail the command */\r
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,\r
+ SCSI_ASENSE_INVALID_FIELD_IN_CDB,\r
+ SCSI_ASENSEQ_NO_QUALIFIER);\r
+\r
+ return false;\r
+ }\r
+ \r
+ /* Test first Dataflash IC is present and responding to commands */\r
+ Dataflash_SelectChip(DATAFLASH_CHIP1);\r
+ Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);\r
+ ReturnByte = Dataflash_ReceiveByte();\r
+ Dataflash_DeselectChip();\r
+\r
+ /* If returned data is invalid, fail the command */\r
+ if (ReturnByte != DF_MANUFACTURER_ATMEL)\r
+ {\r
+ /* Update SENSE key with a hardware error condition and return command fail */\r
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,\r
+ SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,\r
+ SCSI_ASENSEQ_NO_QUALIFIER); \r
+ \r
+ return false;\r
+ }\r
+\r
+ #if (DATAFLASH_TOTALCHIPS == 2)\r
+ /* Test second Dataflash IC is present and responding to commands */\r
+ Dataflash_SelectChip(DATAFLASH_CHIP2);\r
+ Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);\r
+ ReturnByte = Dataflash_ReceiveByte();\r
+ Dataflash_DeselectChip();\r
+\r
+ /* If returned data is invalid, fail the command */\r
+ if (ReturnByte != DF_MANUFACTURER_ATMEL)\r
+ {\r
+ /* Update SENSE key with a hardware error condition and return command fail */\r
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,\r
+ SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,\r
+ SCSI_ASENSEQ_NO_QUALIFIER); \r
+ \r
+ return false;\r
+ }\r
+ #endif\r
+ \r
+ /* Succeed the command and update the bytes transferred counter */\r
+ CommandBlock.DataTransferLength = 0;\r
+ \r
+ return true;\r
+}\r
+\r
+/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address\r
+ * and total number of blocks to process, then calls the appropriate low-level dataflash routine to handle the actual\r
+ * reading and writing of the data.\r
+ *\r
+ * \param IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)\r
+ *\r
+ * \return Boolean true if the command completed successfully, false otherwise.\r
+ */\r
+static bool SCSI_Command_ReadWrite_10(const bool IsDataRead)\r
+{\r
+ uint32_t BlockAddress;\r
+ uint16_t TotalBlocks;\r
+ \r
+ /* Load in the 32-bit block address (SCSI uses big-endian, so have to do it byte-by-byte) */\r
+ ((uint8_t*)&BlockAddress)[3] = CommandBlock.SCSICommandData[2];\r
+ ((uint8_t*)&BlockAddress)[2] = CommandBlock.SCSICommandData[3];\r
+ ((uint8_t*)&BlockAddress)[1] = CommandBlock.SCSICommandData[4];\r
+ ((uint8_t*)&BlockAddress)[0] = CommandBlock.SCSICommandData[5];\r
+\r
+ /* Load in the 16-bit total blocks (SCSI uses big-endian, so have to do it byte-by-byte) */\r
+ ((uint8_t*)&TotalBlocks)[1] = CommandBlock.SCSICommandData[7];\r
+ ((uint8_t*)&TotalBlocks)[0] = CommandBlock.SCSICommandData[8];\r
+ \r
+ /* Check if the block address is outside the maximum allowable value for the LUN */\r
+ if (BlockAddress >= LUN_MEDIA_BLOCKS)\r
+ {\r
+ /* Block address is invalid, update SENSE key and return command fail */\r
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,\r
+ SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,\r
+ SCSI_ASENSEQ_NO_QUALIFIER);\r
+\r
+ return false;\r
+ }\r
+\r
+ #if (TOTAL_LUNS > 1)\r
+ /* Adjust the given block address to the real media address based on the selected LUN */\r
+ BlockAddress += ((uint32_t)CommandBlock.LUN * LUN_MEDIA_BLOCKS);\r
+ #endif\r
+ \r
+ /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */\r
+ if (IsDataRead == DATA_READ)\r
+ DataflashManager_ReadBlocks(BlockAddress, TotalBlocks);\r
+ else\r
+ DataflashManager_WriteBlocks(BlockAddress, TotalBlocks);\r
+\r
+ /* Update the bytes transferred counter and succeed the command */\r
+ CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);\r
+ \r
+ return true;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for SCSI.c.\r
+ */\r
+ \r
+#ifndef _SCSI_H_\r
+#define _SCSI_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <avr/pgmspace.h>\r
+\r
+ #include <LUFA/Common/Common.h> // Function Attribute, Atomic, Debug and ISR Macros\r
+ #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
+ #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
+\r
+ #include "MassStorage.h"\r
+ #include "Descriptors.h"\r
+ #include "DataflashManager.h"\r
+ #include "SCSI_Codes.h"\r
+ \r
+ /* Macros: */\r
+ /** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This\r
+ * is for convenience, as it allows for all three sense values (returned upon request to the host to give information about\r
+ * the last command failure) in a quick and easy manner.\r
+ *\r
+ * \param key New SCSI sense key to set the sense code to\r
+ * \param acode New SCSI additional sense key to set the additional sense code to\r
+ * \param aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to\r
+ */\r
+ #define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = key; \\r
+ SenseData.AdditionalSenseCode = acode; \\r
+ SenseData.AdditionalSenseQualifier = aqual; }MACROE\r
+\r
+ /** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */\r
+ #define DATA_READ true\r
+\r
+ /** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */\r
+ #define DATA_WRITE false\r
+\r
+ /** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */\r
+ #define DEVICE_TYPE_BLOCK 0x00\r
+ \r
+ /** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a CD-ROM device. */\r
+ #define DEVICE_TYPE_CDROM 0x05\r
+\r
+ /* Type Defines: */\r
+ /** Type define for a SCSI response structure to a SCSI INQUIRY command. For details of the\r
+ * structure contents, refer to the SCSI specifications.\r
+ */\r
+ typedef struct\r
+ {\r
+ unsigned char DeviceType : 5;\r
+ unsigned char PeripheralQualifier : 3;\r
+ \r
+ unsigned char _RESERVED1 : 7;\r
+ unsigned char Removable : 1;\r
+ \r
+ uint8_t Version;\r
+ \r
+ unsigned char ResponseDataFormat : 4;\r
+ unsigned char _RESERVED2 : 1;\r
+ unsigned char NormACA : 1;\r
+ unsigned char TrmTsk : 1;\r
+ unsigned char AERC : 1;\r
+\r
+ uint8_t AdditionalLength;\r
+ uint8_t _RESERVED3[2];\r
+\r
+ unsigned char SoftReset : 1;\r
+ unsigned char CmdQue : 1;\r
+ unsigned char _RESERVED4 : 1;\r
+ unsigned char Linked : 1;\r
+ unsigned char Sync : 1;\r
+ unsigned char WideBus16Bit : 1;\r
+ unsigned char WideBus32Bit : 1;\r
+ unsigned char RelAddr : 1;\r
+ \r
+ uint8_t VendorID[8];\r
+ uint8_t ProductID[16];\r
+ uint8_t RevisionID[4];\r
+ } SCSI_Inquiry_Response_t;\r
+ \r
+ /** Type define for a SCSI sense structure to a SCSI REQUEST SENSE command. For details of the\r
+ * structure contents, refer to the SCSI specifications.\r
+ */\r
+ typedef struct\r
+ {\r
+ uint8_t ResponseCode;\r
+ \r
+ uint8_t SegmentNumber;\r
+ \r
+ unsigned char SenseKey : 4;\r
+ unsigned char _RESERVED1 : 1;\r
+ unsigned char ILI : 1;\r
+ unsigned char EOM : 1;\r
+ unsigned char FileMark : 1;\r
+ \r
+ uint8_t Information[4];\r
+ uint8_t AdditionalLength;\r
+ uint8_t CmdSpecificInformation[4];\r
+ uint8_t AdditionalSenseCode;\r
+ uint8_t AdditionalSenseQualifier;\r
+ uint8_t FieldReplaceableUnitCode;\r
+ uint8_t SenseKeySpecific[3];\r
+ } SCSI_Request_Sense_Response_t;\r
+ \r
+ /* Function Prototypes: */\r
+ void SCSI_DecodeSCSICommand(void);\r
+ \r
+ #if defined(INCLUDE_FROM_SCSI_C)\r
+ static bool SCSI_Command_Inquiry(void);\r
+ static bool SCSI_Command_Request_Sense(void);\r
+ static bool SCSI_Command_Read_Capacity_10(void);\r
+ static bool SCSI_Command_Send_Diagnostic(void);\r
+ static bool SCSI_Command_ReadWrite_10(const bool IsDataRead);\r
+ #endif\r
+ \r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header containing macros for possible SCSI commands and SENSE data. Refer to\r
+ * the SCSI standard documentation for more information on each SCSI command and\r
+ * the SENSE data.\r
+ */\r
+ \r
+#ifndef _SCSI_CODES_H_\r
+#define _SCSI_CODES_H_\r
+\r
+ /* Macros: */\r
+ #define SCSI_CMD_INQUIRY 0x12\r
+ #define SCSI_CMD_REQUEST_SENSE 0x03\r
+ #define SCSI_CMD_TEST_UNIT_READY 0x00\r
+ #define SCSI_CMD_READ_CAPACITY_10 0x25\r
+ #define SCSI_CMD_SEND_DIAGNOSTIC 0x1D\r
+ #define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E\r
+ #define SCSI_CMD_WRITE_10 0x2A\r
+ #define SCSI_CMD_READ_10 0x28\r
+ #define SCSI_CMD_WRITE_6 0x0A\r
+ #define SCSI_CMD_READ_6 0x08\r
+ #define SCSI_CMD_VERIFY_10 0x2F\r
+ #define SCSI_CMD_MODE_SENSE_6 0x1A\r
+ #define SCSI_CMD_MODE_SENSE_10 0x5A\r
+\r
+ #define SCSI_SENSE_KEY_GOOD 0x00\r
+ #define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01\r
+ #define SCSI_SENSE_KEY_NOT_READY 0x02\r
+ #define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03\r
+ #define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04\r
+ #define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05\r
+ #define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06\r
+ #define SCSI_SENSE_KEY_DATA_PROTECT 0x07\r
+ #define SCSI_SENSE_KEY_BLANK_CHECK 0x08\r
+ #define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09\r
+ #define SCSI_SENSE_KEY_COPY_ABORTED 0x0A\r
+ #define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B\r
+ #define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D\r
+ #define SCSI_SENSE_KEY_MISCOMPARE 0x0E\r
+\r
+ #define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00\r
+ #define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04\r
+ #define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24\r
+ #define SCSI_ASENSE_WRITE_PROTECTED 0x27\r
+ #define SCSI_ASENSE_FORMAT_ERROR 0x31\r
+ #define SCSI_ASENSE_INVALID_COMMAND 0x20\r
+ #define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21\r
+ #define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A\r
+\r
+ #define SCSI_ASENSEQ_NO_QUALIFIER 0x00\r
+ #define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01\r
+ #define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02\r
+ #define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07\r
+\r
+#endif\r
#include <avr/power.h>\r
\r
#include "Descriptors.h"\r
- #include "SCSI.h"\r
- #include "DataflashManager.h"\r
+\r
+ #include "Lib/SCSI.h"\r
+ #include "Lib/DataflashManager.h"\r
\r
#include <LUFA/Version.h> // Library Version Information\r
#include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * SCSI command processing routines, for SCSI commands issued by the host. Mass Storage\r
- * devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,\r
- * which wrap around standard SCSI device commands for controlling the actual storage medium.\r
- */\r
- \r
-#define INCLUDE_FROM_SCSI_C\r
-#include "SCSI.h"\r
-\r
-/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's\r
- * features and capabilities.\r
- */\r
-SCSI_Inquiry_Response_t InquiryData = \r
- {\r
- .DeviceType = DEVICE_TYPE_BLOCK,\r
- .PeripheralQualifier = 0,\r
- \r
- .Removable = true,\r
- \r
- .Version = 0,\r
- \r
- .ResponseDataFormat = 2,\r
- .NormACA = false,\r
- .TrmTsk = false,\r
- .AERC = false,\r
-\r
- .AdditionalLength = 0x1F,\r
- \r
- .SoftReset = false,\r
- .CmdQue = false,\r
- .Linked = false,\r
- .Sync = false,\r
- .WideBus16Bit = false,\r
- .WideBus32Bit = false,\r
- .RelAddr = false,\r
- \r
- .VendorID = "LUFA",\r
- .ProductID = "Dataflash Disk",\r
- .RevisionID = {'0','.','0','0'},\r
- };\r
-\r
-/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE\r
- * command is issued. This gives information on exactly why the last command failed to complete.\r
- */\r
-SCSI_Request_Sense_Response_t SenseData =\r
- {\r
- .ResponseCode = 0x70,\r
- .AdditionalLength = 0x0A,\r
- };\r
-\r
-\r
-/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches\r
- * to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns\r
- * a command failure due to a ILLEGAL REQUEST.\r
- */\r
-void SCSI_DecodeSCSICommand(void)\r
-{\r
- bool CommandSuccess = false;\r
-\r
- /* Run the appropriate SCSI command hander function based on the passed command */\r
- switch (CommandBlock.SCSICommandData[0])\r
- {\r
- case SCSI_CMD_INQUIRY:\r
- CommandSuccess = SCSI_Command_Inquiry(); \r
- break;\r
- case SCSI_CMD_REQUEST_SENSE:\r
- CommandSuccess = SCSI_Command_Request_Sense();\r
- break;\r
- case SCSI_CMD_READ_CAPACITY_10:\r
- CommandSuccess = SCSI_Command_Read_Capacity_10(); \r
- break;\r
- case SCSI_CMD_SEND_DIAGNOSTIC:\r
- CommandSuccess = SCSI_Command_Send_Diagnostic();\r
- break;\r
- case SCSI_CMD_WRITE_10:\r
- CommandSuccess = SCSI_Command_ReadWrite_10(DATA_WRITE);\r
- break;\r
- case SCSI_CMD_READ_10:\r
- CommandSuccess = SCSI_Command_ReadWrite_10(DATA_READ);\r
- break;\r
- case SCSI_CMD_TEST_UNIT_READY:\r
- case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:\r
- case SCSI_CMD_VERIFY_10:\r
- /* These commands should just succeed, no handling required */\r
- CommandSuccess = true;\r
- CommandBlock.DataTransferLength = 0;\r
- break;\r
- default:\r
- /* Update the SENSE key to reflect the invalid command */\r
- SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,\r
- SCSI_ASENSE_INVALID_COMMAND,\r
- SCSI_ASENSEQ_NO_QUALIFIER);\r
- break;\r
- }\r
- \r
- /* Check if command was successfully processed */\r
- if (CommandSuccess)\r
- {\r
- /* Command succeeded - set the CSW status and update the SENSE key */\r
- CommandStatus.Status = Command_Pass;\r
- \r
- SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,\r
- SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,\r
- SCSI_ASENSEQ_NO_QUALIFIER); \r
- }\r
- else\r
- {\r
- /* Command failed - set the CSW status - failed command function updates the SENSE key */\r
- CommandStatus.Status = Command_Fail;\r
- }\r
-}\r
-\r
-/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features\r
- * and capabilities to the host.\r
- *\r
- * \return Boolean true if the command completed successfully, false otherwise.\r
- */\r
-static bool SCSI_Command_Inquiry(void)\r
-{\r
- uint16_t AllocationLength = (((uint16_t)CommandBlock.SCSICommandData[3] << 8) |\r
- CommandBlock.SCSICommandData[4]);\r
- uint16_t BytesTransferred = (AllocationLength < sizeof(InquiryData))? AllocationLength :\r
- sizeof(InquiryData);\r
-\r
- /* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */\r
- if ((CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||\r
- CommandBlock.SCSICommandData[2])\r
- {\r
- /* Optional but unsupported bits set - update the SENSE key and fail the request */\r
- SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,\r
- SCSI_ASENSE_INVALID_FIELD_IN_CDB,\r
- SCSI_ASENSEQ_NO_QUALIFIER);\r
-\r
- return false;\r
- }\r
-\r
- /* Write the INQUIRY data to the endpoint */\r
- Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);\r
-\r
- uint8_t PadBytes[AllocationLength - BytesTransferred];\r
- \r
- /* Pad out remaining bytes with 0x00 */\r
- Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
-\r
- /* Succeed the command and update the bytes transferred counter */\r
- CommandBlock.DataTransferLength -= BytesTransferred;\r
- \r
- return true;\r
-}\r
-\r
-/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,\r
- * including the error code and additional error information so that the host can determine why a command failed to complete.\r
- *\r
- * \return Boolean true if the command completed successfully, false otherwise.\r
- */\r
-static bool SCSI_Command_Request_Sense(void)\r
-{\r
- uint8_t AllocationLength = CommandBlock.SCSICommandData[4];\r
- uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);\r
- \r
- /* Send the SENSE data - this indicates to the host the status of the last command */\r
- Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);\r
- \r
- uint8_t PadBytes[AllocationLength - BytesTransferred];\r
- \r
- /* Pad out remaining bytes with 0x00 */\r
- Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);\r
-\r
- /* Finalize the stream transfer to send the last packet */\r
- Endpoint_ClearIN();\r
-\r
- /* Succeed the command and update the bytes transferred counter */\r
- CommandBlock.DataTransferLength -= BytesTransferred;\r
-\r
- return true;\r
-}\r
-\r
-/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity\r
- * on the selected Logical Unit (drive), as a number of OS-sized blocks.\r
- *\r
- * \return Boolean true if the command completed successfully, false otherwise.\r
- */\r
-static bool SCSI_Command_Read_Capacity_10(void)\r
-{\r
- /* Send the total number of logical blocks in the current LUN */\r
- Endpoint_Write_DWord_BE(LUN_MEDIA_BLOCKS - 1);\r
-\r
- /* Send the logical block size of the device (must be 512 bytes) */\r
- Endpoint_Write_DWord_BE(VIRTUAL_MEMORY_BLOCK_SIZE);\r
-\r
- /* Check if the current command is being aborted by the host */\r
- if (IsMassStoreReset)\r
- return false;\r
-\r
- /* Send the endpoint data packet to the host */\r
- Endpoint_ClearIN();\r
-\r
- /* Succeed the command and update the bytes transferred counter */\r
- CommandBlock.DataTransferLength -= 8;\r
- \r
- return true;\r
-}\r
-\r
-/** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the\r
- * board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is\r
- * supported.\r
- *\r
- * \return Boolean true if the command completed successfully, false otherwise.\r
- */\r
-static bool SCSI_Command_Send_Diagnostic(void)\r
-{\r
- uint8_t ReturnByte;\r
-\r
- /* Check to see if the SELF TEST bit is not set */\r
- if (!(CommandBlock.SCSICommandData[1] & (1 << 2)))\r
- {\r
- /* Only self-test supported - update SENSE key and fail the command */\r
- SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,\r
- SCSI_ASENSE_INVALID_FIELD_IN_CDB,\r
- SCSI_ASENSEQ_NO_QUALIFIER);\r
-\r
- return false;\r
- }\r
- \r
- /* Test first Dataflash IC is present and responding to commands */\r
- Dataflash_SelectChip(DATAFLASH_CHIP1);\r
- Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);\r
- ReturnByte = Dataflash_ReceiveByte();\r
- Dataflash_DeselectChip();\r
-\r
- /* If returned data is invalid, fail the command */\r
- if (ReturnByte != DF_MANUFACTURER_ATMEL)\r
- {\r
- /* Update SENSE key with a hardware error condition and return command fail */\r
- SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,\r
- SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,\r
- SCSI_ASENSEQ_NO_QUALIFIER); \r
- \r
- return false;\r
- }\r
-\r
- #if (DATAFLASH_TOTALCHIPS == 2)\r
- /* Test second Dataflash IC is present and responding to commands */\r
- Dataflash_SelectChip(DATAFLASH_CHIP2);\r
- Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);\r
- ReturnByte = Dataflash_ReceiveByte();\r
- Dataflash_DeselectChip();\r
-\r
- /* If returned data is invalid, fail the command */\r
- if (ReturnByte != DF_MANUFACTURER_ATMEL)\r
- {\r
- /* Update SENSE key with a hardware error condition and return command fail */\r
- SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,\r
- SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,\r
- SCSI_ASENSEQ_NO_QUALIFIER); \r
- \r
- return false;\r
- }\r
- #endif\r
- \r
- /* Succeed the command and update the bytes transferred counter */\r
- CommandBlock.DataTransferLength = 0;\r
- \r
- return true;\r
-}\r
-\r
-/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address\r
- * and total number of blocks to process, then calls the appropriate low-level dataflash routine to handle the actual\r
- * reading and writing of the data.\r
- *\r
- * \param IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)\r
- *\r
- * \return Boolean true if the command completed successfully, false otherwise.\r
- */\r
-static bool SCSI_Command_ReadWrite_10(const bool IsDataRead)\r
-{\r
- uint32_t BlockAddress;\r
- uint16_t TotalBlocks;\r
- \r
- /* Load in the 32-bit block address (SCSI uses big-endian, so have to do it byte-by-byte) */\r
- ((uint8_t*)&BlockAddress)[3] = CommandBlock.SCSICommandData[2];\r
- ((uint8_t*)&BlockAddress)[2] = CommandBlock.SCSICommandData[3];\r
- ((uint8_t*)&BlockAddress)[1] = CommandBlock.SCSICommandData[4];\r
- ((uint8_t*)&BlockAddress)[0] = CommandBlock.SCSICommandData[5];\r
-\r
- /* Load in the 16-bit total blocks (SCSI uses big-endian, so have to do it byte-by-byte) */\r
- ((uint8_t*)&TotalBlocks)[1] = CommandBlock.SCSICommandData[7];\r
- ((uint8_t*)&TotalBlocks)[0] = CommandBlock.SCSICommandData[8];\r
- \r
- /* Check if the block address is outside the maximum allowable value for the LUN */\r
- if (BlockAddress >= LUN_MEDIA_BLOCKS)\r
- {\r
- /* Block address is invalid, update SENSE key and return command fail */\r
- SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,\r
- SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,\r
- SCSI_ASENSEQ_NO_QUALIFIER);\r
-\r
- return false;\r
- }\r
-\r
- #if (TOTAL_LUNS > 1)\r
- /* Adjust the given block address to the real media address based on the selected LUN */\r
- BlockAddress += ((uint32_t)CommandBlock.LUN * LUN_MEDIA_BLOCKS);\r
- #endif\r
- \r
- /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */\r
- if (IsDataRead == DATA_READ)\r
- DataflashManager_ReadBlocks(BlockAddress, TotalBlocks);\r
- else\r
- DataflashManager_WriteBlocks(BlockAddress, TotalBlocks);\r
-\r
- /* Update the bytes transferred counter and succeed the command */\r
- CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);\r
- \r
- return true;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for SCSI.c.\r
- */\r
- \r
-#ifndef _SCSI_H_\r
-#define _SCSI_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <avr/pgmspace.h>\r
-\r
- #include <LUFA/Common/Common.h> // Function Attribute, Atomic, Debug and ISR Macros\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- #include <LUFA/Drivers/Board/LEDs.h> // LEDs driver\r
-\r
- #include "MassStorage.h"\r
- #include "Descriptors.h"\r
- #include "DataflashManager.h"\r
- #include "SCSI_Codes.h"\r
- \r
- /* Macros: */\r
- /** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This\r
- * is for convenience, as it allows for all three sense values (returned upon request to the host to give information about\r
- * the last command failure) in a quick and easy manner.\r
- *\r
- * \param key New SCSI sense key to set the sense code to\r
- * \param acode New SCSI additional sense key to set the additional sense code to\r
- * \param aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to\r
- */\r
- #define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = key; \\r
- SenseData.AdditionalSenseCode = acode; \\r
- SenseData.AdditionalSenseQualifier = aqual; }MACROE\r
-\r
- /** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */\r
- #define DATA_READ true\r
-\r
- /** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */\r
- #define DATA_WRITE false\r
-\r
- /** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */\r
- #define DEVICE_TYPE_BLOCK 0x00\r
- \r
- /** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a CD-ROM device. */\r
- #define DEVICE_TYPE_CDROM 0x05\r
-\r
- /* Type Defines: */\r
- /** Type define for a SCSI response structure to a SCSI INQUIRY command. For details of the\r
- * structure contents, refer to the SCSI specifications.\r
- */\r
- typedef struct\r
- {\r
- unsigned char DeviceType : 5;\r
- unsigned char PeripheralQualifier : 3;\r
- \r
- unsigned char _RESERVED1 : 7;\r
- unsigned char Removable : 1;\r
- \r
- uint8_t Version;\r
- \r
- unsigned char ResponseDataFormat : 4;\r
- unsigned char _RESERVED2 : 1;\r
- unsigned char NormACA : 1;\r
- unsigned char TrmTsk : 1;\r
- unsigned char AERC : 1;\r
-\r
- uint8_t AdditionalLength;\r
- uint8_t _RESERVED3[2];\r
-\r
- unsigned char SoftReset : 1;\r
- unsigned char CmdQue : 1;\r
- unsigned char _RESERVED4 : 1;\r
- unsigned char Linked : 1;\r
- unsigned char Sync : 1;\r
- unsigned char WideBus16Bit : 1;\r
- unsigned char WideBus32Bit : 1;\r
- unsigned char RelAddr : 1;\r
- \r
- uint8_t VendorID[8];\r
- uint8_t ProductID[16];\r
- uint8_t RevisionID[4];\r
- } SCSI_Inquiry_Response_t;\r
- \r
- /** Type define for a SCSI sense structure to a SCSI REQUEST SENSE command. For details of the\r
- * structure contents, refer to the SCSI specifications.\r
- */\r
- typedef struct\r
- {\r
- uint8_t ResponseCode;\r
- \r
- uint8_t SegmentNumber;\r
- \r
- unsigned char SenseKey : 4;\r
- unsigned char _RESERVED1 : 1;\r
- unsigned char ILI : 1;\r
- unsigned char EOM : 1;\r
- unsigned char FileMark : 1;\r
- \r
- uint8_t Information[4];\r
- uint8_t AdditionalLength;\r
- uint8_t CmdSpecificInformation[4];\r
- uint8_t AdditionalSenseCode;\r
- uint8_t AdditionalSenseQualifier;\r
- uint8_t FieldReplaceableUnitCode;\r
- uint8_t SenseKeySpecific[3];\r
- } SCSI_Request_Sense_Response_t;\r
- \r
- /* Function Prototypes: */\r
- void SCSI_DecodeSCSICommand(void);\r
- \r
- #if defined(INCLUDE_FROM_SCSI_C)\r
- static bool SCSI_Command_Inquiry(void);\r
- static bool SCSI_Command_Request_Sense(void);\r
- static bool SCSI_Command_Read_Capacity_10(void);\r
- static bool SCSI_Command_Send_Diagnostic(void);\r
- static bool SCSI_Command_ReadWrite_10(const bool IsDataRead);\r
- #endif\r
- \r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header containing macros for possible SCSI commands and SENSE data. Refer to\r
- * the SCSI standard documentation for more information on each SCSI command and\r
- * the SENSE data.\r
- */\r
- \r
-#ifndef _SCSI_CODES_H_\r
-#define _SCSI_CODES_H_\r
-\r
- /* Macros: */\r
- #define SCSI_CMD_INQUIRY 0x12\r
- #define SCSI_CMD_REQUEST_SENSE 0x03\r
- #define SCSI_CMD_TEST_UNIT_READY 0x00\r
- #define SCSI_CMD_READ_CAPACITY_10 0x25\r
- #define SCSI_CMD_SEND_DIAGNOSTIC 0x1D\r
- #define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E\r
- #define SCSI_CMD_WRITE_10 0x2A\r
- #define SCSI_CMD_READ_10 0x28\r
- #define SCSI_CMD_WRITE_6 0x0A\r
- #define SCSI_CMD_READ_6 0x08\r
- #define SCSI_CMD_VERIFY_10 0x2F\r
- #define SCSI_CMD_MODE_SENSE_6 0x1A\r
- #define SCSI_CMD_MODE_SENSE_10 0x5A\r
-\r
- #define SCSI_SENSE_KEY_GOOD 0x00\r
- #define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01\r
- #define SCSI_SENSE_KEY_NOT_READY 0x02\r
- #define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03\r
- #define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04\r
- #define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05\r
- #define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06\r
- #define SCSI_SENSE_KEY_DATA_PROTECT 0x07\r
- #define SCSI_SENSE_KEY_BLANK_CHECK 0x08\r
- #define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09\r
- #define SCSI_SENSE_KEY_COPY_ABORTED 0x0A\r
- #define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B\r
- #define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D\r
- #define SCSI_SENSE_KEY_MISCOMPARE 0x0E\r
-\r
- #define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00\r
- #define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04\r
- #define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24\r
- #define SCSI_ASENSE_WRITE_PROTECTED 0x27\r
- #define SCSI_ASENSE_FORMAT_ERROR 0x31\r
- #define SCSI_ASENSE_INVALID_COMMAND 0x20\r
- #define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21\r
- #define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A\r
-\r
- #define SCSI_ASENSEQ_NO_QUALIFIER 0x00\r
- #define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01\r
- #define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02\r
- #define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07\r
-\r
-#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- SCSI.c \\r
- DataflashManager.c \\r
+ Lib/SCSI.c \\r
+ Lib/DataflashManager.c \\r
$(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Address Resolution Protocol (ARP) packet handling routines. This protocol handles the\r
- * conversion of physical MAC addresses to protocol IP addresses between the host and the\r
- * device.\r
- */\r
- \r
-#include "ARP.h"\r
-\r
-/** Processes an ARP packet inside an Ethernet frame, and writes the appropriate response\r
- * to the output Ethernet frame if the host is requesting the IP or MAC address of the\r
- * virtual server device on the network.\r
- *\r
- * \param InDataStart Pointer to the start of the incoming packet's ARP header\r
- * \param OutDataStart Pointer to the start of the outgoing packet's ARP header\r
- *\r
- * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise\r
- */\r
-int16_t ARP_ProcessARPPacket(void* InDataStart, void* OutDataStart)\r
-{\r
- DecodeARPHeader(InDataStart);\r
-\r
- ARP_Header_t* ARPHeaderIN = (ARP_Header_t*)InDataStart;\r
- ARP_Header_t* ARPHeaderOUT = (ARP_Header_t*)OutDataStart;\r
-\r
- /* Ensure that the ARP request is a IPv4 request packet */\r
- if ((SwapEndian_16(ARPHeaderIN->ProtocolType) == ETHERTYPE_IPV4) &&\r
- (SwapEndian_16(ARPHeaderIN->Operation) == ARP_OPERATION_REQUEST))\r
- {\r
- /* If the ARP packet is requesting the MAC or IP of the virtual webserver, return the response */\r
- if (IP_COMPARE(&ARPHeaderIN->TPA, &ServerIPAddress) || \r
- MAC_COMPARE(&ARPHeaderIN->THA, &ServerMACAddress))\r
- {\r
- /* Fill out the ARP response header */\r
- ARPHeaderOUT->HardwareType = ARPHeaderIN->HardwareType;\r
- ARPHeaderOUT->ProtocolType = ARPHeaderIN->ProtocolType;\r
- ARPHeaderOUT->HLEN = ARPHeaderIN->HLEN;\r
- ARPHeaderOUT->PLEN = ARPHeaderIN->PLEN;\r
- ARPHeaderOUT->Operation = SwapEndian_16(ARP_OPERATION_REPLY);\r
-\r
- /* Copy over the sender MAC/IP to the target fields for the response */\r
- ARPHeaderOUT->THA = ARPHeaderIN->SHA;\r
- ARPHeaderOUT->TPA = ARPHeaderIN->SPA;\r
-\r
- /* Copy over the new sender MAC/IP - MAC and IP addresses of the virtual webserver */\r
- ARPHeaderOUT->SHA = ServerMACAddress;\r
- ARPHeaderOUT->SPA = ServerIPAddress;\r
-\r
- /* Return the size of the response so far */\r
- return sizeof(ARP_Header_t);\r
- }\r
- }\r
- \r
- return NO_RESPONSE;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for ARP.c.\r
- */\r
- \r
-#ifndef _ARP_H_\r
-#define _ARP_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <string.h>\r
- \r
- #include <LUFA/Scheduler/Scheduler.h>\r
- \r
- #include "EthernetProtocols.h"\r
- #include "Ethernet.h"\r
- #include "ProtocolDecoders.h"\r
- \r
- /* Macros: */\r
- /** ARP header operation constant, indicating a request from a host for an address translation */\r
- #define ARP_OPERATION_REQUEST 1\r
-\r
- /** ARP header operation constant, indicating a reply from a host giving an address translation */\r
- #define ARP_OPERATION_REPLY 2\r
-\r
- /* Type Defines: */\r
- /** Type define for an ARP packet inside an Ethernet frame. */\r
- typedef struct\r
- {\r
- uint16_t HardwareType; /**< Hardware type constant, indicating the hardware used */\r
- uint16_t ProtocolType; /**< Protocol being resolved, usually ETHERTYPE_IPV4 */\r
- \r
- uint8_t HLEN; /**< Length in bytes of the source/destination hardware addresses */\r
- uint8_t PLEN; /**< Length in bytes of the source/destination protocol addresses */\r
- uint16_t Operation; /**< Type of operation, either ARP_OPERATION_REQUEST or ARP_OPERATION_REPLY */\r
- \r
- MAC_Address_t SHA; /**< Sender's hardware address */\r
- IP_Address_t SPA; /**< Sender's protocol address */\r
- MAC_Address_t THA; /**< Target's hardware address */\r
- IP_Address_t TPA; /**< Target's protocol address */\r
- } ARP_Header_t;\r
- \r
- /* Function Prototypes: */\r
- int16_t ARP_ProcessARPPacket(void* InDataStart, void* OutDataStart);\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Dynamic Host Configuration Protocol (DHCP) packet handling routines. This protocol\r
- * handles the automatic IP negotiation to the host, so that the host will use the provided\r
- * IP address given to it by the device.\r
- */\r
- \r
-#include "DHCP.h"\r
-\r
-/** Processes a DHCP packet inside an Ethernet frame, and writes the appropriate response\r
- * to the output Ethernet frame if the host is requesting or accepting an IP address.\r
- *\r
- * \param IPHeaderInStart Pointer to the start of the incoming packet's IP header\r
- * \param DHCPHeaderInStart Pointer to the start of the incoming packet's DHCP header\r
- * \param DHCPHeaderOutStart Pointer to the start of the outgoing packet's DHCP header\r
- *\r
- * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise\r
- */\r
-int16_t DHCP_ProcessDHCPPacket(void* IPHeaderInStart, void* DHCPHeaderInStart, void* DHCPHeaderOutStart)\r
-{\r
- IP_Header_t* IPHeaderIN = (IP_Header_t*)IPHeaderInStart;\r
- DHCP_Header_t* DHCPHeaderIN = (DHCP_Header_t*)DHCPHeaderInStart;\r
- DHCP_Header_t* DHCPHeaderOUT = (DHCP_Header_t*)DHCPHeaderOutStart;\r
- \r
- uint8_t* DHCPOptionsINStart = (uint8_t*)(DHCPHeaderInStart + sizeof(DHCP_Header_t));\r
- uint8_t* DHCPOptionsOUTStart = (uint8_t*)(DHCPHeaderOutStart + sizeof(DHCP_Header_t));\r
-\r
- DecodeDHCPHeader(DHCPHeaderInStart);\r
-\r
- /* Zero out the response DHCP packet, as much of it legacy and left at 0 */\r
- memset(DHCPHeaderOUT, 0, sizeof(DHCP_Header_t));\r
-\r
- /* Fill out the response DHCP packet */\r
- DHCPHeaderOUT->HardwareType = DHCPHeaderIN->HardwareType;\r
- DHCPHeaderOUT->Operation = DHCP_OP_BOOTREPLY;\r
- DHCPHeaderOUT->HardwareAddressLength = DHCPHeaderIN->HardwareAddressLength;\r
- DHCPHeaderOUT->Hops = 0;\r
- DHCPHeaderOUT->TransactionID = DHCPHeaderIN->TransactionID;\r
- DHCPHeaderOUT->ElapsedSeconds = 0;\r
- DHCPHeaderOUT->Flags = DHCPHeaderIN->Flags;\r
- DHCPHeaderOUT->YourIP = ClientIPAddress;\r
- memcpy(&DHCPHeaderOUT->ClientHardwareAddress, &DHCPHeaderIN->ClientHardwareAddress, sizeof(MAC_Address_t));\r
- DHCPHeaderOUT->Cookie = SwapEndian_32(DHCP_MAGIC_COOKIE);\r
- \r
- /* Alter the incoming IP packet header so that the corrected IP source and destinations are used - this means that\r
- when the response IP header is generated, it will use the corrected addresses and not the null/broatcast addresses */\r
- IPHeaderIN->SourceAddress = ClientIPAddress;\r
- IPHeaderIN->DestinationAddress = ServerIPAddress;\r
-\r
- /* Process the incoming DHCP packet options */\r
- while (DHCPOptionsINStart[0] != DHCP_OPTION_END)\r
- { \r
- /* Find the Message Type DHCP option, to determine the type of DHCP packet */\r
- if (DHCPOptionsINStart[0] == DHCP_OPTION_MESSAGETYPE)\r
- {\r
- if ((DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_DISCOVER) || (DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_REQUEST))\r
- {\r
- /* Fill out the response DHCP packet options for a DHCP OFFER or ACK response */\r
-\r
- *(DHCPOptionsOUTStart++) = DHCP_OPTION_MESSAGETYPE;\r
- *(DHCPOptionsOUTStart++) = 1;\r
- *(DHCPOptionsOUTStart++) = (DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_DISCOVER) ? DHCP_MESSAGETYPE_OFFER\r
- : DHCP_MESSAGETYPE_ACK;\r
-\r
- *(DHCPOptionsOUTStart++) = DHCP_OPTION_SUBNETMASK;\r
- *(DHCPOptionsOUTStart++) = 4;\r
- *(DHCPOptionsOUTStart++) = 0xFF;\r
- *(DHCPOptionsOUTStart++) = 0xFF;\r
- *(DHCPOptionsOUTStart++) = 0xFF;\r
- *(DHCPOptionsOUTStart++) = 0x00;\r
-\r
- *(DHCPOptionsOUTStart++) = DHCP_OPTION_DHCPSERVER;\r
- *(DHCPOptionsOUTStart++) = sizeof(IP_Address_t);\r
- memcpy(DHCPOptionsOUTStart, &ServerIPAddress, sizeof(IP_Address_t));\r
- DHCPOptionsOUTStart += sizeof(IP_Address_t);\r
-\r
- *(DHCPOptionsOUTStart++) = DHCP_OPTION_END;\r
- \r
- return (sizeof(DHCP_Header_t) + 12 + sizeof(IP_Address_t));\r
- }\r
- }\r
- \r
- /* Go to the next DHCP option - skip one byte if option is a padding byte, else skip the complete option's size */\r
- DHCPOptionsINStart += ((DHCPOptionsINStart[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptionsINStart[1] + 2));\r
- }\r
- \r
- return NO_RESPONSE;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for DHCP.c.\r
- */\r
- \r
-#ifndef _DHCP_H_\r
-#define _DHCP_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <string.h>\r
- \r
- #include "EthernetProtocols.h"\r
- #include "Ethernet.h"\r
- #include "ProtocolDecoders.h"\r
-\r
- /* Macros: */\r
- /** DHCP operation constant, indicating a request from a host to a DHCP server */\r
- #define DHCP_OP_BOOTREQUEST 0x01\r
-\r
- /** DHCP operation constant, indicating a reply from a DHCP server to a host */\r
- #define DHCP_OP_BOOTREPLY 0x02\r
- \r
- /** Hardware type constant, indicating Ethernet as a carrier */\r
- #define DHCP_HTYPE_ETHERNET 0x01\r
- \r
- /** Magic boot protocol "cookie", inserted into all BOOTP packets (BOOTP is the carrier of DHCP) */\r
- #define DHCP_MAGIC_COOKIE 0x63825363\r
- \r
- /** DHCP option list entry header, indicating that a subnet mask will follow */\r
- #define DHCP_OPTION_SUBNETMASK 1\r
-\r
- /** DHCP option list entry header, indicating that the DHCP message type constant will follow */\r
- #define DHCP_OPTION_MESSAGETYPE 53\r
-\r
- /** DHCP option list entry header, indicating that the IP address of the DHCP server will follow */\r
- #define DHCP_OPTION_DHCPSERVER 54\r
-\r
- /** DHCP option list entry header, used to pad out option data */\r
- #define DHCP_OPTION_PAD 0\r
-\r
- /** DHCP option list entry header, indicating the end of option data */\r
- #define DHCP_OPTION_END 255\r
- \r
- /** Message type constant, used in the DHCP option data field, requesting that a DHCP server offer an IP address */\r
- #define DHCP_MESSAGETYPE_DISCOVER 1\r
-\r
- /** Message type constant, used in the DHCP option data field, indicating that a DHCP server is offering an IP address */\r
- #define DHCP_MESSAGETYPE_OFFER 2\r
-\r
- /** Message type constant, used in the DHCP option data field, requesting that a DHCP server lease a given IP address */\r
- #define DHCP_MESSAGETYPE_REQUEST 3\r
-\r
- /** Message type constant, used in the DHCP option data field, declining an offered DHCP server IP address lease */\r
- #define DHCP_MESSAGETYPE_DECLINE 4\r
-\r
- /** Message type constant, used in the DHCP option data field, ACKing a host IP lease request */\r
- #define DHCP_MESSAGETYPE_ACK 5\r
-\r
- /** Message type constant, used in the DHCP option data field, NACKing a host IP lease request */\r
- #define DHCP_MESSAGETYPE_NACK 6\r
-\r
- /** Message type constant, used in the DHCP option data field, indicating that a host is releasing a leased IP address */\r
- #define DHCP_MESSAGETYPE_RELEASE 7\r
-\r
- /* Type Defines: */\r
- /** Type define for a DHCP packet inside an Ethernet frame. */\r
- typedef struct\r
- {\r
- uint8_t Operation; /**< DHCP operation, either DHCP_OP_BOOTREQUEST or DHCP_OP_BOOTREPLY */\r
- uint8_t HardwareType; /**< Hardware carrier type constant */\r
- uint8_t HardwareAddressLength; /**< Length in bytes of a hardware (MAC) address on the network */\r
- uint8_t Hops; /**< Number of hops required to reach the server, unused */\r
-\r
- uint32_t TransactionID; /**< Unique ID of the DHCP packet, for positive matching between sent and received packets */\r
-\r
- uint16_t ElapsedSeconds; /**< Elapsed seconds since the request was made */\r
- uint16_t Flags; /**< BOOTP packet flags */\r
- \r
- IP_Address_t ClientIP; /**< Client IP address, if already leased an IP */\r
- IP_Address_t YourIP; /**< Client IP address */\r
- IP_Address_t NextServerIP; /**< Legacy BOOTP protocol field, unused for DHCP */\r
- IP_Address_t RelayAgentIP; /**< Legacy BOOTP protocol field, unused for DHCP */\r
- \r
- uint8_t ClientHardwareAddress[16]; /**< Hardware (MAC) address of the client making a request to the DHCP server */\r
- uint8_t ServerHostnameString[64]; /**< Legacy BOOTP protocol field, unused for DHCP */\r
- uint8_t BootFileName[128]; /**< Legacy BOOTP protocol field, unused for DHCP */\r
- \r
- uint32_t Cookie; /**< Magic BOOTP protocol cookie to indicate a valid packet */\r
- } DHCP_Header_t;\r
-\r
- /* Function Prototypes: */\r
- int16_t DHCP_ProcessDHCPPacket(void* IPHeaderInStart, void* DHCPHeaderInStart, void* DHCPHeaderOutStart);\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Ethernet frame packet handling routines. This protocol handles the processing of raw Ethernet\r
- * frames sent and received, deferring the processing of subpacket protocols to the appropriate\r
- * protocol handlers, such as DHCP or ARP.\r
- */\r
- \r
-#include "Ethernet.h"\r
-\r
-/* Global Variables: */\r
-/** Ethernet Frame buffer structure, to hold the incoming Ethernet frame from the host. */\r
-Ethernet_Frame_Info_t FrameIN;\r
-\r
-/** Ethernet Frame buffer structure, to hold the outgoing Ethernet frame to the host. */\r
-Ethernet_Frame_Info_t FrameOUT;\r
-\r
-/** Constant for convenience when checking against or setting a MAC address to the virtual server MAC address. */\r
-const MAC_Address_t ServerMACAddress = {SERVER_MAC_ADDRESS};\r
-\r
-/** Constant for convenience when checking against or setting an IP address to the virtual server IP address. */\r
-const IP_Address_t ServerIPAddress = {SERVER_IP_ADDRESS};\r
-\r
-/** Constant for convenience when checking against or setting a MAC address to the broadcast MAC address. */\r
-const MAC_Address_t BroadcastMACAddress = {BROADCAST_MAC_ADDRESS};\r
-\r
-/** Constant for convenience when checking against or setting a IP address to the broadcast IP address. */\r
-const IP_Address_t BroadcastIPAddress = {BROADCAST_IP_ADDRESS};\r
-\r
-/** Constant for convenience when checking against or setting an IP address to the client (host) IP address. */\r
-const IP_Address_t ClientIPAddress = {CLIENT_IP_ADDRESS};\r
-\r
-\r
-/** Processes an incoming Ethernet frame, and writes the appropriate response to the output Ethernet\r
- * frame buffer if the sub protocol handlers create a valid response.\r
- */\r
-void Ethernet_ProcessPacket(void)\r
-{\r
- DecodeEthernetFrameHeader(FrameIN.FrameData);\r
-\r
- /* Cast the incoming Ethernet frame to the Ethernet header type */\r
- Ethernet_Frame_Header_t* FrameINHeader = (Ethernet_Frame_Header_t*)&FrameIN.FrameData;\r
- Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData;\r
- \r
- int16_t RetSize = NO_RESPONSE;\r
- \r
- /* Ensure frame is addressed to either all (broadcast) or the virtual webserver, and is a type II frame */\r
- if ((MAC_COMPARE(&FrameINHeader->Destination, &ServerMACAddress) ||\r
- MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress)) &&\r
- (SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE))\r
- {\r
- /* Process the packet depending on its protocol */\r
- switch (SwapEndian_16(FrameINHeader->EtherType))\r
- {\r
- case ETHERTYPE_ARP:\r
- RetSize = ARP_ProcessARPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],\r
- &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);\r
- break; \r
- case ETHERTYPE_IPV4:\r
- RetSize = IP_ProcessIPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],\r
- &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);\r
- break;\r
- }\r
- \r
- /* Protocol processing routine has filled a response, complete the ethernet frame header */\r
- if (RetSize > 0)\r
- {\r
- /* Fill out the response Ethernet frame header */\r
- FrameOUTHeader->Source = ServerMACAddress;\r
- FrameOUTHeader->Destination = FrameINHeader->Source;\r
- FrameOUTHeader->EtherType = FrameINHeader->EtherType;\r
- \r
- /* Set the response length in the buffer and indicate that a response is ready to be sent */\r
- FrameOUT.FrameLength = (sizeof(Ethernet_Frame_Header_t) + RetSize);\r
- FrameOUT.FrameInBuffer = true;\r
- }\r
- }\r
-\r
- /* Check if the packet was processed */\r
- if (RetSize != NO_PROCESS)\r
- {\r
- /* Clear the frame buffer */\r
- FrameIN.FrameInBuffer = false;\r
- }\r
-}\r
-\r
-/** Calculates the appropriate ethernet checksum, consisting of the addition of the one's\r
- * compliment of each word, complimented.\r
- *\r
- * \param Data Pointer to the packet buffer data whose checksum must be calculated\r
- * \param Bytes Number of bytes in the data buffer to process\r
- *\r
- * \return A 16-bit Ethernet checksum value\r
- */\r
-uint16_t Ethernet_Checksum16(void* Data, uint16_t Bytes)\r
-{\r
- uint16_t* Words = (uint16_t*)Data;\r
- uint32_t Checksum = 0;\r
-\r
- for (uint8_t CurrWord = 0; CurrWord < (Bytes >> 1); CurrWord++)\r
- Checksum += Words[CurrWord];\r
- \r
- while (Checksum & 0xFFFF0000)\r
- Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16));\r
- \r
- return ~Checksum;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for Ethernet.c.\r
- */\r
- \r
-#ifndef _ETHERNET_H_\r
-#define _ETHERNET_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <string.h>\r
-\r
- #include "EthernetProtocols.h"\r
- #include "ProtocolDecoders.h"\r
- #include "ICMP.h"\r
- #include "TCP.h"\r
- #include "UDP.h"\r
- #include "DHCP.h"\r
- #include "ARP.h"\r
- #include "IP.h"\r
- \r
- /* Macros: */\r
- /** Physical MAC address of the virtual server on the network */\r
- #define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01} \r
-\r
- /** Physical MAC address of the network broadcast address */\r
- #define BROADCAST_MAC_ADDRESS {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}\r
- \r
- /** Performs a comparison between two MAC addresses, indicating if they are identical.\r
- * \r
- * \param MAC1 First MAC address\r
- * \param MAC2 Second MAC address\r
- *\r
- * \return True if the addresses match, false otherwise\r
- */\r
- #define MAC_COMPARE(MAC1, MAC2) (memcmp(MAC1, MAC2, sizeof(MAC_Address_t)) == 0)\r
-\r
- /** Maximum size of an incoming or outgoing Ethernet frame in bytes */\r
- #define ETHERNET_FRAME_SIZE_MAX 1500\r
- \r
- /** Minimum size of an Ethernet packet in bytes, to conform to the Ethernet V2 packet standard */\r
- #define ETHERNET_VER2_MINSIZE 0x0600\r
- \r
- /** Return value for all sub protocol handling routines, indicating that no response packet has been generated */\r
- #define NO_RESPONSE 0 \r
-\r
- /** Return value for all sub protocol handling routines, indicating that the packet has not yet been handled */\r
- #define NO_PROCESS -1\r
-\r
- /* Type Defines: */\r
- /** Type define for an Ethernet frame buffer. */\r
- typedef struct\r
- {\r
- uint8_t FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents */\r
- uint16_t FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer */\r
- bool FrameInBuffer; /**< Indicates if a frame is currently stored in the buffer */\r
- } Ethernet_Frame_Info_t;\r
-\r
- /** Type define for an Ethernet frame header */\r
- typedef struct\r
- {\r
- MAC_Address_t Destination; /**< Physical MAC address of the packet recipient */\r
- MAC_Address_t Source; /**< Physics MAC address of the packet source */\r
- \r
- union\r
- {\r
- uint16_t EtherType; /**< Ethernet packet subprotocol type, for Ethernet V2 packets */\r
- uint16_t Length; /**< Ethernet frame length, for Ethernet V1 packets */\r
- };\r
- } Ethernet_Frame_Header_t;\r
- \r
- /* External Variables: */\r
- extern Ethernet_Frame_Info_t FrameIN;\r
- extern Ethernet_Frame_Info_t FrameOUT;\r
-\r
- extern const MAC_Address_t ServerMACAddress;\r
- extern const IP_Address_t ServerIPAddress;\r
- extern const MAC_Address_t BroadcastMACAddress;\r
- extern const IP_Address_t BroadcastIPAddress;\r
- extern const IP_Address_t ClientIPAddress;\r
- \r
- /* Function Prototypes: */\r
- void Ethernet_ProcessPacket(void);\r
- uint16_t Ethernet_Checksum16(void* Data, uint16_t Bytes);\r
- \r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * General Ethernet protocol constants and type defines, for use by\r
- * all network protocol portions of the TCP/IP stack.\r
- */\r
-\r
-#ifndef _ETHERNET_PROTOCOLS_H_\r
-#define _ETHERNET_PROTOCOLS_H_\r
-\r
- /* Macros: */\r
- #define ETHERTYPE_IPV4 0x0800\r
- #define ETHERTYPE_ARP 0x0806\r
- #define ETHERTYPE_RARP 0x8035\r
- #define ETHERTYPE_APPLETALK 0x809b\r
- #define ETHERTYPE_APPLETALKARP 0x80f3\r
- #define ETHERTYPE_IEEE8021Q 0x8100\r
- #define ETHERTYPE_NOVELLIPX 0x8137\r
- #define ETHERTYPE_NOVELL 0x8138\r
- #define ETHERTYPE_IPV6 0x86DD\r
- #define ETHERTYPE_COBRANET 0x8819\r
- #define ETHERTYPE_PROVIDERBRIDGING 0x88a8\r
- #define ETHERTYPE_MPLSUNICAST 0x8847\r
- #define ETHERTYPE_MPLSMULTICAST 0x8848\r
- #define ETHERTYPE_PPPoEDISCOVERY 0x8863\r
- #define ETHERTYPE_PPPoESESSION 0x8864\r
- #define ETHERTYPE_EAPOVERLAN 0x888E\r
- #define ETHERTYPE_HYPERSCSI 0x889A\r
- #define ETHERTYPE_ATAOVERETHERNET 0x88A2\r
- #define ETHERTYPE_ETHERCAT 0x88A4\r
- #define ETHERTYPE_SERCOSIII 0x88CD\r
- #define ETHERTYPE_CESoE 0x88D8\r
- #define ETHERTYPE_MACSECURITY 0x88E5\r
- #define ETHERTYPE_FIBRECHANNEL 0x8906\r
- #define ETHERTYPE_QINQ 0x9100\r
- #define ETHERTYPE_VLLT 0xCAFE\r
- \r
- #define PROTOCOL_ICMP 1\r
- #define PROTOCOL_IGMP 2\r
- #define PROTOCOL_TCP 6\r
- #define PROTOCOL_UDP 17\r
- #define PROTOCOL_OSPF 89\r
- #define PROTOCOL_SCTP 132\r
-\r
- /* Type Defines: */\r
- /** Type define for a physical MAC address of a device on a network */\r
- typedef struct\r
- {\r
- uint8_t Octets[6]; /**< Individual bytes of a MAC address */\r
- } MAC_Address_t;\r
- \r
- /** Type define for a protocol IP address of a device on a network */\r
- typedef struct\r
- {\r
- uint8_t Octets[4]; /**< Individual bytes of an IP address */\r
- } IP_Address_t;\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Internet Control Message Protocol (ICMP) packet handling routines. This protocol handles\r
- * Echo requests from the host, to indicate a successful network connection between the host\r
- * and the virtual server.\r
- */\r
- \r
-#include "ICMP.h"\r
-\r
-/** Processes an ICMP packet inside an Ethernet frame, and writes the appropriate response\r
- * to the output Ethernet frame if the host is issuing a ICMP ECHO request.\r
- *\r
- * \param InDataStart Pointer to the start of the incoming packet's ICMP header\r
- * \param OutDataStart Pointer to the start of the outgoing packet's ICMP header\r
- *\r
- * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise\r
- */\r
-int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart)\r
-{\r
- ICMP_Header_t* ICMPHeaderIN = (ICMP_Header_t*)InDataStart;\r
- ICMP_Header_t* ICMPHeaderOUT = (ICMP_Header_t*)OutDataStart;\r
-\r
- DecodeICMPHeader(InDataStart);\r
-\r
- /* Determine if the ICMP packet is an echo request (ping) */\r
- if (ICMPHeaderIN->Type == ICMP_TYPE_ECHOREQUEST)\r
- {\r
- /* Fill out the ICMP response packet */\r
- ICMPHeaderOUT->Type = ICMP_TYPE_ECHOREPLY;\r
- ICMPHeaderOUT->Code = 0;\r
- ICMPHeaderOUT->Checksum = 0;\r
- ICMPHeaderOUT->Id = ICMPHeaderIN->Id;\r
- ICMPHeaderOUT->Sequence = ICMPHeaderIN->Sequence;\r
- \r
- uint16_t DataSize = FrameIN.FrameLength - ((((uint16_t)InDataStart + sizeof(ICMP_Header_t)) - (uint16_t)FrameIN.FrameData));\r
- \r
- /* Copy the remaining payload to the response - echo requests should echo back any sent data */\r
- memcpy(&((uint8_t*)OutDataStart)[sizeof(ICMP_Header_t)],\r
- &((uint8_t*)InDataStart)[sizeof(ICMP_Header_t)],\r
- DataSize);\r
-\r
- ICMPHeaderOUT->Checksum = Ethernet_Checksum16(ICMPHeaderOUT, (DataSize + sizeof(ICMP_Header_t)));\r
-\r
- /* Return the size of the response so far */\r
- return (DataSize + sizeof(ICMP_Header_t));\r
- }\r
- \r
- return NO_RESPONSE;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for ICMP.c.\r
- */\r
-\r
-#ifndef _ICMP_H_\r
-#define _ICMP_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <string.h>\r
- \r
- #include "EthernetProtocols.h"\r
- #include "Ethernet.h"\r
- #include "ProtocolDecoders.h"\r
- \r
- /* Macros: */\r
- /** ICMP message type constant, indicating an ICMP ECHO Reply message */\r
- #define ICMP_TYPE_ECHOREPLY 0\r
-\r
- /** ICMP message type constant, indicating a packet destination is unreachable */\r
- #define ICMP_TYPE_DESTINATIONUNREACHABLE 3\r
- \r
- /** ICMP message type constant, indicating an ICMP Source Quench message */\r
- #define ICMP_TYPE_SOURCEQUENCH 4\r
-\r
- /** ICMP message type constant, indicating an ICMP Redirect message */\r
- #define ICMP_TYPE_REDIRECTMESSAGE 5\r
-\r
- /** ICMP message type constant, indicating an ICMP ECHO Request message */\r
- #define ICMP_TYPE_ECHOREQUEST 8\r
-\r
- /** ICMP message type constant, indicating an ICMP Time Exceeded message */\r
- #define ICMP_TYPE_TIMEEXCEEDED 11\r
- \r
- /* Type Defines: */\r
- /** Type define for an ICMP message header. */\r
- typedef struct\r
- {\r
- uint8_t Type; /**< ICMP message type, a ICMP_TYPE_* constant */\r
- uint8_t Code; /**< ICMP message code, indicating the message value */\r
- uint16_t Checksum; /**< Ethernet checksum of the ICMP message */\r
- uint16_t Id; /**< Id of the ICMP message */\r
- uint16_t Sequence; /**< Sequence number of the ICMP message, to link together message responses */\r
- } ICMP_Header_t;\r
- \r
- /* Function Prototypes: */\r
- int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart);\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Internet Protocol (IP) packet handling routines. This protocol handles IP packets from the\r
- * host which typically encapsulate other protocols such as ICMP, UDP and TCP.\r
- */\r
- \r
-#include "IP.h"\r
-\r
-/** Processes an IP packet inside an Ethernet frame, and writes the appropriate response\r
- * to the output Ethernet frame if one is created by a subprotocol handler.\r
- *\r
- * \param InDataStart Pointer to the start of the incoming packet's IP header\r
- * \param OutDataStart Pointer to the start of the outgoing packet's IP header\r
- *\r
- * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE if no\r
- * response was generated, NO_PROCESS if the packet processing was deferred until the\r
- * next Ethernet packet handler iteration\r
- */\r
-int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart)\r
-{\r
- DecodeIPHeader(InDataStart);\r
-\r
- IP_Header_t* IPHeaderIN = (IP_Header_t*)InDataStart;\r
- IP_Header_t* IPHeaderOUT = (IP_Header_t*)OutDataStart;\r
-\r
- /* Header length is specified in number of longs in the packet header, convert to bytes */\r
- uint16_t HeaderLengthBytes = (IPHeaderIN->HeaderLength * sizeof(uint32_t));\r
-\r
- int16_t RetSize = NO_RESPONSE;\r
-\r
- /* Check to ensure the IP packet is addressed to the virtual webserver's IP or the broadcast IP address */\r
- if (!(IP_COMPARE(&IPHeaderIN->DestinationAddress, &ServerIPAddress)) &&\r
- !(IP_COMPARE(&IPHeaderIN->DestinationAddress, &BroadcastIPAddress)))\r
- {\r
- return NO_RESPONSE;\r
- }\r
- \r
- /* Pass off the IP payload to the appropriate protocol processing routine */\r
- switch (IPHeaderIN->Protocol)\r
- {\r
- case PROTOCOL_ICMP:\r
- RetSize = ICMP_ProcessICMPPacket(&((uint8_t*)InDataStart)[HeaderLengthBytes],\r
- &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]);\r
- break;\r
- case PROTOCOL_TCP:\r
- RetSize = TCP_ProcessTCPPacket(InDataStart,\r
- &((uint8_t*)InDataStart)[HeaderLengthBytes],\r
- &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]); \r
- break;\r
- case PROTOCOL_UDP:\r
- RetSize = UDP_ProcessUDPPacket(InDataStart,\r
- &((uint8_t*)InDataStart)[HeaderLengthBytes],\r
- &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]); \r
- break;\r
- }\r
- \r
- /* Check to see if the protocol processing routine has filled out a response */\r
- if (RetSize > 0)\r
- {\r
- /* Fill out the response IP packet header */\r
- IPHeaderOUT->TotalLength = SwapEndian_16(sizeof(IP_Header_t) + RetSize);\r
- IPHeaderOUT->TypeOfService = 0;\r
- IPHeaderOUT->HeaderLength = (sizeof(IP_Header_t) / sizeof(uint32_t));\r
- IPHeaderOUT->Version = 4;\r
- IPHeaderOUT->Flags = 0;\r
- IPHeaderOUT->FragmentOffset = 0;\r
- IPHeaderOUT->Identification = 0;\r
- IPHeaderOUT->HeaderChecksum = 0;\r
- IPHeaderOUT->Protocol = IPHeaderIN->Protocol;\r
- IPHeaderOUT->TTL = DEFAULT_TTL;\r
- IPHeaderOUT->SourceAddress = IPHeaderIN->DestinationAddress;\r
- IPHeaderOUT->DestinationAddress = IPHeaderIN->SourceAddress;\r
- \r
- IPHeaderOUT->HeaderChecksum = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t));\r
- \r
- /* Return the size of the response so far */\r
- return (sizeof(IP_Header_t) + RetSize);\r
- }\r
- \r
- return RetSize;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for IP.c.\r
- */\r
- \r
-#ifndef _IP_H_\r
-#define _IP_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <string.h>\r
- \r
- #include "EthernetProtocols.h"\r
- #include "Ethernet.h"\r
- #include "ProtocolDecoders.h"\r
- \r
- /* Macros: */\r
- /** Protocol IP address of the host (client) machine, once assigned by DHCP */\r
- #define CLIENT_IP_ADDRESS { 10, 0, 0, 1}\r
-\r
- /** Protocol IP address of the virtual server machine */\r
- #define SERVER_IP_ADDRESS { 10, 0, 0, 2}\r
-\r
- /** Protocol IP address of the broadcast address */\r
- #define BROADCAST_IP_ADDRESS {0xFF, 0xFF, 0xFF, 0xFF}\r
-\r
- /** Default Time To Live (TTL) value for sent packets, indicating the maximum allowable hops until their destination is reached */\r
- #define DEFAULT_TTL 128\r
- \r
- /** Performs a comparison between two IP addresses, indicating if they are identical.\r
- * \r
- * \param IP1 First IP address\r
- * \param IP2 Second IP address\r
- *\r
- * \return True if the addresses match, false otherwise\r
- */\r
- #define IP_COMPARE(IP1, IP2) (memcmp(IP1, IP2, sizeof(IP_Address_t)) == 0)\r
- \r
- /* Type Defines: */\r
- /** Type define of an IP packet header. */\r
- typedef struct\r
- {\r
- unsigned char HeaderLength : 4; /**< Total length of the packet header, in 4-byte blocks */\r
- unsigned char Version : 4; /**< IP protocol version */\r
- uint8_t TypeOfService; /**< Special service type identifier, indicating delay/throughput/reliability levels */\r
- uint16_t TotalLength; /**< Total length of the IP packet, in bytes */\r
-\r
- uint16_t Identification; /**< Identification value for identifying fragmented packets */\r
- unsigned int FragmentOffset : 13; /**< Offset of this IP fragment */\r
- unsigned int Flags : 3; /**< Fragment flags, to indicate if a packet is fragmented */\r
-\r
- uint8_t TTL; /**< Maximum allowable number of hops to reach the packet destination */\r
- uint8_t Protocol; /**< Encapsulated protocol type */\r
- uint16_t HeaderChecksum; /**< Ethernet checksum of the IP header */\r
- \r
- IP_Address_t SourceAddress; /**< Source protocol IP address of the packet */\r
- IP_Address_t DestinationAddress; /**< Destination protocol IP address of the packet */\r
- } IP_Header_t;\r
- \r
- /* Function Prototypes: */\r
- int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart);\r
-\r
-#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Address Resolution Protocol (ARP) packet handling routines. This protocol handles the\r
+ * conversion of physical MAC addresses to protocol IP addresses between the host and the\r
+ * device.\r
+ */\r
+ \r
+#include "ARP.h"\r
+\r
+/** Processes an ARP packet inside an Ethernet frame, and writes the appropriate response\r
+ * to the output Ethernet frame if the host is requesting the IP or MAC address of the\r
+ * virtual server device on the network.\r
+ *\r
+ * \param InDataStart Pointer to the start of the incoming packet's ARP header\r
+ * \param OutDataStart Pointer to the start of the outgoing packet's ARP header\r
+ *\r
+ * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise\r
+ */\r
+int16_t ARP_ProcessARPPacket(void* InDataStart, void* OutDataStart)\r
+{\r
+ DecodeARPHeader(InDataStart);\r
+\r
+ ARP_Header_t* ARPHeaderIN = (ARP_Header_t*)InDataStart;\r
+ ARP_Header_t* ARPHeaderOUT = (ARP_Header_t*)OutDataStart;\r
+\r
+ /* Ensure that the ARP request is a IPv4 request packet */\r
+ if ((SwapEndian_16(ARPHeaderIN->ProtocolType) == ETHERTYPE_IPV4) &&\r
+ (SwapEndian_16(ARPHeaderIN->Operation) == ARP_OPERATION_REQUEST))\r
+ {\r
+ /* If the ARP packet is requesting the MAC or IP of the virtual webserver, return the response */\r
+ if (IP_COMPARE(&ARPHeaderIN->TPA, &ServerIPAddress) || \r
+ MAC_COMPARE(&ARPHeaderIN->THA, &ServerMACAddress))\r
+ {\r
+ /* Fill out the ARP response header */\r
+ ARPHeaderOUT->HardwareType = ARPHeaderIN->HardwareType;\r
+ ARPHeaderOUT->ProtocolType = ARPHeaderIN->ProtocolType;\r
+ ARPHeaderOUT->HLEN = ARPHeaderIN->HLEN;\r
+ ARPHeaderOUT->PLEN = ARPHeaderIN->PLEN;\r
+ ARPHeaderOUT->Operation = SwapEndian_16(ARP_OPERATION_REPLY);\r
+\r
+ /* Copy over the sender MAC/IP to the target fields for the response */\r
+ ARPHeaderOUT->THA = ARPHeaderIN->SHA;\r
+ ARPHeaderOUT->TPA = ARPHeaderIN->SPA;\r
+\r
+ /* Copy over the new sender MAC/IP - MAC and IP addresses of the virtual webserver */\r
+ ARPHeaderOUT->SHA = ServerMACAddress;\r
+ ARPHeaderOUT->SPA = ServerIPAddress;\r
+\r
+ /* Return the size of the response so far */\r
+ return sizeof(ARP_Header_t);\r
+ }\r
+ }\r
+ \r
+ return NO_RESPONSE;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for ARP.c.\r
+ */\r
+ \r
+#ifndef _ARP_H_\r
+#define _ARP_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <string.h>\r
+ \r
+ #include <LUFA/Scheduler/Scheduler.h>\r
+ \r
+ #include "EthernetProtocols.h"\r
+ #include "Ethernet.h"\r
+ #include "ProtocolDecoders.h"\r
+ \r
+ /* Macros: */\r
+ /** ARP header operation constant, indicating a request from a host for an address translation */\r
+ #define ARP_OPERATION_REQUEST 1\r
+\r
+ /** ARP header operation constant, indicating a reply from a host giving an address translation */\r
+ #define ARP_OPERATION_REPLY 2\r
+\r
+ /* Type Defines: */\r
+ /** Type define for an ARP packet inside an Ethernet frame. */\r
+ typedef struct\r
+ {\r
+ uint16_t HardwareType; /**< Hardware type constant, indicating the hardware used */\r
+ uint16_t ProtocolType; /**< Protocol being resolved, usually ETHERTYPE_IPV4 */\r
+ \r
+ uint8_t HLEN; /**< Length in bytes of the source/destination hardware addresses */\r
+ uint8_t PLEN; /**< Length in bytes of the source/destination protocol addresses */\r
+ uint16_t Operation; /**< Type of operation, either ARP_OPERATION_REQUEST or ARP_OPERATION_REPLY */\r
+ \r
+ MAC_Address_t SHA; /**< Sender's hardware address */\r
+ IP_Address_t SPA; /**< Sender's protocol address */\r
+ MAC_Address_t THA; /**< Target's hardware address */\r
+ IP_Address_t TPA; /**< Target's protocol address */\r
+ } ARP_Header_t;\r
+ \r
+ /* Function Prototypes: */\r
+ int16_t ARP_ProcessARPPacket(void* InDataStart, void* OutDataStart);\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Dynamic Host Configuration Protocol (DHCP) packet handling routines. This protocol\r
+ * handles the automatic IP negotiation to the host, so that the host will use the provided\r
+ * IP address given to it by the device.\r
+ */\r
+ \r
+#include "DHCP.h"\r
+\r
+/** Processes a DHCP packet inside an Ethernet frame, and writes the appropriate response\r
+ * to the output Ethernet frame if the host is requesting or accepting an IP address.\r
+ *\r
+ * \param IPHeaderInStart Pointer to the start of the incoming packet's IP header\r
+ * \param DHCPHeaderInStart Pointer to the start of the incoming packet's DHCP header\r
+ * \param DHCPHeaderOutStart Pointer to the start of the outgoing packet's DHCP header\r
+ *\r
+ * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise\r
+ */\r
+int16_t DHCP_ProcessDHCPPacket(void* IPHeaderInStart, void* DHCPHeaderInStart, void* DHCPHeaderOutStart)\r
+{\r
+ IP_Header_t* IPHeaderIN = (IP_Header_t*)IPHeaderInStart;\r
+ DHCP_Header_t* DHCPHeaderIN = (DHCP_Header_t*)DHCPHeaderInStart;\r
+ DHCP_Header_t* DHCPHeaderOUT = (DHCP_Header_t*)DHCPHeaderOutStart;\r
+ \r
+ uint8_t* DHCPOptionsINStart = (uint8_t*)(DHCPHeaderInStart + sizeof(DHCP_Header_t));\r
+ uint8_t* DHCPOptionsOUTStart = (uint8_t*)(DHCPHeaderOutStart + sizeof(DHCP_Header_t));\r
+\r
+ DecodeDHCPHeader(DHCPHeaderInStart);\r
+\r
+ /* Zero out the response DHCP packet, as much of it legacy and left at 0 */\r
+ memset(DHCPHeaderOUT, 0, sizeof(DHCP_Header_t));\r
+\r
+ /* Fill out the response DHCP packet */\r
+ DHCPHeaderOUT->HardwareType = DHCPHeaderIN->HardwareType;\r
+ DHCPHeaderOUT->Operation = DHCP_OP_BOOTREPLY;\r
+ DHCPHeaderOUT->HardwareAddressLength = DHCPHeaderIN->HardwareAddressLength;\r
+ DHCPHeaderOUT->Hops = 0;\r
+ DHCPHeaderOUT->TransactionID = DHCPHeaderIN->TransactionID;\r
+ DHCPHeaderOUT->ElapsedSeconds = 0;\r
+ DHCPHeaderOUT->Flags = DHCPHeaderIN->Flags;\r
+ DHCPHeaderOUT->YourIP = ClientIPAddress;\r
+ memcpy(&DHCPHeaderOUT->ClientHardwareAddress, &DHCPHeaderIN->ClientHardwareAddress, sizeof(MAC_Address_t));\r
+ DHCPHeaderOUT->Cookie = SwapEndian_32(DHCP_MAGIC_COOKIE);\r
+ \r
+ /* Alter the incoming IP packet header so that the corrected IP source and destinations are used - this means that\r
+ when the response IP header is generated, it will use the corrected addresses and not the null/broatcast addresses */\r
+ IPHeaderIN->SourceAddress = ClientIPAddress;\r
+ IPHeaderIN->DestinationAddress = ServerIPAddress;\r
+\r
+ /* Process the incoming DHCP packet options */\r
+ while (DHCPOptionsINStart[0] != DHCP_OPTION_END)\r
+ { \r
+ /* Find the Message Type DHCP option, to determine the type of DHCP packet */\r
+ if (DHCPOptionsINStart[0] == DHCP_OPTION_MESSAGETYPE)\r
+ {\r
+ if ((DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_DISCOVER) || (DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_REQUEST))\r
+ {\r
+ /* Fill out the response DHCP packet options for a DHCP OFFER or ACK response */\r
+\r
+ *(DHCPOptionsOUTStart++) = DHCP_OPTION_MESSAGETYPE;\r
+ *(DHCPOptionsOUTStart++) = 1;\r
+ *(DHCPOptionsOUTStart++) = (DHCPOptionsINStart[2] == DHCP_MESSAGETYPE_DISCOVER) ? DHCP_MESSAGETYPE_OFFER\r
+ : DHCP_MESSAGETYPE_ACK;\r
+\r
+ *(DHCPOptionsOUTStart++) = DHCP_OPTION_SUBNETMASK;\r
+ *(DHCPOptionsOUTStart++) = 4;\r
+ *(DHCPOptionsOUTStart++) = 0xFF;\r
+ *(DHCPOptionsOUTStart++) = 0xFF;\r
+ *(DHCPOptionsOUTStart++) = 0xFF;\r
+ *(DHCPOptionsOUTStart++) = 0x00;\r
+\r
+ *(DHCPOptionsOUTStart++) = DHCP_OPTION_DHCPSERVER;\r
+ *(DHCPOptionsOUTStart++) = sizeof(IP_Address_t);\r
+ memcpy(DHCPOptionsOUTStart, &ServerIPAddress, sizeof(IP_Address_t));\r
+ DHCPOptionsOUTStart += sizeof(IP_Address_t);\r
+\r
+ *(DHCPOptionsOUTStart++) = DHCP_OPTION_END;\r
+ \r
+ return (sizeof(DHCP_Header_t) + 12 + sizeof(IP_Address_t));\r
+ }\r
+ }\r
+ \r
+ /* Go to the next DHCP option - skip one byte if option is a padding byte, else skip the complete option's size */\r
+ DHCPOptionsINStart += ((DHCPOptionsINStart[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptionsINStart[1] + 2));\r
+ }\r
+ \r
+ return NO_RESPONSE;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for DHCP.c.\r
+ */\r
+ \r
+#ifndef _DHCP_H_\r
+#define _DHCP_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <string.h>\r
+ \r
+ #include "EthernetProtocols.h"\r
+ #include "Ethernet.h"\r
+ #include "ProtocolDecoders.h"\r
+\r
+ /* Macros: */\r
+ /** DHCP operation constant, indicating a request from a host to a DHCP server */\r
+ #define DHCP_OP_BOOTREQUEST 0x01\r
+\r
+ /** DHCP operation constant, indicating a reply from a DHCP server to a host */\r
+ #define DHCP_OP_BOOTREPLY 0x02\r
+ \r
+ /** Hardware type constant, indicating Ethernet as a carrier */\r
+ #define DHCP_HTYPE_ETHERNET 0x01\r
+ \r
+ /** Magic boot protocol "cookie", inserted into all BOOTP packets (BOOTP is the carrier of DHCP) */\r
+ #define DHCP_MAGIC_COOKIE 0x63825363\r
+ \r
+ /** DHCP option list entry header, indicating that a subnet mask will follow */\r
+ #define DHCP_OPTION_SUBNETMASK 1\r
+\r
+ /** DHCP option list entry header, indicating that the DHCP message type constant will follow */\r
+ #define DHCP_OPTION_MESSAGETYPE 53\r
+\r
+ /** DHCP option list entry header, indicating that the IP address of the DHCP server will follow */\r
+ #define DHCP_OPTION_DHCPSERVER 54\r
+\r
+ /** DHCP option list entry header, used to pad out option data */\r
+ #define DHCP_OPTION_PAD 0\r
+\r
+ /** DHCP option list entry header, indicating the end of option data */\r
+ #define DHCP_OPTION_END 255\r
+ \r
+ /** Message type constant, used in the DHCP option data field, requesting that a DHCP server offer an IP address */\r
+ #define DHCP_MESSAGETYPE_DISCOVER 1\r
+\r
+ /** Message type constant, used in the DHCP option data field, indicating that a DHCP server is offering an IP address */\r
+ #define DHCP_MESSAGETYPE_OFFER 2\r
+\r
+ /** Message type constant, used in the DHCP option data field, requesting that a DHCP server lease a given IP address */\r
+ #define DHCP_MESSAGETYPE_REQUEST 3\r
+\r
+ /** Message type constant, used in the DHCP option data field, declining an offered DHCP server IP address lease */\r
+ #define DHCP_MESSAGETYPE_DECLINE 4\r
+\r
+ /** Message type constant, used in the DHCP option data field, ACKing a host IP lease request */\r
+ #define DHCP_MESSAGETYPE_ACK 5\r
+\r
+ /** Message type constant, used in the DHCP option data field, NACKing a host IP lease request */\r
+ #define DHCP_MESSAGETYPE_NACK 6\r
+\r
+ /** Message type constant, used in the DHCP option data field, indicating that a host is releasing a leased IP address */\r
+ #define DHCP_MESSAGETYPE_RELEASE 7\r
+\r
+ /* Type Defines: */\r
+ /** Type define for a DHCP packet inside an Ethernet frame. */\r
+ typedef struct\r
+ {\r
+ uint8_t Operation; /**< DHCP operation, either DHCP_OP_BOOTREQUEST or DHCP_OP_BOOTREPLY */\r
+ uint8_t HardwareType; /**< Hardware carrier type constant */\r
+ uint8_t HardwareAddressLength; /**< Length in bytes of a hardware (MAC) address on the network */\r
+ uint8_t Hops; /**< Number of hops required to reach the server, unused */\r
+\r
+ uint32_t TransactionID; /**< Unique ID of the DHCP packet, for positive matching between sent and received packets */\r
+\r
+ uint16_t ElapsedSeconds; /**< Elapsed seconds since the request was made */\r
+ uint16_t Flags; /**< BOOTP packet flags */\r
+ \r
+ IP_Address_t ClientIP; /**< Client IP address, if already leased an IP */\r
+ IP_Address_t YourIP; /**< Client IP address */\r
+ IP_Address_t NextServerIP; /**< Legacy BOOTP protocol field, unused for DHCP */\r
+ IP_Address_t RelayAgentIP; /**< Legacy BOOTP protocol field, unused for DHCP */\r
+ \r
+ uint8_t ClientHardwareAddress[16]; /**< Hardware (MAC) address of the client making a request to the DHCP server */\r
+ uint8_t ServerHostnameString[64]; /**< Legacy BOOTP protocol field, unused for DHCP */\r
+ uint8_t BootFileName[128]; /**< Legacy BOOTP protocol field, unused for DHCP */\r
+ \r
+ uint32_t Cookie; /**< Magic BOOTP protocol cookie to indicate a valid packet */\r
+ } DHCP_Header_t;\r
+\r
+ /* Function Prototypes: */\r
+ int16_t DHCP_ProcessDHCPPacket(void* IPHeaderInStart, void* DHCPHeaderInStart, void* DHCPHeaderOutStart);\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Ethernet frame packet handling routines. This protocol handles the processing of raw Ethernet\r
+ * frames sent and received, deferring the processing of subpacket protocols to the appropriate\r
+ * protocol handlers, such as DHCP or ARP.\r
+ */\r
+ \r
+#include "Ethernet.h"\r
+\r
+/* Global Variables: */\r
+/** Ethernet Frame buffer structure, to hold the incoming Ethernet frame from the host. */\r
+Ethernet_Frame_Info_t FrameIN;\r
+\r
+/** Ethernet Frame buffer structure, to hold the outgoing Ethernet frame to the host. */\r
+Ethernet_Frame_Info_t FrameOUT;\r
+\r
+/** Constant for convenience when checking against or setting a MAC address to the virtual server MAC address. */\r
+const MAC_Address_t ServerMACAddress = {SERVER_MAC_ADDRESS};\r
+\r
+/** Constant for convenience when checking against or setting an IP address to the virtual server IP address. */\r
+const IP_Address_t ServerIPAddress = {SERVER_IP_ADDRESS};\r
+\r
+/** Constant for convenience when checking against or setting a MAC address to the broadcast MAC address. */\r
+const MAC_Address_t BroadcastMACAddress = {BROADCAST_MAC_ADDRESS};\r
+\r
+/** Constant for convenience when checking against or setting a IP address to the broadcast IP address. */\r
+const IP_Address_t BroadcastIPAddress = {BROADCAST_IP_ADDRESS};\r
+\r
+/** Constant for convenience when checking against or setting an IP address to the client (host) IP address. */\r
+const IP_Address_t ClientIPAddress = {CLIENT_IP_ADDRESS};\r
+\r
+\r
+/** Processes an incoming Ethernet frame, and writes the appropriate response to the output Ethernet\r
+ * frame buffer if the sub protocol handlers create a valid response.\r
+ */\r
+void Ethernet_ProcessPacket(void)\r
+{\r
+ DecodeEthernetFrameHeader(FrameIN.FrameData);\r
+\r
+ /* Cast the incoming Ethernet frame to the Ethernet header type */\r
+ Ethernet_Frame_Header_t* FrameINHeader = (Ethernet_Frame_Header_t*)&FrameIN.FrameData;\r
+ Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData;\r
+ \r
+ int16_t RetSize = NO_RESPONSE;\r
+ \r
+ /* Ensure frame is addressed to either all (broadcast) or the virtual webserver, and is a type II frame */\r
+ if ((MAC_COMPARE(&FrameINHeader->Destination, &ServerMACAddress) ||\r
+ MAC_COMPARE(&FrameINHeader->Destination, &BroadcastMACAddress)) &&\r
+ (SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE))\r
+ {\r
+ /* Process the packet depending on its protocol */\r
+ switch (SwapEndian_16(FrameINHeader->EtherType))\r
+ {\r
+ case ETHERTYPE_ARP:\r
+ RetSize = ARP_ProcessARPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],\r
+ &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);\r
+ break; \r
+ case ETHERTYPE_IPV4:\r
+ RetSize = IP_ProcessIPPacket(&FrameIN.FrameData[sizeof(Ethernet_Frame_Header_t)],\r
+ &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)]);\r
+ break;\r
+ }\r
+ \r
+ /* Protocol processing routine has filled a response, complete the ethernet frame header */\r
+ if (RetSize > 0)\r
+ {\r
+ /* Fill out the response Ethernet frame header */\r
+ FrameOUTHeader->Source = ServerMACAddress;\r
+ FrameOUTHeader->Destination = FrameINHeader->Source;\r
+ FrameOUTHeader->EtherType = FrameINHeader->EtherType;\r
+ \r
+ /* Set the response length in the buffer and indicate that a response is ready to be sent */\r
+ FrameOUT.FrameLength = (sizeof(Ethernet_Frame_Header_t) + RetSize);\r
+ FrameOUT.FrameInBuffer = true;\r
+ }\r
+ }\r
+\r
+ /* Check if the packet was processed */\r
+ if (RetSize != NO_PROCESS)\r
+ {\r
+ /* Clear the frame buffer */\r
+ FrameIN.FrameInBuffer = false;\r
+ }\r
+}\r
+\r
+/** Calculates the appropriate ethernet checksum, consisting of the addition of the one's\r
+ * compliment of each word, complimented.\r
+ *\r
+ * \param Data Pointer to the packet buffer data whose checksum must be calculated\r
+ * \param Bytes Number of bytes in the data buffer to process\r
+ *\r
+ * \return A 16-bit Ethernet checksum value\r
+ */\r
+uint16_t Ethernet_Checksum16(void* Data, uint16_t Bytes)\r
+{\r
+ uint16_t* Words = (uint16_t*)Data;\r
+ uint32_t Checksum = 0;\r
+\r
+ for (uint8_t CurrWord = 0; CurrWord < (Bytes >> 1); CurrWord++)\r
+ Checksum += Words[CurrWord];\r
+ \r
+ while (Checksum & 0xFFFF0000)\r
+ Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16));\r
+ \r
+ return ~Checksum;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for Ethernet.c.\r
+ */\r
+ \r
+#ifndef _ETHERNET_H_\r
+#define _ETHERNET_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <string.h>\r
+\r
+ #include "EthernetProtocols.h"\r
+ #include "ProtocolDecoders.h"\r
+ #include "ICMP.h"\r
+ #include "TCP.h"\r
+ #include "UDP.h"\r
+ #include "DHCP.h"\r
+ #include "ARP.h"\r
+ #include "IP.h"\r
+ \r
+ /* Macros: */\r
+ /** Physical MAC address of the virtual server on the network */\r
+ #define SERVER_MAC_ADDRESS {0x00, 0x01, 0x00, 0x01, 0x00, 0x01} \r
+\r
+ /** Physical MAC address of the network broadcast address */\r
+ #define BROADCAST_MAC_ADDRESS {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}\r
+ \r
+ /** Performs a comparison between two MAC addresses, indicating if they are identical.\r
+ * \r
+ * \param MAC1 First MAC address\r
+ * \param MAC2 Second MAC address\r
+ *\r
+ * \return True if the addresses match, false otherwise\r
+ */\r
+ #define MAC_COMPARE(MAC1, MAC2) (memcmp(MAC1, MAC2, sizeof(MAC_Address_t)) == 0)\r
+\r
+ /** Maximum size of an incoming or outgoing Ethernet frame in bytes */\r
+ #define ETHERNET_FRAME_SIZE_MAX 1500\r
+ \r
+ /** Minimum size of an Ethernet packet in bytes, to conform to the Ethernet V2 packet standard */\r
+ #define ETHERNET_VER2_MINSIZE 0x0600\r
+ \r
+ /** Return value for all sub protocol handling routines, indicating that no response packet has been generated */\r
+ #define NO_RESPONSE 0 \r
+\r
+ /** Return value for all sub protocol handling routines, indicating that the packet has not yet been handled */\r
+ #define NO_PROCESS -1\r
+\r
+ /* Type Defines: */\r
+ /** Type define for an Ethernet frame buffer. */\r
+ typedef struct\r
+ {\r
+ uint8_t FrameData[ETHERNET_FRAME_SIZE_MAX]; /**< Ethernet frame contents */\r
+ uint16_t FrameLength; /**< Length in bytes of the Ethernet frame stored in the buffer */\r
+ bool FrameInBuffer; /**< Indicates if a frame is currently stored in the buffer */\r
+ } Ethernet_Frame_Info_t;\r
+\r
+ /** Type define for an Ethernet frame header */\r
+ typedef struct\r
+ {\r
+ MAC_Address_t Destination; /**< Physical MAC address of the packet recipient */\r
+ MAC_Address_t Source; /**< Physics MAC address of the packet source */\r
+ \r
+ union\r
+ {\r
+ uint16_t EtherType; /**< Ethernet packet subprotocol type, for Ethernet V2 packets */\r
+ uint16_t Length; /**< Ethernet frame length, for Ethernet V1 packets */\r
+ };\r
+ } Ethernet_Frame_Header_t;\r
+ \r
+ /* External Variables: */\r
+ extern Ethernet_Frame_Info_t FrameIN;\r
+ extern Ethernet_Frame_Info_t FrameOUT;\r
+\r
+ extern const MAC_Address_t ServerMACAddress;\r
+ extern const IP_Address_t ServerIPAddress;\r
+ extern const MAC_Address_t BroadcastMACAddress;\r
+ extern const IP_Address_t BroadcastIPAddress;\r
+ extern const IP_Address_t ClientIPAddress;\r
+ \r
+ /* Function Prototypes: */\r
+ void Ethernet_ProcessPacket(void);\r
+ uint16_t Ethernet_Checksum16(void* Data, uint16_t Bytes);\r
+ \r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * General Ethernet protocol constants and type defines, for use by\r
+ * all network protocol portions of the TCP/IP stack.\r
+ */\r
+\r
+#ifndef _ETHERNET_PROTOCOLS_H_\r
+#define _ETHERNET_PROTOCOLS_H_\r
+\r
+ /* Macros: */\r
+ #define ETHERTYPE_IPV4 0x0800\r
+ #define ETHERTYPE_ARP 0x0806\r
+ #define ETHERTYPE_RARP 0x8035\r
+ #define ETHERTYPE_APPLETALK 0x809b\r
+ #define ETHERTYPE_APPLETALKARP 0x80f3\r
+ #define ETHERTYPE_IEEE8021Q 0x8100\r
+ #define ETHERTYPE_NOVELLIPX 0x8137\r
+ #define ETHERTYPE_NOVELL 0x8138\r
+ #define ETHERTYPE_IPV6 0x86DD\r
+ #define ETHERTYPE_COBRANET 0x8819\r
+ #define ETHERTYPE_PROVIDERBRIDGING 0x88a8\r
+ #define ETHERTYPE_MPLSUNICAST 0x8847\r
+ #define ETHERTYPE_MPLSMULTICAST 0x8848\r
+ #define ETHERTYPE_PPPoEDISCOVERY 0x8863\r
+ #define ETHERTYPE_PPPoESESSION 0x8864\r
+ #define ETHERTYPE_EAPOVERLAN 0x888E\r
+ #define ETHERTYPE_HYPERSCSI 0x889A\r
+ #define ETHERTYPE_ATAOVERETHERNET 0x88A2\r
+ #define ETHERTYPE_ETHERCAT 0x88A4\r
+ #define ETHERTYPE_SERCOSIII 0x88CD\r
+ #define ETHERTYPE_CESoE 0x88D8\r
+ #define ETHERTYPE_MACSECURITY 0x88E5\r
+ #define ETHERTYPE_FIBRECHANNEL 0x8906\r
+ #define ETHERTYPE_QINQ 0x9100\r
+ #define ETHERTYPE_VLLT 0xCAFE\r
+ \r
+ #define PROTOCOL_ICMP 1\r
+ #define PROTOCOL_IGMP 2\r
+ #define PROTOCOL_TCP 6\r
+ #define PROTOCOL_UDP 17\r
+ #define PROTOCOL_OSPF 89\r
+ #define PROTOCOL_SCTP 132\r
+\r
+ /* Type Defines: */\r
+ /** Type define for a physical MAC address of a device on a network */\r
+ typedef struct\r
+ {\r
+ uint8_t Octets[6]; /**< Individual bytes of a MAC address */\r
+ } MAC_Address_t;\r
+ \r
+ /** Type define for a protocol IP address of a device on a network */\r
+ typedef struct\r
+ {\r
+ uint8_t Octets[4]; /**< Individual bytes of an IP address */\r
+ } IP_Address_t;\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Internet Control Message Protocol (ICMP) packet handling routines. This protocol handles\r
+ * Echo requests from the host, to indicate a successful network connection between the host\r
+ * and the virtual server.\r
+ */\r
+ \r
+#include "ICMP.h"\r
+\r
+/** Processes an ICMP packet inside an Ethernet frame, and writes the appropriate response\r
+ * to the output Ethernet frame if the host is issuing a ICMP ECHO request.\r
+ *\r
+ * \param InDataStart Pointer to the start of the incoming packet's ICMP header\r
+ * \param OutDataStart Pointer to the start of the outgoing packet's ICMP header\r
+ *\r
+ * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise\r
+ */\r
+int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart)\r
+{\r
+ ICMP_Header_t* ICMPHeaderIN = (ICMP_Header_t*)InDataStart;\r
+ ICMP_Header_t* ICMPHeaderOUT = (ICMP_Header_t*)OutDataStart;\r
+\r
+ DecodeICMPHeader(InDataStart);\r
+\r
+ /* Determine if the ICMP packet is an echo request (ping) */\r
+ if (ICMPHeaderIN->Type == ICMP_TYPE_ECHOREQUEST)\r
+ {\r
+ /* Fill out the ICMP response packet */\r
+ ICMPHeaderOUT->Type = ICMP_TYPE_ECHOREPLY;\r
+ ICMPHeaderOUT->Code = 0;\r
+ ICMPHeaderOUT->Checksum = 0;\r
+ ICMPHeaderOUT->Id = ICMPHeaderIN->Id;\r
+ ICMPHeaderOUT->Sequence = ICMPHeaderIN->Sequence;\r
+ \r
+ uint16_t DataSize = FrameIN.FrameLength - ((((uint16_t)InDataStart + sizeof(ICMP_Header_t)) - (uint16_t)FrameIN.FrameData));\r
+ \r
+ /* Copy the remaining payload to the response - echo requests should echo back any sent data */\r
+ memcpy(&((uint8_t*)OutDataStart)[sizeof(ICMP_Header_t)],\r
+ &((uint8_t*)InDataStart)[sizeof(ICMP_Header_t)],\r
+ DataSize);\r
+\r
+ ICMPHeaderOUT->Checksum = Ethernet_Checksum16(ICMPHeaderOUT, (DataSize + sizeof(ICMP_Header_t)));\r
+\r
+ /* Return the size of the response so far */\r
+ return (DataSize + sizeof(ICMP_Header_t));\r
+ }\r
+ \r
+ return NO_RESPONSE;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for ICMP.c.\r
+ */\r
+\r
+#ifndef _ICMP_H_\r
+#define _ICMP_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <string.h>\r
+ \r
+ #include "EthernetProtocols.h"\r
+ #include "Ethernet.h"\r
+ #include "ProtocolDecoders.h"\r
+ \r
+ /* Macros: */\r
+ /** ICMP message type constant, indicating an ICMP ECHO Reply message */\r
+ #define ICMP_TYPE_ECHOREPLY 0\r
+\r
+ /** ICMP message type constant, indicating a packet destination is unreachable */\r
+ #define ICMP_TYPE_DESTINATIONUNREACHABLE 3\r
+ \r
+ /** ICMP message type constant, indicating an ICMP Source Quench message */\r
+ #define ICMP_TYPE_SOURCEQUENCH 4\r
+\r
+ /** ICMP message type constant, indicating an ICMP Redirect message */\r
+ #define ICMP_TYPE_REDIRECTMESSAGE 5\r
+\r
+ /** ICMP message type constant, indicating an ICMP ECHO Request message */\r
+ #define ICMP_TYPE_ECHOREQUEST 8\r
+\r
+ /** ICMP message type constant, indicating an ICMP Time Exceeded message */\r
+ #define ICMP_TYPE_TIMEEXCEEDED 11\r
+ \r
+ /* Type Defines: */\r
+ /** Type define for an ICMP message header. */\r
+ typedef struct\r
+ {\r
+ uint8_t Type; /**< ICMP message type, a ICMP_TYPE_* constant */\r
+ uint8_t Code; /**< ICMP message code, indicating the message value */\r
+ uint16_t Checksum; /**< Ethernet checksum of the ICMP message */\r
+ uint16_t Id; /**< Id of the ICMP message */\r
+ uint16_t Sequence; /**< Sequence number of the ICMP message, to link together message responses */\r
+ } ICMP_Header_t;\r
+ \r
+ /* Function Prototypes: */\r
+ int16_t ICMP_ProcessICMPPacket(void* InDataStart, void* OutDataStart);\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Internet Protocol (IP) packet handling routines. This protocol handles IP packets from the\r
+ * host which typically encapsulate other protocols such as ICMP, UDP and TCP.\r
+ */\r
+ \r
+#include "IP.h"\r
+\r
+/** Processes an IP packet inside an Ethernet frame, and writes the appropriate response\r
+ * to the output Ethernet frame if one is created by a subprotocol handler.\r
+ *\r
+ * \param InDataStart Pointer to the start of the incoming packet's IP header\r
+ * \param OutDataStart Pointer to the start of the outgoing packet's IP header\r
+ *\r
+ * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE if no\r
+ * response was generated, NO_PROCESS if the packet processing was deferred until the\r
+ * next Ethernet packet handler iteration\r
+ */\r
+int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart)\r
+{\r
+ DecodeIPHeader(InDataStart);\r
+\r
+ IP_Header_t* IPHeaderIN = (IP_Header_t*)InDataStart;\r
+ IP_Header_t* IPHeaderOUT = (IP_Header_t*)OutDataStart;\r
+\r
+ /* Header length is specified in number of longs in the packet header, convert to bytes */\r
+ uint16_t HeaderLengthBytes = (IPHeaderIN->HeaderLength * sizeof(uint32_t));\r
+\r
+ int16_t RetSize = NO_RESPONSE;\r
+\r
+ /* Check to ensure the IP packet is addressed to the virtual webserver's IP or the broadcast IP address */\r
+ if (!(IP_COMPARE(&IPHeaderIN->DestinationAddress, &ServerIPAddress)) &&\r
+ !(IP_COMPARE(&IPHeaderIN->DestinationAddress, &BroadcastIPAddress)))\r
+ {\r
+ return NO_RESPONSE;\r
+ }\r
+ \r
+ /* Pass off the IP payload to the appropriate protocol processing routine */\r
+ switch (IPHeaderIN->Protocol)\r
+ {\r
+ case PROTOCOL_ICMP:\r
+ RetSize = ICMP_ProcessICMPPacket(&((uint8_t*)InDataStart)[HeaderLengthBytes],\r
+ &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]);\r
+ break;\r
+ case PROTOCOL_TCP:\r
+ RetSize = TCP_ProcessTCPPacket(InDataStart,\r
+ &((uint8_t*)InDataStart)[HeaderLengthBytes],\r
+ &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]); \r
+ break;\r
+ case PROTOCOL_UDP:\r
+ RetSize = UDP_ProcessUDPPacket(InDataStart,\r
+ &((uint8_t*)InDataStart)[HeaderLengthBytes],\r
+ &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]); \r
+ break;\r
+ }\r
+ \r
+ /* Check to see if the protocol processing routine has filled out a response */\r
+ if (RetSize > 0)\r
+ {\r
+ /* Fill out the response IP packet header */\r
+ IPHeaderOUT->TotalLength = SwapEndian_16(sizeof(IP_Header_t) + RetSize);\r
+ IPHeaderOUT->TypeOfService = 0;\r
+ IPHeaderOUT->HeaderLength = (sizeof(IP_Header_t) / sizeof(uint32_t));\r
+ IPHeaderOUT->Version = 4;\r
+ IPHeaderOUT->Flags = 0;\r
+ IPHeaderOUT->FragmentOffset = 0;\r
+ IPHeaderOUT->Identification = 0;\r
+ IPHeaderOUT->HeaderChecksum = 0;\r
+ IPHeaderOUT->Protocol = IPHeaderIN->Protocol;\r
+ IPHeaderOUT->TTL = DEFAULT_TTL;\r
+ IPHeaderOUT->SourceAddress = IPHeaderIN->DestinationAddress;\r
+ IPHeaderOUT->DestinationAddress = IPHeaderIN->SourceAddress;\r
+ \r
+ IPHeaderOUT->HeaderChecksum = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t));\r
+ \r
+ /* Return the size of the response so far */\r
+ return (sizeof(IP_Header_t) + RetSize);\r
+ }\r
+ \r
+ return RetSize;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for IP.c.\r
+ */\r
+ \r
+#ifndef _IP_H_\r
+#define _IP_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <string.h>\r
+ \r
+ #include "EthernetProtocols.h"\r
+ #include "Ethernet.h"\r
+ #include "ProtocolDecoders.h"\r
+ \r
+ /* Macros: */\r
+ /** Protocol IP address of the host (client) machine, once assigned by DHCP */\r
+ #define CLIENT_IP_ADDRESS { 10, 0, 0, 1}\r
+\r
+ /** Protocol IP address of the virtual server machine */\r
+ #define SERVER_IP_ADDRESS { 10, 0, 0, 2}\r
+\r
+ /** Protocol IP address of the broadcast address */\r
+ #define BROADCAST_IP_ADDRESS {0xFF, 0xFF, 0xFF, 0xFF}\r
+\r
+ /** Default Time To Live (TTL) value for sent packets, indicating the maximum allowable hops until their destination is reached */\r
+ #define DEFAULT_TTL 128\r
+ \r
+ /** Performs a comparison between two IP addresses, indicating if they are identical.\r
+ * \r
+ * \param IP1 First IP address\r
+ * \param IP2 Second IP address\r
+ *\r
+ * \return True if the addresses match, false otherwise\r
+ */\r
+ #define IP_COMPARE(IP1, IP2) (memcmp(IP1, IP2, sizeof(IP_Address_t)) == 0)\r
+ \r
+ /* Type Defines: */\r
+ /** Type define of an IP packet header. */\r
+ typedef struct\r
+ {\r
+ unsigned char HeaderLength : 4; /**< Total length of the packet header, in 4-byte blocks */\r
+ unsigned char Version : 4; /**< IP protocol version */\r
+ uint8_t TypeOfService; /**< Special service type identifier, indicating delay/throughput/reliability levels */\r
+ uint16_t TotalLength; /**< Total length of the IP packet, in bytes */\r
+\r
+ uint16_t Identification; /**< Identification value for identifying fragmented packets */\r
+ unsigned int FragmentOffset : 13; /**< Offset of this IP fragment */\r
+ unsigned int Flags : 3; /**< Fragment flags, to indicate if a packet is fragmented */\r
+\r
+ uint8_t TTL; /**< Maximum allowable number of hops to reach the packet destination */\r
+ uint8_t Protocol; /**< Encapsulated protocol type */\r
+ uint16_t HeaderChecksum; /**< Ethernet checksum of the IP header */\r
+ \r
+ IP_Address_t SourceAddress; /**< Source protocol IP address of the packet */\r
+ IP_Address_t DestinationAddress; /**< Destination protocol IP address of the packet */\r
+ } IP_Header_t;\r
+ \r
+ /* Function Prototypes: */\r
+ int16_t IP_ProcessIPPacket(void* InDataStart, void* OutDataStart);\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/* Protocol decoders for Ethernet, TCP, IP, ICMP and ARP. Each of these routines\r
+ accepts a header to the appropriate protocol and prints out pertinent information\r
+ on the packet through the serial port.\r
+ \r
+ To disable printing of a specific protocol, define the token NO_DECODE_{Protocol}\r
+ in the project makefile, and pass it to the compiler using the -D switch.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Protocol decoding routines, for the plain-text decoding of Ethernet frames for debugging purposes.\r
+ * Enabled protocol decoders will print incoming Ethernet frame contents through the USART in a human\r
+ * readable format.\r
+ *\r
+ * Note that the USART is a slow transmission medium, and will slow down packet processing considerably.\r
+ * Packet decoding routines can be disabled by defining NO_DECODE_{Protocol Name} in the project makefile\r
+ * and passing it to the compiler via the -D switch.\r
+ */\r
+ \r
+#include "ProtocolDecoders.h"\r
+\r
+/** Decodes an Ethernet frame header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of an Ethernet frame header\r
+ */\r
+void DecodeEthernetFrameHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_ETHERNET)\r
+ Ethernet_Frame_Header_t* FrameHeader = (Ethernet_Frame_Header_t*)InDataStart;\r
+ \r
+ printf_P(PSTR("\r\n"));\r
+ \r
+ printf_P(PSTR(" ETHERNET\r\n"));\r
+ printf_P(PSTR(" + Frame Size: %u\r\n"), FrameIN.FrameLength);\r
+\r
+ if (!(MAC_COMPARE(&FrameHeader->Destination, &ServerMACAddress)) &&\r
+ !(MAC_COMPARE(&FrameHeader->Destination, &BroadcastMACAddress)))\r
+ {\r
+ printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n"));\r
+ return;\r
+ }\r
+\r
+ printf_P(PSTR(" + MAC Source : %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader->Source.Octets[0],\r
+ FrameHeader->Source.Octets[1],\r
+ FrameHeader->Source.Octets[2],\r
+ FrameHeader->Source.Octets[3],\r
+ FrameHeader->Source.Octets[4],\r
+ FrameHeader->Source.Octets[5]);\r
+\r
+ printf_P(PSTR(" + MAC Dest: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader->Destination.Octets[0],\r
+ FrameHeader->Destination.Octets[1],\r
+ FrameHeader->Destination.Octets[2],\r
+ FrameHeader->Destination.Octets[3],\r
+ FrameHeader->Destination.Octets[4],\r
+ FrameHeader->Destination.Octets[5]);\r
+\r
+ if (SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE)\r
+ printf_P(PSTR(" + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader->EtherType));\r
+ else\r
+ printf_P(PSTR(" + Protocol: UNKNOWN E1\r\n"));\r
+ #endif\r
+}\r
+\r
+/** Decodes an ARP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of an ARP packet header\r
+ */\r
+void DecodeARPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_ARP)\r
+ ARP_Header_t* ARPHeader = (ARP_Header_t*)InDataStart; \r
+\r
+ printf_P(PSTR(" \\\r\n ARP\r\n"));\r
+\r
+ if (!(IP_COMPARE(&ARPHeader->TPA, &ServerIPAddress)) &&\r
+ !(MAC_COMPARE(&ARPHeader->THA, &ServerMACAddress)))\r
+ {\r
+ printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n"));\r
+ return; \r
+ }\r
+\r
+ printf_P(PSTR(" + Protocol: %x\r\n"), SwapEndian_16(ARPHeader->ProtocolType));\r
+ printf_P(PSTR(" + Operation: %u\r\n"), SwapEndian_16(ARPHeader->Operation));\r
+ \r
+ if (SwapEndian_16(ARPHeader->ProtocolType) == ETHERTYPE_IPV4)\r
+ {\r
+ printf_P(PSTR(" + SHA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader->SHA.Octets[0],\r
+ ARPHeader->SHA.Octets[1],\r
+ ARPHeader->SHA.Octets[2],\r
+ ARPHeader->SHA.Octets[3],\r
+ ARPHeader->SHA.Octets[4],\r
+ ARPHeader->SHA.Octets[5]);\r
+\r
+ printf_P(PSTR(" + SPA IP: %u.%u.%u.%u\r\n"), ARPHeader->SPA.Octets[0],\r
+ ARPHeader->SPA.Octets[1],\r
+ ARPHeader->SPA.Octets[2],\r
+ ARPHeader->SPA.Octets[3]);\r
+\r
+ printf_P(PSTR(" + THA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader->THA.Octets[0],\r
+ ARPHeader->THA.Octets[1],\r
+ ARPHeader->THA.Octets[2],\r
+ ARPHeader->THA.Octets[3],\r
+ ARPHeader->THA.Octets[4],\r
+ ARPHeader->THA.Octets[5]);\r
+\r
+ printf_P(PSTR(" + TPA IP: %u.%u.%u.%u\r\n"), ARPHeader->TPA.Octets[0],\r
+ ARPHeader->TPA.Octets[1],\r
+ ARPHeader->TPA.Octets[2],\r
+ ARPHeader->TPA.Octets[3]);\r
+ }\r
+ #endif\r
+}\r
+\r
+/** Decodes an IP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of an IP packet header\r
+ */\r
+void DecodeIPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_IP)\r
+ IP_Header_t* IPHeader = (IP_Header_t*)InDataStart;\r
+\r
+ uint16_t HeaderLengthBytes = (IPHeader->HeaderLength * sizeof(uint32_t));\r
+\r
+ printf_P(PSTR(" \\\r\n IP\r\n"));\r
+\r
+ if (!(IP_COMPARE(&IPHeader->DestinationAddress, &ServerIPAddress)))\r
+ {\r
+ printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n"));\r
+ return;\r
+ }\r
+\r
+ printf_P(PSTR(" + Header Length: %u Bytes\r\n"), HeaderLengthBytes);\r
+ printf_P(PSTR(" + Packet Version: %u\r\n"), IPHeader->Version);\r
+ printf_P(PSTR(" + Total Length: %u\r\n"), SwapEndian_16(IPHeader->TotalLength));\r
+ \r
+ printf_P(PSTR(" + Protocol: %u\r\n"), IPHeader->Protocol);\r
+ printf_P(PSTR(" + TTL: %u\r\n"), IPHeader->TTL);\r
+ \r
+ printf_P(PSTR(" + IP Src: %u.%u.%u.%u\r\n"), IPHeader->SourceAddress.Octets[0],\r
+ IPHeader->SourceAddress.Octets[1],\r
+ IPHeader->SourceAddress.Octets[2],\r
+ IPHeader->SourceAddress.Octets[3]); \r
+\r
+ printf_P(PSTR(" + IP Dst: %u.%u.%u.%u\r\n"), IPHeader->DestinationAddress.Octets[0],\r
+ IPHeader->DestinationAddress.Octets[1],\r
+ IPHeader->DestinationAddress.Octets[2],\r
+ IPHeader->DestinationAddress.Octets[3]);\r
+ #endif\r
+}\r
+\r
+/** Decodes an ICMP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of an ICMP packet header\r
+ */\r
+void DecodeICMPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_ICMP)\r
+ ICMP_Header_t* ICMPHeader = (ICMP_Header_t*)InDataStart;\r
+\r
+ printf_P(PSTR(" \\\r\n ICMP\r\n"));\r
+\r
+ printf_P(PSTR(" + Type: %u\r\n"), ICMPHeader->Type);\r
+ printf_P(PSTR(" + Code: %u\r\n"), ICMPHeader->Code);\r
+ #endif\r
+}\r
+\r
+/** Decodes a TCP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of a TCP packet header\r
+ */\r
+void DecodeTCPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_TCP)\r
+ TCP_Header_t* TCPHeader = (TCP_Header_t*)InDataStart;\r
+\r
+ uint16_t HeaderLengthBytes = (TCPHeader->DataOffset * sizeof(uint32_t));\r
+\r
+ printf_P(PSTR(" \\\r\n TCP\r\n"));\r
+\r
+ printf_P(PSTR(" + Header Length: %u Bytes\r\n"), HeaderLengthBytes);\r
+\r
+ printf_P(PSTR(" + Source Port: %u\r\n"), SwapEndian_16(TCPHeader->SourcePort));\r
+ printf_P(PSTR(" + Destination Port: %u\r\n"), SwapEndian_16(TCPHeader->DestinationPort));\r
+\r
+ printf_P(PSTR(" + Sequence Number: %lu\r\n"), SwapEndian_32(TCPHeader->SequenceNumber));\r
+ printf_P(PSTR(" + Acknowledgment Number: %lu\r\n"), SwapEndian_32(TCPHeader->AcknowledgmentNumber));\r
+ \r
+ printf_P(PSTR(" + Flags: 0x%02X\r\n"), TCPHeader->Flags);\r
+ \r
+ if (TCP_GetPortState(TCPHeader->DestinationPort) == TCP_Port_Closed)\r
+ printf_P(PSTR(" + NOT LISTENING ON DESTINATION PORT\r\n"));\r
+ #endif\r
+}\r
+\r
+/** Decodes an UDP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of a UDP packet header\r
+ */\r
+void DecodeUDPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_UDP)\r
+ UDP_Header_t* UDPHeader = (UDP_Header_t*)InDataStart;\r
+\r
+ printf_P(PSTR(" \\\r\n UDP\r\n"));\r
+\r
+ printf_P(PSTR(" + Source Port: %u\r\n"), SwapEndian_16(UDPHeader->SourcePort));\r
+ printf_P(PSTR(" + Destination Port: %u\r\n"), SwapEndian_16(UDPHeader->DestinationPort));\r
+\r
+ printf_P(PSTR(" + Data Length: %d\r\n"), SwapEndian_16(UDPHeader->Length));\r
+ #endif\r
+}\r
+\r
+/** Decodes an DHCP header and prints its contents to through the USART in a human readable format.\r
+ *\r
+ * \param InDataStart Pointer to the start of a DHCP packet header\r
+ */\r
+void DecodeDHCPHeader(void* InDataStart)\r
+{\r
+ #if !defined(NO_DECODE_DHCP)\r
+ uint8_t* DHCPOptions = (InDataStart + sizeof(DHCP_Header_t));\r
+\r
+ printf_P(PSTR(" \\\r\n DHCP\r\n"));\r
+\r
+ while (DHCPOptions[0] != DHCP_OPTION_END)\r
+ {\r
+ if (DHCPOptions[0] == DHCP_OPTION_MESSAGETYPE)\r
+ {\r
+ switch (DHCPOptions[2])\r
+ {\r
+ case DHCP_MESSAGETYPE_DISCOVER:\r
+ printf_P(PSTR(" + DISCOVER\r\n"));\r
+ break;\r
+ case DHCP_MESSAGETYPE_REQUEST:\r
+ printf_P(PSTR(" + REQUEST\r\n"));\r
+ break;\r
+ case DHCP_MESSAGETYPE_RELEASE:\r
+ printf_P(PSTR(" + RELEASE\r\n"));\r
+ break;\r
+ case DHCP_MESSAGETYPE_DECLINE:\r
+ printf_P(PSTR(" + DECLINE\r\n"));\r
+ break;\r
+ }\r
+ }\r
+ \r
+ DHCPOptions += ((DHCPOptions[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptions[1] + 2));\r
+ }\r
+\r
+ #endif\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for ProtocolDecoders.c.\r
+ */\r
+\r
+#ifndef _PROTOCOL_DECODERS_H_\r
+#define _PROTOCOL_DECODERS_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ \r
+ #include <LUFA/Drivers/Peripheral/SerialStream.h>\r
+ \r
+ #include "EthernetProtocols.h"\r
+ #include "Ethernet.h"\r
+ \r
+ /* Function Prototypes: */\r
+ void DecodeEthernetFrameHeader(void* InDataStart);\r
+ void DecodeARPHeader(void* InDataStart);\r
+ void DecodeIPHeader(void* InDataStart);\r
+ void DecodeICMPHeader(void* InDataStart);\r
+ void DecodeTCPHeader(void* InDataStart);\r
+ void DecodeUDPHeader(void* InDataStart);\r
+ void DecodeDHCPHeader(void* InDataStart);\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * RNDIS command handler functions. This handles RNDIS commands according to\r
+ * the Microsoft RNDIS specification, creating a USB Ethernet network adapter.\r
+ */\r
+ \r
+#define INCLUDE_FROM_RNDIS_C\r
+#include "RNDIS.h"\r
+\r
+/* Global Variables: */\r
+/** Physical MAC address of the network adapter, which becomes the MAC address of the host for packets sent to the adapter. */\r
+static MAC_Address_t PROGMEM AdapterMACAddress = {ADAPTER_MAC_ADDRESS};\r
+\r
+/** Vendor description of the adapter. This is overridden by the INF file required to install the appropriate RNDIS drivers for\r
+ * the device, but may still be used by the OS in some circumstances.\r
+ */\r
+static char PROGMEM AdapterVendorDescription[] = "LUFA RNDIS Adapter";\r
+\r
+/** List of RNDIS OID commands supported by this adapter. */\r
+static const uint32_t PROGMEM AdapterSupportedOIDList[] =\r
+ {\r
+ OID_GEN_SUPPORTED_LIST,\r
+ OID_GEN_PHYSICAL_MEDIUM,\r
+ OID_GEN_HARDWARE_STATUS,\r
+ OID_GEN_MEDIA_SUPPORTED,\r
+ OID_GEN_MEDIA_IN_USE,\r
+ OID_GEN_MAXIMUM_FRAME_SIZE,\r
+ OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+ OID_GEN_LINK_SPEED,\r
+ OID_GEN_TRANSMIT_BLOCK_SIZE,\r
+ OID_GEN_RECEIVE_BLOCK_SIZE,\r
+ OID_GEN_VENDOR_ID,\r
+ OID_GEN_VENDOR_DESCRIPTION,\r
+ OID_GEN_CURRENT_PACKET_FILTER,\r
+ OID_GEN_MAXIMUM_TOTAL_SIZE,\r
+ OID_GEN_MEDIA_CONNECT_STATUS,\r
+ OID_GEN_XMIT_OK,\r
+ OID_GEN_RCV_OK,\r
+ OID_GEN_XMIT_ERROR,\r
+ OID_GEN_RCV_ERROR,\r
+ OID_GEN_RCV_NO_BUFFER,\r
+ OID_802_3_PERMANENT_ADDRESS,\r
+ OID_802_3_CURRENT_ADDRESS,\r
+ OID_802_3_MULTICAST_LIST,\r
+ OID_802_3_MAXIMUM_LIST_SIZE,\r
+ OID_802_3_RCV_ERROR_ALIGNMENT,\r
+ OID_802_3_XMIT_ONE_COLLISION,\r
+ OID_802_3_XMIT_MORE_COLLISIONS,\r
+ };\r
+\r
+/** Buffer for RNDIS messages (as distinct from Ethernet frames sent through the adapter. This must be big enough to hold the entire\r
+ * Supported OID list, plus the response header. The buffer is half-duplex, and is written to as it is read to save on SRAM - for this\r
+ * reason, care must be taken when constructing RNDIS responses that unread data is not overwritten when writing in responses.\r
+ */\r
+uint8_t RNDISMessageBuffer[sizeof(AdapterSupportedOIDList) + sizeof(RNDIS_QUERY_CMPLT_t)];\r
+\r
+/** Pointer to the RNDIS message header at the top of the RNDIS message buffer, for convenience. */\r
+RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISMessageBuffer;\r
+\r
+/** Indicates if a RNDIS message response is ready to be sent back to the host. */\r
+bool ResponseReady = false;\r
+\r
+/** Current RNDIS adapter state, a value from the RNDIS_States_t enum. */\r
+uint8_t CurrRNDISState = RNDIS_Uninitialized;\r
+\r
+/** Current Ethernet packet filter mask. This is non-zero when the adapter is initialized, or zero when disabled. */\r
+uint32_t CurrPacketFilter = 0; \r
+\r
+\r
+/** Processes the RNDIS message received by the host and stored in the RNDISMessageBuffer global buffer. If a response is\r
+ * created, the ResponseReady global is updated so that the response is written back to the host upon request.\r
+ */\r
+void ProcessRNDISControlMessage(void)\r
+{\r
+ /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of\r
+ this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */\r
+\r
+ switch (MessageHeader->MessageType)\r
+ {\r
+ case REMOTE_NDIS_INITIALIZE_MSG:\r
+ /* Initialize the adapter - return information about the supported RNDIS version and buffer sizes */\r
+\r
+ ResponseReady = true;\r
+ \r
+ RNDIS_INITIALIZE_MSG_t* INITIALIZE_Message = (RNDIS_INITIALIZE_MSG_t*)&RNDISMessageBuffer;\r
+ RNDIS_INITIALIZE_CMPLT_t* INITIALIZE_Response = (RNDIS_INITIALIZE_CMPLT_t*)&RNDISMessageBuffer;\r
+ \r
+ INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;\r
+ INITIALIZE_Response->MessageLength = sizeof(RNDIS_INITIALIZE_CMPLT_t);\r
+ INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;\r
+ INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
+ \r
+ INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;\r
+ INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR; \r
+ INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;\r
+ INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;\r
+ INITIALIZE_Response->MaxPacketsPerTransfer = 1;\r
+ INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_PACKET_MSG_t) + ETHERNET_FRAME_SIZE_MAX);\r
+ INITIALIZE_Response->PacketAlignmentFactor = 0;\r
+ INITIALIZE_Response->AFListOffset = 0;\r
+ INITIALIZE_Response->AFListSize = 0;\r
+ \r
+ CurrRNDISState = RNDIS_Initialized;\r
+ \r
+ break;\r
+ case REMOTE_NDIS_HALT_MSG:\r
+ /* Halt the adapter, reset the adapter state - note that no response should be returned when completed */\r
+\r
+ ResponseReady = false;\r
+ MessageHeader->MessageLength = 0;\r
+\r
+ CurrRNDISState = RNDIS_Uninitialized;\r
+\r
+ break;\r
+ case REMOTE_NDIS_QUERY_MSG:\r
+ /* Request for information about a parameter about the adapter, specified as an OID token */\r
+\r
+ ResponseReady = true;\r
+ \r
+ RNDIS_QUERY_MSG_t* QUERY_Message = (RNDIS_QUERY_MSG_t*)&RNDISMessageBuffer;\r
+ RNDIS_QUERY_CMPLT_t* QUERY_Response = (RNDIS_QUERY_CMPLT_t*)&RNDISMessageBuffer;\r
+ uint32_t Query_Oid = QUERY_Message->Oid;\r
+ \r
+ void* QueryData = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +\r
+ QUERY_Message->InformationBufferOffset];\r
+ void* ResponseData = &RNDISMessageBuffer[sizeof(RNDIS_QUERY_CMPLT_t)]; \r
+ uint16_t ResponseSize;\r
+\r
+ QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;\r
+ QUERY_Response->MessageLength = sizeof(RNDIS_QUERY_CMPLT_t);\r
+ \r
+ if (ProcessNDISQuery(Query_Oid, QueryData, QUERY_Message->InformationBufferLength,\r
+ ResponseData, &ResponseSize))\r
+ {\r
+ QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
+ QUERY_Response->MessageLength += ResponseSize;\r
+ \r
+ QUERY_Response->InformationBufferLength = ResponseSize;\r
+ QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_QUERY_CMPLT_t) - sizeof(RNDIS_Message_Header_t));\r
+ }\r
+ else\r
+ { \r
+ QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;\r
+\r
+ QUERY_Response->InformationBufferLength = 0;\r
+ QUERY_Response->InformationBufferOffset = 0;\r
+ }\r
+ \r
+ break;\r
+ case REMOTE_NDIS_SET_MSG:\r
+ /* Request to set a parameter of the adapter, specified as an OID token */\r
+ \r
+ ResponseReady = true;\r
+ \r
+ RNDIS_SET_MSG_t* SET_Message = (RNDIS_SET_MSG_t*)&RNDISMessageBuffer;\r
+ RNDIS_SET_CMPLT_t* SET_Response = (RNDIS_SET_CMPLT_t*)&RNDISMessageBuffer;\r
+ uint32_t SET_Oid = SET_Message->Oid;\r
+\r
+ SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;\r
+ SET_Response->MessageLength = sizeof(RNDIS_SET_CMPLT_t);\r
+ SET_Response->RequestId = SET_Message->RequestId;\r
+\r
+ void* SetData = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +\r
+ SET_Message->InformationBufferOffset];\r
+ \r
+ if (ProcessNDISSet(SET_Oid, SetData, SET_Message->InformationBufferLength))\r
+ SET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
+ else\r
+ SET_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;\r
+\r
+ break;\r
+ case REMOTE_NDIS_RESET_MSG:\r
+ /* Soft reset the adapter */\r
+ \r
+ ResponseReady = true;\r
+ \r
+ RNDIS_RESET_CMPLT_t* RESET_Response = (RNDIS_RESET_CMPLT_t*)&RNDISMessageBuffer;\r
+\r
+ RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;\r
+ RESET_Response->MessageLength = sizeof(RNDIS_RESET_CMPLT_t);\r
+ RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
+ RESET_Response->AddressingReset = 0;\r
+\r
+ break;\r
+ case REMOTE_NDIS_KEEPALIVE_MSG:\r
+ /* Keep alive message sent to the adapter every 5 seconds when idle to ensure it is still responding */\r
+ \r
+ ResponseReady = true;\r
+ \r
+ RNDIS_KEEPALIVE_MSG_t* KEEPALIVE_Message = (RNDIS_KEEPALIVE_MSG_t*)&RNDISMessageBuffer;\r
+ RNDIS_KEEPALIVE_CMPLT_t* KEEPALIVE_Response = (RNDIS_KEEPALIVE_CMPLT_t*)&RNDISMessageBuffer;\r
+\r
+ KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;\r
+ KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KEEPALIVE_CMPLT_t);\r
+ KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;\r
+ KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
+ \r
+ break;\r
+ }\r
+}\r
+\r
+/** Processes RNDIS query commands, retrieving information from the adapter and reporting it back to the host. The requested\r
+ * parameter is given as an OID value.\r
+ *\r
+ * \param OId OId value of the parameter being queried\r
+ * \param QueryData Pointer to any extra query data being sent by the host to the device inside the RNDIS message buffer\r
+ * \param QuerySize Size in bytes of the extra query data being sent by the host\r
+ * \param ResponseData Pointer to the start of the query response inside the RNDIS message buffer\r
+ * \param ResponseSize Pointer to the size in bytes of the response data being sent to the host\r
+ *\r
+ * \return Boolean true if the query was handled, false otherwise\r
+ */\r
+static bool ProcessNDISQuery(uint32_t OId, void* QueryData, uint16_t QuerySize,\r
+ void* ResponseData, uint16_t* ResponseSize)\r
+{\r
+ /* Handler for REMOTE_NDIS_QUERY_MSG messages */\r
+\r
+ switch (OId)\r
+ {\r
+ case OID_GEN_SUPPORTED_LIST:\r
+ *ResponseSize = sizeof(AdapterSupportedOIDList);\r
+ \r
+ /* Copy the list of supported NDIS OID tokens to the response buffer */\r
+ memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));\r
+ \r
+ return true;\r
+ case OID_GEN_PHYSICAL_MEDIUM:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate that the device is a true ethernet link */\r
+ *((uint32_t*)ResponseData) = 0;\r
+ \r
+ return true;\r
+ case OID_GEN_HARDWARE_STATUS:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Always indicate hardware ready */\r
+ *((uint32_t*)ResponseData) = NdisHardwareStatusReady;\r
+ \r
+ return true;\r
+ case OID_GEN_MEDIA_SUPPORTED:\r
+ case OID_GEN_MEDIA_IN_USE:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate 802.3 (Ethernet) supported by the adapter */\r
+ *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;\r
+ \r
+ return true;\r
+ case OID_GEN_VENDOR_ID:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */\r
+ *((uint32_t*)ResponseData) = 0x00FFFFFF;\r
+ \r
+ return true;\r
+ case OID_GEN_MAXIMUM_FRAME_SIZE:\r
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
+ case OID_GEN_RECEIVE_BLOCK_SIZE:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate that the maximum frame size is the size of the ethernet frame buffer */\r
+ *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;\r
+ \r
+ return true;\r
+ case OID_GEN_VENDOR_DESCRIPTION:\r
+ *ResponseSize = sizeof(AdapterVendorDescription);\r
+ \r
+ /* Copy vendor description string to the response buffer */\r
+ memcpy_P(ResponseData, AdapterVendorDescription, sizeof(AdapterVendorDescription));\r
+ \r
+ return true;\r
+ case OID_GEN_MEDIA_CONNECT_STATUS:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Always indicate that the adapter is connected to a network */\r
+ *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;\r
+ \r
+ return true;\r
+ case OID_GEN_LINK_SPEED:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate 10Mb/s link speed */\r
+ *((uint32_t*)ResponseData) = 100000;\r
+\r
+ return true;\r
+ case OID_802_3_PERMANENT_ADDRESS:\r
+ case OID_802_3_CURRENT_ADDRESS:\r
+ *ResponseSize = sizeof(MAC_Address_t);\r
+ \r
+ /* Copy over the fixed adapter MAC to the response buffer */\r
+ memcpy_P(ResponseData, &AdapterMACAddress, sizeof(MAC_Address_t));\r
+\r
+ return true;\r
+ case OID_802_3_MAXIMUM_LIST_SIZE:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate only one multicast address supported */\r
+ *((uint32_t*)ResponseData) = 1;\r
+ \r
+ return true;\r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate the current packet filter mask */\r
+ *((uint32_t*)ResponseData) = CurrPacketFilter;\r
+ \r
+ return true; \r
+ case OID_GEN_XMIT_OK:\r
+ case OID_GEN_RCV_OK:\r
+ case OID_GEN_XMIT_ERROR:\r
+ case OID_GEN_RCV_ERROR:\r
+ case OID_GEN_RCV_NO_BUFFER:\r
+ case OID_802_3_RCV_ERROR_ALIGNMENT:\r
+ case OID_802_3_XMIT_ONE_COLLISION:\r
+ case OID_802_3_XMIT_MORE_COLLISIONS:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Unused statistic OIDs - always return 0 for each */\r
+ *((uint32_t*)ResponseData) = 0;\r
+ \r
+ return true;\r
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
+ *ResponseSize = sizeof(uint32_t);\r
+ \r
+ /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */\r
+ *((uint32_t*)ResponseData) = (sizeof(RNDISMessageBuffer) + ETHERNET_FRAME_SIZE_MAX);\r
+ \r
+ return true;\r
+ default:\r
+ return false;\r
+ }\r
+}\r
+\r
+/** Processes RNDIS set commands, setting adapter parameters to values given by the host. The requested parameter is given \r
+ * as an OID value.\r
+ *\r
+ * \param OId OId value of the parameter being set\r
+ * \param SetData Pointer to the parameter value in the RNDIS message buffer\r
+ * \param SetSize Size in bytes of the parameter value being sent by the host\r
+ *\r
+ * \return Boolean true if the set was handled, false otherwise\r
+ */\r
+static bool ProcessNDISSet(uint32_t OId, void* SetData, uint16_t SetSize)\r
+{\r
+ /* Handler for REMOTE_NDIS_SET_MSG messages */\r
+\r
+ switch (OId)\r
+ {\r
+ case OID_GEN_CURRENT_PACKET_FILTER:\r
+ /* Save the packet filter mask in case the host queries it again later */\r
+ CurrPacketFilter = *((uint32_t*)SetData);\r
+ \r
+ /* Set the RNDIS state to initialized if the packet filter is non-zero */\r
+ CurrRNDISState = ((CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Data_Initialized);\r
+ \r
+ return true;\r
+ case OID_802_3_MULTICAST_LIST:\r
+ /* Do nothing - throw away the value from the host as it is unused */\r
+ \r
+ return true;\r
+ default:\r
+ return false;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for RNDIS.c.\r
+ */\r
+\r
+#ifndef _RNDIS_H_\r
+#define _RNDIS_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <stdbool.h>\r
+ \r
+ #include "RNDISEthernet.h"\r
+ #include "RNDISConstants.h"\r
+ #include "Ethernet.h"\r
+\r
+ /* Macros: */\r
+ /** Physical MAC Address of the USB network adapter */\r
+ #define ADAPTER_MAC_ADDRESS {0x02, 0x00, 0x02, 0x00, 0x02, 0x00}\r
+ \r
+ /** Implemented RNDIS Version Major */\r
+ #define REMOTE_NDIS_VERSION_MAJOR 0x01\r
+\r
+ /** Implemented RNDIS Version Minor */\r
+ #define REMOTE_NDIS_VERSION_MINOR 0x00\r
+ \r
+ /** RNDIS request to issue a host-to-device NDIS command */\r
+ #define REQ_SendEncapsulatedCommand 0x00\r
+\r
+ /** RNDIS request to issue a device-to-host NDIS response */\r
+ #define REQ_GetEncapsulatedResponse 0x01\r
+ \r
+ /* Enums: */\r
+ /** Enum for the possible NDIS adapter states. */\r
+ enum RNDIS_States_t\r
+ {\r
+ RNDIS_Uninitialized = 0, /**< Adapter currently uninitialized */\r
+ RNDIS_Initialized = 1, /**< Adapter currently initialized but not ready for data transfers */\r
+ RNDIS_Data_Initialized = 2, /**< Adapter currently initialized and ready for data transfers */\r
+ };\r
+\r
+ /** Enum for the NDIS hardware states */\r
+ enum NDIS_Hardware_Status_t\r
+ {\r
+ NdisHardwareStatusReady, /**< Hardware Ready to accept commands from the host */\r
+ NdisHardwareStatusInitializing, /**< Hardware busy initializing */\r
+ NdisHardwareStatusReset, /**< Hardware reset */\r
+ NdisHardwareStatusClosing, /**< Hardware currently closing */\r
+ NdisHardwareStatusNotReady /**< Hardware not ready to accept commands from the host */\r
+ };\r
+\r
+ /* Type Defines: */\r
+ /** Type define for a RNDIS message header, sent before RNDIS messages */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType; /**< RNDIS message type, a REMOTE_NDIS_*_MSG constant */\r
+ uint32_t MessageLength; /**< Total length of the RNDIS message, in bytes */\r
+ } RNDIS_Message_Header_t;\r
+\r
+ /** Type define for a RNDIS packet message, used to encapsulate Ethernet packets sent to and from the adapter */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t DataOffset;\r
+ uint32_t DataLength;\r
+ uint32_t OOBDataOffset;\r
+ uint32_t OOBDataLength;\r
+ uint32_t NumOOBDataElements;\r
+ uint32_t PerPacketInfoOffset;\r
+ uint32_t PerPacketInfoLength;\r
+ uint32_t VcHandle;\r
+ uint32_t Reserved;\r
+ } RNDIS_PACKET_MSG_t;\r
+ \r
+ /** Type define for a RNDIS Initialize command message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ \r
+ uint32_t MajorVersion;\r
+ uint32_t MinorVersion;\r
+ uint32_t MaxTransferSize;\r
+ } RNDIS_INITIALIZE_MSG_t;\r
+ \r
+ /** Type define for a RNDIS Initialize complete response message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ uint32_t Status;\r
+ \r
+ uint32_t MajorVersion;\r
+ uint32_t MinorVersion;\r
+ uint32_t DeviceFlags;\r
+ uint32_t Medium;\r
+ uint32_t MaxPacketsPerTransfer;\r
+ uint32_t MaxTransferSize;\r
+ uint32_t PacketAlignmentFactor;\r
+ uint32_t AFListOffset;\r
+ uint32_t AFListSize;\r
+ } RNDIS_INITIALIZE_CMPLT_t;\r
+ \r
+ /** Type define for a RNDIS Keepalive command message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ } RNDIS_KEEPALIVE_MSG_t;\r
+\r
+ /** Type define for a RNDIS Keepalive complete message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ uint32_t Status;\r
+ } RNDIS_KEEPALIVE_CMPLT_t;\r
+\r
+ /** Type define for a RNDIS Reset complete message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t Status;\r
+\r
+ uint32_t AddressingReset;\r
+ } RNDIS_RESET_CMPLT_t;\r
+ \r
+ /** Type define for a RNDIS Set command message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ \r
+ uint32_t Oid;\r
+ uint32_t InformationBufferLength;\r
+ uint32_t InformationBufferOffset;\r
+ uint32_t DeviceVcHandle;\r
+ } RNDIS_SET_MSG_t;\r
+\r
+ /** Type define for a RNDIS Set complete response message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ uint32_t Status;\r
+ } RNDIS_SET_CMPLT_t;\r
+ \r
+ /** Type define for a RNDIS Query command message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ \r
+ uint32_t Oid;\r
+ uint32_t InformationBufferLength;\r
+ uint32_t InformationBufferOffset;\r
+ uint32_t DeviceVcHandle;\r
+ } RNDIS_QUERY_MSG_t;\r
+ \r
+ /** Type define for a RNDIS Query complete response message */\r
+ typedef struct\r
+ {\r
+ uint32_t MessageType;\r
+ uint32_t MessageLength;\r
+ uint32_t RequestId;\r
+ uint32_t Status;\r
+ \r
+ uint32_t InformationBufferLength;\r
+ uint32_t InformationBufferOffset;\r
+ } RNDIS_QUERY_CMPLT_t;\r
+ \r
+ /* External Variables: */\r
+ extern uint8_t RNDISMessageBuffer[];\r
+ extern RNDIS_Message_Header_t* MessageHeader;\r
+ extern bool ResponseReady;\r
+ extern uint8_t CurrRNDISState;\r
+\r
+ /* Function Prototypes: */\r
+ void ProcessRNDISControlMessage(void);\r
+\r
+ #if defined(INCLUDE_FROM_RNDIS_C)\r
+ static bool ProcessNDISQuery(uint32_t OId, void* QueryData, uint16_t QuerySize,\r
+ void* ResponseData, uint16_t* ResponseSize);\r
+ static bool ProcessNDISSet(uint32_t OId, void* SetData, uint16_t SetSize); \r
+ #endif\r
+ \r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * RNDIS specification related constants. For more information on these\r
+ * constants, please refer to the Microsoft RNDIS specification.\r
+ */\r
+ \r
+#ifndef _RNDIS_CONSTANTS_H_\r
+#define _RNDIS_CONSTANTS_H_\r
+\r
+ /* Macros: */\r
+ #define REMOTE_NDIS_PACKET_MSG 0x00000001UL\r
+ #define REMOTE_NDIS_INITIALIZE_MSG 0x00000002UL\r
+ #define REMOTE_NDIS_HALT_MSG 0x00000003UL\r
+ #define REMOTE_NDIS_QUERY_MSG 0x00000004UL\r
+ #define REMOTE_NDIS_SET_MSG 0x00000005UL\r
+ #define REMOTE_NDIS_RESET_MSG 0x00000006UL\r
+ #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007UL\r
+ #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008UL\r
+\r
+ #define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002UL\r
+ #define REMOTE_NDIS_QUERY_CMPLT 0x80000004UL\r
+ #define REMOTE_NDIS_SET_CMPLT 0x80000005UL\r
+ #define REMOTE_NDIS_RESET_CMPLT 0x80000006UL\r
+ #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008UL\r
+ \r
+ #define REMOTE_NDIS_STATUS_SUCCESS 0x00000000UL\r
+ #define REMOTE_NDIS_STATUS_FAILURE 0xC0000001UL\r
+ #define REMOTE_NDIS_STATUS_INVALID_DATA 0xC0010015UL\r
+ #define REMOTE_NDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL\r
+ #define REMOTE_NDIS_STATUS_MEDIA_CONNECT 0x4001000BUL\r
+ #define REMOTE_NDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL\r
+ \r
+ #define REMOTE_NDIS_MEDIA_STATE_CONNECTED 0x00000000UL\r
+ #define REMOTE_NDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL\r
+ \r
+ #define REMOTE_NDIS_MEDIUM_802_3 0x00000000UL\r
+ \r
+ #define REMOTE_NDIS_DF_CONNECTIONLESS 0x00000001UL\r
+ #define REMOTE_NDIS_DF_CONNECTION_ORIENTED 0x00000002UL\r
+ \r
+ #define OID_GEN_SUPPORTED_LIST 0x00010101UL\r
+ #define OID_GEN_HARDWARE_STATUS 0x00010102UL\r
+ #define OID_GEN_MEDIA_SUPPORTED 0x00010103UL\r
+ #define OID_GEN_MEDIA_IN_USE 0x00010104UL\r
+ #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL\r
+ #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL\r
+ #define OID_GEN_LINK_SPEED 0x00010107UL\r
+ #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL\r
+ #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL\r
+ #define OID_GEN_VENDOR_ID 0x0001010CUL\r
+ #define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL\r
+ #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL\r
+ #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL\r
+ #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL\r
+ #define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL\r
+ #define OID_GEN_XMIT_OK 0x00020101UL\r
+ #define OID_GEN_RCV_OK 0x00020102UL\r
+ #define OID_GEN_XMIT_ERROR 0x00020103UL\r
+ #define OID_GEN_RCV_ERROR 0x00020104UL\r
+ #define OID_GEN_RCV_NO_BUFFER 0x00020105UL\r
+ #define OID_802_3_PERMANENT_ADDRESS 0x01010101UL\r
+ #define OID_802_3_CURRENT_ADDRESS 0x01010102UL\r
+ #define OID_802_3_MULTICAST_LIST 0x01010103UL\r
+ #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL\r
+ #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL\r
+ #define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL\r
+ #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Transmission Control Protocol (TCP) packet handling routines. This protocol handles the reliable in-order transmission\r
+ * and reception of packets to and from devices on a network, to "ports" on the device. It is used in situations where data\r
+ * delivery must be reliable and correct, e.g. HTTP, TELNET and most other non-streaming protocols.\r
+ */\r
+ \r
+#define INCLUDE_FROM_TCP_C\r
+#include "TCP.h"\r
+\r
+/* Global Variables: */\r
+/** Port state table array. This contains the current status of TCP ports in the device. To save on space, only open ports are\r
+ * stored - closed ports may be overwritten at any time, and the system will assume any ports not present in the array are closed. This\r
+ * allows for MAX_OPEN_TCP_PORTS to be less than the number of ports used by the application if desired.\r
+ */\r
+TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS];\r
+\r
+/** Connection state table array. This contains the current status of TCP connections in the device. To save on space, only active\r
+ * (non-closed) connections are stored - closed connections may be overwritten at any time, and the system will assume any connections\r
+ * not present in the array are closed.\r
+ */\r
+TCP_ConnectionState_t ConnectionStateTable[MAX_TCP_CONNECTIONS];\r
+\r
+\r
+/** Task to handle the calling of each registered application's callback function, to process and generate TCP packets at the application\r
+ * level. If an application produces a response, this task constructs the appropriate Ethernet frame and places it into the Ethernet OUT\r
+ * buffer for later transmission.\r
+ */\r
+TASK(TCP_Task)\r
+{\r
+ /* Task to hand off TCP packets to and from the listening applications. */\r
+\r
+ /* Run each application in sequence, to process incoming and generate outgoing packets */\r
+ for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
+ {\r
+ /* Find the corresponding port entry in the port table */\r
+ for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
+ {\r
+ /* Run the application handler for the port */\r
+ if ((PortStateTable[PTableEntry].Port == ConnectionStateTable[CSTableEntry].Port) && \r
+ (PortStateTable[PTableEntry].State == TCP_Port_Open))\r
+ {\r
+ PortStateTable[PTableEntry].ApplicationHandler(&ConnectionStateTable[CSTableEntry], &ConnectionStateTable[CSTableEntry].Info.Buffer);\r
+ }\r
+ }\r
+ }\r
+ \r
+ /* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */\r
+ if (FrameOUT.FrameInBuffer)\r
+ return;\r
+ \r
+ /* Send response packets from each application as the TCP packet buffers are filled by the applications */\r
+ for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
+ {\r
+ /* For each completely received packet, pass it along to the listening application */\r
+ if ((ConnectionStateTable[CSTableEntry].Info.Buffer.Direction == TCP_PACKETDIR_OUT) &&\r
+ (ConnectionStateTable[CSTableEntry].Info.Buffer.Ready))\r
+ {\r
+ Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData;\r
+ IP_Header_t* IPHeaderOUT = (IP_Header_t*)&FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)];\r
+ TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +\r
+ sizeof(IP_Header_t)]; \r
+ void* TCPDataOUT = &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +\r
+ sizeof(IP_Header_t) +\r
+ sizeof(TCP_Header_t)];\r
+\r
+ uint16_t PacketSize = ConnectionStateTable[CSTableEntry].Info.Buffer.Length;\r
+\r
+ /* Fill out the TCP data */\r
+ TCPHeaderOUT->SourcePort = ConnectionStateTable[CSTableEntry].Port;\r
+ TCPHeaderOUT->DestinationPort = ConnectionStateTable[CSTableEntry].RemotePort;\r
+ TCPHeaderOUT->SequenceNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut);\r
+ TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberIn);\r
+ TCPHeaderOUT->DataOffset = (sizeof(TCP_Header_t) / sizeof(uint32_t));\r
+ TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE);\r
+\r
+ TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
+ TCPHeaderOUT->UrgentPointer = 0;\r
+ TCPHeaderOUT->Checksum = 0;\r
+ TCPHeaderOUT->Reserved = 0;\r
+\r
+ memcpy(TCPDataOUT, ConnectionStateTable[CSTableEntry].Info.Buffer.Data, PacketSize);\r
+ \r
+ ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut += PacketSize;\r
+\r
+ TCPHeaderOUT->Checksum = TCP_Checksum16(TCPHeaderOUT, ServerIPAddress,\r
+ ConnectionStateTable[CSTableEntry].RemoteAddress,\r
+ (sizeof(TCP_Header_t) + PacketSize));\r
+\r
+ PacketSize += sizeof(TCP_Header_t);\r
+\r
+ /* Fill out the response IP header */\r
+ IPHeaderOUT->TotalLength = SwapEndian_16(sizeof(IP_Header_t) + PacketSize);\r
+ IPHeaderOUT->TypeOfService = 0;\r
+ IPHeaderOUT->HeaderLength = (sizeof(IP_Header_t) / sizeof(uint32_t));\r
+ IPHeaderOUT->Version = 4;\r
+ IPHeaderOUT->Flags = 0;\r
+ IPHeaderOUT->FragmentOffset = 0;\r
+ IPHeaderOUT->Identification = 0;\r
+ IPHeaderOUT->HeaderChecksum = 0;\r
+ IPHeaderOUT->Protocol = PROTOCOL_TCP;\r
+ IPHeaderOUT->TTL = DEFAULT_TTL;\r
+ IPHeaderOUT->SourceAddress = ServerIPAddress;\r
+ IPHeaderOUT->DestinationAddress = ConnectionStateTable[CSTableEntry].RemoteAddress;\r
+ \r
+ IPHeaderOUT->HeaderChecksum = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t));\r
+ \r
+ PacketSize += sizeof(IP_Header_t);\r
+ \r
+ /* Fill out the response Ethernet frame header */\r
+ FrameOUTHeader->Source = ServerMACAddress;\r
+ FrameOUTHeader->Destination = (MAC_Address_t){{0x02, 0x00, 0x02, 0x00, 0x02, 0x00}};\r
+ FrameOUTHeader->EtherType = SwapEndian_16(ETHERTYPE_IPV4);\r
+\r
+ PacketSize += sizeof(Ethernet_Frame_Header_t);\r
+\r
+ /* Set the response length in the buffer and indicate that a response is ready to be sent */\r
+ FrameOUT.FrameLength = PacketSize;\r
+ FrameOUT.FrameInBuffer = true;\r
+ \r
+ ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false;\r
+ \r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+/** Initializes the TCP protocol handler, clearing the port and connection state tables. This must be called before TCP packets are\r
+ * processed.\r
+ */\r
+void TCP_Init(void)\r
+{\r
+ /* Initialize the port state table with all CLOSED entries */\r
+ for (uint8_t PTableEntry = 0; PTableEntry < MAX_OPEN_TCP_PORTS; PTableEntry++)\r
+ PortStateTable[PTableEntry].State = TCP_Port_Closed;\r
+\r
+ /* Initialize the connection table with all CLOSED entries */\r
+ for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
+ ConnectionStateTable[CSTableEntry].State = TCP_Connection_Closed;\r
+}\r
+\r
+/** Sets the state and callback handler of the given port, specified in big endian to the given state.\r
+ *\r
+ * \param Port Port whose state and callback function to set, specified in big endian\r
+ * \param State New state of the port, a value from the TCP_PortStates_t enum\r
+ * \param Handler Application callback handler for the port\r
+ *\r
+ * \return Boolean true if the port state was set, false otherwise (no more space in the port state table)\r
+ */\r
+bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*))\r
+{\r
+ /* Note, Port number should be specified in BIG endian to simplify network code */\r
+\r
+ /* Check to see if the port entry is already in the port state table */\r
+ for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
+ {\r
+ /* Find existing entry for the port in the table, update it if found */\r
+ if (PortStateTable[PTableEntry].Port == Port)\r
+ {\r
+ PortStateTable[PTableEntry].State = State;\r
+ PortStateTable[PTableEntry].ApplicationHandler = Handler;\r
+ return true;\r
+ }\r
+ }\r
+\r
+ /* Check if trying to open the port -- if so we need to find an unused (closed) entry and replace it */\r
+ if (State == TCP_Port_Open)\r
+ {\r
+ for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
+ {\r
+ /* Find a closed port entry in the table, change it to the given port and state */\r
+ if (PortStateTable[PTableEntry].State == TCP_Port_Closed)\r
+ {\r
+ PortStateTable[PTableEntry].Port = Port;\r
+ PortStateTable[PTableEntry].State = State;\r
+ PortStateTable[PTableEntry].ApplicationHandler = Handler;\r
+ return true;\r
+ }\r
+ }\r
+ \r
+ /* Port not in table and no room to add it, return failure */\r
+ return false;\r
+ }\r
+ else\r
+ {\r
+ /* Port not in table but trying to close it, so operation successful */\r
+ return true;\r
+ }\r
+}\r
+\r
+/** Retrieves the current state of a given TCP port, specified in big endian.\r
+ *\r
+ * \param Port TCP port whose state is to be retrieved, given in big-endian\r
+ *\r
+ * \return A value from the TCP_PortStates_t enum\r
+ */\r
+uint8_t TCP_GetPortState(uint16_t Port)\r
+{\r
+ /* Note, Port number should be specified in BIG endian to simplify network code */\r
+\r
+ for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
+ {\r
+ /* Find existing entry for the port in the table, return the port status if found */\r
+ if (PortStateTable[PTableEntry].Port == Port)\r
+ return PortStateTable[PTableEntry].State;\r
+ }\r
+ \r
+ /* Port not in table, assume closed */\r
+ return TCP_Port_Closed;\r
+}\r
+\r
+/** Sets the connection state of the given port, remote address and remote port to the given TCP connection state. If the\r
+ * connection exists in the connection state table it is updated, otherwise it is created if possible.\r
+ *\r
+ * \param Port TCP port of the connection on the device, specified in big endian\r
+ * \param RemoteAddress Remote protocol IP address of the connected device\r
+ * \param RemotePort TCP port of the remote device in the connection, specified in big endian\r
+ * \param State TCP connection state, a value from the TCP_ConnectionStates_t enum\r
+ *\r
+ * \return Boolean true if the connection was updated or created, false otherwise (no more space in the connection state table)\r
+ */\r
+bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State)\r
+{\r
+ /* Note, Port number should be specified in BIG endian to simplify network code */\r
+\r
+ for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
+ {\r
+ /* Find port entry in the table */\r
+ if ((ConnectionStateTable[CSTableEntry].Port == Port) &&\r
+ IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&\r
+ ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)\r
+ {\r
+ ConnectionStateTable[CSTableEntry].State = State;\r
+ return true;\r
+ }\r
+ }\r
+ \r
+ for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
+ {\r
+ /* Find empty entry in the table */\r
+ if (ConnectionStateTable[CSTableEntry].State == TCP_Connection_Closed)\r
+ {\r
+ ConnectionStateTable[CSTableEntry].Port = Port;\r
+ ConnectionStateTable[CSTableEntry].RemoteAddress = RemoteAddress; \r
+ ConnectionStateTable[CSTableEntry].RemotePort = RemotePort;\r
+ ConnectionStateTable[CSTableEntry].State = State;\r
+ return true;\r
+ }\r
+ }\r
+ \r
+ return false;\r
+}\r
+\r
+/** Retrieves the current state of a given TCP connection to a host.\r
+ *\r
+ * \param Port TCP port on the device in the connection, specified in big endian\r
+ * \param RemoteAddress Remote protocol IP address of the connected host\r
+ * \param RemotePort Remote TCP port of the connected host, specified in big endian\r
+ *\r
+ * \return A value from the TCP_ConnectionStates_t enum\r
+ */\r
+uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort)\r
+{\r
+ /* Note, Port number should be specified in BIG endian to simplify network code */\r
+\r
+ for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
+ {\r
+ /* Find port entry in the table */\r
+ if ((ConnectionStateTable[CSTableEntry].Port == Port) &&\r
+ IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&\r
+ ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)\r
+ \r
+ {\r
+ return ConnectionStateTable[CSTableEntry].State;\r
+ }\r
+ }\r
+ \r
+ return TCP_Connection_Closed;\r
+}\r
+\r
+/** Retrieves the connection info structure of a given connection to a host.\r
+ *\r
+ * \param Port TCP port on the device in the connection, specified in big endian\r
+ * \param RemoteAddress Remote protocol IP address of the connected host\r
+ * \param RemotePort Remote TCP port of the connected host, specified in big endian\r
+ *\r
+ * \return ConnectionInfo structure of the connection if found, NULL otherwise\r
+ */\r
+TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort)\r
+{\r
+ /* Note, Port number should be specified in BIG endian to simplify network code */\r
+\r
+ for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
+ {\r
+ /* Find port entry in the table */\r
+ if ((ConnectionStateTable[CSTableEntry].Port == Port) &&\r
+ IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&\r
+ ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)\r
+ {\r
+ return &ConnectionStateTable[CSTableEntry].Info;\r
+ }\r
+ }\r
+ \r
+ return NULL;\r
+}\r
+\r
+/** Processes a TCP packet inside an Ethernet frame, and writes the appropriate response\r
+ * to the output Ethernet frame if one is created by a application handler.\r
+ *\r
+ * \param IPHeaderInStart Pointer to the start of the incoming packet's IP header\r
+ * \param TCPHeaderInStart Pointer to the start of the incoming packet's TCP header\r
+ * \param TCPHeaderOutStart Pointer to the start of the outgoing packet's TCP header\r
+ *\r
+ * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE if no\r
+ * response was generated, NO_PROCESS if the packet processing was deferred until the\r
+ * next Ethernet packet handler iteration\r
+ */\r
+int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart)\r
+{\r
+ IP_Header_t* IPHeaderIN = (IP_Header_t*)IPHeaderInStart;\r
+ TCP_Header_t* TCPHeaderIN = (TCP_Header_t*)TCPHeaderInStart;\r
+ TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)TCPHeaderOutStart;\r
+\r
+ TCP_ConnectionInfo_t* ConnectionInfo;\r
+ \r
+ DecodeTCPHeader(TCPHeaderInStart);\r
+\r
+ bool PacketResponse = false;\r
+ \r
+ /* Check if the destination port is open and allows incoming connections */\r
+ if (TCP_GetPortState(TCPHeaderIN->DestinationPort) == TCP_Port_Open)\r
+ {\r
+ /* Detect SYN from host to start a connection */\r
+ if (TCPHeaderIN->Flags & TCP_FLAG_SYN)\r
+ TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort, TCP_Connection_Listen);\r
+\r
+ /* Detect RST from host to abort existing connection */\r
+ if (TCPHeaderIN->Flags & TCP_FLAG_RST)\r
+ {\r
+ TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK); \r
+ PacketResponse = true;\r
+ \r
+ TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort, TCP_Connection_Closed); \r
+ }\r
+ else\r
+ {\r
+ /* Process the incoming TCP packet based on the current connection state for the sender and port */\r
+ switch (TCP_GetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort))\r
+ {\r
+ case TCP_Connection_Listen:\r
+ if (TCPHeaderIN->Flags == TCP_FLAG_SYN)\r
+ {\r
+ /* SYN connection when closed starts a connection with a peer */\r
+\r
+ TCPHeaderOUT->Flags = (TCP_FLAG_SYN | TCP_FLAG_ACK); \r
+ PacketResponse = true;\r
+ \r
+ TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort,\r
+ TCP_Connection_SYNReceived);\r
+ \r
+ ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort);\r
+\r
+ ConnectionInfo->SequenceNumberIn = (SwapEndian_32(TCPHeaderIN->SequenceNumber) + 1);\r
+ ConnectionInfo->SequenceNumberOut = 0;\r
+ ConnectionInfo->Buffer.InUse = false;\r
+ }\r
+ \r
+ break;\r
+ case TCP_Connection_SYNReceived:\r
+ if (TCPHeaderIN->Flags == TCP_FLAG_ACK)\r
+ {\r
+ /* ACK during the connection process completes the connection to a peer */\r
+\r
+ TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort, TCP_Connection_Established);\r
+\r
+ ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort);\r
+ \r
+ ConnectionInfo->SequenceNumberOut++;\r
+ }\r
+ \r
+ break;\r
+ case TCP_Connection_Established:\r
+ if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))\r
+ {\r
+ /* FIN ACK when connected to a peer starts the finalization process */\r
+ \r
+ TCPHeaderOUT->Flags = (TCP_FLAG_FIN | TCP_FLAG_ACK); \r
+ PacketResponse = true;\r
+ \r
+ TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort, TCP_Connection_CloseWait);\r
+\r
+ ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort);\r
+\r
+ ConnectionInfo->SequenceNumberIn++;\r
+ ConnectionInfo->SequenceNumberOut++;\r
+ }\r
+ else if ((TCPHeaderIN->Flags == TCP_FLAG_ACK) || (TCPHeaderIN->Flags == (TCP_FLAG_ACK | TCP_FLAG_PSH)))\r
+ {\r
+ ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort);\r
+\r
+ /* Check if the buffer is currently in use either by a buffered data to send, or receive */ \r
+ if ((ConnectionInfo->Buffer.InUse == false) && (ConnectionInfo->Buffer.Ready == false))\r
+ { \r
+ ConnectionInfo->Buffer.Direction = TCP_PACKETDIR_IN;\r
+ ConnectionInfo->Buffer.InUse = true;\r
+ ConnectionInfo->Buffer.Length = 0;\r
+ }\r
+ \r
+ /* Check if the buffer has been claimed by us to read in data from the peer */\r
+ if ((ConnectionInfo->Buffer.Direction == TCP_PACKETDIR_IN) &&\r
+ (ConnectionInfo->Buffer.Length != TCP_WINDOW_SIZE))\r
+ {\r
+ uint16_t IPOffset = (IPHeaderIN->HeaderLength * sizeof(uint32_t));\r
+ uint16_t TCPOffset = (TCPHeaderIN->DataOffset * sizeof(uint32_t));\r
+ uint16_t DataLength = (SwapEndian_16(IPHeaderIN->TotalLength) - IPOffset - TCPOffset);\r
+\r
+ /* Copy the packet data into the buffer */\r
+ memcpy(&ConnectionInfo->Buffer.Data[ConnectionInfo->Buffer.Length],\r
+ &((uint8_t*)TCPHeaderInStart)[TCPOffset],\r
+ DataLength);\r
+\r
+ ConnectionInfo->SequenceNumberIn += DataLength;\r
+ ConnectionInfo->Buffer.Length += DataLength;\r
+ \r
+ /* Check if the buffer is full or if the PSH flag is set, if so indicate buffer ready */\r
+ if ((!(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length)) || (TCPHeaderIN->Flags & TCP_FLAG_PSH))\r
+ {\r
+ ConnectionInfo->Buffer.InUse = false;\r
+ ConnectionInfo->Buffer.Ready = true;\r
+\r
+ TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
+ PacketResponse = true;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Buffer is currently in use by the application, defer processing of the incoming packet */\r
+ return NO_PROCESS;\r
+ }\r
+ }\r
+ \r
+ break;\r
+ case TCP_Connection_Closing:\r
+ ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort);\r
+\r
+ TCPHeaderOUT->Flags = (TCP_FLAG_ACK | TCP_FLAG_FIN);\r
+ PacketResponse = true;\r
+ \r
+ ConnectionInfo->Buffer.InUse = false;\r
+ \r
+ TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort, TCP_Connection_FINWait1);\r
+\r
+ break;\r
+ case TCP_Connection_FINWait1:\r
+ if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))\r
+ {\r
+ ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort);\r
+\r
+ TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
+ PacketResponse = true;\r
+\r
+ ConnectionInfo->SequenceNumberIn++;\r
+ ConnectionInfo->SequenceNumberOut++;\r
+ \r
+ TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort, TCP_Connection_Closed);\r
+ }\r
+ else if (TCPHeaderIN->Flags == TCP_FLAG_ACK)\r
+ {\r
+ TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort, TCP_Connection_FINWait2);\r
+ }\r
+ \r
+ break;\r
+ case TCP_Connection_FINWait2:\r
+ if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))\r
+ {\r
+ ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort);\r
+\r
+ TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
+ PacketResponse = true;\r
+\r
+ ConnectionInfo->SequenceNumberIn++;\r
+ ConnectionInfo->SequenceNumberOut++;\r
+ \r
+ TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort, TCP_Connection_Closed);\r
+ }\r
+ \r
+ break;\r
+ case TCP_Connection_CloseWait:\r
+ if (TCPHeaderIN->Flags == TCP_FLAG_ACK)\r
+ {\r
+ TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort, TCP_Connection_Closed);\r
+ }\r
+ \r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Port is not open, indicate via a RST/ACK response to the sender */\r
+ TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK); \r
+ PacketResponse = true;\r
+ }\r
+ \r
+ /* Check if we need to respond to the sent packet */\r
+ if (PacketResponse)\r
+ {\r
+ ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
+ TCPHeaderIN->SourcePort);\r
+\r
+ TCPHeaderOUT->SourcePort = TCPHeaderIN->DestinationPort;\r
+ TCPHeaderOUT->DestinationPort = TCPHeaderIN->SourcePort;\r
+ TCPHeaderOUT->SequenceNumber = SwapEndian_32(ConnectionInfo->SequenceNumberOut);\r
+ TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionInfo->SequenceNumberIn);\r
+ TCPHeaderOUT->DataOffset = (sizeof(TCP_Header_t) / sizeof(uint32_t));\r
+ \r
+ if (!(ConnectionInfo->Buffer.InUse))\r
+ TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE);\r
+ else\r
+ TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length);\r
+\r
+ TCPHeaderOUT->UrgentPointer = 0;\r
+ TCPHeaderOUT->Checksum = 0;\r
+ TCPHeaderOUT->Reserved = 0;\r
+ \r
+ TCPHeaderOUT->Checksum = TCP_Checksum16(TCPHeaderOUT, IPHeaderIN->DestinationAddress,\r
+ IPHeaderIN->SourceAddress, sizeof(TCP_Header_t)); \r
+\r
+ return sizeof(TCP_Header_t); \r
+ }\r
+\r
+ return NO_RESPONSE;\r
+}\r
+\r
+/** Calculates the appropriate TCP checksum, consisting of the addition of the one's compliment of each word,\r
+ * complimented.\r
+ *\r
+ * \param TCPHeaderOutStart Pointer to the start of the packet's outgoing TCP header\r
+ * \param SourceAddress Source protocol IP address of the outgoing IP header\r
+ * \param SourceAddress DestinationAddress protocol IP address of the outgoing IP header\r
+ * \param TCPOutSize Size in bytes of the TCP data header and payload\r
+ *\r
+ * \return A 16-bit TCP checksum value\r
+ */\r
+static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress,\r
+ IP_Address_t DestinationAddress, uint16_t TCPOutSize)\r
+{\r
+ uint32_t Checksum = 0;\r
+ \r
+ /* TCP/IP checksums are the addition of the one's compliment of each word including the IP pseudo-header,\r
+ complimented */\r
+ \r
+ Checksum += ((uint16_t*)&SourceAddress)[0];\r
+ Checksum += ((uint16_t*)&SourceAddress)[1];\r
+ Checksum += ((uint16_t*)&DestinationAddress)[0];\r
+ Checksum += ((uint16_t*)&DestinationAddress)[1];\r
+ Checksum += SwapEndian_16(PROTOCOL_TCP);\r
+ Checksum += SwapEndian_16(TCPOutSize);\r
+\r
+ for (uint8_t CurrWord = 0; CurrWord < (TCPOutSize >> 1); CurrWord++)\r
+ Checksum += ((uint16_t*)TCPHeaderOutStart)[CurrWord];\r
+ \r
+ if (TCPOutSize & 0x01)\r
+ Checksum += (((uint16_t*)TCPHeaderOutStart)[TCPOutSize >> 1] & 0x00FF);\r
+ \r
+ while (Checksum & 0xFFFF0000)\r
+ Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16));\r
+ \r
+ return ~Checksum;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for TCP.c.\r
+ */\r
+\r
+#ifndef _TCP_H_\r
+#define _TCP_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <stdbool.h>\r
+ \r
+ #include <LUFA/Scheduler/Scheduler.h>\r
+ \r
+ #include "EthernetProtocols.h"\r
+ #include "Ethernet.h"\r
+ #include "ProtocolDecoders.h"\r
+ \r
+ /* Macros: */\r
+ /** Maximum number of TCP ports which can be open at the one time */\r
+ #define MAX_OPEN_TCP_PORTS 1\r
+\r
+ /** Maximum number of TCP connections which can be sustained at the one time */\r
+ #define MAX_TCP_CONNECTIONS 1\r
+\r
+ /** TCP window size, giving the maximum number of bytes which can be buffered at the one time */\r
+ #define TCP_WINDOW_SIZE 1024\r
+ \r
+ /** Port number for HTTP transmissions */\r
+ #define TCP_PORT_HTTP SwapEndian_16(80)\r
+ \r
+ /** Data direction indicator for a TCP application buffer, indicating data from host-to-device */\r
+ #define TCP_PACKETDIR_IN false\r
+\r
+ /** Data direction indicator for a TCP application buffer, indicating data from device-to-host */\r
+ #define TCP_PACKETDIR_OUT true\r
+ \r
+ /** Congestion Window Reduced TCP flag mask */\r
+ #define TCP_FLAG_CWR (1 << 7)\r
+\r
+ /** Explicit Congestion Notification TCP flag mask */\r
+ #define TCP_FLAG_ECE (1 << 6)\r
+\r
+ /** Urgent TCP flag mask */\r
+ #define TCP_FLAG_URG (1 << 5)\r
+\r
+ /** Data Acknowledge TCP flag mask */\r
+ #define TCP_FLAG_ACK (1 << 4)\r
+\r
+ /** Data Push TCP flag mask */\r
+ #define TCP_FLAG_PSH (1 << 3)\r
+\r
+ /** Reset TCP flag mask */\r
+ #define TCP_FLAG_RST (1 << 2)\r
+\r
+ /** Synchronize TCP flag mask */\r
+ #define TCP_FLAG_SYN (1 << 1)\r
+\r
+ /** Connection Finalize TCP flag mask */\r
+ #define TCP_FLAG_FIN (1 << 0)\r
+ \r
+ /** Application macro: Determines if the given application buffer contains a packet received from the host\r
+ *\r
+ * \param Buffer Application buffer to check\r
+ *\r
+ * \return Boolean true if the buffer contains a packet from the host, false otherwise\r
+ */\r
+ #define TCP_APP_HAS_RECEIVED_PACKET(Buffer) (Buffer->Ready && (Buffer->Direction == TCP_PACKETDIR_IN))\r
+\r
+ /** Application macro: Indicates if the application buffer is currently locked by the application for device-to-host transfers.\r
+ *\r
+ * \param Buffer Application buffer to check\r
+ *\r
+ * \return Boolean true if the buffer has been captured by the application for device-to-host transmissions, false otherwise\r
+ */\r
+ #define TCP_APP_HAVE_CAPTURED_BUFFER(Buffer) (!(Buffer->Ready) && Buffer->InUse && \\r
+ (Buffer->Direction == TCP_PACKETDIR_OUT))\r
+\r
+ /** Application macro: Indicates if the application can lock the buffer for multiple continued device-to-host transmissions.\r
+ *\r
+ * \param Buffer Application buffer to check\r
+ *\r
+ * \return Boolean true if the buffer may be captured by the application for device-to-host transmissions, false otherwise\r
+ */\r
+ #define TCP_APP_CAN_CAPTURE_BUFFER(Buffer) Buffer->InUse\r
+\r
+ /** Application macro: Captures the application buffer, locking it for device-to-host transmissions only. This should be\r
+ * performed when the application needs to transmit several packets worth of data in succession with no interruptions from the host.\r
+ *\r
+ * \note The application must check that the buffer can be locked first using TCP_APP_CAN_CAPTURE_BUFFER().\r
+ *\r
+ * \param Buffer Application buffer to lock\r
+ */\r
+ #define TCP_APP_CAPTURE_BUFFER(Buffer) MACROS{ Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->InUse = true; }MACROE\r
+\r
+ /** Application macro: Releases a captured application buffer, allowing for host-to-device packets to be received.\r
+ *\r
+ * \param Buffer Application buffer to release\r
+ */\r
+ #define TCP_APP_RELEASE_BUFFER(Buffer) MACROS{ Buffer->InUse = false; }MACROE\r
+\r
+ /** Application macro: Sends the contents of the given application buffer to the host.\r
+ *\r
+ * \param Buffer Application buffer to send\r
+ * \param Len Length of data contained in the buffer\r
+ */\r
+ #define TCP_APP_SEND_BUFFER(Buffer, Len) MACROS{ Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->Length = Len; Buffer->Ready = true; }MACROE\r
+\r
+ /** Application macro: Clears the application buffer, ready for a packet to be written to it.\r
+ *\r
+ * \param Buffer Application buffer to clear\r
+ */\r
+ #define TCP_APP_CLEAR_BUFFER(Buffer) MACROS{ Buffer->Ready = false; Buffer->Length = 0; }MACROE\r
+ \r
+ /** Application macro: Closes an open connection to a host.\r
+ *\r
+ * \param Connection Open TCP connection to close\r
+ */\r
+ #define TCP_APP_CLOSECONNECTION(Connection) MACROS{ Connection->State = TCP_Connection_Closing; }MACROE\r
+\r
+ /* Enums: */\r
+ /** Enum for possible TCP port states */\r
+ enum TCP_PortStates_t\r
+ {\r
+ TCP_Port_Closed = 0, /**< TCP port closed, no connections to a host may be made on this port. */\r
+ TCP_Port_Open = 1, /**< TCP port open, connections to a host may be made on this port. */\r
+ };\r
+ \r
+ /** Enum for possible TCP connection states */\r
+ enum TCP_ConnectionStates_t\r
+ {\r
+ TCP_Connection_Listen = 0, /**< Listening for a connection from a host */\r
+ TCP_Connection_SYNSent = 1, /**< Unused */\r
+ TCP_Connection_SYNReceived = 2, /**< SYN received, waiting for ACK */\r
+ TCP_Connection_Established = 3, /**< Connection established in both directions */\r
+ TCP_Connection_FINWait1 = 4, /**< Closing, waiting for ACK */\r
+ TCP_Connection_FINWait2 = 5, /**< Closing, waiting for FIN ACK */\r
+ TCP_Connection_CloseWait = 6, /**< Closing, waiting for ACK */\r
+ TCP_Connection_Closing = 7, /**< Unused */\r
+ TCP_Connection_LastACK = 8, /**< Unused */\r
+ TCP_Connection_TimeWait = 9, /**< Unused */\r
+ TCP_Connection_Closed = 10, /**< Connection closed in both directions */ \r
+ };\r
+ \r
+ /* Type Defines: */\r
+ /** Type define for a TCP connection buffer structure, including size, data and direction */\r
+ typedef struct\r
+ {\r
+ uint16_t Length; /**< Length of data in the TCP application buffer */\r
+ uint8_t Data[TCP_WINDOW_SIZE]; /**< TCP application data buffer */\r
+ bool Direction; /**< Buffer transmission direction, either TCP_PACKETDIR_IN or TCP_PACKETDIR_OUT */\r
+ bool Ready; /**< If data from host, indicates buffer ready to be read, otherwise indicates\r
+ * buffer ready to be sent to the host\r
+ */\r
+ bool InUse; /** Indicates if the buffer is locked to to the current direction, and cannot be changed */\r
+ } TCP_ConnectionBuffer_t;\r
+\r
+ /** Type define for a TCP connection information structure */\r
+ typedef struct\r
+ {\r
+ uint32_t SequenceNumberIn; /**< Current TCP sequence number for host-to-device */ \r
+ uint32_t SequenceNumberOut; /**< Current TCP sequence number for device-to-host */\r
+ TCP_ConnectionBuffer_t Buffer; /**< Connection application data buffer */\r
+ } TCP_ConnectionInfo_t;\r
+\r
+ /** Type define for a complete TCP connection state */\r
+ typedef struct\r
+ {\r
+ uint16_t Port; /**< Connection port number on the device */\r
+ uint16_t RemotePort; /**< Connection port number on the host */\r
+ IP_Address_t RemoteAddress; /**< Connection protocol IP address of the host */\r
+ TCP_ConnectionInfo_t Info; /**< Connection information, including application buffer */\r
+ uint8_t State; /**< Current connection state, a value from the TCP_ConnectionStates_t enum */\r
+ } TCP_ConnectionState_t;\r
+\r
+ /** Type define for a TCP port state */\r
+ typedef struct\r
+ {\r
+ uint16_t Port; /**< TCP port number on the device */\r
+ uint8_t State; /**< Current port state, a value from the TCP_PortStates_t enum */\r
+ void (*ApplicationHandler) (TCP_ConnectionState_t* ConnectionState,\r
+ TCP_ConnectionBuffer_t* Buffer); /**< Port application handler */\r
+ } TCP_PortState_t;\r
+\r
+ /** Type define for a TCP packet header */\r
+ typedef struct\r
+ {\r
+ uint16_t SourcePort; /**< Source port of the TCP packet */\r
+ uint16_t DestinationPort; /**< Destination port of the TCP packet */\r
+ \r
+ uint32_t SequenceNumber; /**< Data sequence number of the packet */\r
+ uint32_t AcknowledgmentNumber; /**< Data acknowledgment number of the packet */\r
+ \r
+ unsigned char Reserved : 4; /**< Reserved, must be all 0 */\r
+ unsigned char DataOffset : 4; /**< Offset of the data from the start of the header, in 4 byte chunks */\r
+ uint8_t Flags; /**< TCP packet flags */\r
+ uint16_t WindowSize; /**< Current data window size (bytes remaining in reception buffer) */\r
+ \r
+ uint16_t Checksum; /**< TCP checksum */\r
+ uint16_t UrgentPointer; /**< Urgent data pointer */\r
+ } TCP_Header_t;\r
+\r
+ /* Tasks: */\r
+ TASK(TCP_Task);\r
+ \r
+ /* External Variables: */\r
+ TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS];\r
+\r
+ /* Function Prototypes: */\r
+ void TCP_Init(void);\r
+ bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*));\r
+ uint8_t TCP_GetPortState(uint16_t Port);\r
+ bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State);\r
+ uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort);\r
+ TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort);\r
+ int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart);\r
+\r
+ #if defined(INCLUDE_FROM_TCP_C)\r
+ static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress,\r
+ IP_Address_t DestinationAddress, uint16_t TCPOutSize);\r
+ #endif\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * User Datagram Protocol (UDP) packet handling routines. This protocol handles high throughput, low\r
+ * reliability packets which are typically used to encapsulate streaming data.\r
+ */\r
+ \r
+#define INCLUDE_FROM_UDP_C\r
+#include "UDP.h"\r
+\r
+/** Processes a UDP packet inside an Ethernet frame, and writes the appropriate response\r
+ * to the output Ethernet frame if a subprotocol handler has created a response packet.\r
+ *\r
+ * \param IPHeaderInStart Pointer to the start of the incoming packet's IP header\r
+ * \param UDPHeaderInStart Pointer to the start of the incoming packet's UDP header\r
+ * \param UDPHeaderOutStart Pointer to the start of the outgoing packet's UDP header\r
+ *\r
+ * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise\r
+ */\r
+int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void* UDPHeaderOutStart)\r
+{\r
+ UDP_Header_t* UDPHeaderIN = (UDP_Header_t*)UDPHeaderInStart;\r
+ UDP_Header_t* UDPHeaderOUT = (UDP_Header_t*)UDPHeaderOutStart;\r
+ \r
+ int16_t RetSize = NO_RESPONSE;\r
+ \r
+ DecodeUDPHeader(UDPHeaderInStart);\r
+ \r
+ /* Check to see if the UDP packet is a DHCP packet */\r
+ if (SwapEndian_16(UDPHeaderIN->DestinationPort) == UDP_PORT_DHCP_REQUEST)\r
+ {\r
+ RetSize = DHCP_ProcessDHCPPacket(IPHeaderInStart,\r
+ &((uint8_t*)UDPHeaderInStart)[sizeof(UDP_Header_t)],\r
+ &((uint8_t*)UDPHeaderOutStart)[sizeof(UDP_Header_t)]);\r
+ }\r
+ \r
+ /* Check to see if the protocol processing routine has filled out a response */\r
+ if (RetSize > 0)\r
+ {\r
+ /* Fill out the response UDP packet header */\r
+ UDPHeaderOUT->SourcePort = UDPHeaderIN->DestinationPort;\r
+ UDPHeaderOUT->DestinationPort = UDPHeaderIN->SourcePort;\r
+ UDPHeaderOUT->Checksum = 0;\r
+ UDPHeaderOUT->Length = SwapEndian_16(sizeof(UDP_Header_t) + RetSize);\r
+\r
+ /* Return the size of the response so far */\r
+ return (sizeof(UDP_Header_t) + RetSize);\r
+ }\r
+ \r
+ return NO_RESPONSE;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for IP.c.\r
+ */\r
+\r
+#ifndef _UDP_H_\r
+#define _UDP_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ \r
+ #include "EthernetProtocols.h"\r
+ #include "Ethernet.h"\r
+ #include "ProtocolDecoders.h"\r
+ \r
+ /* Macros: */\r
+ /** Source UDP port for a DHCP request */\r
+ #define UDP_PORT_DHCP_REQUEST 67\r
+\r
+ /** Destination UDP port for a DHCP reply */\r
+ #define UDP_PORT_DHCP_REPLY 68\r
+ \r
+ /* Type Defines: */\r
+ /** Type define for a UDP packet header */\r
+ typedef struct\r
+ {\r
+ uint16_t SourcePort; /**< Packet source port */\r
+ uint16_t DestinationPort; /**< Packet destination port */\r
+ uint16_t Length; /**< Total packet length, in bytes */\r
+ uint16_t Checksum; /**< Optional UDP packet checksum */\r
+ } UDP_Header_t;\r
+ \r
+ /* Function Prototypes: */\r
+ int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void* UDPHeaderOutStart);\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Simple webserver application for demonstrating the RNDIS demo and TCP/IP stack. This\r
+ * application will serve up a static HTTP webpage when requested by the host.\r
+ */\r
+\r
+#include "Webserver.h"\r
+\r
+/** HTTP server response header, for transmission before the page contents. This indicates to the host that a page exists at the\r
+ * given location, and gives extra connection information.\r
+ */\r
+char PROGMEM HTTPHeader[] = "HTTP/1.1 200 OK\r\n"\r
+ "Server: LUFA RNDIS\r\n"\r
+ "Content-type: text/html\r\n"\r
+ "Connection: close\r\n\r\n";\r
+\r
+/** HTTP page to serve to the host when a HTTP request is made. This page is too long for a single response, thus it is automatically\r
+ * broken up into smaller blocks and sent as a series of packets each time the webserver application callback is run.\r
+ */\r
+char PROGMEM HTTPPage[] = \r
+ "<html>"\r
+ " <head>"\r
+ " <title>"\r
+ " LUFA Webserver Demo"\r
+ " </title>"\r
+ " </head>"\r
+ " <body>"\r
+ " <h1>Hello from your USB AVR!</h1>"\r
+ " <p>"\r
+ " Hello! Welcome to the LUFA RNDIS Demo Webserver test page, running on your USB AVR via the LUFA library. This demonstrates the HTTP webserver, TCP/IP stack and RNDIS demo all running atop the LUFA USB stack."\r
+ " <br /><br />"\r
+ " <small>Project Information: <a href=\"http://www.fourwalledcubicle.com/LUFA.php\">http://www.fourwalledcubicle.com/LUFA.php</a>.</small>"\r
+ " <hr />"\r
+ " <i>LUFA Version: </i>" LUFA_VERSION_STRING\r
+ " </p>"\r
+ " </body>"\r
+ "</html>";\r
+\r
+\r
+/** Initializes the Webserver application, opening the appropriate HTTP port in the TCP handler and registering the application\r
+ * callback routine for packets sent to the HTTP protocol port.\r
+ */\r
+void Webserver_Init(void)\r
+{\r
+ /* Open the HTTP port in the TCP protocol so that HTTP connections to the device can be established */\r
+ TCP_SetPortState(TCP_PORT_HTTP, TCP_Port_Open, Webserver_ApplicationCallback);\r
+}\r
+\r
+/** Indicates if a given request equals the given HTTP command.\r
+ *\r
+ * \param RequestHeader HTTP request made by the host\r
+ * \param Command HTTP command to compare the request to\r
+ *\r
+ * \return Boolean true if the command matches the request, false otherwise\r
+ */\r
+static bool IsHTTPCommand(uint8_t* RequestHeader, char* Command)\r
+{\r
+ /* Returns true if the non null terminated string in RequestHeader matches the null terminated string Command */\r
+ return (strncmp((char*)RequestHeader, Command, strlen(Command)) == 0);\r
+}\r
+\r
+/** Application callback routine, executed each time the TCP processing task runs. This callback determines what request\r
+ * has been made (if any), and serves up appropriate responses.\r
+ *\r
+ * \param ConnectionState Pointer to a TCP Connection State structure giving connection information\r
+ * \param Buffer Pointer to the application's send/receive packet buffer\r
+ */\r
+void Webserver_ApplicationCallback(TCP_ConnectionState_t* ConnectionState, TCP_ConnectionBuffer_t* Buffer)\r
+{\r
+ char* BufferDataStr = (char*)Buffer->Data;\r
+ static uint8_t PageBlock = 0;\r
+ \r
+ /* Check to see if a packet has been received on the HTTP port from a remote host */\r
+ if (TCP_APP_HAS_RECEIVED_PACKET(Buffer))\r
+ {\r
+ if (IsHTTPCommand(Buffer->Data, "GET"))\r
+ {\r
+ PageBlock = 0;\r
+\r
+ /* Copy the HTTP response header into the packet buffer */\r
+ strcpy_P(BufferDataStr, HTTPHeader);\r
+ \r
+ /* Send the buffer contents to the host */\r
+ TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr));\r
+\r
+ /* Lock the buffer to Device->Host transmissions only while we send the page contents */\r
+ TCP_APP_CAPTURE_BUFFER(Buffer);\r
+ }\r
+ else if (IsHTTPCommand(Buffer->Data, "HEAD"))\r
+ {\r
+ /* Copy the HTTP response header into the packet buffer */\r
+ strcpy_P(BufferDataStr, HTTPHeader);\r
+\r
+ /* Send the buffer contents to the host */\r
+ TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr));\r
+ }\r
+ else if (IsHTTPCommand(Buffer->Data, "TRACE"))\r
+ {\r
+ /* Echo the host's query back to the host */\r
+ TCP_APP_SEND_BUFFER(Buffer, Buffer->Length);\r
+ }\r
+ else\r
+ {\r
+ /* Unknown request, just clear the buffer (drop the packet) */\r
+ TCP_APP_CLEAR_BUFFER(Buffer);\r
+ }\r
+ }\r
+ else if (TCP_APP_HAVE_CAPTURED_BUFFER(Buffer))\r
+ {\r
+ uint16_t RemLength = strlen_P(&HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE]);\r
+ uint16_t Length;\r
+ \r
+ /* Determine the length of the loaded block */\r
+ Length = ((RemLength > HTTP_REPLY_BLOCK_SIZE) ? HTTP_REPLY_BLOCK_SIZE : RemLength);\r
+\r
+ /* Copy the next buffer sized block of the page to the packet buffer */\r
+ strncpy_P(BufferDataStr, &HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE], Length);\r
+ \r
+ /* Send the buffer contents to the host */\r
+ TCP_APP_SEND_BUFFER(Buffer, Length);\r
+\r
+ /* Check to see if the entire page has been sent */\r
+ if (PageBlock++ == (sizeof(HTTPPage) / HTTP_REPLY_BLOCK_SIZE))\r
+ {\r
+ /* Unlock the buffer so that the host can fill it with future packets */\r
+ TCP_APP_RELEASE_BUFFER(Buffer);\r
+ \r
+ /* Close the connection to the host */\r
+ TCP_APP_CLOSECONNECTION(ConnectionState);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for Webserver.c.\r
+ */\r
+ \r
+#ifndef _WEBSERVER_H_\r
+#define _WEBSERVER_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <avr/pgmspace.h>\r
+ \r
+ #include <LUFA/Version.h>\r
+ \r
+ #include "TCP.h"\r
+ \r
+ /* Macros: */\r
+ /** Maximum size of a HTTP response per transmission */\r
+ #define HTTP_REPLY_BLOCK_SIZE 128\r
+ \r
+ /* Function Prototypes: */\r
+ void Webserver_Init(void);\r
+ void Webserver_ApplicationCallback(TCP_ConnectionState_t* ConnectionState, TCP_ConnectionBuffer_t* Buffer);\r
+\r
+#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/* Protocol decoders for Ethernet, TCP, IP, ICMP and ARP. Each of these routines\r
- accepts a header to the appropriate protocol and prints out pertinent information\r
- on the packet through the serial port.\r
- \r
- To disable printing of a specific protocol, define the token NO_DECODE_{Protocol}\r
- in the project makefile, and pass it to the compiler using the -D switch.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Protocol decoding routines, for the plain-text decoding of Ethernet frames for debugging purposes.\r
- * Enabled protocol decoders will print incoming Ethernet frame contents through the USART in a human\r
- * readable format.\r
- *\r
- * Note that the USART is a slow transmission medium, and will slow down packet processing considerably.\r
- * Packet decoding routines can be disabled by defining NO_DECODE_{Protocol Name} in the project makefile\r
- * and passing it to the compiler via the -D switch.\r
- */\r
- \r
-#include "ProtocolDecoders.h"\r
-\r
-/** Decodes an Ethernet frame header and prints its contents to through the USART in a human readable format.\r
- *\r
- * \param InDataStart Pointer to the start of an Ethernet frame header\r
- */\r
-void DecodeEthernetFrameHeader(void* InDataStart)\r
-{\r
- #if !defined(NO_DECODE_ETHERNET)\r
- Ethernet_Frame_Header_t* FrameHeader = (Ethernet_Frame_Header_t*)InDataStart;\r
- \r
- printf_P(PSTR("\r\n"));\r
- \r
- printf_P(PSTR(" ETHERNET\r\n"));\r
- printf_P(PSTR(" + Frame Size: %u\r\n"), FrameIN.FrameLength);\r
-\r
- if (!(MAC_COMPARE(&FrameHeader->Destination, &ServerMACAddress)) &&\r
- !(MAC_COMPARE(&FrameHeader->Destination, &BroadcastMACAddress)))\r
- {\r
- printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n"));\r
- return;\r
- }\r
-\r
- printf_P(PSTR(" + MAC Source : %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader->Source.Octets[0],\r
- FrameHeader->Source.Octets[1],\r
- FrameHeader->Source.Octets[2],\r
- FrameHeader->Source.Octets[3],\r
- FrameHeader->Source.Octets[4],\r
- FrameHeader->Source.Octets[5]);\r
-\r
- printf_P(PSTR(" + MAC Dest: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), FrameHeader->Destination.Octets[0],\r
- FrameHeader->Destination.Octets[1],\r
- FrameHeader->Destination.Octets[2],\r
- FrameHeader->Destination.Octets[3],\r
- FrameHeader->Destination.Octets[4],\r
- FrameHeader->Destination.Octets[5]);\r
-\r
- if (SwapEndian_16(FrameIN.FrameLength) > ETHERNET_VER2_MINSIZE)\r
- printf_P(PSTR(" + Protocol: 0x%04x\r\n"), SwapEndian_16(FrameHeader->EtherType));\r
- else\r
- printf_P(PSTR(" + Protocol: UNKNOWN E1\r\n"));\r
- #endif\r
-}\r
-\r
-/** Decodes an ARP header and prints its contents to through the USART in a human readable format.\r
- *\r
- * \param InDataStart Pointer to the start of an ARP packet header\r
- */\r
-void DecodeARPHeader(void* InDataStart)\r
-{\r
- #if !defined(NO_DECODE_ARP)\r
- ARP_Header_t* ARPHeader = (ARP_Header_t*)InDataStart; \r
-\r
- printf_P(PSTR(" \\\r\n ARP\r\n"));\r
-\r
- if (!(IP_COMPARE(&ARPHeader->TPA, &ServerIPAddress)) &&\r
- !(MAC_COMPARE(&ARPHeader->THA, &ServerMACAddress)))\r
- {\r
- printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n"));\r
- return; \r
- }\r
-\r
- printf_P(PSTR(" + Protocol: %x\r\n"), SwapEndian_16(ARPHeader->ProtocolType));\r
- printf_P(PSTR(" + Operation: %u\r\n"), SwapEndian_16(ARPHeader->Operation));\r
- \r
- if (SwapEndian_16(ARPHeader->ProtocolType) == ETHERTYPE_IPV4)\r
- {\r
- printf_P(PSTR(" + SHA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader->SHA.Octets[0],\r
- ARPHeader->SHA.Octets[1],\r
- ARPHeader->SHA.Octets[2],\r
- ARPHeader->SHA.Octets[3],\r
- ARPHeader->SHA.Octets[4],\r
- ARPHeader->SHA.Octets[5]);\r
-\r
- printf_P(PSTR(" + SPA IP: %u.%u.%u.%u\r\n"), ARPHeader->SPA.Octets[0],\r
- ARPHeader->SPA.Octets[1],\r
- ARPHeader->SPA.Octets[2],\r
- ARPHeader->SPA.Octets[3]);\r
-\r
- printf_P(PSTR(" + THA MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n"), ARPHeader->THA.Octets[0],\r
- ARPHeader->THA.Octets[1],\r
- ARPHeader->THA.Octets[2],\r
- ARPHeader->THA.Octets[3],\r
- ARPHeader->THA.Octets[4],\r
- ARPHeader->THA.Octets[5]);\r
-\r
- printf_P(PSTR(" + TPA IP: %u.%u.%u.%u\r\n"), ARPHeader->TPA.Octets[0],\r
- ARPHeader->TPA.Octets[1],\r
- ARPHeader->TPA.Octets[2],\r
- ARPHeader->TPA.Octets[3]);\r
- }\r
- #endif\r
-}\r
-\r
-/** Decodes an IP header and prints its contents to through the USART in a human readable format.\r
- *\r
- * \param InDataStart Pointer to the start of an IP packet header\r
- */\r
-void DecodeIPHeader(void* InDataStart)\r
-{\r
- #if !defined(NO_DECODE_IP)\r
- IP_Header_t* IPHeader = (IP_Header_t*)InDataStart;\r
-\r
- uint16_t HeaderLengthBytes = (IPHeader->HeaderLength * sizeof(uint32_t));\r
-\r
- printf_P(PSTR(" \\\r\n IP\r\n"));\r
-\r
- if (!(IP_COMPARE(&IPHeader->DestinationAddress, &ServerIPAddress)))\r
- {\r
- printf_P(PSTR(" + NOT ADDRESSED TO DEVICE\r\n"));\r
- return;\r
- }\r
-\r
- printf_P(PSTR(" + Header Length: %u Bytes\r\n"), HeaderLengthBytes);\r
- printf_P(PSTR(" + Packet Version: %u\r\n"), IPHeader->Version);\r
- printf_P(PSTR(" + Total Length: %u\r\n"), SwapEndian_16(IPHeader->TotalLength));\r
- \r
- printf_P(PSTR(" + Protocol: %u\r\n"), IPHeader->Protocol);\r
- printf_P(PSTR(" + TTL: %u\r\n"), IPHeader->TTL);\r
- \r
- printf_P(PSTR(" + IP Src: %u.%u.%u.%u\r\n"), IPHeader->SourceAddress.Octets[0],\r
- IPHeader->SourceAddress.Octets[1],\r
- IPHeader->SourceAddress.Octets[2],\r
- IPHeader->SourceAddress.Octets[3]); \r
-\r
- printf_P(PSTR(" + IP Dst: %u.%u.%u.%u\r\n"), IPHeader->DestinationAddress.Octets[0],\r
- IPHeader->DestinationAddress.Octets[1],\r
- IPHeader->DestinationAddress.Octets[2],\r
- IPHeader->DestinationAddress.Octets[3]);\r
- #endif\r
-}\r
-\r
-/** Decodes an ICMP header and prints its contents to through the USART in a human readable format.\r
- *\r
- * \param InDataStart Pointer to the start of an ICMP packet header\r
- */\r
-void DecodeICMPHeader(void* InDataStart)\r
-{\r
- #if !defined(NO_DECODE_ICMP)\r
- ICMP_Header_t* ICMPHeader = (ICMP_Header_t*)InDataStart;\r
-\r
- printf_P(PSTR(" \\\r\n ICMP\r\n"));\r
-\r
- printf_P(PSTR(" + Type: %u\r\n"), ICMPHeader->Type);\r
- printf_P(PSTR(" + Code: %u\r\n"), ICMPHeader->Code);\r
- #endif\r
-}\r
-\r
-/** Decodes a TCP header and prints its contents to through the USART in a human readable format.\r
- *\r
- * \param InDataStart Pointer to the start of a TCP packet header\r
- */\r
-void DecodeTCPHeader(void* InDataStart)\r
-{\r
- #if !defined(NO_DECODE_TCP)\r
- TCP_Header_t* TCPHeader = (TCP_Header_t*)InDataStart;\r
-\r
- uint16_t HeaderLengthBytes = (TCPHeader->DataOffset * sizeof(uint32_t));\r
-\r
- printf_P(PSTR(" \\\r\n TCP\r\n"));\r
-\r
- printf_P(PSTR(" + Header Length: %u Bytes\r\n"), HeaderLengthBytes);\r
-\r
- printf_P(PSTR(" + Source Port: %u\r\n"), SwapEndian_16(TCPHeader->SourcePort));\r
- printf_P(PSTR(" + Destination Port: %u\r\n"), SwapEndian_16(TCPHeader->DestinationPort));\r
-\r
- printf_P(PSTR(" + Sequence Number: %lu\r\n"), SwapEndian_32(TCPHeader->SequenceNumber));\r
- printf_P(PSTR(" + Acknowledgment Number: %lu\r\n"), SwapEndian_32(TCPHeader->AcknowledgmentNumber));\r
- \r
- printf_P(PSTR(" + Flags: 0x%02X\r\n"), TCPHeader->Flags);\r
- \r
- if (TCP_GetPortState(TCPHeader->DestinationPort) == TCP_Port_Closed)\r
- printf_P(PSTR(" + NOT LISTENING ON DESTINATION PORT\r\n"));\r
- #endif\r
-}\r
-\r
-/** Decodes an UDP header and prints its contents to through the USART in a human readable format.\r
- *\r
- * \param InDataStart Pointer to the start of a UDP packet header\r
- */\r
-void DecodeUDPHeader(void* InDataStart)\r
-{\r
- #if !defined(NO_DECODE_UDP)\r
- UDP_Header_t* UDPHeader = (UDP_Header_t*)InDataStart;\r
-\r
- printf_P(PSTR(" \\\r\n UDP\r\n"));\r
-\r
- printf_P(PSTR(" + Source Port: %u\r\n"), SwapEndian_16(UDPHeader->SourcePort));\r
- printf_P(PSTR(" + Destination Port: %u\r\n"), SwapEndian_16(UDPHeader->DestinationPort));\r
-\r
- printf_P(PSTR(" + Data Length: %d\r\n"), SwapEndian_16(UDPHeader->Length));\r
- #endif\r
-}\r
-\r
-/** Decodes an DHCP header and prints its contents to through the USART in a human readable format.\r
- *\r
- * \param InDataStart Pointer to the start of a DHCP packet header\r
- */\r
-void DecodeDHCPHeader(void* InDataStart)\r
-{\r
- #if !defined(NO_DECODE_DHCP)\r
- uint8_t* DHCPOptions = (InDataStart + sizeof(DHCP_Header_t));\r
-\r
- printf_P(PSTR(" \\\r\n DHCP\r\n"));\r
-\r
- while (DHCPOptions[0] != DHCP_OPTION_END)\r
- {\r
- if (DHCPOptions[0] == DHCP_OPTION_MESSAGETYPE)\r
- {\r
- switch (DHCPOptions[2])\r
- {\r
- case DHCP_MESSAGETYPE_DISCOVER:\r
- printf_P(PSTR(" + DISCOVER\r\n"));\r
- break;\r
- case DHCP_MESSAGETYPE_REQUEST:\r
- printf_P(PSTR(" + REQUEST\r\n"));\r
- break;\r
- case DHCP_MESSAGETYPE_RELEASE:\r
- printf_P(PSTR(" + RELEASE\r\n"));\r
- break;\r
- case DHCP_MESSAGETYPE_DECLINE:\r
- printf_P(PSTR(" + DECLINE\r\n"));\r
- break;\r
- }\r
- }\r
- \r
- DHCPOptions += ((DHCPOptions[0] == DHCP_OPTION_PAD) ? 1 : (DHCPOptions[1] + 2));\r
- }\r
-\r
- #endif\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for ProtocolDecoders.c.\r
- */\r
-\r
-#ifndef _PROTOCOL_DECODERS_H_\r
-#define _PROTOCOL_DECODERS_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- \r
- #include <LUFA/Drivers/Peripheral/SerialStream.h>\r
- \r
- #include "EthernetProtocols.h"\r
- #include "Ethernet.h"\r
- \r
- /* Function Prototypes: */\r
- void DecodeEthernetFrameHeader(void* InDataStart);\r
- void DecodeARPHeader(void* InDataStart);\r
- void DecodeIPHeader(void* InDataStart);\r
- void DecodeICMPHeader(void* InDataStart);\r
- void DecodeTCPHeader(void* InDataStart);\r
- void DecodeUDPHeader(void* InDataStart);\r
- void DecodeDHCPHeader(void* InDataStart);\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * RNDIS command handler functions. This handles RNDIS commands according to\r
- * the Microsoft RNDIS specification, creating a USB Ethernet network adapter.\r
- */\r
- \r
-#define INCLUDE_FROM_RNDIS_C\r
-#include "RNDIS.h"\r
-\r
-/* Global Variables: */\r
-/** Physical MAC address of the network adapter, which becomes the MAC address of the host for packets sent to the adapter. */\r
-static MAC_Address_t PROGMEM AdapterMACAddress = {ADAPTER_MAC_ADDRESS};\r
-\r
-/** Vendor description of the adapter. This is overridden by the INF file required to install the appropriate RNDIS drivers for\r
- * the device, but may still be used by the OS in some circumstances.\r
- */\r
-static char PROGMEM AdapterVendorDescription[] = "LUFA RNDIS Adapter";\r
-\r
-/** List of RNDIS OID commands supported by this adapter. */\r
-static const uint32_t PROGMEM AdapterSupportedOIDList[] =\r
- {\r
- OID_GEN_SUPPORTED_LIST,\r
- OID_GEN_PHYSICAL_MEDIUM,\r
- OID_GEN_HARDWARE_STATUS,\r
- OID_GEN_MEDIA_SUPPORTED,\r
- OID_GEN_MEDIA_IN_USE,\r
- OID_GEN_MAXIMUM_FRAME_SIZE,\r
- OID_GEN_MAXIMUM_TOTAL_SIZE,\r
- OID_GEN_LINK_SPEED,\r
- OID_GEN_TRANSMIT_BLOCK_SIZE,\r
- OID_GEN_RECEIVE_BLOCK_SIZE,\r
- OID_GEN_VENDOR_ID,\r
- OID_GEN_VENDOR_DESCRIPTION,\r
- OID_GEN_CURRENT_PACKET_FILTER,\r
- OID_GEN_MAXIMUM_TOTAL_SIZE,\r
- OID_GEN_MEDIA_CONNECT_STATUS,\r
- OID_GEN_XMIT_OK,\r
- OID_GEN_RCV_OK,\r
- OID_GEN_XMIT_ERROR,\r
- OID_GEN_RCV_ERROR,\r
- OID_GEN_RCV_NO_BUFFER,\r
- OID_802_3_PERMANENT_ADDRESS,\r
- OID_802_3_CURRENT_ADDRESS,\r
- OID_802_3_MULTICAST_LIST,\r
- OID_802_3_MAXIMUM_LIST_SIZE,\r
- OID_802_3_RCV_ERROR_ALIGNMENT,\r
- OID_802_3_XMIT_ONE_COLLISION,\r
- OID_802_3_XMIT_MORE_COLLISIONS,\r
- };\r
-\r
-/** Buffer for RNDIS messages (as distinct from Ethernet frames sent through the adapter. This must be big enough to hold the entire\r
- * Supported OID list, plus the response header. The buffer is half-duplex, and is written to as it is read to save on SRAM - for this\r
- * reason, care must be taken when constructing RNDIS responses that unread data is not overwritten when writing in responses.\r
- */\r
-uint8_t RNDISMessageBuffer[sizeof(AdapterSupportedOIDList) + sizeof(RNDIS_QUERY_CMPLT_t)];\r
-\r
-/** Pointer to the RNDIS message header at the top of the RNDIS message buffer, for convenience. */\r
-RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)&RNDISMessageBuffer;\r
-\r
-/** Indicates if a RNDIS message response is ready to be sent back to the host. */\r
-bool ResponseReady = false;\r
-\r
-/** Current RNDIS adapter state, a value from the RNDIS_States_t enum. */\r
-uint8_t CurrRNDISState = RNDIS_Uninitialized;\r
-\r
-/** Current Ethernet packet filter mask. This is non-zero when the adapter is initialized, or zero when disabled. */\r
-uint32_t CurrPacketFilter = 0; \r
-\r
-\r
-/** Processes the RNDIS message received by the host and stored in the RNDISMessageBuffer global buffer. If a response is\r
- * created, the ResponseReady global is updated so that the response is written back to the host upon request.\r
- */\r
-void ProcessRNDISControlMessage(void)\r
-{\r
- /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of\r
- this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */\r
-\r
- switch (MessageHeader->MessageType)\r
- {\r
- case REMOTE_NDIS_INITIALIZE_MSG:\r
- /* Initialize the adapter - return information about the supported RNDIS version and buffer sizes */\r
-\r
- ResponseReady = true;\r
- \r
- RNDIS_INITIALIZE_MSG_t* INITIALIZE_Message = (RNDIS_INITIALIZE_MSG_t*)&RNDISMessageBuffer;\r
- RNDIS_INITIALIZE_CMPLT_t* INITIALIZE_Response = (RNDIS_INITIALIZE_CMPLT_t*)&RNDISMessageBuffer;\r
- \r
- INITIALIZE_Response->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;\r
- INITIALIZE_Response->MessageLength = sizeof(RNDIS_INITIALIZE_CMPLT_t);\r
- INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;\r
- INITIALIZE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
- \r
- INITIALIZE_Response->MajorVersion = REMOTE_NDIS_VERSION_MAJOR;\r
- INITIALIZE_Response->MinorVersion = REMOTE_NDIS_VERSION_MINOR; \r
- INITIALIZE_Response->DeviceFlags = REMOTE_NDIS_DF_CONNECTIONLESS;\r
- INITIALIZE_Response->Medium = REMOTE_NDIS_MEDIUM_802_3;\r
- INITIALIZE_Response->MaxPacketsPerTransfer = 1;\r
- INITIALIZE_Response->MaxTransferSize = (sizeof(RNDIS_PACKET_MSG_t) + ETHERNET_FRAME_SIZE_MAX);\r
- INITIALIZE_Response->PacketAlignmentFactor = 0;\r
- INITIALIZE_Response->AFListOffset = 0;\r
- INITIALIZE_Response->AFListSize = 0;\r
- \r
- CurrRNDISState = RNDIS_Initialized;\r
- \r
- break;\r
- case REMOTE_NDIS_HALT_MSG:\r
- /* Halt the adapter, reset the adapter state - note that no response should be returned when completed */\r
-\r
- ResponseReady = false;\r
- MessageHeader->MessageLength = 0;\r
-\r
- CurrRNDISState = RNDIS_Uninitialized;\r
-\r
- break;\r
- case REMOTE_NDIS_QUERY_MSG:\r
- /* Request for information about a parameter about the adapter, specified as an OID token */\r
-\r
- ResponseReady = true;\r
- \r
- RNDIS_QUERY_MSG_t* QUERY_Message = (RNDIS_QUERY_MSG_t*)&RNDISMessageBuffer;\r
- RNDIS_QUERY_CMPLT_t* QUERY_Response = (RNDIS_QUERY_CMPLT_t*)&RNDISMessageBuffer;\r
- uint32_t Query_Oid = QUERY_Message->Oid;\r
- \r
- void* QueryData = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +\r
- QUERY_Message->InformationBufferOffset];\r
- void* ResponseData = &RNDISMessageBuffer[sizeof(RNDIS_QUERY_CMPLT_t)]; \r
- uint16_t ResponseSize;\r
-\r
- QUERY_Response->MessageType = REMOTE_NDIS_QUERY_CMPLT;\r
- QUERY_Response->MessageLength = sizeof(RNDIS_QUERY_CMPLT_t);\r
- \r
- if (ProcessNDISQuery(Query_Oid, QueryData, QUERY_Message->InformationBufferLength,\r
- ResponseData, &ResponseSize))\r
- {\r
- QUERY_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
- QUERY_Response->MessageLength += ResponseSize;\r
- \r
- QUERY_Response->InformationBufferLength = ResponseSize;\r
- QUERY_Response->InformationBufferOffset = (sizeof(RNDIS_QUERY_CMPLT_t) - sizeof(RNDIS_Message_Header_t));\r
- }\r
- else\r
- { \r
- QUERY_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;\r
-\r
- QUERY_Response->InformationBufferLength = 0;\r
- QUERY_Response->InformationBufferOffset = 0;\r
- }\r
- \r
- break;\r
- case REMOTE_NDIS_SET_MSG:\r
- /* Request to set a parameter of the adapter, specified as an OID token */\r
- \r
- ResponseReady = true;\r
- \r
- RNDIS_SET_MSG_t* SET_Message = (RNDIS_SET_MSG_t*)&RNDISMessageBuffer;\r
- RNDIS_SET_CMPLT_t* SET_Response = (RNDIS_SET_CMPLT_t*)&RNDISMessageBuffer;\r
- uint32_t SET_Oid = SET_Message->Oid;\r
-\r
- SET_Response->MessageType = REMOTE_NDIS_SET_CMPLT;\r
- SET_Response->MessageLength = sizeof(RNDIS_SET_CMPLT_t);\r
- SET_Response->RequestId = SET_Message->RequestId;\r
-\r
- void* SetData = &RNDISMessageBuffer[sizeof(RNDIS_Message_Header_t) +\r
- SET_Message->InformationBufferOffset];\r
- \r
- if (ProcessNDISSet(SET_Oid, SetData, SET_Message->InformationBufferLength))\r
- SET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
- else\r
- SET_Response->Status = REMOTE_NDIS_STATUS_NOT_SUPPORTED;\r
-\r
- break;\r
- case REMOTE_NDIS_RESET_MSG:\r
- /* Soft reset the adapter */\r
- \r
- ResponseReady = true;\r
- \r
- RNDIS_RESET_CMPLT_t* RESET_Response = (RNDIS_RESET_CMPLT_t*)&RNDISMessageBuffer;\r
-\r
- RESET_Response->MessageType = REMOTE_NDIS_RESET_CMPLT;\r
- RESET_Response->MessageLength = sizeof(RNDIS_RESET_CMPLT_t);\r
- RESET_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
- RESET_Response->AddressingReset = 0;\r
-\r
- break;\r
- case REMOTE_NDIS_KEEPALIVE_MSG:\r
- /* Keep alive message sent to the adapter every 5 seconds when idle to ensure it is still responding */\r
- \r
- ResponseReady = true;\r
- \r
- RNDIS_KEEPALIVE_MSG_t* KEEPALIVE_Message = (RNDIS_KEEPALIVE_MSG_t*)&RNDISMessageBuffer;\r
- RNDIS_KEEPALIVE_CMPLT_t* KEEPALIVE_Response = (RNDIS_KEEPALIVE_CMPLT_t*)&RNDISMessageBuffer;\r
-\r
- KEEPALIVE_Response->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;\r
- KEEPALIVE_Response->MessageLength = sizeof(RNDIS_KEEPALIVE_CMPLT_t);\r
- KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;\r
- KEEPALIVE_Response->Status = REMOTE_NDIS_STATUS_SUCCESS;\r
- \r
- break;\r
- }\r
-}\r
-\r
-/** Processes RNDIS query commands, retrieving information from the adapter and reporting it back to the host. The requested\r
- * parameter is given as an OID value.\r
- *\r
- * \param OId OId value of the parameter being queried\r
- * \param QueryData Pointer to any extra query data being sent by the host to the device inside the RNDIS message buffer\r
- * \param QuerySize Size in bytes of the extra query data being sent by the host\r
- * \param ResponseData Pointer to the start of the query response inside the RNDIS message buffer\r
- * \param ResponseSize Pointer to the size in bytes of the response data being sent to the host\r
- *\r
- * \return Boolean true if the query was handled, false otherwise\r
- */\r
-static bool ProcessNDISQuery(uint32_t OId, void* QueryData, uint16_t QuerySize,\r
- void* ResponseData, uint16_t* ResponseSize)\r
-{\r
- /* Handler for REMOTE_NDIS_QUERY_MSG messages */\r
-\r
- switch (OId)\r
- {\r
- case OID_GEN_SUPPORTED_LIST:\r
- *ResponseSize = sizeof(AdapterSupportedOIDList);\r
- \r
- /* Copy the list of supported NDIS OID tokens to the response buffer */\r
- memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));\r
- \r
- return true;\r
- case OID_GEN_PHYSICAL_MEDIUM:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate that the device is a true ethernet link */\r
- *((uint32_t*)ResponseData) = 0;\r
- \r
- return true;\r
- case OID_GEN_HARDWARE_STATUS:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Always indicate hardware ready */\r
- *((uint32_t*)ResponseData) = NdisHardwareStatusReady;\r
- \r
- return true;\r
- case OID_GEN_MEDIA_SUPPORTED:\r
- case OID_GEN_MEDIA_IN_USE:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate 802.3 (Ethernet) supported by the adapter */\r
- *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIUM_802_3;\r
- \r
- return true;\r
- case OID_GEN_VENDOR_ID:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */\r
- *((uint32_t*)ResponseData) = 0x00FFFFFF;\r
- \r
- return true;\r
- case OID_GEN_MAXIMUM_FRAME_SIZE:\r
- case OID_GEN_TRANSMIT_BLOCK_SIZE:\r
- case OID_GEN_RECEIVE_BLOCK_SIZE:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate that the maximum frame size is the size of the ethernet frame buffer */\r
- *((uint32_t*)ResponseData) = ETHERNET_FRAME_SIZE_MAX;\r
- \r
- return true;\r
- case OID_GEN_VENDOR_DESCRIPTION:\r
- *ResponseSize = sizeof(AdapterVendorDescription);\r
- \r
- /* Copy vendor description string to the response buffer */\r
- memcpy_P(ResponseData, AdapterVendorDescription, sizeof(AdapterVendorDescription));\r
- \r
- return true;\r
- case OID_GEN_MEDIA_CONNECT_STATUS:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Always indicate that the adapter is connected to a network */\r
- *((uint32_t*)ResponseData) = REMOTE_NDIS_MEDIA_STATE_CONNECTED;\r
- \r
- return true;\r
- case OID_GEN_LINK_SPEED:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate 10Mb/s link speed */\r
- *((uint32_t*)ResponseData) = 100000;\r
-\r
- return true;\r
- case OID_802_3_PERMANENT_ADDRESS:\r
- case OID_802_3_CURRENT_ADDRESS:\r
- *ResponseSize = sizeof(MAC_Address_t);\r
- \r
- /* Copy over the fixed adapter MAC to the response buffer */\r
- memcpy_P(ResponseData, &AdapterMACAddress, sizeof(MAC_Address_t));\r
-\r
- return true;\r
- case OID_802_3_MAXIMUM_LIST_SIZE:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate only one multicast address supported */\r
- *((uint32_t*)ResponseData) = 1;\r
- \r
- return true;\r
- case OID_GEN_CURRENT_PACKET_FILTER:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate the current packet filter mask */\r
- *((uint32_t*)ResponseData) = CurrPacketFilter;\r
- \r
- return true; \r
- case OID_GEN_XMIT_OK:\r
- case OID_GEN_RCV_OK:\r
- case OID_GEN_XMIT_ERROR:\r
- case OID_GEN_RCV_ERROR:\r
- case OID_GEN_RCV_NO_BUFFER:\r
- case OID_802_3_RCV_ERROR_ALIGNMENT:\r
- case OID_802_3_XMIT_ONE_COLLISION:\r
- case OID_802_3_XMIT_MORE_COLLISIONS:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Unused statistic OIDs - always return 0 for each */\r
- *((uint32_t*)ResponseData) = 0;\r
- \r
- return true;\r
- case OID_GEN_MAXIMUM_TOTAL_SIZE:\r
- *ResponseSize = sizeof(uint32_t);\r
- \r
- /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */\r
- *((uint32_t*)ResponseData) = (sizeof(RNDISMessageBuffer) + ETHERNET_FRAME_SIZE_MAX);\r
- \r
- return true;\r
- default:\r
- return false;\r
- }\r
-}\r
-\r
-/** Processes RNDIS set commands, setting adapter parameters to values given by the host. The requested parameter is given \r
- * as an OID value.\r
- *\r
- * \param OId OId value of the parameter being set\r
- * \param SetData Pointer to the parameter value in the RNDIS message buffer\r
- * \param SetSize Size in bytes of the parameter value being sent by the host\r
- *\r
- * \return Boolean true if the set was handled, false otherwise\r
- */\r
-static bool ProcessNDISSet(uint32_t OId, void* SetData, uint16_t SetSize)\r
-{\r
- /* Handler for REMOTE_NDIS_SET_MSG messages */\r
-\r
- switch (OId)\r
- {\r
- case OID_GEN_CURRENT_PACKET_FILTER:\r
- /* Save the packet filter mask in case the host queries it again later */\r
- CurrPacketFilter = *((uint32_t*)SetData);\r
- \r
- /* Set the RNDIS state to initialized if the packet filter is non-zero */\r
- CurrRNDISState = ((CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Data_Initialized);\r
- \r
- return true;\r
- case OID_802_3_MULTICAST_LIST:\r
- /* Do nothing - throw away the value from the host as it is unused */\r
- \r
- return true;\r
- default:\r
- return false;\r
- }\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for RNDIS.c.\r
- */\r
-\r
-#ifndef _RNDIS_H_\r
-#define _RNDIS_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <stdbool.h>\r
- \r
- #include "RNDISEthernet.h"\r
- #include "RNDISConstants.h"\r
- #include "Ethernet.h"\r
-\r
- /* Macros: */\r
- /** Physical MAC Address of the USB network adapter */\r
- #define ADAPTER_MAC_ADDRESS {0x02, 0x00, 0x02, 0x00, 0x02, 0x00}\r
- \r
- /** Implemented RNDIS Version Major */\r
- #define REMOTE_NDIS_VERSION_MAJOR 0x01\r
-\r
- /** Implemented RNDIS Version Minor */\r
- #define REMOTE_NDIS_VERSION_MINOR 0x00\r
- \r
- /** RNDIS request to issue a host-to-device NDIS command */\r
- #define REQ_SendEncapsulatedCommand 0x00\r
-\r
- /** RNDIS request to issue a device-to-host NDIS response */\r
- #define REQ_GetEncapsulatedResponse 0x01\r
- \r
- /* Enums: */\r
- /** Enum for the possible NDIS adapter states. */\r
- enum RNDIS_States_t\r
- {\r
- RNDIS_Uninitialized = 0, /**< Adapter currently uninitialized */\r
- RNDIS_Initialized = 1, /**< Adapter currently initialized but not ready for data transfers */\r
- RNDIS_Data_Initialized = 2, /**< Adapter currently initialized and ready for data transfers */\r
- };\r
-\r
- /** Enum for the NDIS hardware states */\r
- enum NDIS_Hardware_Status_t\r
- {\r
- NdisHardwareStatusReady, /**< Hardware Ready to accept commands from the host */\r
- NdisHardwareStatusInitializing, /**< Hardware busy initializing */\r
- NdisHardwareStatusReset, /**< Hardware reset */\r
- NdisHardwareStatusClosing, /**< Hardware currently closing */\r
- NdisHardwareStatusNotReady /**< Hardware not ready to accept commands from the host */\r
- };\r
-\r
- /* Type Defines: */\r
- /** Type define for a RNDIS message header, sent before RNDIS messages */\r
- typedef struct\r
- {\r
- uint32_t MessageType; /**< RNDIS message type, a REMOTE_NDIS_*_MSG constant */\r
- uint32_t MessageLength; /**< Total length of the RNDIS message, in bytes */\r
- } RNDIS_Message_Header_t;\r
-\r
- /** Type define for a RNDIS packet message, used to encapsulate Ethernet packets sent to and from the adapter */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t DataOffset;\r
- uint32_t DataLength;\r
- uint32_t OOBDataOffset;\r
- uint32_t OOBDataLength;\r
- uint32_t NumOOBDataElements;\r
- uint32_t PerPacketInfoOffset;\r
- uint32_t PerPacketInfoLength;\r
- uint32_t VcHandle;\r
- uint32_t Reserved;\r
- } RNDIS_PACKET_MSG_t;\r
- \r
- /** Type define for a RNDIS Initialize command message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- \r
- uint32_t MajorVersion;\r
- uint32_t MinorVersion;\r
- uint32_t MaxTransferSize;\r
- } RNDIS_INITIALIZE_MSG_t;\r
- \r
- /** Type define for a RNDIS Initialize complete response message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- uint32_t Status;\r
- \r
- uint32_t MajorVersion;\r
- uint32_t MinorVersion;\r
- uint32_t DeviceFlags;\r
- uint32_t Medium;\r
- uint32_t MaxPacketsPerTransfer;\r
- uint32_t MaxTransferSize;\r
- uint32_t PacketAlignmentFactor;\r
- uint32_t AFListOffset;\r
- uint32_t AFListSize;\r
- } RNDIS_INITIALIZE_CMPLT_t;\r
- \r
- /** Type define for a RNDIS Keepalive command message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- } RNDIS_KEEPALIVE_MSG_t;\r
-\r
- /** Type define for a RNDIS Keepalive complete message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- uint32_t Status;\r
- } RNDIS_KEEPALIVE_CMPLT_t;\r
-\r
- /** Type define for a RNDIS Reset complete message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t Status;\r
-\r
- uint32_t AddressingReset;\r
- } RNDIS_RESET_CMPLT_t;\r
- \r
- /** Type define for a RNDIS Set command message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- \r
- uint32_t Oid;\r
- uint32_t InformationBufferLength;\r
- uint32_t InformationBufferOffset;\r
- uint32_t DeviceVcHandle;\r
- } RNDIS_SET_MSG_t;\r
-\r
- /** Type define for a RNDIS Set complete response message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- uint32_t Status;\r
- } RNDIS_SET_CMPLT_t;\r
- \r
- /** Type define for a RNDIS Query command message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- \r
- uint32_t Oid;\r
- uint32_t InformationBufferLength;\r
- uint32_t InformationBufferOffset;\r
- uint32_t DeviceVcHandle;\r
- } RNDIS_QUERY_MSG_t;\r
- \r
- /** Type define for a RNDIS Query complete response message */\r
- typedef struct\r
- {\r
- uint32_t MessageType;\r
- uint32_t MessageLength;\r
- uint32_t RequestId;\r
- uint32_t Status;\r
- \r
- uint32_t InformationBufferLength;\r
- uint32_t InformationBufferOffset;\r
- } RNDIS_QUERY_CMPLT_t;\r
- \r
- /* External Variables: */\r
- extern uint8_t RNDISMessageBuffer[];\r
- extern RNDIS_Message_Header_t* MessageHeader;\r
- extern bool ResponseReady;\r
- extern uint8_t CurrRNDISState;\r
-\r
- /* Function Prototypes: */\r
- void ProcessRNDISControlMessage(void);\r
-\r
- #if defined(INCLUDE_FROM_RNDIS_C)\r
- static bool ProcessNDISQuery(uint32_t OId, void* QueryData, uint16_t QuerySize,\r
- void* ResponseData, uint16_t* ResponseSize);\r
- static bool ProcessNDISSet(uint32_t OId, void* SetData, uint16_t SetSize); \r
- #endif\r
- \r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * RNDIS specification related constants. For more information on these\r
- * constants, please refer to the Microsoft RNDIS specification.\r
- */\r
- \r
-#ifndef _RNDIS_CONSTANTS_H_\r
-#define _RNDIS_CONSTANTS_H_\r
-\r
- /* Macros: */\r
- #define REMOTE_NDIS_PACKET_MSG 0x00000001UL\r
- #define REMOTE_NDIS_INITIALIZE_MSG 0x00000002UL\r
- #define REMOTE_NDIS_HALT_MSG 0x00000003UL\r
- #define REMOTE_NDIS_QUERY_MSG 0x00000004UL\r
- #define REMOTE_NDIS_SET_MSG 0x00000005UL\r
- #define REMOTE_NDIS_RESET_MSG 0x00000006UL\r
- #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007UL\r
- #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008UL\r
-\r
- #define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002UL\r
- #define REMOTE_NDIS_QUERY_CMPLT 0x80000004UL\r
- #define REMOTE_NDIS_SET_CMPLT 0x80000005UL\r
- #define REMOTE_NDIS_RESET_CMPLT 0x80000006UL\r
- #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008UL\r
- \r
- #define REMOTE_NDIS_STATUS_SUCCESS 0x00000000UL\r
- #define REMOTE_NDIS_STATUS_FAILURE 0xC0000001UL\r
- #define REMOTE_NDIS_STATUS_INVALID_DATA 0xC0010015UL\r
- #define REMOTE_NDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL\r
- #define REMOTE_NDIS_STATUS_MEDIA_CONNECT 0x4001000BUL\r
- #define REMOTE_NDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL\r
- \r
- #define REMOTE_NDIS_MEDIA_STATE_CONNECTED 0x00000000UL\r
- #define REMOTE_NDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL\r
- \r
- #define REMOTE_NDIS_MEDIUM_802_3 0x00000000UL\r
- \r
- #define REMOTE_NDIS_DF_CONNECTIONLESS 0x00000001UL\r
- #define REMOTE_NDIS_DF_CONNECTION_ORIENTED 0x00000002UL\r
- \r
- #define OID_GEN_SUPPORTED_LIST 0x00010101UL\r
- #define OID_GEN_HARDWARE_STATUS 0x00010102UL\r
- #define OID_GEN_MEDIA_SUPPORTED 0x00010103UL\r
- #define OID_GEN_MEDIA_IN_USE 0x00010104UL\r
- #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL\r
- #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL\r
- #define OID_GEN_LINK_SPEED 0x00010107UL\r
- #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL\r
- #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL\r
- #define OID_GEN_VENDOR_ID 0x0001010CUL\r
- #define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL\r
- #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL\r
- #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL\r
- #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL\r
- #define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL\r
- #define OID_GEN_XMIT_OK 0x00020101UL\r
- #define OID_GEN_RCV_OK 0x00020102UL\r
- #define OID_GEN_XMIT_ERROR 0x00020103UL\r
- #define OID_GEN_RCV_ERROR 0x00020104UL\r
- #define OID_GEN_RCV_NO_BUFFER 0x00020105UL\r
- #define OID_802_3_PERMANENT_ADDRESS 0x01010101UL\r
- #define OID_802_3_CURRENT_ADDRESS 0x01010102UL\r
- #define OID_802_3_MULTICAST_LIST 0x01010103UL\r
- #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL\r
- #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL\r
- #define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL\r
- #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL\r
-\r
-#endif\r
#include <stdio.h>\r
\r
#include "Descriptors.h"\r
- #include "RNDIS.h"\r
- #include "Ethernet.h"\r
- #include "TCP.h"\r
- #include "ARP.h"\r
- #include "Webserver.h"\r
+\r
+ #include "Lib/RNDIS.h"\r
+ #include "Lib/Ethernet.h"\r
+ #include "Lib/TCP.h"\r
+ #include "Lib/ARP.h"\r
+ #include "Lib/Webserver.h"\r
\r
#include <LUFA/Version.h> // Library Version Information\r
#include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Transmission Control Protocol (TCP) packet handling routines. This protocol handles the reliable in-order transmission\r
- * and reception of packets to and from devices on a network, to "ports" on the device. It is used in situations where data\r
- * delivery must be reliable and correct, e.g. HTTP, TELNET and most other non-streaming protocols.\r
- */\r
- \r
-#define INCLUDE_FROM_TCP_C\r
-#include "TCP.h"\r
-\r
-/* Global Variables: */\r
-/** Port state table array. This contains the current status of TCP ports in the device. To save on space, only open ports are\r
- * stored - closed ports may be overwritten at any time, and the system will assume any ports not present in the array are closed. This\r
- * allows for MAX_OPEN_TCP_PORTS to be less than the number of ports used by the application if desired.\r
- */\r
-TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS];\r
-\r
-/** Connection state table array. This contains the current status of TCP connections in the device. To save on space, only active\r
- * (non-closed) connections are stored - closed connections may be overwritten at any time, and the system will assume any connections\r
- * not present in the array are closed.\r
- */\r
-TCP_ConnectionState_t ConnectionStateTable[MAX_TCP_CONNECTIONS];\r
-\r
-\r
-/** Task to handle the calling of each registered application's callback function, to process and generate TCP packets at the application\r
- * level. If an application produces a response, this task constructs the appropriate Ethernet frame and places it into the Ethernet OUT\r
- * buffer for later transmission.\r
- */\r
-TASK(TCP_Task)\r
-{\r
- /* Task to hand off TCP packets to and from the listening applications. */\r
-\r
- /* Run each application in sequence, to process incoming and generate outgoing packets */\r
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
- {\r
- /* Find the corresponding port entry in the port table */\r
- for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
- {\r
- /* Run the application handler for the port */\r
- if ((PortStateTable[PTableEntry].Port == ConnectionStateTable[CSTableEntry].Port) && \r
- (PortStateTable[PTableEntry].State == TCP_Port_Open))\r
- {\r
- PortStateTable[PTableEntry].ApplicationHandler(&ConnectionStateTable[CSTableEntry], &ConnectionStateTable[CSTableEntry].Info.Buffer);\r
- }\r
- }\r
- }\r
- \r
- /* Bail out early if there is already a frame waiting to be sent in the Ethernet OUT buffer */\r
- if (FrameOUT.FrameInBuffer)\r
- return;\r
- \r
- /* Send response packets from each application as the TCP packet buffers are filled by the applications */\r
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
- {\r
- /* For each completely received packet, pass it along to the listening application */\r
- if ((ConnectionStateTable[CSTableEntry].Info.Buffer.Direction == TCP_PACKETDIR_OUT) &&\r
- (ConnectionStateTable[CSTableEntry].Info.Buffer.Ready))\r
- {\r
- Ethernet_Frame_Header_t* FrameOUTHeader = (Ethernet_Frame_Header_t*)&FrameOUT.FrameData;\r
- IP_Header_t* IPHeaderOUT = (IP_Header_t*)&FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t)];\r
- TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)&FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +\r
- sizeof(IP_Header_t)]; \r
- void* TCPDataOUT = &FrameOUT.FrameData[sizeof(Ethernet_Frame_Header_t) +\r
- sizeof(IP_Header_t) +\r
- sizeof(TCP_Header_t)];\r
-\r
- uint16_t PacketSize = ConnectionStateTable[CSTableEntry].Info.Buffer.Length;\r
-\r
- /* Fill out the TCP data */\r
- TCPHeaderOUT->SourcePort = ConnectionStateTable[CSTableEntry].Port;\r
- TCPHeaderOUT->DestinationPort = ConnectionStateTable[CSTableEntry].RemotePort;\r
- TCPHeaderOUT->SequenceNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut);\r
- TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionStateTable[CSTableEntry].Info.SequenceNumberIn);\r
- TCPHeaderOUT->DataOffset = (sizeof(TCP_Header_t) / sizeof(uint32_t));\r
- TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE);\r
-\r
- TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
- TCPHeaderOUT->UrgentPointer = 0;\r
- TCPHeaderOUT->Checksum = 0;\r
- TCPHeaderOUT->Reserved = 0;\r
-\r
- memcpy(TCPDataOUT, ConnectionStateTable[CSTableEntry].Info.Buffer.Data, PacketSize);\r
- \r
- ConnectionStateTable[CSTableEntry].Info.SequenceNumberOut += PacketSize;\r
-\r
- TCPHeaderOUT->Checksum = TCP_Checksum16(TCPHeaderOUT, ServerIPAddress,\r
- ConnectionStateTable[CSTableEntry].RemoteAddress,\r
- (sizeof(TCP_Header_t) + PacketSize));\r
-\r
- PacketSize += sizeof(TCP_Header_t);\r
-\r
- /* Fill out the response IP header */\r
- IPHeaderOUT->TotalLength = SwapEndian_16(sizeof(IP_Header_t) + PacketSize);\r
- IPHeaderOUT->TypeOfService = 0;\r
- IPHeaderOUT->HeaderLength = (sizeof(IP_Header_t) / sizeof(uint32_t));\r
- IPHeaderOUT->Version = 4;\r
- IPHeaderOUT->Flags = 0;\r
- IPHeaderOUT->FragmentOffset = 0;\r
- IPHeaderOUT->Identification = 0;\r
- IPHeaderOUT->HeaderChecksum = 0;\r
- IPHeaderOUT->Protocol = PROTOCOL_TCP;\r
- IPHeaderOUT->TTL = DEFAULT_TTL;\r
- IPHeaderOUT->SourceAddress = ServerIPAddress;\r
- IPHeaderOUT->DestinationAddress = ConnectionStateTable[CSTableEntry].RemoteAddress;\r
- \r
- IPHeaderOUT->HeaderChecksum = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t));\r
- \r
- PacketSize += sizeof(IP_Header_t);\r
- \r
- /* Fill out the response Ethernet frame header */\r
- FrameOUTHeader->Source = ServerMACAddress;\r
- FrameOUTHeader->Destination = (MAC_Address_t){{0x02, 0x00, 0x02, 0x00, 0x02, 0x00}};\r
- FrameOUTHeader->EtherType = SwapEndian_16(ETHERTYPE_IPV4);\r
-\r
- PacketSize += sizeof(Ethernet_Frame_Header_t);\r
-\r
- /* Set the response length in the buffer and indicate that a response is ready to be sent */\r
- FrameOUT.FrameLength = PacketSize;\r
- FrameOUT.FrameInBuffer = true;\r
- \r
- ConnectionStateTable[CSTableEntry].Info.Buffer.Ready = false;\r
- \r
- break;\r
- }\r
- }\r
-}\r
-\r
-/** Initializes the TCP protocol handler, clearing the port and connection state tables. This must be called before TCP packets are\r
- * processed.\r
- */\r
-void TCP_Init(void)\r
-{\r
- /* Initialize the port state table with all CLOSED entries */\r
- for (uint8_t PTableEntry = 0; PTableEntry < MAX_OPEN_TCP_PORTS; PTableEntry++)\r
- PortStateTable[PTableEntry].State = TCP_Port_Closed;\r
-\r
- /* Initialize the connection table with all CLOSED entries */\r
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
- ConnectionStateTable[CSTableEntry].State = TCP_Connection_Closed;\r
-}\r
-\r
-/** Sets the state and callback handler of the given port, specified in big endian to the given state.\r
- *\r
- * \param Port Port whose state and callback function to set, specified in big endian\r
- * \param State New state of the port, a value from the TCP_PortStates_t enum\r
- * \param Handler Application callback handler for the port\r
- *\r
- * \return Boolean true if the port state was set, false otherwise (no more space in the port state table)\r
- */\r
-bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*))\r
-{\r
- /* Note, Port number should be specified in BIG endian to simplify network code */\r
-\r
- /* Check to see if the port entry is already in the port state table */\r
- for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
- {\r
- /* Find existing entry for the port in the table, update it if found */\r
- if (PortStateTable[PTableEntry].Port == Port)\r
- {\r
- PortStateTable[PTableEntry].State = State;\r
- PortStateTable[PTableEntry].ApplicationHandler = Handler;\r
- return true;\r
- }\r
- }\r
-\r
- /* Check if trying to open the port -- if so we need to find an unused (closed) entry and replace it */\r
- if (State == TCP_Port_Open)\r
- {\r
- for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
- {\r
- /* Find a closed port entry in the table, change it to the given port and state */\r
- if (PortStateTable[PTableEntry].State == TCP_Port_Closed)\r
- {\r
- PortStateTable[PTableEntry].Port = Port;\r
- PortStateTable[PTableEntry].State = State;\r
- PortStateTable[PTableEntry].ApplicationHandler = Handler;\r
- return true;\r
- }\r
- }\r
- \r
- /* Port not in table and no room to add it, return failure */\r
- return false;\r
- }\r
- else\r
- {\r
- /* Port not in table but trying to close it, so operation successful */\r
- return true;\r
- }\r
-}\r
-\r
-/** Retrieves the current state of a given TCP port, specified in big endian.\r
- *\r
- * \param Port TCP port whose state is to be retrieved, given in big-endian\r
- *\r
- * \return A value from the TCP_PortStates_t enum\r
- */\r
-uint8_t TCP_GetPortState(uint16_t Port)\r
-{\r
- /* Note, Port number should be specified in BIG endian to simplify network code */\r
-\r
- for (uint8_t PTableEntry = 0; PTableEntry < MAX_TCP_CONNECTIONS; PTableEntry++)\r
- {\r
- /* Find existing entry for the port in the table, return the port status if found */\r
- if (PortStateTable[PTableEntry].Port == Port)\r
- return PortStateTable[PTableEntry].State;\r
- }\r
- \r
- /* Port not in table, assume closed */\r
- return TCP_Port_Closed;\r
-}\r
-\r
-/** Sets the connection state of the given port, remote address and remote port to the given TCP connection state. If the\r
- * connection exists in the connection state table it is updated, otherwise it is created if possible.\r
- *\r
- * \param Port TCP port of the connection on the device, specified in big endian\r
- * \param RemoteAddress Remote protocol IP address of the connected device\r
- * \param RemotePort TCP port of the remote device in the connection, specified in big endian\r
- * \param State TCP connection state, a value from the TCP_ConnectionStates_t enum\r
- *\r
- * \return Boolean true if the connection was updated or created, false otherwise (no more space in the connection state table)\r
- */\r
-bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State)\r
-{\r
- /* Note, Port number should be specified in BIG endian to simplify network code */\r
-\r
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
- {\r
- /* Find port entry in the table */\r
- if ((ConnectionStateTable[CSTableEntry].Port == Port) &&\r
- IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&\r
- ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)\r
- {\r
- ConnectionStateTable[CSTableEntry].State = State;\r
- return true;\r
- }\r
- }\r
- \r
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
- {\r
- /* Find empty entry in the table */\r
- if (ConnectionStateTable[CSTableEntry].State == TCP_Connection_Closed)\r
- {\r
- ConnectionStateTable[CSTableEntry].Port = Port;\r
- ConnectionStateTable[CSTableEntry].RemoteAddress = RemoteAddress; \r
- ConnectionStateTable[CSTableEntry].RemotePort = RemotePort;\r
- ConnectionStateTable[CSTableEntry].State = State;\r
- return true;\r
- }\r
- }\r
- \r
- return false;\r
-}\r
-\r
-/** Retrieves the current state of a given TCP connection to a host.\r
- *\r
- * \param Port TCP port on the device in the connection, specified in big endian\r
- * \param RemoteAddress Remote protocol IP address of the connected host\r
- * \param RemotePort Remote TCP port of the connected host, specified in big endian\r
- *\r
- * \return A value from the TCP_ConnectionStates_t enum\r
- */\r
-uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort)\r
-{\r
- /* Note, Port number should be specified in BIG endian to simplify network code */\r
-\r
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
- {\r
- /* Find port entry in the table */\r
- if ((ConnectionStateTable[CSTableEntry].Port == Port) &&\r
- IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&\r
- ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)\r
- \r
- {\r
- return ConnectionStateTable[CSTableEntry].State;\r
- }\r
- }\r
- \r
- return TCP_Connection_Closed;\r
-}\r
-\r
-/** Retrieves the connection info structure of a given connection to a host.\r
- *\r
- * \param Port TCP port on the device in the connection, specified in big endian\r
- * \param RemoteAddress Remote protocol IP address of the connected host\r
- * \param RemotePort Remote TCP port of the connected host, specified in big endian\r
- *\r
- * \return ConnectionInfo structure of the connection if found, NULL otherwise\r
- */\r
-TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort)\r
-{\r
- /* Note, Port number should be specified in BIG endian to simplify network code */\r
-\r
- for (uint8_t CSTableEntry = 0; CSTableEntry < MAX_TCP_CONNECTIONS; CSTableEntry++)\r
- {\r
- /* Find port entry in the table */\r
- if ((ConnectionStateTable[CSTableEntry].Port == Port) &&\r
- IP_COMPARE(&ConnectionStateTable[CSTableEntry].RemoteAddress, &RemoteAddress) &&\r
- ConnectionStateTable[CSTableEntry].RemotePort == RemotePort)\r
- {\r
- return &ConnectionStateTable[CSTableEntry].Info;\r
- }\r
- }\r
- \r
- return NULL;\r
-}\r
-\r
-/** Processes a TCP packet inside an Ethernet frame, and writes the appropriate response\r
- * to the output Ethernet frame if one is created by a application handler.\r
- *\r
- * \param IPHeaderInStart Pointer to the start of the incoming packet's IP header\r
- * \param TCPHeaderInStart Pointer to the start of the incoming packet's TCP header\r
- * \param TCPHeaderOutStart Pointer to the start of the outgoing packet's TCP header\r
- *\r
- * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE if no\r
- * response was generated, NO_PROCESS if the packet processing was deferred until the\r
- * next Ethernet packet handler iteration\r
- */\r
-int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart)\r
-{\r
- IP_Header_t* IPHeaderIN = (IP_Header_t*)IPHeaderInStart;\r
- TCP_Header_t* TCPHeaderIN = (TCP_Header_t*)TCPHeaderInStart;\r
- TCP_Header_t* TCPHeaderOUT = (TCP_Header_t*)TCPHeaderOutStart;\r
-\r
- TCP_ConnectionInfo_t* ConnectionInfo;\r
- \r
- DecodeTCPHeader(TCPHeaderInStart);\r
-\r
- bool PacketResponse = false;\r
- \r
- /* Check if the destination port is open and allows incoming connections */\r
- if (TCP_GetPortState(TCPHeaderIN->DestinationPort) == TCP_Port_Open)\r
- {\r
- /* Detect SYN from host to start a connection */\r
- if (TCPHeaderIN->Flags & TCP_FLAG_SYN)\r
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort, TCP_Connection_Listen);\r
-\r
- /* Detect RST from host to abort existing connection */\r
- if (TCPHeaderIN->Flags & TCP_FLAG_RST)\r
- {\r
- TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK); \r
- PacketResponse = true;\r
- \r
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort, TCP_Connection_Closed); \r
- }\r
- else\r
- {\r
- /* Process the incoming TCP packet based on the current connection state for the sender and port */\r
- switch (TCP_GetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort))\r
- {\r
- case TCP_Connection_Listen:\r
- if (TCPHeaderIN->Flags == TCP_FLAG_SYN)\r
- {\r
- /* SYN connection when closed starts a connection with a peer */\r
-\r
- TCPHeaderOUT->Flags = (TCP_FLAG_SYN | TCP_FLAG_ACK); \r
- PacketResponse = true;\r
- \r
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort,\r
- TCP_Connection_SYNReceived);\r
- \r
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress, TCPHeaderIN->SourcePort);\r
-\r
- ConnectionInfo->SequenceNumberIn = (SwapEndian_32(TCPHeaderIN->SequenceNumber) + 1);\r
- ConnectionInfo->SequenceNumberOut = 0;\r
- ConnectionInfo->Buffer.InUse = false;\r
- }\r
- \r
- break;\r
- case TCP_Connection_SYNReceived:\r
- if (TCPHeaderIN->Flags == TCP_FLAG_ACK)\r
- {\r
- /* ACK during the connection process completes the connection to a peer */\r
-\r
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort, TCP_Connection_Established);\r
-\r
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort);\r
- \r
- ConnectionInfo->SequenceNumberOut++;\r
- }\r
- \r
- break;\r
- case TCP_Connection_Established:\r
- if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))\r
- {\r
- /* FIN ACK when connected to a peer starts the finalization process */\r
- \r
- TCPHeaderOUT->Flags = (TCP_FLAG_FIN | TCP_FLAG_ACK); \r
- PacketResponse = true;\r
- \r
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort, TCP_Connection_CloseWait);\r
-\r
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort);\r
-\r
- ConnectionInfo->SequenceNumberIn++;\r
- ConnectionInfo->SequenceNumberOut++;\r
- }\r
- else if ((TCPHeaderIN->Flags == TCP_FLAG_ACK) || (TCPHeaderIN->Flags == (TCP_FLAG_ACK | TCP_FLAG_PSH)))\r
- {\r
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort);\r
-\r
- /* Check if the buffer is currently in use either by a buffered data to send, or receive */ \r
- if ((ConnectionInfo->Buffer.InUse == false) && (ConnectionInfo->Buffer.Ready == false))\r
- { \r
- ConnectionInfo->Buffer.Direction = TCP_PACKETDIR_IN;\r
- ConnectionInfo->Buffer.InUse = true;\r
- ConnectionInfo->Buffer.Length = 0;\r
- }\r
- \r
- /* Check if the buffer has been claimed by us to read in data from the peer */\r
- if ((ConnectionInfo->Buffer.Direction == TCP_PACKETDIR_IN) &&\r
- (ConnectionInfo->Buffer.Length != TCP_WINDOW_SIZE))\r
- {\r
- uint16_t IPOffset = (IPHeaderIN->HeaderLength * sizeof(uint32_t));\r
- uint16_t TCPOffset = (TCPHeaderIN->DataOffset * sizeof(uint32_t));\r
- uint16_t DataLength = (SwapEndian_16(IPHeaderIN->TotalLength) - IPOffset - TCPOffset);\r
-\r
- /* Copy the packet data into the buffer */\r
- memcpy(&ConnectionInfo->Buffer.Data[ConnectionInfo->Buffer.Length],\r
- &((uint8_t*)TCPHeaderInStart)[TCPOffset],\r
- DataLength);\r
-\r
- ConnectionInfo->SequenceNumberIn += DataLength;\r
- ConnectionInfo->Buffer.Length += DataLength;\r
- \r
- /* Check if the buffer is full or if the PSH flag is set, if so indicate buffer ready */\r
- if ((!(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length)) || (TCPHeaderIN->Flags & TCP_FLAG_PSH))\r
- {\r
- ConnectionInfo->Buffer.InUse = false;\r
- ConnectionInfo->Buffer.Ready = true;\r
-\r
- TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
- PacketResponse = true;\r
- }\r
- }\r
- else\r
- {\r
- /* Buffer is currently in use by the application, defer processing of the incoming packet */\r
- return NO_PROCESS;\r
- }\r
- }\r
- \r
- break;\r
- case TCP_Connection_Closing:\r
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort);\r
-\r
- TCPHeaderOUT->Flags = (TCP_FLAG_ACK | TCP_FLAG_FIN);\r
- PacketResponse = true;\r
- \r
- ConnectionInfo->Buffer.InUse = false;\r
- \r
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort, TCP_Connection_FINWait1);\r
-\r
- break;\r
- case TCP_Connection_FINWait1:\r
- if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))\r
- {\r
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort);\r
-\r
- TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
- PacketResponse = true;\r
-\r
- ConnectionInfo->SequenceNumberIn++;\r
- ConnectionInfo->SequenceNumberOut++;\r
- \r
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort, TCP_Connection_Closed);\r
- }\r
- else if (TCPHeaderIN->Flags == TCP_FLAG_ACK)\r
- {\r
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort, TCP_Connection_FINWait2);\r
- }\r
- \r
- break;\r
- case TCP_Connection_FINWait2:\r
- if (TCPHeaderIN->Flags == (TCP_FLAG_FIN | TCP_FLAG_ACK))\r
- {\r
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort);\r
-\r
- TCPHeaderOUT->Flags = TCP_FLAG_ACK;\r
- PacketResponse = true;\r
-\r
- ConnectionInfo->SequenceNumberIn++;\r
- ConnectionInfo->SequenceNumberOut++;\r
- \r
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort, TCP_Connection_Closed);\r
- }\r
- \r
- break;\r
- case TCP_Connection_CloseWait:\r
- if (TCPHeaderIN->Flags == TCP_FLAG_ACK)\r
- {\r
- TCP_SetConnectionState(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort, TCP_Connection_Closed);\r
- }\r
- \r
- break;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- /* Port is not open, indicate via a RST/ACK response to the sender */\r
- TCPHeaderOUT->Flags = (TCP_FLAG_RST | TCP_FLAG_ACK); \r
- PacketResponse = true;\r
- }\r
- \r
- /* Check if we need to respond to the sent packet */\r
- if (PacketResponse)\r
- {\r
- ConnectionInfo = TCP_GetConnectionInfo(TCPHeaderIN->DestinationPort, IPHeaderIN->SourceAddress,\r
- TCPHeaderIN->SourcePort);\r
-\r
- TCPHeaderOUT->SourcePort = TCPHeaderIN->DestinationPort;\r
- TCPHeaderOUT->DestinationPort = TCPHeaderIN->SourcePort;\r
- TCPHeaderOUT->SequenceNumber = SwapEndian_32(ConnectionInfo->SequenceNumberOut);\r
- TCPHeaderOUT->AcknowledgmentNumber = SwapEndian_32(ConnectionInfo->SequenceNumberIn);\r
- TCPHeaderOUT->DataOffset = (sizeof(TCP_Header_t) / sizeof(uint32_t));\r
- \r
- if (!(ConnectionInfo->Buffer.InUse))\r
- TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE);\r
- else\r
- TCPHeaderOUT->WindowSize = SwapEndian_16(TCP_WINDOW_SIZE - ConnectionInfo->Buffer.Length);\r
-\r
- TCPHeaderOUT->UrgentPointer = 0;\r
- TCPHeaderOUT->Checksum = 0;\r
- TCPHeaderOUT->Reserved = 0;\r
- \r
- TCPHeaderOUT->Checksum = TCP_Checksum16(TCPHeaderOUT, IPHeaderIN->DestinationAddress,\r
- IPHeaderIN->SourceAddress, sizeof(TCP_Header_t)); \r
-\r
- return sizeof(TCP_Header_t); \r
- }\r
-\r
- return NO_RESPONSE;\r
-}\r
-\r
-/** Calculates the appropriate TCP checksum, consisting of the addition of the one's compliment of each word,\r
- * complimented.\r
- *\r
- * \param TCPHeaderOutStart Pointer to the start of the packet's outgoing TCP header\r
- * \param SourceAddress Source protocol IP address of the outgoing IP header\r
- * \param SourceAddress DestinationAddress protocol IP address of the outgoing IP header\r
- * \param TCPOutSize Size in bytes of the TCP data header and payload\r
- *\r
- * \return A 16-bit TCP checksum value\r
- */\r
-static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress,\r
- IP_Address_t DestinationAddress, uint16_t TCPOutSize)\r
-{\r
- uint32_t Checksum = 0;\r
- \r
- /* TCP/IP checksums are the addition of the one's compliment of each word including the IP pseudo-header,\r
- complimented */\r
- \r
- Checksum += ((uint16_t*)&SourceAddress)[0];\r
- Checksum += ((uint16_t*)&SourceAddress)[1];\r
- Checksum += ((uint16_t*)&DestinationAddress)[0];\r
- Checksum += ((uint16_t*)&DestinationAddress)[1];\r
- Checksum += SwapEndian_16(PROTOCOL_TCP);\r
- Checksum += SwapEndian_16(TCPOutSize);\r
-\r
- for (uint8_t CurrWord = 0; CurrWord < (TCPOutSize >> 1); CurrWord++)\r
- Checksum += ((uint16_t*)TCPHeaderOutStart)[CurrWord];\r
- \r
- if (TCPOutSize & 0x01)\r
- Checksum += (((uint16_t*)TCPHeaderOutStart)[TCPOutSize >> 1] & 0x00FF);\r
- \r
- while (Checksum & 0xFFFF0000)\r
- Checksum = ((Checksum & 0xFFFF) + (Checksum >> 16));\r
- \r
- return ~Checksum;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for TCP.c.\r
- */\r
-\r
-#ifndef _TCP_H_\r
-#define _TCP_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <stdbool.h>\r
- \r
- #include <LUFA/Scheduler/Scheduler.h>\r
- \r
- #include "EthernetProtocols.h"\r
- #include "Ethernet.h"\r
- #include "ProtocolDecoders.h"\r
- \r
- /* Macros: */\r
- /** Maximum number of TCP ports which can be open at the one time */\r
- #define MAX_OPEN_TCP_PORTS 1\r
-\r
- /** Maximum number of TCP connections which can be sustained at the one time */\r
- #define MAX_TCP_CONNECTIONS 1\r
-\r
- /** TCP window size, giving the maximum number of bytes which can be buffered at the one time */\r
- #define TCP_WINDOW_SIZE 1024\r
- \r
- /** Port number for HTTP transmissions */\r
- #define TCP_PORT_HTTP SwapEndian_16(80)\r
- \r
- /** Data direction indicator for a TCP application buffer, indicating data from host-to-device */\r
- #define TCP_PACKETDIR_IN false\r
-\r
- /** Data direction indicator for a TCP application buffer, indicating data from device-to-host */\r
- #define TCP_PACKETDIR_OUT true\r
- \r
- /** Congestion Window Reduced TCP flag mask */\r
- #define TCP_FLAG_CWR (1 << 7)\r
-\r
- /** Explicit Congestion Notification TCP flag mask */\r
- #define TCP_FLAG_ECE (1 << 6)\r
-\r
- /** Urgent TCP flag mask */\r
- #define TCP_FLAG_URG (1 << 5)\r
-\r
- /** Data Acknowledge TCP flag mask */\r
- #define TCP_FLAG_ACK (1 << 4)\r
-\r
- /** Data Push TCP flag mask */\r
- #define TCP_FLAG_PSH (1 << 3)\r
-\r
- /** Reset TCP flag mask */\r
- #define TCP_FLAG_RST (1 << 2)\r
-\r
- /** Synchronize TCP flag mask */\r
- #define TCP_FLAG_SYN (1 << 1)\r
-\r
- /** Connection Finalize TCP flag mask */\r
- #define TCP_FLAG_FIN (1 << 0)\r
- \r
- /** Application macro: Determines if the given application buffer contains a packet received from the host\r
- *\r
- * \param Buffer Application buffer to check\r
- *\r
- * \return Boolean true if the buffer contains a packet from the host, false otherwise\r
- */\r
- #define TCP_APP_HAS_RECEIVED_PACKET(Buffer) (Buffer->Ready && (Buffer->Direction == TCP_PACKETDIR_IN))\r
-\r
- /** Application macro: Indicates if the application buffer is currently locked by the application for device-to-host transfers.\r
- *\r
- * \param Buffer Application buffer to check\r
- *\r
- * \return Boolean true if the buffer has been captured by the application for device-to-host transmissions, false otherwise\r
- */\r
- #define TCP_APP_HAVE_CAPTURED_BUFFER(Buffer) (!(Buffer->Ready) && Buffer->InUse && \\r
- (Buffer->Direction == TCP_PACKETDIR_OUT))\r
-\r
- /** Application macro: Indicates if the application can lock the buffer for multiple continued device-to-host transmissions.\r
- *\r
- * \param Buffer Application buffer to check\r
- *\r
- * \return Boolean true if the buffer may be captured by the application for device-to-host transmissions, false otherwise\r
- */\r
- #define TCP_APP_CAN_CAPTURE_BUFFER(Buffer) Buffer->InUse\r
-\r
- /** Application macro: Captures the application buffer, locking it for device-to-host transmissions only. This should be\r
- * performed when the application needs to transmit several packets worth of data in succession with no interruptions from the host.\r
- *\r
- * \note The application must check that the buffer can be locked first using TCP_APP_CAN_CAPTURE_BUFFER().\r
- *\r
- * \param Buffer Application buffer to lock\r
- */\r
- #define TCP_APP_CAPTURE_BUFFER(Buffer) MACROS{ Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->InUse = true; }MACROE\r
-\r
- /** Application macro: Releases a captured application buffer, allowing for host-to-device packets to be received.\r
- *\r
- * \param Buffer Application buffer to release\r
- */\r
- #define TCP_APP_RELEASE_BUFFER(Buffer) MACROS{ Buffer->InUse = false; }MACROE\r
-\r
- /** Application macro: Sends the contents of the given application buffer to the host.\r
- *\r
- * \param Buffer Application buffer to send\r
- * \param Len Length of data contained in the buffer\r
- */\r
- #define TCP_APP_SEND_BUFFER(Buffer, Len) MACROS{ Buffer->Direction = TCP_PACKETDIR_OUT; Buffer->Length = Len; Buffer->Ready = true; }MACROE\r
-\r
- /** Application macro: Clears the application buffer, ready for a packet to be written to it.\r
- *\r
- * \param Buffer Application buffer to clear\r
- */\r
- #define TCP_APP_CLEAR_BUFFER(Buffer) MACROS{ Buffer->Ready = false; Buffer->Length = 0; }MACROE\r
- \r
- /** Application macro: Closes an open connection to a host.\r
- *\r
- * \param Connection Open TCP connection to close\r
- */\r
- #define TCP_APP_CLOSECONNECTION(Connection) MACROS{ Connection->State = TCP_Connection_Closing; }MACROE\r
-\r
- /* Enums: */\r
- /** Enum for possible TCP port states */\r
- enum TCP_PortStates_t\r
- {\r
- TCP_Port_Closed = 0, /**< TCP port closed, no connections to a host may be made on this port. */\r
- TCP_Port_Open = 1, /**< TCP port open, connections to a host may be made on this port. */\r
- };\r
- \r
- /** Enum for possible TCP connection states */\r
- enum TCP_ConnectionStates_t\r
- {\r
- TCP_Connection_Listen = 0, /**< Listening for a connection from a host */\r
- TCP_Connection_SYNSent = 1, /**< Unused */\r
- TCP_Connection_SYNReceived = 2, /**< SYN received, waiting for ACK */\r
- TCP_Connection_Established = 3, /**< Connection established in both directions */\r
- TCP_Connection_FINWait1 = 4, /**< Closing, waiting for ACK */\r
- TCP_Connection_FINWait2 = 5, /**< Closing, waiting for FIN ACK */\r
- TCP_Connection_CloseWait = 6, /**< Closing, waiting for ACK */\r
- TCP_Connection_Closing = 7, /**< Unused */\r
- TCP_Connection_LastACK = 8, /**< Unused */\r
- TCP_Connection_TimeWait = 9, /**< Unused */\r
- TCP_Connection_Closed = 10, /**< Connection closed in both directions */ \r
- };\r
- \r
- /* Type Defines: */\r
- /** Type define for a TCP connection buffer structure, including size, data and direction */\r
- typedef struct\r
- {\r
- uint16_t Length; /**< Length of data in the TCP application buffer */\r
- uint8_t Data[TCP_WINDOW_SIZE]; /**< TCP application data buffer */\r
- bool Direction; /**< Buffer transmission direction, either TCP_PACKETDIR_IN or TCP_PACKETDIR_OUT */\r
- bool Ready; /**< If data from host, indicates buffer ready to be read, otherwise indicates\r
- * buffer ready to be sent to the host\r
- */\r
- bool InUse; /** Indicates if the buffer is locked to to the current direction, and cannot be changed */\r
- } TCP_ConnectionBuffer_t;\r
-\r
- /** Type define for a TCP connection information structure */\r
- typedef struct\r
- {\r
- uint32_t SequenceNumberIn; /**< Current TCP sequence number for host-to-device */ \r
- uint32_t SequenceNumberOut; /**< Current TCP sequence number for device-to-host */\r
- TCP_ConnectionBuffer_t Buffer; /**< Connection application data buffer */\r
- } TCP_ConnectionInfo_t;\r
-\r
- /** Type define for a complete TCP connection state */\r
- typedef struct\r
- {\r
- uint16_t Port; /**< Connection port number on the device */\r
- uint16_t RemotePort; /**< Connection port number on the host */\r
- IP_Address_t RemoteAddress; /**< Connection protocol IP address of the host */\r
- TCP_ConnectionInfo_t Info; /**< Connection information, including application buffer */\r
- uint8_t State; /**< Current connection state, a value from the TCP_ConnectionStates_t enum */\r
- } TCP_ConnectionState_t;\r
-\r
- /** Type define for a TCP port state */\r
- typedef struct\r
- {\r
- uint16_t Port; /**< TCP port number on the device */\r
- uint8_t State; /**< Current port state, a value from the TCP_PortStates_t enum */\r
- void (*ApplicationHandler) (TCP_ConnectionState_t* ConnectionState,\r
- TCP_ConnectionBuffer_t* Buffer); /**< Port application handler */\r
- } TCP_PortState_t;\r
-\r
- /** Type define for a TCP packet header */\r
- typedef struct\r
- {\r
- uint16_t SourcePort; /**< Source port of the TCP packet */\r
- uint16_t DestinationPort; /**< Destination port of the TCP packet */\r
- \r
- uint32_t SequenceNumber; /**< Data sequence number of the packet */\r
- uint32_t AcknowledgmentNumber; /**< Data acknowledgment number of the packet */\r
- \r
- unsigned char Reserved : 4; /**< Reserved, must be all 0 */\r
- unsigned char DataOffset : 4; /**< Offset of the data from the start of the header, in 4 byte chunks */\r
- uint8_t Flags; /**< TCP packet flags */\r
- uint16_t WindowSize; /**< Current data window size (bytes remaining in reception buffer) */\r
- \r
- uint16_t Checksum; /**< TCP checksum */\r
- uint16_t UrgentPointer; /**< Urgent data pointer */\r
- } TCP_Header_t;\r
-\r
- /* Tasks: */\r
- TASK(TCP_Task);\r
- \r
- /* External Variables: */\r
- TCP_PortState_t PortStateTable[MAX_OPEN_TCP_PORTS];\r
-\r
- /* Function Prototypes: */\r
- void TCP_Init(void);\r
- bool TCP_SetPortState(uint16_t Port, uint8_t State, void (*Handler)(TCP_ConnectionState_t*, TCP_ConnectionBuffer_t*));\r
- uint8_t TCP_GetPortState(uint16_t Port);\r
- bool TCP_SetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort, uint8_t State);\r
- uint8_t TCP_GetConnectionState(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort);\r
- TCP_ConnectionInfo_t* TCP_GetConnectionInfo(uint16_t Port, IP_Address_t RemoteAddress, uint16_t RemotePort);\r
- int16_t TCP_ProcessTCPPacket(void* IPHeaderInStart, void* TCPHeaderInStart, void* TCPHeaderOutStart);\r
-\r
- #if defined(INCLUDE_FROM_TCP_C)\r
- static uint16_t TCP_Checksum16(void* TCPHeaderOutStart, IP_Address_t SourceAddress,\r
- IP_Address_t DestinationAddress, uint16_t TCPOutSize);\r
- #endif\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * User Datagram Protocol (UDP) packet handling routines. This protocol handles high throughput, low\r
- * reliability packets which are typically used to encapsulate streaming data.\r
- */\r
- \r
-#define INCLUDE_FROM_UDP_C\r
-#include "UDP.h"\r
-\r
-/** Processes a UDP packet inside an Ethernet frame, and writes the appropriate response\r
- * to the output Ethernet frame if a subprotocol handler has created a response packet.\r
- *\r
- * \param IPHeaderInStart Pointer to the start of the incoming packet's IP header\r
- * \param UDPHeaderInStart Pointer to the start of the incoming packet's UDP header\r
- * \param UDPHeaderOutStart Pointer to the start of the outgoing packet's UDP header\r
- *\r
- * \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE otherwise\r
- */\r
-int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void* UDPHeaderOutStart)\r
-{\r
- UDP_Header_t* UDPHeaderIN = (UDP_Header_t*)UDPHeaderInStart;\r
- UDP_Header_t* UDPHeaderOUT = (UDP_Header_t*)UDPHeaderOutStart;\r
- \r
- int16_t RetSize = NO_RESPONSE;\r
- \r
- DecodeUDPHeader(UDPHeaderInStart);\r
- \r
- /* Check to see if the UDP packet is a DHCP packet */\r
- if (SwapEndian_16(UDPHeaderIN->DestinationPort) == UDP_PORT_DHCP_REQUEST)\r
- {\r
- RetSize = DHCP_ProcessDHCPPacket(IPHeaderInStart,\r
- &((uint8_t*)UDPHeaderInStart)[sizeof(UDP_Header_t)],\r
- &((uint8_t*)UDPHeaderOutStart)[sizeof(UDP_Header_t)]);\r
- }\r
- \r
- /* Check to see if the protocol processing routine has filled out a response */\r
- if (RetSize > 0)\r
- {\r
- /* Fill out the response UDP packet header */\r
- UDPHeaderOUT->SourcePort = UDPHeaderIN->DestinationPort;\r
- UDPHeaderOUT->DestinationPort = UDPHeaderIN->SourcePort;\r
- UDPHeaderOUT->Checksum = 0;\r
- UDPHeaderOUT->Length = SwapEndian_16(sizeof(UDP_Header_t) + RetSize);\r
-\r
- /* Return the size of the response so far */\r
- return (sizeof(UDP_Header_t) + RetSize);\r
- }\r
- \r
- return NO_RESPONSE;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for IP.c.\r
- */\r
-\r
-#ifndef _UDP_H_\r
-#define _UDP_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- \r
- #include "EthernetProtocols.h"\r
- #include "Ethernet.h"\r
- #include "ProtocolDecoders.h"\r
- \r
- /* Macros: */\r
- /** Source UDP port for a DHCP request */\r
- #define UDP_PORT_DHCP_REQUEST 67\r
-\r
- /** Destination UDP port for a DHCP reply */\r
- #define UDP_PORT_DHCP_REPLY 68\r
- \r
- /* Type Defines: */\r
- /** Type define for a UDP packet header */\r
- typedef struct\r
- {\r
- uint16_t SourcePort; /**< Packet source port */\r
- uint16_t DestinationPort; /**< Packet destination port */\r
- uint16_t Length; /**< Total packet length, in bytes */\r
- uint16_t Checksum; /**< Optional UDP packet checksum */\r
- } UDP_Header_t;\r
- \r
- /* Function Prototypes: */\r
- int16_t UDP_ProcessUDPPacket(void* IPHeaderInStart, void* UDPHeaderInStart, void* UDPHeaderOutStart);\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Simple webserver application for demonstrating the RNDIS demo and TCP/IP stack. This\r
- * application will serve up a static HTTP webpage when requested by the host.\r
- */\r
-\r
-#include "Webserver.h"\r
-\r
-/** HTTP server response header, for transmission before the page contents. This indicates to the host that a page exists at the\r
- * given location, and gives extra connection information.\r
- */\r
-char PROGMEM HTTPHeader[] = "HTTP/1.1 200 OK\r\n"\r
- "Server: LUFA RNDIS\r\n"\r
- "Content-type: text/html\r\n"\r
- "Connection: close\r\n\r\n";\r
-\r
-/** HTTP page to serve to the host when a HTTP request is made. This page is too long for a single response, thus it is automatically\r
- * broken up into smaller blocks and sent as a series of packets each time the webserver application callback is run.\r
- */\r
-char PROGMEM HTTPPage[] = \r
- "<html>"\r
- " <head>"\r
- " <title>"\r
- " LUFA Webserver Demo"\r
- " </title>"\r
- " </head>"\r
- " <body>"\r
- " <h1>Hello from your USB AVR!</h1>"\r
- " <p>"\r
- " Hello! Welcome to the LUFA RNDIS Demo Webserver test page, running on your USB AVR via the LUFA library. This demonstrates the HTTP webserver, TCP/IP stack and RNDIS demo all running atop the LUFA USB stack."\r
- " <br /><br />"\r
- " <small>Project Information: <a href=\"http://www.fourwalledcubicle.com/LUFA.php\">http://www.fourwalledcubicle.com/LUFA.php</a>.</small>"\r
- " <hr />"\r
- " <i>LUFA Version: </i>" LUFA_VERSION_STRING\r
- " </p>"\r
- " </body>"\r
- "</html>";\r
-\r
-\r
-/** Initializes the Webserver application, opening the appropriate HTTP port in the TCP handler and registering the application\r
- * callback routine for packets sent to the HTTP protocol port.\r
- */\r
-void Webserver_Init(void)\r
-{\r
- /* Open the HTTP port in the TCP protocol so that HTTP connections to the device can be established */\r
- TCP_SetPortState(TCP_PORT_HTTP, TCP_Port_Open, Webserver_ApplicationCallback);\r
-}\r
-\r
-/** Indicates if a given request equals the given HTTP command.\r
- *\r
- * \param RequestHeader HTTP request made by the host\r
- * \param Command HTTP command to compare the request to\r
- *\r
- * \return Boolean true if the command matches the request, false otherwise\r
- */\r
-static bool IsHTTPCommand(uint8_t* RequestHeader, char* Command)\r
-{\r
- /* Returns true if the non null terminated string in RequestHeader matches the null terminated string Command */\r
- return (strncmp((char*)RequestHeader, Command, strlen(Command)) == 0);\r
-}\r
-\r
-/** Application callback routine, executed each time the TCP processing task runs. This callback determines what request\r
- * has been made (if any), and serves up appropriate responses.\r
- *\r
- * \param ConnectionState Pointer to a TCP Connection State structure giving connection information\r
- * \param Buffer Pointer to the application's send/receive packet buffer\r
- */\r
-void Webserver_ApplicationCallback(TCP_ConnectionState_t* ConnectionState, TCP_ConnectionBuffer_t* Buffer)\r
-{\r
- char* BufferDataStr = (char*)Buffer->Data;\r
- static uint8_t PageBlock = 0;\r
- \r
- /* Check to see if a packet has been received on the HTTP port from a remote host */\r
- if (TCP_APP_HAS_RECEIVED_PACKET(Buffer))\r
- {\r
- if (IsHTTPCommand(Buffer->Data, "GET"))\r
- {\r
- PageBlock = 0;\r
-\r
- /* Copy the HTTP response header into the packet buffer */\r
- strcpy_P(BufferDataStr, HTTPHeader);\r
- \r
- /* Send the buffer contents to the host */\r
- TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr));\r
-\r
- /* Lock the buffer to Device->Host transmissions only while we send the page contents */\r
- TCP_APP_CAPTURE_BUFFER(Buffer);\r
- }\r
- else if (IsHTTPCommand(Buffer->Data, "HEAD"))\r
- {\r
- /* Copy the HTTP response header into the packet buffer */\r
- strcpy_P(BufferDataStr, HTTPHeader);\r
-\r
- /* Send the buffer contents to the host */\r
- TCP_APP_SEND_BUFFER(Buffer, strlen(BufferDataStr));\r
- }\r
- else if (IsHTTPCommand(Buffer->Data, "TRACE"))\r
- {\r
- /* Echo the host's query back to the host */\r
- TCP_APP_SEND_BUFFER(Buffer, Buffer->Length);\r
- }\r
- else\r
- {\r
- /* Unknown request, just clear the buffer (drop the packet) */\r
- TCP_APP_CLEAR_BUFFER(Buffer);\r
- }\r
- }\r
- else if (TCP_APP_HAVE_CAPTURED_BUFFER(Buffer))\r
- {\r
- uint16_t RemLength = strlen_P(&HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE]);\r
- uint16_t Length;\r
- \r
- /* Determine the length of the loaded block */\r
- Length = ((RemLength > HTTP_REPLY_BLOCK_SIZE) ? HTTP_REPLY_BLOCK_SIZE : RemLength);\r
-\r
- /* Copy the next buffer sized block of the page to the packet buffer */\r
- strncpy_P(BufferDataStr, &HTTPPage[PageBlock * HTTP_REPLY_BLOCK_SIZE], Length);\r
- \r
- /* Send the buffer contents to the host */\r
- TCP_APP_SEND_BUFFER(Buffer, Length);\r
-\r
- /* Check to see if the entire page has been sent */\r
- if (PageBlock++ == (sizeof(HTTPPage) / HTTP_REPLY_BLOCK_SIZE))\r
- {\r
- /* Unlock the buffer so that the host can fill it with future packets */\r
- TCP_APP_RELEASE_BUFFER(Buffer);\r
- \r
- /* Close the connection to the host */\r
- TCP_APP_CLOSECONNECTION(ConnectionState);\r
- }\r
- }\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for Webserver.c.\r
- */\r
- \r
-#ifndef _WEBSERVER_H_\r
-#define _WEBSERVER_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <avr/pgmspace.h>\r
- \r
- #include <LUFA/Version.h>\r
- \r
- #include "TCP.h"\r
- \r
- /* Macros: */\r
- /** Maximum size of a HTTP response per transmission */\r
- #define HTTP_REPLY_BLOCK_SIZE 128\r
- \r
- /* Function Prototypes: */\r
- void Webserver_Init(void);\r
- void Webserver_ApplicationCallback(TCP_ConnectionState_t* ConnectionState, TCP_ConnectionBuffer_t* Buffer);\r
-\r
-#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- RNDIS.c \\r
- Ethernet.c \\r
- ProtocolDecoders.c \\r
- ICMP.c \\r
- TCP.c \\r
- UDP.c \\r
- DHCP.c \\r
- ARP.c \\r
- IP.c \\r
- Webserver.c \\r
+ Lib/RNDIS.c \\r
+ Lib/Ethernet.c \\r
+ Lib/ProtocolDecoders.c \\r
+ Lib/ICMP.c \\r
+ Lib/TCP.c \\r
+ Lib/UDP.c \\r
+ Lib/DHCP.c \\r
+ Lib/ARP.c \\r
+ Lib/IP.c \\r
+ Lib/Webserver.c \\r
$(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/Peripheral/SerialStream.c \\r
$(LUFA_PATH)/LUFA/Drivers/Peripheral/Serial.c \\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+#include "RingBuff.h"\r
+\r
+void Buffer_Initialize(RingBuff_t* Buffer)\r
+{\r
+ BUFF_ATOMIC_BLOCK\r
+ {\r
+ Buffer->InPtr = (RingBuff_Data_t*)&Buffer->Buffer;\r
+ Buffer->OutPtr = (RingBuff_Data_t*)&Buffer->Buffer;\r
+ Buffer->Elements = 0;\r
+ }\r
+}\r
+\r
+void Buffer_StoreElement(RingBuff_t* Buffer, RingBuff_Data_t Data)\r
+{\r
+ BUFF_ATOMIC_BLOCK\r
+ {\r
+ #if defined(BUFF_DROPOLD)\r
+ if (Buffer->Elements == BUFF_LENGTH)\r
+ {\r
+ Buffer->OutPtr++;\r
+ \r
+ if (Buffer->OutPtr == &Buffer->Buffer[BUFF_LENGTH])\r
+ Buffer->OutPtr = (RingBuff_Data_t*)&Buffer->Buffer;\r
+ }\r
+ else\r
+ {\r
+ Buffer->Elements++;\r
+ }\r
+ #elif defined(BUFF_DROPNEW)\r
+ if (Buffer->Elements == BUFF_LENGTH)\r
+ return;\r
+ \r
+ Buffer->Elements++;\r
+ #elif defined(BUFF_NODROPCHECK)\r
+ Buffer->Elements++;\r
+ #endif\r
+ \r
+ *(Buffer->InPtr) = Data;\r
+ Buffer->InPtr++;\r
+ \r
+ if (Buffer->InPtr == &Buffer->Buffer[BUFF_LENGTH])\r
+ Buffer->InPtr = (RingBuff_Data_t*)&Buffer->Buffer;\r
+ }\r
+}\r
+\r
+RingBuff_Data_t Buffer_GetElement(RingBuff_t* Buffer)\r
+{\r
+ RingBuff_Data_t BuffData;\r
+ \r
+ BUFF_ATOMIC_BLOCK\r
+ {\r
+#if defined(BUFF_EMPTYRETURNSZERO)\r
+ if (!(Buffer->Elements))\r
+ return 0;\r
+#elif !defined(BUFF_NOEMPTYCHECK)\r
+ #error No empty buffer check behaviour specified.\r
+#endif\r
+\r
+ BuffData = *(Buffer->OutPtr);\r
+ \r
+ Buffer->OutPtr++;\r
+ Buffer->Elements--;\r
+ \r
+ if (Buffer->OutPtr == &Buffer->Buffer[BUFF_LENGTH])\r
+ Buffer->OutPtr = (RingBuff_Data_t*)&Buffer->Buffer;\r
+ }\r
+ \r
+ return BuffData;\r
+}\r
+\r
+#if defined(BUFF_USEPEEK)\r
+RingBuff_Data_t Buffer_PeekElement(const RingBuff_t* Buffer)\r
+{\r
+ RingBuff_Data_t BuffData;\r
+\r
+ BUFF_ATOMIC_BLOCK\r
+ {\r
+#if defined(BUFF_EMPTYRETURNSZERO)\r
+ if (!(Buffer->Elements))\r
+ return 0;\r
+#elif !defined(BUFF_NOEMPTYCHECK)\r
+ #error No empty buffer check behaviour specified.\r
+#endif\r
+\r
+ BuffData = *(Buffer->OutPtr);\r
+ }\r
+\r
+ return BuffData;\r
+}\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/* Buffer Configuration: */\r
+ /* Buffer length - select static size of created ring buffers: */\r
+ #define BUFF_STATICSIZE 128 // Set to the static ring buffer size for all ring buffers (place size after define)\r
+\r
+ /* Volatile mode - uncomment to make buffers volatile, for use in ISRs, etc: */\r
+ #define BUFF_VOLATILE // Uncomment to cause all ring buffers to become volatile (and atomic if multi-byte) in access\r
+\r
+ /* Drop mode - select behaviour when Buffer_StoreElement called on a full buffer: */\r
+ #define BUFF_DROPOLD // Uncomment to cause full ring buffers to drop the oldest character to make space when full\r
+ // #define BUFF_DROPNEW // Uncomment to cause full ring buffers to drop the new character when full\r
+ // #define BUFF_NODROPCHECK // Uncomment to ignore full ring buffer checks - checking left to user!\r
+\r
+ /* Underflow behaviour - select behaviour when Buffer_GetElement is called with an empty ring buffer: */\r
+ //#define BUFF_EMPTYRETURNSZERO // Uncomment to return 0 when an empty ring buffer is read\r
+ #define BUFF_NOEMPTYCHECK // Uncomment to disable checking of empty ring buffers - checking left to user!\r
+ \r
+ /* Buffer storage type - set the datatype for the stored data */\r
+ #define BUFF_DATATYPE uint8_t // Change to the data type that is going to be stored into the buffer\r
+ \r
+ /* Peek routine - uncomment to include the peek routine (fetches next byte without removing it from the buffer */\r
+ //#define BUFF_USEPEEK\r
+ \r
+#ifndef _RINGBUFF_H_\r
+#define _RINGBUFF_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <avr/interrupt.h>\r
+ #include <util/atomic.h>\r
+ #include <limits.h>\r
+\r
+ #include <LUFA/Common/Common.h>\r
+\r
+ /* Defines and checks: */\r
+ #if defined(BUFF_STATICSIZE)\r
+ #define BUFF_LENGTH BUFF_STATICSIZE\r
+ #else\r
+ #error No buffer length specified!\r
+ #endif\r
+\r
+ #if !(defined(BUFF_DROPOLD) || defined(BUFF_DROPNEW) || defined(BUFF_NODROPCHECK))\r
+ #error No buffer drop mode specified.\r
+ #endif\r
+\r
+ #if !defined(BUFF_DATATYPE)\r
+ #error Ringbuffer storage data type not specified.\r
+ #endif\r
+\r
+ #if defined(BUFF_VOLATILE)\r
+ #define BUFF_MODE volatile\r
+ #define BUFF_ATOMIC_BLOCK ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
+ #else\r
+ #define BUFF_MODE\r
+ #define BUFF_ATOMIC_BLOCK\r
+ #endif\r
+\r
+ #if (BUFF_STATICSIZE > LONG_MAX)\r
+ #define RingBuff_Elements_t uint64_t\r
+ #elif (BUFF_STATICSIZE > INT_MAX)\r
+ #define RingBuff_Elements_t uint32_t\r
+ #elif (BUFF_STATICSIZE > CHAR_MAX)\r
+ #define RingBuff_Elements_t uint16_t\r
+ #else\r
+ #define RingBuff_Elements_t uint8_t\r
+ #endif\r
+ \r
+ /* Type Defines: */\r
+ typedef BUFF_DATATYPE RingBuff_Data_t;\r
+\r
+ typedef BUFF_MODE struct\r
+ {\r
+ RingBuff_Data_t Buffer[BUFF_LENGTH];\r
+ RingBuff_Data_t* InPtr;\r
+ RingBuff_Data_t* OutPtr;\r
+ RingBuff_Elements_t Elements;\r
+ } RingBuff_t;\r
+ \r
+ /* Function Prototypes: */\r
+ void Buffer_Initialize(RingBuff_t* Buff);\r
+ void Buffer_StoreElement(RingBuff_t* Buffer, RingBuff_Data_t Data);\r
+ RingBuff_Data_t Buffer_GetElement(RingBuff_t* Buffer);\r
+ #if defined(BUFF_USEPEEK)\r
+ RingBuff_Data_t Buffer_PeekElement(const RingBuff_t* Buffer);\r
+ #endif\r
+ \r
+#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-#include "RingBuff.h"\r
-\r
-void Buffer_Initialize(RingBuff_t* Buffer)\r
-{\r
- BUFF_ATOMIC_BLOCK\r
- {\r
- Buffer->InPtr = (RingBuff_Data_t*)&Buffer->Buffer;\r
- Buffer->OutPtr = (RingBuff_Data_t*)&Buffer->Buffer;\r
- Buffer->Elements = 0;\r
- }\r
-}\r
-\r
-void Buffer_StoreElement(RingBuff_t* Buffer, RingBuff_Data_t Data)\r
-{\r
- BUFF_ATOMIC_BLOCK\r
- {\r
- #if defined(BUFF_DROPOLD)\r
- if (Buffer->Elements == BUFF_LENGTH)\r
- {\r
- Buffer->OutPtr++;\r
- \r
- if (Buffer->OutPtr == &Buffer->Buffer[BUFF_LENGTH])\r
- Buffer->OutPtr = (RingBuff_Data_t*)&Buffer->Buffer;\r
- }\r
- else\r
- {\r
- Buffer->Elements++;\r
- }\r
- #elif defined(BUFF_DROPNEW)\r
- if (Buffer->Elements == BUFF_LENGTH)\r
- return;\r
- \r
- Buffer->Elements++;\r
- #elif defined(BUFF_NODROPCHECK)\r
- Buffer->Elements++;\r
- #endif\r
- \r
- *(Buffer->InPtr) = Data;\r
- Buffer->InPtr++;\r
- \r
- if (Buffer->InPtr == &Buffer->Buffer[BUFF_LENGTH])\r
- Buffer->InPtr = (RingBuff_Data_t*)&Buffer->Buffer;\r
- }\r
-}\r
-\r
-RingBuff_Data_t Buffer_GetElement(RingBuff_t* Buffer)\r
-{\r
- RingBuff_Data_t BuffData;\r
- \r
- BUFF_ATOMIC_BLOCK\r
- {\r
-#if defined(BUFF_EMPTYRETURNSZERO)\r
- if (!(Buffer->Elements))\r
- return 0;\r
-#elif !defined(BUFF_NOEMPTYCHECK)\r
- #error No empty buffer check behaviour specified.\r
-#endif\r
-\r
- BuffData = *(Buffer->OutPtr);\r
- \r
- Buffer->OutPtr++;\r
- Buffer->Elements--;\r
- \r
- if (Buffer->OutPtr == &Buffer->Buffer[BUFF_LENGTH])\r
- Buffer->OutPtr = (RingBuff_Data_t*)&Buffer->Buffer;\r
- }\r
- \r
- return BuffData;\r
-}\r
-\r
-#if defined(BUFF_USEPEEK)\r
-RingBuff_Data_t Buffer_PeekElement(const RingBuff_t* Buffer)\r
-{\r
- RingBuff_Data_t BuffData;\r
-\r
- BUFF_ATOMIC_BLOCK\r
- {\r
-#if defined(BUFF_EMPTYRETURNSZERO)\r
- if (!(Buffer->Elements))\r
- return 0;\r
-#elif !defined(BUFF_NOEMPTYCHECK)\r
- #error No empty buffer check behaviour specified.\r
-#endif\r
-\r
- BuffData = *(Buffer->OutPtr);\r
- }\r
-\r
- return BuffData;\r
-}\r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/* Buffer Configuration: */\r
- /* Buffer length - select static size of created ring buffers: */\r
- #define BUFF_STATICSIZE 128 // Set to the static ring buffer size for all ring buffers (place size after define)\r
-\r
- /* Volatile mode - uncomment to make buffers volatile, for use in ISRs, etc: */\r
- #define BUFF_VOLATILE // Uncomment to cause all ring buffers to become volatile (and atomic if multi-byte) in access\r
-\r
- /* Drop mode - select behaviour when Buffer_StoreElement called on a full buffer: */\r
- #define BUFF_DROPOLD // Uncomment to cause full ring buffers to drop the oldest character to make space when full\r
- // #define BUFF_DROPNEW // Uncomment to cause full ring buffers to drop the new character when full\r
- // #define BUFF_NODROPCHECK // Uncomment to ignore full ring buffer checks - checking left to user!\r
-\r
- /* Underflow behaviour - select behaviour when Buffer_GetElement is called with an empty ring buffer: */\r
- //#define BUFF_EMPTYRETURNSZERO // Uncomment to return 0 when an empty ring buffer is read\r
- #define BUFF_NOEMPTYCHECK // Uncomment to disable checking of empty ring buffers - checking left to user!\r
- \r
- /* Buffer storage type - set the datatype for the stored data */\r
- #define BUFF_DATATYPE uint8_t // Change to the data type that is going to be stored into the buffer\r
- \r
- /* Peek routine - uncomment to include the peek routine (fetches next byte without removing it from the buffer */\r
- //#define BUFF_USEPEEK\r
- \r
-#ifndef _RINGBUFF_H_\r
-#define _RINGBUFF_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <avr/interrupt.h>\r
- #include <util/atomic.h>\r
- #include <limits.h>\r
-\r
- #include <LUFA/Common/Common.h>\r
-\r
- /* Defines and checks: */\r
- #if defined(BUFF_STATICSIZE)\r
- #define BUFF_LENGTH BUFF_STATICSIZE\r
- #else\r
- #error No buffer length specified!\r
- #endif\r
-\r
- #if !(defined(BUFF_DROPOLD) || defined(BUFF_DROPNEW) || defined(BUFF_NODROPCHECK))\r
- #error No buffer drop mode specified.\r
- #endif\r
-\r
- #if !defined(BUFF_DATATYPE)\r
- #error Ringbuffer storage data type not specified.\r
- #endif\r
-\r
- #if defined(BUFF_VOLATILE)\r
- #define BUFF_MODE volatile\r
- #define BUFF_ATOMIC_BLOCK ATOMIC_BLOCK(ATOMIC_RESTORESTATE)\r
- #else\r
- #define BUFF_MODE\r
- #define BUFF_ATOMIC_BLOCK\r
- #endif\r
-\r
- #if (BUFF_STATICSIZE > LONG_MAX)\r
- #define RingBuff_Elements_t uint64_t\r
- #elif (BUFF_STATICSIZE > INT_MAX)\r
- #define RingBuff_Elements_t uint32_t\r
- #elif (BUFF_STATICSIZE > CHAR_MAX)\r
- #define RingBuff_Elements_t uint16_t\r
- #else\r
- #define RingBuff_Elements_t uint8_t\r
- #endif\r
- \r
- /* Type Defines: */\r
- typedef BUFF_DATATYPE RingBuff_Data_t;\r
-\r
- typedef BUFF_MODE struct\r
- {\r
- RingBuff_Data_t Buffer[BUFF_LENGTH];\r
- RingBuff_Data_t* InPtr;\r
- RingBuff_Data_t* OutPtr;\r
- RingBuff_Elements_t Elements;\r
- } RingBuff_t;\r
- \r
- /* Function Prototypes: */\r
- void Buffer_Initialize(RingBuff_t* Buff);\r
- void Buffer_StoreElement(RingBuff_t* Buffer, RingBuff_Data_t Data);\r
- RingBuff_Data_t Buffer_GetElement(RingBuff_t* Buffer);\r
- #if defined(BUFF_USEPEEK)\r
- RingBuff_Data_t Buffer_PeekElement(const RingBuff_t* Buffer);\r
- #endif\r
- \r
-#endif\r
#include <avr/power.h>\r
\r
#include "Descriptors.h"\r
- #include "RingBuff.h"\r
+\r
+ #include "Lib/RingBuff.h"\r
\r
#include <LUFA/Version.h> // Library Version Information\r
#include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
Descriptors.c \\r
- RingBuff.c \\r
+ Lib/RingBuff.c \\r
$(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \\r
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Mass Storage Device commands, to issue MSD commands to the device for\r
+ * reading device status, capacity, and other characteristics. This file\r
+ * also contains block read and write functions, so that device blocks\r
+ * can be read and written. In general, these functions would be chained\r
+ * to a FAT library to give file-level access to an attached device's contents.\r
+ *\r
+ * \note Many Mass Storage devices on the market are non-compliant to the\r
+ * specifications and thus can prove difficult to interface with. It\r
+ * may be necessary to retry the functions in the module several times\r
+ * after they have returned and error to successfully send the command\r
+ * to the device. Some devices may also need to have the stream function\r
+ * timeout period extended beyond 100ms (some badly designed devices exceeding\r
+ * 1.5 seconds occasionally) by defining USB_STREAM_TIMEOUT_MS to a\r
+ * larger value in the project makefile and passing it to the compiler\r
+ * via the -D switch.\r
+ */\r
+ \r
+#define INCLUDE_FROM_MASSSTORE_COMMANDS_C\r
+#include "MassStoreCommands.h"\r
+\r
+/* Globals: */\r
+/** Current CBW to send to the device. This is automatically filled by the routines\r
+ * in this file and is not externally accessible.\r
+ */\r
+static CommandBlockWrapper_t SCSICommandBlock;\r
+\r
+/** Current CSW received from the device. This is automatically filled by the routines\r
+ * in this file and is externally accessible so that the return codes may be checked.\r
+ */\r
+CommandStatusWrapper_t SCSICommandStatus;\r
+\r
+/** Current Tag value used in issued CBWs to the device. This is automatically incremented\r
+ * by the routines in this file, and is not externally accessible.\r
+ */\r
+static uint32_t MassStore_Tag = 1;\r
+\r
+\r
+/** Routine to send the current CBW to the device, and increment the Tag value as needed.\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+static uint8_t MassStore_SendCommand(void)\r
+{\r
+ uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
+\r
+ /* Each transmission should have a unique tag value, excluding values 0 and 0xFFFFFFFF */\r
+ if (++MassStore_Tag == 0xFFFFFFFF)\r
+ MassStore_Tag = 1;\r
+\r
+ /* Select the OUT data pipe for CBW transmission */\r
+ Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE);\r
+ Pipe_Unfreeze();\r
+\r
+ /* Write the CBW command to the OUT pipe */\r
+ if ((ErrorCode = Pipe_Write_Stream_LE(&SCSICommandBlock, sizeof(CommandBlockWrapper_t))) != PIPE_RWSTREAM_NoError)\r
+ return ErrorCode;\r
+\r
+ /* Send the data in the OUT pipe to the attached device */\r
+ Pipe_ClearOUT();\r
+ \r
+ while(!(Pipe_IsOUTReady()));\r
+\r
+ /* Freeze pipe after use */\r
+ Pipe_Freeze();\r
+ \r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Waits until the attached device is ready to accept data following a CBW, checking\r
+ * to ensure that the device has not stalled the transaction.\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+static uint8_t MassStore_WaitForDataReceived(void)\r
+{\r
+ uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;\r
+\r
+ /* Unfreeze the OUT pipe so that it can be checked */\r
+ Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE);\r
+ Pipe_Unfreeze();\r
+\r
+ /* Select the IN data pipe for data reception */\r
+ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);\r
+ Pipe_Unfreeze();\r
+\r
+ /* Wait until data received in the IN pipe */\r
+ while (!(Pipe_IsINReceived()))\r
+ {\r
+ /* Check to see if a new frame has been issued (1ms elapsed) */\r
+ if (USB_INT_HasOccurred(USB_INT_HSOFI))\r
+ {\r
+ /* Clear the flag and decrement the timeout period counter */\r
+ USB_INT_Clear(USB_INT_HSOFI);\r
+ TimeoutMSRem--;\r
+\r
+ /* Check to see if the timeout period for the command has elapsed */\r
+ if (!(TimeoutMSRem))\r
+ return PIPE_RWSTREAM_Timeout;\r
+ }\r
+ \r
+ Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE);\r
+\r
+ /* Check if pipe stalled (command failed by device) */\r
+ if (Pipe_IsStalled())\r
+ {\r
+ /* Clear the stall condition on the OUT pipe */\r
+ MassStore_ClearPipeStall(MASS_STORE_DATA_OUT_PIPE);\r
+\r
+ return PIPE_RWSTREAM_PipeStalled;\r
+ }\r
+\r
+ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);\r
+\r
+ /* Check if pipe stalled (command failed by device) */\r
+ if (Pipe_IsStalled())\r
+ {\r
+ /* Clear the stall condition on the IN pipe */\r
+ MassStore_ClearPipeStall(MASS_STORE_DATA_IN_PIPE);\r
+\r
+ return PIPE_RWSTREAM_PipeStalled;\r
+ }\r
+ \r
+ /* Check to see if the device was disconnected, if so exit function */\r
+ if (!(USB_IsConnected))\r
+ return PIPE_RWSTREAM_DeviceDisconnected;\r
+ };\r
+\r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Sends or receives the transaction's data stage to or from the attached device, reading or\r
+ * writing to the nominated buffer.\r
+ *\r
+ * \param BufferPtr Pointer to the data buffer to read from or write to\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+static uint8_t MassStore_SendReceiveData(void* BufferPtr)\r
+{\r
+ uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
+ uint16_t BytesRem = SCSICommandBlock.Header.DataTransferLength;\r
+\r
+ /* Check the direction of the SCSI command data stage */\r
+ if (SCSICommandBlock.Header.Flags & COMMAND_DIRECTION_DATA_IN)\r
+ {\r
+ /* Select the IN data pipe for data reception */\r
+ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);\r
+ Pipe_Unfreeze();\r
+ \r
+ /* Read in the block data from the pipe */\r
+ if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError)\r
+ return ErrorCode;\r
+\r
+ /* Acknowledge the packet */\r
+ Pipe_ClearIN();\r
+ }\r
+ else\r
+ {\r
+ /* Select the OUT data pipe for data transmission */\r
+ Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE);\r
+ Pipe_Unfreeze();\r
+\r
+ /* Write the block data to the pipe */\r
+ if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError)\r
+ return ErrorCode;\r
+\r
+ /* Acknowledge the packet */\r
+ Pipe_ClearOUT();\r
+ \r
+ while (!(Pipe_IsOUTReady()));\r
+ }\r
+ \r
+ /* Freeze used pipe after use */\r
+ Pipe_Freeze();\r
+\r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Routine to receive the current CSW from the device.\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+static uint8_t MassStore_GetReturnedStatus(void)\r
+{\r
+ uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
+\r
+ /* If an error in the command ocurred, abort */\r
+ if ((ErrorCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
+ return ErrorCode;\r
+\r
+ /* Select the IN data pipe for data reception */\r
+ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);\r
+ Pipe_Unfreeze();\r
+ \r
+ /* Load in the CSW from the attached device */\r
+ if ((ErrorCode = Pipe_Read_Stream_LE(&SCSICommandStatus, sizeof(CommandStatusWrapper_t))) != PIPE_RWSTREAM_NoError)\r
+ return ErrorCode;\r
+ \r
+ /* Clear the data ready for next reception */\r
+ Pipe_ClearIN();\r
+ \r
+ /* Freeze the IN pipe after use */\r
+ Pipe_Freeze();\r
+ \r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Clears the stall condition in the attached device on the nominated endpoint number.\r
+ *\r
+ * \param EndpointNum Endpoint number in the attached device whose stall condition is to be cleared\r
+ *\r
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
+ */\r
+uint8_t MassStore_ClearPipeStall(const uint8_t EndpointNum)\r
+{\r
+ USB_ControlRequest = (USB_Request_Header_t)\r
+ {\r
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT),\r
+ .bRequest = REQ_ClearFeature,\r
+ .wValue = FEATURE_ENDPOINT_HALT,\r
+ .wIndex = EndpointNum,\r
+ .wLength = 0,\r
+ };\r
+ \r
+ /* Select the control pipe for the request transfer */\r
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
+\r
+ return USB_Host_SendControlRequest(NULL);\r
+}\r
+\r
+/** Issues a Mass Storage class specific request to reset the attached device's Mass Storage interface,\r
+ * readying the device for the next CBW.\r
+ *\r
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
+ */\r
+uint8_t MassStore_MassStorageReset(void)\r
+{\r
+ USB_ControlRequest = (USB_Request_Header_t)\r
+ {\r
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),\r
+ .bRequest = REQ_MassStorageReset,\r
+ .wValue = 0,\r
+ .wIndex = 0,\r
+ .wLength = 0,\r
+ };\r
+ \r
+ /* Select the control pipe for the request transfer */\r
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
+\r
+ return USB_Host_SendControlRequest(NULL);\r
+}\r
+\r
+/** Issues a Mass Storage class specific request to determine the index of the highest numbered Logical\r
+ * Unit in the attached device.\r
+ *\r
+ * \param MaxLUNIndex Pointer to the location that the maximum LUN index value should be stored\r
+ *\r
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
+ */\r
+uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex)\r
+{\r
+ uint8_t ErrorCode;\r
+\r
+ USB_ControlRequest = (USB_Request_Header_t)\r
+ {\r
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),\r
+ .bRequest = REQ_GetMaxLUN,\r
+ .wValue = 0,\r
+ .wIndex = 0,\r
+ .wLength = 1,\r
+ };\r
+ \r
+ /* Select the control pipe for the request transfer */\r
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
+\r
+ if ((ErrorCode = USB_Host_SendControlRequest(MaxLUNIndex)) == HOST_SENDCONTROL_SetupStalled)\r
+ {\r
+ /* Clear the pipe stall */\r
+ Pipe_ClearStall();\r
+ \r
+ /* Some faulty Mass Storage devices don't implement the GET_MAX_LUN request, so assume a single LUN */\r
+ *MaxLUNIndex = 0; \r
+ }\r
+ \r
+ return ErrorCode;\r
+}\r
+\r
+/** Issues a SCSI Request Sense command to the attached device, to determine the current SCSI sense information. This\r
+ * gives error codes for the last issued SCSI command to the device.\r
+ *\r
+ * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
+ * \param SensePtr Pointer to the sense data structure where the sense data from the device is to be stored\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_Response_t* const SensePtr)\r
+{\r
+ uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+\r
+ /* Create a CBW with a SCSI command to issue REQUEST SENSE command */\r
+ SCSICommandBlock = (CommandBlockWrapper_t)\r
+ {\r
+ .Header =\r
+ {\r
+ .Signature = CBW_SIGNATURE,\r
+ .Tag = MassStore_Tag,\r
+ .DataTransferLength = sizeof(SCSI_Request_Sense_Response_t),\r
+ .Flags = COMMAND_DIRECTION_DATA_IN,\r
+ .LUN = LUNIndex,\r
+ .SCSICommandLength = 6\r
+ },\r
+ \r
+ .SCSICommandData =\r
+ {\r
+ SCSI_CMD_REQUEST_SENSE,\r
+ 0x00, // Reserved\r
+ 0x00, // Reserved\r
+ 0x00, // Reserved\r
+ sizeof(SCSI_Request_Sense_Response_t), // Allocation Length\r
+ 0x00 // Unused (control)\r
+ }\r
+ };\r
+ \r
+ /* Send SCSI command to the attached device */\r
+ MassStore_SendCommand();\r
+\r
+ /* Wait until data received from the device */\r
+ if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ }\r
+\r
+ /* Read the returned sense data into the buffer */\r
+ if ((ReturnCode = MassStore_SendReceiveData((uint8_t*)SensePtr)) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ } \r
+ \r
+ /* Read in the returned CSW from the device */\r
+ if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ }\r
+ \r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Issues a SCSI Device Block Read command to the attached device, to read in one or more data blocks from the\r
+ * storage medium into a buffer.\r
+ *\r
+ * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
+ * \param BlockAddress Start block address to read from\r
+ * \param Blocks Number of blocks to read from the device\r
+ * \param BlockSize Size in bytes of each block to read\r
+ * \param BufferPtr Pointer to the buffer where the read data is to be written to\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
+ const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr)\r
+{\r
+ uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+\r
+ /* Create a CBW with a SCSI command to read in the given blocks from the device */\r
+ SCSICommandBlock = (CommandBlockWrapper_t)\r
+ {\r
+ .Header =\r
+ {\r
+ .Signature = CBW_SIGNATURE,\r
+ .Tag = MassStore_Tag,\r
+ .DataTransferLength = ((uint32_t)Blocks * BlockSize),\r
+ .Flags = COMMAND_DIRECTION_DATA_IN,\r
+ .LUN = LUNIndex,\r
+ .SCSICommandLength = 10\r
+ },\r
+ \r
+ .SCSICommandData =\r
+ {\r
+ SCSI_CMD_READ_10,\r
+ 0x00, // Unused (control bits, all off)\r
+ (BlockAddress >> 24), // MSB of Block Address\r
+ (BlockAddress >> 16),\r
+ (BlockAddress >> 8),\r
+ (BlockAddress & 0xFF), // LSB of Block Address\r
+ 0x00, // Unused (reserved)\r
+ 0x00, // MSB of Total Blocks to Read\r
+ Blocks, // LSB of Total Blocks to Read\r
+ 0x00 // Unused (control)\r
+ }\r
+ };\r
+ \r
+ /* Send SCSI command to the attached device */\r
+ MassStore_SendCommand();\r
+\r
+ /* Wait until data received from the device */\r
+ if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ }\r
+\r
+ /* Read the returned block data into the buffer */\r
+ if ((ReturnCode = MassStore_SendReceiveData(BufferPtr)) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ } \r
+ \r
+ /* Read in the returned CSW from the device */\r
+ if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ }\r
+ \r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Issues a SCSI Device Block Write command to the attached device, to write one or more data blocks to the\r
+ * storage medium from a buffer.\r
+ *\r
+ * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
+ * \param BlockAddress Start block address to write to\r
+ * \param Blocks Number of blocks to write to in the device\r
+ * \param BlockSize Size in bytes of each block to write\r
+ * \param BufferPtr Pointer to the buffer where the write data is to be sourced from\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
+ const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr)\r
+{\r
+ uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+\r
+ /* Create a CBW with a SCSI command to write the given blocks to the device */\r
+ SCSICommandBlock = (CommandBlockWrapper_t)\r
+ {\r
+ .Header =\r
+ {\r
+ .Signature = CBW_SIGNATURE,\r
+ .Tag = MassStore_Tag,\r
+ .DataTransferLength = ((uint32_t)Blocks * BlockSize),\r
+ .Flags = COMMAND_DIRECTION_DATA_OUT,\r
+ .LUN = LUNIndex,\r
+ .SCSICommandLength = 10\r
+ },\r
+ \r
+ .SCSICommandData =\r
+ {\r
+ SCSI_CMD_WRITE_10,\r
+ 0x00, // Unused (control bits, all off)\r
+ (BlockAddress >> 24), // MSB of Block Address\r
+ (BlockAddress >> 16),\r
+ (BlockAddress >> 8),\r
+ (BlockAddress & 0xFF), // LSB of Block Address\r
+ 0x00, // Unused (reserved)\r
+ 0x00, // MSB of Total Blocks to Write\r
+ Blocks, // LSB of Total Blocks to Write\r
+ 0x00 // Unused (control)\r
+ }\r
+ };\r
+ \r
+ /* Send SCSI command to the attached device */\r
+ MassStore_SendCommand();\r
+\r
+ /* Write the data to the device from the buffer */\r
+ if ((ReturnCode = MassStore_SendReceiveData(BufferPtr)) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ } \r
+ \r
+ /* Read in the returned CSW from the device */\r
+ if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ }\r
+ \r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Issues a SCSI Device Test Unit Ready command to the attached device, to determine if the device is ready to accept\r
+ * other commands.\r
+ *\r
+ * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex)\r
+{\r
+ uint8_t ReturnCode = PIPE_RWSTREAM_NoError; \r
+\r
+ /* Create a CBW with a SCSI command to issue TEST UNIT READY command */\r
+ SCSICommandBlock = (CommandBlockWrapper_t)\r
+ {\r
+ .Header =\r
+ {\r
+ .Signature = CBW_SIGNATURE,\r
+ .Tag = MassStore_Tag,\r
+ .DataTransferLength = 0,\r
+ .Flags = COMMAND_DIRECTION_DATA_IN,\r
+ .LUN = LUNIndex,\r
+ .SCSICommandLength = 6\r
+ },\r
+ \r
+ .SCSICommandData =\r
+ {\r
+ SCSI_CMD_TEST_UNIT_READY,\r
+ 0x00, // Reserved\r
+ 0x00, // Reserved\r
+ 0x00, // Reserved\r
+ 0x00, // Reserved\r
+ 0x00 // Unused (control)\r
+ }\r
+ };\r
+ \r
+ /* Send SCSI command to the attached device */\r
+ MassStore_SendCommand();\r
+\r
+ /* Read in the returned CSW from the device */\r
+ if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ }\r
+ \r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Issues a SCSI Device Read Capacity command to the attached device, to determine the capacity of the\r
+ * given Logical Unit within the device.\r
+ *\r
+ * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
+ * \param CapacityPtr Device capacity structure where the capacity data is to be stored\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const CapacityPtr)\r
+{\r
+ uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+\r
+ /* Create a CBW with a SCSI command to issue READ CAPACITY command */\r
+ SCSICommandBlock = (CommandBlockWrapper_t)\r
+ {\r
+ .Header =\r
+ {\r
+ .Signature = CBW_SIGNATURE,\r
+ .Tag = MassStore_Tag,\r
+ .DataTransferLength = sizeof(SCSI_Capacity_t),\r
+ .Flags = COMMAND_DIRECTION_DATA_IN,\r
+ .LUN = LUNIndex,\r
+ .SCSICommandLength = 10\r
+ },\r
+ \r
+ .SCSICommandData =\r
+ {\r
+ SCSI_CMD_READ_CAPACITY_10,\r
+ 0x00, // Reserved\r
+ 0x00, // MSB of Logical block address\r
+ 0x00,\r
+ 0x00,\r
+ 0x00, // LSB of Logical block address\r
+ 0x00, // Reserved\r
+ 0x00, // Reserved\r
+ 0x00, // Partial Medium Indicator\r
+ 0x00 // Unused (control)\r
+ }\r
+ };\r
+ \r
+ /* Send SCSI command to the attached device */\r
+ MassStore_SendCommand();\r
+\r
+ /* Wait until data received from the device */\r
+ if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ }\r
+\r
+ /* Read the returned capacity data into the buffer */\r
+ if ((ReturnCode = MassStore_SendReceiveData(CapacityPtr)) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ }\r
+ \r
+ /* Endian-correct the read data */\r
+ CapacityPtr->Blocks = SwapEndian_32(CapacityPtr->Blocks);\r
+ CapacityPtr->BlockSize = SwapEndian_32(CapacityPtr->BlockSize);\r
+ \r
+ /* Read in the returned CSW from the device */\r
+ if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ }\r
+ \r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Issues a SCSI Device Prevent/Allow Medium Removal command to the attached device, to lock the physical media from\r
+ * being removed. This is a legacy command for SCSI disks with removable storage (such as ZIP disks), but should still\r
+ * be issued before the first read or write command is sent.\r
+ *\r
+ * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
+ * \param PreventRemoval Whether or not the LUN media should be locked to prevent removal or not\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex, const bool PreventRemoval)\r
+{\r
+ uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
+\r
+ /* Create a CBW with a SCSI command to issue PREVENT ALLOW MEDIUM REMOVAL command */\r
+ SCSICommandBlock = (CommandBlockWrapper_t)\r
+ {\r
+ .Header =\r
+ {\r
+ .Signature = CBW_SIGNATURE,\r
+ .Tag = MassStore_Tag,\r
+ .DataTransferLength = 0,\r
+ .Flags = COMMAND_DIRECTION_DATA_OUT,\r
+ .LUN = LUNIndex,\r
+ .SCSICommandLength = 6\r
+ },\r
+ \r
+ .SCSICommandData =\r
+ {\r
+ SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL,\r
+ 0x00, // Reserved\r
+ 0x00, // Reserved\r
+ PreventRemoval, // Prevent flag\r
+ 0x00, // Reserved\r
+ 0x00 // Unused (control)\r
+ }\r
+ };\r
+ \r
+ /* Send SCSI command to the attached device */\r
+ MassStore_SendCommand();\r
+\r
+ /* Read in the returned CSW from the device */\r
+ if ((ReturnCode = MassStore_GetReturnedStatus()))\r
+ {\r
+ Pipe_Freeze();\r
+ return ReturnCode;\r
+ }\r
+ \r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for MassStoreCommands.c.\r
+ */\r
+ \r
+#ifndef _MASS_STORE_COMMANDS_H_\r
+#define _MASS_STORE_COMMANDS_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+\r
+ #include "MassStorageHost.h"\r
+ #include "SCSI_Codes.h"\r
+\r
+ #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
+\r
+ /* Macros: */\r
+ /** Class specific request to reset the Mass Storage interface of the attached device */\r
+ #define REQ_MassStorageReset 0xFF\r
+\r
+ /** Class specific request to retrieve the maximum Logical Unit Number (LUN) index of the attached device */\r
+ #define REQ_GetMaxLUN 0xFE\r
+\r
+ /** Command Block Wrapper signature byte, for verification of valid CBW blocks */\r
+ #define CBW_SIGNATURE 0x43425355UL\r
+\r
+ /** Command Static Wrapper signature byte, for verification of valid CSW blocks */\r
+ #define CSW_SIGNATURE 0x53425355UL\r
+ \r
+ /** Data direction mask for the Flags field of a CBW, indicating Host-to-Device transfer direction */\r
+ #define COMMAND_DIRECTION_DATA_OUT (0 << 7)\r
+\r
+ /** Data direction mask for the Flags field of a CBW, indicating Device-to-Host transfer direction */\r
+ #define COMMAND_DIRECTION_DATA_IN (1 << 7)\r
+ \r
+ /** Timeout period between the issuing of a CBW to a device, and the reception of the first packet */\r
+ #define COMMAND_DATA_TIMEOUT_MS 500\r
+\r
+ /** Pipe number of the Mass Storage data IN pipe */\r
+ #define MASS_STORE_DATA_IN_PIPE 1\r
+\r
+ /** Pipe number of the Mass Storage data OUT pipe */\r
+ #define MASS_STORE_DATA_OUT_PIPE 2\r
+\r
+ /* Type defines: */\r
+ /** Type define for a Mass Storage class Command Block Wrapper, used to wrap SCSI\r
+ * commands for transport over the USB bulk endpoints to the device.\r
+ */\r
+ typedef struct\r
+ {\r
+ struct\r
+ {\r
+ uint32_t Signature; /**< Command block signature, always equal to CBW_SIGNATURE */\r
+ uint32_t Tag; /**< Current CBW tag, to positively associate a CBW with a CSW */\r
+ uint32_t DataTransferLength; /**< Length of data to transfer, following the CBW */\r
+ uint8_t Flags; /**< Block flags, equal to one of the COMMAND_DIRECTION_DATA_* macros */\r
+ uint8_t LUN; /**< Logical Unit Number the CBW is addressed to in the device */\r
+ uint8_t SCSICommandLength; /**< Length of the SCSI command in the CBW */\r
+ } Header;\r
+ \r
+ uint8_t SCSICommandData[16]; /**< SCSI command to issue to the device */\r
+ } CommandBlockWrapper_t;\r
+ \r
+ /** Type define for a Mass Storage class Command Status Wrapper, used to wrap SCSI\r
+ * responses for transport over the USB bulk endpoints from the device.\r
+ */\r
+ typedef struct\r
+ {\r
+ uint32_t Signature; /**< Command status signature, always equal to CSW_SIGNATURE */\r
+ uint32_t Tag; /**< Current CBW tag, to positively associate a CBW with a CSW */\r
+ uint32_t DataTransferResidue; /**< Length of data not transferred */\r
+ uint8_t Status; /**< Command status, a value from the MassStorageHost_CommandStatusCodes_t enum */\r
+ } CommandStatusWrapper_t;\r
+ \r
+ /** Type define for a SCSI Sense structure. Structures of this type are filled out by the\r
+ * device via the MassStore_RequestSense() function, indicating the current sense data of the\r
+ * device (giving explicit error codes for the last issued command). For details of the\r
+ * structure contents, refer to the SCSI specifications.\r
+ */\r
+ typedef struct\r
+ {\r
+ uint8_t ReponseCode;\r
+\r
+ uint8_t SegmentNumber;\r
+ \r
+ unsigned char SenseKey : 4;\r
+ unsigned char _RESERVED1 : 1;\r
+ unsigned char ILI : 1;\r
+ unsigned char EOM : 1;\r
+ unsigned char FileMark : 1;\r
+ \r
+ uint8_t Information[4];\r
+ uint8_t AdditionalLength;\r
+ uint8_t CmdSpecificInformation[4];\r
+ uint8_t AdditionalSenseCode;\r
+ uint8_t AdditionalSenseQualifier;\r
+ uint8_t FieldReplaceableUnitCode;\r
+ uint8_t SenseKeySpecific[3];\r
+ } SCSI_Request_Sense_Response_t;\r
+\r
+ /** SCSI capacity structure, to hold the total capacity of the device in both the number\r
+ * of blocks in the current LUN, and the size of each block. This structure is filled by\r
+ * the device when the MassStore_ReadCapacity() function is called.\r
+ */\r
+ typedef struct\r
+ {\r
+ uint32_t Blocks; /**< Number of blocks in the addressed LUN of the device */\r
+ uint32_t BlockSize; /**< Number of bytes in each block in the addressed LUN */\r
+ } SCSI_Capacity_t;\r
+\r
+ /* Enums: */\r
+ /** CSW status return codes, indicating the overall status of the issued CBW */\r
+ enum MassStorageHost_CommandStatusCodes_t\r
+ {\r
+ Command_Pass = 0, /**< Command completed successfully */\r
+ Command_Fail = 1, /**< Command failed to complete successfully */\r
+ Phase_Error = 2 /**< Phase error while processing the issued command */\r
+ };\r
+ \r
+ /* External Variables: */\r
+ extern CommandStatusWrapper_t SCSICommandStatus;\r
+ \r
+ /* Function Prototypes: */\r
+ #if defined(INCLUDE_FROM_MASSSTORE_COMMANDS_C)\r
+ static uint8_t MassStore_SendCommand(void);\r
+ static uint8_t MassStore_WaitForDataReceived(void);\r
+ static uint8_t MassStore_SendReceiveData(void* BufferPtr) ATTR_NON_NULL_PTR_ARG(1);\r
+ static uint8_t MassStore_GetReturnedStatus(void);\r
+ #endif\r
+ \r
+ uint8_t MassStore_ClearPipeStall(const uint8_t EndpointNum);\r
+ uint8_t MassStore_MassStorageReset(void);\r
+ uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex);\r
+ uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_Response_t* const SensePtr)\r
+ ATTR_NON_NULL_PTR_ARG(2);\r
+ uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
+ const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr) ATTR_NON_NULL_PTR_ARG(5);\r
+ uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
+ const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr) ATTR_NON_NULL_PTR_ARG(5);\r
+ uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const CapacityPtr)\r
+ ATTR_NON_NULL_PTR_ARG(2);\r
+ uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex);\r
+ uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex, const bool PreventRemoval);\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header containing macros for possible SCSI commands and SENSE data. Refer to\r
+ * the SCSI standard documentation for more information on each SCSI command and\r
+ * the SENSE data.\r
+ */\r
+ \r
+#ifndef _SCSI_CODES_H_\r
+#define _SCSI_CODES_H_\r
+\r
+ /* Macros: */\r
+ #define SCSI_CMD_INQUIRY 0x12\r
+ #define SCSI_CMD_REQUEST_SENSE 0x03\r
+ #define SCSI_CMD_TEST_UNIT_READY 0x00\r
+ #define SCSI_CMD_READ_CAPACITY_10 0x25\r
+ #define SCSI_CMD_SEND_DIAGNOSTIC 0x1D\r
+ #define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E\r
+ #define SCSI_CMD_WRITE_10 0x2A\r
+ #define SCSI_CMD_READ_10 0x28\r
+ #define SCSI_CMD_WRITE_6 0x0A\r
+ #define SCSI_CMD_READ_6 0x08\r
+ #define SCSI_CMD_VERIFY_10 0x2F\r
+ #define SCSI_CMD_MODE_SENSE_6 0x1A\r
+ #define SCSI_CMD_MODE_SENSE_10 0x5A\r
+\r
+ #define SCSI_SENSE_KEY_GOOD 0x00\r
+ #define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01\r
+ #define SCSI_SENSE_KEY_NOT_READY 0x02\r
+ #define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03\r
+ #define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04\r
+ #define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05\r
+ #define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06\r
+ #define SCSI_SENSE_KEY_DATA_PROTECT 0x07\r
+ #define SCSI_SENSE_KEY_BLANK_CHECK 0x08\r
+ #define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09\r
+ #define SCSI_SENSE_KEY_COPY_ABORTED 0x0A\r
+ #define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B\r
+ #define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D\r
+ #define SCSI_SENSE_KEY_MISCOMPARE 0x0E\r
+\r
+ #define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00\r
+ #define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04\r
+ #define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24\r
+ #define SCSI_ASENSE_WRITE_PROTECTED 0x27\r
+ #define SCSI_ASENSE_FORMAT_ERROR 0x31\r
+ #define SCSI_ASENSE_INVALID_COMMAND 0x20\r
+ #define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21\r
+ #define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A\r
+\r
+ #define SCSI_ASENSEQ_NO_QUALIFIER 0x00\r
+ #define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01\r
+ #define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02\r
+ #define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07\r
+\r
+#endif\r
#include <ctype.h>\r
\r
#include "ConfigDescriptor.h"\r
- #include "MassStoreCommands.h"\r
+\r
+ #include "Lib/MassStoreCommands.h"\r
\r
#include <LUFA/Version.h> // Library Version Information\r
#include <LUFA/Drivers/Misc/TerminalCodes.h> // ANSI Terminal Escape Codes\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Mass Storage Device commands, to issue MSD commands to the device for\r
- * reading device status, capacity, and other characteristics. This file\r
- * also contains block read and write functions, so that device blocks\r
- * can be read and written. In general, these functions would be chained\r
- * to a FAT library to give file-level access to an attached device's contents.\r
- *\r
- * \note Many Mass Storage devices on the market are non-compliant to the\r
- * specifications and thus can prove difficult to interface with. It\r
- * may be necessary to retry the functions in the module several times\r
- * after they have returned and error to successfully send the command\r
- * to the device. Some devices may also need to have the stream function\r
- * timeout period extended beyond 100ms (some badly designed devices exceeding\r
- * 1.5 seconds occasionally) by defining USB_STREAM_TIMEOUT_MS to a\r
- * larger value in the project makefile and passing it to the compiler\r
- * via the -D switch.\r
- */\r
- \r
-#define INCLUDE_FROM_MASSSTORE_COMMANDS_C\r
-#include "MassStoreCommands.h"\r
-\r
-/* Globals: */\r
-/** Current CBW to send to the device. This is automatically filled by the routines\r
- * in this file and is not externally accessible.\r
- */\r
-static CommandBlockWrapper_t SCSICommandBlock;\r
-\r
-/** Current CSW received from the device. This is automatically filled by the routines\r
- * in this file and is externally accessible so that the return codes may be checked.\r
- */\r
-CommandStatusWrapper_t SCSICommandStatus;\r
-\r
-/** Current Tag value used in issued CBWs to the device. This is automatically incremented\r
- * by the routines in this file, and is not externally accessible.\r
- */\r
-static uint32_t MassStore_Tag = 1;\r
-\r
-\r
-/** Routine to send the current CBW to the device, and increment the Tag value as needed.\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-static uint8_t MassStore_SendCommand(void)\r
-{\r
- uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
-\r
- /* Each transmission should have a unique tag value, excluding values 0 and 0xFFFFFFFF */\r
- if (++MassStore_Tag == 0xFFFFFFFF)\r
- MassStore_Tag = 1;\r
-\r
- /* Select the OUT data pipe for CBW transmission */\r
- Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE);\r
- Pipe_Unfreeze();\r
-\r
- /* Write the CBW command to the OUT pipe */\r
- if ((ErrorCode = Pipe_Write_Stream_LE(&SCSICommandBlock, sizeof(CommandBlockWrapper_t))) != PIPE_RWSTREAM_NoError)\r
- return ErrorCode;\r
-\r
- /* Send the data in the OUT pipe to the attached device */\r
- Pipe_ClearOUT();\r
- \r
- while(!(Pipe_IsOUTReady()));\r
-\r
- /* Freeze pipe after use */\r
- Pipe_Freeze();\r
- \r
- return PIPE_RWSTREAM_NoError;\r
-}\r
-\r
-/** Waits until the attached device is ready to accept data following a CBW, checking\r
- * to ensure that the device has not stalled the transaction.\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-static uint8_t MassStore_WaitForDataReceived(void)\r
-{\r
- uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;\r
-\r
- /* Unfreeze the OUT pipe so that it can be checked */\r
- Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE);\r
- Pipe_Unfreeze();\r
-\r
- /* Select the IN data pipe for data reception */\r
- Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);\r
- Pipe_Unfreeze();\r
-\r
- /* Wait until data received in the IN pipe */\r
- while (!(Pipe_IsINReceived()))\r
- {\r
- /* Check to see if a new frame has been issued (1ms elapsed) */\r
- if (USB_INT_HasOccurred(USB_INT_HSOFI))\r
- {\r
- /* Clear the flag and decrement the timeout period counter */\r
- USB_INT_Clear(USB_INT_HSOFI);\r
- TimeoutMSRem--;\r
-\r
- /* Check to see if the timeout period for the command has elapsed */\r
- if (!(TimeoutMSRem))\r
- return PIPE_RWSTREAM_Timeout;\r
- }\r
- \r
- Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE);\r
-\r
- /* Check if pipe stalled (command failed by device) */\r
- if (Pipe_IsStalled())\r
- {\r
- /* Clear the stall condition on the OUT pipe */\r
- MassStore_ClearPipeStall(MASS_STORE_DATA_OUT_PIPE);\r
-\r
- return PIPE_RWSTREAM_PipeStalled;\r
- }\r
-\r
- Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);\r
-\r
- /* Check if pipe stalled (command failed by device) */\r
- if (Pipe_IsStalled())\r
- {\r
- /* Clear the stall condition on the IN pipe */\r
- MassStore_ClearPipeStall(MASS_STORE_DATA_IN_PIPE);\r
-\r
- return PIPE_RWSTREAM_PipeStalled;\r
- }\r
- \r
- /* Check to see if the device was disconnected, if so exit function */\r
- if (!(USB_IsConnected))\r
- return PIPE_RWSTREAM_DeviceDisconnected;\r
- };\r
-\r
- return PIPE_RWSTREAM_NoError;\r
-}\r
-\r
-/** Sends or receives the transaction's data stage to or from the attached device, reading or\r
- * writing to the nominated buffer.\r
- *\r
- * \param BufferPtr Pointer to the data buffer to read from or write to\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-static uint8_t MassStore_SendReceiveData(void* BufferPtr)\r
-{\r
- uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
- uint16_t BytesRem = SCSICommandBlock.Header.DataTransferLength;\r
-\r
- /* Check the direction of the SCSI command data stage */\r
- if (SCSICommandBlock.Header.Flags & COMMAND_DIRECTION_DATA_IN)\r
- {\r
- /* Select the IN data pipe for data reception */\r
- Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);\r
- Pipe_Unfreeze();\r
- \r
- /* Read in the block data from the pipe */\r
- if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError)\r
- return ErrorCode;\r
-\r
- /* Acknowledge the packet */\r
- Pipe_ClearIN();\r
- }\r
- else\r
- {\r
- /* Select the OUT data pipe for data transmission */\r
- Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE);\r
- Pipe_Unfreeze();\r
-\r
- /* Write the block data to the pipe */\r
- if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError)\r
- return ErrorCode;\r
-\r
- /* Acknowledge the packet */\r
- Pipe_ClearOUT();\r
- \r
- while (!(Pipe_IsOUTReady()));\r
- }\r
- \r
- /* Freeze used pipe after use */\r
- Pipe_Freeze();\r
-\r
- return PIPE_RWSTREAM_NoError;\r
-}\r
-\r
-/** Routine to receive the current CSW from the device.\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-static uint8_t MassStore_GetReturnedStatus(void)\r
-{\r
- uint8_t ErrorCode = PIPE_RWSTREAM_NoError;\r
-\r
- /* If an error in the command ocurred, abort */\r
- if ((ErrorCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
- return ErrorCode;\r
-\r
- /* Select the IN data pipe for data reception */\r
- Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);\r
- Pipe_Unfreeze();\r
- \r
- /* Load in the CSW from the attached device */\r
- if ((ErrorCode = Pipe_Read_Stream_LE(&SCSICommandStatus, sizeof(CommandStatusWrapper_t))) != PIPE_RWSTREAM_NoError)\r
- return ErrorCode;\r
- \r
- /* Clear the data ready for next reception */\r
- Pipe_ClearIN();\r
- \r
- /* Freeze the IN pipe after use */\r
- Pipe_Freeze();\r
- \r
- return PIPE_RWSTREAM_NoError;\r
-}\r
-\r
-/** Clears the stall condition in the attached device on the nominated endpoint number.\r
- *\r
- * \param EndpointNum Endpoint number in the attached device whose stall condition is to be cleared\r
- *\r
- * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
- */\r
-uint8_t MassStore_ClearPipeStall(const uint8_t EndpointNum)\r
-{\r
- USB_ControlRequest = (USB_Request_Header_t)\r
- {\r
- .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT),\r
- .bRequest = REQ_ClearFeature,\r
- .wValue = FEATURE_ENDPOINT_HALT,\r
- .wIndex = EndpointNum,\r
- .wLength = 0,\r
- };\r
- \r
- /* Select the control pipe for the request transfer */\r
- Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
-\r
- return USB_Host_SendControlRequest(NULL);\r
-}\r
-\r
-/** Issues a Mass Storage class specific request to reset the attached device's Mass Storage interface,\r
- * readying the device for the next CBW.\r
- *\r
- * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
- */\r
-uint8_t MassStore_MassStorageReset(void)\r
-{\r
- USB_ControlRequest = (USB_Request_Header_t)\r
- {\r
- .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),\r
- .bRequest = REQ_MassStorageReset,\r
- .wValue = 0,\r
- .wIndex = 0,\r
- .wLength = 0,\r
- };\r
- \r
- /* Select the control pipe for the request transfer */\r
- Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
-\r
- return USB_Host_SendControlRequest(NULL);\r
-}\r
-\r
-/** Issues a Mass Storage class specific request to determine the index of the highest numbered Logical\r
- * Unit in the attached device.\r
- *\r
- * \param MaxLUNIndex Pointer to the location that the maximum LUN index value should be stored\r
- *\r
- * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
- */\r
-uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex)\r
-{\r
- uint8_t ErrorCode;\r
-\r
- USB_ControlRequest = (USB_Request_Header_t)\r
- {\r
- .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),\r
- .bRequest = REQ_GetMaxLUN,\r
- .wValue = 0,\r
- .wIndex = 0,\r
- .wLength = 1,\r
- };\r
- \r
- /* Select the control pipe for the request transfer */\r
- Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
-\r
- if ((ErrorCode = USB_Host_SendControlRequest(MaxLUNIndex)) == HOST_SENDCONTROL_SetupStalled)\r
- {\r
- /* Clear the pipe stall */\r
- Pipe_ClearStall();\r
- \r
- /* Some faulty Mass Storage devices don't implement the GET_MAX_LUN request, so assume a single LUN */\r
- *MaxLUNIndex = 0; \r
- }\r
- \r
- return ErrorCode;\r
-}\r
-\r
-/** Issues a SCSI Request Sense command to the attached device, to determine the current SCSI sense information. This\r
- * gives error codes for the last issued SCSI command to the device.\r
- *\r
- * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
- * \param SensePtr Pointer to the sense data structure where the sense data from the device is to be stored\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_Response_t* const SensePtr)\r
-{\r
- uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
-\r
- /* Create a CBW with a SCSI command to issue REQUEST SENSE command */\r
- SCSICommandBlock = (CommandBlockWrapper_t)\r
- {\r
- .Header =\r
- {\r
- .Signature = CBW_SIGNATURE,\r
- .Tag = MassStore_Tag,\r
- .DataTransferLength = sizeof(SCSI_Request_Sense_Response_t),\r
- .Flags = COMMAND_DIRECTION_DATA_IN,\r
- .LUN = LUNIndex,\r
- .SCSICommandLength = 6\r
- },\r
- \r
- .SCSICommandData =\r
- {\r
- SCSI_CMD_REQUEST_SENSE,\r
- 0x00, // Reserved\r
- 0x00, // Reserved\r
- 0x00, // Reserved\r
- sizeof(SCSI_Request_Sense_Response_t), // Allocation Length\r
- 0x00 // Unused (control)\r
- }\r
- };\r
- \r
- /* Send SCSI command to the attached device */\r
- MassStore_SendCommand();\r
-\r
- /* Wait until data received from the device */\r
- if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- }\r
-\r
- /* Read the returned sense data into the buffer */\r
- if ((ReturnCode = MassStore_SendReceiveData((uint8_t*)SensePtr)) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- } \r
- \r
- /* Read in the returned CSW from the device */\r
- if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- }\r
- \r
- return PIPE_RWSTREAM_NoError;\r
-}\r
-\r
-/** Issues a SCSI Device Block Read command to the attached device, to read in one or more data blocks from the\r
- * storage medium into a buffer.\r
- *\r
- * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
- * \param BlockAddress Start block address to read from\r
- * \param Blocks Number of blocks to read from the device\r
- * \param BlockSize Size in bytes of each block to read\r
- * \param BufferPtr Pointer to the buffer where the read data is to be written to\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
- const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr)\r
-{\r
- uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
-\r
- /* Create a CBW with a SCSI command to read in the given blocks from the device */\r
- SCSICommandBlock = (CommandBlockWrapper_t)\r
- {\r
- .Header =\r
- {\r
- .Signature = CBW_SIGNATURE,\r
- .Tag = MassStore_Tag,\r
- .DataTransferLength = ((uint32_t)Blocks * BlockSize),\r
- .Flags = COMMAND_DIRECTION_DATA_IN,\r
- .LUN = LUNIndex,\r
- .SCSICommandLength = 10\r
- },\r
- \r
- .SCSICommandData =\r
- {\r
- SCSI_CMD_READ_10,\r
- 0x00, // Unused (control bits, all off)\r
- (BlockAddress >> 24), // MSB of Block Address\r
- (BlockAddress >> 16),\r
- (BlockAddress >> 8),\r
- (BlockAddress & 0xFF), // LSB of Block Address\r
- 0x00, // Unused (reserved)\r
- 0x00, // MSB of Total Blocks to Read\r
- Blocks, // LSB of Total Blocks to Read\r
- 0x00 // Unused (control)\r
- }\r
- };\r
- \r
- /* Send SCSI command to the attached device */\r
- MassStore_SendCommand();\r
-\r
- /* Wait until data received from the device */\r
- if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- }\r
-\r
- /* Read the returned block data into the buffer */\r
- if ((ReturnCode = MassStore_SendReceiveData(BufferPtr)) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- } \r
- \r
- /* Read in the returned CSW from the device */\r
- if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- }\r
- \r
- return PIPE_RWSTREAM_NoError;\r
-}\r
-\r
-/** Issues a SCSI Device Block Write command to the attached device, to write one or more data blocks to the\r
- * storage medium from a buffer.\r
- *\r
- * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
- * \param BlockAddress Start block address to write to\r
- * \param Blocks Number of blocks to write to in the device\r
- * \param BlockSize Size in bytes of each block to write\r
- * \param BufferPtr Pointer to the buffer where the write data is to be sourced from\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
- const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr)\r
-{\r
- uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
-\r
- /* Create a CBW with a SCSI command to write the given blocks to the device */\r
- SCSICommandBlock = (CommandBlockWrapper_t)\r
- {\r
- .Header =\r
- {\r
- .Signature = CBW_SIGNATURE,\r
- .Tag = MassStore_Tag,\r
- .DataTransferLength = ((uint32_t)Blocks * BlockSize),\r
- .Flags = COMMAND_DIRECTION_DATA_OUT,\r
- .LUN = LUNIndex,\r
- .SCSICommandLength = 10\r
- },\r
- \r
- .SCSICommandData =\r
- {\r
- SCSI_CMD_WRITE_10,\r
- 0x00, // Unused (control bits, all off)\r
- (BlockAddress >> 24), // MSB of Block Address\r
- (BlockAddress >> 16),\r
- (BlockAddress >> 8),\r
- (BlockAddress & 0xFF), // LSB of Block Address\r
- 0x00, // Unused (reserved)\r
- 0x00, // MSB of Total Blocks to Write\r
- Blocks, // LSB of Total Blocks to Write\r
- 0x00 // Unused (control)\r
- }\r
- };\r
- \r
- /* Send SCSI command to the attached device */\r
- MassStore_SendCommand();\r
-\r
- /* Write the data to the device from the buffer */\r
- if ((ReturnCode = MassStore_SendReceiveData(BufferPtr)) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- } \r
- \r
- /* Read in the returned CSW from the device */\r
- if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- }\r
- \r
- return PIPE_RWSTREAM_NoError;\r
-}\r
-\r
-/** Issues a SCSI Device Test Unit Ready command to the attached device, to determine if the device is ready to accept\r
- * other commands.\r
- *\r
- * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex)\r
-{\r
- uint8_t ReturnCode = PIPE_RWSTREAM_NoError; \r
-\r
- /* Create a CBW with a SCSI command to issue TEST UNIT READY command */\r
- SCSICommandBlock = (CommandBlockWrapper_t)\r
- {\r
- .Header =\r
- {\r
- .Signature = CBW_SIGNATURE,\r
- .Tag = MassStore_Tag,\r
- .DataTransferLength = 0,\r
- .Flags = COMMAND_DIRECTION_DATA_IN,\r
- .LUN = LUNIndex,\r
- .SCSICommandLength = 6\r
- },\r
- \r
- .SCSICommandData =\r
- {\r
- SCSI_CMD_TEST_UNIT_READY,\r
- 0x00, // Reserved\r
- 0x00, // Reserved\r
- 0x00, // Reserved\r
- 0x00, // Reserved\r
- 0x00 // Unused (control)\r
- }\r
- };\r
- \r
- /* Send SCSI command to the attached device */\r
- MassStore_SendCommand();\r
-\r
- /* Read in the returned CSW from the device */\r
- if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- }\r
- \r
- return PIPE_RWSTREAM_NoError;\r
-}\r
-\r
-/** Issues a SCSI Device Read Capacity command to the attached device, to determine the capacity of the\r
- * given Logical Unit within the device.\r
- *\r
- * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
- * \param CapacityPtr Device capacity structure where the capacity data is to be stored\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const CapacityPtr)\r
-{\r
- uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
-\r
- /* Create a CBW with a SCSI command to issue READ CAPACITY command */\r
- SCSICommandBlock = (CommandBlockWrapper_t)\r
- {\r
- .Header =\r
- {\r
- .Signature = CBW_SIGNATURE,\r
- .Tag = MassStore_Tag,\r
- .DataTransferLength = sizeof(SCSI_Capacity_t),\r
- .Flags = COMMAND_DIRECTION_DATA_IN,\r
- .LUN = LUNIndex,\r
- .SCSICommandLength = 10\r
- },\r
- \r
- .SCSICommandData =\r
- {\r
- SCSI_CMD_READ_CAPACITY_10,\r
- 0x00, // Reserved\r
- 0x00, // MSB of Logical block address\r
- 0x00,\r
- 0x00,\r
- 0x00, // LSB of Logical block address\r
- 0x00, // Reserved\r
- 0x00, // Reserved\r
- 0x00, // Partial Medium Indicator\r
- 0x00 // Unused (control)\r
- }\r
- };\r
- \r
- /* Send SCSI command to the attached device */\r
- MassStore_SendCommand();\r
-\r
- /* Wait until data received from the device */\r
- if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- }\r
-\r
- /* Read the returned capacity data into the buffer */\r
- if ((ReturnCode = MassStore_SendReceiveData(CapacityPtr)) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- }\r
- \r
- /* Endian-correct the read data */\r
- CapacityPtr->Blocks = SwapEndian_32(CapacityPtr->Blocks);\r
- CapacityPtr->BlockSize = SwapEndian_32(CapacityPtr->BlockSize);\r
- \r
- /* Read in the returned CSW from the device */\r
- if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError)\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- }\r
- \r
- return PIPE_RWSTREAM_NoError;\r
-}\r
-\r
-/** Issues a SCSI Device Prevent/Allow Medium Removal command to the attached device, to lock the physical media from\r
- * being removed. This is a legacy command for SCSI disks with removable storage (such as ZIP disks), but should still\r
- * be issued before the first read or write command is sent.\r
- *\r
- * \param LUNIndex Index of the LUN inside the device the command is being addressed to\r
- * \param PreventRemoval Whether or not the LUN media should be locked to prevent removal or not\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex, const bool PreventRemoval)\r
-{\r
- uint8_t ReturnCode = PIPE_RWSTREAM_NoError;\r
-\r
- /* Create a CBW with a SCSI command to issue PREVENT ALLOW MEDIUM REMOVAL command */\r
- SCSICommandBlock = (CommandBlockWrapper_t)\r
- {\r
- .Header =\r
- {\r
- .Signature = CBW_SIGNATURE,\r
- .Tag = MassStore_Tag,\r
- .DataTransferLength = 0,\r
- .Flags = COMMAND_DIRECTION_DATA_OUT,\r
- .LUN = LUNIndex,\r
- .SCSICommandLength = 6\r
- },\r
- \r
- .SCSICommandData =\r
- {\r
- SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL,\r
- 0x00, // Reserved\r
- 0x00, // Reserved\r
- PreventRemoval, // Prevent flag\r
- 0x00, // Reserved\r
- 0x00 // Unused (control)\r
- }\r
- };\r
- \r
- /* Send SCSI command to the attached device */\r
- MassStore_SendCommand();\r
-\r
- /* Read in the returned CSW from the device */\r
- if ((ReturnCode = MassStore_GetReturnedStatus()))\r
- {\r
- Pipe_Freeze();\r
- return ReturnCode;\r
- }\r
- \r
- return PIPE_RWSTREAM_NoError;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for MassStoreCommands.c.\r
- */\r
- \r
-#ifndef _MASS_STORE_COMMANDS_H_\r
-#define _MASS_STORE_COMMANDS_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
-\r
- #include "MassStorageHost.h"\r
- #include "SCSI_Codes.h"\r
-\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
-\r
- /* Macros: */\r
- /** Class specific request to reset the Mass Storage interface of the attached device */\r
- #define REQ_MassStorageReset 0xFF\r
-\r
- /** Class specific request to retrieve the maximum Logical Unit Number (LUN) index of the attached device */\r
- #define REQ_GetMaxLUN 0xFE\r
-\r
- /** Command Block Wrapper signature byte, for verification of valid CBW blocks */\r
- #define CBW_SIGNATURE 0x43425355UL\r
-\r
- /** Command Static Wrapper signature byte, for verification of valid CSW blocks */\r
- #define CSW_SIGNATURE 0x53425355UL\r
- \r
- /** Data direction mask for the Flags field of a CBW, indicating Host-to-Device transfer direction */\r
- #define COMMAND_DIRECTION_DATA_OUT (0 << 7)\r
-\r
- /** Data direction mask for the Flags field of a CBW, indicating Device-to-Host transfer direction */\r
- #define COMMAND_DIRECTION_DATA_IN (1 << 7)\r
- \r
- /** Timeout period between the issuing of a CBW to a device, and the reception of the first packet */\r
- #define COMMAND_DATA_TIMEOUT_MS 500\r
-\r
- /** Pipe number of the Mass Storage data IN pipe */\r
- #define MASS_STORE_DATA_IN_PIPE 1\r
-\r
- /** Pipe number of the Mass Storage data OUT pipe */\r
- #define MASS_STORE_DATA_OUT_PIPE 2\r
-\r
- /* Type defines: */\r
- /** Type define for a Mass Storage class Command Block Wrapper, used to wrap SCSI\r
- * commands for transport over the USB bulk endpoints to the device.\r
- */\r
- typedef struct\r
- {\r
- struct\r
- {\r
- uint32_t Signature; /**< Command block signature, always equal to CBW_SIGNATURE */\r
- uint32_t Tag; /**< Current CBW tag, to positively associate a CBW with a CSW */\r
- uint32_t DataTransferLength; /**< Length of data to transfer, following the CBW */\r
- uint8_t Flags; /**< Block flags, equal to one of the COMMAND_DIRECTION_DATA_* macros */\r
- uint8_t LUN; /**< Logical Unit Number the CBW is addressed to in the device */\r
- uint8_t SCSICommandLength; /**< Length of the SCSI command in the CBW */\r
- } Header;\r
- \r
- uint8_t SCSICommandData[16]; /**< SCSI command to issue to the device */\r
- } CommandBlockWrapper_t;\r
- \r
- /** Type define for a Mass Storage class Command Status Wrapper, used to wrap SCSI\r
- * responses for transport over the USB bulk endpoints from the device.\r
- */\r
- typedef struct\r
- {\r
- uint32_t Signature; /**< Command status signature, always equal to CSW_SIGNATURE */\r
- uint32_t Tag; /**< Current CBW tag, to positively associate a CBW with a CSW */\r
- uint32_t DataTransferResidue; /**< Length of data not transferred */\r
- uint8_t Status; /**< Command status, a value from the MassStorageHost_CommandStatusCodes_t enum */\r
- } CommandStatusWrapper_t;\r
- \r
- /** Type define for a SCSI Sense structure. Structures of this type are filled out by the\r
- * device via the MassStore_RequestSense() function, indicating the current sense data of the\r
- * device (giving explicit error codes for the last issued command). For details of the\r
- * structure contents, refer to the SCSI specifications.\r
- */\r
- typedef struct\r
- {\r
- uint8_t ReponseCode;\r
-\r
- uint8_t SegmentNumber;\r
- \r
- unsigned char SenseKey : 4;\r
- unsigned char _RESERVED1 : 1;\r
- unsigned char ILI : 1;\r
- unsigned char EOM : 1;\r
- unsigned char FileMark : 1;\r
- \r
- uint8_t Information[4];\r
- uint8_t AdditionalLength;\r
- uint8_t CmdSpecificInformation[4];\r
- uint8_t AdditionalSenseCode;\r
- uint8_t AdditionalSenseQualifier;\r
- uint8_t FieldReplaceableUnitCode;\r
- uint8_t SenseKeySpecific[3];\r
- } SCSI_Request_Sense_Response_t;\r
-\r
- /** SCSI capacity structure, to hold the total capacity of the device in both the number\r
- * of blocks in the current LUN, and the size of each block. This structure is filled by\r
- * the device when the MassStore_ReadCapacity() function is called.\r
- */\r
- typedef struct\r
- {\r
- uint32_t Blocks; /**< Number of blocks in the addressed LUN of the device */\r
- uint32_t BlockSize; /**< Number of bytes in each block in the addressed LUN */\r
- } SCSI_Capacity_t;\r
-\r
- /* Enums: */\r
- /** CSW status return codes, indicating the overall status of the issued CBW */\r
- enum MassStorageHost_CommandStatusCodes_t\r
- {\r
- Command_Pass = 0, /**< Command completed successfully */\r
- Command_Fail = 1, /**< Command failed to complete successfully */\r
- Phase_Error = 2 /**< Phase error while processing the issued command */\r
- };\r
- \r
- /* External Variables: */\r
- extern CommandStatusWrapper_t SCSICommandStatus;\r
- \r
- /* Function Prototypes: */\r
- #if defined(INCLUDE_FROM_MASSSTORE_COMMANDS_C)\r
- static uint8_t MassStore_SendCommand(void);\r
- static uint8_t MassStore_WaitForDataReceived(void);\r
- static uint8_t MassStore_SendReceiveData(void* BufferPtr) ATTR_NON_NULL_PTR_ARG(1);\r
- static uint8_t MassStore_GetReturnedStatus(void);\r
- #endif\r
- \r
- uint8_t MassStore_ClearPipeStall(const uint8_t EndpointNum);\r
- uint8_t MassStore_MassStorageReset(void);\r
- uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex);\r
- uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_Response_t* const SensePtr)\r
- ATTR_NON_NULL_PTR_ARG(2);\r
- uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
- const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr) ATTR_NON_NULL_PTR_ARG(5);\r
- uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress,\r
- const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr) ATTR_NON_NULL_PTR_ARG(5);\r
- uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const CapacityPtr)\r
- ATTR_NON_NULL_PTR_ARG(2);\r
- uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex);\r
- uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex, const bool PreventRemoval);\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header containing macros for possible SCSI commands and SENSE data. Refer to\r
- * the SCSI standard documentation for more information on each SCSI command and\r
- * the SENSE data.\r
- */\r
- \r
-#ifndef _SCSI_CODES_H_\r
-#define _SCSI_CODES_H_\r
-\r
- /* Macros: */\r
- #define SCSI_CMD_INQUIRY 0x12\r
- #define SCSI_CMD_REQUEST_SENSE 0x03\r
- #define SCSI_CMD_TEST_UNIT_READY 0x00\r
- #define SCSI_CMD_READ_CAPACITY_10 0x25\r
- #define SCSI_CMD_SEND_DIAGNOSTIC 0x1D\r
- #define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E\r
- #define SCSI_CMD_WRITE_10 0x2A\r
- #define SCSI_CMD_READ_10 0x28\r
- #define SCSI_CMD_WRITE_6 0x0A\r
- #define SCSI_CMD_READ_6 0x08\r
- #define SCSI_CMD_VERIFY_10 0x2F\r
- #define SCSI_CMD_MODE_SENSE_6 0x1A\r
- #define SCSI_CMD_MODE_SENSE_10 0x5A\r
-\r
- #define SCSI_SENSE_KEY_GOOD 0x00\r
- #define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01\r
- #define SCSI_SENSE_KEY_NOT_READY 0x02\r
- #define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03\r
- #define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04\r
- #define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05\r
- #define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06\r
- #define SCSI_SENSE_KEY_DATA_PROTECT 0x07\r
- #define SCSI_SENSE_KEY_BLANK_CHECK 0x08\r
- #define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09\r
- #define SCSI_SENSE_KEY_COPY_ABORTED 0x0A\r
- #define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B\r
- #define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D\r
- #define SCSI_SENSE_KEY_MISCOMPARE 0x0E\r
-\r
- #define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00\r
- #define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04\r
- #define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24\r
- #define SCSI_ASENSE_WRITE_PROTECTED 0x27\r
- #define SCSI_ASENSE_FORMAT_ERROR 0x31\r
- #define SCSI_ASENSE_INVALID_COMMAND 0x20\r
- #define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21\r
- #define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A\r
-\r
- #define SCSI_ASENSEQ_NO_QUALIFIER 0x00\r
- #define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01\r
- #define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02\r
- #define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07\r
-\r
-#endif\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
ConfigDescriptor.c \\r
- MassStoreCommands.c \\r
+ Lib/MassStoreCommands.c \\r
$(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/Peripheral/SerialStream.c \\r
$(LUFA_PATH)/LUFA/Drivers/Peripheral/Serial.c \\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header containing macros for possible PIMA commands. Refer to the PIMA standard\r
+ * documentation for more information on each PIMA command.\r
+ */\r
+\r
+#ifndef _PIMA_CODES_H_\r
+\r
+ /* Macros: */\r
+ #define PIMA_OPERATION_GETDEVICEINFO 0x1001\r
+ #define PIMA_OPERATION_OPENSESSION 0x1002\r
+ #define PIMA_OPERATION_CLOSESESSION 0x1003\r
+ \r
+ #define PIMA_RESPONSE_OK 0x2001\r
+ #define PIMA_RESPONSE_GENERALERROR 0x2002\r
+ #define PIMA_RESPONSE_SESSIONNOTOPEN 0x2003\r
+ #define PIMA_RESPONSE_INVALIDTRANSACTIONID 0x2004\r
+ #define PIMA_RESPONSE_OPERATIONNOTSUPPORTED 0x2005\r
+ #define PIMA_RESPONSE_PARAMETERNOTSUPPORTED 0x2006\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Still Image Device commands, to issue PIMA commands to the device for\r
+ * reading device status, capacity, and other characteristics as well as\r
+ * reading and writing of stored image data.\r
+ */\r
+\r
+#include "StillImageCommands.h"\r
+\r
+/* Globals: */\r
+/** PIMA block container for the block to send to the device */\r
+PIMA_Container_t PIMA_SendBlock;\r
+\r
+/** PIMA block container for the last received block from the device */\r
+PIMA_Container_t PIMA_ReceivedBlock;\r
+\r
+/** PIMA block container for the last event block received from the device */\r
+PIMA_Container_t PIMA_EventBlock;\r
+\r
+\r
+/** Function to send the PIMA command container to the attached still image device. */\r
+void SImage_SendBlockHeader(void)\r
+{\r
+ /* Unfreeze the data OUT pipe ready for data transmission */\r
+ Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);\r
+ Pipe_Unfreeze();\r
+\r
+ /* Write the PIMA block to the data OUT pipe */\r
+ Pipe_Write_Stream_LE(&PIMA_SendBlock, PIMA_COMMAND_SIZE(0));\r
+ \r
+ /* If the block type is a command, send its parameters (if any) */\r
+ if (PIMA_SendBlock.Type == CType_CommandBlock)\r
+ {\r
+ /* Determine the size of the parameters in the block via the data length attribute */\r
+ uint8_t ParamBytes = (PIMA_SendBlock.DataLength - PIMA_COMMAND_SIZE(0));\r
+\r
+ /* Check if any parameters in the command block */\r
+ if (ParamBytes)\r
+ {\r
+ /* Write the PIMA parameters to the data OUT pipe */\r
+ Pipe_Write_Stream_LE(&PIMA_SendBlock.Params, ParamBytes);\r
+ }\r
+ \r
+ /* Send the PIMA command block to the attached device */\r
+ Pipe_ClearOUT();\r
+ }\r
+ \r
+ /* Freeze pipe after use */\r
+ Pipe_Freeze();\r
+}\r
+\r
+/** Function to receive a PIMA event container from the attached still image device. */\r
+void SImage_RecieveEventHeader(void)\r
+{\r
+ /* Unfreeze the events pipe */\r
+ Pipe_SelectPipe(SIMAGE_EVENTS_PIPE);\r
+ Pipe_Unfreeze();\r
+ \r
+ /* Read in the event data into the global structure */\r
+ Pipe_Read_Stream_LE(&PIMA_EventBlock, sizeof(PIMA_EventBlock));\r
+ \r
+ /* Clear the pipe after read complete to prepare for next event */\r
+ Pipe_ClearIN();\r
+ \r
+ /* Freeze the event pipe again after use */\r
+ Pipe_Freeze();\r
+}\r
+\r
+/** Function to receive a PIMA response container from the attached still image device. */\r
+uint8_t SImage_RecieveBlockHeader(void)\r
+{\r
+ uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;\r
+\r
+ /* Unfreeze the data IN pipe */\r
+ Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);\r
+ Pipe_Unfreeze();\r
+ \r
+ /* Wait until data received on the IN pipe */\r
+ while (!(Pipe_IsReadWriteAllowed()))\r
+ {\r
+ /* Check to see if a new frame has been issued (1ms elapsed) */\r
+ if (USB_INT_HasOccurred(USB_INT_HSOFI))\r
+ {\r
+ /* Clear the flag and decrement the timeout period counter */\r
+ USB_INT_Clear(USB_INT_HSOFI);\r
+ TimeoutMSRem--;\r
+\r
+ /* Check to see if the timeout period for the command has elapsed */\r
+ if (!(TimeoutMSRem))\r
+ {\r
+ /* Return error code */\r
+ return PIPE_RWSTREAM_Timeout;\r
+ }\r
+ }\r
+ \r
+ Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);\r
+\r
+ /* Check if pipe stalled (command failed by device) */\r
+ if (Pipe_IsStalled())\r
+ {\r
+ /* Clear the stall condition on the OUT pipe */\r
+ SImage_ClearPipeStall(SIMAGE_DATA_OUT_PIPE);\r
+\r
+ /* Return error code and break out of the loop */\r
+ return PIPE_RWSTREAM_PipeStalled;\r
+ }\r
+\r
+ Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);\r
+\r
+ /* Check if pipe stalled (command failed by device) */\r
+ if (Pipe_IsStalled())\r
+ {\r
+ /* Clear the stall condition on the IN pipe */\r
+ SImage_ClearPipeStall(SIMAGE_DATA_IN_PIPE);\r
+\r
+ /* Return error code */\r
+ return PIPE_RWSTREAM_PipeStalled;\r
+ }\r
+ \r
+ /* Check to see if the device was disconnected, if so exit function */\r
+ if (!(USB_IsConnected))\r
+ {\r
+ /* Return error code */\r
+ return PIPE_RWSTREAM_DeviceDisconnected;\r
+ }\r
+ };\r
+ \r
+ /* Freeze OUT pipe after use */\r
+ Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);\r
+ Pipe_Freeze();\r
+\r
+ /* Select the IN data pipe for data reception */\r
+ Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);\r
+ \r
+ /* Load in the response from the attached device */\r
+ Pipe_Read_Stream_LE(&PIMA_ReceivedBlock, PIMA_COMMAND_SIZE(0));\r
+ \r
+ /* Check if the returned block type is a response block */\r
+ if (PIMA_ReceivedBlock.Type == CType_ResponseBlock)\r
+ {\r
+ /* Determine the size of the parameters in the block via the data length attribute */\r
+ uint8_t ParamBytes = (PIMA_ReceivedBlock.DataLength - PIMA_COMMAND_SIZE(0));\r
+\r
+ /* Check if the device has returned any parameters */\r
+ if (ParamBytes)\r
+ {\r
+ /* Read the PIMA parameters from the data IN pipe */\r
+ Pipe_Read_Stream_LE(&PIMA_ReceivedBlock.Params, ParamBytes);\r
+ }\r
+ \r
+ /* Clear pipe bank after use */\r
+ Pipe_ClearIN();\r
+ }\r
+ \r
+ /* Freeze the IN pipe after use */\r
+ Pipe_Freeze();\r
+ \r
+ return PIPE_RWSTREAM_NoError;\r
+}\r
+\r
+/** Function to send the given data to the device, after a command block has been issued.\r
+ *\r
+ * \param Buffer Source data buffer to send to the device\r
+ * \param Bytes Number of bytes to send\r
+ */\r
+void SImage_SendData(void* Buffer, uint16_t Bytes)\r
+{\r
+ /* Unfreeze the data OUT pipe */\r
+ Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);\r
+ Pipe_Unfreeze();\r
+ \r
+ /* Write the data contents to the pipe */\r
+ Pipe_Write_Stream_LE(Buffer, Bytes);\r
+\r
+ /* Send the last packet to the attached device */\r
+ Pipe_ClearOUT();\r
+\r
+ /* Freeze the pipe again after use */\r
+ Pipe_Freeze();\r
+}\r
+\r
+/** Function to receive the given data to the device, after a response block has been received.\r
+ *\r
+ * \param Buffer Destination data buffer to put read bytes from the device\r
+ * \param Bytes Number of bytes to receive\r
+ *\r
+ * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
+ */\r
+uint8_t SImage_ReadData(void* Buffer, uint16_t Bytes)\r
+{\r
+ uint8_t ErrorCode;\r
+\r
+ /* Unfreeze the data IN pipe */\r
+ Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);\r
+ Pipe_Unfreeze();\r
+\r
+ /* Read in the data into the buffer */\r
+ ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes);\r
+\r
+ /* Freeze the pipe again after use */\r
+ Pipe_Freeze();\r
+ \r
+ return ErrorCode;\r
+}\r
+\r
+/** Function to test if a PIMA event block is waiting to be read in from the attached device.\r
+ *\r
+ * \return True if an event is waiting to be read in from the device, false otherwise\r
+ */\r
+bool SImage_IsEventReceived(void)\r
+{\r
+ bool IsEventReceived = false;\r
+\r
+ /* Unfreeze the Event pipe */\r
+ Pipe_SelectPipe(SIMAGE_EVENTS_PIPE);\r
+ Pipe_Unfreeze();\r
+ \r
+ /* If the pipe contains data, an event has been received */\r
+ if (Pipe_BytesInPipe())\r
+ IsEventReceived = true;\r
+ \r
+ /* Freeze the pipe after use */\r
+ Pipe_Freeze();\r
+ \r
+ return IsEventReceived;\r
+}\r
+\r
+/** Clears the stall condition in the attached device on the nominated endpoint number.\r
+ *\r
+ * \param EndpointNum Endpoint number in the attached device whose stall condition is to be cleared\r
+ *\r
+ * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
+ */\r
+uint8_t SImage_ClearPipeStall(const uint8_t EndpointNum)\r
+{\r
+ USB_ControlRequest = (USB_Request_Header_t)\r
+ {\r
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT),\r
+ .bRequest = REQ_ClearFeature,\r
+ .wValue = FEATURE_ENDPOINT_HALT,\r
+ .wIndex = EndpointNum,\r
+ .wLength = 0,\r
+ };\r
+ \r
+ /* Select the control pipe for the request transfer */\r
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
+\r
+ return USB_Host_SendControlRequest(NULL);\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for StillImageCommands.c.\r
+ */\r
+ \r
+#ifndef _STILL_IMAGE_COMMANDS_H_\r
+#define _STILL_IMAGE_COMMANDS_H_\r
+\r
+ /* Includes: */\r
+ #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
+ \r
+ #include "PIMACodes.h"\r
+\r
+ /* Macros: */\r
+ /** Pipe number of the Still Image data IN pipe */\r
+ #define SIMAGE_DATA_IN_PIPE 0x01\r
+\r
+ /** Pipe number of the Still Image data OUT pipe */\r
+ #define SIMAGE_DATA_OUT_PIPE 0x02\r
+\r
+ /** Pipe number of the Still Image events pipe */\r
+ #define SIMAGE_EVENTS_PIPE 0x03\r
+\r
+ /** Timeout period between the issuing of a command to a device, and the reception of the first packet */\r
+ #define COMMAND_DATA_TIMEOUT_MS 5000\r
+ \r
+ /** Used in the DataLength field of a PIMA container, to give the total container size in bytes for\r
+ * a command container.\r
+ *\r
+ * \param params Number of parameters which are to be sent in the Param field of the container\r
+ */\r
+ #define PIMA_COMMAND_SIZE(params) ((sizeof(PIMA_SendBlock) - sizeof(PIMA_SendBlock.Params)) + \\r
+ (params * sizeof(PIMA_SendBlock.Params[0])))\r
+\r
+ /** Used in the DataLength field of a PIMA container, to give the total container size in bytes for\r
+ * a data container.\r
+ *\r
+ * \param datalen Length in bytes of the data in the container\r
+ */\r
+ #define PIMA_DATA_SIZE(datalen) ((sizeof(PIMA_SendBlock) - sizeof(PIMA_SendBlock.Params)) + datalen)\r
+\r
+ /* Type Defines: */\r
+ /** Type define for a PIMA container, use to send commands and receive responses to and from an\r
+ * attached Still Image device.\r
+ */\r
+ typedef struct\r
+ {\r
+ uint32_t DataLength; /**< Length of the container and data, in bytes */\r
+ uint16_t Type; /**< Container type, a value from the PIMA_Container_Types_t enum */\r
+ uint16_t Code; /**< Command, event or response code of the container */\r
+ uint32_t TransactionID; /**< Unique container ID to link blocks together */\r
+ uint32_t Params[4]; /**< Block parameters to be issued along with the block code (command blocks only) */\r
+ } PIMA_Container_t;\r
+ \r
+ /* Enums: */\r
+ /** Enum for the possible PIMA contains types. */\r
+ enum PIMA_Container_Types_t\r
+ {\r
+ CType_Undefined = 0, /**< Undefined container type */\r
+ CType_CommandBlock = 1, /**< Command Block container type */\r
+ CType_DataBlock = 2, /**< Data Block container type */\r
+ CType_ResponseBlock = 3, /**< Response container type */\r
+ CType_EventBlock = 4, /**< Event Block container type */\r
+ };\r
+ \r
+ /* External Variables: */\r
+ extern PIMA_Container_t PIMA_SendBlock;\r
+ extern PIMA_Container_t PIMA_ReceivedBlock;\r
+ extern PIMA_Container_t PIMA_EventBlock;\r
+ \r
+ /* Function Prototypes: */\r
+ void SImage_SendBlockHeader(void);\r
+ uint8_t SImage_RecieveBlockHeader(void);\r
+ void SImage_RecieveEventHeader(void);\r
+ void SImage_SendData(void* Buffer, uint16_t Bytes);\r
+ uint8_t SImage_ReadData(void* Buffer, uint16_t Bytes);\r
+ bool SImage_IsEventReceived(void);\r
+ uint8_t SImage_ClearPipeStall(const uint8_t EndpointNum);\r
+\r
+#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header containing macros for possible PIMA commands. Refer to the PIMA standard\r
- * documentation for more information on each PIMA command.\r
- */\r
-\r
-#ifndef _PIMA_CODES_H_\r
-\r
- /* Macros: */\r
- #define PIMA_OPERATION_GETDEVICEINFO 0x1001\r
- #define PIMA_OPERATION_OPENSESSION 0x1002\r
- #define PIMA_OPERATION_CLOSESESSION 0x1003\r
- \r
- #define PIMA_RESPONSE_OK 0x2001\r
- #define PIMA_RESPONSE_GENERALERROR 0x2002\r
- #define PIMA_RESPONSE_SESSIONNOTOPEN 0x2003\r
- #define PIMA_RESPONSE_INVALIDTRANSACTIONID 0x2004\r
- #define PIMA_RESPONSE_OPERATIONNOTSUPPORTED 0x2005\r
- #define PIMA_RESPONSE_PARAMETERNOTSUPPORTED 0x2006\r
-\r
-#endif\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Still Image Device commands, to issue PIMA commands to the device for\r
- * reading device status, capacity, and other characteristics as well as\r
- * reading and writing of stored image data.\r
- */\r
-\r
-#include "StillImageCommands.h"\r
-\r
-/* Globals: */\r
-/** PIMA block container for the block to send to the device */\r
-PIMA_Container_t PIMA_SendBlock;\r
-\r
-/** PIMA block container for the last received block from the device */\r
-PIMA_Container_t PIMA_ReceivedBlock;\r
-\r
-/** PIMA block container for the last event block received from the device */\r
-PIMA_Container_t PIMA_EventBlock;\r
-\r
-\r
-/** Function to send the PIMA command container to the attached still image device. */\r
-void SImage_SendBlockHeader(void)\r
-{\r
- /* Unfreeze the data OUT pipe ready for data transmission */\r
- Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);\r
- Pipe_Unfreeze();\r
-\r
- /* Write the PIMA block to the data OUT pipe */\r
- Pipe_Write_Stream_LE(&PIMA_SendBlock, PIMA_COMMAND_SIZE(0));\r
- \r
- /* If the block type is a command, send its parameters (if any) */\r
- if (PIMA_SendBlock.Type == CType_CommandBlock)\r
- {\r
- /* Determine the size of the parameters in the block via the data length attribute */\r
- uint8_t ParamBytes = (PIMA_SendBlock.DataLength - PIMA_COMMAND_SIZE(0));\r
-\r
- /* Check if any parameters in the command block */\r
- if (ParamBytes)\r
- {\r
- /* Write the PIMA parameters to the data OUT pipe */\r
- Pipe_Write_Stream_LE(&PIMA_SendBlock.Params, ParamBytes);\r
- }\r
- \r
- /* Send the PIMA command block to the attached device */\r
- Pipe_ClearOUT();\r
- }\r
- \r
- /* Freeze pipe after use */\r
- Pipe_Freeze();\r
-}\r
-\r
-/** Function to receive a PIMA event container from the attached still image device. */\r
-void SImage_RecieveEventHeader(void)\r
-{\r
- /* Unfreeze the events pipe */\r
- Pipe_SelectPipe(SIMAGE_EVENTS_PIPE);\r
- Pipe_Unfreeze();\r
- \r
- /* Read in the event data into the global structure */\r
- Pipe_Read_Stream_LE(&PIMA_EventBlock, sizeof(PIMA_EventBlock));\r
- \r
- /* Clear the pipe after read complete to prepare for next event */\r
- Pipe_ClearIN();\r
- \r
- /* Freeze the event pipe again after use */\r
- Pipe_Freeze();\r
-}\r
-\r
-/** Function to receive a PIMA response container from the attached still image device. */\r
-uint8_t SImage_RecieveBlockHeader(void)\r
-{\r
- uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;\r
-\r
- /* Unfreeze the data IN pipe */\r
- Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);\r
- Pipe_Unfreeze();\r
- \r
- /* Wait until data received on the IN pipe */\r
- while (!(Pipe_IsReadWriteAllowed()))\r
- {\r
- /* Check to see if a new frame has been issued (1ms elapsed) */\r
- if (USB_INT_HasOccurred(USB_INT_HSOFI))\r
- {\r
- /* Clear the flag and decrement the timeout period counter */\r
- USB_INT_Clear(USB_INT_HSOFI);\r
- TimeoutMSRem--;\r
-\r
- /* Check to see if the timeout period for the command has elapsed */\r
- if (!(TimeoutMSRem))\r
- {\r
- /* Return error code */\r
- return PIPE_RWSTREAM_Timeout;\r
- }\r
- }\r
- \r
- Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);\r
-\r
- /* Check if pipe stalled (command failed by device) */\r
- if (Pipe_IsStalled())\r
- {\r
- /* Clear the stall condition on the OUT pipe */\r
- SImage_ClearPipeStall(SIMAGE_DATA_OUT_PIPE);\r
-\r
- /* Return error code and break out of the loop */\r
- return PIPE_RWSTREAM_PipeStalled;\r
- }\r
-\r
- Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);\r
-\r
- /* Check if pipe stalled (command failed by device) */\r
- if (Pipe_IsStalled())\r
- {\r
- /* Clear the stall condition on the IN pipe */\r
- SImage_ClearPipeStall(SIMAGE_DATA_IN_PIPE);\r
-\r
- /* Return error code */\r
- return PIPE_RWSTREAM_PipeStalled;\r
- }\r
- \r
- /* Check to see if the device was disconnected, if so exit function */\r
- if (!(USB_IsConnected))\r
- {\r
- /* Return error code */\r
- return PIPE_RWSTREAM_DeviceDisconnected;\r
- }\r
- };\r
- \r
- /* Freeze OUT pipe after use */\r
- Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);\r
- Pipe_Freeze();\r
-\r
- /* Select the IN data pipe for data reception */\r
- Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);\r
- \r
- /* Load in the response from the attached device */\r
- Pipe_Read_Stream_LE(&PIMA_ReceivedBlock, PIMA_COMMAND_SIZE(0));\r
- \r
- /* Check if the returned block type is a response block */\r
- if (PIMA_ReceivedBlock.Type == CType_ResponseBlock)\r
- {\r
- /* Determine the size of the parameters in the block via the data length attribute */\r
- uint8_t ParamBytes = (PIMA_ReceivedBlock.DataLength - PIMA_COMMAND_SIZE(0));\r
-\r
- /* Check if the device has returned any parameters */\r
- if (ParamBytes)\r
- {\r
- /* Read the PIMA parameters from the data IN pipe */\r
- Pipe_Read_Stream_LE(&PIMA_ReceivedBlock.Params, ParamBytes);\r
- }\r
- \r
- /* Clear pipe bank after use */\r
- Pipe_ClearIN();\r
- }\r
- \r
- /* Freeze the IN pipe after use */\r
- Pipe_Freeze();\r
- \r
- return PIPE_RWSTREAM_NoError;\r
-}\r
-\r
-/** Function to send the given data to the device, after a command block has been issued.\r
- *\r
- * \param Buffer Source data buffer to send to the device\r
- * \param Bytes Number of bytes to send\r
- */\r
-void SImage_SendData(void* Buffer, uint16_t Bytes)\r
-{\r
- /* Unfreeze the data OUT pipe */\r
- Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);\r
- Pipe_Unfreeze();\r
- \r
- /* Write the data contents to the pipe */\r
- Pipe_Write_Stream_LE(Buffer, Bytes);\r
-\r
- /* Send the last packet to the attached device */\r
- Pipe_ClearOUT();\r
-\r
- /* Freeze the pipe again after use */\r
- Pipe_Freeze();\r
-}\r
-\r
-/** Function to receive the given data to the device, after a response block has been received.\r
- *\r
- * \param Buffer Destination data buffer to put read bytes from the device\r
- * \param Bytes Number of bytes to receive\r
- *\r
- * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum\r
- */\r
-uint8_t SImage_ReadData(void* Buffer, uint16_t Bytes)\r
-{\r
- uint8_t ErrorCode;\r
-\r
- /* Unfreeze the data IN pipe */\r
- Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);\r
- Pipe_Unfreeze();\r
-\r
- /* Read in the data into the buffer */\r
- ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes);\r
-\r
- /* Freeze the pipe again after use */\r
- Pipe_Freeze();\r
- \r
- return ErrorCode;\r
-}\r
-\r
-/** Function to test if a PIMA event block is waiting to be read in from the attached device.\r
- *\r
- * \return True if an event is waiting to be read in from the device, false otherwise\r
- */\r
-bool SImage_IsEventReceived(void)\r
-{\r
- bool IsEventReceived = false;\r
-\r
- /* Unfreeze the Event pipe */\r
- Pipe_SelectPipe(SIMAGE_EVENTS_PIPE);\r
- Pipe_Unfreeze();\r
- \r
- /* If the pipe contains data, an event has been received */\r
- if (Pipe_BytesInPipe())\r
- IsEventReceived = true;\r
- \r
- /* Freeze the pipe after use */\r
- Pipe_Freeze();\r
- \r
- return IsEventReceived;\r
-}\r
-\r
-/** Clears the stall condition in the attached device on the nominated endpoint number.\r
- *\r
- * \param EndpointNum Endpoint number in the attached device whose stall condition is to be cleared\r
- *\r
- * \return A value from the USB_Host_SendControlErrorCodes_t enum\r
- */\r
-uint8_t SImage_ClearPipeStall(const uint8_t EndpointNum)\r
-{\r
- USB_ControlRequest = (USB_Request_Header_t)\r
- {\r
- .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT),\r
- .bRequest = REQ_ClearFeature,\r
- .wValue = FEATURE_ENDPOINT_HALT,\r
- .wIndex = EndpointNum,\r
- .wLength = 0,\r
- };\r
- \r
- /* Select the control pipe for the request transfer */\r
- Pipe_SelectPipe(PIPE_CONTROLPIPE);\r
-\r
- return USB_Host_SendControlRequest(NULL);\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for StillImageCommands.c.\r
- */\r
- \r
-#ifndef _STILL_IMAGE_COMMANDS_H_\r
-#define _STILL_IMAGE_COMMANDS_H_\r
-\r
- /* Includes: */\r
- #include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
- \r
- #include "PIMACodes.h"\r
-\r
- /* Macros: */\r
- /** Pipe number of the Still Image data IN pipe */\r
- #define SIMAGE_DATA_IN_PIPE 0x01\r
-\r
- /** Pipe number of the Still Image data OUT pipe */\r
- #define SIMAGE_DATA_OUT_PIPE 0x02\r
-\r
- /** Pipe number of the Still Image events pipe */\r
- #define SIMAGE_EVENTS_PIPE 0x03\r
-\r
- /** Timeout period between the issuing of a command to a device, and the reception of the first packet */\r
- #define COMMAND_DATA_TIMEOUT_MS 5000\r
- \r
- /** Used in the DataLength field of a PIMA container, to give the total container size in bytes for\r
- * a command container.\r
- *\r
- * \param params Number of parameters which are to be sent in the Param field of the container\r
- */\r
- #define PIMA_COMMAND_SIZE(params) ((sizeof(PIMA_SendBlock) - sizeof(PIMA_SendBlock.Params)) + \\r
- (params * sizeof(PIMA_SendBlock.Params[0])))\r
-\r
- /** Used in the DataLength field of a PIMA container, to give the total container size in bytes for\r
- * a data container.\r
- *\r
- * \param datalen Length in bytes of the data in the container\r
- */\r
- #define PIMA_DATA_SIZE(datalen) ((sizeof(PIMA_SendBlock) - sizeof(PIMA_SendBlock.Params)) + datalen)\r
-\r
- /* Type Defines: */\r
- /** Type define for a PIMA container, use to send commands and receive responses to and from an\r
- * attached Still Image device.\r
- */\r
- typedef struct\r
- {\r
- uint32_t DataLength; /**< Length of the container and data, in bytes */\r
- uint16_t Type; /**< Container type, a value from the PIMA_Container_Types_t enum */\r
- uint16_t Code; /**< Command, event or response code of the container */\r
- uint32_t TransactionID; /**< Unique container ID to link blocks together */\r
- uint32_t Params[4]; /**< Block parameters to be issued along with the block code (command blocks only) */\r
- } PIMA_Container_t;\r
- \r
- /* Enums: */\r
- /** Enum for the possible PIMA contains types. */\r
- enum PIMA_Container_Types_t\r
- {\r
- CType_Undefined = 0, /**< Undefined container type */\r
- CType_CommandBlock = 1, /**< Command Block container type */\r
- CType_DataBlock = 2, /**< Data Block container type */\r
- CType_ResponseBlock = 3, /**< Response container type */\r
- CType_EventBlock = 4, /**< Event Block container type */\r
- };\r
- \r
- /* External Variables: */\r
- extern PIMA_Container_t PIMA_SendBlock;\r
- extern PIMA_Container_t PIMA_ReceivedBlock;\r
- extern PIMA_Container_t PIMA_EventBlock;\r
- \r
- /* Function Prototypes: */\r
- void SImage_SendBlockHeader(void);\r
- uint8_t SImage_RecieveBlockHeader(void);\r
- void SImage_RecieveEventHeader(void);\r
- void SImage_SendData(void* Buffer, uint16_t Bytes);\r
- uint8_t SImage_ReadData(void* Buffer, uint16_t Bytes);\r
- bool SImage_IsEventReceived(void);\r
- uint8_t SImage_ClearPipeStall(const uint8_t EndpointNum);\r
-\r
-#endif\r
#include <stdio.h>\r
\r
#include "ConfigDescriptor.h"\r
- #include "PIMACodes.h"\r
- #include "StillImageCommands.h"\r
+\r
+ #include "Lib/PIMACodes.h"\r
+ #include "Lib/StillImageCommands.h"\r
\r
#include <LUFA/Drivers/Misc/TerminalCodes.h> // ANSI Terminal Escape Codes\r
#include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
# List C source files here. (C dependencies are automatically generated.)\r
SRC = $(TARGET).c \\r
ConfigDescriptor.c \\r
- StillImageCommands.c \\r
+ Lib/StillImageCommands.c \\r
$(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \\r
$(LUFA_PATH)/LUFA/Drivers/Peripheral/SerialStream.c \\r
$(LUFA_PATH)/LUFA/Drivers/Peripheral/Serial.c \\r
-<Project name="LUFA"><Folder name="Demos"><Folder name="Device"><Folder name="AudioInput"><File path="Demos\Device\AudioInput\AudioInput.c"></File><File path="Demos\Device\AudioInput\AudioInput.h"></File><File path="Demos\Device\AudioInput\AudioInput.txt"></File><File path="Demos\Device\AudioInput\Descriptors.c"></File><File path="Demos\Device\AudioInput\Descriptors.h"></File><File path="Demos\Device\AudioInput\Doxygen.conf"></File><File path="Demos\Device\AudioInput\makefile"></File></Folder><Folder name="AudioOutput"><File path="Demos\Device\AudioOutput\AudioOutput.c"></File><File path="Demos\Device\AudioOutput\AudioOutput.h"></File><File path="Demos\Device\AudioOutput\AudioOutput.txt"></File><File path="Demos\Device\AudioOutput\Descriptors.c"></File><File path="Demos\Device\AudioOutput\Descriptors.h"></File><File path="Demos\Device\AudioOutput\Doxygen.conf"></File><File path="Demos\Device\AudioOutput\makefile"></File></Folder><Folder name="CDC"><File path="Demos\Device\CDC\CDC.c"></File><File path="Demos\Device\CDC\CDC.h"></File><File path="Demos\Device\CDC\CDC.txt"></File><File path="Demos\Device\CDC\Descriptors.c"></File><File path="Demos\Device\CDC\Descriptors.h"></File><File path="Demos\Device\CDC\Doxygen.conf"></File><File path="Demos\Device\CDC\LUFA CDC.inf"></File><File path="Demos\Device\CDC\makefile"></File></Folder><Folder name="DualCDC"><File path="Demos\Device\DualCDC\Descriptors.c"></File><File path="Demos\Device\DualCDC\Descriptors.h"></File><File path="Demos\Device\DualCDC\Doxygen.conf"></File><File path="Demos\Device\DualCDC\DualCDC.c"></File><File path="Demos\Device\DualCDC\DualCDC.h"></File><File path="Demos\Device\DualCDC\DualCDC.txt"></File><File path="Demos\Device\DualCDC\LUFA DualCDC.inf"></File><File path="Demos\Device\DualCDC\makefile"></File></Folder><Folder name="GenericHID"><File path="Demos\Device\GenericHID\Descriptors.c"></File><File path="Demos\Device\GenericHID\Descriptors.h"></File><File path="Demos\Device\GenericHID\GenericHID.c"></File><File path="Demos\Device\GenericHID\GenericHID.h"></File><File path="Demos\Device\GenericHID\makefile"></File><File path="Demos\Device\GenericHID\GenericHID.txt"></File><File path="Demos\Device\GenericHID\Doxygen.conf"></File></Folder><Folder name="Joystick"><File path="Demos\Device\Joystick\Descriptors.c"></File><File path="Demos\Device\Joystick\Descriptors.h"></File><File path="Demos\Device\Joystick\Doxygen.conf"></File><File path="Demos\Device\Joystick\Joystick.c"></File><File path="Demos\Device\Joystick\Joystick.h"></File><File path="Demos\Device\Joystick\Joystick.txt"></File><File path="Demos\Device\Joystick\makefile"></File></Folder><Folder name="Keyboard"><File path="Demos\Device\Keyboard\Descriptors.c"></File><File path="Demos\Device\Keyboard\Descriptors.h"></File><File path="Demos\Device\Keyboard\Doxygen.conf"></File><File path="Demos\Device\Keyboard\Keyboard.c"></File><File path="Demos\Device\Keyboard\Keyboard.h"></File><File path="Demos\Device\Keyboard\Keyboard.txt"></File><File path="Demos\Device\Keyboard\makefile"></File></Folder><Folder name="KeyboardMouse"><File path="Demos\Device\KeyboardMouse\Descriptors.c"></File><File path="Demos\Device\KeyboardMouse\Descriptors.h"></File><File path="Demos\Device\KeyboardMouse\Doxygen.conf"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.c"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.h"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.txt"></File><File path="Demos\Device\KeyboardMouse\makefile"></File></Folder><Folder name="MassStorage"><File path="Demos\Device\MassStorage\DataflashManager.c"></File><File path="Demos\Device\MassStorage\DataflashManager.h"></File><File path="Demos\Device\MassStorage\Descriptors.c"></File><File path="Demos\Device\MassStorage\Descriptors.h"></File><File path="Demos\Device\MassStorage\Doxygen.conf"></File><File path="Demos\Device\MassStorage\makefile"></File><File path="Demos\Device\MassStorage\MassStorage.c"></File><File path="Demos\Device\MassStorage\MassStorage.h"></File><File path="Demos\Device\MassStorage\MassStorage.txt"></File><File path="Demos\Device\MassStorage\SCSI.c"></File><File path="Demos\Device\MassStorage\SCSI.h"></File><File path="Demos\Device\MassStorage\SCSI_Codes.h"></File></Folder><Folder name="MIDI"><File path="Demos\Device\MIDI\Descriptors.c"></File><File path="Demos\Device\MIDI\Descriptors.h"></File><File path="Demos\Device\MIDI\Doxygen.conf"></File><File path="Demos\Device\MIDI\makefile"></File><File path="Demos\Device\MIDI\MIDI.c"></File><File path="Demos\Device\MIDI\MIDI.h"></File><File path="Demos\Device\MIDI\MIDI.txt"></File></Folder><Folder name="Mouse"><File path="Demos\Device\Mouse\Descriptors.c"></File><File path="Demos\Device\Mouse\Descriptors.h"></File><File path="Demos\Device\Mouse\Doxygen.conf"></File><File path="Demos\Device\Mouse\makefile"></File><File path="Demos\Device\Mouse\Mouse.c"></File><File path="Demos\Device\Mouse\Mouse.h"></File><File path="Demos\Device\Mouse\Mouse.txt"></File></Folder><Folder name="RNDISEthernet"><File path="Demos\Device\RNDISEthernet\ARP.c"></File><File path="Demos\Device\RNDISEthernet\ARP.h"></File><File path="Demos\Device\RNDISEthernet\Descriptors.c"></File><File path="Demos\Device\RNDISEthernet\Descriptors.h"></File><File path="Demos\Device\RNDISEthernet\DHCP.c"></File><File path="Demos\Device\RNDISEthernet\DHCP.h"></File><File path="Demos\Device\RNDISEthernet\Doxygen.conf"></File><File path="Demos\Device\RNDISEthernet\Ethernet.c"></File><File path="Demos\Device\RNDISEthernet\Ethernet.h"></File><File path="Demos\Device\RNDISEthernet\EthernetProtocols.h"></File><File path="Demos\Device\RNDISEthernet\ICMP.c"></File><File path="Demos\Device\RNDISEthernet\ICMP.h"></File><File path="Demos\Device\RNDISEthernet\IP.c"></File><File path="Demos\Device\RNDISEthernet\IP.h"></File><File path="Demos\Device\RNDISEthernet\LUFA RNDIS.inf"></File><File path="Demos\Device\RNDISEthernet\makefile"></File><File path="Demos\Device\RNDISEthernet\ProtocolDecoders.c"></File><File path="Demos\Device\RNDISEthernet\ProtocolDecoders.h"></File><File path="Demos\Device\RNDISEthernet\RNDIS.c"></File><File path="Demos\Device\RNDISEthernet\RNDIS.h"></File><File path="Demos\Device\RNDISEthernet\RNDISConstants.h"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.c"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.h"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.txt"></File><File path="Demos\Device\RNDISEthernet\TCP.c"></File><File path="Demos\Device\RNDISEthernet\TCP.h"></File><File path="Demos\Device\RNDISEthernet\UDP.c"></File><File path="Demos\Device\RNDISEthernet\UDP.h"></File><File path="Demos\Device\RNDISEthernet\Webserver.c"></File><File path="Demos\Device\RNDISEthernet\Webserver.h"></File></Folder><Folder name="USBtoSerial"><File path="Demos\Device\USBtoSerial\Descriptors.c"></File><File path="Demos\Device\USBtoSerial\Descriptors.h"></File><File path="Demos\Device\USBtoSerial\Doxygen.conf"></File><File path="Demos\Device\USBtoSerial\LUFA USBtoSerial.inf"></File><File path="Demos\Device\USBtoSerial\makefile"></File><File path="Demos\Device\USBtoSerial\RingBuff.c"></File><File path="Demos\Device\USBtoSerial\RingBuff.h"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.c"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.h"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.txt"></File></Folder><File path="Demos\Device\makefile"></File></Folder><Folder name="Host"><Folder name="CDCHost"><File path="Demos\Host\CDCHost\CDCHost.c"></File><File path="Demos\Host\CDCHost\CDCHost.h"></File><File path="Demos\Host\CDCHost\CDCHost.txt"></File><File path="Demos\Host\CDCHost\ConfigDescriptor.c"></File><File path="Demos\Host\CDCHost\ConfigDescriptor.h"></File><File path="Demos\Host\CDCHost\Doxygen.conf"></File><File path="Demos\Host\CDCHost\makefile"></File></Folder><Folder name="GenericHIDHost"><File path="Demos\Host\GenericHIDHost\ConfigDescriptor.c"></File><File path="Demos\Host\GenericHIDHost\ConfigDescriptor.h"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.c"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.h"></File><File path="Demos\Host\GenericHIDHost\makefile"></File><File path="Demos\Host\GenericHIDHost\Doxygen.conf"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.txt"></File></Folder><Folder name="KeyboardHost"><File path="Demos\Host\KeyboardHost\ConfigDescriptor.c"></File><File path="Demos\Host\KeyboardHost\ConfigDescriptor.h"></File><File path="Demos\Host\KeyboardHost\Doxygen.conf"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.c"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.h"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.txt"></File><File path="Demos\Host\KeyboardHost\makefile"></File></Folder><Folder name="KeyboardHostWithParser"><File path="Demos\Host\KeyboardHostWithParser\ConfigDescriptor.c"></File><File path="Demos\Host\KeyboardHostWithParser\ConfigDescriptor.h"></File><File path="Demos\Host\KeyboardHostWithParser\Doxygen.conf"></File><File path="Demos\Host\KeyboardHostWithParser\HIDReport.c"></File><File path="Demos\Host\KeyboardHostWithParser\HIDReport.h"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.c"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.h"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.txt"></File><File path="Demos\Host\KeyboardHostWithParser\makefile"></File></Folder><Folder name="MassStorageHost"><File path="Demos\Host\MassStorageHost\ConfigDescriptor.c"></File><File path="Demos\Host\MassStorageHost\ConfigDescriptor.h"></File><File path="Demos\Host\MassStorageHost\Doxygen.conf"></File><File path="Demos\Host\MassStorageHost\makefile"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.c"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.h"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.txt"></File><File path="Demos\Host\MassStorageHost\MassStoreCommands.c"></File><File path="Demos\Host\MassStorageHost\MassStoreCommands.h"></File><File path="Demos\Host\MassStorageHost\SCSI_Codes.h"></File></Folder><Folder name="MouseHost"><File path="Demos\Host\MouseHost\ConfigDescriptor.c"></File><File path="Demos\Host\MouseHost\ConfigDescriptor.h"></File><File path="Demos\Host\MouseHost\Doxygen.conf"></File><File path="Demos\Host\MouseHost\makefile"></File><File path="Demos\Host\MouseHost\MouseHost.c"></File><File path="Demos\Host\MouseHost\MouseHost.h"></File><File path="Demos\Host\MouseHost\MouseHost.txt"></File></Folder><Folder name="MouseHostWithParser"><File path="Demos\Host\MouseHostWithParser\ConfigDescriptor.c"></File><File path="Demos\Host\MouseHostWithParser\ConfigDescriptor.h"></File><File path="Demos\Host\MouseHostWithParser\Doxygen.conf"></File><File path="Demos\Host\MouseHostWithParser\HIDReport.c"></File><File path="Demos\Host\MouseHostWithParser\HIDReport.h"></File><File path="Demos\Host\MouseHostWithParser\makefile"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.c"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.h"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.txt"></File></Folder><Folder name="StillImageHost"><File path="Demos\Host\StillImageHost\ConfigDescriptor.c"></File><File path="Demos\Host\StillImageHost\ConfigDescriptor.h"></File><File path="Demos\Host\StillImageHost\Doxygen.conf"></File><File path="Demos\Host\StillImageHost\makefile"></File><File path="Demos\Host\StillImageHost\PIMACodes.h"></File><File path="Demos\Host\StillImageHost\StillImageCommands.c"></File><File path="Demos\Host\StillImageHost\StillImageCommands.h"></File><File path="Demos\Host\StillImageHost\StillImageHost.c"></File><File path="Demos\Host\StillImageHost\StillImageHost.h"></File><File path="Demos\Host\StillImageHost\StillImageHost.txt"></File></Folder><File path="Demos\Host\makefile"></File></Folder><Folder name="OTG"><Folder name="TestApp"><File path="Demos\OTG\TestApp\Descriptors.c"></File><File path="Demos\OTG\TestApp\Descriptors.h"></File><File path="Demos\OTG\TestApp\Doxygen.conf"></File><File path="Demos\OTG\TestApp\makefile"></File><File path="Demos\OTG\TestApp\TestApp.c"></File><File path="Demos\OTG\TestApp\TestApp.h"></File><File path="Demos\OTG\TestApp\TestApp.txt"></File><File path="Demos\OTG\TestApp\TestEvents.c"></File><File path="Demos\OTG\TestApp\TestEvents.h"></File></Folder><File path="Demos\OTG\makefile"></File></Folder><File path="Demos\makefile"></File></Folder><Folder name="LUFA"><Folder name="Common"><File path="LUFA\Common\Common.h"></File><File path="LUFA\Common\FunctionAttributes.h"></File><File path="LUFA\Common\BoardTypes.h"></File></Folder><Folder name="Drivers"><Folder name="USB"><Folder name="LowLevel"><File path="LUFA\Drivers\USB\LowLevel\HostChapter9.h"></File><File path="LUFA\Drivers\USB\LowLevel\LowLevel.c"></File><File path="LUFA\Drivers\USB\LowLevel\LowLevel.h"></File><File path="LUFA\Drivers\USB\LowLevel\Pipe.c"></File><File path="LUFA\Drivers\USB\LowLevel\Pipe.h"></File><File path="LUFA\Drivers\USB\LowLevel\DevChapter9.c"></File><File path="LUFA\Drivers\USB\LowLevel\DevChapter9.h"></File><File path="LUFA\Drivers\USB\LowLevel\Device.h"></File><File path="LUFA\Drivers\USB\LowLevel\Endpoint.c"></File><File path="LUFA\Drivers\USB\LowLevel\Endpoint.h"></File><File path="LUFA\Drivers\USB\LowLevel\Host.c"></File><File path="LUFA\Drivers\USB\LowLevel\Host.h"></File><File path="LUFA\Drivers\USB\LowLevel\HostChapter9.c"></File><File path="LUFA\Drivers\USB\LowLevel\OTG.h"></File></Folder><Folder name="HighLevel"><File path="LUFA\Drivers\USB\HighLevel\USBTask.h"></File><File path="LUFA\Drivers\USB\HighLevel\Events.c"></File><File path="LUFA\Drivers\USB\HighLevel\Events.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBInterrupt.c"></File><File path="LUFA\Drivers\USB\HighLevel\USBInterrupt.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBTask.c"></File><File path="LUFA\Drivers\USB\HighLevel\StdDescriptors.h"></File><File path="LUFA\Drivers\USB\HighLevel\StdRequestType.h"></File><File path="LUFA\Drivers\USB\HighLevel\StreamCallbacks.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBMode.h"></File><File path="LUFA\Drivers\USB\HighLevel\ConfigDescriptor.c"></File><File path="LUFA\Drivers\USB\HighLevel\ConfigDescriptor.h"></File></Folder><Folder name="Class"><File path="LUFA\Drivers\USB\Class\HIDParser.c"></File><File path="LUFA\Drivers\USB\Class\HIDParser.h"></File><File path="LUFA\Drivers\USB\Class\HIDReportData.h"></File></Folder><File path="LUFA\Drivers\USB\USB.h"></File></Folder><Folder name="Misc"><File path="LUFA\Drivers\Misc\TerminalCodes.h"></File></Folder><Folder name="Board"><Folder name="USBKEY"><File path="LUFA\Drivers\Board\USBKEY\Dataflash.h"></File><File path="LUFA\Drivers\Board\USBKEY\Joystick.h"></File><File path="LUFA\Drivers\Board\USBKEY\AT45DB642D.h"></File><File path="LUFA\Drivers\Board\USBKEY\LEDs.h"></File><File path="LUFA\Drivers\Board\USBKEY\Buttons.h"></File></Folder><Folder name="STK526"><File path="LUFA\Drivers\Board\STK526\Dataflash.h"></File><File path="LUFA\Drivers\Board\STK526\Joystick.h"></File><File path="LUFA\Drivers\Board\STK526\AT45DB642D.h"></File><File path="LUFA\Drivers\Board\STK526\LEDs.h"></File><File path="LUFA\Drivers\Board\STK526\Buttons.h"></File></Folder><Folder name="STK525"><File path="LUFA\Drivers\Board\STK525\Dataflash.h"></File><File path="LUFA\Drivers\Board\STK525\Joystick.h"></File><File path="LUFA\Drivers\Board\STK525\AT45DB321C.h"></File><File path="LUFA\Drivers\Board\STK525\LEDs.h"></File><File path="LUFA\Drivers\Board\STK525\Buttons.h"></File></Folder><Folder name="RZUSBSTICK"><File path="LUFA\Drivers\Board\RZUSBSTICK\LEDs.h"></File></Folder><Folder name="ATAVRUSBRF01"><File path="LUFA\Drivers\Board\ATAVRUSBRF01\LEDs.h"></File><File path="LUFA\Drivers\Board\ATAVRUSBRF01\Buttons.h"></File></Folder><File path="LUFA\Drivers\Board\Temperature.h"></File><File path="LUFA\Drivers\Board\Dataflash.h"></File><File path="LUFA\Drivers\Board\Joystick.h"></File><File path="LUFA\Drivers\Board\Temperature.c"></File><File path="LUFA\Drivers\Board\LEDs.h"></File><File path="LUFA\Drivers\Board\Buttons.h"></File></Folder><Folder name="Peripheral"><Folder name="AT90USBXXX67"><File path="LUFA\Drivers\Peripheral\AT90USBXXX67\ADC.h"></File></Folder><File path="LUFA\Drivers\Peripheral\ADC.h"></File><File path="LUFA\Drivers\Peripheral\Serial.c"></File><File path="LUFA\Drivers\Peripheral\Serial.h"></File><File path="LUFA\Drivers\Peripheral\SPI.h"></File><File path="LUFA\Drivers\Peripheral\SerialStream.c"></File><File path="LUFA\Drivers\Peripheral\SerialStream.h"></File></Folder></Folder><Folder name="Scheduler"><File path="LUFA\Scheduler\Scheduler.h"></File><File path="LUFA\Scheduler\Scheduler.c"></File></Folder><Folder name="MemoryAllocator"><File path="LUFA\MemoryAllocator\DynAlloc.h"></File><File path="LUFA\MemoryAllocator\DynAlloc.c"></File></Folder><Folder name="DriverStubs"><File path="LUFA\DriverStubs\Dataflash.h"></File><File path="LUFA\DriverStubs\Joystick.h"></File><File path="LUFA\DriverStubs\LEDs.h"></File><File path="LUFA\DriverStubs\Buttons.h"></File></Folder><File path="LUFA\makefile"></File><File path="LUFA\Version.h"></File><File path="LUFA\BuildingLinkableLibraries.txt"></File><File path="LUFA\GettingStarted.txt"></File><File path="LUFA\MainPage.txt"></File><File path="LUFA\SchedulerOverview.txt"></File><File path="LUFA\VIDAndPIDValues.txt"></File><File path="LUFA\ChangeLog.txt"></File><File path="LUFA\CompileTimeTokens.txt"></File><File path="LUFA\MigrationInformation.txt"></File><File path="LUFA\DirectorySummaries.txt"></File><File path="LUFA\Doxygen.conf"></File><File path="LUFA\WritingBoardDrivers.txt"></File><File path="LUFA\LUFAPoweredProjects.txt"></File><File path="LUFA\Groups.txt"></File></Folder><Folder name="Projects"><Folder name="MagStripe"><File path="Projects\Magstripe\Descriptors.c"></File><File path="Projects\Magstripe\Descriptors.h"></File><File path="Projects\Magstripe\Magstripe.c"></File><File path="Projects\Magstripe\Magstripe.h"></File><File path="Projects\Magstripe\MagstripeHW.h"></File><File path="Projects\Magstripe\makefile"></File><File path="Projects\Magstripe\Magstripe.txt"></File><File path="Projects\Magstripe\Doxygen.conf"></File><File path="Projects\Magstripe\CircularBitBuffer.c"></File><File path="Projects\Magstripe\CircularBitBuffer.h"></File></Folder><File path="Projects\makefile"></File></Folder><Folder name="Bootloaders"><Folder name="DFU"><File path="Bootloaders\DFU\BootloaderDFU.c"></File><File path="Bootloaders\DFU\BootloaderDFU.h"></File><File path="Bootloaders\DFU\Descriptors.c"></File><File path="Bootloaders\DFU\Descriptors.h"></File><File path="Bootloaders\DFU\makefile"></File><File path="Bootloaders\DFU\BootloaderDFU.txt"></File><File path="Bootloaders\DFU\Doxygen.conf"></File></Folder><Folder name="CDC"><File path="Bootloaders\CDC\BootloaderCDC.c"></File><File path="Bootloaders\CDC\BootloaderCDC.h"></File><File path="Bootloaders\CDC\Descriptors.c"></File><File path="Bootloaders\CDC\Descriptors.h"></File><File path="Bootloaders\CDC\makefile"></File><File path="Bootloaders\CDC\LUFA CDC Bootloader.inf"></File><File path="Bootloaders\CDC\Doxygen.conf"></File><File path="Bootloaders\CDC\BootloaderCDC.txt"></File></Folder><Folder name="TeensyHID"><File path="Bootloaders\TeensyHID\Descriptors.c"></File><File path="Bootloaders\TeensyHID\Descriptors.h"></File><File path="Bootloaders\TeensyHID\makefile"></File><File path="Bootloaders\TeensyHID\TeensyHID.c"></File><File path="Bootloaders\TeensyHID\TeensyHID.h"></File><File path="Bootloaders\TeensyHID\TeensyHID.txt"></File></Folder><File path="Bootloaders\makefile"></File></Folder><File path="makefile"></File></Project>
\ No newline at end of file
+<Project name="LUFA"><Folder name="Demos"><Folder name="Device"><Folder name="AudioInput"><File path="Demos\Device\AudioInput\AudioInput.c"></File><File path="Demos\Device\AudioInput\AudioInput.h"></File><File path="Demos\Device\AudioInput\AudioInput.txt"></File><File path="Demos\Device\AudioInput\Descriptors.c"></File><File path="Demos\Device\AudioInput\Descriptors.h"></File><File path="Demos\Device\AudioInput\Doxygen.conf"></File><File path="Demos\Device\AudioInput\makefile"></File></Folder><Folder name="AudioOutput"><File path="Demos\Device\AudioOutput\AudioOutput.c"></File><File path="Demos\Device\AudioOutput\AudioOutput.h"></File><File path="Demos\Device\AudioOutput\AudioOutput.txt"></File><File path="Demos\Device\AudioOutput\Descriptors.c"></File><File path="Demos\Device\AudioOutput\Descriptors.h"></File><File path="Demos\Device\AudioOutput\Doxygen.conf"></File><File path="Demos\Device\AudioOutput\makefile"></File></Folder><Folder name="CDC"><File path="Demos\Device\CDC\CDC.c"></File><File path="Demos\Device\CDC\CDC.h"></File><File path="Demos\Device\CDC\CDC.txt"></File><File path="Demos\Device\CDC\Descriptors.c"></File><File path="Demos\Device\CDC\Descriptors.h"></File><File path="Demos\Device\CDC\Doxygen.conf"></File><File path="Demos\Device\CDC\LUFA CDC.inf"></File><File path="Demos\Device\CDC\makefile"></File></Folder><Folder name="DualCDC"><File path="Demos\Device\DualCDC\Descriptors.c"></File><File path="Demos\Device\DualCDC\Descriptors.h"></File><File path="Demos\Device\DualCDC\Doxygen.conf"></File><File path="Demos\Device\DualCDC\DualCDC.c"></File><File path="Demos\Device\DualCDC\DualCDC.h"></File><File path="Demos\Device\DualCDC\DualCDC.txt"></File><File path="Demos\Device\DualCDC\LUFA DualCDC.inf"></File><File path="Demos\Device\DualCDC\makefile"></File></Folder><Folder name="GenericHID"><File path="Demos\Device\GenericHID\Descriptors.c"></File><File path="Demos\Device\GenericHID\Descriptors.h"></File><File path="Demos\Device\GenericHID\GenericHID.c"></File><File path="Demos\Device\GenericHID\GenericHID.h"></File><File path="Demos\Device\GenericHID\makefile"></File><File path="Demos\Device\GenericHID\GenericHID.txt"></File><File path="Demos\Device\GenericHID\Doxygen.conf"></File></Folder><Folder name="Joystick"><File path="Demos\Device\Joystick\Descriptors.c"></File><File path="Demos\Device\Joystick\Descriptors.h"></File><File path="Demos\Device\Joystick\Doxygen.conf"></File><File path="Demos\Device\Joystick\Joystick.c"></File><File path="Demos\Device\Joystick\Joystick.h"></File><File path="Demos\Device\Joystick\Joystick.txt"></File><File path="Demos\Device\Joystick\makefile"></File></Folder><Folder name="Keyboard"><File path="Demos\Device\Keyboard\Descriptors.c"></File><File path="Demos\Device\Keyboard\Descriptors.h"></File><File path="Demos\Device\Keyboard\Doxygen.conf"></File><File path="Demos\Device\Keyboard\Keyboard.c"></File><File path="Demos\Device\Keyboard\Keyboard.h"></File><File path="Demos\Device\Keyboard\Keyboard.txt"></File><File path="Demos\Device\Keyboard\makefile"></File></Folder><Folder name="KeyboardMouse"><File path="Demos\Device\KeyboardMouse\Descriptors.c"></File><File path="Demos\Device\KeyboardMouse\Descriptors.h"></File><File path="Demos\Device\KeyboardMouse\Doxygen.conf"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.c"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.h"></File><File path="Demos\Device\KeyboardMouse\KeyboardMouse.txt"></File><File path="Demos\Device\KeyboardMouse\makefile"></File></Folder><Folder name="MassStorage"><Folder name="Lib"><File path="Demos\Device\MassStorage\Lib\DataflashManager.c"></File><File path="Demos\Device\MassStorage\Lib\DataflashManager.h"></File><File path="Demos\Device\MassStorage\Lib\SCSI.c"></File><File path="Demos\Device\MassStorage\Lib\SCSI.h"></File><File path="Demos\Device\MassStorage\Lib\SCSI_Codes.h"></File></Folder><File path="Demos\Device\MassStorage\Descriptors.c"></File><File path="Demos\Device\MassStorage\Descriptors.h"></File><File path="Demos\Device\MassStorage\Doxygen.conf"></File><File path="Demos\Device\MassStorage\makefile"></File><File path="Demos\Device\MassStorage\MassStorage.c"></File><File path="Demos\Device\MassStorage\MassStorage.h"></File><File path="Demos\Device\MassStorage\MassStorage.txt"></File></Folder><Folder name="MIDI"><File path="Demos\Device\MIDI\Descriptors.c"></File><File path="Demos\Device\MIDI\Descriptors.h"></File><File path="Demos\Device\MIDI\Doxygen.conf"></File><File path="Demos\Device\MIDI\makefile"></File><File path="Demos\Device\MIDI\MIDI.c"></File><File path="Demos\Device\MIDI\MIDI.h"></File><File path="Demos\Device\MIDI\MIDI.txt"></File></Folder><Folder name="Mouse"><File path="Demos\Device\Mouse\Descriptors.c"></File><File path="Demos\Device\Mouse\Descriptors.h"></File><File path="Demos\Device\Mouse\Doxygen.conf"></File><File path="Demos\Device\Mouse\makefile"></File><File path="Demos\Device\Mouse\Mouse.c"></File><File path="Demos\Device\Mouse\Mouse.h"></File><File path="Demos\Device\Mouse\Mouse.txt"></File></Folder><Folder name="RNDISEthernet"><Folder name="Lib"><File path="Demos\Device\RNDISEthernet\Lib\Webserver.h"></File><File path="Demos\Device\RNDISEthernet\Lib\ARP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\ARP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\DHCP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\DHCP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\Ethernet.c"></File><File path="Demos\Device\RNDISEthernet\Lib\Ethernet.h"></File><File path="Demos\Device\RNDISEthernet\Lib\EthernetProtocols.h"></File><File path="Demos\Device\RNDISEthernet\Lib\ICMP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\ICMP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\IP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\IP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\ProtocolDecoders.c"></File><File path="Demos\Device\RNDISEthernet\Lib\ProtocolDecoders.h"></File><File path="Demos\Device\RNDISEthernet\Lib\RNDIS.c"></File><File path="Demos\Device\RNDISEthernet\Lib\RNDIS.h"></File><File path="Demos\Device\RNDISEthernet\Lib\RNDISConstants.h"></File><File path="Demos\Device\RNDISEthernet\Lib\TCP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\TCP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\UDP.c"></File><File path="Demos\Device\RNDISEthernet\Lib\UDP.h"></File><File path="Demos\Device\RNDISEthernet\Lib\Webserver.c"></File></Folder><File path="Demos\Device\RNDISEthernet\Descriptors.c"></File><File path="Demos\Device\RNDISEthernet\Descriptors.h"></File><File path="Demos\Device\RNDISEthernet\Doxygen.conf"></File><File path="Demos\Device\RNDISEthernet\LUFA RNDIS.inf"></File><File path="Demos\Device\RNDISEthernet\makefile"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.c"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.h"></File><File path="Demos\Device\RNDISEthernet\RNDISEthernet.txt"></File></Folder><Folder name="USBtoSerial"><Folder name="Lib"><File path="Demos\Device\USBtoSerial\Lib\RingBuff.c"></File><File path="Demos\Device\USBtoSerial\Lib\RingBuff.h"></File></Folder><File path="Demos\Device\USBtoSerial\Descriptors.c"></File><File path="Demos\Device\USBtoSerial\Descriptors.h"></File><File path="Demos\Device\USBtoSerial\Doxygen.conf"></File><File path="Demos\Device\USBtoSerial\LUFA USBtoSerial.inf"></File><File path="Demos\Device\USBtoSerial\makefile"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.c"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.h"></File><File path="Demos\Device\USBtoSerial\USBtoSerial.txt"></File></Folder><File path="Demos\Device\makefile"></File></Folder><Folder name="Host"><Folder name="CDCHost"><File path="Demos\Host\CDCHost\CDCHost.c"></File><File path="Demos\Host\CDCHost\CDCHost.h"></File><File path="Demos\Host\CDCHost\CDCHost.txt"></File><File path="Demos\Host\CDCHost\ConfigDescriptor.c"></File><File path="Demos\Host\CDCHost\ConfigDescriptor.h"></File><File path="Demos\Host\CDCHost\Doxygen.conf"></File><File path="Demos\Host\CDCHost\makefile"></File></Folder><Folder name="GenericHIDHost"><File path="Demos\Host\GenericHIDHost\ConfigDescriptor.c"></File><File path="Demos\Host\GenericHIDHost\ConfigDescriptor.h"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.c"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.h"></File><File path="Demos\Host\GenericHIDHost\makefile"></File><File path="Demos\Host\GenericHIDHost\Doxygen.conf"></File><File path="Demos\Host\GenericHIDHost\GenericHIDHost.txt"></File></Folder><Folder name="KeyboardHost"><File path="Demos\Host\KeyboardHost\ConfigDescriptor.c"></File><File path="Demos\Host\KeyboardHost\ConfigDescriptor.h"></File><File path="Demos\Host\KeyboardHost\Doxygen.conf"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.c"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.h"></File><File path="Demos\Host\KeyboardHost\KeyboardHost.txt"></File><File path="Demos\Host\KeyboardHost\makefile"></File></Folder><Folder name="KeyboardHostWithParser"><File path="Demos\Host\KeyboardHostWithParser\ConfigDescriptor.c"></File><File path="Demos\Host\KeyboardHostWithParser\ConfigDescriptor.h"></File><File path="Demos\Host\KeyboardHostWithParser\Doxygen.conf"></File><File path="Demos\Host\KeyboardHostWithParser\HIDReport.c"></File><File path="Demos\Host\KeyboardHostWithParser\HIDReport.h"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.c"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.h"></File><File path="Demos\Host\KeyboardHostWithParser\KeyboardHostWithParser.txt"></File><File path="Demos\Host\KeyboardHostWithParser\makefile"></File></Folder><Folder name="MassStorageHost"><Folder name="Lib"><File path="Demos\Host\MassStorageHost\Lib\MassStoreCommands.c"></File><File path="Demos\Host\MassStorageHost\Lib\MassStoreCommands.h"></File><File path="Demos\Host\MassStorageHost\Lib\SCSI_Codes.h"></File></Folder><File path="Demos\Host\MassStorageHost\ConfigDescriptor.c"></File><File path="Demos\Host\MassStorageHost\ConfigDescriptor.h"></File><File path="Demos\Host\MassStorageHost\Doxygen.conf"></File><File path="Demos\Host\MassStorageHost\makefile"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.c"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.h"></File><File path="Demos\Host\MassStorageHost\MassStorageHost.txt"></File></Folder><Folder name="MouseHost"><File path="Demos\Host\MouseHost\ConfigDescriptor.c"></File><File path="Demos\Host\MouseHost\ConfigDescriptor.h"></File><File path="Demos\Host\MouseHost\Doxygen.conf"></File><File path="Demos\Host\MouseHost\makefile"></File><File path="Demos\Host\MouseHost\MouseHost.c"></File><File path="Demos\Host\MouseHost\MouseHost.h"></File><File path="Demos\Host\MouseHost\MouseHost.txt"></File></Folder><Folder name="MouseHostWithParser"><File path="Demos\Host\MouseHostWithParser\ConfigDescriptor.c"></File><File path="Demos\Host\MouseHostWithParser\ConfigDescriptor.h"></File><File path="Demos\Host\MouseHostWithParser\Doxygen.conf"></File><File path="Demos\Host\MouseHostWithParser\HIDReport.c"></File><File path="Demos\Host\MouseHostWithParser\HIDReport.h"></File><File path="Demos\Host\MouseHostWithParser\makefile"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.c"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.h"></File><File path="Demos\Host\MouseHostWithParser\MouseHostWithParser.txt"></File></Folder><Folder name="StillImageHost"><Folder name="Lib"><File path="Demos\Host\StillImageHost\Lib\PIMACodes.h"></File><File path="Demos\Host\StillImageHost\Lib\StillImageCommands.c"></File><File path="Demos\Host\StillImageHost\Lib\StillImageCommands.h"></File></Folder><File path="Demos\Host\StillImageHost\ConfigDescriptor.c"></File><File path="Demos\Host\StillImageHost\ConfigDescriptor.h"></File><File path="Demos\Host\StillImageHost\Doxygen.conf"></File><File path="Demos\Host\StillImageHost\makefile"></File><File path="Demos\Host\StillImageHost\StillImageHost.c"></File><File path="Demos\Host\StillImageHost\StillImageHost.h"></File><File path="Demos\Host\StillImageHost\StillImageHost.txt"></File></Folder><File path="Demos\Host\makefile"></File></Folder><Folder name="OTG"><Folder name="TestApp"><File path="Demos\OTG\TestApp\Descriptors.c"></File><File path="Demos\OTG\TestApp\Descriptors.h"></File><File path="Demos\OTG\TestApp\Doxygen.conf"></File><File path="Demos\OTG\TestApp\makefile"></File><File path="Demos\OTG\TestApp\TestApp.c"></File><File path="Demos\OTG\TestApp\TestApp.h"></File><File path="Demos\OTG\TestApp\TestApp.txt"></File><File path="Demos\OTG\TestApp\TestEvents.c"></File><File path="Demos\OTG\TestApp\TestEvents.h"></File></Folder><File path="Demos\OTG\makefile"></File></Folder><File path="Demos\makefile"></File></Folder><Folder name="LUFA"><Folder name="Common"><File path="LUFA\Common\Common.h"></File><File path="LUFA\Common\FunctionAttributes.h"></File><File path="LUFA\Common\BoardTypes.h"></File></Folder><Folder name="Drivers"><Folder name="USB"><Folder name="LowLevel"><File path="LUFA\Drivers\USB\LowLevel\HostChapter9.h"></File><File path="LUFA\Drivers\USB\LowLevel\LowLevel.c"></File><File path="LUFA\Drivers\USB\LowLevel\LowLevel.h"></File><File path="LUFA\Drivers\USB\LowLevel\Pipe.c"></File><File path="LUFA\Drivers\USB\LowLevel\Pipe.h"></File><File path="LUFA\Drivers\USB\LowLevel\DevChapter9.c"></File><File path="LUFA\Drivers\USB\LowLevel\DevChapter9.h"></File><File path="LUFA\Drivers\USB\LowLevel\Device.h"></File><File path="LUFA\Drivers\USB\LowLevel\Endpoint.c"></File><File path="LUFA\Drivers\USB\LowLevel\Endpoint.h"></File><File path="LUFA\Drivers\USB\LowLevel\Host.c"></File><File path="LUFA\Drivers\USB\LowLevel\Host.h"></File><File path="LUFA\Drivers\USB\LowLevel\HostChapter9.c"></File><File path="LUFA\Drivers\USB\LowLevel\OTG.h"></File></Folder><Folder name="HighLevel"><File path="LUFA\Drivers\USB\HighLevel\USBTask.h"></File><File path="LUFA\Drivers\USB\HighLevel\Events.c"></File><File path="LUFA\Drivers\USB\HighLevel\Events.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBInterrupt.c"></File><File path="LUFA\Drivers\USB\HighLevel\USBInterrupt.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBTask.c"></File><File path="LUFA\Drivers\USB\HighLevel\StdDescriptors.h"></File><File path="LUFA\Drivers\USB\HighLevel\StdRequestType.h"></File><File path="LUFA\Drivers\USB\HighLevel\StreamCallbacks.h"></File><File path="LUFA\Drivers\USB\HighLevel\USBMode.h"></File><File path="LUFA\Drivers\USB\HighLevel\ConfigDescriptor.c"></File><File path="LUFA\Drivers\USB\HighLevel\ConfigDescriptor.h"></File></Folder><Folder name="Class"><File path="LUFA\Drivers\USB\Class\HIDParser.c"></File><File path="LUFA\Drivers\USB\Class\HIDParser.h"></File><File path="LUFA\Drivers\USB\Class\HIDReportData.h"></File></Folder><File path="LUFA\Drivers\USB\USB.h"></File></Folder><Folder name="Misc"><File path="LUFA\Drivers\Misc\TerminalCodes.h"></File></Folder><Folder name="Board"><Folder name="USBKEY"><File path="LUFA\Drivers\Board\USBKEY\Dataflash.h"></File><File path="LUFA\Drivers\Board\USBKEY\Joystick.h"></File><File path="LUFA\Drivers\Board\USBKEY\AT45DB642D.h"></File><File path="LUFA\Drivers\Board\USBKEY\LEDs.h"></File><File path="LUFA\Drivers\Board\USBKEY\Buttons.h"></File></Folder><Folder name="STK526"><File path="LUFA\Drivers\Board\STK526\Dataflash.h"></File><File path="LUFA\Drivers\Board\STK526\Joystick.h"></File><File path="LUFA\Drivers\Board\STK526\AT45DB642D.h"></File><File path="LUFA\Drivers\Board\STK526\LEDs.h"></File><File path="LUFA\Drivers\Board\STK526\Buttons.h"></File></Folder><Folder name="STK525"><File path="LUFA\Drivers\Board\STK525\Dataflash.h"></File><File path="LUFA\Drivers\Board\STK525\Joystick.h"></File><File path="LUFA\Drivers\Board\STK525\AT45DB321C.h"></File><File path="LUFA\Drivers\Board\STK525\LEDs.h"></File><File path="LUFA\Drivers\Board\STK525\Buttons.h"></File></Folder><Folder name="RZUSBSTICK"><File path="LUFA\Drivers\Board\RZUSBSTICK\LEDs.h"></File></Folder><Folder name="ATAVRUSBRF01"><File path="LUFA\Drivers\Board\ATAVRUSBRF01\LEDs.h"></File><File path="LUFA\Drivers\Board\ATAVRUSBRF01\Buttons.h"></File></Folder><File path="LUFA\Drivers\Board\Temperature.h"></File><File path="LUFA\Drivers\Board\Dataflash.h"></File><File path="LUFA\Drivers\Board\Joystick.h"></File><File path="LUFA\Drivers\Board\Temperature.c"></File><File path="LUFA\Drivers\Board\LEDs.h"></File><File path="LUFA\Drivers\Board\Buttons.h"></File></Folder><Folder name="Peripheral"><Folder name="AT90USBXXX67"><File path="LUFA\Drivers\Peripheral\AT90USBXXX67\ADC.h"></File></Folder><File path="LUFA\Drivers\Peripheral\ADC.h"></File><File path="LUFA\Drivers\Peripheral\Serial.c"></File><File path="LUFA\Drivers\Peripheral\Serial.h"></File><File path="LUFA\Drivers\Peripheral\SPI.h"></File><File path="LUFA\Drivers\Peripheral\SerialStream.c"></File><File path="LUFA\Drivers\Peripheral\SerialStream.h"></File></Folder></Folder><Folder name="Scheduler"><File path="LUFA\Scheduler\Scheduler.h"></File><File path="LUFA\Scheduler\Scheduler.c"></File></Folder><Folder name="MemoryAllocator"><File path="LUFA\MemoryAllocator\DynAlloc.h"></File><File path="LUFA\MemoryAllocator\DynAlloc.c"></File></Folder><Folder name="DriverStubs"><File path="LUFA\DriverStubs\Dataflash.h"></File><File path="LUFA\DriverStubs\Joystick.h"></File><File path="LUFA\DriverStubs\LEDs.h"></File><File path="LUFA\DriverStubs\Buttons.h"></File></Folder><File path="LUFA\makefile"></File><File path="LUFA\Version.h"></File><File path="LUFA\BuildingLinkableLibraries.txt"></File><File path="LUFA\GettingStarted.txt"></File><File path="LUFA\MainPage.txt"></File><File path="LUFA\SchedulerOverview.txt"></File><File path="LUFA\VIDAndPIDValues.txt"></File><File path="LUFA\ChangeLog.txt"></File><File path="LUFA\CompileTimeTokens.txt"></File><File path="LUFA\MigrationInformation.txt"></File><File path="LUFA\DirectorySummaries.txt"></File><File path="LUFA\Doxygen.conf"></File><File path="LUFA\WritingBoardDrivers.txt"></File><File path="LUFA\LUFAPoweredProjects.txt"></File><File path="LUFA\Groups.txt"></File></Folder><Folder name="Projects"><Folder name="MagStripe"><Folder name="Lib"><File path="Projects\Magstripe\Lib\CircularBitBuffer.c"></File><File path="Projects\Magstripe\Lib\CircularBitBuffer.h"></File><File path="Projects\Magstripe\Lib\MagstripeHW.h"></File></Folder><File path="Projects\Magstripe\Descriptors.c"></File><File path="Projects\Magstripe\Descriptors.h"></File><File path="Projects\Magstripe\Magstripe.c"></File><File path="Projects\Magstripe\Magstripe.h"></File><File path="Projects\Magstripe\makefile"></File><File path="Projects\Magstripe\Magstripe.txt"></File><File path="Projects\Magstripe\Doxygen.conf"></File></Folder><File path="Projects\makefile"></File></Folder><Folder name="Bootloaders"><Folder name="DFU"><File path="Bootloaders\DFU\BootloaderDFU.c"></File><File path="Bootloaders\DFU\BootloaderDFU.h"></File><File path="Bootloaders\DFU\Descriptors.c"></File><File path="Bootloaders\DFU\Descriptors.h"></File><File path="Bootloaders\DFU\makefile"></File><File path="Bootloaders\DFU\BootloaderDFU.txt"></File><File path="Bootloaders\DFU\Doxygen.conf"></File></Folder><Folder name="CDC"><File path="Bootloaders\CDC\BootloaderCDC.c"></File><File path="Bootloaders\CDC\BootloaderCDC.h"></File><File path="Bootloaders\CDC\Descriptors.c"></File><File path="Bootloaders\CDC\Descriptors.h"></File><File path="Bootloaders\CDC\makefile"></File><File path="Bootloaders\CDC\LUFA CDC Bootloader.inf"></File><File path="Bootloaders\CDC\Doxygen.conf"></File><File path="Bootloaders\CDC\BootloaderCDC.txt"></File></Folder><Folder name="TeensyHID"><File path="Bootloaders\TeensyHID\Descriptors.c"></File><File path="Bootloaders\TeensyHID\Descriptors.h"></File><File path="Bootloaders\TeensyHID\makefile"></File><File path="Bootloaders\TeensyHID\TeensyHID.c"></File><File path="Bootloaders\TeensyHID\TeensyHID.h"></File><File path="Bootloaders\TeensyHID\TeensyHID.txt"></File></Folder><File path="Bootloaders\makefile"></File></Folder><File path="makefile"></File></Project>
\ No newline at end of file
* - Fixed incorrect PID value being used in the USBtoSerial project (thanks to Phill)\r
* - Deleted StdDescriptors.c, renamed USB_GetDescriptor() to CALLBACK_USB_GetDescriptor, moved ConfigDescriptor.c/.h from the\r
* LUFA/Drivers/USB/Class/ directory to LUFA/Drivers/USB/HighLevel/ in preperation for the new USB class APIs\r
+ * - Moved out each demos' functionality library files (e.g. Ring Buffer library) to /Lib directories for a better directory structure\r
*\r
*\r
* \section Sec_ChangeLog090510 Version 090510\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** Circular bit buffer library. This will allow for individual bits\r
- * to be stored in packed form inside circular buffers, to reduce\r
- * overall RAM usage.\r
- */\r
-\r
-#include "CircularBitBuffer.h"\r
-\r
-/** Function to initialize or reset a bit buffer, ready for data to be stored into it. */\r
-void BitBuffer_Init(BitBuffer_t* Buffer)\r
-{\r
- /* Reset the number of stored bits in the buffer */\r
- Buffer->Elements = 0;\r
- \r
- /* Reset the data in and out pointer structures in the buffer to the first buffer bit */\r
- Buffer->In.CurrentByte = Buffer->Data;\r
- Buffer->In.ByteMask = (1 << 0);\r
- Buffer->Out.CurrentByte = Buffer->Data;\r
- Buffer->Out.ByteMask = (1 << 0);\r
-}\r
-\r
-/** Function to store the given bit into the given bit buffer. */\r
-void BitBuffer_StoreNextBit(BitBuffer_t* Buffer, bool Bit)\r
-{\r
- /* If the bit to store is true, set the next bit in the buffer */\r
- if (Bit)\r
- *Buffer->In.CurrentByte |= Buffer->In.ByteMask;\r
- \r
- /* Increment the number of stored bits in the buffer counter */\r
- Buffer->Elements++;\r
- \r
- /* Check if the current buffer byte is full of stored bits */\r
- if (Buffer->In.ByteMask == (1 << 7))\r
- {\r
- /* Check if the end of the buffer has been reached, if so reset to start of buffer, otherwise advance to next bit */\r
- if (Buffer->In.CurrentByte != &Buffer->Data[sizeof(Buffer->Data) - 1])\r
- Buffer->In.CurrentByte++;\r
- else\r
- Buffer->In.CurrentByte = Buffer->Data;\r
- \r
- /* Reset the storage bit mask in the current buffer byte to the first bit */ \r
- Buffer->In.ByteMask = (1 << 0);\r
- }\r
- else\r
- {\r
- /* Shift the current storage bit mask to the next bit in the current byte */\r
- Buffer->In.ByteMask <<= 1;\r
- }\r
-}\r
-\r
-/** Function to retrieve the next bit stored in the given bit buffer. */\r
-bool BitBuffer_GetNextBit(BitBuffer_t* Buffer)\r
-{ \r
- /* Retrieve the value of the next bit stored in the buffer */\r
- bool Bit = ((*Buffer->Out.CurrentByte & Buffer->Out.ByteMask) != 0);\r
-\r
- /* Clear the buffer bit */\r
- *Buffer->Out.CurrentByte &= ~Buffer->Out.ByteMask;\r
-\r
- /* Decrement the number of stored bits in the buffer counter */\r
- Buffer->Elements--;\r
- \r
- /* Check if the current buffer byte is empty of stored bits */ \r
- if (Buffer->Out.ByteMask == (1 << 7))\r
- {\r
- /* Check if the end of the buffer has been reached, if so reset to start of buffer, otherwise advance to next bit */\r
- if (Buffer->Out.CurrentByte != &Buffer->Data[sizeof(Buffer->Data) - 1])\r
- Buffer->Out.CurrentByte++;\r
- else\r
- Buffer->Out.CurrentByte = Buffer->Data; \r
- \r
- /* Reset the retrieval bit mask in the current buffer byte to the first bit */ \r
- Buffer->Out.ByteMask = (1 << 0);\r
- }\r
- else\r
- {\r
- /* Shift the current retrieval bit mask to the next bit in the current byte */\r
- Buffer->Out.ByteMask <<= 1;\r
- }\r
-\r
- /* Return the retrieved bit from the buffer */\r
- return Bit;\r
-}\r
+++ /dev/null
-/*\r
- LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
- \r
- dean [at] fourwalledcubicle [dot] com\r
- www.fourwalledcubicle.com\r
-*/\r
-\r
-/*\r
- Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
- Permission to use, copy, modify, and distribute this software\r
- and its documentation for any purpose and without fee is hereby\r
- granted, provided that the above copyright notice appear in all\r
- copies and that both that the copyright notice and this\r
- permission notice and warranty disclaimer appear in supporting\r
- documentation, and that the name of the author not be used in\r
- advertising or publicity pertaining to distribution of the\r
- software without specific, written prior permission.\r
-\r
- The author disclaim all warranties with regard to this\r
- software, including all implied warranties of merchantability\r
- and fitness. In no event shall the author be liable for any\r
- special, indirect or consequential damages or any damages\r
- whatsoever resulting from loss of use, data or profits, whether\r
- in an action of contract, negligence or other tortious action,\r
- arising out of or in connection with the use or performance of\r
- this software.\r
-*/\r
-\r
-/** \file\r
- *\r
- * Header file for CircularBitBuffer.c.\r
- */\r
-\r
-#ifndef _CIRCULARBITBUFFER_H_\r
-#define _CIRCULARBITBUFFER_H_\r
-\r
- /* Includes: */\r
- #include <avr/io.h>\r
- #include <stdbool.h>\r
- \r
- #include <LUFA/Common/Common.h>\r
-\r
- /* Macros: */\r
- #if (defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \\r
- defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__)) || defined(__DOXYGEN__)\r
- /** Maximum number of bits which can be stored into a bit buffer. The memory usage is one eighth of this value per buffer. */\r
- #define MAX_BITS 8192\r
- #else\r
- #define MAX_BITS 1024\r
- #endif\r
- \r
- /* Type Defines: */\r
- /* Type define for a pointer to a bit in a bit buffer. */\r
- typedef struct\r
- {\r
- uint8_t* CurrentByte; /**< Pointer to the current byte in the buffer */\r
- uint8_t ByteMask; /**< Mask of the current bit in the buffer */\r
- } BitBufferPointer_t;\r
-\r
- /** Type define for a circular packet bit buffer. */\r
- typedef struct\r
- {\r
- uint8_t Data[MAX_BITS / 8]; /**< Buffer to hold the stored bits in packed form */\r
- uint16_t Elements; /**< Number of stored bits in the bit buffer */\r
- \r
- BitBufferPointer_t In; /**< Bit pointer to the next storage location in the buffer */\r
- BitBufferPointer_t Out; /**< Bit pointer to the next retrieval location in the buffer */\r
- } BitBuffer_t;\r
- \r
- /* Function Prototypes: */ \r
- /** Initializes or resets a given bit buffer, ready to store new bits.\r
- * \r
- * \param Buffer Bit buffer to initialize\r
- */\r
- void BitBuffer_Init(BitBuffer_t* Buffer) ATTR_NON_NULL_PTR_ARG(1);\r
- \r
- /** Stores a bit into the next location inside a given bit buffer.\r
- *\r
- * \param Buffer Bit buffer to store a bit into\r
- * \param Bit Bit to store into the buffer\r
- */\r
- void BitBuffer_StoreNextBit(BitBuffer_t* Buffer, bool Bit) ATTR_NON_NULL_PTR_ARG(1);\r
- \r
- /** Retrieves a bit from the next location inside a given bit buffer.\r
- *\r
- * \param Buffer Bit buffer to store a bit into\r
- *\r
- * \return Next bit from the buffer\r
- */\r
- bool BitBuffer_GetNextBit(BitBuffer_t* Buffer) ATTR_NON_NULL_PTR_ARG(1);\r
- \r
-#endif\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** Circular bit buffer library. This will allow for individual bits\r
+ * to be stored in packed form inside circular buffers, to reduce\r
+ * overall RAM usage.\r
+ */\r
+\r
+#include "CircularBitBuffer.h"\r
+\r
+/** Function to initialize or reset a bit buffer, ready for data to be stored into it. */\r
+void BitBuffer_Init(BitBuffer_t* Buffer)\r
+{\r
+ /* Reset the number of stored bits in the buffer */\r
+ Buffer->Elements = 0;\r
+ \r
+ /* Reset the data in and out pointer structures in the buffer to the first buffer bit */\r
+ Buffer->In.CurrentByte = Buffer->Data;\r
+ Buffer->In.ByteMask = (1 << 0);\r
+ Buffer->Out.CurrentByte = Buffer->Data;\r
+ Buffer->Out.ByteMask = (1 << 0);\r
+}\r
+\r
+/** Function to store the given bit into the given bit buffer. */\r
+void BitBuffer_StoreNextBit(BitBuffer_t* Buffer, bool Bit)\r
+{\r
+ /* If the bit to store is true, set the next bit in the buffer */\r
+ if (Bit)\r
+ *Buffer->In.CurrentByte |= Buffer->In.ByteMask;\r
+ \r
+ /* Increment the number of stored bits in the buffer counter */\r
+ Buffer->Elements++;\r
+ \r
+ /* Check if the current buffer byte is full of stored bits */\r
+ if (Buffer->In.ByteMask == (1 << 7))\r
+ {\r
+ /* Check if the end of the buffer has been reached, if so reset to start of buffer, otherwise advance to next bit */\r
+ if (Buffer->In.CurrentByte != &Buffer->Data[sizeof(Buffer->Data) - 1])\r
+ Buffer->In.CurrentByte++;\r
+ else\r
+ Buffer->In.CurrentByte = Buffer->Data;\r
+ \r
+ /* Reset the storage bit mask in the current buffer byte to the first bit */ \r
+ Buffer->In.ByteMask = (1 << 0);\r
+ }\r
+ else\r
+ {\r
+ /* Shift the current storage bit mask to the next bit in the current byte */\r
+ Buffer->In.ByteMask <<= 1;\r
+ }\r
+}\r
+\r
+/** Function to retrieve the next bit stored in the given bit buffer. */\r
+bool BitBuffer_GetNextBit(BitBuffer_t* Buffer)\r
+{ \r
+ /* Retrieve the value of the next bit stored in the buffer */\r
+ bool Bit = ((*Buffer->Out.CurrentByte & Buffer->Out.ByteMask) != 0);\r
+\r
+ /* Clear the buffer bit */\r
+ *Buffer->Out.CurrentByte &= ~Buffer->Out.ByteMask;\r
+\r
+ /* Decrement the number of stored bits in the buffer counter */\r
+ Buffer->Elements--;\r
+ \r
+ /* Check if the current buffer byte is empty of stored bits */ \r
+ if (Buffer->Out.ByteMask == (1 << 7))\r
+ {\r
+ /* Check if the end of the buffer has been reached, if so reset to start of buffer, otherwise advance to next bit */\r
+ if (Buffer->Out.CurrentByte != &Buffer->Data[sizeof(Buffer->Data) - 1])\r
+ Buffer->Out.CurrentByte++;\r
+ else\r
+ Buffer->Out.CurrentByte = Buffer->Data; \r
+ \r
+ /* Reset the retrieval bit mask in the current buffer byte to the first bit */ \r
+ Buffer->Out.ByteMask = (1 << 0);\r
+ }\r
+ else\r
+ {\r
+ /* Shift the current retrieval bit mask to the next bit in the current byte */\r
+ Buffer->Out.ByteMask <<= 1;\r
+ }\r
+\r
+ /* Return the retrieved bit from the buffer */\r
+ return Bit;\r
+}\r
--- /dev/null
+/*\r
+ LUFA Library\r
+ Copyright (C) Dean Camera, 2009.\r
+ \r
+ dean [at] fourwalledcubicle [dot] com\r
+ www.fourwalledcubicle.com\r
+*/\r
+\r
+/*\r
+ Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)\r
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+ Permission to use, copy, modify, and distribute this software\r
+ and its documentation for any purpose and without fee is hereby\r
+ granted, provided that the above copyright notice appear in all\r
+ copies and that both that the copyright notice and this\r
+ permission notice and warranty disclaimer appear in supporting\r
+ documentation, and that the name of the author not be used in\r
+ advertising or publicity pertaining to distribution of the\r
+ software without specific, written prior permission.\r
+\r
+ The author disclaim all warranties with regard to this\r
+ software, including all implied warranties of merchantability\r
+ and fitness. In no event shall the author be liable for any\r
+ special, indirect or consequential damages or any damages\r
+ whatsoever resulting from loss of use, data or profits, whether\r
+ in an action of contract, negligence or other tortious action,\r
+ arising out of or in connection with the use or performance of\r
+ this software.\r
+*/\r
+\r
+/** \file\r
+ *\r
+ * Header file for CircularBitBuffer.c.\r
+ */\r
+\r
+#ifndef _CIRCULARBITBUFFER_H_\r
+#define _CIRCULARBITBUFFER_H_\r
+\r
+ /* Includes: */\r
+ #include <avr/io.h>\r
+ #include <stdbool.h>\r
+ \r
+ #include <LUFA/Common/Common.h>\r
+\r
+ /* Macros: */\r
+ #if (defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \\r
+ defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__)) || defined(__DOXYGEN__)\r
+ /** Maximum number of bits which can be stored into a bit buffer. The memory usage is one eighth of this value per buffer. */\r
+ #define MAX_BITS 8192\r
+ #else\r
+ #define MAX_BITS 1024\r
+ #endif\r
+ \r
+ /* Type Defines: */\r
+ /* Type define for a pointer to a bit in a bit buffer. */\r
+ typedef struct\r
+ {\r
+ uint8_t* CurrentByte; /**< Pointer to the current byte in the buffer */\r
+ uint8_t ByteMask; /**< Mask of the current bit in the buffer */\r
+ } BitBufferPointer_t;\r
+\r
+ /** Type define for a circular packet bit buffer. */\r
+ typedef struct\r
+ {\r
+ uint8_t Data[MAX_BITS / 8]; /**< Buffer to hold the stored bits in packed form */\r
+ uint16_t Elements; /**< Number of stored bits in the bit buffer */\r
+ \r
+ BitBufferPointer_t In; /**< Bit pointer to the next storage location in the buffer */\r
+ BitBufferPointer_t Out; /**< Bit pointer to the next retrieval location in the buffer */\r
+ } BitBuffer_t;\r
+ \r
+ /* Function Prototypes: */ \r
+ /** Initializes or resets a given bit buffer, ready to store new bits.\r
+ * \r
+ * \param Buffer Bit buffer to initialize\r
+ */\r
+ void BitBuffer_Init(BitBuffer_t* Buffer) ATTR_NON_NULL_PTR_ARG(1);\r
+ \r
+ /** Stores a bit into the next location inside a given bit buffer.\r
+ *\r
+ * \param Buffer Bit buffer to store a bit into\r
+ * \param Bit Bit to store into the buffer\r
+ */\r
+ void BitBuffer_StoreNextBit(BitBuffer_t* Buffer, bool Bit) ATTR_NON_NULL_PTR_ARG(1);\r
+ \r
+ /** Retrieves a bit from the next location inside a given bit buffer.\r
+ *\r
+ * \param Buffer Bit buffer to store a bit into\r
+ *\r
+ * \return Next bit from the buffer\r
+ */\r
+ bool BitBuffer_GetNextBit(BitBuffer_t* Buffer) ATTR_NON_NULL_PTR_ARG(1);\r
+ \r
+#endif\r
--- /dev/null
+/*
+ Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)
+ Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, and distribute this software
+ and its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/*
+ NOTE: The user of this include file MUST define the following macros
+ prior to including the file:
+
+ MAG_T1_CLOCK_PIN Pin connected to Track 1 clock wire (ie. PORTC1)
+ MAG_T1_DATA_PIN Pin connected to Track 1 data wire (ie. PORTC2)
+ MAG_T2_CLOCK_PIN Pin connected to Track 2 clock wire (ie. PORTC3)
+ MAG_T2_DATA_PIN Pin connected to Track 2 data wire (ie. PORTC0)
+ MAG_T3_CLOCK_PIN Pin connected to Track 3 clock wire (ie. PORTC5)
+ MAG_T3_DATA_PIN Pin connected to Track 3 data wire (ie. PORTC6)
+ MAG_CLS_PIN Pin connected to card loaded wire (ie. PORTC4)
+ MAG_PIN PIN macro for the reader's port (ie. PINC)
+ MAG_DDR DDR macro for the reader's port (ie. DDRC)
+ MAG_PORT PORT macro for the reader's port (ie. PORTC)
+
+ The example macros listed above assume that the Track 2 data wire is
+ connected to pin 0 on port C, the Track 2 clock wire is connected to
+ pin 3 on port C (similarly for Tracks 1 and 3), and the card loaded
+ wire is connected to pin 4 on port C.
+
+ If the magstripe reader you are using only reads one or two tracks,
+ then set the clock and data pins for the tracks it doesn't read to a
+ pin that is unused. For example, on the AT90USBKey, any of the pins on
+ port C that do not have wires attached will be unused since they are
+ not connected to any onboard devices (such as the joystick or
+ temperature sensor).
+
+ Connecting wires to pins on different ports (ie. a data wire to pin 0
+ on port C and a clock wire to pin 0 on port D) is currently
+ unsupported. All pins specified above must be on the same port.
+*/
+
+/** \file
+ *
+ * Driver header for a TTL Magnetic Card reader device (such as the Omron V3B-4K).
+ */
+
+#ifndef _MAGSTRIPEHW_H_
+#define _MAGSTRIPEHW_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+
+ #include <LUFA/Common/Common.h>
+
+ /* Private Interface - For use in library only: */
+ /* Macros: */
+ /** Mask of the track data, clock and card detection pins. */
+ #define MAG_MASK (MAG_T1_DATA | MAG_T1_CLOCK | \
+ MAG_T2_DATA | MAG_T2_CLOCK | \
+ MAG_T3_DATA | MAG_T3_CLOCK | \
+ MAG_CARDPRESENT)
+
+ /* Public Interface - May be used in end-application: */
+ /* Inline Functions: */
+ /** Initializes the magnetic stripe card reader ports and pins so that the card reader
+ * device can be controlled and read by the card reader driver. This must be called before
+ * trying to read any of the card reader's status lines.
+ */
+ static inline void Magstripe_Init(void)
+ {
+ MAG_DDR &= ~MAG_MASK;
+ MAG_PORT |= MAG_MASK;
+ };
+
+ /** Returns the status of all the magnetic card reader's outputs.
+ *
+ * \return A mask indicating which card lines are high or low
+ */
+ static inline uint8_t Magstripe_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Magstripe_GetStatus(void)
+ {
+ /* Magstripe IOs are active low and must be inverted when read */
+ return ((uint8_t)~MAG_PIN & MAG_MASK);
+ }
+
+#endif
#include <string.h>\r
\r
#include "Descriptors.h"\r
- #include "MagstripeHW.h"\r
- #include "CircularBitBuffer.h"\r
+\r
+ #include "Lib/MagstripeHW.h"\r
+ #include "Lib/CircularBitBuffer.h"\r
\r
#include <LUFA/Version.h> // Library Version Information\r
#include <LUFA/Drivers/USB/USB.h> // USB Functionality\r
+++ /dev/null
-/*
- Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is hereby
- granted, provided that the above copyright notice appear in all
- copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/*
- NOTE: The user of this include file MUST define the following macros
- prior to including the file:
-
- MAG_T1_CLOCK_PIN Pin connected to Track 1 clock wire (ie. PORTC1)
- MAG_T1_DATA_PIN Pin connected to Track 1 data wire (ie. PORTC2)
- MAG_T2_CLOCK_PIN Pin connected to Track 2 clock wire (ie. PORTC3)
- MAG_T2_DATA_PIN Pin connected to Track 2 data wire (ie. PORTC0)
- MAG_T3_CLOCK_PIN Pin connected to Track 3 clock wire (ie. PORTC5)
- MAG_T3_DATA_PIN Pin connected to Track 3 data wire (ie. PORTC6)
- MAG_CLS_PIN Pin connected to card loaded wire (ie. PORTC4)
- MAG_PIN PIN macro for the reader's port (ie. PINC)
- MAG_DDR DDR macro for the reader's port (ie. DDRC)
- MAG_PORT PORT macro for the reader's port (ie. PORTC)
-
- The example macros listed above assume that the Track 2 data wire is
- connected to pin 0 on port C, the Track 2 clock wire is connected to
- pin 3 on port C (similarly for Tracks 1 and 3), and the card loaded
- wire is connected to pin 4 on port C.
-
- If the magstripe reader you are using only reads one or two tracks,
- then set the clock and data pins for the tracks it doesn't read to a
- pin that is unused. For example, on the AT90USBKey, any of the pins on
- port C that do not have wires attached will be unused since they are
- not connected to any onboard devices (such as the joystick or
- temperature sensor).
-
- Connecting wires to pins on different ports (ie. a data wire to pin 0
- on port C and a clock wire to pin 0 on port D) is currently
- unsupported. All pins specified above must be on the same port.
-*/
-
-/** \file
- *
- * Driver header for a TTL Magnetic Card reader device (such as the Omron V3B-4K).
- */
-
-#ifndef _MAGSTRIPEHW_H_
-#define _MAGSTRIPEHW_H_
-
- /* Includes: */
- #include <avr/io.h>
-
- #include <LUFA/Common/Common.h>
-
- /* Private Interface - For use in library only: */
- /* Macros: */
- /** Mask of the track data, clock and card detection pins. */
- #define MAG_MASK (MAG_T1_DATA | MAG_T1_CLOCK | \
- MAG_T2_DATA | MAG_T2_CLOCK | \
- MAG_T3_DATA | MAG_T3_CLOCK | \
- MAG_CARDPRESENT)
-
- /* Public Interface - May be used in end-application: */
- /* Inline Functions: */
- /** Initializes the magnetic stripe card reader ports and pins so that the card reader
- * device can be controlled and read by the card reader driver. This must be called before
- * trying to read any of the card reader's status lines.
- */
- static inline void Magstripe_Init(void)
- {
- MAG_DDR &= ~MAG_MASK;
- MAG_PORT |= MAG_MASK;
- };
-
- /** Returns the status of all the magnetic card reader's outputs.
- *
- * \return A mask indicating which card lines are high or low
- */
- static inline uint8_t Magstripe_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
- static inline uint8_t Magstripe_GetStatus(void)
- {
- /* Magstripe IOs are active low and must be inverted when read */
- return ((uint8_t)~MAG_PIN & MAG_MASK);
- }
-
-#endif
# List C source files here. (C dependencies are automatically generated.)
SRC = $(TARGET).c \
Descriptors.c \
- CircularBitBuffer.c \
+ Lib/CircularBitBuffer.c \
$(LUFA_PATH)/LUFA/Scheduler/Scheduler.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/DevChapter9.c \
$(LUFA_PATH)/LUFA/Drivers/USB/LowLevel/Endpoint.c \