108#include <sys/types.h>
142static char sharing_shall_block = TRUE;
144#define COLOR_RED "\33[01;31m"
145#define COLOR_GREEN "\33[32m"
146#define COLOR_BLUE "\33[34m"
147#define COLOR_MAGENTA "\33[35m"
148#define COLOR_NORMAL "\33[0m"
155static void trace(
const char *func,
const char direction,
const char *fmt, ...)
159 fprintf(stderr, COLOR_GREEN
"%c " COLOR_BLUE
"[%lX] " COLOR_GREEN
"%s ",
160 direction, pthread_self(), func);
162 fprintf(stderr, COLOR_MAGENTA);
164 vfprintf(stderr, fmt, args);
167 fprintf(stderr, COLOR_NORMAL
"\n");
170#define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__);
171#define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__);
173#define API_TRACE_IN(...)
174#define API_TRACE_OUT(...)
179#define PROFILE_FILE "/tmp/pcsc_profile"
185pthread_t threads[MAX_THREADS];
186struct timeval profile_time_start[MAX_THREADS];
190#define PROFILE_START profile_start();
191#define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
193static void profile_start(
void)
195 static char initialized = FALSE;
204 sprintf(filename,
"%s-%d", PROFILE_FILE, getuid());
205 profile_fd = fopen(filename,
"a+");
206 if (NULL == profile_fd)
208 fprintf(stderr, COLOR_RED
"Can't open %s: %s" COLOR_NORMAL
"\n",
209 PROFILE_FILE, strerror(errno));
212 fprintf(profile_fd,
"\nStart a new profile\n");
214 if (isatty(fileno(stderr)))
221 for (i=0; i<MAX_THREADS; i++)
222 if (pthread_equal(0, threads[i]))
228 gettimeofday(&profile_time_start[i], NULL);
231static void profile_end(
const char *f, LONG rv)
233 struct timeval profile_time_end;
238 gettimeofday(&profile_time_end, NULL);
241 for (i=0; i<MAX_THREADS; i++)
242 if (pthread_equal(t, threads[i]))
247 fprintf(stderr, COLOR_BLUE
" WARNING: no start info for %s\n", f);
251 d =
time_sub(&profile_time_end, &profile_time_start[i]);
260 COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld "
261 COLOR_BLUE
"0x%08lX %s" COLOR_NORMAL
"\n",
262 f, d, rv, pcsc_stringify_error(rv));
264 fprintf(stderr, COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld"
265 COLOR_NORMAL
"\n", f, d);
267 fprintf(profile_fd,
"%s %ld\n", f, d);
273#define PROFILE_END(rv)
288static int CHANNEL_MAP_seeker(
const void *el,
const void *key)
292 if ((el == NULL) || (key == NULL))
294 Log3(PCSC_LOG_CRITICAL,
295 "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
326static list_t contextMapList;
328static int SCONTEXTMAP_seeker(
const void *el,
const void *key)
332 if ((el == NULL) || (key == NULL))
334 Log3(PCSC_LOG_CRITICAL,
335 "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
378static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE,
380static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
384static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
385 LPBYTE pbAttr, LPDWORD pcbAttrLen);
387static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
388static LONG getReaderStatesAndRegisterForEvents(
SCONTEXTMAP * currentContextMap);
389static LONG unregisterFromEvents(
SCONTEXTMAP * currentContextMap);
432 return currentContextMap != NULL;
473LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
474 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
478 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
488 pvReserved2, phContext);
493 API_TRACE_OUT(
"%ld", *phContext)
499DESTRUCTOR
static void destructor(
void)
501 list_destroy(&contextMapList);
534 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
538 uint32_t dwClientID = 0;
542 if (phContext == NULL)
558 lrv = list_init(&contextMapList);
561 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
566 lrv = list_attributes_seeker(&contextMapList,
570 Log2(PCSC_LOG_CRITICAL,
571 "list_attributes_seeker failed with return value: %d", lrv);
572 list_destroy(&contextMapList);
576 if (getenv(
"PCSCLITE_NO_BLOCKING"))
578 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
579 sharing_shall_block = FALSE;
608 Log1(PCSC_LOG_CRITICAL,
609 "Your pcscd is too old and does not support CMD_VERSION");
613 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
627 scEstablishStruct.dwScope = dwScope;
628 scEstablishStruct.hContext = 0;
632 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
640 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
648 rv = scEstablishStruct.rv;
658 *phContext = scEstablishStruct.hContext;
700 API_TRACE_IN(
"%ld", hContext)
708 if (NULL == currentContextMap)
714 scReleaseStruct.hContext = hContext;
718 currentContextMap->dwClientID,
719 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
728 currentContextMap->dwClientID);
733 rv = scReleaseStruct.rv;
735 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
807 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
808 LPDWORD pdwActiveProtocol)
815 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
820 if (phCard == NULL || pdwActiveProtocol == NULL)
825 if (szReader == NULL)
831 if (strlen(szReader) > MAX_READERNAME)
838 if (NULL == currentContextMap)
841 memset(scConnectStruct.szReader, 0,
sizeof scConnectStruct.szReader);
842 strncpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
843 scConnectStruct.szReader[
sizeof scConnectStruct.szReader -1] =
'\0';
845 scConnectStruct.hContext = hContext;
846 scConnectStruct.dwShareMode = dwShareMode;
847 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
848 scConnectStruct.hCard = 0;
849 scConnectStruct.dwActiveProtocol = 0;
853 sizeof(scConnectStruct), (
void *) &scConnectStruct);
862 currentContextMap->dwClientID);
867 *phCard = scConnectStruct.hCard;
868 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
875 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
878 rv = scConnectStruct.rv;
881 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
884 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
962 DWORD dwPreferredProtocols, DWORD dwInitialization,
963 LPDWORD pdwActiveProtocol)
971 API_TRACE_IN(
"%ld %ld %ld", hCard, dwShareMode, dwPreferredProtocols)
973 if (pdwActiveProtocol == NULL)
982 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
987 scReconnectStruct.hCard = hCard;
988 scReconnectStruct.dwShareMode = dwShareMode;
989 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
990 scReconnectStruct.dwInitialization = dwInitialization;
991 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
995 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
1003 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
1004 currentContextMap->dwClientID);
1009 rv = scReconnectStruct.rv;
1013 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1018 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
1021 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1024 API_TRACE_OUT(
"%ld", *pdwActiveProtocol)
1068 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1073 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1081 scDisconnectStruct.hCard = hCard;
1082 scDisconnectStruct.dwDisposition = dwDisposition;
1086 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1094 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1095 currentContextMap->dwClientID);
1101 SCardRemoveHandle(hCard);
1102 rv = scDisconnectStruct.rv;
1105 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1158 API_TRACE_IN(
"%ld", hCard)
1170 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1175 scBeginStruct.hCard = hCard;
1179 currentContextMap->dwClientID,
1180 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1189 currentContextMap->dwClientID);
1194 rv = scBeginStruct.rv;
1199 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1203 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1258 API_TRACE_IN(
"%ld", hCard)
1263 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1268 scEndStruct.hCard = hCard;
1269 scEndStruct.dwDisposition = dwDisposition;
1273 currentContextMap->dwClientID,
1274 sizeof(scEndStruct), (
void *) &scEndStruct);
1283 currentContextMap->dwClientID);
1288 rv = scEndStruct.rv;
1291 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1395 LPDWORD pcchReaderLen, LPDWORD pdwState,
1396 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1398 DWORD dwReaderLen, dwAtrLen;
1405 char *bufReader = NULL;
1406 LPBYTE bufAtr = NULL;
1419 if (pcchReaderLen == NULL)
1420 pcchReaderLen = &dummy;
1422 if (pcbAtrLen == NULL)
1426 dwReaderLen = *pcchReaderLen;
1427 dwAtrLen = *pcbAtrLen;
1438 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1444 rv = getReaderStates(currentContextMap);
1448 r = pChannelMap->readerName;
1463 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1464 scStatusStruct.hCard = hCard;
1467 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1476 currentContextMap->dwClientID);
1481 rv = scStatusStruct.rv;
1485 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1502 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1513 dwReaderLen = *pcchReaderLen;
1514 if (NULL == szReaderName)
1519 bufReader = malloc(dwReaderLen);
1520 if (NULL == bufReader)
1525 *(
char **)szReaderName = bufReader;
1528 bufReader = szReaderName;
1533 if (*pcchReaderLen > dwReaderLen)
1536 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1541 dwAtrLen = *pcbAtrLen;
1547 bufAtr = malloc(dwAtrLen);
1553 *(LPBYTE *)pbAtr = bufAtr;
1560 if (*pcbAtrLen > dwAtrLen)
1563 memcpy(bufAtr,
readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1567 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1687 DWORD dwBreakFlag = 0;
1690 int currentReaderCount = 0;
1694 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1696 for (j=0; j<cReaders; j++)
1698 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1699 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1703 if ((rgReaderStates == NULL && cReaders > 0)
1711 for (j = 0; j < cReaders; j++)
1713 if (rgReaderStates[j].szReader == NULL)
1720 int nbNonIgnoredReaders = cReaders;
1722 for (j=0; j<cReaders; j++)
1724 nbNonIgnoredReaders--;
1726 if (0 == nbNonIgnoredReaders)
1743 if (NULL == currentContextMap)
1750 rv = getReaderStatesAndRegisterForEvents(currentContextMap);
1755 for (j=0; j<cReaders; j++)
1757 const char *readerName;
1760 readerName = rgReaderStates[j].szReader;
1763 if (strcmp(readerName,
readerStates[i].readerName) == 0)
1771 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1780 for (j = 0; j < cReaders; j++)
1781 rgReaderStates[j].dwEventState = 0;
1784 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1789 currentReaderCount++;
1792 if ((DWORD)-1 == dwTimeout)
1802 currReader = &rgReaderStates[j];
1807 const char *readerName;
1811 readerName = currReader->szReader;
1814 if (strcmp(readerName,
readerStates[i].readerName) == 0)
1822 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1824 int k, newReaderCount = 0;
1830 if (newReaderCount != currentReaderCount)
1832 Log1(PCSC_LOG_INFO,
"Reader list changed");
1833 currentReaderCount = newReaderCount;
1841 currReader->dwEventState =
1857 uint32_t readerState;
1863 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1864 Log0(PCSC_LOG_DEBUG);
1875 if (currReader->dwCurrentState & 0xFFFF0000)
1877 unsigned int currentCounter;
1879 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1885 Log0(PCSC_LOG_DEBUG);
1891 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1903 Log0(PCSC_LOG_DEBUG);
1912 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1914 Log0(PCSC_LOG_DEBUG);
1922#ifndef DISABLE_AUTO_POWER_ON
1930 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1934 currReader->cbAtr = 0;
1940 currReader->dwEventState &= ~SCARD_STATE_PRESENT;
1941 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1942 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1943 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1944 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1945 currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
1946 currReader->dwEventState &= ~SCARD_STATE_MUTE;
1947 currReader->dwEventState &= ~SCARD_STATE_INUSE;
1953 Log0(PCSC_LOG_DEBUG);
1961 currReader->dwEventState &= ~SCARD_STATE_EMPTY;
1962 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1963 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1964 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1965 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1966 currReader->dwEventState &= ~SCARD_STATE_MUTE;
1971 Log0(PCSC_LOG_DEBUG);
1981 Log0(PCSC_LOG_DEBUG);
1991 Log0(PCSC_LOG_DEBUG);
2001 currReader->dwEventState &= ~SCARD_STATE_INUSE;
2005 Log0(PCSC_LOG_DEBUG);
2015 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2019 Log0(PCSC_LOG_DEBUG);
2026 currReader->dwEventState &= ~SCARD_STATE_INUSE;
2027 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2032 Log0(PCSC_LOG_DEBUG);
2035 else if (currReader-> dwCurrentState
2039 Log0(PCSC_LOG_DEBUG);
2051 Log0(PCSC_LOG_DEBUG);
2067 if (dwBreakFlag == 1)
2073 struct timeval before, after;
2075 gettimeofday(&before, NULL);
2086 &waitStatusStruct,
sizeof(waitStatusStruct),
2097 rv = unregisterFromEvents(currentContextMap);
2106 rv = waitStatusStruct.rv;
2111 rv = getReaderStatesAndRegisterForEvents(currentContextMap);
2119 gettimeofday(&after, NULL);
2121 dwTime -= diff/1000;
2141 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2146 (void)unregisterFromEvents(currentContextMap);
2148 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2153 for (j=0; j<cReaders; j++)
2155 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2156 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2213LONG SCardControl(
SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
2214 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2215 LPDWORD lpBytesReturned)
2225 if (NULL != lpBytesReturned)
2226 *lpBytesReturned = 0;
2231 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2245 scControlStruct.hCard = hCard;
2246 scControlStruct.dwControlCode = dwControlCode;
2247 scControlStruct.cbSendLength = cbSendLength;
2248 scControlStruct.cbRecvLength = cbRecvLength;
2249 scControlStruct.dwBytesReturned = 0;
2250 scControlStruct.rv = 0;
2253 sizeof(scControlStruct), &scControlStruct);
2259 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2260 currentContextMap->dwClientID);
2269 currentContextMap->dwClientID);
2276 if (scControlStruct.dwBytesReturned > cbRecvLength)
2278 if (NULL != lpBytesReturned)
2279 *lpBytesReturned = scControlStruct.dwBytesReturned;
2285 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2286 currentContextMap->dwClientID);
2293 if (NULL != lpBytesReturned)
2294 *lpBytesReturned = scControlStruct.dwBytesReturned;
2296 rv = scControlStruct.rv;
2299 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2427 unsigned char *buf = NULL;
2431 if (NULL == pcbAttrLen)
2443 buf = malloc(*pcbAttrLen);
2450 *(
unsigned char **)pbAttr = buf;
2513 if (NULL == pbAttr || 0 == cbAttrLen)
2524static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2525 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2535 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2546 scGetSetStruct.hCard = hCard;
2547 scGetSetStruct.dwAttrId = dwAttrId;
2549 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2552 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2553 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2557 scGetSetStruct.cbAttrLen =
sizeof scGetSetStruct.pbAttr;
2560 sizeof(scGetSetStruct), &scGetSetStruct);
2569 currentContextMap->dwClientID);
2579 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2583 DWORD correct_value = scGetSetStruct.cbAttrLen;
2584 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2585 *pcbAttrLen = correct_value;
2590 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2593 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2595 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2597 rv = scGetSetStruct.rv;
2600 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2664 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2666 LPDWORD pcbRecvLength)
2675 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2676 pcbRecvLength == NULL || pioSendPci == NULL)
2685 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2700 scTransmitStruct.hCard = hCard;
2701 scTransmitStruct.cbSendLength = cbSendLength;
2702 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2703 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2704 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2709 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2710 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2719 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2725 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2742 if (scTransmitStruct.pcbRecvLength > *pcbRecvLength)
2744 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2750 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2758 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2759 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2763 rv = scTransmitStruct.rv;
2767 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2772 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2775 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2845 LPSTR mszReaders, LPDWORD pcchReaders)
2847 DWORD dwReadersLen = 0;
2855 API_TRACE_IN(
"%ld", hContext)
2860 if (pcchReaders == NULL)
2867 if (NULL == currentContextMap)
2874 rv = getReaderStates(currentContextMap);
2881 dwReadersLen += strlen(
readerStates[i].readerName) + 1;
2886 if (1 == dwReadersLen)
2894 if (NULL == mszReaders)
2899 buf = malloc(dwReadersLen);
2905 *(
char **)mszReaders = buf;
2912 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2919 if (mszReaders == NULL)
2937 *pcchReaders = dwReadersLen;
2939 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2942 API_TRACE_OUT(
"%d", *pcchReaders)
2972 free((
void *)pvMem);
3040 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
3041 const unsigned int dwGroups =
sizeof(ReaderGroup);
3047 if (NULL == currentContextMap)
3052 if (NULL == mszGroups)
3057 buf = malloc(dwGroups);
3063 *(
char **)mszGroups = buf;
3069 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3077 memcpy(buf, ReaderGroup, dwGroups);
3080 *pcchGroups = dwGroups;
3082 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3124 uint32_t dwClientID = 0;
3129 API_TRACE_IN(
"%ld", hContext)
3137 if (NULL == currentContextMap)
3159 scCancelStruct.hContext = hContext;
3163 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3171 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3176 rv = scCancelStruct.rv;
3215 API_TRACE_IN(
"%ld", hContext)
3253 if (NULL == newContextMap)
3256 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3257 newContextMap->
hContext = hContext;
3261 (void)pthread_mutex_init(&newContextMap->
mMutex, NULL);
3263 lrv = list_init(&newContextMap->channelMapList);
3266 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3270 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3271 CHANNEL_MAP_seeker);
3274 Log2(PCSC_LOG_CRITICAL,
3275 "list_attributes_seeker failed with return value: %d", lrv);
3276 list_destroy(&newContextMap->channelMapList);
3280 lrv = list_append(&contextMapList, newContextMap);
3283 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3285 list_destroy(&newContextMap->channelMapList);
3293 (void)pthread_mutex_destroy(&newContextMap->
mMutex);
3294 free(newContextMap);
3323 if (NULL != currentContextMap)
3324 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
3328 return currentContextMap;
3345 return list_seek(&contextMapList, &hContext);
3359 if (NULL != currentContextMap)
3360 SCardCleanContext(currentContextMap);
3363static void SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3365 int list_index, lrv;
3372 (void)pthread_mutex_destroy(&targetContextMap->
mMutex);
3374 listSize = list_size(&targetContextMap->channelMapList);
3375 for (list_index = 0; list_index < listSize; list_index++)
3377 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3379 if (NULL == currentChannelMap)
3381 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3387 free(currentChannelMap->readerName);
3388 free(currentChannelMap);
3392 list_destroy(&targetContextMap->channelMapList);
3394 lrv = list_delete(&contextMapList, targetContextMap);
3397 Log2(PCSC_LOG_CRITICAL,
3398 "list_delete failed with return value: %d", lrv);
3401 free(targetContextMap);
3417 if (NULL == newChannelMap)
3420 newChannelMap->hCard = hCard;
3421 newChannelMap->readerName = strdup(readerName);
3423 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3426 free(newChannelMap->readerName);
3427 free(newChannelMap);
3428 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3443 rv = SCardGetContextAndChannelFromHandleTH(hCard, ¤tContextMap,
3444 ¤tChannelMap);
3448 free(currentChannelMap->readerName);
3450 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3453 Log2(PCSC_LOG_CRITICAL,
3454 "list_delete failed with return value: %d", lrv);
3457 free(currentChannelMap);
3462static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE hCard,
3471 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3475 (void)pthread_mutex_lock(&(*targetContextMap)->mMutex);
3482static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3491 *targetContextMap = NULL;
3492 *targetChannelMap = NULL;
3494 listSize = list_size(&contextMapList);
3496 for (list_index = 0; list_index < listSize; list_index++)
3498 currentContextMap = list_get_at(&contextMapList, list_index);
3499 if (currentContextMap == NULL)
3501 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3505 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3507 if (currentChannelMap != NULL)
3509 *targetContextMap = currentContextMap;
3510 *targetChannelMap = currentChannelMap;
3528 struct stat statBuffer;
3531 socketName = getSocketName();
3532 rv = stat(socketName, &statBuffer);
3536 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3537 socketName, strerror(errno));
3544static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3546 int32_t dwClientID = currentContextMap->
dwClientID;
3561static LONG getReaderStatesAndRegisterForEvents(
SCONTEXTMAP * currentContextMap)
3563 int32_t dwClientID = currentContextMap->
dwClientID;
3577static LONG unregisterFromEvents(
SCONTEXTMAP * currentContextMap)
3579 int32_t dwClientID = currentContextMap->
dwClientID;
3585 dwClientID, 0, NULL);
3602 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.
char 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...
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
uint32_t readerState
SCARD_* bit field.
uint32_t cardAtrLength
ATR length.
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 short 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 int SCardGetContextValidity(SCARDCONTEXT hContext)
Tell if a context index from the Application Context vector _psContextMap is valid or not.
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 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 reponse 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 reponse 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()