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

📄 usim_drv.c

📁 8032底层驱动部分。因为可以移植 所以单独来拿出来
💻 C
📖 第 1 页 / 共 5 页
字号:
		speed = SPEED_372;
	}
	dbg_print("select speed %d(372:64:32, 0:1:2)", speed); 
	
	// generate PTS packet
	pts[PPSS] = 0xff;
	pck = 0xff;
	pts[PPS0] = USIM_PTS_PS1_MSK;
	if(usim_dcb.T1_support && usim_dcb.app_proto == USIM_PROTOCOL && !usim_dcb.T0_support ) // priority T1 > T0
	{	// T1 only usim card will go to here
		dbg_print("select T=1\r\n");
		pts[PPS0] |= USIM_PTS_PS0_T1;			
	}
	else
		dbg_print("select T=0\r\n");
	pck ^= pts[PPS0];
	if(speed == SPEED_372)
		pts[PPS1] = ATR_TA1_372_5;
	else if(speed == SPEED_64)
		pts[PPS1] = ATR_TA1_64;
	else if(speed == SPEED_32) 	// SPEED_32
		pts[PPS1] = ATR_TA1_32;					
	pck ^= pts[PPS1];
		
	// send PTS packet
	usim_dcb.main_state = PTS_STATE;	
	pts[PCK] = pck;
	SIM_FIFO_Flush();	            
	SIM_SetRXTIDE(PPS_LEN); 
	for(i=0;i<PPS_LEN;i++)
	{		
		DRV_WriteReg(SIM_DATA,pts[i]);
	}
	usim_set_timeout(INIT_WWT_T0);
	USIM_WAIT_EVENT();
	usim_set_timeout(0);
	if(usim_dcb.ev_status != USIM_NO_ERROR)
		echoed = KAL_FALSE;
	// read the response
	if(echoed)
	{
		for(i=0;i<PPS_LEN;i++)
		{		
			pts_r[i] = DRV_Reg(SIM_DATA);
			if(pts[i]!= pts_r[i])
				echoed = KAL_FALSE;
		}
	}
	if(echoed)
	{
		dbg_print("PTS OK!\r\n");
		usim_set_speed(speed); 
	}
	else
	{
		dbg_print("PTS Fail!\r\n");
		usim_set_speed(Speed372); 
	}

exit:	
	// GSM will only use T=0, no matter t=1 is supported.
	if(usim_dcb.T1_support && !usim_dcb.T0_support &&
		(usim_dcb.app_proto == USIM_PROTOCOL) && echoed )
	{	// T1 only usim card will go to here
		usim_dcb.phy_proto = T1_PROTOCOL;		
		usim_set_protocol(T1_PROTOCOL);
		USIM_DISABLE_TXRX_HANSHAKE();					
		SIM_SetRXRetry(0);
		SIM_SetTXRetry(0);
	}
	else
	{
		usim_dcb.phy_proto = T0_PROTOCOL;	
		if(usim_dcb.app_proto == USIM_PROTOCOL)
			usim_set_protocol(T0_PROTOCOL); // SIM_PROTOCOL is enabled at simd.c			
		SIM_SetRXRetry(7);
		SIM_SetTXRetry(7);
		USIM_ENABLE_TXRX_HANSHAKE();
	}
	
	
}

/*************************************************************************
* FUNCTION
*  usim_set_timeout
*
* DESCRIPTION
*	 setup the timeout value in the unit of etu
*
* PARAMETERS
*	timeout: timeout value in the unit of etu , 0 means disabling timeout
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void usim_set_timeout(kal_uint32 timeout)
{	
	if(timeout)
	{
		timeout >>= 2;
		SIM_SetTOUT(timeout+TOUT_OFFSET);
		usim_dcb.timeout = timeout+TOUT_OFFSET;
	}
	else
	{
		USIM_DISABLE_TOUT();
	}
}
/*************************************************************************
* FUNCTION
*  usim_set_speed
*
* DESCRIPTION
*	 setup the baudrate of the SIM card, only support 372, 64 and 32.
*	 speed 16 is not supported, use speed32 insteadly.
*
* PARAMETERS
*	timeout: timeout value in the unit of etu , 0 means disabling timeout
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void usim_set_speed(usim_speed_enum speed)
{	
	switch(speed)
	{
		case SPEED_372: 
			// clock: 13/4 = 3.25M, with default etu F/372
			DRV_WriteReg(SIM_BRR,(SIM_BRR_CLK_Div4 | SIM_BRR_BAUD_Div372));
			break;
		case SPEED_64:
			DRV_WriteReg(SIM_BRR,(SIM_BRR_CLK_Div4 | SIM_BRR_BAUD_Div64));
			break;
		case SPEED_32:
			DRV_WriteReg(SIM_BRR,(SIM_BRR_CLK_Div4 | SIM_BRR_BAUD_Div32));
			break;
	}
	usim_dcb.speed = speed;		
	usim_dcb.BWT = usim_dcb.BWT*BWT_Factor[speed]+11;
}
/*************************************************************************
* FUNCTION
*  usim_set_protocol
*
* DESCRIPTION
*	 setup the physical protocol layer including T=0 and T=1.
*
* PARAMETERS
*	T: physical protocol layer including T=0 and T=1.
*
* RETURNS
*
* GLOBALS AFFECTED
*
*************************************************************************/
static void usim_set_protocol(usim_protocol_enum T)
{
	if( T == T1_PROTOCOL)
	{
		USIM_ENABLE_T1();
	}
	else
	{
		USIM_ENABLE_T0();
	}
	usim_dcb.phy_proto = T;
}
/*************************************************************************
* FUNCTION
*  usim_select_power
*
* DESCRIPTION
	1. Try the input voltage from application layer if availabe.
	2. Try the possible voltage which the ME can support.
	3. Get the valid TS
*
* PARAMETERS
	1. ExpectVolt: application layer give a expected power class

* RETURNS
*  KAL_TRUE: Valid TS is received
*  KAL_FALSE: Valid TS is not received, card is not present or not supported
*
* GLOBALS AFFECTED
*	usim_dcb
*
*************************************************************************/
static kal_bool usim_select_power(usim_power_enum ExpectVolt)
{
	kal_uint32 retry;

	dbg_print("usim_select_power with power: %d \r\n", ExpectVolt);

	SIM_FIFO_Flush();	
	if(usim_dcb.warm_rst == KAL_FALSE)
	{
		usim_deactivation();
		// decide the initial power class
		usim_dcb.power_in = ExpectVolt;
		if(ExpectVolt != UNKNOWN_POWER_CLASS)
		{			
			usim_dcb.power = ExpectVolt;
		}
		else
		{		
			if (usim_dcb.sim_env == ME_30V_ONLY)
			{
				usim_dcb.power = CLASS_B_30V;
			}
			else // ME_18_ONLY, ME_18V_30V
			{
			   usim_dcb.power = CLASS_C_18V;
			}
		}
	}	
	// start from low power class to high, if no ATR received, try another power class
	// if the an invalid TS byte is received, change the convention with the same power class
	retry = 0;
	while(retry++ < 3)
	{
		kal_set_eg_events(usim_dcb.event,0,KAL_AND);
		usim_activation();	
		USIM_WAIT_EVENT();
		if(usim_dcb.ev_status == USIM_NO_ERROR )
		{	// a correct TS byte is received			
			USIM_WAIT_EVENT();			
			// all ATR characters are received
			if(usim_dcb.ev_status != USIM_ATR_REC)
				return KAL_FALSE;
			else
				return KAL_TRUE;
		}
		else if(usim_dcb.ev_status == USIM_ATR_REC)
		{	// all ATR characters are received
			return KAL_TRUE;
		}
		else if(usim_dcb.warm_rst == KAL_TRUE)
		{
			dbg_print("warm reset fail!!\r\n");
			usim_deactivation();
			return KAL_FALSE;
		}
		else if((usim_dcb.ev_status == USIM_TS_INVALID || usim_dcb.ev_status == USIM_RX_INVALID)
			&& (usim_dcb.dir == USIM_DIRECT))
		{				
			// try another convention 
			usim_dcb.dir = !usim_dcb.dir;
			usim_deactivation();			
			dbg_print("change another convention %d !!\r\n", usim_dcb.dir);			
		}
		else if(usim_dcb.ev_status == USIM_NO_ATR || usim_dcb.ev_status == USIM_BWT_TIMEOUT ||
			(usim_dcb.ev_status == USIM_TS_INVALID || usim_dcb.ev_status == USIM_RX_INVALID ))
		{
			retry = 0;
			usim_dcb.dir = USIM_DIRECT;
			// deactivate and delay			
			usim_deactivation();
			// change another power class if availabe, no retry with the same power class
			if(usim_dcb.sim_env == ME_18V_30V )
			{
				if(usim_dcb.power_in == UNKNOWN_POWER_CLASS && usim_dcb.power == CLASS_C_18V )
				{
					usim_dcb.power = CLASS_B_30V;
				}
				else if(usim_dcb.power_in != UNKNOWN_POWER_CLASS && usim_dcb.power_in == usim_dcb.power)
				{
					if(usim_dcb.power_in == CLASS_C_18V)
						usim_dcb.power = CLASS_B_30V;
					else
						usim_dcb.power = CLASS_C_18V;
				}				
				else
				{
					return KAL_FALSE;
				}				
			}
			else
			{
				return KAL_FALSE;
			}
			
		}
		else
		{
			ASSERT(0);
		}
	}
	return KAL_FALSE;
}
/*************************************************************************
* FUNCTION
*  usim_activation
*
* DESCRIPTION
* Perform the activation of USIM
* It is a cold reset
* select the power according to usim_dcb.power (input)
* select the convention according to usim_dcb.dir (input)
* the clock rate adopted is SPEED_372
* set the default timeout value
*
* PARAMETERS
	None
	
* RETURNS
	None
	
* GLOBALS AFFECTED
*	usim_dcb
*
*************************************************************************/
static void usim_activation(void)
{
	kal_uint16 reg = 0;

	dbg_print("usim_activation, pow = %d, dir: %d \r\n",usim_dcb.power, usim_dcb.dir);
	
#ifdef MT6318
   if (usim_dcb.power == CLASS_B_30V)
      pmic_vsim_sel(VSIM_3);
   else
      pmic_vsim_sel(VSIM_1_8);
#elif( (!defined(MT6318))&& (!defined(MT6305)) )   // No PMIC
	if (usim_dcb.power != CLASS_B_30V)
	{
		reg = SIM_CONF_SIMSEL;
	}
#else /*Phone setting*/
	if (usim_dcb.power == CLASS_B_30V) 
	{
		reg = SIM_CONF_SIMSEL;
	}
#endif   /*Phone setting*/
	if(usim_dcb.dir == USIM_DIRECT)
		reg |= SIM_CONF_Direct;
	else
		reg |= SIM_CONF_InDirect;
	
	if(KAL_TRUE == usim_dcb.ts_hsk_en)
	{
		reg |= (SIM_CONF_TXHSK | SIM_CONF_RXHSK);
      SIM_SetRXRetry(1);
	   SIM_SetTXRetry(1);		
	}
	else
	{
      SIM_SetRXRetry(0);
	   SIM_SetTXRetry(0);		
	}	
	DRV_WriteReg(SIM_CONF,reg);
	
	SIM_FIFO_Flush();
	SIM_SetRXTIDE(2);	// generate a interrupt while TS byte and T0 is received
	DRV_WriteReg(SIM_IRQEN,USIM_IRQEN_ATR|SIM_STS_RXERR);
	reg = DRV_Reg(SIM_STS);	
	usim_dcb.main_state = ACTIVATION_STATE;
	usim_dcb.ev_status = USIM_NO_ERROR;
	if(usim_dcb.warm_rst == KAL_FALSE)
	{
		USIM_POW_ON();	
	}
	else
	{
		USIM_WRST();
		kal_sleep_task(10);
	}
	// go to usim_hisr of case RXTIDE, ATRERR, RXERR(parity error)
}
	
