108#include <sys/types.h>
138#define SCARD_PROTOCOL_ANY_OLD 0x1000
145static char sharing_shall_block = TRUE;
147#define COLOR_RED "\33[01;31m"
148#define COLOR_GREEN "\33[32m"
149#define COLOR_BLUE "\33[34m"
150#define COLOR_MAGENTA "\33[35m"
151#define COLOR_NORMAL "\33[0m"
158static void trace(
const char *func,
const char direction,
const char *fmt, ...)
162 fprintf(stderr, COLOR_GREEN
"%c " COLOR_BLUE
"[%lX] " COLOR_GREEN
"%s ",
163 direction, pthread_self(), func);
165 fprintf(stderr, COLOR_MAGENTA);
167 vfprintf(stderr, fmt, args);
170 fprintf(stderr, COLOR_NORMAL
"\n");
173#define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__);
174#define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__);
176#define API_TRACE_IN(...)
177#define API_TRACE_OUT(...)
182#define PROFILE_FILE "/tmp/pcsc_profile"
188pthread_t threads[MAX_THREADS];
189struct timeval profile_time_start[MAX_THREADS];
193#define PROFILE_START profile_start();
194#define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
196static void profile_start(
void)
198 static char initialized = FALSE;
207 sprintf(filename,
"%s-%d", PROFILE_FILE, getuid());
208 profile_fd = fopen(filename,
"a+");
209 if (NULL == profile_fd)
211 fprintf(stderr, COLOR_RED
"Can't open %s: %s" COLOR_NORMAL
"\n",
212 PROFILE_FILE, strerror(errno));
215 fprintf(profile_fd,
"\nStart a new profile\n");
217 if (isatty(fileno(stderr)))
224 for (i=0; i<MAX_THREADS; i++)
225 if (pthread_equal(0, threads[i]))
231 gettimeofday(&profile_time_start[i], NULL);
234static void profile_end(
const char *f, LONG rv)
236 struct timeval profile_time_end;
241 gettimeofday(&profile_time_end, NULL);
244 for (i=0; i<MAX_THREADS; i++)
245 if (pthread_equal(t, threads[i]))
250 fprintf(stderr, COLOR_BLUE
" WARNING: no start info for %s\n", f);
254 d =
time_sub(&profile_time_end, &profile_time_start[i]);
263 COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld "
264 COLOR_BLUE
"0x%08lX %s" COLOR_NORMAL
"\n",
267 fprintf(stderr, COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld"
268 COLOR_NORMAL
"\n", f, d);
270 fprintf(profile_fd,
"%s %ld\n", f, d);
276#define PROFILE_END(rv)
291static int CHANNEL_MAP_seeker(
const void *el,
const void *key)
295 if ((el == NULL) || (key == NULL))
297 Log3(PCSC_LOG_CRITICAL,
298 "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
329static list_t contextMapList;
331static int SCONTEXTMAP_seeker(
const void *el,
const void *key)
335 if ((el == NULL) || (key == NULL))
337 Log3(PCSC_LOG_CRITICAL,
338 "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
381static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE,
383static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
387static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
388 LPBYTE pbAttr, LPDWORD pcbAttrLen);
390static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
391static LONG getReaderStatesAndRegisterForEvents(
SCONTEXTMAP * currentContextMap);
392static LONG unregisterFromEvents(
SCONTEXTMAP * currentContextMap);
435 return currentContextMap != NULL;
477 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
481 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
491 pvReserved2, phContext);
496 API_TRACE_OUT(
"%ld", *phContext)
502DESTRUCTOR
static void destructor(
void)
504 list_destroy(&contextMapList);
536 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
540 uint32_t dwClientID = 0;
544 if (phContext == NULL)
560 lrv = list_init(&contextMapList);
563 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
568 lrv = list_attributes_seeker(&contextMapList,
572 Log2(PCSC_LOG_CRITICAL,
573 "list_attributes_seeker failed with return value: %d", lrv);
574 list_destroy(&contextMapList);
578 if (getenv(
"PCSCLITE_NO_BLOCKING"))
580 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
581 sharing_shall_block = FALSE;
610 Log1(PCSC_LOG_CRITICAL,
611 "Your pcscd is too old and does not support CMD_VERSION");
616 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
630 scEstablishStruct.dwScope = dwScope;
631 scEstablishStruct.hContext = 0;
635 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
643 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
651 rv = scEstablishStruct.rv;
661 *phContext = scEstablishStruct.hContext;
703 API_TRACE_IN(
"%ld", hContext)
711 if (NULL == currentContextMap)
717 scReleaseStruct.hContext = hContext;
721 currentContextMap->dwClientID,
722 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
731 currentContextMap->dwClientID);
736 rv = scReleaseStruct.rv;
738 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
810 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
811 LPDWORD pdwActiveProtocol)
818 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
823 if (phCard == NULL || pdwActiveProtocol == NULL)
828 if (szReader == NULL)
834 if (strlen(szReader) > MAX_READERNAME)
841 if (NULL == currentContextMap)
844 memset(scConnectStruct.szReader, 0,
sizeof scConnectStruct.szReader);
845 strncpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
846 scConnectStruct.szReader[
sizeof scConnectStruct.szReader -1] =
'\0';
848 scConnectStruct.hContext = hContext;
849 scConnectStruct.dwShareMode = dwShareMode;
850 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
851 scConnectStruct.hCard = 0;
852 scConnectStruct.dwActiveProtocol = 0;
856 sizeof(scConnectStruct), (
void *) &scConnectStruct);
865 currentContextMap->dwClientID);
870 *phCard = scConnectStruct.hCard;
871 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
878 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
881 rv = scConnectStruct.rv;
884 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
887 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
965 DWORD dwPreferredProtocols, DWORD dwInitialization,
966 LPDWORD pdwActiveProtocol)
974 API_TRACE_IN(
"%ld %ld %ld", hCard, dwShareMode, dwPreferredProtocols)
976 if (pdwActiveProtocol == NULL)
985 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
990 scReconnectStruct.hCard = hCard;
991 scReconnectStruct.dwShareMode = dwShareMode;
992 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
993 scReconnectStruct.dwInitialization = dwInitialization;
994 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
998 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
1006 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
1007 currentContextMap->dwClientID);
1012 rv = scReconnectStruct.rv;
1016 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1021 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
1024 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1027 API_TRACE_OUT(
"%ld", *pdwActiveProtocol)
1071 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1076 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1084 scDisconnectStruct.hCard = hCard;
1085 scDisconnectStruct.dwDisposition = dwDisposition;
1089 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1097 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1098 currentContextMap->dwClientID);
1104 SCardRemoveHandle(hCard);
1105 rv = scDisconnectStruct.rv;
1108 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1161 API_TRACE_IN(
"%ld", hCard)
1173 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1178 scBeginStruct.hCard = hCard;
1182 currentContextMap->dwClientID,
1183 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1192 currentContextMap->dwClientID);
1197 rv = scBeginStruct.rv;
1202 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1206 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1261 API_TRACE_IN(
"%ld", hCard)
1266 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1271 scEndStruct.hCard = hCard;
1272 scEndStruct.dwDisposition = dwDisposition;
1276 currentContextMap->dwClientID,
1277 sizeof(scEndStruct), (
void *) &scEndStruct);
1286 currentContextMap->dwClientID);
1291 rv = scEndStruct.rv;
1294 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1398 LPDWORD pcchReaderLen, LPDWORD pdwState,
1399 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1401 DWORD dwReaderLen, dwAtrLen;
1408 char *bufReader = NULL;
1409 LPBYTE bufAtr = NULL;
1422 if (pcchReaderLen == NULL)
1423 pcchReaderLen = &dummy;
1425 if (pcbAtrLen == NULL)
1429 dwReaderLen = *pcchReaderLen;
1430 dwAtrLen = *pcbAtrLen;
1441 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1447 rv = getReaderStates(currentContextMap);
1451 r = pChannelMap->readerName;
1466 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1467 scStatusStruct.hCard = hCard;
1470 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1479 currentContextMap->dwClientID);
1484 rv = scStatusStruct.rv;
1488 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1505 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1516 dwReaderLen = *pcchReaderLen;
1517 if (NULL == szReaderName)
1522 bufReader = malloc(dwReaderLen);
1523 if (NULL == bufReader)
1528 *(
char **)szReaderName = bufReader;
1531 bufReader = szReaderName;
1536 if (*pcchReaderLen > dwReaderLen)
1539 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1544 dwAtrLen = *pcbAtrLen;
1550 bufAtr = malloc(dwAtrLen);
1556 *(LPBYTE *)pbAtr = bufAtr;
1563 if (*pcbAtrLen > dwAtrLen)
1566 memcpy(bufAtr,
readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1570 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1690 DWORD dwBreakFlag = 0;
1693 int currentReaderCount = 0;
1697 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1699 for (j=0; j<cReaders; j++)
1701 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1702 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1706 if ((rgReaderStates == NULL && cReaders > 0)
1714 for (j = 0; j < cReaders; j++)
1716 if (rgReaderStates[j].szReader == NULL)
1723 int nbNonIgnoredReaders = cReaders;
1725 for (j=0; j<cReaders; j++)
1727 nbNonIgnoredReaders--;
1729 if (0 == nbNonIgnoredReaders)
1746 if (NULL == currentContextMap)
1753 rv = getReaderStatesAndRegisterForEvents(currentContextMap);
1758 for (j=0; j<cReaders; j++)
1760 const char *readerName;
1763 readerName = rgReaderStates[j].szReader;
1766 if (strcmp(readerName,
readerStates[i].readerName) == 0)
1774 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1783 for (j = 0; j < cReaders; j++)
1784 rgReaderStates[j].dwEventState = 0;
1787 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1792 currentReaderCount++;
1795 if ((DWORD)-1 == dwTimeout)
1805 currReader = &rgReaderStates[j];
1810 const char *readerName;
1814 readerName = currReader->szReader;
1817 if (strcmp(readerName,
readerStates[i].readerName) == 0)
1825 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1827 int k, newReaderCount = 0;
1833 if (newReaderCount != currentReaderCount)
1835 Log1(PCSC_LOG_INFO,
"Reader list changed");
1836 currentReaderCount = newReaderCount;
1844 currReader->dwEventState =
1860 uint32_t readerState;
1866 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1867 Log0(PCSC_LOG_DEBUG);
1878 if (currReader->dwCurrentState & 0xFFFF0000)
1880 unsigned int currentCounter;
1882 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1888 Log0(PCSC_LOG_DEBUG);
1894 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1906 Log0(PCSC_LOG_DEBUG);
1915 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1917 Log0(PCSC_LOG_DEBUG);
1925#ifndef DISABLE_AUTO_POWER_ON
1933 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1937 currReader->cbAtr = 0;
1943 currReader->dwEventState &= ~SCARD_STATE_PRESENT;
1944 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1945 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1946 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1947 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1948 currReader->dwEventState &= ~SCARD_STATE_ATRMATCH;
1949 currReader->dwEventState &= ~SCARD_STATE_MUTE;
1950 currReader->dwEventState &= ~SCARD_STATE_INUSE;
1956 Log0(PCSC_LOG_DEBUG);
1964 currReader->dwEventState &= ~SCARD_STATE_EMPTY;
1965 currReader->dwEventState &= ~SCARD_STATE_UNAWARE;
1966 currReader->dwEventState &= ~SCARD_STATE_IGNORE;
1967 currReader->dwEventState &= ~SCARD_STATE_UNKNOWN;
1968 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1969 currReader->dwEventState &= ~SCARD_STATE_MUTE;
1974 Log0(PCSC_LOG_DEBUG);
1984 Log0(PCSC_LOG_DEBUG);
1994 Log0(PCSC_LOG_DEBUG);
2004 currReader->dwEventState &= ~SCARD_STATE_INUSE;
2008 Log0(PCSC_LOG_DEBUG);
2018 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2022 Log0(PCSC_LOG_DEBUG);
2029 currReader->dwEventState &= ~SCARD_STATE_INUSE;
2030 currReader->dwEventState &= ~SCARD_STATE_EXCLUSIVE;
2035 Log0(PCSC_LOG_DEBUG);
2038 else if (currReader-> dwCurrentState
2042 Log0(PCSC_LOG_DEBUG);
2054 Log0(PCSC_LOG_DEBUG);
2070 if (dwBreakFlag == 1)
2076 struct timeval before, after;
2078 gettimeofday(&before, NULL);
2089 &waitStatusStruct,
sizeof(waitStatusStruct),
2100 rv = unregisterFromEvents(currentContextMap);
2109 rv = waitStatusStruct.rv;
2114 rv = getReaderStatesAndRegisterForEvents(currentContextMap);
2122 gettimeofday(&after, NULL);
2124 dwTime -= diff/1000;
2144 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2149 (void)unregisterFromEvents(currentContextMap);
2151 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2156 for (j=0; j<cReaders; j++)
2158 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2159 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2217 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2218 LPDWORD lpBytesReturned)
2228 if (NULL != lpBytesReturned)
2229 *lpBytesReturned = 0;
2234 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2248 scControlStruct.hCard = hCard;
2249 scControlStruct.dwControlCode = dwControlCode;
2250 scControlStruct.cbSendLength = cbSendLength;
2251 scControlStruct.cbRecvLength = cbRecvLength;
2252 scControlStruct.dwBytesReturned = 0;
2253 scControlStruct.rv = 0;
2256 sizeof(scControlStruct), &scControlStruct);
2262 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2263 currentContextMap->dwClientID);
2272 currentContextMap->dwClientID);
2279 if (scControlStruct.dwBytesReturned > cbRecvLength)
2281 if (NULL != lpBytesReturned)
2282 *lpBytesReturned = scControlStruct.dwBytesReturned;
2288 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2289 currentContextMap->dwClientID);
2296 if (NULL != lpBytesReturned)
2297 *lpBytesReturned = scControlStruct.dwBytesReturned;
2299 rv = scControlStruct.rv;
2302 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2430 unsigned char *buf = NULL;
2434 if (NULL == pcbAttrLen)
2446 buf = malloc(*pcbAttrLen);
2453 *(
unsigned char **)pbAttr = buf;
2516 if (NULL == pbAttr || 0 == cbAttrLen)
2527static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2528 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2538 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2549 scGetSetStruct.hCard = hCard;
2550 scGetSetStruct.dwAttrId = dwAttrId;
2552 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2555 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2556 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2560 scGetSetStruct.cbAttrLen =
sizeof scGetSetStruct.pbAttr;
2563 sizeof(scGetSetStruct), &scGetSetStruct);
2572 currentContextMap->dwClientID);
2582 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2586 DWORD correct_value = scGetSetStruct.cbAttrLen;
2587 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2588 *pcbAttrLen = correct_value;
2593 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2596 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2598 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2600 rv = scGetSetStruct.rv;
2603 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2667 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2669 LPDWORD pcbRecvLength)
2678 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2679 pcbRecvLength == NULL || pioSendPci == NULL)
2688 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2703 scTransmitStruct.hCard = hCard;
2704 scTransmitStruct.cbSendLength = cbSendLength;
2705 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2706 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2707 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2712 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2713 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2722 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2728 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2745 if (scTransmitStruct.pcbRecvLength > *pcbRecvLength)
2747 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2753 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2761 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2762 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2766 rv = scTransmitStruct.rv;
2770 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2775 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2778 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2848 LPSTR mszReaders, LPDWORD pcchReaders)
2850 DWORD dwReadersLen = 0;
2858 API_TRACE_IN(
"%ld", hContext)
2863 if (pcchReaders == NULL)
2870 if (NULL == currentContextMap)
2877 rv = getReaderStates(currentContextMap);
2884 dwReadersLen += strlen(
readerStates[i].readerName) + 1;
2889 if (1 == dwReadersLen)
2897 if (NULL == mszReaders)
2902 buf = malloc(dwReadersLen);
2908 *(
char **)mszReaders = buf;
2915 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2922 if (mszReaders == NULL)
2940 *pcchReaders = dwReadersLen;
2942 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2945 API_TRACE_OUT(
"%d", *pcchReaders)
2975 free((
void *)pvMem);
3043 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
3044 const unsigned int dwGroups =
sizeof(ReaderGroup);
3050 if (NULL == currentContextMap)
3055 if (NULL == mszGroups)
3060 buf = malloc(dwGroups);
3066 *(
char **)mszGroups = buf;
3072 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3080 memcpy(buf, ReaderGroup, dwGroups);
3083 *pcchGroups = dwGroups;
3085 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3127 uint32_t dwClientID = 0;
3132 API_TRACE_IN(
"%ld", hContext)
3140 if (NULL == currentContextMap)
3162 scCancelStruct.hContext = hContext;
3166 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3174 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3179 rv = scCancelStruct.rv;
3218 API_TRACE_IN(
"%ld", hContext)
3256 if (NULL == newContextMap)
3259 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3260 newContextMap->
hContext = hContext;
3264 (void)pthread_mutex_init(&newContextMap->
mMutex, NULL);
3266 lrv = list_init(&newContextMap->channelMapList);
3269 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3273 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3274 CHANNEL_MAP_seeker);
3277 Log2(PCSC_LOG_CRITICAL,
3278 "list_attributes_seeker failed with return value: %d", lrv);
3279 list_destroy(&newContextMap->channelMapList);
3283 lrv = list_append(&contextMapList, newContextMap);
3286 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3288 list_destroy(&newContextMap->channelMapList);
3296 (void)pthread_mutex_destroy(&newContextMap->
mMutex);
3297 free(newContextMap);
3326 if (NULL != currentContextMap)
3327 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
3331 return currentContextMap;
3348 return list_seek(&contextMapList, &hContext);
3362 if (NULL != currentContextMap)
3363 SCardCleanContext(currentContextMap);
3366static void SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3368 int list_index, lrv;
3375 (void)pthread_mutex_destroy(&targetContextMap->
mMutex);
3377 listSize = list_size(&targetContextMap->channelMapList);
3378 for (list_index = 0; list_index < listSize; list_index++)
3380 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3382 if (NULL == currentChannelMap)
3384 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3390 free(currentChannelMap->readerName);
3391 free(currentChannelMap);
3395 list_destroy(&targetContextMap->channelMapList);
3397 lrv = list_delete(&contextMapList, targetContextMap);
3400 Log2(PCSC_LOG_CRITICAL,
3401 "list_delete failed with return value: %d", lrv);
3404 free(targetContextMap);
3420 if (NULL == newChannelMap)
3423 newChannelMap->hCard = hCard;
3424 newChannelMap->readerName = strdup(readerName);
3426 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3429 free(newChannelMap->readerName);
3430 free(newChannelMap);
3431 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3446 rv = SCardGetContextAndChannelFromHandleTH(hCard, ¤tContextMap,
3447 ¤tChannelMap);
3451 free(currentChannelMap->readerName);
3453 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3456 Log2(PCSC_LOG_CRITICAL,
3457 "list_delete failed with return value: %d", lrv);
3460 free(currentChannelMap);
3465static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE hCard,
3474 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3478 (void)pthread_mutex_lock(&(*targetContextMap)->mMutex);
3485static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3494 *targetContextMap = NULL;
3495 *targetChannelMap = NULL;
3497 listSize = list_size(&contextMapList);
3499 for (list_index = 0; list_index < listSize; list_index++)
3501 currentContextMap = list_get_at(&contextMapList, list_index);
3502 if (currentContextMap == NULL)
3504 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3508 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3510 if (currentChannelMap != NULL)
3512 *targetContextMap = currentContextMap;
3513 *targetChannelMap = currentChannelMap;
3531 struct stat statBuffer;
3534 socketName = getSocketName();
3535 rv = stat(socketName, &statBuffer);
3539 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3540 socketName, strerror(errno));
3547static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3549 int32_t dwClientID = currentContextMap->
dwClientID;
3564static LONG getReaderStatesAndRegisterForEvents(
SCONTEXTMAP * currentContextMap)
3566 int32_t dwClientID = currentContextMap->
dwClientID;
3580static LONG unregisterFromEvents(
SCONTEXTMAP * currentContextMap)
3582 int32_t dwClientID = currentContextMap->
dwClientID;
3588 dwClientID, 0, NULL);
3605 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.
LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
Releases memory that has been returned from the resource manager using the SCARD_AUTOALLOCATE length ...
LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
Set an attribute of the IFD Handler.
PCSC_API const char * pcsc_stringify_error(const LONG pcscError)
Returns a human readable text for the given PC/SC error code.
LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, SCARD_READERSTATE *rgReaderStates, DWORD cReaders)
Blocks execution until the current availability of the cards in a specific set of readers changes.
LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
Terminates a connection made through SCardConnect().
LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Establishes a connection to the reader specified in * szReader.
LONG SCardReleaseContext(SCARDCONTEXT hContext)
Destroys a communication context to the PC/SC Resource Manager.
LONG SCardIsValidContext(SCARDCONTEXT hContext)
Check if a SCARDCONTEXT is valid.
LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
Returns a list of currently available readers on the system.
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().
LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups)
Returns a list of currently available reader groups on the system.
LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
Creates an Application Context to the PC/SC Resource Manager.
LONG SCardCancel(SCARDCONTEXT hContext)
Cancels a specific blocking SCardGetStatusChange() function.
LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
Get an attribute from the IFD Handler (reader driver).
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.
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 SCardBeginTransaction(SCARDHANDLE hCard)
Establishes a temporary exclusive access mode for doing a serie of commands in a transaction.
LONG SCardStatus(SCARDHANDLE hCard, LPSTR szReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
Returns the current status of the reader connected to by hCard.
LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
Ends a previously begun transaction.
#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_F_COMM_ERROR
An internal communications error has been detected.
#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()