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