?? usbdisk.c
字號(hào):
s = HostCtrlTransfer374( SetupGetCfgDescr, buf, &len ); // 執(zhí)行控制傳輸
if ( s == ERR_SUCCESS ) {
if ( len < ( (PUSB_SETUP_REQ)SetupGetCfgDescr ) -> wLengthL ) s = USB_INT_BUF_OVER; // 返回長(zhǎng)度錯(cuò)誤
else {
memcpy ( BufLogDescr, SetupGetCfgDescr, sizeof( SetupGetCfgDescr ) );
( (PUSB_SETUP_REQ)BufLogDescr ) -> wLengthL = ( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL; // 完整配置描述符的總長(zhǎng)度
s = HostCtrlTransfer374( BufLogDescr, buf, &len ); // 執(zhí)行控制傳輸
if ( s == ERR_SUCCESS ) {
if ( len < ( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL ) s = USB_INT_BUF_OVER; // 描述符長(zhǎng)度錯(cuò)誤
}
}
}
return( s );
}
UINT8 SetUsbAddress( UINT8 addr ) // 設(shè)置USB設(shè)備地址
{
UINT8 s;
UINT8 BufSetAddr[ sizeof( SetupSetUsbAddr ) ] ;
memcpy ( BufSetAddr, SetupSetUsbAddr, sizeof( SetupSetUsbAddr ) );
( (PUSB_SETUP_REQ)BufSetAddr ) -> wValueL = addr; // USB設(shè)備地址
s = HostCtrlTransfer374( BufSetAddr, NULL, NULL ); // 執(zhí)行控制傳輸
if ( s == ERR_SUCCESS ) {
SetHostUsbAddr( addr ); // 設(shè)置USB主機(jī)當(dāng)前操作的USB設(shè)備地址
}
mDelaymS( 3 ); // 等待USB設(shè)備完成操作
return( s );
}
UINT8 SetUsbConfig( UINT8 cfg ) // 設(shè)置USB設(shè)備配置
{
UINT8 BufSetCfg[ sizeof( SetupSetUsbConfig ) ] ;
memcpy ( BufSetCfg, SetupSetUsbConfig, sizeof( SetupSetUsbConfig ) );
( (PUSB_SETUP_REQ)BufSetCfg ) -> wValueL = cfg; // USB設(shè)備配置
return( HostCtrlTransfer374( BufSetCfg, NULL, NULL ) ); // 執(zhí)行控制傳輸
}
/* ********** BulkOnly傳輸協(xié)議層 ********** */
#ifdef BIG_ENDIAN
#define USB_BO_CBW_SIG 0x55534243 /* 命令塊CBW識(shí)別標(biāo)志'USBC' */
#define USB_BO_CSW_SIG 0x55534253 /* 命令狀態(tài)塊CSW識(shí)別標(biāo)志'USBS' */
#else
#define USB_BO_CBW_SIG 0x43425355 /* 命令塊CBW識(shí)別標(biāo)志'USBC' */
#define USB_BO_CSW_SIG 0x53425355 /* 命令狀態(tài)塊CSW識(shí)別標(biāo)志'USBS' */
#endif
#define USB_BO_CBW_SIZE 0x1F /* 命令塊CBW的總長(zhǎng)度 */
#define USB_BO_CSW_SIZE 0x0D /* 命令狀態(tài)塊CSW的總長(zhǎng)度 */
typedef union _BULK_ONLY_CMD {
struct {
UINT32 mCBW_Sig;
UINT32 mCBW_Tag;
UINT32 mCBW_DataLen; /* 輸入: 數(shù)據(jù)傳輸長(zhǎng)度 */
UINT8 mCBW_Flag; /* 輸入: 傳輸方向等標(biāo)志 */
UINT8 mCBW_LUN;
UINT8 mCBW_CB_Len; /* 輸入: 命令塊的長(zhǎng)度,有效值是1到16 */
UINT8 mCBW_CB_Buf[16]; /* 輸入: 命令塊,該緩沖區(qū)最多為16個(gè)字節(jié) */
} mCBW; /* BulkOnly協(xié)議的命令塊, 輸入CBW結(jié)構(gòu) */
struct {
UINT32 mCSW_Sig;
UINT32 mCSW_Tag;
UINT32 mCSW_Residue; /* 返回: 剩余數(shù)據(jù)長(zhǎng)度 */
UINT8 mCSW_Status; /* 返回: 命令執(zhí)行結(jié)果狀態(tài) */
} mCSW; /* BulkOnly協(xié)議的命令狀態(tài)塊, 輸出CSW結(jié)構(gòu) */
} BULK_ONLY_CMD;
BULK_ONLY_CMD idata mBOC; /* BulkOnly傳輸結(jié)構(gòu) */
UINT8 mSaveUsbPid; /* 保存最近一次執(zhí)行的事務(wù)PID */
UINT8 mSaveDevEndpTog; /* 保存當(dāng)前批量端點(diǎn)的同步標(biāo)志 */
UINT8 mDiskBulkInEndp; /* IN端點(diǎn)地址 */
UINT8 mDiskBulkOutEndp; /* OUT端點(diǎn)地址 */
UINT8 mDiskInterfNumber; /* 接口號(hào) */
/* 檢查磁盤是否連接 */
// 返回: ERR_SUCCESS 已經(jīng)連接, USB_INT_CONNECT剛連接, USB_INT_DISCONNECT斷開
UINT8 IsDiskConnect( void )
{
if ( Read374Byte( REG_INTER_FLAG ) & BIT_IF_DEV_DETECT ) { /* 檢測(cè)到插拔事件 */
SetHostUsbAddr( 0x00 );
HostSetBusFree( ); // USB總線空閑
Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT | BIT_IF_TRANSFER ); /* 清中斷標(biāo)志 */
if ( Read374Byte( REG_INTER_FLAG ) & BIT_IF_DEV_ATTACH ) return( USB_INT_CONNECT ); /* USB設(shè)備處于連接狀態(tài) */
return( USB_INT_DISCONNECT );
}
if ( Read374Byte( REG_INTER_FLAG ) & BIT_IF_DEV_ATTACH ) { /* USB設(shè)備處于連接狀態(tài) */
return( ERR_SUCCESS ); /* 連接狀態(tài) */
}
return( USB_INT_DISCONNECT );
}
/* 傳輸事務(wù),需預(yù)先輸入mSaveUsbPid,PID令牌+目的端點(diǎn)地址,同步標(biāo)志,返回同CH375,NAK重試,出錯(cuò)重試 */
UINT8 HostTransactInter( void )
{
UINT8 s, r, retry;
for ( retry = 3; retry != 0; retry -- ) { /* 錯(cuò)誤重試計(jì)數(shù) */
s = Wait374Interrupt( );
if ( s == ERR_USB_UNKNOWN ) return( s ); // 中斷超時(shí),可能是硬件異常
s = Read374Byte( REG_INTER_FLAG ); // 獲取中斷狀態(tài)
if ( s & BIT_IF_DEV_DETECT ) { /* USB設(shè)備插拔事件 */
mDelayuS( 200 ); // 等待傳輸完成
Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT | BIT_IF_TRANSFER ); // 清中斷標(biāo)志
if ( s & BIT_IF_DEV_ATTACH ) { /* USB設(shè)備連接事件 */
if ( s & BIT_IF_USB_DX_IN ) { /* 速度匹配,不需要切換速度 */
return( USB_INT_CONNECT ); /* 全速USB設(shè)備 */
}
else { /* 速度失配,需要切換速度 */
return( USB_INT_CONNECT_LS ); /* 低速USB設(shè)備 */
}
}
else { /* USB設(shè)備斷開事件 */
return( USB_INT_DISCONNECT );
}
}
else if ( s & BIT_IF_TRANSFER ) { /* 傳輸完成 */
Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_TRANSFER ); /* 清中斷標(biāo)志 */
s = Read374Byte( REG_USB_STATUS ); /* USB狀態(tài) */
r = s & BIT_STAT_DEV_RESP; /* USB設(shè)備應(yīng)答狀態(tài) */
if ( mSaveUsbPid == DEF_USB_PID_IN ) { /* IN */
if ( M_IS_HOST_IN_DATA( s ) ) { /* DEF_USB_PID_DATA0 or DEF_USB_PID_DATA1 */
if ( s & BIT_STAT_TOG_MATCH ) return( ERR_SUCCESS ); /* IN數(shù)據(jù)同步,操作成功 */
goto mHostTransRetry; /* 不同步則需丟棄后重試 */
}
}
else { /* OUT */
if ( r == DEF_USB_PID_ACK ) return( ERR_SUCCESS ); /* OUT or SETUP,操作成功 */
}
if ( r == DEF_USB_PID_NAK ) { /* NAK重試 */
retry ++;
goto mHostTransRetry;
}
else if ( ! M_IS_HOST_TIMEOUT( s ) ) return( r | 0x20 ); /* 錯(cuò)誤或者無(wú)需重試或者意外應(yīng)答,不是超時(shí)/出錯(cuò) */
}
else { /* 其它中斷,不應(yīng)該發(fā)生的情況 */
mDelayuS( 200 ); // 等待傳輸完成
Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_INTER_FLAG ); // 清中斷標(biāo)志
}
mHostTransRetry:
if ( retry > 1 ) { /* 繼續(xù)重試 */
Write374Byte( REG_USB_H_CTRL, Read374Byte( REG_USB_H_CTRL ) | BIT_HOST_START ); /* 再次啟動(dòng)傳輸 */
}
}
return( 0x20 ); /* 應(yīng)答超時(shí) */
}
/* 設(shè)置批量數(shù)據(jù)輸入 */
void mSetBulkIn( void )
{
mSaveUsbPid = DEF_USB_PID_IN; /* 輸入 */
Write374Byte( REG_USB_H_PID, M_MK_HOST_PID_ENDP( DEF_USB_PID_IN, mDiskBulkInEndp ) ); /* 指定令牌PID和目的端點(diǎn)號(hào) */
Write374Byte( REG_USB_H_CTRL, mSaveDevEndpTog | BIT_HOST_START ); /* 設(shè)置同步標(biāo)志并啟動(dòng)傳輸 */
}
/* 設(shè)置批量數(shù)據(jù)輸出 */
void mSetBulkOut( void )
{
mSaveUsbPid = DEF_USB_PID_OUT; /* 輸出 */
Write374Byte( REG_USB_H_PID, M_MK_HOST_PID_ENDP( DEF_USB_PID_OUT, mDiskBulkOutEndp ) ); /* 指定令牌PID和目的端點(diǎn)號(hào) */
Write374Byte( REG_USB_H_CTRL, mSaveDevEndpTog | BIT_HOST_START ); /* 設(shè)置同步標(biāo)志并啟動(dòng)傳輸 */
}
/* 大小端數(shù)據(jù)轉(zhuǎn)換 */
UINT32 mSwapEndian( UINT32 dat )
{
return( ( dat << 24 ) & 0xFF000000 | ( dat << 8 ) & 0x00FF0000 | ( dat >> 8 ) & 0x0000FF00 | ( dat >> 24 ) & 0x000000FF );
}
UINT8 mClearEndpStall( UINT8 endp )
{
UINT8 ReqBuf[ sizeof( SetupClrEndpStall ) ];
memcpy( ReqBuf, SetupClrEndpStall, sizeof( SetupClrEndpStall ) ); // 清除端點(diǎn)的錯(cuò)誤
( (PUSB_SETUP_REQ)ReqBuf ) -> wIndexL = endp; // 端點(diǎn)地址
return( HostCtrlTransfer374( ReqBuf, NULL, NULL ) ); /* 清除端點(diǎn)的錯(cuò)誤 */
}
UINT8 mResetErrorBOC( UINT8 LastError )
{
UINT8 s;
UINT8 ReqBuf[ sizeof( BoResetUsbDisk ) ];
s = IsDiskConnect( ); // 檢查U盤是否連接
if ( s != ERR_SUCCESS ) return( s ); // 斷開或者剛連接
memcpy( ReqBuf, BoResetUsbDisk, sizeof( BoResetUsbDisk ) ); // 復(fù)位USB存儲(chǔ)器
( (PUSB_SETUP_REQ)ReqBuf ) -> wIndexL = mDiskInterfNumber; // 接口號(hào)
s = HostCtrlTransfer374( ReqBuf, NULL, NULL ); // 執(zhí)行控制傳輸
if ( s == USB_INT_DISCONNECT ) return( s ); /* 檢測(cè)到USB設(shè)備斷開事件,磁盤已經(jīng)斷開 */
mClearEndpStall( mDiskBulkInEndp | 0x80 ); /* 清除IN端點(diǎn)錯(cuò)誤 */
mClearEndpStall( mDiskBulkOutEndp ); /* 清除OUT端點(diǎn)錯(cuò)誤 */
mSaveDevEndpTog &= ~ ( BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG );
return( LastError ); /* 返回原錯(cuò)誤碼 */
}
/* 執(zhí)行基于BulkOnly協(xié)議的命令,該子程序比較簡(jiǎn)化,并未處理各種錯(cuò)誤,實(shí)際應(yīng)用必須處理 */
UINT8 mBulkOnlyCmd( PUINT8 DataBuf )
{
UINT8 s, len;
UINT32 TotalLen;
mBOC.mCBW.mCBW_Sig = USB_BO_CBW_SIG;
mBOC.mCBW.mCBW_Tag = 0x03740374;
mBOC.mCBW.mCBW_LUN = 0;
Write374Block( RAM_HOST_TRAN, USB_BO_CBW_SIZE, (PUINT8)( & mBOC.mCBW ) ); /* 向CH374主機(jī)端點(diǎn)的發(fā)送緩沖區(qū)寫入CBW */
Write374Byte( REG_USB_LENGTH, USB_BO_CBW_SIZE );
mSetBulkOut( ); /* 輸出 */
#ifdef DEBUG_NOW
printf( "*B:C=%02XH\n", (UINT16)( mBOC.mCBW.mCBW_CB_Buf[0] ) );
#endif
s = HostTransactInter( ); /* 向USB盤的OUT端點(diǎn)輸出CBW */
if ( s == USB_INT_DISCONNECT ) return( s ); /* 檢測(cè)到USB設(shè)備斷開事件,磁盤已經(jīng)斷開 */
if ( s != ERR_SUCCESS ) { /* 發(fā)送CBW失敗 */
#ifdef DEBUG_NOW
printf( "*B:C1=%02XH\n", (UINT16)s );
#endif
mResetErrorBOC( s );
Write374Block( RAM_HOST_TRAN, USB_BO_CBW_SIZE, (PUINT8)( & mBOC.mCBW ) ); /* 向CH374主機(jī)端點(diǎn)的發(fā)送緩沖區(qū)寫入CBW */
Write374Byte( REG_USB_LENGTH, USB_BO_CBW_SIZE );
mSetBulkOut( ); /* 輸出 */
#ifdef DEBUG_NOW
printf( "*B:C2=%02XH\n", (UINT16)( mBOC.mCBW.mCBW_CB_Buf[0] ) );
#endif
s = HostTransactInter( ); /* 向USB盤的OUT端點(diǎn)輸出CBW */
if ( s != ERR_SUCCESS ) return( mResetErrorBOC( s ) );
}
mSaveDevEndpTog ^= BIT_HOST_TRAN_TOG; /* OUT端點(diǎn)的數(shù)據(jù)同步標(biāo)志翻轉(zhuǎn) */
if ( mBOC.mCBW.mCBW_DataLen ) { /* 有數(shù)據(jù)需要傳輸,此處使用雙緩沖區(qū)提高效率,但導(dǎo)致程序復(fù)雜 */
#ifdef BIG_ENDIAN
TotalLen = mSwapEndian( mBOC.mCBW.mCBW_DataLen );
#else
TotalLen = mBOC.mCBW.mCBW_DataLen;
#endif
#ifdef CH374_DOUBLE_BUF
if ( mBOC.mCBW.mCBW_Flag & 0x80 ) { /* 接收 */
Write374Byte( REG_USB_SETUP, M_SET_RAM_MODE_2RX( BIT_SETP_HOST_MODE | BIT_SETP_AUTO_SOF ) ); /* 全速USB主機(jī)模式,USB總線空閑,發(fā)SOF,雙緩沖區(qū) */
mSetBulkIn( ); /* 輸入 */
while ( TotalLen ) { /* 有數(shù)據(jù)需要傳輸 */
#ifdef DEBUG_NOW
printf( "*B:I=%lX\n", TotalLen );
#endif
s = HostTransactInter( ); /* 接收數(shù)據(jù) */
if ( s != ERR_SUCCESS ) { /* 操作失敗 */
if ( s == ( DEF_USB_PID_STALL | 0x20 ) ) mClearEndpStall( mDiskBulkInEndp | 0x80 ); /* 清除端點(diǎn)錯(cuò)誤 */
break;
}
mSaveDevEndpTog ^= BIT_HOST_RECV_TOG; /* IN端點(diǎn)的數(shù)據(jù)同步標(biāo)志翻轉(zhuǎn) */
len = Read374Byte( REG_USB_LENGTH );
if ( TotalLen > len ) TotalLen -= len;
else TotalLen = 0;
if ( len == 64 && TotalLen ) mSetBulkIn( ); /* 準(zhǔn)備下一次輸入 */
Read374Block( mSaveDevEndpTog & BIT_HOST_RECV_TOG ? RAM_HOST_RECV : RAM_HOST_EXCH, len, DataBuf );
DataBuf += len;
if ( len < 64 ) break;
}
}
else { /* 發(fā)送 */
Write374Byte( REG_USB_SETUP, M_SET_RAM_MODE_2TX( BIT_SETP_HOST_MODE | BIT_SETP_AUTO_SOF ) ); /* 全速USB主機(jī)模式,USB總線空閑,發(fā)SOF,雙緩沖區(qū) */
len = TotalLen >= 64 ? 64 : TotalLen;
Write374Block( mSaveDevEndpTog & BIT_HOST_TRAN_TOG ? RAM_HOST_EXCH : RAM_HOST_TRAN, len, DataBuf );
Write374Byte( REG_USB_LENGTH, len );
mSetBulkOut( ); /* 輸出 */
while ( TotalLen ) { /* 有數(shù)據(jù)需要傳輸 */
#ifdef DEBUG_NOW
printf( "*B:O=%lX\n", TotalLen );
#endif
TotalLen -= len;
DataBuf += len;
if ( len == 64 && TotalLen ) { /* 準(zhǔn)備下一次輸出 */
len = TotalLen >= 64 ? 64 : TotalLen;
Write374Block( mSaveDevEndpTog & BIT_HOST_TRAN_TOG ? RAM_HOST_TRAN : RAM_HOST_EXCH, len, DataBuf );
}
else len = 0;
s = HostTransactInter( ); /* 發(fā)送數(shù)據(jù) */
if ( s != ERR_SUCCESS ) { /* 操作失敗 */
if ( s == ( DEF_USB_PID_STALL | 0x20 ) ) mClearEndpStall( mDiskBulkOutEndp ); /* 清除端點(diǎn)錯(cuò)誤 */
break;
}
mSaveDevEndpTog ^= BIT_HOST_TRAN_TOG; /* OUT端點(diǎn)的數(shù)據(jù)同步標(biāo)志翻轉(zhuǎn) */
if ( len ) {
Write374Byte( REG_USB_LENGTH, len );
mSetBulkOut( ); /* 輸出 */
}
else break;
}
}
Write374Byte( REG_USB_SETUP, M_SET_RAM_MODE_OFF( BIT_SETP_HOST_MODE | BIT_SETP_AUTO_SOF ) ); /* 全速USB主機(jī)模式,USB總線空閑,發(fā)SOF */
#else
if ( mBOC.mCBW.mCBW_Flag & 0x80 ) { /* 接收 */
while ( TotalLen ) { /* 有數(shù)據(jù)需要傳輸 */
#ifdef DEBUG_NOW
printf( "*B:I=%lX\n", TotalLen );
#endif
mSetBulkIn( ); /* 輸入 */
s = HostTransactInter( ); /* 接收數(shù)據(jù) */
if ( s != ERR_SUCCESS ) { /* 操作失敗 */
if ( s == ( DEF_USB_PID_STALL | 0x20 ) ) mClearEndpStall( mDiskBulkInEndp | 0x80 ); /* 清除端點(diǎn)錯(cuò)誤 */
break;
}
len = Read374Byte( REG_USB_LENGTH );
Read374Block( RAM_HOST_RECV, len, DataBuf );
if ( TotalLen > len ) TotalLen -= len;
else TotalLen = 0;
DataBuf += len;
mSaveDevEndpTog ^= BIT_HOST_RECV_TOG; /* IN端點(diǎn)的數(shù)據(jù)同步標(biāo)志翻轉(zhuǎn) */
if ( len < 64 ) break;
}
}
else { /* 發(fā)送 */
while ( TotalLen ) { /* 有數(shù)據(jù)需要傳輸 */
#ifdef DEBUG_NOW
printf( "*B:O=%lX\n", TotalLen );
#endif
len = TotalLen >= 64 ? 64 : TotalLen;
Write374Block( RAM_HOST_TRAN, len, DataBuf );
Write374Byte( REG_USB_LENGTH, len );
mSetBulkOut( ); /* 輸出 */
TotalLen -= len;
DataBuf += len;
s = HostTransactInter( ); /* 發(fā)送數(shù)據(jù) */
if ( s != ERR_SUCCESS ) { /* 操作失敗 */
if ( s == ( DEF_USB_PID_STALL | 0x20 ) ) mClearEndpStall( mDiskBulkOutEndp ); /* 清除端點(diǎn)錯(cuò)誤 */
break;
}
mSaveDevEndpTog ^= BIT_HOST_TRAN_TOG; /* OUT端點(diǎn)的數(shù)據(jù)同步標(biāo)志翻轉(zhuǎn) */
if ( len < 64 ) break;
}
}
#endif
if ( s != ERR_SUCCESS ) { /* 數(shù)據(jù)傳輸失敗 */
if ( s != ( DEF_USB_PID_STALL | 0x20 ) ) return( s );
}
}
mSetBulkIn( ); /* 輸入 */
#ifdef DEBUG_NOW
printf( "*B:S\n" );
#endif
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -