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

📄 sim_driver.c

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

#include "sfr_def.h"
#include "id.h"

#include "sim_driver.h"
#include "v_sim_contact.h"
#include "..\mmi\wt_cnt.h"

#include "ap_ui.h"

#include "yd_debug.h"

///////////////////////////////////////////////////////////////////////////////
//
// SIM interface param
//
///////////////////////////////////////////////////////////////////////////////

#define SIM_DEFAULT_F			372			// initial bit rate
#define SIM_DEFAULT_D			1			// initial bit rate

#define SIM_DEFAULT_N			0			// extra guard time
#define SIM_DEFAULT_WI			10			// initial wait time

#define SIM_DEFAULT_BAUD_FACTOR	(SIM_DEFAULT_F / SIM_DEFAULT_D)
#define SIM_DEFAULT_CLK_COUNTER	2
#define SIM_DEFAULT_BRG_COUNTER	(SIM_DEFAULT_BAUD_FACTOR * SIM_DEFAULT_CLK_COUNTER * 2 / 16)

#define SIM_MAX_F				512
#define SIM_MAX_D				8

#define SIM_MAX_BAUD_FACTOR		(SIM_MAX_F / SIM_MAX_D)
#define SIM_MAX_CLK_COUNTER		1
#define SIM_MAX_BRG_COUNTER		(SIM_MAX_BAUD_FACTOR * SIM_MAX_CLK_COUNTER * 2 / 16)

#ifdef KEVIN_VERIFY_MSG_DEBUG	// Kevin 2005-6-29 for KEVIN_VERIFY_MSG_DEBUG
extern unsigned char  ucDebugCode[];
#endif
static unsigned char sim_atr_TS;

static unsigned short sim_guard_time, sim_wait_time;
static unsigned char sim_wait_time_WI;

static const unsigned short sim_factor_F[] = {
	372, 372, 558, 744, 1116, 1488, 1860, 0, 0, 512, 768, 1024, 1536, 2048, 0, 0
};

static const unsigned char sim_factor_D[] = {
	0, 1, 2, 4, 8, 16, 0, 0, 0, 0, -2, -4, -8, -16, -32, -64
};

static const unsigned char sim_interface_char_len[] = {
	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
};

///////////////////////////////////////////////////////////////////////////////
//
// SIM buffer
//
///////////////////////////////////////////////////////////////////////////////

#define MAX_ATR_BUFSIZE			33

#define SIM_RX_BUFSIZE			256		// kevin 2005-5-24 for sim_rx_buf size 
#define SIM_RX_BUFMASK			0xFF

static unsigned char sim_rx_buf[ SIM_RX_BUFSIZE ];	// rx ring buffer
static unsigned char sim_rx_head, sim_rx_tail;

static unsigned char sim_rx_data;

///////////////////////////////////////////////////////////////////////////////
//
// SIM driver status
//
///////////////////////////////////////////////////////////////////////////////

unsigned char sim_card_ready;

static unsigned char sim_in_transaction;

#ifdef KEVIN_VERIFY_MSG_DEBUG	// Kevin 2005-6-29 for KEVIN_VERIFY_MSG_DEBUG
unsigned char sim_rx_status;
#else
static unsigned char sim_rx_status;
#endif

#define SIM_STATUS_OK			0x00
#define SIM_STATUS_RX_ERROR		0x01
#define SIM_STATUS_RX_TIMEOUT	0x02
#define SIM_STATUS_RX_OVERFLOW	0x03
#define SIM_STATUS_VERIFY_FAIL	0x04
#define SIM_STATUS_INVALID_TS	0x05
#define SIM_STATUS_INVALID_TCK	0x06
#define SIM_STATUS_INVALID_ACK	0x07
#define SIM_STATUS_INVALID_TA1	0x08
#define SIM_STATUS_INVALID_PI1	0x09
#define SIM_STATUS_INVALID_PCK	0x0A
#define SIM_STATUS_PPS_FAIL		0x0B

///////////////////////////////////////////////////////////////////////////////
//
// UART2 routine
//
///////////////////////////////////////////////////////////////////////////////

#define UART2_C1_TX_ENABLE		0x01
#define UART2_C1_RX_ENABLE		0x04

#define UART2_start()			(u2c1 |= UART2_C1_RX_ENABLE | UART2_C1_TX_ENABLE)
#define UART2_stop()			(u2c1 &= ~(UART2_C1_RX_ENABLE | UART2_C1_TX_ENABLE))

