108 #include <sys/types.h>
114 #include <sys/time.h>
116 #include <sys/wait.h>
138 #define SCARD_PROTOCOL_ANY_OLD 0x1000
145 static 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"
158 static 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"
184 #include <sys/time.h>
187 #define MAX_THREADS 5
188 pthread_t threads[MAX_THREADS];
189 struct timeval profile_time_start[MAX_THREADS];
193 #define PROFILE_START profile_start();
194 #define PROFILE_END(rv) profile_end(__FUNCTION__, rv);
196 static 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);
234 static 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);
275 #define PROFILE_START
276 #define PROFILE_END(rv)
291 static 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",
329 static list_t contextMapList;
331 static 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",
381 static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE,
383 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE,
387 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
388 LPBYTE pbAttr, LPDWORD pcbAttrLen);
390 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap);
391 static LONG getReaderStatesAndRegisterForEvents(
SCONTEXTMAP * currentContextMap);
392 static 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)
529 LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
533 uint32_t dwClientID = 0;
537 if (phContext == NULL)
554 lrv = list_init(&contextMapList);
557 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d",
562 lrv = list_attributes_seeker(&contextMapList,
566 Log2(PCSC_LOG_CRITICAL,
567 "list_attributes_seeker failed with return value: %d", lrv);
568 list_destroy(&contextMapList);
572 if (getenv(
"PCSCLITE_NO_BLOCKING"))
574 Log1(PCSC_LOG_INFO,
"Disable shared blocking");
575 sharing_shall_block = FALSE;
604 Log1(PCSC_LOG_CRITICAL,
605 "Your pcscd is too old and does not support CMD_VERSION");
610 Log3(PCSC_LOG_INFO,
"Server is protocol version %d:%d",
624 scEstablishStruct.dwScope = dwScope;
625 scEstablishStruct.hContext = 0;
629 sizeof(scEstablishStruct), (
void *) &scEstablishStruct);
637 rv =
MessageReceive(&scEstablishStruct,
sizeof(scEstablishStruct),
645 rv = scEstablishStruct.rv;
655 *phContext = scEstablishStruct.hContext;
697 API_TRACE_IN(
"%ld", hContext)
705 if (NULL == currentContextMap)
711 scReleaseStruct.hContext = hContext;
715 currentContextMap->dwClientID,
716 sizeof(scReleaseStruct), (
void *) &scReleaseStruct);
725 currentContextMap->dwClientID);
730 rv = scReleaseStruct.rv;
732 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
804 DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
805 LPDWORD pdwActiveProtocol)
812 API_TRACE_IN(
"%ld %s %ld %ld", hContext, szReader, dwShareMode, dwPreferredProtocols)
817 if (phCard == NULL || pdwActiveProtocol == NULL)
822 if (szReader == NULL)
828 if (strlen(szReader) > MAX_READERNAME)
835 if (NULL == currentContextMap)
838 memset(scConnectStruct.szReader, 0,
sizeof scConnectStruct.szReader);
839 strncpy(scConnectStruct.szReader, szReader,
sizeof scConnectStruct.szReader);
840 scConnectStruct.szReader[
sizeof scConnectStruct.szReader -1] =
'\0';
842 scConnectStruct.hContext = hContext;
843 scConnectStruct.dwShareMode = dwShareMode;
844 scConnectStruct.dwPreferredProtocols = dwPreferredProtocols;
845 scConnectStruct.hCard = 0;
846 scConnectStruct.dwActiveProtocol = 0;
850 sizeof(scConnectStruct), (
void *) &scConnectStruct);
859 currentContextMap->dwClientID);
864 *phCard = scConnectStruct.hCard;
865 *pdwActiveProtocol = scConnectStruct.dwActiveProtocol;
872 rv = SCardAddHandle(*phCard, currentContextMap, szReader);
875 rv = scConnectStruct.rv;
878 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
881 API_TRACE_OUT(
"%d", *pdwActiveProtocol)
959 DWORD dwPreferredProtocols, DWORD dwInitialization,
960 LPDWORD pdwActiveProtocol)
968 API_TRACE_IN(
"%ld %ld %ld", hCard, dwShareMode, dwPreferredProtocols)
970 if (pdwActiveProtocol == NULL)
979 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
984 scReconnectStruct.hCard = hCard;
985 scReconnectStruct.dwShareMode = dwShareMode;
986 scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
987 scReconnectStruct.dwInitialization = dwInitialization;
988 scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
992 sizeof(scReconnectStruct), (
void *) &scReconnectStruct);
1000 rv =
MessageReceive(&scReconnectStruct,
sizeof(scReconnectStruct),
1001 currentContextMap->dwClientID);
1006 rv = scReconnectStruct.rv;
1010 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1015 *pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
1018 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1021 API_TRACE_OUT(
"%ld", *pdwActiveProtocol)
1065 API_TRACE_IN(
"%ld %ld", hCard, dwDisposition)
1070 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1078 scDisconnectStruct.hCard = hCard;
1079 scDisconnectStruct.dwDisposition = dwDisposition;
1083 sizeof(scDisconnectStruct), (
void *) &scDisconnectStruct);
1091 rv =
MessageReceive(&scDisconnectStruct,
sizeof(scDisconnectStruct),
1092 currentContextMap->dwClientID);
1098 SCardRemoveHandle(hCard);
1099 rv = scDisconnectStruct.rv;
1102 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1155 API_TRACE_IN(
"%ld", hCard)
1167 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1172 scBeginStruct.hCard = hCard;
1176 currentContextMap->dwClientID,
1177 sizeof(scBeginStruct), (
void *) &scBeginStruct);
1186 currentContextMap->dwClientID);
1191 rv = scBeginStruct.rv;
1196 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1200 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1255 API_TRACE_IN(
"%ld", hCard)
1260 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1265 scEndStruct.hCard = hCard;
1266 scEndStruct.dwDisposition = dwDisposition;
1270 currentContextMap->dwClientID,
1271 sizeof(scEndStruct), (
void *) &scEndStruct);
1280 currentContextMap->dwClientID);
1285 rv = scEndStruct.rv;
1288 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1392 LPDWORD pcchReaderLen, LPDWORD pdwState,
1393 LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
1395 DWORD dwReaderLen, dwAtrLen;
1402 char *bufReader = NULL;
1403 LPBYTE bufAtr = NULL;
1416 if (pcchReaderLen == NULL)
1417 pcchReaderLen = &dummy;
1419 if (pcbAtrLen == NULL)
1423 dwReaderLen = *pcchReaderLen;
1424 dwAtrLen = *pcbAtrLen;
1435 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
1441 rv = getReaderStates(currentContextMap);
1445 r = pChannelMap->readerName;
1460 memset(&scStatusStruct, 0,
sizeof(scStatusStruct));
1461 scStatusStruct.hCard = hCard;
1464 sizeof(scStatusStruct), (
void *) &scStatusStruct);
1473 currentContextMap->dwClientID);
1478 rv = scStatusStruct.rv;
1482 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1499 *pcchReaderLen = strlen(pChannelMap->readerName) + 1;
1510 dwReaderLen = *pcchReaderLen;
1511 if (NULL == szReaderName)
1516 bufReader = malloc(dwReaderLen);
1517 if (NULL == bufReader)
1522 *(
char **)szReaderName = bufReader;
1525 bufReader = szReaderName;
1530 if (*pcchReaderLen > dwReaderLen)
1533 strncpy(bufReader, pChannelMap->readerName, dwReaderLen);
1538 dwAtrLen = *pcbAtrLen;
1544 bufAtr = malloc(dwAtrLen);
1550 *(LPBYTE *)pbAtr = bufAtr;
1557 if (*pcbAtrLen > dwAtrLen)
1560 memcpy(bufAtr,
readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
1564 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
1684 DWORD dwBreakFlag = 0;
1687 int currentReaderCount = 0;
1691 API_TRACE_IN(
"%ld %ld %d", hContext, dwTimeout, cReaders)
1693 for (j=0; j<cReaders; j++)
1695 API_TRACE_IN(
"[%d] %s %lX %lX", j, rgReaderStates[j].szReader,
1696 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
1700 if ((rgReaderStates == NULL && cReaders > 0)
1708 for (j = 0; j < cReaders; j++)
1710 if (rgReaderStates[j].szReader == NULL)
1717 int nbNonIgnoredReaders = cReaders;
1719 for (j=0; j<cReaders; j++)
1721 nbNonIgnoredReaders--;
1723 if (0 == nbNonIgnoredReaders)
1740 if (NULL == currentContextMap)
1747 rv = getReaderStatesAndRegisterForEvents(currentContextMap);
1752 for (j=0; j<cReaders; j++)
1754 const char *readerName;
1757 readerName = rgReaderStates[j].szReader;
1760 if (strcmp(readerName,
readerStates[i].readerName) == 0)
1768 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") != 0)
1777 for (j = 0; j < cReaders; j++)
1778 rgReaderStates[j].dwEventState = 0;
1781 Log2(PCSC_LOG_DEBUG,
"Event Loop Start, dwTimeout: %ld", dwTimeout);
1786 currentReaderCount++;
1789 if ((DWORD)-1 == dwTimeout)
1799 currReader = &rgReaderStates[j];
1804 const char *readerName;
1808 readerName = currReader->szReader;
1811 if (strcmp(readerName,
readerStates[i].readerName) == 0)
1819 if (strcasecmp(readerName,
"\\\\?PnP?\\Notification") == 0)
1821 int k, newReaderCount = 0;
1827 if (newReaderCount != currentReaderCount)
1829 Log1(PCSC_LOG_INFO,
"Reader list changed");
1830 currentReaderCount = newReaderCount;
1838 currReader->dwEventState =
1854 uint32_t readerState;
1861 Log0(PCSC_LOG_DEBUG);
1872 if (currReader->dwCurrentState & 0xFFFF0000)
1874 unsigned int currentCounter;
1876 currentCounter = (currReader->dwCurrentState >> 16) & 0xFFFF;
1882 Log0(PCSC_LOG_DEBUG);
1888 currReader->dwEventState = ((currReader->dwEventState & 0xffff )
1900 Log0(PCSC_LOG_DEBUG);
1911 Log0(PCSC_LOG_DEBUG);
1925 memcpy(currReader->rgbAtr, rContext->
cardAtr,
1929 currReader->cbAtr = 0;
1948 Log0(PCSC_LOG_DEBUG);
1966 Log0(PCSC_LOG_DEBUG);
1976 Log0(PCSC_LOG_DEBUG);
1986 Log0(PCSC_LOG_DEBUG);
2000 Log0(PCSC_LOG_DEBUG);
2014 Log0(PCSC_LOG_DEBUG);
2027 Log0(PCSC_LOG_DEBUG);
2030 else if (currReader-> dwCurrentState
2034 Log0(PCSC_LOG_DEBUG);
2046 Log0(PCSC_LOG_DEBUG);
2062 if (dwBreakFlag == 1)
2068 struct timeval before, after;
2070 gettimeofday(&before, NULL);
2081 &waitStatusStruct,
sizeof(waitStatusStruct),
2092 rv = unregisterFromEvents(currentContextMap);
2101 rv = waitStatusStruct.rv;
2106 rv = getReaderStatesAndRegisterForEvents(currentContextMap);
2114 gettimeofday(&after, NULL);
2116 dwTime -= diff/1000;
2136 Log1(PCSC_LOG_DEBUG,
"Event Loop End");
2141 (void)unregisterFromEvents(currentContextMap);
2143 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2148 for (j=0; j<cReaders; j++)
2150 API_TRACE_OUT(
"[%d] %s %X %X", j, rgReaderStates[j].szReader,
2151 rgReaderStates[j].dwCurrentState, rgReaderStates[j].dwEventState)
2209 DWORD cbSendLength, LPVOID pbRecvBuffer, DWORD cbRecvLength,
2210 LPDWORD lpBytesReturned)
2220 if (NULL != lpBytesReturned)
2221 *lpBytesReturned = 0;
2226 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2241 scControlStruct.hCard = hCard;
2242 scControlStruct.dwControlCode = dwControlCode;
2243 scControlStruct.cbSendLength = cbSendLength;
2244 scControlStruct.cbRecvLength = cbRecvLength;
2245 scControlStruct.dwBytesReturned = 0;
2246 scControlStruct.rv = 0;
2249 sizeof(scControlStruct), &scControlStruct);
2255 rv =
MessageSend((
char *)pbSendBuffer, cbSendLength,
2256 currentContextMap->dwClientID);
2265 currentContextMap->dwClientID);
2273 rv =
MessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
2274 currentContextMap->dwClientID);
2281 if (NULL != lpBytesReturned)
2282 *lpBytesReturned = scControlStruct.dwBytesReturned;
2284 rv = scControlStruct.rv;
2287 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2415 unsigned char *buf = NULL;
2419 if (NULL == pcbAttrLen)
2431 buf = malloc(*pcbAttrLen);
2438 *(
unsigned char **)pbAttr = buf;
2501 if (NULL == pbAttr || 0 == cbAttrLen)
2512 static LONG SCardGetSetAttrib(
SCARDHANDLE hCard,
int command, DWORD dwAttrId,
2513 LPBYTE pbAttr, LPDWORD pcbAttrLen)
2523 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2534 scGetSetStruct.hCard = hCard;
2535 scGetSetStruct.dwAttrId = dwAttrId;
2537 memset(scGetSetStruct.pbAttr, 0,
sizeof(scGetSetStruct.pbAttr));
2540 memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
2541 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2545 scGetSetStruct.cbAttrLen =
sizeof scGetSetStruct.pbAttr;
2548 sizeof(scGetSetStruct), &scGetSetStruct);
2557 currentContextMap->dwClientID);
2567 if (*pcbAttrLen < scGetSetStruct.cbAttrLen)
2571 DWORD correct_value = scGetSetStruct.cbAttrLen;
2572 scGetSetStruct.cbAttrLen = *pcbAttrLen;
2573 *pcbAttrLen = correct_value;
2578 *pcbAttrLen = scGetSetStruct.cbAttrLen;
2581 memcpy(pbAttr, scGetSetStruct.pbAttr, scGetSetStruct.cbAttrLen);
2583 memset(scGetSetStruct.pbAttr, 0x00,
sizeof(scGetSetStruct.pbAttr));
2585 rv = scGetSetStruct.rv;
2588 (void)pthread_mutex_unlock(¤tContextMap->mMutex);
2652 LPCBYTE pbSendBuffer, DWORD cbSendLength,
2654 LPDWORD pcbRecvLength)
2663 if (pbSendBuffer == NULL || pbRecvBuffer == NULL ||
2664 pcbRecvLength == NULL || pioSendPci == NULL)
2673 rv = SCardGetContextChannelAndLockFromHandle(hCard, ¤tContextMap,
2689 scTransmitStruct.hCard = hCard;
2690 scTransmitStruct.cbSendLength = cbSendLength;
2691 scTransmitStruct.pcbRecvLength = *pcbRecvLength;
2692 scTransmitStruct.ioSendPciProtocol = pioSendPci->
dwProtocol;
2693 scTransmitStruct.ioSendPciLength = pioSendPci->
cbPciLength;
2698 scTransmitStruct.ioRecvPciProtocol = pioRecvPci->
dwProtocol;
2699 scTransmitStruct.ioRecvPciLength = pioRecvPci->
cbPciLength;
2708 sizeof(scTransmitStruct), (
void *) &scTransmitStruct);
2714 rv =
MessageSend((
void *)pbSendBuffer, cbSendLength,
2732 rv =
MessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
2740 pioRecvPci->
dwProtocol = scTransmitStruct.ioRecvPciProtocol;
2741 pioRecvPci->
cbPciLength = scTransmitStruct.ioRecvPciLength;
2745 rv = scTransmitStruct.rv;
2749 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2754 *pcbRecvLength = scTransmitStruct.pcbRecvLength;
2757 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2827 LPSTR mszReaders, LPDWORD pcchReaders)
2829 DWORD dwReadersLen = 0;
2837 API_TRACE_IN(
"%ld", hContext)
2842 if (pcchReaders == NULL)
2849 if (NULL == currentContextMap)
2856 rv = getReaderStates(currentContextMap);
2863 dwReadersLen += strlen(
readerStates[i].readerName) + 1;
2868 if (1 == dwReadersLen)
2876 if (NULL == mszReaders)
2881 buf = malloc(dwReadersLen);
2887 *(
char **)mszReaders = buf;
2894 if ((NULL != mszReaders) && (*pcchReaders < dwReadersLen))
2901 if (mszReaders == NULL)
2919 *pcchReaders = dwReadersLen;
2921 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
2924 API_TRACE_OUT(
"%d", *pcchReaders)
2954 free((
void *)pvMem);
3022 const char ReaderGroup[] =
"SCard$DefaultReaders\0";
3023 const unsigned int dwGroups =
sizeof(ReaderGroup);
3029 if (NULL == currentContextMap)
3034 if (NULL == mszGroups)
3039 buf = malloc(dwGroups);
3045 *(
char **)mszGroups = buf;
3051 if ((NULL != mszGroups) && (*pcchGroups < dwGroups))
3059 memcpy(buf, ReaderGroup, dwGroups);
3062 *pcchGroups = dwGroups;
3064 (void)pthread_mutex_unlock(¤tContextMap->
mMutex);
3106 uint32_t dwClientID = 0;
3111 API_TRACE_IN(
"%ld", hContext)
3119 if (NULL == currentContextMap)
3141 scCancelStruct.hContext = hContext;
3145 sizeof(scCancelStruct), (
void *) &scCancelStruct);
3153 rv =
MessageReceive(&scCancelStruct,
sizeof(scCancelStruct), dwClientID);
3158 rv = scCancelStruct.rv;
3197 API_TRACE_IN(
"%ld", hContext)
3235 if (NULL == newContextMap)
3238 Log2(PCSC_LOG_DEBUG,
"Allocating new SCONTEXTMAP @%p", newContextMap);
3239 newContextMap->
hContext = hContext;
3243 (void)pthread_mutex_init(&newContextMap->
mMutex, NULL);
3245 lrv = list_init(&newContextMap->channelMapList);
3248 Log2(PCSC_LOG_CRITICAL,
"list_init failed with return value: %d", lrv);
3252 lrv = list_attributes_seeker(&newContextMap->channelMapList,
3253 CHANNEL_MAP_seeker);
3256 Log2(PCSC_LOG_CRITICAL,
3257 "list_attributes_seeker failed with return value: %d", lrv);
3258 list_destroy(&newContextMap->channelMapList);
3262 lrv = list_append(&contextMapList, newContextMap);
3265 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3267 list_destroy(&newContextMap->channelMapList);
3275 (void)pthread_mutex_destroy(&newContextMap->
mMutex);
3276 free(newContextMap);
3305 if (NULL != currentContextMap)
3306 (void)pthread_mutex_lock(¤tContextMap->
mMutex);
3310 return currentContextMap;
3327 return list_seek(&contextMapList, &hContext);
3341 if (NULL != currentContextMap)
3342 SCardCleanContext(currentContextMap);
3345 static void SCardCleanContext(
SCONTEXTMAP * targetContextMap)
3347 int list_index, lrv;
3354 (void)pthread_mutex_destroy(&targetContextMap->
mMutex);
3356 listSize = list_size(&targetContextMap->channelMapList);
3357 for (list_index = 0; list_index < listSize; list_index++)
3359 currentChannelMap = list_get_at(&targetContextMap->channelMapList,
3361 if (NULL == currentChannelMap)
3363 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3369 free(currentChannelMap->readerName);
3370 free(currentChannelMap);
3374 list_destroy(&targetContextMap->channelMapList);
3376 lrv = list_delete(&contextMapList, targetContextMap);
3379 Log2(PCSC_LOG_CRITICAL,
3380 "list_delete failed with return value: %d", lrv);
3383 free(targetContextMap);
3399 if (NULL == newChannelMap)
3402 newChannelMap->hCard = hCard;
3403 newChannelMap->readerName = strdup(readerName);
3405 lrv = list_append(¤tContextMap->channelMapList, newChannelMap);
3408 free(newChannelMap->readerName);
3409 free(newChannelMap);
3410 Log2(PCSC_LOG_CRITICAL,
"list_append failed with return value: %d",
3425 rv = SCardGetContextAndChannelFromHandleTH(hCard, ¤tContextMap,
3426 ¤tChannelMap);
3430 free(currentChannelMap->readerName);
3432 lrv = list_delete(¤tContextMap->channelMapList, currentChannelMap);
3435 Log2(PCSC_LOG_CRITICAL,
3436 "list_delete failed with return value: %d", lrv);
3439 free(currentChannelMap);
3444 static LONG SCardGetContextChannelAndLockFromHandle(
SCARDHANDLE hCard,
3453 rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
3457 (void)pthread_mutex_lock(&(*targetContextMap)->mMutex);
3464 static LONG SCardGetContextAndChannelFromHandleTH(
SCARDHANDLE hCard,
3473 *targetContextMap = NULL;
3474 *targetChannelMap = NULL;
3476 listSize = list_size(&contextMapList);
3478 for (list_index = 0; list_index < listSize; list_index++)
3480 currentContextMap = list_get_at(&contextMapList, list_index);
3481 if (currentContextMap == NULL)
3483 Log2(PCSC_LOG_CRITICAL,
"list_get_at failed for index %d",
3487 currentChannelMap = list_seek(¤tContextMap->channelMapList,
3489 if (currentChannelMap != NULL)
3491 *targetContextMap = currentContextMap;
3492 *targetChannelMap = currentChannelMap;
3510 struct stat statBuffer;
3513 socketName = getSocketName();
3514 rv = stat(socketName, &statBuffer);
3518 Log3(PCSC_LOG_INFO,
"PCSC Not Running: %s: %s",
3519 socketName, strerror(errno));
3526 static LONG getReaderStates(
SCONTEXTMAP * currentContextMap)
3528 int32_t dwClientID = currentContextMap->
dwClientID;
3543 static LONG getReaderStatesAndRegisterForEvents(
SCONTEXTMAP * currentContextMap)
3545 int32_t dwClientID = currentContextMap->
dwClientID;
3559 static LONG unregisterFromEvents(
SCONTEXTMAP * currentContextMap)
3561 int32_t dwClientID = currentContextMap->
dwClientID;
3567 dwClientID, 0, NULL);
3584 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.
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.
PCSC_API const char * pcsc_stringify_error(const LONG pcscError)
Returns a human readable text for the given PC/SC error code.
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_STATE_ATRMATCH
ATR matches card.
#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()