parent
57071dea22
commit
64f17a679f
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
LUFA Library
|
||||||
|
Copyright (C) Dean Camera, 2013.
|
||||||
|
|
||||||
|
dean [at] fourwalledcubicle [dot] com
|
||||||
|
www.lufa-lib.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that the copyright notice and this
|
||||||
|
permission notice and warranty disclaimer appear in supporting
|
||||||
|
documentation, and that the name of the author not be used in
|
||||||
|
advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
The author disclaims all warranties with regard to this
|
||||||
|
software, including all implied warranties of merchantability
|
||||||
|
and fitness. In no event shall the author be liable for any
|
||||||
|
special, indirect or consequential damages or any damages
|
||||||
|
whatsoever resulting from loss of use, data or profits, whether
|
||||||
|
in an action of contract, negligence or other tortious action,
|
||||||
|
arising out of or in connection with the use or performance of
|
||||||
|
this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \brief LUFA Library Configuration Header File
|
||||||
|
*
|
||||||
|
* This header file is used to configure LUFA's compile time options,
|
||||||
|
* as an alternative to the compile time constants supplied through
|
||||||
|
* a makefile.
|
||||||
|
*
|
||||||
|
* For information on what each token does, refer to the LUFA
|
||||||
|
* manual section "Summary of Compile Tokens".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LUFA_CONFIG_H_
|
||||||
|
#define _LUFA_CONFIG_H_
|
||||||
|
|
||||||
|
#if (ARCH == ARCH_AVR8)
|
||||||
|
|
||||||
|
/* Non-USB Related Configuration Tokens: */
|
||||||
|
// #define DISABLE_TERMINAL_CODES
|
||||||
|
|
||||||
|
/* USB Class Driver Related Tokens: */
|
||||||
|
// #define HID_HOST_BOOT_PROTOCOL_ONLY
|
||||||
|
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
|
||||||
|
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
|
||||||
|
// #define HID_MAX_COLLECTIONS {Insert Value Here}
|
||||||
|
// #define HID_MAX_REPORTITEMS {Insert Value Here}
|
||||||
|
// #define HID_MAX_REPORT_IDS {Insert Value Here}
|
||||||
|
// #define NO_CLASS_DRIVER_AUTOFLUSH
|
||||||
|
|
||||||
|
/* General USB Driver Related Tokens: */
|
||||||
|
// #define ORDERED_EP_CONFIG
|
||||||
|
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
|
||||||
|
#define USB_DEVICE_ONLY
|
||||||
|
// #define USB_HOST_ONLY
|
||||||
|
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
|
||||||
|
// #define NO_LIMITED_CONTROLLER_CONNECT
|
||||||
|
// #define NO_SOF_EVENTS
|
||||||
|
|
||||||
|
/* USB Device Mode Driver Related Tokens: */
|
||||||
|
#define USE_RAM_DESCRIPTORS
|
||||||
|
// #define USE_FLASH_DESCRIPTORS
|
||||||
|
// #define USE_EEPROM_DESCRIPTORS
|
||||||
|
// #define NO_INTERNAL_SERIAL
|
||||||
|
#define FIXED_CONTROL_ENDPOINT_SIZE 8
|
||||||
|
// #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
|
||||||
|
#define FIXED_NUM_CONFIGURATIONS 1
|
||||||
|
// #define CONTROL_ONLY_DEVICE
|
||||||
|
#define INTERRUPT_CONTROL_ENDPOINT
|
||||||
|
// #define NO_DEVICE_REMOTE_WAKEUP
|
||||||
|
// #define NO_DEVICE_SELF_POWER
|
||||||
|
|
||||||
|
/* USB Host Mode Driver Related Tokens: */
|
||||||
|
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
|
||||||
|
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
|
||||||
|
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
|
||||||
|
// #define NO_AUTO_VBUS_MANAGEMENT
|
||||||
|
// #define INVERTED_VBUS_ENABLE_LINE
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error Unsupported architecture for this LUFA configuration file.
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
LUFA Library
|
||||||
|
Copyright (C) Dean Camera, 2013.
|
||||||
|
|
||||||
|
dean [at] fourwalledcubicle [dot] com
|
||||||
|
www.lufa-lib.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that the copyright notice and this
|
||||||
|
permission notice and warranty disclaimer appear in supporting
|
||||||
|
documentation, and that the name of the author not be used in
|
||||||
|
advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
The author disclaims all warranties with regard to this
|
||||||
|
software, including all implied warranties of merchantability
|
||||||
|
and fitness. In no event shall the author be liable for any
|
||||||
|
special, indirect or consequential damages or any damages
|
||||||
|
whatsoever resulting from loss of use, data or profits, whether
|
||||||
|
in an action of contract, negligence or other tortious action,
|
||||||
|
arising out of or in connection with the use or performance of
|
||||||
|
this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
|
||||||
|
/** 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.
|
||||||
|
*/
|
||||||
|
const USB_Descriptor_Device_t DeviceDescriptor =
|
||||||
|
{
|
||||||
|
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
|
||||||
|
|
||||||
|
.USBSpecification = VERSION_BCD(01.10),
|
||||||
|
.Class = USB_CSCP_NoDeviceClass,
|
||||||
|
.SubClass = USB_CSCP_NoDeviceSubclass,
|
||||||
|
.Protocol = USB_CSCP_NoDeviceProtocol,
|
||||||
|
|
||||||
|
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
|
||||||
|
|
||||||
|
.VendorID = 0x03EB,
|
||||||
|
.ProductID = 0x2045,
|
||||||
|
.ReleaseNumber = VERSION_BCD(00.01),
|
||||||
|
|
||||||
|
.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.
|
||||||
|
*/
|
||||||
|
const USB_Descriptor_Configuration_t 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_RESERVED,
|
||||||
|
|
||||||
|
.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 = MS_CSCP_MassStorageClass,
|
||||||
|
.SubClass = MS_CSCP_SCSITransparentSubclass,
|
||||||
|
.Protocol = MS_CSCP_BulkOnlyTransportProtocol,
|
||||||
|
|
||||||
|
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||||
|
},
|
||||||
|
|
||||||
|
.MS_DataInEndpoint =
|
||||||
|
{
|
||||||
|
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||||
|
|
||||||
|
.EndpointAddress = MASS_STORAGE_IN_EPADDR,
|
||||||
|
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||||
|
.EndpointSize = MASS_STORAGE_IO_EPSIZE,
|
||||||
|
.PollingIntervalMS = 0x05
|
||||||
|
},
|
||||||
|
|
||||||
|
.MS_DataOutEndpoint =
|
||||||
|
{
|
||||||
|
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||||
|
|
||||||
|
.EndpointAddress = MASS_STORAGE_OUT_EPADDR,
|
||||||
|
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||||
|
.EndpointSize = MASS_STORAGE_IO_EPSIZE,
|
||||||
|
.PollingIntervalMS = 0x05
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 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.
|
||||||
|
*/
|
||||||
|
const USB_Descriptor_String_t 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.
|
||||||
|
*/
|
||||||
|
const USB_Descriptor_String_t 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.
|
||||||
|
*/
|
||||||
|
const USB_Descriptor_String_t ProductString =
|
||||||
|
{
|
||||||
|
.Header = {.Size = USB_STRING_LEN(15), .Type = DTYPE_String},
|
||||||
|
|
||||||
|
.UnicodeString = L"LUFA Bootloader"
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 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,
|
||||||
|
const void** const DescriptorAddress)
|
||||||
|
{
|
||||||
|
const uint8_t DescriptorType = (wValue >> 8);
|
||||||
|
const uint8_t DescriptorNumber = (wValue & 0xFF);
|
||||||
|
|
||||||
|
const void* Address = NULL;
|
||||||
|
uint16_t Size = NO_DESCRIPTOR;
|
||||||
|
|
||||||
|
switch (DescriptorType)
|
||||||
|
{
|
||||||
|
case DTYPE_Device:
|
||||||
|
Address = &DeviceDescriptor;
|
||||||
|
Size = sizeof(USB_Descriptor_Device_t);
|
||||||
|
break;
|
||||||
|
case DTYPE_Configuration:
|
||||||
|
Address = &ConfigurationDescriptor;
|
||||||
|
Size = sizeof(USB_Descriptor_Configuration_t);
|
||||||
|
break;
|
||||||
|
case DTYPE_String:
|
||||||
|
switch (DescriptorNumber)
|
||||||
|
{
|
||||||
|
case 0x00:
|
||||||
|
Address = &LanguageString;
|
||||||
|
Size = pgm_read_byte(&LanguageString.Header.Size);
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
Address = &ManufacturerString;
|
||||||
|
Size = pgm_read_byte(&ManufacturerString.Header.Size);
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
Address = &ProductString;
|
||||||
|
Size = pgm_read_byte(&ProductString.Header.Size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*DescriptorAddress = Address;
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
LUFA Library
|
||||||
|
Copyright (C) Dean Camera, 2013.
|
||||||
|
|
||||||
|
dean [at] fourwalledcubicle [dot] com
|
||||||
|
www.lufa-lib.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that the copyright notice and this
|
||||||
|
permission notice and warranty disclaimer appear in supporting
|
||||||
|
documentation, and that the name of the author not be used in
|
||||||
|
advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
The author disclaims all warranties with regard to this
|
||||||
|
software, including all implied warranties of merchantability
|
||||||
|
and fitness. In no event shall the author be liable for any
|
||||||
|
special, indirect or consequential damages or any damages
|
||||||
|
whatsoever resulting from loss of use, data or profits, whether
|
||||||
|
in an action of contract, negligence or other tortious action,
|
||||||
|
arising out of or in connection with the use or performance of
|
||||||
|
this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
*
|
||||||
|
* Header file for Descriptors.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DESCRIPTORS_H_
|
||||||
|
#define _DESCRIPTORS_H_
|
||||||
|
|
||||||
|
/* Includes: */
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
#include <LUFA/Drivers/USB/USB.h>
|
||||||
|
|
||||||
|
/* Macros: */
|
||||||
|
/** Endpoint address of the Mass Storage device-to-host data IN endpoint. */
|
||||||
|
#define MASS_STORAGE_IN_EPADDR (ENDPOINT_DIR_IN | 3)
|
||||||
|
|
||||||
|
/** Endpoint address of the Mass Storage host-to-device data OUT endpoint. */
|
||||||
|
#define MASS_STORAGE_OUT_EPADDR (ENDPOINT_DIR_OUT | 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;
|
||||||
|
|
||||||
|
// Mass Storage Interface
|
||||||
|
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,
|
||||||
|
const void** const DescriptorAddress)
|
||||||
|
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,321 @@
|
|||||||
|
/*
|
||||||
|
LUFA Library
|
||||||
|
Copyright (C) Dean Camera, 2013.
|
||||||
|
|
||||||
|
dean [at] fourwalledcubicle [dot] com
|
||||||
|
www.lufa-lib.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that the copyright notice and this
|
||||||
|
permission notice and warranty disclaimer appear in supporting
|
||||||
|
documentation, and that the name of the author not be used in
|
||||||
|
advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
The author disclaims all warranties with regard to this
|
||||||
|
software, including all implied warranties of merchantability
|
||||||
|
and fitness. In no event shall the author be liable for any
|
||||||
|
special, indirect or consequential damages or any damages
|
||||||
|
whatsoever resulting from loss of use, data or profits, whether
|
||||||
|
in an action of contract, negligence or other tortious action,
|
||||||
|
arising out of or in connection with the use or performance of
|
||||||
|
this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
*
|
||||||
|
* SCSI command processing routines, for SCSI commands issued by the host. Mass Storage
|
||||||
|
* devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,
|
||||||
|
* which wrap around standard SCSI device commands for controlling the actual storage medium.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INCLUDE_FROM_SCSI_C
|
||||||
|
#include "SCSI.h"
|
||||||
|
|
||||||
|
/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's
|
||||||
|
* features and capabilities.
|
||||||
|
*/
|
||||||
|
static const SCSI_Inquiry_Response_t InquiryData =
|
||||||
|
{
|
||||||
|
.DeviceType = DEVICE_TYPE_BLOCK,
|
||||||
|
.PeripheralQualifier = 0,
|
||||||
|
|
||||||
|
.Removable = true,
|
||||||
|
|
||||||
|
.Version = 0,
|
||||||
|
|
||||||
|
.ResponseDataFormat = 2,
|
||||||
|
.NormACA = false,
|
||||||
|
.TrmTsk = false,
|
||||||
|
.AERC = false,
|
||||||
|
|
||||||
|
.AdditionalLength = 0x1F,
|
||||||
|
|
||||||
|
.SoftReset = false,
|
||||||
|
.CmdQue = false,
|
||||||
|
.Linked = false,
|
||||||
|
.Sync = false,
|
||||||
|
.WideBus16Bit = false,
|
||||||
|
.WideBus32Bit = false,
|
||||||
|
.RelAddr = false,
|
||||||
|
|
||||||
|
.VendorID = "LUFA",
|
||||||
|
.ProductID = "Bootloader",
|
||||||
|
.RevisionID = {'0','.','0','0'},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE
|
||||||
|
* command is issued. This gives information on exactly why the last command failed to complete.
|
||||||
|
*/
|
||||||
|
static SCSI_Request_Sense_Response_t SenseData =
|
||||||
|
{
|
||||||
|
.ResponseCode = 0x70,
|
||||||
|
.AdditionalLength = 0x0A,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches
|
||||||
|
* to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns
|
||||||
|
* a command failure due to a ILLEGAL REQUEST.
|
||||||
|
*
|
||||||
|
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||||
|
*
|
||||||
|
* \return Boolean true if the command completed successfully, false otherwise
|
||||||
|
*/
|
||||||
|
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||||
|
{
|
||||||
|
bool CommandSuccess = false;
|
||||||
|
|
||||||
|
/* Run the appropriate SCSI command hander function based on the passed command */
|
||||||
|
switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
|
||||||
|
{
|
||||||
|
case SCSI_CMD_INQUIRY:
|
||||||
|
CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);
|
||||||
|
break;
|
||||||
|
case SCSI_CMD_REQUEST_SENSE:
|
||||||
|
CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
|
||||||
|
break;
|
||||||
|
case SCSI_CMD_READ_CAPACITY_10:
|
||||||
|
CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
|
||||||
|
break;
|
||||||
|
case SCSI_CMD_SEND_DIAGNOSTIC:
|
||||||
|
CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
|
||||||
|
break;
|
||||||
|
case SCSI_CMD_WRITE_10:
|
||||||
|
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
|
||||||
|
break;
|
||||||
|
case SCSI_CMD_READ_10:
|
||||||
|
CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
|
||||||
|
break;
|
||||||
|
case SCSI_CMD_MODE_SENSE_6:
|
||||||
|
CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
|
||||||
|
break;
|
||||||
|
case SCSI_CMD_TEST_UNIT_READY:
|
||||||
|
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
|
||||||
|
case SCSI_CMD_VERIFY_10:
|
||||||
|
/* These commands should just succeed, no handling required */
|
||||||
|
CommandSuccess = true;
|
||||||
|
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Update the SENSE key to reflect the invalid command */
|
||||||
|
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||||
|
SCSI_ASENSE_INVALID_COMMAND,
|
||||||
|
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if command was successfully processed */
|
||||||
|
if (CommandSuccess)
|
||||||
|
{
|
||||||
|
SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
|
||||||
|
SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
|
||||||
|
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
|
||||||
|
* and capabilities to the host.
|
||||||
|
*
|
||||||
|
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||||
|
*
|
||||||
|
* \return Boolean true if the command completed successfully, false otherwise.
|
||||||
|
*/
|
||||||
|
static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||||
|
{
|
||||||
|
uint16_t AllocationLength = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]);
|
||||||
|
uint16_t BytesTransferred = MIN(AllocationLength, sizeof(InquiryData));
|
||||||
|
|
||||||
|
/* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */
|
||||||
|
if ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
|
||||||
|
MSInterfaceInfo->State.CommandBlock.SCSICommandData[2])
|
||||||
|
{
|
||||||
|
/* Optional but unsupported bits set - update the SENSE key and fail the request */
|
||||||
|
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||||
|
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
|
||||||
|
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NULL);
|
||||||
|
|
||||||
|
/* Pad out remaining bytes with 0x00 */
|
||||||
|
Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
|
||||||
|
|
||||||
|
/* Finalize the stream transfer to send the last packet */
|
||||||
|
Endpoint_ClearIN();
|
||||||
|
|
||||||
|
/* Succeed the command and update the bytes transferred counter */
|
||||||
|
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
|
||||||
|
* including the error code and additional error information so that the host can determine why a command failed to complete.
|
||||||
|
*
|
||||||
|
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||||
|
*
|
||||||
|
* \return Boolean true if the command completed successfully, false otherwise.
|
||||||
|
*/
|
||||||
|
static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||||
|
{
|
||||||
|
uint8_t AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
|
||||||
|
uint8_t BytesTransferred = MIN(AllocationLength, sizeof(SenseData));
|
||||||
|
|
||||||
|
Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NULL);
|
||||||
|
Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
|
||||||
|
Endpoint_ClearIN();
|
||||||
|
|
||||||
|
/* Succeed the command and update the bytes transferred counter */
|
||||||
|
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
|
||||||
|
* on the selected Logical Unit (drive), as a number of OS-sized blocks.
|
||||||
|
*
|
||||||
|
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||||
|
*
|
||||||
|
* \return Boolean true if the command completed successfully, false otherwise.
|
||||||
|
*/
|
||||||
|
static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||||
|
{
|
||||||
|
uint32_t LastBlockAddressInLUN = (LUN_MEDIA_BLOCKS - 1);
|
||||||
|
uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE;
|
||||||
|
|
||||||
|
Endpoint_Write_Stream_BE(&LastBlockAddressInLUN, sizeof(LastBlockAddressInLUN), NULL);
|
||||||
|
Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NULL);
|
||||||
|
Endpoint_ClearIN();
|
||||||
|
|
||||||
|
/* Succeed the command and update the bytes transferred counter */
|
||||||
|
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
|
||||||
|
* board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is
|
||||||
|
* supported.
|
||||||
|
*
|
||||||
|
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||||
|
*
|
||||||
|
* \return Boolean true if the command completed successfully, false otherwise.
|
||||||
|
*/
|
||||||
|
static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||||
|
{
|
||||||
|
/* Check to see if the SELF TEST bit is not set */
|
||||||
|
if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
|
||||||
|
{
|
||||||
|
/* Only self-test supported - update SENSE key and fail the command */
|
||||||
|
SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
|
||||||
|
SCSI_ASENSE_INVALID_FIELD_IN_CDB,
|
||||||
|
SCSI_ASENSEQ_NO_QUALIFIER);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Succeed the command and update the bytes transferred counter */
|
||||||
|
MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
|
||||||
|
* and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual
|
||||||
|
* reading and writing of the data.
|
||||||
|
*
|
||||||
|
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||||
|
* \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
|
||||||
|
*
|
||||||
|
* \return Boolean true if the command completed successfully, false otherwise.
|
||||||
|
*/
|
||||||
|
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
|
const bool IsDataRead)
|
||||||
|
{
|
||||||
|
uint32_t BlockAddress;
|
||||||
|
uint16_t TotalBlocks;
|
||||||
|
|
||||||
|
/* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
|
||||||
|
BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
|
||||||
|
|
||||||
|
/* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
|
||||||
|
TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
|
||||||
|
|
||||||
|
/* 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 false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
|
||||||
|
if (IsDataRead == DATA_READ)
|
||||||
|
VirtualFAT_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
||||||
|
else
|
||||||
|
VirtualFAT_WriteBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
|
||||||
|
|
||||||
|
/* Update the bytes transferred counter and succeed the command */
|
||||||
|
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
|
||||||
|
* the SCSI device, as well as the device's Write Protect status.
|
||||||
|
*
|
||||||
|
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
|
||||||
|
*
|
||||||
|
* \return Boolean true if the command completed successfully, false otherwise.
|
||||||
|
*/
|
||||||
|
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||||
|
{
|
||||||
|
/* Send an empty header response with the Write Protect flag status */
|
||||||
|
Endpoint_Write_8(0x00);
|
||||||
|
Endpoint_Write_8(0x00);
|
||||||
|
Endpoint_Write_8(0x00);
|
||||||
|
Endpoint_Write_8(0x00);
|
||||||
|
Endpoint_ClearIN();
|
||||||
|
|
||||||
|
/* Update the bytes transferred counter and succeed the command */
|
||||||
|
MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
LUFA Library
|
||||||
|
Copyright (C) Dean Camera, 2013.
|
||||||
|
|
||||||
|
dean [at] fourwalledcubicle [dot] com
|
||||||
|
www.lufa-lib.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that the copyright notice and this
|
||||||
|
permission notice and warranty disclaimer appear in supporting
|
||||||
|
documentation, and that the name of the author not be used in
|
||||||
|
advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
The author disclaims all warranties with regard to this
|
||||||
|
software, including all implied warranties of merchantability
|
||||||
|
and fitness. In no event shall the author be liable for any
|
||||||
|
special, indirect or consequential damages or any damages
|
||||||
|
whatsoever resulting from loss of use, data or profits, whether
|
||||||
|
in an action of contract, negligence or other tortious action,
|
||||||
|
arising out of or in connection with the use or performance of
|
||||||
|
this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
*
|
||||||
|
* Header file for SCSI.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SCSI_H_
|
||||||
|
#define _SCSI_H_
|
||||||
|
|
||||||
|
/* Includes: */
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
#include <LUFA/Drivers/USB/USB.h>
|
||||||
|
|
||||||
|
#include "../MassStorage.h"
|
||||||
|
#include "../Descriptors.h"
|
||||||
|
#include "VirtualFAT.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 \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
|
||||||
|
#define DATA_READ true
|
||||||
|
|
||||||
|
/** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */
|
||||||
|
#define DATA_WRITE false
|
||||||
|
|
||||||
|
/** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */
|
||||||
|
#define DEVICE_TYPE_BLOCK 0x00
|
||||||
|
|
||||||
|
/* Function Prototypes: */
|
||||||
|
bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||||
|
|
||||||
|
#if defined(INCLUDE_FROM_SCSI_C)
|
||||||
|
static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||||
|
static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||||
|
static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||||
|
static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||||
|
static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
|
const bool IsDataRead);
|
||||||
|
static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
LUFA Library
|
||||||
|
Copyright (C) Dean Camera, 2013.
|
||||||
|
|
||||||
|
dean [at] fourwalledcubicle [dot] com
|
||||||
|
www.lufa-lib.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that the copyright notice and this
|
||||||
|
permission notice and warranty disclaimer appear in supporting
|
||||||
|
documentation, and that the name of the author not be used in
|
||||||
|
advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
The author disclaims all warranties with regard to this
|
||||||
|
software, including all implied warranties of merchantability
|
||||||
|
and fitness. In no event shall the author be liable for any
|
||||||
|
special, indirect or consequential damages or any damages
|
||||||
|
whatsoever resulting from loss of use, data or profits, whether
|
||||||
|
in an action of contract, negligence or other tortious action,
|
||||||
|
arising out of or in connection with the use or performance of
|
||||||
|
this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "VirtualFAT.h"
|
||||||
|
|
||||||
|
static const FATBootBlock_t BootBlock =
|
||||||
|
{
|
||||||
|
.Bootstrap = {0xEB, 0x3C, 0x90},
|
||||||
|
.Description = "mkdosfs",
|
||||||
|
.BlockSize = VIRTUAL_MEMORY_BLOCK_SIZE,
|
||||||
|
.BlocksPerAllocationUnit = ALLOCATION_UNIT_BLOCKS,
|
||||||
|
.ReservedBlocks = 1,
|
||||||
|
.FATCopies = 2,
|
||||||
|
.RootDirectoryEntries = 512,
|
||||||
|
.TotalBlocks16 = LUN_MEDIA_BLOCKS,
|
||||||
|
.MediaDescriptor = 0xF8,
|
||||||
|
.BlocksPerFAT = 1,
|
||||||
|
.BlocksPerTrack = 32,
|
||||||
|
.Heads = 64,
|
||||||
|
.HiddenBlocks = 0,
|
||||||
|
.TotalBlocks32 = 0,
|
||||||
|
.PhysicalDriveNum = 0,
|
||||||
|
.ExtendedBootRecordSig = 0x29,
|
||||||
|
.VolumeSerialNumber = 0x12345678,
|
||||||
|
.VolumeLabel = "LUFA BOOT ",
|
||||||
|
.FilesystemIdentifier = "FAT16 ",
|
||||||
|
.BootstrapProgram = {0},
|
||||||
|
.MagicSignature = 0xAA55,
|
||||||
|
};
|
||||||
|
|
||||||
|
static FATDirectoryEntry_t FirmwareFileEntry =
|
||||||
|
{
|
||||||
|
.Filename = "Firmware",
|
||||||
|
.Extension = "bin",
|
||||||
|
.Attributes = 0,
|
||||||
|
.Reserved = {0},
|
||||||
|
.CreationTime = (1 << 11) | (1 << 5),
|
||||||
|
.CreationDate = (9 << 9) | (2 << 5) | (14 << 0),
|
||||||
|
.StartingCluster = 4,
|
||||||
|
.FileSize = (FLASHEND + 1UL),
|
||||||
|
};
|
||||||
|
|
||||||
|
static void WriteBlock(uint16_t BlockNumber)
|
||||||
|
{
|
||||||
|
uint8_t BlockBuffer[512];
|
||||||
|
|
||||||
|
/* Wait until endpoint is ready before continuing */
|
||||||
|
if (Endpoint_WaitUntilReady())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Endpoint_Read_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
|
||||||
|
Endpoint_ClearOUT();
|
||||||
|
|
||||||
|
// TODO: Write to FLASH
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReadBlock(uint16_t BlockNumber)
|
||||||
|
{
|
||||||
|
uint8_t BlockBuffer[512];
|
||||||
|
memset(BlockBuffer, 0x00, sizeof(BlockBuffer));
|
||||||
|
|
||||||
|
switch (BlockNumber)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
memcpy(BlockBuffer, &BootBlock, sizeof(FATBootBlock_t));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
/* Cluster 0: Media type/Reserved */
|
||||||
|
((uint16_t*)&BlockBuffer)[0] = 0xFF00 | BootBlock.MediaDescriptor;
|
||||||
|
|
||||||
|
/* Cluster 1: Reserved */
|
||||||
|
((uint16_t*)&BlockBuffer)[1] = 0xFFFF;
|
||||||
|
|
||||||
|
/* Cluster 2: Reserved */
|
||||||
|
((uint16_t*)&BlockBuffer)[2] = 0xFFFF;
|
||||||
|
|
||||||
|
/* Cluster 3: FIRMWARE.BIN File Entry */
|
||||||
|
((uint16_t*)&BlockBuffer)[3] = 0xFFFF;
|
||||||
|
|
||||||
|
/* Cluster 4 onwards: Cluster chain of FIRMWARE.BIN */
|
||||||
|
for (uint16_t i = 0; i < ((FLASHEND + 1) / (VIRTUAL_MEMORY_BLOCK_SIZE * ALLOCATION_UNIT_BLOCKS)); i++)
|
||||||
|
{
|
||||||
|
((uint16_t*)&BlockBuffer)[i + 4] = i + 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark last cluster as end of file */
|
||||||
|
((uint16_t*)&BlockBuffer)[((FLASHEND + 1) / (VIRTUAL_MEMORY_BLOCK_SIZE * ALLOCATION_UNIT_BLOCKS)) + 4] = 0xFFFF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
memcpy(BlockBuffer, &FirmwareFileEntry, sizeof(FATDirectoryEntry_t));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until endpoint is ready before continuing */
|
||||||
|
if (Endpoint_WaitUntilReady())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
|
||||||
|
Endpoint_ClearIN();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
|
const uint32_t BlockAddress,
|
||||||
|
uint16_t TotalBlocks)
|
||||||
|
{
|
||||||
|
uint16_t CurrentBlock = (uint16_t)BlockAddress;
|
||||||
|
|
||||||
|
while (TotalBlocks--)
|
||||||
|
WriteBlock(CurrentBlock++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VirtualFAT_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
|
const uint32_t BlockAddress,
|
||||||
|
uint16_t TotalBlocks)
|
||||||
|
{
|
||||||
|
uint16_t CurrentBlock = (uint16_t)BlockAddress;
|
||||||
|
|
||||||
|
while (TotalBlocks--)
|
||||||
|
ReadBlock(CurrentBlock++);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
LUFA Library
|
||||||
|
Copyright (C) Dean Camera, 2013.
|
||||||
|
|
||||||
|
dean [at] fourwalledcubicle [dot] com
|
||||||
|
www.lufa-lib.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that the copyright notice and this
|
||||||
|
permission notice and warranty disclaimer appear in supporting
|
||||||
|
documentation, and that the name of the author not be used in
|
||||||
|
advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
The author disclaims all warranties with regard to this
|
||||||
|
software, including all implied warranties of merchantability
|
||||||
|
and fitness. In no event shall the author be liable for any
|
||||||
|
special, indirect or consequential damages or any damages
|
||||||
|
whatsoever resulting from loss of use, data or profits, whether
|
||||||
|
in an action of contract, negligence or other tortious action,
|
||||||
|
arising out of or in connection with the use or performance of
|
||||||
|
this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _VIRTUALFAT_H_
|
||||||
|
#define _VIRTUALFAT_H_
|
||||||
|
|
||||||
|
/* Includes: */
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
#include <LUFA/Drivers/USB/USB.h>
|
||||||
|
|
||||||
|
/* Macros: */
|
||||||
|
#define VIRTUAL_MEMORY_BLOCK_SIZE 512
|
||||||
|
#define ALLOCATION_UNIT_BLOCKS 4
|
||||||
|
#define LUN_MEDIA_BLOCKS ((FLASHEND + 1) / VIRTUAL_MEMORY_BLOCK_SIZE) + 16
|
||||||
|
|
||||||
|
/* Type Definitions: */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t Bootstrap[3];
|
||||||
|
uint8_t Description[8];
|
||||||
|
uint16_t BlockSize;
|
||||||
|
uint8_t BlocksPerAllocationUnit;
|
||||||
|
uint16_t ReservedBlocks;
|
||||||
|
uint8_t FATCopies;
|
||||||
|
uint16_t RootDirectoryEntries;
|
||||||
|
uint16_t TotalBlocks16;
|
||||||
|
uint8_t MediaDescriptor;
|
||||||
|
uint16_t BlocksPerFAT;
|
||||||
|
uint16_t BlocksPerTrack;
|
||||||
|
uint16_t Heads;
|
||||||
|
uint32_t HiddenBlocks;
|
||||||
|
uint32_t TotalBlocks32;
|
||||||
|
uint16_t PhysicalDriveNum;
|
||||||
|
uint8_t ExtendedBootRecordSig;
|
||||||
|
uint32_t VolumeSerialNumber;
|
||||||
|
uint8_t VolumeLabel[11];
|
||||||
|
uint8_t FilesystemIdentifier[8];
|
||||||
|
uint8_t BootstrapProgram[448];
|
||||||
|
uint16_t MagicSignature;
|
||||||
|
} FATBootBlock_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t Filename[8];
|
||||||
|
uint8_t Extension[3];
|
||||||
|
uint8_t Attributes;
|
||||||
|
uint8_t Reserved[10];
|
||||||
|
uint16_t CreationTime;
|
||||||
|
uint16_t CreationDate;
|
||||||
|
uint16_t StartingCluster;
|
||||||
|
uint32_t FileSize;
|
||||||
|
} FATDirectoryEntry_t;
|
||||||
|
|
||||||
|
/* Function Prototypes: */
|
||||||
|
void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
|
const uint32_t BlockAddress,
|
||||||
|
uint16_t TotalBlocks);
|
||||||
|
|
||||||
|
void VirtualFAT_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
|
||||||
|
const uint32_t BlockAddress,
|
||||||
|
uint16_t TotalBlocks);
|
||||||
|
#endif
|
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
LUFA Library
|
||||||
|
Copyright (C) Dean Camera, 2013.
|
||||||
|
|
||||||
|
dean [at] fourwalledcubicle [dot] com
|
||||||
|
www.lufa-lib.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that the copyright notice and this
|
||||||
|
permission notice and warranty disclaimer appear in supporting
|
||||||
|
documentation, and that the name of the author not be used in
|
||||||
|
advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
The author disclaims all warranties with regard to this
|
||||||
|
software, including all implied warranties of merchantability
|
||||||
|
and fitness. In no event shall the author be liable for any
|
||||||
|
special, indirect or consequential damages or any damages
|
||||||
|
whatsoever resulting from loss of use, data or profits, whether
|
||||||
|
in an action of contract, negligence or other tortious action,
|
||||||
|
arising out of or in connection with the use or performance of
|
||||||
|
this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
*
|
||||||
|
* Main source file for the MassStorage demo. This file contains the main tasks of
|
||||||
|
* the demo and is responsible for the initial application hardware configuration.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MassStorage.h"
|
||||||
|
|
||||||
|
/** LUFA Mass Storage Class driver interface configuration and state information. This structure is
|
||||||
|
* passed to all Mass Storage Class driver functions, so that multiple instances of the same class
|
||||||
|
* within a device can be differentiated from one another.
|
||||||
|
*/
|
||||||
|
USB_ClassInfo_MS_Device_t Disk_MS_Interface =
|
||||||
|
{
|
||||||
|
.Config =
|
||||||
|
{
|
||||||
|
.InterfaceNumber = 0,
|
||||||
|
.DataINEndpoint =
|
||||||
|
{
|
||||||
|
.Address = MASS_STORAGE_IN_EPADDR,
|
||||||
|
.Size = MASS_STORAGE_IO_EPSIZE,
|
||||||
|
.Banks = 1,
|
||||||
|
},
|
||||||
|
.DataOUTEndpoint =
|
||||||
|
{
|
||||||
|
.Address = MASS_STORAGE_OUT_EPADDR,
|
||||||
|
.Size = MASS_STORAGE_IO_EPSIZE,
|
||||||
|
.Banks = 1,
|
||||||
|
},
|
||||||
|
.TotalLUNs = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Main program entry point. This routine contains the overall program flow, including initial
|
||||||
|
* setup of all components and the main program loop.
|
||||||
|
*/
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
SetupHardware();
|
||||||
|
|
||||||
|
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
|
||||||
|
GlobalInterruptEnable();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
MS_Device_USBTask(&Disk_MS_Interface);
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Relocate the interrupt vector table to the bootloader section */
|
||||||
|
MCUCR = (1 << IVCE);
|
||||||
|
MCUCR = (1 << IVSEL);
|
||||||
|
|
||||||
|
/* Hardware Initialization */
|
||||||
|
LEDs_Init();
|
||||||
|
USB_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Event handler for the library USB Connection event. */
|
||||||
|
void EVENT_USB_Device_Connect(void)
|
||||||
|
{
|
||||||
|
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Event handler for the library USB Disconnection event. */
|
||||||
|
void EVENT_USB_Device_Disconnect(void)
|
||||||
|
{
|
||||||
|
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Event handler for the library USB Configuration Changed event. */
|
||||||
|
void EVENT_USB_Device_ConfigurationChanged(void)
|
||||||
|
{
|
||||||
|
bool ConfigSuccess = true;
|
||||||
|
|
||||||
|
ConfigSuccess &= MS_Device_ConfigureEndpoints(&Disk_MS_Interface);
|
||||||
|
|
||||||
|
LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Event handler for the library USB Control Request reception event. */
|
||||||
|
void EVENT_USB_Device_ControlRequest(void)
|
||||||
|
{
|
||||||
|
MS_Device_ProcessControlRequest(&Disk_MS_Interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Mass Storage class driver callback function the reception of SCSI commands from the host, which must be processed.
|
||||||
|
*
|
||||||
|
* \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface configuration structure being referenced
|
||||||
|
*/
|
||||||
|
bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
|
||||||
|
{
|
||||||
|
bool CommandSuccess;
|
||||||
|
|
||||||
|
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
|
||||||
|
CommandSuccess = SCSI_DecodeSCSICommand(MSInterfaceInfo);
|
||||||
|
LEDs_SetAllLEDs(LEDMASK_USB_READY);
|
||||||
|
|
||||||
|
return CommandSuccess;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
LUFA Library
|
||||||
|
Copyright (C) Dean Camera, 2013.
|
||||||
|
|
||||||
|
dean [at] fourwalledcubicle [dot] com
|
||||||
|
www.lufa-lib.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||||
|
|
||||||
|
Permission to use, copy, modify, distribute, and sell this
|
||||||
|
software and its documentation for any purpose is hereby granted
|
||||||
|
without fee, provided that the above copyright notice appear in
|
||||||
|
all copies and that both that the copyright notice and this
|
||||||
|
permission notice and warranty disclaimer appear in supporting
|
||||||
|
documentation, and that the name of the author not be used in
|
||||||
|
advertising or publicity pertaining to distribution of the
|
||||||
|
software without specific, written prior permission.
|
||||||
|
|
||||||
|
The author disclaims all warranties with regard to this
|
||||||
|
software, including all implied warranties of merchantability
|
||||||
|
and fitness. In no event shall the author be liable for any
|
||||||
|
special, indirect or consequential damages or any damages
|
||||||
|
whatsoever resulting from loss of use, data or profits, whether
|
||||||
|
in an action of contract, negligence or other tortious action,
|
||||||
|
arising out of or in connection with the use or performance of
|
||||||
|
this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
*
|
||||||
|
* Header file for 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 <string.h>
|
||||||
|
|
||||||
|
#include "Descriptors.h"
|
||||||
|
|
||||||
|
#include "Lib/SCSI.h"
|
||||||
|
|
||||||
|
#include <LUFA/Drivers/Board/LEDs.h>
|
||||||
|
#include <LUFA/Drivers/USB/USB.h>
|
||||||
|
|
||||||
|
/* Macros: */
|
||||||
|
/** 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
|
||||||
|
|
||||||
|
/* Function Prototypes: */
|
||||||
|
void SetupHardware(void);
|
||||||
|
|
||||||
|
void EVENT_USB_Device_Connect(void);
|
||||||
|
void EVENT_USB_Device_Disconnect(void);
|
||||||
|
void EVENT_USB_Device_ConfigurationChanged(void);
|
||||||
|
void EVENT_USB_Device_ControlRequest(void);
|
||||||
|
|
||||||
|
bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
#
|
||||||
|
# LUFA Library
|
||||||
|
# Copyright (C) Dean Camera, 2013.
|
||||||
|
#
|
||||||
|
# dean [at] fourwalledcubicle [dot] com
|
||||||
|
# www.lufa-lib.org
|
||||||
|
#
|
||||||
|
# --------------------------------------
|
||||||
|
# LUFA Project Makefile.
|
||||||
|
# --------------------------------------
|
||||||
|
|
||||||
|
# Run "make help" for target help.
|
||||||
|
|
||||||
|
MCU = at90usb1287
|
||||||
|
ARCH = AVR8
|
||||||
|
BOARD = USBKEY
|
||||||
|
F_CPU = 8000000
|
||||||
|
F_USB = $(F_CPU)
|
||||||
|
OPTIMIZATION = s
|
||||||
|
TARGET = MassStorage
|
||||||
|
SRC = $(TARGET).c Descriptors.c Lib/SCSI.c Lib/VirtualFAT.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
|
||||||
|
LUFA_PATH = ../../../LUFA
|
||||||
|
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/
|
||||||
|
LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET)
|
||||||
|
|
||||||
|
# Flash size and bootloader section sizes of the target, in KB. These must
|
||||||
|
# match the target's total FLASH size and the bootloader size set in the
|
||||||
|
# device's fuses.
|
||||||
|
FLASH_SIZE_KB := 128
|
||||||
|
BOOT_SECTION_SIZE_KB := 8
|
||||||
|
|
||||||
|
# Bootloader address calculation formulas
|
||||||
|
# Do not modify these macros, but rather modify the dependent values above.
|
||||||
|
CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
|
||||||
|
BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
|
||||||
|
BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - $(strip $(1)) )
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
all:
|
||||||
|
|
||||||
|
# Include LUFA build script makefiles
|
||||||
|
include $(LUFA_PATH)/Build/lufa_core.mk
|
||||||
|
include $(LUFA_PATH)/Build/lufa_sources.mk
|
||||||
|
include $(LUFA_PATH)/Build/lufa_build.mk
|
||||||
|
include $(LUFA_PATH)/Build/lufa_cppcheck.mk
|
||||||
|
include $(LUFA_PATH)/Build/lufa_doxygen.mk
|
||||||
|
include $(LUFA_PATH)/Build/lufa_avrdude.mk
|
||||||
|
include $(LUFA_PATH)/Build/lufa_atprogram.mk
|
Loading…
Reference in new issue