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.

946 lines
22 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) SCM Microsystems, 1998 - 1999
  6. //
  7. // File: cbhndlr.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #if defined( SMCLIB_VXD )
  11. #include "Driver98.h"
  12. #else
  13. #include "DriverNT.h"
  14. #endif
  15. #include "SerialIF.h"
  16. #include "STCCmd.h"
  17. #include "CBHndlr.h"
  18. #include "T0Hndlr.h"
  19. NTSTATUS
  20. CBCardPower(
  21. PSMARTCARD_EXTENSION SmartcardExtension
  22. )
  23. /*++
  24. CBCardPower:
  25. callback handler for SMCLIB RDF_CARD_POWER
  26. Arguments:
  27. SmartcardExtension context of call
  28. Return Value:
  29. STATUS_SUCCESS
  30. STATUS_NO_MEDIA
  31. STATUS_TIMEOUT
  32. STATUS_BUFFER_TOO_SMALL
  33. --*/
  34. {
  35. NTSTATUS NTStatus = STATUS_SUCCESS;
  36. UCHAR ATRBuffer[ ATR_SIZE ];
  37. ULONG ATRLength;
  38. PREADER_EXTENSION ReaderExtension;
  39. SERIAL_TIMEOUTS Timeouts;
  40. SmartcardDebug( DEBUG_TRACE, ("SCMSTCS!CBCardPower Enter\n" ));
  41. ReaderExtension = SmartcardExtension->ReaderExtension;
  42. // discard old ATR
  43. SmartcardExtension->CardCapabilities.ATR.Length = 0;
  44. SmartcardExtension->CardCapabilities.Protocol.Selected =
  45. SCARD_PROTOCOL_UNDEFINED;
  46. // set standard timeouts for the worker thread
  47. Timeouts.ReadIntervalTimeout = SR_READ_INTERVAL_TIMEOUT;
  48. Timeouts.ReadTotalTimeoutConstant = SR_READ_TOTAL_TIMEOUT_CONSTANT;
  49. Timeouts.ReadTotalTimeoutMultiplier = 0;
  50. Timeouts.WriteTotalTimeoutConstant = SR_WRITE_TOTAL_TIMEOUT_CONSTANT;
  51. Timeouts.WriteTotalTimeoutMultiplier = 0;
  52. NTStatus = IFSerialIoctl(
  53. ReaderExtension,
  54. IOCTL_SERIAL_SET_TIMEOUTS,
  55. &Timeouts,
  56. sizeof(Timeouts),
  57. NULL,
  58. 0
  59. );
  60. ASSERT(NTStatus == STATUS_SUCCESS);
  61. // set the ATR timeout in milli sec
  62. ReaderExtension->ReadTimeout = 1500;
  63. switch (SmartcardExtension->MinorIoControlCode)
  64. {
  65. case SCARD_WARM_RESET:
  66. // if the card was not powerd, fall through to cold reset
  67. if( SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_SWALLOWED )
  68. {
  69. // reset the card
  70. ATRLength = ATR_SIZE;
  71. NTStatus = STCReset(
  72. ReaderExtension,
  73. 0, // not used: 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 = STCReset(
  85. ReaderExtension,
  86. 0, // not used: ReaderExtension->Device,
  87. FALSE, // cold reset
  88. ATRBuffer,
  89. &ATRLength
  90. );
  91. break;
  92. case SCARD_POWER_DOWN:
  93. // discard old card status
  94. ATRLength = 0;
  95. STCPowerOff( ReaderExtension );
  96. NTStatus = STATUS_SUCCESS;
  97. CBUpdateCardState( SmartcardExtension, SCARD_PRESENT );
  98. break;
  99. }
  100. // finish the request
  101. if( NTStatus == STATUS_SUCCESS )
  102. {
  103. // update all neccessary data if an ATR was received
  104. if( ATRLength > 2 )
  105. {
  106. // copy ATR to user buffer buffer
  107. if( ATRLength <= SmartcardExtension->IoRequest.ReplyBufferLength )
  108. {
  109. SysCopyMemory(
  110. SmartcardExtension->IoRequest.ReplyBuffer,
  111. ATRBuffer,
  112. ATRLength
  113. );
  114. *SmartcardExtension->IoRequest.Information = ATRLength;
  115. }
  116. else
  117. {
  118. NTStatus = STATUS_BUFFER_TOO_SMALL;
  119. }
  120. // copy ATR to card capability buffer
  121. if( ATRLength <= MAXIMUM_ATR_LENGTH )
  122. {
  123. SysCopyMemory(
  124. SmartcardExtension->CardCapabilities.ATR.Buffer,
  125. ATRBuffer,
  126. ATRLength
  127. );
  128. SmartcardExtension->CardCapabilities.ATR.Length =
  129. (UCHAR)ATRLength;
  130. // let the lib update the card capabilities
  131. NTStatus = SmartcardUpdateCardCapabilities(
  132. SmartcardExtension
  133. );
  134. }
  135. else
  136. {
  137. NTStatus = STATUS_BUFFER_TOO_SMALL;
  138. }
  139. if( NTStatus == STATUS_SUCCESS )
  140. {
  141. ULONG minWaitTime;
  142. // set the stc registers
  143. CBSynchronizeSTC( SmartcardExtension );
  144. // now set the new - card specific - timeouts
  145. if( SmartcardExtension->CardCapabilities.Protocol.Selected ==
  146. SCARD_PROTOCOL_T1 )
  147. {
  148. ReaderExtension->ReadTimeout =
  149. Timeouts.ReadTotalTimeoutConstant =
  150. SmartcardExtension->CardCapabilities.T1.BWT / 1000;
  151. Timeouts.ReadIntervalTimeout =
  152. SmartcardExtension->CardCapabilities.T1.CWT / 1000;
  153. }
  154. else
  155. {
  156. ReaderExtension->ReadTimeout =
  157. Timeouts.ReadIntervalTimeout =
  158. Timeouts.ReadTotalTimeoutConstant =
  159. SmartcardExtension->CardCapabilities.T0.WT / 1000 * 5;
  160. }
  161. minWaitTime = (KeQueryTimeIncrement() / 10000) * 5;
  162. if (Timeouts.ReadTotalTimeoutConstant < minWaitTime) {
  163. Timeouts.ReadTotalTimeoutConstant = minWaitTime;
  164. }
  165. if (Timeouts.ReadIntervalTimeout < minWaitTime) {
  166. Timeouts.ReadIntervalTimeout = minWaitTime;
  167. }
  168. if (ReaderExtension->ReadTimeout < minWaitTime) {
  169. ReaderExtension->ReadTimeout = minWaitTime;
  170. }
  171. // set standard timeouts for the worker thread
  172. Timeouts.ReadTotalTimeoutMultiplier = 0;
  173. NTStatus = IFSerialIoctl(
  174. ReaderExtension,
  175. IOCTL_SERIAL_SET_TIMEOUTS,
  176. &Timeouts,
  177. sizeof(Timeouts),
  178. NULL,
  179. 0
  180. );
  181. ASSERT(NTStatus == STATUS_SUCCESS);
  182. }
  183. }
  184. }
  185. SmartcardDebug(
  186. DEBUG_TRACE,
  187. ( "SCMSTCS!CBCardPower Exit: %X\n",
  188. NTStatus )
  189. );
  190. return( NTStatus );
  191. }
  192. NTSTATUS
  193. CBSetProtocol(
  194. PSMARTCARD_EXTENSION SmartcardExtension
  195. )
  196. /*++
  197. CBSetProtocol:
  198. callback handler for SMCLIB RDF_SET_PROTOCOL
  199. Arguments:
  200. SmartcardExtension context of call
  201. Return Value:
  202. STATUS_SUCCESS
  203. STATUS_NO_MEDIA
  204. STATUS_TIMEOUT
  205. STATUS_BUFFER_TOO_SMALL
  206. STATUS_INVALID_DEVICE_STATE
  207. STATUS_INVALID_DEVICE_REQUEST
  208. --*/
  209. {
  210. NTSTATUS NTStatus = STATUS_PENDING;
  211. UCHAR PTSRequest[5], PTSReply[5];
  212. ULONG NewProtocol;
  213. PREADER_EXTENSION ReaderExtension;
  214. SmartcardDebug( DEBUG_TRACE, ("SCMSTCS!CBSetProtocol Enter\n" ));
  215. ReaderExtension = SmartcardExtension->ReaderExtension;
  216. NewProtocol = SmartcardExtension->MinorIoControlCode;
  217. // check if the card is already in specific state
  218. if( ( SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC ) &&
  219. ( SmartcardExtension->CardCapabilities.Protocol.Selected & NewProtocol ))
  220. {
  221. NTStatus = STATUS_SUCCESS;
  222. }
  223. // protocol supported?
  224. if( !( SmartcardExtension->CardCapabilities.Protocol.Supported & NewProtocol ) ||
  225. !( SmartcardExtension->ReaderCapabilities.SupportedProtocols & NewProtocol ))
  226. {
  227. NTStatus = STATUS_INVALID_DEVICE_REQUEST;
  228. }
  229. // send PTS
  230. while( NTStatus == STATUS_PENDING )
  231. {
  232. // set initial character of PTS
  233. PTSRequest[0] = 0xFF;
  234. // set the format character
  235. if( NewProtocol & SCARD_PROTOCOL_T1 )
  236. {
  237. PTSRequest[1] = 0x11;
  238. SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T1;
  239. }
  240. else
  241. {
  242. PTSRequest[1] = 0x10;
  243. SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0;
  244. }
  245. // PTS1 codes Fl and Dl
  246. PTSRequest[2] =
  247. SmartcardExtension->CardCapabilities.PtsData.Fl << 4 |
  248. SmartcardExtension->CardCapabilities.PtsData.Dl;
  249. // check character
  250. PTSRequest[3] = PTSRequest[0] ^ PTSRequest[1] ^ PTSRequest[2];
  251. // write PTSRequest
  252. NTStatus = STCWriteICC1( ReaderExtension, PTSRequest, 4 );
  253. // get response
  254. if( NTStatus == STATUS_SUCCESS )
  255. {
  256. ULONG BufferLength = sizeof(PTSReply);
  257. NTStatus = STCReadICC1(
  258. ReaderExtension,
  259. PTSReply,
  260. &BufferLength,
  261. 4
  262. );
  263. if(( NTStatus == STATUS_SUCCESS ) && !SysCompareMemory( PTSRequest, PTSReply, 4))
  264. {
  265. // set the stc registers
  266. SmartcardExtension->CardCapabilities.Dl =
  267. SmartcardExtension->CardCapabilities.PtsData.Dl;
  268. SmartcardExtension->CardCapabilities.Fl =
  269. SmartcardExtension->CardCapabilities.PtsData.Fl;
  270. CBSynchronizeSTC( SmartcardExtension );
  271. // the card replied correctly to the PTS-request
  272. break;
  273. }
  274. }
  275. //
  276. // The card did either NOT reply or it replied incorrectly
  277. // so try default values
  278. //
  279. SmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_DEFAULT;
  280. SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET;
  281. NTStatus = CBCardPower( SmartcardExtension );
  282. if( NTStatus == STATUS_SUCCESS )
  283. {
  284. NTStatus = STATUS_PENDING;
  285. }
  286. else
  287. {
  288. NTStatus = STATUS_DEVICE_PROTOCOL_ERROR;
  289. }
  290. }
  291. if( NTStatus == STATUS_TIMEOUT )
  292. {
  293. NTStatus = STATUS_IO_TIMEOUT;
  294. }
  295. if( NTStatus == STATUS_SUCCESS )
  296. {
  297. ULONG minWaitTime;
  298. SERIAL_TIMEOUTS Timeouts;
  299. if( SmartcardExtension->CardCapabilities.Protocol.Selected ==
  300. SCARD_PROTOCOL_T1 )
  301. {
  302. ReaderExtension->ReadTimeout =
  303. Timeouts.ReadTotalTimeoutConstant =
  304. SmartcardExtension->CardCapabilities.T1.BWT / 1000;
  305. Timeouts.ReadIntervalTimeout =
  306. SmartcardExtension->CardCapabilities.T1.CWT / 1000;
  307. }
  308. else
  309. {
  310. ReaderExtension->ReadTimeout =
  311. Timeouts.ReadIntervalTimeout =
  312. Timeouts.ReadTotalTimeoutConstant =
  313. SmartcardExtension->CardCapabilities.T0.WT / 1000 * 5;
  314. }
  315. minWaitTime = (KeQueryTimeIncrement() / 10000) * 5;
  316. if (Timeouts.ReadTotalTimeoutConstant < minWaitTime) {
  317. Timeouts.ReadTotalTimeoutConstant = minWaitTime;
  318. }
  319. if (Timeouts.ReadIntervalTimeout < minWaitTime) {
  320. Timeouts.ReadIntervalTimeout = minWaitTime;
  321. }
  322. if (ReaderExtension->ReadTimeout < minWaitTime) {
  323. ReaderExtension->ReadTimeout = minWaitTime;
  324. }
  325. Timeouts.WriteTotalTimeoutConstant = SR_WRITE_TOTAL_TIMEOUT_CONSTANT;
  326. Timeouts.WriteTotalTimeoutMultiplier = 0;
  327. Timeouts.ReadTotalTimeoutMultiplier = 0;
  328. NTStatus = IFSerialIoctl(
  329. ReaderExtension,
  330. IOCTL_SERIAL_SET_TIMEOUTS,
  331. &Timeouts,
  332. sizeof(Timeouts),
  333. NULL,
  334. 0
  335. );
  336. ASSERT(NTStatus == STATUS_SUCCESS);
  337. // indicate that the card is in specific mode
  338. SmartcardExtension->ReaderCapabilities.CurrentState =
  339. SCARD_SPECIFIC;
  340. // return the selected protocol to the caller
  341. *(PULONG) SmartcardExtension->IoRequest.ReplyBuffer =
  342. SmartcardExtension->CardCapabilities.Protocol.Selected;
  343. *SmartcardExtension->IoRequest.Information =
  344. sizeof(SmartcardExtension->CardCapabilities.Protocol.Selected);
  345. }
  346. else
  347. {
  348. SmartcardExtension->CardCapabilities.Protocol.Selected =
  349. SCARD_PROTOCOL_UNDEFINED;
  350. *(PULONG) SmartcardExtension->IoRequest.ReplyBuffer = 0;
  351. *SmartcardExtension->IoRequest.Information = 0;
  352. }
  353. SmartcardDebug( DEBUG_TRACE, ("SCMSTCS!CBSetProtocol: Exit %X\n", NTStatus ));
  354. return( NTStatus );
  355. }
  356. NTSTATUS
  357. CBTransmit(
  358. PSMARTCARD_EXTENSION SmartcardExtension
  359. )
  360. /*++
  361. CBTransmit:
  362. callback handler for SMCLIB RDF_TRANSMIT
  363. Arguments:
  364. SmartcardExtension context of call
  365. Return Value:
  366. STATUS_SUCCESS
  367. STATUS_NO_MEDIA
  368. STATUS_TIMEOUT
  369. STATUS_INVALID_DEVICE_REQUEST
  370. --*/
  371. {
  372. NTSTATUS NTStatus = STATUS_SUCCESS;
  373. SmartcardDebug( DEBUG_TRACE, ("SCMSTCS!CBTransmit Enter\n" ));
  374. // dispatch on the selected protocol
  375. switch( SmartcardExtension->CardCapabilities.Protocol.Selected )
  376. {
  377. case SCARD_PROTOCOL_T0:
  378. NTStatus = CBT0Transmit( SmartcardExtension );
  379. break;
  380. case SCARD_PROTOCOL_T1:
  381. NTStatus = CBT1Transmit( SmartcardExtension );
  382. break;
  383. case SCARD_PROTOCOL_RAW:
  384. NTStatus = CBRawTransmit( SmartcardExtension );
  385. break;
  386. default:
  387. NTStatus = STATUS_INVALID_DEVICE_REQUEST;
  388. break;
  389. }
  390. SmartcardDebug( DEBUG_TRACE, ("SCMSTCS!CBTransmit Exit: %X\n", NTStatus ));
  391. return( NTStatus );
  392. }
  393. NTSTATUS
  394. CBT0Transmit(
  395. PSMARTCARD_EXTENSION SmartcardExtension
  396. )
  397. /*++
  398. CBT0Transmit:
  399. finishes the callback RDF_TRANSMIT for the T0 protocol
  400. Arguments:
  401. SmartcardExtension context of call
  402. Return Value:
  403. STATUS_SUCCESS
  404. STATUS_NO_MEDIA
  405. STATUS_TIMEOUT
  406. STATUS_INVALID_DEVICE_REQUEST
  407. --*/
  408. {
  409. NTSTATUS NTStatus = STATUS_SUCCESS;
  410. SmartcardDebug( DEBUG_TRACE, ("SCMSTCS!CBT0Transmit Enter\n" ));
  411. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  412. SmartcardExtension->SmartcardReply.BufferLength =
  413. SmartcardExtension->SmartcardReply.BufferSize;
  414. // let the lib setup the T=1 APDU & check for errors
  415. NTStatus = SmartcardT0Request( SmartcardExtension );
  416. if( NTStatus == STATUS_SUCCESS )
  417. {
  418. NTStatus = T0_ExchangeData(
  419. SmartcardExtension->ReaderExtension,
  420. SmartcardExtension->SmartcardRequest.Buffer,
  421. SmartcardExtension->SmartcardRequest.BufferLength,
  422. SmartcardExtension->SmartcardReply.Buffer,
  423. &SmartcardExtension->SmartcardReply.BufferLength
  424. );
  425. if( NTStatus == STATUS_SUCCESS )
  426. {
  427. // let the lib evaluate the result & tansfer the data
  428. NTStatus = SmartcardT0Reply( SmartcardExtension );
  429. }
  430. }
  431. SmartcardDebug( DEBUG_TRACE,("SCMSTCS!CBT0Transmit Exit: %X\n", NTStatus ));
  432. return( NTStatus );
  433. }
  434. NTSTATUS
  435. CBT1Transmit(
  436. PSMARTCARD_EXTENSION SmartcardExtension
  437. )
  438. /*++
  439. CBT1Transmit:
  440. finishes the callback RDF_TRANSMIT for the T1 protocol
  441. Arguments:
  442. SmartcardExtension context of call
  443. Return Value:
  444. STATUS_SUCCESS
  445. STATUS_NO_MEDIA
  446. STATUS_TIMEOUT
  447. STATUS_INVALID_DEVICE_REQUEST
  448. --*/
  449. {
  450. NTSTATUS NTStatus = STATUS_SUCCESS;
  451. ULONG BufferLength,AlreadyRead;
  452. SmartcardDebug( DEBUG_TRACE, ("SCMSTCS!CBT1Transmit Enter\n" ));
  453. //KJ
  454. RtlZeroMemory( SmartcardExtension->SmartcardReply.Buffer,
  455. sizeof(SmartcardExtension->SmartcardReply.Buffer));
  456. // use the lib support to construct the T=1 packets
  457. do {
  458. // no header for the T=1 protocol
  459. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  460. SmartcardExtension->T1.NAD = 0;
  461. // let the lib setup the T=1 APDU & check for errors
  462. NTStatus = SmartcardT1Request( SmartcardExtension );
  463. if( NTStatus == STATUS_SUCCESS )
  464. {
  465. // send command (don't calculate LRC because CRC may be used!)
  466. NTStatus = STCWriteICC1(
  467. SmartcardExtension->ReaderExtension,
  468. SmartcardExtension->SmartcardRequest.Buffer,
  469. SmartcardExtension->SmartcardRequest.BufferLength
  470. );
  471. //
  472. // extend the timeout if a Wtx request was sent by the card. if the
  473. // card responds before the waiting time extension expires, the data are
  474. // buffered in the reader. A delay without polling the reader status
  475. // slows down the performance of the driver, but wtx is an exeption,
  476. // not the rule.
  477. //
  478. if (SmartcardExtension->T1.Wtx)
  479. {
  480. SysDelay(
  481. (( SmartcardExtension->T1.Wtx *
  482. SmartcardExtension->CardCapabilities.T1.BWT + 999L )/
  483. 1000L)
  484. );
  485. }
  486. // get response
  487. SmartcardExtension->SmartcardReply.BufferLength = 0;
  488. if( NTStatus == STATUS_SUCCESS )
  489. {
  490. BufferLength = SmartcardExtension->SmartcardReply.BufferSize;
  491. NTStatus = STCReadICC1(
  492. SmartcardExtension->ReaderExtension,
  493. SmartcardExtension->SmartcardReply.Buffer,
  494. &BufferLength,
  495. 3
  496. );
  497. // if we have read more then 3 bytes
  498. if(BufferLength > 3)
  499. {
  500. AlreadyRead = BufferLength - 3;
  501. }
  502. else
  503. {
  504. AlreadyRead = 0;
  505. }
  506. if( NTStatus == STATUS_SUCCESS )
  507. {
  508. ULONG Length;
  509. Length = (ULONG)SmartcardExtension->SmartcardReply.Buffer[ LEN_IDX ] + 1;
  510. if( Length + 3 < MIN_BUFFER_SIZE )
  511. {
  512. BufferLength =
  513. SmartcardExtension->SmartcardReply.BufferSize -
  514. Length;
  515. NTStatus = STCReadICC1(
  516. SmartcardExtension->ReaderExtension,
  517. (&SmartcardExtension->SmartcardReply.Buffer[ DATA_IDX ]) + AlreadyRead,
  518. &BufferLength,
  519. Length-AlreadyRead
  520. );
  521. SmartcardExtension->SmartcardReply.BufferLength = Length + 3;
  522. }
  523. else
  524. {
  525. NTStatus = STATUS_BUFFER_TOO_SMALL;
  526. }
  527. }
  528. //
  529. // if STCRead detects an LRC error, ignore it (maybe CRC used). Timeouts will
  530. // be detected by the lib if len=0
  531. //
  532. if(( NTStatus == STATUS_CRC_ERROR ) || ( NTStatus == STATUS_IO_TIMEOUT ))
  533. {
  534. NTStatus = STATUS_SUCCESS;
  535. }
  536. if( NTStatus == STATUS_SUCCESS )
  537. {
  538. // let the lib evaluate the result & setup the next APDU
  539. NTStatus = SmartcardT1Reply( SmartcardExtension );
  540. }
  541. }
  542. }
  543. // continue if the lib wants to send the next packet
  544. } while( NTStatus == STATUS_MORE_PROCESSING_REQUIRED );
  545. if( NTStatus == STATUS_IO_TIMEOUT )
  546. {
  547. NTStatus = STATUS_DEVICE_PROTOCOL_ERROR;
  548. }
  549. SmartcardDebug( DEBUG_TRACE,( "SCMSTCS!CBT1Transmit Exit: %X\n", NTStatus ));
  550. return ( NTStatus );
  551. }
  552. NTSTATUS
  553. CBRawTransmit(
  554. PSMARTCARD_EXTENSION SmartcardExtension
  555. )
  556. /*++
  557. CBRawTransmit:
  558. finishes the callback RDF_TRANSMIT for the RAW protocol
  559. Arguments:
  560. SmartcardExtension context of call
  561. Return Value:
  562. STATUS_SUCCESS
  563. STATUS_NO_MEDIA
  564. STATUS_TIMEOUT
  565. STATUS_INVALID_DEVICE_REQUEST
  566. --*/
  567. {
  568. NTSTATUS NTStatus = STATUS_SUCCESS;
  569. NTStatus = STATUS_UNSUCCESSFUL;
  570. SmartcardDebug( DEBUG_TRACE, ("SCMSTCS!CBRawTransmit Exit: %X\n", NTStatus ));
  571. return ( NTStatus );
  572. }
  573. NTSTATUS
  574. CBCardTracking(
  575. PSMARTCARD_EXTENSION SmartcardExtension
  576. )
  577. /*++
  578. CBCardTracking:
  579. callback handler for SMCLIB RDF_CARD_TRACKING. the requested event was
  580. validated by the smclib (i.e. a card removal request will only be passed
  581. if a card is present).
  582. for a win95 build STATUS_PENDING will be returned without any other action.
  583. for NT the cancel routine for the irp will be set to the drivers cancel
  584. routine.
  585. Arguments:
  586. SmartcardExtension context of call
  587. Return Value:
  588. STATUS_PENDING
  589. --*/
  590. {
  591. SmartcardDebug( DEBUG_TRACE, ("SCMSTCS!CBCardTracking Enter\n" ));
  592. #if defined( SMCLIB_VXD )
  593. #else
  594. {
  595. KIRQL CurrentIrql;
  596. // set cancel routine
  597. IoAcquireCancelSpinLock( &CurrentIrql );
  598. IoSetCancelRoutine(
  599. SmartcardExtension->OsData->NotificationIrp,
  600. DrvCancel
  601. );
  602. IoReleaseCancelSpinLock( CurrentIrql );
  603. }
  604. #endif
  605. SmartcardDebug( DEBUG_TRACE, ( "SCMSTCS!CBCardTracking Exit\n" ));
  606. return( STATUS_PENDING );
  607. }
  608. VOID
  609. CBUpdateCardState(
  610. PSMARTCARD_EXTENSION SmartcardExtension,
  611. ULONG RequestedState
  612. )
  613. /*++
  614. CBUpdateCardState:
  615. updates the variable CurrentState in SmartcardExtension
  616. Arguments:
  617. SmartcardExtension context of call
  618. Return Value:
  619. STATUS_SUCCESS
  620. --*/
  621. {
  622. NTSTATUS NTStatus = STATUS_SUCCESS;
  623. UCHAR Status;
  624. KIRQL Irql;
  625. BOOLEAN StateChanged = FALSE;
  626. ULONG NewState = RequestedState;
  627. if (RequestedState == SCARD_UNKNOWN) {
  628. // read card state from reader
  629. NTStatus = STCReadSTCRegister(
  630. SmartcardExtension->ReaderExtension,
  631. ADR_IO_CONFIG,
  632. 1,
  633. &Status
  634. );
  635. ASSERT(NTStatus == STATUS_SUCCESS);
  636. if (NTStatus == STATUS_SUCCESS) {
  637. if ((Status & M_SD) == 0) {
  638. NewState = SCARD_ABSENT;
  639. } else {
  640. NewState = SCARD_SWALLOWED;
  641. }
  642. }
  643. }
  644. if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_UNKNOWN ||
  645. SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT &&
  646. NewState <= SCARD_ABSENT ||
  647. SmartcardExtension->ReaderCapabilities.CurrentState <= SCARD_ABSENT &&
  648. NewState > SCARD_ABSENT) {
  649. StateChanged = TRUE;
  650. }
  651. KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &Irql);
  652. if(RequestedState != SCARD_UNKNOWN ||
  653. NTStatus == STATUS_SUCCESS && StateChanged)
  654. {
  655. SmartcardExtension->ReaderCapabilities.CurrentState = NewState;
  656. }
  657. #if defined( SMCLIB_VXD )
  658. //
  659. // if a tracking request is pending, finish it (even if an error occured!)
  660. // to prevent a hangup of an application
  661. //
  662. if( SmartcardExtension->OsData->NotificationOverlappedData != NULL )
  663. {
  664. SmartcardCompleteCardTracking( SmartcardExtension );
  665. }
  666. #else
  667. if(StateChanged && SmartcardExtension->OsData->NotificationIrp != NULL)
  668. {
  669. KIRQL CurrentIrql;
  670. IoAcquireCancelSpinLock( &CurrentIrql );
  671. IoSetCancelRoutine( SmartcardExtension->OsData->NotificationIrp, NULL );
  672. IoReleaseCancelSpinLock( CurrentIrql );
  673. SmartcardExtension->OsData->NotificationIrp->IoStatus.Status =
  674. STATUS_SUCCESS;
  675. SmartcardExtension->OsData->NotificationIrp->IoStatus.Information = 0;
  676. IoCompleteRequest(
  677. SmartcardExtension->OsData->NotificationIrp,
  678. IO_NO_INCREMENT
  679. );
  680. SmartcardExtension->OsData->NotificationIrp = NULL;
  681. }
  682. KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, Irql);
  683. #endif
  684. }
  685. NTSTATUS
  686. CBSynchronizeSTC(
  687. PSMARTCARD_EXTENSION SmartcardExtension
  688. )
  689. /*++
  690. CBSynchronizeSTC:
  691. updates the card dependend data of the stc (wait times, ETU...)
  692. Arguments:
  693. SmartcardExtension context of call
  694. Return Value:
  695. STATUS_SUCCESS
  696. --*/
  697. {
  698. NTSTATUS NTStatus = STATUS_SUCCESS;
  699. PREADER_EXTENSION ReaderExtension;
  700. ULONG CWT,
  701. BWT,
  702. CGT,
  703. ETU;
  704. UCHAR Dl,
  705. Fl,
  706. N;
  707. PCLOCK_RATE_CONVERSION ClockRateConversion;
  708. PBIT_RATE_ADJUSTMENT BitRateAdjustment;
  709. ReaderExtension = SmartcardExtension->ReaderExtension;
  710. ClockRateConversion = SmartcardExtension->CardCapabilities.ClockRateConversion;
  711. BitRateAdjustment = SmartcardExtension->CardCapabilities.BitRateAdjustment;
  712. // cycle length
  713. Dl = SmartcardExtension->CardCapabilities.Dl;
  714. Fl = SmartcardExtension->CardCapabilities.Fl;
  715. ETU = ClockRateConversion[Fl & 0x0F].F;
  716. ETU /= BitRateAdjustment[ Dl & 0x0F ].DNumerator;
  717. ETU *= BitRateAdjustment[ Dl & 0x0F ].DDivisor;
  718. // ETU += (ETU % 2 == 0) ? 0 : 1;
  719. // a extra guard time of 0xFF means minimum delay in both directions
  720. N = SmartcardExtension->CardCapabilities.N;
  721. if( N == 0xFF )
  722. {
  723. N = 0;
  724. }
  725. // set character waiting & guard time
  726. switch ( SmartcardExtension->CardCapabilities.Protocol.Selected )
  727. {
  728. case SCARD_PROTOCOL_T0:
  729. CWT = 960 * SmartcardExtension->CardCapabilities.T0.WI;
  730. CGT = 14 + N;
  731. break;
  732. case SCARD_PROTOCOL_T1:
  733. CWT = 1000 + ( 0x01 << SmartcardExtension->CardCapabilities.T1.CWI );
  734. BWT = 11 + ( 0x01 << SmartcardExtension->CardCapabilities.T1.BWI ) * 960;
  735. CGT = 15 + N; // 12 + N; sicrypt error
  736. NTStatus = STCSetBWT( ReaderExtension, BWT * ETU );
  737. break;
  738. default:
  739. NTStatus = STATUS_UNSUCCESSFUL;
  740. break;
  741. }
  742. if(( NTStatus == STATUS_SUCCESS ) && ETU )
  743. {
  744. NTStatus = STCSetETU( ReaderExtension, ETU );
  745. if( NTStatus == STATUS_SUCCESS )
  746. {
  747. NTStatus = STCSetCGT( ReaderExtension, CGT );
  748. if( NTStatus == STATUS_SUCCESS )
  749. {
  750. NTStatus = STCSetCWT( ReaderExtension, CWT * ETU );
  751. }
  752. }
  753. }
  754. return( NTStatus );
  755. }