PCSC那事儿(三十一--PCSCD)

 

 

  121

  122                                 if ((strcmp(lpcReader, lpcStripReader) == 0) &&

  123                                         (dwPort == (sReadersContexts[i])->dwPort))

  124                                 {

  125                                         Log1(PCSC_LOG_ERROR, "Duplicate reader found.");

  126                                         return SCARD_E_DUPLICATE_READER;

  127                                  }

  128                         }

  129                 }

  130         }

  131

121~127 行,表示如果读卡器名字相同,读卡器 port 也相同,则失败。

  132         /* We must find an empty slot to put the reader structure */

  133         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

  134         {

  135                 if ((sReadersContexts[i])->vHandle == 0)

  136                  {

  137                         dwContext = i;

  138                         break;

  139                 }

  140         }

  141

  142         if (i == PCSCLITE_MAX_READERS_CONTEXTS)

  143         {

  144                 /* No more spots left return */

  145                 return SCARD_E_NO_MEMORY;

  146         }

  147

132~147 行,寻找可用的读卡器上下文。没有找到也就是读卡器上下文数组都被占用,则失败。

 

  148         /* Check and set the readername to see if it must be enumerated */

  149         parentNode = RFSetReaderName(sReadersContexts[dwContext], lpcReader,

  150                 lpcLibrary, dwPort, 0);

  151          if (parentNode < -1)

  152                 return SCARD_E_NO_MEMORY;

 

RFSetReaderName 实现什么?

定义在 readerfactory.c 中,

实现如下:

  480 LONG RFSetReaderName(PREADER_CONTEXT rContext, LPSTR readerName,

  481         LPSTR libraryName, DWORD dwPort, DWORD dwSlot)

  482 {

  483         LONG parent = -1;       /* reader number of the parent of the clone */

  484         DWORD valueLength;

  485         int currentDigit = -1;

  486         int supportedChannels = 0;

  487         int usedDigits[PCSCLITE_MAX_READERS_CONTEXTS];

  488         int i;

  489

  490         /* Clear the list */

  491         for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

  492                 usedDigits[i] = FALSE;

492 行, usedDigits 做什么用?对于使用相同读卡器驱动库的读卡器进行编号 .

  493

  494         if ((0 == dwSlot) && (dwNumReadersContexts != 0))

  495         {

  496                 for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

  497                 {

  498                         if ((sReadersContexts[i])->vHandle != 0)

  499                         {

  500                                 if (strcmp((sReadersContexts[i])->lpcLibrary, libraryName) == 0)

  501                                 {

493~501 行开始用驱动库名字遍历读卡器上下文,

494 行, 0==dwSlot ,因为调用这个函数的唯一函数是 RFAddReader, RFAddReader 会处理多 slot 的情况。这里仅仅需要判断是否为 0

 

  502                                         UCHAR tagValue[1];

  503                                         LONG ret;

  504

  505                                         /* Ask the driver if it supports multiple channels */

  506                                         valueLength = sizeof(tagValue);

  507                                         ret = IFDGetCapabilities((sReadersContexts[i]),

  508                                                  TAG_IFD_SIMULTANEOUS_ACCESS,

  509                                                 &valueLength, tagValue);

  510

  511                                         if ((ret == IFD_SUCCESS) && (valueLength == 1) &&

  512                                                  (tagValue[0] > 1))

  513                                         {

  514                                                 supportedChannels = tagValue[0];

  515                                                 Log2(PCSC_LOG_INFO,

  516                                                          "Support %d simultaneous readers", tagValue[0]);

  517                                         }

  518                                         else

  519                                                 supportedChannels = 1;

 

507 行,查询驱动的能力,同一个驱动能否支持几个读卡器的并发访问。如果能支持,那么

最多能支持 supportedChannels 个使用相同驱动的读卡器。

 

  520

  521                                         /* Check to see if it is a hotplug reader and different */

  522                                         if (((((sReadersContexts[i])->dwPort & 0xFFFF0000) ==

  523                                                         PCSCLITE_HP_BASE_PORT)

  524                                                 && ((sReadersContexts[i])->dwPort != dwPort))

  525                                                  || (supportedChannels > 1))

  526                                         {

520~526 行,

#define PCSCLITE_HP_BASE_PORT               0x200000

522 行, sReadersContexts[i])->dwPort & 0xFFFF0000 ,则代表热插拔设备,只要 dwPort 不等,就可以找到 parent 来共享一些内部资源 .  supportedChannels > 1 ,主要用在非热插拔设备,只要驱动支持,也可以多个读卡器共用一些资源。

 

 

 

  527                                                  char *lpcReader = sReadersContexts[i]->lpcReader;

  528

  529                                                 /*

  530                                                  * tells the caller who the parent of this

  531                                                   * clone is so it can use it's shared

  532                                                  * resources like mutex/etc.

  533                                                  */

  534                                                 parent = i;

  535

  536                                                 /*

  537                                                  * If the same reader already exists and it is

  538                                                  * hotplug then we must look for others and

  539                                                  * enumerate the readername

  540                                                  */

  541                                                 currentDigit = strtol(lpcReader + strlen(lpcReader) - 5, N     ULL , 16);

  542

  543                                                 /* This spot is taken */

  544                                                 usedDigits[currentDigit] = TRUE;

  545                                         }

  546                                  }

  547                         }

  548                 }

  549         }

