📄 usim_drv.c
字号:
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 + -