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
00026 #include "misc.h"
00027 #include "pcsclite.h"
00028 #include "ifdhandler.h"
00029 #include "debuglog.h"
00030 #include "thread_generic.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
00039 static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
00040
00041 void EHStatusHandlerThread(PREADER_CONTEXT);
00042
00043 LONG EHInitializeEventStructures(void)
00044 {
00045 int fd, i, pageSize;
00046
00047 fd = 0;
00048 i = 0;
00049 pageSize = 0;
00050
00051 SYS_RemoveFile(PCSCLITE_PUBSHM_FILE);
00052
00053 fd = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDWR | O_CREAT, 00644);
00054 if (fd < 0)
00055 {
00056 Log3(PCSC_LOG_CRITICAL, "Cannot create public shared file %s: %s",
00057 PCSCLITE_PUBSHM_FILE, strerror(errno));
00058 exit(1);
00059 }
00060
00061 SYS_Chmod(PCSCLITE_PUBSHM_FILE,
00062 S_IRGRP | S_IREAD | S_IWRITE | S_IROTH);
00063
00064 pageSize = SYS_GetPageSize();
00065
00066
00067
00068
00069 SYS_SeekFile(fd, pageSize * PCSCLITE_MAX_READERS_CONTEXTS);
00070 SYS_WriteFile(fd, "", 1);
00071
00072
00073
00074
00075 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00076 {
00077 readerStates[i] = (PREADER_STATE)
00078 SYS_MemoryMap(sizeof(READER_STATE), fd, (i * pageSize));
00079 if (readerStates[i] == 0)
00080 {
00081 Log3(PCSC_LOG_CRITICAL, "Cannot memory map public shared file %s: %s",
00082 PCSCLITE_PUBSHM_FILE, strerror(errno));
00083 exit(1);
00084 }
00085
00086
00087
00088
00089 memset((readerStates[i])->readerName, 0, MAX_READERNAME);
00090 memset((readerStates[i])->cardAtr, 0, MAX_ATR_SIZE);
00091 (readerStates[i])->readerID = 0;
00092 (readerStates[i])->readerState = 0;
00093 (readerStates[i])->lockState = 0;
00094 (readerStates[i])->readerSharing = 0;
00095 (readerStates[i])->cardAtrLength = 0;
00096 (readerStates[i])->cardProtocol = SCARD_PROTOCOL_UNSET;
00097 }
00098
00099 return SCARD_S_SUCCESS;
00100 }
00101
00102 LONG EHDestroyEventHandler(PREADER_CONTEXT rContext)
00103 {
00104 if (NULL == rContext->readerState)
00105 {
00106 Log1(PCSC_LOG_ERROR, "Thread never started (reader init failed?)");
00107 return SCARD_S_SUCCESS;
00108 }
00109
00110 if ('\0' == rContext->readerState->readerName[0])
00111 {
00112 Log1(PCSC_LOG_INFO, "Thread already stomped.");
00113 return SCARD_S_SUCCESS;
00114 }
00115
00116
00117
00118
00119 rContext->dwLockId = 0xFFFF;
00120
00121 Log1(PCSC_LOG_INFO, "Stomping thread.");
00122
00123 do
00124 {
00125
00126
00127
00128 SYS_USleep(50000);
00129 }
00130 while (rContext->dwLockId == 0xFFFF);
00131
00132
00133
00134
00135
00136 memset(rContext->readerState->readerName, 0,
00137 sizeof(rContext->readerState->readerName));
00138 memset(rContext->readerState->cardAtr, 0,
00139 sizeof(rContext->readerState->cardAtr));
00140 rContext->readerState->readerID = 0;
00141 rContext->readerState->readerState = 0;
00142 rContext->readerState->lockState = 0;
00143 rContext->readerState->readerSharing = 0;
00144 rContext->readerState->cardAtrLength = 0;
00145 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
00146
00147
00148 rContext->pthThread = 0;
00149
00150 Log1(PCSC_LOG_INFO, "Thread stomped.");
00151
00152 return SCARD_S_SUCCESS;
00153 }
00154
00155 LONG EHSpawnEventHandler(PREADER_CONTEXT rContext)
00156 {
00157 LONG rv;
00158 DWORD dwStatus = 0;
00159 int i;
00160 UCHAR ucAtr[MAX_ATR_SIZE];
00161 DWORD dwAtrLen = 0;
00162
00163 rv = IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen);
00164 if (rv != SCARD_S_SUCCESS)
00165 {
00166 Log2(PCSC_LOG_ERROR, "Initial Check Failed on %s", rContext->lpcReader);
00167 return SCARD_F_UNKNOWN_ERROR;
00168 }
00169
00170
00171
00172
00173 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
00174 {
00175 if ((readerStates[i])->readerID == 0)
00176 break;
00177 }
00178
00179 if (i == PCSCLITE_MAX_READERS_CONTEXTS)
00180 return SCARD_F_INTERNAL_ERROR;
00181
00182
00183
00184
00185 rContext->readerState = readerStates[i];
00186 strlcpy(rContext->readerState->readerName, rContext->lpcReader,
00187 sizeof(rContext->readerState->readerName));
00188 memcpy(rContext->readerState->cardAtr, ucAtr, dwAtrLen);
00189 rContext->readerState->readerID = i + 100;
00190 rContext->readerState->readerState = dwStatus;
00191 rContext->readerState->readerSharing = rContext->dwContexts;
00192 rContext->readerState->cardAtrLength = dwAtrLen;
00193 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
00194
00195 rv = SYS_ThreadCreate(&rContext->pthThread, THREAD_ATTR_DETACHED,
00196 (PCSCLITE_THREAD_FUNCTION( ))EHStatusHandlerThread, (LPVOID) rContext);
00197 if (rv == 1)
00198 return SCARD_S_SUCCESS;
00199 else
00200 return SCARD_E_NO_MEMORY;
00201 }
00202
00203 void EHStatusHandlerThread(PREADER_CONTEXT rContext)
00204 {
00205 LONG rv;
00206 LPCTSTR lpcReader;
00207 DWORD dwStatus, dwReaderSharing;
00208 DWORD dwCurrentState;
00209 int pageSize;
00210
00211
00212
00213
00214 dwStatus = 0;
00215 dwReaderSharing = 0;
00216 dwCurrentState = 0;
00217
00218 lpcReader = rContext->lpcReader;
00219
00220 pageSize = SYS_GetPageSize();
00221
00222 rv = IFDStatusICC(rContext, &dwStatus, rContext->readerState->cardAtr,
00223 &rContext->readerState->cardAtrLength);
00224 if (dwStatus & SCARD_PRESENT)
00225 {
00226 rContext->readerState->cardAtrLength = MAX_ATR_SIZE;
00227 rv = IFDPowerICC(rContext, IFD_POWER_UP,
00228 rContext->readerState->cardAtr,
00229 &rContext->readerState->cardAtrLength);
00230
00231
00232 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
00233
00234 if (rv == IFD_SUCCESS)
00235 {
00236 dwStatus |= SCARD_PRESENT;
00237 dwStatus &= ~SCARD_ABSENT;
00238 dwStatus |= SCARD_POWERED;
00239 dwStatus |= SCARD_NEGOTIABLE;
00240 dwStatus &= ~SCARD_SPECIFIC;
00241 dwStatus &= ~SCARD_SWALLOWED;
00242 dwStatus &= ~SCARD_UNKNOWN;
00243
00244 if (rContext->readerState->cardAtrLength > 0)
00245 {
00246 LogXxd(PCSC_LOG_INFO, "Card ATR: ",
00247 rContext->readerState->cardAtr,
00248 rContext->readerState->cardAtrLength);
00249 }
00250 else
00251 Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
00252 }
00253 else
00254 {
00255 dwStatus |= SCARD_PRESENT;
00256 dwStatus &= ~SCARD_ABSENT;
00257 dwStatus |= SCARD_SWALLOWED;
00258 dwStatus &= ~SCARD_POWERED;
00259 dwStatus &= ~SCARD_NEGOTIABLE;
00260 dwStatus &= ~SCARD_SPECIFIC;
00261 dwStatus &= ~SCARD_UNKNOWN;
00262 Log2(PCSC_LOG_ERROR, "Error powering up card: %d", rv);
00263 }
00264
00265 dwCurrentState = SCARD_PRESENT;
00266 }
00267 else
00268 {
00269 dwStatus |= SCARD_ABSENT;
00270 dwStatus &= ~SCARD_PRESENT;
00271 dwStatus &= ~SCARD_POWERED;
00272 dwStatus &= ~SCARD_NEGOTIABLE;
00273 dwStatus &= ~SCARD_SPECIFIC;
00274 dwStatus &= ~SCARD_SWALLOWED;
00275 dwStatus &= ~SCARD_UNKNOWN;
00276 rContext->readerState->cardAtrLength = 0;
00277 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
00278
00279 dwCurrentState = SCARD_ABSENT;
00280 }
00281
00282
00283
00284
00285 rContext->readerState->readerState = dwStatus;
00286 rContext->readerState->readerSharing = dwReaderSharing =
00287 rContext->dwContexts;
00288
00289 SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
00290
00291 while (1)
00292 {
00293 dwStatus = 0;
00294
00295 rv = IFDStatusICC(rContext, &dwStatus,
00296 rContext->readerState->cardAtr,
00297 &rContext->readerState->cardAtrLength);
00298
00299 if (rv != SCARD_S_SUCCESS)
00300 {
00301 Log2(PCSC_LOG_ERROR, "Error communicating to: %s", lpcReader);
00302
00303
00304
00305
00306
00307 rContext->readerState->readerState &= ~SCARD_ABSENT;
00308 rContext->readerState->readerState &= ~SCARD_PRESENT;
00309 rContext->readerState->readerState &= ~SCARD_POWERED;
00310 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00311 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00312 rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00313 rContext->readerState->readerState |= SCARD_UNKNOWN;
00314 rContext->readerState->cardAtrLength = 0;
00315 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
00316
00317 dwCurrentState = SCARD_UNKNOWN;
00318
00319 SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 }
00341
00342 if (dwStatus & SCARD_ABSENT)
00343 {
00344 if (dwCurrentState == SCARD_PRESENT ||
00345 dwCurrentState == SCARD_UNKNOWN)
00346 {
00347
00348
00349
00350 Log2(PCSC_LOG_INFO, "Card Removed From %s", lpcReader);
00351
00352
00353
00354 RFSetReaderEventState(rContext, SCARD_REMOVED);
00355
00356 rContext->readerState->cardAtrLength = 0;
00357 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
00358 rContext->readerState->readerState |= SCARD_ABSENT;
00359 rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00360 rContext->readerState->readerState &= ~SCARD_PRESENT;
00361 rContext->readerState->readerState &= ~SCARD_POWERED;
00362 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00363 rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00364 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00365 dwCurrentState = SCARD_ABSENT;
00366
00367 SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
00368 }
00369
00370 }
00371 else if (dwStatus & SCARD_PRESENT)
00372 {
00373 if (dwCurrentState == SCARD_ABSENT ||
00374 dwCurrentState == SCARD_UNKNOWN)
00375 {
00376
00377
00378
00379 SYS_USleep(PCSCLITE_STATUS_WAIT);
00380 rContext->readerState->cardAtrLength = MAX_ATR_SIZE;
00381 rv = IFDPowerICC(rContext, IFD_POWER_UP,
00382 rContext->readerState->cardAtr,
00383 &rContext->readerState->cardAtrLength);
00384
00385
00386 rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNSET;
00387
00388 if (rv == IFD_SUCCESS)
00389 {
00390 rContext->readerState->readerState |= SCARD_PRESENT;
00391 rContext->readerState->readerState &= ~SCARD_ABSENT;
00392 rContext->readerState->readerState |= SCARD_POWERED;
00393 rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00394 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00395 rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00396 rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00397
00398
00399
00400
00401 RFSetReaderEventState(rContext, SCARD_RESET);
00402 }
00403 else
00404 {
00405 rContext->readerState->readerState |= SCARD_PRESENT;
00406 rContext->readerState->readerState &= ~SCARD_ABSENT;
00407 rContext->readerState->readerState |= SCARD_SWALLOWED;
00408 rContext->readerState->readerState &= ~SCARD_POWERED;
00409 rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00410 rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00411 rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00412 rContext->readerState->cardAtrLength = 0;
00413 }
00414
00415 dwCurrentState = SCARD_PRESENT;
00416
00417 SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
00418
00419 Log2(PCSC_LOG_INFO, "Card inserted into %s", lpcReader);
00420
00421 if (rv == IFD_SUCCESS)
00422 {
00423 if (rContext->readerState->cardAtrLength > 0)
00424 {
00425 LogXxd(PCSC_LOG_INFO, "Card ATR: ",
00426 rContext->readerState->cardAtr,
00427 rContext->readerState->cardAtrLength);
00428 }
00429 else
00430 Log1(PCSC_LOG_INFO, "Card ATR: (NULL)");
00431 }
00432 else
00433 Log1(PCSC_LOG_ERROR,"Error powering up card.");
00434 }
00435 }
00436
00437 if (rContext->dwLockId == 0xFFFF)
00438 {
00439
00440
00441
00442 rContext->dwLockId = 0;
00443 SYS_ThreadDetach(rContext->pthThread);
00444 SYS_ThreadExit(0);
00445 }
00446
00447
00448
00449
00450
00451 if (dwReaderSharing != rContext->dwContexts)
00452 {
00453 dwReaderSharing = rContext->dwContexts;
00454 rContext->readerState->readerSharing = dwReaderSharing;
00455 SYS_MMapSynchronize((void *) rContext->readerState, pageSize);
00456 }
00457
00458 SYS_USleep(PCSCLITE_STATUS_POLL_RATE);
00459 }
00460 }
00461
00462 void EHSetSharingEvent(PREADER_CONTEXT rContext, DWORD dwValue)
00463 {
00464 rContext->readerState->lockState = dwValue;
00465 }