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

📄 card.c

📁 psam+sim+sam的一些技术文档
💻 C
字号:
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<ctype.h>
#include	<absacc.h>
#include	<reg52.h>
#include	<usign.h>
#include	<float.h>
#include 	<INTRINS.h>
#include	"hardware.h"
#include	"card.h"

uchar		bTC1;

/*
功能:卡片冷复位
输入:CardSocketNo:卡座号(0:CPU用户卡或SLE4404; 1:PSAM1; 2:PSAM2)
      pDataMsg:数据缓冲区
      	nLength:接收数据长度
      	Cmdbuf: 未使用
      	DataBuf:接收数据
返回:
	0x9000:操作成功
	0x0303:无该卡座号
	0x0101:通讯错误
*/
uint Card_Cold_Reset(uchar CardSocketNo,DATAMESSAGE  *pDataMsg)
{
	uchar length;
	
	if(CardSocketNo>2)
		return 0x0303;
	length = _CardSmartOpen(CardSocketNo ,pDataMsg->DataBuf);
	if(length == 0)return 0x0101;
	pDataMsg->nLength = length;
	_Delay(COMM_DELAY_ETU);
	return 0x9000;
}

/*
功能:卡片热复位
输入:CardSocketNo:卡座号(0:CPU用户卡或SLE4404; 1:PSAM1; 2:PSAM2)
      pDataMsg:数据缓冲区
      	nLength:接收数据长度
      	Cmdbuf: 未使用
      	DataBuf:接收数据
返回:
	0x9000:操作成功
	0x0303:无该卡座号
	0x0101:通讯错误
*/
uint Card_Warm_Reset(uchar CardSocketNo,DATAMESSAGE  *pDataMsg)
{
	uchar length;
	
	if(CardSocketNo>2)
		return 0x0303;
	length = _CardSmartOpen(CardSocketNo ,pDataMsg->DataBuf);
	if(length == 0)return 0x0101;
	pDataMsg->nLength = length;
	_Delay(COMM_DELAY_ETU);	
	return 0x9000;
}

/*
功能:从卡片读取数据
输入: chPosition:卡座号(0:CPU用户卡或SLE4404; 1:PSAM1; 2:PSAM2)
      pDataMsg:数据缓冲区
      	nLength:实际接收数据长度 (应为:未使用)
      	Cmdbuf: CPU卡指令
      	DataBuf:接收数据
返回:
	0x9000:操作成功
	0x0303:无该卡座号
	0x0101:通讯错误
*/
uint  CPU_Card_Read (uchar chPosition,DATAMESSAGE  *pDataMsg)
{
	uint	iStatus;

	if(chPosition >2)return 0x0303;
	_CardSetCard(chPosition);
	if(chPosition == 0)
	   if(_CardTestDoor())return 0x0202;

	pDataMsg->nLength=5;
	iStatus=_CardSmartApdu(chPosition,pDataMsg);
/*	if( (uchar)(iStatus>>8) ==0x61)
		return	0x9000;
	if( iStatus!=0x9000)
 		return 0x0101;
 	else
 		return	0x9000;
*/
	_Delay(COMM_DELAY_ETU);
	return	 iStatus;				
}

/*
功能:
输入: chPosition:卡座号(0:CPU用户卡或SLE4404; 1:PSAM1; 2:PSAM2)
      pDataMsg:数据缓冲区
      	nLength:未使用
      	Cmdbuf: CPU卡指令
      	DataBuf:等待发送的数据
返回:
	0x9000:操作成功
	0x0303:无该卡座号
	0x0101:通讯错误
*/
uint  CPU_Card_Write (uchar chPosition,DATAMESSAGE  *pDataMsg)
{
	uint	iStatus;

	if(chPosition >2)return 0x0303;
	_CardSetCard(chPosition);
	if(chPosition == 0)
	   if(_CardTestDoor())return 0x0202;

	pDataMsg->nLength=(pDataMsg->CmdBuf[4])+5;
	iStatus=_CardSmartApdu(chPosition,pDataMsg);
/*	if( (uchar)(iStatus>>8) ==0x61)
		return	0x9000;
	if( iStatus!=0x9000)
 		return 0x0101;
 	else
 		return	0x9000;
*/
	_Delay(COMM_DELAY_ETU);
	return	 iStatus;				//为测试方便,返回状态吗,正常使用按银行规定返回		
}



