📄 usbh_storage_if.c
字号:
/*
* description: USBH Mass Storage Class Interface
* Maker : Shuichi Yanagihara
* Copyright : (C)2005,SEIKO EPSON Corp. All Rights Reserved.
*/
#include "SPRDEF.h"
#include "SPRSTS.h"
#include "OSCall.h"
#include "drvacs.h"
#include "usbh_SampleTask.h"
#include "usbh_storage_api.h"
#include "usbh_storage_if.h"
#include "usbh_usbd_api.h"
#include "usbh_hcd.h"
#include "usbh_hcds_common.h"
#include <DebugTask.h>
/*****************************************
* Constants define
*****************************************/
/* Command Status */
#define NO_OP 0x00 /* Command No Operation */
#define URB_LINK 0x01 /* Register USB */
#define WAIT_START 0x02 /* waiting for start with DirectCopy Mode. */
#define CBW_CMP 0x03 /* CBW transfer complete */
#define DATA_CMP 0x04 /* Daata transfer complete */
#define CSW_CMP 0x05 /* CSW transfer complete */
#define CLEAR_EP_IN 0x00
#define CLEAR_EP_OUT 0x01
#define MASK_EP_NUMBER (0x7F)
/*****************************************
* structures declaration
*****************************************/
/* BulkOnly Transport CBW */
typedef struct tagUSBH_STRG_CBW{
ULONG signature;
ULONG tag;
ULONG transferLength;
UCHAR flag;
UCHAR lun;
UCHAR cbdLength;
UCHAR cbd[16];
}USBH_STRG_CBW;
/* BulkOnly Transport CSW */
typedef struct tagUSBH_STRG_CSW{
ULONG signature;
ULONG tag;
ULONG dataResidue;
UCHAR status;
}USBH_STRG_CSW;
/* Control transfer,Setup packet */
typedef struct tagUSBH_STRG_CTL_SETUP{
UCHAR bmRequestType;
UCHAR bRequest;
USHORT wValue;
USHORT wIndex;
USHORT wLength;
}USBH_STRG_CTL_SETUP;
/*****************************************
* Function prototype declaration
*****************************************/
static LONG USBH_STRG_PutCmd( USHORT deviceNo, DRIVEACCESS_FUNCCMDPARA *pCmdBlock, UCHAR opCode);
static LONG USBH_STRG_MakeStorageURB( USHORT deviceNo, UCHAR transferMode, DRIVEACCESS_FUNCCMDPARA *pCmdBlock, DRIVEACCESS_FUNCTRANPARA *pTranPara, USBH_USBD_URB *pUrb );
static LONG USBH_STRG_MakeCtlURB( USHORT deviceNo, USBH_STRG_CTL_SETUP *pSetup, UCHAR *pTranData, USBH_USBD_URB *pUrb );
static LONG USBH_STRG_ResetRecovery( USHORT deviceNo );
static void USBH_STRG_USBDInitCallback( ULONG event, ULONG param1, void *pParam );
static void USBH_STRG_DeviceCallback( ULONG event, ULONG param1, void *pParam );
static void USBH_STRG_ReturnValueCallback( ULONG event, ULONG param1, void *pParam );
static void USBH_STRG_SetConfigCallback( ULONG event, ULONG param1, void *pParam );
static void USBH_STRG_ResetCallback( ULONG event, ULONG param1, void *pParam );
static void USBH_STRG_SubmitURBCallback( ULONG event, ULONG param1, void *pParam );
static void USBH_STRG_UnlinkURBCallback( ULONG event, ULONG param1, void *pParam );
static void USBH_STRG_CBWCompCallback( USBH_USBD_URB *pUrb);
static void USBH_STRG_DataCompCallback( USBH_USBD_URB *pUrb);
static void USBH_STRG_CSWCompCallback( USBH_USBD_URB *pUrb);
static void USBH_STRG_CtlCompCallback( USBH_USBD_URB *pUrb);
/*****************************************
* Macros definition
*****************************************/
/*****************************************
* Variables definition
*****************************************/
static DRIVEACCESS_FUNCDEVICELIST DeviceList; /* Device list (device type & the number of devices connected.) */
static DRIVEACCESS_FUNCDEVICELIST *pDeviceList; /* Device list (device type & the number of devices connected.) */
static UCHAR classid; /* Class ID number */
static USBH_STRG_CTL_SETUP setupData[USBH_STRG_MAX_DEVICE];
static USBH_USBD_URB ctlUrb[USBH_STRG_MAX_DEVICE], /* Storage Class Control URB */
cbwUrb[USBH_STRG_MAX_DEVICE], /* Storage Class CBW URB */
dataUrb[USBH_STRG_MAX_DEVICE], /* Storage Class Data URB */
cswUrb[USBH_STRG_MAX_DEVICE]; /* Storage Class CSW URB */
static USBH_STRG_CBW bulkCbw[USBH_STRG_MAX_DEVICE]; /* CBW Data */
static USBH_STRG_CSW bulkCsw[USBH_STRG_MAX_DEVICE]; /* CSW Data */
static USBH_STRG_DEVICE_PARA devicePara[USBH_STRG_MAX_DEVICE]; /* Device Information Parameter */
static CALLBACK_PROC USBH_STRG_IFDMACompCBR[USBH_STRG_MAX_DEVICE]; /* DMA Complete CALLBACK TABLE */
static CALLBACK_PROC USBH_STRG_IFIntrqCompCBR[USBH_STRG_MAX_DEVICE]; /* Intrq Complete CALLBACK TABLE */
static USBH_STRG_CALLBACK_PARA callbackPara; /* The cyccle handler parameter that passed from the Callback */
static USBH_STRG_CYCHDR_PARA cychdrPara; /* the parameter that used for internal information of cycle handler */
/*=============================================================================================
// Function_Name: USBH_STRG_IFReset
//
// description : Initialize this module
//
// Initialize the internal variables used in this module.
//
// argument : void
//
// return : STATUS_SUCCESS Completed successfully
// STATUS_UNSUCCESSFUL Completed with error
//
// global : classid The class ID number
===============================================================================================*/
LONG USBH_STRG_IFReset( void )
{
USHORT i, j;
LONG result;
OS_FLGPTN flgPtn;
pDeviceList = &DeviceList;
for(i = 0; i < USBH_STRG_MAX_DEVICE; i++){
/* DeviceParameter Initialize */
devicePara[i].devAdr = 0;
devicePara[i].subClass = 0;
devicePara[i].lun = 0;
devicePara[i].commandStatus = NO_OP;
devicePara[i].deviceStatus = DRV_FUNC_CMD_COMP;
/* Request Sensd Data Initialize */
for(j = 0; j < REQSENSE_LENGTH; j++) {
devicePara[i].reqSenseData[j] = 0;
}
devicePara[i].reqSenseData[2] = MEDIUM_ERROR;
/* Identify Data Initialize */
for(j = 0; j < IDENTIFY_LENGTH; j++) {
devicePara[i].identifyData[j] = 0;
}
/* DeviceList Initialize */
pDeviceList->deviceType[i] = NO_DEVICE;
/* CBW Initialize */
bulkCbw[i].signature = CBW_SIGNATURE;
bulkCbw[i].tag = 0;
}
pDeviceList->deviceCount = USBH_STRG_MAX_DEVICE;
/* Clear the status of the cycle handler. */
cychdrPara.ctlPass = EVENT_NONE;
/* USBD initialization */
result = USBH_USBD_Init(USBH_STRG_USBDInitCallback);
if( result != USBH_USBD_STATUS_SUCCESS ){
return STATUS_UNSUCCESSFUL;
}
/* Waiting for the completion of the USBD initialization */
OS_WaiFlg(FLGID_USBH_SAMPLE, FLG_EVENT_USBDINIT_CMP_USBH_SAMPLE, OS_TWF_ORW, &flgPtn);
OS_ClrFlg(FLGID_USBH_SAMPLE, ~(FLG_EVENT_USBDINIT_CMP_USBH_SAMPLE));
/* Register to USBD */
result = USBH_USBD_EntryClass(STRG_CLASS_CODE, &classid, USBH_STRG_ReturnValueCallback, USBH_STRG_DeviceCallback);
if( result != USBH_USBD_STATUS_SUCCESS ){
return STATUS_UNSUCCESSFUL;
}
/* Waiting for the completion of the USBD registration. */
OS_WaiFlg(FLGID_USBH_SAMPLE, FLG_EVENT_USBDENTRY_CMP_USBH_SAMPLE, OS_TWF_ORW, &flgPtn);
OS_ClrFlg(FLGID_USBH_SAMPLE, ~(FLG_EVENT_USBDENTRY_CMP_USBH_SAMPLE));
if(callbackPara.event != USBH_USBD_MSG_ENTRYC_NG ) {
return STATUS_UNSUCCESSFUL;
}
return result;
}
/*=============================================================================================
// Function_Name: USBH_STRG_IFDeviceReset
//
// description : Reset the specified device
//
// The reset demand of the specified device is lodged to the subordinate position module.
// When processing it to the device, that processing is interrupted.
//
// argument : deviceNo (in)Device No.
//
// return : STATUS_SUCCESS Completed successfully
// STATUS_UNSUCCESSFUL Completed with error
//
// flag : OpenFlag Indicates if the module is usable
//
// global : classid The class ID number
===============================================================================================*/
LONG USBH_STRG_IFDeviceReset( USHORT deviceNo )
{
LONG result;
OS_FLGPTN flgPtn;
/* If the URB is in registering, cancel it. */
switch(devicePara[deviceNo].commandStatus) {
case URB_LINK:
USBH_USBD_UnlinkURB(&cbwUrb[deviceNo], classid, USBH_STRG_UnlinkURBCallback);
break;
case CBW_CMP:
USBH_USBD_UnlinkURB(&cbwUrb[deviceNo], classid, USBH_STRG_UnlinkURBCallback);
break;
case DATA_CMP:
USBH_USBD_UnlinkURB(&cbwUrb[deviceNo], classid, USBH_STRG_UnlinkURBCallback);
break;
case CSW_CMP:
devicePara[deviceNo].commandStatus = NO_OP;
break;
}
if(devicePara[deviceNo].commandStatus != NO_OP) {
/* Waiting for the completion of UnlinkURB */
OS_WaiFlg(FLGID_USBH_SAMPLE, FLG_EVENT_UNLINKURB_CMP_USBH_SAMPLE, OS_TWF_ORW, &flgPtn);
OS_ClrFlg(FLGID_USBH_SAMPLE, ~(FLG_EVENT_UNLINKURB_CMP_USBH_SAMPLE));
if(callbackPara.event != USBH_USBD_MSG_UNLINK_OK) {
return STATUS_UNSUCCESSFUL;
} else {
devicePara[deviceNo].commandStatus = NO_OP;
}
}
/* Reset demand for specified device */
result = USBH_USBD_Reset(classid, devicePara[deviceNo].devAdr, USBH_STRG_ResetCallback);
if(result != STATUS_SUCCESS) {
return result;
}
/* Waiting for the URB Reset Complete */
OS_WaiFlg(FLGID_USBH_SAMPLE, FLG_EVENT_USBRESET_CMP_USBH_SAMPLE, OS_TWF_ORW, &flgPtn);
OS_ClrFlg(FLGID_USBH_SAMPLE, ~(FLG_EVENT_USBRESET_CMP_USBH_SAMPLE));
devicePara[deviceNo].deviceStatus = DRV_FUNC_CMD_COMP;
return STATUS_SUCCESS;
}
/*=============================================================================================
// Function_Name: USBH_STRG_IFGetDeviceList
//
// description : It informs the upper layer of the number of connected devices and each device type.
//
// It informs the upper layer of the number of connected devices and each device type.
//
// argument : *pList (in)the pointer that points to the device list.
//
// return : STATUS_SUCCESS Completed successfully
// STATUS_UNSUCCESSFUL Completed with error
===============================================================================================*/
LONG USBH_STRG_IFGetDeviceList( UCHAR *pList )
{
UCHAR i;
/* Change pDeviceList to pList */
((DRIVEACCESS_FUNCDEVICELIST *)pList)->deviceCount = pDeviceList->deviceCount;
for(i=0; i < USBH_STRG_MAX_DEVICE; i++){
if( pDeviceList->deviceType[i] == NO_DEVICE ){
((DRIVEACCESS_FUNCDEVICELIST *)pList)->deviceType[i] = DRV_FUNC_CF;
} else {
((DRIVEACCESS_FUNCDEVICELIST *)pList)->deviceType[i] = pDeviceList->deviceType[i];
}
}
return STATUS_SUCCESS;
}
/*=============================================================================================
// Function_Name: USBH_STRG_IFGetDeviceParameter
//
// description : It informs the upper layer of the detailed information of the connected device.
//
// It informs the upper layer of the detailed information of the connected device.
// Device information is 256 word data that can be acquired with Identify(Packet) Device.
//
// argument : deviceNo (in)Device No.
// *pDataPtr (out)The pointer that points to thedevice information.
//
// return : STATUS_SUCCESS Completed successfully
// STATUS_UNSUCCESSFUL Completed with error
===============================================================================================*/
LONG USBH_STRG_IFGetDeviceParameter( USHORT deviceNo, UCHAR *pDataPtr)
{
UCHAR senseKey = 0x00, inqData[INQUIRY_LENGTH], rdCapaData[8], rdFormCapaData[20];
USHORT i;
LONG result;
ULONG status;
DRIVEACCESS_FUNCCMDPARA cmdBlock;
DRIVEACCESS_FUNCTRANPARA tranPara;
/* Get the device information in the case that the device infornmation unacquisited */
if(devicePara[deviceNo].identifyData[1] == 0x00) {
/* Execute TEST UNIT READY */
result = USBH_STRG_PutCmd(deviceNo, &cmdBlock, TEST_UNIT_READY);
if(result != STATUS_SUCCESS) {
return STATUS_UNSUCCESSFUL;
}
tranPara.dataSize = 0;
/* When error occure,it retry untill becoming No Sense. */
do {
result = USBH_STRG_IFSyncCommand(deviceNo, (UCHAR)devicePara[deviceNo].commandMode, &cmdBlock, &tranPara, &status, devicePara[deviceNo].reqSenseData);
if(result == STATUS_UNSUCCESSFUL) {
senseKey = devicePara[deviceNo].reqSenseData[2] & 0x0F;
/* When error ocured,check the Sense Key */
if(senseKey == HARDWARE_ERROR) {
return STATUS_UNSUCCESSFUL;
}
}
} while(senseKey != NO_SENSE);
/* Execute INQUIRY */
result = USBH_STRG_PutCmd(deviceNo, &cmdBlock, INQUIRY);
if(result != STATUS_SUCCESS) {
return STATUS_UNSUCCESSFUL;
}
tranPara.dataPointer = (ULONG) &inqData[0];
result = USBH_STRG_IFSyncCommand(deviceNo, (UCHAR)devicePara[deviceNo].commandMode, &cmdBlock, &tranPara, &status, devicePara[deviceNo].reqSenseData);
if(result != STATUS_SUCCESS) {
return STATUS_UNSUCCESSFUL;
}
/*** Generate the Identify Data ***/
/* Device Type Set */
devicePara[deviceNo].identifyData[0] = inqData[0] & 0x1F;
/* Update the DeviceTypeof DeviceList */
switch(devicePara[deviceNo].identifyData[0]) {
case DIRECT_DEV:
pDeviceList->deviceType[deviceNo] = DRV_FUNC_HDD;
break;
case WRONCE_DEV:
case CDROM_DEV:
pDeviceList->deviceType[deviceNo] = DRV_FUNC_CD;
break;
case OPTICAL_DEV:
pDeviceList->deviceType[deviceNo] = DRV_FUNC_MO;
break;
default:
break;
}
/* Removable Set */
if( (inqData[1] & 0x80) != 0) {
devicePara[deviceNo].identifyData[1] = inqData[1];
} else {
/* Turned on the Non-Removal Bit at non-Removable device. */
devicePara[deviceNo].identifyData[1] = (~inqData[1]) & 0x40;
}
/* Vendor ID Set */
devicePara[deviceNo].identifyData[54] = inqData[8];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -