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 {
00186
00187 RESPONSECODE (*fct)(DWORD) = NULL;
00188
00189 dwGetSize = sizeof(fct);
00190 rv = IFDGetCapabilities(rContext, TAG_IFD_STOP_POLLING_THREAD,
00191 &dwGetSize, (PUCHAR)&fct);
00192
00193 if ((IFD_SUCCESS == rv) && (dwGetSize == sizeof(fct)))
00194 {
00195 Log1(PCSC_LOG_INFO, "Request stoping of polling thread");
00196 fct(rContext->slot);
00197 }
00198 else
00199 Log1(PCSC_LOG_INFO, "Waiting polling thread");
00200 }
00201
00202
00203 rv = pthread_join(rContext->pthThread, NULL);
00204 if (rv)
00205 Log2(PCSC_LOG_ERROR, "pthread_join failed: %s", strerror(rv));
00206
00207
00208
00209
00210
00211 memset(rContext->readerState->readerName, 0,
00212 sizeof(rContext->readerState->readerName));
00213 memset(rContext->readerState->cardAtr, 0,
00214 sizeof(rContext->readerState->cardAtr));
00215 rContext->readerState->readerID = 0;
00216 rContext->readerState->readerState = 0;
00217 rContext->readerState->readerSharing = 0;
00218 rContext->readerState->cardAtrLength = 0;
00219 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00220
00221
00222 rContext->pthThread = 0;
00223
00224 Log1(PCSC_LOG_INFO, "Thread stomped.");
00225
00226 return SCARD_S_SUCCESS;
00227 }
00228
00229 LONG EHSpawnEventHandler(READER_CONTEXT * rContext,
00230 RESPONSECODE (*card_event)(DWORD))
00231 {
00232 LONG rv;
00233 DWORD dwStatus = 0;
00234 int i;
00235 UCHAR ucAtr[MAX_ATR_SIZE];
00236 DWORD dwAtrLen = 0;
00237
00238 rv = IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen);
00239 if (rv != SCARD_S_SUCCESS)
00240 {
00241 Log2(PCSC_LOG_ERROR, "Initial Check Failed on %s", rContext->lpcReader);
00242 return SCARD_F_UNKNOWN_ERROR;
00243 }
00244
00245
00246
00247
00248 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00249 {
00250 if (readerStates[i].readerID == 0)
00251 break;
00252 }
00253
00254 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00255 return SCARD_F_INTERNAL_ERROR;
00256
00257
00258
00259
00260 rContext->readerState = &readerStates[i];
00261 (void)strlcpy(rContext->readerState->readerName, rContext->lpcReader,
00262 sizeof(rContext->readerState->readerName));
00263 memcpy(rContext->readerState->cardAtr, ucAtr, dwAtrLen);
00264 rContext->readerState->readerID = i + 100;
00265 rContext->readerState->readerState = dwStatus;
00266 rContext->readerState->readerSharing = rContext->contexts;
00267 rContext->readerState->cardAtrLength = dwAtrLen;
00268 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00269
00270 rContext->pthCardEvent = card_event;
00271 rv = ThreadCreate(&rContext->pthThread, 0,
00272 (PCSCLITE_THREAD_FUNCTION( ))EHStatusHandlerThread, (LPVOID) rContext);
00273 if (rv)
00274 {
00275 Log2(PCSC_LOG_ERROR, "ThreadCreate failed: %s", strerror(rv));
00276 return SCARD_E_NO_MEMORY;
00277 }
00278 else
00279 return SCARD_S_SUCCESS;
00280 }
00281
00282 static void incrementEventCounter(struct pubReaderStatesList *readerState)
00283 {
00284 int counter;
00285
00286 counter = (readerState -> readerState >> 16) & 0xFFFF;
00287 counter++;
00288 readerState -> readerState = (readerState -> readerState & 0xFFFF)
00289 + (counter << 16);
00290 }
00291
00292 static void EHStatusHandlerThread(READER_CONTEXT * rContext)
00293 {
00294 LONG rv;
00295 LPCSTR lpcReader;
00296 DWORD dwStatus;
00297 int32_t readerSharing;
00298 DWORD dwCurrentState;
00299 DWORD dwAtrLen;
00300
00301
00302
00303
00304 dwStatus = 0;
00305 readerSharing = 0;
00306 dwCurrentState = 0;
00307
00308 lpcReader = rContext->lpcReader;
00309
00310 dwAtrLen = rContext->readerState->cardAtrLength;
00311 rv = IFDStatusICC(rContext, &dwStatus, rContext->readerState->cardAtr,
00312 &dwAtrLen);
00313 rContext->readerState->cardAtrLength = dwAtrLen;
00314
00315 if (dwStatus & SCARD_PRESENT)
00316 {
00317 dwAtrLen = MAX_ATR_SIZE;
00318 rv = IFDPowerICC(rContext, IFD_POWER_UP,
00319 rContext->readerState->cardAtr,
00320 &dwAtrLen);
00321 rContext->readerState->cardAtrLength = dwAtrLen;
00322
00323
00324 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00325
00326 if (rv == IFD_SUCCESS)
00327 {
00328 dwStatus |= SCARD_PRESENT;
00329 dwStatus &= ~SCARD_ABSENT;
00330 dwStatus |= SCARD_POWERED;
00331 dwStatus |= SCARD_NEGOTIABLE;
00332 dwStatus &= ~SCARD_SPECIFIC;
00333 dwStatus &= ~SCARD_SWALLOWED;
00334 dwStatus &= ~SCARD_UNKNOWN;
00335
00336 if (rContext->readerState->cardAtrLength > 0)
00337 {
00338 LogXxd(PCSC_LOG_INFO, "Card ATR: ",
00339 rContext->readerState->cardAtr,
00340 rContext->readerState->cardAtrLength);
00341 }
00342 else
00343 Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
00344 }
00345 else
00346 {
00347 dwStatus |= SCARD_PRESENT;
00348 dwStatus &= ~SCARD_ABSENT;
00349 dwStatus |= SCARD_SWALLOWED;
00350 dwStatus &= ~SCARD_POWERED;
00351 dwStatus &= ~SCARD_NEGOTIABLE;
00352 dwStatus &= ~SCARD_SPECIFIC;
00353 dwStatus &= ~SCARD_UNKNOWN;
00354 Log3(PCSC_LOG_ERROR, "Error powering up card: %d 0x%04X", rv, rv);
00355 }
00356
00357 dwCurrentState = SCARD_PRESENT;
00358 }
00359 else
00360 {
00361 dwStatus |= SCARD_ABSENT;
00362 dwStatus &= ~SCARD_PRESENT;
00363 dwStatus &= ~SCARD_POWERED;
00364 dwStatus &= ~SCARD_NEGOTIABLE;
00365 dwStatus &= ~SCARD_SPECIFIC;
00366 dwStatus &= ~SCARD_SWALLOWED;
00367 dwStatus &= ~SCARD_UNKNOWN;
00368 rContext->readerState->cardAtrLength = 0;
00369 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00370
00371 dwCurrentState = SCARD_ABSENT;
00372 }
00373
00374
00375
00376
00377 rContext->readerState->readerState = dwStatus;
00378 rContext->readerState->readerSharing = readerSharing =
00379 rContext->contexts;
00380
00381 (void)EHSignalEventToClients();
00382
00383 while (1)
00384 {
00385 dwStatus = 0;
00386
00387 dwAtrLen = rContext->readerState->cardAtrLength;
00388 rv = IFDStatusICC(rContext, &dwStatus,
00389 rContext->readerState->cardAtr,
00390 &dwAtrLen);
00391 rContext->readerState->cardAtrLength = dwAtrLen;
00392
00393 if (rv != SCARD_S_SUCCESS)
00394 {
00395 Log2(PCSC_LOG_ERROR, "Error communicating to: %s", lpcReader);
00396
00397
00398
00399
00400 rContext->readerState->readerState &= ~SCARD_ABSENT;
00401 rContext->readerState->readerState &= ~SCARD_PRESENT;
00402 rContext->readerState->readerState &= ~SCARD_POWERED;
00403 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00404 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00405 rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00406 rContext->readerState->readerState |= SCARD_UNKNOWN;
00407 rContext->readerState->cardAtrLength = 0;
00408 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00409
00410 dwCurrentState = SCARD_UNKNOWN;
00411
00412 (void)EHSignalEventToClients();
00413 }
00414
00415 if (dwStatus & SCARD_ABSENT)
00416 {
00417 if (dwCurrentState == SCARD_PRESENT ||
00418 dwCurrentState == SCARD_UNKNOWN)
00419 {
00420
00421
00422
00423 Log2(PCSC_LOG_INFO, "Card Removed From %s", lpcReader);
00424
00425
00426
00427 (void)RFSetReaderEventState(rContext, SCARD_REMOVED);
00428
00429 rContext->readerState->cardAtrLength = 0;
00430 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00431 rContext->readerState->readerState |= SCARD_ABSENT;
00432 rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00433 rContext->readerState->readerState &= ~SCARD_PRESENT;
00434 rContext->readerState->readerState &= ~SCARD_POWERED;
00435 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00436 rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00437 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00438 dwCurrentState = SCARD_ABSENT;
00439
00440 incrementEventCounter(rContext->readerState);
00441
00442 (void)EHSignalEventToClients();
00443 }
00444
00445 }
00446 else if (dwStatus & SCARD_PRESENT)
00447 {
00448 if (dwCurrentState == SCARD_ABSENT ||
00449 dwCurrentState == SCARD_UNKNOWN)
00450 {
00451
00452
00453
00454 dwAtrLen = MAX_ATR_SIZE;
00455 rv = IFDPowerICC(rContext, IFD_POWER_UP,
00456 rContext->readerState->cardAtr,
00457 &dwAtrLen);
00458 rContext->readerState->cardAtrLength = dwAtrLen;
00459
00460
00461 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00462
00463 if (rv == IFD_SUCCESS)
00464 {
00465 rContext->readerState->readerState |= SCARD_PRESENT;
00466 rContext->readerState->readerState &= ~SCARD_ABSENT;
00467 rContext->readerState->readerState |= SCARD_POWERED;
00468 rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00469 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00470 rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00471 rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00472 }
00473 else
00474 {
00475 rContext->readerState->readerState |= SCARD_PRESENT;
00476 rContext->readerState->readerState &= ~SCARD_ABSENT;
00477 rContext->readerState->readerState |= SCARD_SWALLOWED;
00478 rContext->readerState->readerState &= ~SCARD_POWERED;
00479 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00480 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00481 rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00482 rContext->readerState->cardAtrLength = 0;
00483 }
00484
00485 dwCurrentState = SCARD_PRESENT;
00486
00487 incrementEventCounter(rContext->readerState);
00488
00489 Log2(PCSC_LOG_INFO, "Card inserted into %s", lpcReader);
00490
00491 (void)EHSignalEventToClients();
00492
00493 if (rv == IFD_SUCCESS)
00494 {
00495 if (rContext->readerState->cardAtrLength > 0)
00496 {
00497 LogXxd(PCSC_LOG_INFO, "Card ATR: ",
00498 rContext->readerState->cardAtr,
00499 rContext->readerState->cardAtrLength);
00500 }
00501 else
00502 Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
00503 }
00504 else
00505 Log1(PCSC_LOG_ERROR,"Error powering up card.");
00506 }
00507 }
00508
00509
00510
00511
00512 if (readerSharing != rContext->contexts)
00513 {
00514 readerSharing = rContext->contexts;
00515 rContext->readerState->readerSharing = readerSharing;
00516 (void)EHSignalEventToClients();
00517 }
00518
00519 if (rContext->pthCardEvent)
00520 {
00521 int ret;
00522
00523 ret = rContext->pthCardEvent(rContext->slot);
00524 if (IFD_NO_SUCH_DEVICE == ret)
00525 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
00526 }
00527 else
00528 (void)SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
00529
00530 if (rContext->hLockId == 0xFFFF)
00531 {
00532
00533
00534
00535 (void)EHSignalEventToClients();
00536 Log1(PCSC_LOG_INFO, "Die");
00537 rContext->hLockId = 0;
00538 (void)pthread_exit(NULL);
00539 }
00540 }
00541 }
00542