📄 sim_driver.c
字号:
/* set default value */
interface_char_TA1 = 0x11; /* F:372, D:1 */
interface_char_TC1 = SIM_DEFAULT_N;
interface_char_TC2 = SIM_DEFAULT_WI;
/* parse interface charater */
rx_ptr = 1;
interface_char_lvl = 0;
interface_char_map = buf.atr[0] >> 4; /* Y1 */
while (interface_char_map)
{
interface_char_lvl++;
switch (interface_char_lvl)
{
case 1:
if (interface_char_map & 0x01) /* TA1 */ /* clock rate conversion factor FI and bit rate adjustment factor DI */
{
interface_char_TA1 = buf.atr[rx_ptr];
if (sim_factor_F[ interface_char_TA1 >> 4 ] == 0 ||
sim_factor_D[ interface_char_TA1 & 0x0F ] == 0)
{
sim_rx_status = SIM_STATUS_INVALID_TA1;
goto label_open_driver_error;
}
}
if (interface_char_map & 0x02) /* TB1 */ /* programming current factor II and programming voltage factor PI1 */
{
interface_char_TB1 = buf.atr[rx_ptr + sim_interface_char_len[interface_char_map & 0x01]];
if ((interface_char_TB1 & 0x1F) != 0)
{
sim_rx_status = SIM_STATUS_INVALID_PI1; /* VPP is not connected internally in card */
goto label_open_driver_error;
}
}
if (interface_char_map & 0x04) /* TC1 */ /* extra guard time N */
{
interface_char_TC1 = buf.atr[rx_ptr + sim_interface_char_len[interface_char_map & 0x03]];
}
break;
case 2:
if (interface_char_map & 0x04) /* TC2 */ /* working wait time WI */
{
interface_char_TC2 = buf.atr[rx_ptr + sim_interface_char_len[interface_char_map & 0x03]];
}
break;
default:
break;
}
rx_ptr += sim_interface_char_len[interface_char_map];
if (interface_char_map & 0x08) /* TDi present */
interface_char_map = buf.atr[rx_ptr - 1] >> 4;
else
interface_char_map = 0;
}
/* ignore historical charater and TCK */
SIM_SetInterfaceParams(SIM_DEFAULT_BAUD_FACTOR, SIM_DEFAULT_CLK_COUNTER, interface_char_TC1, interface_char_TC2);
/* check protocol parameter */
if ((protocol_type_T == 0) &&
(interface_char_TA1 == 0x11 || interface_char_TA1 == 0x01))
{
goto label_open_driver_ok;
}
factor_F = sim_factor_F[ interface_char_TA1 >> 4 ];
factor_D = sim_factor_D[ interface_char_TA1 & 0x0F ];
if (factor_D & 0x80)
baud_factor = factor_F * (-factor_D);
else
baud_factor = factor_F / factor_D;
if ((baud_factor & 0x03) != 0) // baud_factor is not a multiple of 4
{
label_use_default_rate:
pps_selection = 0; // use default rate
baud_factor = SIM_DEFAULT_BAUD_FACTOR;
clk_counter = SIM_DEFAULT_CLK_COUNTER;
brg_counter = SIM_DEFAULT_BRG_COUNTER;
}
else
{
if ((baud_factor & 0x07) == 0)
clk_counter = 1; // baud_factor is a multiple of 8
else
clk_counter = 2; // baud_factor is a multiple of 4
brg_counter = (baud_factor * clk_counter * 2 / 16);
if (brg_counter < SIM_DEFAULT_BRG_COUNTER)
{
pps_selection = 1; // use speed rate
if (brg_counter < SIM_MAX_BRG_COUNTER)
{
baud_factor = SIM_MAX_BAUD_FACTOR;
clk_counter = SIM_MAX_CLK_COUNTER;
brg_counter = SIM_MAX_BRG_COUNTER;
interface_char_TA1 = 0x94;
}
}
else
goto label_use_default_rate;
}
/* prepare PPS */
buf.pps.req[0] = 0xFF; // PPSS
if (pps_selection)
{
buf.pps.req[1] = 0x10; // PPS0
buf.pps.req[2] = interface_char_TA1; // PPS1
buf.pps.req[3] = SIM_CalcCheckChar(buf.pps.req, 3); // PCK
}
else
{
buf.pps.req[1] = 0x00; // PPS0
buf.pps.req[2] = 0xFF; // PCK
}
/* start PPS */
UART2_start();
/* PPS transaction */
SIM_Transaction_PPS(buf.pps.req, buf.pps.rsp);
/* stop PPS */
UART2_stop();
if (sim_rx_status != SIM_STATUS_OK)
{
sim_rx_status = SIM_STATUS_PPS_FAIL;
goto label_open_driver_error;
}
sim_rx_status = SIM_STATUS_PPS_FAIL;
if ((buf.pps.rsp[1] & 0x0F) != 0) /* T != 0 */
goto label_open_driver_error;
if ((buf.pps.rsp[1] & 0x10) == 0) /* card wants to use default rate */
goto label_open_driver_ok;
if (pps_selection)
{
if (buf.pps.rsp[2] != interface_char_TA1)
goto label_open_driver_error;
SIM_CLK_taX = clk_counter - 1;
u2brg = brg_counter - 1;
SIM_SetInterfaceParams(baud_factor, clk_counter, interface_char_TC1, interface_char_TC2);
}
else
{
if (buf.pps.rsp[2] != 0x11) /* card dont want to use default rate */
goto label_open_driver_error;
}
label_open_driver_ok:
sim_card_ready = 1;
SIM_CLK_PrepareOff();
}
void SIM_CloseDriver(void)
{
sim_card_ready = 0;
/* close UART2 port */
UART2_close();
/* deactivate SIM contact */
SIM_RST = 0; /* RST is in state L */
SIM_IO_OUT = 0; /* I/O is in state A */
#ifdef SIM_CNTL
SIM_CNTL = 0; /* VCC shall be off */
#endif
SIM_CLK_taXs = 0; /* CLK stop */
MFLG_WAIT_SIM_DRIVER = 0; // enable WAIT mode
}
///////////////////////////////////////////////////////////////////////////////
//
// SIM Transaction
//
///////////////////////////////////////////////////////////////////////////////
#define SIM_Transaction_SendHeader(h) SIM_SendBuffer(h, 5)
#define SIM_Transaction_SendData SIM_SendBuffer
static unsigned char SIM_ReceiveACK(void)
{
while (1)
{
if (SIM_ReceiveByte() != SIM_STATUS_OK)
break;
if (sim_rx_data != 0x60)
break;
}
return sim_rx_status;
}
static void SIM_Transaction_SendData_ACK(unsigned char *tx_buf, unsigned char tx_len, unsigned char INS)
{
while (1)
{
if (SIM_SendByte( *tx_buf++ ) != SIM_STATUS_OK)
return;
tx_len--;
if (tx_len == 0)
break;
if (SIM_ReceiveACK() != SIM_STATUS_OK)
return;
if (INS != (~sim_rx_data & 0xFE))
{
sim_rx_status = SIM_STATUS_INVALID_ACK;
return;
}
}
}
void SIM_Transaction_ReceiveData(unsigned char *rx_buf, unsigned char Le)
{
unsigned short rx_len;
unsigned char rx_ptr;
if (Le == 0)
rx_len = 256;
else
rx_len = Le;
/* prepare wait time */
SIM_PrepareTimer(0x80, sim_wait_time); // clock source f32
do
{
if (SIM_ReceiveByte() != SIM_STATUS_OK)
return;
*rx_buf++ = sim_rx_data;
} while (--rx_len);
}
static void SIM_Transaction_ReceiveData_ACK(unsigned char *rx_buf, unsigned char Le, unsigned char INS)
{
unsigned short rx_len;
if (Le == 0)
rx_len = 256;
else
rx_len = Le;
/* prepare wait time */
SIM_PrepareTimer(0x80, sim_wait_time); // clock source f32
while (1)
{
if (SIM_ReceiveByte() != SIM_STATUS_OK)
return;
*rx_buf++ = sim_rx_data;
rx_len--;
if (rx_len == 0)
break;
if (SIM_ReceiveACK() != SIM_STATUS_OK)
return;
if (INS != (~sim_rx_data & 0xFE))
{
sim_rx_status = SIM_STATUS_INVALID_ACK;
return;
}
} while (--rx_len);
}
static void SIM_Transaction_ReceiveStatus(sim_transaction_t *transaction)
{
/* prepare wait time */
SIM_PrepareTimer(0x80, sim_wait_time); // clock source f32
if (SIM_ReceiveACK() != SIM_STATUS_OK)
return;
transaction->SW1 = sim_rx_data;
if (SIM_ReceiveByte() != SIM_STATUS_OK)
return;
transaction->SW2 = sim_rx_data;
}
static void SIM_Transaction_ReceiveResponse(sim_transaction_t *transaction)
{
/* prepare wait time */
SIM_PrepareTimer(0x80, sim_wait_time); // clock source f32
if (SIM_ReceiveACK() != SIM_STATUS_OK)
return;
if (transaction->INS == (sim_rx_data & 0xFE))
{
SIM_Transaction_ReceiveData(transaction->rsp_data, transaction->P3);
if (sim_rx_status != SIM_STATUS_OK)
return;
SIM_Transaction_ReceiveStatus(transaction);
}
else if (transaction->INS == (~sim_rx_data & 0xFE))
{
SIM_Transaction_ReceiveData_ACK(transaction->rsp_data, transaction->P3, transaction->INS);
if (sim_rx_status != SIM_STATUS_OK)
return;
SIM_Transaction_ReceiveStatus(transaction);
}
else
{
transaction->SW1 = sim_rx_data;
if (SIM_ReceiveByte() != SIM_STATUS_OK)
return;
transaction->SW2 = sim_rx_data;
}
}
static void SIM_Transaction_SendCommand(sim_transaction_t *transaction)
{
/* prepare wait time */
SIM_PrepareTimer(0x80, sim_wait_time); // clock source f32
if (SIM_ReceiveACK() != SIM_STATUS_OK)
return;
if (transaction->INS == (sim_rx_data & 0xFE))
{
SIM_Transaction_SendData(transaction->cmd_data, transaction->P3);
if (sim_rx_status != SIM_STATUS_OK)
return;
SIM_Transaction_ReceiveStatus(transaction);
}
else if (transaction->INS == (~sim_rx_data & 0xFE))
{
SIM_Transaction_SendData_ACK(transaction->cmd_data, transaction->P3, transaction->INS);
if (sim_rx_status != SIM_STATUS_OK)
return;
SIM_Transaction_ReceiveStatus(transaction);
}
else
{
transaction->SW1 = sim_rx_data;
if (SIM_ReceiveByte() != SIM_STATUS_OK)
return;
transaction->SW2 = sim_rx_data;
}
}
static void SIM_Transaction_GetResponse(sim_transaction_t *transaction)
{
unsigned char Le;
sim_transaction_t get_response;
Le = transaction->cmd_data[ transaction->P3 ];
if (transaction->SW1 == 0x61)
{
if (transaction->SW2 < Le)
Le = transaction->SW2;
}
get_response.CASE = SIM_CASE_2;
get_response.CLA = transaction->CLA;
get_response.INS = 0xC0;
get_response.P1 = 0;
get_response.P2 = 0;
get_response.P3 = Le;
get_response.cmd_data = 0;
get_response.rsp_data = transaction->rsp_data;
/* GET_RESPONSE send transaction header */
SIM_Transaction_SendHeader(&get_response.CLA);
if (sim_rx_status != SIM_STATUS_OK)
return;
SIM_Transaction_ReceiveResponse(&get_response);
if (sim_rx_status != SIM_STATUS_OK)
return;
transaction->SW1 = get_response.SW1;
transaction->SW2 = get_response.SW2;
}
void SIM_Transaction(sim_transaction_t *transaction)
{
if (!sim_card_ready)
goto label_unspecified_error;
SIM_CLK_SwitchOn();
SIM_ResetRingBuffer();
UART2_start();
/* send transaction header */
SIM_Transaction_SendHeader(&transaction->CLA);
if (sim_rx_status != SIM_STATUS_OK)
goto label_uart2_stop;
switch (transaction->CASE)
{
case SIM_CASE_1:
SIM_Transaction_ReceiveStatus(transaction);
break;
case SIM_CASE_2:
SIM_Transaction_ReceiveResponse(transaction);
break;
case SIM_CASE_3:
SIM_Transaction_SendCommand(transaction);
break;
case SIM_CASE_4:
SIM_Transaction_SendCommand(transaction);
if (sim_rx_status != SIM_STATUS_OK)
goto label_uart2_stop;
if (!(transaction->SW1 == 0x61) &&
!(transaction->SW1 == 0x90 && transaction->SW2 == 0x00))
{
goto label_uart2_stop;
}
SIM_Transaction_GetResponse(transaction);
break;
}
label_uart2_stop:
UART2_stop();
SIM_CLK_PrepareOff();
if (sim_rx_status != SIM_STATUS_OK)
{
label_unspecified_error:
#ifdef KEVIN_VERIFY_MSG_DEBUG // Kevin 2005-6-29 for KEVIN_VERIFY_MSG_DEBUG
ucDebugCode[1] = sim_rx_status;
#endif
transaction->SW1 = 0x6F; // no precise diagnosis
transaction->SW2 = 0x00;
}
}
#if 0 // for test only
sim_transaction_t test;
unsigned char cmd_data[10];
unsigned char rsp_data[30];
unsigned char SIM_Test1(void)
{
/* SELECT DFtelecom */
test.CASE = SIM_CASE_3;
test.CLA = 0xA0;
test.INS = 0xA4;
test.P1 = 0;
test.P2 = 0;
test.P3 = 2;
test.cmd_data = cmd_data;
test.rsp_data = 0;
cmd_data[0] = 0x7F;
cmd_data[1] = 0x10;
SIM_Transaction(&test);
if (test.SW1 != 0x9F)
return 1;
/* GET_RESPONSE */
test.CASE = SIM_CASE_2;
test.CLA = 0xA0;
test.INS = 0xC0;
test.P1 = 0;
test.P2 = 0;
test.P3 = test.SW2;
test.cmd_data = 0;
test.rsp_data = rsp_data;
SIM_Transaction(&test);
if (test.SW1 == 0x90 && test.SW2 == 0x00)
return 0;
else
return 1;
}
unsigned char SIM_Test2(void)
{
/* SELECT EFADN */
test.CASE = SIM_CASE_3;
test.CLA = 0xA0;
test.INS = 0xA4;
test.P1 = 0;
test.P2 = 0;
test.P3 = 2;
test.cmd_data = cmd_data;
test.rsp_data = 0;
cmd_data[0] = 0x6F;
cmd_data[1] = 0x3A;
SIM_Transaction(&test);
if (test.SW1 != 0x9F)
return 1;
/* GET_RESPONSE */
test.CASE = SIM_CASE_2;
test.CLA = 0xA0;
test.INS = 0xC0;
test.P1 = 0;
test.P2 = 0;
test.P3 = test.SW2;
test.cmd_data = 0;
test.rsp_data = rsp_data;
SIM_Transaction(&test);
if (test.SW1 == 0x90 && test.SW2 == 0x00)
return 0;
else
return 1;
}
#endif // for test only
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -