#include "PcscCall.h" #include "cmb.h" #define SCARD_SCOPE_SYSTEM 0x0002 /**< Scope in system */ #define SCARD_E_NO_READERS_AVAILABLE ((LONG)0x8010002E) /**< Cannot find a smart card reader. */ #define SCARD_UNPOWER_CARD 0x0002 /**< Power down on close */ #define SCARD_SHARE_EXCLUSIVE 0x0001 /**< Exclusive mode only */ #define SCARD_PROTOCOL_T0 0x0001 /**< T=0 active protocol. */ #define SCARD_PROTOCOL_T1 0x0002 /**< T=1 active protocol. */ #define SCARD_STATE_UNAWARE 0x0000 /**< App wants status */ #define SCARD_SHARE_DIRECT 0x0003 /**< Raw mode only */ #define SCARD_PROTOCOL_UNDEFINED 0x0000 /**< protocol not set */ #define SCARD_LEAVE_CARD 0x0000 /**< Do nothing on close */ #define SCARD_CTL_CODE(code) (0x42000000 + (code)) #define IOCTL_CCID_ESCAPE SCARD_CTL_CODE(1) PcscCall::PcscCall() { m_sErrInfo[0] = 0; m_sReadName[0] = 0; m_hContext = NULL; m_hCurCard = NULL; SCardEstablishContext = NULL; } bool PcscCall::Load() { void *hLib = dlopen("libpcsclite.so", RTLD_LAZY); //load so if(hLib == NULL) { strcpy(m_sErrInfo, "load libpcsclite.so error"); return false; } SCardEstablishContext = (pSCardEstablishContext)dlsym(hLib, "SCardEstablishContext"); if (SCardEstablishContext == NULL) { strcpy(m_sErrInfo, "find function SCardEstablishContext error"); return false; } SCardListReaders = (pSCardListReaders)dlsym(hLib, "SCardListReaders"); SCardConnect = (pSCardConnect)dlsym(hLib, "SCardConnect"); SCardDisconnect = (pSCardDisconnect)dlsym(hLib, "SCardDisconnect"); SCardGetStatusChange = (pSCardGetStatusChange)dlsym(hLib, "SCardGetStatusChange"); SCardStatus = (pSCardStatus)dlsym(hLib, "SCardStatus"); SCardTransmit = (pSCardTransmit)dlsym(hLib, "SCardTransmit"); SCardCancel = (pSCardCancel)dlsym(hLib, "SCardCancel"); SCardReleaseContext = (pSCardReleaseContext)dlsym(hLib, "SCardReleaseContext"); SCardIsValidContext = (pSCardIsValidContext)dlsym(hLib, "SCardIsValidContext"); SCardControl = (pSCardControl)dlsym(hLib, "SCardControl"); m_sErrInfo[0] = 0; return true; } bool PcscCall::Open(const char* sNameIn) { if (SCardEstablishContext == NULL && Load() == false) return false; LONG iRet = SCARD_S_SUCCESS; if (m_hContext == NULL) iRet = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &m_hContext); if (iRet != SCARD_S_SUCCESS || m_hContext == NULL) { sprintf(m_sErrInfo, "PCSC SCardEstablishContext %x", iRet); return false; } char sNameList[1024]=""; ULONG dwLeng=1024; iRet = SCardListReaders(m_hContext, NULL, sNameList , &dwLeng); if (iRet == SCARD_E_NO_READERS_AVAILABLE) { sprintf(m_sErrInfo, "PCSC SCardListReaders NO_READERS %x", iRet); return false; } if (iRet != SCARD_S_SUCCESS || strlen(sNameList) < 16) { sprintf(m_sErrInfo, "PCSC SCardListReaders %x", iRet); return false; } if (m_hCurCard) SCardDisconnect(m_hCurCard, SCARD_UNPOWER_CARD); m_hCurCard = NULL; int iLen = sNameIn ? strlen(sNameIn) : 0; char* pEnd = sNameList + dwLeng; for (char* pName = sNameList; pName < pEnd; pName++) { if (memcmp(pName, sNameIn, iLen) == 0) { strcpy(m_sReadName, pName); return true; } pName += strlen(pName); } sprintf(m_sErrInfo, "PCSC SCardListReaders not fond"); return false; } bool PcscCall::Close() { if (m_hCurCard) DicConnect(); if (m_hContext > 0) { SCardCancel(m_hContext); SCardReleaseContext(m_hContext); m_hContext = 0; } m_sReadName[0] = 0; return false; } int PcscCall::GetState() { if (m_hContext == 0) { strcpy(m_sErrInfo, "PCSC not opened"); return STATE_NO_READER; } long iRet = SCARD_S_SUCCESS; SCARD_READERSTATE ReaderState; ReaderState.szReader = m_sReadName; ReaderState.dwCurrentState = SCARD_STATE_UNAWARE; ReaderState.dwEventState = 0; DWORD Value_timeout = 0; DWORD ReaderCount = 1; iRet = SCardGetStatusChange(m_hContext, Value_timeout, &ReaderState, ReaderCount); if (iRet != SCARD_S_SUCCESS) { sprintf(m_sErrInfo, "PCSC SCardGetStatusChange %x", iRet); return STATE_ERROR; } if (ReaderState.cbAtr > 0) { return STATE_HAVE_CARD; } return STATE_NO_CARD; } bool PcscCall::Connect(char* sATR, int& iLen) { if (m_hContext == NULL) { strcpy(m_sErrInfo, "PCSC not opened"); return STATE_NO_READER; } if (m_hCurCard) SCardDisconnect(m_hCurCard, SCARD_UNPOWER_CARD); m_hCurCard = NULL; LONG iRet = SCardConnect(m_hContext, m_sReadName, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, &m_hCurCard, &m_APrtocol); if (iRet != 0) { sprintf(m_sErrInfo, "PCSC SCardConnect %s %x", m_sReadName, iRet); return false; } ULONG dwState; char szReader[256] = {0}; BYTE byData[256] = {0}; ULONG iDataLen = 256; ULONG iReaderLen = 256; iRet = SCardStatus(m_hCurCard, szReader, &iReaderLen, &dwState, &m_APrtocol, byData, &iDataLen); if (iRet != SCARD_S_SUCCESS ) { sprintf(m_sErrInfo, "PCSC SCardStatus %x", iRet); return false; } memcpy(sATR, byData, iDataLen); iLen = iDataLen; return true; } bool PcscCall::DicConnect() { if (m_hCurCard) SCardDisconnect(m_hCurCard, SCARD_UNPOWER_CARD); m_hCurCard = NULL; return true; } int PcscCall::ChipIO(const char* sIn, char* sOut) { if (m_hCurCard == NULL) { strcpy(m_sErrInfo, "PCSC not connected"); return STATE_NO_READER; } SCARD_IO_REQUEST pioSendRequest; pioSendRequest.dwProtocol = m_APrtocol; pioSendRequest.cbPciLength = sizeof(SCARD_IO_REQUEST); BYTE bSend[512], bRecv[512]; ULONG iLen = ::HexStrToANSI(sIn, bSend); ULONG iRcv = 512; LONG iRet = SCardTransmit(m_hCurCard, &pioSendRequest, bSend, iLen, NULL, bRecv, &iRcv); if (iRet != SCARD_S_SUCCESS) { sprintf(m_sErrInfo, "PCSC SCardTransmit %x", iRet); return STATE_ERROR; } ::ANSIToHexStr(bRecv, iRcv, sOut); return 0; } int PcscCall::SendCMD(const char* sIn, char* sOut) { if (m_hContext == 0) { strcpy(m_sErrInfo, "PCSC not opened"); return STATE_NO_READER; } if (m_hCurCard) SCardDisconnect(m_hCurCard, SCARD_UNPOWER_CARD); m_hCurCard = NULL; long iRet = SCARD_S_SUCCESS; SCARDHANDLE hCurCard = 0; ULONG dwOutProtocal = 0; iRet = SCardConnect(m_hContext, m_sReadName, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_UNDEFINED,&hCurCard, &dwOutProtocal); if (iRet != 0) { sprintf(m_sErrInfo, "PCSC SCardConnect %s %x", m_sReadName, iRet); return STATE_ERROR; } BYTE bSend[512], bRecv[512]; ULONG iLen = ::HexStrToANSI(sIn, bSend); ULONG iRcv = 512; iRet = SCardControl(hCurCard, IOCTL_CCID_ESCAPE, bSend, iLen, bRecv, 512, &iRcv); if (iRet != SCARD_S_SUCCESS) { sprintf(m_sErrInfo, "PCSC SCardControl %s %x", m_sReadName, iRet); return STATE_ERROR; } ::ANSIToHexStr(bRecv, iRcv, sOut); iRet = SCardDisconnect(hCurCard, SCARD_LEAVE_CARD); if (iRet != SCARD_S_SUCCESS) { sprintf(m_sErrInfo, "PCSC SCardDisconnect %x", iRet); return STATE_ERROR; } return STATE_NO_CARD; }