104 #include <sys/types.h>
110 #include <sys/time.h>
112 #include <sys/wait.h>
135 #define SCARD_PROTOCOL_ANY_OLD 0x1000
142 static char sharing_shall_block = TRUE;
144 #define COLOR_RED "\33[01;31m"
145 #define COLOR_GREEN "\33[32m"
146 #define COLOR_BLUE "\33[34m"
147 #define COLOR_MAGENTA "\33[35m"
148 #define COLOR_NORMAL "\33[0m"
155 static void trace(
const char *func,
const char direction,
const char *fmt, ...)
159 fprintf(stderr, COLOR_GREEN
"%c " COLOR_BLUE
"[%lX] " COLOR_GREEN
"%s ",
160 direction, pthread_self(), func);
162 fprintf(stderr, COLOR_MAGENTA);
164 vfprintf(stderr, fmt, args);
167 fprintf(stderr, COLOR_NORMAL
"\n");
170 #define API_TRACE_IN(...) trace(__FUNCTION__, '<', __VA_ARGS__);
171 #define API_TRACE_OUT(...) trace(__FUNCTION__, '>', __VA_ARGS__);
173 #define API_TRACE_IN(...)
174 #define API_TRACE_OUT(...)
179 #define PROFILE_FILE "/tmp/pcsc_profile"
181 #include <sys/time.h>
184 #define MAX_THREADS 5
185 pthread_t threads[MAX_THREADS];
186 struct timeval profile_time_start[MAX_THREADS];
190 #define PROFILE_START profile_start();
191 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
193 static void profile_start(
void)
195 static char initialized = FALSE;
204 sprintf(filename,
"%s-%d", PROFILE_FILE, getuid());
205 profile_fd = fopen(filename,
"a+");
206 if (NULL == profile_fd)
208 fprintf(stderr, COLOR_RED
"Can't open %s: %s" COLOR_NORMAL
"\n",
209 PROFILE_FILE, strerror(errno));
212 fprintf(profile_fd,
"\nStart a new profile\n");
214 if (isatty(fileno(stderr)))
221 for (i=0; i<MAX_THREADS; i++)
222 if (pthread_equal(0, threads[i]))
228 gettimeofday(&profile_time_start[i], NULL);
231 static void profile_end(
const char *f, LONG rv)
233 struct timeval profile_time_end;
238 gettimeofday(&profile_time_end, NULL);
241 for (i=0; i<MAX_THREADS; i++)
242 if (pthread_equal(t, threads[i]))
247 fprintf(stderr, COLOR_BLUE
" WARNING: no start info for %s\n", f);
251 d =
time_sub(&profile_time_end, &profile_time_start[i]);
260 COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld "
261 COLOR_BLUE
"0x%08lX %s" COLOR_NORMAL
"\n",
264 fprintf(stderr, COLOR_RED
"RESULT %s " COLOR_MAGENTA
"%ld"
265 COLOR_NORMAL
"\n", f, d);
267 fprintf(profile_fd,
"%s %ld\n", f, d);
272 #define PROFILE_START
273 #define PROFILE_END(rv)
288 static int CHANNEL_MAP_seeker(
const void *el,
const void *key)
292 if ((el == NULL) || (key == NULL))
294 Log3(PCSC_LOG_CRITICAL,
295 "CHANNEL_MAP_seeker called with NULL pointer: el=%p, key=%p",
321 static list_t contextMapList;
323 static int SCONTEXTMAP_seeker(
const void *el,
const void *key)
327 if ((el == NULL) || (key == NULL))
329 Log3(PCSC_LOG_CRITICAL,
330 "SCONTEXTMAP_seeker called with NULL pointer: el=%p, key=%p",
373 static LONG SCardGetContextAndChannelFromHandle(
SCARDHANDLE,
375 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
379 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
380 LPBYTE pbAttr, LPDWORD pcbAttrLen);
382 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
395 return pthread_mutex_lock(&clientMutex);
405 return pthread_mutex_unlock(&clientMutex);
445 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
449 API_TRACE_IN(
"%ld, %p, %p", dwScope, pvReserved1, pvReserved2)
463 pvReserved2, phContext);
468 API_TRACE_OUT(
"%ld", *phContext)
501 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
505 uint32_t dwClientID = 0;
509 if (phContext == NULL)
526 lrv = list_init(&contextMapList);
529 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
534 lrv = list_attributes_seeker(&contextMapList,
538 Log2(PCSC_LOG_CRITICAL,
539 "list_attributes_seeker failed with return value: %d", lrv);
540 list_destroy(&contextMapList);
544 if (getenv(
"PCSCLITE_NO_BLOCKING"))
546 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
547 sharing_shall_block = FALSE;
576 Log1(PCSC_LOG_CRITICAL,
577 "Your pcscd is too old and does not support CMD_VERSION");
581 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
592 scEstablishStruct.dwScope = dwScope;
593 scEstablishStruct.hContext = 0;
597 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
605 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
612 return scEstablishStruct.rv;
620 *phContext = scEstablishStruct.hContext;
657 API_TRACE_IN(
"%ld", hContext)
665 if (NULL == currentContextMap)
671 (void)pthread_mutex_lock(¤tContextMap->mMutex);
675 if (NULL == currentContextMap)
684 scReleaseStruct.hContext = hContext;
688 currentContextMap->dwClientID,
689 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
698 currentContextMap->dwClientID);
703 rv = scReleaseStruct.rv;
705 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
778 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
779 LPDWORD pdwActiveProtocol)
786 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
791 if (phCard == NULL || pdwActiveProtocol == NULL)
796 if (szReader == NULL)
802 if (strlen(szReader) > MAX_READERNAME)
809 if (NULL == currentContextMap)
812 (void)pthread_mutex_lock(¤tContextMap->mMutex);
816 if (NULL == currentContextMap)
822 strlcpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
824 scConnectStruct.hContext = hContext;
825 scConnectStruct.dwShareMode = dwShareMode;
826 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
827 scConnectStruct.hCard = 0;
828 scConnectStruct.dwActiveProtocol = 0;
832 sizeof(scConnectStruct), (
void *) &scConnectStruct);
841 currentContextMap->dwClientID);
846 *phCard = scConnectStruct.hCard;
847 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
854 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
857 rv = scConnectStruct.rv;
860 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
863 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
942 DWORD dwPreferredProtocols, DWORD dwInitialization,
943 LPDWORD pdwActiveProtocol)
952 if (pdwActiveProtocol == NULL)
958 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
966 (void)pthread_mutex_lock(¤tContextMap->mMutex);
969 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
979 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
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);
1063 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1068 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1076 (void)pthread_mutex_lock(¤tContextMap->mMutex);
1079 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1089 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1094 scDisconnectStruct.hCard = hCard;
1095 scDisconnectStruct.dwDisposition = dwDisposition;
1099 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1107 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1108 currentContextMap->dwClientID);
1114 (void)SCardRemoveHandle(hCard);
1115 rv = scDisconnectStruct.rv;
1118 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1175 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1187 (void)pthread_mutex_lock(¤tContextMap->mMutex);
1190 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1200 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1204 scBeginStruct.hCard = hCard;
1208 currentContextMap->dwClientID,
1209 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1218 currentContextMap->dwClientID);
1223 rv = scBeginStruct.rv;
1228 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1232 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1292 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1297 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
1300 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1310 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
1314 scEndStruct.hCard = hCard;
1315 scEndStruct.dwDisposition = dwDisposition;
1320 sizeof(scEndStruct), (
void *) &scEndStruct);
1337 randnum = SYS_RandomInt(1000, 10000);
1339 rv = scEndStruct.rv;
1342 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
1445 LPDWORD pcchReaderLen, LPDWORD pdwState,
1446 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1448 DWORD dwReaderLen, dwAtrLen;
1455 char *bufReader = NULL;
1456 LPBYTE bufAtr = NULL;
1469 if (pcchReaderLen == NULL)
1470 pcchReaderLen = &dummy;
1472 if (pcbAtrLen == NULL)
1476 dwReaderLen = *pcchReaderLen;
1477 dwAtrLen = *pcbAtrLen;
1485 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1493 (void)pthread_mutex_lock(¤tContextMap->mMutex);
1496 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
1506 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1511 rv = getReaderStates(currentContextMap);
1515 r = pChannelMap->readerName;
1519 if (r && strcmp(r, readerStates[i].readerName) == 0)
1523 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1530 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1531 scStatusStruct.hCard = hCard;
1534 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1543 currentContextMap->dwClientID);
1548 rv = scStatusStruct.rv;
1552 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1569 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1573 *pdwState = (readerStates[i].
eventCounter << 16) + readerStates[i].readerState;
1580 dwReaderLen = *pcchReaderLen;
1581 if (NULL == mszReaderName)
1586 bufReader = malloc(dwReaderLen);
1587 if (NULL == bufReader)
1592 *(
char **)mszReaderName = bufReader;
1595 bufReader = mszReaderName;
1600 if (*pcchReaderLen > dwReaderLen)
1603 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1608 dwAtrLen = *pcbAtrLen;
1614 bufAtr = malloc(dwAtrLen);
1620 *(LPBYTE *)pbAtr = bufAtr;
1627 if (*pcbAtrLen > dwAtrLen)
1630 memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1634 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1740 DWORD dwBreakFlag = 0;
1743 int currentReaderCount = 0;
1747 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1749 for (j=0; j<cReaders; j++)
1751 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1752 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1756 if ((rgReaderStates == NULL && cReaders > 0)
1764 for (j = 0; j < cReaders; j++)
1766 if (rgReaderStates[j].szReader == NULL)
1773 int nbNonIgnoredReaders = cReaders;
1775 for (j=0; j<cReaders; j++)
1777 nbNonIgnoredReaders--;
1779 if (0 == nbNonIgnoredReaders)
1796 if (NULL == currentContextMap)
1802 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
1806 if (NULL == currentContextMap)
1816 rv = getReaderStates(currentContextMap);
1821 for (j=0; j<cReaders; j++)
1823 const char *readerName;
1826 readerName = rgReaderStates[j].szReader;
1829 if (strcmp(readerName, readerStates[i].readerName) == 0)
1834 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1837 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1846 for (j = 0; j < cReaders; j++)
1847 rgReaderStates[j].dwEventState = 0;
1850 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1854 if (readerStates[j].readerName[0] !=
'\0')
1855 currentReaderCount++;
1858 if ((DWORD)-1 == dwTimeout)
1868 currReader = &rgReaderStates[j];
1873 const char *readerName;
1877 readerName = currReader->szReader;
1880 if (strcmp(readerName, readerStates[i].readerName) == 0)
1885 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
1888 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1890 int k, newReaderCount = 0;
1893 if (readerStates[k].readerName[0] !=
'\0')
1896 if (newReaderCount != currentReaderCount)
1898 Log1(PCSC_LOG_INFO,
"Reader list changed");
1899 currentReaderCount = newReaderCount;
1907 currReader->dwEventState =
1923 uint32_t readerState;
1930 Log0(PCSC_LOG_DEBUG);
1935 rContext = &readerStates[i];
1941 if (currReader->dwCurrentState & 0xFFFF0000)
1943 unsigned int currentCounter;
1945 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1951 Log0(PCSC_LOG_DEBUG);
1957 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1969 Log0(PCSC_LOG_DEBUG);
1978 currReader->dwEventState &= ~SCARD_STATE_UNAVAILABLE;
1980 Log0(PCSC_LOG_DEBUG);
1994 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1998 currReader->cbAtr = 0;
2017 Log0(PCSC_LOG_DEBUG);
2022 else if (readerState & SCARD_PRESENT)
2035 Log0(PCSC_LOG_DEBUG);
2045 Log0(PCSC_LOG_DEBUG);
2055 Log0(PCSC_LOG_DEBUG);
2069 Log0(PCSC_LOG_DEBUG);
2076 if (readerState & SCARD_PRESENT)
2083 Log0(PCSC_LOG_DEBUG);
2096 Log0(PCSC_LOG_DEBUG);
2099 else if (currReader-> dwCurrentState
2103 Log0(PCSC_LOG_DEBUG);
2115 Log0(PCSC_LOG_DEBUG);
2131 if (dwBreakFlag == 1)
2137 struct timeval before, after;
2139 gettimeofday(&before, NULL);
2141 waitStatusStruct.
timeOut = dwTime;
2149 sizeof(waitStatusStruct), &waitStatusStruct);
2158 &waitStatusStruct,
sizeof(waitStatusStruct),
2170 sizeof(waitStatusStruct), &waitStatusStruct);
2177 sizeof(waitStatusStruct),
2190 rv = waitStatusStruct.rv;
2195 rv = getReaderStates(currentContextMap);
2203 gettimeofday(&after, NULL);
2205 dwTime -= diff/1000;
2225 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2227 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2232 for (j=0; j<cReaders; j++)
2234 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2235 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2293 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2294 LPDWORD lpBytesReturned)
2304 if (NULL != lpBytesReturned)
2305 *lpBytesReturned = 0;
2310 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2318 (void)pthread_mutex_lock(¤tContextMap->mMutex);
2321 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2331 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2342 scControlStruct.hCard = hCard;
2343 scControlStruct.dwControlCode = dwControlCode;
2344 scControlStruct.cbSendLength = cbSendLength;
2345 scControlStruct.cbRecvLength = cbRecvLength;
2346 scControlStruct.dwBytesReturned = 0;
2347 scControlStruct.rv = 0;
2350 sizeof(scControlStruct), &scControlStruct);
2356 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2357 currentContextMap->dwClientID);
2366 currentContextMap->dwClientID);
2374 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2375 currentContextMap->dwClientID);
2382 if (NULL != lpBytesReturned)
2383 *lpBytesReturned = scControlStruct.dwBytesReturned;
2385 rv = scControlStruct.rv;
2388 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2503 unsigned char *buf = NULL;
2507 if (NULL == pcbAttrLen)
2519 buf = malloc(*pcbAttrLen);
2526 *(
unsigned char **)pbAttr = buf;
2589 if (NULL == pbAttr || 0 == cbAttrLen)
2600 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2601 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2611 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2616 (void)pthread_mutex_lock(¤tContextMap->mMutex);
2619 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2629 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2639 scGetSetStruct.hCard = hCard;
2640 scGetSetStruct.dwAttrId = dwAttrId;
2641 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2643 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2645 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2648 sizeof(scGetSetStruct), &scGetSetStruct);
2657 currentContextMap->dwClientID);
2667 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2669 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2673 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2676 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2678 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2680 rv = scGetSetStruct.rv;
2683 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2747 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2749 LPDWORD pcbRecvLength)
2758 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2759 pcbRecvLength == NULL || pioSendPci == NULL)
2765 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2777 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
2780 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
2790 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2801 scTransmitStruct.hCard = hCard;
2802 scTransmitStruct.cbSendLength = cbSendLength;
2803 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2804 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2805 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2810 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2811 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2820 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2826 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2844 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2852 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2853 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2857 rv = scTransmitStruct.rv;
2861 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2866 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2869 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2927 LPSTR mszReaders, LPDWORD pcchReaders)
2929 DWORD dwReadersLen = 0;
2937 API_TRACE_IN(
"%ld", hContext)
2942 if (pcchReaders == NULL)
2949 if (NULL == currentContextMap)
2955 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
2959 if (NULL == currentContextMap)
2966 rv = getReaderStates(currentContextMap);
2972 if (readerStates[i].readerName[0] !=
'\0')
2973 dwReadersLen += strlen(readerStates[i].readerName) + 1;
2978 if (1 == dwReadersLen)
2986 if (NULL == mszReaders)
2991 buf = malloc(dwReadersLen);
2997 *(
char **)mszReaders = buf;
3004 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
3011 if (mszReaders == NULL)
3016 if (readerStates[i].readerName[0] !=
'\0')
3021 strcpy(buf, readerStates[i].readerName);
3022 buf += strlen(readerStates[i].readerName)+1;
3029 *pcchReaders = dwReadersLen;
3031 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3034 API_TRACE_OUT(
"%d", *pcchReaders)
3063 if (NULL == currentContextMap)
3066 free((
void *)pvMem);
3134 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
3135 const unsigned int dwGroups =
sizeof(ReaderGroup);
3141 if (NULL == currentContextMap)
3144 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
3148 if (NULL == currentContextMap)
3156 if (NULL == mszGroups)
3161 buf = malloc(dwGroups);
3167 *(
char **)mszGroups = buf;
3173 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3181 memcpy(buf, ReaderGroup, dwGroups);
3184 *pcchGroups = dwGroups;
3186 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3226 uint32_t dwClientID = 0;
3230 API_TRACE_IN(
"%ld", hContext)
3236 if (NULL == currentContextMap)
3242 if (! currentContextMap->cancellable)
3255 scCancelStruct.hContext = hContext;
3259 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3267 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3272 rv = scCancelStruct.rv;
3312 API_TRACE_IN(
"%ld", hContext)
3320 if (currentContextMap == NULL)
3351 if (NULL == newContextMap)
3354 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3355 newContextMap->
hContext = hContext;
3359 (void)pthread_mutex_init(&newContextMap->
mMutex, NULL);
3361 lrv = list_init(&newContextMap->channelMapList);
3364 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3368 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3369 CHANNEL_MAP_seeker);
3372 Log2(PCSC_LOG_CRITICAL,
3373 "list_attributes_seeker failed with return value: %d", lrv);
3374 list_destroy(&newContextMap->channelMapList);
3378 lrv = list_append(&contextMapList, newContextMap);
3381 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3383 list_destroy(&newContextMap->channelMapList);
3391 (void)pthread_mutex_destroy(&newContextMap->
mMutex);
3392 free(newContextMap);
3417 return currentContextMap;
3434 return list_seek(&contextMapList, &hContext);
3451 if (NULL == currentContextMap)
3454 return SCardCleanContext(currentContextMap);
3457 static LONG SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3459 int list_index, lrv;
3466 (void)pthread_mutex_destroy(&targetContextMap->
mMutex);
3468 listSize = list_size(&targetContextMap->channelMapList);
3469 for (list_index = 0; list_index < listSize; list_index++)
3471 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3473 if (NULL == currentChannelMap)
3475 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3481 free(currentChannelMap->readerName);
3482 free(currentChannelMap);
3486 list_destroy(&targetContextMap->channelMapList);
3488 lrv = list_delete(&contextMapList, targetContextMap);
3491 Log2(PCSC_LOG_CRITICAL,
3492 "list_delete failed with return value: %d", lrv);
3495 free(targetContextMap);
3511 if (NULL == newChannelMap)
3514 newChannelMap->hCard = hCard;
3515 newChannelMap->readerName = strdup(readerName);
3517 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3520 free(newChannelMap->readerName);
3521 free(newChannelMap);
3522 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3537 rv = SCardGetContextAndChannelFromHandle(hCard, ¤tContextMap,
3538 ¤tChannelMap);
3542 free(currentChannelMap->readerName);
3544 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3547 Log2(PCSC_LOG_CRITICAL,
3548 "list_delete failed with return value: %d", lrv);
3551 free(currentChannelMap);
3556 static LONG SCardGetContextAndChannelFromHandle(
SCARDHANDLE hCard,
3565 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3572 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3581 *targetContextMap = NULL;
3582 *targetChannelMap = NULL;
3584 listSize = list_size(&contextMapList);
3586 for (list_index = 0; list_index < listSize; list_index++)
3588 currentContextMap = list_get_at(&contextMapList, list_index);
3589 if (currentContextMap == NULL)
3591 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3595 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3597 if (currentChannelMap != NULL)
3599 *targetContextMap = currentContextMap;
3600 *targetChannelMap = currentChannelMap;
3622 struct stat statBuffer;
3625 socketName = getSocketName();
3626 rv = stat(socketName, &statBuffer);
3630 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3631 socketName, strerror(errno));
3638 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3640 int32_t dwClientID = currentContextMap->
dwClientID;
3648 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.