Add svn:eol-style property to source files, so that the line endings are correctly converted to the target system's native end of line style.

This commit is contained in:
Dean Camera 2010-05-08 03:12:14 +00:00
parent e331b531c6
commit 071e02c6b6
839 changed files with 274562 additions and 274562 deletions

View file

@ -1,217 +1,217 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* USB Device Descriptors, for library use when in USB device mode. Descriptors are special
* computer-readable structures which the host requests upon device enumeration, to determine
* the device's capabilities and functions.
*/
#include "Descriptors.h"
/* On some devices, there is a factory set internal serial number which can be automatically sent to the host as
* the device's serial number when the Device Descriptor's .SerialNumStrIndex entry is set to USE_INTERNAL_SERIAL.
* This allows the host to track a device across insertions on different ports, allowing them to retain allocated
* resources like COM port numbers and drivers. On demos using this feature, give a warning on unsupported devices
* so that the user can supply their own serial number descriptor instead or remove the USE_INTERNAL_SERIAL value
* from the Device Descriptor (forcing the host to generate a serial number for each device from the VID, PID and
* port location).
*/
#if (USE_INTERNAL_SERIAL == NO_DESCRIPTOR)
#warning USE_INTERNAL_SERIAL is not available on this AVR - please manually construct a device serial descriptor.
#endif
/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
* device characteristics, including the supported USB version, control endpoint size and the
* number of device configurations. The descriptor is read out by the USB host when the enumeration
* process begins.
*/
USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
.USBSpecification = VERSION_BCD(01.10),
.Class = 0x00,
.SubClass = 0x00,
.Protocol = 0x00,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
.ProductID = 0x2045,
.ReleaseNumber = 0x0000,
.ManufacturerStrIndex = 0x01,
.ProductStrIndex = 0x02,
.SerialNumStrIndex = USE_INTERNAL_SERIAL,
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
};
/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
* of the device in one of its supported configurations, including information about any device interfaces
* and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
* a configuration so that the host may correctly communicate with the USB device.
*/
USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
.Config =
{
.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
.TotalInterfaces = 1,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = NO_DESCRIPTOR,
.ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.MS_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = 0,
.AlternateSetting = 0,
.TotalEndpoints = 2,
.Class = 0x08,
.SubClass = 0x06,
.Protocol = 0x50,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.MS_DataInEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | MASS_STORAGE_IN_EPNUM),
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = MASS_STORAGE_IO_EPSIZE,
.PollingIntervalMS = 0x00
},
.MS_DataOutEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_OUT | MASS_STORAGE_OUT_EPNUM),
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = MASS_STORAGE_IO_EPSIZE,
.PollingIntervalMS = 0x00
}
};
/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
* via the language ID table available at USB.org what languages the device supports for its string descriptors.
*/
USB_Descriptor_String_t PROGMEM LanguageString =
{
.Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
.UnicodeString = {LANGUAGE_ID_ENG}
};
/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
* form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
USB_Descriptor_String_t PROGMEM ManufacturerString =
{
.Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
.UnicodeString = L"Dean Camera"
};
/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
USB_Descriptor_String_t PROGMEM ProductString =
{
.Header = {.Size = USB_STRING_LEN(22), .Type = DTYPE_String},
.UnicodeString = L"LUFA Mass Storage Demo"
};
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
* documentation) by the application code so that the address and size of a requested descriptor can be given
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
* is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
* USB host.
*/
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
{
const uint8_t DescriptorType = (wValue >> 8);
const uint8_t DescriptorNumber = (wValue & 0xFF);
void* Address = NULL;
uint16_t Size = NO_DESCRIPTOR;
switch (DescriptorType)
{
case DTYPE_Device:
Address = (void*)&DeviceDescriptor;
Size = sizeof(USB_Descriptor_Device_t);
break;
case DTYPE_Configuration:
Address = (void*)&ConfigurationDescriptor;
Size = sizeof(USB_Descriptor_Configuration_t);
break;
case DTYPE_String:
switch (DescriptorNumber)
{
case 0x00:
Address = (void*)&LanguageString;
Size = pgm_read_byte(&LanguageString.Header.Size);
break;
case 0x01:
Address = (void*)&ManufacturerString;
Size = pgm_read_byte(&ManufacturerString.Header.Size);
break;
case 0x02:
Address = (void*)&ProductString;
Size = pgm_read_byte(&ProductString.Header.Size);
break;
}
break;
}
*DescriptorAddress = Address;
return Size;
}
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* USB Device Descriptors, for library use when in USB device mode. Descriptors are special
* computer-readable structures which the host requests upon device enumeration, to determine
* the device's capabilities and functions.
*/
#include "Descriptors.h"
/* On some devices, there is a factory set internal serial number which can be automatically sent to the host as
* the device's serial number when the Device Descriptor's .SerialNumStrIndex entry is set to USE_INTERNAL_SERIAL.
* This allows the host to track a device across insertions on different ports, allowing them to retain allocated
* resources like COM port numbers and drivers. On demos using this feature, give a warning on unsupported devices
* so that the user can supply their own serial number descriptor instead or remove the USE_INTERNAL_SERIAL value
* from the Device Descriptor (forcing the host to generate a serial number for each device from the VID, PID and
* port location).
*/
#if (USE_INTERNAL_SERIAL == NO_DESCRIPTOR)
#warning USE_INTERNAL_SERIAL is not available on this AVR - please manually construct a device serial descriptor.
#endif
/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
* device characteristics, including the supported USB version, control endpoint size and the
* number of device configurations. The descriptor is read out by the USB host when the enumeration
* process begins.
*/
USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
.USBSpecification = VERSION_BCD(01.10),
.Class = 0x00,
.SubClass = 0x00,
.Protocol = 0x00,
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
.VendorID = 0x03EB,
.ProductID = 0x2045,
.ReleaseNumber = 0x0000,
.ManufacturerStrIndex = 0x01,
.ProductStrIndex = 0x02,
.SerialNumStrIndex = USE_INTERNAL_SERIAL,
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
};
/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
* of the device in one of its supported configurations, including information about any device interfaces
* and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
* a configuration so that the host may correctly communicate with the USB device.
*/
USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
{
.Config =
{
.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
.TotalInterfaces = 1,
.ConfigurationNumber = 1,
.ConfigurationStrIndex = NO_DESCRIPTOR,
.ConfigAttributes = USB_CONFIG_ATTR_BUSPOWERED,
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
},
.MS_Interface =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
.InterfaceNumber = 0,
.AlternateSetting = 0,
.TotalEndpoints = 2,
.Class = 0x08,
.SubClass = 0x06,
.Protocol = 0x50,
.InterfaceStrIndex = NO_DESCRIPTOR
},
.MS_DataInEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_IN | MASS_STORAGE_IN_EPNUM),
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = MASS_STORAGE_IO_EPSIZE,
.PollingIntervalMS = 0x00
},
.MS_DataOutEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
.EndpointAddress = (ENDPOINT_DESCRIPTOR_DIR_OUT | MASS_STORAGE_OUT_EPNUM),
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
.EndpointSize = MASS_STORAGE_IO_EPSIZE,
.PollingIntervalMS = 0x00
}
};
/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
* via the language ID table available at USB.org what languages the device supports for its string descriptors.
*/
USB_Descriptor_String_t PROGMEM LanguageString =
{
.Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
.UnicodeString = {LANGUAGE_ID_ENG}
};
/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
* form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
USB_Descriptor_String_t PROGMEM ManufacturerString =
{
.Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
.UnicodeString = L"Dean Camera"
};
/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
USB_Descriptor_String_t PROGMEM ProductString =
{
.Header = {.Size = USB_STRING_LEN(22), .Type = DTYPE_String},
.UnicodeString = L"LUFA Mass Storage Demo"
};
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
* documentation) by the application code so that the address and size of a requested descriptor can be given
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
* is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
* USB host.
*/
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
{
const uint8_t DescriptorType = (wValue >> 8);
const uint8_t DescriptorNumber = (wValue & 0xFF);
void* Address = NULL;
uint16_t Size = NO_DESCRIPTOR;
switch (DescriptorType)
{
case DTYPE_Device:
Address = (void*)&DeviceDescriptor;
Size = sizeof(USB_Descriptor_Device_t);
break;
case DTYPE_Configuration:
Address = (void*)&ConfigurationDescriptor;
Size = sizeof(USB_Descriptor_Configuration_t);
break;
case DTYPE_String:
switch (DescriptorNumber)
{
case 0x00:
Address = (void*)&LanguageString;
Size = pgm_read_byte(&LanguageString.Header.Size);
break;
case 0x01:
Address = (void*)&ManufacturerString;
Size = pgm_read_byte(&ManufacturerString.Header.Size);
break;
case 0x02:
Address = (void*)&ProductString;
Size = pgm_read_byte(&ProductString.Header.Size);
break;
}
break;
}
*DescriptorAddress = Address;
return Size;
}

