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

📄 pcsccom.cpp

📁 一个类似Smart Card PCSC协议
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//pcsccom.cpp

#include "stdafx.h"
#include "pcsccom.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <windows.h>

#pragma data_seg ("PortData")
PCSCCOM_STRUCT g_STUPortArray[256];
#pragma data_seg ("PortData")
//IC function
BOOL  PCSCCOM_API bOpenPort(UINT nPortNum)
{
	BOOL bRtn(FALSE);
	CFileException ex;
	CHAR szPortName[32];
	TCHAR szError[1024];
	//int Result;

	if(g_STUPortArray[nPortNum].bOpen != FALSE)
		return FALSE;

	sprintf(szPortName,"\\\\.\\COM%d",nPortNum+1);	
	g_STUPortArray[nPortNum].hPortFile = CreateFile(szPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL,
		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); // 
	if(g_STUPortArray[nPortNum].hPortFile == INVALID_HANDLE_VALUE){
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szError,1024,NULL);
		pcscWriteErrorLog(szError,2);
		return FALSE;
	}
	
	//set comm property
	DCB dcb;
	bRtn = GetCommState(g_STUPortArray[nPortNum].hPortFile,&dcb);
	if(! bRtn){
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szError,1024,NULL);
		pcscWriteErrorLog(szError,2);
		return bRtn;
	}
	dcb.BaudRate = CBR_9600;
	//dcb.fParity = TRUE;
	dcb.Parity = NOPARITY;
	dcb.ByteSize = 8;
	dcb.StopBits = ONESTOPBIT;
	dcb.fRtsControl = RTS_CONTROL_DISABLE;
	dcb.fDtrControl = DTR_CONTROL_DISABLE;
	//dcb.fAbortOnError = FALSE;
	bRtn = SetCommState(g_STUPortArray[nPortNum].hPortFile,&dcb);
	if(! bRtn){
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szError,1024,NULL);
		pcscWriteErrorLog(szError,2);
		return bRtn;
	}	

	// set event mask
	bRtn = SetCommMask(g_STUPortArray[nPortNum].hPortFile,EV_RXCHAR|EV_TXEMPTY);
	if(! bRtn){
		pcscWriteErrorLog("Failed to Set Comm Mask",2);
		return bRtn;
	}
	//set size of input/output buffer
	SetupComm( g_STUPortArray[nPortNum].hPortFile, 1024,1024) ; 
	//clear up input/output buffer
	PurgeComm( g_STUPortArray[nPortNum].hPortFile, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); 

	//set comm timeout
	COMMTIMEOUTS CommTimeout;
	bRtn = GetCommTimeouts(g_STUPortArray[nPortNum].hPortFile,&CommTimeout);
	if(! bRtn){
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szError,1024,NULL);
		sprintf(szError,"%s%s","Failed to get timeout configuration of current port:",szError);
		pcscWriteErrorLog(szError,2);
		return bRtn;
	}
	CommTimeout.ReadIntervalTimeout = MAXDWORD;
	CommTimeout.ReadTotalTimeoutConstant = 0;
	CommTimeout.ReadTotalTimeoutMultiplier = 0;
	CommTimeout.WriteTotalTimeoutConstant = 0;
	CommTimeout.WriteTotalTimeoutMultiplier = 0;
	bRtn = SetCommTimeouts(g_STUPortArray[nPortNum].hPortFile,&CommTimeout);
	if(! bRtn){
		FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szError,1024,NULL);
		sprintf(szError,"%s%s","Failed to configure timeout of current port:",szError);
		pcscWriteErrorLog(szError,2);
		return bRtn;
	}/**/

	// init ProcessCompletionEvent
	g_STUPortArray[nPortNum].ReceiveEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
	g_STUPortArray[nPortNum].ROverlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );

	g_STUPortArray[nPortNum].hCardChangedMutex = CreateMutex( NULL, FALSE, NULL );
	
	// reset reader
	EscapeCommFunction( g_STUPortArray[nPortNum].hPortFile, SETDTR );
	EscapeCommFunction( g_STUPortArray[nPortNum].hPortFile, SETRTS );

	Sleep( 100 );

	//init other variable
	g_STUPortArray[nPortNum].bOpen = TRUE;
	g_STUPortArray[nPortNum].fReadReady = FALSE;
	g_STUPortArray[nPortNum].fAPDUHead = FALSE;
	g_STUPortArray[nPortNum].fConnect  = FALSE;
	g_STUPortArray[nPortNum].nTryConnect = 0;

	return TRUE;
}

