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