📄 bot_driver.c
字号:
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support - ROUSSET -
* ----------------------------------------------------------------------------
* Copyright (c) 2006, Atmel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaiimer below.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the disclaimer below in the documentation and/or
* other materials provided with the distribution.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*
$Id: bot_driver.c 198 2006-10-30 10:01:09Z jjoannic $
*/
//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include "core/common.h"
#include "core/device.h"
#include "core/board.h"
#include "core/trace.h"
#include "core/usb.h"
#include "core/standard.h"
#include "msd.h"
#include "media.h"
#include "sbc.h"
#include "lun.h"
#include "bot_driver.h"
#include "sbc_methods.h"
//------------------------------------------------------------------------------
// Global variables
//------------------------------------------------------------------------------
//! \brief Descriptors used by the BOT driver
//! \brief Device descriptor
//! \see S_usb_device_descriptor
const S_usb_device_descriptor sDevice = {
sizeof(S_usb_device_descriptor), // Size of this descriptor in bytes
USB_DEVICE_DESCRIPTOR, // DEVICE Descriptor Type
USB2_00, // USB specification 2.00
0x00, // Class is specified in interface
0x00, // Subclass is specified in interface
0x00, // Protocol is specified in interface
USB_ENDPOINT0_MAXPACKETSIZE, // Maximum packet size for endpoint zero
USB_VENDOR_ATMEL, // Vendor ID (ATMEL, 03EBh)
BOT_PRODUCT_ID, // Product ID (6202h)
0x0001, // Device release number is 0.01
0x01, // Index of manufacturer string
0x02, // Index of product string
0x03, // Index of serial number string
0x01 // One possible configuration
};
//! \brief Configuration descriptor
//! \see S_bot_configuration_descriptor
//! \see S_usb_configuration_descriptor
//! \see S_usb_interface_descriptor
//! \see S_usb_endpoint_descriptor
const S_bot_configuration_descriptor sConfiguration = {
// Configuration Descriptor
{
sizeof(S_usb_configuration_descriptor), // Size of this descriptor
USB_CONFIGURATION_DESCRIPTOR, // CONFIGURATION descriptor type
sizeof(S_bot_configuration_descriptor), // Total size of descriptors
0x01, // One interface
0x01, // Configuration number 1
0x00, // No string description
USB_CONFIG_SELF_NOWAKEUP, // Device is self-powered
// Remote wakeup not supported
USB_POWER_MA(100), // 100mA consumption
},
// MSD Class Interface Descriptor
{
sizeof(S_usb_interface_descriptor), // Size of this descriptor in bytes
USB_INTERFACE_DESCRIPTOR, // INTERFACE descriptor type
0x00, // Interface number 0
0x00, // Setting 0
BOT_NUM_ENDPOINTS - 1, // Two endpoints used (excluding endpoint 0)
USB_CLASS_MASS_STORAGE, // Mass storage class code
MSD_SUBCLASS_SCSI, // SCSI subclass code
MSD_PROTOCOL_BULK_ONLY, // Bulk-only transport protocol
0x00 // No string description
},
// Bulk-OUT Endpoint Descriptor
{
sizeof(S_usb_endpoint_descriptor), // Size of this descriptor in bytes
USB_ENDPOINT_DESCRIPTOR, // ENDPOINT descriptor type
USB_ENDPOINT_OUT | BOT_EPT_BULK_OUT, // OUT endpoint, address 01h
ENDPOINT_TYPE_BULK, // Bulk endpoint
64, // Maximum packet size is 64 bytes
0x00, // Must be 0 for full-speed bulk
},
// Bulk_IN Endpoint Descriptor
{
sizeof(S_usb_endpoint_descriptor), // Size of this descriptor in bytes
USB_ENDPOINT_DESCRIPTOR, // ENDPOINT descriptor type
USB_ENDPOINT_IN | BOT_EPT_BULK_IN, // IN endpoint, address 02h
ENDPOINT_TYPE_BULK, // Bulk endpoint
64, // Maximum packet size if 64 bytes
0x00, // Must be 0 for full-speed bulk
}
};
//! \brief Language ID
//! \see S_usb_language_id
static const S_usb_language_id sLanguageID = {
USB_STRING_DESCRIPTOR_SIZE(1),
USB_STRING_DESCRIPTOR,
USB_LANGUAGE_ENGLISH_US
};
//! \brief Manufacturer description string
static const char pStringManufacturer[] = {
USB_STRING_DESCRIPTOR_SIZE(5),
USB_STRING_DESCRIPTOR,
USB_UNICODE('A'),
USB_UNICODE('T'),
USB_UNICODE('M'),
USB_UNICODE('E'),
USB_UNICODE('L')
};
//! \brief Product description string
static const char pStringProduct[] = {
USB_STRING_DESCRIPTOR_SIZE(14),
USB_STRING_DESCRIPTOR,
USB_UNICODE('A'),
USB_UNICODE('T'),
USB_UNICODE('M'),
USB_UNICODE('E'),
USB_UNICODE('L'),
USB_UNICODE(' '),
USB_UNICODE('A'),
USB_UNICODE('T'),
USB_UNICODE('9'),
USB_UNICODE('1'),
USB_UNICODE(' '),
USB_UNICODE('M'),
USB_UNICODE('S'),
USB_UNICODE('D')
};
//! \brief Device serial number
//!
//! The serial number must be at least 12 characters long and made up
//! of only letters & numbers to be compliant with the MSD specification
static const char pStringSerialNumber[] = {
USB_STRING_DESCRIPTOR_SIZE(12),
USB_STRING_DESCRIPTOR,
USB_UNICODE('0'),
USB_UNICODE('1'),
USB_UNICODE('2'),
USB_UNICODE('3'),
USB_UNICODE('4'),
USB_UNICODE('5'),
USB_UNICODE('6'),
USB_UNICODE('7'),
USB_UNICODE('8'),
USB_UNICODE('9'),
USB_UNICODE('A'),
USB_UNICODE('B')
};
//! \brief List of string descriptors used by the device
static const char *pStrings[] = {
(char *) &sLanguageID,
pStringManufacturer,
pStringProduct,
pStringSerialNumber
};
//! \brief List of endpoint descriptors used by the device
static const S_usb_endpoint_descriptor *pEndpoints[] = {
&(sConfiguration.sBulkOut),
&(sConfiguration.sBulkIn)
};
//! \brief List of standard descriptors
//! \see S_std_descriptors
static const S_std_descriptors sDescriptors = {
&sDevice,
(S_usb_configuration_descriptor *) &sConfiguration,
pStrings,
pEndpoints
};
//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief Returns the expected transfer length and direction (IN, OUT or don't
//! care) from the host point-of-view.
//! \param pCbw Pointer to the CBW to examinate
//! \param pLength Expected length of command
//! \param pType Expected direction of command
//------------------------------------------------------------------------------
static void BOT_GetCommandInformation(S_msd_cbw *pCbw,
unsigned int *pLength,
unsigned char *pType)
{
// Expected host transfer direction and length
(*pLength) = pCbw->dCBWDataTransferLength;
if (*pLength == 0) {
(*pType) = BOT_NO_TRANSFER;
}
else if (ISSET(pCbw->bmCBWFlags, MSD_CBW_DEVICE_TO_HOST)) {
(*pType) = BOT_DEVICE_TO_HOST;
}
else {
(*pType) = BOT_HOST_TO_DEVICE;
}
}
//------------------------------------------------------------------------------
//! \brief Pre-processes a command by checking the differences between the
//! host and device expectations in term of transfer type and length.
//!
//! Once one of the thirteen cases is identified, the actions to do
//! during the post-processing phase are stored in the dCase variable
//! of the command state.
//! \param pBot Pointer to a S_bot instance
//! \return true if the command is supported, false otherwise
//------------------------------------------------------------------------------
static bool BOT_PreProcessCommand(S_bot *pBot)
{
unsigned int dHostLength;
unsigned int dDeviceLength;
unsigned char bHostType;
unsigned char bDeviceType;
bool isCommandSupported;
S_bot_command_state *pCommandState = &(pBot->sCommandState);
S_msd_csw *pCsw = &(pCommandState->sCsw);
S_msd_cbw *pCbw = &(pCommandState->sCbw);
S_lun *pLun = &(pBot->pLun[(unsigned char) pCbw->bCBWLUN]);
// Get information about the command
// Host-side
BOT_GetCommandInformation(pCbw, &dHostLength, &bHostType);
// Device-side
isCommandSupported = SBC_GetCommandInformation(pCbw->pCommand,
&dDeviceLength,
&bDeviceType,
pLun);
// Initialize data residue and result status
pCsw->dCSWDataResidue = 0;
pCsw->bCSWStatus = MSD_CSW_COMMAND_PASSED;
// Check if the command is supported
if (isCommandSupported) {
// Identify the command case
// Case 1 (Hn = Dn)
if ((bHostType == BOT_NO_TRANSFER)
&& (bDeviceType == BOT_NO_TRANSFER)) {
pCommandState->bCase = 0;
pCommandState->dLength = 0;
}
// Case 2 (Hn < Di)
else if ((bHostType == BOT_NO_TRANSFER)
&& (bDeviceType == BOT_DEVICE_TO_HOST)) {
TRACE_WARNING("W: BOT_PreProcessCommand: Case 2\n\r");
pCommandState->bCase = BOT_CASE_PHASE_ERROR;
pCommandState->dLength = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -