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

📄 usbh_hcds_urb.c

📁 epson usb2.0 控制芯片 S1R72V05 固件程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *	description	: USBH HCD URB Management(static)
 *	Maker		: Hiromichi Kondo
 *	Copyright	: (C)2005,SEIKO EPSON Corp. All Rights Reserved.
 */



#include <OSCall.h>
#include <string.h>			/* memset */
#include <SPRDEF.h>
#include <SPRSTS.h>
#include <usbh_hcd.h>
#include <usbh_hcds_common.h>
#include <usbh_hcds_channel.h>
#include <usbh_hcds_vhub.h>
#include <usbh_hcds_user_config.h>



/*****************************************
 * Define definition
 *****************************************/
#define NUM_USB_CH						USBH_HCDS_CH_NUM_USB_CH
#define NUM_PENDING_CH					NUM_USB_CH
#define CH_NUM_PENDING					(0xFE)
#define CH_NUM_UNKNOWN					(0xFF)
#define BO_CBW_SIZE						(31)
#define BO_CSW_SIZE						(13)
#define HUB_BIT							(0x01)
#define HUB_PORT_BIT					(0x02)
#define OFFSET_BO_CBW_DATA_LENGTH		(0x08)
#define BO_CBW_DATA_LENGTH				(0x04)

/*****************************************
 * Structure definition
 *****************************************/
typedef struct tagCH_INFO{
	unsigned char chNum;
	unsigned char chType;
}CH_INFO;

typedef struct tagURB_MANAGER{
	USBH_HCD_LIST_HEAD sActiveURBList;
	USBH_HCD_LIST_HEAD sCtrlURBList;
	USBH_HCD_LIST_HEAD sBulkURBList;
	USBH_HCD_LIST_HEAD sIntURBList;
	USBH_HCD_LIST_HEAD sIsoURBList;
	USBH_HCD_LIST_HEAD sStrgURBList;
	USBH_HCD_URB *psRootIntUrb;
	unsigned short pendingAsyncSetupCount;
	CH_INFO sCHInfo[NUM_USB_CH + 1];
}URB_MANAGER;

/*****************************************
 * Function prototype declaration
 *****************************************/
#ifdef DEBUG_C

long NotifyStatusChanged( unsigned long param0, unsigned long param1, void *pParam );

#else /* #ifdef DEBUG_C */

static long NotifyStatusChanged( unsigned long param0, unsigned long param1, void *pParam );

#endif /* #ifdef DEBUG_C */

Inline void URBListEndpointSearchCancel( USBH_HCD_LIST_HEAD *psSearchList, USBH_HCD_USBDEV *psRootDev,
											unsigned char devNum, unsigned char epAddress );
static long URBTranCmpCallback( unsigned long chNum, unsigned long urbStatus, void *pParam	);
Inline void CheckQueuedURB( CH_INFO *psCHInfo );
Inline long CheckStorageModeURB( USBH_HCD_URB *psUrb );
Inline void ExecURBCallback( USBH_HCD_URB *psUrb, unsigned long urbStatus );
Inline unsigned long GetFIFOSize( USBH_HCD_URB *psUrb, unsigned char chType );

 /*****************************************
 * Variable definition
 *****************************************/
#ifdef DEBUG_C

URB_MANAGER URBStatus;

#else /* #ifdef DEBUG_C */

static URB_MANAGER URBStatus;

#endif /* #ifdef DEBUG_C */

/*=============================================================================================
// Function_Name: USBH_HCDS_URBInit
//
// description	: URB management block initialization
//
//				  Initialize URB Management block
//
// argument 	: None
//
// return		: None
===============================================================================================*/
void USBH_HCDS_URBInit( void )
{
	unsigned int i;


	memset(&URBStatus, 0, sizeof(URBStatus));
	USBH_HCDS_InitListHead(&URBStatus.sActiveURBList);
	USBH_HCDS_InitListHead(&URBStatus.sCtrlURBList);
	USBH_HCDS_InitListHead(&URBStatus.sBulkURBList);
	USBH_HCDS_InitListHead(&URBStatus.sIntURBList);
	USBH_HCDS_InitListHead(&URBStatus.sIsoURBList);
	USBH_HCDS_InitListHead(&URBStatus.sStrgURBList);
	URBStatus.psRootIntUrb = NULL;

	for( i = 0; i < NUM_USB_CH; i++ ){
		URBStatus.sCHInfo[i].chNum = CH_NUM_UNKNOWN;
	}
	URBStatus.sCHInfo[NUM_PENDING_CH].chNum = CH_NUM_PENDING;
}

/*=============================================================================================
// Function_Name: USBH_HCDS_URBSubmit
//
// description	: URB register and execute
//
//				  Passed URB is checked, registered and executed
//
// argument 	: *psUrb							(in)Pointer of URB structure
//				  pfnCallback						(in)Pointer of callback function that is called when completed
//
// return		: STATUS_SUCCESS			Processing completed successfully
//				  STATUS_INVALID_PARAMETER	Parameter error
===============================================================================================*/
long USBH_HCDS_URBSubmit( USBH_HCD_URB *psUrb, USBH_HCD_USBDEV *psRootDev )
{
	unsigned char pipeType, chNum, chType;
	unsigned long fifoSize;
	long retValue;


	/*==========================/
	Common URB parameter check /
	/==========================*/
	if( psUrb->pHCPriv != NULL ){
		/* Private area for Host Control is used */

		return STATUS_INVALID_PARAMETER;
	}

	if( psUrb->psDev == NULL ){
		/* The pointer of the USB device information structure is NULL */

		return STATUS_INVALID_PARAMETER;
	}

	if( psUrb->transBufLength != 0 ){
		/* There are datas to transfer */

		if( (psUrb->transFlag & USBH_HCD_URB_DIRECT_COPY) == 0 ){
			/* URB_DIRECT_COPY is not set in the transfer flag */

			if( psUrb->pTransBuf == NULL ){
				/* The pointer in the transfer buffer is NULL */

				return STATUS_INVALID_PARAMETER;
			}
		}
	}

	pipeType = USBH_HCDS_GetPipeType(psUrb->pipe);


	/*=============================/
	Checks route hub addressing/
	/=============================*/
	if( psUrb->psDev == psRootDev ){
		/* Route hub addressing */

		if( pipeType == USBH_HCD_PIPE_CONTROL ){
			/* URB of USB request */

			if( psUrb->pSetupPacket == NULL ){
				/* The pointer of the SETUP packet data is NULL */

				return STATUS_INVALID_PARAMETER;
			}
			retValue = USBH_HCDS_VHUBRequest(psUrb);
			if( retValue != STATUS_SUCCESS ){
				return retValue;
			}

			/*==============================/
			Call the callback of URB completion/
			/==============================*/
			ExecURBCallback(psUrb, USBH_HCD_URBSTS_SUCCESS);

		} else if( pipeType == USBH_HCD_PIPE_INTERRUPT ){
			/* URB of interrupt IN */

			/*================================================================/
			Save URB of Interrupt IN, and register the notification destination of port status changing /
			/================================================================*/
			URBStatus.psRootIntUrb = psUrb;

			USBH_HCDS_VHUBRegisterCBR(NotifyStatusChanged);

			/*=======================/
			Buried Channel information /
			/=======================*/
			psUrb->pHCPriv = psUrb;

		} else {
			/* Invalid URB */

			return STATUS_INVALID_PARAMETER;
		}

	} else {
		/* USB device addressing*/

		/*=================/
		Channel allocation/
		/=================*/
		switch( pipeType ){
			case USBH_HCD_PIPE_ISOCHRONOUS:
				chType = USBH_HCDS_CH_TYPE_ISO;
				break;
			case USBH_HCD_PIPE_INTERRUPT:
				chType = USBH_HCDS_CH_TYPE_INT;
				break;
			case USBH_HCD_PIPE_CONTROL:
				chType = USBH_HCDS_CH_TYPE_CTRL;
				break;
			case USBH_HCD_PIPE_BULK:
				if( psUrb->transFlag & USBH_HCD_URB_STRG_MODE ){
					/* URB_STRG_MODE is set in the transfer flag */

					retValue = CheckStorageModeURB(psUrb);
					if( retValue != STATUS_SUCCESS ){
						return retValue;
					}
					chType = USBH_HCDS_CH_TYPE_STRG;
				} else {
					chType = USBH_HCDS_CH_TYPE_BULK;
				}
				break;
			default:
				return STATUS_INVALID_PARAMETER;
		}
		fifoSize = GetFIFOSize(psUrb, chType);
		chNum = CH_NUM_UNKNOWN;
		if( (chType == USBH_HCDS_CH_TYPE_BULK) && (URBStatus.pendingAsyncSetupCount != 0)){
			/* The Bulk transfer is required while reserving synchronous transfer(Interrupt/Isochronous) setting */

			retValue = STATUS_UNSUCCESSFUL;	/* The channel is not allocated and it be putted into the queue. */
		} else {
			USBH_HCDS_InterruptDisable();
			retValue = USBH_HCDS_CHAlloc(&chNum, chType, fifoSize);
			USBH_HCDS_InterruptEnable();
		}


		if( retValue != STATUS_SUCCESS ){
			/* Channel allocation failure */

			if( retValue == STATUS_CANNOT_SETUP ){
				/* It is used by Bulk transfer and when it is not possible to set it */

				URBStatus.pendingAsyncSetupCount++;	/* Update the synchronous transfer(Interrupt/Isochronous) setting reservation counter */
			} else if( retValue == STATUS_UNSUCCESSFUL ){
				/* Channel allocate failed */

				if( (chType == USBH_HCDS_CH_TYPE_INT) || (chType == USBH_HCDS_CH_TYPE_ISO) ){
					/* It makes an error because queuing cannot be done for synchronous transfer type(Interrupt/Isochronous) */

					psUrb->pHCPriv = NULL;
					return retValue;
				}
			} else {
				/* parameter error or the memory allocate error */
					psUrb->pHCPriv = NULL;
					return retValue;
			}

			/*=======================/
			Buried channel information /
			/=======================*/
			psUrb->pHCPriv = &URBStatus.sCHInfo[NUM_PENDING_CH];

			/*=================================/
			/Be putted into the queue by the channel empty waiting /
			/=================================*/
			USBH_HCDS_InterruptDisable();
			switch( chType ){
				case USBH_HCDS_CH_TYPE_ISO:
					USBH_HCDS_ListAddTail(&(psUrb->sList), &(URBStatus.sIsoURBList));
					break;
				case USBH_HCDS_CH_TYPE_INT:
					USBH_HCDS_ListAddTail(&(psUrb->sList), &(URBStatus.sIntURBList));
					break;
				case USBH_HCDS_CH_TYPE_CTRL:
					USBH_HCDS_ListAddTail(&(psUrb->sList), &(URBStatus.sCtrlURBList));
					break;
				case USBH_HCDS_CH_TYPE_BULK:
					USBH_HCDS_ListAddTail(&(psUrb->sList), &(URBStatus.sBulkURBList));
					break;
				case USBH_HCDS_CH_TYPE_STRG:
					USBH_HCDS_ListAddTail(&(psUrb->sList), &(URBStatus.sStrgURBList));
					break;
			}
			USBH_HCDS_InterruptEnable();
		} else {
			/* Channel allocation success */

			/*=======================/
			Buried channel information /
			/=======================*/
			psUrb->pHCPriv = &URBStatus.sCHInfo[chNum];
			URBStatus.sCHInfo[chNum].chNum = chNum;
			URBStatus.sCHInfo[chNum].chType = chType;

			/*==========================================/
			Put into URB active queue, and execute the channel/
			/==========================================*/
			USBH_HCDS_InterruptDisable();
			USBH_HCDS_ListAddTail(&(psUrb->sList), &(URBStatus.sActiveURBList));
			USBH_HCDS_InterruptEnable();

			retValue = USBH_HCDS_CHTranGo(psUrb, chNum, URBTranCmpCallback);
			if( retValue != STATUS_SUCCESS ){
				psUrb->pHCPriv = NULL;
				return retValue;
			}
		}
	}

	return STATUS_SUCCESS;
}

/*=============================================================================================
// Function_Name: USBH_HCDS_URBUnlink
//
// description	: URB cancel and delete process
//
//				  Passed URB is checked, canceled and deleted
//
// argument 	: *psUrb							(in)Pointer of URB structure
//				  pfnCallback						(in)Pointer of callback function that is called when completed
//
// return		: STATUS_SUCCESS			Processing completed successfully
//				  STATUS_INVALID_PARAMETER	Parameter error
===============================================================================================*/
long USBH_HCDS_URBUnlink( USBH_HCD_URB *psUrb, USBH_HCD_USBDEV *psRootDev )
{
	CH_INFO *psCHInfo;
	long retValue;


	/*==========================/
	Common URB parameter check /
	/==========================*/
	if( psUrb->psDev == NULL ){
		/* The pointer of the USB device information structure is NULL */

		return STATUS_INVALID_PARAMETER;
	}

	if( psUrb->pHCPriv == NULL ){
		/* Nothing is done because URB is not registered and not executed */
		;
	} else {
		/* Private area for Host Control is used */

		if( psUrb->transFlag & USBH_HCD_URB_STRG_MODE ){
			/* URB_STRG_MODE is set in the transfer flag */

			retValue = CheckStorageModeURB(psUrb);
			if( retValue != STATUS_SUCCESS ){
				return retValue;
			}
		}

		/*=============================/
		Check if it is the route hub addressing /
		/=============================*/
		if( psUrb->psDev == psRootDev ){
			/* Route hub addressing */

			if( psUrb == URBStatus.psRootIntUrb ){
				/* URB of Interrupt IN */

				/*================================================================/
				URB of Interrupt IN is deleted, and the notification destination of port status changing is deleted /
				/================================================================*/
				URBStatus.psRootIntUrb = NULL;

				USBH_HCDS_VHUBRegisterCBR(NULL);

				psUrb->pHCPriv = NULL;
			}
		} else {
			/* USB device addressing */

			/* URB is executed or is in execution waiting */

			USBH_HCDS_InterruptDisable();
			psCHInfo = (CH_INFO *)psUrb->pHCPriv;
			if( psCHInfo->chNum != CH_NUM_UNKNOWN && psCHInfo->chNum != CH_NUM_PENDING ){
				/* In executing */

#ifdef HCD_PARAMCHK_C
				retValue = USBH_HCDS_CHTranCancel(psUrb, psCHInfo->chNum);
				if( retValue != STATUS_SUCCESS ){
					USBH_HCDS_InterruptEnable();
					return retValue;
				}
#else	/* #ifdef HCD_PARAMCHK_C */
				USBH_HCDS_CHTranCancel(psUrb, psCHInfo->chNum);
#endif	/* #ifdef HCD_PARAMCHK_C */
			}
			USBH_HCDS_ListDel(&(psUrb->sList));
			psUrb->pHCPriv = NULL;
			USBH_HCDS_InterruptEnable();

			/* Queuing URB is checked */
			CheckQueuedURB(psCHInfo);
		}
		if( (psUrb->transFlag & USBH_HCD_URB_ASYNC_UNLINK) != 0 ){
			/* The callback of URB is called before it reports on the cancel completion */

			/*==============================/
			Call the completion callback of URB/
			/==============================*/
			ExecURBCallback(psUrb, USBH_HCD_URBSTS_CONNRESET);
		}
	}

	return STATUS_SUCCESS;
}

/*=============================================================================================
// Function_Name: USBH_HCDS_URBEndpointAllCancel
//
// description	:  Cancel all URB of corresponding Endpoint
//
//				  Corresponding URB is canceled from passed USB device information structure and Endpoint address
//
// argument 	: *psDev					(in)Pointer of USB device information structure
//				  epAddress					(in)Endpoint address(Direction+EP number)
//
// return		: STATUS_SUCCESS			Processing completed successfully
//				  STATUS_INVALID_PARAMETER	Parameter error
===============================================================================================*/
long USBH_HCDS_URBEndpointAllCancel( USBH_HCD_USBDEV *psDev, USBH_HCD_USBDEV *psRootDev, unsigned char epAddress )
{
	unsigned char targetDevNum;


	if( psDev == psRootDev ){
		/* Route hub addressing */

		/*===============/
		Cancel process/
		/===============*/
		if( URBStatus.psRootIntUrb != NULL ){
			/* URB for interrupt has been registered */

			USBH_HCDS_URBUnlink(URBStatus.psRootIntUrb, psRootDev);
		}
	} else {
		/* USB device addressing */

		targetDevNum = psDev->devNum;
		USBH_HCDS_InterruptDisable();
		URBListEndpointSearchCancel(&URBStatus.sCtrlURBList, psRootDev, targetDevNum, epAddress);
		URBListEndpointSearchCancel(&URBStatus.sBulkURBList, psRootDev, targetDevNum, epAddress);
		URBListEndpointSearchCancel(&URBStatus.sIntURBList, psRootDev, targetDevNum, epAddress);
		URBListEndpointSearchCancel(&URBStatus.sIsoURBList, psRootDev, targetDevNum, epAddress);
		URBListEndpointSearchCancel(&URBStatus.sStrgURBList, psRootDev, targetDevNum, epAddress);
		URBListEndpointSearchCancel(&URBStatus.sActiveURBList, psRootDev, targetDevNum, epAddress);
		USBH_HCDS_InterruptEnable();
	}
	return STATUS_SUCCESS;
}

/*=============================================================================================

⌨️ 快捷键说明

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