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

Generated on Thu Aug 28 20:14:32 2008 for pcsc-lite by  doxygen 1.5.6