81 #include <sys/types.h>
112 #define SCARD_PROTOCOL_ANY_OLD 0x1000
119 static char sharing_shall_block = TRUE;
121 #define COLOR_RED "\33[01;31m"
122 #define COLOR_GREEN "\33[32m"
123 #define COLOR_BLUE "\33[34m"
124 #define COLOR_MAGENTA "\33[35m"
125 #define COLOR_NORMAL "\33[0m"
127 #define TIMEOUT_TIME 3
134 static void trace(
const char *func,
const char direction,
const char *fmt, ...)
138 fprintf(stderr, COLOR_GREEN
"%c " COLOR_BLUE
"[%lX] " COLOR_GREEN
"%s ",
139 direction, pthread_self(), func);
141 fprintf(stderr, COLOR_MAGENTA);
143 vfprintf(stderr, fmt, args);
146 fprintf(stderr, COLOR_NORMAL
"\n");
149 #define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__);
150 #define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__);
152 #define API_TRACE_IN(...)
153 #define API_TRACE_OUT(...)
158 #define PROFILE_FILE "/tmp/pcsc_profile"
160 #include <sys/time.h>
163 #define MAX_THREADS 5
164 pthread_t threads[MAX_THREADS];
165 struct timeval profile_time_start[MAX_THREADS];
169 #define PROFILE_START profile_start();
170 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
172 static void profile_start(
void)
174 static char initialized = FALSE;
183 sprintf(filename,
"%s-%d", PROFILE_FILE, getuid());
184 profile_fd = fopen(filename,
"a+");
185 if (NULL == profile_fd)
187 fprintf(stderr, COLOR_RED
"Can't open %s: %s" COLOR_NORMAL
"\n",
188 PROFILE_FILE, strerror(errno));
191 fprintf(profile_fd,
"\nStart a new profile\n");
193 if (isatty(fileno(stderr)))
200 for (i=0; i<MAX_THREADS; i++)
201 if (pthread_equal(0, threads[i]))
207 gettimeofday(&profile_time_start[i], NULL);
210 static void profile_end(
const char *f, LONG rv)
212 struct timeval profile_time_end;
217 gettimeofday(&profile_time_end, NULL);
220 for (i=0; i<MAX_THREADS; i++)
221 if (pthread_equal(t, threads[i]))
226 fprintf(stderr, COLOR_BLUE
" WARNING: no start info for %s\n", f);
230 d =
time_sub(&profile_time_end, &profile_time_start[i]);
239 COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld "
240 COLOR_BLUE
"0x%08lX %s" COLOR_NORMAL
"\n",
243 fprintf(stderr, COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld"
244 COLOR_NORMAL
"\n", f, d);
246 fprintf(profile_fd,
"%s %ld\n", f, d);
251 #define PROFILE_START
252 #define PROFILE_END(rv)
267 static int CHANNEL_MAP_seeker(
const void *el,
const void *key)
271 if ((el == NULL) || (key == NULL))
273 Log3(PCSC_LOG_CRITICAL,
274 "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
300 static list_t contextMapList;
302 static int SCONTEXTMAP_seeker(
const void *el,
const void *key)
306 if ((el == NULL) || (key == NULL))
308 Log3(PCSC_LOG_CRITICAL,
309 "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
352 static LONG SCardGetContextAndChannelFromHandle(
SCARDHANDLE,
354 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
358 static void SCardInvalidateHandles(
void);
359 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
360 LPBYTE pbAttr, LPDWORD pcbAttrLen);
362 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
375 return pthread_mutex_lock(&clientMutex);
385 return pthread_mutex_unlock(&clientMutex);
425 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
428 static int first_time = TRUE;
430 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
439 pthread_atfork(NULL, NULL, SCardInvalidateHandles);
453 pvReserved2, phContext);
458 API_TRACE_OUT(
"%ld", *phContext)
491 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
495 uint32_t dwClientID = 0;
499 if (phContext == NULL)
516 lrv = list_init(&contextMapList);
519 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
524 lrv = list_attributes_seeker(&contextMapList,
528 Log2(PCSC_LOG_CRITICAL,
529 "list_attributes_seeker failed with return value: %d", lrv);
530 list_destroy(&contextMapList);
534 if (getenv(
"PCSCLITE_NO_BLOCKING"))
536 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
537 sharing_shall_block = FALSE;
564 dwClientID, TIMEOUT_TIME*1000L);
567 Log1(PCSC_LOG_CRITICAL,
568 "Your pcscd is too old and does not support CMD_VERSION");
572 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
583 scEstablishStruct.dwScope = dwScope;
584 scEstablishStruct.hContext = 0;
588 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
596 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
603 return scEstablishStruct.rv;
611 *phContext = scEstablishStruct.hContext;
648 API_TRACE_IN(
"%ld", hContext)
656 if (NULL == currentContextMap)
662 (void)pthread_mutex_lock(currentContextMap->mMutex);
666 if (NULL == currentContextMap)
675 scReleaseStruct.hContext = hContext;
679 currentContextMap->dwClientID,
680 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
689 currentContextMap->dwClientID);
694 rv = scReleaseStruct.rv;
696 (void)pthread_mutex_unlock(currentContextMap->mMutex);
769 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
770 LPDWORD pdwActiveProtocol)
777 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
782 if (phCard == NULL || pdwActiveProtocol == NULL)
787 if (szReader == NULL)
793 if (strlen(szReader) > MAX_READERNAME)
800 if (NULL == currentContextMap)
803 (void)pthread_mutex_lock(currentContextMap->mMutex);
807 if (NULL == currentContextMap)
813 strlcpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
815 scConnectStruct.hContext = hContext;
816 scConnectStruct.dwShareMode = dwShareMode;
817 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
818 scConnectStruct.hCard = 0;
819 scConnectStruct.dwActiveProtocol = 0;
823 sizeof(scConnectStruct), (
void *) &scConnectStruct);
832 currentContextMap->dwClientID);
837 *phCard = scConnectStruct.hCard;
838 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
845 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
848 rv = scConnectStruct.rv;
851 (void)pthread_mutex_unlock(currentContextMap->mMutex);
854 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
933 DWORD dwPreferredProtocols, DWORD dwInitialization,
934 LPDWORD pdwActiveProtocol)
943 if (pdwActiveProtocol == NULL)
949 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
957 (void)pthread_mutex_lock(currentContextMap->mMutex);
960 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
968 scReconnectStruct.hCard = hCard;
969 scReconnectStruct.dwShareMode = dwShareMode;
970 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
971 scReconnectStruct.dwInitialization = dwInitialization;
972 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
976 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
984 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
985 currentContextMap->dwClientID);
990 rv = scReconnectStruct.rv;
994 (void)pthread_mutex_unlock(currentContextMap->mMutex);
999 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
1002 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1048 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1053 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1061 (void)pthread_mutex_lock(currentContextMap->mMutex);
1064 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1075 scDisconnectStruct.hCard = hCard;
1076 scDisconnectStruct.dwDisposition = dwDisposition;
1080 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1088 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1089 currentContextMap->dwClientID);
1095 (void)SCardRemoveHandle(hCard);
1096 rv = scDisconnectStruct.rv;
1099 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1156 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1168 (void)pthread_mutex_lock(currentContextMap->mMutex);
1171 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1179 scBeginStruct.hCard = hCard;
1183 currentContextMap->dwClientID,
1184 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1193 currentContextMap->dwClientID);
1198 rv = scBeginStruct.rv;
1203 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1207 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1267 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1272 (void)pthread_mutex_lock(currentContextMap->
mMutex);
1275 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1283 scEndStruct.hCard = hCard;
1284 scEndStruct.dwDisposition = dwDisposition;
1289 sizeof(scEndStruct), (
void *) &scEndStruct);
1306 randnum = SYS_RandomInt(1000, 10000);
1308 rv = scEndStruct.rv;
1311 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
1414 LPDWORD pcchReaderLen, LPDWORD pdwState,
1415 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1417 DWORD dwReaderLen, dwAtrLen;
1424 char *bufReader = NULL;
1425 LPBYTE bufAtr = NULL;
1438 if (pcchReaderLen == NULL)
1439 pcchReaderLen = &dummy;
1441 if (pcbAtrLen == NULL)
1445 dwReaderLen = *pcchReaderLen;
1446 dwAtrLen = *pcbAtrLen;
1454 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1462 (void)pthread_mutex_lock(currentContextMap->mMutex);
1465 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1474 rv = getReaderStates(currentContextMap);
1478 r = pChannelMap->readerName;
1482 if (r && strcmp(r, readerStates[i].readerName) == 0)
1486 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1493 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1494 scStatusStruct.hCard = hCard;
1497 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1506 currentContextMap->dwClientID);
1511 rv = scStatusStruct.rv;
1515 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1532 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1536 *pdwState = (readerStates[i].
eventCounter << 16) + readerStates[i].readerState;
1543 dwReaderLen = *pcchReaderLen;
1544 if (NULL == mszReaderName)
1549 bufReader = malloc(dwReaderLen);
1550 if (NULL == bufReader)
1555 *(
char **)mszReaderName = bufReader;
1558 bufReader = mszReaderName;
1563 if (*pcchReaderLen > dwReaderLen)
1566 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1571 dwAtrLen = *pcbAtrLen;
1577 bufAtr = malloc(dwAtrLen);
1583 *(LPBYTE *)pbAtr = bufAtr;
1590 if (*pcbAtrLen > dwAtrLen)
1593 memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1597 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1703 DWORD dwBreakFlag = 0;
1706 int currentReaderCount = 0;
1710 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1712 for (j=0; j<cReaders; j++)
1714 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1715 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1719 if ((rgReaderStates == NULL && cReaders > 0)
1727 for (j = 0; j < cReaders; j++)
1729 if (rgReaderStates[j].szReader == NULL)
1736 int nbNonIgnoredReaders = cReaders;
1738 for (j=0; j<cReaders; j++)
1740 nbNonIgnoredReaders--;
1742 if (0 == nbNonIgnoredReaders)
1759 if (NULL == currentContextMap)
1765 (void)pthread_mutex_lock(currentContextMap->
mMutex);
1769 if (NULL == currentContextMap)
1779 rv = getReaderStates(currentContextMap);
1784 for (j=0; j<cReaders; j++)
1786 const char *readerName;
1789 readerName = rgReaderStates[j].szReader;
1792 if (strcmp(readerName, readerStates[i].readerName) == 0)
1797 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1800 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1809 for (j = 0; j < cReaders; j++)
1810 rgReaderStates[j].dwEventState = 0;
1813 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1817 if (readerStates[j].readerName[0] !=
'\0')
1818 currentReaderCount++;
1821 if ((DWORD)-1 == dwTimeout)
1831 currReader = &rgReaderStates[j];
1836 const char *readerName;
1840 readerName = currReader->szReader;
1843 if (strcmp(readerName, readerStates[i].readerName) == 0)
1848 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1851 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1853 int k, newReaderCount = 0;
1856 if (readerStates[k].readerName[0] !=
'\0')
1859 if (newReaderCount != currentReaderCount)
1861 Log1(PCSC_LOG_INFO,
"Reader list changed");
1862 currentReaderCount = newReaderCount;
1870 currReader->dwEventState =
1886 uint32_t readerState;
1893 Log0(PCSC_LOG_DEBUG);
1898 rContext = &readerStates[i];
1904 if (currReader->dwCurrentState & 0xFFFF0000)
1906 unsigned int currentCounter;
1908 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1914 Log0(PCSC_LOG_DEBUG);
1920 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1932 Log0(PCSC_LOG_DEBUG);
1941 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1943 Log0(PCSC_LOG_DEBUG);
1957 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1961 currReader->cbAtr = 0;
1980 Log0(PCSC_LOG_DEBUG);
1985 else if (readerState & SCARD_PRESENT)
1998 Log0(PCSC_LOG_DEBUG);
2008 Log0(PCSC_LOG_DEBUG);
2018 Log0(PCSC_LOG_DEBUG);
2032 Log0(PCSC_LOG_DEBUG);
2039 if (readerState & SCARD_PRESENT)
2046 Log0(PCSC_LOG_DEBUG);
2059 Log0(PCSC_LOG_DEBUG);
2062 else if (currReader-> dwCurrentState
2066 Log0(PCSC_LOG_DEBUG);
2078 Log0(PCSC_LOG_DEBUG);
2094 if (dwBreakFlag == 1)
2100 struct timeval before, after;
2102 gettimeofday(&before, NULL);
2104 waitStatusStruct.
timeOut = dwTime;
2112 sizeof(waitStatusStruct), &waitStatusStruct);
2121 &waitStatusStruct,
sizeof(waitStatusStruct),
2133 sizeof(waitStatusStruct), &waitStatusStruct);
2140 sizeof(waitStatusStruct),
2153 rv = waitStatusStruct.rv;
2158 rv = getReaderStates(currentContextMap);
2166 gettimeofday(&after, NULL);
2168 dwTime -= diff/1000;
2188 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2190 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
2195 for (j=0; j<cReaders; j++)
2197 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2198 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2256 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2257 LPDWORD lpBytesReturned)
2267 if (NULL != lpBytesReturned)
2268 *lpBytesReturned = 0;
2273 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2281 (void)pthread_mutex_lock(currentContextMap->mMutex);
2284 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2299 scControlStruct.hCard = hCard;
2300 scControlStruct.dwControlCode = dwControlCode;
2301 scControlStruct.cbSendLength = cbSendLength;
2302 scControlStruct.cbRecvLength = cbRecvLength;
2303 scControlStruct.dwBytesReturned = 0;
2304 scControlStruct.rv = 0;
2307 sizeof(scControlStruct), &scControlStruct);
2313 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2314 currentContextMap->dwClientID);
2323 currentContextMap->dwClientID);
2331 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2332 currentContextMap->dwClientID);
2339 if (NULL != lpBytesReturned)
2340 *lpBytesReturned = scControlStruct.dwBytesReturned;
2342 rv = scControlStruct.rv;
2345 (void)pthread_mutex_unlock(currentContextMap->mMutex);
2460 unsigned char *buf = NULL;
2464 if (NULL == pcbAttrLen)
2476 buf = malloc(*pcbAttrLen);
2483 *(
unsigned char **)pbAttr = buf;
2546 if (NULL == pbAttr || 0 == cbAttrLen)
2557 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2558 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2568 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2573 (void)pthread_mutex_lock(currentContextMap->mMutex);
2576 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2590 scGetSetStruct.hCard = hCard;
2591 scGetSetStruct.dwAttrId = dwAttrId;
2592 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2594 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2596 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2599 sizeof(scGetSetStruct), &scGetSetStruct);
2608 currentContextMap->dwClientID);
2618 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2620 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2624 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2627 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2629 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2631 rv = scGetSetStruct.rv;
2634 (void)pthread_mutex_unlock(currentContextMap->mMutex);
2698 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2700 LPDWORD pcbRecvLength)
2709 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2710 pcbRecvLength == NULL || pioSendPci == NULL)
2716 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2728 (void)pthread_mutex_lock(currentContextMap->
mMutex);
2731 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2746 scTransmitStruct.hCard = hCard;
2747 scTransmitStruct.cbSendLength = cbSendLength;
2748 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2749 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2750 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2755 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2756 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2765 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2771 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2789 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2797 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2798 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2802 rv = scTransmitStruct.rv;
2806 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
2811 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2814 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
2872 LPSTR mszReaders, LPDWORD pcchReaders)
2874 DWORD dwReadersLen = 0;
2882 API_TRACE_IN(
"%ld", hContext)
2887 if (pcchReaders == NULL)
2894 if (NULL == currentContextMap)
2900 (void)pthread_mutex_lock(currentContextMap->
mMutex);
2904 if (NULL == currentContextMap)
2911 rv = getReaderStates(currentContextMap);
2917 if (readerStates[i].readerName[0] !=
'\0')
2918 dwReadersLen += strlen(readerStates[i].readerName) + 1;
2923 if (1 == dwReadersLen)
2931 buf = malloc(dwReadersLen);
2937 if (NULL == mszReaders)
2942 *(
char **)mszReaders = buf;
2949 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2956 if (mszReaders == NULL)
2961 if (readerStates[i].readerName[0] !=
'\0')
2966 strcpy(buf, readerStates[i].readerName);
2967 buf += strlen(readerStates[i].readerName)+1;
2974 *pcchReaders = dwReadersLen;
2976 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
2979 API_TRACE_OUT(
"%d", *pcchReaders)
3008 if (NULL == currentContextMap)
3011 free((
void *)pvMem);
3079 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
3080 const unsigned int dwGroups =
sizeof(ReaderGroup);
3086 if (NULL == currentContextMap)
3089 (void)pthread_mutex_lock(currentContextMap->
mMutex);
3093 if (NULL == currentContextMap)
3101 if (NULL == mszGroups)
3106 buf = malloc(dwGroups);
3112 *(
char **)mszGroups = buf;
3118 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3126 memcpy(buf, ReaderGroup, dwGroups);
3129 *pcchGroups = dwGroups;
3131 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
3171 uint32_t dwClientID = 0;
3175 API_TRACE_IN(
"%ld", hContext)
3181 if (NULL == currentContextMap)
3187 if (! currentContextMap->cancellable)
3200 scCancelStruct.hContext = hContext;
3204 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3212 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3217 rv = scCancelStruct.rv;
3257 API_TRACE_IN(
"%ld", hContext)
3265 if (currentContextMap == NULL)
3296 if (NULL == newContextMap)
3299 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3300 newContextMap->
hContext = hContext;
3304 newContextMap->
mMutex = malloc(
sizeof(pthread_mutex_t));
3305 if (NULL == newContextMap->
mMutex)
3307 Log2(PCSC_LOG_DEBUG,
"Freeing SCONTEXTMAP @%p", newContextMap);
3308 free(newContextMap);
3311 (void)pthread_mutex_init(newContextMap->
mMutex, NULL);
3313 lrv = list_init(&newContextMap->channelMapList);
3316 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3320 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3321 CHANNEL_MAP_seeker);
3324 Log2(PCSC_LOG_CRITICAL,
3325 "list_attributes_seeker failed with return value: %d", lrv);
3326 list_destroy(&newContextMap->channelMapList);
3330 lrv = list_append(&contextMapList, newContextMap);
3333 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3335 list_destroy(&newContextMap->channelMapList);
3343 (void)pthread_mutex_destroy(newContextMap->
mMutex);
3344 free(newContextMap->
mMutex);
3345 free(newContextMap);
3370 return currentContextMap;
3387 return list_seek(&contextMapList, &hContext);
3404 if (NULL == currentContextMap)
3407 return SCardCleanContext(currentContextMap);
3410 static LONG SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3412 int list_index, lrv;
3419 (void)pthread_mutex_destroy(targetContextMap->
mMutex);
3420 free(targetContextMap->
mMutex);
3421 targetContextMap->
mMutex = NULL;
3423 listSize = list_size(&targetContextMap->channelMapList);
3424 for (list_index = 0; list_index < listSize; list_index++)
3426 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3428 if (NULL == currentChannelMap)
3430 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3436 free(currentChannelMap->readerName);
3437 free(currentChannelMap);
3441 list_destroy(&targetContextMap->channelMapList);
3443 lrv = list_delete(&contextMapList, targetContextMap);
3446 Log2(PCSC_LOG_CRITICAL,
3447 "list_delete failed with return value: %d", lrv);
3450 free(targetContextMap);
3466 if (NULL == newChannelMap)
3469 newChannelMap->hCard = hCard;
3470 newChannelMap->readerName = strdup(readerName);
3472 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3475 free(newChannelMap->readerName);
3476 free(newChannelMap);
3477 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3492 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
3493 ¤tChannelMap);
3497 free(currentChannelMap->readerName);
3499 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3502 Log2(PCSC_LOG_CRITICAL,
3503 "list_delete failed with return value: %d", lrv);
3506 free(currentChannelMap);
3511 static LONG SCardGetContextAndChannelFromHandle(
SCARDHANDLE hCard,
3520 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3527 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3536 *targetContextMap = NULL;
3537 *targetChannelMap = NULL;
3539 listSize = list_size(&contextMapList);
3541 for (list_index = 0; list_index < listSize; list_index++)
3543 currentContextMap = list_get_at(&contextMapList, list_index);
3544 if (currentContextMap == NULL)
3546 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3550 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3552 if (currentChannelMap != NULL)
3554 *targetContextMap = currentContextMap;
3555 *targetChannelMap = currentChannelMap;
3577 struct stat statBuffer;
3580 socketName = getSocketName();
3581 rv = stat(socketName, &statBuffer);
3585 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3586 socketName, strerror(errno));
3593 static void SCardInvalidateHandles(
void)
3598 while (list_size(&contextMapList) != 0)
3602 currentContextMap = list_get_at(&contextMapList, 0);
3603 if (currentContextMap != NULL)
3604 (void)SCardCleanContext(currentContextMap);
3606 Log1(PCSC_LOG_CRITICAL,
"list_get_at returned NULL");
3612 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3614 int32_t dwClientID = currentContextMap->
dwClientID;
3622 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.
PCSC_API 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.
PCSC_API 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()
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()
PCSC_API 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.
#define PROTOCOL_VERSION_MAJOR
Major version of the current message protocol.
#define SCARD_PROTOCOL_T1
T=1 active protocol.
contained in SCARD_DISCONNECT Messages.
PCSC_API 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.
PCSC_API 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.
PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
Terminates a connection made through SCardConnect().
PCSC_API 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.
const SCARD_IO_REQUEST g_rgSCardRawPci
Protocol Control Information for raw access.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
PCSC_API 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.
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.
PCSC_API 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
PCSC_API LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Establishes a connection to the reader specified in * szReader.
PCSC_API 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.
PCSC_API 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.
pthread_mutex_t * mMutex
Mutex for this context.
PCSC_API 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)
PCSC_API 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.
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.
PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
Ends a previously begun transaction.
PCSC_API 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().
const SCARD_IO_REQUEST g_rgSCardT1Pci
Protocol Control Information for T=1.
#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
const SCARD_IO_REQUEST g_rgSCardT0Pci
Protocol Control Information for T=0.
This handles smart card reader communications.
PCSC_API 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.