eventhandler.c

Go to the documentation of this file.
00001 /*
00002  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
00003  *
00004  * Copyright (C) 2000
00005  *  David Corcoran <corcoran@linuxnet.com>
00006  * Copyright (C) 2004
00007  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00008  *
00009  * $Id: eventhandler.c 2151 2006-09-06 20:02:47Z rousseau $
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      * Jump to end of file space and allocate zero's
00068      */
00069     SYS_SeekFile(fd, pageSize * PCSCLITE_MAX_READERS_CONTEXTS);
00070     SYS_WriteFile(fd, "", 1);
00071 
00072     /*
00073      * Allocate each reader structure
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] == MAP_FAILED)
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          * Zero out each value in the struct
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      * Set the thread to 0 to exit thread
00118      */
00119     rContext->dwLockId = 0xFFFF;
00120 
00121     Log1(PCSC_LOG_INFO, "Stomping thread.");
00122 
00123     do
00124     {
00125         /*
00126          * Wait 0.05 seconds for the child to respond
00127          */
00128         SYS_USleep(50000);
00129     }
00130     while (rContext->dwLockId == 0xFFFF);
00131     /*
00132      * Zero out the public status struct to allow it to be recycled and
00133      * used again
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     /* Zero the thread */
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      * Find an empty reader slot and insert the new reader
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      * Set all the attributes to this reader
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     LPCSTR lpcReader;
00207     DWORD dwStatus, dwReaderSharing;
00208     DWORD dwCurrentState;
00209     int pageSize;
00210 
00211     /*
00212      * Zero out everything
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         /* the protocol is unset after a power on */
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      * Set all the public attributes to this reader
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              * Set error status on this reader while errors occur
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              * This code causes race conditions on G4's with USB
00323              * insertion
00324              */
00325             /*
00326              * dwErrorCount += 1; SYS_Sleep(1);
00327              */
00328             /*
00329              * After 10 seconds of errors, try to reinitialize the reader
00330              * This sometimes helps bring readers out of *crazy* states.
00331              */
00332             /*
00333              * if ( dwErrorCount == 10 ) { RFUnInitializeReader( rContext
00334              * ); RFInitializeReader( rContext ); dwErrorCount = 0; }
00335              */
00336 
00337             /*
00338              * End of race condition code block
00339              */
00340         }
00341 
00342         if (dwStatus & SCARD_ABSENT)
00343         {
00344             if (dwCurrentState == SCARD_PRESENT ||
00345                 dwCurrentState == SCARD_UNKNOWN)
00346             {
00347                 /*
00348                  * Change the status structure
00349                  */
00350                 Log2(PCSC_LOG_INFO, "Card Removed From %s", lpcReader);
00351                 /*
00352                  * Notify the card has been removed
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                  * Power and reset the card
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                 /* the protocol is unset after a power on */
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                      * Notify the card has been reset
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              * Exit and notify the caller
00441              */
00442             rContext->dwLockId = 0;
00443             SYS_ThreadDetach(rContext->pthThread);
00444             SYS_ThreadExit(0);
00445         }
00446 
00447         /*
00448          * Sharing may change w/o an event pass it on
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 }

Generated on Tue Feb 6 21:25:44 2007 for pcsc-lite by  doxygen 1.5.1