View file

@ -1,71 +1,71 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for Descriptors.c.
*/
#ifndef _DESCRIPTORS_H_
#define _DESCRIPTORS_H_
/* Includes: */
#include <LUFA/Drivers/USB/USB.h>
#include <avr/pgmspace.h>
/* Macros: */
/** Endpoint number of the Mass Storage device-to-host data IN endpoint. */
#define MASS_STORAGE_IN_EPNUM 3
/** Endpoint number of the Mass Storage host-to-device data OUT endpoint. */
#define MASS_STORAGE_OUT_EPNUM 4
/** Size in bytes of the Mass Storage data endpoints. */
#define MASS_STORAGE_IO_EPSIZE 64
/* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
* vary between devices, and which describe the device's usage to the host.
*/
typedef struct
{
USB_Descriptor_Configuration_Header_t Config;
USB_Descriptor_Interface_t MS_Interface;
USB_Descriptor_Endpoint_t MS_DataInEndpoint;
USB_Descriptor_Endpoint_t MS_DataOutEndpoint;
} USB_Descriptor_Configuration_t;
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
#endif
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for Descriptors.c.
*/
#ifndef _DESCRIPTORS_H_
#define _DESCRIPTORS_H_
/* Includes: */
#include <LUFA/Drivers/USB/USB.h>
#include <avr/pgmspace.h>
/* Macros: */
/** Endpoint number of the Mass Storage device-to-host data IN endpoint. */
#define MASS_STORAGE_IN_EPNUM 3
/** Endpoint number of the Mass Storage host-to-device data OUT endpoint. */
#define MASS_STORAGE_OUT_EPNUM 4
/** Size in bytes of the Mass Storage data endpoints. */
#define MASS_STORAGE_IO_EPSIZE 64
/* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
* vary between devices, and which describe the device's usage to the host.
*/
typedef struct
{
USB_Descriptor_Configuration_Header_t Config;
USB_Descriptor_Interface_t MS_Interface;
USB_Descriptor_Endpoint_t MS_DataInEndpoint;
USB_Descriptor_Endpoint_t MS_DataOutEndpoint;
} USB_Descriptor_Configuration_t;
/* Function Prototypes: */
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,78 +1,78 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for DataflashManager.c.
*/
#ifndef _DATAFLASH_MANAGER_H_
#define _DATAFLASH_MANAGER_H_
/* Includes: */
#include <avr/io.h>
#include "MassStorage.h"
#include "Descriptors.h"
#include <LUFA/Common/Common.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Board/Dataflash.h>
/* Preprocessor Checks: */
#if (DATAFLASH_PAGE_SIZE % 16)
#error Dataflash page size must be a multiple of 16 bytes.
#endif
/* Defines: */
/** Total number of bytes of the storage medium, comprised of one or more dataflash ICs. */
#define VIRTUAL_MEMORY_BYTES ((uint32_t)DATAFLASH_PAGES * DATAFLASH_PAGE_SIZE * DATAFLASH_TOTALCHIPS)
/** Block size of the device. This is kept at 512 to remain compatible with the OS despite the underlying
* storage media (Dataflash) using a different native block size. Do not change this value.
*/
#define VIRTUAL_MEMORY_BLOCK_SIZE 512
/** Total number of blocks of the virtual memory for reporting to the host as the device's total capacity. Do not
* change this value; change VIRTUAL_MEMORY_BYTES instead to alter the media size.
*/
#define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)
/* Function Prototypes: */
void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);
void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);
void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,
uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,
uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
void DataflashManager_ResetDataflashProtections(void);
bool DataflashManager_CheckDataflashOperation(void);
#endif
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for DataflashManager.c.
*/
#ifndef _DATAFLASH_MANAGER_H_
#define _DATAFLASH_MANAGER_H_
/* Includes: */
#include <avr/io.h>
#include "MassStorage.h"
#include "Descriptors.h"
#include <LUFA/Common/Common.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Board/Dataflash.h>
/* Preprocessor Checks: */
#if (DATAFLASH_PAGE_SIZE % 16)
#error Dataflash page size must be a multiple of 16 bytes.
#endif
/* Defines: */
/** Total number of bytes of the storage medium, comprised of one or more dataflash ICs. */
#define VIRTUAL_MEMORY_BYTES ((uint32_t)DATAFLASH_PAGES * DATAFLASH_PAGE_SIZE * DATAFLASH_TOTALCHIPS)
/** Block size of the device. This is kept at 512 to remain compatible with the OS despite the underlying
* storage media (Dataflash) using a different native block size. Do not change this value.
*/
#define VIRTUAL_MEMORY_BLOCK_SIZE 512
/** Total number of blocks of the virtual memory for reporting to the host as the device's total capacity. Do not
* change this value; change VIRTUAL_MEMORY_BYTES instead to alter the media size.
*/
#define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)
/* Function Prototypes: */
void DataflashManager_WriteBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);
void DataflashManager_ReadBlocks(const uint32_t BlockAddress, uint16_t TotalBlocks);
void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,
uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks,
uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
void DataflashManager_ResetDataflashProtections(void);
bool DataflashManager_CheckDataflashOperation(void);
#endif

View file

