⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbdisk.c

📁 USB驱动程序 共写USB单片机开发者使用
💻 C
📖 第 1 页 / 共 3 页
字号:
	s = HostCtrlTransfer374( SetupGetCfgDescr, buf, &len );  // 执行控制传输
	if ( s == ERR_SUCCESS ) {
		if ( len < ( (PUSB_SETUP_REQ)SetupGetCfgDescr ) -> wLengthL ) s = USB_INT_BUF_OVER;  // 返回长度错误
		else {
			memcpy ( BufLogDescr, SetupGetCfgDescr, sizeof( SetupGetCfgDescr ) );
			( (PUSB_SETUP_REQ)BufLogDescr ) -> wLengthL = ( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL;  // 完整配置描述符的总长度
			s = HostCtrlTransfer374( BufLogDescr, buf, &len );  // 执行控制传输
			if ( s == ERR_SUCCESS ) {
				if ( len < ( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL ) s = USB_INT_BUF_OVER;  // 描述符长度错误
			}
		}
	}
	return( s );
}

UINT8	SetUsbAddress( UINT8 addr )  // 设置USB设备地址
{
	UINT8	s;
	UINT8	BufSetAddr[ sizeof( SetupSetUsbAddr ) ] ;
	memcpy ( BufSetAddr, SetupSetUsbAddr, sizeof( SetupSetUsbAddr ) );
	( (PUSB_SETUP_REQ)BufSetAddr ) -> wValueL = addr;  // USB设备地址
	s = HostCtrlTransfer374( BufSetAddr, NULL, NULL );  // 执行控制传输
	if ( s == ERR_SUCCESS ) {
		SetHostUsbAddr( addr );  // 设置USB主机当前操作的USB设备地址
	}
	mDelaymS( 3 );  // 等待USB设备完成操作
	return( s );
}

UINT8	SetUsbConfig( UINT8 cfg )  // 设置USB设备配置
{
	UINT8	BufSetCfg[ sizeof( SetupSetUsbConfig ) ] ;
	memcpy ( BufSetCfg, SetupSetUsbConfig, sizeof( SetupSetUsbConfig ) );
	( (PUSB_SETUP_REQ)BufSetCfg ) -> wValueL = cfg;  // USB设备配置
	return( HostCtrlTransfer374( BufSetCfg, NULL, NULL ) );  // 执行控制传输
}

/* ********** BulkOnly传输协议层 ********** */

#ifdef BIG_ENDIAN
#define USB_BO_CBW_SIG		0x55534243	/* 命令块CBW识别标志'USBC' */
#define USB_BO_CSW_SIG		0x55534253	/* 命令状态块CSW识别标志'USBS' */
#else
#define USB_BO_CBW_SIG		0x43425355	/* 命令块CBW识别标志'USBC' */
#define USB_BO_CSW_SIG		0x53425355	/* 命令状态块CSW识别标志'USBS' */
#endif

#define USB_BO_CBW_SIZE			0x1F	/* 命令块CBW的总长度 */
#define USB_BO_CSW_SIZE			0x0D	/* 命令状态块CSW的总长度 */

typedef union _BULK_ONLY_CMD {
	struct {
		UINT32	mCBW_Sig;
		UINT32	mCBW_Tag;
		UINT32	mCBW_DataLen;			/* 输入: 数据传输长度 */
		UINT8	mCBW_Flag;				/* 输入: 传输方向等标志 */
		UINT8	mCBW_LUN;
		UINT8	mCBW_CB_Len;			/* 输入: 命令块的长度,有效值是1到16 */
		UINT8	mCBW_CB_Buf[16];		/* 输入: 命令块,该缓冲区最多为16个字节 */
	} mCBW;								/* BulkOnly协议的命令块, 输入CBW结构 */
	struct {
		UINT32	mCSW_Sig;
		UINT32	mCSW_Tag;
		UINT32	mCSW_Residue;			/* 返回: 剩余数据长度 */
		UINT8	mCSW_Status;			/* 返回: 命令执行结果状态 */
	} mCSW;								/* BulkOnly协议的命令状态块, 输出CSW结构 */
} BULK_ONLY_CMD;

BULK_ONLY_CMD	idata	mBOC;			/* BulkOnly传输结构 */
UINT8			mSaveUsbPid;			/* 保存最近一次执行的事务PID */
UINT8			mSaveDevEndpTog;		/* 保存当前批量端点的同步标志 */
UINT8			mDiskBulkInEndp;		/* IN端点地址 */
UINT8			mDiskBulkOutEndp;		/* OUT端点地址 */
UINT8			mDiskInterfNumber;		/* 接口号 */

/* 检查磁盘是否连接 */
// 返回: ERR_SUCCESS 已经连接, USB_INT_CONNECT刚连接, USB_INT_DISCONNECT断开
UINT8	IsDiskConnect( void )
{
	if ( Read374Byte( REG_INTER_FLAG ) & BIT_IF_DEV_DETECT ) {  /* 检测到插拔事件 */
		SetHostUsbAddr( 0x00 );
		HostSetBusFree( );  // USB总线空闲
		Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT | BIT_IF_TRANSFER );  /* 清中断标志 */
		if ( Read374Byte( REG_INTER_FLAG ) & BIT_IF_DEV_ATTACH ) return( USB_INT_CONNECT );  /* USB设备处于连接状态 */
		return( USB_INT_DISCONNECT );
	}
	if ( Read374Byte( REG_INTER_FLAG ) & BIT_IF_DEV_ATTACH ) {  /* USB设备处于连接状态 */
		return( ERR_SUCCESS );  /* 连接状态 */
	}
	return( USB_INT_DISCONNECT );
}

