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

Generated on Thu Feb 21 01:47:31 2008 for pcsc-lite by  doxygen 1.5.5