pcsc-lite  1.8.2
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-2011
00009  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00010  *
00011  * $Id: ifdwrapper.c 5860 2011-07-09 11:29:52Z 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 "debuglog.h"
00027 #include "readerfactory.h"
00028 #include "ifdwrapper.h"
00029 #include "atrhandler.h"
00030 #include "dyn_generic.h"
00031 #include "sys_generic.h"
00032 #include "utils.h"
00033 
00034 #ifdef PCSCLITE_STATIC_DRIVER
00035 /* check that either IFDHANDLERv2 or IFDHANDLERv3 is
00036  * defined */
00037   #if ! (defined(IFDHANDLERv2) || defined(IFDHANDLERv3))
00038   #error IFDHANDLER version not defined
00039   #endif
00040 #endif
00041 
00046 LONG IFDSetPTS(READER_CONTEXT * rContext, DWORD dwProtocol, UCHAR ucFlags,
00047     UCHAR ucPTS1, UCHAR ucPTS2, UCHAR ucPTS3)
00048 {
00049     RESPONSECODE rv = IFD_SUCCESS;
00050 
00051 #ifndef PCSCLITE_STATIC_DRIVER
00052     RESPONSECODE(*IFDH_set_protocol_parameters) (DWORD, DWORD, UCHAR,
00053         UCHAR, UCHAR, UCHAR) = NULL;
00054 
00055     IFDH_set_protocol_parameters = (RESPONSECODE(*)(DWORD, DWORD, UCHAR,
00056         UCHAR, UCHAR, UCHAR))
00057         rContext->psFunctions.psFunctions_v2.pvfSetProtocolParameters;
00058 
00059     if (NULL == IFDH_set_protocol_parameters)
00060         return SCARD_E_UNSUPPORTED_FEATURE;
00061 #endif
00062 
00063     /*
00064      * Locking is done in winscard.c SCardConnect() and SCardReconnect()
00065      *
00066      * This avoids to renegotiate the protocol and confuse the card
00067      * Error returned by CCID driver is: CCID_Receive Procedure byte conflict
00068      */
00069 
00070 #ifndef PCSCLITE_STATIC_DRIVER
00071     rv = (*IFDH_set_protocol_parameters) (rContext->slot,
00072         dwProtocol, ucFlags, ucPTS1, ucPTS2, ucPTS3);
00073 #else
00074     rv = IFDHSetProtocolParameters(rContext->slot, dwProtocol, ucFlags,
00075         ucPTS1, ucPTS2, ucPTS3);
00076 #endif
00077 
00078     return rv;
00079 }
00080 
00084 LONG IFDOpenIFD(READER_CONTEXT * rContext)
00085 {
00086     RESPONSECODE rv = 0;
00087 
00088 #ifndef PCSCLITE_STATIC_DRIVER
00089     RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL;
00090     RESPONSECODE(*IFDH_create_channel_by_name) (DWORD, LPSTR) = NULL;
00091 
00092     if (rContext->version == IFD_HVERSION_2_0)
00093         IFDH_create_channel =
00094             rContext->psFunctions.psFunctions_v2.pvfCreateChannel;
00095     else
00096     {
00097         IFDH_create_channel =
00098             rContext->psFunctions.psFunctions_v3.pvfCreateChannel;
00099         IFDH_create_channel_by_name =
00100             rContext->psFunctions.psFunctions_v3.pvfCreateChannelByName;
00101     }
00102 #endif
00103 
00104     /* LOCK THIS CODE REGION */
00105     (void)pthread_mutex_lock(rContext->mMutex);
00106 
00107 #ifndef PCSCLITE_STATIC_DRIVER
00108     if (rContext->version == IFD_HVERSION_2_0)
00109     {
00110         rv = (*IFDH_create_channel) (rContext->slot, rContext->port);
00111     } else
00112     {
00113         /* use device name only if defined */
00114         if (rContext->device[0] != '\0')
00115             rv = (*IFDH_create_channel_by_name) (rContext->slot, rContext->device);
00116         else
00117             rv = (*IFDH_create_channel) (rContext->slot, rContext->port);
00118     }
00119 #else
00120 #if defined(IFDHANDLERv2)
00121     rv = IFDHCreateChannel(rContext->slot, rContext->port);
00122 #else
00123     {
00124         /* Use device name only if defined */
00125         if (rContext->lpcDevice[0] != '\0')
00126             rv = IFDHCreateChannelByName(rContext->slot, rContext->lpcDevice);
00127         else
00128             rv = IFDHCreateChannel(rContext->slot, rContext->port);
00129     }
00130 #endif
00131 #endif
00132 
00133     /* END OF LOCKED REGION */
00134     (void)pthread_mutex_unlock(rContext->mMutex);
00135 
00136     return rv;
00137 }
00138 
00142 LONG IFDCloseIFD(READER_CONTEXT * rContext)
00143 {
00144     RESPONSECODE rv = IFD_SUCCESS;
00145     int repeat;
00146 
00147 #ifndef PCSCLITE_STATIC_DRIVER
00148     RESPONSECODE(*IFDH_close_channel) (DWORD) = NULL;
00149 
00150     IFDH_close_channel = rContext->psFunctions.psFunctions_v2.pvfCloseChannel;
00151 #endif
00152 
00153     /* TRY TO LOCK THIS CODE REGION */
00154     repeat = 5;
00155 again:
00156     rv = pthread_mutex_trylock(rContext->mMutex);
00157     if (EBUSY == rv)
00158     {
00159         Log1(PCSC_LOG_ERROR, "Locking failed");
00160         repeat--;
00161         if (repeat)
00162         {
00163             (void)SYS_USleep(100*1000); /* 100 ms */
00164             goto again;
00165         }
00166     }
00167 
00168 #ifndef PCSCLITE_STATIC_DRIVER
00169     rv = (*IFDH_close_channel) (rContext->slot);
00170 #else
00171     rv = IFDHCloseChannel(rContext->slot);
00172 #endif
00173 
00174     /* END OF LOCKED REGION */
00175     (void)pthread_mutex_unlock(rContext->mMutex);
00176 
00177     return rv;
00178 }
00179 
00183 LONG IFDSetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
00184             DWORD dwLength, PUCHAR pucValue)
00185 {
00186     RESPONSECODE rv = IFD_SUCCESS;
00187 
00188 #ifndef PCSCLITE_STATIC_DRIVER
00189     RESPONSECODE(*IFDH_set_capabilities) (DWORD, DWORD, DWORD, PUCHAR) = NULL;
00190 
00191     IFDH_set_capabilities = rContext->psFunctions.psFunctions_v2.pvfSetCapabilities;
00192 #endif
00193 
00194     /*
00195      * Let the calling function lock this otherwise a deadlock will
00196      * result
00197      */
00198 
00199 #ifndef PCSCLITE_STATIC_DRIVER
00200     rv = (*IFDH_set_capabilities) (rContext->slot, dwTag,
00201             dwLength, pucValue);
00202 #else
00203     rv = IFDHSetCapabilities(rContext->slot, dwTag, dwLength, pucValue);
00204 #endif
00205 
00206     return rv;
00207 }
00208 
00214 LONG IFDGetCapabilities(READER_CONTEXT * rContext, DWORD dwTag,
00215     PDWORD pdwLength, PUCHAR pucValue)
00216 {
00217     RESPONSECODE rv = IFD_SUCCESS;
00218 
00219 #ifndef PCSCLITE_STATIC_DRIVER
00220     RESPONSECODE(*IFDH_get_capabilities) (DWORD, DWORD, PDWORD, /*@out@*/ PUCHAR) = NULL;
00221 
00222     IFDH_get_capabilities =
00223         rContext->psFunctions.psFunctions_v2.pvfGetCapabilities;
00224 #endif
00225 
00226     /* LOCK THIS CODE REGION */
00227     (void)pthread_mutex_lock(rContext->mMutex);
00228 
00229 #ifndef PCSCLITE_STATIC_DRIVER
00230     rv = (*IFDH_get_capabilities) (rContext->slot, dwTag, pdwLength, pucValue);
00231 #else
00232     rv = IFDHGetCapabilities(rContext->slot, dwTag, pdwLength, pucValue);
00233 #endif
00234 
00235     /* END OF LOCKED REGION */
00236     (void)pthread_mutex_unlock(rContext->mMutex);
00237 
00238     return rv;
00239 }
00240 
00244 LONG IFDPowerICC(READER_CONTEXT * rContext, DWORD dwAction,
00245     PUCHAR pucAtr, PDWORD pdwAtrLen)
00246 {
00247     RESPONSECODE rv;
00248     DWORD dwStatus;
00249     UCHAR dummyAtr[MAX_ATR_SIZE];
00250     DWORD dummyAtrLen = sizeof(dummyAtr);
00251 
00252 #ifndef PCSCLITE_STATIC_DRIVER
00253     RESPONSECODE(*IFDH_power_icc) (DWORD, DWORD, PUCHAR, PDWORD) = NULL;
00254 #endif
00255 
00256     /*
00257      * Zero out everything
00258      */
00259     dwStatus = 0;
00260 
00261     if (NULL == pucAtr)
00262         pucAtr = dummyAtr;
00263     if (NULL == pdwAtrLen)
00264         pdwAtrLen = &dummyAtrLen;
00265 
00266     /*
00267      * Check that the card is inserted first
00268      */
00269     (void)IFDStatusICC(rContext, &dwStatus);
00270 
00271     if (dwStatus & SCARD_ABSENT)
00272         return SCARD_W_REMOVED_CARD;
00273 #ifndef PCSCLITE_STATIC_DRIVER
00274     IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC;
00275 #endif
00276 
00277     /* LOCK THIS CODE REGION */
00278     (void)pthread_mutex_lock(rContext->mMutex);
00279 
00280 #ifndef PCSCLITE_STATIC_DRIVER
00281     rv = (*IFDH_power_icc) (rContext->slot, dwAction, pucAtr, pdwAtrLen);
00282 #else
00283     rv = IFDHPowerICC(rContext->slot, dwAction, pucAtr, pdwAtrLen);
00284 #endif
00285 
00286     /* END OF LOCKED REGION */
00287     (void)pthread_mutex_unlock(rContext->mMutex);
00288 
00289     /* use clean values in case of error */
00290     if (rv != IFD_SUCCESS)
00291     {
00292         *pdwAtrLen = 0;
00293         pucAtr[0] = '\0';
00294 
00295         if (rv == IFD_NO_SUCH_DEVICE)
00296         {
00297             (void)SendHotplugSignal();
00298             return SCARD_E_READER_UNAVAILABLE;
00299         }
00300 
00301         return SCARD_E_NOT_TRANSACTED;
00302     }
00303 
00304     return rv;
00305 }
00306 
00311 LONG IFDStatusICC(READER_CONTEXT * rContext, PDWORD pdwStatus)
00312 {
00313     RESPONSECODE rv = IFD_SUCCESS;
00314     DWORD dwCardStatus = 0;
00315 
00316 #ifndef PCSCLITE_STATIC_DRIVER
00317     RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL;
00318 
00319     IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence;
00320 #endif
00321 
00322     /* LOCK THIS CODE REGION */
00323     (void)pthread_mutex_lock(rContext->mMutex);
00324 
00325 #ifndef PCSCLITE_STATIC_DRIVER
00326     rv = (*IFDH_icc_presence) (rContext->slot);
00327 #else
00328     rv = IFDHICCPresence(rContext->slot);
00329 #endif
00330 
00331     /* END OF LOCKED REGION */
00332     (void)pthread_mutex_unlock(rContext->mMutex);
00333 
00334     if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
00335         dwCardStatus |= SCARD_PRESENT;
00336     else
00337         if (rv == IFD_ICC_NOT_PRESENT)
00338             dwCardStatus |= SCARD_ABSENT;
00339         else
00340         {
00341             Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
00342             *pdwStatus = SCARD_UNKNOWN;
00343 
00344             if (rv == IFD_NO_SUCH_DEVICE)
00345             {
00346                 (void)SendHotplugSignal();
00347                 return SCARD_E_READER_UNAVAILABLE;
00348             }
00349 
00350             return SCARD_E_NOT_TRANSACTED;
00351         }
00352 
00353     *pdwStatus = dwCardStatus;
00354 
00355     return SCARD_S_SUCCESS;
00356 }
00357 
00358 /*
00359  * Function: IFDControl Purpose : This function provides a means for
00360  * toggling a specific action on the reader such as swallow, eject,
00361  * biometric.
00362  */
00363 
00364 /*
00365  * Valid only for IFDHandler version 2.0
00366  */
00367 
00368 LONG IFDControl_v2(READER_CONTEXT * rContext, PUCHAR TxBuffer,
00369     DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength)
00370 {
00371     RESPONSECODE rv = IFD_SUCCESS;
00372 
00373 #ifndef PCSCLITE_STATIC_DRIVER
00374     RESPONSECODE(*IFDH_control_v2) (DWORD, PUCHAR, DWORD, /*@out@*/ PUCHAR,
00375         PDWORD);
00376 #endif
00377 
00378     if (rContext->version != IFD_HVERSION_2_0)
00379         return SCARD_E_UNSUPPORTED_FEATURE;
00380 
00381 #ifndef PCSCLITE_STATIC_DRIVER
00382     IFDH_control_v2 = rContext->psFunctions.psFunctions_v2.pvfControl;
00383 #endif
00384 
00385     /* LOCK THIS CODE REGION */
00386     (void)pthread_mutex_lock(rContext->mMutex);
00387 
00388 #ifndef PCSCLITE_STATIC_DRIVER
00389     rv = (*IFDH_control_v2) (rContext->slot, TxBuffer, TxLength,
00390         RxBuffer, RxLength);
00391 #elif defined(IFDHANDLERv2)
00392     rv = IFDHControl(rContext->slot, TxBuffer, TxLength,
00393         RxBuffer, RxLength);
00394 #endif
00395 
00396     /* END OF LOCKED REGION */
00397     (void)pthread_mutex_unlock(rContext->mMutex);
00398 
00399     if (rv == IFD_SUCCESS)
00400         return SCARD_S_SUCCESS;
00401     else
00402     {
00403         Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
00404         LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
00405         LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *RxLength);
00406         return SCARD_E_NOT_TRANSACTED;
00407     }
00408 }
00409 
00415 /*
00416  * Valid only for IFDHandler version 3.0 and up
00417  */
00418 
00419 LONG IFDControl(READER_CONTEXT * rContext, DWORD ControlCode,
00420     LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength,
00421     LPDWORD BytesReturned)
00422 {
00423     RESPONSECODE rv = IFD_SUCCESS;
00424 
00425 #ifndef PCSCLITE_STATIC_DRIVER
00426     RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD);
00427 #endif
00428 
00429     if (rContext->version < IFD_HVERSION_3_0)
00430         return SCARD_E_UNSUPPORTED_FEATURE;
00431 
00432 #ifndef PCSCLITE_STATIC_DRIVER
00433     IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl;
00434 #endif
00435 
00436     /* LOCK THIS CODE REGION */
00437     (void)pthread_mutex_lock(rContext->mMutex);
00438 
00439 #ifndef PCSCLITE_STATIC_DRIVER
00440     rv = (*IFDH_control) (rContext->slot, ControlCode, TxBuffer,
00441         TxLength, RxBuffer, RxLength, BytesReturned);
00442 #elif defined(IFDHANDLERv3)
00443     rv = IFDHControl(rContext->slot, ControlCode, TxBuffer,
00444         TxLength, RxBuffer, RxLength, BytesReturned);
00445 #endif
00446 
00447     /* END OF LOCKED REGION */
00448     (void)pthread_mutex_unlock(rContext->mMutex);
00449 
00450     if (rv == IFD_SUCCESS)
00451         return SCARD_S_SUCCESS;
00452     else
00453     {
00454         Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
00455         Log3(PCSC_LOG_DEBUG, "ControlCode: 0x%.8lX BytesReturned: %ld",
00456             ControlCode, *BytesReturned);
00457         LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
00458         LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *BytesReturned);
00459 
00460         if (rv == IFD_NO_SUCH_DEVICE)
00461         {
00462             (void)SendHotplugSignal();
00463             return SCARD_E_READER_UNAVAILABLE;
00464         }
00465 
00466         if ((IFD_ERROR_NOT_SUPPORTED == rv) || (IFD_NOT_SUPPORTED == rv))
00467             return SCARD_E_UNSUPPORTED_FEATURE;
00468 
00469         if (IFD_ERROR_INSUFFICIENT_BUFFER ==rv)
00470             return SCARD_E_INSUFFICIENT_BUFFER;
00471 
00472         return SCARD_E_NOT_TRANSACTED;
00473     }
00474 }
00475 
00479 LONG IFDTransmit(READER_CONTEXT * rContext, SCARD_IO_HEADER pioTxPci,
00480     PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer,
00481     PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
00482 {
00483     RESPONSECODE rv = IFD_SUCCESS;
00484 
00485 #ifndef PCSCLITE_STATIC_DRIVER
00486     RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR,
00487         DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
00488 #endif
00489 
00490     /* log the APDU */
00491     DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength);
00492 
00493 #ifndef PCSCLITE_STATIC_DRIVER
00494     IFDH_transmit_to_icc =
00495         rContext->psFunctions.psFunctions_v2.pvfTransmitToICC;
00496 #endif
00497 
00498     /* LOCK THIS CODE REGION */
00499     (void)pthread_mutex_lock(rContext->mMutex);
00500 
00501 #ifndef PCSCLITE_STATIC_DRIVER
00502     rv = (*IFDH_transmit_to_icc) (rContext->slot, pioTxPci, (LPBYTE)
00503         pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
00504 #else
00505     rv = IFDHTransmitToICC(rContext->slot, pioTxPci,
00506         (LPBYTE) pucTxBuffer, dwTxLength,
00507         pucRxBuffer, pdwRxLength, pioRxPci);
00508 #endif
00509 
00510     /* END OF LOCKED REGION */
00511     (void)pthread_mutex_unlock(rContext->mMutex);
00512 
00513     /* log the returned status word */
00514     DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength);
00515 
00516     if (rv == IFD_SUCCESS)
00517         return SCARD_S_SUCCESS;
00518     else
00519     {
00520         Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
00521 
00522         if (rv == IFD_NO_SUCH_DEVICE)
00523         {
00524             (void)SendHotplugSignal();
00525             return SCARD_E_READER_UNAVAILABLE;
00526         }
00527 
00528         return SCARD_E_NOT_TRANSACTED;
00529     }
00530 }
00531