107 #include <sys/types.h>
113 #include <sys/time.h>
115 #include <sys/wait.h>
138 #define SCARD_PROTOCOL_ANY_OLD 0x1000
145 static char sharing_shall_block = TRUE;
147 #define COLOR_RED "\33[01;31m"
148 #define COLOR_GREEN "\33[32m"
149 #define COLOR_BLUE "\33[34m"
150 #define COLOR_MAGENTA "\33[35m"
151 #define COLOR_NORMAL "\33[0m"
158 static void trace(
const char *func,
const char direction,
const char *fmt, ...)
162 fprintf(stderr, COLOR_GREEN
"%c " COLOR_BLUE
"[%lX] " COLOR_GREEN
"%s ",
163 direction, pthread_self(), func);
165 fprintf(stderr, COLOR_MAGENTA);
167 vfprintf(stderr, fmt, args);
170 fprintf(stderr, COLOR_NORMAL
"\n");
173 #define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__);
174 #define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__);
176 #define API_TRACE_IN(...)
177 #define API_TRACE_OUT(...)
182 #define PROFILE_FILE "/tmp/pcsc_profile"
184 #include <sys/time.h>
187 #define MAX_THREADS 5
188 pthread_t threads[MAX_THREADS];
189 struct timeval profile_time_start[MAX_THREADS];
193 #define PROFILE_START profile_start();
194 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
196 static void profile_start(
void)
198 static char initialized = FALSE;
207 sprintf(filename,
"%s-%d", PROFILE_FILE, getuid());
208 profile_fd = fopen(filename,
"a+");
209 if (NULL == profile_fd)
211 fprintf(stderr, COLOR_RED
"Can't open %s: %s" COLOR_NORMAL
"\n",
212 PROFILE_FILE, strerror(errno));
215 fprintf(profile_fd,
"\nStart a new profile\n");
217 if (isatty(fileno(stderr)))
224 for (i=0; i<MAX_THREADS; i++)
225 if (pthread_equal(0, threads[i]))
231 gettimeofday(&profile_time_start[i], NULL);
234 static void profile_end(
const char *f, LONG rv)
236 struct timeval profile_time_end;
241 gettimeofday(&profile_time_end, NULL);
244 for (i=0; i<MAX_THREADS; i++)
245 if (pthread_equal(t, threads[i]))
250 fprintf(stderr, COLOR_BLUE
" WARNING: no start info for %s\n", f);
254 d =
time_sub(&profile_time_end, &profile_time_start[i]);
263 COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld "
264 COLOR_BLUE
"0x%08lX %s" COLOR_NORMAL
"\n",
267 fprintf(stderr, COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld"
268 COLOR_NORMAL
"\n", f, d);
270 fprintf(profile_fd,
"%s %ld\n", f, d);
275 #define PROFILE_START
276 #define PROFILE_END(rv)
291 static int CHANNEL_MAP_seeker(
const void *el,
const void *key)
295 if ((el == NULL) || (key == NULL))
297 Log3(PCSC_LOG_CRITICAL,
298 "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
324 static list_t contextMapList;
326 static int SCONTEXTMAP_seeker(
const void *el,
const void *key)
330 if ((el == NULL) || (key == NULL))
332 Log3(PCSC_LOG_CRITICAL,
333 "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
376 static LONG SCardGetContextAndChannelFromHandle(
SCARDHANDLE,
378 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
382 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
383 LPBYTE pbAttr, LPDWORD pcbAttrLen);
385 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
398 return pthread_mutex_lock(&clientMutex);
408 return pthread_mutex_unlock(&clientMutex);
448 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
452 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
466 pvReserved2, phContext);
471 API_TRACE_OUT(
"%ld", *phContext)
504 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
508 uint32_t dwClientID = 0;
512 if (phContext == NULL)
529 lrv = list_init(&contextMapList);
532 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
537 lrv = list_attributes_seeker(&contextMapList,
541 Log2(PCSC_LOG_CRITICAL,
542 "list_attributes_seeker failed with return value: %d", lrv);
543 list_destroy(&contextMapList);
547 if (getenv(
"PCSCLITE_NO_BLOCKING"))
549 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
550 sharing_shall_block = FALSE;
579 Log1(PCSC_LOG_CRITICAL,
580 "Your pcscd is too old and does not support CMD_VERSION");
584 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
595 scEstablishStruct.dwScope = dwScope;
596 scEstablishStruct.hContext = 0;
600 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
608 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
615 return scEstablishStruct.rv;
623 *phContext = scEstablishStruct.hContext;
660 API_TRACE_IN(
"%ld", hContext)
668 if (NULL == currentContextMap)
674 (void)pthread_mutex_lock(¤tContextMap->mMutex);
678 if (NULL == currentContextMap)
687 scReleaseStruct.hContext = hContext;
691 currentContextMap->dwClientID,
692 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
701 currentContextMap->dwClientID);
706 rv = scReleaseStruct.rv;
708 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
781 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
782 LPDWORD pdwActiveProtocol)
789 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
794 if (phCard == NULL || pdwActiveProtocol == NULL)
799 if (szReader == NULL)
805 if (strlen(szReader) > MAX_READERNAME)
812 if (NULL == currentContextMap)
815 (void)pthread_mutex_lock(¤tContextMap->mMutex);
819 if (NULL == currentContextMap)
825 strlcpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
827 scConnectStruct.hContext = hContext;
828 scConnectStruct.dwShareMode = dwShareMode;
829 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
830 scConnectStruct.hCard = 0;
831 scConnectStruct.dwActiveProtocol = 0;
835 sizeof(scConnectStruct), (
void *) &scConnectStruct);
844 currentContextMap->dwClientID);
849 *phCard = scConnectStruct.hCard;
850 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
857 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
860 rv = scConnectStruct.rv;
863 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
866 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
945 DWORD dwPreferredProtocols, DWORD dwInitialization,
946 LPDWORD pdwActiveProtocol)
955 if (pdwActiveProtocol == NULL)
961 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
969 (void)pthread_mutex_lock(¤tContextMap->mMutex);
972 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
982 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
986 scReconnectStruct.hCard = hCard;
987 scReconnectStruct.dwShareMode = dwShareMode;
988 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
989 scReconnectStruct.dwInitialization = dwInitialization;
990 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
994 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
1002 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
1003 currentContextMap->dwClientID);
1008 rv = scReconnectStruct.rv;
1012 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1017 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
1020 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1066 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1071 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1079 (void)pthread_mutex_lock(¤tContextMap->mMutex);
1082 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1092 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1097 scDisconnectStruct.hCard = hCard;
1098 scDisconnectStruct.dwDisposition = dwDisposition;
1102 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1110 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1111 currentContextMap->dwClientID);
1117 (void)SCardRemoveHandle(hCard);
1118 rv = scDisconnectStruct.rv;
1121 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1178 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1190 (void)pthread_mutex_lock(¤tContextMap->mMutex);
1193 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1203 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1207 scBeginStruct.hCard = hCard;
1211 currentContextMap->dwClientID,
1212 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1221 currentContextMap->dwClientID);
1226 rv = scBeginStruct.rv;
1231 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1235 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1295 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1300 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
1303 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1313 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
1317 scEndStruct.hCard = hCard;
1318 scEndStruct.dwDisposition = dwDisposition;
1323 sizeof(scEndStruct), (
void *) &scEndStruct);
1340 randnum = SYS_RandomInt(1000, 10000);
1342 rv = scEndStruct.rv;
1345 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
1448 LPDWORD pcchReaderLen, LPDWORD pdwState,
1449 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1451 DWORD dwReaderLen, dwAtrLen;
1458 char *bufReader = NULL;
1459 LPBYTE bufAtr = NULL;
1472 if (pcchReaderLen == NULL)
1473 pcchReaderLen = &dummy;
1475 if (pcbAtrLen == NULL)
1479 dwReaderLen = *pcchReaderLen;
1480 dwAtrLen = *pcbAtrLen;
1488 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1496 (void)pthread_mutex_lock(¤tContextMap->mMutex);
1499 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1509 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1514 rv = getReaderStates(currentContextMap);
1518 r = pChannelMap->readerName;
1522 if (r && strcmp(r, readerStates[i].readerName) == 0)
1526 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1533 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1534 scStatusStruct.hCard = hCard;
1537 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1546 currentContextMap->dwClientID);
1551 rv = scStatusStruct.rv;
1555 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1572 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1576 *pdwState = (readerStates[i].
eventCounter << 16) + readerStates[i].readerState;
1583 dwReaderLen = *pcchReaderLen;
1584 if (NULL == mszReaderName)
1589 bufReader = malloc(dwReaderLen);
1590 if (NULL == bufReader)
1595 *(
char **)mszReaderName = bufReader;
1598 bufReader = mszReaderName;
1603 if (*pcchReaderLen > dwReaderLen)
1606 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1611 dwAtrLen = *pcbAtrLen;
1617 bufAtr = malloc(dwAtrLen);
1623 *(LPBYTE *)pbAtr = bufAtr;
1630 if (*pcbAtrLen > dwAtrLen)
1633 memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1637 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1743 DWORD dwBreakFlag = 0;
1746 int currentReaderCount = 0;
1750 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1752 for (j=0; j<cReaders; j++)
1754 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1755 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1759 if ((rgReaderStates == NULL && cReaders > 0)
1767 for (j = 0; j < cReaders; j++)
1769 if (rgReaderStates[j].szReader == NULL)
1776 int nbNonIgnoredReaders = cReaders;
1778 for (j=0; j<cReaders; j++)
1780 nbNonIgnoredReaders--;
1782 if (0 == nbNonIgnoredReaders)
1799 if (NULL == currentContextMap)
1805 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
1809 if (NULL == currentContextMap)
1819 rv = getReaderStates(currentContextMap);
1824 for (j=0; j<cReaders; j++)
1826 const char *readerName;
1829 readerName = rgReaderStates[j].szReader;
1832 if (strcmp(readerName, readerStates[i].readerName) == 0)
1837 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1840 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1849 for (j = 0; j < cReaders; j++)
1850 rgReaderStates[j].dwEventState = 0;
1853 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1857 if (readerStates[j].readerName[0] !=
'\0')
1858 currentReaderCount++;
1861 if ((DWORD)-1 == dwTimeout)
1871 currReader = &rgReaderStates[j];
1876 const char *readerName;
1880 readerName = currReader->szReader;
1883 if (strcmp(readerName, readerStates[i].readerName) == 0)
1888 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1891 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1893 int k, newReaderCount = 0;
1896 if (readerStates[k].readerName[0] !=
'\0')
1899 if (newReaderCount != currentReaderCount)
1901 Log1(PCSC_LOG_INFO,
"Reader list changed");
1902 currentReaderCount = newReaderCount;
1910 currReader->dwEventState =
1926 uint32_t readerState;
1933 Log0(PCSC_LOG_DEBUG);
1938 rContext = &readerStates[i];
1944 if (currReader->dwCurrentState & 0xFFFF0000)
1946 unsigned int currentCounter;
1948 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1954 Log0(PCSC_LOG_DEBUG);
1960 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1972 Log0(PCSC_LOG_DEBUG);
1981 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1983 Log0(PCSC_LOG_DEBUG);
1997 memcpy(currReader->rgbAtr, rContext->
cardAtr,
2001 currReader->cbAtr = 0;
2020 Log0(PCSC_LOG_DEBUG);
2025 else if (readerState & SCARD_PRESENT)
2038 Log0(PCSC_LOG_DEBUG);
2048 Log0(PCSC_LOG_DEBUG);
2058 Log0(PCSC_LOG_DEBUG);
2072 Log0(PCSC_LOG_DEBUG);
2079 if (readerState & SCARD_PRESENT)
2086 Log0(PCSC_LOG_DEBUG);
2099 Log0(PCSC_LOG_DEBUG);
2102 else if (currReader-> dwCurrentState
2106 Log0(PCSC_LOG_DEBUG);
2118 Log0(PCSC_LOG_DEBUG);
2134 if (dwBreakFlag == 1)
2140 struct timeval before, after;
2142 gettimeofday(&before, NULL);
2144 waitStatusStruct.
timeOut = dwTime;
2152 sizeof(waitStatusStruct), &waitStatusStruct);
2161 &waitStatusStruct,
sizeof(waitStatusStruct),
2173 sizeof(waitStatusStruct), &waitStatusStruct);
2180 sizeof(waitStatusStruct),
2193 rv = waitStatusStruct.rv;
2198 rv = getReaderStates(currentContextMap);
2206 gettimeofday(&after, NULL);
2208 dwTime -= diff/1000;
2228 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2230 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2235 for (j=0; j<cReaders; j++)
2237 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2238 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2296 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2297 LPDWORD lpBytesReturned)
2307 if (NULL != lpBytesReturned)
2308 *lpBytesReturned = 0;
2313 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2321 (void)pthread_mutex_lock(¤tContextMap->mMutex);
2324 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2334 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2345 scControlStruct.hCard = hCard;
2346 scControlStruct.dwControlCode = dwControlCode;
2347 scControlStruct.cbSendLength = cbSendLength;
2348 scControlStruct.cbRecvLength = cbRecvLength;
2349 scControlStruct.dwBytesReturned = 0;
2350 scControlStruct.rv = 0;
2353 sizeof(scControlStruct), &scControlStruct);
2359 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2360 currentContextMap->dwClientID);
2369 currentContextMap->dwClientID);
2377 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2378 currentContextMap->dwClientID);
2385 if (NULL != lpBytesReturned)
2386 *lpBytesReturned = scControlStruct.dwBytesReturned;
2388 rv = scControlStruct.rv;
2391 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2506 unsigned char *buf = NULL;
2510 if (NULL == pcbAttrLen)
2522 buf = malloc(*pcbAttrLen);
2529 *(
unsigned char **)pbAttr = buf;
2592 if (NULL == pbAttr || 0 == cbAttrLen)
2603 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2604 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2614 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2619 (void)pthread_mutex_lock(¤tContextMap->mMutex);
2622 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2632 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2642 scGetSetStruct.hCard = hCard;
2643 scGetSetStruct.dwAttrId = dwAttrId;
2644 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2646 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2648 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2651 sizeof(scGetSetStruct), &scGetSetStruct);
2660 currentContextMap->dwClientID);
2670 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2672 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2676 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2679 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2681 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2683 rv = scGetSetStruct.rv;
2686 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2750 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2752 LPDWORD pcbRecvLength)
2761 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2762 pcbRecvLength == NULL || pioSendPci == NULL)
2768 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2780 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
2783 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2793 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2804 scTransmitStruct.hCard = hCard;
2805 scTransmitStruct.cbSendLength = cbSendLength;
2806 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2807 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2808 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2813 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2814 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2823 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2829 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2847 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2855 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2856 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2860 rv = scTransmitStruct.rv;
2864 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2869 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2872 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2930 LPSTR mszReaders, LPDWORD pcchReaders)
2932 DWORD dwReadersLen = 0;
2940 API_TRACE_IN(
"%ld", hContext)
2945 if (pcchReaders == NULL)
2952 if (NULL == currentContextMap)
2958 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
2962 if (NULL == currentContextMap)
2969 rv = getReaderStates(currentContextMap);
2975 if (readerStates[i].readerName[0] !=
'\0')
2976 dwReadersLen += strlen(readerStates[i].readerName) + 1;
2981 if (1 == dwReadersLen)
2989 if (NULL == mszReaders)
2994 buf = malloc(dwReadersLen);
3000 *(
char **)mszReaders = buf;
3007 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
3014 if (mszReaders == NULL)
3019 if (readerStates[i].readerName[0] !=
'\0')
3024 strcpy(buf, readerStates[i].readerName);
3025 buf += strlen(readerStates[i].readerName)+1;
3032 *pcchReaders = dwReadersLen;
3034 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3037 API_TRACE_OUT(
"%d", *pcchReaders)
3066 if (NULL == currentContextMap)
3069 free((
void *)pvMem);
3137 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
3138 const unsigned int dwGroups =
sizeof(ReaderGroup);
3144 if (NULL == currentContextMap)
3147 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
3151 if (NULL == currentContextMap)
3159 if (NULL == mszGroups)
3164 buf = malloc(dwGroups);
3170 *(
char **)mszGroups = buf;
3176 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3184 memcpy(buf, ReaderGroup, dwGroups);
3187 *pcchGroups = dwGroups;
3189 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3229 uint32_t dwClientID = 0;
3233 API_TRACE_IN(
"%ld", hContext)
3239 if (NULL == currentContextMap)
3245 if (! currentContextMap->cancellable)
3258 scCancelStruct.hContext = hContext;
3262 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3270 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3275 rv = scCancelStruct.rv;
3315 API_TRACE_IN(
"%ld", hContext)
3323 if (currentContextMap == NULL)
3354 if (NULL == newContextMap)
3357 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3358 newContextMap->
hContext = hContext;
3362 (void)pthread_mutex_init(&newContextMap->
mMutex, NULL);
3364 lrv = list_init(&newContextMap->channelMapList);
3367 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3371 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3372 CHANNEL_MAP_seeker);
3375 Log2(PCSC_LOG_CRITICAL,
3376 "list_attributes_seeker failed with return value: %d", lrv);
3377 list_destroy(&newContextMap->channelMapList);
3381 lrv = list_append(&contextMapList, newContextMap);
3384 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3386 list_destroy(&newContextMap->channelMapList);
3394 (void)pthread_mutex_destroy(&newContextMap->
mMutex);
3395 free(newContextMap);
3420 return currentContextMap;
3437 return list_seek(&contextMapList, &hContext);
3454 if (NULL == currentContextMap)
3457 return SCardCleanContext(currentContextMap);
3460 static LONG SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3462 int list_index, lrv;
3469 (void)pthread_mutex_destroy(&targetContextMap->
mMutex);
3471 listSize = list_size(&targetContextMap->channelMapList);
3472 for (list_index = 0; list_index < listSize; list_index++)
3474 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3476 if (NULL == currentChannelMap)
3478 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3484 free(currentChannelMap->readerName);
3485 free(currentChannelMap);
3489 list_destroy(&targetContextMap->channelMapList);
3491 lrv = list_delete(&contextMapList, targetContextMap);
3494 Log2(PCSC_LOG_CRITICAL,
3495 "list_delete failed with return value: %d", lrv);
3498 free(targetContextMap);
3514 if (NULL == newChannelMap)
3517 newChannelMap->hCard = hCard;
3518 newChannelMap->readerName = strdup(readerName);
3520 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3523 free(newChannelMap->readerName);
3524 free(newChannelMap);
3525 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3540 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
3541 ¤tChannelMap);
3545 free(currentChannelMap->readerName);
3547 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3550 Log2(PCSC_LOG_CRITICAL,
3551 "list_delete failed with return value: %d", lrv);
3554 free(currentChannelMap);
3559 static LONG SCardGetContextAndChannelFromHandle(
SCARDHANDLE hCard,
3568 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3575 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3584 *targetContextMap = NULL;
3585 *targetChannelMap = NULL;
3587 listSize = list_size(&contextMapList);
3589 for (list_index = 0; list_index < listSize; list_index++)
3591 currentContextMap = list_get_at(&contextMapList, list_index);
3592 if (currentContextMap == NULL)
3594 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3598 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3600 if (currentChannelMap != NULL)
3602 *targetContextMap = currentContextMap;
3603 *targetChannelMap = currentChannelMap;
3625 struct stat statBuffer;
3628 socketName = getSocketName();
3629 rv = stat(socketName, &statBuffer);
3633 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3634 socketName, strerror(errno));
3641 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3643 int32_t dwClientID = currentContextMap->
dwClientID;
3651 rv =
MessageReceive(&readerStates,
sizeof(readerStates), dwClientID);
used by SCardBeginTransaction()
contained in SCARD_CONNECT Messages.
uint32_t cardAtrLength
ATR length.
static SCONTEXTMAP * SCardGetContext(SCARDCONTEXT)
Get the index from the Application Context vector _psContextMap for the passed context.
wait for a reader state change
contained in SCARD_CANCEL Messages.
contained in SCARD_TRANSMIT Messages.
#define SCARD_STATE_UNAVAILABLE
Status unavailable.
LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
Returns a list of currently available readers on the system.
contained in SCARD_END_TRANSACTION Messages.
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
INTERNAL int ClientCloseSession(uint32_t dwClientID)
Closes the socket used by the client to communicate with the server.
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups)
Returns a list of currently available reader groups on the system.
#define SCARD_STATE_EMPTY
Card removed.
get the client/server protocol version
static SCONTEXTMAP * SCardGetContextTH(SCARDCONTEXT)
Get the address from the Application Context list _psContextMap for the passed context.
#define SCARD_STATE_IGNORE
Ignore this reader.
#define SCARD_UNKNOWN
Unknown state.
PCSC_API char * pcsc_stringify_error(const LONG pcscError)
Returns a human readable text for the given PC/SC error code.
static short isExecuted
Make sure the initialization code is executed only once.
used by SCardEstablishContext()
PCSC_API const SCARD_IO_REQUEST g_rgSCardT1Pci
Protocol Control Information for T=1.
INTERNAL LONG MessageSendWithHeader(uint32_t command, uint32_t dwClientID, uint64_t size, void *data_void)
Wrapper for the MessageSend() function.
int32_t minor
IPC minor PROTOCOL_VERSION_MINOR.
#define SCARD_F_COMM_ERROR
An internal communications error has been detected.
used by SCardEndTransaction()
LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
Creates an Application Context to the PC/SC Resource Manager.
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_STATE_CHANGED
State has changed.
This handles abstract system level calls.
static LONG SCardRemoveContext(SCARDCONTEXT)
Removes an Application Context from a control vector.
#define SCARD_E_NO_SERVICE
The Smart card resource manager is not running.
uint32_t eventCounter
number of card events
#define SCARD_E_NO_READERS_AVAILABLE
Cannot find a smart card reader.
static LONG SCardUnlockThread(void)
Unlocks a mutex so another thread may use the client.
PCSC_API const SCARD_IO_REQUEST g_rgSCardRawPci
Protocol Control Information for raw access.
#define PROTOCOL_VERSION_MAJOR
Major version of the current message protocol.
#define SCARD_PROTOCOL_T1
T=1 active protocol.
contained in SCARD_DISCONNECT Messages.
LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
Releases memory that has been returned from the resource manager using the SCARD_AUTOALLOCATE length ...
LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, SCARD_READERSTATE *rgReaderStates, DWORD cReaders)
Blocks execution until the current availability of the cards in a specific set of readers changes...
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
Get an attribute from the IFD Handler (reader driver).
#define SCARD_PRESENT
Card is present.
Information contained in SCARD_RELEASE_CONTEXT Messages.
LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
Terminates a connection made through SCardConnect().
LONG SCardCancel(SCARDCONTEXT hContext)
Cancels all pending blocking requests on the SCardGetStatusChange() function.
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
contained in SCARD_BEGIN_TRANSACTION Messages.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
LONG SCardIsValidContext(SCARDCONTEXT hContext)
Check if a SCARDCONTEXT is valid.
static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT)
Creates a communication context to the PC/SC Resource Manager.
#define INFINITE
Infinite timeout.
#define SCARD_STATE_UNKNOWN
Reader unknown.
Represents the an Application Context on the Client side.
Information contained in SCARD_ESTABLISH_CONTEXT Messages.
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
Information transmitted in CMD_VERSION Messages.
INTERNAL LONG MessageReceive(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Called by the Client to get the reponse from the server or vice-versa.
used by SCardReleaseContext()
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
contained in SCARD_STATUS Messages.
contained in SCARD_RECONNECT Messages.
unsigned long dwProtocol
Protocol identifier.
uint32_t timeOut
timeout in ms
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
contained in SCARD_GET_ATTRIB and Messages.
prototypes of strlcpy()/strlcat() imported from OpenBSD
#define SCARD_STATE_PRESENT
Card inserted.
PCSC_API const SCARD_IO_REQUEST g_rgSCardT0Pci
Protocol Control Information for T=0.
This defines some structures and #defines to be used over the transport layer.
Information contained in CMD_WAIT_READER_STATE_CHANGE Messages.
DWORD dwClientID
Client Connection ID.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
#define SCARD_STATE_ATRMATCH
ATR matches card.
LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
Reestablishes a connection to a reader that was previously connected to using SCardConnect().
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 MAX_BUFFER_SIZE_EXTENDED
enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer
static READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]
Area used to read status information about the readers.
#define PCSCLITE_STATUS_POLL_RATE
Status polling rate.
Represents an Application Context Channel.
This handles card insertion/removal events, updates ATR, protocol, and status information.
SCARDCONTEXT hContext
Application Context ID.
#define SCARD_PROTOCOL_ANY
IFD determines prot.
char cancellable
We are in a cancellable call.
stop waiting for a reader state change
LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Establishes a connection to the reader specified in * szReader.
LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
Returns the current status of the reader connected to by hCard.
LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
Set an attribute of the IFD Handler.
#define SCARD_STATE_EXCLUSIVE
Exclusive Mode.
#define SCARD_SWALLOWED
Card not powered.
static LONG SCardAddContext(SCARDCONTEXT, DWORD)
Functions for managing instances of SCardEstablishContext() These functions keep track of Context han...
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
LONG SCARDHANDLE
hCard returned by SCardConnect()
static LONG SCardLockThread(void)
Locks a mutex so another thread must wait to use this function.
LONG SCardCheckDaemonAvailability(void)
Checks if the server is running.
INTERNAL int ClientSetupSession(uint32_t *pdwClientID)
Prepares a communication channel for the client to talk to the server.
#define PROTOCOL_VERSION_MINOR
Minor version of the current message protocol.
LONG SCardBeginTransaction(SCARDHANDLE hCard)
Establishes a temporary exclusive access mode for doing a serie of commands in a transaction.
This keeps a list of defines for pcsc-lite.
#define SCARD_PROTOCOL_RAW
Raw active protocol.
#define SCARD_STATE_INUSE
Shared Mode.
Protocol Control Information (PCI)
LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
Sends a command directly to the IFD Handler (reader driver) to be processed by the reader...
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
#define SCARD_ABSENT
Card is absent.
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
Define an exported public reader state structure so each application gets instant notification of cha...
INTERNAL LONG MessageSend(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Sends a menssage from client to server or vice-versa.
used by SCardDisconnect()
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
contained in SCARD_CONTROL Messages.
This keeps track of a list of currently available reader structures.
pthread_mutex_t mMutex
Mutex for this context.
static pthread_mutex_t clientMutex
Ensure that some functions be accessed in thread-safe mode.
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 PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
int32_t major
IPC major PROTOCOL_VERSION_MAJOR.
LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
Ends a previously begun transaction.
LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
Sends an APDU to the smart card contained in the reader connected to by SCardConnect().
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
#define SCARD_S_SUCCESS
error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx
This handles smart card reader communications.
LONG SCardReleaseContext(SCARDCONTEXT hContext)
Destroys a communication context to the PC/SC Resource Manager.
INTERNAL LONG MessageReceiveTimeout(uint32_t command, void *buffer_void, uint64_t buffer_size, int32_t filedes, long timeOut)
Called by the Client to get the reponse from the server or vice-versa.
#define SCARD_E_TIMEOUT
The user-specified timeout value has expired.
#define SCARD_STATE_UNAWARE
App wants status.
#define SCARD_STATE_MUTE
Unresponsive card.