107 #include <sys/time.h>
132 #define PROFILE_FILE "/tmp/pcscd_profile"
134 #include <sys/time.h>
138 struct timeval profile_time_start;
142 #define PROFILE_START profile_start(__FUNCTION__);
143 #define PROFILE_END profile_end(__FUNCTION__, __LINE__);
145 static void profile_start(
const char *f)
147 static char initialized = FALSE;
152 fd = fopen(PROFILE_FILE,
"a+");
155 fprintf(stderr,
"\33[01;31mCan't open %s: %s\33[0m\n",
156 PROFILE_FILE, strerror(errno));
159 fprintf(fd,
"\nStart a new profile\n");
162 if (isatty(fileno(stderr)))
168 gettimeofday(&profile_time_start, NULL);
172 static void profile_end(
const char *f,
int line)
174 struct timeval profile_time_end;
177 gettimeofday(&profile_time_end, NULL);
178 d =
time_sub(&profile_time_end, &profile_time_start);
181 fprintf(stderr,
"\33[01;31mRESULT %s \33[35m%ld\33[0m (%d)\n", f, d,
183 fprintf(fd,
"%s %ld\n", f, d);
188 #define PROFILE_START
193 #define SCARD_PROTOCOL_ANY_OLD 0x1000
195 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
196 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
213 *phContext = SYS_RandomInt(0, -1);
215 Log2(PCSC_LOG_DEBUG,
"Establishing Context: 0x%lX", *phContext);
226 Log2(PCSC_LOG_DEBUG,
"Releasing Context: 0x%lX", hContext);
232 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
233 LPDWORD pdwActiveProtocol)
237 uint32_t readerState;
256 Log3(PCSC_LOG_DEBUG,
"Attempting Connect to %s using protocol: %ld",
257 szReader, dwPreferredProtocols);
259 rv = RFReaderInfo((LPSTR) szReader, &rContext);
262 Log2(PCSC_LOG_ERROR,
"Reader %s Not Found", szReader);
269 rv = RFCheckReaderStatus(rContext);
284 Log1(PCSC_LOG_ERROR,
"Error Reader Exclusive");
294 Log1(PCSC_LOG_INFO,
"Waiting for release of lock");
297 Log1(PCSC_LOG_INFO,
"Lock released");
312 Log1(PCSC_LOG_DEBUG,
"Card Not Inserted");
332 Log1(PCSC_LOG_DEBUG,
"power up complete.");
333 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
338 Log3(PCSC_LOG_ERROR,
"Error powering up card: %ld 0x%04lX",
344 Log1(PCSC_LOG_ERROR,
"Card Not Powered");
352 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_INUSE");
370 (void)pthread_mutex_lock(rContext->
mMutex);
375 int availableProtocols, defaultProtocol;
383 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
387 availableProtocols, defaultProtocol);
390 if (SET_PROTOCOL_PPS_FAILED == ret)
392 (void)pthread_mutex_unlock(rContext->
mMutex);
397 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
399 (void)pthread_mutex_unlock(rContext->
mMutex);
407 (void)pthread_mutex_unlock(rContext->
mMutex);
411 (void)pthread_mutex_unlock(rContext->
mMutex);
426 switch (*pdwActiveProtocol)
429 case SCARD_PROTOCOL_T1:
430 Log2(PCSC_LOG_DEBUG,
"Active Protocol: T=%d",
434 case SCARD_PROTOCOL_RAW:
435 Log1(PCSC_LOG_DEBUG,
"Active Protocol: RAW");
439 Log2(PCSC_LOG_ERROR,
"Active Protocol: unknown %ld",
444 Log1(PCSC_LOG_DEBUG,
"Direct access: no protocol selected");
449 *phCard = RFCreateReaderHandle(rContext);
451 Log2(PCSC_LOG_DEBUG,
"hCard Identity: %lx", *phCard);
465 (void)RFLockSharing(*phCard, rContext);
469 (void)RFDestroyReaderHandle(*phCard);
486 rv = RFAddReaderHandle(rContext, *phCard);
493 (void)RFDestroyReaderHandle(*phCard);
512 UNREF_READER(rContext)
520 DWORD dwPreferredProtocols, DWORD dwInitialization,
521 LPDWORD pdwActiveProtocol)
526 Log1(PCSC_LOG_DEBUG,
"Attempting reconnect to token.");
552 rv = RFReaderInfoById(hCard, &rContext);
559 rv = RFCheckReaderStatus(rContext);
566 rv = RFCheckSharing(hCard, rContext);
578 (void)RFSetReaderEventState(rContext,
SCARD_RESET);
606 Log1(PCSC_LOG_DEBUG,
"Reset complete.");
607 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
614 Log1(PCSC_LOG_ERROR,
"Error resetting card.");
656 if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
664 (void)pthread_mutex_lock(rContext->
mMutex);
669 int availableProtocols, defaultProtocol;
677 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
681 availableProtocols, defaultProtocol);
684 if (SET_PROTOCOL_PPS_FAILED == ret)
686 (void)pthread_mutex_unlock(rContext->
mMutex);
691 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
693 (void)pthread_mutex_unlock(rContext->
mMutex);
701 (void)pthread_mutex_unlock(rContext->
mMutex);
705 (void)pthread_mutex_unlock(rContext->
mMutex);
720 switch (*pdwActiveProtocol)
722 case SCARD_PROTOCOL_T0:
723 case SCARD_PROTOCOL_T1:
724 Log2(PCSC_LOG_DEBUG,
"Active Protocol: T=%d",
725 (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
728 case SCARD_PROTOCOL_RAW:
729 Log1(PCSC_LOG_DEBUG,
"Active Protocol: RAW");
733 Log2(PCSC_LOG_ERROR,
"Active Protocol: unknown %ld",
738 Log1(PCSC_LOG_DEBUG,
"Direct access: no protocol selected");
753 (void)RFLockSharing(hCard, rContext);
775 (void)RFUnlockSharing(hCard, rContext);
792 (void)RFUnlockSharing(hCard, rContext);
805 (void)RFClearReaderEventState(rContext, hCard);
815 UNREF_READER(rContext)
835 rv = RFReaderInfoById(hCard, &rContext);
843 && (rContext->
hLockId != hCard))
845 Log1(PCSC_LOG_INFO,
"Waiting for release of lock");
848 Log1(PCSC_LOG_INFO,
"Lock released");
858 rv = RFUnlockAllSharing(hCard, rContext);
872 Log2(PCSC_LOG_DEBUG,
"Active Contexts: %d", rContext->
contexts);
873 Log2(PCSC_LOG_DEBUG,
"dwDisposition: %ld", dwDisposition);
883 (void)RFSetReaderEventState(rContext,
SCARD_RESET);
897 #ifdef DISABLE_AUTO_POWER_ON
899 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_UNPOWERED");
909 #ifdef DISABLE_AUTO_POWER_ON
917 Log3(PCSC_LOG_ERROR,
"Error powering down card: %d 0x%04X",
925 Log1(PCSC_LOG_INFO,
"Skip card power on");
939 Log1(PCSC_LOG_DEBUG,
"Reset complete.");
940 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
947 Log1(PCSC_LOG_ERROR,
"Error resetting card.");
959 UCHAR controlBuffer[5];
966 controlBuffer[0] = 0x20;
967 controlBuffer[1] = 0x15;
968 controlBuffer[2] = (rContext->
slot & 0x0000FFFF) + 1;
969 controlBuffer[3] = 0x00;
970 controlBuffer[4] = 0x00;
972 rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
977 if (receiveLength == 2 && receiveBuffer[0] == 0x90)
979 Log1(PCSC_LOG_DEBUG,
"Card ejected successfully.");
985 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
988 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
1001 (void)RFRemoveReaderHandle(rContext, hCard);
1002 (void)RFDestroyReaderHandle(hCard);
1022 RESPONSECODE (*fct)(DWORD) = NULL;
1028 if (POWER_STATE_POWERED <= rContext->powerState)
1030 #ifdef DISABLE_AUTO_POWER_ON
1034 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_GRACE_PERIOD");
1038 Log1(PCSC_LOG_DEBUG,
"powerState: POWER_STATE_GRACE_PERIOD");
1046 dwGetSize =
sizeof(fct);
1048 &dwGetSize, (PUCHAR)&fct);
1050 if ((
IFD_SUCCESS == rv) && (dwGetSize ==
sizeof(fct)))
1052 Log1(PCSC_LOG_INFO,
"Stopping polling thread");
1053 fct(rContext->
slot);
1065 UNREF_READER(rContext)
1079 rv = RFReaderInfoById(hCard, &rContext);
1086 rv = RFCheckReaderStatus(rContext);
1093 rv = RFCheckReaderEventState(rContext, hCard);
1097 rv = RFLockSharing(hCard, rContext);
1104 Log2(PCSC_LOG_DEBUG,
"Status: 0x%08lX", rv);
1107 UNREF_READER(rContext)
1131 rv = RFReaderInfoById(hCard, &rContext);
1138 rv = RFCheckReaderEventState(rContext, hCard);
1167 (void)RFSetReaderEventState(rContext,
SCARD_RESET);
1178 Log1(PCSC_LOG_DEBUG,
"Reset complete.");
1179 LogXxd(PCSC_LOG_DEBUG,
"Card ATR: ",
1186 Log1(PCSC_LOG_ERROR,
"Error resetting card.");
1197 UCHAR controlBuffer[5];
1199 DWORD receiveLength;
1204 controlBuffer[0] = 0x20;
1205 controlBuffer[1] = 0x15;
1206 controlBuffer[2] = (rContext->
slot & 0x0000FFFF) + 1;
1207 controlBuffer[3] = 0x00;
1208 controlBuffer[4] = 0x00;
1210 rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
1215 if (receiveLength == 2 && receiveBuffer[0] == 0x90)
1217 Log1(PCSC_LOG_DEBUG,
"Card ejected successfully.");
1223 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
1226 Log1(PCSC_LOG_ERROR,
"Error ejecting card.");
1241 rv2 = RFUnlockSharing(hCard, rContext);
1247 Log2(PCSC_LOG_DEBUG,
"Status: 0x%08lX", rv);
1250 UNREF_READER(rContext)
1256 LPDWORD pcchReaderLen, LPDWORD pdwState,
1257 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1264 (void)mszReaderNames;
1265 (void)pcchReaderLen;
1275 rv = RFReaderInfoById(hCard, &rContext);
1282 rv = RFCheckSharing(hCard, rContext);
1301 rv = RFCheckReaderEventState(rContext, hCard);
1308 rv = RFCheckReaderStatus(rContext);
1313 UNREF_READER(rContext)
1319 LPCVOID pbSendBuffer, DWORD cbSendLength,
1320 LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
1326 *lpBytesReturned = 0;
1332 rv = RFReaderInfoById(hCard, &rContext);
1339 rv = RFCheckSharing(hCard, rContext);
1343 if (IFD_HVERSION_2_0 == rContext->
version)
1344 if (NULL == pbSendBuffer || 0 == cbSendLength)
1353 rv = RFCheckReaderStatus(rContext);
1357 if (IFD_HVERSION_2_0 == rContext->
version)
1360 *lpBytesReturned = cbRecvLength;
1361 rv = IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
1362 cbSendLength, pbRecvBuffer, lpBytesReturned);
1365 if (IFD_HVERSION_3_0 == rContext->
version)
1366 rv =
IFDControl(rContext, dwControlCode, pbSendBuffer,
1367 cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
1372 UNREF_READER(rContext)
1378 LPBYTE pbAttr, LPDWORD pcbAttrLen)
1387 rv = RFReaderInfoById(hCard, &rContext);
1394 rv = RFCheckSharing(hCard, rContext);
1401 rv = RFCheckReaderStatus(rContext);
1408 rv = RFCheckReaderEventState(rContext, hCard);
1427 if (len > *pcbAttrLen)
1447 UNREF_READER(rContext)
1453 LPCBYTE pbAttr, DWORD cbAttrLen)
1462 rv = RFReaderInfoById(hCard, &rContext);
1469 rv = RFCheckSharing(hCard, rContext);
1476 rv = RFCheckReaderStatus(rContext);
1483 rv = RFCheckReaderEventState(rContext, hCard);
1497 UNREF_READER(rContext)
1503 LPCBYTE pbSendBuffer, DWORD cbSendLength,
1505 LPDWORD pcbRecvLength)
1510 DWORD dwRxLength, tempRxLength;
1512 dwRxLength = *pcbRecvLength;
1525 rv = RFReaderInfoById(hCard, &rContext);
1532 rv = RFCheckSharing(hCard, rContext);
1539 rv = RFCheckReaderStatus(rContext);
1546 rv = RFCheckReaderEventState(rContext, hCard);
1579 sSendPci.Protocol = 0;
1583 sSendPci.Protocol = 1;
1596 for (i = 0 ; prot != 1 ; i++)
1599 sSendPci.Protocol = i;
1608 Log2(PCSC_LOG_DEBUG,
"Send Protocol: T=%ld", sSendPci.Protocol);
1610 tempRxLength = dwRxLength;
1613 && (rContext->
version == IFD_HVERSION_2_0))
1615 rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
1616 pbRecvBuffer, &dwRxLength);
1619 rv =
IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
1620 cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
1633 Log2(PCSC_LOG_ERROR,
"Card not transacted: 0x%08lX", rv);
1640 if (tempRxLength < dwRxLength)
1650 *pcbRecvLength = dwRxLength;
1653 UNREF_READER(rContext)
struct pubReaderStatesList * readerState
link to the reader state
uint32_t cardAtrLength
ATR length.
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME
Reader's display name.
int32_t contexts
Number of open contexts.
#define IFD_ERROR_TAG
tag unknown
#define SCARD_E_PROTO_MISMATCH
The requested protocols are incompatible with the protocol currently in use with the smart card...
volatile SCARDHANDLE hLockId
Lock Id.
#define SCARD_SCOPE_USER
Scope in user space.
#define TAG_IFD_STOP_POLLING_THREAD
method used to stop the polling thread (instead of just pthread_kill())
#define SCARD_ATTR_DEVICE_SYSTEM_NAME
Reader's system name.
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
LONG IFDGetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, PDWORD pdwLength, PUCHAR pucValue)
Get's capabilities in the reader.
This keeps a list of defines shared between the driver and the application.
char readerName[MAX_READERNAME]
reader name
unsigned long cbPciLength
Protocol Control Inf Length.
int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
#define SCARD_E_NOT_TRANSACTED
An attempt was made to end a non-existent transaction.
#define SCARD_LEAVE_CARD
Do nothing on close.
This handles protocol defaults, PTS, etc.
This handles abstract system level calls.
int slot
Current Reader Slot.
This wraps the dynamic ifdhandler functions.
#define SCARD_PROTOCOL_T1
T=1 active protocol.
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
#define SCARD_SCOPE_TERMINAL
Scope in terminal.
#define SCARD_W_UNRESPONSIVE_CARD
The smart card is not responding to a reset.
#define SCARD_PROTOCOL_ANY_OLD
used for backward compatibility
#define SCARD_PRESENT
Card is present.
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
#define SCARD_NEGOTIABLE
Ready for PTS.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
This keeps track of smart card protocols, timing issues and Answer to Reset ATR handling.
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
#define SCARD_RESET
Card was reset.
#define SCARD_SHARE_SHARED
Shared mode only.
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.
unsigned long dwProtocol
Protocol identifier.
#define IFD_POWER_DOWN
power down the card
int version
IFD Handler version number.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
pthread_mutex_t * mMutex
Mutex for this connection.
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
short ATRDecodeAtr(int *availableProtocols, int *currentProtocol, PUCHAR pucAtr, DWORD dwLength)
parse an ATR
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define SCARD_UNPOWER_CARD
Power down on close.
LONG IFDSetCapabilities(READER_CONTEXT *rContext, DWORD dwTag, DWORD dwLength, PUCHAR pucValue)
Set capabilities in the reader.
#define SCARD_W_REMOVED_CARD
The smart card has been removed, so further communication is not possible.
#define SCARD_SWALLOWED
Card not powered.
#define SCARD_E_UNSUPPORTED_FEATURE
This smart card does not support the requested feature.
int powerState
auto power off state
#define SCARD_PROTOCOL_UNDEFINED
protocol not set
#define SCARD_RESET_CARD
Reset on close.
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
LONG SCARDHANDLE
hCard returned by SCardConnect()
LONG IFDPowerICC(READER_CONTEXT *rContext, DWORD dwAction, PUCHAR pucAtr, PDWORD pdwAtrLen)
Power up/down or reset's an ICC located in the IFD.
#define SCARD_SHARE_EXCLUSIVE
Exclusive mode only.
#define SCARD_POWERED
Card is powered.
DWORD PHSetProtocol(struct ReaderContext *rContext, DWORD dwPreferred, UCHAR ucAvailable, UCHAR ucDefault)
Determine which protocol to use.
This keeps a list of defines for pcsc-lite.
#define SCARD_PROTOCOL_RAW
Raw active protocol.
#define SCARD_EJECT_CARD
Eject on close.
Protocol Control Information (PCI)
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
#define SCARD_SCOPE_GLOBAL
Scope is global.
#define SCARD_W_UNPOWERED_CARD
Power has been removed from the smart card, so that further communication is not possible.
#define SCARD_ABSENT
Card is absent.
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
#define SCARD_E_NO_SMARTCARD
The operation requires a Smart Card, but no Smart Card is currently in the device.
This keeps track of a list of currently available reader structures.
#define MAX_ATR_SIZE
Maximum ATR size.
#define IFD_ERROR_INSUFFICIENT_BUFFER
buffer is too small
uint32_t readerState
SCARD_* bit field.
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
#define SCARD_SHARE_DIRECT
Raw mode only.
#define PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
pthread_mutex_t powerState_lock
powerState mutex
#define IFD_RESET
warm reset
#define SCARD_S_SUCCESS
error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx
#define SCARD_SCOPE_SYSTEM
Scope in system.
This handles smart card reader communications.
#define IFD_POWER_UP
power up the card
#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, biometric.
#define SCARD_F_INTERNAL_ERROR
An internal consistency check failed.