00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00018 #include "config.h"
00019 #include <sys/types.h>
00020 #include <sys/stat.h>
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <pthread.h>
00026
00027 #include "misc.h"
00028 #include "pcscd.h"
00029 #include "ifdhandler.h"
00030 #include "debuglog.h"
00031 #include "readerfactory.h"
00032 #include "eventhandler.h"
00033 #include "dyn_generic.h"
00034 #include "sys_generic.h"
00035 #include "ifdwrapper.h"
00036 #include "prothandler.h"
00037 #include "strlcpycat.h"
00038 #include "utils.h"
00039 #include "winscard_svc.h"
00040 #include "simclist.h"
00041
00042 READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00043 static list_t ClientsWaitingForEvent;
00044 pthread_mutex_t ClientsWaitingForEvent_lock;
00046 static void EHStatusHandlerThread(READER_CONTEXT *);
00047
00048 LONG EHRegisterClientForEvent(int32_t filedes)
00049 {
00050 (void)pthread_mutex_lock(&ClientsWaitingForEvent_lock);
00051
00052 (void)list_append(&ClientsWaitingForEvent, &filedes);
00053
00054 (void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock);
00055
00056 return SCARD_S_SUCCESS;
00057 }
00058
00063 LONG EHTryToUnregisterClientForEvent(int32_t filedes)
00064 {
00065 LONG rv = SCARD_S_SUCCESS;
00066 int ret;
00067
00068 (void)pthread_mutex_lock(&ClientsWaitingForEvent_lock);
00069
00070 ret = list_delete(&ClientsWaitingForEvent, &filedes);
00071
00072 (void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock);
00073
00074 if (ret < 0)
00075 rv = SCARD_F_INTERNAL_ERROR;
00076
00077 return rv;
00078 }
00079
00083 LONG EHUnregisterClientForEvent(int32_t filedes)
00084 {
00085 LONG rv = EHTryToUnregisterClientForEvent(filedes);
00086
00087 if (rv < 0)
00088 Log2(PCSC_LOG_ERROR, "Can't remove client: %d", filedes);
00089
00090 return rv;
00091 }
00092
00096 LONG EHSignalEventToClients(void)
00097 {
00098 LONG rv = SCARD_S_SUCCESS;
00099 int32_t filedes;
00100
00101 (void)pthread_mutex_lock(&ClientsWaitingForEvent_lock);
00102
00103 (void)list_iterator_start(&ClientsWaitingForEvent);
00104 while (list_iterator_hasnext(&ClientsWaitingForEvent))
00105 {
00106 filedes = *(int32_t *)list_iterator_next(&ClientsWaitingForEvent);
00107 rv = MSGSignalClient(filedes, SCARD_S_SUCCESS);
00108 }
00109 (void)list_iterator_stop(&ClientsWaitingForEvent);
00110
00111 (void)list_clear(&ClientsWaitingForEvent);
00112
00113 (void)pthread_mutex_unlock(&ClientsWaitingForEvent_lock);
00114
00115 return rv;
00116 }
00117
00118 LONG EHInitializeEventStructures(void)
00119 {
00120 int i;
00121
00122 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00123 {
00124
00125 memset(readerStates[i].readerName, 0, MAX_READERNAME);
00126 memset(readerStates[i].cardAtr, 0, MAX_ATR_SIZE);
00127 readerStates[i].readerID = 0;
00128 readerStates[i].readerState = 0;
00129 readerStates[i].readerSharing = 0;
00130 readerStates[i].cardAtrLength = 0;
00131 readerStates[i].cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00132 }
00133
00134 (void)list_init(&ClientsWaitingForEvent);
00135
00136
00137 (void)list_attributes_copy(&ClientsWaitingForEvent, list_meter_int32_t, 1);
00138
00139
00140 (void)list_attributes_comparator(&ClientsWaitingForEvent, list_comparator_int32_t);
00141
00142 (void)pthread_mutex_init(&ClientsWaitingForEvent_lock, NULL);
00143
00144 return SCARD_S_SUCCESS;
00145 }
00146
00147 LONG EHDestroyEventHandler(READER_CONTEXT * rContext)
00148 {
00149 int rv;
00150 DWORD dwGetSize;
00151 UCHAR ucGetData[1];
00152
00153 if (NULL == rContext->readerState)
00154 {
00155 Log1(PCSC_LOG_ERROR, "Thread never started (reader init failed?)");
00156 return SCARD_S_SUCCESS;
00157 }
00158
00159 if ('\0' == rContext->readerState->readerName[0])
00160 {
00161 Log1(PCSC_LOG_INFO, "Thread already stomped.");
00162 return SCARD_S_SUCCESS;
00163 }
00164
00165
00166
00167
00168 rContext->hLockId = 0xFFFF;
00169
00170 Log1(PCSC_LOG_INFO, "Stomping thread.");
00171
00172
00173 dwGetSize = sizeof(ucGetData);
00174 rv = IFDGetCapabilities(rContext, TAG_IFD_POLLING_THREAD_KILLABLE,
00175 &dwGetSize, ucGetData);
00176
00177 #ifdef HAVE_PTHREAD_CANCEL
00178 if ((IFD_SUCCESS == rv) && (1 == dwGetSize) && ucGetData[0])
00179 {
00180 Log1(PCSC_LOG_INFO, "Killing polling thread");
00181 (void)pthread_cancel(rContext->pthThread);
00182 }
00183 else
00184 #endif
00185 Log1(PCSC_LOG_INFO, "Waiting polling thread");
00186
00187
00188 rv = pthread_join(rContext->pthThread, NULL);
00189 if (rv)
00190 Log2(PCSC_LOG_ERROR, "pthread_join failed: %s", strerror(rv));
00191
00192
00193
00194
00195
00196 memset(rContext->readerState->readerName, 0,
00197 sizeof(rContext->readerState->readerName));
00198 memset(rContext->readerState->cardAtr, 0,
00199 sizeof(rContext->readerState->cardAtr));
00200 rContext->readerState->readerID = 0;
00201 rContext->readerState->readerState = 0;
00202 rContext->readerState->readerSharing = 0;
00203 rContext->readerState->cardAtrLength = 0;
00204 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00205
00206
00207 rContext->pthThread = 0;
00208
00209 Log1(PCSC_LOG_INFO, "Thread stomped.");
00210
00211 return SCARD_S_SUCCESS;
00212 }
00213
00214 LONG EHSpawnEventHandler(READER_CONTEXT * rContext,
00215 RESPONSECODE (*card_event)(DWORD))
00216 {
00217 LONG rv;
00218 DWORD dwStatus = 0;
00219 int i;
00220 UCHAR ucAtr[MAX_ATR_SIZE];
00221 DWORD dwAtrLen = 0;
00222
00223 rv = IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen);
00224 if (rv != SCARD_S_SUCCESS)
00225 {
00226 Log2(PCSC_LOG_ERROR, "Initial Check Failed on %s", rContext->lpcReader);
00227 return SCARD_F_UNKNOWN_ERROR;
00228 }
00229
00230
00231
00232
00233 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00234 {
00235 if (readerStates[i].readerID == 0)
00236 break;
00237 }
00238
00239 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00240 return SCARD_F_INTERNAL_ERROR;
00241
00242
00243
00244
00245 rContext->readerState = &readerStates[i];
00246 (void)strlcpy(rContext->readerState->readerName, rContext->lpcReader,
00247 sizeof(rContext->readerState->readerName));
00248 memcpy(rContext->readerState->cardAtr, ucAtr, dwAtrLen);
00249 rContext->readerState->readerID = i + 100;
00250 rContext->readerState->readerState = dwStatus;
00251 rContext->readerState->readerSharing = rContext->contexts;
00252 rContext->readerState->cardAtrLength = dwAtrLen;
00253 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00254
00255 rContext->pthCardEvent = card_event;
00256 rv = ThreadCreate(&rContext->pthThread, 0,
00257 (PCSCLITE_THREAD_FUNCTION( ))EHStatusHandlerThread, (LPVOID) rContext);
00258 if (rv)
00259 {
00260 Log2(PCSC_LOG_ERROR, "ThreadCreate failed: %s", strerror(rv));
00261 return SCARD_E_NO_MEMORY;
00262 }
00263 else
00264 return SCARD_S_SUCCESS;
00265 }
00266
00267 static void incrementEventCounter(struct pubReaderStatesList *readerState)
00268 {
00269 int counter;
00270
00271 counter = (readerState -> readerState >> 16) & 0xFFFF;
00272 counter++;
00273 readerState -> readerState = (readerState -> readerState & 0xFFFF)
00274 + (counter << 16);
00275 }
00276
00277 static void EHStatusHandlerThread(READER_CONTEXT * rContext)
00278 {
00279 LONG rv;
00280 LPCSTR lpcReader;
00281 DWORD dwStatus;
00282 int32_t readerSharing;
00283 DWORD dwCurrentState;
00284 DWORD dwAtrLen;
00285
00286
00287
00288
00289 dwStatus = 0;
00290 readerSharing = 0;
00291 dwCurrentState = 0;
00292
00293 lpcReader = rContext->lpcReader;
00294
00295 dwAtrLen = rContext->readerState->cardAtrLength;
00296 rv = IFDStatusICC(rContext, &dwStatus, rContext->readerState->cardAtr,
00297 &dwAtrLen);
00298 rContext->readerState->cardAtrLength = dwAtrLen;
00299
00300 if (dwStatus & SCARD_PRESENT)
00301 {
00302 dwAtrLen = MAX_ATR_SIZE;
00303 rv = IFDPowerICC(rContext, IFD_POWER_UP,
00304 rContext->readerState->cardAtr,
00305 &dwAtrLen);
00306 rContext->readerState->cardAtrLength = dwAtrLen;
00307
00308
00309 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00310
00311 if (rv == IFD_SUCCESS)
00312 {
00313 dwStatus |= SCARD_PRESENT;
00314 dwStatus &= ~SCARD_ABSENT;
00315 dwStatus |= SCARD_POWERED;
00316 dwStatus |= SCARD_NEGOTIABLE;
00317 dwStatus &= ~SCARD_SPECIFIC;
00318 dwStatus &= ~SCARD_SWALLOWED;
00319 dwStatus &= ~SCARD_UNKNOWN;
00320
00321 if (rContext->readerState->cardAtrLength > 0)
00322 {
00323 LogXxd(PCSC_LOG_INFO, "Card ATR: ",
00324 rContext->readerState->cardAtr,
00325 rContext->readerState->cardAtrLength);
00326 }
00327 else
00328 Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
00329 }
00330 else
00331 {
00332 dwStatus |= SCARD_PRESENT;
00333 dwStatus &= ~SCARD_ABSENT;
00334 dwStatus |= SCARD_SWALLOWED;
00335 dwStatus &= ~SCARD_POWERED;
00336 dwStatus &= ~SCARD_NEGOTIABLE;
00337 dwStatus &= ~SCARD_SPECIFIC;
00338 dwStatus &= ~SCARD_UNKNOWN;
00339 Log3(PCSC_LOG_ERROR, "Error powering up card: %d 0x%04X", rv, rv);
00340 }
00341
00342 dwCurrentState = SCARD_PRESENT;
00343 }
00344 else
00345 {
00346 dwStatus |= SCARD_ABSENT;
00347 dwStatus &= ~SCARD_PRESENT;
00348 dwStatus &= ~SCARD_POWERED;
00349 dwStatus &= ~SCARD_NEGOTIABLE;
00350 dwStatus &= ~SCARD_SPECIFIC;
00351 dwStatus &= ~SCARD_SWALLOWED;
00352 dwStatus &= ~SCARD_UNKNOWN;
00353 rContext->readerState->cardAtrLength = 0;
00354 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00355
00356 dwCurrentState = SCARD_ABSENT;
00357 }
00358
00359
00360
00361
00362 rContext->readerState->readerState = dwStatus;
00363 rContext->readerState->readerSharing = readerSharing =
00364 rContext->contexts;
00365
00366 (void)EHSignalEventToClients();
00367
00368 while (1)
00369 {
00370 dwStatus = 0;
00371
00372 dwAtrLen = rContext->readerState->cardAtrLength;
00373 rv = IFDStatusICC(rContext, &dwStatus,
00374 rContext->readerState->cardAtr,
00375 &dwAtrLen);
00376 rContext->readerState->cardAtrLength = dwAtrLen;
00377
00378 if (rv != SCARD_S_SUCCESS)
00379 {
00380 Log2(PCSC_LOG_ERROR, "Error communicating to: %s", lpcReader);
00381
00382
00383
00384
00385 rContext->readerState->readerState &= ~SCARD_ABSENT;
00386 rContext->readerState->readerState &= ~SCARD_PRESENT;
00387 rContext->readerState->readerState &= ~SCARD_POWERED;
00388 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00389 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00390 rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00391 rContext->readerState->readerState |= SCARD_UNKNOWN;
00392 rContext->readerState->cardAtrLength = 0;
00393 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00394
00395 dwCurrentState = SCARD_UNKNOWN;
00396
00397 (void)EHSignalEventToClients();
00398 }
00399
00400 if (dwStatus & SCARD_ABSENT)
00401 {
00402 if (dwCurrentState == SCARD_PRESENT ||
00403 dwCurrentState == SCARD_UNKNOWN)
00404 {
00405
00406
00407
00408 Log2(PCSC_LOG_INFO, "Card Removed From %s", lpcReader);
00409
00410
00411
00412 (void)RFSetReaderEventState(rContext, SCARD_REMOVED);
00413
00414 rContext->readerState->cardAtrLength = 0;
00415 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00416 rContext->readerState->readerState |= SCARD_ABSENT;
00417 rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00418 rContext->readerState->readerState &= ~SCARD_PRESENT;
00419 rContext->readerState->readerState &= ~SCARD_POWERED;
00420 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00421 rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00422 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00423 dwCurrentState = SCARD_ABSENT;
00424
00425 incrementEventCounter(rContext->readerState);
00426
00427 (void)EHSignalEventToClients();
00428 }
00429
00430 }
00431 else if (dwStatus & SCARD_PRESENT)
00432 {
00433 if (dwCurrentState == SCARD_ABSENT ||
00434 dwCurrentState == SCARD_UNKNOWN)
00435 {
00436
00437
00438
00439 dwAtrLen = MAX_ATR_SIZE;
00440 rv = IFDPowerICC(rContext, IFD_POWER_UP,
00441 rContext->readerState->cardAtr,
00442 &dwAtrLen);
00443 rContext->readerState->cardAtrLength = dwAtrLen;
00444
00445
00446 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00447
00448 if (rv == IFD_SUCCESS)
00449 {
00450 rContext->readerState->readerState |= SCARD_PRESENT;
00451 rContext->readerState->readerState &= ~SCARD_ABSENT;
00452 rContext->readerState->readerState |= SCARD_POWERED;
00453 rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00454 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00455 rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00456 rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00457 }
00458 else
00459 {
00460 rContext->readerState->readerState |= SCARD_PRESENT;
00461 rContext->readerState->readerState &= ~SCARD_ABSENT;
00462 rContext->readerState->readerState |= SCARD_SWALLOWED;
00463 rContext->readerState->readerState &= ~SCARD_POWERED;
00464 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00465 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00466 rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00467 rContext->readerState->cardAtrLength = 0;
00468 }
00469
00470 dwCurrentState = SCARD_PRESENT;
00471
00472 incrementEventCounter(rContext->readerState);
00473
00474 Log2(PCSC_LOG_INFO, "Card inserted into %s", lpcReader);
00475
00476 (void)EHSignalEventToClients();
00477
00478 if (rv == IFD_SUCCESS)
00479 {
00480 if (rContext->readerState->cardAtrLength > 0)
00481 {
00482 LogXxd(PCSC_LOG_INFO, "Card ATR: ",
00483 rContext->readerState->cardAtr,
00484 rContext->readerState->cardAtrLength);
00485 }
00486 else
00487 Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
00488 }
00489 else
00490 Log1(PCSC_LOG_ERROR,"Error powering up card.");
00491 }
00492 }
00493
00494
00495
00496
00497 if (readerSharing != rContext->contexts)
00498 {
00499 readerSharing = rContext->contexts;
00500 rContext->readerState->readerSharing = readerSharing;
00501 (void)EHSignalEventToClients();
00502 }
00503
00504 if (rContext->pthCardEvent)
00505 {
00506 int ret;
00507
00508 ret = rContext->pthCardEvent(rContext->slot);
00509 if (IFD_NO_SUCH_DEVICE == ret)
00510 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
00511 }
00512 else
00513 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
00514
00515 if (rContext->hLockId == 0xFFFF)
00516 {
00517
00518
00519
00520 (void)EHSignalEventToClients();
00521 Log1(PCSC_LOG_INFO, "Die");
00522 rContext->hLockId = 0;
00523 (void)pthread_exit(NULL);
00524 }
00525 }
00526 }
00527