@ -1,293 +1,293 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* SCSI command processing routines, for SCSI commands issued by the host. Mass Storage
* devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,
* which wrap around standard SCSI device commands for controlling the actual storage medium.
*/
#define INCLUDE_FROM_SCSI_C
#include "SCSI.h"
/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's
* features and capabilities.
*/
SCSI_Inquiry_Response_t InquiryData =
{
.DeviceType = DEVICE_TYPE_BLOCK,
.PeripheralQualifier = 0,
.Removable = true,
.Version = 0,
.ResponseDataFormat = 2,
.NormACA = false,
.TrmTsk = false,
.AERC = false,
.AdditionalLength = 0x1F,
.SoftReset = false,
.CmdQue = false,
.Linked = false,
.Sync = false,
.WideBus16Bit = false,
.WideBus32Bit = false,
.RelAddr = false,
.VendorID = "LUFA",
.ProductID = "Dataflash Disk",
.RevisionID = {'0','.','0','0'},
};
/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE
* command is issued. This gives information on exactly why the last command failed to complete.
*/
SCSI_Request_Sense_Response_t SenseData =
{
.ResponseCode = 0x70,
.AdditionalLength = 0x0A,
};
/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches
* to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns
* a command failure due to a ILLEGAL REQUEST.
*
* \return Boolean true if the command completed successfully, false otherwise
*/
bool SCSI_DecodeSCSICommand(void)
{
/* Set initial sense data, before the requested command is processed */
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
SCSI_ASENSEQ_NO_QUALIFIER);
/* Run the appropriate SCSI command hander function based on the passed command */
switch (CommandBlock.SCSICommandData[0])
{
case SCSI_CMD_INQUIRY:
SCSI_Command_Inquiry();
break;
case SCSI_CMD_REQUEST_SENSE:
SCSI_Command_Request_Sense();
break;
case SCSI_CMD_READ_CAPACITY_10:
SCSI_Command_Read_Capacity_10();
break;
case SCSI_CMD_SEND_DIAGNOSTIC:
SCSI_Command_Send_Diagnostic();
break;
case SCSI_CMD_WRITE_10:
SCSI_Command_ReadWrite_10(DATA_WRITE);
break;
case SCSI_CMD_READ_10:
SCSI_Command_ReadWrite_10(DATA_READ);
break;
case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10:
/* These commands should just succeed, no handling required */
CommandBlock.DataTransferLength = 0;
break;
default:
/* Update the SENSE key to reflect the invalid command */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_INVALID_COMMAND,
SCSI_ASENSEQ_NO_QUALIFIER);
break;
}
return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD);
}
/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
* and capabilities to the host.
*/
static void SCSI_Command_Inquiry(void)
{
uint16_t AllocationLength = (((uint16_t)CommandBlock.SCSICommandData[3] << 8) |
CommandBlock.SCSICommandData[4]);
uint16_t BytesTransferred = (AllocationLength < sizeof(InquiryData))? AllocationLength :
sizeof(InquiryData);
/* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */
if ((CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
CommandBlock.SCSICommandData[2])
{
/* Optional but unsupported bits set - update the SENSE key and fail the request */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
SCSI_ASENSEQ_NO_QUALIFIER);
return;
}
/* Write the INQUIRY data to the endpoint */
Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);
uint8_t PadBytes[AllocationLength - BytesTransferred];
/* Pad out remaining bytes with 0x00 */
Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
CommandBlock.DataTransferLength -= BytesTransferred;
}
/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
* including the error code and additional error information so that the host can determine why a command failed to complete.
*/
static void SCSI_Command_Request_Sense(void)
{
uint8_t AllocationLength = CommandBlock.SCSICommandData[4];
uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
/* Send the SENSE data - this indicates to the host the status of the last command */
Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);
uint8_t PadBytes[AllocationLength - BytesTransferred];
/* Pad out remaining bytes with 0x00 */
Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
CommandBlock.DataTransferLength -= BytesTransferred;
}
/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
* on the selected Logical Unit (drive), as a number of OS-sized blocks.
*/
static void SCSI_Command_Read_Capacity_10(void)
{
/* Send the total number of logical blocks in the current LUN */
Endpoint_Write_DWord_BE(LUN_MEDIA_BLOCKS - 1);
/* Send the logical block size of the device (must be 512 bytes) */
Endpoint_Write_DWord_BE(VIRTUAL_MEMORY_BLOCK_SIZE);
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return;
/* Send the endpoint data packet to the host */
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
CommandBlock.DataTransferLength -= 8;
}
/** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
* board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is
* supported.
*/
static void SCSI_Command_Send_Diagnostic(void)
{
/* Check to see if the SELF TEST bit is not set */
if (!(CommandBlock.SCSICommandData[1] & (1 << 2)))
{
/* Only self-test supported - update SENSE key and fail the command */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
SCSI_ASENSEQ_NO_QUALIFIER);
return;
}
/* Check to see if all attached Dataflash ICs are functional */
if (!(DataflashManager_CheckDataflashOperation()))
{
/* Update SENSE key with a hardware error condition and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
SCSI_ASENSEQ_NO_QUALIFIER);
return;
}
/* Succeed the command and update the bytes transferred counter */
CommandBlock.DataTransferLength = 0;
}
/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
* and total number of blocks to process, then calls the appropriate low-level dataflash routine to handle the actual
* reading and writing of the data.
*
* \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
*/
static void SCSI_Command_ReadWrite_10(const bool IsDataRead)
{
uint32_t BlockAddress;
uint16_t TotalBlocks;
/* Load in the 32-bit block address (SCSI uses big-endian, so have to do it byte-by-byte) */
((uint8_t*)&BlockAddress)[3] = CommandBlock.SCSICommandData[2];
((uint8_t*)&BlockAddress)[2] = CommandBlock.SCSICommandData[3];
((uint8_t*)&BlockAddress)[1] = CommandBlock.SCSICommandData[4];
((uint8_t*)&BlockAddress)[0] = CommandBlock.SCSICommandData[5];
/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to do it byte-by-byte) */
((uint8_t*)&TotalBlocks)[1] = CommandBlock.SCSICommandData[7];
((uint8_t*)&TotalBlocks)[0] = CommandBlock.SCSICommandData[8];
/* Check if the block address is outside the maximum allowable value for the LUN */
if (BlockAddress >= LUN_MEDIA_BLOCKS)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
SCSI_ASENSEQ_NO_QUALIFIER);
return;
}
#if (TOTAL_LUNS > 1)
/* Adjust the given block address to the real media address based on the selected LUN */
BlockAddress += ((uint32_t)CommandBlock.LUN * LUN_MEDIA_BLOCKS);
#endif
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
if (IsDataRead == DATA_READ)
DataflashManager_ReadBlocks(BlockAddress, TotalBlocks);
else
DataflashManager_WriteBlocks(BlockAddress, TotalBlocks);
/* Update the bytes transferred counter and succeed the command */
CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
}
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* SCSI command processing routines, for SCSI commands issued by the host. Mass Storage
* devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,
* which wrap around standard SCSI device commands for controlling the actual storage medium.
*/
#define INCLUDE_FROM_SCSI_C
#include "SCSI.h"
/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's
* features and capabilities.
*/
SCSI_Inquiry_Response_t InquiryData =
{
.DeviceType = DEVICE_TYPE_BLOCK,
.PeripheralQualifier = 0,
.Removable = true,
.Version = 0,
.ResponseDataFormat = 2,
.NormACA = false,
.TrmTsk = false,
.AERC = false,
.AdditionalLength = 0x1F,
.SoftReset = false,
.CmdQue = false,
.Linked = false,
.Sync = false,
.WideBus16Bit = false,
.WideBus32Bit = false,
.RelAddr = false,
.VendorID = "LUFA",
.ProductID = "Dataflash Disk",
.RevisionID = {'0','.','0','0'},
};
/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE
* command is issued. This gives information on exactly why the last command failed to complete.
*/
SCSI_Request_Sense_Response_t SenseData =
{
.ResponseCode = 0x70,
.AdditionalLength = 0x0A,
};
/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches
* to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns
* a command failure due to a ILLEGAL REQUEST.
*
* \return Boolean true if the command completed successfully, false otherwise
*/
bool SCSI_DecodeSCSICommand(void)
{
/* Set initial sense data, before the requested command is processed */
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
SCSI_ASENSEQ_NO_QUALIFIER);
/* Run the appropriate SCSI command hander function based on the passed command */
switch (CommandBlock.SCSICommandData[0])
{
case SCSI_CMD_INQUIRY:
SCSI_Command_Inquiry();
break;
case SCSI_CMD_REQUEST_SENSE:
SCSI_Command_Request_Sense();
break;
case SCSI_CMD_READ_CAPACITY_10:
SCSI_Command_Read_Capacity_10();
break;
case SCSI_CMD_SEND_DIAGNOSTIC:
SCSI_Command_Send_Diagnostic();
break;
case SCSI_CMD_WRITE_10:
SCSI_Command_ReadWrite_10(DATA_WRITE);
break;
case SCSI_CMD_READ_10:
SCSI_Command_ReadWrite_10(DATA_READ);
break;
case SCSI_CMD_TEST_UNIT_READY:
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
case SCSI_CMD_VERIFY_10:
/* These commands should just succeed, no handling required */
CommandBlock.DataTransferLength = 0;
break;
default:
/* Update the SENSE key to reflect the invalid command */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_INVALID_COMMAND,
SCSI_ASENSEQ_NO_QUALIFIER);
break;
}
return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD);
}
/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
* and capabilities to the host.
*/
static void SCSI_Command_Inquiry(void)
{
uint16_t AllocationLength = (((uint16_t)CommandBlock.SCSICommandData[3] << 8) |
CommandBlock.SCSICommandData[4]);
uint16_t BytesTransferred = (AllocationLength < sizeof(InquiryData))? AllocationLength :
sizeof(InquiryData);
/* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */
if ((CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
CommandBlock.SCSICommandData[2])
{
/* Optional but unsupported bits set - update the SENSE key and fail the request */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
SCSI_ASENSEQ_NO_QUALIFIER);
return;
}
/* Write the INQUIRY data to the endpoint */
Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);
uint8_t PadBytes[AllocationLength - BytesTransferred];
/* Pad out remaining bytes with 0x00 */
Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
CommandBlock.DataTransferLength -= BytesTransferred;
}
/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
* including the error code and additional error information so that the host can determine why a command failed to complete.
*/
static void SCSI_Command_Request_Sense(void)
{
uint8_t AllocationLength = CommandBlock.SCSICommandData[4];
uint8_t BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
/* Send the SENSE data - this indicates to the host the status of the last command */
Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, StreamCallback_AbortOnMassStoreReset);
uint8_t PadBytes[AllocationLength - BytesTransferred];
/* Pad out remaining bytes with 0x00 */
Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), StreamCallback_AbortOnMassStoreReset);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
CommandBlock.DataTransferLength -= BytesTransferred;
}
/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
* on the selected Logical Unit (drive), as a number of OS-sized blocks.
*/
static void SCSI_Command_Read_Capacity_10(void)
{
/* Send the total number of logical blocks in the current LUN */
Endpoint_Write_DWord_BE(LUN_MEDIA_BLOCKS - 1);
/* Send the logical block size of the device (must be 512 bytes) */
Endpoint_Write_DWord_BE(VIRTUAL_MEMORY_BLOCK_SIZE);
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return;
/* Send the endpoint data packet to the host */
Endpoint_ClearIN();
/* Succeed the command and update the bytes transferred counter */
CommandBlock.DataTransferLength -= 8;
}
/** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
* board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is
* supported.
*/
static void SCSI_Command_Send_Diagnostic(void)
{
/* Check to see if the SELF TEST bit is not set */
if (!(CommandBlock.SCSICommandData[1] & (1 << 2)))
{
/* Only self-test supported - update SENSE key and fail the command */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
SCSI_ASENSEQ_NO_QUALIFIER);
return;
}
/* Check to see if all attached Dataflash ICs are functional */
if (!(DataflashManager_CheckDataflashOperation()))
{
/* Update SENSE key with a hardware error condition and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
SCSI_ASENSEQ_NO_QUALIFIER);
return;
}
/* Succeed the command and update the bytes transferred counter */
CommandBlock.DataTransferLength = 0;
}
/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
* and total number of blocks to process, then calls the appropriate low-level dataflash routine to handle the actual
* reading and writing of the data.
*
* \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
*/
static void SCSI_Command_ReadWrite_10(const bool IsDataRead)
{
uint32_t BlockAddress;
uint16_t TotalBlocks;
/* Load in the 32-bit block address (SCSI uses big-endian, so have to do it byte-by-byte) */
((uint8_t*)&BlockAddress)[3] = CommandBlock.SCSICommandData[2];
((uint8_t*)&BlockAddress)[2] = CommandBlock.SCSICommandData[3];
((uint8_t*)&BlockAddress)[1] = CommandBlock.SCSICommandData[4];
((uint8_t*)&BlockAddress)[0] = CommandBlock.SCSICommandData[5];
/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to do it byte-by-byte) */
((uint8_t*)&TotalBlocks)[1] = CommandBlock.SCSICommandData[7];
((uint8_t*)&TotalBlocks)[0] = CommandBlock.SCSICommandData[8];
/* Check if the block address is outside the maximum allowable value for the LUN */
if (BlockAddress >= LUN_MEDIA_BLOCKS)
{
/* Block address is invalid, update SENSE key and return command fail */
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
SCSI_ASENSEQ_NO_QUALIFIER);
return;
}
#if (TOTAL_LUNS > 1)
/* Adjust the given block address to the real media address based on the selected LUN */
BlockAddress += ((uint32_t)CommandBlock.LUN * LUN_MEDIA_BLOCKS);
#endif
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
if (IsDataRead == DATA_READ)
DataflashManager_ReadBlocks(BlockAddress, TotalBlocks);
else
DataflashManager_WriteBlocks(BlockAddress, TotalBlocks);
/* Update the bytes transferred counter and succeed the command */
CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
}