void UART2_open(void)
{
	u2mr = 0x65;	// even parity, one stop bit, internal clock, 8 bits
	u2c0 = 0x10;	// LSB first (direct format), disable CTS/RTS, clock source f1
	u2c1 = 0x90;	// no reverse (direct format), interrupt on transmission complete

	u2brg = SIM_DEFAULT_BRG_COUNTER - 1;

	s2tic = 0x00;	/* disable tx interrupt */
	s2ric = 0x06;	/* enable rx interrupt, level 6 */
}

void UART2_close(void)
{
	u2mr = 0x00;
	u2c0 = 0x00;
	u2c1 = 0x00;
	
	s2tic = 0x00;	/* disable tx interrupt */
	s2ric = 0x00;	/* disable rx interrupt */
}

void UART2_tx_int(void)
{
	/* do not use interrupt mode, because guardtime required */
}

void UART2_rx_int(void)
{
	unsigned char rx_status, rx_data;
	unsigned char ptr;

	rx_data = u2rbl;
	rx_status = u2rbh;
	asm(" fset i");

	if (rx_status & 0xF0)
	{
		sim_rx_status = SIM_STATUS_RX_ERROR;
	}
	else
	{
		ptr = (sim_rx_tail + 1) & SIM_RX_BUFMASK;
		if (ptr == sim_rx_head)
		{
			sim_rx_status = SIM_STATUS_RX_OVERFLOW;
		}
		else
		{
			sim_rx_buf[ sim_rx_tail ] = rx_data;
			sim_rx_tail = ptr;
		}
	}
}

///////////////////////////////////////////////////////////////////////////////
//
// Ring Buffer
//
///////////////////////////////////////////////////////////////////////////////

static void SIM_ResetRingBuffer(void)
{
	sim_rx_status = SIM_STATUS_OK;
	sim_rx_head = sim_rx_tail = 0;
}

///////////////////////////////////////////////////////////////////////////////
//
// Timer function
//
///////////////////////////////////////////////////////////////////////////////

static void SIM_PrepareTimer(unsigned char clk_src, unsigned short interval)
{
	SIM_CNT_taXs = 0;
	SIM_CNT_taXmr = clk_src | 0x02;	/* one-shot timer mode */
	SIM_CNT_taXic = 0x00;	/* disable interrupt */
	SIM_CNT_taX = interval;
	SIM_CNT_taXs = 1;
}

static void SIM_Delay(void)
{
	SIM_CNT_taXos = 1;
	while (SIM_CNT_ir_taXic != 1)	/* wait time expired */
		;
	SIM_CNT_ir_taXic = 0;
}

///////////////////////////////////////////////////////////////////////////////
//
// CLK function
//
///////////////////////////////////////////////////////////////////////////////

static void SIM_CLK_Init(void)
{
	SIM_CLK_taXs = 0;
	SIM_CLK_taXic = 0x00;	/* disable interrupt */
	SIM_CLK_taXmr = 0x04;   /* timer mode, clock souce f1, pulse output */
	SIM_CLK_taX = SIM_DEFAULT_CLK_COUNTER - 1;
}

static void SIM_CLK_SwitchOn(void)
{
	sim_in_transaction = 1;
	STimerMgr_StopTimer(ID_STIMER_SIM_DRIVER);

	if (MFLG_WAIT_SIM_DRIVER == 0)	// CLK maybe stopped before
	{
#if 0
		if (SIM_CLK_taXs == 0)
			SIM_CLK_taXs = 1;
#endif
			
		SIM_PrepareTimer(0x40, 744 - 1);	// clock source f8
		SIM_Delay();
	}
}

static void SIM_CLK_SwitchOff(void)
{
	if (sim_in_transaction)
		return;

#if 0
	if (SIM_CLK_taXs == 1)
		SIM_CLK_taXs = 0;
#endif

	MFLG_WAIT_SIM_DRIVER = 0;	// enable WAIT mode
}

static void SIM_CLK_PrepareOff(void)
{
	MFLG_WAIT_SIM_DRIVER = 1;	// disable WAIT mode

	sim_in_transaction = 0;
	STimerMgr_StartTimer(ID_STIMER_SIM_DRIVER, 2, SIM_CLK_SwitchOff);	// wait 1860 CLK at least
}

///////////////////////////////////////////////////////////////////////////////
//
// SIM IO routine
//
///////////////////////////////////////////////////////////////////////////////

