📄 usim_drv.c
字号:
{
case ATR_STATE:
dbg_print("ATR_STATE (timeout) should not go over here ");
// may be optimized by parsing the content instead of using timeout.
// read the remaining bytes of ATR
{
kal_uint32 count;
count = DRV_Reg(SIM_COUNT);
while(count--)
{
usim_dcb.ATR_data[usim_dcb.ATR_index++] = (kal_uint8)DRV_Reg(SIM_DATA);
}
usim_dcb.ev_status = USIM_ATR_REC;
USIM_SET_EVENT();
}
break;
case CLK_STOPPING_STATE:
dbg_print("CLK_STOPPING_STATE ");
{
kal_bool level;
usim_set_timeout(0);
usim_dcb.main_state = CLK_STOPPED_STATE;
if(usim_dcb.clock_stop_type == CLOCK_STOP_HIGH )
level = KAL_TRUE;
else
level = KAL_FALSE;
SIM_Idle(level);
SIM_DisAllIntr();
#if defined(USIM_DEBUG)
end = get_duration_tick(start);
dbg_print("clock stoped!! duration = %d", end);
#endif
}
break;
case CLK_STOPPED_STATE:
dbg_print("CLK_STOPPED_STATE ");
{
usim_dcb.main_state = MAIN_CMD_READY_STATE;
usim_dcb.ev_status = USIM_NO_ERROR;
USIM_SET_EVENT();
dbg_print("clock start!!");
}
break;
default:
dbg_print("default:");
DMA_Stop(usim_dcb.dma_port);
usim_dcb.ev_status = USIM_BWT_TIMEOUT;
USIM_SET_EVENT();
}
dbg_print("\r\n");
}
static void usim_hisr(void)
{
kal_uint32 int_status;
int_status = DRV_Reg(SIM_STS);
usim_dcb.int_status = int_status;
PUSH_INT(int_status);
dbg_print("usim_hisr int:%x\r\n",int_status);
if(int_status & SIM_STS_RXERR )
{
dbg_print("parity error \r\n");
usim_set_timeout(0);
usim_dcb.ev_status = USIM_RX_INVALID;
if(usim_dcb.main_state == ACTIVATION_STATE)
{
SIM_DisAllIntr();
USIM_SET_EVENT();
goto end_of_hisr;
}
// wait t1end interrupt
}
if(int_status& SIM_STS_EDCERR)
{
dbg_print("EDC error \r\n");
usim_set_timeout(0);
usim_dcb.ev_status = USIM_RX_INVALID;
}
if(int_status& SIM_STS_TOUT)
{
usim_timeout_handler();
goto end_of_hisr;
}
if(int_status & SIM_STS_T1END)
{
usim_t1end_handler();
}
if(int_status & SIM_STS_RX)
{
usim_rx_handler(int_status);
}
if(int_status & SIM_STS_SIMOFF)
{
usim_dcb.ev_status = USIM_POWER_OFF;
USIM_SET_EVENT();
goto end_of_hisr;
}
if(int_status & SIM_STS_TXERR || int_status & SIM_STS_OV)
{
ASSERT(0);
}
if(int_status & SIM_STS_NATR)
{
usim_dcb.ev_status = USIM_NO_ATR;
USIM_SET_EVENT();
}
end_of_hisr:
IRQClearInt(IRQ_SIM_CODE);
IRQUnmask(IRQ_SIM_CODE);
}
/*************************************************************************
* FUNCTION
* usim_rx_handler
*
* DESCRIPTION
* 1. It is called byt usim_hisr
* 2. It is called while RXTIDE interrupt is triggerred
*
* PARAMETERS
None
* RETURNS
None
* GLOBALS AFFECTED
* usim_dcb
*
*************************************************************************/
static void usim_rx_handler(kal_uint32 int_status)
{
dbg_print("usim_rx_handler ");
switch(usim_dcb.main_state)
{
case ACTIVATION_STATE:
dbg_print("ACTIVATION_STATE ");
{
kal_uint8 TS,T0,count;
TS = DRV_Reg(SIM_DATA);
dbg_print("TS = %x ", TS);
if(TS == 0x3B || TS == 0x3F)
{
usim_set_timeout(INIT_WWT_T0);
USIM_ENABLE_TXRX_HANSHAKE();
SIM_SetRXRetry(USIM_RETRY);
SIM_SetTXRetry(USIM_RETRY);
count = 0;
T0 = DRV_Reg(SIM_DATA);
usim_dcb.hist_index = T0&0xf; // use to contain the length of historical char (temperary)
USIM_CAL_TD_COUNT(T0, count);
if((T0 & TDMask) == NULL)
{
count += usim_dcb.hist_index;
if(count >= SIM_TOTAL_FIFO_LEN)
{
usim_dcb.abort = KAL_TRUE; // for temp usage (separate two times)
count -= 6;
}
usim_dcb.resync = KAL_TRUE; // for temp usage (last time)
}
else
count++;
if(count == 0)
{
usim_dcb.ev_status = USIM_ATR_REC;
USIM_SET_EVENT();
}
else
{
usim_dcb.rx_size = count+1; // for temp usage (index to TD byte)
SIM_SetRXTIDE(count);
DRV_WriteReg(SIM_IRQEN,USIM_IRQEN_NORMAL);
usim_dcb.ev_status = USIM_NO_ERROR;
}
usim_dcb.main_state = ATR_STATE;
usim_dcb.ATR_index = 0;
usim_dcb.ATR_data[usim_dcb.ATR_index++] = TS;
usim_dcb.ATR_data[usim_dcb.ATR_index++] = T0;
}
else
{
kal_uint16 reg;
usim_dcb.ev_status = USIM_TS_INVALID;
SIM_DisAllIntr(); // prevent the following ATR bytes trigger RX interrupt
reg = DRV_Reg(SIM_STS);
}
USIM_SET_EVENT();
}
break;
case ATR_STATE:
{ // receive all ATR data without timeout to indicate
kal_uint32 count;
kal_uint8 TD;
count = DRV_Reg(SIM_COUNT);
dbg_print("ATR_STATE : %d ",count);
while(count--)
usim_dcb.ATR_data[usim_dcb.ATR_index++] = (kal_uint8)DRV_Reg(SIM_DATA);
if(usim_dcb.abort == KAL_TRUE)
{
usim_dcb.abort = KAL_FALSE;
SIM_SetRXTIDE(6);
usim_dcb.resync = KAL_TRUE;
break;
}
if(usim_dcb.resync == KAL_FALSE)
{
TD = usim_dcb.ATR_data[usim_dcb.rx_size];
dbg_print(", TD = %x ,%d", TD,usim_dcb.rx_size);
count = 0;
USIM_CAL_TD_COUNT(TD, count);
if((TD & TDMask) == NULL)
{
count += usim_dcb.hist_index;
if(count >= SIM_TOTAL_FIFO_LEN)
{
// usim_dcb.rx_index = count; // for temp usage (total ATR len)
usim_dcb.abort = KAL_TRUE; // for temp usage (separate two times)
count -= 6;
}
usim_dcb.resync = KAL_TRUE; // for temp usage (last time)
}
else
count++;
usim_dcb.rx_size += (count); // for temp usage (index to TD byte)
SIM_SetRXTIDE(count);
}
else
{
usim_set_timeout(0);
dbg_print("\r\n!! all ATR received \r\n");
usim_dcb.hist_index = 0;
usim_dcb.rx_size = 0;
usim_dcb.resync = KAL_FALSE;
usim_dcb.abort = KAL_FALSE;
usim_dcb.ev_status = USIM_ATR_REC;
USIM_SET_EVENT();
}
}
break;
case PTS_STATE:
SIM_DisAllIntr();
usim_dcb.ev_status = USIM_NO_ERROR;
USIM_SET_EVENT();
break;
}
}
/*************************************************************************
* FUNCTION
* usim_send_block
*
* DESCRIPTION
* 1. sending a block to UICC, with header in usim_dcb.header_tx
* 2. if len > 0 then using DMA to transfer data from tx buffer to the fifo of sim
interface.
3. after a complete block is sent, T1END is generated
4. after that, three bytes of received block header will come into rx fifo
*
* PARAMETERS
adrs: tx buffer address
* RETURNS
None
* GLOBALS AFFECTED
* usim_dcb
*
*************************************************************************/
static void usim_send_block(kal_uint8 *adrs )
{
kal_uint32 len, pcb;
kal_uint8 *header;
usim_dcb_struct *dcb = &usim_dcb;
header = dcb->header_tx;
dcb->main_state = CMD_TX_STATE;
USIM_CLR_FIFO();
// write header into fifo
len = header[T1_LEN_INDEX];
pcb = header[T1_PCB_INDEX];
dbg_print("usim_send_block [00][%x][%x]\r\n",pcb, len);
#if defined(USIM_DEBUG)
{
kal_uint32 i;
dbg_print("tx:");
if(USIM_IS_SBLOCK(pcb)&& len ==1)
{
dbg_print(" %x",header[T1_INF_INDEX]);
}
else
{
for(i=0;i<len;i++)
{
dbg_print(" %x",adrs[i]);
}
}
dbg_print("\r\n");
}
#endif
DRV_WriteReg(SIM_DATA, header[T1_NAD_INDEX]);
DRV_WriteReg(SIM_DATA, pcb);
DRV_WriteReg(SIM_DATA, len);
DRV_WriteReg(SIM_IMP3, len);
// transfer by DMA if the count > 12, otherwise by MCU
SIM_SetTXTIDE(1);
if(len > 12)
{
dcb->dma_menu.addr = (kal_uint32)adrs;
dcb->dma_input.type = DMA_HWTX;
dcb->dma_input.count = (kal_uint16)len;
USIM_TX_START_T1();
DMA_Config(dcb->dma_port,&dcb->dma_input,KAL_TRUE);
}
else if(USIM_IS_SBLOCK(pcb)&& len ==1)
{
DRV_WriteReg(SIM_DATA, header[T1_INF_INDEX]);
USIM_TX_START_T1();
}
else
{
kal_uint32 i;
for(i=0;i<len;i++)
DRV_WriteReg(SIM_DATA, adrs[i]);
USIM_TX_START_T1();
}
DRV_WriteReg(SIM_IRQEN, SIM_STS_T1END);
}
/*
1. send S blocks of request or response.
2. if sending request, check if the response is correct.
3. if sending response,
4. EDC will be generated(tx) and removed(rx) by T1 controller
id: PCB of the S block
param: parameter of the S-block
*/
static usim_status_enum usim_send_s_block(usim_s_block_id_enum id, kal_uint8 param)
{
kal_uint8 *tx_buf, *rx_buf, len, t;
kal_bool is_resp;
kal_uint32 i;
usim_dcb_struct *dcb = &usim_dcb;
dbg_print("usim_send_s_block id:%x, param:%d \r\n", id, param);
tx_buf = dcb->header_tx;
rx_buf = dcb->header_rx;
tx_buf[T1_NAD_INDEX] = USIM_NAD_DEFAULT;
tx_buf[T1_PCB_INDEX] = id;
is_resp = ((id & PCB_S_RESP) != 0);
dcb->cmd_state = (is_resp)?(S_BlOCK_RESP_TX):(S_BlOCK_REQ_TX);
if(id==IFS_REQ || id==WTX_REQ || id==IFS_RESP|| id==WTX_RESP )
{
len = 4;
tx_buf[T1_LEN_INDEX] = 1;
}
else
{
len = 3;
tx_buf[T1_LEN_INDEX] = 0;
}
tx_buf[T1_INF_INDEX] = param;
dcb->retry = 0;
while(dcb->retry++ < 3)
{
usim_send_block(¶m);
USIM_WAIT_EVENT();
if(usim_dcb.ev_status == USIM_NO_ERROR)
{
if(!is_resp)
{
for(t=0,i=0;i<len;i++)
t += rx_buf[i]^tx_buf[i];
if(t != PCB_S_RESP)
continue;
}
break;
}
}
if(dcb->retry == 4)
{
usim_deactivation();
}
#if 0
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
/* under construction !*/
#endif
return USIM_NO_ERROR;
}
/*************************************************************************
* FUNCTION
* usim_rx_block_handler
*
* DESCRIPTION
* 1. process the received block including I, R, and S blocks
* 2. prepare the next sending block header in the usim_dcb.header_tx
*
* PARAMETERS
adrs: address of the data buffer
* RETURNS
KAL_TRUE: a valid block is received
KAL_FALSE: an invalid block is received
* GLOBALS AFFECTED
* usim_dcb
*
*************************************************************************/
static kal_bool usim_rx_block_handler(kal_uint32 *adrs)
{
kal_uint8 pcb, len;
if(usim_dcb.header_rx[T1_NAD_INDEX] != 0)
{
dbg_print("(invlid block) invalid NAD\r\n");
return KAL_FALSE;
}
pcb = usim_dcb.header_rx[T1_PCB_INDEX];
len = usim_dcb.header_rx[T1_LEN_INDEX];
if(len > usim_dcb.ifsd) // 0 <= len <= IFSC (max 254)
return KAL_FALSE;
#if defined(USIM_DEBUG)
{
dbg_print("rx:%x %x %x",usim_dcb.header_rx[0],usim_dcb.header_rx[1],usim_dcb.header_rx[2]);
if(USIM_IS_SBLOCK( usim_dcb.header_rx[1]))
dbg_print(" %x \r\n",usim_dcb.rx_buf[3]);
}
#endif
// USIM_INV_N(usim_dcb.ns);
if(USIM_IS_IBLOCK(pcb))
{ // I-block
dbg_print("received a I-block\r\n");
if(pcb & PCB_I_RFU)
{
dbg_print("(invlid block) error PCB \r\n");
return KAL_FALSE;
}
#if defined(USIM_DEBUG)
{
kal_uint32 i;
for(i=0;i<len;i++)
{
dbg_print(" %x",usim_dcb.rx_buf[usim_dcb.rx_index+i]);
}
dbg_print("\r\n");
}
#endif
if((pcb & PCB_I_SEQ) != usim_dcb.nr)
{
dbg_print("(invlid block) receive sequence err\r\n");
return KAL_FALSE;
}
if(usim_dcb.header_rx[T1_LEN_INDEX] > usim_dcb.ifsd)
{
dbg_print("(invalid block) receive lenght > IFSD \r\n");
return KAL_FALSE;
}
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.tx_chain = KAL_FALSE;
USIM_INV_N(usim_dcb.nr);
usim_dcb.retry = 0;
usim_dcb.tx_size -= usim_dcb.header_tx[T1_LEN_INDEX];
usim_dcb.tx_index += usim_dcb.header_tx[T1_LEN_INDEX];
usim_dcb.rx_size -= usim_dcb.header_rx[T1_LEN_INDEX];
usim_dcb.rx_index += usim_dcb.header_rx[T1_LEN_INDEX];
if(pcb & PCB_I_M)
{
// a chaining I-block received send a R-block
usim_dcb.rx_chain = KAL_TRUE;
dbg_print("chaining...\r\n");
USIM_MAKE_R_BLOCK(PCB_R_STATUS_OK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -