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