107 #include <sys/types.h> 113 #include <sys/time.h> 115 #include <sys/wait.h> 137 #define SCARD_PROTOCOL_ANY_OLD 0x1000 144 static char sharing_shall_block = TRUE;
146 #define COLOR_RED "\33[01;31m" 147 #define COLOR_GREEN "\33[32m" 148 #define COLOR_BLUE "\33[34m" 149 #define COLOR_MAGENTA "\33[35m" 150 #define COLOR_NORMAL "\33[0m" 157 static void trace(
const char *func,
const char direction,
const char *fmt, ...)
161 fprintf(stderr, COLOR_GREEN
"%c " COLOR_BLUE
"[%lX] " COLOR_GREEN
"%s ",
162 direction, pthread_self(), func);
164 fprintf(stderr, COLOR_MAGENTA);
166 vfprintf(stderr, fmt, args);
169 fprintf(stderr, COLOR_NORMAL
"\n");
172 #define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__); 173 #define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__); 175 #define API_TRACE_IN(...) 176 #define API_TRACE_OUT(...) 181 #define PROFILE_FILE "/tmp/pcsc_profile" 183 #include <sys/time.h> 186 #define MAX_THREADS 5 187 pthread_t threads[MAX_THREADS];
188 struct timeval profile_time_start[MAX_THREADS];
192 #define PROFILE_START profile_start(); 193 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv); 195 static void profile_start(
void)
197 static char initialized = FALSE;
206 sprintf(filename,
"%s-%d", PROFILE_FILE, getuid());
207 profile_fd = fopen(filename,
"a+");
208 if (NULL == profile_fd)
210 fprintf(stderr, COLOR_RED
"Can't open %s: %s" COLOR_NORMAL
"\n",
211 PROFILE_FILE, strerror(errno));
214 fprintf(profile_fd,
"\nStart a new profile\n");
216 if (isatty(fileno(stderr)))
223 for (i=0; i<MAX_THREADS; i++)
224 if (pthread_equal(0, threads[i]))
230 gettimeofday(&profile_time_start[i], NULL);
233 static void profile_end(
const char *f, LONG rv)
235 struct timeval profile_time_end;
240 gettimeofday(&profile_time_end, NULL);
243 for (i=0; i<MAX_THREADS; i++)
244 if (pthread_equal(t, threads[i]))
249 fprintf(stderr, COLOR_BLUE
" WARNING: no start info for %s\n", f);
253 d =
time_sub(&profile_time_end, &profile_time_start[i]);
262 COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld " 263 COLOR_BLUE
"0x%08lX %s" COLOR_NORMAL
"\n",
266 fprintf(stderr, COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld" 267 COLOR_NORMAL
"\n", f, d);
269 fprintf(profile_fd,
"%s %ld\n", f, d);
274 #define PROFILE_START 275 #define PROFILE_END(rv) 290 static int CHANNEL_MAP_seeker(
const void *el,
const void *key)
292 const CHANNEL_MAP * channelMap = el;
294 if ((el == NULL) || (key == NULL))
296 Log3(PCSC_LOG_CRITICAL,
297 "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
323 static list_t contextMapList;
325 static int SCONTEXTMAP_seeker(
const void *el,
const void *key)
329 if ((el == NULL) || (key == NULL))
331 Log3(PCSC_LOG_CRITICAL,
332 "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
375 static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE,
377 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
381 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
382 LPBYTE pbAttr, LPDWORD pcbAttrLen);
384 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
397 return pthread_mutex_lock(&clientMutex);
407 return pthread_mutex_unlock(&clientMutex);
447 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
451 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
461 pvReserved2, phContext);
466 API_TRACE_OUT(
"%ld", *phContext)
499 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
503 uint32_t dwClientID = 0;
507 if (phContext == NULL)
524 lrv = list_init(&contextMapList);
527 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
532 lrv = list_attributes_seeker(&contextMapList,
536 Log2(PCSC_LOG_CRITICAL,
537 "list_attributes_seeker failed with return value: %d", lrv);
538 list_destroy(&contextMapList);
542 if (getenv(
"PCSCLITE_NO_BLOCKING"))
544 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
545 sharing_shall_block = FALSE;
574 Log1(PCSC_LOG_CRITICAL,
575 "Your pcscd is too old and does not support CMD_VERSION");
579 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
590 scEstablishStruct.dwScope = dwScope;
591 scEstablishStruct.hContext = 0;
595 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
603 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
610 return scEstablishStruct.rv;
618 *phContext = scEstablishStruct.hContext;
655 API_TRACE_IN(
"%ld", hContext)
663 if (NULL == currentContextMap)
669 scReleaseStruct.hContext = hContext;
673 currentContextMap->dwClientID,
674 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
683 currentContextMap->dwClientID);
688 rv = scReleaseStruct.rv;
690 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
763 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
764 LPDWORD pdwActiveProtocol)
771 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
776 if (phCard == NULL || pdwActiveProtocol == NULL)
781 if (szReader == NULL)
787 if (strlen(szReader) > MAX_READERNAME)
794 if (NULL == currentContextMap)
797 strncpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
798 scConnectStruct.szReader[
sizeof scConnectStruct.szReader -1] =
'\0';
800 scConnectStruct.hContext = hContext;
801 scConnectStruct.dwShareMode = dwShareMode;
802 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
803 scConnectStruct.hCard = 0;
804 scConnectStruct.dwActiveProtocol = 0;
808 sizeof(scConnectStruct), (
void *) &scConnectStruct);
817 currentContextMap->dwClientID);
822 *phCard = scConnectStruct.hCard;
823 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
830 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
833 rv = scConnectStruct.rv;
836 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
839 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
918 DWORD dwPreferredProtocols, DWORD dwInitialization,
919 LPDWORD pdwActiveProtocol)
924 CHANNEL_MAP * pChannelMap;
927 API_TRACE_IN(
"%ld %ld %ld", hCard, dwShareMode, dwPreferredProtocols)
929 if (pdwActiveProtocol == NULL)
938 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
943 scReconnectStruct.hCard = hCard;
944 scReconnectStruct.dwShareMode = dwShareMode;
945 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
946 scReconnectStruct.dwInitialization = dwInitialization;
947 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
951 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
959 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
960 currentContextMap->dwClientID);
965 rv = scReconnectStruct.rv;
969 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
974 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
977 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
980 API_TRACE_OUT(
"%ld", *pdwActiveProtocol)
1021 CHANNEL_MAP * pChannelMap;
1024 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1029 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1037 scDisconnectStruct.hCard = hCard;
1038 scDisconnectStruct.dwDisposition = dwDisposition;
1042 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1050 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1051 currentContextMap->dwClientID);
1057 (void)SCardRemoveHandle(hCard);
1058 rv = scDisconnectStruct.rv;
1061 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1111 CHANNEL_MAP * pChannelMap;
1114 API_TRACE_IN(
"%ld", hCard)
1126 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1131 scBeginStruct.hCard = hCard;
1135 currentContextMap->dwClientID,
1136 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1145 currentContextMap->dwClientID);
1150 rv = scBeginStruct.rv;
1155 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1159 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1212 CHANNEL_MAP * pChannelMap;
1215 API_TRACE_IN(
"%ld", hCard)
1220 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1225 scEndStruct.hCard = hCard;
1226 scEndStruct.dwDisposition = dwDisposition;
1231 sizeof(scEndStruct), (
void *) &scEndStruct);
1248 randnum = SYS_RandomInt(1000, 10000);
1250 rv = scEndStruct.rv;
1253 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
1357 LPDWORD pcchReaderLen, LPDWORD pdwState,
1358 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1360 DWORD dwReaderLen, dwAtrLen;
1365 CHANNEL_MAP * pChannelMap;
1367 char *bufReader = NULL;
1368 LPBYTE bufAtr = NULL;
1381 if (pcchReaderLen == NULL)
1382 pcchReaderLen = &dummy;
1384 if (pcbAtrLen == NULL)
1388 dwReaderLen = *pcchReaderLen;
1389 dwAtrLen = *pcbAtrLen;
1400 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1406 rv = getReaderStates(currentContextMap);
1410 r = pChannelMap->readerName;
1414 if (r && strcmp(r, readerStates[i].readerName) == 0)
1418 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1425 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1426 scStatusStruct.hCard = hCard;
1429 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1438 currentContextMap->dwClientID);
1443 rv = scStatusStruct.rv;
1447 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1464 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1468 *pdwState = (readerStates[i].
eventCounter << 16) + readerStates[i].readerState;
1475 dwReaderLen = *pcchReaderLen;
1476 if (NULL == mszReaderName)
1481 bufReader = malloc(dwReaderLen);
1482 if (NULL == bufReader)
1487 *(
char **)mszReaderName = bufReader;
1490 bufReader = mszReaderName;
1495 if (*pcchReaderLen > dwReaderLen)
1498 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1503 dwAtrLen = *pcbAtrLen;
1509 bufAtr = malloc(dwAtrLen);
1515 *(LPBYTE *)pbAtr = bufAtr;
1522 if (*pcbAtrLen > dwAtrLen)
1525 memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1529 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1635 DWORD dwBreakFlag = 0;
1638 int currentReaderCount = 0;
1642 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1644 for (j=0; j<cReaders; j++)
1646 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1647 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1651 if ((rgReaderStates == NULL && cReaders > 0)
1659 for (j = 0; j < cReaders; j++)
1661 if (rgReaderStates[j].szReader == NULL)
1668 int nbNonIgnoredReaders = cReaders;
1670 for (j=0; j<cReaders; j++)
1672 nbNonIgnoredReaders--;
1674 if (0 == nbNonIgnoredReaders)
1691 if (NULL == currentContextMap)
1698 rv = getReaderStates(currentContextMap);
1703 for (j=0; j<cReaders; j++)
1705 const char *readerName;
1708 readerName = rgReaderStates[j].szReader;
1711 if (strcmp(readerName, readerStates[i].readerName) == 0)
1716 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1719 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1728 for (j = 0; j < cReaders; j++)
1729 rgReaderStates[j].dwEventState = 0;
1732 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1736 if (readerStates[j].readerName[0] !=
'\0')
1737 currentReaderCount++;
1740 if ((DWORD)-1 == dwTimeout)
1750 currReader = &rgReaderStates[j];
1755 const char *readerName;
1759 readerName = currReader->szReader;
1762 if (strcmp(readerName, readerStates[i].readerName) == 0)
1767 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1770 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1772 int k, newReaderCount = 0;
1775 if (readerStates[k].readerName[0] !=
'\0')
1778 if (newReaderCount != currentReaderCount)
1780 Log1(PCSC_LOG_INFO,
"Reader list changed");
1781 currentReaderCount = newReaderCount;
1789 currReader->dwEventState =
1805 uint32_t readerState;
1812 Log0(PCSC_LOG_DEBUG);
1817 rContext = &readerStates[i];
1823 if (currReader->dwCurrentState & 0xFFFF0000)
1825 unsigned int currentCounter;
1827 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1833 Log0(PCSC_LOG_DEBUG);
1839 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1851 Log0(PCSC_LOG_DEBUG);
1860 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1862 Log0(PCSC_LOG_DEBUG);
1876 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1880 currReader->cbAtr = 0;
1899 Log0(PCSC_LOG_DEBUG);
1904 else if (readerState & SCARD_PRESENT)
1917 Log0(PCSC_LOG_DEBUG);
1927 Log0(PCSC_LOG_DEBUG);
1937 Log0(PCSC_LOG_DEBUG);
1951 Log0(PCSC_LOG_DEBUG);
1958 if (readerState & SCARD_PRESENT)
1965 Log0(PCSC_LOG_DEBUG);
1978 Log0(PCSC_LOG_DEBUG);
1981 else if (currReader-> dwCurrentState
1985 Log0(PCSC_LOG_DEBUG);
1997 Log0(PCSC_LOG_DEBUG);
2013 if (dwBreakFlag == 1)
2019 struct timeval before, after;
2021 gettimeofday(&before, NULL);
2023 waitStatusStruct.
timeOut = dwTime;
2031 sizeof(waitStatusStruct), &waitStatusStruct);
2040 &waitStatusStruct,
sizeof(waitStatusStruct),
2052 sizeof(waitStatusStruct), &waitStatusStruct);
2059 sizeof(waitStatusStruct),
2072 rv = waitStatusStruct.rv;
2077 rv = getReaderStates(currentContextMap);
2085 gettimeofday(&after, NULL);
2087 dwTime -= diff/1000;
2107 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2109 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2114 for (j=0; j<cReaders; j++)
2116 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2117 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2175 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2176 LPDWORD lpBytesReturned)
2181 CHANNEL_MAP * pChannelMap;
2186 if (NULL != lpBytesReturned)
2187 *lpBytesReturned = 0;
2192 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2207 scControlStruct.hCard = hCard;
2208 scControlStruct.dwControlCode = dwControlCode;
2209 scControlStruct.cbSendLength = cbSendLength;
2210 scControlStruct.cbRecvLength = cbRecvLength;
2211 scControlStruct.dwBytesReturned = 0;
2212 scControlStruct.rv = 0;
2215 sizeof(scControlStruct), &scControlStruct);
2221 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2222 currentContextMap->dwClientID);
2231 currentContextMap->dwClientID);
2239 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2240 currentContextMap->dwClientID);
2247 if (NULL != lpBytesReturned)
2248 *lpBytesReturned = scControlStruct.dwBytesReturned;
2250 rv = scControlStruct.rv;
2253 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2368 unsigned char *buf = NULL;
2372 if (NULL == pcbAttrLen)
2384 buf = malloc(*pcbAttrLen);
2391 *(
unsigned char **)pbAttr = buf;
2454 if (NULL == pbAttr || 0 == cbAttrLen)
2465 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2466 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2471 CHANNEL_MAP * pChannelMap;
2476 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2487 scGetSetStruct.hCard = hCard;
2488 scGetSetStruct.dwAttrId = dwAttrId;
2489 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2491 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2493 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2496 sizeof(scGetSetStruct), &scGetSetStruct);
2505 currentContextMap->dwClientID);
2515 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2517 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2521 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2524 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2526 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2528 rv = scGetSetStruct.rv;
2531 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2595 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2597 LPDWORD pcbRecvLength)
2601 CHANNEL_MAP * pChannelMap;
2606 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2607 pcbRecvLength == NULL || pioSendPci == NULL)
2616 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2632 scTransmitStruct.hCard = hCard;
2633 scTransmitStruct.cbSendLength = cbSendLength;
2634 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2635 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2636 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2641 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2642 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2651 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2657 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2675 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2683 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2684 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2688 rv = scTransmitStruct.rv;
2692 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2697 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2700 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2761 LPSTR mszReaders, LPDWORD pcchReaders)
2763 DWORD dwReadersLen = 0;
2771 API_TRACE_IN(
"%ld", hContext)
2776 if (pcchReaders == NULL)
2783 if (NULL == currentContextMap)
2790 rv = getReaderStates(currentContextMap);
2796 if (readerStates[i].readerName[0] !=
'\0')
2797 dwReadersLen += strlen(readerStates[i].readerName) + 1;
2802 if (1 == dwReadersLen)
2810 if (NULL == mszReaders)
2815 buf = malloc(dwReadersLen);
2821 *(
char **)mszReaders = buf;
2828 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2835 if (mszReaders == NULL)
2840 if (readerStates[i].readerName[0] !=
'\0')
2845 strcpy(buf, readerStates[i].readerName);
2846 buf += strlen(readerStates[i].readerName)+1;
2853 *pcchReaders = dwReadersLen;
2855 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2858 API_TRACE_OUT(
"%d", *pcchReaders)
2887 if (NULL == currentContextMap)
2890 free((
void *)pvMem);
2958 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
2959 const unsigned int dwGroups =
sizeof(ReaderGroup);
2965 if (NULL == currentContextMap)
2970 if (NULL == mszGroups)
2975 buf = malloc(dwGroups);
2981 *(
char **)mszGroups = buf;
2987 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
2995 memcpy(buf, ReaderGroup, dwGroups);
2998 *pcchGroups = dwGroups;
3000 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3040 uint32_t dwClientID = 0;
3044 API_TRACE_IN(
"%ld", hContext)
3050 if (NULL == currentContextMap)
3056 if (! currentContextMap->cancellable)
3069 scCancelStruct.hContext = hContext;
3073 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3081 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3086 rv = scCancelStruct.rv;
3126 API_TRACE_IN(
"%ld", hContext)
3134 if (currentContextMap == NULL)
3165 if (NULL == newContextMap)
3168 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3169 newContextMap->
hContext = hContext;
3173 (void)pthread_mutex_init(&newContextMap->
mMutex, NULL);
3175 lrv = list_init(&newContextMap->channelMapList);
3178 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3182 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3183 CHANNEL_MAP_seeker);
3186 Log2(PCSC_LOG_CRITICAL,
3187 "list_attributes_seeker failed with return value: %d", lrv);
3188 list_destroy(&newContextMap->channelMapList);
3192 lrv = list_append(&contextMapList, newContextMap);
3195 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3197 list_destroy(&newContextMap->channelMapList);
3205 (void)pthread_mutex_destroy(&newContextMap->
mMutex);
3206 free(newContextMap);
3232 if (lock && NULL != currentContextMap)
3233 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
3237 return currentContextMap;
3254 return list_seek(&contextMapList, &hContext);
3271 if (NULL == currentContextMap)
3274 return SCardCleanContext(currentContextMap);
3277 static LONG SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3279 int list_index, lrv;
3281 CHANNEL_MAP * currentChannelMap;
3286 (void)pthread_mutex_destroy(&targetContextMap->
mMutex);
3288 listSize = list_size(&targetContextMap->channelMapList);
3289 for (list_index = 0; list_index < listSize; list_index++)
3291 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3293 if (NULL == currentChannelMap)
3295 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3301 free(currentChannelMap->readerName);
3302 free(currentChannelMap);
3306 list_destroy(&targetContextMap->channelMapList);
3308 lrv = list_delete(&contextMapList, targetContextMap);
3311 Log2(PCSC_LOG_CRITICAL,
3312 "list_delete failed with return value: %d", lrv);
3315 free(targetContextMap);
3327 CHANNEL_MAP * newChannelMap;
3330 newChannelMap = malloc(
sizeof(CHANNEL_MAP));
3331 if (NULL == newChannelMap)
3334 newChannelMap->hCard = hCard;
3335 newChannelMap->readerName = strdup(readerName);
3337 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3340 free(newChannelMap->readerName);
3341 free(newChannelMap);
3342 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3353 CHANNEL_MAP * currentChannelMap;
3357 rv = SCardGetContextAndChannelFromHandleTH(hCard, ¤tContextMap,
3358 ¤tChannelMap);
3362 free(currentChannelMap->readerName);
3364 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3367 Log2(PCSC_LOG_CRITICAL,
3368 "list_delete failed with return value: %d", lrv);
3371 free(currentChannelMap);
3376 static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE hCard,
3377 SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
3385 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3389 (void)pthread_mutex_lock(&(*targetContextMap)->mMutex);
3396 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3397 SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
3402 CHANNEL_MAP * currentChannelMap;
3405 *targetContextMap = NULL;
3406 *targetChannelMap = NULL;
3408 listSize = list_size(&contextMapList);
3410 for (list_index = 0; list_index < listSize; list_index++)
3412 currentContextMap = list_get_at(&contextMapList, list_index);
3413 if (currentContextMap == NULL)
3415 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3419 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3421 if (currentChannelMap != NULL)
3423 *targetContextMap = currentContextMap;
3424 *targetChannelMap = currentChannelMap;
3442 struct stat statBuffer;
3445 socketName = getSocketName();
3446 rv = stat(socketName, &statBuffer);
3450 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3451 socketName, strerror(errno));
3458 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3460 int32_t dwClientID = currentContextMap->
dwClientID;
3468 rv =
MessageReceive(&readerStates,
sizeof(readerStates), dwClientID);
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
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.
#define SCARD_S_SUCCESS
No error was encountered.
contained in SCARD_END_TRANSACTION Messages.
#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_E_TIMEOUT
The user-specified timeout value has expired.
#define SCARD_STATE_EMPTY
Card removed.
#define SCARD_E_NO_SERVICE
The Smart card resource manager is not running.
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_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
#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.
#define SCARD_E_NO_READERS_AVAILABLE
Cannot find a smart card reader.
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.
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_STATE_CHANGED
State has changed.
This handles abstract system level calls.
static LONG SCardRemoveContext(SCARDCONTEXT)
Removes an Application Context from a control vector.
uint32_t eventCounter
number of card events
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...
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.
#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_NO_MEMORY
Not enough memory available to complete this command.
contained in SCARD_STATUS Messages.
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
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.
#define SCARD_F_COMM_ERROR
An internal communications error has been detected.
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.
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
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_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...
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
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()
contained in SCARD_CONTROL Messages.
This keeps track of a list of currently available reader structures.
static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT)
Creates a communication context to the PC/SC Resource Manager.
pthread_mutex_t mMutex
Mutex for this context.
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
static pthread_mutex_t clientMutex
Ensure that some functions be accessed in thread-safe mode.
uint32_t readerState
SCARD_* bit field.
#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_INVALID_HANDLE
The supplied handle was invalid.
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_STATE_UNAWARE
App wants status.
#define SCARD_STATE_MUTE
Unresponsive card.