534 行,体现了享元模式,一会就能看到享了哪些内容。

541 行, currentDigit 记录目前使用相同驱动的读卡器号。

 

  550

  551         /* default value */

  552         i = 0;

  553

  554         /* Other identical readers exist on the same bus */

  555         if (currentDigit != -1)

  556         {

  557                  for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)

  558                 {

  559                         /* get the first free digit */

  560                         if (usedDigits[i] == FALSE)

  561                                 break;

  562                 }

  563

  564                 if (i == PCSCLITE_MAX_READERS_CONTEXTS)

  565                 {

  566                         Log2(PCSC_LOG_ERROR, "Max number of readers reached: %d", PCSCLITE_MAX_READERS_CON     TEXTS);

  567                          return -2;

  568                 }

  569

  570                 if (i >= supportedChannels)

  571                 {

  572                         Log3(PCSC_LOG_ERROR, "Driver %s does not support more than "

  573                                 "%d reader(s). Maybe the driver should support "

  574                                 "TAG_IFD_SIMULTANEOUS_ACCESS", libraryName, supportedChannels);

550~574 行,进行检查,一切都是为了得到相对使用同一个驱动的不同读卡器的唯一的读卡器号。即使使用相同驱动的每一个读卡器也各自占用一个 reader 上下文。

 

  579         snprintf(rContext->lpcReader, sizeof(rContext->lpcReader), "%s %02X %02lX",

  580                 readerName, i, dwSlot);

  581

  582         /* Set the slot in 0xDDDDCCCC */

  583         rContext->dwSlot = (i << 16) + dwSlot;

  584

  585         return parent;

  586 }

579 行,构造读卡器名字, 583 行可以知道 dwslot 的高 16 (31~16bit) ,放置读卡器编号。

 

回到 RFAddReader

  153

  154         (void)strlcpy((sReadersContexts[dwContext])->lpcLibrary, lpcLibrary,

  155                 sizeof((sReadersContexts[dwContext])->lpcLibrary));

  156         (void)strlcpy((sReadersContexts[dwContext])->lpcDevice, lpcDevice,

  157                 sizeof((sReadersContexts[dwContext])->lpcDevice));

  158         (sReadersContexts[dwContext])->dwVersion = 0;

  159         (sReadersContexts[dwContext])->dwPort = dwPort;

  160         (sReadersContexts[dwContext])->mMutex = NULL;

  161         (sReadersContexts[dwContext])->dwBlockStatus = 0;

  162         (sReadersContexts[dwContext])->dwContexts = 0;

  163         (sReadersContexts[dwContext])->pthThread = 0;

  164         (sReadersContexts[dwContext])->dwLockId = 0;

  165         (sReadersContexts[dwContext])->LockCount = 0;

  166         (sReadersContexts[dwContext])->vHandle = NULL;

  167         (sReadersContexts[dwContext])->pdwFeeds = NULL;

  168         (sReadersContexts[dwContext])->pdwMutex = NULL;

  169         (sReadersContexts[dwContext])->dwIdentity =

  170                 (dwContext + 1) << IDENTITY_SHIFT;

  171          (sReadersContexts[dwContext])->readerState = NULL;

  172

  173         for (i = 0; i < PCSCLITE_MAX_READER_CONTEXT_CHANNELS; i++)

  174                 (sReadersContexts[dwContext])->psHandles[i].hCard = 0;

  175

153~175 继续初始化。

176         /* If a clone to this reader exists take some values from that clone */

  177         if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS)

  178         {

  179                 (sReadersContexts[dwContext])->pdwFeeds =

  180                   (sReadersContexts[parentNode])->pdwFeeds;

  181                 *(sReadersContexts[dwContext])->pdwFeeds += 1;

  182                 (sReadersContexts[dwContext])->vHandle =

  183                   (sReadersContexts[parentNode])->vHandle;

  184                 (sReadersContexts[dwContext])->mMutex =

  185                   (sReadersContexts[parentNode])->mMutex;

  186                 (sReadersContexts[dwContext])->pdwMutex =

  187                   (sReadersContexts[parentNode])->pdwMutex;

  188

  189                  /* Call on the driver to see if it is thread safe */

  190                 dwGetSize = sizeof(ucThread);

  191                 rv = IFDGetCapabilities((sReadersContexts[parentNode]),

  192                         TAG_IFD_THREAD_SAFE, &dwGetSize, ucThread);

  193

  194                 if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1)

  195                 {

  196                         Log1(PCSC_LOG_INFO, "Driver is thread safe");

  197                         (sReadersContexts[dwContext])->mMutex = NULL;

  198                         (sReadersContexts[dwContext])->pdwMutex = NULL;

  199                 }

  200                 else

  201                         *(sReadersContexts[dwContext])->pdwMutex += 1;

  202         }

