125#define PROFILE_FILE "/tmp/pcscd_profile"
131struct timeval profile_time_start;
135#define PROFILE_START profile_start(__FUNCTION__);
136#define PROFILE_END profile_end(__FUNCTION__, __LINE__);
138static void profile_start(
const char *f)
140 static bool initialized =
false;
145 fd = fopen(PROFILE_FILE,
"a+");
148 fprintf(stderr,
"\33[01;31mCan't open %s: %s\33[0m\n",
149 PROFILE_FILE, strerror(errno));
152 fprintf(fd,
"\nStart a new profile\n");
155 if (isatty(fileno(stderr)))
161 gettimeofday(&profile_time_start, NULL);
165static void profile_end(
const char *f,
int line)
167 struct timeval profile_time_end;
170 gettimeofday(&profile_time_end, NULL);
171 d =
time_sub(&profile_time_end, &profile_time_start);
174 fprintf(stderr,
"\33[01;31mRESULT %s \33[35m%ld\33[0m (%d)\n", f, d,
176 fprintf(fd,
"%s %ld\n", f, d);
186#define SCARD_PROTOCOL_ANY_OLD 0x1000
188static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
190LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
191 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
210 Log2(PCSC_LOG_DEBUG,
"Establishing Context: 0x%lX", *phContext);
224 Log2(PCSC_LOG_DEBUG,
"Releasing Context: 0x%lX", hContext);
229LONG SCardConnect(
SCARDCONTEXT hContext, LPCSTR szReader,
230 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
231 LPDWORD pdwActiveProtocol)
234 READER_CONTEXT * rContext = NULL;
253 Log3(PCSC_LOG_DEBUG,
"Attempting Connect to %s using protocol: %ld",
254 szReader, dwPreferredProtocols);
256 rv = RFReaderInfo((LPSTR) szReader, &rContext);
259 Log2(PCSC_LOG_ERROR,
"Reader %s Not Found", szReader);
266 rv = RFCheckReaderStatus(rContext);
281 Log1(PCSC_LOG_ERROR,
"Error Reader Exclusive");
291 Log1(PCSC_LOG_INFO,
"Waiting for release of lock");
294 Log1(PCSC_LOG_INFO,
"Lock released");
307 Log1(PCSC_LOG_DEBUG,
"Card Not Inserted");
314 if (POWER_STATE_UNPOWERED == rContext->
powerState)
327 Log1(PCSC_LOG_DEBUG,
"power up complete.");
328 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
333 Log2(PCSC_LOG_ERROR,
"Error powering up card: %s",
339 Log1(PCSC_LOG_ERROR,
"Card Not Powered");
347 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_IN_USE");
365 (void)pthread_mutex_lock(rContext->
mMutex);
370 int availableProtocols, defaultProtocol;
382 availableProtocols &= dwPreferredProtocols;
385 availableProtocols, defaultProtocol);
388 if (SET_PROTOCOL_PPS_FAILED == ret)
390 (void)pthread_mutex_unlock(rContext->
mMutex);
395 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
397 (void)pthread_mutex_unlock(rContext->
mMutex);
405 (void)pthread_mutex_unlock(rContext->
mMutex);
409 (void)pthread_mutex_unlock(rContext->
mMutex);
424 switch (*pdwActiveProtocol)
428 Log2(PCSC_LOG_DEBUG,
"Active Protocol: T=%d",
433 Log1(PCSC_LOG_DEBUG,
"Active Protocol: RAW");
437 Log2(PCSC_LOG_ERROR,
"Active Protocol: unknown %ld",
442 Log1(PCSC_LOG_DEBUG,
"Direct access: no protocol selected");
450 (void)pthread_mutex_lock(&LockMutex);
452 *phCard = RFCreateReaderHandle(rContext);
454 Log2(PCSC_LOG_DEBUG,
"hCard Identity: %lx", *phCard);
468 (void)RFLockSharing(*phCard, rContext);
474 (void)pthread_mutex_unlock(&LockMutex);
489 rv = RFAddReaderHandle(rContext, *phCard);
491 (void)pthread_mutex_unlock(&LockMutex);
516 UNREF_READER(rContext)
523LONG SCardReconnect(
SCARDHANDLE hCard, DWORD dwShareMode,
524 DWORD dwPreferredProtocols, DWORD dwInitialization,
525 LPDWORD pdwActiveProtocol)
528 READER_CONTEXT * rContext = NULL;
530 Log1(PCSC_LOG_DEBUG,
"Attempting reconnect to token.");
556 rv = RFReaderInfoById(hCard, &rContext);
563 rv = RFCheckReaderStatus(rContext);
570 rv = RFCheckSharing(hCard, rContext);
582 RFSetReaderEventState(rContext, SCARD_RESET);
607 Log1(PCSC_LOG_DEBUG,
"Reset complete.");
608 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
615 Log1(PCSC_LOG_ERROR,
"Error resetting card.");
665 (void)pthread_mutex_lock(rContext->
mMutex);
670 int availableProtocols, defaultProtocol;
682 availableProtocols &= dwPreferredProtocols;
685 availableProtocols, defaultProtocol);
688 if (SET_PROTOCOL_PPS_FAILED == ret)
690 (void)pthread_mutex_unlock(rContext->
mMutex);
695 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
697 (void)pthread_mutex_unlock(rContext->
mMutex);
705 (void)pthread_mutex_unlock(rContext->
mMutex);
709 (void)pthread_mutex_unlock(rContext->
mMutex);
719 RFSetPowerState(rContext, POWER_STATE_IN_USE);
720 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_IN_USE");
728 switch (*pdwActiveProtocol)
732 Log2(PCSC_LOG_DEBUG,
"Active Protocol: T=%d",
737 Log1(PCSC_LOG_DEBUG,
"Active Protocol: RAW");
741 Log2(PCSC_LOG_ERROR,
"Active Protocol: unknown %ld",
746 Log1(PCSC_LOG_DEBUG,
"Direct access: no protocol selected");
761 (void)RFLockSharing(hCard, rContext);
783 (void)RFUnlockSharing(hCard, rContext);
800 (void)RFUnlockSharing(hCard, rContext);
813 (void)RFClearReaderEventState(rContext, hCard);
823 UNREF_READER(rContext)
828LONG SCardDisconnect(
SCARDHANDLE hCard, DWORD dwDisposition)
831 READER_CONTEXT * rContext = NULL;
843 rv = RFReaderInfoById(hCard, &rContext);
854 && (rContext->
hLockId != hCard))
856 Log1(PCSC_LOG_INFO,
"Waiting for release of lock");
859 Log1(PCSC_LOG_INFO,
"Lock released");
869 rv = RFUnlockAllSharing(hCard, rContext);
883 Log2(PCSC_LOG_DEBUG,
"Active Contexts: %d", rContext->
contexts);
884 Log2(PCSC_LOG_DEBUG,
"dwDisposition: %ld", dwDisposition);
894 RFSetReaderEventState(rContext, SCARD_RESET);
905 RFSetPowerState(rContext, POWER_STATE_UNPOWERED);
906 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_UNPOWERED");
922 Log1(PCSC_LOG_DEBUG,
"Reset complete.");
923 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
931 Log2(PCSC_LOG_ERROR,
"Error powering down card: %s",
936 Log1(PCSC_LOG_ERROR,
"Error resetting card.");
948 UCHAR controlBuffer[5];
955 controlBuffer[0] = 0x20;
956 controlBuffer[1] = 0x15;
957 controlBuffer[2] = (rContext->
slot & 0x0000FFFF) + 1;
958 controlBuffer[3] = 0x00;
959 controlBuffer[4] = 0x00;
961 rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
966 if (receiveLength == 2 && receiveBuffer[0] == 0x90)
968 Log1(PCSC_LOG_DEBUG,
"Card ejected successfully.");
974 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
977 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
990 (void)RFRemoveReaderHandle(rContext, hCard);
1010 RESPONSECODE (*fct)(DWORD) = NULL;
1016 if (POWER_STATE_POWERED <= rContext->powerState)
1018 rContext->
powerState = POWER_STATE_GRACE_PERIOD;
1019 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_GRACE_PERIOD");
1026 dwGetSize =
sizeof(fct);
1028 &dwGetSize, (PUCHAR)&fct);
1030 if ((
IFD_SUCCESS == rv) && (dwGetSize ==
sizeof(fct)))
1032 Log1(PCSC_LOG_INFO,
"Stopping polling thread");
1033 fct(rContext->
slot);
1045 UNREF_READER(rContext)
1053 READER_CONTEXT * rContext;
1059 rv = RFReaderInfoById(hCard, &rContext);
1066 rv = RFCheckReaderStatus(rContext);
1073 rv = RFCheckReaderEventState(rContext, hCard);
1077 rv = RFLockSharing(hCard, rContext);
1084 Log2(PCSC_LOG_DEBUG,
"Status: %s", rv2text(rv));
1087 UNREF_READER(rContext)
1092LONG SCardEndTransaction(
SCARDHANDLE hCard, DWORD dwDisposition)
1096 READER_CONTEXT * rContext = NULL;
1111 rv = RFReaderInfoById(hCard, &rContext);
1118 rv = RFCheckReaderEventState(rContext, hCard);
1127 && (rContext->
hLockId != hCard))
1129 Log1(PCSC_LOG_INFO,
"No card reset within a transaction");
1156 RFSetReaderEventState(rContext, SCARD_RESET);
1167 Log1(PCSC_LOG_DEBUG,
"Reset complete.");
1168 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
1175 Log1(PCSC_LOG_ERROR,
"Error resetting card.");
1186 UCHAR controlBuffer[5];
1188 DWORD receiveLength;
1193 controlBuffer[0] = 0x20;
1194 controlBuffer[1] = 0x15;
1195 controlBuffer[2] = (rContext->
slot & 0x0000FFFF) + 1;
1196 controlBuffer[3] = 0x00;
1197 controlBuffer[4] = 0x00;
1199 rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
1204 if (receiveLength == 2 && receiveBuffer[0] == 0x90)
1206 Log1(PCSC_LOG_DEBUG,
"Card ejected successfully.");
1212 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
1215 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
1230 rv2 = RFUnlockSharing(hCard, rContext);
1236 Log2(PCSC_LOG_DEBUG,
"Status: %s", rv2text(rv));
1239 UNREF_READER(rContext)
1244LONG SCardStatus(
SCARDHANDLE hCard, LPSTR szReaderNames,
1245 LPDWORD pcchReaderLen, LPDWORD pdwState,
1246 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1249 READER_CONTEXT * rContext = NULL;
1253 (void)szReaderNames;
1254 (void)pcchReaderLen;
1264 rv = RFReaderInfoById(hCard, &rContext);
1271 rv = RFCheckSharing(hCard, rContext);
1290 rv = RFCheckReaderEventState(rContext, hCard);
1297 rv = RFCheckReaderStatus(rContext);
1302 UNREF_READER(rContext)
1307LONG SCardControl(
SCARDHANDLE hCard, DWORD dwControlCode,
1308 LPCVOID pbSendBuffer, DWORD cbSendLength,
1309 LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
1312 READER_CONTEXT * rContext = NULL;
1315 *lpBytesReturned = 0;
1321 rv = RFReaderInfoById(hCard, &rContext);
1328 rv = RFCheckSharing(hCard, rContext);
1332 if (IFD_HVERSION_2_0 == rContext->
version)
1333 if (NULL == pbSendBuffer || 0 == cbSendLength)
1342 rv = RFCheckReaderStatus(rContext);
1346 if (IFD_HVERSION_2_0 == rContext->
version)
1349 *lpBytesReturned = cbRecvLength;
1350 rv = IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
1351 cbSendLength, pbRecvBuffer, lpBytesReturned);
1354 if (IFD_HVERSION_3_0 == rContext->
version)
1355 rv =
IFDControl(rContext, dwControlCode, pbSendBuffer,
1356 cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
1361 UNREF_READER(rContext)
1366LONG SCardGetAttrib(
SCARDHANDLE hCard, DWORD dwAttrId,
1367 LPBYTE pbAttr, LPDWORD pcbAttrLen)
1370 READER_CONTEXT * rContext = NULL;
1376 rv = RFReaderInfoById(hCard, &rContext);
1383 rv = RFCheckSharing(hCard, rContext);
1390 rv = RFCheckReaderStatus(rContext);
1397 rv = RFCheckReaderEventState(rContext, hCard);
1416 if (len > *pcbAttrLen)
1436 UNREF_READER(rContext)
1441LONG SCardSetAttrib(
SCARDHANDLE hCard, DWORD dwAttrId,
1442 LPCBYTE pbAttr, DWORD cbAttrLen)
1445 READER_CONTEXT * rContext = NULL;
1451 rv = RFReaderInfoById(hCard, &rContext);
1458 rv = RFCheckSharing(hCard, rContext);
1465 rv = RFCheckReaderStatus(rContext);
1472 rv = RFCheckReaderEventState(rContext, hCard);
1486 UNREF_READER(rContext)
1492 LPCBYTE pbSendBuffer, DWORD cbSendLength,
1494 LPDWORD pcbRecvLength)
1497 READER_CONTEXT * rContext = NULL;
1499 DWORD dwRxLength, tempRxLength;
1501 dwRxLength = *pcbRecvLength;
1514 rv = RFReaderInfoById(hCard, &rContext);
1521 rv = RFCheckSharing(hCard, rContext);
1528 rv = RFCheckReaderStatus(rContext);
1535 rv = RFCheckReaderEventState(rContext, hCard);
1568 sSendPci.Protocol = 0;
1572 sSendPci.Protocol = 1;
1585 for (i = 0 ; prot != 1 && i < 16; i++)
1588 sSendPci.Protocol = i;
1597 Log2(PCSC_LOG_DEBUG,
"Send Protocol: T=%ld", sSendPci.Protocol);
1599 tempRxLength = dwRxLength;
1602 && (rContext->
version == IFD_HVERSION_2_0))
1604 rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
1605 pbRecvBuffer, &dwRxLength);
1608 rv =
IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
1609 cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
1622 Log2(PCSC_LOG_ERROR,
"Card not transacted: %s", rv2text(rv));
1637 if (tempRxLength < dwRxLength)
1647 *pcbRecvLength = dwRxLength;
1650 UNREF_READER(rContext)
short ATRDecodeAtr(int *availableProtocols, int *currentProtocol, PUCHAR pucAtr, DWORD dwLength)
parse an ATR
This keeps track of smart card protocols, timing issues and Answer to Reset ATR handling.
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
#define PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.
#define SCARD_W_UNRESPONSIVE_CARD
The smart card is not responding to a reset.
#define SCARD_E_PROTO_MISMATCH
The requested protocols are incompatible with the protocol currently in use with the smart card.
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
#define SCARD_S_SUCCESS
No error was encountered.
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
#define SCARD_W_REMOVED_CARD
The smart card has been removed, so further communication is not possible.
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
#define SCARD_E_NO_SMARTCARD
The operation requires a Smart Card, but no Smart Card is currently in the device.
#define SCARD_E_NOT_TRANSACTED
An attempt was made to end a non-existent transaction.
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
#define SCARD_W_UNPOWERED_CARD
Power has been removed from the smart card, so that further communication is not possible.
#define SCARD_E_UNSUPPORTED_FEATURE
This smart card does not support the requested feature.
#define IFD_POWER_UP
power up the card
#define IFD_ERROR_TAG
tag unknown
#define TAG_IFD_STOP_POLLING_THREAD
method used to stop the polling thread (instead of just pthread_kill())
#define IFD_POWER_DOWN
power down the card
struct _SCARD_IO_HEADER SCARD_IO_HEADER
Use by SCardTransmit().
#define IFD_RESET
warm reset
#define IFD_ERROR_INSUFFICIENT_BUFFER
buffer is too small
#define IFD_SUCCESS
no error
LONG IFDControl(READER_CONTEXT *rContext, DWORD ControlCode, LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength, LPDWORD BytesReturned)
Provide a means for toggling a specific action on the reader such as swallow, eject,...
RESPONSECODE IFDGetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, PDWORD pdwLength, PUCHAR pucValue)
Gets capabilities in the reader.
LONG IFDTransmit(READER_CONTEXT *rContext, SCARD_IO_HEADER pioTxPci, PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer, PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
Transmit an APDU to the ICC.
RESPONSECODE IFDSetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, DWORD dwLength, PUCHAR pucValue)
Set capabilities in the reader.
RESPONSECODE IFDPowerICC(READER_CONTEXT *rContext, DWORD dwAction, PUCHAR pucAtr, PDWORD pdwAtrLen)
Power up/down or reset's an ICC located in the IFD.
This wraps the dynamic ifdhandler functions.
#define SCARD_SCOPE_SYSTEM
Scope in system.
#define SCARD_RESET_CARD
Reset on close.
#define SCARD_SWALLOWED
Card not powered.
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
#define SCARD_PROTOCOL_T1
T=1 active protocol.
#define SCARD_SHARE_DIRECT
Raw mode only.
#define SCARD_SCOPE_USER
Scope in user space.
#define SCARD_SCOPE_GLOBAL
Scope is global.
#define SCARD_PRESENT
Card is present.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
#define SCARD_EJECT_CARD
Eject on close.
#define SCARD_UNPOWER_CARD
Power down on close.
#define SCARD_SHARE_SHARED
Shared mode only.
#define SCARD_POWERED
Card is powered.
#define MAX_ATR_SIZE
Maximum ATR size.
#define SCARD_ABSENT
Card is absent.
#define SCARD_SCOPE_TERMINAL
Scope in terminal.
#define SCARD_PROTOCOL_RAW
Raw active protocol.
#define SCARD_LEAVE_CARD
Do nothing on close.
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
#define SCARD_SHARE_EXCLUSIVE
Exclusive mode only.
#define SCARD_NEGOTIABLE
Ready for PTS.
LONG SCARDHANDLE
hCard returned by SCardConnect()
DWORD PHSetProtocol(struct ReaderContext *rContext, DWORD dwPreferred, UCHAR ucAvailable, UCHAR ucDefault)
Determine which protocol to use.
This handles protocol defaults, PTS, etc.
This keeps a list of defines shared between the driver and the application.
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME
Reader's display name.
#define SCARD_ATTR_DEVICE_SYSTEM_NAME
Reader's system name.
This keeps track of a list of currently available reader structures.
READER_STATE readerState
reader state
pthread_mutex_t * mMutex
Mutex for this connection.
pthread_mutex_t powerState_lock
powerState mutex
_Atomic int32_t contexts
Number of open contexts.
int slot
Current Reader Slot.
_Atomic SCARDHANDLE hLockId
Lock Id.
int version
IFD Handler version number.
int powerState
auto power off state
Protocol Control Information (PCI).
unsigned long dwProtocol
Protocol identifier.
unsigned long cbPciLength
Protocol Control Inf Length.
_Atomic int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
char readerName[MAX_READERNAME]
reader name
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
_Atomic uint32_t cardAtrLength
ATR length.
uint32_t readerState
SCARD_* bit field.
This handles abstract system level calls.
int SYS_RandomInt(void)
Generate a pseudo random number.
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
long int time_sub(struct timeval *a, struct timeval *b)
return the difference (as long int) in µs between 2 struct timeval r = a - b
#define SCARD_PROTOCOL_ANY_OLD
used for backward compatibility
This handles smart card reader communications.