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