109 #include <sys/types.h>
115 #include <sys/time.h>
117 #include <sys/wait.h>
139 #define SCARD_PROTOCOL_ANY_OLD 0x1000
146 static char sharing_shall_block = TRUE;
148 #define COLOR_RED "\33[01;31m"
149 #define COLOR_GREEN "\33[32m"
150 #define COLOR_BLUE "\33[34m"
151 #define COLOR_MAGENTA "\33[35m"
152 #define COLOR_NORMAL "\33[0m"
159 static void trace(
const char *func,
const char direction,
const char *fmt, ...)
163 fprintf(stderr, COLOR_GREEN
"%c " COLOR_BLUE
"[%lX] " COLOR_GREEN
"%s ",
164 direction, pthread_self(), func);
166 fprintf(stderr, COLOR_MAGENTA);
168 vfprintf(stderr, fmt, args);
171 fprintf(stderr, COLOR_NORMAL
"\n");
174 #define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__);
175 #define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__);
177 #define API_TRACE_IN(...)
178 #define API_TRACE_OUT(...)
183 #define PROFILE_FILE "/tmp/pcsc_profile"
185 #include <sys/time.h>
188 #define MAX_THREADS 5
189 pthread_t threads[MAX_THREADS];
190 struct timeval profile_time_start[MAX_THREADS];
194 #define PROFILE_START profile_start();
195 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
197 static void profile_start(
void)
199 static char initialized = FALSE;
208 sprintf(filename,
"%s-%d", PROFILE_FILE, getuid());
209 profile_fd = fopen(filename,
"a+");
210 if (NULL == profile_fd)
212 fprintf(stderr, COLOR_RED
"Can't open %s: %s" COLOR_NORMAL
"\n",
213 PROFILE_FILE, strerror(errno));
216 fprintf(profile_fd,
"\nStart a new profile\n");
218 if (isatty(fileno(stderr)))
225 for (i=0; i<MAX_THREADS; i++)
226 if (pthread_equal(0, threads[i]))
232 gettimeofday(&profile_time_start[i], NULL);
235 static void profile_end(
const char *f, LONG rv)
237 struct timeval profile_time_end;
242 gettimeofday(&profile_time_end, NULL);
245 for (i=0; i<MAX_THREADS; i++)
246 if (pthread_equal(t, threads[i]))
251 fprintf(stderr, COLOR_BLUE
" WARNING: no start info for %s\n", f);
255 d =
time_sub(&profile_time_end, &profile_time_start[i]);
264 COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld "
265 COLOR_BLUE
"0x%08lX %s" COLOR_NORMAL
"\n",
268 fprintf(stderr, COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld"
269 COLOR_NORMAL
"\n", f, d);
271 fprintf(profile_fd,
"%s %ld\n", f, d);
276 #define PROFILE_START
277 #define PROFILE_END(rv)
292 static int CHANNEL_MAP_seeker(
const void *el,
const void *key)
296 if ((el == NULL) || (key == NULL))
298 Log3(PCSC_LOG_CRITICAL,
299 "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
325 static list_t contextMapList;
327 static int SCONTEXTMAP_seeker(
const void *el,
const void *key)
331 if ((el == NULL) || (key == NULL))
333 Log3(PCSC_LOG_CRITICAL,
334 "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
377 static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE,
379 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
383 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
384 LPBYTE pbAttr, LPDWORD pcbAttrLen);
386 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
399 return pthread_mutex_lock(&clientMutex);
409 return pthread_mutex_unlock(&clientMutex);
449 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
453 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
463 pvReserved2, phContext);
468 API_TRACE_OUT(
"%ld", *phContext)
501 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
505 uint32_t dwClientID = 0;
509 if (phContext == NULL)
526 lrv = list_init(&contextMapList);
529 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
534 lrv = list_attributes_seeker(&contextMapList,
538 Log2(PCSC_LOG_CRITICAL,
539 "list_attributes_seeker failed with return value: %d", lrv);
540 list_destroy(&contextMapList);
544 if (getenv(
"PCSCLITE_NO_BLOCKING"))
546 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
547 sharing_shall_block = FALSE;
576 Log1(PCSC_LOG_CRITICAL,
577 "Your pcscd is too old and does not support CMD_VERSION");
581 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
592 scEstablishStruct.dwScope = dwScope;
593 scEstablishStruct.hContext = 0;
597 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
605 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
612 return scEstablishStruct.rv;
620 *phContext = scEstablishStruct.hContext;
657 API_TRACE_IN(
"%ld", hContext)
665 if (NULL == currentContextMap)
671 scReleaseStruct.hContext = hContext;
675 currentContextMap->dwClientID,
676 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
685 currentContextMap->dwClientID);
690 rv = scReleaseStruct.rv;
692 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
765 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
766 LPDWORD pdwActiveProtocol)
773 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
778 if (phCard == NULL || pdwActiveProtocol == NULL)
783 if (szReader == NULL)
789 if (strlen(szReader) > MAX_READERNAME)
796 if (NULL == currentContextMap)
799 strncpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
800 scConnectStruct.szReader[
sizeof scConnectStruct.szReader -1] =
'\0';
802 scConnectStruct.hContext = hContext;
803 scConnectStruct.dwShareMode = dwShareMode;
804 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
805 scConnectStruct.hCard = 0;
806 scConnectStruct.dwActiveProtocol = 0;
810 sizeof(scConnectStruct), (
void *) &scConnectStruct);
819 currentContextMap->dwClientID);
824 *phCard = scConnectStruct.hCard;
825 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
832 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
835 rv = scConnectStruct.rv;
838 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
841 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
920 DWORD dwPreferredProtocols, DWORD dwInitialization,
921 LPDWORD pdwActiveProtocol)
929 API_TRACE_IN(
"%ld %ld %ld", hCard, dwShareMode, dwPreferredProtocols)
931 if (pdwActiveProtocol == NULL)
940 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
945 scReconnectStruct.hCard = hCard;
946 scReconnectStruct.dwShareMode = dwShareMode;
947 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
948 scReconnectStruct.dwInitialization = dwInitialization;
949 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
953 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
961 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
962 currentContextMap->dwClientID);
967 rv = scReconnectStruct.rv;
971 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
976 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
979 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
982 API_TRACE_OUT(
"%ld", *pdwActiveProtocol)
1026 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1031 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1039 scDisconnectStruct.hCard = hCard;
1040 scDisconnectStruct.dwDisposition = dwDisposition;
1044 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1052 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1053 currentContextMap->dwClientID);
1059 (void)SCardRemoveHandle(hCard);
1060 rv = scDisconnectStruct.rv;
1063 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1116 API_TRACE_IN(
"%ld", hCard)
1128 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1133 scBeginStruct.hCard = hCard;
1137 currentContextMap->dwClientID,
1138 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1147 currentContextMap->dwClientID);
1152 rv = scBeginStruct.rv;
1157 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1161 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1217 API_TRACE_IN(
"%ld", hCard)
1222 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1227 scEndStruct.hCard = hCard;
1228 scEndStruct.dwDisposition = dwDisposition;
1233 sizeof(scEndStruct), (
void *) &scEndStruct);
1250 randnum = SYS_RandomInt(1000, 10000);
1252 rv = scEndStruct.rv;
1255 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
1359 LPDWORD pcchReaderLen, LPDWORD pdwState,
1360 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1362 DWORD dwReaderLen, dwAtrLen;
1369 char *bufReader = NULL;
1370 LPBYTE bufAtr = NULL;
1383 if (pcchReaderLen == NULL)
1384 pcchReaderLen = &dummy;
1386 if (pcbAtrLen == NULL)
1390 dwReaderLen = *pcchReaderLen;
1391 dwAtrLen = *pcbAtrLen;
1402 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1408 rv = getReaderStates(currentContextMap);
1412 r = pChannelMap->readerName;
1416 if (r && strcmp(r, readerStates[i].readerName) == 0)
1420 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1427 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1428 scStatusStruct.hCard = hCard;
1431 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1440 currentContextMap->dwClientID);
1445 rv = scStatusStruct.rv;
1449 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1466 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1470 *pdwState = (readerStates[i].
eventCounter << 16) + readerStates[i].readerState;
1477 dwReaderLen = *pcchReaderLen;
1478 if (NULL == mszReaderName)
1483 bufReader = malloc(dwReaderLen);
1484 if (NULL == bufReader)
1489 *(
char **)mszReaderName = bufReader;
1492 bufReader = mszReaderName;
1497 if (*pcchReaderLen > dwReaderLen)
1500 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1505 dwAtrLen = *pcbAtrLen;
1511 bufAtr = malloc(dwAtrLen);
1517 *(LPBYTE *)pbAtr = bufAtr;
1524 if (*pcbAtrLen > dwAtrLen)
1527 memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1531 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1637 DWORD dwBreakFlag = 0;
1640 int currentReaderCount = 0;
1644 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1646 for (j=0; j<cReaders; j++)
1648 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1649 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1653 if ((rgReaderStates == NULL && cReaders > 0)
1661 for (j = 0; j < cReaders; j++)
1663 if (rgReaderStates[j].szReader == NULL)
1670 int nbNonIgnoredReaders = cReaders;
1672 for (j=0; j<cReaders; j++)
1674 nbNonIgnoredReaders--;
1676 if (0 == nbNonIgnoredReaders)
1693 if (NULL == currentContextMap)
1700 rv = getReaderStates(currentContextMap);
1705 for (j=0; j<cReaders; j++)
1707 const char *readerName;
1710 readerName = rgReaderStates[j].szReader;
1713 if (strcmp(readerName, readerStates[i].readerName) == 0)
1718 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1721 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1730 for (j = 0; j < cReaders; j++)
1731 rgReaderStates[j].dwEventState = 0;
1734 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1738 if (readerStates[j].readerName[0] !=
'\0')
1739 currentReaderCount++;
1742 if ((DWORD)-1 == dwTimeout)
1752 currReader = &rgReaderStates[j];
1757 const char *readerName;
1761 readerName = currReader->szReader;
1764 if (strcmp(readerName, readerStates[i].readerName) == 0)
1769 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1772 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1774 int k, newReaderCount = 0;
1777 if (readerStates[k].readerName[0] !=
'\0')
1780 if (newReaderCount != currentReaderCount)
1782 Log1(PCSC_LOG_INFO,
"Reader list changed");
1783 currentReaderCount = newReaderCount;
1791 currReader->dwEventState =
1807 uint32_t readerState;
1814 Log0(PCSC_LOG_DEBUG);
1819 rContext = &readerStates[i];
1825 if (currReader->dwCurrentState & 0xFFFF0000)
1827 unsigned int currentCounter;
1829 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1835 Log0(PCSC_LOG_DEBUG);
1841 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1853 Log0(PCSC_LOG_DEBUG);
1862 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1864 Log0(PCSC_LOG_DEBUG);
1878 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1882 currReader->cbAtr = 0;
1901 Log0(PCSC_LOG_DEBUG);
1906 else if (readerState & SCARD_PRESENT)
1919 Log0(PCSC_LOG_DEBUG);
1929 Log0(PCSC_LOG_DEBUG);
1939 Log0(PCSC_LOG_DEBUG);
1953 Log0(PCSC_LOG_DEBUG);
1960 if (readerState & SCARD_PRESENT)
1967 Log0(PCSC_LOG_DEBUG);
1980 Log0(PCSC_LOG_DEBUG);
1983 else if (currReader-> dwCurrentState
1987 Log0(PCSC_LOG_DEBUG);
1999 Log0(PCSC_LOG_DEBUG);
2015 if (dwBreakFlag == 1)
2021 struct timeval before, after;
2023 gettimeofday(&before, NULL);
2025 waitStatusStruct.
timeOut = dwTime;
2033 sizeof(waitStatusStruct), &waitStatusStruct);
2042 &waitStatusStruct,
sizeof(waitStatusStruct),
2054 sizeof(waitStatusStruct), &waitStatusStruct);
2061 sizeof(waitStatusStruct),
2074 rv = waitStatusStruct.rv;
2079 rv = getReaderStates(currentContextMap);
2087 gettimeofday(&after, NULL);
2089 dwTime -= diff/1000;
2109 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2111 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2116 for (j=0; j<cReaders; j++)
2118 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2119 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2177 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2178 LPDWORD lpBytesReturned)
2188 if (NULL != lpBytesReturned)
2189 *lpBytesReturned = 0;
2194 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2209 scControlStruct.hCard = hCard;
2210 scControlStruct.dwControlCode = dwControlCode;
2211 scControlStruct.cbSendLength = cbSendLength;
2212 scControlStruct.cbRecvLength = cbRecvLength;
2213 scControlStruct.dwBytesReturned = 0;
2214 scControlStruct.rv = 0;
2217 sizeof(scControlStruct), &scControlStruct);
2223 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2224 currentContextMap->dwClientID);
2233 currentContextMap->dwClientID);
2241 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2242 currentContextMap->dwClientID);
2249 if (NULL != lpBytesReturned)
2250 *lpBytesReturned = scControlStruct.dwBytesReturned;
2252 rv = scControlStruct.rv;
2255 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2370 unsigned char *buf = NULL;
2374 if (NULL == pcbAttrLen)
2386 buf = malloc(*pcbAttrLen);
2393 *(
unsigned char **)pbAttr = buf;
2456 if (NULL == pbAttr || 0 == cbAttrLen)
2467 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2468 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2478 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2489 scGetSetStruct.hCard = hCard;
2490 scGetSetStruct.dwAttrId = dwAttrId;
2491 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2493 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2495 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2498 sizeof(scGetSetStruct), &scGetSetStruct);
2507 currentContextMap->dwClientID);
2517 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2519 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2523 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2526 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2528 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2530 rv = scGetSetStruct.rv;
2533 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2597 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2599 LPDWORD pcbRecvLength)
2608 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2609 pcbRecvLength == NULL || pioSendPci == NULL)
2618 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2634 scTransmitStruct.hCard = hCard;
2635 scTransmitStruct.cbSendLength = cbSendLength;
2636 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2637 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2638 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2643 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2644 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2653 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2659 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2677 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2685 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2686 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2690 rv = scTransmitStruct.rv;
2694 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2699 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2702 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2763 LPSTR mszReaders, LPDWORD pcchReaders)
2765 DWORD dwReadersLen = 0;
2773 API_TRACE_IN(
"%ld", hContext)
2778 if (pcchReaders == NULL)
2785 if (NULL == currentContextMap)
2792 rv = getReaderStates(currentContextMap);
2798 if (readerStates[i].readerName[0] !=
'\0')
2799 dwReadersLen += strlen(readerStates[i].readerName) + 1;
2804 if (1 == dwReadersLen)
2812 if (NULL == mszReaders)
2817 buf = malloc(dwReadersLen);
2823 *(
char **)mszReaders = buf;
2830 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2837 if (mszReaders == NULL)
2842 if (readerStates[i].readerName[0] !=
'\0')
2847 strcpy(buf, readerStates[i].readerName);
2848 buf += strlen(readerStates[i].readerName)+1;
2855 *pcchReaders = dwReadersLen;
2857 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2860 API_TRACE_OUT(
"%d", *pcchReaders)
2889 if (NULL == currentContextMap)
2892 free((
void *)pvMem);
2960 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
2961 const unsigned int dwGroups =
sizeof(ReaderGroup);
2967 if (NULL == currentContextMap)
2972 if (NULL == mszGroups)
2977 buf = malloc(dwGroups);
2983 *(
char **)mszGroups = buf;
2989 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
2997 memcpy(buf, ReaderGroup, dwGroups);
3000 *pcchGroups = dwGroups;
3002 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3042 uint32_t dwClientID = 0;
3046 API_TRACE_IN(
"%ld", hContext)
3052 if (NULL == currentContextMap)
3058 if (! currentContextMap->cancellable)
3071 scCancelStruct.hContext = hContext;
3075 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3083 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3088 rv = scCancelStruct.rv;
3128 API_TRACE_IN(
"%ld", hContext)
3136 if (currentContextMap == NULL)
3167 if (NULL == newContextMap)
3170 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3171 newContextMap->
hContext = hContext;
3175 (void)pthread_mutex_init(&newContextMap->
mMutex, NULL);
3177 lrv = list_init(&newContextMap->channelMapList);
3180 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3184 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3185 CHANNEL_MAP_seeker);
3188 Log2(PCSC_LOG_CRITICAL,
3189 "list_attributes_seeker failed with return value: %d", lrv);
3190 list_destroy(&newContextMap->channelMapList);
3194 lrv = list_append(&contextMapList, newContextMap);
3197 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3199 list_destroy(&newContextMap->channelMapList);
3207 (void)pthread_mutex_destroy(&newContextMap->
mMutex);
3208 free(newContextMap);
3233 if (lock && NULL != currentContextMap)
3234 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
3238 return currentContextMap;
3255 return list_seek(&contextMapList, &hContext);
3272 if (NULL == currentContextMap)
3275 return SCardCleanContext(currentContextMap);
3278 static LONG SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3280 int list_index, lrv;
3287 (void)pthread_mutex_destroy(&targetContextMap->
mMutex);
3289 listSize = list_size(&targetContextMap->channelMapList);
3290 for (list_index = 0; list_index < listSize; list_index++)
3292 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3294 if (NULL == currentChannelMap)
3296 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3302 free(currentChannelMap->readerName);
3303 free(currentChannelMap);
3307 list_destroy(&targetContextMap->channelMapList);
3309 lrv = list_delete(&contextMapList, targetContextMap);
3312 Log2(PCSC_LOG_CRITICAL,
3313 "list_delete failed with return value: %d", lrv);
3316 free(targetContextMap);
3332 if (NULL == newChannelMap)
3335 newChannelMap->hCard = hCard;
3336 newChannelMap->readerName = strdup(readerName);
3338 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3341 free(newChannelMap->readerName);
3342 free(newChannelMap);
3343 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3358 rv = SCardGetContextAndChannelFromHandleTH(hCard, ¤tContextMap,
3359 ¤tChannelMap);
3363 free(currentChannelMap->readerName);
3365 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3368 Log2(PCSC_LOG_CRITICAL,
3369 "list_delete failed with return value: %d", lrv);
3372 free(currentChannelMap);
3377 static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE hCard,
3386 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3390 (void)pthread_mutex_lock(&(*targetContextMap)->mMutex);
3397 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3406 *targetContextMap = NULL;
3407 *targetChannelMap = NULL;
3409 listSize = list_size(&contextMapList);
3411 for (list_index = 0; list_index < listSize; list_index++)
3413 currentContextMap = list_get_at(&contextMapList, list_index);
3414 if (currentContextMap == NULL)
3416 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3420 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3422 if (currentChannelMap != NULL)
3424 *targetContextMap = currentContextMap;
3425 *targetChannelMap = currentChannelMap;
3443 struct stat statBuffer;
3446 socketName = getSocketName();
3447 rv = stat(socketName, &statBuffer);
3451 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3452 socketName, strerror(errno));
3459 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3461 int32_t dwClientID = currentContextMap->
dwClientID;
3469 rv =
MessageReceive(&readerStates,
sizeof(readerStates), dwClientID);
used by SCardBeginTransaction()
contained in SCARD_CONNECT Messages.
uint32_t cardAtrLength
ATR length.
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()
static SCONTEXTMAP * SCardGetAndLockContext(SCARDCONTEXT, int)
Get the index from the Application Context vector _psContextMap for the passed context.
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.
#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.