UINT PCSCCOM_API iConnectCard(UINT nPortNum, UINT nProtocolType, BYTE *pATR, UINT *nATRLen)
{
	BYTE lBuf[1024],szBuf[512];
	UINT nReadDataLen(0),nPackLen(0);
	CHAR szSendData[1024];
	UINT iRtn(0);
	DWORD length(0);
	char szErrorMsg[1024];
	BOOL bRtn(FALSE);

	g_STUPortArray[nPortNum].nProtocolType = nProtocolType;
	if(INVALID_HANDLE_VALUE == g_STUPortArray[nPortNum].hPortFile)
		return UINT(FAIL_COMMUNICATE);
	if(1 == g_STUPortArray[nPortNum].nProtocolType)
		g_STUPortArray[nPortNum].fAPDUHead = FALSE;

	//bReadData(nPortNum,lBuf,&nReadDataLen);
	iRtn = iDisconnectCard(nPortNum);
	if(0x9000 == iRtn){
		switch(g_STUPortArray[nPortNum].nProtocolType)
		{
		case 0://cpu t=0
			break;
		case 1://cpu t=1
			break;
		case 2://sle4428 AM8KS
			iRtn = bSetMemoryICType(nPortNum, "0102010507", 10);
			if(iRtn != 0x9000)
				return iRtn;
			break;
		case 3://sle4442 AM2KS
			iRtn = bSetMemoryICType(nPortNum, "0102010604", 10);
			if(iRtn != 0x9000)
				return iRtn;
			break;
		case 4://sle4406 ST1305  AM104  GPM103  AT88SC06
			iRtn = bSetMemoryICType(nPortNum, "0102010103", 10);
			if(iRtn != 0x9000)
				return iRtn;
			break;
		case 5://at24c01-16 ST14C02C  ST14C04C  AM1KF-4KF  GFM1K-8K
			iRtn = bSetMemoryICType(nPortNum, "0102010200", 10);
			if(iRtn != 0x9000)
				return iRtn;
			break;
		default:
			return UINT(WRONG_INS_STRUCT);
		}
		memcpy(szSendData,"\x02",1);
		memcpy(szSendData+1,"01800081",8);
		memcpy(szSendData+9,"\x03",1);
		bRtn = bWriteData(nPortNum,szSendData,10);
		
		memset(lBuf,0,1024);
		memset(szBuf,0,512);
		iRtn = bReadData(nPortNum,lBuf,&nReadDataLen);
		if(iRtn != TRUE)
		{
			sprintf(szErrorMsg,"COM%d: iConnectCard failed to read data from port for connecting reader , SW:1111",nPortNum+1);
			pcscWriteErrorLog(szErrorMsg,3);
			return UINT(FAIL_READ_DATA);
		}

		nPackHexToByte(lBuf,nReadDataLen,szBuf,&nPackLen);
		if(!( (szBuf[0] == 0x01) && (szBuf[1] == 0x90) && (szBuf[2] == 0x00) ) )
		{
			if((szBuf[0] == 0x01) && (szBuf[1] == 0x60) && (szBuf[2] == 0x02) && (szBuf[3] == 0x00))
			{
				if(g_STUPortArray[nPortNum].nTryConnect > 10)
				{
					sprintf(szErrorMsg,"COM%d: iConnectCard returning data is wrong for connecting reader , %s",nPortNum+1,lBuf);
					pcscWriteErrorLog(szErrorMsg,3);
					g_STUPortArray[nPortNum].nTryConnect = 0;
					return UINT(WRONG_RETURN_FORMAT);
				}
				else
				{					
					return iConnectCard(nPortNum, nProtocolType, pATR, nATRLen);
				}
			}
			else
			{
				sprintf(szErrorMsg,"COM%d: iConnectCard returning data is wrong for connecting reader ,%s",nPortNum+1,lBuf);
				pcscWriteErrorLog(szErrorMsg,3);
				return UINT(WRONG_RETURN_FORMAT);
			}
		}
		else{
			memcpy(pATR,szBuf+4,szBuf[3]);//-1		
			*nATRLen = szBuf[3];//-2;
			pATR[*nATRLen] = 0;
			if(g_STUPortArray[nPortNum].nProtocolType != 5)
			{
				if(0 == *nATRLen)
				{
					return UINT(WRONG_READ_LENGTH);
				}
			}
			
			switch(g_STUPortArray[nPortNum].nProtocolType){	
			case 1:
				memcpy(szSendData,"\x02",1);
				memcpy(szSendData+1,"01A10500C101F838A5",18);
				memcpy(szSendData+19,"\x03",1);
				bRtn = bWriteData(nPortNum,szSendData,20);
				
				memset(lBuf,0,1024);
				iRtn = bReadData(nPortNum,lBuf,&nReadDataLen);
				if(iRtn != TRUE)
				{
					sprintf(szErrorMsg,"COM%d: iConnectCard t=1 failed to read data from port, SW:1111",nPortNum+1);
					pcscWriteErrorLog(szErrorMsg,3);
					return UINT(FAIL_READ_DATA);					
				}
				else
				{
					lBuf[nReadDataLen] = 0;
					if(strcmp((char*)lBuf,(char*)"0190000500E101F81894") != 0)
					{
						sprintf(szErrorMsg,"COM%d: iConnectCard t=1 reading data is wrong ,not 0190000500E101F81894, %s",nPortNum+1,lBuf);
						pcscWriteErrorLog(szErrorMsg,3);
						return UINT(FAIL_SET_T1);						
					}
				}
				break;
			default:
				break;
			}
		}
	}
	else
	{
		sprintf(szErrorMsg,"COM%d: iDisconnectCard SW:FFFF",nPortNum+1);
		pcscWriteErrorLog(szErrorMsg,3);
		return UINT(FAIL_COMMUNICATE);
	}

	g_STUPortArray[nPortNum].fConnect = TRUE;
	return UINT(0x9000);
}

