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

📄 u_control.c

📁 EPSON USB DEVICE MASS-STORAGE CLASS driver, BULK ONLY on Ram disk
💻 C
字号:
/******************************************************************************
 * File name   : control.c
 * Module name : Control transfer module
 * Author	   : Hiromichi.Kondo
 *----------------------------------------------------------------------------
 * $Id: control.c,v 1.3 2003/05/16 06:53:43 9551619 Exp $
 *****************************************************************************/
#include "u_value.h"
#include "u_ram_data.h"
#include "u_rom_data.h"
#include "u_regNikka.h"

/*--- Function Prototype ---------------------------------------------------*/
void ControlTransfer(void);
void ControlRequest(void);
void ControlDataSet(void);
void ControlDataSend(void);
void ControlDataRcv(void);
void ControlDataGet(void);
#if 1
void FIFOReadProc(BYTE *p);
#endif
void ControlParaUpdate(void);
void AcceptDevSpecCmdCheck(void);
void ControlStatusStart(void);
void ControlStatusEnd(void);
void TestModeProc(void);

/*****************************************************************************	
 * control_tbl
 *****************************************************************************/
void (*const control_tbl[])() = {
	ControlRequest,
	ControlDataSet,
	ControlDataSend,
	ControlDataRcv,
	ControlDataGet,
	ControlParaUpdate,
	ControlStatusStart,
	ControlStatusEnd
};

void ControlTransfer(void)
{
	if (control_state >= CTRL_IDLE)
		panic(6);
	
	/* control_state  */
	control_tbl[control_state]();
}

/*****************************************************************************	
 * ControlRequest
 *****************************************************************************/
void ControlRequest(void)
{
	int ret;
	
	usb_flag.Init		 = 0;			/*  */
	usb_flag.USBReqRcvd  = 0;			/* USB */

	rEPnControl_BP.EP0FIFO_Clr = 1;

	rEP0ControlIN_BP.EnShortPkt = 0;	/* EnShortPkt = 0 */
	rEP0IntStat = rEP0IntStat;			/*  */
	rEP0IntEnb_BP.EnIN_TranACK = 1;		/* IN_TranACK */
	rMainIntStat = 0x01;				/* RcvEP0SETUP = 0 */

	rEP0Control_BP.INxOUT = ((rEP0SETUP_0 & 0x80) ? 1 : 0);

	req_tran_cnt = MKWORD(rEP0SETUP_7,rEP0SETUP_6);

	switch(rEP0SETUP_0 & 0x60)
	{
		case STANDARD_REQUEST:
			ret = StandardRequest();
			break;
		case CLASS_REQUEST:
			ret = ClassRequest();
			break;
		case VENDOR_REQUEST:
			ret = VendorRequest();
			break;
		default:
			ret = REQUEST_ERROR;
			break;
	}
	
	if (ret == REQUEST_OK)
	{
		if(req_tran_cnt != 0)
		{
			if(rEP0Control_BP.INxOUT)
			{
				control_state = CTRL_DATA_SET;
			}
			else
			{
				rEP0ControlOUT_BP.ForceNAK = 0;
				control_state = CTRL_DATA_GET;
			}
		}
		else
		{
			control_state = CTRL_STS_START;
		}
	}
	else
	{
		/*  STALL  */
		rEP0ControlIN_BP.ForceSTALL = 1;
		rEP0ControlOUT_BP.ForceSTALL = 1;
		control_state = CTRL_IDLE;
	}
}

/*****************************************************************************	
 * ControlDataSet
 *****************************************************************************/
void ControlDataSet(void)
{
	int i;

	if( usb_flag.ReplyDescriptor )
	{
		/* Descriptor */
		usb_flag.ReplyDescriptor = 0;	/* Descriptor */

		rEP0IntEnb_BP.EnIN_TranACK = 0;	/* IN_TranACK */

		rDescAdrs_H = DWORD2BYTE_LH((DWORD)tran_start_addr);
		rDescAdrs_L = DWORD2BYTE_LL((DWORD)tran_start_addr);

		rDescSize_H = WORD2BYTE_H(actual_tran_cnt);
		rDescSize_L = WORD2BYTE_L(actual_tran_cnt);

		rEP0Control_BP.ReplyDescriptor = 1;
	}
	else
	{
		if( actual_tran_cnt >= max_pkt_size_0 )
		{
			rCPU_JoinWr = 0x00;
			rEnEPnFIFO_Access_BP.EnEPnFIFO_Wr = 1;
			for( i=max_pkt_size_0; i>0; i--)
			{
				rEPnFIFOforCPU = *tran_start_addr;
				tran_start_addr++;
			}
			rEnEPnFIFO_Access_BP.EnEPnFIFO_Wr = 0;
			actual_tran_cnt -= max_pkt_size_0;
		}
		else
		{
			rCPU_JoinWr = 0x00;
			rEnEPnFIFO_Access_BP.EnEPnFIFO_Wr = 1;
			for( i=actual_tran_cnt; i>0; i-- )
			{
				rEPnFIFOforCPU = *tran_start_addr;
				tran_start_addr++;
			}
			rEnEPnFIFO_Access_BP.EnEPnFIFO_Wr = 0;

			actual_tran_cnt = 0;

			rEP0ControlIN_BP.EnShortPkt = 1;
		}
	}

	control_state  = CTRL_DATA_SEND;
	control_result = NO_RESULT;
	rEP0ControlIN_BP.ForceNAK = 0;
}

/*****************************************************************************	
 *	ControlDataSend
 *****************************************************************************/
void ControlDataSend(void)
{
	if( control_result == EP0_IN_ACK )
	{
		/* IN_TranACK */
		control_result = NO_RESULT;
		retry_cnt_0 = 0;

		if( actual_tran_cnt )
		{
			control_state = CTRL_DATA_SET;
		}
		else
		{
			if( req_tran_cnt == total_tran_cnt )
			{
				control_state = CTRL_STS_START;
			}
			else
			{
				if( total_tran_cnt & (max_pkt_size_0 - 1) )
				{
					control_state = CTRL_STS_START;
				}
				else
				{
					rEP0ControlIN_BP.EnShortPkt = 1;
				}
			}
		}
	}
	else
	{
		if( control_result == EP0_IN_ERR )
		{
			/* IN_TranErr */
			control_result = NO_RESULT;

			if( rEP0ControlIN_BP.ForceSTALL == 1 )
				panic(7);

#ifdef DEBUG_PRINT
			EP0INErrorCount++;
#endif
		}
		else
		{
			if( control_result == DESCRIPTOR_CMP )
			{
				actual_tran_cnt = MKWORD(rDescSize_H, rDescSize_L);

				retry_cnt_0 = 0;
				rEPnControl_BP.EP0FIFO_Clr = 1;
				if( actual_tran_cnt == req_tran_cnt )
				{
					rEP0ControlIN_BP.ForceSTALL = 1;
					rEP0ControlOUT_BP.ForceSTALL = 1;
					control_state = CTRL_IDLE;
				}
				else
				{
					control_state = CTRL_STS_START;
				}
			}
			else
			{
				if( usb_flag.USBReqRcvd )
				{
					/* SETUP */
					control_state = CTRL_REQ_CHECK;
				}
				else
				{
					if( rEP0IntStat_BP.OUT_TranNAK ){
						/* OUT_TranNAK */
						rEP0IntStat = 0x04;

						retry_cnt_0++;

						if( retry_cnt_0 > MAX_RETRY_CNT )
						{
							/* FIFO */
							actual_tran_cnt = retry_cnt_0 = 0;
							rEPnControl_BP.EP0FIFO_Clr = 1;

							control_state = CTRL_STS_START;
						}
					}
				}
			}
		}
	}
}

/*****************************************************************************	
 *	ControlDataRcv
 *****************************************************************************/
void ControlDataRcv(void)
{
	if( control_result == EP0_OUT_ACK )
	{
		/* OUT_TranACK */
		control_result = NO_RESULT;
		retry_cnt_0 = 0;
		control_state = CTRL_DATA_GET;
	}
	else
	{
		if( control_result == EP0_OUT_ERR )
		{
			/* OUT_TranErr */
			if( rEP0ControlOUT_BP.ForceSTALL == 1 )
				panic(8);

#ifdef DEBUG_PRINT
			EP0OUTErrorCount++;
#endif
		}
		else
		{
			if( usb_flag.USBReqRcvd )
			{
				/* SETUP */
				control_state = CTRL_REQ_CHECK;
			}
			else
			{
				if( rEP0IntStat_BP.IN_TranNAK )
				{
					/* IN_TranNAK */
					rEP0IntStat = 0x08;

					retry_cnt_0++;

					if( retry_cnt_0 > MAX_RETRY_CNT )
					{
						/* FIFO */
						actual_tran_cnt = retry_cnt_0 = 0;
						rEPnControl_BP.EP0FIFO_Clr = 1;

						control_state = CTRL_STS_START;
					}
				}
			}
		}
	}
}

/*****************************************************************************	
 *	ControlDataGet
 *****************************************************************************/
void ControlDataGet(void)
{
	int i;
	int fifo_remain;

	control_result = NO_RESULT;

	rCPU_JoinRd = 0x00;
	fifo_remain = MKWORD(rEPnRdRemain_H, rEPnRdRemain_L);

	if( fifo_remain == 0 )
	{
		if( actual_tran_cnt )
		{
			control_state = ((total_tran_cnt == actual_tran_cnt) ? \
								CTRL_DATA_RCV : CTRL_PARA_UPDATE);
		}
		else
		{
			control_state = CTRL_STS_START;
		}
	}
	else
	{
		if( actual_tran_cnt < fifo_remain )
		{
			rEP0ControlIN_BP.ForceSTALL = 1;
			rEP0ControlOUT_BP.ForceSTALL = 1;
			control_state = CTRL_IDLE;
		}
		else
		{
			rCPU_JoinRd = 0x00;
			rEnEPnFIFO_Access_BP.EnEPnFIFO_Rd = 1;
			for( i=fifo_remain; i>0; i-- )
			{
				*tran_start_addr = rEPnFIFOforCPU;
				tran_start_addr++;
			}
			rEnEPnFIFO_Access_BP.EnEPnFIFO_Rd = 0;
			actual_tran_cnt -= fifo_remain;

			if( actual_tran_cnt )
			{
				rEP0ControlOUT_BP.ForceNAK = 0;
				control_state = CTRL_DATA_RCV;
			}
			else
			{
				control_state = CTRL_PARA_UPDATE;
			}
		}
	}
}


/*****************************************************************************	
 * ControlParaUpdate
 *****************************************************************************/
void ControlParaUpdate(void)
{
	switch(rEP0SETUP_1)
	{
		case TEST_EP0_OUT:
			if( actual_tran_cnt )
			{
				rEP0ControlIN_BP.ForceSTALL = 1;
				rEP0ControlOUT_BP.ForceSTALL = 1;
				control_state = CTRL_IDLE;
			}
			else
			{
				control_state = CTRL_STS_START;
			}
			break;
		case ACCEPT_DEV_SPC_CMD:
			/* Accept Device-Specific Command */
			AcceptDevSpecCmdCheck();
			break;
		default:
			/*  */
			rEP0ControlIN_BP.ForceSTALL = 1;
			rEP0ControlOUT_BP.ForceSTALL = 1;
			control_state = CTRL_IDLE;
	}
}

/*****************************************************************************	
 * AcceptDevSpecCmdCheck
 *****************************************************************************/
void AcceptDevSpecCmdCheck(void)
{
	int i;

	if( protocol_phase == DATA_PHASE )
	{
		if( usb_wk_data[0] == 0x1D && usb_wk_data[1] == 0x04 )
		{
			/* CBI Reset */
			rEP0ControlIN_BP.ForceSTALL = 1;
			rEP0ControlOUT_BP.ForceSTALL = 1;
			
			control_state = CTRL_IDLE;
		}
		else
		{
			/* CBI Reset */
			protocol_phase = COMMAND_PHASE;		/*  */
			int_in_state = INT_IN_IDLE;			/* InterruptINIDLE */

			for( i=0; i<12; i++ )
				cmd_block[i] = usb_wk_data[i];

			device_flag.RcvCommand = 1;			/* */

			control_state = CTRL_STS_START;
			
			if( cmd_status == COMMAND_FAILED )
			{
				/* FAILED */
				rEPaControl_BP.ForceSTALL = 0;
				rEPbControl_BP.ForceSTALL = 0;
			}
		}
	}
	else
	{
		if( protocol_phase == STATUS_PHASE )
		{
			protocol_phase = COMMAND_PHASE;
			int_in_state = INT_IN_IDLE;			/* InterruptINIDLE */
		}

		for( i=0; i<12; i++ )
			cmd_block[i] = usb_wk_data[i];

		device_flag.RcvCommand = 1;			/* */

		control_state = CTRL_STS_START;

		if( cmd_status == COMMAND_FAILED )
		{
			/* FAILED */
			rEPaControl_BP.ForceSTALL = 0;
			rEPbControl_BP.ForceSTALL = 0;
		}
	}

}

/*****************************************************************************	
 * ControlStatusStart
 *****************************************************************************/
void ControlStatusStart(void)
{
	rEP0IntStat = rEP0IntStat;

	if( rEP0Control_BP.INxOUT )
	{
		/* (IN) */
		rEP0Control_BP.INxOUT = 0;
		rEP0ControlOUT_BP.ForceNAK = 0;
	}
	else
	{
		/* (OUT) */
		if( usb_flag.Address )
		{
			/* Address */
			usb_flag.Address = 0;				/* Address */
			rUSB_Address_BP.AutoSetAddress = 1;	/* Auton Set Address */
		}
		rEP0Control_BP.INxOUT = 1;
		rEP0ControlIN_BP.ForceNAK = 0;
		rEP0ControlIN_BP.EnShortPkt = 1;
	}

	control_result = NO_RESULT;
	control_state = CTRL_STS_END;
}

/*****************************************************************************	
 * ControlStatusEnd
 *****************************************************************************/
void ControlStatusEnd(void)
{
	int fifo_remain;

	if( control_result == EP0_IN_ACK || control_result == EP0_OUT_ACK )
	{
		/* IN_TranACKOUT_TranACK */
		control_result = NO_RESULT;
		retry_cnt_0 = 0;

		rCPU_JoinRd = 0x00;
		fifo_remain = MKWORD(rEPnRdRemain_H, rEPnRdRemain_L);
		
		if( fifo_remain != 0)
		{
			/* FIFOEmpty */
			rEP0ControlIN_BP.ForceSTALL = 1;
			rEP0ControlOUT_BP.ForceSTALL = 1;
			control_state = CTRL_IDLE;
		}
		else
		{
			if( usb_flag.TestMode )
			{
				/* TestMode */
				usb_flag.TestMode = 0;			/* TestMode */

				TestModeProc();					/* TestMode */
			}
		}
		control_state = CTRL_IDLE;
	}
	else
	{
		if( control_result == EP0_IN_ERR || control_result == EP0_OUT_ERR )
		{
			/* IN_TranErrOUT_TranErr */
			control_result = NO_RESULT;

			if( control_result == EP0_IN_ERR )
			{
				if( rEP0ControlIN_BP.ForceSTALL == 1 )
					panic(9);

#ifdef DEBUG_PRINT
				EP0INErrorCount++;
#endif
			}
			else
			{
				if( rEP0ControlOUT_BP.ForceSTALL == 1 )
					panic(10);

#ifdef DEBUG_PRINT
				EP0OUTErrorCount++;
#endif
			}
		}
		else
		{
			if(usb_flag.USBReqRcvd)
			{
				/* SETUP */
				control_state = CTRL_REQ_CHECK;
			}
			else
			{
				if( rEP0Control_BP.INxOUT )
				{
					if( rEP0IntStat_BP.OUT_TranNAK )
					{
						/* OutTranNAK */
						retry_cnt_0 = 0;

						rEP0Control_BP.INxOUT = 0;

						if( req_tran_cnt != 0 && actual_tran_cnt == 0 )
						{
							/* Zero Length */
							rEP0ControlOUT_BP.ForceNAK = 0;
							control_state = CTRL_DATA_GET;
						}
						else
						{
							rEP0ControlIN_BP.ForceSTALL = 1;
							rEP0ControlOUT_BP.ForceSTALL = 1;
							control_state = CTRL_IDLE;
						}
					}
				}
				else
				{
					/* OUT */
					if( rEP0IntStat_BP.IN_TranNAK )
					{
						/* INTranNAK */
						retry_cnt_0 = 0;

						rEP0Control_BP.INxOUT = 1;

						if( actual_tran_cnt )
						{
							rEP0ControlIN_BP.ForceSTALL = 1;
							rEP0ControlOUT_BP.ForceSTALL = 1;
							control_state = CTRL_IDLE;
						}else{
							/* Zero Length */
							rEP0ControlIN_BP.ForceNAK = 0;
							rEP0ControlIN_BP.EnShortPkt = 1;
							control_state = CTRL_DATA_SEND;
						}
					}
				}
			}
		}
	}
}

/*****************************************************************************	
 * TestModeProc
 *****************************************************************************/
void TestModeProc(void)
{
	rMainIntEnb = 0x00;
	rSIE_IntEnb  = 0x00;
	rEPrIntEnb	= 0x00;
	rDMA_IntEnb = 0x00;
	rFIFO_IntEnb = 0x00;

	if( rUSB_Test_BP.Test_J || rUSB_Test_BP.Test_K )
	{
		/* Test_J  Test_k */
		rXcvrControl_BP.OpMode = 0x02;	/* Disable Bitstuffing and NRZI encoding) */
	}
	rUSB_Control_BP.EnAutoNego = 0;		/* AutoNego */
	rUSB_Control_BP.DisBusDetect = 1;	/*  */

	rUSB_Test_BP.EnUSB_Test = 1;		/* TestMode */

	/* VBUS  */
	do
	{
		if( VBUSCheck() == 0 ) break;
	}while( 1 );
	
	/* VBUS TestModeOFFAttach */
	rUSB_Test_BP.EnUSB_Test = 0;		/* TestMode */
	rXcvrControl_BP.OpMode = 0x01;		/* Non Drive */
	rXcvrControl_BP.RpuEnb = 0;
	rUSB_Control_BP.ActiveUSB = 0;		/* USB */

#ifdef DEBUG_PRINT
	for (;;){
		DebugProc();
	}
#else
	for (;;)
		;
#endif
}

⌨️ 快捷键说明

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