View file

@ -1,149 +1,149 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for SCSI.c.
*/
#ifndef _SCSI_H_
#define _SCSI_H_
/* Includes: */
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <LUFA/Common/Common.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include "MassStorage.h"
#include "Descriptors.h"
#include "DataflashManager.h"
#include "SCSI_Codes.h"
/* Macros: */
/** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This
* is for convenience, as it allows for all three sense values (returned upon request to the host to give information about
* the last command failure) in a quick and easy manner.
*
* \param[in] key New SCSI sense key to set the sense code to
* \param[in] acode New SCSI additional sense key to set the additional sense code to
* \param[in] aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to
*/
#define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = (key); \
SenseData.AdditionalSenseCode = (acode); \
SenseData.AdditionalSenseQualifier = (aqual); }MACROE
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
#define DATA_READ true
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */
#define DATA_WRITE false
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */
#define DEVICE_TYPE_BLOCK 0x00
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a CD-ROM device. */
#define DEVICE_TYPE_CDROM 0x05
/* Type Defines: */
/** Type define for a SCSI response structure to a SCSI INQUIRY command. For details of the
* structure contents, refer to the SCSI specifications.
*/
typedef struct
{
unsigned char DeviceType : 5;
unsigned char PeripheralQualifier : 3;
unsigned char _RESERVED1 : 7;
unsigned char Removable : 1;
uint8_t Version;
unsigned char ResponseDataFormat : 4;
unsigned char _RESERVED2 : 1;
unsigned char NormACA : 1;
unsigned char TrmTsk : 1;
unsigned char AERC : 1;
uint8_t AdditionalLength;
uint8_t _RESERVED3[2];
unsigned char SoftReset : 1;
unsigned char CmdQue : 1;
unsigned char _RESERVED4 : 1;
unsigned char Linked : 1;
unsigned char Sync : 1;
unsigned char WideBus16Bit : 1;
unsigned char WideBus32Bit : 1;
unsigned char RelAddr : 1;
uint8_t VendorID[8];
uint8_t ProductID[16];
uint8_t RevisionID[4];
} SCSI_Inquiry_Response_t;
/** Type define for a SCSI sense structure to a SCSI REQUEST SENSE command. For details of the
* structure contents, refer to the SCSI specifications.
*/
typedef struct
{
uint8_t ResponseCode;
uint8_t SegmentNumber;
unsigned char SenseKey : 4;
unsigned char _RESERVED1 : 1;
unsigned char ILI : 1;
unsigned char EOM : 1;
unsigned char FileMark : 1;
uint8_t Information[4];
uint8_t AdditionalLength;
uint8_t CmdSpecificInformation[4];
uint8_t AdditionalSenseCode;
uint8_t AdditionalSenseQualifier;
uint8_t FieldReplaceableUnitCode;
uint8_t SenseKeySpecific[3];
} SCSI_Request_Sense_Response_t;
/* Function Prototypes: */
bool SCSI_DecodeSCSICommand(void);
#if defined(INCLUDE_FROM_SCSI_C)
static void SCSI_Command_Inquiry(void);
static void SCSI_Command_Request_Sense(void);
static void SCSI_Command_Read_Capacity_10(void);
static void SCSI_Command_Send_Diagnostic(void);
static void SCSI_Command_ReadWrite_10(const bool IsDataRead);
#endif
#endif
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for SCSI.c.
*/
#ifndef _SCSI_H_
#define _SCSI_H_
/* Includes: */
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <LUFA/Common/Common.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include "MassStorage.h"
#include "Descriptors.h"
#include "DataflashManager.h"
#include "SCSI_Codes.h"
/* Macros: */
/** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This
* is for convenience, as it allows for all three sense values (returned upon request to the host to give information about
* the last command failure) in a quick and easy manner.
*
* \param[in] key New SCSI sense key to set the sense code to
* \param[in] acode New SCSI additional sense key to set the additional sense code to
* \param[in] aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to
*/
#define SCSI_SET_SENSE(key, acode, aqual) MACROS{ SenseData.SenseKey = (key); \
SenseData.AdditionalSenseCode = (acode); \
SenseData.AdditionalSenseQualifier = (aqual); }MACROE
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
#define DATA_READ true
/** Macro for the SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */
#define DATA_WRITE false
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */
#define DEVICE_TYPE_BLOCK 0x00
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a CD-ROM device. */
#define DEVICE_TYPE_CDROM 0x05
/* Type Defines: */
/** Type define for a SCSI response structure to a SCSI INQUIRY command. For details of the
* structure contents, refer to the SCSI specifications.
*/
typedef struct
{
unsigned char DeviceType : 5;
unsigned char PeripheralQualifier : 3;
unsigned char _RESERVED1 : 7;
unsigned char Removable : 1;
uint8_t Version;
unsigned char ResponseDataFormat : 4;
unsigned char _RESERVED2 : 1;
unsigned char NormACA : 1;
unsigned char TrmTsk : 1;
unsigned char AERC : 1;
uint8_t AdditionalLength;
uint8_t _RESERVED3[2];
unsigned char SoftReset : 1;
unsigned char CmdQue : 1;
unsigned char _RESERVED4 : 1;
unsigned char Linked : 1;
unsigned char Sync : 1;
unsigned char WideBus16Bit : 1;
unsigned char WideBus32Bit : 1;
unsigned char RelAddr : 1;
uint8_t VendorID[8];
uint8_t ProductID[16];
uint8_t RevisionID[4];
} SCSI_Inquiry_Response_t;
/** Type define for a SCSI sense structure to a SCSI REQUEST SENSE command. For details of the
* structure contents, refer to the SCSI specifications.
*/
typedef struct
{
uint8_t ResponseCode;
uint8_t SegmentNumber;
unsigned char SenseKey : 4;
unsigned char _RESERVED1 : 1;
unsigned char ILI : 1;
unsigned char EOM : 1;
unsigned char FileMark : 1;
uint8_t Information[4];
uint8_t AdditionalLength;
uint8_t CmdSpecificInformation[4];
uint8_t AdditionalSenseCode;
uint8_t AdditionalSenseQualifier;
uint8_t FieldReplaceableUnitCode;
uint8_t SenseKeySpecific[3];
} SCSI_Request_Sense_Response_t;
/* Function Prototypes: */
bool SCSI_DecodeSCSICommand(void);
#if defined(INCLUDE_FROM_SCSI_C)
static void SCSI_Command_Inquiry(void);
static void SCSI_Command_Request_Sense(void);
static void SCSI_Command_Read_Capacity_10(void);
static void SCSI_Command_Send_Diagnostic(void);
static void SCSI_Command_ReadWrite_10(const bool IsDataRead);
#endif
#endif

