PCSC那事儿(十八--SCardCancel)

 

SCardCancel

 

3495 LONG SCardCancel(SCARDCONTEXT hContext)

3496 {

3497         LONG dwContextIndex;

3498         LONG rv = SCARD_S_SUCCESS;

3499

3500         PROFILE_START

3501

3502         dwContextIndex = SCardGetContextIndice(hContext);

3503         if (dwContextIndex == -1)

3504                 return SCARD_E_INVALID_HANDLE;

3505

3506         /*

3507          * Set the block status for this Context so blocking calls will

3508          * complete

3509          */

3510         psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;

3511

3512         if (StatSynchronizeContext(hContext))

3513                 rv = SCARD_F_INTERNAL_ERROR;

3514

3515         PROFILE_END(rv)

3516

3517         return rv;

3518 }

 

 

 

 

SCardCancel 的作用,取消所有阻塞请求,当然了这些 SCard 前缀的函数里,只有

SCardGetStatusChange 是会发生阻塞的。

 

而在 SCardGetStatusChange 的实现里

有两处用到

2279                         if (BLOCK_STATUS_RESUME

2280                                 == psContextMap[dwContextIndex].contextBlockStatus)

2281                                 break;

2301          if (psContextMap[dwContextIndex].contextBlockStatus == BLOCK_STATUS_RESUME)

2302                  rv = SCARD_E_CANCELLED;

 

 

也就是无条件跳出上面提到的 while(1) 循环体。从而实现取消阻塞请求。

前面提到的

3585 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)

 

 

 

实现中也就是上下文初始化过程

3595                         psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;

 

 

 

原来应用上下文初始化状态的上下文阻塞状态初始化为 BLOCK_STATUS_RESUME

根据搜索, readerfactory.c 也有一处,用到 BLOCK_STATUS_RESUME

 

1013 LONG RFUnblockReader(PREADER_CONTEXT rContext)

1014 {

1015          rContext->dwBlockStatus = BLOCK_STATUS_RESUME;

1016         return SCARD_S_SUCCESS;

1017 }

 

 

从函数名称上看,绝对也是用于取消阻塞的。

这是函数属于服务端,而且服务端实际上正如它自己注释的,目前没有用到这个函数。

 

 

 

BLOCK_STATUS_BLOCKING 用到的地发有

 

SCardGetStatusChange 的实现中

1988         psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_BLOCKING;

 

 

 

1988 行后开始上面提到的 readerStates currReader 的比对。

而后面的不断探测设备事件的循环体中,如果 contextBlockStatus 变为

BLOCK_STATUS_RESUME ( 调用 SCardCancel ) ,则退出循环体。

 

SCardGetStatusChange 覆盖 1872~2312 行。

实现部分有些过长的。结束了。

 

往事不要再提,人生几多风雨 ...”

 

可是目前,还要回去,回到 testpcsc.c

 

146         if (SCARD_E_NO_READERS_AVAILABLE == rv)

147         {

148                 printf("Testing SCardGetStatusChange /n");

149                 printf("Please insert a working reader/t: ");

150                 (void)fflush(stdout);

151                 rgReaderStates[0].szReader = "?PnP?//Notification";

152                 rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

153

154                 rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);

155                  test_rv(rv, hContext, PANIC);

156          }

 

 

明白了吧,很清楚了吧。

154                 rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);

 

 

永久等待,直到有读卡器事件出现。

I'm here for you.

 

接下来

 

157

158         printf("Testing SCardListReaders/t: ");

159 #ifdef USE_AUTOALLOCATE

160         dwReaders = SCARD_AUTOALLOCATE;

161         rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders);

162 #else

163         rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders);

164         test_rv(rv, hContext, PANIC);

 

165

166         printf("Testing SCardListReaders/t: ");

167         mszReaders = calloc(dwReaders, sizeof(char));

168         rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);

169 #endif

170         test_rv(rv, hContext, DONT_PANIC);

171

172         /*

173           * Have to understand the multi-string here

174          */

175         p = 0;

176         for (i = 0; i+1 < dwReaders; i++)

177         {

178                 ++p;

179                 printf(GREEN "Reader %02d: %s/n" NORMAL , p, &mszReaders[i]);

180                  iList[p] = i;

181                 while (mszReaders[++i] != 0) ;

182          }

 

 

 

161 行,解释过了。

163 行,解释过了。

因为能过到 157 行的就是等到了读卡器事件。

175~182 行,打印出来到的读卡器的名称。

 

184         if (p > 1)

185                 do

186                 {

187                         char input[80];

188

189                         printf("Enter the reader number/t/t: ");

190                          (void)fgets(input, sizeof(input), stdin);

191                         (void)sscanf(input, "%d", &iReader);

192

193                         if (iReader > p || iReader <= 0)

194                                 printf("Invalid Value - try again/n");

195                 }

196                 while (iReader > p || iReader <= 0);

197         else

198                  iReader = 1;

 

 

 

 

184~198 行,说明如果事件过后,来了 n 个读卡器,当然 n 必须大于等于1 .

如果 n 大于1,那么 testpcsc.c 也不知道怎么办。上报 APPLICATION ,让

APPLICATION 做出选择,挑选需要的读卡器。

如果 n 等于,那么只有一个读卡器来到,就是它了,不用选择了。

 

199

200         rgReaderStates[0].szReader = &mszReaders[iList[iReader]];

201         rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;

202

203         printf("Waiting for card insertion/t: ");

204         (void)fflush(stdout);

205         rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);

206         test_rv(rv, hContext, PANIC);

207         if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN)

208         {

209                 printf("/nA reader has been connected/disconnected/n");

210                 goto wait_for_card_again;

211          }

 

 

 

 

正如 209 行所提示,有可能读卡器来后又走了。

如果读卡器没有拔出,而且读卡器内已经插入卡,则

 

212

213         printf("Testing SCardConnect/t/t: ");

214         rv = SCardConnect(hContext, &mszReaders[iList[iReader]],

215                 SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,

216                  &hCard, &dwPref);

217          test_rv(rv, hContext, PANIC);

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值