1/* 2 * Copyright (c) 2000-2007 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * ifdwrapper.c 26 * SmartCardServices 27 */ 28 29/* 30 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 31 * 32 * Copyright (C) 1999-2004 33 * David Corcoran <corcoran@linuxnet.com> 34 * Damien Sauveron <damien.sauveron@labri.fr> 35 * Ludovic Rousseau <ludovic.rousseau@free.fr> 36 * 37 * $Id: ifdwrapper.c 123 2010-03-27 10:50:42Z ludovic.rousseau@gmail.com $ 38 */ 39 40/** 41 * @file 42 * @brief This wraps the dynamic ifdhandler functions. 43 */ 44 45#include "config.h" 46#include "wintypes.h" 47#include "pcsclite.h" 48#include "ifdhandler.h" 49#include "debuglog.h" 50#include "readerfactory.h" 51#include "ifdwrapper.h" 52#include "atrhandler.h" 53#include "dyn_generic.h" 54#include "sys_generic.h" 55 56#include <security_utilities/debugging.h> 57 58#undef PCSCLITE_STATIC_DRIVER 59 60/** 61 * Set the protocol type selection (PTS). 62 * This function sets the appropriate protocol to be used on the card. 63 */ 64LONG IFDSetPTS(PREADER_CONTEXT rContext, DWORD dwProtocol, UCHAR ucFlags, 65 UCHAR ucPTS1, UCHAR ucPTS2, UCHAR ucPTS3) 66{ 67 RESPONSECODE rv = IFD_SUCCESS; 68 UCHAR ucValue[1]; 69 70#ifndef PCSCLITE_STATIC_DRIVER 71 RESPONSECODE(*IFD_set_protocol_parameters) (DWORD, UCHAR, UCHAR, 72 UCHAR, UCHAR) = NULL; 73 RESPONSECODE(*IFDH_set_protocol_parameters) (DWORD, DWORD, UCHAR, 74 UCHAR, UCHAR, UCHAR) = NULL; 75 76 if (rContext->dwVersion == IFD_HVERSION_1_0) 77 { 78 IFD_set_protocol_parameters = (RESPONSECODE(*)(DWORD, UCHAR, UCHAR, 79 UCHAR, UCHAR)) rContext->psFunctions.psFunctions_v1.pvfSetProtocolParameters; 80 81 if (NULL == IFD_set_protocol_parameters) 82 return SCARD_E_UNSUPPORTED_FEATURE; 83 } 84 else 85 { 86 IFDH_set_protocol_parameters = (RESPONSECODE(*)(DWORD, DWORD, UCHAR, 87 UCHAR, UCHAR, UCHAR)) 88 rContext->psFunctions.psFunctions_v2.pvfSetProtocolParameters; 89 90 if (NULL == IFDH_set_protocol_parameters) 91 return SCARD_E_UNSUPPORTED_FEATURE; 92 } 93#endif 94 95 /* 96 * Locking is done in winscard.c SCardConnect() and SCardReconnect() 97 * 98 * This avoids renegotiating the protocol and confusing the card 99 * Error returned by CCID driver is: CCID_Receive Procedure byte conflict 100 */ 101 102 ucValue[0] = rContext->dwSlot; 103 104#ifndef PCSCLITE_STATIC_DRIVER 105 if (rContext->dwVersion == IFD_HVERSION_1_0) 106 { 107 ucValue[0] = rContext->dwSlot; 108 (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); 109 rv = (*IFD_set_protocol_parameters) (dwProtocol, 110 ucFlags, ucPTS1, ucPTS2, ucPTS3); 111 } 112 else 113 { 114 rv = (*IFDH_set_protocol_parameters) (rContext->dwSlot, 115 dwProtocol, 116 ucFlags, ucPTS1, 117 ucPTS2, ucPTS3); 118 } 119#else 120 if (rContext->dwVersion == IFD_HVERSION_1_0) 121 { 122 ucValue[0] = rContext->dwSlot; 123 (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); 124 rv = IFD_Set_Protocol_Parameters(dwProtocol, ucFlags, ucPTS1, 125 ucPTS2, ucPTS3); 126 } 127 else 128 { 129 rv = IFDHSetProtocolParameters(rContext->dwSlot, dwProtocol, 130 ucFlags, ucPTS1, ucPTS2, ucPTS3); 131 } 132#endif 133 134 return rv; 135} 136 137/** 138 * Open a communication channel to the IFD. 139 */ 140LONG IFDOpenIFD(PREADER_CONTEXT rContext) 141{ 142 RESPONSECODE rv = 0; 143 144#ifndef PCSCLITE_STATIC_DRIVER 145 RESPONSECODE(*IO_create_channel) (DWORD) = NULL; 146 RESPONSECODE(*IFDH_create_channel) (DWORD, DWORD) = NULL; 147 RESPONSECODE(*IFDH_create_channel_by_name) (DWORD, LPSTR) = NULL; 148 149 if (rContext->dwVersion == IFD_HVERSION_1_0) 150 IO_create_channel = 151 rContext->psFunctions.psFunctions_v1.pvfCreateChannel; 152 else 153 if (rContext->dwVersion == IFD_HVERSION_2_0) 154 IFDH_create_channel = 155 rContext->psFunctions.psFunctions_v2.pvfCreateChannel; 156 else 157 { 158 IFDH_create_channel = 159 rContext->psFunctions.psFunctions_v3.pvfCreateChannel; 160 IFDH_create_channel_by_name = 161 rContext->psFunctions.psFunctions_v3.pvfCreateChannelByName; 162 } 163#endif 164 165 /* LOCK THIS CODE REGION */ 166 (void)SYS_MutexLock(rContext->mMutex); 167 168#ifndef PCSCLITE_STATIC_DRIVER 169 if (rContext->dwVersion == IFD_HVERSION_1_0) 170 { 171 rv = (*IO_create_channel) (rContext->dwPort); 172 } else if (rContext->dwVersion == IFD_HVERSION_2_0) 173 { 174 rv = (*IFDH_create_channel) (rContext->dwSlot, rContext->dwPort); 175 } else 176 { 177 /* use device name only if defined */ 178 if (rContext->lpcDevice[0] != '\0') 179 rv = (*IFDH_create_channel_by_name) (rContext->dwSlot, rContext->lpcDevice); 180 else 181 rv = (*IFDH_create_channel) (rContext->dwSlot, rContext->dwPort); 182 } 183#else 184 if (rContext->dwVersion == IFD_HVERSION_1_0) 185 { 186 rv = IO_Create_Channel(rContext->dwPort); 187 } else if (rContext->dwVersion == IFD_HVERSION_2_0) 188 { 189 rv = IFDHCreateChannel(rContext->dwSlot, rContext->dwPort); 190 } else 191 { 192 /* Use device name only if defined */ 193 if (rContext->lpcDevice[0] != '\0') 194 rv = IFDHCreateChannelByName(rContext->dwSlot, rContext->lpcDevice); 195 else 196 rv = IFDHCreateChannel(rContext->dwSlot, rContext->dwPort); 197 } 198#endif 199 200 /* END OF LOCKED REGION */ 201 (void)SYS_MutexUnLock(rContext->mMutex); 202 203 return rv; 204} 205 206/** 207 * Close a communication channel to the IFD. 208 */ 209LONG IFDCloseIFD(PREADER_CONTEXT rContext) 210{ 211 RESPONSECODE rv = IFD_SUCCESS; 212 213#ifndef PCSCLITE_STATIC_DRIVER 214 RESPONSECODE(*IO_close_channel) (void) = NULL; 215 RESPONSECODE(*IFDH_close_channel) (DWORD) = NULL; 216 217 if (rContext->dwVersion == IFD_HVERSION_1_0) 218 IO_close_channel = rContext->psFunctions.psFunctions_v1.pvfCloseChannel; 219 else 220 IFDH_close_channel = rContext->psFunctions.psFunctions_v2.pvfCloseChannel; 221#endif 222 223 /* LOCK THIS CODE REGION */ 224 (void)SYS_MutexLock(rContext->mMutex); 225#ifndef PCSCLITE_STATIC_DRIVER 226 if (rContext->dwVersion == IFD_HVERSION_1_0) 227 228 rv = (*IO_close_channel) (); 229 else 230 rv = (*IFDH_close_channel) (rContext->dwSlot); 231#else 232 if (rContext->dwVersion == IFD_HVERSION_1_0) 233 rv = IO_Close_Channel(); 234 else 235 rv = IFDHCloseChannel(rContext->dwSlot); 236#endif 237 238 /* END OF LOCKED REGION */ 239 (void)SYS_MutexUnLock(rContext->mMutex); 240 241 return rv; 242} 243 244/** 245 * Set capabilities in the reader. 246 */ 247LONG IFDSetCapabilities(PREADER_CONTEXT rContext, DWORD dwTag, 248 DWORD dwLength, PUCHAR pucValue) 249{ 250 RESPONSECODE rv = IFD_SUCCESS; 251 252#ifndef PCSCLITE_STATIC_DRIVER 253 RESPONSECODE(*IFD_set_capabilities) (DWORD, PUCHAR) = NULL; 254 RESPONSECODE(*IFDH_set_capabilities) (DWORD, DWORD, DWORD, PUCHAR) = NULL; 255 256 if (rContext->dwVersion == IFD_HVERSION_1_0) 257 IFD_set_capabilities = rContext->psFunctions.psFunctions_v1.pvfSetCapabilities; 258 else 259 IFDH_set_capabilities = rContext->psFunctions.psFunctions_v2.pvfSetCapabilities; 260#endif 261 262 /* 263 * Let the calling function lock this otherwise a deadlock will 264 * result 265 */ 266 267#ifndef PCSCLITE_STATIC_DRIVER 268 if (rContext->dwVersion == IFD_HVERSION_1_0) 269 rv = (*IFD_set_capabilities) (dwTag, pucValue); 270 else 271 rv = (*IFDH_set_capabilities) (rContext->dwSlot, dwTag, 272 dwLength, pucValue); 273#else 274 if (rContext->dwVersion == IFD_HVERSION_1_0) 275 rv = IFD_Set_Capabilities(dwTag, pucValue); 276 else 277 rv = IFDHSetCapabilities(rContext->dwSlot, dwTag, dwLength, 278 pucValue); 279#endif 280 281 return rv; 282} 283 284/** 285 * Get's capabilities in the reader. 286 * Other functions int this file will call 287 * the driver directly to not cause a deadlock. 288 */ 289LONG IFDGetCapabilities(PREADER_CONTEXT rContext, DWORD dwTag, 290 PDWORD pdwLength, PUCHAR pucValue) 291{ 292 RESPONSECODE rv = IFD_SUCCESS; 293 294#ifndef PCSCLITE_STATIC_DRIVER 295 RESPONSECODE(*IFD_get_capabilities) (DWORD, /*@out@*/ PUCHAR) = NULL; 296 RESPONSECODE(*IFDH_get_capabilities) (DWORD, DWORD, PDWORD, /*@out@*/ PUCHAR) = NULL; 297 298 if (rContext->dwVersion == IFD_HVERSION_1_0) 299 IFD_get_capabilities = 300 rContext->psFunctions.psFunctions_v1.pvfGetCapabilities; 301 else 302 IFDH_get_capabilities = 303 rContext->psFunctions.psFunctions_v2.pvfGetCapabilities; 304#endif 305 306 /* LOCK THIS CODE REGION */ 307 (void)SYS_MutexLock(rContext->mMutex); 308 309#ifndef PCSCLITE_STATIC_DRIVER 310 if (rContext->dwVersion == IFD_HVERSION_1_0) 311 rv = (*IFD_get_capabilities) (dwTag, pucValue); 312 else 313 rv = (*IFDH_get_capabilities) (rContext->dwSlot, dwTag, 314 pdwLength, pucValue); 315#else 316 if (rContext->dwVersion == IFD_HVERSION_1_0) 317 rv = IFD_Get_Capabilities(dwTag, pucValue); 318 else 319 rv = IFDHGetCapabilities(rContext->dwSlot, dwTag, pdwLength, 320 pucValue); 321#endif 322 323 /* END OF LOCKED REGION */ 324 (void)SYS_MutexUnLock(rContext->mMutex); 325 326 return rv; 327} 328 329/** 330 * Power up/down or reset's an ICC located in the IFD. 331 */ 332LONG IFDPowerICC(PREADER_CONTEXT rContext, DWORD dwAction, 333 const unsigned char *pucAtr, PDWORD pdwAtrLen) 334{ 335 RESPONSECODE rv; 336 short ret; 337 SMARTCARD_EXTENSION sSmartCard; 338 DWORD dwStatus; 339 UCHAR ucValue[1]; 340 341#ifndef PCSCLITE_STATIC_DRIVER 342 RESPONSECODE(*IFD_power_icc) (DWORD) = NULL; 343 RESPONSECODE(*IFDH_power_icc) (DWORD, DWORD, PUCHAR, PDWORD) = NULL; 344#endif 345 346 /* 347 * Zero out everything 348 */ 349 rv = IFD_SUCCESS; 350 dwStatus = 0; 351 ucValue[0] = 0; 352 353 /* 354 * Check that the card is inserted first 355 */ 356 (void)IFDStatusICC(rContext, &dwStatus, pucAtr, pdwAtrLen); 357 358 if (dwStatus & SCARD_ABSENT) 359 return SCARD_W_REMOVED_CARD; 360#ifndef PCSCLITE_STATIC_DRIVER 361 if (rContext->dwVersion == IFD_HVERSION_1_0) 362 IFD_power_icc = rContext->psFunctions.psFunctions_v1.pvfPowerICC; 363 else 364 IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC; 365#endif 366 367 /* LOCK THIS CODE REGION */ 368 (void)SYS_MutexLock(rContext->mMutex); 369 370#ifndef PCSCLITE_STATIC_DRIVER 371 if (rContext->dwVersion == IFD_HVERSION_1_0) 372 { 373 ucValue[0] = rContext->dwSlot; 374 (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); 375 rv = (*IFD_power_icc) (dwAction); 376 } 377 else 378 { 379 rv = (*IFDH_power_icc) (rContext->dwSlot, dwAction, 380 (unsigned char *)pucAtr, pdwAtrLen); 381 382 ret = ATRDecodeAtr(&sSmartCard, pucAtr, *pdwAtrLen); 383 } 384#else 385 if (rContext->dwVersion == IFD_HVERSION_1_0) 386 { 387 ucValue[0] = rContext->dwSlot; 388 (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); 389 rv = IFD_Power_ICC(dwAction); 390 } 391 else 392 rv = IFDHPowerICC(rContext->dwSlot, dwAction, pucAtr, pdwAtrLen); 393#endif 394 395 /* END OF LOCKED REGION */ 396 (void)SYS_MutexUnLock(rContext->mMutex); 397 398 /* use clean values in case of error */ 399 if (rv != IFD_SUCCESS) 400 { 401 *pdwAtrLen = 0; 402// pucAtr[0] = '\0'; 403 404 if (rv == IFD_NO_SUCH_DEVICE) 405 { 406 // (void)SendHotplugSignal(); 407 return SCARD_E_READER_UNAVAILABLE; 408 } 409 410 return SCARD_E_NOT_TRANSACTED; 411 } 412 413 /* 414 * Get the ATR and it's length 415 */ 416 if (rContext->dwVersion == IFD_HVERSION_1_0) 417 (void)IFDStatusICC(rContext, &dwStatus, pucAtr, pdwAtrLen); 418 419 return rv; 420} 421 422/** 423 * Provide statistical information about the IFD and ICC including insertions, 424 * atr, powering status/etc. 425 */ 426LONG IFDStatusICC(PREADER_CONTEXT rContext, PDWORD pdwStatus, 427 const unsigned char *pucAtr, PDWORD pdwAtrLen) 428{ 429 RESPONSECODE rv = IFD_SUCCESS; 430 DWORD dwTag = 0, dwCardStatus = 0; 431 SMARTCARD_EXTENSION sSmartCard; 432 UCHAR ucValue[1] = "\x00"; 433 434#ifndef PCSCLITE_STATIC_DRIVER 435 RESPONSECODE(*IFD_is_icc_present) (void) = NULL; 436 RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL; 437 RESPONSECODE(*IFD_get_capabilities) (DWORD, /*@out@*/ PUCHAR) = NULL; 438 439 if (rContext->dwVersion == IFD_HVERSION_1_0) 440 { 441 IFD_is_icc_present = 442 rContext->psFunctions.psFunctions_v1.pvfICCPresence; 443 IFD_get_capabilities = 444 rContext->psFunctions.psFunctions_v1.pvfGetCapabilities; 445 } 446 else 447 { 448 IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence; 449 // Defensive measure 450 if (!IFDH_icc_presence) 451 return SCARD_E_SYSTEM_CANCELLED; 452 } 453#endif 454 455 /* LOCK THIS CODE REGION */ 456 (void)SYS_MutexLock(rContext->mMutex); 457 458#ifndef PCSCLITE_STATIC_DRIVER 459 if (rContext->dwVersion == IFD_HVERSION_1_0) 460 { 461 ucValue[0] = rContext->dwSlot; 462 (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); 463 rv = (*IFD_is_icc_present) (); 464 } 465 else 466 rv = (*IFDH_icc_presence) (rContext->dwSlot); 467#else 468 if (rContext->dwVersion == IFD_HVERSION_1_0) 469 { 470 ucValue[0] = rContext->dwSlot; 471 (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); 472 rv = IFD_Is_ICC_Present(); 473 } 474 else 475 rv = IFDHICCPresence(rContext->dwSlot); 476#endif 477 478 /* END OF LOCKED REGION */ 479 (void)SYS_MutexUnLock(rContext->mMutex); 480 481 if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT) 482 dwCardStatus |= SCARD_PRESENT; 483 else 484 if (rv == IFD_ICC_NOT_PRESENT) 485 dwCardStatus |= SCARD_ABSENT; 486 else 487 { 488 Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); 489 *pdwStatus = SCARD_UNKNOWN; 490 491 if (rv == IFD_NO_SUCH_DEVICE) 492 { 493 // (void)SendHotplugSignal(); 494 return SCARD_E_READER_UNAVAILABLE; 495 } 496 497 return SCARD_E_NOT_TRANSACTED; 498 } 499 500 /* 501 * Now lets get the ATR and process it if IFD Handler version 1.0. 502 * IFD Handler version 2.0 does this immediately after reset/power up 503 * to conserve resources 504 */ 505 506 if (rContext->dwVersion == IFD_HVERSION_1_0) 507 { 508 if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT) 509 { 510 short ret; 511 512 dwTag = TAG_IFD_ATR; 513 514 /* LOCK THIS CODE REGION */ 515 (void)SYS_MutexLock(rContext->mMutex); 516 517 ucValue[0] = rContext->dwSlot; 518 (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); 519 520#ifndef PCSCLITE_STATIC_DRIVER 521 rv = (*IFD_get_capabilities) (dwTag, (unsigned char *)pucAtr); 522#else 523 rv = IFD_Get_Capabilities(dwTag, pucAtr); 524#endif 525 526 /* END OF LOCKED REGION */ 527 (void)SYS_MutexUnLock(rContext->mMutex); 528 529 /* 530 * FIX :: This is a temporary way to return the correct size 531 * of the ATR since most of the drivers return MAX_ATR_SIZE 532 */ 533 534 ret = ATRDecodeAtr(&sSmartCard, pucAtr, MAX_ATR_SIZE); 535 536 /* 537 * Might be a memory card without an ATR 538 */ 539 if (ret == 0) 540 *pdwAtrLen = 0; 541 else 542 *pdwAtrLen = sSmartCard.ATR.Length; 543 } 544 else 545 { 546 /* 547 * No card is inserted - Atr length is 0 548 */ 549 *pdwAtrLen = 0; 550 } 551 /* 552 * End of FIX 553 */ 554 } 555 556 *pdwStatus = dwCardStatus; 557 558 return SCARD_S_SUCCESS; 559} 560 561/* 562 * Function: IFDControl Purpose : This function provides a means for 563 * toggling a specific action on the reader such as swallow, eject, 564 * biometric. 565 */ 566 567/* 568 * Valid only for IFDHandler version 2.0 569 */ 570 571LONG IFDControl_v2(PREADER_CONTEXT rContext, PUCHAR TxBuffer, 572 DWORD TxLength, PUCHAR RxBuffer, PDWORD RxLength) 573{ 574 RESPONSECODE rv = IFD_SUCCESS; 575 576#ifndef PCSCLITE_STATIC_DRIVER 577 RESPONSECODE(*IFDH_control_v2) (DWORD, PUCHAR, DWORD, /*@out@*/ PUCHAR, 578 PDWORD); 579#endif 580 581 if (rContext->dwVersion != IFD_HVERSION_2_0) 582 return SCARD_E_UNSUPPORTED_FEATURE; 583 584#ifndef PCSCLITE_STATIC_DRIVER 585 IFDH_control_v2 = rContext->psFunctions.psFunctions_v2.pvfControl; 586#endif 587 588 /* LOCK THIS CODE REGION */ 589 (void)SYS_MutexLock(rContext->mMutex); 590 591#ifndef PCSCLITE_STATIC_DRIVER 592 rv = (*IFDH_control_v2) (rContext->dwSlot, TxBuffer, TxLength, 593 RxBuffer, RxLength); 594#else 595 rv = IFDHControl_v2(rContext->dwSlot, TxBuffer, TxLength, 596 RxBuffer, RxLength); 597#endif 598 599 /* END OF LOCKED REGION */ 600 (void)SYS_MutexUnLock(rContext->mMutex); 601 602 if (rv == IFD_SUCCESS) 603 return SCARD_S_SUCCESS; 604 else 605 { 606 Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); 607 LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength); 608 LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *RxLength); 609 return SCARD_E_NOT_TRANSACTED; 610 } 611} 612 613/** 614 * Provide a means for toggling a specific action on the reader such as 615 * swallow, eject, biometric. 616 */ 617 618/* 619 * Valid only for IFDHandler version 3.0 and up 620 */ 621 622LONG IFDControl(PREADER_CONTEXT rContext, DWORD ControlCode, 623 LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength, 624 LPDWORD BytesReturned) 625{ 626 RESPONSECODE rv = IFD_SUCCESS; 627 628#ifndef PCSCLITE_STATIC_DRIVER 629 RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD); 630#endif 631 632 if (rContext->dwVersion < IFD_HVERSION_3_0) 633 return SCARD_E_UNSUPPORTED_FEATURE; 634 635#ifndef PCSCLITE_STATIC_DRIVER 636 IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl; 637#endif 638 639 /* LOCK THIS CODE REGION */ 640 (void)SYS_MutexLock(rContext->mMutex); 641 642#ifndef PCSCLITE_STATIC_DRIVER 643 rv = (*IFDH_control) (rContext->dwSlot, ControlCode, TxBuffer, 644 TxLength, RxBuffer, RxLength, BytesReturned); 645#else 646 rv = IFDHControl(rContext->dwSlot, ControlCode, TxBuffer, 647 TxLength, RxBuffer, RxLength, BytesReturned); 648#endif 649 650 /* END OF LOCKED REGION */ 651 (void)SYS_MutexUnLock(rContext->mMutex); 652 653 if (rv == IFD_SUCCESS) 654 return SCARD_S_SUCCESS; 655 else 656 { 657 Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); 658 Log3(PCSC_LOG_DEBUG, "ControlCode: 0x%.8LX BytesReturned: %ld", 659 ControlCode, *BytesReturned); 660 LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength); 661 LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *BytesReturned); 662 663 if (rv == IFD_NO_SUCH_DEVICE) 664 { 665// (void)SendHotplugSignal(); 666 return SCARD_E_READER_UNAVAILABLE; 667 } 668 669 return SCARD_E_NOT_TRANSACTED; 670 } 671} 672 673/** 674 * Transmit an APDU to the ICC. 675 */ 676LONG IFDTransmit(PREADER_CONTEXT rContext, SCARD_IO_HEADER pioTxPci, 677 PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer, 678 PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci) 679{ 680 RESPONSECODE rv = IFD_SUCCESS; 681 UCHAR ucValue[1] = "\x00"; 682 683#ifndef PCSCLITE_STATIC_DRIVER 684 RESPONSECODE(*IFD_transmit_to_icc) (SCARD_IO_HEADER, PUCHAR, DWORD, 685 /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL; 686 RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR, 687 DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL; 688#endif 689 690 /* log the APDU */ 691 DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength); 692 693#ifndef PCSCLITE_STATIC_DRIVER 694 if (rContext->dwVersion == IFD_HVERSION_1_0) 695 IFD_transmit_to_icc = 696 rContext->psFunctions.psFunctions_v1.pvfTransmitToICC; 697 else 698 IFDH_transmit_to_icc = 699 rContext->psFunctions.psFunctions_v2.pvfTransmitToICC; 700#endif 701 702 /* LOCK THIS CODE REGION */ 703 (void)SYS_MutexLock(rContext->mMutex); 704 705#ifndef PCSCLITE_STATIC_DRIVER 706 if (rContext->dwVersion == IFD_HVERSION_1_0) 707 { 708 ucValue[0] = rContext->dwSlot; 709 (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); 710 rv = (*IFD_transmit_to_icc) (pioTxPci, (LPBYTE) pucTxBuffer, 711 dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci); 712 } 713 else 714 rv = (*IFDH_transmit_to_icc) (rContext->dwSlot, pioTxPci, 715 (LPBYTE) pucTxBuffer, dwTxLength, 716 pucRxBuffer, pdwRxLength, pioRxPci); 717#else 718 if (rContext->dwVersion == IFD_HVERSION_1_0) 719 { 720 ucValue[0] = rContext->dwSlot; 721 (void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue); 722 rv = IFD_Transmit_to_ICC(pioTxPci, (LPBYTE) pucTxBuffer, 723 dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci); 724 } 725 else 726 rv = IFDHTransmitToICC(rContext->dwSlot, pioTxPci, 727 (LPBYTE) pucTxBuffer, dwTxLength, 728 pucRxBuffer, pdwRxLength, pioRxPci); 729#endif 730 731 /* END OF LOCKED REGION */ 732 (void)SYS_MutexUnLock(rContext->mMutex); 733 734 /* log the returned status word */ 735 DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength); 736 737 if (rv == IFD_SUCCESS) 738 return SCARD_S_SUCCESS; 739 else 740 { 741 Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv); 742 743 if (rv == IFD_NO_SUCH_DEVICE) 744 { 745 // (void)SendHotplugSignal(); 746 return SCARD_E_READER_UNAVAILABLE; 747 } 748 749 return SCARD_E_NOT_TRANSACTED; 750 } 751} 752 753