static void usim_lisr(void)
{
   IRQMask(IRQ_SIM_CODE);
   kal_activate_hisr(usim_dcb.hisr);
}
/*************************************************************************
* FUNCTION
*  usim_deactivation
*
* DESCRIPTION
*	1. deactivate the UICC card 
*	2. wait util the the deactivation is complete
*
* PARAMETERS
	None
	
* RETURNS
	None
	
* GLOBALS AFFECTED
*	usim_dcb.main_state
*
*************************************************************************/
static void usim_deactivation(void) 
{	
	dbg_print("usim_deactivation\r\n");

	if(DRV_Reg(SIM_CTRL)&SIM_CTRL_SIMON)
	{
		kal_uint32 i = 5;
		// before deactivate the SIM interface, turn on the clock first.
		DRV_Reg(SIM_CTRL) &= ~SIM_CTRL_HALT;
		while(i--);
		kal_set_eg_events(usim_dcb.event,0,KAL_AND);
	   DRV_WriteReg(SIM_IRQEN, SIM_IRQEN_SIMOFF);
	   DRV_Reg(SIM_CTRL) &= ~SIM_CTRL_SIMON;	   
	   USIM_WAIT_EVENT();
	   USIM_CLR_FIFO();
	   usim_dcb.main_state = DEACTIVATION_STATE;
	   if(usim_dcb.ev_status == USIM_POWER_OFF)
	   	usim_dcb.main_state = DEACTIVATION_STATE;
	   else 
	   	ASSERT(0);
	}
}
/*************************************************************************
* FUNCTION
*  usim_t1end_handler
*
* DESCRIPTION
*	1. it is called while t1end interrupt is generated.
*	2. there are two different states in this function: 
		CMD_TX_STATE: a complete block is sent to UICC
		CMD_RX_INF_STATE: a complete block is received from UICC 
*
* PARAMETERS
	None
	
* RETURNS
	None
	
* GLOBALS AFFECTED
*	usim_dcb.main_state
*
*************************************************************************/
static void usim_t1end_handler(void)
{	
	dbg_print("usim_t1end_handler ");
	switch(usim_dcb.main_state)
	{
		case CMD_TX_STATE:
			dbg_print("CMD_TX_STATE ");

			USIM_DMA_RX_TIDE();
			usim_dcb.dma_menu.addr = (kal_uint32)usim_dcb.dma_buffer; // (kal_uint32)usim_dcb.rx_buf+usim_dcb.rx_index;
			usim_dcb.dma_input.type = DMA_HWRX;
			usim_dcb.dma_input.count = USIM_DMA_MAX_SIZE;
			DMA_Config(usim_dcb.dma_port,&usim_dcb.dma_input,KAL_TRUE);
			if(usim_dcb.wtx == KAL_TRUE)
			{
				usim_dcb.wtx = KAL_FALSE;
				usim_set_timeout(usim_dcb.BWT * usim_dcb.wtx_m);
			}
			else
				usim_set_timeout(usim_dcb.BWT);
			usim_dcb.ev_status = USIM_NO_ERROR;
			usim_dcb.main_state = CMD_RX_STATE;
			DRV_WriteReg(SIM_IRQEN, (SIM_STS_EDCERR|SIM_STS_RXERR|SIM_STS_T1END|SIM_STS_OV|SIM_STS_TOUT)); 			
			break;
		case CMD_RX_STATE:
			{
				kal_uint8 len, pcb;
				kal_uint8 *dma_buffer = usim_dcb.dma_buffer;
				
				usim_set_timeout(0);
				DMA_Stop(usim_dcb.dma_port);	
				if(usim_dcb.ev_status == USIM_RX_INVALID)
				{
					// comes from EDC or parity error
					USIM_SET_EVENT();
					return;
				}
				// receive a complete block, except a S-block received, there still is one
				// parameter byte in the fifo
				usim_dcb.header_rx[T1_NAD_INDEX] = dma_buffer[T1_NAD_INDEX]; // NAD
				pcb = usim_dcb.header_rx[T1_PCB_INDEX] = dma_buffer[T1_PCB_INDEX]; // PCB
				len = usim_dcb.header_rx[T1_LEN_INDEX] = dma_buffer[T1_LEN_INDEX]; // LEN	
				dbg_print("CMD_RX_STATE (reveive a block!! len: %d)",len );

				if(len)
				{
					if(len == 1 && USIM_IS_SBLOCK(pcb))
					{
						usim_dcb.header_rx[T1_INF_INDEX] = dma_buffer[T1_INF_INDEX];
					}
					else
					{
						kal_mem_cpy(usim_dcb.rx_buf+usim_dcb.rx_index, &dma_buffer[T1_INF_INDEX], len);
					}
				}
				usim_dcb.ev_status = USIM_NO_ERROR;							
				USIM_SET_EVENT();
			}
			break;
	}
	dbg_print("\r\n");
}
static void usim_timeout_handler()
{
	dbg_print("usim_timeout_handler ");
	
	switch(usim_dcb.main_state)

⌨️ 快捷键说明

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