108#include <sys/types.h>
138static bool sharing_shall_block =
true;
140#define COLOR_RED "\33[01;31m"
141#define COLOR_GREEN "\33[32m"
142#define COLOR_BLUE "\33[34m"
143#define COLOR_MAGENTA "\33[35m"
144#define COLOR_NORMAL "\33[0m"
151static void trace(
const char *func,
const char direction,
const char *fmt, ...)
155 fprintf(stderr, COLOR_GREEN
"%c " COLOR_BLUE
"[%lX] " COLOR_GREEN
"%s ",
156 direction, pthread_self(), func);
158 fprintf(stderr, COLOR_MAGENTA);
160 vfprintf(stderr, fmt, args);
163 fprintf(stderr, COLOR_NORMAL
"\n");
166#define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__);
167#define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__);
169#define API_TRACE_IN(...)
170#define API_TRACE_OUT(...)
175#define PROFILE_FILE "/tmp/pcsc_profile"
181pthread_t threads[MAX_THREADS];
182struct timeval profile_time_start[MAX_THREADS];
186#define PROFILE_START profile_start();
187#define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
189static void profile_start(
void)
191 static bool initialized =
false;
200 sprintf(filename,
"%s-%d", PROFILE_FILE, getuid());
201 profile_fd = fopen(filename,
"a+");
202 if (NULL == profile_fd)
204 fprintf(stderr, COLOR_RED
"Can't open %s: %s" COLOR_NORMAL
"\n",
205 PROFILE_FILE, strerror(errno));
208 fprintf(profile_fd,
"\nStart a new profile\n");
210 if (isatty(fileno(stderr)))
217 for (i=0; i<MAX_THREADS; i++)
218 if (pthread_equal(0, threads[i]))
224 gettimeofday(&profile_time_start[i], NULL);
227static void profile_end(
const char *f, LONG rv)
229 struct timeval profile_time_end;
234 gettimeofday(&profile_time_end, NULL);
237 for (i=0; i<MAX_THREADS; i++)
238 if (pthread_equal(t, threads[i]))
243 fprintf(stderr, COLOR_BLUE
" WARNING: no start info for %s\n", f);
247 d =
time_sub(&profile_time_end, &profile_time_start[i]);
256 COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld "
257 COLOR_BLUE
"0x%08lX %s" COLOR_NORMAL
"\n",
258 f, d, rv, pcsc_stringify_error(rv));
260 fprintf(stderr, COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld"
261 COLOR_NORMAL
"\n", f, d);
263 fprintf(profile_fd,
"%s %ld\n", f, d);
269#define PROFILE_END(rv)
284static int CHANNEL_MAP_seeker(
const void *el,
const void *key)
288 if ((el == NULL) || (key == NULL))
290 Log3(PCSC_LOG_CRITICAL,
291 "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
322static list_t contextMapList;
324static int SCONTEXTMAP_seeker(
const void *el,
const void *key)
328 if ((el == NULL) || (key == NULL))
330 Log3(PCSC_LOG_CRITICAL,
331 "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
346static pthread_once_t init_lib_control = PTHREAD_ONCE_INIT;
359static pthread_mutex_t readerStatesMutex = PTHREAD_MUTEX_INITIALIZER;
376static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE,
378static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
382static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
383 LPBYTE pbAttr, LPDWORD pcbAttrLen);
385static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
386static LONG getReaderStatesAndRegisterForEvents(
SCONTEXTMAP * currentContextMap);
387static LONG unregisterFromEvents(
SCONTEXTMAP * currentContextMap);
430 return currentContextMap != NULL;
471LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
472 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
476 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
486 pvReserved2, phContext);
491 API_TRACE_OUT(
"%ld", *phContext)
497DESTRUCTOR
static void destructor(
void)
499 list_destroy(&contextMapList);
507static void init_lib(
void)
514 lrv = list_init(&contextMapList);
517 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
522 lrv = list_attributes_seeker(&contextMapList,
526 Log2(PCSC_LOG_CRITICAL,
527 "list_attributes_seeker failed with return value: %d", lrv);
528 list_destroy(&contextMapList);
532 if (getenv(
"PCSCLITE_NO_BLOCKING"))
534 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
535 sharing_shall_block =
false;
570 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
574 uint32_t dwClientID = 0;
578 if (phContext == NULL)
583 pthread_once(&init_lib_control, init_lib);
609 Log1(PCSC_LOG_CRITICAL,
610 "Your pcscd is too old and does not support CMD_VERSION");
614 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
628 scEstablishStruct.dwScope = dwScope;
629 scEstablishStruct.hContext = 0;
633 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
641 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
649 rv = scEstablishStruct.rv;
659 *phContext = scEstablishStruct.hContext;
701 API_TRACE_IN(
"%ld", hContext)
709 if (NULL == currentContextMap)
715 scReleaseStruct.hContext = hContext;
719 currentContextMap->dwClientID,
720 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
729 currentContextMap->dwClientID);
734 rv = scReleaseStruct.rv;
736 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
808 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
809 LPDWORD pdwActiveProtocol)
816 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
821 if (phCard == NULL || pdwActiveProtocol == NULL)
826 if (szReader == NULL)
832 if (strlen(szReader) > MAX_READERNAME)
839 if (NULL == currentContextMap)
842 memset(scConnectStruct.szReader, 0,
sizeof scConnectStruct.szReader);
843 strncpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
844 scConnectStruct.szReader[
sizeof scConnectStruct.szReader -1] =
'\0';
846 scConnectStruct.hContext = hContext;
847 scConnectStruct.dwShareMode = dwShareMode;
848 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
849 scConnectStruct.hCard = 0;
850 scConnectStruct.dwActiveProtocol = 0;
854 sizeof(scConnectStruct), (
void *) &scConnectStruct);
863 currentContextMap->dwClientID);
868 *phCard = scConnectStruct.hCard;
869 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
876 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
879 rv = scConnectStruct.rv;
882 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
885 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
963 DWORD dwPreferredProtocols, DWORD dwInitialization,
964 LPDWORD pdwActiveProtocol)
972 API_TRACE_IN(
"%ld %ld %ld", hCard, dwShareMode, dwPreferredProtocols)
974 if (pdwActiveProtocol == NULL)
983 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
988 scReconnectStruct.hCard = hCard;
989 scReconnectStruct.dwShareMode = dwShareMode;
990 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
991 scReconnectStruct.dwInitialization = dwInitialization;
992 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
996 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
1004 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
1005 currentContextMap->dwClientID);
1010 rv = scReconnectStruct.rv;
1014 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1019 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
1022 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1025 API_TRACE_OUT(
"%ld", *pdwActiveProtocol)
1069 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1074 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1082 scDisconnectStruct.hCard = hCard;
1083 scDisconnectStruct.dwDisposition = dwDisposition;
1087 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1095 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1096 currentContextMap->dwClientID);
1102 SCardRemoveHandle(hCard);
1103 rv = scDisconnectStruct.rv;
1106 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1160 API_TRACE_IN(
"%ld", hCard)
1172 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1177 scBeginStruct.hCard = hCard;
1181 currentContextMap->dwClientID,
1182 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1191 currentContextMap->dwClientID);
1196 rv = scBeginStruct.rv;
1201 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1205 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1260 API_TRACE_IN(
"%ld", hCard)
1265 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1270 scEndStruct.hCard = hCard;
1271 scEndStruct.dwDisposition = dwDisposition;
1275 currentContextMap->dwClientID,
1276 sizeof(scEndStruct), (
void *) &scEndStruct);
1285 currentContextMap->dwClientID);
1290 rv = scEndStruct.rv;
1293 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1397 LPDWORD pcchReaderLen, LPDWORD pdwState,
1398 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1400 DWORD dwReaderLen, dwAtrLen;
1407 char *bufReader = NULL;
1408 LPBYTE bufAtr = NULL;
1421 if (pcchReaderLen == NULL)
1422 pcchReaderLen = &dummy;
1424 if (pcbAtrLen == NULL)
1428 dwReaderLen = *pcchReaderLen;
1429 dwAtrLen = *pcbAtrLen;
1440 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1446 (void)pthread_mutex_lock(&readerStatesMutex);
1449 rv = getReaderStates(currentContextMap);
1453 r = pChannelMap->readerName;
1468 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1469 scStatusStruct.hCard = hCard;
1472 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1481 currentContextMap->dwClientID);
1486 rv = scStatusStruct.rv;
1490 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1491 (void)pthread_mutex_unlock(&readerStatesMutex);
1508 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1519 dwReaderLen = *pcchReaderLen;
1520 if (NULL == szReaderName)
1525 bufReader = malloc(dwReaderLen);
1526 if (NULL == bufReader)
1531 *(
char **)szReaderName = bufReader;
1534 bufReader = szReaderName;
1539 if (*pcchReaderLen > dwReaderLen)
1542 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1547 dwAtrLen = *pcbAtrLen;
1553 bufAtr = malloc(dwAtrLen);
1559 *(LPBYTE *)pbAtr = bufAtr;
1566 if (*pcbAtrLen > dwAtrLen)
1569 memcpy(bufAtr,
readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1573 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1574 (void)pthread_mutex_unlock(&readerStatesMutex);
1694 DWORD dwBreakFlag = 0;
1697 int currentReaderCount = 0;
1701 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1703 for (j=0; j<cReaders; j++)
1705 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1706 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1710 if ((rgReaderStates == NULL && cReaders > 0)
1718 for (j = 0; j < cReaders; j++)
1720 if (rgReaderStates[j].szReader == NULL)
1727 int nbNonIgnoredReaders = cReaders;
1729 for (j=0; j<cReaders; j++)
1731 nbNonIgnoredReaders--;
1733 if (0 == nbNonIgnoredReaders)
1750 if (NULL == currentContextMap)
1757 (void)pthread_mutex_lock(&readerStatesMutex);
1760 rv = getReaderStatesAndRegisterForEvents(currentContextMap);
1764 (void)pthread_mutex_unlock(&readerStatesMutex);
1769 for (j=0; j<cReaders; j++)
1771 const char *readerName;
1774 readerName = rgReaderStates[j].szReader;
1777 if (strcmp(readerName,
readerStates[i].readerName) == 0)
1785 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1788 (void)pthread_mutex_unlock(&readerStatesMutex);
1793 (void)pthread_mutex_unlock(&readerStatesMutex);
1796 for (j = 0; j < cReaders; j++)
1797 rgReaderStates[j].dwEventState = 0;
1800 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1805 currentReaderCount++;
1808 if ((DWORD)-1 == dwTimeout)
1818 currReader = &rgReaderStates[j];
1823 const char *readerName;
1827 (void)pthread_mutex_lock(&readerStatesMutex);
1830 readerName = currReader->szReader;
1833 if (strcmp(readerName,
readerStates[i].readerName) == 0)
1841 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1843 int k, newReaderCount = 0;
1849 if (newReaderCount != currentReaderCount)
1851 Log1(PCSC_LOG_INFO,
"Reader list changed");
1852 currentReaderCount = newReaderCount;
1860 currReader->dwEventState =
1876 uint32_t readerState;
1882 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1883 Log0(PCSC_LOG_DEBUG);
1894 if (currReader->dwCurrentState & 0xFFFF0000)
1896 unsigned int currentCounter;
1898 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1904 Log0(PCSC_LOG_DEBUG);
1910 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1922 Log0(PCSC_LOG_DEBUG);
1931 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1933 Log0(PCSC_LOG_DEBUG);
1941#ifndef DISABLE_AUTO_POWER_ON
1949 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1953 currReader->cbAtr = 0;
1959 currReader->dwEventState &= ~SCARD_STATE_PRESENT;
1960 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1961 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1962 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1963 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1964 currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
1965 currReader->dwEventState &= ~SCARD_STATE_MUTE;
1966 currReader->dwEventState &= ~SCARD_STATE_INUSE;
1972 Log0(PCSC_LOG_DEBUG);
1980 currReader->dwEventState &= ~SCARD_STATE_EMPTY;
1981 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1982 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1983 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1984 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1985 currReader->dwEventState &= ~SCARD_STATE_MUTE;
1990 Log0(PCSC_LOG_DEBUG);
2000 Log0(PCSC_LOG_DEBUG);
2010 Log0(PCSC_LOG_DEBUG);
2020 currReader->dwEventState &= ~SCARD_STATE_INUSE;
2024 Log0(PCSC_LOG_DEBUG);
2034 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2038 Log0(PCSC_LOG_DEBUG);
2045 currReader->dwEventState &= ~SCARD_STATE_INUSE;
2046 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2051 Log0(PCSC_LOG_DEBUG);
2054 else if (currReader-> dwCurrentState
2058 Log0(PCSC_LOG_DEBUG);
2070 Log0(PCSC_LOG_DEBUG);
2075 (void)pthread_mutex_unlock(&readerStatesMutex);
2088 if (dwBreakFlag == 1)
2094 struct timeval before, after;
2096 gettimeofday(&before, NULL);
2107 &waitStatusStruct,
sizeof(waitStatusStruct),
2118 rv = unregisterFromEvents(currentContextMap);
2127 rv = waitStatusStruct.rv;
2132 (void)pthread_mutex_lock(&readerStatesMutex);
2133 rv = getReaderStatesAndRegisterForEvents(currentContextMap);
2134 (void)pthread_mutex_unlock(&readerStatesMutex);
2142 gettimeofday(&after, NULL);
2144 dwTime -= diff/1000;
2164 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2169 (void)unregisterFromEvents(currentContextMap);
2171 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2176 for (j=0; j<cReaders; j++)
2178 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2179 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2236LONG SCardControl(
SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
2237 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2238 LPDWORD lpBytesReturned)
2248 if (NULL != lpBytesReturned)
2249 *lpBytesReturned = 0;
2254 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2268 scControlStruct.hCard = hCard;
2269 scControlStruct.dwControlCode = dwControlCode;
2270 scControlStruct.cbSendLength = cbSendLength;
2271 scControlStruct.cbRecvLength = cbRecvLength;
2272 scControlStruct.dwBytesReturned = 0;
2273 scControlStruct.rv = 0;
2276 sizeof(scControlStruct), &scControlStruct);
2282 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2283 currentContextMap->dwClientID);
2292 currentContextMap->dwClientID);
2299 if (scControlStruct.dwBytesReturned > cbRecvLength)
2301 if (NULL != lpBytesReturned)
2302 *lpBytesReturned = scControlStruct.dwBytesReturned;
2308 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2309 currentContextMap->dwClientID);
2316 if (NULL != lpBytesReturned)
2317 *lpBytesReturned = scControlStruct.dwBytesReturned;
2319 rv = scControlStruct.rv;
2322 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2451 unsigned char *buf = NULL;
2455 if (NULL == pcbAttrLen)
2467 buf = malloc(*pcbAttrLen);
2474 *(
unsigned char **)pbAttr = buf;
2537 if (NULL == pbAttr || 0 == cbAttrLen)
2548static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2549 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2559 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2570 scGetSetStruct.hCard = hCard;
2571 scGetSetStruct.dwAttrId = dwAttrId;
2573 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2576 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2577 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2581 scGetSetStruct.cbAttrLen =
sizeof scGetSetStruct.pbAttr;
2584 sizeof(scGetSetStruct), &scGetSetStruct);
2593 currentContextMap->dwClientID);
2603 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2607 DWORD correct_value = scGetSetStruct.cbAttrLen;
2608 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2609 *pcbAttrLen = correct_value;
2614 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2617 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2619 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2621 rv = scGetSetStruct.rv;
2624 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2688 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2690 LPDWORD pcbRecvLength)
2699 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2700 pcbRecvLength == NULL || pioSendPci == NULL)
2709 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2724 scTransmitStruct.hCard = hCard;
2725 scTransmitStruct.cbSendLength = cbSendLength;
2726 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2727 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2728 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2733 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2734 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2743 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2749 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2766 if (scTransmitStruct.pcbRecvLength > *pcbRecvLength)
2768 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2774 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2782 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2783 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2787 rv = scTransmitStruct.rv;
2791 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2796 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2799 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2869 LPSTR mszReaders, LPDWORD pcchReaders)
2871 DWORD dwReadersLen = 0;
2879 API_TRACE_IN(
"%ld", hContext)
2884 if (pcchReaders == NULL)
2891 if (NULL == currentContextMap)
2898 (void)pthread_mutex_lock(&readerStatesMutex);
2901 rv = getReaderStates(currentContextMap);
2908 dwReadersLen += strlen(
readerStates[i].readerName) + 1;
2913 if (1 == dwReadersLen)
2921 if (NULL == mszReaders)
2926 buf = malloc(dwReadersLen);
2932 *(
char **)mszReaders = buf;
2939 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2946 if (mszReaders == NULL)
2964 *pcchReaders = dwReadersLen;
2966 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2967 (void)pthread_mutex_unlock(&readerStatesMutex);
2970 API_TRACE_OUT(
"%d", *pcchReaders)
3000 free((
void *)pvMem);
3068 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
3069 const unsigned int dwGroups =
sizeof(ReaderGroup);
3075 if (NULL == currentContextMap)
3080 if (NULL == mszGroups)
3085 buf = malloc(dwGroups);
3091 *(
char **)mszGroups = buf;
3097 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3105 memcpy(buf, ReaderGroup, dwGroups);
3108 *pcchGroups = dwGroups;
3110 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3152 uint32_t dwClientID = 0;
3157 API_TRACE_IN(
"%ld", hContext)
3165 if (NULL == currentContextMap)
3187 scCancelStruct.hContext = hContext;
3191 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3199 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3204 rv = scCancelStruct.rv;
3243 API_TRACE_IN(
"%ld", hContext)
3281 if (NULL == newContextMap)
3284 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3285 newContextMap->
hContext = hContext;
3289 (void)pthread_mutex_init(&newContextMap->
mMutex, NULL);
3291 lrv = list_init(&newContextMap->channelMapList);
3294 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3298 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3299 CHANNEL_MAP_seeker);
3302 Log2(PCSC_LOG_CRITICAL,
3303 "list_attributes_seeker failed with return value: %d", lrv);
3304 list_destroy(&newContextMap->channelMapList);
3308 lrv = list_append(&contextMapList, newContextMap);
3311 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3313 list_destroy(&newContextMap->channelMapList);
3321 (void)pthread_mutex_destroy(&newContextMap->
mMutex);
3322 free(newContextMap);
3351 if (NULL != currentContextMap)
3352 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
3356 return currentContextMap;
3373 return list_seek(&contextMapList, &hContext);
3387 if (NULL != currentContextMap)
3388 SCardCleanContext(currentContextMap);
3391static void SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3393 int list_index, lrv;
3400 (void)pthread_mutex_destroy(&targetContextMap->
mMutex);
3402 listSize = list_size(&targetContextMap->channelMapList);
3403 for (list_index = 0; list_index < listSize; list_index++)
3405 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3407 if (NULL == currentChannelMap)
3409 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3415 free(currentChannelMap->readerName);
3416 free(currentChannelMap);
3420 list_destroy(&targetContextMap->channelMapList);
3422 lrv = list_delete(&contextMapList, targetContextMap);
3425 Log2(PCSC_LOG_CRITICAL,
3426 "list_delete failed with return value: %d", lrv);
3429 free(targetContextMap);
3445 if (NULL == newChannelMap)
3448 newChannelMap->hCard = hCard;
3449 newChannelMap->readerName = strdup(readerName);
3451 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3454 free(newChannelMap->readerName);
3455 free(newChannelMap);
3456 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3471 rv = SCardGetContextAndChannelFromHandleTH(hCard, ¤tContextMap,
3472 ¤tChannelMap);
3476 free(currentChannelMap->readerName);
3478 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3481 Log2(PCSC_LOG_CRITICAL,
3482 "list_delete failed with return value: %d", lrv);
3485 free(currentChannelMap);
3490static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE hCard,
3499 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3503 (void)pthread_mutex_lock(&(*targetContextMap)->mMutex);
3510static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3519 *targetContextMap = NULL;
3520 *targetChannelMap = NULL;
3522 listSize = list_size(&contextMapList);
3524 for (list_index = 0; list_index < listSize; list_index++)
3526 currentContextMap = list_get_at(&contextMapList, list_index);
3527 if (currentContextMap == NULL)
3529 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3533 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3535 if (currentChannelMap != NULL)
3537 *targetContextMap = currentContextMap;
3538 *targetChannelMap = currentChannelMap;
3556 struct stat statBuffer;
3559 socketName = getSocketName();
3560 rv = stat(socketName, &statBuffer);
3564 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3565 socketName, strerror(errno));
3572static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3574 int32_t dwClientID = currentContextMap->
dwClientID;
3589static LONG getReaderStatesAndRegisterForEvents(
SCONTEXTMAP * currentContextMap)
3591 int32_t dwClientID = currentContextMap->
dwClientID;
3605static LONG unregisterFromEvents(
SCONTEXTMAP * currentContextMap)
3607 int32_t dwClientID = currentContextMap->
dwClientID;
3613 dwClientID, 0, NULL);
3630 rv = waitStatusStruct.rv;
This handles card insertion/removal events, updates ATR, protocol, and status information.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
#define PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
#define SCARD_E_CANCELLED
The action was cancelled by an SCardCancel request.
#define SCARD_S_SUCCESS
No error was encountered.
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
#define SCARD_E_NO_READERS_AVAILABLE
Cannot find a smart card reader.
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
#define SCARD_E_TIMEOUT
The user-specified timeout value has expired.
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
#define SCARD_E_NO_SERVICE
The Smart card resource manager is not running.
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
This keeps a list of defines for pcsc-lite.
#define PCSCLITE_STATUS_POLL_RATE
Status polling rate.
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
#define SCARD_STATE_IGNORE
Ignore this reader.
#define SCARD_SWALLOWED
Card not powered.
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
#define SCARD_PROTOCOL_T1
T=1 active protocol.
#define SCARD_PRESENT
Card is present.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
#define SCARD_STATE_INUSE
Shared Mode.
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
#define SCARD_STATE_UNAVAILABLE
Status unavailable.
#define SCARD_STATE_PRESENT
Card inserted.
#define SCARD_ABSENT
Card is absent.
#define SCARD_UNKNOWN
Unknown state.
#define SCARD_STATE_UNKNOWN
Reader unknown.
#define INFINITE
Infinite timeout.
#define SCARD_STATE_EMPTY
Card removed.
#define SCARD_PROTOCOL_RAW
Raw active protocol.
#define SCARD_STATE_MUTE
Unresponsive card.
#define SCARD_STATE_CHANGED
State has changed.
#define SCARD_PROTOCOL_ANY
IFD determines prot.
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
#define MAX_BUFFER_SIZE_EXTENDED
enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer
#define SCARD_STATE_EXCLUSIVE
Exclusive Mode.
#define SCARD_STATE_UNAWARE
App wants status.
LONG SCARDHANDLE
hCard returned by SCardConnect()
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
This keeps track of a list of currently available reader structures.
Protocol Control Information (PCI)
unsigned long dwProtocol
Protocol identifier.
unsigned long cbPciLength
Protocol Control Inf Length.
Represents an Application Context Channel.
Represents an Application Context on the Client side.
pthread_mutex_t mMutex
Mutex for this context.
SCARDCONTEXT hContext
Application Context ID.
DWORD dwClientID
Client Connection ID.
bool cancellable
We are in a cancellable call.
contained in SCARD_BEGIN_TRANSACTION Messages.
contained in SCARD_CANCEL Messages.
contained in SCARD_CONNECT Messages.
contained in SCARD_CONTROL Messages.
contained in SCARD_DISCONNECT Messages.
contained in SCARD_END_TRANSACTION Messages.
Information contained in SCARD_ESTABLISH_CONTEXT Messages.
contained in SCARD_GET_ATTRIB and Messages.
Define an exported public reader state structure so each application gets instant notification of cha...
_Atomic int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
uint32_t eventCounter
number of card events
_Atomic uint32_t cardAtrLength
ATR length.
uint32_t readerState
SCARD_* bit field.
contained in SCARD_RECONNECT Messages.
Information contained in SCARD_RELEASE_CONTEXT Messages.
contained in SCARD_STATUS Messages.
contained in SCARD_TRANSMIT Messages.
Information transmitted in CMD_VERSION Messages.
int32_t major
IPC major PROTOCOL_VERSION_MAJOR.
int32_t minor
IPC minor PROTOCOL_VERSION_MINOR.
Information contained in CMD_WAIT_READER_STATE_CHANGE Messages.
This handles abstract system level calls.
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
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
This handles smart card reader communications.
static bool isExecuted
Make sure the initialization code is executed only once.
static void SCardLockThread(void)
Locks a mutex so another thread must wait to use this function.
static void SCardRemoveContext(SCARDCONTEXT)
Removes an Application Context from a control vector.
static SCONTEXTMAP * SCardGetAndLockContext(SCARDCONTEXT)
Get the SCONTEXTMAP * from the Application Context vector _psContextMap for the passed context.
static bool SCardGetContextValidity(SCARDCONTEXT hContext)
Tell if a context index from the Application Context vector _psContextMap is valid or not.
static void SCardUnlockThread(void)
Unlocks a mutex so another thread may use the client.
static pthread_mutex_t clientMutex
Ensure that some functions be accessed in thread-safe mode.
LONG SCardCheckDaemonAvailability(void)
Checks if the server is running.
static SCONTEXTMAP * SCardGetContextTH(SCARDCONTEXT)
Get the address from the Application Context list _psContextMap for the passed context.
static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT)
Creates a communication context to the PC/SC Resource Manager.
PCSC_API const SCARD_IO_REQUEST g_rgSCardRawPci
Protocol Control Information for raw access.
static LONG SCardAddContext(SCARDCONTEXT, DWORD)
Functions for managing instances of SCardEstablishContext() These functions keep track of Context han...
PCSC_API const SCARD_IO_REQUEST g_rgSCardT1Pci
Protocol Control Information for T=1.
static READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]
Area used to read status information about the readers.
PCSC_API const SCARD_IO_REQUEST g_rgSCardT0Pci
Protocol Control Information for T=0.
INTERNAL int ClientSetupSession(uint32_t *pdwClientID)
Prepares a communication channel for the client to talk to the server.
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 response from the server or vice-versa.
INTERNAL LONG MessageSendWithHeader(uint32_t command, uint32_t dwClientID, uint64_t size, void *data_void)
Wrapper for the MessageSend() function.
INTERNAL LONG MessageSend(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Sends a menssage from client to server or vice-versa.
INTERNAL void ClientCloseSession(uint32_t dwClientID)
Closes the socket used by the client to communicate with the server.
INTERNAL LONG MessageReceive(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Called by the Client to get the response from the server or vice-versa.
This defines some structures and #defines to be used over the transport layer.
#define PROTOCOL_VERSION_MAJOR
Major version of the current message protocol.
#define PROTOCOL_VERSION_MINOR
Minor version of the current message protocol.
@ SCARD_DISCONNECT
used by SCardDisconnect()
@ SCARD_SET_ATTRIB
used by SCardSetAttrib()
@ SCARD_RELEASE_CONTEXT
used by SCardReleaseContext()
@ CMD_STOP_WAITING_READER_STATE_CHANGE
stop waiting for a reader state change
@ CMD_GET_READERS_STATE
get the readers state
@ SCARD_CONTROL
used by SCardControl()
@ CMD_VERSION
get the client/server protocol version
@ CMD_WAIT_READER_STATE_CHANGE
wait for a reader state change
@ SCARD_RECONNECT
used by SCardReconnect()
@ SCARD_STATUS
used by SCardStatus()
@ SCARD_GET_ATTRIB
used by SCardGetAttrib()
@ SCARD_BEGIN_TRANSACTION
used by SCardBeginTransaction()
@ SCARD_TRANSMIT
used by SCardTransmit()
@ SCARD_END_TRANSACTION
used by SCardEndTransaction()
@ SCARD_CANCEL
used by SCardCancel()
@ SCARD_CONNECT
used by SCardConnect()
@ SCARD_ESTABLISH_CONTEXT
used by SCardEstablishContext()