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 * readerfactory.c 26 * SmartCardServices 27 */ 28 29 30/****************************************************************** 31 32 MUSCLE SmartCard Development ( http://www.linuxnet.com ) 33 Title : readerfactory.c 34 Package: pcsc lite 35 Author : David Corcoran 36 Date : 7/27/99 37 License: Copyright (C) 1999 David Corcoran 38 <corcoran@linuxnet.com> 39 Purpose: This keeps track of a list of currently 40 available reader structures. 41 42$Id: readerfactory.c 123 2010-03-27 10:50:42Z ludovic.rousseau@gmail.com $ 43 44********************************************************************/ 45 46#include "config.h" 47#include <stdio.h> 48#include <stdlib.h> 49#include <string.h> 50#include <unistd.h> 51#include <sys/types.h> 52#include <sys/stat.h> 53#include <sys/errno.h> 54#include <fcntl.h> 55 56#include "wintypes.h" 57#include "pcsclite.h" 58#include "ifdhandler.h" 59#include "debuglog.h" 60#include "thread_generic.h" 61#include "readerfactory.h" 62#include "dyn_generic.h" 63#include "sys_generic.h" 64#include "eventhandler.h" 65#include "ifdwrapper.h" 66#include "readerState.h" 67 68#include <security_utilities/debugging.h> 69 70/* 71 64 bit 72 */ 73 74#include <mach/machine.h> 75#include <sys/sysctl.h> 76#include "configfile.h" 77 78static cpu_type_t architectureForPid(pid_t pid); 79 80#ifndef PCSCLITE_HP_BASE_PORT 81#define PCSCLITE_HP_BASE_PORT 0x200000 82#endif /* PCSCLITE_HP_BASE_PORT */ 83 84static LONG RFLoadReader(PREADER_CONTEXT); 85static LONG RFUnBindFunctions(PREADER_CONTEXT); 86static LONG RFUnloadReader(PREADER_CONTEXT); 87 88static PREADER_CONTEXT sReadersContexts[PCSCLITE_MAX_READERS_CONTEXTS]; 89static DWORD dwNumReadersContexts = 0; 90static DWORD lastLockID = 0; 91static PCSCLITE_MUTEX_T sReadersContextsLock = NULL; 92 93static int ReaderContextConstructor(PREADER_CONTEXT ctx, LPCSTR lpcReader, 94 DWORD dwPort, LPCSTR lpcLibrary, LPCSTR lpcDevice); 95static void ReaderContextDestructor(PREADER_CONTEXT ctx); 96static void ReaderContextFree(PREADER_CONTEXT ctx); 97static void ReaderContextClear(PREADER_CONTEXT ctx); 98static int ReaderContextInsert(PREADER_CONTEXT ctx); 99static int ReaderContextRemove(PREADER_CONTEXT ctx); 100static int ReaderContextCheckDuplicateReader(LPCSTR lpcReader, DWORD dwPort); 101static int ReaderSlotCount(PREADER_CONTEXT ctx); 102static BOOL ReaderDriverIsThreadSafe(PREADER_CONTEXT ctx, BOOL testSlot); 103static BOOL ReaderNameMatchForIndex(DWORD dwPort, LPCSTR lpcReader, int index); 104static void ReaderContextDuplicateSlot(PREADER_CONTEXT ctxBase, PREADER_CONTEXT ctxSlot, int slotNumber, BOOL baseIsThreadSafe); 105static int ReaderCheckForClone(PREADER_CONTEXT ctx, LPCSTR lpcReader, 106 DWORD dwPort, LPCSTR lpcLibrary); 107 108extern int DBUpdateReaders(const char *readerconf); 109 110LONG RFAllocateReaderSpace() 111{ 112 int i; 113 114 sReadersContextsLock = (PCSCLITE_MUTEX_T) malloc(sizeof(PCSCLITE_MUTEX)); 115 SYS_MutexInit(sReadersContextsLock); 116 117 /* 118 * Allocate each reader structure 119 */ 120 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 121 sReadersContexts[i] = (PREADER_CONTEXT) calloc(1, sizeof(READER_CONTEXT)); 122 123 /* 124 * Create public event structures 125 */ 126 return EHInitializeEventStructures(); 127} 128 129LONG RFAddReader(LPSTR lpcReader, DWORD dwPort, LPSTR lpcLibrary, LPSTR lpcDevice) 130{ 131 int slotCount; 132 LONG rv = SCARD_E_NO_MEMORY; 133 int slot; 134 PREADER_CONTEXT baseContext = NULL; 135 136 if ((lpcReader == NULL) || (lpcLibrary == NULL) || (lpcDevice == NULL)) 137 return SCARD_E_INVALID_VALUE; 138 139 /* Reader name too long? */ 140 if (strlen(lpcReader) >= MAX_READERNAME) 141 { 142 Log3(PCSC_LOG_ERROR, "Reader name too long: %d chars instead of max %d", 143 strlen(lpcReader), MAX_READERNAME); 144 return SCARD_E_INVALID_VALUE; 145 } 146 147 /* Library name too long? */ 148 if (strlen(lpcLibrary) >= MAX_LIBNAME) 149 { 150 Log3(PCSC_LOG_ERROR, "Library name too long: %d chars instead of max %d", 151 strlen(lpcLibrary), MAX_LIBNAME); 152 return SCARD_E_INVALID_VALUE; 153 } 154 155 /* Device name too long? */ 156 if (strlen(lpcDevice) >= MAX_DEVICENAME) 157 { 158 Log3(PCSC_LOG_ERROR, "Device name too long: %d chars instead of max %d", 159 strlen(lpcDevice), MAX_DEVICENAME); 160 return SCARD_E_INVALID_VALUE; 161 } 162 163 rv = ReaderContextCheckDuplicateReader(lpcReader, dwPort); 164 if (rv) 165 return rv; 166 167 // Make sure we have an empty slot to put the reader structure 168 rv = ReaderContextInsert(NULL); 169 if (rv != SCARD_S_SUCCESS) 170 return rv; 171 172 // Allocate a temporary reader context struct 173 baseContext = (PREADER_CONTEXT) calloc(1, sizeof(READER_CONTEXT)); 174 175 rv = ReaderContextConstructor(baseContext, lpcReader, dwPort, lpcLibrary, lpcDevice); 176 if (rv != SCARD_S_SUCCESS) 177 goto xit; 178 179 rv = ReaderCheckForClone(baseContext, lpcReader, dwPort, lpcLibrary); 180 if (rv != SCARD_S_SUCCESS) 181 goto xit; 182 183 rv = RFInitializeReader(baseContext); 184 if (rv != SCARD_S_SUCCESS) 185 goto xit; 186 187 rv = ReaderContextInsert(baseContext); 188 if (rv != SCARD_S_SUCCESS) 189 goto xit; 190 191 rv = EHSpawnEventHandler(baseContext); 192 if (rv != SCARD_S_SUCCESS) 193 goto xit; 194 195 slotCount = ReaderSlotCount(baseContext); 196 if (slotCount <= 1) 197 return SCARD_S_SUCCESS; 198 199 /* 200 * Check the number of slots and create a different 201 * structure for each one accordingly 202 */ 203 204 BOOL baseIsThreadSafe = ReaderDriverIsThreadSafe(baseContext, 1); 205 206 for (slot = 1; slot < slotCount; slot++) 207 { 208 // Make sure we have an empty slot to put the reader structure 209 // If not, we remove the whole reader 210 rv = ReaderContextInsert(NULL); 211 if (rv != SCARD_S_SUCCESS) 212 { 213 rv = RFRemoveReader(lpcReader, dwPort); 214 return rv; 215 } 216 217 // Allocate a temporary reader context struct 218 PREADER_CONTEXT ctxSlot = (PREADER_CONTEXT) calloc(1, sizeof(READER_CONTEXT)); 219 220 rv = ReaderContextConstructor(ctxSlot, lpcReader, dwPort, lpcLibrary, lpcDevice); 221 if (rv != SCARD_S_SUCCESS) 222 { 223 ReaderContextDestructor(ctxSlot); 224 free(ctxSlot); 225 return rv; 226 } 227 228 ReaderContextDuplicateSlot(baseContext, ctxSlot, slot, baseIsThreadSafe); 229 230 rv = RFInitializeReader(ctxSlot); 231 if (rv != SCARD_S_SUCCESS) 232 { 233 Log2(PCSC_LOG_ERROR, "%s init failed.", lpcReader); 234 ReaderContextDestructor(ctxSlot); 235 free(ctxSlot); 236 return rv; 237 } 238 239 rv = ReaderContextInsert(ctxSlot); 240 if (rv != SCARD_S_SUCCESS) 241 return rv; 242 243 rv = EHSpawnEventHandler(ctxSlot); 244 if (rv != SCARD_S_SUCCESS) 245 return rv; 246 } 247 248xit: 249 if (rv != SCARD_S_SUCCESS) 250 { 251 // Cannot connect to reader, so exit gracefully 252 Log3(PCSC_LOG_ERROR, "RFAddReader: %s init failed: %d", lpcReader, rv); 253 ReaderContextDestructor(baseContext); 254 free(baseContext); 255 } 256 257 return rv; 258} 259 260LONG RFRemoveReader(LPSTR lpcReader, DWORD dwPort) 261{ 262 LONG rv; 263 PREADER_CONTEXT tmpContext = NULL; 264 265 if (lpcReader == 0) 266 return SCARD_E_INVALID_VALUE; 267 268 secdebug("pcscd", "RFRemoveReader: removing %s", lpcReader); 269 while ((rv = RFReaderInfoNamePort(dwPort, lpcReader, &tmpContext)) == SCARD_S_SUCCESS) 270 { 271 // Try to destroy the thread 272 rv = EHDestroyEventHandler(tmpContext); 273 274 rv = RFUnInitializeReader(tmpContext); 275 if (rv != SCARD_S_SUCCESS) 276 return rv; 277 278 ReaderContextRemove(tmpContext); 279 } 280 281 return SCARD_S_SUCCESS; 282} 283 284LONG RFSetReaderName(PREADER_CONTEXT rContext, LPCSTR readerName, 285 LPCSTR libraryName, DWORD dwPort, DWORD dwSlot) 286{ 287 LONG parent = -1; /* reader number of the parent of the clone */ 288 DWORD valueLength; 289 int currentDigit = -1; 290 int supportedChannels = 0; 291 int usedDigits[PCSCLITE_MAX_READERS_CONTEXTS] = {0,}; 292 int i; 293 294 if ((0 == dwSlot) && (dwNumReadersContexts != 0)) 295 { 296 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 297 { 298 if (sReadersContexts[i] == NULL) 299 continue; 300 if ((sReadersContexts[i])->vHandle != 0) 301 { 302 if (strcmp((sReadersContexts[i])->lpcLibrary, libraryName) == 0) 303 { 304 UCHAR tagValue[1]; 305 LONG ret; 306 307 /* 308 * Ask the driver if it supports multiple channels 309 */ 310 valueLength = sizeof(tagValue); 311 ret = IFDGetCapabilities((sReadersContexts[i]), 312 TAG_IFD_SIMULTANEOUS_ACCESS, 313 &valueLength, tagValue); 314 315 if ((ret == IFD_SUCCESS) && (valueLength == 1) && 316 (tagValue[0] > 1)) 317 { 318 supportedChannels = tagValue[0]; 319 Log2(PCSC_LOG_INFO, 320 "Support %d simultaneous readers", tagValue[0]); 321 } 322 else 323 supportedChannels = 1; 324 325 /* 326 * Check to see if it is a hotplug reader and 327 * different 328 */ 329 if (((((sReadersContexts[i])->dwPort & 0xFFFF0000) == 330 PCSCLITE_HP_BASE_PORT) 331 && ((sReadersContexts[i])->dwPort != dwPort)) 332 || (supportedChannels > 1)) 333 { 334 char *lpcReader = sReadersContexts[i]->lpcReader; 335 336 /* 337 * tells the caller who the parent of this 338 * clone is so it can use it's shared 339 * resources like mutex/etc. 340 */ 341 parent = i; 342 343 /* 344 * If the same reader already exists and it is 345 * hotplug then we must look for others and 346 * enumerate the readername 347 */ 348 currentDigit = strtol(lpcReader + strlen(lpcReader) - 5, NULL, 16); 349 350 /* 351 * This spot is taken 352 */ 353 usedDigits[currentDigit] = 1; 354 } 355 } 356 } 357 } 358 359 } 360 361 /* default value */ 362 i = 0; 363 364 /* Other identical readers exist on the same bus */ 365 if (currentDigit != -1) 366 { 367 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 368 { 369 /* get the first free digit */ 370 if (usedDigits[i] == 0) 371 break; 372 } 373 374 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 375 { 376 Log2(PCSC_LOG_ERROR, "Max number of readers reached: %d", PCSCLITE_MAX_READERS_CONTEXTS); 377 return -2; 378 } 379 380 if (i >= supportedChannels) 381 { 382 Log3(PCSC_LOG_ERROR, "Driver %s does not support more than " 383 "%d reader(s). Maybe the driver should support " 384 "TAG_IFD_SIMULTANEOUS_ACCESS", libraryName, supportedChannels); 385 return -2; 386 } 387 } 388 389 sprintf(rContext->lpcReader, "%s %02X %02X", readerName, i, dwSlot); 390 391 /* 392 * Set the slot in 0xDDDDCCCC 393 */ 394 rContext->dwSlot = (i << 16) + dwSlot; 395 396 return parent; 397} 398 399LONG RFReaderInfo(LPSTR lpcReader, PREADER_CONTEXT * sReader) 400{ 401 int i; 402 LONG rv = SCARD_E_UNKNOWN_READER; 403 404 if (lpcReader == 0) 405 return SCARD_E_UNKNOWN_READER; 406 407 SYS_MutexLock(sReadersContextsLock); 408 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 409 { 410 if ((sReadersContexts[i]!=NULL) && ((sReadersContexts[i])->vHandle != 0)) 411 { 412 if (strcmp(lpcReader, (sReadersContexts[i])->lpcReader) == 0) 413 { 414 *sReader = sReadersContexts[i]; 415 rv = SCARD_S_SUCCESS; 416 break; 417 } 418 } 419 } 420 SYS_MutexUnLock(sReadersContextsLock); 421 422 return rv; 423} 424 425LONG RFReaderInfoNamePort(DWORD dwPort, LPSTR lpcReader, 426 PREADER_CONTEXT * sReader) 427{ 428 int ix; 429 LONG rv = SCARD_E_INVALID_VALUE; 430 431 SYS_MutexLock(sReadersContextsLock); 432 for (ix = 0; ix < PCSCLITE_MAX_READERS_CONTEXTS; ix++) 433 { 434 if ((sReadersContexts[ix]!=NULL) && ((sReadersContexts[ix])->vHandle != 0) && 435 ReaderNameMatchForIndex(dwPort, lpcReader, ix)) 436 { 437 *sReader = sReadersContexts[ix]; 438 rv = SCARD_S_SUCCESS; 439 break; 440 } 441 } 442 SYS_MutexUnLock(sReadersContextsLock); 443 444 return rv; 445} 446 447LONG RFReaderInfoById(DWORD dwIdentity, PREADER_CONTEXT * sReader) 448{ 449 int i; 450 LONG rv = SCARD_E_INVALID_VALUE; 451 452 /* 453 * Strip off the lower nibble and get the identity 454 */ 455 dwIdentity = dwIdentity >> (sizeof(DWORD) / 2) * 8; 456 dwIdentity = dwIdentity << (sizeof(DWORD) / 2) * 8; 457 458 SYS_MutexLock(sReadersContextsLock); 459 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 460 { 461 if ((sReadersContexts[i]!=NULL) && (dwIdentity == (sReadersContexts[i])->dwIdentity)) 462 { 463 *sReader = sReadersContexts[i]; 464 rv = SCARD_S_SUCCESS; 465 break; 466 } 467 } 468 SYS_MutexUnLock(sReadersContextsLock); 469 470 return rv; 471} 472 473static LONG RFLoadReader(PREADER_CONTEXT rContext) 474{ 475 if (rContext->vHandle != 0) 476 { 477 Log1(PCSC_LOG_ERROR, "Warning library pointer not NULL"); 478 /* 479 * Another reader exists with this library loaded 480 */ 481 return SCARD_S_SUCCESS; 482 } 483 484 return DYN_LoadLibrary(&rContext->vHandle, rContext->lpcLibrary); 485} 486 487LONG RFBindFunctions(PREADER_CONTEXT rContext) 488{ 489 int rv1, rv2, rv3; 490 void *f; 491 492 /* 493 * Use this function as a dummy to determine the IFD Handler version 494 * type 1.0/2.0/3.0. Suppress error messaging since it can't be 1.0, 495 * 2.0 and 3.0. 496 */ 497 498 Log1(PCSC_LOG_INFO, "Binding driver functions"); 499 500// DebugLogSuppress(DEBUGLOG_IGNORE_ENTRIES); 501 502 rv1 = DYN_GetAddress(rContext->vHandle, &f, "IO_Create_Channel"); 503 rv2 = DYN_GetAddress(rContext->vHandle, &f, "IFDHCreateChannel"); 504 rv3 = DYN_GetAddress(rContext->vHandle, &f, "IFDHCreateChannelByName"); 505 506// DebugLogSuppress(DEBUGLOG_LOG_ENTRIES); 507 508 if (rv1 != SCARD_S_SUCCESS && rv2 != SCARD_S_SUCCESS && rv3 != SCARD_S_SUCCESS) 509 { 510 /* 511 * Neither version of the IFD Handler was found - exit 512 */ 513 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing"); 514 515 exit(1); 516 } else if (rv1 == SCARD_S_SUCCESS) 517 { 518 /* 519 * Ifd Handler 1.0 found 520 */ 521 rContext->dwVersion = IFD_HVERSION_1_0; 522 } else if (rv3 == SCARD_S_SUCCESS) 523 { 524 /* 525 * Ifd Handler 3.0 found 526 */ 527 rContext->dwVersion = IFD_HVERSION_3_0; 528 } 529 else 530 { 531 /* 532 * Ifd Handler 2.0 found 533 */ 534 rContext->dwVersion = IFD_HVERSION_2_0; 535 } 536 537 /* 538 * The following binds version 1.0 of the IFD Handler specs 539 */ 540 541 if (rContext->dwVersion == IFD_HVERSION_1_0) 542 { 543 Log1(PCSC_LOG_INFO, "Loading IFD Handler 1.0"); 544 545#define GET_ADDRESS_OPTIONALv1(field, function, code) \ 546{ \ 547 void *f1 = NULL; \ 548 if (SCARD_S_SUCCESS != DYN_GetAddress(rContext->vHandle, &f1, "IFD_" #function)) \ 549 { \ 550 code \ 551 } \ 552 rContext->psFunctions.psFunctions_v1.pvf ## field = f1; \ 553} 554 555#define GET_ADDRESSv1(field, function) \ 556 GET_ADDRESS_OPTIONALv1(field, function, \ 557 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #function ); \ 558 exit(1); ) 559 560 DYN_GetAddress(rContext->vHandle, &f, "IO_Create_Channel"); 561 rContext->psFunctions.psFunctions_v1.pvfCreateChannel = f; 562 563 if (SCARD_S_SUCCESS != DYN_GetAddress(rContext->vHandle, &f, 564 "IO_Close_Channel")) 565 { 566 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing"); 567 exit(1); 568 } 569 rContext->psFunctions.psFunctions_v1.pvfCloseChannel = f; 570 571 GET_ADDRESSv1(GetCapabilities, Get_Capabilities) 572 GET_ADDRESSv1(SetCapabilities, Set_Capabilities) 573 GET_ADDRESSv1(PowerICC, Power_ICC) 574 GET_ADDRESSv1(TransmitToICC, Transmit_to_ICC) 575 GET_ADDRESSv1(ICCPresence, Is_ICC_Present) 576 577 GET_ADDRESS_OPTIONALv1(SetProtocolParameters, Set_Protocol_Parameters, ) 578 } 579 else if (rContext->dwVersion == IFD_HVERSION_2_0) 580 { 581 /* 582 * The following binds version 2.0 of the IFD Handler specs 583 */ 584 585#define GET_ADDRESS_OPTIONALv2(s, code) \ 586{ \ 587 void *f1 = NULL; \ 588 if (SCARD_S_SUCCESS != DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s)) \ 589 { \ 590 code \ 591 } \ 592 rContext->psFunctions.psFunctions_v2.pvf ## s = f1; \ 593} 594 595#define GET_ADDRESSv2(s) \ 596 GET_ADDRESS_OPTIONALv2(s, \ 597 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \ 598 exit(1); ) 599 600 Log1(PCSC_LOG_INFO, "Loading IFD Handler 2.0"); 601 602 GET_ADDRESSv2(CreateChannel) 603 GET_ADDRESSv2(CloseChannel) 604 GET_ADDRESSv2(GetCapabilities) 605 GET_ADDRESSv2(SetCapabilities) 606 GET_ADDRESSv2(PowerICC) 607 GET_ADDRESSv2(TransmitToICC) 608 GET_ADDRESSv2(ICCPresence) 609 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, ) 610 611 GET_ADDRESSv2(Control) 612 } 613 else if (rContext->dwVersion == IFD_HVERSION_3_0) 614 { 615 /* 616 * The following binds version 3.0 of the IFD Handler specs 617 */ 618 619#define GET_ADDRESS_OPTIONALv3(s, code) \ 620{ \ 621 void *f1 = NULL; \ 622 if (SCARD_S_SUCCESS != DYN_GetAddress(rContext->vHandle, &f1, "IFDH" #s)) \ 623 { \ 624 code \ 625 } \ 626 rContext->psFunctions.psFunctions_v3.pvf ## s = f1; \ 627} 628 629#define GET_ADDRESSv3(s) \ 630 GET_ADDRESS_OPTIONALv3(s, \ 631 Log1(PCSC_LOG_CRITICAL, "IFDHandler functions missing: " #s ); \ 632 exit(1); ) 633 634 Log1(PCSC_LOG_INFO, "Loading IFD Handler 3.0"); 635 636 GET_ADDRESSv2(CreateChannel) 637 GET_ADDRESSv2(CloseChannel) 638 GET_ADDRESSv2(GetCapabilities) 639 GET_ADDRESSv2(SetCapabilities) 640 GET_ADDRESSv2(PowerICC) 641 GET_ADDRESSv2(TransmitToICC) 642 GET_ADDRESSv2(ICCPresence) 643 GET_ADDRESS_OPTIONALv2(SetProtocolParameters, ) 644 645 GET_ADDRESSv3(CreateChannelByName) 646 GET_ADDRESSv3(Control) 647 } 648 else 649 { 650 /* 651 * Who knows what could have happenned for it to get here. 652 */ 653 Log1(PCSC_LOG_CRITICAL, "IFD Handler not 1.0/2.0 or 3.0"); 654 exit(1); 655 } 656 657 return SCARD_S_SUCCESS; 658} 659 660static LONG RFUnBindFunctions(PREADER_CONTEXT rContext) 661{ 662 /* 663 * Zero out everything 664 */ 665 666 Log1(PCSC_LOG_INFO, "Unbinding driver functions"); 667 memset(&rContext->psFunctions, 0, sizeof(rContext->psFunctions)); 668 669 return SCARD_S_SUCCESS; 670} 671 672static LONG RFUnloadReader(PREADER_CONTEXT rContext) 673{ 674 /* 675 * Make sure no one else is using this library 676 */ 677 678 Log1(PCSC_LOG_INFO, "Unloading reader driver."); 679 if (*rContext->pdwFeeds == 1) 680 { 681 Log1(PCSC_LOG_INFO, "--- closing dynamic library"); 682 DYN_CloseLibrary(&rContext->vHandle); 683 } 684 685 rContext->vHandle = 0; 686 687 return SCARD_S_SUCCESS; 688} 689 690LONG RFCheckSharing(DWORD hCard) 691{ 692 LONG rv; 693 PREADER_CONTEXT rContext = NULL; 694 695 rv = RFReaderInfoById(hCard, &rContext); 696 697 if (rv != SCARD_S_SUCCESS) 698 return rv; 699 700 if (rContext->dwLockId == 0 || rContext->dwLockId == hCard) 701 return SCARD_S_SUCCESS; 702 else 703 { 704 secdebug("pcscd", "RFCheckSharing: sharing violation, dwLockId: 0x%02X", rContext->dwLockId); 705 return SCARD_E_SHARING_VIOLATION; 706 } 707} 708 709LONG RFLockSharing(DWORD hCard) 710{ 711 PREADER_CONTEXT rContext = NULL; 712 713 RFReaderInfoById(hCard, &rContext); 714 715 if (RFCheckSharing(hCard) == SCARD_S_SUCCESS) 716 { 717 EHSetSharingEvent(rContext, 1); 718 rContext->dwLockId = hCard; 719 } 720 else 721 return SCARD_E_SHARING_VIOLATION; 722 723 return SCARD_S_SUCCESS; 724} 725 726LONG RFUnlockSharing(DWORD hCard) 727{ 728 PREADER_CONTEXT rContext = NULL; 729 LONG rv; 730 731 rv = RFReaderInfoById(hCard, &rContext); 732 if (rv != SCARD_S_SUCCESS) 733 return rv; 734 735 rv = RFCheckSharing(hCard); 736 if (rv != SCARD_S_SUCCESS) 737 return rv; 738 739 EHSetSharingEvent(rContext, 0); 740 rContext->dwLockId = 0; 741 742 return SCARD_S_SUCCESS; 743} 744 745LONG RFUnblockContext(SCARDCONTEXT hContext) 746{ 747 int i; 748 749 SYS_MutexLock(sReadersContextsLock); 750 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 751 if (sReadersContexts[i]) 752 (sReadersContexts[i])->dwBlockStatus = hContext; 753 SYS_MutexUnLock(sReadersContextsLock); 754 755 return SCARD_S_SUCCESS; 756} 757 758LONG RFUnblockReader(PREADER_CONTEXT rContext) 759{ 760 rContext->dwBlockStatus = BLOCK_STATUS_RESUME; 761 return SCARD_S_SUCCESS; 762} 763 764LONG RFInitializeReader(PREADER_CONTEXT rContext) 765{ 766 LONG rv; 767 768 /* 769 * Spawn the event handler thread 770 */ 771 Log3(PCSC_LOG_INFO, "Attempting startup of %s using %s", 772 rContext->lpcReader, rContext->lpcLibrary); 773 774 /******************************************/ 775 /* 776 * This section loads the library 777 */ 778 /******************************************/ 779 rv = RFLoadReader(rContext); 780 if (rv != SCARD_S_SUCCESS) 781 { 782 Log2(PCSC_LOG_ERROR, "RFLoadReader failed: %X", rv); 783 return rv; 784 } 785 786 /*******************************************/ 787 /* 788 * This section binds the functions 789 */ 790 /*******************************************/ 791 rv = RFBindFunctions(rContext); 792 793 if (rv != SCARD_S_SUCCESS) 794 { 795 Log2(PCSC_LOG_ERROR, "RFBindFunctions failed: %X", rv); 796 RFUnloadReader(rContext); 797 return rv; 798 } 799 800 /*******************************************/ 801 /* 802 * This section tries to open the port 803 */ 804 /*******************************************/ 805 806 rv = IFDOpenIFD(rContext); 807 808 if (rv != IFD_SUCCESS) 809 { 810 Log3(PCSC_LOG_CRITICAL, "Open Port %X Failed (%s)", 811 rContext->dwPort, rContext->lpcDevice); 812 RFUnBindFunctions(rContext); 813 RFUnloadReader(rContext); 814 return SCARD_E_INVALID_TARGET; 815 } 816 817 return SCARD_S_SUCCESS; 818} 819 820LONG RFUnInitializeReader(PREADER_CONTEXT rContext) 821{ 822 Log2(PCSC_LOG_INFO, "Attempting shutdown of %s.", 823 rContext->lpcReader); 824 825 /* 826 * Close the port, unbind the functions, and unload the library 827 */ 828 829 /* 830 * If the reader is getting uninitialized then it is being unplugged 831 * so I can't send a IFDPowerICC call to it 832 * 833 * IFDPowerICC( rContext, IFD_POWER_DOWN, Atr, &AtrLen ); 834 */ 835 IFDCloseIFD(rContext); 836 RFUnBindFunctions(rContext); 837 RFUnloadReader(rContext); 838 839 return SCARD_S_SUCCESS; 840} 841 842SCARDHANDLE RFCreateReaderHandle(PREADER_CONTEXT rContext) 843{ 844 USHORT randHandle; 845 846 /* 847 * Create a random handle with 16 bits check to see if it already is 848 * used. 849 */ 850 randHandle = SYS_Random(SYS_GetSeed(), 10, 65000); 851 852 while (1) 853 { 854 int i; 855 856 SYS_MutexLock(sReadersContextsLock); 857 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 858 { 859 if ((sReadersContexts[i]!=NULL) && ((sReadersContexts[i])->vHandle != 0)) 860 { 861 int j; 862 863 for (j = 0; j < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; j++) 864 { 865 if ((rContext->dwIdentity + randHandle) == 866 (sReadersContexts[i])->psHandles[j].hCard) 867 { 868 /* 869 * Get a new handle and loop again 870 */ 871 randHandle = SYS_Random(randHandle, 10, 65000); 872 continue; 873 } 874 } 875 } 876 } 877 SYS_MutexUnLock(sReadersContextsLock); 878 879 /* 880 * Once the for loop is completed w/o restart a good handle was 881 * found and the loop can be exited. 882 */ 883 884 if (i == PCSCLITE_MAX_READERS_CONTEXTS) 885 break; 886 } 887 888 return rContext->dwIdentity + randHandle; 889} 890 891LONG RFFindReaderHandle(SCARDHANDLE hCard) 892{ 893 int i; 894 LONG rv = SCARD_E_INVALID_HANDLE; 895 896 SYS_MutexLock(sReadersContextsLock); 897 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 898 { 899 if ((sReadersContexts[i]!=NULL) && ((sReadersContexts[i])->vHandle != 0)) 900 { 901 int j; 902 903 for (j = 0; j < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; j++) 904 { 905 if (hCard == (sReadersContexts[i])->psHandles[j].hCard) 906 { 907 rv = SCARD_S_SUCCESS; 908 goto xit; 909 } 910 } 911 } 912 } 913xit: 914 SYS_MutexUnLock(sReadersContextsLock); 915 916 return rv; 917} 918 919LONG RFDestroyReaderHandle(SCARDHANDLE hCard) 920{ 921 return SCARD_S_SUCCESS; 922} 923 924LONG RFAddReaderHandle(PREADER_CONTEXT rContext, SCARDHANDLE hCard) 925{ 926 int i; 927 928 for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++) 929 { 930 if (rContext->psHandles[i].hCard == 0) 931 { 932 rContext->psHandles[i].hCard = hCard; 933 rContext->psHandles[i].dwEventStatus = 0; 934 break; 935 } 936 } 937 938 if (i == PCSCLITE_MAX_READER_CONTEXT_CHANNELS) 939 /* List is full */ 940 return SCARD_E_INSUFFICIENT_BUFFER; 941 942 return SCARD_S_SUCCESS; 943} 944 945LONG RFRemoveReaderHandle(PREADER_CONTEXT rContext, SCARDHANDLE hCard) 946{ 947 int i; 948 949 for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++) 950 { 951 if (rContext->psHandles[i].hCard == hCard) 952 { 953 rContext->psHandles[i].hCard = 0; 954 rContext->psHandles[i].dwEventStatus = 0; 955 break; 956 } 957 } 958 959 if (i == PCSCLITE_MAX_READER_CONTEXT_CHANNELS) 960 /* Not Found */ 961 return SCARD_E_INVALID_HANDLE; 962 963 return SCARD_S_SUCCESS; 964} 965 966LONG RFSetReaderEventState(PREADER_CONTEXT rContext, DWORD dwEvent) 967{ 968 int i; 969 970 /* 971 * Set all the handles for that reader to the event 972 */ 973 for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++) 974 { 975 if (rContext->psHandles[i].hCard != 0) 976 rContext->psHandles[i].dwEventStatus = dwEvent; 977 } 978 979 return SCARD_S_SUCCESS; 980} 981 982LONG RFCheckReaderEventState(PREADER_CONTEXT rContext, SCARDHANDLE hCard) 983{ 984 int i; 985 986 for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++) 987 { 988 if (rContext->psHandles[i].hCard == hCard) 989 { 990 if (rContext->psHandles[i].dwEventStatus == SCARD_REMOVED) 991 return SCARD_W_REMOVED_CARD; 992 else 993 { 994 if (rContext->psHandles[i].dwEventStatus == SCARD_RESET) 995 return SCARD_W_RESET_CARD; 996 else 997 { 998 if (rContext->psHandles[i].dwEventStatus == 0) 999 return SCARD_S_SUCCESS; 1000 else 1001 return SCARD_E_INVALID_VALUE; 1002 } 1003 } 1004 } 1005 } 1006 1007 return SCARD_E_INVALID_HANDLE; 1008} 1009 1010LONG RFClearReaderEventState(PREADER_CONTEXT rContext, SCARDHANDLE hCard) 1011{ 1012 int i; 1013 1014 for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++) 1015 { 1016 if (rContext->psHandles[i].hCard == hCard) 1017 rContext->psHandles[i].dwEventStatus = 0; 1018 } 1019 1020 if (i == PCSCLITE_MAX_READER_CONTEXT_CHANNELS) 1021 /* Not Found */ 1022 return SCARD_E_INVALID_HANDLE; 1023 1024 return SCARD_S_SUCCESS; 1025} 1026 1027LONG RFCheckReaderStatus(PREADER_CONTEXT rContext) 1028{ 1029 LONG rx = 0; 1030 rx = ((rContext == NULL) || (rContext->readerState == NULL) || 1031 (SharedReaderState_State(rContext->readerState) & SCARD_UNKNOWN))?SCARD_E_READER_UNAVAILABLE:SCARD_S_SUCCESS; 1032 return rx; 1033} 1034 1035void RFCleanupReaders(int shouldExit) 1036{ 1037 int i; 1038 1039 Log1(PCSC_LOG_INFO, "entering cleaning function"); 1040 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 1041 { 1042 if ((sReadersContexts[i]!=NULL) && (sReadersContexts[i]->vHandle != 0)) 1043 { 1044 LONG rv; 1045 char lpcStripReader[MAX_READERNAME]; 1046 1047 Log2(PCSC_LOG_INFO, "Stopping reader: %s", 1048 sReadersContexts[i]->lpcReader); 1049 1050 strncpy(lpcStripReader, (sReadersContexts[i])->lpcReader, 1051 sizeof(lpcStripReader)); 1052 /* 1053 * strip the 6 last char ' 00 00' 1054 */ 1055 lpcStripReader[strlen(lpcStripReader) - 6] = '\0'; 1056 1057 rv = RFRemoveReader(lpcStripReader, sReadersContexts[i]->dwPort); 1058 1059 if (rv != SCARD_S_SUCCESS) 1060 Log2(PCSC_LOG_ERROR, "RFRemoveReader error: 0x%08X", rv); 1061 } 1062 } 1063 1064 secdebug("pcscd", "RFCleanupReaders: exiting cleaning function"); 1065 /* 1066 * exit() will call at_exit() 1067 */ 1068 1069 if (shouldExit) 1070 exit(0); 1071} 1072 1073int RFStartSerialReaders(const char *readerconf) 1074{ 1075 return DBUpdateReaders((char *)readerconf); 1076} 1077 1078void RFReCheckReaderConf(void) 1079{ 1080} 1081 1082void RFSuspendAllReaders() 1083{ 1084 int ix; 1085 secdebug("pcscd", "RFSuspendAllReaders"); 1086 Log1(PCSC_LOG_DEBUG, "zzzzz zzzzz zzzzz zzzzz RFSuspendAllReaders zzzzz zzzzz zzzzz zzzzz "); 1087 1088 // @@@ We still need code to mark state first as "trying to sleep", in case 1089 // not all of it gets done before we sleep 1090 for (ix = 0; ix < PCSCLITE_MAX_READERS_CONTEXTS; ix++) 1091 { 1092 if ((sReadersContexts[ix]!=NULL) && ((sReadersContexts[ix])->vHandle != 0)) 1093 { 1094 EHDestroyEventHandler(sReadersContexts[ix]); 1095 IFDCloseIFD(sReadersContexts[ix]); 1096 } 1097 } 1098} 1099 1100void RFAwakeAllReaders(void) 1101{ 1102 LONG rv = IFD_SUCCESS; 1103 int i; 1104 1105 secdebug("pcscd", "RFAwakeAllReaders"); 1106 Log1(PCSC_LOG_DEBUG, "----- ----- ----- ----- RFAwakeAllReaders ----- ----- ----- ----- "); 1107 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) 1108 { 1109 if (sReadersContexts[i]==NULL) 1110 continue; 1111 /* If the library is loaded and the event handler is not running */ 1112 if ( ((sReadersContexts[i])->vHandle != 0) && 1113 ((sReadersContexts[i])->pthThread == 0) ) 1114 { 1115 int jx; 1116 int alreadyInitializedFlag = 0; 1117 1118 // If a clone of this already did the initialization, 1119 // set flag so we don't do again 1120 for (jx=0; jx < i; jx++) 1121 { 1122 if (((sReadersContexts[jx])->vHandle == (sReadersContexts[i])->vHandle)&& 1123 ((sReadersContexts[jx])->dwPort == (sReadersContexts[i])->dwPort)&& 1124 ((sReadersContexts[jx])->dwSlot == (sReadersContexts[i])->dwSlot)) 1125 { 1126 alreadyInitializedFlag = 1; 1127 } 1128 } 1129 1130 if (!alreadyInitializedFlag) 1131 { 1132 SYS_USleep(100000L); // 0.1s (in microseconds) 1133 rv = IFDOpenIFD(sReadersContexts[i]); 1134 } 1135 1136 RFSetReaderEventState(sReadersContexts[i], SCARD_RESET); 1137 if (rv != IFD_SUCCESS) 1138 { 1139 Log3(PCSC_LOG_ERROR, "Open Port %X Failed (%s)", 1140 (sReadersContexts[i])->dwPort, (sReadersContexts[i])->lpcDevice); 1141 Log2(PCSC_LOG_ERROR, " with error 0x%08X", rv); 1142 continue; 1143 } 1144 1145 EHSpawnEventHandler(sReadersContexts[i]); 1146 } 1147 } 1148} 1149 1150#pragma mark ---------- Context Share Lock Tracking ---------- 1151 1152void ReaderContextLock(PREADER_CONTEXT rContext) 1153{ 1154 if (rContext) 1155 { 1156 secdebug("pcscd", "===> ReaderContextLock [was: %02X]", rContext->dwLockId); 1157 rContext->dwLockId = 0xFFFF; 1158 lastLockID = -3; // something different 1159 } 1160} 1161 1162void ReaderContextUnlock(PREADER_CONTEXT rContext) 1163{ 1164 if (rContext) 1165 { 1166 secdebug("pcscd", "<=== ReaderContextUnlock [was: %02X]", rContext->dwLockId); 1167 rContext->dwLockId = 0; 1168 lastLockID = -2; // something different 1169 } 1170} 1171 1172int ReaderContextIsLocked(PREADER_CONTEXT rContext) 1173{ 1174 if (rContext) 1175 { 1176 if (rContext->dwLockId && (rContext->dwLockId != lastLockID)) // otherwise too many messages 1177 { 1178 lastLockID = rContext->dwLockId; 1179 secdebug("pcscd", ".... ReaderContextLock state: %02X", rContext->dwLockId); 1180 } 1181 return (rContext->dwLockId == 0xFFFF)?1:0; 1182 } 1183 else 1184 return 0; 1185} 1186 1187#pragma mark ---------- Reader Context Management ---------- 1188 1189static int ReaderContextConstructor(PREADER_CONTEXT ctx, LPCSTR lpcReader, 1190 DWORD dwPort, LPCSTR lpcLibrary, LPCSTR lpcDevice) 1191{ 1192 // We assume the struct was created with a calloc, so we don't call ReaderContextClear 1193 if (!ctx) 1194 return SCARD_E_NO_MEMORY; 1195 1196 strlcpy(ctx->lpcLibrary, lpcLibrary, sizeof(ctx->lpcLibrary)); 1197 strlcpy(ctx->lpcDevice, lpcDevice, sizeof(ctx->lpcDevice)); 1198 ctx->dwPort = dwPort; 1199 1200 /* 1201 Initialize pdwFeeds to 1, otherwise multiple cloned readers will cause 1202 pcscd to crash when RFUnloadReader unloads the driver library 1203 and there are still devices attached using it 1204 */ 1205 ctx->pdwFeeds = malloc(sizeof(DWORD)); 1206 *ctx->pdwFeeds = 1; 1207 1208 ctx->mMutex = (PCSCLITE_MUTEX_T) malloc(sizeof(PCSCLITE_MUTEX)); 1209 SYS_MutexInit(ctx->mMutex); 1210 1211 ctx->pdwMutex = malloc(sizeof(DWORD)); 1212 *ctx->pdwMutex = 1; 1213 1214 return SCARD_S_SUCCESS; 1215} 1216 1217static int ReaderCheckForClone(PREADER_CONTEXT ctx, LPCSTR lpcReader, 1218 DWORD dwPort, LPCSTR lpcLibrary) 1219{ 1220 // Check and set the readername to see if it must be enumerated 1221 // A parentNode of -2 or less indicates fatal error 1222 1223 LONG parentNode = RFSetReaderName(ctx, lpcReader, lpcLibrary, dwPort, 0); 1224 if (parentNode < -1) 1225 return SCARD_E_NO_MEMORY; 1226 1227 // If a clone to this reader exists take some values from that clone 1228 if ((parentNode >= 0) && (parentNode < PCSCLITE_MAX_READERS_CONTEXTS) 1229 && sReadersContexts[parentNode]) 1230 { 1231 SYS_MutexLock(sReadersContextsLock); 1232 ctx->pdwFeeds = (sReadersContexts[parentNode])->pdwFeeds; 1233 *ctx->pdwFeeds += 1; 1234 ctx->vHandle = (sReadersContexts[parentNode])->vHandle; 1235 ctx->mMutex = (sReadersContexts[parentNode])->mMutex; 1236 ctx->pdwMutex = (sReadersContexts[parentNode])->pdwMutex; 1237 SYS_MutexUnLock(sReadersContextsLock); 1238 1239 if (0 && ReaderDriverIsThreadSafe(sReadersContexts[parentNode], 0)) 1240 { 1241 ctx->mMutex = 0; 1242 ctx->pdwMutex = NULL; 1243 } 1244 else 1245 *ctx->pdwMutex += 1; 1246 } 1247 1248 return SCARD_S_SUCCESS; 1249} 1250 1251static void ReaderContextDestructor(PREADER_CONTEXT ctx) 1252{ 1253 ReaderContextFree(ctx); 1254} 1255 1256static void ReaderContextFree(PREADER_CONTEXT ctx) 1257{ 1258 if (!ctx) 1259 return; 1260 1261 // Destroy and free the mutex 1262 if (ctx->pdwMutex) 1263 { 1264 if (*ctx->pdwMutex == 1) 1265 { 1266 SYS_MutexDestroy(ctx->mMutex); 1267 free(ctx->mMutex); 1268 } 1269 *ctx->pdwMutex -= 1; 1270 } 1271 1272 // Destroy and free the mutex counter 1273 if (ctx->pdwMutex && (*ctx->pdwMutex == 0)) 1274 { 1275 free(ctx->pdwMutex); 1276 ctx->pdwMutex = NULL; 1277 } 1278 1279 if (ctx->pdwFeeds) 1280 { 1281 *ctx->pdwFeeds -= 1; 1282 if (*ctx->pdwFeeds == 0) 1283 { 1284 free(ctx->pdwFeeds); 1285 ctx->pdwFeeds = NULL; 1286 } 1287 } 1288 1289 // zero out everything else 1290 ReaderContextClear(ctx); 1291} 1292 1293static void ReaderContextClear(PREADER_CONTEXT ctx) 1294{ 1295 // This assumes that ReaderContextFree has already been called if necessary 1296 if (ctx) 1297 memset(ctx, 0, sizeof(READER_CONTEXT)); 1298} 1299 1300static int ReaderContextInsert(PREADER_CONTEXT ctx) 1301{ 1302 // Find an empty slot to put the reader structure, and copy it in 1303 // If NULL is passed in, just return whether a spot is available or not 1304 1305 int ix, rv = SCARD_E_NO_MEMORY; 1306 1307 SYS_MutexLock(sReadersContextsLock); 1308 for (ix = 0; ix < PCSCLITE_MAX_READERS_CONTEXTS; ix++) 1309 { 1310 if ((sReadersContexts[ix] == NULL) || (sReadersContexts[ix])->vHandle == 0) 1311 { 1312 if (ctx) 1313 { 1314 if (sReadersContexts[ix]) 1315 free(sReadersContexts[ix]); 1316 sReadersContexts[ix] = ctx; 1317 (sReadersContexts[ix])->dwIdentity = (ix + 1) << (sizeof(DWORD) / 2) * 8; 1318 dwNumReadersContexts += 1; 1319 } 1320 rv = SCARD_S_SUCCESS; 1321 break; 1322 } 1323 } 1324 SYS_MutexUnLock(sReadersContextsLock); 1325 return rv; 1326} 1327 1328static int ReaderContextRemove(PREADER_CONTEXT ctx) 1329{ 1330 int ix, rv = SCARD_E_UNKNOWN_READER; 1331 PREADER_CONTEXT ctxToRemove = NULL; 1332 DWORD dwPort = ctx->dwPort; 1333 LPSTR lpcReader = ctx->lpcReader; 1334 SYS_MutexLock(sReadersContextsLock); 1335 for (ix = 0; ix < PCSCLITE_MAX_READERS_CONTEXTS; ix++) 1336 { 1337 if (!ReaderNameMatchForIndex(dwPort, lpcReader, ix)) 1338 continue; 1339 1340 ctxToRemove = sReadersContexts[ix]; 1341 sReadersContexts[ix] = NULL; 1342 dwNumReadersContexts -= 1; 1343 rv = SCARD_S_SUCCESS; 1344 break; 1345 } 1346 SYS_MutexUnLock(sReadersContextsLock); 1347 // We can do this cleanup outside the lock 1348 if (ctxToRemove) 1349 { 1350 ReaderContextDestructor(ctxToRemove); 1351 free(ctxToRemove); 1352 } 1353 return rv; 1354} 1355 1356static int ReaderContextCheckDuplicateReader(LPCSTR lpcReader, DWORD dwPort) 1357{ 1358 // Readers with the same name and same port cannot be used 1359 1360 if (dwNumReadersContexts == 0) 1361 return SCARD_S_SUCCESS; 1362 1363 int ix, rv = SCARD_S_SUCCESS; 1364 SYS_MutexLock(sReadersContextsLock); 1365 for (ix = 0; ix < PCSCLITE_MAX_READERS_CONTEXTS; ix++) 1366 { 1367 if ((sReadersContexts[ix]==NULL) || ((sReadersContexts[ix])->vHandle == 0)) 1368 continue; 1369 1370 if (ReaderNameMatchForIndex(dwPort, lpcReader, ix)) 1371 { 1372 Log1(PCSC_LOG_ERROR, "Duplicate reader found."); 1373 rv = SCARD_E_DUPLICATE_READER; 1374 break; 1375 } 1376 } 1377 SYS_MutexUnLock(sReadersContextsLock); 1378 return rv; 1379} 1380 1381static int ReaderSlotCount(PREADER_CONTEXT ctx) 1382{ 1383 // Call on the driver to see if there are multiple slots 1384 // If we encounter errors, pretend it is just a single slot reader 1385 1386 UCHAR ucGetData[1]; 1387 DWORD dwGetSize = sizeof(ucGetData); 1388 int rv = IFDGetCapabilities(ctx, TAG_IFD_SLOTS_NUMBER, &dwGetSize, ucGetData); 1389 1390 //Reader does not have this defined, so assume a single slot 1391 if (rv != IFD_SUCCESS || dwGetSize != 1 || ucGetData[0] == 0) 1392 return 1; 1393 1394 // Reader has this defined and it only has one slot 1395 if (rv == IFD_SUCCESS && dwGetSize == 1 && ucGetData[0] == 1) 1396 return 1; 1397 1398 return (int)ucGetData[0]; 1399} 1400 1401static BOOL ReaderDriverIsThreadSafe(PREADER_CONTEXT ctx, BOOL testSlot) 1402{ 1403 // Call on the driver to see if it is thread safe 1404 UCHAR ucThread[1]; 1405 DWORD dwGetSize = sizeof(ucThread); 1406 int rv = IFDGetCapabilities(ctx, testSlot?TAG_IFD_SLOT_THREAD_SAFE:TAG_IFD_THREAD_SAFE, 1407 &dwGetSize, ucThread); 1408 if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1) 1409 { 1410 Log1(PCSC_LOG_INFO, "Driver is thread safe"); 1411 return 1; 1412 } 1413 else 1414 { 1415 Log1(PCSC_LOG_INFO, "Driver is not thread safe"); 1416 return 0; 1417 } 1418} 1419 1420static BOOL ReaderNameMatchForIndex(DWORD dwPort, LPCSTR lpcReader, int index) 1421{ 1422 // "index" is index in sReadersContexts 1423 char lpcStripReader[MAX_READERNAME]; 1424 int tmplen; 1425 1426 if (sReadersContexts[index]==NULL) 1427 return 0; 1428 1429 strncpy(lpcStripReader, (sReadersContexts[index])->lpcReader, sizeof(lpcStripReader)); 1430 tmplen = strlen(lpcStripReader); 1431 lpcStripReader[tmplen - 6] = 0; 1432 1433 return ((strcmp(lpcReader, lpcStripReader) == 0) && (dwPort == (sReadersContexts[index])->dwPort))?1:0; 1434} 1435 1436static void ReaderContextDuplicateSlot(PREADER_CONTEXT ctxBase, PREADER_CONTEXT ctxSlot, int slotNumber, BOOL baseIsThreadSafe) 1437{ 1438 // Copy the previous reader name and set the slot number 1439 // The slot number for the base is 0 1440 1441 int ix; 1442 char *tmpReader = ctxSlot->lpcReader; 1443 strlcpy(tmpReader, ctxBase->lpcReader, sizeof(ctxSlot->lpcReader)); 1444 sprintf(tmpReader + strlen(tmpReader) - 2, "%02X", slotNumber); 1445 1446 strlcpy(ctxSlot->lpcLibrary, ctxBase->lpcLibrary, sizeof(ctxSlot->lpcLibrary)); 1447 strlcpy(ctxSlot->lpcDevice, ctxBase->lpcDevice, sizeof(ctxSlot->lpcDevice)); 1448 1449 ctxSlot->dwVersion = ctxBase->dwVersion; 1450 ctxSlot->dwPort = ctxBase->dwPort; 1451 ctxSlot->vHandle = ctxBase->vHandle; 1452 ctxSlot->mMutex = ctxBase->mMutex; 1453 ctxSlot->pdwMutex = ctxBase->pdwMutex; 1454 ctxSlot->dwSlot = ctxBase->dwSlot + slotNumber; 1455 1456 ctxSlot->pdwFeeds = ctxBase->pdwFeeds; 1457 1458 *ctxSlot->pdwFeeds += 1; 1459 1460 ctxSlot->dwBlockStatus = 0; 1461 ctxSlot->dwContexts = 0; 1462 ctxSlot->dwLockId = 0; 1463 ctxSlot->readerState = NULL; 1464 ctxSlot->dwIdentity = (slotNumber + 1) << (sizeof(DWORD) / 2) * 8; 1465 1466 for (ix = 0; ix < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; ix++) 1467 ctxSlot->psHandles[ix].hCard = 0; 1468 1469 if (!ctxSlot->pdwMutex) 1470 ctxSlot->pdwMutex = malloc(sizeof(DWORD)); 1471 if (baseIsThreadSafe) 1472 { 1473 ctxSlot->mMutex = malloc(sizeof(PCSCLITE_MUTEX)); 1474 SYS_MutexInit(ctxSlot->mMutex); 1475 *ctxSlot->pdwMutex = 1; 1476 } 1477 else 1478 *ctxSlot->pdwMutex += 1; 1479} 1480