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