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 3304 2009-02-06 08:46:19Z 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 #include "utils.h"
00097 
00098 #undef DO_PROFILE
00099 #ifdef DO_PROFILE
00100 
00101 #ifndef FALSE
00102 #define FALSE 0
00103 #define TRUE 1
00104 #endif
00105 
00106 #define PROFILE_FILE "/tmp/pcscd_profile"
00107 #include <stdio.h>
00108 #include <sys/time.h>
00109 #include <errno.h>
00110 #include <unistd.h>
00111 
00112 struct timeval profile_time_start;
00113 FILE *fd;
00114 char profile_tty;
00115 
00116 #define PROFILE_START profile_start(__FUNCTION__);
00117 #define PROFILE_END profile_end(__FUNCTION__, __LINE__);
00118 
00119 static void profile_start(const char *f)
00120 {
00121     static char initialized = FALSE;
00122 
00123     if (!initialized)
00124     {
00125         initialized = TRUE;
00126         fd = fopen(PROFILE_FILE, "a+");
00127         if (NULL == fd)
00128         {
00129             fprintf(stderr, "\33[01;31mCan't open %s: %s\33[0m\n",
00130                 PROFILE_FILE, strerror(errno));
00131             exit(-1);
00132         }
00133         fprintf(fd, "\nStart a new profile\n");
00134         fflush(fd);
00135 
00136         if (isatty(fileno(stderr)))
00137             profile_tty = TRUE;
00138         else
00139             profile_tty = FALSE;
00140     }
00141 
00142     gettimeofday(&profile_time_start, NULL);
00143 } /* profile_start */
00144 
00145 /* r = a - b */
00146 static long int time_sub(struct timeval *a, struct timeval *b)
00147 {
00148     struct timeval r;
00149     r.tv_sec = a -> tv_sec - b -> tv_sec;
00150     r.tv_usec = a -> tv_usec - b -> tv_usec;
00151     if (r.tv_usec < 0)
00152     {
00153         r.tv_sec--;
00154         r.tv_usec += 1000000;
00155     }
00156 
00157     return r.tv_sec * 1000000 + r.tv_usec;
00158 } /* time_sub */
00159 
00160 
00161 static void profile_end(const char *f, int line)
00162 {
00163     struct timeval profile_time_end;
00164     long d;
00165 
00166     gettimeofday(&profile_time_end, NULL);
00167     d = time_sub(&profile_time_end, &profile_time_start);
00168 
00169     if (profile_tty)
00170         fprintf(stderr, "\33[01;31mRESULT %s \33[35m%ld\33[0m (%d)\n", f, d,
00171             line);
00172     fprintf(fd, "%s %ld\n", f, d);
00173     fflush(fd);
00174 } /* profile_end */
00175 
00176 #else
00177 #define PROFILE_START
00178 #define PROFILE_END
00179 #endif
00180 
00182 #define SCARD_PROTOCOL_ANY_OLD   0x1000
00183 
00185 #define SCARD_LAST_CONTEXT       1
00186 
00187 #define SCARD_NO_CONTEXT         0
00188 
00189 #define SCARD_EXCLUSIVE_CONTEXT -1
00190 
00191 #define SCARD_NO_LOCK            0
00192 
00193 SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, sizeof(SCARD_IO_REQUEST) };
00194 SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, sizeof(SCARD_IO_REQUEST) };
00195 SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, sizeof(SCARD_IO_REQUEST) };
00196 
00217 LONG SCardEstablishContext(DWORD dwScope, /*@unused@*/ LPCVOID pvReserved1,
00218     /*@unused@*/ LPCVOID pvReserved2, LPSCARDCONTEXT phContext)
00219 {
00220     (void)pvReserved1;
00221     (void)pvReserved2;
00222     /*
00223      * Check for NULL pointer
00224      */
00225     if (phContext == 0)
00226         return SCARD_E_INVALID_PARAMETER;
00227 
00228     if (dwScope != SCARD_SCOPE_USER && dwScope != SCARD_SCOPE_TERMINAL &&
00229         dwScope != SCARD_SCOPE_SYSTEM && dwScope != SCARD_SCOPE_GLOBAL)
00230     {
00231         *phContext = 0;
00232         return SCARD_E_INVALID_VALUE;
00233     }
00234 
00235     /*
00236      * Unique identifier for this server so that it can uniquely be
00237      * identified by clients and distinguished from others
00238      */
00239 
00240     *phContext = (PCSCLITE_SVC_IDENTITY + SYS_RandomInt(1, 65535));
00241 
00242     Log2(PCSC_LOG_DEBUG, "Establishing Context: %d", *phContext);
00243 
00244     return SCARD_S_SUCCESS;
00245 }
00246 
00247 LONG SCardReleaseContext(SCARDCONTEXT hContext)
00248 {
00249     /*
00250      * Nothing to do here RPC layer will handle this
00251      */
00252 
00253     Log2(PCSC_LOG_DEBUG, "Releasing Context: %d", hContext);
00254 
00255     return SCARD_S_SUCCESS;
00256 }
00257 
00258 LONG SCardSetTimeout(/*@unused@*/ SCARDCONTEXT hContext,
00259     /*@unused@*/ DWORD dwTimeout)
00260 {
00261     /*
00262      * This is only used at the client side of an RPC call but just in
00263      * case someone calls it here
00264      */
00265 
00266     (void)hContext;
00267     (void)dwTimeout;
00268     return SCARD_E_UNSUPPORTED_FEATURE;
00269 }
00270 
00271 LONG SCardConnect(/*@unused@*/ SCARDCONTEXT hContext, LPCSTR szReader,
00272     DWORD dwShareMode, DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
00273     LPDWORD pdwActiveProtocol)
00274 {
00275     LONG rv;
00276     PREADER_CONTEXT rContext = NULL;
00277     DWORD dwStatus;
00278 
00279     (void)hContext;
00280     PROFILE_START
00281 
00282     /*
00283      * Check for NULL parameters
00284      */
00285     if (szReader == NULL || phCard == NULL || pdwActiveProtocol == NULL)
00286         return SCARD_E_INVALID_PARAMETER;
00287     else
00288         *phCard = 0;
00289 
00290     if ((dwShareMode != SCARD_SHARE_DIRECT) &&
00291             !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00292             !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00293             !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00294             !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00295         return SCARD_E_PROTO_MISMATCH;
00296 
00297     if (dwShareMode != SCARD_SHARE_EXCLUSIVE &&
00298             dwShareMode != SCARD_SHARE_SHARED &&
00299             dwShareMode != SCARD_SHARE_DIRECT)
00300         return SCARD_E_INVALID_VALUE;
00301 
00302     Log3(PCSC_LOG_DEBUG, "Attempting Connect to %s using protocol: %d",
00303         szReader, dwPreferredProtocols);
00304 
00305     rv = RFReaderInfo((LPSTR) szReader, &rContext);
00306 
00307     if (rv != SCARD_S_SUCCESS)
00308     {
00309         Log2(PCSC_LOG_ERROR, "Reader %s Not Found", szReader);
00310         return rv;
00311     }
00312 
00313     /*
00314      * Make sure the reader is working properly
00315      */
00316     rv = RFCheckReaderStatus(rContext);
00317     if (rv != SCARD_S_SUCCESS)
00318         return rv;
00319 
00320     /*******************************************
00321      *
00322      * This section checks for simple errors
00323      *
00324      *******************************************/
00325 
00326     /*
00327      * Connect if not exclusive mode
00328      */
00329     if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00330     {
00331         Log1(PCSC_LOG_ERROR, "Error Reader Exclusive");
00332         return SCARD_E_SHARING_VIOLATION;
00333     }
00334 
00335     /*
00336      * wait until a possible transaction is finished
00337      */
00338     if (rContext->dwLockId != 0)
00339     {
00340         Log1(PCSC_LOG_INFO, "Waiting for release of lock");
00341         while (rContext->dwLockId != 0)
00342             (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
00343         Log1(PCSC_LOG_INFO, "Lock released");
00344     }
00345 
00346     /* the reader has been removed while we were waiting */
00347     if (NULL == rContext->readerState)
00348         return SCARD_E_NO_SMARTCARD;
00349 
00350     /*******************************************
00351      *
00352      * This section tries to determine the
00353      * presence of a card or not
00354      *
00355      *******************************************/
00356     dwStatus = rContext->readerState->readerState;
00357 
00358     if (dwShareMode != SCARD_SHARE_DIRECT)
00359     {
00360         if (!(dwStatus & SCARD_PRESENT))
00361         {
00362             Log1(PCSC_LOG_ERROR, "Card Not Inserted");
00363             return SCARD_E_NO_SMARTCARD;
00364         }
00365 
00366         if (dwStatus & SCARD_SWALLOWED)
00367         {
00368             Log1(PCSC_LOG_ERROR, "Card Not Powered");
00369             return SCARD_W_UNPOWERED_CARD;
00370         }
00371     }
00372 
00373 
00374     /*******************************************
00375      *
00376      * This section tries to decode the ATR
00377      * and set up which protocol to use
00378      *
00379      *******************************************/
00380     if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
00381         rContext->readerState->cardProtocol = SCARD_PROTOCOL_RAW;
00382     else
00383     {
00384         if (dwShareMode != SCARD_SHARE_DIRECT)
00385         {
00386             /* lock here instead in IFDSetPTS() to lock up to
00387              * setting rContext->readerState->cardProtocol */
00388             (void)SYS_MutexLock(rContext->mMutex);
00389 
00390             /* the protocol is not yet set (no PPS yet) */
00391             if (SCARD_PROTOCOL_UNDEFINED == rContext->readerState->cardProtocol)
00392             {
00393                 UCHAR ucAvailable, ucDefault;
00394                 int ret;
00395 
00396                 ucDefault = PHGetDefaultProtocol(rContext->readerState->cardAtr,
00397                     rContext->readerState->cardAtrLength);
00398                 ucAvailable =
00399                     PHGetAvailableProtocols(rContext->readerState->cardAtr,
00400                             rContext->readerState->cardAtrLength);
00401 
00402                 /*
00403                  * If it is set to ANY let it do any of the protocols
00404                  */
00405                 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
00406                     dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
00407 
00408                 ret = PHSetProtocol(rContext, dwPreferredProtocols,
00409                     ucAvailable, ucDefault);
00410 
00411                 /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error  */
00412                 if (SET_PROTOCOL_PPS_FAILED == ret)
00413                 {
00414                     (void)SYS_MutexUnLock(rContext->mMutex);
00415                     return SCARD_W_UNRESPONSIVE_CARD;
00416                 }
00417 
00418                 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
00419                 {
00420                     (void)SYS_MutexUnLock(rContext->mMutex);
00421                     return SCARD_E_PROTO_MISMATCH;
00422                 }
00423 
00424                 /* use negociated protocol */
00425                 rContext->readerState->cardProtocol = ret;
00426 
00427                 (void)SYS_MutexUnLock(rContext->mMutex);
00428             }
00429             else
00430             {
00431                 (void)SYS_MutexUnLock(rContext->mMutex);
00432 
00433                 if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
00434                     return SCARD_E_PROTO_MISMATCH;
00435             }
00436         }
00437     }
00438 
00439     *pdwActiveProtocol = rContext->readerState->cardProtocol;
00440 
00441     if (dwShareMode != SCARD_SHARE_DIRECT)
00442     {
00443         if ((*pdwActiveProtocol != SCARD_PROTOCOL_T0)
00444             && (*pdwActiveProtocol != SCARD_PROTOCOL_T1))
00445             Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %d",
00446                 *pdwActiveProtocol);
00447         else
00448             Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
00449                 (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
00450     }
00451     else
00452         Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
00453 
00454     /*
00455      * Prepare the SCARDHANDLE identity
00456      */
00457     *phCard = RFCreateReaderHandle(rContext);
00458 
00459     Log2(PCSC_LOG_DEBUG, "hCard Identity: %x", *phCard);
00460 
00461     /*******************************************
00462      *
00463      * This section tries to set up the
00464      * exclusivity modes. -1 is exclusive
00465      *
00466      *******************************************/
00467 
00468     if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
00469     {
00470         if (rContext->dwContexts == SCARD_NO_CONTEXT)
00471         {
00472             rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
00473             (void)RFLockSharing(*phCard);
00474         }
00475         else
00476         {
00477             (void)RFDestroyReaderHandle(*phCard);
00478             *phCard = 0;
00479             return SCARD_E_SHARING_VIOLATION;
00480         }
00481     }
00482     else
00483     {
00484         /*
00485          * Add a connection to the context stack
00486          */
00487         rContext->dwContexts += 1;
00488     }
00489 
00490     /*
00491      * Add this handle to the handle list
00492      */
00493     rv = RFAddReaderHandle(rContext, *phCard);
00494 
00495     if (rv != SCARD_S_SUCCESS)
00496     {
00497         /*
00498          * Clean up - there is no more room
00499          */
00500         (void)RFDestroyReaderHandle(*phCard);
00501         if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00502             rContext->dwContexts = SCARD_NO_CONTEXT;
00503         else
00504             if (rContext->dwContexts > SCARD_NO_CONTEXT)
00505                 rContext->dwContexts -= 1;
00506 
00507         *phCard = 0;
00508 
00509         PROFILE_END
00510 
00511         return SCARD_F_INTERNAL_ERROR;
00512     }
00513 
00514     /*
00515      * Propagate new state to Shared Memory
00516      */
00517     rContext->readerState->readerSharing = rContext->dwContexts;
00518     (void)StatSynchronize(rContext->readerState);
00519 
00520     PROFILE_END
00521 
00522     return SCARD_S_SUCCESS;
00523 }
00524 
00525 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00526     DWORD dwPreferredProtocols, DWORD dwInitialization,
00527     LPDWORD pdwActiveProtocol)
00528 {
00529     LONG rv;
00530     PREADER_CONTEXT rContext = NULL;
00531 
00532     Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");
00533 
00534     if (hCard == 0)
00535         return SCARD_E_INVALID_HANDLE;
00536 
00537     /*
00538      * Handle the dwInitialization
00539      */
00540     if (dwInitialization != SCARD_LEAVE_CARD &&
00541             dwInitialization != SCARD_RESET_CARD &&
00542             dwInitialization != SCARD_UNPOWER_CARD)
00543         return SCARD_E_INVALID_VALUE;
00544 
00545     if (dwShareMode != SCARD_SHARE_SHARED &&
00546             dwShareMode != SCARD_SHARE_EXCLUSIVE &&
00547             dwShareMode != SCARD_SHARE_DIRECT)
00548         return SCARD_E_INVALID_VALUE;
00549 
00550     if ((dwShareMode != SCARD_SHARE_DIRECT) &&
00551             !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00552             !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00553             !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00554             !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00555         return SCARD_E_PROTO_MISMATCH;
00556 
00557     if (pdwActiveProtocol == NULL)
00558         return SCARD_E_INVALID_PARAMETER;
00559 
00560     rv = RFReaderInfoById(hCard, &rContext);
00561     if (rv != SCARD_S_SUCCESS)
00562         return rv;
00563 
00564     /*
00565      * Make sure the reader is working properly
00566      */
00567     rv = RFCheckReaderStatus(rContext);
00568     if (rv != SCARD_S_SUCCESS)
00569         return rv;
00570 
00571     rv = RFFindReaderHandle(hCard);
00572     if (rv != SCARD_S_SUCCESS)
00573         return rv;
00574 
00575     /*
00576      * Make sure no one has a lock on this reader
00577      */
00578     rv = RFCheckSharing(hCard);
00579     if (rv != SCARD_S_SUCCESS)
00580         return rv;
00581 
00582     /*
00583      * RFUnblockReader( rContext ); FIX - this doesn't work
00584      */
00585 
00586     if (dwInitialization == SCARD_RESET_CARD ||
00587         dwInitialization == SCARD_UNPOWER_CARD)
00588     {
00589         DWORD dwAtrLen;
00590         /*
00591          * Currently pcsc-lite keeps the card powered constantly
00592          */
00593         dwAtrLen = rContext->readerState->cardAtrLength;
00594         if (SCARD_RESET_CARD == dwInitialization)
00595             rv = IFDPowerICC(rContext, IFD_RESET,
00596                 rContext->readerState->cardAtr,
00597                 &dwAtrLen);
00598         else
00599         {
00600             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
00601                 rContext->readerState->cardAtr,
00602                 &dwAtrLen);
00603             rv = IFDPowerICC(rContext, IFD_POWER_UP,
00604                 rContext->readerState->cardAtr,
00605                 &dwAtrLen);
00606         }
00607         rContext->readerState->cardAtrLength = dwAtrLen;
00608 
00609         /* the protocol is unset after a power on */
00610         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00611 
00612         /*
00613          * Notify the card has been reset
00614          * Not doing this could result in deadlock
00615          */
00616         rv = RFCheckReaderEventState(rContext, hCard);
00617         switch(rv)
00618         {
00619             /* avoid deadlock */
00620             case SCARD_W_RESET_CARD:
00621                 break;
00622 
00623             case SCARD_W_REMOVED_CARD:
00624                 Log1(PCSC_LOG_ERROR, "card removed");
00625                 return SCARD_W_REMOVED_CARD;
00626 
00627             /* invalid EventStatus */
00628             case SCARD_E_INVALID_VALUE:
00629                 Log1(PCSC_LOG_ERROR, "invalid EventStatus");
00630                 return SCARD_F_INTERNAL_ERROR;
00631 
00632             /* invalid hCard, but hCard was widely used some lines above :( */
00633             case SCARD_E_INVALID_HANDLE:
00634                 Log1(PCSC_LOG_ERROR, "invalid handle");
00635                 return SCARD_F_INTERNAL_ERROR;
00636 
00637             case SCARD_S_SUCCESS:
00638                 /*
00639                  * Notify the card has been reset
00640                  */
00641                 (void)RFSetReaderEventState(rContext, SCARD_RESET);
00642 
00643                 /*
00644                  * Set up the status bit masks on dwStatus
00645                  */
00646                 if (rv == SCARD_S_SUCCESS)
00647                 {
00648                     rContext->readerState->readerState |= SCARD_PRESENT;
00649                     rContext->readerState->readerState &= ~SCARD_ABSENT;
00650                     rContext->readerState->readerState |= SCARD_POWERED;
00651                     rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00652                     rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00653                     rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00654                     rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00655                 }
00656                 else
00657                 {
00658                     rContext->readerState->readerState |= SCARD_PRESENT;
00659                     rContext->readerState->readerState &= ~SCARD_ABSENT;
00660                     rContext->readerState->readerState |= SCARD_SWALLOWED;
00661                     rContext->readerState->readerState &= ~SCARD_POWERED;
00662                     rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00663                     rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00664                     rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00665                     rContext->readerState->cardAtrLength = 0;
00666                 }
00667 
00668                 if (rContext->readerState->cardAtrLength > 0)
00669                 {
00670                     Log1(PCSC_LOG_DEBUG, "Reset complete.");
00671                     LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
00672                         rContext->readerState->cardAtr,
00673                         rContext->readerState->cardAtrLength);
00674                 }
00675                 else
00676                 {
00677                     DWORD dwStatus, dwAtrLen2;
00678                     UCHAR ucAtr[MAX_ATR_SIZE];
00679 
00680                     Log1(PCSC_LOG_ERROR, "Error resetting card.");
00681                     (void)IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen2);
00682                     if (dwStatus & SCARD_PRESENT)
00683                         return SCARD_W_UNRESPONSIVE_CARD;
00684                     else
00685                         return SCARD_E_NO_SMARTCARD;
00686                 }
00687                 break;
00688 
00689             default:
00690                 Log2(PCSC_LOG_ERROR,
00691                     "invalid retcode from RFCheckReaderEventState (%X)", rv);
00692                 return SCARD_F_INTERNAL_ERROR;
00693                 break;
00694         }
00695     }
00696     else
00697         if (dwInitialization == SCARD_LEAVE_CARD)
00698         {
00699             /*
00700              * Do nothing
00701              */
00702         }
00703 
00704     /*******************************************
00705      *
00706      * This section tries to decode the ATR
00707      * and set up which protocol to use
00708      *
00709      *******************************************/
00710     if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
00711         rContext->readerState->cardProtocol = SCARD_PROTOCOL_RAW;
00712     else
00713     {
00714         if (dwShareMode != SCARD_SHARE_DIRECT)
00715         {
00716             /* lock here instead in IFDSetPTS() to lock up to
00717              * setting rContext->readerState->cardProtocol */
00718             (void)SYS_MutexLock(rContext->mMutex);
00719 
00720             /* the protocol is not yet set (no PPS yet) */
00721             if (SCARD_PROTOCOL_UNDEFINED == rContext->readerState->cardProtocol)
00722             {
00723                 UCHAR ucAvailable, ucDefault;
00724                 int ret;
00725 
00726                 ucDefault = PHGetDefaultProtocol(rContext->readerState->cardAtr,
00727                     rContext->readerState->cardAtrLength);
00728                 ucAvailable =
00729                     PHGetAvailableProtocols(rContext->readerState->cardAtr,
00730                             rContext->readerState->cardAtrLength);
00731 
00732                 /* If it is set to ANY let it do any of the protocols */
00733                 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
00734                     dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
00735 
00736                 ret = PHSetProtocol(rContext, dwPreferredProtocols,
00737                     ucAvailable, ucDefault);
00738 
00739                 /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error  */
00740                 if (SET_PROTOCOL_PPS_FAILED == ret)
00741                 {
00742                     (void)SYS_MutexUnLock(rContext->mMutex);
00743                     return SCARD_W_UNRESPONSIVE_CARD;
00744                 }
00745 
00746                 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
00747                 {
00748                     (void)SYS_MutexUnLock(rContext->mMutex);
00749                     return SCARD_E_PROTO_MISMATCH;
00750                 }
00751 
00752                 /* use negociated protocol */
00753                 rContext->readerState->cardProtocol = ret;
00754 
00755                 (void)SYS_MutexUnLock(rContext->mMutex);
00756             }
00757             else
00758             {
00759                 (void)SYS_MutexUnLock(rContext->mMutex);
00760 
00761                 if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
00762                     return SCARD_E_PROTO_MISMATCH;
00763             }
00764         }
00765     }
00766 
00767     *pdwActiveProtocol = rContext->readerState->cardProtocol;
00768 
00769     if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
00770     {
00771         if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00772         {
00773             /*
00774              * Do nothing - we are already exclusive
00775              */
00776         } else
00777         {
00778             if (rContext->dwContexts == SCARD_LAST_CONTEXT)
00779             {
00780                 rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
00781                 (void)RFLockSharing(hCard);
00782             } else
00783             {
00784                 return SCARD_E_SHARING_VIOLATION;
00785             }
00786         }
00787     } else if (dwShareMode == SCARD_SHARE_SHARED)
00788     {
00789         if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
00790         {
00791             /*
00792              * Do nothing - in sharing mode already
00793              */
00794         } else
00795         {
00796             /*
00797              * We are in exclusive mode but want to share now
00798              */
00799             (void)RFUnlockSharing(hCard);
00800             rContext->dwContexts = SCARD_LAST_CONTEXT;
00801         }
00802     } else if (dwShareMode == SCARD_SHARE_DIRECT)
00803     {
00804         if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
00805         {
00806             /*
00807              * Do nothing - in sharing mode already
00808              */
00809         } else
00810         {
00811             /*
00812              * We are in exclusive mode but want to share now
00813              */
00814             (void)RFUnlockSharing(hCard);
00815             rContext->dwContexts = SCARD_LAST_CONTEXT;
00816         }
00817     } else
00818         return SCARD_E_INVALID_VALUE;
00819 
00820     /*
00821      * Clear a previous event to the application
00822      */
00823     (void)RFClearReaderEventState(rContext, hCard);
00824 
00825     /*
00826      * Propagate new state to Shared Memory
00827      */
00828     rContext->readerState->readerSharing = rContext->dwContexts;
00829     (void)StatSynchronize(rContext->readerState);
00830 
00831     return SCARD_S_SUCCESS;
00832 }
00833 
00834 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
00835 {
00836     LONG rv;
00837     PREADER_CONTEXT rContext = NULL;
00838     DWORD dwAtrLen;
00839 
00840     if (hCard == 0)
00841         return SCARD_E_INVALID_HANDLE;
00842 
00843     rv = RFReaderInfoById(hCard, &rContext);
00844     if (rv != SCARD_S_SUCCESS)
00845         return rv;
00846 
00847     rv = RFFindReaderHandle(hCard);
00848     if (rv != SCARD_S_SUCCESS)
00849         return rv;
00850 
00851     if ((dwDisposition != SCARD_LEAVE_CARD)
00852         && (dwDisposition != SCARD_UNPOWER_CARD)
00853         && (dwDisposition != SCARD_RESET_CARD)
00854         && (dwDisposition != SCARD_EJECT_CARD))
00855         return SCARD_E_INVALID_VALUE;
00856 
00857     /*
00858      * wait until a possible transaction is finished
00859      */
00860     if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->dwLockId != 0)
00861         && (rContext->dwLockId != hCard))
00862     {
00863         Log1(PCSC_LOG_INFO, "Waiting for release of lock");
00864         while (rContext->dwLockId != 0)
00865             (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
00866         Log1(PCSC_LOG_INFO, "Lock released");
00867     }
00868 
00869     /* the reader has been removed while we were waiting */
00870     if (NULL == rContext->readerState)
00871         return SCARD_E_NO_SMARTCARD;
00872 
00873     /*
00874      * Unlock any blocks on this context
00875      */
00876     rv = RFUnlockSharing(hCard);
00877     if (rv != SCARD_S_SUCCESS)
00878         return rv;
00879 
00880     Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->dwContexts);
00881 
00882     if (dwDisposition == SCARD_RESET_CARD ||
00883         dwDisposition == SCARD_UNPOWER_CARD)
00884     {
00885         /*
00886          * Currently pcsc-lite keeps the card powered constantly
00887          */
00888         dwAtrLen = rContext->readerState->cardAtrLength;
00889         if (SCARD_RESET_CARD == dwDisposition)
00890             rv = IFDPowerICC(rContext, IFD_RESET,
00891                 rContext->readerState->cardAtr,
00892                 &dwAtrLen);
00893         else
00894         {
00895             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
00896                 rContext->readerState->cardAtr,
00897                 &dwAtrLen);
00898             rv = IFDPowerICC(rContext, IFD_POWER_UP,
00899                 rContext->readerState->cardAtr,
00900                 &dwAtrLen);
00901         }
00902         rContext->readerState->cardAtrLength = dwAtrLen;
00903 
00904         /* the protocol is unset after a power on */
00905         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00906 
00907         /*
00908          * Notify the card has been reset
00909          */
00910         (void)RFSetReaderEventState(rContext, SCARD_RESET);
00911 
00912         /*
00913          * Set up the status bit masks on dwStatus
00914          */
00915         if (rv == SCARD_S_SUCCESS)
00916         {
00917             rContext->readerState->readerState |= SCARD_PRESENT;
00918             rContext->readerState->readerState &= ~SCARD_ABSENT;
00919             rContext->readerState->readerState |= SCARD_POWERED;
00920             rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00921             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00922             rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00923             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00924         }
00925         else
00926         {
00927             if (rContext->readerState->readerState & SCARD_ABSENT)
00928                 rContext->readerState->readerState &= ~SCARD_PRESENT;
00929             else
00930                 rContext->readerState->readerState |= SCARD_PRESENT;
00931             /* SCARD_ABSENT flag is already set */
00932             rContext->readerState->readerState |= SCARD_SWALLOWED;
00933             rContext->readerState->readerState &= ~SCARD_POWERED;
00934             rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00935             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00936             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00937             rContext->readerState->cardAtrLength = 0;
00938         }
00939 
00940         if (rContext->readerState->cardAtrLength > 0)
00941             Log1(PCSC_LOG_DEBUG, "Reset complete.");
00942         else
00943             Log1(PCSC_LOG_ERROR, "Error resetting card.");
00944     }
00945     else if (dwDisposition == SCARD_EJECT_CARD)
00946     {
00947         UCHAR controlBuffer[5];
00948         UCHAR receiveBuffer[MAX_BUFFER_SIZE];
00949         DWORD receiveLength;
00950 
00951         /*
00952          * Set up the CTBCS command for Eject ICC
00953          */
00954         controlBuffer[0] = 0x20;
00955         controlBuffer[1] = 0x15;
00956         controlBuffer[2] = (rContext->dwSlot & 0x0000FFFF) + 1;
00957         controlBuffer[3] = 0x00;
00958         controlBuffer[4] = 0x00;
00959         receiveLength = 2;
00960         rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
00961             &receiveLength);
00962 
00963         if (rv == SCARD_S_SUCCESS)
00964         {
00965             if (receiveLength == 2 && receiveBuffer[0] == 0x90)
00966             {
00967                 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
00968                 /*
00969                  * Successful
00970                  */
00971             }
00972             else
00973                 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
00974         }
00975         else
00976             Log1(PCSC_LOG_ERROR, "Error ejecting card.");
00977 
00978     }
00979     else if (dwDisposition == SCARD_LEAVE_CARD)
00980     {
00981         /*
00982          * Do nothing
00983          */
00984     }
00985 
00986     /*
00987      * Remove and destroy this handle
00988      */
00989     (void)RFRemoveReaderHandle(rContext, hCard);
00990     (void)RFDestroyReaderHandle(hCard);
00991 
00992     /*
00993      * For exclusive connection reset it to no connections
00994      */
00995     if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00996         rContext->dwContexts = SCARD_NO_CONTEXT;
00997     else
00998     {
00999         /*
01000          * Remove a connection from the context stack
01001          */
01002         rContext->dwContexts -= 1;
01003 
01004         if (rContext->dwContexts < 0)
01005             rContext->dwContexts = 0;
01006     }
01007 
01008     /*
01009      * Propagate new state to Shared Memory
01010      */
01011     rContext->readerState->readerSharing = rContext->dwContexts;
01012     (void)StatSynchronize(rContext->readerState);
01013 
01014     return SCARD_S_SUCCESS;
01015 }
01016 
01017 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01018 {
01019     LONG rv;
01020     PREADER_CONTEXT rContext;
01021 
01022     if (hCard == 0)
01023         return SCARD_E_INVALID_HANDLE;
01024 
01025     rv = RFReaderInfoById(hCard, &rContext);
01026 
01027     /*
01028      * Cannot find the hCard in this context
01029      */
01030     if (rv != SCARD_S_SUCCESS)
01031         return rv;
01032 
01033     /*
01034      * Make sure the reader is working properly
01035      */
01036     rv = RFCheckReaderStatus(rContext);
01037     if (rv != SCARD_S_SUCCESS)
01038         return rv;
01039 
01040     rv = RFFindReaderHandle(hCard);
01041     if (rv != SCARD_S_SUCCESS)
01042         return rv;
01043 
01044     /*
01045      * Make sure some event has not occurred
01046      */
01047     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01048         return rv;
01049 
01050     rv = RFLockSharing(hCard);
01051 
01052     /* if the transaction is not yet ready we sleep a bit so the client
01053      * do not retry immediately */
01054     if (SCARD_E_SHARING_VIOLATION == rv)
01055         (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
01056 
01057     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01058 
01059     return rv;
01060 }
01061 
01062 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01063 {
01064     LONG rv;
01065     PREADER_CONTEXT rContext = NULL;
01066     DWORD dwAtrLen;
01067 
01068     /*
01069      * Ignoring dwDisposition for now
01070      */
01071     if (hCard == 0)
01072         return SCARD_E_INVALID_HANDLE;
01073 
01074     if ((dwDisposition != SCARD_LEAVE_CARD)
01075         && (dwDisposition != SCARD_UNPOWER_CARD)
01076         && (dwDisposition != SCARD_RESET_CARD)
01077         && (dwDisposition != SCARD_EJECT_CARD))
01078     return SCARD_E_INVALID_VALUE;
01079 
01080     rv = RFReaderInfoById(hCard, &rContext);
01081 
01082     /*
01083      * Cannot find the hCard in this context
01084      */
01085     if (rv != SCARD_S_SUCCESS)
01086         return rv;
01087 
01088     rv = RFFindReaderHandle(hCard);
01089     if (rv != SCARD_S_SUCCESS)
01090         return rv;
01091 
01092     /*
01093      * Make sure some event has not occurred
01094      */
01095     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01096         return rv;
01097 
01098     if (dwDisposition == SCARD_RESET_CARD ||
01099         dwDisposition == SCARD_UNPOWER_CARD)
01100     {
01101         /*
01102          * Currently pcsc-lite keeps the card always powered
01103          */
01104         dwAtrLen = rContext->readerState->cardAtrLength;
01105         if (SCARD_RESET_CARD == dwDisposition)
01106             rv = IFDPowerICC(rContext, IFD_RESET,
01107                 rContext->readerState->cardAtr,
01108                 &dwAtrLen);
01109         else
01110         {
01111             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
01112                 rContext->readerState->cardAtr,
01113                 &dwAtrLen);
01114             rv = IFDPowerICC(rContext, IFD_POWER_UP,
01115                 rContext->readerState->cardAtr,
01116                 &dwAtrLen);
01117         }
01118         rContext->readerState->cardAtrLength = dwAtrLen;
01119 
01120         /* the protocol is unset after a power on */
01121         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
01122 
01123         /*
01124          * Notify the card has been reset
01125          */
01126         (void)RFSetReaderEventState(rContext, SCARD_RESET);
01127 
01128         /*
01129          * Set up the status bit masks on dwStatus
01130          */
01131         if (rv == SCARD_S_SUCCESS)
01132         {
01133             rContext->readerState->readerState |= SCARD_PRESENT;
01134             rContext->readerState->readerState &= ~SCARD_ABSENT;
01135             rContext->readerState->readerState |= SCARD_POWERED;
01136             rContext->readerState->readerState |= SCARD_NEGOTIABLE;
01137             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
01138             rContext->readerState->readerState &= ~SCARD_SWALLOWED;
01139             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
01140         }
01141         else
01142         {
01143             if (rContext->readerState->readerState & SCARD_ABSENT)
01144                 rContext->readerState->readerState &= ~SCARD_PRESENT;
01145             else
01146                 rContext->readerState->readerState |= SCARD_PRESENT;
01147             /* SCARD_ABSENT flag is already set */
01148             rContext->readerState->readerState |= SCARD_SWALLOWED;
01149             rContext->readerState->readerState &= ~SCARD_POWERED;
01150             rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
01151             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
01152             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
01153             rContext->readerState->cardAtrLength = 0;
01154         }
01155 
01156         if (rContext->readerState->cardAtrLength > 0)
01157             Log1(PCSC_LOG_DEBUG, "Reset complete.");
01158         else
01159             Log1(PCSC_LOG_ERROR, "Error resetting card.");
01160 
01161     }
01162     else if (dwDisposition == SCARD_EJECT_CARD)
01163     {
01164         UCHAR controlBuffer[5];
01165         UCHAR receiveBuffer[MAX_BUFFER_SIZE];
01166         DWORD receiveLength;
01167 
01168         /*
01169          * Set up the CTBCS command for Eject ICC
01170          */
01171         controlBuffer[0] = 0x20;
01172         controlBuffer[1] = 0x15;
01173         controlBuffer[2] = (rContext->dwSlot & 0x0000FFFF) + 1;
01174         controlBuffer[3] = 0x00;
01175         controlBuffer[4] = 0x00;
01176         receiveLength = 2;
01177         rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
01178             &receiveLength);
01179 
01180         if (rv == SCARD_S_SUCCESS)
01181         {
01182             if (receiveLength == 2 && receiveBuffer[0] == 0x90)
01183             {
01184                 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
01185                 /*
01186                  * Successful
01187                  */
01188             }
01189             else
01190                 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
01191         }
01192         else
01193             Log1(PCSC_LOG_ERROR, "Error ejecting card.");
01194 
01195     }
01196     else if (dwDisposition == SCARD_LEAVE_CARD)
01197     {
01198         /*
01199          * Do nothing
01200          */
01201     }
01202 
01203     /*
01204      * Unlock any blocks on this context
01205      */
01206     (void)RFUnlockSharing(hCard);
01207 
01208     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01209 
01210     return rv;
01211 }
01212 
01213 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01214 {
01215     LONG rv;
01216     PREADER_CONTEXT rContext = NULL;
01217 
01218     /*
01219      * Ignoring dwDisposition for now
01220      */
01221     if (hCard == 0)
01222         return SCARD_E_INVALID_HANDLE;
01223 
01224     rv = RFReaderInfoById(hCard, &rContext);
01225 
01226     /*
01227      * Cannot find the hCard in this context
01228      */
01229     if (rv != SCARD_S_SUCCESS)
01230         return rv;
01231 
01232     rv = RFFindReaderHandle(hCard);
01233     if (rv != SCARD_S_SUCCESS)
01234         return rv;
01235 
01236     /*
01237      * Make sure some event has not occurred
01238      */
01239     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01240         return rv;
01241 
01242     rv = RFUnlockSharing(hCard);
01243 
01244     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01245 
01246     return rv;
01247 }
01248 
01249 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
01250     LPDWORD pcchReaderLen, LPDWORD pdwState,
01251     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01252 {
01253     LONG rv;
01254     PREADER_CONTEXT rContext = NULL;
01255 
01256     if (hCard == 0)
01257         return SCARD_E_INVALID_HANDLE;
01258 
01259     rv = RFReaderInfoById(hCard, &rContext);
01260 
01261     /*
01262      * Cannot find the hCard in this context
01263      */
01264     if (rv != SCARD_S_SUCCESS)
01265         return rv;
01266 
01267     if (strlen(rContext->lpcReader) > MAX_BUFFER_SIZE
01268             || rContext->readerState->cardAtrLength > MAX_ATR_SIZE)
01269         return SCARD_F_INTERNAL_ERROR;
01270 
01271     /*
01272      * This is a client side function however the server maintains the
01273      * list of events between applications so it must be passed through to
01274      * obtain this event if it has occurred
01275      */
01276 
01277     /*
01278      * Make sure some event has not occurred
01279      */
01280     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01281         return rv;
01282 
01283     /*
01284      * Make sure the reader is working properly
01285      */
01286     rv = RFCheckReaderStatus(rContext);
01287     if (rv != SCARD_S_SUCCESS)
01288         return rv;
01289 
01290     if (mszReaderNames)
01291     {  /* want reader name */
01292         if (pcchReaderLen)
01293         { /* & present reader name length */
01294             if (*pcchReaderLen >= strlen(rContext->lpcReader))
01295             { /* & enough room */
01296                 *pcchReaderLen = strlen(rContext->lpcReader);
01297                 strncpy(mszReaderNames, rContext->lpcReader, MAX_READERNAME);
01298             }
01299             else
01300             {        /* may report only reader name len */
01301                 *pcchReaderLen = strlen(rContext->lpcReader);
01302                 rv = SCARD_E_INSUFFICIENT_BUFFER;
01303             }
01304         }
01305         else
01306         {            /* present buf & no buflen */
01307             return SCARD_E_INVALID_PARAMETER;
01308         }
01309     }
01310     else
01311     {
01312         if (pcchReaderLen)
01313         { /* want reader len only */
01314             *pcchReaderLen = strlen(rContext->lpcReader);
01315         }
01316         else
01317         {
01318         /* nothing todo */
01319         }
01320     }
01321 
01322     if (pdwState)
01323         *pdwState = rContext->readerState->readerState;
01324 
01325     if (pdwProtocol)
01326         *pdwProtocol = rContext->readerState->cardProtocol;
01327 
01328     if (pbAtr)
01329     {  /* want ATR */
01330         if (pcbAtrLen)
01331         { /* & present ATR length */
01332             if (*pcbAtrLen >= rContext->readerState->cardAtrLength)
01333             { /* & enough room */
01334                 *pcbAtrLen = rContext->readerState->cardAtrLength;
01335                 memcpy(pbAtr, rContext->readerState->cardAtr,
01336                     rContext->readerState->cardAtrLength);
01337             }
01338             else
01339             { /* may report only ATR len */
01340                 *pcbAtrLen = rContext->readerState->cardAtrLength;
01341                 rv = SCARD_E_INSUFFICIENT_BUFFER;
01342             }
01343         }
01344         else
01345         { /* present buf & no buflen */
01346             return SCARD_E_INVALID_PARAMETER;
01347         }
01348     }
01349     else
01350     {
01351         if (pcbAtrLen)
01352         { /* want ATR len only */
01353             *pcbAtrLen = rContext->readerState->cardAtrLength;
01354         }
01355         else
01356         {
01357             /* nothing todo */
01358         }
01359     }
01360 
01361     return rv;
01362 }
01363 
01364 LONG SCardGetStatusChange(/*@unused@*/ SCARDCONTEXT hContext,
01365     /*@unused@*/ DWORD dwTimeout,
01366     /*@unused@*/ LPSCARD_READERSTATE_A rgReaderStates,
01367     /*@unused@*/ DWORD cReaders)
01368 {
01369     /*
01370      * Client side function
01371      */
01372     (void)hContext;
01373     (void)dwTimeout;
01374     (void)rgReaderStates;
01375     (void)cReaders;
01376     return SCARD_S_SUCCESS;
01377 }
01378 
01379 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
01380     LPCVOID pbSendBuffer, DWORD cbSendLength,
01381     LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
01382 {
01383     LONG rv;
01384     PREADER_CONTEXT rContext = NULL;
01385 
01386     /* 0 bytes returned by default */
01387     *lpBytesReturned = 0;
01388 
01389     if (0 == hCard)
01390         return SCARD_E_INVALID_HANDLE;
01391 
01392     /*
01393      * Make sure no one has a lock on this reader
01394      */
01395     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01396         return rv;
01397 
01398     rv = RFReaderInfoById(hCard, &rContext);
01399     if (rv != SCARD_S_SUCCESS)
01400         return rv;
01401 
01402     if (IFD_HVERSION_2_0 == rContext->dwVersion)
01403         if (NULL == pbSendBuffer || 0 == cbSendLength)
01404             return SCARD_E_INVALID_PARAMETER;
01405 
01406     /*
01407      * Make sure the reader is working properly
01408      */
01409     rv = RFCheckReaderStatus(rContext);
01410     if (rv != SCARD_S_SUCCESS)
01411         return rv;
01412 
01413     rv = RFFindReaderHandle(hCard);
01414     if (rv != SCARD_S_SUCCESS)
01415         return rv;
01416 
01417     /*
01418      * Make sure some event has not occurred
01419      */
01420     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01421         return rv;
01422 
01423     if (IFD_HVERSION_2_0 == rContext->dwVersion)
01424     {
01425         /* we must wrap a API 3.0 client in an API 2.0 driver */
01426         *lpBytesReturned = cbRecvLength;
01427         return IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
01428             cbSendLength, pbRecvBuffer, lpBytesReturned);
01429     }
01430     else
01431         if (IFD_HVERSION_3_0 == rContext->dwVersion)
01432             return IFDControl(rContext, dwControlCode, pbSendBuffer,
01433                 cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
01434         else
01435             return SCARD_E_UNSUPPORTED_FEATURE;
01436 }
01437 
01438 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
01439     LPBYTE pbAttr, LPDWORD pcbAttrLen)
01440 {
01441     LONG rv;
01442     PREADER_CONTEXT rContext = NULL;
01443 
01444     if (0 == hCard)
01445         return SCARD_E_INVALID_HANDLE;
01446 
01447     /*
01448      * Make sure no one has a lock on this reader
01449      */
01450     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01451         return rv;
01452 
01453     rv = RFReaderInfoById(hCard, &rContext);
01454     if (rv != SCARD_S_SUCCESS)
01455         return rv;
01456 
01457     /*
01458      * Make sure the reader is working properly
01459      */
01460     rv = RFCheckReaderStatus(rContext);
01461     if (rv != SCARD_S_SUCCESS)
01462         return rv;
01463 
01464     rv = RFFindReaderHandle(hCard);
01465     if (rv != SCARD_S_SUCCESS)
01466         return rv;
01467 
01468     /*
01469      * Make sure some event has not occurred
01470      */
01471     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01472         return rv;
01473 
01474     rv = IFDGetCapabilities(rContext, dwAttrId, pcbAttrLen, pbAttr);
01475     if (rv == IFD_SUCCESS)
01476         return SCARD_S_SUCCESS;
01477     else
01478         if (rv == IFD_ERROR_TAG)
01479             return SCARD_E_UNSUPPORTED_FEATURE;
01480         else
01481             return SCARD_E_NOT_TRANSACTED;
01482 }
01483 
01484 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
01485     LPCBYTE pbAttr, DWORD cbAttrLen)
01486 {
01487     LONG rv;
01488     PREADER_CONTEXT rContext = NULL;
01489 
01490     if (0 == hCard)
01491         return SCARD_E_INVALID_HANDLE;
01492 
01493     /*
01494      * Make sure no one has a lock on this reader
01495      */
01496     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01497         return rv;
01498 
01499     rv = RFReaderInfoById(hCard, &rContext);
01500     if (rv != SCARD_S_SUCCESS)
01501         return rv;
01502 
01503     /*
01504      * Make sure the reader is working properly
01505      */
01506     rv = RFCheckReaderStatus(rContext);
01507     if (rv != SCARD_S_SUCCESS)
01508         return rv;
01509 
01510     rv = RFFindReaderHandle(hCard);
01511     if (rv != SCARD_S_SUCCESS)
01512         return rv;
01513 
01514     /*
01515      * Make sure some event has not occurred
01516      */
01517     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01518         return rv;
01519 
01520     rv = IFDSetCapabilities(rContext, dwAttrId, cbAttrLen, (PUCHAR)pbAttr);
01521     if (rv == IFD_SUCCESS)
01522         return SCARD_S_SUCCESS;
01523     else
01524         if (rv == IFD_ERROR_TAG)
01525             return SCARD_E_UNSUPPORTED_FEATURE;
01526         else
01527             return SCARD_E_NOT_TRANSACTED;
01528 }
01529 
01530 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
01531     LPCBYTE pbSendBuffer, DWORD cbSendLength,
01532     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
01533     LPDWORD pcbRecvLength)
01534 {
01535     LONG rv;
01536     PREADER_CONTEXT rContext = NULL;
01537     SCARD_IO_HEADER sSendPci, sRecvPci;
01538     DWORD dwRxLength, tempRxLength;
01539 
01540     if (pcbRecvLength == 0)
01541         return SCARD_E_INVALID_PARAMETER;
01542 
01543     dwRxLength = *pcbRecvLength;
01544     *pcbRecvLength = 0;
01545 
01546     if (hCard == 0)
01547         return SCARD_E_INVALID_HANDLE;
01548 
01549     if (pbSendBuffer == NULL || pbRecvBuffer == NULL || pioSendPci == NULL)
01550         return SCARD_E_INVALID_PARAMETER;
01551 
01552     /*
01553      * Must at least send a 4 bytes APDU
01554      */
01555     if (cbSendLength < 4)
01556         return SCARD_E_INVALID_PARAMETER;
01557 
01558     /*
01559      * Must at least have 2 status words even for SCardControl
01560      */
01561     if (dwRxLength < 2)
01562         return SCARD_E_INSUFFICIENT_BUFFER;
01563 
01564     /*
01565      * Make sure no one has a lock on this reader
01566      */
01567     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01568         return rv;
01569 
01570     rv = RFReaderInfoById(hCard, &rContext);
01571     if (rv != SCARD_S_SUCCESS)
01572         return rv;
01573 
01574     /*
01575      * Make sure the reader is working properly
01576      */
01577     rv = RFCheckReaderStatus(rContext);
01578     if (rv != SCARD_S_SUCCESS)
01579         return rv;
01580 
01581     rv = RFFindReaderHandle(hCard);
01582     if (rv != SCARD_S_SUCCESS)
01583         return rv;
01584 
01585     /*
01586      * Make sure some event has not occurred
01587      */
01588     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01589         return rv;
01590 
01591     /*
01592      * Check for some common errors
01593      */
01594     if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
01595     {
01596         if (rContext->readerState->readerState & SCARD_ABSENT)
01597         {
01598             return SCARD_E_NO_SMARTCARD;
01599         }
01600     }
01601 
01602     if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
01603     {
01604         if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
01605         {
01606             if (pioSendPci->dwProtocol != rContext->readerState->cardProtocol)
01607             {
01608                 return SCARD_E_PROTO_MISMATCH;
01609             }
01610         }
01611     }
01612 
01613     /*
01614      * Quick fix: PC/SC starts at 1 for bit masking but the IFD_Handler
01615      * just wants 0 or 1
01616      */
01617 
01618     sSendPci.Protocol = 0; /* protocol T=0 by default */
01619 
01620     if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
01621     {
01622         sSendPci.Protocol = 1;
01623     } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
01624     {
01625         /*
01626          * This is temporary ......
01627          */
01628         sSendPci.Protocol = SCARD_PROTOCOL_RAW;
01629     } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
01630     {
01631       /* Fix by Amira (Athena) */
01632         unsigned long i;
01633         unsigned long prot = rContext->readerState->cardProtocol;
01634 
01635         for (i = 0 ; prot != 1 ; i++)
01636             prot >>= 1;
01637 
01638         sSendPci.Protocol = i;
01639     }
01640 
01641     sSendPci.Length = pioSendPci->cbPciLength;
01642 
01643     sRecvPci.Protocol = pioRecvPci->dwProtocol;
01644     sRecvPci.Length = pioRecvPci->cbPciLength;
01645 
01646     /* the protocol number is decoded a few lines above */
01647     Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%d", sSendPci.Protocol);
01648 
01649     tempRxLength = dwRxLength;
01650 
01651     if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
01652     {
01653         rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
01654             pbRecvBuffer, &dwRxLength);
01655     } else
01656     {
01657         rv = IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
01658             cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
01659     }
01660 
01661     pioRecvPci->dwProtocol = sRecvPci.Protocol;
01662     pioRecvPci->cbPciLength = sRecvPci.Length;
01663 
01664     /*
01665      * Check for any errors that might have occurred
01666      */
01667 
01668     if (rv != SCARD_S_SUCCESS)
01669     {
01670         *pcbRecvLength = 0;
01671         Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv);
01672         return SCARD_E_NOT_TRANSACTED;
01673     }
01674 
01675     /*
01676      * Available is less than received
01677      */
01678     if (tempRxLength < dwRxLength)
01679     {
01680         *pcbRecvLength = 0;
01681         return SCARD_E_INSUFFICIENT_BUFFER;
01682     }
01683 
01684     /*
01685      * Successful return
01686      */
01687     *pcbRecvLength = dwRxLength;
01688     return SCARD_S_SUCCESS;
01689 }
01690 
01691 LONG SCardListReaders(/*@unused@*/ SCARDCONTEXT hContext,
01692     /*@unused@*/ LPCSTR mszGroups,
01693     /*@unused@*/ LPSTR mszReaders,
01694     /*@unused@*/ LPDWORD pcchReaders)
01695 {
01696     /*
01697      * Client side function
01698      */
01699     (void)hContext;
01700     (void)mszGroups;
01701     (void)mszReaders;
01702     (void)pcchReaders;
01703     return SCARD_S_SUCCESS;
01704 }
01705 
01706 LONG SCardCancel(/*@unused@*/ SCARDCONTEXT hContext)
01707 {
01708     /*
01709      * Client side function
01710      */
01711     (void)hContext;
01712     return SCARD_S_SUCCESS;
01713 }
01714 

Generated on Mon Aug 17 01:00:12 2009 for pcsc-lite by  doxygen 1.5.9