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

📄 sim_driver.c

📁 对SIM卡进行操作的驱动程序。实现了GSM规范中规定的基本功能。该驱动也是基于三菱M16C/60MCU的
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* 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 + -