ifdwrapper.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) 2003-2004
00007  *  Damien Sauveron <damien.sauveron@labri.fr>
00008  * Copyright (C) 2002-2009
00009  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00010  *
00011  * $Id: ifdwrapper.c 4885 2010-04-18 12:17:56Z rousseau $
00012  */
00013 
00019 #include <errno.h>
00020 #include <unistd.h>
00021 #include <pthread.h>
00022 
00023 #include "config.h"
00024 #include "misc.h"
00025 #include "pcscd.h"
00026 #include "ifdhandler.h"
00027 #include "debuglog.h"
00028 #include "readerfactory.h"
00029 #include "ifdwrapper.h"
00030 #include "atrhandler.h"
00031 #include "dyn_generic.h"
00032 #include "sys_generic.h"
00033 #include "utils.h"
00034 
00039 LONG IFDSetPTS(READER_CONTEXT * rContext, DWORD dwProtocol, UCHAR ucFlags,
00040     UCHAR ucPTS1, UCHAR ucPTS2, UCHAR ucPTS3)
00041 {
00042     RESPONSECODE rv = IFD_SUCCESS;
00043     UCHAR ucValue[1];
00044 
00045 #ifndef PCSCLITE_STATIC_DRIVER
00046     RESPONSECODE(*IFD_set_protocol_parameters) (DWORD, UCHAR, UCHAR,
00047         UCHAR, UCHAR) = NULL;
00048     RESPONSECODE(*IFDH_set_protocol_parameters) (DWORD, DWORD, UCHAR,
00049         UCHAR, UCHAR, UCHAR) = NULL;
00050 
00051     if (rContext->version == IFD_HVERSION_1_0)
00052     {
00053         IFD_set_protocol_parameters = (RESPONSECODE(*)(DWORD, UCHAR, UCHAR,
00054             UCHAR, UCHAR)) rContext->psFunctions.psFunctions_v1.pvfSetProtocolParameters;
00055 
00056         if (NULL == IFD_set_protocol_parameters)
00057             return SCARD_E_UNSUPPORTED_FEATURE;
00058     }
00059     else
00060     {
00061         IFDH_set_protocol_parameters = (RESPONSECODE(*)(DWORD, DWORD, UCHAR,
00062             UCHAR, UCHAR, UCHAR))
00063             rContext->psFunctions.psFunctions_v2.pvfSetProtocolParameters;
00064 
00065         if (NULL == IFDH_set_protocol_parameters)
00066             return SCARD_E_UNSUPPORTED_FEATURE;
00067     }
00068 #endif
00069 
00070     /*
00071      * Locking is done in winscard.c SCardConnect() and SCardReconnect()
00072      *
00073      * This avoids to renegotiate the protocol and confuse the card
00074      * Error returned by CCID driver is: CCID_Receive Procedure byte conflict
00075      */
00076 
00077     ucValue[0] = rContext->slot;
00078 
00079 #ifndef PCSCLITE_STATIC_DRIVER
00080     if (rContext->version == IFD_HVERSION_1_0)
00081     {
00082         ucValue[0] = rContext->slot;
00083         (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
00084         rv = (*IFD_set_protocol_parameters) (dwProtocol,
00085             ucFlags, ucPTS1, ucPTS2, ucPTS3);
00086     }
00087     else
00088     {
00089         rv = (*IFDH_set_protocol_parameters) (rContext->slot,
00090             dwProtocol, ucFlags, ucPTS1, ucPTS2, ucPTS3);
00091     }
00092 #else
00093 #ifdef IFDHANDLERv1
00094     {
00095         ucValue[0] = rContext->slot;
00096         (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
00097         rv = IFD_Set_Protocol_Parameters(dwProtocol, ucFlags, ucPTS1,
00098             ucPTS2, ucPTS3);
00099     }
00100 #else
00101     rv = IFDHSetProtocolParameters(rContext->slot, dwProtocol, ucFlags,
00102         ucPTS1, ucPTS2, ucPTS3); 
00103 #endif
00104 #endif
00105 
00106     return rv;
00107 }
00108 
00112 LONG IFDOpenIFD(READER_CONTEXT * rContext)
00113 {
00114     RESPONSECODE rv = 0;
00115 
00116 #ifndef PCSCLITE_STATIC_DRIVER
00117     RESPONSECODE(*IO_create_channel) (DWORD) = NULL;
00118     RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL;
00119     RESPONSECODE(*IFDH_create_channel_by_name) (DWORD, LPSTR) = NULL;
00120 
00121     if (rContext->version == IFD_HVERSION_1_0)
00122         IO_create_channel =
00123             rContext->psFunctions.psFunctions_v1.pvfCreateChannel;
00124     else
00125         if (rContext->version == IFD_HVERSION_2_0)
00126             IFDH_create_channel =
00127                 rContext->psFunctions.psFunctions_v2.pvfCreateChannel;
00128         else
00129         {
00130             IFDH_create_channel =
00131                 rContext->psFunctions.psFunctions_v3.pvfCreateChannel;
00132             IFDH_create_channel_by_name =
00133                 rContext->psFunctions.psFunctions_v3.pvfCreateChannelByName;
00134         }
00135 #endif
00136 
00137     /* LOCK THIS CODE REGION */
00138     (void)pthread_mutex_lock(rContext->mMutex);
00139 
00140 #ifndef PCSCLITE_STATIC_DRIVER
00141     if (rContext->version == IFD_HVERSION_1_0)
00142     {
00143         rv = (*IO_create_channel) (rContext->port);
00144     } else if (rContext->version == IFD_HVERSION_2_0)
00145     {
00146         rv = (*IFDH_create_channel) (rContext->slot, rContext->port);
00147     } else
00148     {
00149         /* use device name only if defined */
00150         if (rContext->lpcDevice[0] != '\0')
00151             rv = (*IFDH_create_channel_by_name) (rContext->slot, rContext->lpcDevice);
00152         else
00153             rv = (*IFDH_create_channel) (rContext->slot, rContext->port);
00154     }
00155 #else
00156 #ifdef IFDHANDLERv1
00157     rv = IO_Create_Channel(rContext->port);
00158 #elif IFDHANDLERv2
00159     rv = IFDHCreateChannel(rContext->slot, rContext->port);
00160 #else
00161     {
00162         /* Use device name only if defined */
00163         if (rContext->lpcDevice[0] != '\0')
00164             rv = IFDHCreateChannelByName(rContext->slot, rContext->lpcDevice);
00165         else
00166             rv = IFDHCreateChannel(rContext->slot, rContext->port);
00167     }
00168 #endif
00169 #endif
00170 
00171     /* END OF LOCKED REGION */
00172     (void)pthread_mutex_unlock(rContext->mMutex);
00173 
00174     return rv;
00175 }
00176 
00180 LONG IFDCloseIFD(READER_CONTEXT * rContext)
00181 {
00182     RESPONSECODE rv = IFD_SUCCESS;
00183     int repeat;
00184 
00185 #ifndef PCSCLITE_STATIC_DRIVER
00186     RESPONSECODE(*IO_close_channel) (void) = NULL;
00187     RESPONSECODE(*IFDH_close_channel) (DWORD) = NULL;
00188 
00189     if (rContext->version == IFD_HVERSION_1_0)
00190         IO_close_channel = rContext->psFunctions.psFunctions_v1.pvfCloseChannel;
00191     else
00192         IFDH_close_channel = rContext->psFunctions.psFunctions_v2.pvfCloseChannel;
00193 #endif
00194 
00195     /* TRY TO LOCK THIS CODE REGION */
00196     repeat = 5;
00197 again:
00198     rv = pthread_mutex_trylock(rContext->mMutex);
00199     if (EBUSY == rv)
00200     {
00201         Log1(PCSC_LOG_ERROR, "Locking failed");
00202         repeat--;
00203         if (repeat)
00204         {
00205             (void)SYS_USleep(100*1000); /* 100 ms */
00206             goto again;
00207         }
00208     }
00209 
00210 #ifndef PCSCLITE_STATIC_DRIVER
00211     if (rContext->version == IFD_HVERSION_1_0)
00212 
00213         rv = (*IO_close_channel) ();
00214     else
00215         rv = (*IFDH_close_channel) (rContext->slot);
00216 #else
00217 #ifdef IFDHANDLERv1
00218     rv = IO_Close_Channel();
00219 #else
00220     rv = IFDHCloseChannel(rContext->slot);
00221 #endif
00222 #endif
00223 
00224     /* END OF LOCKED REGION */
00225     (void)pthread_mutex_unlock(rContext->mMutex);
00226 
00227     return rv;
00228 }
00229 
00233 LONG IFDSetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
00234             DWORD dwLength, PUCHAR pucValue)
00235 {
00236     RESPONSECODE rv = IFD_SUCCESS;
00237 
00238 #ifndef PCSCLITE_STATIC_DRIVER
00239     RESPONSECODE(*IFD_set_capabilities) (DWORD, PUCHAR) = NULL;
00240     RESPONSECODE(*IFDH_set_capabilities) (DWORD, DWORD, DWORD, PUCHAR) = NULL;
00241 
00242     if (rContext->version == IFD_HVERSION_1_0)
00243         IFD_set_capabilities = rContext->psFunctions.psFunctions_v1.pvfSetCapabilities;
00244     else
00245         IFDH_set_capabilities = rContext->psFunctions.psFunctions_v2.pvfSetCapabilities;
00246 #endif
00247 
00248     /*
00249      * Let the calling function lock this otherwise a deadlock will
00250      * result
00251      */
00252 
00253 #ifndef PCSCLITE_STATIC_DRIVER
00254     if (rContext->version == IFD_HVERSION_1_0)
00255         rv = (*IFD_set_capabilities) (dwTag, pucValue);
00256     else
00257         rv = (*IFDH_set_capabilities) (rContext->slot, dwTag,
00258             dwLength, pucValue);
00259 #else
00260 #ifdef IFDHANDLERv1
00261     rv = IFD_Set_Capabilities(dwTag, pucValue);
00262 #else
00263     rv = IFDHSetCapabilities(rContext->slot, dwTag, dwLength, pucValue);
00264 #endif
00265 #endif
00266 
00267     return rv;
00268 }
00269 
00275 LONG IFDGetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
00276     PDWORD pdwLength, PUCHAR pucValue)
00277 {
00278     RESPONSECODE rv = IFD_SUCCESS;
00279 
00280 #ifndef PCSCLITE_STATIC_DRIVER
00281     RESPONSECODE(*IFD_get_capabilities) (DWORD, /*@out@*/ PUCHAR) = NULL;
00282     RESPONSECODE(*IFDH_get_capabilities) (DWORD, DWORD, PDWORD, /*@out@*/ PUCHAR) = NULL;
00283 
00284     if (rContext->version == IFD_HVERSION_1_0)
00285         IFD_get_capabilities =
00286             rContext->psFunctions.psFunctions_v1.pvfGetCapabilities;
00287     else
00288         IFDH_get_capabilities =
00289             rContext->psFunctions.psFunctions_v2.pvfGetCapabilities;
00290 #endif
00291 
00292     /* LOCK THIS CODE REGION */
00293     (void)pthread_mutex_lock(rContext->mMutex);
00294 
00295 #ifndef PCSCLITE_STATIC_DRIVER
00296     if (rContext->version == IFD_HVERSION_1_0)
00297         rv = (*IFD_get_capabilities) (dwTag, pucValue);
00298     else
00299         rv = (*IFDH_get_capabilities) (rContext->slot, dwTag,
00300             pdwLength, pucValue);
00301 #else
00302 #ifdef IFDHANDLERv1
00303     rv = IFD_Get_Capabilities(dwTag, pucValue);
00304 #else
00305     rv = IFDHGetCapabilities(rContext->slot, dwTag, pdwLength, pucValue);
00306 #endif
00307 #endif
00308 
00309     /* END OF LOCKED REGION */
00310     (void)pthread_mutex_unlock(rContext->mMutex);
00311 
00312     return rv;
00313 }
00314 
00318 LONG IFDPowerICC(READER_CONTEXT * rContext, DWORD dwAction,
00319     PUCHAR pucAtr, PDWORD pdwAtrLen)
00320 {
00321     RESPONSECODE rv;
00322 #ifndef PCSCLITE_STATIC_DRIVER
00323     short ret;
00324     SMARTCARD_EXTENSION sSmartCard;
00325 #endif
00326     DWORD dwStatus;
00327     UCHAR ucValue[1];
00328 
00329 #ifndef PCSCLITE_STATIC_DRIVER
00330     RESPONSECODE(*IFD_power_icc) (DWORD) = NULL;
00331     RESPONSECODE(*IFDH_power_icc) (DWORD, DWORD, PUCHAR, PDWORD) = NULL;
00332 #endif
00333 
00334     /*
00335      * Zero out everything
00336      */
00337     rv = IFD_SUCCESS;
00338     dwStatus = 0;
00339     ucValue[0] = 0;
00340 
00341     /*
00342      * Check that the card is inserted first
00343      */
00344     (void)IFDStatusICC(rContext, &dwStatus, pucAtr, pdwAtrLen);
00345 
00346     if (dwStatus & SCARD_ABSENT)
00347         return SCARD_W_REMOVED_CARD;
00348 #ifndef PCSCLITE_STATIC_DRIVER
00349     if (rContext->version == IFD_HVERSION_1_0)
00350         IFD_power_icc = rContext->psFunctions.psFunctions_v1.pvfPowerICC;
00351     else
00352         IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC;
00353 #endif
00354 
00355     /* LOCK THIS CODE REGION */
00356     (void)pthread_mutex_lock(rContext->mMutex);
00357 
00358 #ifndef PCSCLITE_STATIC_DRIVER
00359     if (rContext->version == IFD_HVERSION_1_0)
00360     {
00361         ucValue[0] = rContext->slot;
00362         (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
00363         rv = (*IFD_power_icc) (dwAction);
00364     }
00365     else
00366     {
00367         rv = (*IFDH_power_icc) (rContext->slot, dwAction,
00368             pucAtr, pdwAtrLen);
00369 
00370         ret = ATRDecodeAtr(&sSmartCard, pucAtr, *pdwAtrLen);
00371     }
00372 #else
00373 #ifdef IFDHANDLERv1
00374     {
00375         ucValue[0] = rContext->slot;
00376         (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
00377         rv = IFD_Power_ICC(dwAction);
00378     }
00379 #else
00380     rv = IFDHPowerICC(rContext->slot, dwAction, pucAtr, pdwAtrLen);
00381 #endif
00382 #endif
00383 
00384     /* END OF LOCKED REGION */
00385     (void)pthread_mutex_unlock(rContext->mMutex);
00386 
00387     /* use clean values in case of error */
00388     if (rv != IFD_SUCCESS)
00389     {
00390         *pdwAtrLen = 0;
00391         pucAtr[0] = '\0';
00392 
00393         if (rv == IFD_NO_SUCH_DEVICE)
00394         {
00395             (void)SendHotplugSignal();
00396             return SCARD_E_READER_UNAVAILABLE;
00397         }
00398 
00399         return SCARD_E_NOT_TRANSACTED;
00400     }
00401 
00402     /*
00403      * Get the ATR and it's length
00404      */
00405     if (rContext->version == IFD_HVERSION_1_0)
00406         (void)IFDStatusICC(rContext, &dwStatus, pucAtr, pdwAtrLen);
00407 
00408     return rv;
00409 }
00410 
00415 LONG IFDStatusICC(READER_CONTEXT * rContext, PDWORD pdwStatus,
00416     PUCHAR pucAtr, PDWORD pdwAtrLen)
00417 {
00418     RESPONSECODE rv = IFD_SUCCESS;
00419     DWORD dwTag = 0, dwCardStatus = 0;
00420     SMARTCARD_EXTENSION sSmartCard;
00421     UCHAR ucValue[1] = "\x00";
00422 
00423 #ifndef PCSCLITE_STATIC_DRIVER
00424     RESPONSECODE(*IFD_is_icc_present) (void) = NULL;
00425     RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL;
00426     RESPONSECODE(*IFD_get_capabilities) (DWORD, /*@out@*/ PUCHAR) = NULL;
00427 
00428     if (rContext->version == IFD_HVERSION_1_0)
00429     {
00430         IFD_is_icc_present =
00431             rContext->psFunctions.psFunctions_v1.pvfICCPresence;
00432         IFD_get_capabilities =
00433             rContext->psFunctions.psFunctions_v1.pvfGetCapabilities;
00434     }
00435     else
00436         IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence;
00437 #endif
00438 
00439     /* LOCK THIS CODE REGION */
00440     (void)pthread_mutex_lock(rContext->mMutex);
00441 
00442 #ifndef PCSCLITE_STATIC_DRIVER
00443     if (rContext->version == IFD_HVERSION_1_0)
00444     {
00445         ucValue[0] = rContext->slot;
00446         (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
00447         rv = (*IFD_is_icc_present) ();
00448     }
00449     else
00450         rv = (*IFDH_icc_presence) (rContext->slot);
00451 #else
00452 #ifdef IFDHANDLERv1
00453     {
00454         ucValue[0] = rContext->slot;
00455         (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
00456         rv = IFD_Is_ICC_Present();
00457     }
00458 #else
00459     rv = IFDHICCPresence(rContext->slot);
00460 #endif
00461 #endif
00462 
00463     /* END OF LOCKED REGION */
00464     (void)pthread_mutex_unlock(rContext->mMutex);
00465 
00466     if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
00467         dwCardStatus |= SCARD_PRESENT;
00468     else
00469         if (rv == IFD_ICC_NOT_PRESENT)
00470             dwCardStatus |= SCARD_ABSENT;
00471         else
00472         {
00473             Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
00474             *pdwStatus = SCARD_UNKNOWN;
00475 
00476             if (rv == IFD_NO_SUCH_DEVICE)
00477             {
00478                 (void)SendHotplugSignal();
00479                 return SCARD_E_READER_UNAVAILABLE;
00480             }
00481 
00482             return SCARD_E_NOT_TRANSACTED;
00483         }
00484 
00485     /*
00486      * Now lets get the ATR and process it if IFD Handler version 1.0.
00487      * IFD Handler version 2.0 does this immediately after reset/power up
00488      * to conserve resources
00489      */
00490 
00491     if (rContext->version == IFD_HVERSION_1_0)
00492     {
00493         if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
00494         {
00495             short ret;
00496 
00497             dwTag = TAG_IFD_ATR;
00498 
00499             /* LOCK THIS CODE REGION */
00500             (void)pthread_mutex_lock(rContext->mMutex);
00501 
00502             ucValue[0] = rContext->slot;
00503             (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
00504 
00505 #ifndef PCSCLITE_STATIC_DRIVER
00506             rv = (*IFD_get_capabilities) (dwTag, pucAtr);
00507 #else
00508 #ifdef IFDHANDLERv1
00509             rv = IFD_Get_Capabilities(dwTag, pucAtr);
00510 #endif
00511 #endif
00512 
00513             /* END OF LOCKED REGION */
00514             (void)pthread_mutex_unlock(rContext->mMutex);
00515 
00516             /*
00517              * FIX :: This is a temporary way to return the correct size
00518              * of the ATR since most of the drivers return MAX_ATR_SIZE
00519              */
00520 
00521             ret = ATRDecodeAtr(&sSmartCard, pucAtr, MAX_ATR_SIZE);
00522 
00523             /*
00524              * Might be a memory card without an ATR
00525              */
00526             if (ret == 0)
00527                 *pdwAtrLen = 0;
00528             else
00529                 *pdwAtrLen = sSmartCard.ATR.Length;
00530         }
00531         else
00532         {
00533             /*
00534              * No card is inserted - Atr length is 0
00535              */
00536             *pdwAtrLen = 0;
00537         }
00538         /*
00539          * End of FIX
00540          */
00541     }
00542 
00543     *pdwStatus = dwCardStatus;
00544 
00545     return SCARD_S_SUCCESS;
00546 }
00547 
00548 /*
00549  * Function: IFDControl Purpose : This function provides a means for
00550  * toggling a specific action on the reader such as swallow, eject,
00551  * biometric.
00552  */
00553 
00554 /*
00555  * Valid only for IFDHandler version 2.0
00556  */
00557 
00558 LONG IFDControl_v2(READER_CONTEXT * rContext, PUCHAR TxBuffer,
00559     DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength)
00560 {
00561     RESPONSECODE rv = IFD_SUCCESS;
00562 
00563 #ifndef PCSCLITE_STATIC_DRIVER
00564     RESPONSECODE(*IFDH_control_v2) (DWORD, PUCHAR, DWORD, /*@out@*/ PUCHAR,
00565         PDWORD);
00566 #endif
00567 
00568     if (rContext->version != IFD_HVERSION_2_0)
00569         return SCARD_E_UNSUPPORTED_FEATURE;
00570 
00571 #ifndef PCSCLITE_STATIC_DRIVER
00572     IFDH_control_v2 = rContext->psFunctions.psFunctions_v2.pvfControl;
00573 #endif
00574 
00575     /* LOCK THIS CODE REGION */
00576     (void)pthread_mutex_lock(rContext->mMutex);
00577 
00578 #ifndef PCSCLITE_STATIC_DRIVER
00579     rv = (*IFDH_control_v2) (rContext->slot, TxBuffer, TxLength,
00580         RxBuffer, RxLength);
00581 #elif IFDHANDLERv2
00582     rv = IFDHControl(rContext->slot, TxBuffer, TxLength,
00583         RxBuffer, RxLength);
00584 #endif
00585 
00586     /* END OF LOCKED REGION */
00587     (void)pthread_mutex_unlock(rContext->mMutex);
00588 
00589     if (rv == IFD_SUCCESS)
00590         return SCARD_S_SUCCESS;
00591     else
00592     {
00593         Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
00594         LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
00595         LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *RxLength);
00596         return SCARD_E_NOT_TRANSACTED;
00597     }
00598 }
00599 
00605 /*
00606  * Valid only for IFDHandler version 3.0 and up
00607  */
00608 
00609 LONG IFDControl(READER_CONTEXT * rContext, DWORD ControlCode,
00610     LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength,
00611     LPDWORD BytesReturned)
00612 {
00613     RESPONSECODE rv = IFD_SUCCESS;
00614 
00615 #ifndef PCSCLITE_STATIC_DRIVER
00616     RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD);
00617 #endif
00618 
00619     if (rContext->version < IFD_HVERSION_3_0)
00620         return SCARD_E_UNSUPPORTED_FEATURE;
00621 
00622 #ifndef PCSCLITE_STATIC_DRIVER
00623     IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl;
00624 #endif
00625 
00626     /* LOCK THIS CODE REGION */
00627     (void)pthread_mutex_lock(rContext->mMutex);
00628 
00629 #ifndef PCSCLITE_STATIC_DRIVER
00630     rv = (*IFDH_control) (rContext->slot, ControlCode, TxBuffer,
00631         TxLength, RxBuffer, RxLength, BytesReturned);
00632 #elif IFDHANDLERv3
00633     rv = IFDHControl(rContext->slot, ControlCode, TxBuffer,
00634         TxLength, RxBuffer, RxLength, BytesReturned);
00635 #endif
00636 
00637     /* END OF LOCKED REGION */
00638     (void)pthread_mutex_unlock(rContext->mMutex);
00639 
00640     if (rv == IFD_SUCCESS)
00641         return SCARD_S_SUCCESS;
00642     else
00643     {
00644         Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
00645         Log3(PCSC_LOG_DEBUG, "ControlCode: 0x%.8LX BytesReturned: %ld",
00646             ControlCode, *BytesReturned);
00647         LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
00648         LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *BytesReturned);
00649 
00650         if (rv == IFD_NO_SUCH_DEVICE)
00651         {
00652             (void)SendHotplugSignal();
00653             return SCARD_E_READER_UNAVAILABLE;
00654         }
00655 
00656         if ((IFD_ERROR_NOT_SUPPORTED == rv) || (IFD_NOT_SUPPORTED == rv))
00657             return SCARD_E_UNSUPPORTED_FEATURE;
00658 
00659         if (IFD_ERROR_INSUFFICIENT_BUFFER ==rv)
00660             return SCARD_E_INSUFFICIENT_BUFFER;
00661 
00662         return SCARD_E_NOT_TRANSACTED;
00663     }
00664 }
00665 
00669 LONG IFDTransmit(READER_CONTEXT * rContext, SCARD_IO_HEADER pioTxPci,
00670     PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer,
00671     PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
00672 {
00673     RESPONSECODE rv = IFD_SUCCESS;
00674 
00675 #ifndef PCSCLITE_STATIC_DRIVER
00676     RESPONSECODE(*IFD_transmit_to_icc) (SCARD_IO_HEADER, PUCHAR, DWORD,
00677         /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
00678     RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR,
00679         DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
00680 #endif
00681 
00682     /* log the APDU */
00683     DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength);
00684 
00685 #ifndef PCSCLITE_STATIC_DRIVER
00686     if (rContext->version == IFD_HVERSION_1_0)
00687         IFD_transmit_to_icc =
00688             rContext->psFunctions.psFunctions_v1.pvfTransmitToICC;
00689     else
00690         IFDH_transmit_to_icc =
00691             rContext->psFunctions.psFunctions_v2.pvfTransmitToICC;
00692 #endif
00693 
00694     /* LOCK THIS CODE REGION */
00695     (void)pthread_mutex_lock(rContext->mMutex);
00696 
00697 #ifndef PCSCLITE_STATIC_DRIVER
00698     if (rContext->version == IFD_HVERSION_1_0)
00699     {
00700         UCHAR ucValue[1];
00701 
00702         ucValue[0] = rContext->slot;
00703         (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
00704         rv = (*IFD_transmit_to_icc) (pioTxPci, (LPBYTE) pucTxBuffer,
00705             dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
00706     }
00707     else
00708         rv = (*IFDH_transmit_to_icc) (rContext->slot, pioTxPci,
00709             (LPBYTE) pucTxBuffer, dwTxLength,
00710             pucRxBuffer, pdwRxLength, pioRxPci);
00711 #else
00712 #ifdef IFDHANDLERv1
00713     {
00714         UCHAR ucValue[1];
00715 
00716         ucValue[0] = rContext->slot;
00717         (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
00718         rv = IFD_Transmit_to_ICC(pioTxPci, (LPBYTE) pucTxBuffer,
00719             dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
00720     }
00721 #else
00722     rv = IFDHTransmitToICC(rContext->slot, pioTxPci,
00723         (LPBYTE) pucTxBuffer, dwTxLength,
00724         pucRxBuffer, pdwRxLength, pioRxPci);
00725 #endif
00726 #endif
00727 
00728     /* END OF LOCKED REGION */
00729     (void)pthread_mutex_unlock(rContext->mMutex);
00730 
00731     /* log the returned status word */
00732     DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength);
00733 
00734     if (rv == IFD_SUCCESS)
00735         return SCARD_S_SUCCESS;
00736     else
00737     {
00738         Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
00739 
00740         if (rv == IFD_NO_SUCH_DEVICE)
00741         {
00742             (void)SendHotplugSignal();
00743             return SCARD_E_READER_UNAVAILABLE;
00744         }
00745 
00746         return SCARD_E_NOT_TRANSACTED;
00747     }
00748 }
00749