Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

906 lines
28 KiB

  1. /*++
  2. Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
  3. Module Name:
  4. PscrCB.c
  5. Abstract:
  6. callback handler for PSCR.xxx driver
  7. Author:
  8. Andreas Straub
  9. Environment:
  10. Win 95 Sys... calls are resolved by Pscr95Wrap.asm functions and
  11. Pscr95Wrap.h macros, resp.
  12. NT 4.0 Sys... functions resolved by PscrNTWrap.c functions and
  13. PscrNTWrap.h macros, resp.
  14. Revision History:
  15. Andreas Straub 8/18/1997 1.00 Initial Version
  16. Andreas Straub 9/24/1997 1.02 Flush Interface if card tracking
  17. requested
  18. --*/
  19. #if defined( SMCLIB_VXD )
  20. #include <Pscr95.h>
  21. #else // SMCLIB_VXD
  22. #include <PscrNT.h>
  23. #endif // SMCLIB_VXD
  24. #include <PscrRdWr.h>
  25. #include <PscrCmd.h>
  26. #include <PscrCB.h>
  27. NTSTATUS
  28. CBCardPower(
  29. PSMARTCARD_EXTENSION SmartcardExtension
  30. )
  31. /*++
  32. CBCardPower:
  33. callback handler for SMCLIB RDF_CARD_POWER
  34. Arguments:
  35. SmartcardExtension context of call
  36. Return Value:
  37. STATUS_SUCCESS
  38. STATUS_NO_MEDIA
  39. STATUS_TIMEOUT
  40. STATUS_BUFFER_TOO_SMALL
  41. --*/
  42. {
  43. NTSTATUS NTStatus = STATUS_SUCCESS;
  44. UCHAR ATRBuffer[ ATR_SIZE ], TLVList[16];
  45. ULONG Command,
  46. ATRLength;
  47. PREADER_EXTENSION ReaderExtension;
  48. BYTE CardState;
  49. #if DBG || DEBUG
  50. static PCHAR request[] = { "PowerDown", "ColdReset", "WarmReset" };
  51. #endif
  52. SmartcardDebug(
  53. DEBUG_TRACE,
  54. ( "PSCR!CBCardPower: Enter, Request = %s\n",
  55. request[SmartcardExtension->MinorIoControlCode])
  56. );
  57. ReaderExtension = SmartcardExtension->ReaderExtension;
  58. //
  59. // update actual power state
  60. //
  61. Command = SmartcardExtension->MinorIoControlCode;
  62. switch ( Command )
  63. {
  64. case SCARD_WARM_RESET:
  65. // if the card was not powerd, fall thru to cold reset
  66. if( SmartcardExtension->ReaderCapabilities.CurrentState >
  67. SCARD_SWALLOWED )
  68. {
  69. // reset the card
  70. ATRLength = ATR_SIZE;
  71. NTStatus = CmdReset(
  72. ReaderExtension,
  73. ReaderExtension->Device,
  74. TRUE, // warm reset
  75. ATRBuffer,
  76. &ATRLength
  77. );
  78. break;
  79. }
  80. // warm reset not possible because card was not powerd
  81. case SCARD_COLD_RESET:
  82. // reset the card
  83. ATRLength = ATR_SIZE;
  84. NTStatus = CmdReset(
  85. ReaderExtension,
  86. ReaderExtension->Device,
  87. FALSE, // cold reset
  88. ATRBuffer,
  89. &ATRLength
  90. );
  91. break;
  92. case SCARD_POWER_DOWN:
  93. ATRLength = 0;
  94. NTStatus = CmdDeactivate(
  95. ReaderExtension,
  96. ReaderExtension->Device
  97. );
  98. // discard old card status
  99. CardState = CBGetCardState(SmartcardExtension);
  100. CBUpdateCardState(SmartcardExtension, CardState, FALSE);
  101. break;
  102. }
  103. if (NT_SUCCESS(NTStatus)) {
  104. //
  105. // Set the 'restart of work waiting time' counter for T=0
  106. // This will send a WTX request for n NULL bytes received
  107. //
  108. TLVList[0] = TAG_SET_NULL_BYTES;
  109. TLVList[1] = 1;
  110. TLVList[2] = 0x05;
  111. NTStatus = CmdSetInterfaceParameter(
  112. ReaderExtension,
  113. DEVICE_READER,
  114. TLVList,
  115. 3
  116. );
  117. }
  118. ASSERT(NT_SUCCESS(NTStatus));
  119. // finish the request
  120. if( NT_SUCCESS( NTStatus ))
  121. {
  122. // update all neccessary data if an ATR was received
  123. if( ATRLength > 2 )
  124. {
  125. //
  126. // the lib expects only the ATR, so we skip the
  127. // 900x from the reader
  128. //
  129. ATRLength -= 2;
  130. // copy ATR to user buffer buffer
  131. if( ATRLength <= SmartcardExtension->IoRequest.ReplyBufferLength )
  132. {
  133. SysCopyMemory(
  134. SmartcardExtension->IoRequest.ReplyBuffer,
  135. ATRBuffer,
  136. ATRLength
  137. );
  138. *SmartcardExtension->IoRequest.Information = ATRLength;
  139. }
  140. else
  141. {
  142. NTStatus = STATUS_BUFFER_TOO_SMALL;
  143. }
  144. // copy ATR to card capability buffer
  145. if( ATRLength <= MAXIMUM_ATR_LENGTH )
  146. {
  147. SysCopyMemory(
  148. SmartcardExtension->CardCapabilities.ATR.Buffer,
  149. ATRBuffer,
  150. ATRLength
  151. );
  152. SmartcardExtension->CardCapabilities.ATR.Length =
  153. ( UCHAR )ATRLength;
  154. // let the lib update the card capabilities
  155. NTStatus = SmartcardUpdateCardCapabilities(
  156. SmartcardExtension
  157. );
  158. }
  159. else
  160. {
  161. NTStatus = STATUS_BUFFER_TOO_SMALL;
  162. }
  163. }
  164. }
  165. if( !NT_SUCCESS( NTStatus ))
  166. {
  167. switch( NTStatus )
  168. {
  169. case STATUS_NO_MEDIA:
  170. case STATUS_BUFFER_TOO_SMALL:
  171. break;
  172. case STATUS_TIMEOUT:
  173. NTStatus = STATUS_IO_TIMEOUT;
  174. break;
  175. default:
  176. NTStatus = STATUS_UNRECOGNIZED_MEDIA;
  177. break;
  178. }
  179. }
  180. SmartcardDebug(
  181. DEBUG_TRACE,
  182. ( "PSCR!CBCardPower: Exit (%lx)\n", NTStatus )
  183. );
  184. return( NTStatus );
  185. }
  186. NTSTATUS
  187. CBSetProtocol(
  188. PSMARTCARD_EXTENSION SmartcardExtension
  189. )
  190. /*++
  191. CBSetProtocol:
  192. callback handler for SMCLIB RDF_SET_PROTOCOL
  193. Arguments:
  194. SmartcardExtension context of call
  195. Return Value:
  196. STATUS_SUCCESS
  197. STATUS_NO_MEDIA
  198. STATUS_TIMEOUT
  199. STATUS_BUFFER_TOO_SMALL
  200. STATUS_INVALID_DEVICE_STATE
  201. STATUS_INVALID_DEVICE_REQUEST
  202. --*/
  203. {
  204. NTSTATUS NTStatus = STATUS_PENDING;
  205. USHORT SCLibProtocol;
  206. UCHAR TLVList[ TLV_BUFFER_SIZE ];
  207. PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
  208. if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC) {
  209. return STATUS_SUCCESS;
  210. }
  211. SmartcardDebug(
  212. DEBUG_TRACE,
  213. ( "PSCR!CBSetProtocol: Enter\n" )
  214. );
  215. SCLibProtocol = ( USHORT )( SmartcardExtension->MinorIoControlCode );
  216. if (SCLibProtocol & (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1))
  217. {
  218. //
  219. // setup the TLV list for the Set Interface Parameter List
  220. //
  221. TLVList[ 0 ] = TAG_ICC_PROTOCOLS;
  222. TLVList[ 1 ] = 0x01;
  223. TLVList[ 2 ] =
  224. (SCLibProtocol & SCARD_PROTOCOL_T1 ? PSCR_PROTOCOL_T1 : PSCR_PROTOCOL_T0);
  225. // do the PTS
  226. NTStatus = CmdSetInterfaceParameter(
  227. ReaderExtension,
  228. ReaderExtension->Device,
  229. TLVList,
  230. 3 // size of list
  231. );
  232. } else {
  233. // we don't support other modi
  234. NTStatus = STATUS_INVALID_DEVICE_REQUEST;
  235. }
  236. // if protocol selection failed, prevent from calling invalid protocols
  237. if( NT_SUCCESS( NTStatus ))
  238. {
  239. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
  240. SCLibProtocol = (SCLibProtocol & SCARD_PROTOCOL_T1 &
  241. SmartcardExtension->CardCapabilities.Protocol.Supported) ?
  242. SCARD_PROTOCOL_T1 :
  243. SCARD_PROTOCOL_T0;
  244. }
  245. else
  246. {
  247. SCLibProtocol = SCARD_PROTOCOL_UNDEFINED;
  248. }
  249. // Return the selected protocol to the caller.
  250. SmartcardExtension->CardCapabilities.Protocol.Selected = SCLibProtocol;
  251. *( PULONG )( SmartcardExtension->IoRequest.ReplyBuffer ) = SCLibProtocol;
  252. *( SmartcardExtension->IoRequest.Information ) = sizeof( ULONG );
  253. SmartcardDebug(
  254. DEBUG_TRACE,
  255. ( "PSCR!CBSetProtocol: Exit (%lx)\n", NTStatus )
  256. );
  257. return ( NTStatus );
  258. }
  259. NTSTATUS
  260. CBTransmit(
  261. PSMARTCARD_EXTENSION SmartcardExtension
  262. )
  263. /*++
  264. CBTransmit:
  265. callback handler for SMCLIB RDF_TRANSMIT
  266. Arguments:
  267. SmartcardExtension context of call
  268. Return Value:
  269. STATUS_SUCCESS
  270. STATUS_NO_MEDIA
  271. STATUS_TIMEOUT
  272. STATUS_INVALID_DEVICE_REQUEST
  273. --*/
  274. {
  275. NTSTATUS NTStatus = STATUS_SUCCESS;
  276. SmartcardDebug(
  277. DEBUG_TRACE,
  278. ( "PSCR!CBTransmit: Enter\n" )
  279. );
  280. // dispatch on the selected protocol
  281. switch( SmartcardExtension->CardCapabilities.Protocol.Selected )
  282. {
  283. case SCARD_PROTOCOL_T0:
  284. NTStatus = CBT0Transmit( SmartcardExtension );
  285. break;
  286. case SCARD_PROTOCOL_T1:
  287. NTStatus = CBT1Transmit( SmartcardExtension );
  288. break;
  289. case SCARD_PROTOCOL_RAW:
  290. NTStatus = CBRawTransmit( SmartcardExtension );
  291. break;
  292. default:
  293. NTStatus = STATUS_INVALID_DEVICE_REQUEST;
  294. break;
  295. }
  296. SmartcardDebug(
  297. DEBUG_TRACE,
  298. ( "PSCR!CBTransmit: Exit (%lx)\n", NTStatus )
  299. );
  300. return( NTStatus );
  301. }
  302. NTSTATUS
  303. CBRawTransmit(
  304. PSMARTCARD_EXTENSION SmartcardExtension
  305. )
  306. /*++
  307. CBRawTransmit:
  308. finishes the callback RDF_TRANSMIT for the RAW protocol
  309. Arguments:
  310. SmartcardExtension context of call
  311. Return Value:
  312. STATUS_SUCCESS
  313. STATUS_NO_MEDIA
  314. STATUS_TIMEOUT
  315. STATUS_INVALID_DEVICE_REQUEST
  316. --*/
  317. {
  318. NTSTATUS NTStatus = STATUS_SUCCESS;
  319. UCHAR TLVList[ TLV_BUFFER_SIZE ],
  320. Val,
  321. Len;
  322. ULONG TLVListLen;
  323. PREADER_EXTENSION ReaderExtension;
  324. SmartcardDebug(
  325. DEBUG_TRACE,
  326. ( "PSCR!CBRawTransmit: Enter\n" )
  327. );
  328. ReaderExtension = SmartcardExtension->ReaderExtension;
  329. //
  330. // read the status file of ICC1 from the reader
  331. //
  332. TLVListLen = TLV_BUFFER_SIZE;
  333. NTStatus = CmdReadStatusFile(
  334. ReaderExtension,
  335. ReaderExtension->Device,
  336. TLVList,
  337. &TLVListLen
  338. );
  339. //
  340. // check the active protocol of the reader
  341. //
  342. if( NT_SUCCESS( NTStatus ))
  343. {
  344. NTStatus = CmdGetTagValue(
  345. TAG_ICC_PROTOCOLS,
  346. TLVList,
  347. TLVListLen,
  348. &Len,
  349. ( PVOID ) &Val
  350. );
  351. // execute the active protocol
  352. if( NT_SUCCESS( NTStatus ))
  353. {
  354. // translate the actual protocol to a value the lib can understand
  355. switch( Val )
  356. {
  357. case PSCR_PROTOCOL_T0:
  358. NTStatus = CBT0Transmit( SmartcardExtension );
  359. break;
  360. case PSCR_PROTOCOL_T1:
  361. NTStatus = CBT1Transmit( SmartcardExtension );
  362. break;
  363. default:
  364. NTStatus = STATUS_UNSUCCESSFUL;
  365. break;
  366. }
  367. }
  368. }
  369. SmartcardDebug(
  370. DEBUG_TRACE,
  371. ( "PSCR!CBRawTransmit: Exit (%lx)\n", NTStatus )
  372. );
  373. return ( NTStatus );
  374. }
  375. NTSTATUS
  376. CBT1Transmit(
  377. PSMARTCARD_EXTENSION SmartcardExtension
  378. )
  379. /*++
  380. CBT1Transmit:
  381. finishes the callback RDF_TRANSMIT for the T1 protocol
  382. Arguments:
  383. SmartcardExtension context of call
  384. Return Value:
  385. STATUS_SUCCESS
  386. STATUS_NO_MEDIA
  387. STATUS_TIMEOUT
  388. STATUS_INVALID_DEVICE_REQUEST
  389. --*/
  390. {
  391. NTSTATUS NTStatus = STATUS_SUCCESS;
  392. ULONG IOBytes;
  393. SmartcardDebug(
  394. DEBUG_TRACE,
  395. ( "PSCR!CBT1Transmit: Enter\n" )
  396. );
  397. //
  398. // use the lib support to construct the T=1 packets
  399. //
  400. do {
  401. //
  402. // no header for the T=1 protocol
  403. //
  404. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  405. //
  406. // SCM-TM: Siemens 4440 accepts only NAD=0!!!
  407. //
  408. SmartcardExtension->T1.NAD = 0;
  409. //
  410. // let the lib setup the T=1 APDU & check for errors
  411. //
  412. NTStatus = SmartcardT1Request( SmartcardExtension );
  413. if( NT_SUCCESS( NTStatus ))
  414. {
  415. // send command (don't calculate LRC because CRC may be used!)
  416. IOBytes = 0;
  417. NTStatus = PscrWriteDirect(
  418. SmartcardExtension->ReaderExtension,
  419. SmartcardExtension->SmartcardRequest.Buffer,
  420. SmartcardExtension->SmartcardRequest.BufferLength,
  421. &IOBytes
  422. );
  423. //
  424. // extend the timeout if a Wtx request was sent by the card. if the
  425. // card responds before the waiting time extension expires, the data are
  426. // buffered in the reader. A delay without polling the reader status
  427. // slows down the performance of the driver, but wtx is an exeption,
  428. // not the rule.
  429. //
  430. if (SmartcardExtension->T1.Wtx)
  431. {
  432. SysDelay(
  433. (( SmartcardExtension->T1.Wtx *
  434. SmartcardExtension->CardCapabilities.T1.BWT + 999L )/
  435. 1000L)
  436. );
  437. }
  438. // get response
  439. SmartcardExtension->SmartcardReply.BufferLength = 0;
  440. NTStatus = PscrRead(
  441. SmartcardExtension->ReaderExtension,
  442. SmartcardExtension->SmartcardReply.Buffer,
  443. MAX_T1_BLOCK_SIZE,
  444. &SmartcardExtension->SmartcardReply.BufferLength
  445. );
  446. // if PscrRead detects an LRC error, ignore it (maybe CRC used)
  447. if( NTStatus == STATUS_CRC_ERROR )
  448. {
  449. NTStatus = STATUS_SUCCESS;
  450. }
  451. //
  452. // We even continue if the prev. read failed.
  453. // We let the smart card library continue, because it might
  454. // send a resynch. request in case of a timeout
  455. //
  456. NTStatus = SmartcardT1Reply( SmartcardExtension );
  457. }
  458. // continue if the lib wants to send the next packet
  459. } while( NTStatus == STATUS_MORE_PROCESSING_REQUIRED );
  460. SmartcardDebug(
  461. DEBUG_TRACE,
  462. ( "PSCR!CBT1Transmit: Exit (%lx)\n", NTStatus )
  463. );
  464. return ( NTStatus );
  465. }
  466. NTSTATUS
  467. CBT0Transmit(
  468. PSMARTCARD_EXTENSION SmartcardExtension
  469. )
  470. /*++
  471. CBT0Transmit:
  472. finishes the callback RDF_TRANSMIT for the T0 protocol
  473. Arguments:
  474. SmartcardExtension context of call
  475. Return Value:
  476. STATUS_SUCCESS
  477. STATUS_NO_MEDIA
  478. STATUS_TIMEOUT
  479. STATUS_INVALID_DEVICE_REQUEST
  480. --*/
  481. {
  482. NTSTATUS NTStatus = STATUS_SUCCESS;
  483. PUCHAR pRequest,pReply;
  484. ULONG IOBytes, APDULength, RequestLength;
  485. UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
  486. UCHAR WtxReply[16];
  487. SmartcardDebug(
  488. DEBUG_TRACE,
  489. ( "PSCR!CBT0Transmit: Enter\n" )
  490. );
  491. pRequest = SmartcardExtension->SmartcardRequest.Buffer;
  492. pReply = SmartcardExtension->SmartcardReply.Buffer;
  493. // setup the command header
  494. pRequest[ PSCR_NAD ] =
  495. ( SmartcardExtension->ReaderExtension->Device == DEVICE_ICC1 ) ?
  496. NAD_TO_ICC1 : NAD_TO_ICC1;
  497. pRequest[ PSCR_PCB ] = PCB_DEFAULT;
  498. //
  499. // get the length of the user data packet & set the appropriate LEN
  500. // information the complete user packet consists of a SCARD_IO_REQUEST
  501. // structure followed by the APDU. the length of SCARD_IO_REQUEST is
  502. // transferred in the member cbPciLength of the structure
  503. //
  504. APDULength = SmartcardExtension->IoRequest.RequestBufferLength;
  505. APDULength -= ((PSCARD_IO_REQUEST) SmartcardExtension->
  506. IoRequest.RequestBuffer)->cbPciLength;
  507. //
  508. // a 4 byte APDU will be patched to a 5 byte TPDU by the lib; see
  509. // annex of the ISO
  510. //
  511. if( APDULength == 4 ) APDULength++;
  512. //
  513. // if the total length of the T1 (reader) packet is larger than 0xFF
  514. // the extended length notation will be used
  515. //
  516. if( APDULength >= 0xFF )
  517. {
  518. pRequest[ PSCR_LEN ] = 0xFF;
  519. pRequest[ PSCR_LEN+1 ] = HIBYTE( APDULength );
  520. pRequest[ PSCR_LEN+2 ] = LOBYTE( APDULength );
  521. SmartcardExtension->SmartcardRequest.BufferLength =
  522. PSCR_EXT_PROLOGUE_LENGTH;
  523. }
  524. else
  525. {
  526. pRequest[ PSCR_LEN ] = ( UCHAR ) APDULength;
  527. SmartcardExtension->SmartcardRequest.BufferLength =
  528. PSCR_PROLOGUE_LENGTH;
  529. }
  530. // let the lib setup the T=1 APDU & check for errors
  531. NTStatus = SmartcardT0Request( SmartcardExtension );
  532. RequestLength = SmartcardExtension->SmartcardRequest.BufferLength;
  533. while( NT_SUCCESS( NTStatus ))
  534. {
  535. // send command
  536. IOBytes = 0;
  537. NTStatus = PscrWrite(
  538. SmartcardExtension->ReaderExtension,
  539. pRequest,
  540. RequestLength,
  541. &IOBytes
  542. );
  543. // get response
  544. if( NT_SUCCESS( NTStatus ))
  545. {
  546. IOBytes = 0;
  547. NTStatus = PscrRead(
  548. SmartcardExtension->ReaderExtension,
  549. IOData,
  550. MAX_T1_BLOCK_SIZE,
  551. &IOBytes
  552. );
  553. // extract APDU from T=1 transport packet
  554. if( NT_SUCCESS( NTStatus ))
  555. {
  556. if (IOData[ PSCR_PCB ] == WTX_REQUEST) {
  557. WtxReply[PSCR_NAD] = NAD_TO_PSCR;
  558. WtxReply[PSCR_PCB] = WTX_REPLY;
  559. WtxReply[PSCR_LEN] = 1;
  560. WtxReply[PSCR_INF] = IOData[PSCR_INF];
  561. RequestLength = 4;
  562. pRequest = WtxReply;
  563. continue;
  564. }
  565. if( IOData[ PSCR_LEN ] == 0xFF )
  566. {
  567. //
  568. // extended length byte used
  569. //
  570. APDULength = IOData[ PSCR_LEN + 1 ] << 8;
  571. APDULength += IOData[ PSCR_LEN + 2 ];
  572. SmartcardExtension->SmartcardReply.BufferLength = APDULength ;
  573. SysCopyMemory( pReply, &IOData[ PSCR_APDU + 2 ], APDULength );
  574. }
  575. else
  576. {
  577. SmartcardExtension->SmartcardReply.BufferLength =
  578. IOData[ PSCR_LEN ];
  579. SysCopyMemory(
  580. pReply,
  581. &IOData[ PSCR_APDU ],
  582. IOData[ PSCR_LEN ]
  583. );
  584. }
  585. // let the lib evaluate the result & tansfer the data
  586. NTStatus = SmartcardT0Reply( SmartcardExtension );
  587. break;
  588. }
  589. }
  590. }
  591. SmartcardDebug(
  592. DEBUG_TRACE,
  593. ( "PSCR!CBT0Transmit: Exit (%lx)\n", NTStatus )
  594. );
  595. return( NTStatus );
  596. }
  597. NTSTATUS
  598. CBCardTracking(
  599. PSMARTCARD_EXTENSION SmartcardExtension
  600. )
  601. /*++
  602. CBCardTracking:
  603. callback handler for SMCLIB RDF_CARD_TRACKING. the requested event was
  604. validated by the smclib (i.e. a card removal request will only be passed
  605. if a card is present).
  606. for a win95 build STATUS_PENDING will be returned without any other action.
  607. for NT the cancel routine for the irp will be set to the drivers cancel
  608. routine.
  609. Arguments:
  610. SmartcardExtension context of call
  611. Return Value:
  612. STATUS_PENDING
  613. --*/
  614. {
  615. KIRQL CancelIrql;
  616. SmartcardDebug(
  617. DEBUG_TRACE,
  618. ( "PSCR!CBCardTracking: Enter\n" )
  619. );
  620. // set cancel routine
  621. IoAcquireCancelSpinLock( &CancelIrql );
  622. IoSetCancelRoutine(
  623. SmartcardExtension->OsData->NotificationIrp,
  624. PscrCancel
  625. );
  626. IoReleaseCancelSpinLock( CancelIrql );
  627. SmartcardDebug(
  628. DEBUG_TRACE,
  629. ( "PSCR!CBCardTracking: Exit \n" )
  630. );
  631. return( STATUS_PENDING );
  632. }
  633. VOID
  634. CBUpdateCardState(
  635. PSMARTCARD_EXTENSION SmartcardExtension,
  636. UCHAR IccState,
  637. BOOLEAN SystemWakeUp
  638. )
  639. {
  640. ULONG oldState;
  641. KIRQL currentIrql, irql;
  642. KeAcquireSpinLock(
  643. &SmartcardExtension->OsData->SpinLock,
  644. &irql
  645. );
  646. SmartcardDebug(
  647. DEBUG_TRACE,
  648. ( "PSCR!CBUpdateCardState: Enter \n" )
  649. );
  650. oldState =
  651. (SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT ?
  652. SCARD_PRESENT : SCARD_ABSENT);
  653. SmartcardExtension->ReaderCapabilities.CurrentState =
  654. (IccState == PSCR_ICC_PRESENT ? SCARD_PRESENT : SCARD_ABSENT);
  655. SmartcardDebug(
  656. DEBUG_DRIVER,
  657. ( "PSCR!CBUpdateCardState: Smart card %s\n",
  658. IccState == PSCR_ICC_PRESENT ? "inserted" : "removed")
  659. );
  660. IoAcquireCancelSpinLock( &currentIrql );
  661. if( SmartcardExtension->OsData->NotificationIrp != NULL && (
  662. SystemWakeUp && (
  663. oldState == SCARD_PRESENT ||
  664. SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_PRESENT) ||
  665. SmartcardExtension->ReaderCapabilities.CurrentState != oldState)) {
  666. PIRP notificationIrp = InterlockedExchangePointer(
  667. &(SmartcardExtension->OsData->NotificationIrp),
  668. NULL
  669. );
  670. IoSetCancelRoutine(
  671. notificationIrp,
  672. NULL
  673. );
  674. IoReleaseCancelSpinLock( currentIrql );
  675. if (notificationIrp->Cancel == FALSE) {
  676. // finish the request
  677. notificationIrp->IoStatus.Status = STATUS_SUCCESS;
  678. notificationIrp->IoStatus.Information = 0;
  679. SmartcardDebug(
  680. DEBUG_DRIVER,
  681. ( "PSCR!CBUpdateCardState: Completing Irp %lx\n",
  682. notificationIrp)
  683. );
  684. IoCompleteRequest(notificationIrp, IO_NO_INCREMENT );
  685. }
  686. } else {
  687. IoReleaseCancelSpinLock( currentIrql );
  688. }
  689. SmartcardDebug(
  690. DEBUG_TRACE,
  691. ( "PSCR!CBUpdateCardState: Exit \n" )
  692. );
  693. KeReleaseSpinLock(
  694. &SmartcardExtension->OsData->SpinLock,
  695. irql
  696. );
  697. }
  698. UCHAR
  699. CBGetCardState(
  700. PSMARTCARD_EXTENSION SmartcardExtension
  701. )
  702. /*++
  703. CBUpdateCardState:
  704. updates the variable CurrentState in SmartcardExtension
  705. Arguments:
  706. SmartcardExtension context of call
  707. Return Value:
  708. STATUS_SUCCESS
  709. --*/
  710. {
  711. NTSTATUS NTStatus = STATUS_SUCCESS;
  712. UCHAR TLVList[ TLV_BUFFER_SIZE ], Val, Len;
  713. ULONG TLVListLen;
  714. PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
  715. // read the status file of ICC1 from the reader
  716. TLVListLen = TLV_BUFFER_SIZE;
  717. if( NT_SUCCESS( CmdReadStatusFile(
  718. ReaderExtension,
  719. ReaderExtension->Device,
  720. TLVList,
  721. &TLVListLen
  722. ))) {
  723. // get reader status value
  724. CmdGetTagValue(
  725. TAG_READER_STATUS,
  726. TLVList,
  727. TLVListLen,
  728. &Len,
  729. ( PVOID ) &Val
  730. );
  731. }
  732. else
  733. {
  734. // IO-error is interpreted as card absent
  735. Val = PSCR_ICC_ABSENT;
  736. }
  737. return Val;
  738. }
  739. // -------------------------------- END OF FILE ------------------------------