View file

@ -1,85 +1,85 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header containing macros for possible SCSI commands and SENSE data. Refer to
* the SCSI standard documentation for more information on each SCSI command and
* the SENSE data.
*/
#ifndef _SCSI_CODES_H_
#define _SCSI_CODES_H_
/* Macros: */
#define SCSI_CMD_INQUIRY 0x12
#define SCSI_CMD_REQUEST_SENSE 0x03
#define SCSI_CMD_TEST_UNIT_READY 0x00
#define SCSI_CMD_READ_CAPACITY_10 0x25
#define SCSI_CMD_SEND_DIAGNOSTIC 0x1D
#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
#define SCSI_CMD_WRITE_10 0x2A
#define SCSI_CMD_READ_10 0x28
#define SCSI_CMD_WRITE_6 0x0A
#define SCSI_CMD_READ_6 0x08
#define SCSI_CMD_VERIFY_10 0x2F
#define SCSI_CMD_MODE_SENSE_6 0x1A
#define SCSI_CMD_MODE_SENSE_10 0x5A
#define SCSI_SENSE_KEY_GOOD 0x00
#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
#define SCSI_SENSE_KEY_NOT_READY 0x02
#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
#define SCSI_SENSE_KEY_DATA_PROTECT 0x07
#define SCSI_SENSE_KEY_BLANK_CHECK 0x08
#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
#define SCSI_SENSE_KEY_COPY_ABORTED 0x0A
#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
#define SCSI_SENSE_KEY_MISCOMPARE 0x0E
#define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00
#define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04
#define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24
#define SCSI_ASENSE_WRITE_PROTECTED 0x27
#define SCSI_ASENSE_FORMAT_ERROR 0x31
#define SCSI_ASENSE_INVALID_COMMAND 0x20
#define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21
#define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A
#define SCSI_ASENSEQ_NO_QUALIFIER 0x00
#define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01
#define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07
#endif
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header containing macros for possible SCSI commands and SENSE data. Refer to
* the SCSI standard documentation for more information on each SCSI command and
* the SENSE data.
*/
#ifndef _SCSI_CODES_H_
#define _SCSI_CODES_H_
/* Macros: */
#define SCSI_CMD_INQUIRY 0x12
#define SCSI_CMD_REQUEST_SENSE 0x03
#define SCSI_CMD_TEST_UNIT_READY 0x00
#define SCSI_CMD_READ_CAPACITY_10 0x25
#define SCSI_CMD_SEND_DIAGNOSTIC 0x1D
#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
#define SCSI_CMD_WRITE_10 0x2A
#define SCSI_CMD_READ_10 0x28
#define SCSI_CMD_WRITE_6 0x0A
#define SCSI_CMD_READ_6 0x08
#define SCSI_CMD_VERIFY_10 0x2F
#define SCSI_CMD_MODE_SENSE_6 0x1A
#define SCSI_CMD_MODE_SENSE_10 0x5A
#define SCSI_SENSE_KEY_GOOD 0x00
#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
#define SCSI_SENSE_KEY_NOT_READY 0x02
#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
#define SCSI_SENSE_KEY_DATA_PROTECT 0x07
#define SCSI_SENSE_KEY_BLANK_CHECK 0x08
#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
#define SCSI_SENSE_KEY_COPY_ABORTED 0x0A
#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
#define SCSI_SENSE_KEY_MISCOMPARE 0x0E
#define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00
#define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04
#define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24
#define SCSI_ASENSE_WRITE_PROTECTED 0x27
#define SCSI_ASENSE_FORMAT_ERROR 0x31
#define SCSI_ASENSE_INVALID_COMMAND 0x20
#define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21
#define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A
#define SCSI_ASENSEQ_NO_QUALIFIER 0x00
#define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01
#define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02
#define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07
#endif

View file

