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