static unsigned char SIM_SendByte(unsigned char tx_data)
{
	extern const far unsigned char t_invert[256];
	unsigned char rx_data;

	if (sim_atr_TS != 0x3B)
	{
		tx_data = t_invert[ ~tx_data ];	/* inverse and reverse the data */
	}
	
	u2tb = tx_data;
	while (txept_u2c0 != 1)	/* wait transmission complete */
		;

	while (sim_rx_status == SIM_STATUS_OK)
	{
		if (sim_rx_head != sim_rx_tail)
		{
			rx_data = sim_rx_buf[ sim_rx_head ];
			sim_rx_head = (sim_rx_head + 1) & SIM_RX_BUFMASK;

			/* verify send byte */
			if (rx_data != tx_data)
			{
                                sim_rx_status = SIM_STATUS_VERIFY_FAIL;
                            }
			break;
		}
	}
	
	return sim_rx_status;
}

static unsigned char SIM_ReceiveByte(void)
{
	extern const far unsigned char t_invert[256];
	unsigned char WI;

	WI = sim_wait_time_WI;

	SIM_CNT_ir_taXic = 0;
	SIM_CNT_taXos = 1;	/* start wait time */

	while (sim_rx_status == SIM_STATUS_OK)
	{
		if (sim_rx_head != sim_rx_tail)
		{
			sim_rx_data = sim_rx_buf[ sim_rx_head ];
			sim_rx_head = (sim_rx_head + 1) % SIM_RX_BUFSIZE;
			if (sim_atr_TS != 0x3B)
			{
				sim_rx_data = t_invert[ ~sim_rx_data ];	/* inverse and reverse the data */
			}
			break;
		}

		if (SIM_CNT_ir_taXic == 1)
		{
			SIM_CNT_ir_taXic = 0;

			WI--;
			if (WI == 0)	/* wait time expired */
			{
				sim_rx_status = SIM_STATUS_RX_TIMEOUT;
				break;
			}

			SIM_CNT_taXos = 1;	/* restart wait time */
		}
	}
	
	return sim_rx_status;
}

static void SIM_SendBuffer(unsigned char *tx_buf, unsigned char tx_len)
{
	/* prepare guard time */
	SIM_PrepareTimer(0x40, sim_guard_time);	// clock source f8
	
	do
	{
		SIM_Delay();

		if (SIM_SendByte( *tx_buf++ ) != SIM_STATUS_OK)
			return;
	} while (--tx_len);
}

static void SIM_ReceiveBuffer(unsigned char *rx_buf, unsigned char rx_len)
{
	do
	{
		if (SIM_ReceiveByte() != SIM_STATUS_OK)
			return;

		*rx_buf++ = sim_rx_data;
	} while (--rx_len);
}

///////////////////////////////////////////////////////////////////////////////
//
// PPS Transaction
//
///////////////////////////////////////////////////////////////////////////////

static unsigned char SIM_CalcCheckChar(unsigned char *buf, unsigned char len)
{
	unsigned char i, ck = 0;

	for (i = 0; i < len; i++)
		ck ^= buf[i];	

	return ck;
}

static void SIM_Transaction_PPS(unsigned char *req, unsigned char *rsp)
{
	unsigned char len;
	
	/* send PPS */
	len = sim_interface_char_len[ req[1] >> 4 ] + 3;

	SIM_SendBuffer(&req[0], len);
	if (sim_rx_status != SIM_STATUS_OK)
		return;

	/* prepare wait time */
	SIM_PrepareTimer(0x80, sim_wait_time);	// clock source f32

	/* receive PPSS, PPS0 */
	SIM_ReceiveBuffer(&rsp[0], 2);
	if (sim_rx_status != SIM_STATUS_OK)
		return;

	/* receive PPS1, PPS2, PPS3, PCK */
	len = sim_interface_char_len[ rsp[1] >> 4 ] + 1;

	SIM_ReceiveBuffer(&rsp[2], len);
	if (sim_rx_status != SIM_STATUS_OK)
		return;
	
	len += 2;
	if (SIM_CalcCheckChar(rsp, len) != 0)
	{
		sim_rx_status = SIM_STATUS_INVALID_PCK;
	}
	else if (rsp[0] != 0xFF)	// PPSS
	{
		sim_rx_status = SIM_STATUS_PPS_FAIL;
	}
}

///////////////////////////////////////////////////////////////////////////////
//
// SIM driver routine
//
///////////////////////////////////////////////////////////////////////////////