@ -1,336 +1,336 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Main source file for the Mass Storage demo. This file contains the main tasks of the demo and
* is responsible for the initial application hardware configuration.
*/
#define INCLUDE_FROM_MASSSTORAGE_C
#include "MassStorage.h"
/** Structure to hold the latest Command Block Wrapper issued by the host, containing a SCSI command to execute. */
CommandBlockWrapper_t CommandBlock;
/** Structure to hold the latest Command Status Wrapper to return to the host, containing the status of the last issued command. */
CommandStatusWrapper_t CommandStatus = { .Signature = CSW_SIGNATURE };
/** Flag to asynchronously abort any in-progress data transfers upon the reception of a mass storage reset command. */
volatile bool IsMassStoreReset = false;
/** Main program entry point. This routine configures the hardware required by the application, then
* enters a loop to run the application tasks in sequence.
*/
int main(void)
{
SetupHardware();
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
sei();
for (;;)
{
MassStorage_Task();
USB_USBTask();
}
}
/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Disable clock division */
clock_prescale_set(clock_div_1);
/* Hardware Initialization */
LEDs_Init();
SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
Dataflash_Init();
USB_Init();
/* Clear Dataflash sector protections, if enabled */
DataflashManager_ResetDataflashProtections();
}
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Device_Connect(void)
{
/* Indicate USB enumerating */
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
/* Reset the MSReset flag upon connection */
IsMassStoreReset = false;
}
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
* the status LEDs and stops the Mass Storage management task.
*/
void EVENT_USB_Device_Disconnect(void)
{
/* Indicate USB not ready */
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
* of the USB device after enumeration - the device endpoints are configured and the Mass Storage management task started.
*/
void EVENT_USB_Device_ConfigurationChanged(void)
{
/* Indicate USB connected and ready */
LEDs_SetAllLEDs(LEDMASK_USB_READY);
/* Setup Mass Storage In and Out Endpoints */
if (!(Endpoint_ConfigureEndpoint(MASS_STORAGE_IN_EPNUM, EP_TYPE_BULK,
ENDPOINT_DIR_IN, MASS_STORAGE_IO_EPSIZE,
ENDPOINT_BANK_SINGLE)))
{
LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
if (!(Endpoint_ConfigureEndpoint(MASS_STORAGE_OUT_EPNUM, EP_TYPE_BULK,
ENDPOINT_DIR_OUT, MASS_STORAGE_IO_EPSIZE,
ENDPOINT_BANK_SINGLE)))
{
LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
}
/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
* control requests that are not handled internally by the USB library (including the Mass Storage class-specific
* requests) so that they can be handled appropriately for the application.
*/
void EVENT_USB_Device_UnhandledControlRequest(void)
{
/* Process UFI specific control requests */
switch (USB_ControlRequest.bRequest)
{
case REQ_MassStorageReset:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
/* Indicate that the current transfer should be aborted */
IsMassStoreReset = true;
Endpoint_ClearStatusStage();
}
break;
case REQ_GetMaxLUN:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
/* Indicate to the host the number of supported LUNs (virtual disks) on the device */
Endpoint_Write_Byte(TOTAL_LUNS - 1);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
break;
}
}
/** Task to manage the Mass Storage interface, reading in Command Block Wrappers from the host, processing the SCSI commands they
* contain, and returning Command Status Wrappers back to the host to indicate the success or failure of the last issued command.
*/
void MassStorage_Task(void)
{
/* Device must be connected and configured for the task to run */
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
/* Select the Data Out Endpoint */
Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
/* Check to see if a command from the host has been issued */
if (Endpoint_IsReadWriteAllowed())
{
/* Indicate busy */
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
/* Process sent command block from the host */
if (ReadInCommandBlock())
{
/* Check direction of command, select Data IN endpoint if data is from the device */
if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)
Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
/* Decode the received SCSI command, set returned status code */
CommandStatus.Status = SCSI_DecodeSCSICommand() ? Command_Pass : Command_Fail;
/* Load in the CBW tag into the CSW to link them together */
CommandStatus.Tag = CommandBlock.Tag;
/* Load in the data residue counter into the CSW */
CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength;
/* Stall the selected data pipe if command failed (if data is still to be transferred) */
if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue))
Endpoint_StallTransaction();
/* Return command status block to the host */
ReturnCommandStatus();
/* Indicate ready */
LEDs_SetAllLEDs(LEDMASK_USB_READY);
}
else
{
/* Indicate error reading in the command block from the host */
LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
}
/* Check if a Mass Storage Reset occurred */
if (IsMassStoreReset)
{
/* Reset the data endpoint banks */
Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM);
Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM);
Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
Endpoint_ClearStall();
Endpoint_ResetDataToggle();
Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
Endpoint_ClearStall();
Endpoint_ResetDataToggle();
/* Clear the abort transfer flag */
IsMassStoreReset = false;
}
}
/** Function to read in a command block from the host, via the bulk data OUT endpoint. This function reads in the next command block
* if one has been issued, and performs validation to ensure that the block command is valid.
*
* \return Boolean true if a valid command block has been read in from the endpoint, false otherwise
*/
static bool ReadInCommandBlock(void)
{
/* Select the Data Out endpoint */
Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
/* Read in command block header */
Endpoint_Read_Stream_LE(&CommandBlock, (sizeof(CommandBlock) - sizeof(CommandBlock.SCSICommandData)),
StreamCallback_AbortOnMassStoreReset);
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return false;
/* Verify the command block - abort if invalid */
if ((CommandBlock.Signature != CBW_SIGNATURE) ||
(CommandBlock.LUN >= TOTAL_LUNS) ||
(CommandBlock.Flags & 0x1F) ||
(CommandBlock.SCSICommandLength == 0) ||
(CommandBlock.SCSICommandLength > MAX_SCSI_COMMAND_LENGTH))
{
/* Stall both data pipes until reset by host */
Endpoint_StallTransaction();
Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
Endpoint_StallTransaction();
return false;
}
/* Read in command block command data */
Endpoint_Read_Stream_LE(&CommandBlock.SCSICommandData,
CommandBlock.SCSICommandLength,
StreamCallback_AbortOnMassStoreReset);
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return false;
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearOUT();
return true;
}
/** Returns the filled Command Status Wrapper back to the host via the bulk data IN endpoint, waiting for the host to clear any
* stalled data endpoints as needed.
*/
static void ReturnCommandStatus(void)
{
/* Select the Data Out endpoint */
Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
/* While data pipe is stalled, wait until the host issues a control request to clear the stall */
while (Endpoint_IsStalled())
{
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return;
}
/* Select the Data In endpoint */
Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
/* While data pipe is stalled, wait until the host issues a control request to clear the stall */
while (Endpoint_IsStalled())
{
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return;
}
/* Write the CSW to the endpoint */
Endpoint_Write_Stream_LE(&CommandStatus, sizeof(CommandStatus),
StreamCallback_AbortOnMassStoreReset);
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return;
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
}
/** Stream callback function for the Endpoint stream read and write functions. This callback will abort the current stream transfer
* if a Mass Storage Reset request has been issued to the control endpoint.
*/
uint8_t StreamCallback_AbortOnMassStoreReset(void)
{
/* Abort if a Mass Storage reset command was received */
if (IsMassStoreReset)
return STREAMCALLBACK_Abort;
/* Continue with the current stream operation */
return STREAMCALLBACK_Continue;
}
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Main source file for the Mass Storage demo. This file contains the main tasks of the demo and
* is responsible for the initial application hardware configuration.
*/
#define INCLUDE_FROM_MASSSTORAGE_C
#include "MassStorage.h"
/** Structure to hold the latest Command Block Wrapper issued by the host, containing a SCSI command to execute. */
CommandBlockWrapper_t CommandBlock;
/** Structure to hold the latest Command Status Wrapper to return to the host, containing the status of the last issued command. */
CommandStatusWrapper_t CommandStatus = { .Signature = CSW_SIGNATURE };
/** Flag to asynchronously abort any in-progress data transfers upon the reception of a mass storage reset command. */
volatile bool IsMassStoreReset = false;
/** Main program entry point. This routine configures the hardware required by the application, then
* enters a loop to run the application tasks in sequence.
*/
int main(void)
{
SetupHardware();
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
sei();
for (;;)
{
MassStorage_Task();
USB_USBTask();
}
}
/** Configures the board hardware and chip peripherals for the demo's functionality. */
void SetupHardware(void)
{
/* Disable watchdog if enabled by bootloader/fuses */
MCUSR &= ~(1 << WDRF);
wdt_disable();
/* Disable clock division */
clock_prescale_set(clock_div_1);
/* Hardware Initialization */
LEDs_Init();
SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
Dataflash_Init();
USB_Init();
/* Clear Dataflash sector protections, if enabled */
DataflashManager_ResetDataflashProtections();
}
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
void EVENT_USB_Device_Connect(void)
{
/* Indicate USB enumerating */
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
/* Reset the MSReset flag upon connection */
IsMassStoreReset = false;
}
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
* the status LEDs and stops the Mass Storage management task.
*/
void EVENT_USB_Device_Disconnect(void)
{
/* Indicate USB not ready */
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
}
/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
* of the USB device after enumeration - the device endpoints are configured and the Mass Storage management task started.
*/
void EVENT_USB_Device_ConfigurationChanged(void)
{
/* Indicate USB connected and ready */
LEDs_SetAllLEDs(LEDMASK_USB_READY);
/* Setup Mass Storage In and Out Endpoints */
if (!(Endpoint_ConfigureEndpoint(MASS_STORAGE_IN_EPNUM, EP_TYPE_BULK,
ENDPOINT_DIR_IN, MASS_STORAGE_IO_EPSIZE,
ENDPOINT_BANK_SINGLE)))
{
LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
if (!(Endpoint_ConfigureEndpoint(MASS_STORAGE_OUT_EPNUM, EP_TYPE_BULK,
ENDPOINT_DIR_OUT, MASS_STORAGE_IO_EPSIZE,
ENDPOINT_BANK_SINGLE)))
{
LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
}
/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
* control requests that are not handled internally by the USB library (including the Mass Storage class-specific
* requests) so that they can be handled appropriately for the application.
*/
void EVENT_USB_Device_UnhandledControlRequest(void)
{
/* Process UFI specific control requests */
switch (USB_ControlRequest.bRequest)
{
case REQ_MassStorageReset:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
/* Indicate that the current transfer should be aborted */
IsMassStoreReset = true;
Endpoint_ClearStatusStage();
}
break;
case REQ_GetMaxLUN:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
/* Indicate to the host the number of supported LUNs (virtual disks) on the device */
Endpoint_Write_Byte(TOTAL_LUNS - 1);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
break;
}
}
/** Task to manage the Mass Storage interface, reading in Command Block Wrappers from the host, processing the SCSI commands they
* contain, and returning Command Status Wrappers back to the host to indicate the success or failure of the last issued command.
*/
void MassStorage_Task(void)
{
/* Device must be connected and configured for the task to run */
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
/* Select the Data Out Endpoint */
Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
/* Check to see if a command from the host has been issued */
if (Endpoint_IsReadWriteAllowed())
{
/* Indicate busy */
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
/* Process sent command block from the host */
if (ReadInCommandBlock())
{
/* Check direction of command, select Data IN endpoint if data is from the device */
if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)
Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
/* Decode the received SCSI command, set returned status code */
CommandStatus.Status = SCSI_DecodeSCSICommand() ? Command_Pass : Command_Fail;
/* Load in the CBW tag into the CSW to link them together */
CommandStatus.Tag = CommandBlock.Tag;
/* Load in the data residue counter into the CSW */
CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength;
/* Stall the selected data pipe if command failed (if data is still to be transferred) */
if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue))
Endpoint_StallTransaction();
/* Return command status block to the host */
ReturnCommandStatus();
/* Indicate ready */
LEDs_SetAllLEDs(LEDMASK_USB_READY);
}
else
{
/* Indicate error reading in the command block from the host */
LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
}
/* Check if a Mass Storage Reset occurred */
if (IsMassStoreReset)
{
/* Reset the data endpoint banks */
Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM);
Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM);
Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
Endpoint_ClearStall();
Endpoint_ResetDataToggle();
Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
Endpoint_ClearStall();
Endpoint_ResetDataToggle();
/* Clear the abort transfer flag */
IsMassStoreReset = false;
}
}
/** Function to read in a command block from the host, via the bulk data OUT endpoint. This function reads in the next command block
* if one has been issued, and performs validation to ensure that the block command is valid.
*
* \return Boolean true if a valid command block has been read in from the endpoint, false otherwise
*/
static bool ReadInCommandBlock(void)
{
/* Select the Data Out endpoint */
Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
/* Read in command block header */
Endpoint_Read_Stream_LE(&CommandBlock, (sizeof(CommandBlock) - sizeof(CommandBlock.SCSICommandData)),
StreamCallback_AbortOnMassStoreReset);
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return false;
/* Verify the command block - abort if invalid */
if ((CommandBlock.Signature != CBW_SIGNATURE) ||
(CommandBlock.LUN >= TOTAL_LUNS) ||
(CommandBlock.Flags & 0x1F) ||
(CommandBlock.SCSICommandLength == 0) ||
(CommandBlock.SCSICommandLength > MAX_SCSI_COMMAND_LENGTH))
{
/* Stall both data pipes until reset by host */
Endpoint_StallTransaction();
Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
Endpoint_StallTransaction();
return false;
}
/* Read in command block command data */
Endpoint_Read_Stream_LE(&CommandBlock.SCSICommandData,
CommandBlock.SCSICommandLength,
StreamCallback_AbortOnMassStoreReset);
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return false;
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearOUT();
return true;
}
/** Returns the filled Command Status Wrapper back to the host via the bulk data IN endpoint, waiting for the host to clear any
* stalled data endpoints as needed.
*/
static void ReturnCommandStatus(void)
{
/* Select the Data Out endpoint */
Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);
/* While data pipe is stalled, wait until the host issues a control request to clear the stall */
while (Endpoint_IsStalled())
{
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return;
}
/* Select the Data In endpoint */
Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);
/* While data pipe is stalled, wait until the host issues a control request to clear the stall */
while (Endpoint_IsStalled())
{
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return;
}
/* Write the CSW to the endpoint */
Endpoint_Write_Stream_LE(&CommandStatus, sizeof(CommandStatus),
StreamCallback_AbortOnMassStoreReset);
/* Check if the current command is being aborted by the host */
if (IsMassStoreReset)
return;
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
}
/** Stream callback function for the Endpoint stream read and write functions. This callback will abort the current stream transfer
* if a Mass Storage Reset request has been issued to the control endpoint.
*/
uint8_t StreamCallback_AbortOnMassStoreReset(void)
{
/* Abort if a Mass Storage reset command was received */
if (IsMassStoreReset)
return STREAMCALLBACK_Abort;
/* Continue with the current stream operation */
return STREAMCALLBACK_Continue;
}

View file

@ -1,152 +1,152 @@
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for MassStorage.c.
*/
#ifndef _MASS_STORAGE_H_
#define _MASS_STORAGE_H_
/* Includes: */
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include "Descriptors.h"
#include "Lib/SCSI.h"
#include "Lib/DataflashManager.h"
#include <LUFA/Version.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/Board/Dataflash.h>
/* Macros: */
/** Mass Storage Class specific request to reset the Mass Storage interface, ready for the next command. */
#define REQ_MassStorageReset 0xFF
/** Mass Storage Class specific request to retrieve the total number of Logical Units (drives) in the SCSI device. */
#define REQ_GetMaxLUN 0xFE
/** Maximum length of a SCSI command which can be issued by the device or host in a Mass Storage bulk wrapper. */
#define MAX_SCSI_COMMAND_LENGTH 16
/** Total number of Logical Units (drives) in the device. The total device capacity is shared equally between
* each drive - this can be set to any positive non-zero amount.
*/
#define TOTAL_LUNS 1
/** Blocks in each LUN, calculated from the total capacity divided by the total number of Logical Units in the device. */
#define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS)
/** Magic signature for a Command Block Wrapper used in the Mass Storage Bulk-Only transport protocol. */
#define CBW_SIGNATURE 0x43425355UL
/** Magic signature for a Command Status Wrapper used in the Mass Storage Bulk-Only transport protocol. */
#define CSW_SIGNATURE 0x53425355UL
/** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from host-to-device. */
#define COMMAND_DIRECTION_DATA_OUT (0 << 7)
/** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from device-to-host. */
#define COMMAND_DIRECTION_DATA_IN (1 << 7)
/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
#define LEDMASK_USB_NOTREADY LEDS_LED1
/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
#define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
#define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
#define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is busy. */
#define LEDMASK_USB_BUSY LEDS_LED2
/* Type defines: */
/** Type define for a Command Block Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */
typedef struct
{
uint32_t Signature; /**< Command block signature, must be CBW_SIGNATURE to indicate a valid Command Block */
uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */
uint32_t DataTransferLength; /** Length of the optional data portion of the issued command, in bytes */
uint8_t Flags; /**< Command block flags, indicating command data direction */
uint8_t LUN; /**< Logical Unit number this command is issued to */
uint8_t SCSICommandLength; /**< Length of the issued SCSI command within the SCSI command data array */
uint8_t SCSICommandData[MAX_SCSI_COMMAND_LENGTH]; /**< Issued SCSI command in the Command Block */
} CommandBlockWrapper_t;
/** Type define for a Command Status Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */
typedef struct
{
uint32_t Signature; /**< Status block signature, must be CSW_SIGNATURE to indicate a valid Command Status */
uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */
uint32_t DataTransferResidue; /**< Number of bytes of data not processed in the SCSI command */
uint8_t Status; /**< Status code of the issued command - a value from the MassStorage_CommandStatusCodes_t enum */
} CommandStatusWrapper_t;
/* Enums: */
/** Enum for the possible command status wrapper return status codes. */
enum MassStorage_CommandStatusCodes_t
{
Command_Pass = 0, /**< Command completed with no error */
Command_Fail = 1, /**< Command failed to complete - host may check the exact error via a SCSI REQUEST SENSE command */
Phase_Error = 2 /**< Command failed due to being invalid in the current phase */
};
/* Global Variables: */
extern CommandBlockWrapper_t CommandBlock;
extern CommandStatusWrapper_t CommandStatus;
extern volatile bool IsMassStoreReset;
/* Function Prototypes: */
void SetupHardware(void);
void MassStorage_Task(void);
void EVENT_USB_Device_Connect(void);
void EVENT_USB_Device_Disconnect(void);
void EVENT_USB_Device_ConfigurationChanged(void);
void EVENT_USB_Device_UnhandledControlRequest(void);
#if defined(INCLUDE_FROM_MASSSTORAGE_C)
static bool ReadInCommandBlock(void);
static void ReturnCommandStatus(void);
#endif
uint8_t StreamCallback_AbortOnMassStoreReset(void);
#endif
/*
LUFA Library
Copyright (C) Dean Camera, 2010.
dean [at] fourwalledcubicle [dot] com
www.fourwalledcubicle.com
*/
/*
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of the author not be used in
advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
The author disclaim all warranties with regard to this
software, including all implied warranties of merchantability
and fitness. In no event shall the author be liable for any
special, indirect or consequential damages or any damages
whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action,
arising out of or in connection with the use or performance of
this software.
*/
/** \file
*
* Header file for MassStorage.c.
*/
#ifndef _MASS_STORAGE_H_
#define _MASS_STORAGE_H_
/* Includes: */
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include "Descriptors.h"
#include "Lib/SCSI.h"
#include "Lib/DataflashManager.h"
#include <LUFA/Version.h>
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Drivers/Board/LEDs.h>
#include <LUFA/Drivers/Board/Dataflash.h>
/* Macros: */
/** Mass Storage Class specific request to reset the Mass Storage interface, ready for the next command. */
#define REQ_MassStorageReset 0xFF
/** Mass Storage Class specific request to retrieve the total number of Logical Units (drives) in the SCSI device. */
#define REQ_GetMaxLUN 0xFE
/** Maximum length of a SCSI command which can be issued by the device or host in a Mass Storage bulk wrapper. */
#define MAX_SCSI_COMMAND_LENGTH 16
/** Total number of Logical Units (drives) in the device. The total device capacity is shared equally between
* each drive - this can be set to any positive non-zero amount.
*/
#define TOTAL_LUNS 1
/** Blocks in each LUN, calculated from the total capacity divided by the total number of Logical Units in the device. */
#define LUN_MEDIA_BLOCKS (VIRTUAL_MEMORY_BLOCKS / TOTAL_LUNS)
/** Magic signature for a Command Block Wrapper used in the Mass Storage Bulk-Only transport protocol. */
#define CBW_SIGNATURE 0x43425355UL
/** Magic signature for a Command Status Wrapper used in the Mass Storage Bulk-Only transport protocol. */
#define CSW_SIGNATURE 0x53425355UL
/** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from host-to-device. */
#define COMMAND_DIRECTION_DATA_OUT (0 << 7)
/** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from device-to-host. */
#define COMMAND_DIRECTION_DATA_IN (1 << 7)
/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
#define LEDMASK_USB_NOTREADY LEDS_LED1
/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
#define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
#define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
#define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
/** LED mask for the library LED driver, to indicate that the USB interface is busy. */
#define LEDMASK_USB_BUSY LEDS_LED2
/* Type defines: */
/** Type define for a Command Block Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */
typedef struct
{
uint32_t Signature; /**< Command block signature, must be CBW_SIGNATURE to indicate a valid Command Block */
uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */
uint32_t DataTransferLength; /** Length of the optional data portion of the issued command, in bytes */
uint8_t Flags; /**< Command block flags, indicating command data direction */
uint8_t LUN; /**< Logical Unit number this command is issued to */
uint8_t SCSICommandLength; /**< Length of the issued SCSI command within the SCSI command data array */
uint8_t SCSICommandData[MAX_SCSI_COMMAND_LENGTH]; /**< Issued SCSI command in the Command Block */
} CommandBlockWrapper_t;
/** Type define for a Command Status Wrapper, used in the Mass Storage Bulk-Only Transport protocol. */
typedef struct
{
uint32_t Signature; /**< Status block signature, must be CSW_SIGNATURE to indicate a valid Command Status */
uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper */
uint32_t DataTransferResidue; /**< Number of bytes of data not processed in the SCSI command */
uint8_t Status; /**< Status code of the issued command - a value from the MassStorage_CommandStatusCodes_t enum */
} CommandStatusWrapper_t;
/* Enums: */
/** Enum for the possible command status wrapper return status codes. */
enum MassStorage_CommandStatusCodes_t
{
Command_Pass = 0, /**< Command completed with no error */
Command_Fail = 1, /**< Command failed to complete - host may check the exact error via a SCSI REQUEST SENSE command */
Phase_Error = 2 /**< Command failed due to being invalid in the current phase */
};
/* Global Variables: */
extern CommandBlockWrapper_t CommandBlock;
extern CommandStatusWrapper_t CommandStatus;
extern volatile bool IsMassStoreReset;
/* Function Prototypes: */
void SetupHardware(void);
void MassStorage_Task(void);
void EVENT_USB_Device_Connect(void);
void EVENT_USB_Device_Disconnect(void);
void EVENT_USB_Device_ConfigurationChanged(void);
void EVENT_USB_Device_UnhandledControlRequest(void);
#if defined(INCLUDE_FROM_MASSSTORAGE_C)
static bool ReadInCommandBlock(void);
static void ReturnCommandStatus(void);
#endif
uint8_t StreamCallback_AbortOnMassStoreReset(void);
#endif

