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",
374static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE,
376static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
380static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
381 LPBYTE pbAttr, LPDWORD pcbAttrLen);
383static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
384static LONG getReaderStatesAndRegisterForEvents(
SCONTEXTMAP * currentContextMap);
385static LONG unregisterFromEvents(
SCONTEXTMAP * currentContextMap);
428 return currentContextMap != NULL;
469LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
470 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
474 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
484 pvReserved2, phContext);
489 API_TRACE_OUT(
"%ld", *phContext)
495DESTRUCTOR
static void destructor(
void)
497 list_destroy(&contextMapList);
530 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
534 uint32_t dwClientID = 0;
538 if (phContext == NULL)
554 lrv = list_init(&contextMapList);
557 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
562 lrv = list_attributes_seeker(&contextMapList,
566 Log2(PCSC_LOG_CRITICAL,
567 "list_attributes_seeker failed with return value: %d", lrv);
568 list_destroy(&contextMapList);
572 if (getenv(
"PCSCLITE_NO_BLOCKING"))
574 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
575 sharing_shall_block =
false;
604 Log1(PCSC_LOG_CRITICAL,
605 "Your pcscd is too old and does not support CMD_VERSION");
609 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
623 scEstablishStruct.dwScope = dwScope;
624 scEstablishStruct.hContext = 0;
628 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
636 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
644 rv = scEstablishStruct.rv;
654 *phContext = scEstablishStruct.hContext;
696 API_TRACE_IN(
"%ld", hContext)
704 if (NULL == currentContextMap)
710 scReleaseStruct.hContext = hContext;
714 currentContextMap->dwClientID,
715 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
724 currentContextMap->dwClientID);
729 rv = scReleaseStruct.rv;
731 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
803 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
804 LPDWORD pdwActiveProtocol)
811 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
816 if (phCard == NULL || pdwActiveProtocol == NULL)
821 if (szReader == NULL)
827 if (strlen(szReader) > MAX_READERNAME)
834 if (NULL == currentContextMap)
837 memset(scConnectStruct.szReader, 0,
sizeof scConnectStruct.szReader);
838 strncpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
839 scConnectStruct.szReader[
sizeof scConnectStruct.szReader -1] =
'\0';
841 scConnectStruct.hContext = hContext;
842 scConnectStruct.dwShareMode = dwShareMode;
843 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
844 scConnectStruct.hCard = 0;
845 scConnectStruct.dwActiveProtocol = 0;
849 sizeof(scConnectStruct), (
void *) &scConnectStruct);
858 currentContextMap->dwClientID);
863 *phCard = scConnectStruct.hCard;
864 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
871 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
874 rv = scConnectStruct.rv;
877 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
880 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
958 DWORD dwPreferredProtocols, DWORD dwInitialization,
959 LPDWORD pdwActiveProtocol)
967 API_TRACE_IN(
"%ld %ld %ld", hCard, dwShareMode, dwPreferredProtocols)
969 if (pdwActiveProtocol == NULL)
978 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
983 scReconnectStruct.hCard = hCard;
984 scReconnectStruct.dwShareMode = dwShareMode;
985 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
986 scReconnectStruct.dwInitialization = dwInitialization;
987 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
991 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
999 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
1000 currentContextMap->dwClientID);
1005 rv = scReconnectStruct.rv;
1009 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1014 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
1017 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1020 API_TRACE_OUT(
"%ld", *pdwActiveProtocol)
1064 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1069 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1077 scDisconnectStruct.hCard = hCard;
1078 scDisconnectStruct.dwDisposition = dwDisposition;
1082 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1090 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1091 currentContextMap->dwClientID);
1097 SCardRemoveHandle(hCard);
1098 rv = scDisconnectStruct.rv;
1101 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1155 API_TRACE_IN(
"%ld", hCard)
1167 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1172 scBeginStruct.hCard = hCard;
1176 currentContextMap->dwClientID,
1177 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1186 currentContextMap->dwClientID);
1191 rv = scBeginStruct.rv;
1196 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1200 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1255 API_TRACE_IN(
"%ld", hCard)
1260 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1265 scEndStruct.hCard = hCard;
1266 scEndStruct.dwDisposition = dwDisposition;
1270 currentContextMap->dwClientID,
1271 sizeof(scEndStruct), (
void *) &scEndStruct);
1280 currentContextMap->dwClientID);
1285 rv = scEndStruct.rv;
1288 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1392 LPDWORD pcchReaderLen, LPDWORD pdwState,
1393 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1395 DWORD dwReaderLen, dwAtrLen;
1402 char *bufReader = NULL;
1403 LPBYTE bufAtr = NULL;
1416 if (pcchReaderLen == NULL)
1417 pcchReaderLen = &dummy;
1419 if (pcbAtrLen == NULL)
1423 dwReaderLen = *pcchReaderLen;
1424 dwAtrLen = *pcbAtrLen;
1435 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1441 rv = getReaderStates(currentContextMap);
1445 r = pChannelMap->readerName;
1460 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1461 scStatusStruct.hCard = hCard;
1464 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1473 currentContextMap->dwClientID);
1478 rv = scStatusStruct.rv;
1482 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1499 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1510 dwReaderLen = *pcchReaderLen;
1511 if (NULL == szReaderName)
1516 bufReader = malloc(dwReaderLen);
1517 if (NULL == bufReader)
1522 *(
char **)szReaderName = bufReader;
1525 bufReader = szReaderName;
1530 if (*pcchReaderLen > dwReaderLen)
1533 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1538 dwAtrLen = *pcbAtrLen;
1544 bufAtr = malloc(dwAtrLen);
1550 *(LPBYTE *)pbAtr = bufAtr;
1557 if (*pcbAtrLen > dwAtrLen)
1560 memcpy(bufAtr,
readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1564 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1684 DWORD dwBreakFlag = 0;
1687 int currentReaderCount = 0;
1691 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1693 for (j=0; j<cReaders; j++)
1695 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1696 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1700 if ((rgReaderStates == NULL && cReaders > 0)
1708 for (j = 0; j < cReaders; j++)
1710 if (rgReaderStates[j].szReader == NULL)
1717 int nbNonIgnoredReaders = cReaders;
1719 for (j=0; j<cReaders; j++)
1721 nbNonIgnoredReaders--;
1723 if (0 == nbNonIgnoredReaders)
1740 if (NULL == currentContextMap)
1747 rv = getReaderStatesAndRegisterForEvents(currentContextMap);
1752 for (j=0; j<cReaders; j++)
1754 const char *readerName;
1757 readerName = rgReaderStates[j].szReader;
1760 if (strcmp(readerName,
readerStates[i].readerName) == 0)
1768 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1777 for (j = 0; j < cReaders; j++)
1778 rgReaderStates[j].dwEventState = 0;
1781 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1786 currentReaderCount++;
1789 if ((DWORD)-1 == dwTimeout)
1799 currReader = &rgReaderStates[j];
1804 const char *readerName;
1808 readerName = currReader->szReader;
1811 if (strcmp(readerName,
readerStates[i].readerName) == 0)
1819 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1821 int k, newReaderCount = 0;
1827 if (newReaderCount != currentReaderCount)
1829 Log1(PCSC_LOG_INFO,
"Reader list changed");
1830 currentReaderCount = newReaderCount;
1838 currReader->dwEventState =
1854 uint32_t readerState;
1860 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1861 Log0(PCSC_LOG_DEBUG);
1872 if (currReader->dwCurrentState & 0xFFFF0000)
1874 unsigned int currentCounter;
1876 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1882 Log0(PCSC_LOG_DEBUG);
1888 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1900 Log0(PCSC_LOG_DEBUG);
1909 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1911 Log0(PCSC_LOG_DEBUG);
1919#ifndef DISABLE_AUTO_POWER_ON
1927 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1931 currReader->cbAtr = 0;
1937 currReader->dwEventState &= ~SCARD_STATE_PRESENT;
1938 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1939 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1940 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1941 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1942 currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
1943 currReader->dwEventState &= ~SCARD_STATE_MUTE;
1944 currReader->dwEventState &= ~SCARD_STATE_INUSE;
1950 Log0(PCSC_LOG_DEBUG);
1958 currReader->dwEventState &= ~SCARD_STATE_EMPTY;
1959 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1960 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1961 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1962 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1963 currReader->dwEventState &= ~SCARD_STATE_MUTE;
1968 Log0(PCSC_LOG_DEBUG);
1978 Log0(PCSC_LOG_DEBUG);
1988 Log0(PCSC_LOG_DEBUG);
1998 currReader->dwEventState &= ~SCARD_STATE_INUSE;
2002 Log0(PCSC_LOG_DEBUG);
2012 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2016 Log0(PCSC_LOG_DEBUG);
2023 currReader->dwEventState &= ~SCARD_STATE_INUSE;
2024 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2029 Log0(PCSC_LOG_DEBUG);
2032 else if (currReader-> dwCurrentState
2036 Log0(PCSC_LOG_DEBUG);
2048 Log0(PCSC_LOG_DEBUG);
2064 if (dwBreakFlag == 1)
2070 struct timeval before, after;
2072 gettimeofday(&before, NULL);
2083 &waitStatusStruct,
sizeof(waitStatusStruct),
2094 rv = unregisterFromEvents(currentContextMap);
2103 rv = waitStatusStruct.rv;
2108 rv = getReaderStatesAndRegisterForEvents(currentContextMap);
2116 gettimeofday(&after, NULL);
2118 dwTime -= diff/1000;
2138 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2143 (void)unregisterFromEvents(currentContextMap);
2145 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2150 for (j=0; j<cReaders; j++)
2152 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2153 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2210LONG SCardControl(
SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
2211 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2212 LPDWORD lpBytesReturned)
2222 if (NULL != lpBytesReturned)
2223 *lpBytesReturned = 0;
2228 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2242 scControlStruct.hCard = hCard;
2243 scControlStruct.dwControlCode = dwControlCode;
2244 scControlStruct.cbSendLength = cbSendLength;
2245 scControlStruct.cbRecvLength = cbRecvLength;
2246 scControlStruct.dwBytesReturned = 0;
2247 scControlStruct.rv = 0;
2250 sizeof(scControlStruct), &scControlStruct);
2256 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2257 currentContextMap->dwClientID);
2266 currentContextMap->dwClientID);
2273 if (scControlStruct.dwBytesReturned > cbRecvLength)
2275 if (NULL != lpBytesReturned)
2276 *lpBytesReturned = scControlStruct.dwBytesReturned;
2282 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2283 currentContextMap->dwClientID);
2290 if (NULL != lpBytesReturned)
2291 *lpBytesReturned = scControlStruct.dwBytesReturned;
2293 rv = scControlStruct.rv;
2296 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2425 unsigned char *buf = NULL;
2429 if (NULL == pcbAttrLen)
2441 buf = malloc(*pcbAttrLen);
2448 *(
unsigned char **)pbAttr = buf;
2511 if (NULL == pbAttr || 0 == cbAttrLen)
2522static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2523 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2533 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2544 scGetSetStruct.hCard = hCard;
2545 scGetSetStruct.dwAttrId = dwAttrId;
2547 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2550 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2551 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2555 scGetSetStruct.cbAttrLen =
sizeof scGetSetStruct.pbAttr;
2558 sizeof(scGetSetStruct), &scGetSetStruct);
2567 currentContextMap->dwClientID);
2577 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2581 DWORD correct_value = scGetSetStruct.cbAttrLen;
2582 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2583 *pcbAttrLen = correct_value;
2588 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2591 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2593 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2595 rv = scGetSetStruct.rv;
2598 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2662 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2664 LPDWORD pcbRecvLength)
2673 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2674 pcbRecvLength == NULL || pioSendPci == NULL)
2683 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2698 scTransmitStruct.hCard = hCard;
2699 scTransmitStruct.cbSendLength = cbSendLength;
2700 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2701 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2702 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2707 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2708 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2717 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2723 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2740 if (scTransmitStruct.pcbRecvLength > *pcbRecvLength)
2742 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2748 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2756 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2757 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2761 rv = scTransmitStruct.rv;
2765 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2770 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2773 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2843 LPSTR mszReaders, LPDWORD pcchReaders)
2845 DWORD dwReadersLen = 0;
2853 API_TRACE_IN(
"%ld", hContext)
2858 if (pcchReaders == NULL)
2865 if (NULL == currentContextMap)
2872 rv = getReaderStates(currentContextMap);
2879 dwReadersLen += strlen(
readerStates[i].readerName) + 1;
2884 if (1 == dwReadersLen)
2892 if (NULL == mszReaders)
2897 buf = malloc(dwReadersLen);
2903 *(
char **)mszReaders = buf;
2910 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2917 if (mszReaders == NULL)
2935 *pcchReaders = dwReadersLen;
2937 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2940 API_TRACE_OUT(
"%d", *pcchReaders)
2970 free((
void *)pvMem);
3038 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
3039 const unsigned int dwGroups =
sizeof(ReaderGroup);
3045 if (NULL == currentContextMap)
3050 if (NULL == mszGroups)
3055 buf = malloc(dwGroups);
3061 *(
char **)mszGroups = buf;
3067 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3075 memcpy(buf, ReaderGroup, dwGroups);
3078 *pcchGroups = dwGroups;
3080 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3122 uint32_t dwClientID = 0;
3127 API_TRACE_IN(
"%ld", hContext)
3135 if (NULL == currentContextMap)
3157 scCancelStruct.hContext = hContext;
3161 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3169 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3174 rv = scCancelStruct.rv;
3213 API_TRACE_IN(
"%ld", hContext)
3251 if (NULL == newContextMap)
3254 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3255 newContextMap->
hContext = hContext;
3259 (void)pthread_mutex_init(&newContextMap->
mMutex, NULL);
3261 lrv = list_init(&newContextMap->channelMapList);
3264 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3268 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3269 CHANNEL_MAP_seeker);
3272 Log2(PCSC_LOG_CRITICAL,
3273 "list_attributes_seeker failed with return value: %d", lrv);
3274 list_destroy(&newContextMap->channelMapList);
3278 lrv = list_append(&contextMapList, newContextMap);
3281 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3283 list_destroy(&newContextMap->channelMapList);
3291 (void)pthread_mutex_destroy(&newContextMap->
mMutex);
3292 free(newContextMap);
3321 if (NULL != currentContextMap)
3322 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
3326 return currentContextMap;
3343 return list_seek(&contextMapList, &hContext);
3357 if (NULL != currentContextMap)
3358 SCardCleanContext(currentContextMap);
3361static void SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3363 int list_index, lrv;
3370 (void)pthread_mutex_destroy(&targetContextMap->
mMutex);
3372 listSize = list_size(&targetContextMap->channelMapList);
3373 for (list_index = 0; list_index < listSize; list_index++)
3375 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3377 if (NULL == currentChannelMap)
3379 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3385 free(currentChannelMap->readerName);
3386 free(currentChannelMap);
3390 list_destroy(&targetContextMap->channelMapList);
3392 lrv = list_delete(&contextMapList, targetContextMap);
3395 Log2(PCSC_LOG_CRITICAL,
3396 "list_delete failed with return value: %d", lrv);
3399 free(targetContextMap);
3415 if (NULL == newChannelMap)
3418 newChannelMap->hCard = hCard;
3419 newChannelMap->readerName = strdup(readerName);
3421 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3424 free(newChannelMap->readerName);
3425 free(newChannelMap);
3426 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3441 rv = SCardGetContextAndChannelFromHandleTH(hCard, ¤tContextMap,
3442 ¤tChannelMap);
3446 free(currentChannelMap->readerName);
3448 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3451 Log2(PCSC_LOG_CRITICAL,
3452 "list_delete failed with return value: %d", lrv);
3455 free(currentChannelMap);
3460static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE hCard,
3469 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3473 (void)pthread_mutex_lock(&(*targetContextMap)->mMutex);
3480static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3489 *targetContextMap = NULL;
3490 *targetChannelMap = NULL;
3492 listSize = list_size(&contextMapList);
3494 for (list_index = 0; list_index < listSize; list_index++)
3496 currentContextMap = list_get_at(&contextMapList, list_index);
3497 if (currentContextMap == NULL)
3499 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3503 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3505 if (currentChannelMap != NULL)
3507 *targetContextMap = currentContextMap;
3508 *targetChannelMap = currentChannelMap;
3526 struct stat statBuffer;
3529 socketName = getSocketName();
3530 rv = stat(socketName, &statBuffer);
3534 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3535 socketName, strerror(errno));
3542static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3544 int32_t dwClientID = currentContextMap->
dwClientID;
3559static LONG getReaderStatesAndRegisterForEvents(
SCONTEXTMAP * currentContextMap)
3561 int32_t dwClientID = currentContextMap->
dwClientID;
3575static LONG unregisterFromEvents(
SCONTEXTMAP * currentContextMap)
3577 int32_t dwClientID = currentContextMap->
dwClientID;
3583 dwClientID, 0, NULL);
3600 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...
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 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()