static void SIM_SetInterfaceParams(unsigned short baud_factor, unsigned char clk_counter, unsigned char N, unsigned char WI)
{
	unsigned short tmp = baud_factor * clk_counter;
	
	sim_guard_time = ((unsigned short)(N + (12 - 10)) * (tmp * 2 / 8)) - 1;	// clock source f8
	sim_wait_time = (tmp * 2 * (960 / 32)) - 1;	// clock source 32
	sim_wait_time_WI = WI;
}

void SIM_OpenDriver(void)
{
	union {
		unsigned char atr[MAX_ATR_BUFSIZE];	// answer to reset
		struct {
			unsigned char req[6];
			unsigned char rsp[6];
		} pps;	// protocol and parameter selection
	} buf;
	unsigned char rx_ptr, rx_len;
	unsigned char protocol_type_T;
	unsigned char interface_char_lvl, interface_char_map;
	unsigned char interface_char_TA1, interface_char_TB1, interface_char_TC1, interface_char_TC2;
	unsigned short factor_F, baud_factor, brg_counter;
	unsigned char factor_D, clk_counter, pps_selection;

         
	SIM_ResetRingBuffer();
	SIM_SetInterfaceParams(SIM_DEFAULT_BAUD_FACTOR, SIM_DEFAULT_CLK_COUNTER, SIM_DEFAULT_N, SIM_DEFAULT_WI);

	/* activate SIM contact */
	SIM_RST = 0;		/* RST is in state L */
#ifdef SIM_CNTL
	SIM_CNTL = 1;		/* VCC shall be powered */
#endif
	SIM_IO_OUT = 1;		/* I/O in the interface device shall be put in reception mode */

	SIM_CLK_Init();		/* CLK shall be provided with a suitable and stable clock */
	SIM_CLK_taXs = 1;

	/* set minimum reset time */
	SIM_PrepareTimer(0x80, (SIM_DEFAULT_CLK_COUNTER * 2 * (40000 / 32)) - 1);	// clock source f32
	SIM_Delay();

	/* open UART2 port */
	UART2_open();

	/* prepare receiving ATR */
	sim_atr_TS = 0x3B;	
	protocol_type_T = 0;

	/* prepare wait time */
	SIM_PrepareTimer(0x80, sim_wait_time);	// clock source f32

	SIM_RST = 1;

	/* start ATR */
	UART2_start();

	/* receive TS */
	if (SIM_ReceiveByte() != SIM_STATUS_OK)
		goto label_atr_stop;

	if (sim_rx_data != 0x3B && sim_rx_data != 0x03)
	{
		sim_rx_status = SIM_STATUS_INVALID_TS;
		goto label_atr_stop;
	}
	
	sim_atr_TS = sim_rx_data;

	/* receive T0 */
	if (SIM_ReceiveByte() != SIM_STATUS_OK)
		goto label_atr_stop;

	buf.atr[0] = sim_rx_data;

	/* receive interface char */
	rx_ptr = 1;
	interface_char_lvl = 0;
	interface_char_map = buf.atr[0] >> 4;	/* Y1 */

	while (interface_char_map)
	{
		rx_len = sim_interface_char_len[ interface_char_map ];

		SIM_ReceiveBuffer(&buf.atr[rx_ptr], rx_len);
		if (sim_rx_status != SIM_STATUS_OK)
			goto label_atr_stop;

		interface_char_lvl++;
		if (interface_char_lvl == 1)
		{
			if (interface_char_map & 0x08)	/* TD1 */
				protocol_type_T = sim_rx_data & 0x0F;
		}

		rx_ptr += rx_len;
		if (interface_char_map & 0x08)	/* check TDi */
			interface_char_map = sim_rx_data >> 4;	/* Yi+1 */
		else
			interface_char_map = 0;
	}

	/* receive historical char */
	rx_len = buf.atr[0] & 0x0F;
	if (rx_len != 0)
	{
		SIM_ReceiveBuffer(&buf.atr[rx_ptr], rx_len);
		if (sim_rx_status != SIM_STATUS_OK)
			goto label_atr_stop;
		
		rx_ptr += rx_len;
	}

	/* receive TCK */
	if (protocol_type_T != 0)
	{
		if (SIM_ReceiveByte() != SIM_STATUS_OK)
			goto label_atr_stop;
	
		buf.atr[ rx_ptr++ ] = sim_rx_data;
	}
		
	/* stop ATR */
label_atr_stop:
	UART2_stop();

	if (sim_rx_status != SIM_STATUS_OK)
	{
label_open_driver_error:
		SIM_CloseDriver();                  
		return;
	}
	

⌨️ 快捷键说明

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