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);
230 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
231 LPDWORD pdwActiveProtocol)
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");
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, defaultProtocol);
385 if (SET_PROTOCOL_PPS_FAILED == ret)
387 (void)pthread_mutex_unlock(rContext->
mMutex);
392 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
394 (void)pthread_mutex_unlock(rContext->
mMutex);
402 (void)pthread_mutex_unlock(rContext->
mMutex);
406 (void)pthread_mutex_unlock(rContext->
mMutex);
421 switch (*pdwActiveProtocol)
425 Log2(PCSC_LOG_DEBUG,
"Active Protocol: T=%d",
430 Log1(PCSC_LOG_DEBUG,
"Active Protocol: RAW");
434 Log2(PCSC_LOG_ERROR,
"Active Protocol: unknown %ld",
439 Log1(PCSC_LOG_DEBUG,
"Direct access: no protocol selected");
447 (void)pthread_mutex_lock(&LockMutex);
449 *phCard = RFCreateReaderHandle(rContext);
451 Log2(PCSC_LOG_DEBUG,
"hCard Identity: %lx", *phCard);
465 (void)RFLockSharing(*phCard, rContext);
471 (void)pthread_mutex_unlock(&LockMutex);
486 rv = RFAddReaderHandle(rContext, *phCard);
488 (void)pthread_mutex_unlock(&LockMutex);
513 UNREF_READER(rContext)
521 DWORD dwPreferredProtocols, DWORD dwInitialization,
522 LPDWORD pdwActiveProtocol)
527 Log1(PCSC_LOG_DEBUG,
"Attempting reconnect to token.");
553 rv = RFReaderInfoById(hCard, &rContext);
560 rv = RFCheckReaderStatus(rContext);
567 rv = RFCheckSharing(hCard, rContext);
604 Log1(PCSC_LOG_DEBUG,
"Reset complete.");
605 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
612 Log1(PCSC_LOG_ERROR,
"Error resetting card.");
662 (void)pthread_mutex_lock(rContext->
mMutex);
667 int availableProtocols, defaultProtocol;
679 availableProtocols, defaultProtocol);
682 if (SET_PROTOCOL_PPS_FAILED == ret)
684 (void)pthread_mutex_unlock(rContext->
mMutex);
689 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
691 (void)pthread_mutex_unlock(rContext->
mMutex);
699 (void)pthread_mutex_unlock(rContext->
mMutex);
703 (void)pthread_mutex_unlock(rContext->
mMutex);
714 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_IN_USE");
722 switch (*pdwActiveProtocol)
726 Log2(PCSC_LOG_DEBUG,
"Active Protocol: T=%d",
731 Log1(PCSC_LOG_DEBUG,
"Active Protocol: RAW");
735 Log2(PCSC_LOG_ERROR,
"Active Protocol: unknown %ld",
740 Log1(PCSC_LOG_DEBUG,
"Direct access: no protocol selected");
755 (void)RFLockSharing(hCard, rContext);
777 (void)RFUnlockSharing(hCard, rContext);
794 (void)RFUnlockSharing(hCard, rContext);
807 (void)RFClearReaderEventState(rContext, hCard);
817 UNREF_READER(rContext)
837 rv = RFReaderInfoById(hCard, &rContext);
848 && (rContext->
hLockId != hCard))
850 Log1(PCSC_LOG_INFO,
"Waiting for release of lock");
853 Log1(PCSC_LOG_INFO,
"Lock released");
863 rv = RFUnlockAllSharing(hCard, rContext);
877 Log2(PCSC_LOG_DEBUG,
"Active Contexts: %d", rContext->
contexts);
878 Log2(PCSC_LOG_DEBUG,
"dwDisposition: %ld", dwDisposition);
900 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_UNPOWERED");
916 Log1(PCSC_LOG_DEBUG,
"Reset complete.");
917 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
925 Log2(PCSC_LOG_ERROR,
"Error powering down card: %s",
930 Log1(PCSC_LOG_ERROR,
"Error resetting card.");
942 UCHAR controlBuffer[5];
949 controlBuffer[0] = 0x20;
950 controlBuffer[1] = 0x15;
951 controlBuffer[2] = (rContext->
slot & 0x0000FFFF) + 1;
952 controlBuffer[3] = 0x00;
953 controlBuffer[4] = 0x00;
955 rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
960 if (receiveLength == 2 && receiveBuffer[0] == 0x90)
962 Log1(PCSC_LOG_DEBUG,
"Card ejected successfully.");
968 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
971 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
984 (void)RFRemoveReaderHandle(rContext, hCard);
1004 RESPONSECODE (*fct)(DWORD) = NULL;
1013 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_GRACE_PERIOD");
1026 Log1(PCSC_LOG_INFO,
"Stopping polling thread");
1053 rv = RFReaderInfoById(hCard, &
rContext);
1060 rv = RFCheckReaderStatus(
rContext);
1067 rv = RFCheckReaderEventState(
rContext, hCard);
1071 rv = RFLockSharing(hCard,
rContext);
1078 Log2(PCSC_LOG_DEBUG,
"Status: %s", rv2text(rv));
1105 rv = RFReaderInfoById(hCard, &
rContext);
1112 rv = RFCheckReaderEventState(
rContext, hCard);
1123 Log1(PCSC_LOG_INFO,
"No card reset within a transaction");
1158 rContext->readerState->readerState =
1161 Log1(PCSC_LOG_DEBUG,
"Reset complete.");
1162 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
1164 rContext->readerState->cardAtrLength);
1168 rContext->readerState->cardAtrLength = 0;
1169 Log1(PCSC_LOG_ERROR,
"Error resetting card.");
1174 rContext->readerState->readerState =
1200 Log1(PCSC_LOG_DEBUG,
"Card ejected successfully.");
1206 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
1209 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
1230 Log2(PCSC_LOG_DEBUG,
"Status: %s", rv2text(rv));
1258 rv = RFReaderInfoById(hCard, &
rContext);
1265 rv = RFCheckSharing(hCard,
rContext);
1284 rv = RFCheckReaderEventState(
rContext, hCard);
1291 rv = RFCheckReaderStatus(
rContext);
1315 rv = RFReaderInfoById(hCard, &
rContext);
1322 rv = RFCheckSharing(hCard,
rContext);
1326 if (IFD_HVERSION_2_0 ==
rContext->version)
1336 rv = RFCheckReaderStatus(
rContext);
1340 if (IFD_HVERSION_2_0 ==
rContext->version)
1348 if (IFD_HVERSION_3_0 ==
rContext->version)
1370 rv = RFReaderInfoById(hCard, &
rContext);
1377 rv = RFCheckSharing(hCard,
rContext);
1384 rv = RFCheckReaderStatus(
rContext);
1391 rv = RFCheckReaderEventState(
rContext, hCard);
1436 LPCBYTE pbAttr, DWORD cbAttrLen)
1445 rv = RFReaderInfoById(hCard, &
rContext);
1452 rv = RFCheckSharing(hCard,
rContext);
1459 rv = RFCheckReaderStatus(
rContext);
1466 rv = RFCheckReaderEventState(
rContext, hCard);
1488 LPDWORD pcbRecvLength)
1508 rv = RFReaderInfoById(hCard, &
rContext);
1515 rv = RFCheckSharing(hCard,
rContext);
1522 rv = RFCheckReaderStatus(
rContext);
1529 rv = RFCheckReaderEventState(
rContext, hCard);
1577 unsigned long prot =
rContext->readerState->cardProtocol;
1579 for (
i = 0 ;
prot != 1 &&
i < 16;
i++)
1591 Log2(PCSC_LOG_DEBUG,
"Send Protocol: T=%ld",
sSendPci.Protocol);
1596 && (
rContext->version == IFD_HVERSION_2_0))
1616 Log2(PCSC_LOG_ERROR,
"Card not transacted: %s", rv2text(rv));
1620 rContext->readerState->cardAtrLength = 0;
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
#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.
This keeps a list of defines for pcsc-lite.
@ POWER_STATE_IN_USE
card is used
@ POWER_STATE_UNPOWERED
auto power off
@ POWER_STATE_POWERED
powered
@ POWER_STATE_GRACE_PERIOD
card was in use
#define SCARD_RESET
Card was reset.
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
#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.
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.
struct pubReaderStatesList * readerState
link to the reader state
int powerState
auto power off state
Protocol Control Information (PCI)
int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
uint32_t readerState
SCARD_* bit field.
uint32_t cardAtrLength
ATR length.
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.