📄 mass_bulktrance.c
字号:
#include "HostStack.h"
uint8 BulkGetCSWStatus(transfer_instance *Bulk_tr_In_Ptr, uint8 *CBW_BuffPtr);
void BulkCBWSet( uint8 *CBW_BuffPtr,
uint32 DataTransferLength,
uint8 CBWFlags,
uint8 bCBW_LUN,
uint8 CBWCBLength,
uint8 *RBC_BuffPtr);
uint8 BulkCommand_handle( MassStorageClass *MSC_ptr,
uint8 *CBW_BuffPtr,
uint8 *Data_BuffPtr,
uint8 Tr_Direction,
uint16 *transfer_size);
//******************************************************************************************
// 函数名称:MassStorageReset
// 输入参数:DevicePtr,设备描述信息结构指针
// 输出参数:TRUE,正常完成
// FALSE,出错
// 功能描述:大容量设备复位请求。
//******************************************************************************************
unsigned char MassStorageReset(device_instance * DevicePtr)
{
unsigned char None =0;
USB_Device_Request req; // 设备请求结构
unsigned short err;
req.bmRequestType = 0x21; // 大容量容中的,获取最大单元号
req.bRequest = 0xff;
req.wValue = 0;
req.wIndex = 0;
req.wLength = 0;
err = control_transfer( &req, DevicePtr, &None ); // 发送控制传输
return (err ? FALSE : TRUE);
}
//******************************************************************************************
// 函数名称:GetMaxLUN
// 输入参数:DevicePtr,设备描述信息结构指针
// 输出参数:返回最大逻辑单元数,返回值为0表示只有1个逻辑单元存在。
// 出错返回去0xff.
// 功能描述:获取设备的逻辑单元总数请求。
//******************************************************************************************
unsigned char GetMaxLUN(device_instance * DevicePtr)
{
unsigned char MaxLUN =0;
USB_Device_Request req; // 设备请求结构
req.bmRequestType = 0xa1; // 大容量容中的,获取最大单元号
req.bRequest = 0xfe;
req.wValue = 0;
req.wIndex = 0;
req.wLength = 1;
if ( control_transfer( &req, DevicePtr, &MaxLUN ) ) // 发送控制传输
return ( 0xff );
return (MaxLUN);
}
//*****************************************************************************************
// 函数名称:ResetRecovery
// 输入参数:dvi_ptr,设备描述信息数据结构
// 输出参数:TRUE,正常返回,
// FALSE,出错返回。
// 功能描述:复位恢复处理。
//*****************************************************************************************
uint8 ResetRecovery(device_instance * dvi_ptr)
{
endpoint_info *epi_ptr;
if(FALSE == MassStorageReset(dvi_ptr)) // 大容量设备复位
return FALSE;
epi_ptr = find_endport_type(dvi_ptr, Ep_TransferType_Bulk, Ep_Direction_IN_ENDPOINT, 1);
if(FALSE == ClearEndpointSTALL( dvi_ptr, epi_ptr)) // 清批量输出停止状态
return FALSE;
epi_ptr = find_endport_type(dvi_ptr, Ep_TransferType_Bulk, Ep_Direction_OUT_ENDPOINT, 1);
if(FALSE == ClearEndpointSTALL( dvi_ptr, epi_ptr)) // 清批量输入停止状态
return FALSE;
return TRUE;
}
//*****************************************************************************************
// 函数名称:BulkOnlyTransport
// 输入参数:tr_with_rbc_ptr,设备描述信息数据结构
// 输出参数:COMMAND_PASSED,命令完成
// COMMAND_FAILED,命令失败
// PHASE_ERROR,相位出错
// PERSISTENT_FAILURE,严重出错
// 功能描述:复位恢复处理。
//*****************************************************************************************
uint8 BulkOnlyComHandle(TR_With_RBC *tr_with_rbc_ptr)
{
uint8 CSWStatus;
/* CBW设置 */
BulkCBWSet( tr_with_rbc_ptr->MSC->CBW_BuffPtr,
tr_with_rbc_ptr->DataTransferLength,
tr_with_rbc_ptr->TrDirection,
tr_with_rbc_ptr->LUN,
tr_with_rbc_ptr->CBLength,
tr_with_rbc_ptr->MSC->RBC_BuffPtr
);
/* CBW处理 */
CSWStatus = BulkCommand_handle( tr_with_rbc_ptr->MSC,
tr_with_rbc_ptr->MSC->CBW_BuffPtr,
tr_with_rbc_ptr->Data_BuffPtr,
tr_with_rbc_ptr->TrDirection,
&tr_with_rbc_ptr->DataTransferLength);
if( CSWStatus == FALSE )/* 设备发生了不可纠正的错误 */
return PERSISTENT_FAILURE;
/* 接收CSW */
CSWStatus = BulkGetCSWStatus( tr_with_rbc_ptr->MSC->tr_bulk_in_ptr,
tr_with_rbc_ptr->MSC->CBW_BuffPtr);
/* 返回命令执行状态 */
if(CSWStatus == COMMAND_PASSED)
return COMMAND_PASSED;
if((CSWStatus == 0xff)||(CSWStatus == PHASE_ERROR))
{ /*执行复位恢复*/
if( FALSE == ResetRecovery(tr_with_rbc_ptr->MSC->dvi_ptr))
return PERSISTENT_FAILURE; /* 复位恢复不能正常完成 */
return PHASE_ERROR;
}
if(CSWStatus == COMMAND_FAILED)
return COMMAND_FAILED;
return PERSISTENT_FAILURE;
}
//******************************************************************************************
// 函数名称:BulkCommand_handle
// 输入参数:Bulk_tr_In_Ptr,批量输入传输描述符
// Bulk_tr_Out_Ptr,批量输出传输描述符
// CBW_BuffPtr,命令包缓冲区指针
// Data_BuffPtr,数据缓冲区指针
// Tr_Direction,数据传输方向,输入、输出、无数据
// transfer_size,传输的数据长度。
// 输出参数:TRUE,正常完成
// FALSE,出错
// 功能描述:单批量协议命令处理。
//******************************************************************************************
uint8 BulkCommand_handle( MassStorageClass *MSC_ptr,
uint8 *CBW_BuffPtr,
uint8 *Data_BuffPtr,
uint8 Tr_Direction,
uint16 *transfer_size)
{
uint8 Completion_Code;
uint16 CBW_size;
device_instance *dvi_ptr;
endpoint_info *epi_ptr;
/* 命令包输出 */
CBW_size = 31; /* 包长度固定为31字节 */
Completion_Code = bulk_transaction( DirectionPID_OUT, CBW_BuffPtr, &CBW_size, MSC_ptr->tr_bulk_out_ptr);
if(Completion_Code)
return FALSE; // 没有定义的错误
if(Tr_Direction == IN_DATA)
Completion_Code = bulk_transaction(DirectionPID_IN,Data_BuffPtr, transfer_size, MSC_ptr->tr_bulk_in_ptr);
if(Tr_Direction ==OUT_DATA)
Completion_Code = bulk_transaction(DirectionPID_OUT,Data_BuffPtr, transfer_size, MSC_ptr->tr_bulk_out_ptr);
if(Completion_Code)
{
if(Completion_Code == 0x04) // 如果端点停止
{
if(Tr_Direction == IN_DATA) // 清批量输入端点STALL
{
epi_ptr = MSC_ptr->tr_bulk_in_ptr->epi_ptr; // 端点描述信息数据结构指针
dvi_ptr = MSC_ptr->dvi_ptr; // 设备描述信息数据结构指针
return ClearEndpointSTALL( dvi_ptr, epi_ptr);
}
if(Tr_Direction ==OUT_DATA) // 清批量输出端点STALL
{
epi_ptr = MSC_ptr->tr_bulk_out_ptr->epi_ptr; // 端点描述信息数据结构指针
dvi_ptr = MSC_ptr->dvi_ptr; // 设备描述信息数据结构指针
return ClearEndpointSTALL( dvi_ptr, epi_ptr);
}
}
if(Completion_Code == 0x09)
return TRUE;
return FALSE; // 没有定义的错误
}
return TRUE; // 没有定义的错误
}
//************************************************************************************
// 函数名称:BulkGetCSWStatus
// 输入参数:Bulk_tr_In_Ptr,批量输入传输描述符
// CBW_BuffPtr,命令块包缓冲区指针
// 输出参数:正常返回命令状态:0、1、2
// 出错返回0xff;
// 功能描述:获取命令状态包
//************************************************************************************
uint8 BulkGetCSWStatus(transfer_instance *Bulk_tr_In_Ptr, uint8 *CBW_BuffPtr)
{
#define CSW_LENGTH 13
COMMAND_STATUS_WRAPPER CSWB;
uint8 CSWStatus;
uint16 transfer_size = CSW_LENGTH;
uint32 dCSWDataResidue;
uint32 dCBW_DataXferLen;
COMMAND_BLOCK_WRAPPER *CBW_ptr;
CBW_ptr = (COMMAND_BLOCK_WRAPPER *) CBW_BuffPtr;
CSWStatus = bulk_transaction(DirectionPID_IN, (uint8 *)&CSWB,
&transfer_size, Bulk_tr_In_Ptr);
if(CSWStatus==NULL)
{
/* 检验CSW是否有效 */
if(transfer_size == CSW_LENGTH)
if((CSWB.dCSW_Signature_0==0x55)&&
(CSWB.dCSW_Signature_1==0x53)&&
(CSWB.dCSW_Signature_2==0x42)&&
(CSWB.dCSW_Signature_3==0x53)&&
(CSWB.dCSW_Tag == CBW_ptr->dCBW_Tag))
{ /* 检验CSW是否有意义 */
if(CSWB.bCSW_Status==PHASE_ERROR)
return (PHASE_ERROR);
if(CSWB.bCSW_Status < PHASE_ERROR)
{
dCSWDataResidue = CSWB.dCSW_DataResidue_0+
CSWB.dCSW_DataResidue_1*0x100+
CSWB.dCSW_DataResidue_2*0x10000+
CSWB.dCSW_DataResidue_3*0x1000000;
dCBW_DataXferLen = CBW_ptr->dCBW_DataXferLen_0+
CBW_ptr->dCBW_DataXferLen_1*0x100+
CBW_ptr->dCBW_DataXferLen_2*0x10000+
CBW_ptr->dCBW_DataXferLen_3*0x1000000;
if(dCSWDataResidue <= dCBW_DataXferLen)
return CSWB.bCSW_Status;
}
}
}
return (0xff);
}
//************************************************************************************
// 函数名称:BulkCBWSet
// 输入参数:CBW_BuffPtr,命令包缓冲区指针
// DataTransferLength,数据传输的字节数
// CBWFlags,传输的方向,0为主机到设备、非0设备到主机。
// CBWCBLength,命令有效长度
// RBC_BuffPtr,命令缓冲区指针
// 输出参数:无
// 功能描述:大容量单批量传输CBW设置
//************************************************************************************
void BulkCBWSet( uint8 *CBW_BuffPtr,
uint32 DataTransferLength,
uint8 CBWFlags,
uint8 bCBW_LUN,
uint8 CBWCBLength,
uint8 *RBC_BuffPtr)
{
COMMAND_BLOCK_WRAPPER *CBW_ptr;
uint8 *RBC_in_CBW_ptr;
CBW_ptr = (COMMAND_BLOCK_WRAPPER *) CBW_BuffPtr;
/* 固定特征码在初始化时已设置并一直保持 */
CBW_ptr->dCBW_Tag ++;
CBW_ptr->dCBW_DataXferLen_0 = (uint8)DataTransferLength;
CBW_ptr->dCBW_DataXferLen_1 = (uint8)(DataTransferLength/0x100);
CBW_ptr->dCBW_DataXferLen_2 = (uint8)(DataTransferLength/0x10000);
CBW_ptr->dCBW_DataXferLen_3 = (uint8)(DataTransferLength/0x1000000);
CBW_ptr->bCBW_Flag = (CBWFlags == OUT_DATA)? 0x00 :0x80 ;
CBW_ptr->bCBW_LUN = bCBW_LUN;
CBW_ptr->bCBW_CDBLength = CBWCBLength;
RBC_in_CBW_ptr = &CBW_ptr->bCBW_CDBLength +1;
memset(RBC_in_CBW_ptr,0,16);
memcpy( RBC_in_CBW_ptr , RBC_BuffPtr, CBWCBLength );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -