📄 card.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 + -