pcsc-lite 1.7.2
|
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