81 #include <sys/types.h> 112 #define SCARD_PROTOCOL_ANY_OLD 0x1000 119 static char sharing_shall_block = TRUE;
121 #define COLOR_RED "\33[01;31m" 122 #define COLOR_GREEN "\33[32m" 123 #define COLOR_BLUE "\33[34m" 124 #define COLOR_MAGENTA "\33[35m" 125 #define COLOR_NORMAL "\33[0m" 132 static void trace(
const char *func,
const char direction,
const char *fmt, ...)
136 fprintf(stderr, COLOR_GREEN
"%c " COLOR_BLUE
"[%lX] " COLOR_GREEN
"%s ",
137 direction, pthread_self(), func);
139 fprintf(stderr, COLOR_MAGENTA);
141 vfprintf(stderr, fmt, args);
144 fprintf(stderr, COLOR_NORMAL
"\n");
147 #define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__); 148 #define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__); 150 #define API_TRACE_IN(...) 151 #define API_TRACE_OUT(...) 156 #define PROFILE_FILE "/tmp/pcsc_profile" 158 #include <sys/time.h> 161 #define MAX_THREADS 5 162 pthread_t threads[MAX_THREADS];
163 struct timeval profile_time_start[MAX_THREADS];
167 #define PROFILE_START profile_start(); 168 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv); 170 static void profile_start(
void)
172 static char initialized = FALSE;
181 sprintf(filename,
"%s-%d", PROFILE_FILE, getuid());
182 profile_fd = fopen(filename,
"a+");
183 if (NULL == profile_fd)
185 fprintf(stderr, COLOR_RED
"Can't open %s: %s" COLOR_NORMAL
"\n",
186 PROFILE_FILE, strerror(errno));
189 fprintf(profile_fd,
"\nStart a new profile\n");
191 if (isatty(fileno(stderr)))
198 for (i=0; i<MAX_THREADS; i++)
199 if (pthread_equal(0, threads[i]))
205 gettimeofday(&profile_time_start[i], NULL);
208 static void profile_end(
const char *f, LONG rv)
210 struct timeval profile_time_end;
215 gettimeofday(&profile_time_end, NULL);
218 for (i=0; i<MAX_THREADS; i++)
219 if (pthread_equal(t, threads[i]))
224 fprintf(stderr, COLOR_BLUE
" WARNING: no start info for %s\n", f);
228 d =
time_sub(&profile_time_end, &profile_time_start[i]);
237 COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld " 238 COLOR_BLUE
"0x%08lX %s" COLOR_NORMAL
"\n",
241 fprintf(stderr, COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld" 242 COLOR_NORMAL
"\n", f, d);
244 fprintf(profile_fd,
"%s %ld\n", f, d);
249 #define PROFILE_START 250 #define PROFILE_END(rv) 265 static int CHANNEL_MAP_seeker(
const void *el,
const void *key)
267 const CHANNEL_MAP * channelMap = el;
269 if ((el == NULL) || (key == NULL))
271 Log3(PCSC_LOG_CRITICAL,
272 "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
298 static list_t contextMapList;
300 static int SCONTEXTMAP_seeker(
const void *el,
const void *key)
304 if ((el == NULL) || (key == NULL))
306 Log3(PCSC_LOG_CRITICAL,
307 "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
350 static LONG SCardGetContextAndChannelFromHandle(
SCARDHANDLE,
352 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
356 static void SCardInvalidateHandles(
void);
357 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
358 LPBYTE pbAttr, LPDWORD pcbAttrLen);
360 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
373 return pthread_mutex_lock(&clientMutex);
383 return pthread_mutex_unlock(&clientMutex);
423 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
426 static int first_time = TRUE;
428 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
437 pthread_atfork(NULL, NULL, SCardInvalidateHandles);
451 pvReserved2, phContext);
456 API_TRACE_OUT(
"%ld", *phContext)
489 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
493 uint32_t dwClientID = 0;
497 if (phContext == NULL)
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;
564 Log1(PCSC_LOG_CRITICAL,
565 "Your pcscd is too old and does not support CMD_VERSION");
569 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
580 scEstablishStruct.dwScope = dwScope;
581 scEstablishStruct.hContext = 0;
585 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
593 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
600 return scEstablishStruct.rv;
608 *phContext = scEstablishStruct.hContext;
645 API_TRACE_IN(
"%ld", hContext)
653 if (NULL == currentContextMap)
659 (void)pthread_mutex_lock(currentContextMap->mMutex);
663 if (NULL == currentContextMap)
672 scReleaseStruct.hContext = hContext;
676 currentContextMap->dwClientID,
677 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
686 currentContextMap->dwClientID);
691 rv = scReleaseStruct.rv;
693 (void)pthread_mutex_unlock(currentContextMap->mMutex);
766 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
767 LPDWORD pdwActiveProtocol)
774 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
779 if (phCard == NULL || pdwActiveProtocol == NULL)
784 if (szReader == NULL)
790 if (strlen(szReader) > MAX_READERNAME)
797 if (NULL == currentContextMap)
800 (void)pthread_mutex_lock(currentContextMap->mMutex);
804 if (NULL == currentContextMap)
810 strlcpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
812 scConnectStruct.hContext = hContext;
813 scConnectStruct.dwShareMode = dwShareMode;
814 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
815 scConnectStruct.hCard = 0;
816 scConnectStruct.dwActiveProtocol = 0;
820 sizeof(scConnectStruct), (
void *) &scConnectStruct);
829 currentContextMap->dwClientID);
834 *phCard = scConnectStruct.hCard;
835 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
842 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
845 rv = scConnectStruct.rv;
848 (void)pthread_mutex_unlock(currentContextMap->mMutex);
851 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
930 DWORD dwPreferredProtocols, DWORD dwInitialization,
931 LPDWORD pdwActiveProtocol)
936 CHANNEL_MAP * pChannelMap;
940 if (pdwActiveProtocol == NULL)
946 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
954 (void)pthread_mutex_lock(currentContextMap->mMutex);
957 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
965 scReconnectStruct.hCard = hCard;
966 scReconnectStruct.dwShareMode = dwShareMode;
967 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
968 scReconnectStruct.dwInitialization = dwInitialization;
969 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
973 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
981 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
982 currentContextMap->dwClientID);
987 rv = scReconnectStruct.rv;
991 (void)pthread_mutex_unlock(currentContextMap->mMutex);
996 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
999 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1042 CHANNEL_MAP * pChannelMap;
1045 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1050 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1058 (void)pthread_mutex_lock(currentContextMap->mMutex);
1061 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1072 scDisconnectStruct.hCard = hCard;
1073 scDisconnectStruct.dwDisposition = dwDisposition;
1077 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1085 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1086 currentContextMap->dwClientID);
1092 (void)SCardRemoveHandle(hCard);
1093 rv = scDisconnectStruct.rv;
1096 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1146 CHANNEL_MAP * pChannelMap;
1153 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1165 (void)pthread_mutex_lock(currentContextMap->mMutex);
1168 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1176 scBeginStruct.hCard = hCard;
1180 currentContextMap->dwClientID,
1181 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1190 currentContextMap->dwClientID);
1195 rv = scBeginStruct.rv;
1200 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1204 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1257 CHANNEL_MAP * pChannelMap;
1264 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1269 (void)pthread_mutex_lock(currentContextMap->
mMutex);
1272 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1280 scEndStruct.hCard = hCard;
1281 scEndStruct.dwDisposition = dwDisposition;
1286 sizeof(scEndStruct), (
void *) &scEndStruct);
1303 randnum = SYS_RandomInt(1000, 10000);
1305 rv = scEndStruct.rv;
1308 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
1411 LPDWORD pcchReaderLen, LPDWORD pdwState,
1412 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1414 DWORD dwReaderLen, dwAtrLen;
1419 CHANNEL_MAP * pChannelMap;
1421 char *bufReader = NULL;
1422 LPBYTE bufAtr = NULL;
1435 if (pcchReaderLen == NULL)
1436 pcchReaderLen = &dummy;
1438 if (pcbAtrLen == NULL)
1442 dwReaderLen = *pcchReaderLen;
1443 dwAtrLen = *pcbAtrLen;
1451 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1459 (void)pthread_mutex_lock(currentContextMap->mMutex);
1462 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1471 rv = getReaderStates(currentContextMap);
1475 r = pChannelMap->readerName;
1479 if (r && strcmp(r, readerStates[i].readerName) == 0)
1483 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1490 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1491 scStatusStruct.hCard = hCard;
1494 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1503 currentContextMap->dwClientID);
1508 rv = scStatusStruct.rv;
1512 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1529 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1533 *pdwState = (readerStates[i].
eventCounter << 16) + readerStates[i].readerState;
1540 dwReaderLen = *pcchReaderLen;
1541 bufReader = malloc(dwReaderLen);
1542 if (NULL == bufReader)
1547 if (NULL == mszReaderName)
1552 *(
char **)mszReaderName = bufReader;
1555 bufReader = mszReaderName;
1560 if (*pcchReaderLen > dwReaderLen)
1563 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1568 dwAtrLen = *pcbAtrLen;
1569 bufAtr = malloc(dwAtrLen);
1580 *(LPBYTE *)pbAtr = bufAtr;
1587 if (*pcbAtrLen > dwAtrLen)
1590 memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1594 (void)pthread_mutex_unlock(currentContextMap->mMutex);
1700 DWORD dwBreakFlag = 0;
1703 int currentReaderCount = 0;
1707 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1709 for (j=0; j<cReaders; j++)
1711 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1712 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1716 if ((rgReaderStates == NULL && cReaders > 0)
1724 for (j = 0; j < cReaders; j++)
1726 if (rgReaderStates[j].szReader == NULL)
1733 int nbNonIgnoredReaders = cReaders;
1735 for (j=0; j<cReaders; j++)
1737 nbNonIgnoredReaders--;
1739 if (0 == nbNonIgnoredReaders)
1756 if (NULL == currentContextMap)
1762 (void)pthread_mutex_lock(currentContextMap->
mMutex);
1766 if (NULL == currentContextMap)
1776 rv = getReaderStates(currentContextMap);
1781 for (j=0; j<cReaders; j++)
1783 const char *readerName;
1786 readerName = rgReaderStates[j].szReader;
1789 if (strcmp(readerName, readerStates[i].readerName) == 0)
1794 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1797 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1806 for (j = 0; j < cReaders; j++)
1807 rgReaderStates[j].dwEventState = 0;
1810 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1814 if (readerStates[j].readerName[0] !=
'\0')
1815 currentReaderCount++;
1818 if ((DWORD)-1 == dwTimeout)
1828 currReader = &rgReaderStates[j];
1833 const char *readerName;
1837 readerName = currReader->szReader;
1840 if (strcmp(readerName, readerStates[i].readerName) == 0)
1845 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1848 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1850 int k, newReaderCount = 0;
1853 if (readerStates[k].readerName[0] !=
'\0')
1856 if (newReaderCount != currentReaderCount)
1858 Log1(PCSC_LOG_INFO,
"Reader list changed");
1859 currentReaderCount = newReaderCount;
1867 currReader->dwEventState =
1883 uint32_t readerState;
1890 Log0(PCSC_LOG_DEBUG);
1895 rContext = &readerStates[i];
1901 if (currReader->dwCurrentState & 0xFFFF0000)
1903 unsigned int currentCounter;
1905 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1911 Log0(PCSC_LOG_DEBUG);
1917 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1929 Log0(PCSC_LOG_DEBUG);
1938 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1940 Log0(PCSC_LOG_DEBUG);
1954 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1958 currReader->cbAtr = 0;
1977 Log0(PCSC_LOG_DEBUG);
1982 else if (readerState & SCARD_PRESENT)
1995 Log0(PCSC_LOG_DEBUG);
2005 Log0(PCSC_LOG_DEBUG);
2015 Log0(PCSC_LOG_DEBUG);
2029 Log0(PCSC_LOG_DEBUG);
2036 if (readerState & SCARD_PRESENT)
2043 Log0(PCSC_LOG_DEBUG);
2056 Log0(PCSC_LOG_DEBUG);
2059 else if (currReader-> dwCurrentState
2063 Log0(PCSC_LOG_DEBUG);
2075 Log0(PCSC_LOG_DEBUG);
2091 if (dwBreakFlag == 1)
2097 struct timeval before, after;
2099 gettimeofday(&before, NULL);
2101 waitStatusStruct.
timeOut = dwTime;
2109 sizeof(waitStatusStruct), &waitStatusStruct);
2118 &waitStatusStruct,
sizeof(waitStatusStruct),
2130 sizeof(waitStatusStruct), &waitStatusStruct);
2137 sizeof(waitStatusStruct),
2150 rv = waitStatusStruct.rv;
2155 rv = getReaderStates(currentContextMap);
2163 gettimeofday(&after, NULL);
2165 dwTime -= diff/1000;
2185 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2187 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
2192 for (j=0; j<cReaders; j++)
2194 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2195 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2253 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2254 LPDWORD lpBytesReturned)
2259 CHANNEL_MAP * pChannelMap;
2264 if (NULL != lpBytesReturned)
2265 *lpBytesReturned = 0;
2270 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2278 (void)pthread_mutex_lock(currentContextMap->mMutex);
2281 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2296 scControlStruct.hCard = hCard;
2297 scControlStruct.dwControlCode = dwControlCode;
2298 scControlStruct.cbSendLength = cbSendLength;
2299 scControlStruct.cbRecvLength = cbRecvLength;
2300 scControlStruct.dwBytesReturned = 0;
2301 scControlStruct.rv = 0;
2304 sizeof(scControlStruct), &scControlStruct);
2310 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2311 currentContextMap->dwClientID);
2320 currentContextMap->dwClientID);
2328 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2329 currentContextMap->dwClientID);
2336 if (NULL != lpBytesReturned)
2337 *lpBytesReturned = scControlStruct.dwBytesReturned;
2339 rv = scControlStruct.rv;
2342 (void)pthread_mutex_unlock(currentContextMap->mMutex);
2457 unsigned char *buf = NULL;
2461 if (NULL == pcbAttrLen)
2473 buf = malloc(*pcbAttrLen);
2480 *(
unsigned char **)pbAttr = buf;
2543 if (NULL == pbAttr || 0 == cbAttrLen)
2554 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2555 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2560 CHANNEL_MAP * pChannelMap;
2565 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2570 (void)pthread_mutex_lock(currentContextMap->mMutex);
2573 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2587 scGetSetStruct.hCard = hCard;
2588 scGetSetStruct.dwAttrId = dwAttrId;
2589 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2591 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2593 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2596 sizeof(scGetSetStruct), &scGetSetStruct);
2605 currentContextMap->dwClientID);
2615 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2617 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2621 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2624 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2626 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2628 rv = scGetSetStruct.rv;
2631 (void)pthread_mutex_unlock(currentContextMap->mMutex);
2695 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2697 LPDWORD pcbRecvLength)
2701 CHANNEL_MAP * pChannelMap;
2706 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2707 pcbRecvLength == NULL || pioSendPci == NULL)
2713 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2725 (void)pthread_mutex_lock(currentContextMap->
mMutex);
2728 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2743 scTransmitStruct.hCard = hCard;
2744 scTransmitStruct.cbSendLength = cbSendLength;
2745 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2746 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2747 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2752 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2753 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2762 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2768 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2786 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2794 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2795 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2799 rv = scTransmitStruct.rv;
2803 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
2808 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2811 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
2869 LPSTR mszReaders, LPDWORD pcchReaders)
2871 DWORD dwReadersLen = 0;
2879 API_TRACE_IN(
"%ld", hContext)
2884 if (pcchReaders == NULL)
2891 if (NULL == currentContextMap)
2897 (void)pthread_mutex_lock(currentContextMap->
mMutex);
2901 if (NULL == currentContextMap)
2908 rv = getReaderStates(currentContextMap);
2914 if (readerStates[i].readerName[0] !=
'\0')
2915 dwReadersLen += strlen(readerStates[i].readerName) + 1;
2920 if (1 == dwReadersLen)
2928 buf = malloc(dwReadersLen);
2934 if (NULL == mszReaders)
2939 *(
char **)mszReaders = buf;
2946 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2953 if (mszReaders == NULL)
2958 if (readerStates[i].readerName[0] !=
'\0')
2963 strcpy(buf, readerStates[i].readerName);
2964 buf += strlen(readerStates[i].readerName)+1;
2971 *pcchReaders = dwReadersLen;
2973 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
2976 API_TRACE_OUT(
"%d", *pcchReaders)
3005 if (NULL == currentContextMap)
3008 free((
void *)pvMem);
3076 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
3077 const unsigned int dwGroups =
sizeof(ReaderGroup);
3083 if (NULL == currentContextMap)
3086 (void)pthread_mutex_lock(currentContextMap->
mMutex);
3090 if (NULL == currentContextMap)
3098 buf = malloc(dwGroups);
3104 if (NULL == mszGroups)
3109 *(
char **)mszGroups = buf;
3115 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3123 memcpy(buf, ReaderGroup, dwGroups);
3126 *pcchGroups = dwGroups;
3128 (void)pthread_mutex_unlock(currentContextMap->
mMutex);
3168 uint32_t dwClientID = 0;
3172 API_TRACE_IN(
"%ld", hContext)
3178 if (NULL == currentContextMap)
3184 if (! currentContextMap->cancellable)
3197 scCancelStruct.hContext = hContext;
3201 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3209 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3214 rv = scCancelStruct.rv;
3254 API_TRACE_IN(
"%ld", hContext)
3262 if (currentContextMap == NULL)
3293 if (NULL == newContextMap)
3296 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3297 newContextMap->
hContext = hContext;
3301 newContextMap->
mMutex = malloc(
sizeof(pthread_mutex_t));
3302 if (NULL == newContextMap->
mMutex)
3304 Log2(PCSC_LOG_DEBUG,
"Freeing SCONTEXTMAP @%p", newContextMap);
3305 free(newContextMap);
3308 (void)pthread_mutex_init(newContextMap->
mMutex, NULL);
3310 lrv = list_init(&newContextMap->channelMapList);
3313 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3317 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3318 CHANNEL_MAP_seeker);
3321 Log2(PCSC_LOG_CRITICAL,
3322 "list_attributes_seeker failed with return value: %d", lrv);
3323 list_destroy(&newContextMap->channelMapList);
3327 lrv = list_append(&contextMapList, newContextMap);
3330 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3332 list_destroy(&newContextMap->channelMapList);
3340 (void)pthread_mutex_destroy(newContextMap->
mMutex);
3341 free(newContextMap->
mMutex);
3342 free(newContextMap);
3367 return currentContextMap;
3384 return list_seek(&contextMapList, &hContext);
3401 if (NULL == currentContextMap)
3404 return SCardCleanContext(currentContextMap);
3407 static LONG SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3409 int list_index, lrv;
3411 CHANNEL_MAP * currentChannelMap;
3416 (void)pthread_mutex_destroy(targetContextMap->
mMutex);
3417 free(targetContextMap->
mMutex);
3418 targetContextMap->
mMutex = NULL;
3420 listSize = list_size(&targetContextMap->channelMapList);
3421 for (list_index = 0; list_index < listSize; list_index++)
3423 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3425 if (NULL == currentChannelMap)
3427 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3433 free(currentChannelMap->readerName);
3434 free(currentChannelMap);
3438 list_destroy(&targetContextMap->channelMapList);
3440 lrv = list_delete(&contextMapList, targetContextMap);
3443 Log2(PCSC_LOG_CRITICAL,
3444 "list_delete failed with return value: %d", lrv);
3447 free(targetContextMap);
3459 CHANNEL_MAP * newChannelMap;
3462 newChannelMap = malloc(
sizeof(CHANNEL_MAP));
3463 if (NULL == newChannelMap)
3466 newChannelMap->hCard = hCard;
3467 newChannelMap->readerName = strdup(readerName);
3469 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3472 free(newChannelMap->readerName);
3473 free(newChannelMap);
3474 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3485 CHANNEL_MAP * currentChannelMap;
3489 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
3490 ¤tChannelMap);
3494 free(currentChannelMap->readerName);
3496 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3499 Log2(PCSC_LOG_CRITICAL,
3500 "list_delete failed with return value: %d", lrv);
3503 free(currentChannelMap);
3508 static LONG SCardGetContextAndChannelFromHandle(
SCARDHANDLE hCard,
3509 SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
3517 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3524 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3525 SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
3530 CHANNEL_MAP * currentChannelMap;
3533 *targetContextMap = NULL;
3534 *targetChannelMap = NULL;
3536 listSize = list_size(&contextMapList);
3538 for (list_index = 0; list_index < listSize; list_index++)
3540 currentContextMap = list_get_at(&contextMapList, list_index);
3541 if (currentContextMap == NULL)
3543 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3547 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3549 if (currentChannelMap != NULL)
3551 *targetContextMap = currentContextMap;
3552 *targetChannelMap = currentChannelMap;
3574 struct stat statBuffer;
3577 socketName = getSocketName();
3578 rv = stat(socketName, &statBuffer);
3582 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3583 socketName, strerror(errno));
3590 static void SCardInvalidateHandles(
void)
3595 while (list_size(&contextMapList) != 0)
3599 currentContextMap = list_get_at(&contextMapList, 0);
3600 if (currentContextMap != NULL)
3601 (void)SCardCleanContext(currentContextMap);
3603 Log1(PCSC_LOG_CRITICAL,
"list_get_at returned NULL");
3609 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3611 int32_t dwClientID = currentContextMap->
dwClientID;
3619 rv =
MessageReceive(&readerStates,
sizeof(readerStates), dwClientID);
used by SCardBeginTransaction()
contained in SCARD_CONNECT Messages.
uint32_t cardAtrLength
ATR length.
static SCONTEXTMAP * SCardGetContext(SCARDCONTEXT)
Get the index from the Application Context vector _psContextMap for the passed context.
wait for a reader state change
contained in SCARD_CANCEL Messages.
contained in SCARD_TRANSMIT Messages.
#define SCARD_STATE_UNAVAILABLE
Status unavailable.
LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
Returns a list of currently available readers on the system.
contained in SCARD_END_TRANSACTION Messages.
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
INTERNAL int ClientCloseSession(uint32_t dwClientID)
Closes the socket used by the client to communicate with the server.
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups)
Returns a list of currently available reader groups on the system.
#define SCARD_STATE_EMPTY
Card removed.
get the client/server protocol version
static SCONTEXTMAP * SCardGetContextTH(SCARDCONTEXT)
Get the address from the Application Context list _psContextMap for the passed context.
#define SCARD_STATE_IGNORE
Ignore this reader.
#define SCARD_UNKNOWN
Unknown state.
PCSC_API char * pcsc_stringify_error(const LONG pcscError)
Returns a human readable text for the given PC/SC error code.
static short isExecuted
Make sure the initialization code is executed only once.
used by SCardEstablishContext()
PCSC_API const SCARD_IO_REQUEST g_rgSCardT1Pci
Protocol Control Information for T=1.
INTERNAL LONG MessageSendWithHeader(uint32_t command, uint32_t dwClientID, uint64_t size, void *data_void)
Wrapper for the MessageSend() function.
int32_t minor
IPC minor PROTOCOL_VERSION_MINOR.
#define SCARD_F_COMM_ERROR
An internal communications error has been detected.
used by SCardEndTransaction()
LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
Creates an Application Context to the PC/SC Resource Manager.
unsigned long cbPciLength
Protocol Control Inf Length.
int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
#define SCARD_STATE_CHANGED
State has changed.
This handles abstract system level calls.
static LONG SCardRemoveContext(SCARDCONTEXT)
Removes an Application Context from a control vector.
#define SCARD_E_NO_SERVICE
The Smart card resource manager is not running.
uint32_t eventCounter
number of card events
#define SCARD_E_NO_READERS_AVAILABLE
Cannot find a smart card reader.
static LONG SCardUnlockThread(void)
Unlocks a mutex so another thread may use the client.
PCSC_API const SCARD_IO_REQUEST g_rgSCardRawPci
Protocol Control Information for raw access.
#define PROTOCOL_VERSION_MAJOR
Major version of the current message protocol.
#define SCARD_PROTOCOL_T1
T=1 active protocol.
contained in SCARD_DISCONNECT Messages.
LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
Releases memory that has been returned from the resource manager using the SCARD_AUTOALLOCATE length ...
LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, SCARD_READERSTATE *rgReaderStates, DWORD cReaders)
Blocks execution until the current availability of the cards in a specific set of readers changes...
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
Get an attribute from the IFD Handler (reader driver).
#define SCARD_PRESENT
Card is present.
Information contained in SCARD_RELEASE_CONTEXT Messages.
LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
Terminates a connection made through SCardConnect().
LONG SCardCancel(SCARDCONTEXT hContext)
Cancels all pending blocking requests on the SCardGetStatusChange() function.
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
contained in SCARD_BEGIN_TRANSACTION Messages.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
LONG SCardIsValidContext(SCARDCONTEXT hContext)
Check if a SCARDCONTEXT is valid.
#define INFINITE
Infinite timeout.
#define SCARD_STATE_UNKNOWN
Reader unknown.
Represents the an Application Context on the Client side.
Information contained in SCARD_ESTABLISH_CONTEXT Messages.
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
Information transmitted in CMD_VERSION Messages.
INTERNAL LONG MessageReceive(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Called by the Client to get the reponse from the server or vice-versa.
used by SCardReleaseContext()
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
contained in SCARD_STATUS Messages.
contained in SCARD_RECONNECT Messages.
unsigned long dwProtocol
Protocol identifier.
uint32_t timeOut
timeout in ms
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
contained in SCARD_GET_ATTRIB and Messages.
prototypes of strlcpy()/strlcat() imported from OpenBSD
#define SCARD_STATE_PRESENT
Card inserted.
PCSC_API const SCARD_IO_REQUEST g_rgSCardT0Pci
Protocol Control Information for T=0.
This defines some structures and #defines to be used over the transport layer.
Information contained in CMD_WAIT_READER_STATE_CHANGE Messages.
DWORD dwClientID
Client Connection ID.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
#define SCARD_STATE_ATRMATCH
ATR matches card.
LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
Reestablishes a connection to a reader that was previously connected to using SCardConnect().
long int time_sub(struct timeval *a, struct timeval *b)
return the difference (as long int) in µs between 2 struct timeval r = a - b
#define MAX_BUFFER_SIZE_EXTENDED
enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer
static READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]
Area used to read status information about the readers.
#define PCSCLITE_STATUS_POLL_RATE
Status polling rate.
Represents an Application Context Channel.
This handles card insertion/removal events, updates ATR, protocol, and status information.
SCARDCONTEXT hContext
Application Context ID.
#define SCARD_PROTOCOL_ANY
IFD determines prot.
char cancellable
We are in a cancellable call.
stop waiting for a reader state change
LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Establishes a connection to the reader specified in * szReader.
LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
Returns the current status of the reader connected to by hCard.
LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
Set an attribute of the IFD Handler.
#define SCARD_STATE_EXCLUSIVE
Exclusive Mode.
#define SCARD_SWALLOWED
Card not powered.
static LONG SCardAddContext(SCARDCONTEXT, DWORD)
Functions for managing instances of SCardEstablishContext() These functions keep track of Context han...
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
LONG SCARDHANDLE
hCard returned by SCardConnect()
static LONG SCardLockThread(void)
Locks a mutex so another thread must wait to use this function.
LONG SCardCheckDaemonAvailability(void)
Checks if the server is running.
INTERNAL int ClientSetupSession(uint32_t *pdwClientID)
Prepares a communication channel for the client to talk to the server.
#define PROTOCOL_VERSION_MINOR
Minor version of the current message protocol.
pthread_mutex_t * mMutex
Mutex for this context.
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.
static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT)
Creates a communication context to the PC/SC Resource Manager.
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.