View file

@ -1,92 +1,92 @@
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage Mass Storage Device Demo
*
* \section SSec_Compat Demo Compatibility:
*
* The following list indicates what microcontrollers are compatible with this demo.
*
* - Series 7 USB AVRs
* - Series 6 USB AVRs
* - Series 4 USB AVRs
* - Series 2 USB AVRs
*
* \section SSec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this demo.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Device</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Mass Storage Device</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>Bulk-Only Transport</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>USBIF Mass Storage Standard \n
* USB Bulk-Only Transport Standard \n
* SCSI Primary Commands Specification \n
* SCSI Block Commands Specification</td>
* </tr>
* <tr>
* <td><b>Usable Speeds:</b></td>
* <td>Full Speed Mode</td>
* </tr>
* </table>
*
* \section SSec_Description Project Description:
*
* Dual LUN Mass Storage demonstration application. This gives a simple
* reference application for implementing a multiple LUN USB Mass Storage
* device using the basic USB UFI drivers in all modern OSes (i.e. no
* special drivers required).
*
* On start-up the system will automatically enumerate and function as an
* external mass storage device with two LUNs (separate disks) which may
* be formatted and used in the same manner as commercial USB Mass Storage
* devices.
*
* You will need to format the mass storage drives upon first run of this
* demonstration - as the device acts only as a data block transport between
* the host and the storage media, it does not matter what file system is used,
* as the data interpretation is performed by the host and not the USB device.
*
* This demo is not restricted to only two LUNs; by changing the TOTAL_LUNS
* value in MassStorageDualLUN.h, any number of LUNs can be used (from 1 to
* 255), with each LUN being allocated an equal portion of the available
* Dataflash memory.
*
* The USB control endpoint is managed entirely by the library using endpoint
* interrupts, as the INTERRUPT_CONTROL_ENDPOINT option is enabled. This allows for
* the host to reset the Mass Storage device state during long transfers without
* the need for complicated polling logic.
*
* \section SSec_Options Project Options
*
* The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
*
* <table>
* <tr>
* <td><b>Define Name:</b></td>
* <td><b>Location:</b></td>
* <td><b>Description:</b></td>
* </tr>
* <tr>
* <td>TOTAL_LUNS</td>
* <td>MassStorage.h</td>
* <td>Total number of Logical Units (drives) in the device. The total device capacity is shared equally between each drive
* - this can be set to any positive non-zero amount.</td>
* </tr>
* </table>
*/
/** \file
*
* This file contains special DoxyGen information for the generation of the main page and other special
* documentation pages. It is not a project source file.
*/
/** \mainpage Mass Storage Device Demo
*
* \section SSec_Compat Demo Compatibility:
*
* The following list indicates what microcontrollers are compatible with this demo.
*
* - Series 7 USB AVRs
* - Series 6 USB AVRs
* - Series 4 USB AVRs
* - Series 2 USB AVRs
*
* \section SSec_Info USB Information:
*
* The following table gives a rundown of the USB utilization of this demo.
*
* <table>
* <tr>
* <td><b>USB Mode:</b></td>
* <td>Device</td>
* </tr>
* <tr>
* <td><b>USB Class:</b></td>
* <td>Mass Storage Device</td>
* </tr>
* <tr>
* <td><b>USB Subclass:</b></td>
* <td>Bulk-Only Transport</td>
* </tr>
* <tr>
* <td><b>Relevant Standards:</b></td>
* <td>USBIF Mass Storage Standard \n
* USB Bulk-Only Transport Standard \n
* SCSI Primary Commands Specification \n
* SCSI Block Commands Specification</td>
* </tr>
* <tr>
* <td><b>Usable Speeds:</b></td>
* <td>Full Speed Mode</td>
* </tr>
* </table>
*
* \section SSec_Description Project Description:
*
* Dual LUN Mass Storage demonstration application. This gives a simple
* reference application for implementing a multiple LUN USB Mass Storage
* device using the basic USB UFI drivers in all modern OSes (i.e. no
* special drivers required).
*
* On start-up the system will automatically enumerate and function as an
* external mass storage device with two LUNs (separate disks) which may
* be formatted and used in the same manner as commercial USB Mass Storage
* devices.
*
* You will need to format the mass storage drives upon first run of this
* demonstration - as the device acts only as a data block transport between
* the host and the storage media, it does not matter what file system is used,
* as the data interpretation is performed by the host and not the USB device.
*
* This demo is not restricted to only two LUNs; by changing the TOTAL_LUNS
* value in MassStorageDualLUN.h, any number of LUNs can be used (from 1 to
* 255), with each LUN being allocated an equal portion of the available
* Dataflash memory.
*
* The USB control endpoint is managed entirely by the library using endpoint
* interrupts, as the INTERRUPT_CONTROL_ENDPOINT option is enabled. This allows for
* the host to reset the Mass Storage device state during long transfers without
* the need for complicated polling logic.
*
* \section SSec_Options Project Options
*
* The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
*
* <table>
* <tr>
* <td><b>Define Name:</b></td>
* <td><b>Location:</b></td>
* <td><b>Description:</b></td>
* </tr>
* <tr>
* <td>TOTAL_LUNS</td>
* <td>MassStorage.h</td>
* <td>Total number of Logical Units (drives) in the device. The total device capacity is shared equally between each drive
* - this can be set to any positive non-zero amount.</td>
* </tr>
* </table>
*/

File diff suppressed because it is too large Load diff