UINT PCSCCOM_API iTransmitAPDU(UINT nPortNum, BYTE *pInData, UINT nInDataLen, BYTE *pOutData, UINT *nOutDataLen)
{
	BYTE lBuf[1024],szBuf[512];
	UINT nReadDataLen(0),nPackLen(0);
	BYTE szSendData[1024];
	UINT iRtn(0),nRtnValue(0xFFFF);
	CHAR Buf[5];
	BOOL bRtn(FALSE);
	UINT nLc = 0;

	if(INVALID_HANDLE_VALUE == g_STUPortArray[nPortNum].hPortFile)
		return UINT(FAIL_COMMUNICATE);
	if(! g_STUPortArray[nPortNum].fConnect)
		return UINT(FAIL_COMMUNICATE);
	if(nInDataLen%2)
		return nInDataLen;
	
	memset(szSendData,0,576);
	memcpy(szSendData,"\x02",1);
	switch(g_STUPortArray[nPortNum].nProtocolType){
		case 0:
			memcpy(szSendData+1,"01A0",4);

			sprintf(Buf,"%02X",nInDataLen/2);
			memcpy(szSendData+5,Buf,2);

			memcpy(szSendData+7,pInData,nInDataLen);

			nPackHexToByte(szSendData+1,nInDataLen+6,szBuf,&nPackLen);
			sprintf(Buf,"%02X",cSumParityByte(szBuf,nPackLen));
			memcpy(szSendData+7+nInDataLen,Buf,2);

			memcpy(szSendData+9+nInDataLen,"\x03",1);
			memcpy(szSendData+10+nInDataLen, "\x00", 1);
			break;
		case 1:
			g_STUPortArray[nPortNum].fAPDUHead = !g_STUPortArray[nPortNum].fAPDUHead;

			memcpy(szSendData+1,"01A1",4);

			sprintf(Buf,"%02X",nInDataLen/2+4);
			memcpy(szSendData+5,Buf,2);

			if(g_STUPortArray[nPortNum].fAPDUHead)
				memcpy(szSendData+7,"0000",4);
			else
				memcpy(szSendData+7,"0040",4);

			sprintf(Buf,"%02X",nInDataLen/2);
			memcpy(szSendData+11,Buf,2);

			memcpy(szSendData+13,pInData,nInDataLen);

			nPackHexToByte(szSendData+9,nInDataLen+4,szBuf,&nPackLen);
			sprintf(Buf,"%02X",cSumParityByte(szBuf,nPackLen));
			memcpy(szSendData+13+nInDataLen,Buf,2);

			nPackHexToByte(szSendData+1,nInDataLen+14,szBuf,&nPackLen);
			sprintf(Buf,"%02X",cSumParityByte(szBuf,nPackLen));
			memcpy(szSendData+15+nInDataLen,Buf,2);

			memcpy(szSendData+17+nInDataLen,"\x03",1);
			memcpy(szSendData+18+nInDataLen, "\x00", 1);
			break;
		default :
			memcpy(szSendData+1, pInData, 4);//copy INS
			switch(pInData[3])
			{
			case '0':			
				//read data from IC
				memcpy(szSendData+5, "030000", 6);
				memcpy(szSendData+11, pInData+10, 2);//copy Le

				nPackHexToByte(szSendData+1, 12, szBuf, &nPackLen);
				sprintf(Buf,"%02X",cSumParityByte(szBuf,nPackLen));
				memcpy(szSendData+13, Buf, 2);

				memcpy(szSendData+15,"\x03",1);
				memcpy(szSendData+16, "\x00", 1);
				break;
			case '1':			
				//write data to IC
				nPackHexToByte(pInData+8, 2, szBuf, &nPackLen);
				nLc = szBuf[0];
				sprintf(Buf, "%02X", nLc+2);
				memcpy(szSendData+5, Buf, 2);
				
				memcpy(szSendData+7, "0000", 4);
				memcpy(szSendData+11, pInData+10, 2*nLc);
				
				nPackHexToByte(szSendData+1, 10+2*nLc, szBuf, &nPackLen);
				sprintf(Buf,"%02X",cSumParityByte(szBuf,nPackLen));
				memcpy(szSendData+11+2*nLc, Buf, 2);
				
				memcpy(szSendData+13+2*nLc, "\x03", 1);
				memcpy(szSendData+14+2*nLc, "\x00", 1);
				break;
			case '2':
				nPackHexToByte(pInData+8, 2, szBuf, &nPackLen);
				nLc = szBuf[0];
				
				memcpy(szSendData+5, pInData+8, 2*(nLc+1));
				nPackHexToByte(szSendData+1, 6+2*nLc, szBuf, &nPackLen);
				sprintf(Buf,"%02X",cSumParityByte(szBuf,nPackLen));
				memcpy(szSendData+7+2*nLc, Buf, 2);

				memcpy(szSendData+9+2*nLc, "\x03", 1);
				memcpy(szSendData+10+2*nLc, "\x00", 1);
				break;
			default:
				return UINT(WRONG_INS_STRUCT);
				break;
			}
			break;
	}
	/////////execute apdu and read data
	bRtn = bWriteData(nPortNum, (CHAR*)szSendData, strlen((CHAR*)szSendData));			
	//read data for last apdu
	iRtn = bReadData(nPortNum,lBuf,&nReadDataLen);
	if(iRtn != TRUE)
		return UINT(FAIL_READ_DATA);
	//parse reading data
	nPackHexToByte(lBuf,nReadDataLen,szBuf,&nPackLen);
	if(4 == nReadDataLen)
		return UINT(256*szBuf[0]+szBuf[1]);
	if(!( (szBuf[0] == 0x01) && (szBuf[1] == 0x90) && (szBuf[2] == 0x00) ))
		return UINT(WRONG_RETURN_FORMAT);//fromat of returning data is wrong

⌨️ 快捷键说明

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