pcsc-lite 1.5.5

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 4332 2009-07-21 10:21:01Z 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         else
00438             rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00439     }
00440 
00441     *pdwActiveProtocol = rContext->readerState->cardProtocol;
00442 
00443     if (dwShareMode != SCARD_SHARE_DIRECT)
00444     {
00445         if ((*pdwActiveProtocol != SCARD_PROTOCOL_T0)
00446             && (*pdwActiveProtocol != SCARD_PROTOCOL_T1))
00447             Log2(PCSC_LOG_ERROR, "Active Protocol: unknown %d",
00448                 *pdwActiveProtocol);
00449         else
00450             Log2(PCSC_LOG_DEBUG, "Active Protocol: T=%d",
00451                 (*pdwActiveProtocol == SCARD_PROTOCOL_T0) ? 0 : 1);
00452     }
00453     else
00454         Log1(PCSC_LOG_DEBUG, "Direct access: no protocol selected");
00455 
00456     /*
00457      * Prepare the SCARDHANDLE identity
00458      */
00459     *phCard = RFCreateReaderHandle(rContext);
00460 
00461     Log2(PCSC_LOG_DEBUG, "hCard Identity: %x", *phCard);
00462 
00463     /*******************************************
00464      *
00465      * This section tries to set up the
00466      * exclusivity modes. -1 is exclusive
00467      *
00468      *******************************************/
00469 
00470     if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
00471     {
00472         if (rContext->dwContexts == SCARD_NO_CONTEXT)
00473         {
00474             rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
00475             (void)RFLockSharing(*phCard);
00476         }
00477         else
00478         {
00479             (void)RFDestroyReaderHandle(*phCard);
00480             *phCard = 0;
00481             return SCARD_E_SHARING_VIOLATION;
00482         }
00483     }
00484     else
00485     {
00486         /*
00487          * Add a connection to the context stack
00488          */
00489         rContext->dwContexts += 1;
00490     }
00491 
00492     /*
00493      * Add this handle to the handle list
00494      */
00495     rv = RFAddReaderHandle(rContext, *phCard);
00496 
00497     if (rv != SCARD_S_SUCCESS)
00498     {
00499         /*
00500          * Clean up - there is no more room
00501          */
00502         (void)RFDestroyReaderHandle(*phCard);
00503         if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00504             rContext->dwContexts = SCARD_NO_CONTEXT;
00505         else
00506             if (rContext->dwContexts > SCARD_NO_CONTEXT)
00507                 rContext->dwContexts -= 1;
00508 
00509         *phCard = 0;
00510 
00511         PROFILE_END
00512 
00513         return SCARD_F_INTERNAL_ERROR;
00514     }
00515 
00516     /*
00517      * Propagate new state to Shared Memory
00518      */
00519     rContext->readerState->readerSharing = rContext->dwContexts;
00520     (void)StatSynchronize(rContext->readerState);
00521 
00522     PROFILE_END
00523 
00524     return SCARD_S_SUCCESS;
00525 }
00526 
00527 LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
00528     DWORD dwPreferredProtocols, DWORD dwInitialization,
00529     LPDWORD pdwActiveProtocol)
00530 {
00531     LONG rv;
00532     PREADER_CONTEXT rContext = NULL;
00533 
00534     Log1(PCSC_LOG_DEBUG, "Attempting reconnect to token.");
00535 
00536     if (hCard == 0)
00537         return SCARD_E_INVALID_HANDLE;
00538 
00539     /*
00540      * Handle the dwInitialization
00541      */
00542     if (dwInitialization != SCARD_LEAVE_CARD &&
00543             dwInitialization != SCARD_RESET_CARD &&
00544             dwInitialization != SCARD_UNPOWER_CARD)
00545         return SCARD_E_INVALID_VALUE;
00546 
00547     if (dwShareMode != SCARD_SHARE_SHARED &&
00548             dwShareMode != SCARD_SHARE_EXCLUSIVE &&
00549             dwShareMode != SCARD_SHARE_DIRECT)
00550         return SCARD_E_INVALID_VALUE;
00551 
00552     if ((dwShareMode != SCARD_SHARE_DIRECT) &&
00553             !(dwPreferredProtocols & SCARD_PROTOCOL_T0) &&
00554             !(dwPreferredProtocols & SCARD_PROTOCOL_T1) &&
00555             !(dwPreferredProtocols & SCARD_PROTOCOL_RAW) &&
00556             !(dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD))
00557         return SCARD_E_PROTO_MISMATCH;
00558 
00559     if (pdwActiveProtocol == NULL)
00560         return SCARD_E_INVALID_PARAMETER;
00561 
00562     rv = RFReaderInfoById(hCard, &rContext);
00563     if (rv != SCARD_S_SUCCESS)
00564         return rv;
00565 
00566     /*
00567      * Make sure the reader is working properly
00568      */
00569     rv = RFCheckReaderStatus(rContext);
00570     if (rv != SCARD_S_SUCCESS)
00571         return rv;
00572 
00573     rv = RFFindReaderHandle(hCard);
00574     if (rv != SCARD_S_SUCCESS)
00575         return rv;
00576 
00577     /*
00578      * Make sure no one has a lock on this reader
00579      */
00580     rv = RFCheckSharing(hCard);
00581     if (rv != SCARD_S_SUCCESS)
00582         return rv;
00583 
00584     /*
00585      * RFUnblockReader( rContext ); FIX - this doesn't work
00586      */
00587 
00588     if (dwInitialization == SCARD_RESET_CARD ||
00589         dwInitialization == SCARD_UNPOWER_CARD)
00590     {
00591         DWORD dwAtrLen;
00592         /*
00593          * Currently pcsc-lite keeps the card powered constantly
00594          */
00595         dwAtrLen = rContext->readerState->cardAtrLength;
00596         if (SCARD_RESET_CARD == dwInitialization)
00597             rv = IFDPowerICC(rContext, IFD_RESET,
00598                 rContext->readerState->cardAtr,
00599                 &dwAtrLen);
00600         else
00601         {
00602             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
00603                 rContext->readerState->cardAtr,
00604                 &dwAtrLen);
00605             rv = IFDPowerICC(rContext, IFD_POWER_UP,
00606                 rContext->readerState->cardAtr,
00607                 &dwAtrLen);
00608         }
00609         rContext->readerState->cardAtrLength = dwAtrLen;
00610 
00611         /* the protocol is unset after a power on */
00612         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00613 
00614         /*
00615          * Notify the card has been reset
00616          * Not doing this could result in deadlock
00617          */
00618         rv = RFCheckReaderEventState(rContext, hCard);
00619         switch(rv)
00620         {
00621             /* avoid deadlock */
00622             case SCARD_W_RESET_CARD:
00623                 break;
00624 
00625             case SCARD_W_REMOVED_CARD:
00626                 Log1(PCSC_LOG_ERROR, "card removed");
00627                 return SCARD_W_REMOVED_CARD;
00628 
00629             /* invalid EventStatus */
00630             case SCARD_E_INVALID_VALUE:
00631                 Log1(PCSC_LOG_ERROR, "invalid EventStatus");
00632                 return SCARD_F_INTERNAL_ERROR;
00633 
00634             /* invalid hCard, but hCard was widely used some lines above :( */
00635             case SCARD_E_INVALID_HANDLE:
00636                 Log1(PCSC_LOG_ERROR, "invalid handle");
00637                 return SCARD_F_INTERNAL_ERROR;
00638 
00639             case SCARD_S_SUCCESS:
00640                 /*
00641                  * Notify the card has been reset
00642                  */
00643                 (void)RFSetReaderEventState(rContext, SCARD_RESET);
00644 
00645                 /*
00646                  * Set up the status bit masks on dwStatus
00647                  */
00648                 if (rv == SCARD_S_SUCCESS)
00649                 {
00650                     rContext->readerState->readerState |= SCARD_PRESENT;
00651                     rContext->readerState->readerState &= ~SCARD_ABSENT;
00652                     rContext->readerState->readerState |= SCARD_POWERED;
00653                     rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00654                     rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00655                     rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00656                     rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00657                 }
00658                 else
00659                 {
00660                     rContext->readerState->readerState |= SCARD_PRESENT;
00661                     rContext->readerState->readerState &= ~SCARD_ABSENT;
00662                     rContext->readerState->readerState |= SCARD_SWALLOWED;
00663                     rContext->readerState->readerState &= ~SCARD_POWERED;
00664                     rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00665                     rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00666                     rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00667                     rContext->readerState->cardAtrLength = 0;
00668                 }
00669 
00670                 if (rContext->readerState->cardAtrLength > 0)
00671                 {
00672                     Log1(PCSC_LOG_DEBUG, "Reset complete.");
00673                     LogXxd(PCSC_LOG_DEBUG, "Card ATR: ",
00674                         rContext->readerState->cardAtr,
00675                         rContext->readerState->cardAtrLength);
00676                 }
00677                 else
00678                 {
00679                     DWORD dwStatus, dwAtrLen2;
00680                     UCHAR ucAtr[MAX_ATR_SIZE];
00681 
00682                     Log1(PCSC_LOG_ERROR, "Error resetting card.");
00683                     (void)IFDStatusICC(rContext, &dwStatus, ucAtr, &dwAtrLen2);
00684                     if (dwStatus & SCARD_PRESENT)
00685                         return SCARD_W_UNRESPONSIVE_CARD;
00686                     else
00687                         return SCARD_E_NO_SMARTCARD;
00688                 }
00689                 break;
00690 
00691             default:
00692                 Log2(PCSC_LOG_ERROR,
00693                     "invalid retcode from RFCheckReaderEventState (%X)", rv);
00694                 return SCARD_F_INTERNAL_ERROR;
00695                 break;
00696         }
00697     }
00698     else
00699         if (dwInitialization == SCARD_LEAVE_CARD)
00700         {
00701             /*
00702              * Do nothing
00703              */
00704         }
00705 
00706     /*******************************************
00707      *
00708      * This section tries to decode the ATR
00709      * and set up which protocol to use
00710      *
00711      *******************************************/
00712     if (dwPreferredProtocols & SCARD_PROTOCOL_RAW)
00713         rContext->readerState->cardProtocol = SCARD_PROTOCOL_RAW;
00714     else
00715     {
00716         if (dwShareMode != SCARD_SHARE_DIRECT)
00717         {
00718             /* lock here instead in IFDSetPTS() to lock up to
00719              * setting rContext->readerState->cardProtocol */
00720             (void)SYS_MutexLock(rContext->mMutex);
00721 
00722             /* the protocol is not yet set (no PPS yet) */
00723             if (SCARD_PROTOCOL_UNDEFINED == rContext->readerState->cardProtocol)
00724             {
00725                 UCHAR ucAvailable, ucDefault;
00726                 int ret;
00727 
00728                 ucDefault = PHGetDefaultProtocol(rContext->readerState->cardAtr,
00729                     rContext->readerState->cardAtrLength);
00730                 ucAvailable =
00731                     PHGetAvailableProtocols(rContext->readerState->cardAtr,
00732                             rContext->readerState->cardAtrLength);
00733 
00734                 /* If it is set to ANY let it do any of the protocols */
00735                 if (dwPreferredProtocols & SCARD_PROTOCOL_ANY_OLD)
00736                     dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
00737 
00738                 ret = PHSetProtocol(rContext, dwPreferredProtocols,
00739                     ucAvailable, ucDefault);
00740 
00741                 /* keep cardProtocol = SCARD_PROTOCOL_UNDEFINED in case of error  */
00742                 if (SET_PROTOCOL_PPS_FAILED == ret)
00743                 {
00744                     (void)SYS_MutexUnLock(rContext->mMutex);
00745                     return SCARD_W_UNRESPONSIVE_CARD;
00746                 }
00747 
00748                 if (SET_PROTOCOL_WRONG_ARGUMENT == ret)
00749                 {
00750                     (void)SYS_MutexUnLock(rContext->mMutex);
00751                     return SCARD_E_PROTO_MISMATCH;
00752                 }
00753 
00754                 /* use negociated protocol */
00755                 rContext->readerState->cardProtocol = ret;
00756 
00757                 (void)SYS_MutexUnLock(rContext->mMutex);
00758             }
00759             else
00760             {
00761                 (void)SYS_MutexUnLock(rContext->mMutex);
00762 
00763                 if (! (dwPreferredProtocols & rContext->readerState->cardProtocol))
00764                     return SCARD_E_PROTO_MISMATCH;
00765             }
00766         }
00767         else
00768             rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00769     }
00770 
00771     *pdwActiveProtocol = rContext->readerState->cardProtocol;
00772 
00773     if (dwShareMode == SCARD_SHARE_EXCLUSIVE)
00774     {
00775         if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
00776         {
00777             /*
00778              * Do nothing - we are already exclusive
00779              */
00780         } else
00781         {
00782             if (rContext->dwContexts == SCARD_LAST_CONTEXT)
00783             {
00784                 rContext->dwContexts = SCARD_EXCLUSIVE_CONTEXT;
00785                 (void)RFLockSharing(hCard);
00786             } else
00787             {
00788                 return SCARD_E_SHARING_VIOLATION;
00789             }
00790         }
00791     } else if (dwShareMode == SCARD_SHARE_SHARED)
00792     {
00793         if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
00794         {
00795             /*
00796              * Do nothing - in sharing mode already
00797              */
00798         } else
00799         {
00800             /*
00801              * We are in exclusive mode but want to share now
00802              */
00803             (void)RFUnlockSharing(hCard);
00804             rContext->dwContexts = SCARD_LAST_CONTEXT;
00805         }
00806     } else if (dwShareMode == SCARD_SHARE_DIRECT)
00807     {
00808         if (rContext->dwContexts != SCARD_EXCLUSIVE_CONTEXT)
00809         {
00810             /*
00811              * Do nothing - in sharing mode already
00812              */
00813         } else
00814         {
00815             /*
00816              * We are in exclusive mode but want to share now
00817              */
00818             (void)RFUnlockSharing(hCard);
00819             rContext->dwContexts = SCARD_LAST_CONTEXT;
00820         }
00821     } else
00822         return SCARD_E_INVALID_VALUE;
00823 
00824     /*
00825      * Clear a previous event to the application
00826      */
00827     (void)RFClearReaderEventState(rContext, hCard);
00828 
00829     /*
00830      * Propagate new state to Shared Memory
00831      */
00832     rContext->readerState->readerSharing = rContext->dwContexts;
00833     (void)StatSynchronize(rContext->readerState);
00834 
00835     return SCARD_S_SUCCESS;
00836 }
00837 
00838 LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
00839 {
00840     LONG rv;
00841     PREADER_CONTEXT rContext = NULL;
00842     DWORD dwAtrLen;
00843 
00844     if (hCard == 0)
00845         return SCARD_E_INVALID_HANDLE;
00846 
00847     rv = RFReaderInfoById(hCard, &rContext);
00848     if (rv != SCARD_S_SUCCESS)
00849         return rv;
00850 
00851     rv = RFFindReaderHandle(hCard);
00852     if (rv != SCARD_S_SUCCESS)
00853         return rv;
00854 
00855     if ((dwDisposition != SCARD_LEAVE_CARD)
00856         && (dwDisposition != SCARD_UNPOWER_CARD)
00857         && (dwDisposition != SCARD_RESET_CARD)
00858         && (dwDisposition != SCARD_EJECT_CARD))
00859         return SCARD_E_INVALID_VALUE;
00860 
00861     /*
00862      * wait until a possible transaction is finished
00863      */
00864     if ((dwDisposition != SCARD_LEAVE_CARD) && (rContext->dwLockId != 0)
00865         && (rContext->dwLockId != hCard))
00866     {
00867         Log1(PCSC_LOG_INFO, "Waiting for release of lock");
00868         while (rContext->dwLockId != 0)
00869             (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
00870         Log1(PCSC_LOG_INFO, "Lock released");
00871     }
00872 
00873     /* the reader has been removed while we were waiting */
00874     if (NULL == rContext->readerState)
00875         return SCARD_E_NO_SMARTCARD;
00876 
00877     /*
00878      * Unlock any blocks on this context
00879      */
00880     rv = RFUnlockAllSharing(hCard);
00881     if (rv != SCARD_S_SUCCESS)
00882         return rv;
00883 
00884     Log2(PCSC_LOG_DEBUG, "Active Contexts: %d", rContext->dwContexts);
00885 
00886     if (dwDisposition == SCARD_RESET_CARD ||
00887         dwDisposition == SCARD_UNPOWER_CARD)
00888     {
00889         /*
00890          * Currently pcsc-lite keeps the card powered constantly
00891          */
00892         dwAtrLen = rContext->readerState->cardAtrLength;
00893         if (SCARD_RESET_CARD == dwDisposition)
00894             rv = IFDPowerICC(rContext, IFD_RESET,
00895                 rContext->readerState->cardAtr,
00896                 &dwAtrLen);
00897         else
00898         {
00899             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
00900                 rContext->readerState->cardAtr,
00901                 &dwAtrLen);
00902             rv = IFDPowerICC(rContext, IFD_POWER_UP,
00903                 rContext->readerState->cardAtr,
00904                 &dwAtrLen);
00905         }
00906         rContext->readerState->cardAtrLength = dwAtrLen;
00907 
00908         /* the protocol is unset after a power on */
00909         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
00910 
00911         /*
00912          * Notify the card has been reset
00913          */
00914         (void)RFSetReaderEventState(rContext, SCARD_RESET);
00915 
00916         /*
00917          * Set up the status bit masks on dwStatus
00918          */
00919         if (rv == SCARD_S_SUCCESS)
00920         {
00921             rContext->readerState->readerState |= SCARD_PRESENT;
00922             rContext->readerState->readerState &= ~SCARD_ABSENT;
00923             rContext->readerState->readerState |= SCARD_POWERED;
00924             rContext->readerState->readerState |= SCARD_NEGOTIABLE;
00925             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00926             rContext->readerState->readerState &= ~SCARD_SWALLOWED;
00927             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00928         }
00929         else
00930         {
00931             if (rContext->readerState->readerState & SCARD_ABSENT)
00932                 rContext->readerState->readerState &= ~SCARD_PRESENT;
00933             else
00934                 rContext->readerState->readerState |= SCARD_PRESENT;
00935             /* SCARD_ABSENT flag is already set */
00936             rContext->readerState->readerState |= SCARD_SWALLOWED;
00937             rContext->readerState->readerState &= ~SCARD_POWERED;
00938             rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
00939             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
00940             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
00941             rContext->readerState->cardAtrLength = 0;
00942         }
00943 
00944         if (rContext->readerState->cardAtrLength > 0)
00945             Log1(PCSC_LOG_DEBUG, "Reset complete.");
00946         else
00947             Log1(PCSC_LOG_ERROR, "Error resetting card.");
00948     }
00949     else if (dwDisposition == SCARD_EJECT_CARD)
00950     {
00951         UCHAR controlBuffer[5];
00952         UCHAR receiveBuffer[MAX_BUFFER_SIZE];
00953         DWORD receiveLength;
00954 
00955         /*
00956          * Set up the CTBCS command for Eject ICC
00957          */
00958         controlBuffer[0] = 0x20;
00959         controlBuffer[1] = 0x15;
00960         controlBuffer[2] = (rContext->dwSlot & 0x0000FFFF) + 1;
00961         controlBuffer[3] = 0x00;
00962         controlBuffer[4] = 0x00;
00963         receiveLength = 2;
00964         rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
00965             &receiveLength);
00966 
00967         if (rv == SCARD_S_SUCCESS)
00968         {
00969             if (receiveLength == 2 && receiveBuffer[0] == 0x90)
00970             {
00971                 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
00972                 /*
00973                  * Successful
00974                  */
00975             }
00976             else
00977                 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
00978         }
00979         else
00980             Log1(PCSC_LOG_ERROR, "Error ejecting card.");
00981 
00982     }
00983     else if (dwDisposition == SCARD_LEAVE_CARD)
00984     {
00985         /*
00986          * Do nothing
00987          */
00988     }
00989 
00990     /*
00991      * Remove and destroy this handle
00992      */
00993     (void)RFRemoveReaderHandle(rContext, hCard);
00994     (void)RFDestroyReaderHandle(hCard);
00995 
00996     /*
00997      * For exclusive connection reset it to no connections
00998      */
00999     if (rContext->dwContexts == SCARD_EXCLUSIVE_CONTEXT)
01000         rContext->dwContexts = SCARD_NO_CONTEXT;
01001     else
01002     {
01003         /*
01004          * Remove a connection from the context stack
01005          */
01006         rContext->dwContexts -= 1;
01007 
01008         if (rContext->dwContexts < 0)
01009             rContext->dwContexts = 0;
01010     }
01011 
01012     /*
01013      * Propagate new state to Shared Memory
01014      */
01015     rContext->readerState->readerSharing = rContext->dwContexts;
01016     (void)StatSynchronize(rContext->readerState);
01017 
01018     return SCARD_S_SUCCESS;
01019 }
01020 
01021 LONG SCardBeginTransaction(SCARDHANDLE hCard)
01022 {
01023     LONG rv;
01024     PREADER_CONTEXT rContext;
01025 
01026     if (hCard == 0)
01027         return SCARD_E_INVALID_HANDLE;
01028 
01029     rv = RFReaderInfoById(hCard, &rContext);
01030 
01031     /*
01032      * Cannot find the hCard in this context
01033      */
01034     if (rv != SCARD_S_SUCCESS)
01035         return rv;
01036 
01037     /*
01038      * Make sure the reader is working properly
01039      */
01040     rv = RFCheckReaderStatus(rContext);
01041     if (rv != SCARD_S_SUCCESS)
01042         return rv;
01043 
01044     rv = RFFindReaderHandle(hCard);
01045     if (rv != SCARD_S_SUCCESS)
01046         return rv;
01047 
01048     /*
01049      * Make sure some event has not occurred
01050      */
01051     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01052         return rv;
01053 
01054     rv = RFLockSharing(hCard);
01055 
01056     /* if the transaction is not yet ready we sleep a bit so the client
01057      * do not retry immediately */
01058     if (SCARD_E_SHARING_VIOLATION == rv)
01059         (void)SYS_USleep(PCSCLITE_LOCK_POLL_RATE);
01060 
01061     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01062 
01063     return rv;
01064 }
01065 
01066 LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
01067 {
01068     LONG rv;
01069     PREADER_CONTEXT rContext = NULL;
01070     DWORD dwAtrLen;
01071 
01072     /*
01073      * Ignoring dwDisposition for now
01074      */
01075     if (hCard == 0)
01076         return SCARD_E_INVALID_HANDLE;
01077 
01078     if ((dwDisposition != SCARD_LEAVE_CARD)
01079         && (dwDisposition != SCARD_UNPOWER_CARD)
01080         && (dwDisposition != SCARD_RESET_CARD)
01081         && (dwDisposition != SCARD_EJECT_CARD))
01082     return SCARD_E_INVALID_VALUE;
01083 
01084     rv = RFReaderInfoById(hCard, &rContext);
01085 
01086     /*
01087      * Cannot find the hCard in this context
01088      */
01089     if (rv != SCARD_S_SUCCESS)
01090         return rv;
01091 
01092     rv = RFFindReaderHandle(hCard);
01093     if (rv != SCARD_S_SUCCESS)
01094         return rv;
01095 
01096     /*
01097      * Make sure some event has not occurred
01098      */
01099     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01100         return rv;
01101 
01102     if (dwDisposition == SCARD_RESET_CARD ||
01103         dwDisposition == SCARD_UNPOWER_CARD)
01104     {
01105         /*
01106          * Currently pcsc-lite keeps the card always powered
01107          */
01108         dwAtrLen = rContext->readerState->cardAtrLength;
01109         if (SCARD_RESET_CARD == dwDisposition)
01110             rv = IFDPowerICC(rContext, IFD_RESET,
01111                 rContext->readerState->cardAtr,
01112                 &dwAtrLen);
01113         else
01114         {
01115             rv = IFDPowerICC(rContext, IFD_POWER_DOWN,
01116                 rContext->readerState->cardAtr,
01117                 &dwAtrLen);
01118             rv = IFDPowerICC(rContext, IFD_POWER_UP,
01119                 rContext->readerState->cardAtr,
01120                 &dwAtrLen);
01121         }
01122         rContext->readerState->cardAtrLength = dwAtrLen;
01123 
01124         /* the protocol is unset after a power on */
01125         rContext->readerState->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
01126 
01127         /*
01128          * Notify the card has been reset
01129          */
01130         (void)RFSetReaderEventState(rContext, SCARD_RESET);
01131 
01132         /*
01133          * Set up the status bit masks on dwStatus
01134          */
01135         if (rv == SCARD_S_SUCCESS)
01136         {
01137             rContext->readerState->readerState |= SCARD_PRESENT;
01138             rContext->readerState->readerState &= ~SCARD_ABSENT;
01139             rContext->readerState->readerState |= SCARD_POWERED;
01140             rContext->readerState->readerState |= SCARD_NEGOTIABLE;
01141             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
01142             rContext->readerState->readerState &= ~SCARD_SWALLOWED;
01143             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
01144         }
01145         else
01146         {
01147             if (rContext->readerState->readerState & SCARD_ABSENT)
01148                 rContext->readerState->readerState &= ~SCARD_PRESENT;
01149             else
01150                 rContext->readerState->readerState |= SCARD_PRESENT;
01151             /* SCARD_ABSENT flag is already set */
01152             rContext->readerState->readerState |= SCARD_SWALLOWED;
01153             rContext->readerState->readerState &= ~SCARD_POWERED;
01154             rContext->readerState->readerState &= ~SCARD_NEGOTIABLE;
01155             rContext->readerState->readerState &= ~SCARD_SPECIFIC;
01156             rContext->readerState->readerState &= ~SCARD_UNKNOWN;
01157             rContext->readerState->cardAtrLength = 0;
01158         }
01159 
01160         if (rContext->readerState->cardAtrLength > 0)
01161             Log1(PCSC_LOG_DEBUG, "Reset complete.");
01162         else
01163             Log1(PCSC_LOG_ERROR, "Error resetting card.");
01164 
01165     }
01166     else if (dwDisposition == SCARD_EJECT_CARD)
01167     {
01168         UCHAR controlBuffer[5];
01169         UCHAR receiveBuffer[MAX_BUFFER_SIZE];
01170         DWORD receiveLength;
01171 
01172         /*
01173          * Set up the CTBCS command for Eject ICC
01174          */
01175         controlBuffer[0] = 0x20;
01176         controlBuffer[1] = 0x15;
01177         controlBuffer[2] = (rContext->dwSlot & 0x0000FFFF) + 1;
01178         controlBuffer[3] = 0x00;
01179         controlBuffer[4] = 0x00;
01180         receiveLength = 2;
01181         rv = IFDControl_v2(rContext, controlBuffer, 5, receiveBuffer,
01182             &receiveLength);
01183 
01184         if (rv == SCARD_S_SUCCESS)
01185         {
01186             if (receiveLength == 2 && receiveBuffer[0] == 0x90)
01187             {
01188                 Log1(PCSC_LOG_DEBUG, "Card ejected successfully.");
01189                 /*
01190                  * Successful
01191                  */
01192             }
01193             else
01194                 Log1(PCSC_LOG_ERROR, "Error ejecting card.");
01195         }
01196         else
01197             Log1(PCSC_LOG_ERROR, "Error ejecting card.");
01198 
01199     }
01200     else if (dwDisposition == SCARD_LEAVE_CARD)
01201     {
01202         /*
01203          * Do nothing
01204          */
01205     }
01206 
01207     /*
01208      * Unlock any blocks on this context
01209      */
01210     (void)RFUnlockSharing(hCard);
01211 
01212     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01213 
01214     return rv;
01215 }
01216 
01217 LONG SCardCancelTransaction(SCARDHANDLE hCard)
01218 {
01219     LONG rv;
01220     PREADER_CONTEXT rContext = NULL;
01221 
01222     /*
01223      * Ignoring dwDisposition for now
01224      */
01225     if (hCard == 0)
01226         return SCARD_E_INVALID_HANDLE;
01227 
01228     rv = RFReaderInfoById(hCard, &rContext);
01229 
01230     /*
01231      * Cannot find the hCard in this context
01232      */
01233     if (rv != SCARD_S_SUCCESS)
01234         return rv;
01235 
01236     rv = RFFindReaderHandle(hCard);
01237     if (rv != SCARD_S_SUCCESS)
01238         return rv;
01239 
01240     /*
01241      * Make sure some event has not occurred
01242      */
01243     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01244         return rv;
01245 
01246     rv = RFUnlockSharing(hCard);
01247 
01248     Log2(PCSC_LOG_DEBUG, "Status: 0x%08X", rv);
01249 
01250     return rv;
01251 }
01252 
01253 LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderNames,
01254     LPDWORD pcchReaderLen, LPDWORD pdwState,
01255     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen)
01256 {
01257     LONG rv;
01258     PREADER_CONTEXT rContext = NULL;
01259 
01260     if (hCard == 0)
01261         return SCARD_E_INVALID_HANDLE;
01262 
01263     rv = RFReaderInfoById(hCard, &rContext);
01264 
01265     /*
01266      * Cannot find the hCard in this context
01267      */
01268     if (rv != SCARD_S_SUCCESS)
01269         return rv;
01270 
01271     if (strlen(rContext->lpcReader) > MAX_BUFFER_SIZE
01272             || rContext->readerState->cardAtrLength > MAX_ATR_SIZE)
01273         return SCARD_F_INTERNAL_ERROR;
01274 
01275     /*
01276      * This is a client side function however the server maintains the
01277      * list of events between applications so it must be passed through to
01278      * obtain this event if it has occurred
01279      */
01280 
01281     /*
01282      * Make sure some event has not occurred
01283      */
01284     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01285         return rv;
01286 
01287     /*
01288      * Make sure the reader is working properly
01289      */
01290     rv = RFCheckReaderStatus(rContext);
01291     if (rv != SCARD_S_SUCCESS)
01292         return rv;
01293 
01294     if (mszReaderNames)
01295     {  /* want reader name */
01296         if (pcchReaderLen)
01297         { /* & present reader name length */
01298             if (*pcchReaderLen >= strlen(rContext->lpcReader))
01299             { /* & enough room */
01300                 *pcchReaderLen = strlen(rContext->lpcReader);
01301                 strncpy(mszReaderNames, rContext->lpcReader, MAX_READERNAME);
01302             }
01303             else
01304             {        /* may report only reader name len */
01305                 *pcchReaderLen = strlen(rContext->lpcReader);
01306                 rv = SCARD_E_INSUFFICIENT_BUFFER;
01307             }
01308         }
01309         else
01310         {            /* present buf & no buflen */
01311             return SCARD_E_INVALID_PARAMETER;
01312         }
01313     }
01314     else
01315     {
01316         if (pcchReaderLen)
01317         { /* want reader len only */
01318             *pcchReaderLen = strlen(rContext->lpcReader);
01319         }
01320         else
01321         {
01322         /* nothing todo */
01323         }
01324     }
01325 
01326     if (pdwState)
01327         *pdwState = rContext->readerState->readerState;
01328 
01329     if (pdwProtocol)
01330         *pdwProtocol = rContext->readerState->cardProtocol;
01331 
01332     if (pbAtr)
01333     {  /* want ATR */
01334         if (pcbAtrLen)
01335         { /* & present ATR length */
01336             if (*pcbAtrLen >= rContext->readerState->cardAtrLength)
01337             { /* & enough room */
01338                 *pcbAtrLen = rContext->readerState->cardAtrLength;
01339                 memcpy(pbAtr, rContext->readerState->cardAtr,
01340                     rContext->readerState->cardAtrLength);
01341             }
01342             else
01343             { /* may report only ATR len */
01344                 *pcbAtrLen = rContext->readerState->cardAtrLength;
01345                 rv = SCARD_E_INSUFFICIENT_BUFFER;
01346             }
01347         }
01348         else
01349         { /* present buf & no buflen */
01350             return SCARD_E_INVALID_PARAMETER;
01351         }
01352     }
01353     else
01354     {
01355         if (pcbAtrLen)
01356         { /* want ATR len only */
01357             *pcbAtrLen = rContext->readerState->cardAtrLength;
01358         }
01359         else
01360         {
01361             /* nothing todo */
01362         }
01363     }
01364 
01365     return rv;
01366 }
01367 
01368 LONG SCardGetStatusChange(/*@unused@*/ SCARDCONTEXT hContext,
01369     /*@unused@*/ DWORD dwTimeout,
01370     /*@unused@*/ LPSCARD_READERSTATE_A rgReaderStates,
01371     /*@unused@*/ DWORD cReaders)
01372 {
01373     /*
01374      * Client side function
01375      */
01376     (void)hContext;
01377     (void)dwTimeout;
01378     (void)rgReaderStates;
01379     (void)cReaders;
01380     return SCARD_S_SUCCESS;
01381 }
01382 
01383 LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
01384     LPCVOID pbSendBuffer, DWORD cbSendLength,
01385     LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned)
01386 {
01387     LONG rv;
01388     PREADER_CONTEXT rContext = NULL;
01389 
01390     /* 0 bytes returned by default */
01391     *lpBytesReturned = 0;
01392 
01393     if (0 == hCard)
01394         return SCARD_E_INVALID_HANDLE;
01395 
01396     /*
01397      * Make sure no one has a lock on this reader
01398      */
01399     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01400         return rv;
01401 
01402     rv = RFReaderInfoById(hCard, &rContext);
01403     if (rv != SCARD_S_SUCCESS)
01404         return rv;
01405 
01406     if (IFD_HVERSION_2_0 == rContext->dwVersion)
01407         if (NULL == pbSendBuffer || 0 == cbSendLength)
01408             return SCARD_E_INVALID_PARAMETER;
01409 
01410     /*
01411      * Make sure the reader is working properly
01412      */
01413     rv = RFCheckReaderStatus(rContext);
01414     if (rv != SCARD_S_SUCCESS)
01415         return rv;
01416 
01417     rv = RFFindReaderHandle(hCard);
01418     if (rv != SCARD_S_SUCCESS)
01419         return rv;
01420 
01421     /*
01422      * Make sure some event has not occurred
01423      */
01424     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01425         return rv;
01426 
01427     if (IFD_HVERSION_2_0 == rContext->dwVersion)
01428     {
01429         /* we must wrap a API 3.0 client in an API 2.0 driver */
01430         *lpBytesReturned = cbRecvLength;
01431         return IFDControl_v2(rContext, (PUCHAR)pbSendBuffer,
01432             cbSendLength, pbRecvBuffer, lpBytesReturned);
01433     }
01434     else
01435         if (IFD_HVERSION_3_0 == rContext->dwVersion)
01436             return IFDControl(rContext, dwControlCode, pbSendBuffer,
01437                 cbSendLength, pbRecvBuffer, cbRecvLength, lpBytesReturned);
01438         else
01439             return SCARD_E_UNSUPPORTED_FEATURE;
01440 }
01441 
01442 LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
01443     LPBYTE pbAttr, LPDWORD pcbAttrLen)
01444 {
01445     LONG rv;
01446     PREADER_CONTEXT rContext = NULL;
01447 
01448     if (0 == hCard)
01449         return SCARD_E_INVALID_HANDLE;
01450 
01451     /*
01452      * Make sure no one has a lock on this reader
01453      */
01454     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01455         return rv;
01456 
01457     rv = RFReaderInfoById(hCard, &rContext);
01458     if (rv != SCARD_S_SUCCESS)
01459         return rv;
01460 
01461     /*
01462      * Make sure the reader is working properly
01463      */
01464     rv = RFCheckReaderStatus(rContext);
01465     if (rv != SCARD_S_SUCCESS)
01466         return rv;
01467 
01468     rv = RFFindReaderHandle(hCard);
01469     if (rv != SCARD_S_SUCCESS)
01470         return rv;
01471 
01472     /*
01473      * Make sure some event has not occurred
01474      */
01475     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01476         return rv;
01477 
01478     rv = IFDGetCapabilities(rContext, dwAttrId, pcbAttrLen, pbAttr);
01479     if (rv == IFD_SUCCESS)
01480         return SCARD_S_SUCCESS;
01481     else
01482         if (rv == IFD_ERROR_TAG)
01483             return SCARD_E_UNSUPPORTED_FEATURE;
01484         else
01485             return SCARD_E_NOT_TRANSACTED;
01486 }
01487 
01488 LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
01489     LPCBYTE pbAttr, DWORD cbAttrLen)
01490 {
01491     LONG rv;
01492     PREADER_CONTEXT rContext = NULL;
01493 
01494     if (0 == hCard)
01495         return SCARD_E_INVALID_HANDLE;
01496 
01497     /*
01498      * Make sure no one has a lock on this reader
01499      */
01500     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01501         return rv;
01502 
01503     rv = RFReaderInfoById(hCard, &rContext);
01504     if (rv != SCARD_S_SUCCESS)
01505         return rv;
01506 
01507     /*
01508      * Make sure the reader is working properly
01509      */
01510     rv = RFCheckReaderStatus(rContext);
01511     if (rv != SCARD_S_SUCCESS)
01512         return rv;
01513 
01514     rv = RFFindReaderHandle(hCard);
01515     if (rv != SCARD_S_SUCCESS)
01516         return rv;
01517 
01518     /*
01519      * Make sure some event has not occurred
01520      */
01521     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01522         return rv;
01523 
01524     rv = IFDSetCapabilities(rContext, dwAttrId, cbAttrLen, (PUCHAR)pbAttr);
01525     if (rv == IFD_SUCCESS)
01526         return SCARD_S_SUCCESS;
01527     else
01528         if (rv == IFD_ERROR_TAG)
01529             return SCARD_E_UNSUPPORTED_FEATURE;
01530         else
01531             return SCARD_E_NOT_TRANSACTED;
01532 }
01533 
01534 LONG SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
01535     LPCBYTE pbSendBuffer, DWORD cbSendLength,
01536     LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
01537     LPDWORD pcbRecvLength)
01538 {
01539     LONG rv;
01540     PREADER_CONTEXT rContext = NULL;
01541     SCARD_IO_HEADER sSendPci, sRecvPci;
01542     DWORD dwRxLength, tempRxLength;
01543 
01544     if (pcbRecvLength == 0)
01545         return SCARD_E_INVALID_PARAMETER;
01546 
01547     dwRxLength = *pcbRecvLength;
01548     *pcbRecvLength = 0;
01549 
01550     if (hCard == 0)
01551         return SCARD_E_INVALID_HANDLE;
01552 
01553     if (pbSendBuffer == NULL || pbRecvBuffer == NULL || pioSendPci == NULL)
01554         return SCARD_E_INVALID_PARAMETER;
01555 
01556     /*
01557      * Must at least send a 4 bytes APDU
01558      */
01559     if (cbSendLength < 4)
01560         return SCARD_E_INVALID_PARAMETER;
01561 
01562     /*
01563      * Must at least have 2 status words even for SCardControl
01564      */
01565     if (dwRxLength < 2)
01566         return SCARD_E_INSUFFICIENT_BUFFER;
01567 
01568     /*
01569      * Make sure no one has a lock on this reader
01570      */
01571     if ((rv = RFCheckSharing(hCard)) != SCARD_S_SUCCESS)
01572         return rv;
01573 
01574     rv = RFReaderInfoById(hCard, &rContext);
01575     if (rv != SCARD_S_SUCCESS)
01576         return rv;
01577 
01578     /*
01579      * Make sure the reader is working properly
01580      */
01581     rv = RFCheckReaderStatus(rContext);
01582     if (rv != SCARD_S_SUCCESS)
01583         return rv;
01584 
01585     rv = RFFindReaderHandle(hCard);
01586     if (rv != SCARD_S_SUCCESS)
01587         return rv;
01588 
01589     /*
01590      * Make sure some event has not occurred
01591      */
01592     if ((rv = RFCheckReaderEventState(rContext, hCard)) != SCARD_S_SUCCESS)
01593         return rv;
01594 
01595     /*
01596      * Check for some common errors
01597      */
01598     if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
01599     {
01600         if (rContext->readerState->readerState & SCARD_ABSENT)
01601         {
01602             return SCARD_E_NO_SMARTCARD;
01603         }
01604     }
01605 
01606     if (pioSendPci->dwProtocol != SCARD_PROTOCOL_RAW)
01607     {
01608         if (pioSendPci->dwProtocol != SCARD_PROTOCOL_ANY_OLD)
01609         {
01610             if (pioSendPci->dwProtocol != rContext->readerState->cardProtocol)
01611             {
01612                 return SCARD_E_PROTO_MISMATCH;
01613             }
01614         }
01615     }
01616 
01617     /*
01618      * Quick fix: PC/SC starts at 1 for bit masking but the IFD_Handler
01619      * just wants 0 or 1
01620      */
01621 
01622     sSendPci.Protocol = 0; /* protocol T=0 by default */
01623 
01624     if (pioSendPci->dwProtocol == SCARD_PROTOCOL_T1)
01625     {
01626         sSendPci.Protocol = 1;
01627     } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
01628     {
01629         /*
01630          * This is temporary ......
01631          */
01632         sSendPci.Protocol = SCARD_PROTOCOL_RAW;
01633     } else if (pioSendPci->dwProtocol == SCARD_PROTOCOL_ANY_OLD)
01634     {
01635       /* Fix by Amira (Athena) */
01636         unsigned long i;
01637         unsigned long prot = rContext->readerState->cardProtocol;
01638 
01639         for (i = 0 ; prot != 1 ; i++)
01640             prot >>= 1;
01641 
01642         sSendPci.Protocol = i;
01643     }
01644 
01645     sSendPci.Length = pioSendPci->cbPciLength;
01646 
01647     sRecvPci.Protocol = pioRecvPci->dwProtocol;
01648     sRecvPci.Length = pioRecvPci->cbPciLength;
01649 
01650     /* the protocol number is decoded a few lines above */
01651     Log2(PCSC_LOG_DEBUG, "Send Protocol: T=%d", sSendPci.Protocol);
01652 
01653     tempRxLength = dwRxLength;
01654 
01655     if (pioSendPci->dwProtocol == SCARD_PROTOCOL_RAW)
01656     {
01657         rv = IFDControl_v2(rContext, (PUCHAR) pbSendBuffer, cbSendLength,
01658             pbRecvBuffer, &dwRxLength);
01659     } else
01660     {
01661         rv = IFDTransmit(rContext, sSendPci, (PUCHAR) pbSendBuffer,
01662             cbSendLength, pbRecvBuffer, &dwRxLength, &sRecvPci);
01663     }
01664 
01665     pioRecvPci->dwProtocol = sRecvPci.Protocol;
01666     pioRecvPci->cbPciLength = sRecvPci.Length;
01667 
01668     /*
01669      * Check for any errors that might have occurred
01670      */
01671 
01672     if (rv != SCARD_S_SUCCESS)
01673     {
01674         *pcbRecvLength = 0;
01675         Log2(PCSC_LOG_ERROR, "Card not transacted: 0x%08lX", rv);
01676         return rv;
01677     }
01678 
01679     /*
01680      * Available is less than received
01681      */
01682     if (tempRxLength < dwRxLength)
01683     {
01684         *pcbRecvLength = 0;
01685         return SCARD_E_INSUFFICIENT_BUFFER;
01686     }
01687 
01688     /*
01689      * Successful return
01690      */
01691     *pcbRecvLength = dwRxLength;
01692     return SCARD_S_SUCCESS;
01693 }
01694 
01695 LONG SCardListReaders(/*@unused@*/ SCARDCONTEXT hContext,
01696     /*@unused@*/ LPCSTR mszGroups,
01697     /*@unused@*/ LPSTR mszReaders,
01698     /*@unused@*/ LPDWORD pcchReaders)
01699 {
01700     /*
01701      * Client side function
01702      */
01703     (void)hContext;
01704     (void)mszGroups;
01705     (void)mszReaders;
01706     (void)pcchReaders;
01707     return SCARD_S_SUCCESS;
01708 }
01709 
01710 LONG SCardCancel(/*@unused@*/ SCARDCONTEXT hContext)
01711 {
01712     /*
01713      * Client side function
01714      */
01715     (void)hContext;
01716     return SCARD_S_SUCCESS;
01717 }
01718