81 #include <sys/types.h>
112 #define SCARD_PROTOCOL_ANY_OLD 0x1000
119 static char sharing_shall_block = TRUE;
121 #define COLOR_RED "\33[01;31m"
122 #define COLOR_GREEN "\33[32m"
123 #define COLOR_BLUE "\33[34m"
124 #define COLOR_MAGENTA "\33[35m"
125 #define COLOR_NORMAL "\33[0m"
132 static void trace(
const char *func,
const char direction,
const char *fmt, ...)
136 fprintf(stderr, COLOR_GREEN
"%c " COLOR_BLUE
"[%lX] " COLOR_GREEN
"%s ",
137 direction, pthread_self(), func);
139 fprintf(stderr, COLOR_MAGENTA);
141 vfprintf(stderr, fmt, args);
144 fprintf(stderr, COLOR_NORMAL
"\n");
147 #define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__);
148 #define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__);
150 #define API_TRACE_IN(...)
151 #define API_TRACE_OUT(...)
156 #define PROFILE_FILE "/tmp/pcsc_profile"
158 #include <sys/time.h>
161 #define MAX_THREADS 5
162 pthread_t threads[MAX_THREADS];
163 struct timeval profile_time_start[MAX_THREADS];
167 #define PROFILE_START profile_start();
168 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
170 static void profile_start(
void)
172 static char initialized = FALSE;
181 sprintf(filename,
"%s-%d", PROFILE_FILE, getuid());
182 profile_fd = fopen(filename,
"a+");
183 if (NULL == profile_fd)
185 fprintf(stderr, COLOR_RED
"Can't open %s: %s" COLOR_NORMAL
"\n",
186 PROFILE_FILE, strerror(errno));
189 fprintf(profile_fd,
"\nStart a new profile\n");
191 if (isatty(fileno(stderr)))
198 for (i=0; i<MAX_THREADS; i++)
199 if (pthread_equal(0, threads[i]))
205 gettimeofday(&profile_time_start[i], NULL);
208 static void profile_end(
const char *f, LONG rv)
210 struct timeval profile_time_end;
215 gettimeofday(&profile_time_end, NULL);
218 for (i=0; i<MAX_THREADS; i++)
219 if (pthread_equal(t, threads[i]))
224 fprintf(stderr, COLOR_BLUE
" WARNING: no start info for %s\n", f);
228 d =
time_sub(&profile_time_end, &profile_time_start[i]);
237 COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld "
238 COLOR_BLUE
"0x%08lX %s" COLOR_NORMAL
"\n",
241 fprintf(stderr, COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld"
242 COLOR_NORMAL
"\n", f, d);
244 fprintf(profile_fd,
"%s %ld\n", f, d);
249 #define PROFILE_START
250 #define PROFILE_END(rv)
265 static int CHANNEL_MAP_seeker(
const void *el,
const void *key)
269 if ((el == NULL) || (key == NULL))
271 Log3(PCSC_LOG_CRITICAL,
272 "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
298 static list_t contextMapList;
300 static int SCONTEXTMAP_seeker(
const void *el,
const void *key)
304 if ((el == NULL) || (key == NULL))
306 Log3(PCSC_LOG_CRITICAL,
307 "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
350 static LONG SCardGetContextAndChannelFromHandle(
SCARDHANDLE,
352 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
356 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
357 LPBYTE pbAttr, LPDWORD pcbAttrLen);
359 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
372 return pthread_mutex_lock(&clientMutex);
382 return pthread_mutex_unlock(&clientMutex);
422 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
426 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
440 pvReserved2, phContext);
445 API_TRACE_OUT(
"%ld", *phContext)
478 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
482 uint32_t dwClientID = 0;
486 if (phContext == NULL)
503 lrv = list_init(&contextMapList);
506 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
511 lrv = list_attributes_seeker(&contextMapList,
515 Log2(PCSC_LOG_CRITICAL,
516 "list_attributes_seeker failed with return value: %d", lrv);
517 list_destroy(&contextMapList);
521 if (getenv(
"PCSCLITE_NO_BLOCKING"))
523 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
524 sharing_shall_block = FALSE;
553 Log1(PCSC_LOG_CRITICAL,
554 "Your pcscd is too old and does not support CMD_VERSION");
558 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
569 scEstablishStruct.dwScope = dwScope;
570 scEstablishStruct.hContext = 0;
574 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
582 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
589 return scEstablishStruct.rv;
597 *phContext = scEstablishStruct.hContext;
634 API_TRACE_IN(
"%ld", hContext)
642 if (NULL == currentContextMap)
648 (void)pthread_mutex_lock(¤tContextMap->mMutex);
652 if (NULL == currentContextMap)
661 scReleaseStruct.hContext = hContext;
665 currentContextMap->dwClientID,
666 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
675 currentContextMap->dwClientID);
680 rv = scReleaseStruct.rv;
682 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
755 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
756 LPDWORD pdwActiveProtocol)
763 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
768 if (phCard == NULL || pdwActiveProtocol == NULL)
773 if (szReader == NULL)
779 if (strlen(szReader) > MAX_READERNAME)
786 if (NULL == currentContextMap)
789 (void)pthread_mutex_lock(¤tContextMap->mMutex);
793 if (NULL == currentContextMap)
799 strlcpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
801 scConnectStruct.hContext = hContext;
802 scConnectStruct.dwShareMode = dwShareMode;
803 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
804 scConnectStruct.hCard = 0;
805 scConnectStruct.dwActiveProtocol = 0;
809 sizeof(scConnectStruct), (
void *) &scConnectStruct);
818 currentContextMap->dwClientID);
823 *phCard = scConnectStruct.hCard;
824 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
831 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
834 rv = scConnectStruct.rv;
837 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
840 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
919 DWORD dwPreferredProtocols, DWORD dwInitialization,
920 LPDWORD pdwActiveProtocol)
929 if (pdwActiveProtocol == NULL)
935 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
943 (void)pthread_mutex_lock(¤tContextMap->mMutex);
946 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
956 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
960 scReconnectStruct.hCard = hCard;
961 scReconnectStruct.dwShareMode = dwShareMode;
962 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
963 scReconnectStruct.dwInitialization = dwInitialization;
964 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
968 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
976 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
977 currentContextMap->dwClientID);
982 rv = scReconnectStruct.rv;
986 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
991 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
994 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1040 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1045 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1053 (void)pthread_mutex_lock(¤tContextMap->mMutex);
1056 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1066 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1071 scDisconnectStruct.hCard = hCard;
1072 scDisconnectStruct.dwDisposition = dwDisposition;
1076 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1084 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1085 currentContextMap->dwClientID);
1091 (void)SCardRemoveHandle(hCard);
1092 rv = scDisconnectStruct.rv;
1095 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1152 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1164 (void)pthread_mutex_lock(¤tContextMap->mMutex);
1167 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1177 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1181 scBeginStruct.hCard = hCard;
1185 currentContextMap->dwClientID,
1186 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1195 currentContextMap->dwClientID);
1200 rv = scBeginStruct.rv;
1205 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1209 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1269 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1274 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
1277 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1287 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
1291 scEndStruct.hCard = hCard;
1292 scEndStruct.dwDisposition = dwDisposition;
1297 sizeof(scEndStruct), (
void *) &scEndStruct);
1314 randnum = SYS_RandomInt(1000, 10000);
1316 rv = scEndStruct.rv;
1319 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
1422 LPDWORD pcchReaderLen, LPDWORD pdwState,
1423 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1425 DWORD dwReaderLen, dwAtrLen;
1432 char *bufReader = NULL;
1433 LPBYTE bufAtr = NULL;
1446 if (pcchReaderLen == NULL)
1447 pcchReaderLen = &dummy;
1449 if (pcbAtrLen == NULL)
1453 dwReaderLen = *pcchReaderLen;
1454 dwAtrLen = *pcbAtrLen;
1462 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1470 (void)pthread_mutex_lock(¤tContextMap->mMutex);
1473 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1483 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1488 rv = getReaderStates(currentContextMap);
1492 r = pChannelMap->readerName;
1496 if (r && strcmp(r, readerStates[i].readerName) == 0)
1500 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1507 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1508 scStatusStruct.hCard = hCard;
1511 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1520 currentContextMap->dwClientID);
1525 rv = scStatusStruct.rv;
1529 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1546 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1550 *pdwState = (readerStates[i].
eventCounter << 16) + readerStates[i].readerState;
1557 dwReaderLen = *pcchReaderLen;
1558 if (NULL == mszReaderName)
1563 bufReader = malloc(dwReaderLen);
1564 if (NULL == bufReader)
1569 *(
char **)mszReaderName = bufReader;
1572 bufReader = mszReaderName;
1577 if (*pcchReaderLen > dwReaderLen)
1580 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1585 dwAtrLen = *pcbAtrLen;
1591 bufAtr = malloc(dwAtrLen);
1597 *(LPBYTE *)pbAtr = bufAtr;
1604 if (*pcbAtrLen > dwAtrLen)
1607 memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1611 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1717 DWORD dwBreakFlag = 0;
1720 int currentReaderCount = 0;
1724 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1726 for (j=0; j<cReaders; j++)
1728 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1729 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1733 if ((rgReaderStates == NULL && cReaders > 0)
1741 for (j = 0; j < cReaders; j++)
1743 if (rgReaderStates[j].szReader == NULL)
1750 int nbNonIgnoredReaders = cReaders;
1752 for (j=0; j<cReaders; j++)
1754 nbNonIgnoredReaders--;
1756 if (0 == nbNonIgnoredReaders)
1773 if (NULL == currentContextMap)
1779 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
1783 if (NULL == currentContextMap)
1793 rv = getReaderStates(currentContextMap);
1798 for (j=0; j<cReaders; j++)
1800 const char *readerName;
1803 readerName = rgReaderStates[j].szReader;
1806 if (strcmp(readerName, readerStates[i].readerName) == 0)
1811 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1814 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1823 for (j = 0; j < cReaders; j++)
1824 rgReaderStates[j].dwEventState = 0;
1827 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1831 if (readerStates[j].readerName[0] !=
'\0')
1832 currentReaderCount++;
1835 if ((DWORD)-1 == dwTimeout)
1845 currReader = &rgReaderStates[j];
1850 const char *readerName;
1854 readerName = currReader->szReader;
1857 if (strcmp(readerName, readerStates[i].readerName) == 0)
1862 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1865 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1867 int k, newReaderCount = 0;
1870 if (readerStates[k].readerName[0] !=
'\0')
1873 if (newReaderCount != currentReaderCount)
1875 Log1(PCSC_LOG_INFO,
"Reader list changed");
1876 currentReaderCount = newReaderCount;
1884 currReader->dwEventState =
1900 uint32_t readerState;
1907 Log0(PCSC_LOG_DEBUG);
1912 rContext = &readerStates[i];
1918 if (currReader->dwCurrentState & 0xFFFF0000)
1920 unsigned int currentCounter;
1922 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1928 Log0(PCSC_LOG_DEBUG);
1934 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1946 Log0(PCSC_LOG_DEBUG);
1955 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1957 Log0(PCSC_LOG_DEBUG);
1971 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1975 currReader->cbAtr = 0;
1994 Log0(PCSC_LOG_DEBUG);
1999 else if (readerState & SCARD_PRESENT)
2012 Log0(PCSC_LOG_DEBUG);
2022 Log0(PCSC_LOG_DEBUG);
2032 Log0(PCSC_LOG_DEBUG);
2046 Log0(PCSC_LOG_DEBUG);
2053 if (readerState & SCARD_PRESENT)
2060 Log0(PCSC_LOG_DEBUG);
2073 Log0(PCSC_LOG_DEBUG);
2076 else if (currReader-> dwCurrentState
2080 Log0(PCSC_LOG_DEBUG);
2092 Log0(PCSC_LOG_DEBUG);
2108 if (dwBreakFlag == 1)
2114 struct timeval before, after;
2116 gettimeofday(&before, NULL);
2118 waitStatusStruct.
timeOut = dwTime;
2126 sizeof(waitStatusStruct), &waitStatusStruct);
2135 &waitStatusStruct,
sizeof(waitStatusStruct),
2147 sizeof(waitStatusStruct), &waitStatusStruct);
2154 sizeof(waitStatusStruct),
2167 rv = waitStatusStruct.rv;
2172 rv = getReaderStates(currentContextMap);
2180 gettimeofday(&after, NULL);
2182 dwTime -= diff/1000;
2202 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2204 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2209 for (j=0; j<cReaders; j++)
2211 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2212 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2270 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2271 LPDWORD lpBytesReturned)
2281 if (NULL != lpBytesReturned)
2282 *lpBytesReturned = 0;
2287 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2295 (void)pthread_mutex_lock(¤tContextMap->mMutex);
2298 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2308 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2319 scControlStruct.hCard = hCard;
2320 scControlStruct.dwControlCode = dwControlCode;
2321 scControlStruct.cbSendLength = cbSendLength;
2322 scControlStruct.cbRecvLength = cbRecvLength;
2323 scControlStruct.dwBytesReturned = 0;
2324 scControlStruct.rv = 0;
2327 sizeof(scControlStruct), &scControlStruct);
2333 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2334 currentContextMap->dwClientID);
2343 currentContextMap->dwClientID);
2351 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2352 currentContextMap->dwClientID);
2359 if (NULL != lpBytesReturned)
2360 *lpBytesReturned = scControlStruct.dwBytesReturned;
2362 rv = scControlStruct.rv;
2365 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2480 unsigned char *buf = NULL;
2484 if (NULL == pcbAttrLen)
2496 buf = malloc(*pcbAttrLen);
2503 *(
unsigned char **)pbAttr = buf;
2566 if (NULL == pbAttr || 0 == cbAttrLen)
2577 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2578 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2588 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2593 (void)pthread_mutex_lock(¤tContextMap->mMutex);
2596 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2606 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2616 scGetSetStruct.hCard = hCard;
2617 scGetSetStruct.dwAttrId = dwAttrId;
2618 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2620 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2622 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2625 sizeof(scGetSetStruct), &scGetSetStruct);
2634 currentContextMap->dwClientID);
2644 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2646 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2650 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2653 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2655 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2657 rv = scGetSetStruct.rv;
2660 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2724 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2726 LPDWORD pcbRecvLength)
2735 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2736 pcbRecvLength == NULL || pioSendPci == NULL)
2742 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2754 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
2757 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2767 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2778 scTransmitStruct.hCard = hCard;
2779 scTransmitStruct.cbSendLength = cbSendLength;
2780 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2781 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2782 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2787 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2788 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2797 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2803 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2821 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2829 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2830 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2834 rv = scTransmitStruct.rv;
2838 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2843 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2846 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2904 LPSTR mszReaders, LPDWORD pcchReaders)
2906 DWORD dwReadersLen = 0;
2914 API_TRACE_IN(
"%ld", hContext)
2919 if (pcchReaders == NULL)
2926 if (NULL == currentContextMap)
2932 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
2936 if (NULL == currentContextMap)
2943 rv = getReaderStates(currentContextMap);
2949 if (readerStates[i].readerName[0] !=
'\0')
2950 dwReadersLen += strlen(readerStates[i].readerName) + 1;
2955 if (1 == dwReadersLen)
2963 buf = malloc(dwReadersLen);
2969 if (NULL == mszReaders)
2974 *(
char **)mszReaders = buf;
2981 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2988 if (mszReaders == NULL)
2993 if (readerStates[i].readerName[0] !=
'\0')
2998 strcpy(buf, readerStates[i].readerName);
2999 buf += strlen(readerStates[i].readerName)+1;
3006 *pcchReaders = dwReadersLen;
3008 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3011 API_TRACE_OUT(
"%d", *pcchReaders)
3040 if (NULL == currentContextMap)
3043 free((
void *)pvMem);
3111 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
3112 const unsigned int dwGroups =
sizeof(ReaderGroup);
3118 if (NULL == currentContextMap)
3121 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
3125 if (NULL == currentContextMap)
3133 if (NULL == mszGroups)
3138 buf = malloc(dwGroups);
3144 *(
char **)mszGroups = buf;
3150 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3158 memcpy(buf, ReaderGroup, dwGroups);
3161 *pcchGroups = dwGroups;
3163 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3203 uint32_t dwClientID = 0;
3207 API_TRACE_IN(
"%ld", hContext)
3213 if (NULL == currentContextMap)
3219 if (! currentContextMap->cancellable)
3232 scCancelStruct.hContext = hContext;
3236 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3244 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3249 rv = scCancelStruct.rv;
3289 API_TRACE_IN(
"%ld", hContext)
3297 if (currentContextMap == NULL)
3328 if (NULL == newContextMap)
3331 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3332 newContextMap->
hContext = hContext;
3336 (void)pthread_mutex_init(&newContextMap->
mMutex, NULL);
3338 lrv = list_init(&newContextMap->channelMapList);
3341 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3345 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3346 CHANNEL_MAP_seeker);
3349 Log2(PCSC_LOG_CRITICAL,
3350 "list_attributes_seeker failed with return value: %d", lrv);
3351 list_destroy(&newContextMap->channelMapList);
3355 lrv = list_append(&contextMapList, newContextMap);
3358 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3360 list_destroy(&newContextMap->channelMapList);
3368 (void)pthread_mutex_destroy(&newContextMap->
mMutex);
3369 free(newContextMap);
3394 return currentContextMap;
3411 return list_seek(&contextMapList, &hContext);
3428 if (NULL == currentContextMap)
3431 return SCardCleanContext(currentContextMap);
3434 static LONG SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3436 int list_index, lrv;
3443 (void)pthread_mutex_destroy(&targetContextMap->
mMutex);
3445 listSize = list_size(&targetContextMap->channelMapList);
3446 for (list_index = 0; list_index < listSize; list_index++)
3448 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3450 if (NULL == currentChannelMap)
3452 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3458 free(currentChannelMap->readerName);
3459 free(currentChannelMap);
3463 list_destroy(&targetContextMap->channelMapList);
3465 lrv = list_delete(&contextMapList, targetContextMap);
3468 Log2(PCSC_LOG_CRITICAL,
3469 "list_delete failed with return value: %d", lrv);
3472 free(targetContextMap);
3488 if (NULL == newChannelMap)
3491 newChannelMap->hCard = hCard;
3492 newChannelMap->readerName = strdup(readerName);
3494 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3497 free(newChannelMap->readerName);
3498 free(newChannelMap);
3499 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3514 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
3515 ¤tChannelMap);
3519 free(currentChannelMap->readerName);
3521 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3524 Log2(PCSC_LOG_CRITICAL,
3525 "list_delete failed with return value: %d", lrv);
3528 free(currentChannelMap);
3533 static LONG SCardGetContextAndChannelFromHandle(
SCARDHANDLE hCard,
3542 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3549 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3558 *targetContextMap = NULL;
3559 *targetChannelMap = NULL;
3561 listSize = list_size(&contextMapList);
3563 for (list_index = 0; list_index < listSize; list_index++)
3565 currentContextMap = list_get_at(&contextMapList, list_index);
3566 if (currentContextMap == NULL)
3568 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3572 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3574 if (currentChannelMap != NULL)
3576 *targetContextMap = currentContextMap;
3577 *targetChannelMap = currentChannelMap;
3599 struct stat statBuffer;
3602 socketName = getSocketName();
3603 rv = stat(socketName, &statBuffer);
3607 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3608 socketName, strerror(errno));
3615 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3617 int32_t dwClientID = currentContextMap->
dwClientID;
3625 rv =
MessageReceive(&readerStates,
sizeof(readerStates), dwClientID);
used by SCardBeginTransaction()
contained in SCARD_CONNECT Messages.
uint32_t cardAtrLength
ATR length.
static SCONTEXTMAP * SCardGetContext(SCARDCONTEXT)
Get the index from the Application Context vector _psContextMap for the passed context.
wait for a reader state change
contained in SCARD_CANCEL Messages.
contained in SCARD_TRANSMIT Messages.
#define SCARD_STATE_UNAVAILABLE
Status unavailable.
LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LPDWORD pcchReaders)
Returns a list of currently available readers on the system.
contained in SCARD_END_TRANSACTION Messages.
#define SCARD_E_READER_UNAVAILABLE
The specified reader is not currently available for use.
#define PCSCLITE_SHARING_NO_CONTEXT
No application is using the reader.
INTERNAL int ClientCloseSession(uint32_t dwClientID)
Closes the socket used by the client to communicate with the server.
#define MAX_BUFFER_SIZE
Maximum Tx/Rx Buffer for short APDU.
LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, LPDWORD pcchGroups)
Returns a list of currently available reader groups on the system.
#define SCARD_STATE_EMPTY
Card removed.
get the client/server protocol version
static SCONTEXTMAP * SCardGetContextTH(SCARDCONTEXT)
Get the address from the Application Context list _psContextMap for the passed context.
#define SCARD_STATE_IGNORE
Ignore this reader.
#define SCARD_UNKNOWN
Unknown state.
PCSC_API char * pcsc_stringify_error(const LONG pcscError)
Returns a human readable text for the given PC/SC error code.
static short isExecuted
Make sure the initialization code is executed only once.
used by SCardEstablishContext()
PCSC_API const SCARD_IO_REQUEST g_rgSCardT1Pci
Protocol Control Information for T=1.
INTERNAL LONG MessageSendWithHeader(uint32_t command, uint32_t dwClientID, uint64_t size, void *data_void)
Wrapper for the MessageSend() function.
int32_t minor
IPC minor PROTOCOL_VERSION_MINOR.
#define SCARD_F_COMM_ERROR
An internal communications error has been detected.
used by SCardEndTransaction()
LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
Creates an Application Context to the PC/SC Resource Manager.
unsigned long cbPciLength
Protocol Control Inf Length.
int32_t readerSharing
PCSCLITE_SHARING_* sharing status.
#define SCARD_E_INVALID_PARAMETER
One or more of the supplied parameters could not be properly interpreted.
#define SCARD_STATE_CHANGED
State has changed.
This handles abstract system level calls.
static LONG SCardRemoveContext(SCARDCONTEXT)
Removes an Application Context from a control vector.
#define SCARD_E_NO_SERVICE
The Smart card resource manager is not running.
uint32_t eventCounter
number of card events
#define SCARD_E_NO_READERS_AVAILABLE
Cannot find a smart card reader.
static LONG SCardUnlockThread(void)
Unlocks a mutex so another thread may use the client.
PCSC_API const SCARD_IO_REQUEST g_rgSCardRawPci
Protocol Control Information for raw access.
#define PROTOCOL_VERSION_MAJOR
Major version of the current message protocol.
#define SCARD_PROTOCOL_T1
T=1 active protocol.
contained in SCARD_DISCONNECT Messages.
LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem)
Releases memory that has been returned from the resource manager using the SCARD_AUTOALLOCATE length ...
LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, SCARD_READERSTATE *rgReaderStates, DWORD cReaders)
Blocks execution until the current availability of the cards in a specific set of readers changes...
#define SCARD_E_INVALID_HANDLE
The supplied handle was invalid.
LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr, LPDWORD pcbAttrLen)
Get an attribute from the IFD Handler (reader driver).
#define SCARD_PRESENT
Card is present.
Information contained in SCARD_RELEASE_CONTEXT Messages.
LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
Terminates a connection made through SCardConnect().
LONG SCardCancel(SCARDCONTEXT hContext)
Cancels all pending blocking requests on the SCardGetStatusChange() function.
int SYS_USleep(int)
Makes the current process sleep for some microseconds.
contained in SCARD_BEGIN_TRANSACTION Messages.
#define PCSCLITE_SHARING_EXCLUSIVE_CONTEXT
Reader used in exclusive mode.
LONG SCardIsValidContext(SCARDCONTEXT hContext)
Check if a SCARDCONTEXT is valid.
static LONG SCardEstablishContextTH(DWORD, LPCVOID, LPCVOID, LPSCARDCONTEXT)
Creates a communication context to the PC/SC Resource Manager.
#define INFINITE
Infinite timeout.
#define SCARD_STATE_UNKNOWN
Reader unknown.
Represents the an Application Context on the Client side.
Information contained in SCARD_ESTABLISH_CONTEXT Messages.
#define PCSCLITE_LOCK_POLL_RATE
Lock polling rate.
#define SCARD_AUTOALLOCATE
see SCardFreeMemory()
Information transmitted in CMD_VERSION Messages.
INTERNAL LONG MessageReceive(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Called by the Client to get the reponse from the server or vice-versa.
used by SCardReleaseContext()
LONG SCARDCONTEXT
hContext returned by SCardEstablishContext()
#define SCARD_E_INVALID_VALUE
One or more of the supplied parameters values could not be properly interpreted.
contained in SCARD_STATUS Messages.
contained in SCARD_RECONNECT Messages.
unsigned long dwProtocol
Protocol identifier.
uint32_t timeOut
timeout in ms
#define PCSCLITE_MAX_READERS_CONTEXTS
Maximum readers context (a slot is count as a reader)
contained in SCARD_GET_ATTRIB and Messages.
prototypes of strlcpy()/strlcat() imported from OpenBSD
#define SCARD_STATE_PRESENT
Card inserted.
PCSC_API const SCARD_IO_REQUEST g_rgSCardT0Pci
Protocol Control Information for T=0.
This defines some structures and #defines to be used over the transport layer.
Information contained in CMD_WAIT_READER_STATE_CHANGE Messages.
DWORD dwClientID
Client Connection ID.
#define SCARD_PROTOCOL_T0
T=0 active protocol.
#define SCARD_STATE_ATRMATCH
ATR matches card.
LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode, DWORD dwPreferredProtocols, DWORD dwInitialization, LPDWORD pdwActiveProtocol)
Reestablishes a connection to a reader that was previously connected to using SCardConnect().
long int time_sub(struct timeval *a, struct timeval *b)
return the difference (as long int) in µs between 2 struct timeval r = a - b
#define MAX_BUFFER_SIZE_EXTENDED
enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer
static READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS]
Area used to read status information about the readers.
#define PCSCLITE_STATUS_POLL_RATE
Status polling rate.
Represents an Application Context Channel.
This handles card insertion/removal events, updates ATR, protocol, and status information.
SCARDCONTEXT hContext
Application Context ID.
#define SCARD_PROTOCOL_ANY
IFD determines prot.
char cancellable
We are in a cancellable call.
stop waiting for a reader state change
LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol)
Establishes a connection to the reader specified in * szReader.
LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
Returns the current status of the reader connected to by hCard.
LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr, DWORD cbAttrLen)
Set an attribute of the IFD Handler.
#define SCARD_STATE_EXCLUSIVE
Exclusive Mode.
#define SCARD_SWALLOWED
Card not powered.
static LONG SCardAddContext(SCARDCONTEXT, DWORD)
Functions for managing instances of SCardEstablishContext() These functions keep track of Context han...
UCHAR cardAtr[MAX_ATR_SIZE]
ATR.
LONG SCARDHANDLE
hCard returned by SCardConnect()
static LONG SCardLockThread(void)
Locks a mutex so another thread must wait to use this function.
LONG SCardCheckDaemonAvailability(void)
Checks if the server is running.
INTERNAL int ClientSetupSession(uint32_t *pdwClientID)
Prepares a communication channel for the client to talk to the server.
#define PROTOCOL_VERSION_MINOR
Minor version of the current message protocol.
LONG SCardBeginTransaction(SCARDHANDLE hCard)
Establishes a temporary exclusive access mode for doing a serie of commands in a transaction.
This keeps a list of defines for pcsc-lite.
#define SCARD_PROTOCOL_RAW
Raw active protocol.
#define SCARD_STATE_INUSE
Shared Mode.
Protocol Control Information (PCI)
LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
Sends a command directly to the IFD Handler (reader driver) to be processed by the reader...
#define SCARD_E_SHARING_VIOLATION
The smart card cannot be accessed because of other connections outstanding.
#define SCARD_ABSENT
Card is absent.
uint32_t cardProtocol
SCARD_PROTOCOL_* value.
Define an exported public reader state structure so each application gets instant notification of cha...
INTERNAL LONG MessageSend(void *buffer_void, uint64_t buffer_size, int32_t filedes)
Sends a menssage from client to server or vice-versa.
used by SCardDisconnect()
#define SCARD_E_NO_MEMORY
Not enough memory available to complete this command.
contained in SCARD_CONTROL Messages.
This keeps track of a list of currently available reader structures.
pthread_mutex_t mMutex
Mutex for this context.
static pthread_mutex_t clientMutex
Ensure that some functions be accessed in thread-safe mode.
uint32_t readerState
SCARD_* bit field.
#define SCARD_E_INSUFFICIENT_BUFFER
The data buffer to receive returned data is too small for the returned data.
#define PCSCLITE_SHARING_LAST_CONTEXT
One application is using the reader.
int32_t major
IPC major PROTOCOL_VERSION_MAJOR.
LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
Ends a previously begun transaction.
LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, LPCBYTE pbSendBuffer, DWORD cbSendLength, SCARD_IO_REQUEST *pioRecvPci, LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength)
Sends an APDU to the smart card contained in the reader connected to by SCardConnect().
#define SCARD_E_UNKNOWN_READER
The specified reader name is not recognized.
#define SCARD_S_SUCCESS
error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx
This handles smart card reader communications.
LONG SCardReleaseContext(SCARDCONTEXT hContext)
Destroys a communication context to the PC/SC Resource Manager.
INTERNAL LONG MessageReceiveTimeout(uint32_t command, void *buffer_void, uint64_t buffer_size, int32_t filedes, long timeOut)
Called by the Client to get the reponse from the server or vice-versa.
#define SCARD_E_TIMEOUT
The user-specified timeout value has expired.
#define SCARD_STATE_UNAWARE
App wants status.
#define SCARD_STATE_MUTE
Unresponsive card.