/*                  
功能:测试用户卡是否插入
输入:
输出: 1:未插入;0:插入
注意:
*/              
uchar	_CardTestDoor(void)
{
	if(INSERT==1)
		return 1;
	else
		return 0;
}	

/*                  
功能:选择卡座
输入:0:用户卡;1:PSAM1; 2:PSAM2
输出: 
注意:
*/              
void   _CardSetCard(uchar ICNO)
{
	if(ICNO==0)
	{
         S1=0;               
         S0=0;               
         return;
    }                    
	if(ICNO==1)
	{
         S1=0;               
         S0=1;               
         return;
    }             
	if(ICNO==2)
	{
         S1=1;               
         S0=0;               
         return;
    }  
    S1=1;               
    S0=1;               
    return;
}                           

/*                  
功能:用户卡/PSAM1/PSAM2复位
输入:0:用户卡;1:PSAM1; 2:PSAM2
输出: ATR数据的长度(0:复位失败;其他:复位正确) 
      ResetData:ATR数据;
注意:
      1ETU=372*4/12=124指令周期
*/   
uchar  _CardSmartOpen(uchar CardSocketNo ,uchar *ResetData)
{
	code	const	uchar	abF1[11]={0x10,0x20,0x30,0x40,0x50,0x60,0x90,0xa0,0xb0,0xc0,0xd0};		//合法的F1,内部时钟不支持
	code	const	uchar	abD1[11]={0x01,0x02,0x03,0x04,0x05,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};		//合法的D1
	uchar	bLoc,i,bResetTines,bRetCode;
	uchar	bTA1,bTD1,bTDi,bHisLen,bF1,bD1;
	uint	iRetCodeChar;

	_CardSetCard(CardSocketNo);				//选择相应卡座的IO

	if(CardSocketNo==0)						//用户卡
	{
		if(POWER_CONTROL==1)				//冷复位
			bResetTines=2;					//一次冷复位和一次热复位
		else
			bResetTines=1;					//仅一次热复位,	针对人行检测中心的检测	
	}
	else
	{
		bResetTines=2;						//PSAM卡:一次冷复位和一次热复位									
	}
	while(1)
	{
		if(CardSocketNo==0)					//用户卡
		{
			if(POWER_CONTROL==1)
			{
				RSTCPU=0;						//RST=0,冷复位
				POWER_CONTROL=0;				//vcc=1
				_Delay(1);
				IO=1;							//IO=1
				ENCLK=1;
				ENCLKCPU=1;
				ENCLK4404=0;					//CLK有效
				_Delay(9);						//delay 41472 clk(clk=4.608MHZ,4.608*9=41472 CLK)
				RSTCPU=1;						//RST=1
			}
			else
			{
				RSTCPU=0;						//RST=0,热复位
				POWER_CONTROL=0;				//vcc=1
				IO=1;							//IO=1
				ENCLK=1;
				ENCLKCPU=1;
				ENCLK4404=0;					//CLK有效
				_Delay(9);						//delay 41472 clk(clk=4.608MHZ,4.608*9=41472 CLK)
				RSTCPU=1;						//RST=1
			}				
				
		}
		if(CardSocketNo==PSAM1)				//PSAM1
		{
			RSTPSAM1=0;						//RST=0,冷复位和热复位时序可统一
			_Delay(1);
			IO=1;							//IO=1
			ENCLK=1;
			ENCLKPSAM1=1;
			ENCLK4404=0;					//CLK有效
			_Delay(9);						//delay 41472 clk(clk=4.608MHZ,4.608*9=41472 CLK)
			RSTPSAM1=1;						//RST=1
		}
		if(CardSocketNo==PSAM2)				//PSAM1
		{
			RSTPSAM2=0;						//RST=0,冷复位和热复位时序可统一
			_Delay(1);
			IO=1;							//IO=1
			ENCLK=1;
			ENCLKPSAM2=1;
			ENCLK4404=0;					//CLK有效
			_Delay(9);						//delay 41472 clk(clk=4.608MHZ,4.608*9=41472 CLK)
			RSTPSAM2=1;						//RST=1
		}		

		iRetCodeChar=GetByteFirstATR();		//TS					
		bRetCode=(uchar)(iRetCodeChar>>8);
		if(bRetCode==TIMEOUT)
		{
			vReleaseCard();					//通讯超时,释放卡片
			return 0;										
		}
		if(bRetCode!=OK)
			goto	RESET_AGAIN;			//接收数据出错,重新复位
		if( (uchar)iRetCodeChar!=0x3b)
			goto	RESET_AGAIN;
		ResetData[0]=(uchar)iRetCodeChar;			
    	
		iRetCodeChar=GetByteATR();					//T0					
		bRetCode=(uchar)(iRetCodeChar>>8);	
		if(bRetCode!=OK)
		{
			goto	RESET_AGAIN;				//接收数据出错,重新复位				
		}		
		ResetData[1]=(uchar)iRetCodeChar;			
		bTDi=( (uchar)iRetCodeChar) &0xf0;
		bHisLen=( (uchar)iRetCodeChar) &0x0f;			//历史字节的长度
		i=0;
		bTA1=0x11;										//TA1的缺省值
		bTC1=0x00;										//TC1的缺省值
		bTD1=0x00;										//TD1的缺省值	
		bLoc=2;									//ATR的位置																
		while(bTDi)
		{
			if( (bTDi&0x10)==0x10)
			{
				iRetCodeChar=GetByteATR();					//TAi					
				bRetCode=(uchar)(iRetCodeChar>>8);	
				if(bRetCode!=OK)
				{
					goto	RESET_AGAIN;				//接收数据出错,重新复位
				}		
				ResetData[bLoc]=(uchar)iRetCodeChar;			
				bLoc++;
				if(i==0)
					bTA1=(uchar)iRetCodeChar;
			}
			if( (bTDi&0x20)==0x20)
			{
				iRetCodeChar=GetByteATR();					//TBi					
				bRetCode=(uchar)(iRetCodeChar>>8);	
				if(bRetCode!=OK)
				{
					goto	RESET_AGAIN;				//接收数据出错,重新复位					
				}		
				ResetData[bLoc]=(uchar)iRetCodeChar;			
				bLoc++;
			}
			if( (bTDi&0x40)==0x40)
			{
				iRetCodeChar=GetByteATR();					//TCi
				bRetCode=(uchar)(iRetCodeChar>>8);	
				if(bRetCode!=OK)
				{
					goto	RESET_AGAIN;				//接收数据出错,重新复位
				}		
				ResetData[bLoc]=(uchar)iRetCodeChar;			
				bLoc++;
				if(i==0)
				{
					bTC1=(uchar)iRetCodeChar;			
					if(bTC1==0xff)
						bTC1=0;							//TC1=0xff,即等价为TC1=0
				}
			}
			bTDi=bTDi&0x80;								//清TAi,TBi,TCi对应地位
			if( (bTDi&0x80)==0x80)
			{
				iRetCodeChar=GetByteATR();					//TDi					
				bRetCode=(uchar)(iRetCodeChar>>8);	
				if(bRetCode!=OK)
				{
					goto	RESET_AGAIN;				//接收数据出错,重新复位
				}		
				ResetData[bLoc]=(uchar)iRetCodeChar;			
				bLoc++;
				if(i==0)
					bTD1=(uchar)iRetCodeChar;			
				bTDi=( (uchar)iRetCodeChar) &0xf0;			
			}				
			i++;
		}
		if(bTD1!=0x00)
			bHisLen++;								//若为T=1,为接收TCK作准备				
		for(i=0;i<bHisLen;i++)						//接收历史字符或TCK(T=1)
		{
			iRetCodeChar=GetByteATR();					//TDi					
			bRetCode=(uchar)(iRetCodeChar>>8);	
			if(bRetCode!=OK)
			{
					goto	RESET_AGAIN;				//接收数据出错,重新复位
			}		
			ResetData[bLoc]=(uchar)iRetCodeChar;			
			bLoc++;
		}
		bF1=bTA1&0xf0;
		for(i=0;i<sizeof(abF1);i++)
		{
			if(bF1==abF1[i])
				break;
		}
		if(i==sizeof(abF1) )
		{
			goto	RESET_AGAIN;				//非法的F1,重新复位					
		}			
		bD1=bTA1&0x0f;
		for(i=0;i<sizeof(abD1);i++)
		{
			if(bD1==abD1[i])
				break;
		}
		if(i==sizeof(abD1) )
		{
			goto	RESET_AGAIN;				//非法的D1,重新复位					
		}
		return	bLoc;							//返回ATR长度
		
RESET_AGAIN:
		bResetTines--;
		if(bResetTines==0)
		{
			vReleaseCard();							//非法的或通讯出错,释放卡片
			return 0;								
		}
	}
}		

/*                  
功能:	给CPU卡发送命令
输入:    
		DATAMESSAGE->nLength:命令总长度
    	DATAMESSAGE->CmdBuf:五字节的命令头
    	DATAMESSAGE->DataBuf:命令数据域
输出: 
		SW1SW2
//		DATAMESSAGE->nLength:返回数据的总长度(含SW1SW2)
    	DATAMESSAGE->DataBuf:返回数据域(含SW1SW2)
注意:	DATAMESSAGE->nLength与以前的定义不同
*/    
uint	_CardSmartApdu(uchar CardSocketNo,DATAMESSAGE  *pDataMsg )
{
	uchar	i,bLocSend,bLocRec,bRetCode;
	uchar	abSW[2];
	uint	iRetCodeChar;

	_CardSetCard(CardSocketNo);								//选择相应卡座的IO
ExchangeApdu:	
	bLocSend=0;												//将要发送的数据域的地址
	bLocRec=0;												//接收数据域的地址	
	for(i=0;i<5;i++)
	{
		bRetCode=SendByte(bTC1,pDataMsg->CmdBuf[i]);		//发送CLA,INS,P1,P2,P3
		if(bRetCode!=OK)
		{
			return	0x0101;
		}
	}	
		
GetCourseByte:		
	iRetCodeChar=GetByteRAPDU();									
	bRetCode=(uchar)(iRetCodeChar>>8);	
	if(bRetCode!=OK)
	{
		return	0x0101;
	}	
	if((uchar)iRetCodeChar==0x60)					//过程字节=0x60;
		goto	GetCourseByte;
	if((uchar)iRetCodeChar==pDataMsg->CmdBuf[1])	//过程字节=INS	
	{
		if(pDataMsg->nLength==5)					//2S 接收数据
		{
			for(i=bLocRec;i<(pDataMsg->CmdBuf[4]);i++)
			{
				iRetCodeChar=GetByteRAPDU();									
				bRetCode=(uchar)(iRetCodeChar>>8);	
				if(bRetCode!=OK)
				{
					return	0x0101;
				}					
				pDataMsg->DataBuf[i]=(uchar)iRetCodeChar;
			}
			for(i=0;i<2;i++)						//2S 接收sw1sw2
			{
				iRetCodeChar=GetByteRAPDU();									
				bRetCode=(uchar)(iRetCodeChar>>8);	
				if(bRetCode!=OK)
				{
					return	0x0101;
				}					
				abSW[i]=(uchar)iRetCodeChar;
			}			
			pDataMsg->nLength=pDataMsg->CmdBuf[4];
			iRetCodeChar=(uint)(abSW[0]<<8)+abSW[1];
			goto	CardSmartApduOk;
		}
		else
		{											//过程字节=INS,3s,4s发送剩余的数据域
			for(i=0;i<16;i++)
				_Delay_1ETU();						//反向时间9->5+9=18->5ETU		
			if(bTC1!=0)
			{
				for(i=0;i<bTC1;i++)
					_Delay_1ETU();					//反向时间再增加TC1个ETU
			}
			for(i=bLocSend;i<pDataMsg->CmdBuf[4];i++)
			{
				bRetCode=SendByte(bTC1,pDataMsg->DataBuf[i]);	//发送剩余的数据域
				if(bRetCode!=OK)
				{
					return	0x0101;
				}	
			}
			goto	GetCourseByte;
		}		
	}
	i=pDataMsg->CmdBuf[1]^0xff;					//i=INS的反
	if((uchar)iRetCodeChar==i)					//过程字节=INS的反
	{
		if(pDataMsg->nLength==5)					//INS的反, 2S 接收一个字节
		{
			iRetCodeChar=GetByteRAPDU();									
			bRetCode=(uchar)(iRetCodeChar>>8);	
			if(bRetCode!=OK)
			{
				return	0x0101;
			}					
			pDataMsg->DataBuf[bLocRec]=(uchar)iRetCodeChar;	
			bLocRec++;
			goto	GetCourseByte;		
		}
		else										//INS的反, 3s4s发送数据
		{
			for(i=0;i<16;i++)
				_Delay_1ETU();						//反向时间9->5+9=18->5ETU		
			if(bTC1!=0)
			{
				for(i=0;i<bTC1;i++)
					_Delay_1ETU();					//反向时间再增加TC1个ETU
			}
			
			bRetCode=SendByte(bTC1,pDataMsg->DataBuf[bLocSend]);		//发送一个数据
			bLocSend++;
			if(bRetCode!=OK)
			{
				return	0x0101;
			}
			goto	GetCourseByte;	
		}
	}

	abSW[0]=(uchar)iRetCodeChar;			//2S3s4s命令接收SW1SW2
	iRetCodeChar=GetByteRAPDU();									
	bRetCode=(uchar)(iRetCodeChar>>8);	
	if(bRetCode!=OK)
	{
		return	0x0101;
	}
	abSW[1]=(uchar)iRetCodeChar;
		
	if(bLocRec!=0)
		pDataMsg->nLength=pDataMsg->CmdBuf[4];		//INS的反, 2S指令
	else
		pDataMsg->nLength=0;
	iRetCodeChar=(uint)(abSW[0]<<8)+abSW[1];
	
CardSmartApduOk:
	if( (uchar)(iRetCodeChar>>8)==0x61)
	{
		pDataMsg->CmdBuf[0]=0x00;						//取响应
		pDataMsg->CmdBuf[1]=0xc0;	
		pDataMsg->CmdBuf[2]=0x00;
		pDataMsg->CmdBuf[3]=0x00;
		pDataMsg->CmdBuf[4]=(uchar)iRetCodeChar;
		pDataMsg->nLength=5;
		for(i=0;i<COMM_DELAY_ETU;i++)
			_Delay_1ETU();						
		goto	ExchangeApdu;
	}
	if( (uchar)(iRetCodeChar>>8)==0x6c)
	{
		pDataMsg->CmdBuf[4]=(uchar)iRetCodeChar;		//6cxx
		pDataMsg->nLength=5;
		for(i=0;i<COMM_DELAY_ETU;i++)
			_Delay_1ETU();						
		goto	ExchangeApdu;
	}	
	if( (pDataMsg->CmdBuf[0]==0x00) && (pDataMsg->CmdBuf[1]==0xc0) )
		return	0x9000;
	return	iRetCodeChar;
}	


/*                  
功能:卡片下电
输入:none
输出: none
注意:
*/              
void	vReleaseCard(void)
{

	_CardSetCard(0);
	RSTCPU=0;						//RST=0
/////////////////////////////////////	
	IO=1;							//IO=1	
/////////////////////////////////////	
	_Delay(1);
	ENCLK=0;
	ENCLKCPU=0;
	ENCLK4404=0;					//CLK=0
	IO=0;							//IO=0	
	_Delay(1);						
	POWER_CONTROL=1;				//vcc=0
}

/*                  
功能:用户卡初始状态,所有引脚的电压为0
输入:none
输出: none
注意:
*/        
void	vInitCard(void)
{
	_CardSetCard(0);	
	RSTCPU=0;						//RST=0
	ENCLK=0;
	ENCLKCPU=0;
	ENCLK4404=0;					//CLK=0
	IO=0;							//IO=0	
	POWER_CONTROL=1;				//vcc=0
}

⌨️ 快捷键说明

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