/* 传输事务,需预先输入mSaveUsbPid,PID令牌+目的端点地址,同步标志,返回同CH375,NAK重试,出错重试 */
UINT8	HostTransactInter( void )
{
	UINT8	s, r, retry;
	for ( retry = 3; retry != 0; retry -- ) {  /* 错误重试计数 */
		s = Wait374Interrupt( );
		if ( s == ERR_USB_UNKNOWN ) return( s );  // 中断超时,可能是硬件异常
		s = Read374Byte( REG_INTER_FLAG );  // 获取中断状态
		if ( s & BIT_IF_DEV_DETECT ) {  /* USB设备插拔事件 */
			mDelayuS( 200 );  // 等待传输完成
			Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT | BIT_IF_TRANSFER );  // 清中断标志
			if ( s & BIT_IF_DEV_ATTACH ) {  /* USB设备连接事件 */
				if ( s & BIT_IF_USB_DX_IN ) {  /* 速度匹配,不需要切换速度 */
					return( USB_INT_CONNECT );  /* 全速USB设备 */
				}
				else {  /* 速度失配,需要切换速度 */
					return( USB_INT_CONNECT_LS );  /* 低速USB设备 */
				}
			}
			else {  /* USB设备断开事件 */
				return( USB_INT_DISCONNECT );
			}
		}
		else if ( s & BIT_IF_TRANSFER ) {  /* 传输完成 */
			Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_TRANSFER );  /* 清中断标志 */
			s = Read374Byte( REG_USB_STATUS );  /* USB状态 */
			r = s & BIT_STAT_DEV_RESP;  /* USB设备应答状态 */
			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数据同步,操作成功 */
					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 );  /* 错误或者无需重试或者意外应答,不是超时/出错 */
		}
		else {  /* 其它中断,不应该发生的情况 */
			mDelayuS( 200 );  // 等待传输完成
			Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_INTER_FLAG );  // 清中断标志
		}
mHostTransRetry:
		if ( retry > 1 ) {  /* 继续重试 */
			Write374Byte( REG_USB_H_CTRL, Read374Byte( REG_USB_H_CTRL ) | BIT_HOST_START );  /* 再次启动传输 */
		}
	}
	return( 0x20 );  /* 应答超时 */
}

/* 设置批量数据输入 */
void	mSetBulkIn( void )
{
	mSaveUsbPid = DEF_USB_PID_IN;  /* 输入 */
	Write374Byte( REG_USB_H_PID, M_MK_HOST_PID_ENDP( DEF_USB_PID_IN, mDiskBulkInEndp ) );  /* 指定令牌PID和目的端点号 */
	Write374Byte( REG_USB_H_CTRL, mSaveDevEndpTog | BIT_HOST_START );  /* 设置同步标志并启动传输 */
}

/* 设置批量数据输出 */
void	mSetBulkOut( void )
{
	mSaveUsbPid = DEF_USB_PID_OUT;  /* 输出 */
	Write374Byte( REG_USB_H_PID, M_MK_HOST_PID_ENDP( DEF_USB_PID_OUT, mDiskBulkOutEndp ) );  /* 指定令牌PID和目的端点号 */
	Write374Byte( REG_USB_H_CTRL, mSaveDevEndpTog | BIT_HOST_START );  /* 设置同步标志并启动传输 */
}

/* 大小端数据转换 */
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 ) );  // 清除端点的错误
	( (PUSB_SETUP_REQ)ReqBuf ) -> wIndexL = endp;  // 端点地址
	return( HostCtrlTransfer374( ReqBuf, NULL, NULL ) );  /* 清除端点的错误 */
}

UINT8	mResetErrorBOC( UINT8 LastError )
{
	UINT8	s;
	UINT8	ReqBuf[ sizeof( BoResetUsbDisk ) ];
	s = IsDiskConnect( );  // 检查U盘是否连接
	if ( s != ERR_SUCCESS ) return( s );  // 断开或者刚连接
	memcpy( ReqBuf, BoResetUsbDisk, sizeof( BoResetUsbDisk ) );  // 复位USB存储器
	( (PUSB_SETUP_REQ)ReqBuf ) -> wIndexL = mDiskInterfNumber;  // 接口号
	s = HostCtrlTransfer374( ReqBuf, NULL, NULL );  // 执行控制传输
	if ( s == USB_INT_DISCONNECT ) return( s );  /* 检测到USB设备断开事件,磁盘已经断开 */
	mClearEndpStall( mDiskBulkInEndp | 0x80 );  /* 清除IN端点错误 */
	mClearEndpStall( mDiskBulkOutEndp );  /* 清除OUT端点错误 */
	mSaveDevEndpTog &= ~ ( BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG );
	return( LastError );  /* 返回原错误码 */
}

/* 执行基于BulkOnly协议的命令,该子程序比较简化,并未处理各种错误,实际应用必须处理 */
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主机端点的发送缓冲区写入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端点输出CBW */
	if ( s == USB_INT_DISCONNECT ) return( s );  /* 检测到USB设备断开事件,磁盘已经断开 */
	if ( s != ERR_SUCCESS ) {  /* 发送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主机端点的发送缓冲区写入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端点输出CBW */
		if ( s != ERR_SUCCESS ) return( mResetErrorBOC( s ) );
	}
	mSaveDevEndpTog ^= BIT_HOST_TRAN_TOG;  /* OUT端点的数据同步标志翻转 */
	if ( mBOC.mCBW.mCBW_DataLen ) {  /* 有数据需要传输,此处使用双缓冲区提高效率,但导致程序复杂 */
#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主机模式,USB总线空闲,发SOF,双缓冲区 */
			mSetBulkIn( );  /* 输入 */
			while ( TotalLen ) {  /* 有数据需要传输 */
#ifdef DEBUG_NOW
				printf( "*B:I=%lX\n", TotalLen );
#endif
				s = HostTransactInter( );  /* 接收数据 */
				if ( s != ERR_SUCCESS ) {  /* 操作失败 */
					if ( s == ( DEF_USB_PID_STALL | 0x20 ) ) mClearEndpStall( mDiskBulkInEndp | 0x80 );  /* 清除端点错误 */
					break;
				}
				mSaveDevEndpTog ^= BIT_HOST_RECV_TOG;  /* IN端点的数据同步标志翻转 */
				len = Read374Byte( REG_USB_LENGTH );
				if ( TotalLen > len ) TotalLen -= len;
				else TotalLen = 0;
				if ( len == 64 && TotalLen ) mSetBulkIn( );  /* 准备下一次输入 */
				Read374Block( mSaveDevEndpTog & BIT_HOST_RECV_TOG ? RAM_HOST_RECV : RAM_HOST_EXCH, len, DataBuf );
				DataBuf += len;
				if ( len < 64 ) break;
			}
		}
		else {  /* 发送 */
			Write374Byte( REG_USB_SETUP, M_SET_RAM_MODE_2TX( BIT_SETP_HOST_MODE | BIT_SETP_AUTO_SOF ) );  /* 全速USB主机模式,USB总线空闲,发SOF,双缓冲区 */
			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 ) {  /* 有数据需要传输 */
#ifdef DEBUG_NOW
				printf( "*B:O=%lX\n", TotalLen );
#endif
				TotalLen -= len;
				DataBuf += len;
				if ( len == 64 && TotalLen ) {  /* 准备下一次输出 */
					len = TotalLen >= 64 ? 64 : TotalLen;
					Write374Block( mSaveDevEndpTog & BIT_HOST_TRAN_TOG ? RAM_HOST_TRAN : RAM_HOST_EXCH, len, DataBuf );
				}
				else len = 0;
				s = HostTransactInter( );  /* 发送数据 */
				if ( s != ERR_SUCCESS ) {  /* 操作失败 */
					if ( s == ( DEF_USB_PID_STALL | 0x20 ) ) mClearEndpStall( mDiskBulkOutEndp );  /* 清除端点错误 */
					break;
				}
				mSaveDevEndpTog ^= BIT_HOST_TRAN_TOG;  /* OUT端点的数据同步标志翻转 */
				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主机模式,USB总线空闲,发SOF */
#else
		if ( mBOC.mCBW.mCBW_Flag & 0x80 ) {  /* 接收 */
			while ( TotalLen ) {  /* 有数据需要传输 */
#ifdef DEBUG_NOW
				printf( "*B:I=%lX\n", TotalLen );
#endif
				mSetBulkIn( );  /* 输入 */
				s = HostTransactInter( );  /* 接收数据 */
				if ( s != ERR_SUCCESS ) {  /* 操作失败 */
					if ( s == ( DEF_USB_PID_STALL | 0x20 ) ) mClearEndpStall( mDiskBulkInEndp | 0x80 );  /* 清除端点错误 */
					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端点的数据同步标志翻转 */
				if ( len < 64 ) break;
			}
		}
		else {  /* 发送 */
			while ( TotalLen ) {  /* 有数据需要传输 */
#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( );  /* 发送数据 */
				if ( s != ERR_SUCCESS ) {  /* 操作失败 */
					if ( s == ( DEF_USB_PID_STALL | 0x20 ) ) mClearEndpStall( mDiskBulkOutEndp );  /* 清除端点错误 */
					break;
				}
				mSaveDevEndpTog ^= BIT_HOST_TRAN_TOG;  /* OUT端点的数据同步标志翻转 */
				if ( len < 64 ) break;
			}
		}
#endif
		if ( s != ERR_SUCCESS ) {  /* 数据传输失败 */
			if ( s != ( DEF_USB_PID_STALL | 0x20 ) ) return( s );
		}
	}
	mSetBulkIn( );  /* 输入 */
#ifdef DEBUG_NOW
	printf( "*B:S\n" );
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -