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

📄 usim_drv.c

📁 8032底层驱动部分。因为可以移植 所以单独来拿出来
💻 C
📖 第 1 页 / 共 5 页
字号:
		}
		else
		{	// command complete
			dbg_print("command complete!!\r\n");
			usim_dcb.rx_chain = KAL_FALSE;
			usim_dcb.retry = 0;
			usim_dcb.main_state = MAIN_CMD_READY_STATE;
		}				
	}
	else if(USIM_IS_RBLOCK(pcb))
	{	// R-block
		dbg_print("received a R-block\r\n");
		if(usim_dcb.header_tx[T1_PCB_INDEX]== RESYNC_REQ)
		{
			// must receive a S RESP not any other block
			dbg_print("(invalid block) must receive a S RESP not any other block \r\n");
			return KAL_FALSE;			
		}
		if(len)
		{
			dbg_print("(invalid block) R block of len = %d \r\n", len);
			return KAL_FALSE;
		}						
		if(usim_dcb.tx_chain && (pcb & PCB_R_STATUS) == 0)
		{	// receive a err free R block
			if(((pcb & PCB_R_SEQ)<<2) == usim_dcb.ns )
			{	// send next chaining block				
				if(usim_dcb.abort == KAL_TRUE)
				{
					usim_dcb.main_state = MAIN_CMD_READY_STATE;
				}
				else if(usim_dcb.tx_size != 0)
				{
					// normal chaining case
					usim_dcb.retry = 0;
					usim_dcb.tx_size -= usim_dcb.ifsc;
					usim_dcb.tx_index += usim_dcb.ifsc; 			
					*adrs =(kal_uint32)(usim_dcb.tx_buf+usim_dcb.tx_index);
					if(usim_dcb.tx_size <= usim_dcb.ifsc)
					{
						pcb = 0;
						len = usim_dcb.tx_size;
						usim_dcb.cmd_state = I_BLOCK_M0_TX;
					}
					else	// txSize > IFSC
					{
						pcb = PCB_I_M;
						len = usim_dcb.ifsc;
						usim_dcb.cmd_state = I_BLOCK_M1_TX;
					}
					if(usim_dcb.ns) 
						pcb |= PCB_I_SEQ;
					usim_dcb.header_tx[T1_PCB_INDEX] = pcb;
					usim_dcb.header_tx[T1_LEN_INDEX] = len;	
					usim_dcb.header_tx_bak[T1_PCB_INDEX] = pcb;
					usim_dcb.header_tx_bak[T1_LEN_INDEX] = len;	
					USIM_INV_N(usim_dcb.ns);
					}
			}
			else
			{	// sending the previous I block again				
				usim_dcb.retry++;
				usim_dcb.cmd_state = usim_dcb.cmd_state_bak;
				usim_dcb.header_tx[T1_PCB_INDEX] = usim_dcb.header_tx_bak[T1_PCB_INDEX];
				usim_dcb.header_tx[T1_LEN_INDEX] = usim_dcb.header_tx_bak[T1_LEN_INDEX];				
			}
		}
		else
		{
			// error handling R-Block received
			if((pcb & PCB_R_SEQ)<<2 != (usim_dcb.ns) )
			{	// previous sending sequence
				usim_dcb.retry++;
				usim_dcb.cmd_state = usim_dcb.cmd_state_bak;
				usim_dcb.header_tx[T1_PCB_INDEX] = usim_dcb.header_tx_bak[T1_PCB_INDEX];
				usim_dcb.header_tx[T1_LEN_INDEX] = usim_dcb.header_tx_bak[T1_LEN_INDEX];
			}
			else
			{				
				// next sending sequence
				// send the previous R-block again
				usim_dcb.retry = 0;
				return KAL_FALSE;
			}			
		}		
	}
	else if(USIM_IS_SBLOCK(pcb))
	{	// S-block(REQ)
		dbg_print("receive S-block(%x)\r\n",pcb);
		if(USIM_IS_RESP(pcb))
		{	// response (only resync response block will be received.)
			dbg_print("receive RESP block!\r\n");
			if(pcb == RESYNC_RESP && usim_dcb.header_tx[T1_PCB_INDEX]== RESYNC_REQ )
			{
				if(len != 0)
				{
					dbg_print("Invalid len of RESYNC");
					return KAL_FALSE;
				}
				// resync complete (the card is reset to the initial state)
				usim_dcb.main_state = MAIN_CMD_READY_STATE;
				usim_dcb.ns = 0;
				usim_dcb.nr = 0;
				usim_dcb.resync = KAL_TRUE;
				usim_dcb.retry = 0;
				// usim_dcb.ifsc = USIM_IFSC_DEFAULT;
			}
			else
			{
				dbg_print("receive a error S RESP,[%x]\r\n", pcb);
				return KAL_FALSE;			
			}
		}
		else
		{ // receiving a S-block of request
			if(usim_dcb.header_tx[T1_PCB_INDEX]== RESYNC_REQ)
			{
				// must receive a S RESP not any other block
				dbg_print("(invalid block) must receive a S RESP not any other block \r\n");
				return KAL_FALSE;			
			}
		
			usim_dcb.cmd_state = S_BlOCK_RESP_TX;
			usim_dcb.header_tx[T1_PCB_INDEX]= pcb|PCB_S_RESP;
			usim_dcb.header_tx[T1_LEN_INDEX]= len;		
			if(len)
			{
				usim_dcb.header_tx[T1_INF_INDEX] = usim_dcb.header_rx[T1_INF_INDEX];
			}
			switch(pcb)
			{
				case RESYNC_REQ:
					dbg_print("(ERR) receive RESYNC_REQ\r\n");
					return KAL_FALSE;
					break;
				case IFS_REQ:	
					dbg_print("receive IFS_REQ\r\n");					
					if(len != 1)
						return KAL_FALSE;
					usim_dcb.ifsc = usim_dcb.header_rx[T1_INF_INDEX];
					break;
				case ABORT_REQ:
					dbg_print("receive ABORT_REQ\r\n");
					if(len != 0)
						return KAL_FALSE;	
					usim_dcb.retry = 0;
					usim_dcb.abort = KAL_TRUE;
					break;
				case WTX_REQ:
					if(len != 1)
						return KAL_FALSE;
					usim_dcb.retry = 0;
					dbg_print("receive WTX_REQ\r\n");
					// re-start the BWT( according to the spec, the timer should be restart after 
					// the WTX response has been sent.
					usim_dcb.wtx = KAL_TRUE;
					usim_dcb.wtx_m = usim_dcb.header_rx[T1_INF_INDEX];;
					break;
				default:
					return KAL_FALSE;
			}
		}
	}
	else
	{
		dbg_print("Invalid PCB \r\n");
		return KAL_FALSE;
	}
	
	return KAL_TRUE;
}
/*************************************************************************
* FUNCTION
*  usim_err_handler
*
* DESCRIPTION
*	1. send R block to UICC to indicate the previous block is error at previous two retry. 
*	2. send S(RESYN) to UICC to recover the errors.
*	3. deactivate the UICC 
*
* PARAMETERS
*	
* RETURNS
*	
* GLOBALS AFFECTED
*	usim_dcb.retry
*
*************************************************************************/
static void usim_err_handler(void)
{
	// send R block
	usim_dcb.retry++;
	dbg_print("usim_err_handler %d",usim_dcb.retry);	
	USIM_CLR_FIFO();
	if(usim_dcb.retry < 3)
	{
		dbg_print("send R block!\r\n");
		{
			if(usim_dcb.ev_status == USIM_RX_INVALID)
			{
				USIM_MAKE_R_BLOCK(PCB_R_STATUS_EDC_ERR);	
			}
			else
			{
				USIM_MAKE_R_BLOCK(PCB_R_STATUS_OTHER_ERR);	
			}	
		}
	}
	else if(usim_dcb.retry <  6)
	{
		// next level error handling => resync		
		dbg_print("send RESYNC REQ !\r\n");
		USIM_MAKE_S_RESYNC();		
	}
	else
	{
		// deactivate
		usim_deactivation();
	}
}

/*************************************************************************
* FUNCTION
*  usim_send_i_block
*
* DESCRIPTION
*	1. send I block to UICC with length of ifsc including case 1~4.
*
* PARAMETERS
*	1. txData: tx buffer containing command header optional with tx data.
*	2. txSize: length of the tx data
*	3. rxData: rx buffer (must inluding two extra one for sw1 and sw2)
*	4. rxSize: length of the rx data except sw1|sw2
*	
* RETURNS
*	status bytes(SW1|SW2), 0 means a physical error.
*	
* GLOBALS AFFECTED
*	usim_dcb
*
*************************************************************************/
static sim_status usim_send_i_block(kal_uint8  *txData,kal_uint32  *txSize,kal_uint8  *rxData, kal_uint32  *rxSize)
{	
	kal_uint8 pcb, len;
	kal_uint32 count,adrs;
	usim_status_enum status;
	kal_uint16 sw;

	dbg_print("\r\n\r\n @@@@ usim_send_i_block @@@@\r\n");
	DRVPDN_Disable(DRVPDN_CON1,DRVPDN_CON1_SIM,PDN_SIM);
	if(usim_dcb.clock_stop_en == KAL_TRUE)
	{
		if(usim_dcb.main_state == CLK_STOPPING_STATE)
		{
			usim_set_timeout(0);
			usim_dcb.main_state = MAIN_CMD_READY_STATE;
		}
		else if(usim_dcb.main_state == CLK_STOPPED_STATE)
		{
			DRV_Reg(SIM_CTRL) &= ~SIM_CTRL_HALT;	
			usim_set_timeout(usim_dcb.etu_of_700);
			DRV_WriteReg(SIM_IRQEN, SIM_IRQEN_TOUT);
			USIM_WAIT_EVENT();			
		}
	}
	
	do
	{
		status = USIM_NO_ERROR;
		usim_dcb.tx_index = 0;
		usim_dcb.rx_index = 0;
		usim_dcb.tx_buf = txData;
		if(*rxSize == 0)
			usim_dcb.rx_buf = usim_dcb.sw;	
		else
			usim_dcb.rx_buf = rxData;
		usim_dcb.tx_size = *txSize;			
		usim_dcb.rx_size = *rxSize+2; // include SW1, SW2 
		usim_dcb.retry = 0;
		usim_dcb.abort = KAL_FALSE;
		usim_dcb.resync = KAL_FALSE;
		usim_dcb.rx_chain = KAL_FALSE;
		
		count = *txSize;
		adrs =(kal_uint32)usim_dcb.tx_buf;
		if(count <= usim_dcb.ifsc)
		{
			pcb = 0;
			len = count;
			usim_dcb.tx_chain = KAL_FALSE;
			usim_dcb.cmd_state = I_BLOCK_M0_TX;
		}
		else	// txSize > IFSC
		{
			pcb = PCB_I_M;
			len = usim_dcb.ifsc;
			usim_dcb.tx_chain = KAL_TRUE;
			usim_dcb.cmd_state = I_BLOCK_M1_TX;
		}
		if(usim_dcb.ns) 
			pcb |= PCB_I_SEQ;
		
		usim_dcb.cmd_state_bak = usim_dcb.cmd_state;	
		usim_dcb.header_tx[T1_NAD_INDEX] = USIM_NAD_DEFAULT;
		usim_dcb.header_tx[T1_PCB_INDEX] = pcb;
		usim_dcb.header_tx_bak[T1_PCB_INDEX] = pcb;
		usim_dcb.header_tx[T1_LEN_INDEX] = len;		
		usim_dcb.header_tx_bak[T1_LEN_INDEX] = len;
		USIM_INV_N(usim_dcb.ns);
		
		while(1)
		{
			usim_send_block((kal_uint8*)adrs);
			USIM_WAIT_EVENT();			
			if(usim_dcb.ev_status == USIM_NO_ERROR)
			{	// a complete block is received
				if(usim_rx_block_handler(&adrs)== KAL_FALSE)
					usim_err_handler();
			}
			else 
			{
				usim_err_handler();
			}
			if(usim_dcb.main_state == MAIN_CMD_READY_STATE)
			{
				// command complete
				*rxSize = usim_dcb.rx_index;
				break;
			}
		}
		
		if(usim_dcb.abort == KAL_TRUE)
		{
			status = USIM_DATA_ABORT;
			break;
		}
		if(usim_dcb.main_state == DEACTIVATION_STATE)
		{
			status =  USIM_DEACTIVATED;
			break;
		}
	}while(usim_dcb.resync == KAL_TRUE);

	if(usim_dcb.clock_stop_en == KAL_TRUE)
	{
		usim_dcb.main_state = CLK_STOPPING_STATE;		
		usim_set_timeout(usim_dcb.etu_of_1860);
		DRV_WriteReg(SIM_IRQEN, SIM_IRQEN_TOUT);
		#if defined(USIM_DEBUG)
		start = get_current_time();
		#endif
	}
	usim_dcb.status = status;
	if(status != USIM_NO_ERROR)
		return STATUS_FAIL;
	// the *rxsize include the sw1 and sw1, the upper layer should prepare it.
	*rxSize -= 2;
	if(*rxSize == 0)
		return (kal_uint16)((usim_dcb.sw[0]<<8)|(usim_dcb.sw[1]));
	sw = (rxData[*rxSize]<<8)|(rxData[*rxSize+1]);
	return sw;

}

/*************************************************************************
* FUNCTION
*  usim_update_sim_to_ready
*
* DESCRIPTION
*	1. update the ATR informations from usim_dcb into SimCard
*		to make sim(t=0) driver work..
*
* PARAMETERS
*	
* RETURNS
*	
* GLOBALS AFFECTED
*	SimCard
*	TOUTValue
*
*************************************************************************/
void static usim_update_sim_to_ready(void)
{
	extern kal_uint32 TOUTValue;
	
	SimCard.app_proto = usim_dcb.app_proto;
	SimCard.State = SIM_PROCESSCMD;
	SimCard.Data_format = usim_dcb.dir;
	if(usim_dcb.power == CLASS_B_30V)
		SimCard.Power = SIM_30V;
	else if(usim_dcb.power == CLASS_C_18V)
		SimCard.Power = SIM_18V;
	SimCard.SIM_ENV = usim_dcb.sim_env;
	SimCard.Speed = usim_dcb.speed;
	SimCard.clkStop = usim_dcb.clock_stop_en;
	if(usim_dcb.clock_stop_type == CLOCK_STOP_HIGH)
		SimCard.clkStopLevel = KAL_TRUE;
	else if(usim_dcb.clock_stop_type == CLOCK_STOP_LOW)
		SimCard.clkStopLevel = KAL_FALSE;
	SimCard.sim_card_speed = usim_dcb.card_speed;
	TOUTValue = usim_dcb.WWT>>2;
}
/*************************************************************************
* FUNCTION
*  L1usim_Init
*
* DESCRIPTION
*	1. It is the initialization function of usim driver
*	2. It shall be called only once.
*	3. It gets the customization data of borad-supported voltage.
*	4. It initialize the structure of usim control block .
*	5. It get a GPT handler, a dma port,and register lisr, hisr, a event groug 
*
* PARAMETERS
	None
	
* RETURNS
	None
	
* GLOBALS AFFECTED
*	usim_dcb
*
*************************************************************************/
void L1usim_Init(void)	
{	
	if(usim_dcb.warm_rst == KAL_FALSE)
	{
		usim_dcb.sim_env = SIM_GetCurrentEnv();
		usim_dcb.dir = USIM_DIRECT;
		usim_dcb.speed = SPEED_372;
		usim_dcb.clock_stop_en = KAL_FALSE;
		usim_dcb.clock_stop_type = CLOCK_STOP_UNKONW;
		usim_dcb.phy_proto = T1_PROTOCOL;
		usim_dcb.warm_rst = KAL_FALSE;
		usim_dcb.rx_size = 0;
		usim_dcb.rx_buf = NULL;
		usim_dcb.tx_size = 0;
		usim_dcb.tx_buf = NULL;
		usim_dcb.Fi = FI_DEFAULT;	
		usim_dcb.Di = DI_DEFAULT;
		usim_dcb.header_tx[0] = NAD;
		usim_dcb.ts_hsk_en = KAL_TRUE;
		usim_dcb.WWT = INIT_WWT_T0;
		usim_dcb.etu_of_1860 = (1860/32);
		usim_dcb.etu_of_700 = (700/32);
		usim_dcb.present = KAL_TRUE;
					
		// note: MT6218B half channel can't work, use full channel insteadly.
		#if !defined(MT6218B) && !defined(MT6218)
		if(usim_dcb.dma_port == 0)
			usim_dcb.dma_port = DMA_GetChannel(DMA_SIM);
		usim_dcb.dma_menu.TMOD.burst_mode = KAL_FALSE;
		usim_dcb.dma_menu.master = DMA_SIM;
		usim_dcb.dma_menu.addr = NULL;
		usim_dcb.dma_input.type = DMA_HWTX;
		usim_dcb.dma_input.size = DMA_BYTE;
		usim_dcb.dma_input.callback = NULL;
		usim_dcb.dma_input.menu = &usim_dcb.dma_menu;
		#endif
		
		if(usim_dcb.event == NULL)
			usim_dcb.event = kal_create_event_group("USIM_EV");

		if(usim_dcb.hisr == NULL)
			usim_dcb.hisr = kal_create_hisr("USIM_HISR",1,512,usim_hisr,NULL);

		if(usim_dcb.gpt_handle == NULL)
			GPTI_GetHandle(&usim_dcb.gpt_handle);
		IRQSensitivity(IRQ_SIM_CODE,LEVEL_SENSITIVE);
		IRQUnmask(IRQ_SIM_CODE);
	}
	
	// reset these value no matter cold or warm reset
	usim_dcb.main_state = ACTIVATION_STATE;
	usim_dcb.ifsc = USIM_IFSC_DEFAULT;
	usim_dcb.ifsd = USIM_IFSD_DEFAULT;
	usim_dcb.ns = 0;
	usim_dcb.nr = 0;
	IRQ_Register_LISR(IRQ_SIM_CODE, usim_lisr,"USIM_Lisr");	
}

/*************************************************************************
* FUNCTION
*  L1sim_Reset
*
* DESCRIPTION
* 1. Reset the sim card and parse the ATR and perform the PTS(optional) and 
		enter the command ready mode
* 2. First time it is a cold reset, second it's a warm reset
* 3. If the ExpectVolt equal to the current volt, perform a warm reset. 
		Otherwise perform a cold reset.
* 4. Finally, S-block of IFS request is sent the UICC to configure the IFSD  
*
* PARAMETERS
	1. ExpectVolt: application layer give a expected power class

* RETURNS
*  USIM_VOLT_NOT_SUPPORT: Valid TS is received
*  KAL_FALSE: Valid TS is not received, card is not present or not supported
*
* GLOBALS AFFECTED
*	usim_dcb
*
*************************************************************************/
usim_status_enum L1usim_Reset(usim_power_enum ExpectVolt, usim_power_enum *ResultVolt)
{

⌨️ 快捷键说明

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