winscard.c

Go to the documentation of this file.
00001 /*
00002  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
00003  *
00004  * Copyright (C) 1999-2004
00005  *  David Corcoran <corcoran@linuxnet.com>
00006  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00007  *
00008  * $Id: winscard.c 2884 2008-04-21 12:30:58Z rousseau $
00009  */
00010 
00081 #include "config.h"
00082 #include <stdlib.h>
00083 #include <sys/time.h>
00084 #include <string.h>
00085 
00086 #include "pcscd.h"
00087 #include "winscard.h"
00088 #include "ifdhandler.h"
00089 #include "debuglog.h"
00090 #include "readerfactory.h"
00091 #include "prothandler.h"
00092 #include "ifdwrapper.h"
00093 #include "atrhandler.h"
00094 #include "sys_generic.h"
00095 #include "eventhandler.h"
00096 
00097 #undef DO_PROFILE
00098 #ifdef DO_PROFILE
00099 
00100 #ifndef FALSE
00101 #define FALSE 0
00102 #define TRUE 1
00103 #endif
00104 
00105 #define PROFILE_FILE "/tmp/pcscd_profile"
00106 #include <stdio.h>
00107 #include <sys/time.h>
00108 #include <errno.h>
00109 #include <unistd.h>
00110 
00111 struct timeval profile_time_start;
00112 FILE *fd;
00113 char profile_tty;
00114 
00115 #define PROFILE_START profile_start(__FUNCTION__);
00116 #define PROFILE_END profile_end(__FUNCTION__, __LINE__);
00117 
00118 static void profile_start(const char *f)
00119 {
00120     static char initialized = FALSE;
00121 
00122     if (!initialized)
00123     {
00124         initialized = TRUE;
00125         fd = fopen(PROFILE_FILE, "a+");
00126         if (NULL == fd)
00127         {
00128             fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00129                 PROFILE_FILE, strerror(errno));
00130             exit(-1);
00131         }
00132         fprintf(fd, "\nStart a new profile\n");
00133         fflush(fd);
00134 
00135         if (isatty(fileno(stderr)))
00136             profile_tty = TRUE;
00137         else
00138             profile_tty = FALSE;
00139     }
00140 
00141     gettimeofday(&profile_time_start, NULL);
00142 } /* profile_start */
00143 
00144 /* r = a - b */
00145 static long int time_sub(struct timeval *a, struct timeval *b)
00146 {
00147     struct timeval r;
00148     r.tv_sec = a -> tv_sec - b -> tv_sec;
00149     r.tv_usec = a -> tv_usec - b -> tv_usec;
00150     if (r.tv_usec < 0)
00151     {
00152         r.tv_sec--;
00153         r.tv_usec += 1000000;
00154     }
00155 
00156     return r.tv_sec * 1000000 + r.tv_usec;
00157 } /* time_sub */
00158 
00159 
00160 static void profile_end(const char *f, int line)
00161 {
00162     struct timeval profile_time_end;
00163     long d;
00164 
00165     gettimeofday(&profile_time_end, NULL);
00166     d = time_sub(&profile_time_end, &profile_time_start);
00167 
00168     if (profile_tty)
00169         fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m (%d)\n", f, d,
00170             line);
00171     fprintf(fd, "%s %ld\n", f, d);
00172     fflush(fd);
00173 } /* profile_end */
00174 
00175 #else
00176 #define PROFILE_START
00177 #define PROFILE_END
00178 #endif
00179 
00181 #define SCARD_PROTOCOL_ANY_OLD   0x1000
00182 
00184 #define SCARD_LAST_CONTEXT       1
00185 
00186 #define SCARD_NO_CONTEXT         0
00187 
00188 #define SCARD_EXCLUSIVE_CONTEXT -1
00189 
00190 #define SCARD_NO_LOCK            0
00191 
00192 SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, sizeof(SCARD_IO_REQUEST) };
00193 SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(SCARD_IO_REQUEST) };
00194 SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, sizeof(SCARD_IO_REQUEST) };
00195 
00216 LONG SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
00217     LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00218 {
00219     /*
00220      * Check for NULL pointer
00221      */
00222     if (phContext == 0)
00223         return SCARD_E_INVALID_PARAMETER;
00224 
00225     if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
00226         dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
00227     {
00228 
00229         *phContext = 0;
00230         return SCARD_E_INVALID_VALUE;
00231     }
00232 
00233     /*
00234      * Unique identifier for this server so that it can uniquely be
00235      * identified by clients and distinguished from others
00236      */
00237 
00238     *phContext = (PCSCLITE_SVC_IDENTITY + SYS_RandomInt(1, 65535));
00239 
00240     Log2(PCSC_LOG_DEBUG, "Establishing Context: %d", *phContext);
00241 
00242     return SCARD_S_SUCCESS;
00243 }
00244 
00245 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00246 {
00247     /*
00248      * Nothing to do here RPC layer will handle this
00249      */
00250 
00251     Log2(PCSC_LOG_DEBUG, "Releasing Context: %d", hContext);
00252 
00253     return SCARD_S_SUCCESS;
00254 }
00255 
00256 LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout)
00257 {
00258     /*
00259      * This is only used at the client side of an RPC call but just in
00260      * case someone calls it here
00261      */
00262 
00263     return SCARD_E_UNSUPPORTED_FEATURE;
00264 }
00265 
00266 LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader,
00267     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00268     LPDWORD pdwActiveProtocol)
00269 {
00270     LONG rv;
00271     PREADER_CONTEXT rContext = NULL;
00272     DWORD dwStatus;
00273 
00274     PROFILE_START
00275 
00276     /*
00277      * Check for NULL parameters
00278      */
00279     if (szReader == NULL || phCard == NULL || pdwActiveProtocol == NULL)
00280         return SCARD_E_INVALID_PARAMETER;
00281     else
00282         *phCard = 0;
00283 
00284     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00285             !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00286             !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00287             !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00288         return SCARD_E_PROTO_MISMATCH;
00289 
00290     if (dwShareMode != SCARD_SHARE_EXCLUSIVE &&
00291             dwShareMode != SCARD_SHARE_SHARED &&
00292             dwShareMode != SCARD_SHARE_DIRECT)
00293         return SCARD_E_INVALID_VALUE;
00294 
00295     Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %d",
00296         szReader, dwPreferredProtocols);
00297 
00298     rv = RFReaderInfo((LPSTR) szReader, &rContext);
00299 
00300     if (rv != SCARD_S_SUCCESS)
00301     {
00302         Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader);
00303         return rv;
00304     }
00305 
00306     /*
00307      * Make sure the reader is working properly
00308      */
00309     rv = RFCheckReaderStatus(rContext);
00310     if (rv != SCARD_S_SUCCESS)
00311         return rv;
00312 
00313     /*******************************************
00314      *
00315      * This section checks for simple errors
00316      *
00317      *******************************************/
00318 
00319     /*
00320      * Connect if not exclusive mode
00321      */
00322     if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00323     {
00324         Log1(PCSC_LOG_ERROR, "Error Reader Exclusive");
00325         return SCARD_E_SHARING_VIOLATION;
00326     }
00327 
00328     /*
00329      * wait until a possible transaction is finished
00330      */
00331     if (rContext->dwLockId != 0)
00332     {
00333         Log1(PCSC_LOG_INFO, "Waiting for release of lock");
00334         while (rContext->dwLockId != 0)
00335             SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
00336         Log1(PCSC_LOG_INFO, "Lock released");
00337     }
00338 
00339     /* the reader has been removed while we were waiting */
00340     if (NULL == rContext->readerState)
00341         return SCARD_E_NO_SMARTCARD;
00342 
00343     /*******************************************
00344      *
00345      * This section tries to determine the
00346      * presence of a card or not
00347      *
00348      *******************************************/
00349     dwStatus = rContext->readerState->readerState;
00350 
00351     if (dwShareMode != SCARD_SHARE_DIRECT)
00352     {
00353         if (!(dwStatus & SCARD_PRESENT))
00354         {
00355             Log1(PCSC_LOG_ERROR, "Card Not Inserted");
00356             return SCARD_E_NO_SMARTCARD;
00357         }
00358 
00359         if (dwStatus & SCARD_SWALLOWED)
00360         {
00361             Log1(PCSC_LOG_ERROR, "Card Not Powered");
00362             return SCARD_W_UNPOWERED_CARD;
00363         }
00364     }
00365 
00366 
00367     /*******************************************
00368      *
00369      * This section tries to decode the ATR
00370      * and set up which protocol to use
00371      *
00372      *******************************************/
00373     if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
00374         rContext->readerState->cardProtocol = SCARD_PROTOCOL_RAW;
00375     else
00376     {
00377         if (dwShareMode != SCARD_SHARE_DIRECT)
00378         {
00379             /* the protocol is not yet set (no PPS yet) */
00380             if (SCARD_PROTOCOL_UNDEFINED == rContext->readerState->cardProtocol)
00381             {
00382                 UCHAR ucAvailable, ucDefault;
00383                 int ret;
00384 
00385                 ucDefault = PHGetDefaultProtocol(rContext->readerState->cardAtr,
00386                     rContext->readerState->cardAtrLength);
00387                 ucAvailable =
00388                     PHGetAvailableProtocols(rContext->readerState->cardAtr,
00389                             rContext->readerState->cardAtrLength);
00390 
00391                 /*
00392                  * If it is set to ANY let it do any of the protocols
00393                  */
00394                 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
00395                     dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
00396 
00397                 ret = PHSetProtocol(rContext, dwPreferredProtocols,
00398                     ucAvailable, ucDefault);
00399 
00400                 /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error  */
00401                 if (SET_PROTOCOL_PPS_FAILED == ret)
00402                     return SCARD_W_UNRESPONSIVE_CARD;
00403 
00404                 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
00405                     return SCARD_E_PROTO_MISMATCH;
00406 
00407                 /* use negociated protocol */
00408                 rContext->readerState->cardProtocol = ret;
00409             }
00410             else
00411             {
00412                 if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
00413                     return SCARD_E_PROTO_MISMATCH;
00414             }
00415         }
00416     }
00417 
00418     *pdwActiveProtocol = rContext->readerState->cardProtocol;
00419 
00420     if (dwShareMode != SCARD_SHARE_DIRECT)
00421     {
00422         if ((*pdwActiveProtocol != SCARD_PROTOCOL_T0)
00423             && (*pdwActiveProtocol != SCARD_PROTOCOL_T1))
00424             Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %d",
00425                 *pdwActiveProtocol);
00426         else
00427             Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
00428                 (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
00429     }
00430     else
00431         Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
00432 
00433     /*
00434      * Prepare the SCARDHANDLE identity
00435      */
00436     *phCard = RFCreateReaderHandle(rContext);
00437 
00438     Log2(PCSC_LOG_DEBUG, "hCard Identity: %x", *phCard);
00439 
00440     /*******************************************
00441      *
00442      * This section tries to set up the
00443      * exclusivity modes. -1 is exclusive
00444      *
00445      *******************************************/
00446 
00447     if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
00448     {
00449         if (rContext->dwContexts == SCARD_NO_CONTEXT)
00450         {
00451             rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
00452             RFLockSharing(*phCard);
00453         }
00454         else
00455         {
00456             RFDestroyReaderHandle(*phCard);
00457             *phCard = 0;
00458             return SCARD_E_SHARING_VIOLATION;
00459         }
00460     }
00461     else
00462     {
00463         /*
00464          * Add a connection to the context stack
00465          */
00466         rContext->dwContexts += 1;
00467     }
00468 
00469     /*
00470      * Add this handle to the handle list
00471      */
00472     rv = RFAddReaderHandle(rContext, *phCard);
00473 
00474     if (rv != SCARD_S_SUCCESS)
00475     {
00476         /*
00477          * Clean up - there is no more room
00478          */
00479         RFDestroyReaderHandle(*phCard);
00480         if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00481             rContext->dwContexts = SCARD_NO_CONTEXT;
00482         else
00483             if (rContext->dwContexts > SCARD_NO_CONTEXT)
00484                 rContext->dwContexts -= 1;
00485 
00486         *phCard = 0;
00487 
00488         PROFILE_END
00489 
00490         return SCARD_F_INTERNAL_ERROR;
00491     }
00492 
00493     /*
00494      * Propagate new state to Shared Memory
00495      */
00496     rContext->readerState->readerSharing = rContext->dwContexts;
00497     SYS_MMapSynchronize((void *) rContext->readerState, SYS_GetPageSize() );
00498 
00499     PROFILE_END
00500 
00501     return SCARD_S_SUCCESS;
00502 }
00503 
00504 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00505     DWORD dwPreferredProtocols, DWORD dwInitialization,
00506     LPDWORD pdwActiveProtocol)
00507 {
00508     LONG rv;
00509     PREADER_CONTEXT rContext = NULL;
00510 
00511     Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");
00512 
00513     if (hCard == 0)
00514         return SCARD_E_INVALID_HANDLE;
00515 
00516     /*
00517      * Handle the dwInitialization
00518      */
00519     if (dwInitialization != SCARD_LEAVE_CARD &&
00520             dwInitialization != SCARD_RESET_CARD &&
00521             dwInitialization != SCARD_UNPOWER_CARD)
00522         return SCARD_E_INVALID_VALUE;
00523 
00524     if (dwShareMode != SCARD_SHARE_SHARED &&
00525             dwShareMode != SCARD_SHARE_EXCLUSIVE &&
00526             dwShareMode != SCARD_SHARE_DIRECT)
00527         return SCARD_E_INVALID_VALUE;
00528 
00529     if (!(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00530             !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00531             !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00532             !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00533         return SCARD_E_PROTO_MISMATCH;
00534 
00535     if (pdwActiveProtocol == NULL)
00536         return SCARD_E_INVALID_PARAMETER;
00537 
00538     rv = RFReaderInfoById(hCard, &rContext);
00539     if (rv != SCARD_S_SUCCESS)
00540         return rv;
00541 
00542     /*
00543      * Make sure the reader is working properly
00544      */
00545     rv = RFCheckReaderStatus(rContext);
00546     if (rv != SCARD_S_SUCCESS)
00547         return rv;
00548 
00549     rv = RFFindReaderHandle(hCard);
00550     if (rv != SCARD_S_SUCCESS)
00551         return rv;
00552 
00553     /*
00554      * Make sure no one has a lock on this reader
00555      */
00556     rv = RFCheckSharing(hCard);
00557     if (rv != SCARD_S_SUCCESS)
00558         return rv;
00559 
00560     /*
00561      * RFUnblockReader( rContext ); FIX - this doesn't work
00562      */
00563 
00564     if (dwInitialization == SCARD_RESET_CARD ||
00565         dwInitialization == SCARD_UNPOWER_CARD)
00566     {
00567         DWORD dwAtrLen;
00568         /*
00569          * Currently pcsc-lite keeps the card powered constantly
00570          */
00571         dwAtrLen = rContext->readerState->cardAtrLength;
00572         if (SCARD_RESET_CARD == dwInitialization)
00573             rv = IFDPowerICC(rContext, IFD_RESET,
00574                 rContext->readerState->cardAtr,
00575                 &dwAtrLen);
00576         else
00577         {
00578             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
00579                 rContext->readerState->cardAtr,
00580                 &dwAtrLen);
00581             rv = IFDPowerICC(rContext, IFD_POWER_UP,
00582                 rContext->readerState->cardAtr,
00583                 &dwAtrLen);
00584         }
00585         rContext->readerState->cardAtrLength = dwAtrLen;
00586 
00587         /* the protocol is unset after a power on */
00588         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00589 
00590         /*
00591          * Notify the card has been reset
00592          * Not doing this could result in deadlock
00593          */
00594         rv = RFCheckReaderEventState(rContext, hCard);
00595         switch(rv)
00596         {
00597             /* avoid deadlock */
00598             case SCARD_W_RESET_CARD:
00599                 break;
00600 
00601             case SCARD_W_REMOVED_CARD:
00602                 Log1(PCSC_LOG_ERROR, "card removed");
00603                 return SCARD_W_REMOVED_CARD;
00604 
00605             /* invalid EventStatus */
00606             case SCARD_E_INVALID_VALUE:
00607                 Log1(PCSC_LOG_ERROR, "invalid EventStatus");
00608                 return SCARD_F_INTERNAL_ERROR;
00609 
00610             /* invalid hCard, but hCard was widely used some lines above :( */
00611             case SCARD_E_INVALID_HANDLE:
00612                 Log1(PCSC_LOG_ERROR, "invalid handle");
00613                 return SCARD_F_INTERNAL_ERROR;
00614 
00615             case SCARD_S_SUCCESS:
00616                 /*
00617                  * Notify the card has been reset
00618                  */
00619                 RFSetReaderEventState(rContext, SCARD_RESET);
00620 
00621                 /*
00622                  * Set up the status bit masks on dwStatus
00623                  */
00624                 if (rv == SCARD_S_SUCCESS)
00625                 {
00626                     rContext->readerState->readerState |= SCARD_PRESENT;
00627                     rContext->readerState->readerState &= ~SCARD_ABSENT;
00628                     rContext->readerState->readerState |= SCARD_POWERED;
00629                     rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00630                     rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00631                     rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00632                     rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00633                 }
00634                 else
00635                 {
00636                     rContext->readerState->readerState |= SCARD_PRESENT;
00637                     rContext->readerState->readerState &= ~SCARD_ABSENT;
00638                     rContext->readerState->readerState |= SCARD_SWALLOWED;
00639                     rContext->readerState->readerState &= ~SCARD_POWERED;
00640                     rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00641                     rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00642                     rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00643                     rContext->readerState->cardAtrLength = 0;
00644                 }
00645 
00646                 if (rContext->readerState->cardAtrLength > 0)
00647                 {
00648                     Log1(PCSC_LOG_DEBUG, "Reset complete.");
00649                     LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
00650                         rContext->readerState->cardAtr,
00651                         rContext->readerState->cardAtrLength);
00652                 }
00653                 else
00654                 {
00655                     DWORD dwStatus, dwAtrLen2;
00656                     UCHAR ucAtr[MAX_ATR_SIZE];
00657 
00658                     Log1(PCSC_LOG_ERROR, "Error resetting card.");
00659                     IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen2);
00660                     if (dwStatus & SCARD_PRESENT)
00661                         return SCARD_W_UNRESPONSIVE_CARD;
00662                     else
00663                         return SCARD_E_NO_SMARTCARD;
00664                 }
00665                 break;
00666 
00667             default:
00668                 Log2(PCSC_LOG_ERROR,
00669                     "invalid retcode from RFCheckReaderEventState (%X)", rv);
00670                 return SCARD_F_INTERNAL_ERROR;
00671                 break;
00672         }
00673     }
00674     else
00675         if (dwInitialization == SCARD_LEAVE_CARD)
00676         {
00677             /*
00678              * Do nothing
00679              */
00680         }
00681 
00682     /*******************************************
00683      *
00684      * This section tries to decode the ATR
00685      * and set up which protocol to use
00686      *
00687      *******************************************/
00688     if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
00689         rContext->readerState->cardProtocol = SCARD_PROTOCOL_RAW;
00690     else
00691     {
00692         if (dwShareMode != SCARD_SHARE_DIRECT)
00693         {
00694             /* the protocol is not yet set (no PPS yet) */
00695             if (SCARD_PROTOCOL_UNDEFINED == rContext->readerState->cardProtocol)
00696             {
00697                 UCHAR ucAvailable, ucDefault;
00698                 int ret;
00699 
00700                 ucDefault = PHGetDefaultProtocol(rContext->readerState->cardAtr,
00701                     rContext->readerState->cardAtrLength);
00702                 ucAvailable =
00703                     PHGetAvailableProtocols(rContext->readerState->cardAtr,
00704                             rContext->readerState->cardAtrLength);
00705 
00706                 /* If it is set to ANY let it do any of the protocols */
00707                 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
00708                     dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
00709 
00710                 ret = PHSetProtocol(rContext, dwPreferredProtocols,
00711                     ucAvailable, ucDefault);
00712 
00713                 /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error  */
00714                 if (SET_PROTOCOL_PPS_FAILED == ret)
00715                     return SCARD_W_UNRESPONSIVE_CARD;
00716 
00717                 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
00718                     return SCARD_E_PROTO_MISMATCH;
00719 
00720                 /* use negociated protocol */
00721                 rContext->readerState->cardProtocol = ret;
00722             }
00723             else
00724             {
00725                 if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
00726                     return SCARD_E_PROTO_MISMATCH;
00727             }
00728         }
00729     }
00730 
00731     *pdwActiveProtocol = rContext->readerState->cardProtocol;
00732 
00733     if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
00734     {
00735         if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00736         {
00737             /*
00738              * Do nothing - we are already exclusive
00739              */
00740         } else
00741         {
00742             if (rContext->dwContexts == SCARD_LAST_CONTEXT)
00743             {
00744                 rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
00745                 RFLockSharing(hCard);
00746             } else
00747             {
00748                 return SCARD_E_SHARING_VIOLATION;
00749             }
00750         }
00751     } else if (dwShareMode == SCARD_SHARE_SHARED)
00752     {
00753         if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
00754         {
00755             /*
00756              * Do nothing - in sharing mode already
00757              */
00758         } else
00759         {
00760             /*
00761              * We are in exclusive mode but want to share now
00762              */
00763             RFUnlockSharing(hCard);
00764             rContext->dwContexts = SCARD_LAST_CONTEXT;
00765         }
00766     } else if (dwShareMode == SCARD_SHARE_DIRECT)
00767     {
00768         if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
00769         {
00770             /*
00771              * Do nothing - in sharing mode already
00772              */
00773         } else
00774         {
00775             /*
00776              * We are in exclusive mode but want to share now
00777              */
00778             RFUnlockSharing(hCard);
00779             rContext->dwContexts = SCARD_LAST_CONTEXT;
00780         }
00781     } else
00782         return SCARD_E_INVALID_VALUE;
00783 
00784     /*
00785      * Clear a previous event to the application
00786      */
00787     RFClearReaderEventState(rContext, hCard);
00788 
00789     /*
00790      * Propagate new state to Shared Memory
00791      */
00792     rContext->readerState->readerSharing = rContext->dwContexts;
00793     SYS_MMapSynchronize((void *) rContext->readerState, SYS_GetPageSize() );
00794 
00795     return SCARD_S_SUCCESS;
00796 }
00797 
00798 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
00799 {
00800     LONG rv;
00801     PREADER_CONTEXT rContext = NULL;
00802     DWORD dwAtrLen;
00803 
00804     if (hCard == 0)
00805         return SCARD_E_INVALID_HANDLE;
00806 
00807     rv = RFReaderInfoById(hCard, &rContext);
00808     if (rv != SCARD_S_SUCCESS)
00809         return rv;
00810 
00811     rv = RFFindReaderHandle(hCard);
00812     if (rv != SCARD_S_SUCCESS)
00813         return rv;
00814 
00815     if ((dwDisposition != SCARD_LEAVE_CARD)
00816         && (dwDisposition != SCARD_UNPOWER_CARD)
00817         && (dwDisposition != SCARD_RESET_CARD)
00818         && (dwDisposition != SCARD_EJECT_CARD))
00819         return SCARD_E_INVALID_VALUE;
00820 
00821     /*
00822      * wait until a possible transaction is finished
00823      */
00824     if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->dwLockId != 0)
00825         && (rContext->dwLockId != hCard))
00826     {
00827         Log1(PCSC_LOG_INFO, "Waiting for release of lock");
00828         while (rContext->dwLockId != 0)
00829             SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
00830         Log1(PCSC_LOG_INFO, "Lock released");
00831     }
00832 
00833     /* the reader has been removed while we were waiting */
00834     if (NULL == rContext->readerState)
00835         return SCARD_E_NO_SMARTCARD;
00836 
00837     /*
00838      * Unlock any blocks on this context
00839      */
00840     rv = RFUnlockSharing(hCard);
00841     if (rv != SCARD_S_SUCCESS)
00842         return rv;
00843 
00844     Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->dwContexts);
00845 
00846     if (dwDisposition == SCARD_RESET_CARD ||
00847         dwDisposition == SCARD_UNPOWER_CARD)
00848     {
00849         /*
00850          * Currently pcsc-lite keeps the card powered constantly
00851          */
00852         dwAtrLen = rContext->readerState->cardAtrLength;
00853         if (SCARD_RESET_CARD == dwDisposition)
00854             rv = IFDPowerICC(rContext, IFD_RESET,
00855                 rContext->readerState->cardAtr,
00856                 &dwAtrLen);
00857         else
00858         {
00859             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
00860                 rContext->readerState->cardAtr,
00861                 &dwAtrLen);
00862             rv = IFDPowerICC(rContext, IFD_POWER_UP,
00863                 rContext->readerState->cardAtr,
00864                 &dwAtrLen);
00865         }
00866         rContext->readerState->cardAtrLength = dwAtrLen;
00867 
00868         /* the protocol is unset after a power on */
00869         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00870 
00871         /*
00872          * Notify the card has been reset
00873          */
00874         RFSetReaderEventState(rContext, SCARD_RESET);
00875 
00876         /*
00877          * Set up the status bit masks on dwStatus
00878          */
00879         if (rv == SCARD_S_SUCCESS)
00880         {
00881             rContext->readerState->readerState |= SCARD_PRESENT;
00882             rContext->readerState->readerState &= ~SCARD_ABSENT;
00883             rContext->readerState->readerState |= SCARD_POWERED;
00884             rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00885             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00886             rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00887             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00888         }
00889         else
00890         {
00891             if (rContext->readerState->readerState & SCARD_ABSENT)
00892                 rContext->readerState->readerState &= ~SCARD_PRESENT;
00893             else
00894                 rContext->readerState->readerState |= SCARD_PRESENT;
00895             /* SCARD_ABSENT flag is already set */
00896             rContext->readerState->readerState |= SCARD_SWALLOWED;
00897             rContext->readerState->readerState &= ~SCARD_POWERED;
00898             rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00899             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00900             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00901             rContext->readerState->cardAtrLength = 0;
00902         }
00903 
00904         if (rContext->readerState->cardAtrLength > 0)
00905             Log1(PCSC_LOG_DEBUG, "Reset complete.");
00906         else
00907             Log1(PCSC_LOG_ERROR, "Error resetting card.");
00908     }
00909     else if (dwDisposition == SCARD_EJECT_CARD)
00910     {
00911         UCHAR controlBuffer[5];
00912         UCHAR receiveBuffer[MAX_BUFFER_SIZE];
00913         DWORD receiveLength;
00914 
00915         /*
00916          * Set up the CTBCS command for Eject ICC
00917          */
00918         controlBuffer[0] = 0x20;
00919         controlBuffer[1] = 0x15;
00920         controlBuffer[2] = (rContext->dwSlot & 0x0000FFFF) + 1;
00921         controlBuffer[3] = 0x00;
00922         controlBuffer[4] = 0x00;
00923         receiveLength = 2;
00924         rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
00925             &receiveLength);
00926 
00927         if (rv == SCARD_S_SUCCESS)
00928         {
00929             if (receiveLength == 2 && receiveBuffer[0] == 0x90)
00930             {
00931                 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
00932                 /*
00933                  * Successful
00934                  */
00935             }
00936             else
00937                 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
00938         }
00939         else
00940             Log1(PCSC_LOG_ERROR, "Error ejecting card.");
00941 
00942     }
00943     else if (dwDisposition == SCARD_LEAVE_CARD)
00944     {
00945         /*
00946          * Do nothing
00947          */
00948     }
00949 
00950     /*
00951      * Remove and destroy this handle
00952      */
00953     RFRemoveReaderHandle(rContext, hCard);
00954     RFDestroyReaderHandle(hCard);
00955 
00956     /*
00957      * For exclusive connection reset it to no connections
00958      */
00959     if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00960         rContext->dwContexts = SCARD_NO_CONTEXT;
00961     else
00962     {
00963         /*
00964          * Remove a connection from the context stack
00965          */
00966         rContext->dwContexts -= 1;
00967 
00968         if (rContext->dwContexts < 0)
00969             rContext->dwContexts = 0;
00970     }
00971 
00972     /*
00973      * Propagate new state to Shared Memory
00974      */
00975     rContext->readerState->readerSharing = rContext->dwContexts;
00976     SYS_MMapSynchronize((void *) rContext->readerState, SYS_GetPageSize() );
00977 
00978     return SCARD_S_SUCCESS;
00979 }
00980 
00981 LONG SCardBeginTransaction(SCARDHANDLE hCard)
00982 {
00983     LONG rv;
00984     PREADER_CONTEXT rContext;
00985 
00986     if (hCard == 0)
00987         return SCARD_E_INVALID_HANDLE;
00988 
00989     rv = RFReaderInfoById(hCard, &rContext);
00990 
00991     /*
00992      * Cannot find the hCard in this context
00993      */
00994     if (rv != SCARD_S_SUCCESS)
00995         return rv;
00996 
00997     /*
00998      * Make sure the reader is working properly
00999      */
01000     rv = RFCheckReaderStatus(rContext);
01001     if (rv != SCARD_S_SUCCESS)
01002         return rv;
01003 
01004     rv = RFFindReaderHandle(hCard);
01005     if (rv != SCARD_S_SUCCESS)
01006         return rv;
01007 
01008     /*
01009      * Make sure some event has not occurred
01010      */
01011     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01012         return rv;
01013 
01014     rv = RFLockSharing(hCard);
01015 
01016     /* if the transaction is not yet ready we sleep a bit so the client
01017      * do not retry immediately */
01018     if (SCARD_E_SHARING_VIOLATION == rv)
01019         SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
01020 
01021     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01022 
01023     return rv;
01024 }
01025 
01026 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01027 {
01028     LONG rv;
01029     PREADER_CONTEXT rContext = NULL;
01030     DWORD dwAtrLen;
01031 
01032     /*
01033      * Ignoring dwDisposition for now
01034      */
01035     if (hCard == 0)
01036         return SCARD_E_INVALID_HANDLE;
01037 
01038     if ((dwDisposition != SCARD_LEAVE_CARD)
01039         && (dwDisposition != SCARD_UNPOWER_CARD)
01040         && (dwDisposition != SCARD_RESET_CARD)
01041         && (dwDisposition != SCARD_EJECT_CARD))
01042     return SCARD_E_INVALID_VALUE;
01043 
01044     rv = RFReaderInfoById(hCard, &rContext);
01045 
01046     /*
01047      * Cannot find the hCard in this context
01048      */
01049     if (rv != SCARD_S_SUCCESS)
01050         return rv;
01051 
01052     rv = RFFindReaderHandle(hCard);
01053     if (rv != SCARD_S_SUCCESS)
01054         return rv;
01055 
01056     /*
01057      * Make sure some event has not occurred
01058      */
01059     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01060         return rv;
01061 
01062     if (dwDisposition == SCARD_RESET_CARD ||
01063         dwDisposition == SCARD_UNPOWER_CARD)
01064     {
01065         /*
01066          * Currently pcsc-lite keeps the card always powered
01067          */
01068         dwAtrLen = rContext->readerState->cardAtrLength;
01069         if (SCARD_RESET_CARD == dwDisposition)
01070             rv = IFDPowerICC(rContext, IFD_RESET,
01071                 rContext->readerState->cardAtr,
01072                 &dwAtrLen);
01073         else
01074         {
01075             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
01076                 rContext->readerState->cardAtr,
01077                 &dwAtrLen);
01078             rv = IFDPowerICC(rContext, IFD_POWER_UP,
01079                 rContext->readerState->cardAtr,
01080                 &dwAtrLen);
01081         }
01082         rContext->readerState->cardAtrLength = dwAtrLen;
01083 
01084         /* the protocol is unset after a power on */
01085         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
01086 
01087         /*
01088          * Notify the card has been reset
01089          */
01090         RFSetReaderEventState(rContext, SCARD_RESET);
01091 
01092         /*
01093          * Set up the status bit masks on dwStatus
01094          */
01095         if (rv == SCARD_S_SUCCESS)
01096         {
01097             rContext->readerState->readerState |= SCARD_PRESENT;
01098             rContext->readerState->readerState &= ~SCARD_ABSENT;
01099             rContext->readerState->readerState |= SCARD_POWERED;
01100             rContext->readerState->readerState |= SCARD_NEGOTIABLE;
01101             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
01102             rContext->readerState->readerState &= ~SCARD_SWALLOWED;
01103             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
01104         }
01105         else
01106         {
01107             if (rContext->readerState->readerState & SCARD_ABSENT)
01108                 rContext->readerState->readerState &= ~SCARD_PRESENT;
01109             else
01110                 rContext->readerState->readerState |= SCARD_PRESENT;
01111             /* SCARD_ABSENT flag is already set */
01112             rContext->readerState->readerState |= SCARD_SWALLOWED;
01113             rContext->readerState->readerState &= ~SCARD_POWERED;
01114             rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
01115             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
01116             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
01117             rContext->readerState->cardAtrLength = 0;
01118         }
01119 
01120         if (rContext->readerState->cardAtrLength > 0)
01121             Log1(PCSC_LOG_DEBUG, "Reset complete.");
01122         else
01123             Log1(PCSC_LOG_ERROR, "Error resetting card.");
01124 
01125     }
01126     else if (dwDisposition == SCARD_EJECT_CARD)
01127     {
01128         UCHAR controlBuffer[5];
01129         UCHAR receiveBuffer[MAX_BUFFER_SIZE];
01130         DWORD receiveLength;
01131 
01132         /*
01133          * Set up the CTBCS command for Eject ICC
01134          */
01135         controlBuffer[0] = 0x20;
01136         controlBuffer[1] = 0x15;
01137         controlBuffer[2] = (rContext->dwSlot & 0x0000FFFF) + 1;
01138         controlBuffer[3] = 0x00;
01139         controlBuffer[4] = 0x00;
01140         receiveLength = 2;
01141         rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
01142             &receiveLength);
01143 
01144         if (rv == SCARD_S_SUCCESS)
01145         {
01146             if (receiveLength == 2 && receiveBuffer[0] == 0x90)
01147             {
01148                 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
01149                 /*
01150                  * Successful
01151                  */
01152             }
01153             else
01154                 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
01155         }
01156         else
01157             Log1(PCSC_LOG_ERROR, "Error ejecting card.");
01158 
01159     }
01160     else if (dwDisposition == SCARD_LEAVE_CARD)
01161     {
01162         /*
01163          * Do nothing
01164          */
01165     }
01166 
01167     /*
01168      * Unlock any blocks on this context
01169      */
01170     RFUnlockSharing(hCard);
01171 
01172     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01173 
01174     return rv;
01175 }
01176 
01177 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01178 {
01179     LONG rv;
01180     PREADER_CONTEXT rContext = NULL;
01181 
01182     /*
01183      * Ignoring dwDisposition for now
01184      */
01185     if (hCard == 0)
01186         return SCARD_E_INVALID_HANDLE;
01187 
01188     rv = RFReaderInfoById(hCard, &rContext);
01189 
01190     /*
01191      * Cannot find the hCard in this context
01192      */
01193     if (rv != SCARD_S_SUCCESS)
01194         return rv;
01195 
01196     rv = RFFindReaderHandle(hCard);
01197     if (rv != SCARD_S_SUCCESS)
01198         return rv;
01199 
01200     /*
01201      * Make sure some event has not occurred
01202      */
01203     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01204         return rv;
01205 
01206     rv = RFUnlockSharing(hCard);
01207 
01208     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01209 
01210     return rv;
01211 }
01212 
01213 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
01214     LPDWORD pcchReaderLen, LPDWORD pdwState,
01215     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01216 {
01217     LONG rv;
01218     PREADER_CONTEXT rContext = NULL;
01219 
01220     if (hCard == 0)
01221         return SCARD_E_INVALID_HANDLE;
01222 
01223     rv = RFReaderInfoById(hCard, &rContext);
01224 
01225     /*
01226      * Cannot find the hCard in this context
01227      */
01228     if (rv != SCARD_S_SUCCESS)
01229         return rv;
01230 
01231     if (strlen(rContext->lpcReader) > MAX_BUFFER_SIZE
01232             || rContext->readerState->cardAtrLength > MAX_ATR_SIZE)
01233         return SCARD_F_INTERNAL_ERROR;
01234 
01235     /*
01236      * This is a client side function however the server maintains the
01237      * list of events between applications so it must be passed through to
01238      * obtain this event if it has occurred
01239      */
01240 
01241     /*
01242      * Make sure some event has not occurred
01243      */
01244     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01245         return rv;
01246 
01247     /*
01248      * Make sure the reader is working properly
01249      */
01250     rv = RFCheckReaderStatus(rContext);
01251     if (rv != SCARD_S_SUCCESS)
01252         return rv;
01253 
01254     if (mszReaderNames)
01255     {  /* want reader name */
01256         if (pcchReaderLen)
01257         { /* & present reader name length */
01258             if (*pcchReaderLen >= strlen(rContext->lpcReader))
01259             { /* & enough room */
01260                 *pcchReaderLen = strlen(rContext->lpcReader);
01261                 strncpy(mszReaderNames, rContext->lpcReader, MAX_READERNAME);
01262             }
01263             else
01264             {        /* may report only reader name len */
01265                 *pcchReaderLen = strlen(rContext->lpcReader);
01266                 rv = SCARD_E_INSUFFICIENT_BUFFER;
01267             }
01268         }
01269         else
01270         {            /* present buf & no buflen */
01271             return SCARD_E_INVALID_PARAMETER;
01272         }
01273     }
01274     else
01275     {
01276         if (pcchReaderLen)
01277         { /* want reader len only */
01278             *pcchReaderLen = strlen(rContext->lpcReader);
01279         }
01280         else
01281         {
01282         /* nothing todo */
01283         }
01284     }
01285 
01286     if (pdwState)
01287         *pdwState = rContext->readerState->readerState;
01288 
01289     if (pdwProtocol)
01290         *pdwProtocol = rContext->readerState->cardProtocol;
01291 
01292     if (pbAtr)
01293     {  /* want ATR */
01294         if (pcbAtrLen)
01295         { /* & present ATR length */
01296             if (*pcbAtrLen >= rContext->readerState->cardAtrLength)
01297             { /* & enough room */
01298                 *pcbAtrLen = rContext->readerState->cardAtrLength;
01299                 memcpy(pbAtr, rContext->readerState->cardAtr,
01300                     rContext->readerState->cardAtrLength);
01301             }
01302             else
01303             { /* may report only ATR len */
01304                 *pcbAtrLen = rContext->readerState->cardAtrLength;
01305                 rv = SCARD_E_INSUFFICIENT_BUFFER;
01306             }
01307         }
01308         else
01309         { /* present buf & no buflen */
01310             return SCARD_E_INVALID_PARAMETER;
01311         }
01312     }
01313     else
01314     {
01315         if (pcbAtrLen)
01316         { /* want ATR len only */
01317             *pcbAtrLen = rContext->readerState->cardAtrLength;
01318         }
01319         else
01320         {
01321             /* nothing todo */
01322         }
01323     }
01324 
01325     return rv;
01326 }
01327 
01328 LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout,
01329     LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders)
01330 {
01331     /*
01332      * Client side function
01333      */
01334     return SCARD_S_SUCCESS;
01335 }
01336 
01337 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
01338     LPCVOID pbSendBuffer, DWORD cbSendLength,
01339     LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
01340 {
01341     LONG rv;
01342     PREADER_CONTEXT rContext = NULL;
01343 
01344     /* 0 bytes returned by default */
01345     *lpBytesReturned = 0;
01346 
01347     if (0 == hCard)
01348         return SCARD_E_INVALID_HANDLE;
01349 
01350     /*
01351      * Make sure no one has a lock on this reader
01352      */
01353     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01354         return rv;
01355 
01356     rv = RFReaderInfoById(hCard, &rContext);
01357     if (rv != SCARD_S_SUCCESS)
01358         return rv;
01359 
01360     if (IFD_HVERSION_2_0 == rContext->dwVersion)
01361         if (NULL == pbSendBuffer || 0 == cbSendLength)
01362             return SCARD_E_INVALID_PARAMETER;
01363 
01364     /*
01365      * Make sure the reader is working properly
01366      */
01367     rv = RFCheckReaderStatus(rContext);
01368     if (rv != SCARD_S_SUCCESS)
01369         return rv;
01370 
01371     rv = RFFindReaderHandle(hCard);
01372     if (rv != SCARD_S_SUCCESS)
01373         return rv;
01374 
01375     /*
01376      * Make sure some event has not occurred
01377      */
01378     if ((rv = R