前面提到了享元,使用同一个驱动的读卡器可以共享一些内存。包括 pdwFeeds, vHandle, pdwMutex.

 

pdwFeeds 表示驱动库的共享计数。

pdwMutex 表示驱动库的锁共享计数。

190~199 行,如果驱动本身支持多线程,则 mMutex pdwMutex 就不需要了。这些多线程的事情就有驱动去做, APPLICATION 不再为此头痛。

 

  204         if ((sReadersContexts[dwContext])->pdwFeeds == NULL)

  205          {

  206                 (sReadersContexts[dwContext])->pdwFeeds = malloc(sizeof(DWORD));

  207

  208                 /* Initialize pdwFeeds to 1, otherwise multiple

  209                    cloned readers will cause pcscd to crash when

  210                     RFUnloadReader unloads the driver library

  211                    and there are still devices attached using it --mikeg*/

  212                 *(sReadersContexts[dwContext])->pdwFeeds = 1;

  213         }

  214

  215         if ((sReadersContexts[dwContext])->mMutex == 0)

  216         {

  217                 (sReadersContexts[dwContext])->mMutex =

  218                         malloc(sizeof(PCSCLITE_MUTEX));

  219                 (void)SYS_MutexInit((sReadersContexts[dwContext])->mMutex);

  220          }

  221

  222         if ((sReadersContexts[dwContext])->pdwMutex == NULL)

  223         {

  224                 (sReadersContexts[dwContext])->pdwMutex = malloc(sizeof(DWORD));

  225                 *(sReadersContexts[dwContext])->pdwMutex = 1;

  226         }

  227

  228         dwNumReadersContexts += 1;

 

204~228 行,还是要说说。记得上面 197~198 行吗?

这样对于系统中可共享驱动的读卡器,就多此一举了。 mMutex

pdwMutex 没有必要再初始化了。

228 行,已经使用读卡器上下文计数加 1.

真的这样吗?

实际上,不是这样的。在后面 RFUnloadReader 中,调用

RFRemoveReader 的时候,

423                 if ((NULL == sContext->pdwMutex) || (NULL == sContext->pdwFeeds))

这两个字段拿来判断该 reader 对应的上下文是否已经移除。还有,使用同一个驱动的所有

reader 上下文是否都移除了。

另外,可以进一步减小锁粒度,相同驱动的不同读卡器 ( ) 采用各自的锁。而不是同一个计数锁。增加并发访问的能力。

 

 

 

 

 

dwNumReadersContexts 表示正被使用的 reader 上下文计数。

  229         rv = RFInitializeReader(sReadersContexts[dwContext]);

  230         if (rv != SCARD_S_SUCCESS)

  231         {

  232                 /* Cannot connect to reader. Exit gracefully */

  233                 Log2(PCSC_LOG_ERROR, "%s init failed.", lpcReader);

  234                 (void)RFRemoveReader(lpcReader, dwPort);

  235                 return rv;

  236         }

230 行, RFInitializeReader 定义在 readerfactory.c

实现如下:

1019 LONG RFInitializeReader(PREADER_CONTEXT rContext)

1020 {

1021         LONG rv;

1022

1023         /* Spawn the event handler thread */

1024         Log3(PCSC_LOG_INFO, "Attempting startup of %s using %s",

1025                 rContext->lpcReader, rContext->lpcLibrary);

1026

1027         /* loads the library */

1028         rv = RFLoadReader(rContext);

1029         if (rv != SCARD_S_SUCCESS)

1030         {

1031                 Log2(PCSC_LOG_ERROR, "RFLoadReader failed: %X", rv);

1032                 return rv;

1033         }

1034

1035         /* binds the functions */

1036         rv = RFBindFunctions(rContext);

1037

1038         if (rv != SCARD_S_SUCCESS)

1039         {

1040                  Log2(PCSC_LOG_ERROR, "RFBindFunctions failed: %X", rv);

1041                 (void)RFUnloadReader(rContext);

1042                 return rv;

1043         }

1044

1045         /* tries to open the port */

1046         rv = IFDOpenIFD(rContext);

1047

1048         if (rv != IFD_SUCCESS)

1049         {

1050                 Log3(PCSC_LOG_CRITICAL, " Open Port %X Failed (%s)",

1051                         rContext->dwPort, rContext->lpcDevice);

1052                 (void)RFUnBindFunctions(rContext);

1053                 (void)RFUnloadReader(rContext);

1054                 if (IFD_NO_SUCH_DEVICE == rv)

1055                         return SCARD_E_UNKNOWN_READER;

1056                 else

1057                         return SCARD_E_INVALID_TARGET;

1058         }

1059

1060         return SCARD_S_SUCCESS;

1061 }

这么多行,其实主要的有 3 步。

RFLoadReader, RFBindFunctions, IFDOpenIFD

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值