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.

1175 lines
30 KiB

  1. /*++
  2. Copyright (c) 1998 SCM Microsystems, Inc.
  3. Module Name:
  4. StcCb.c
  5. Abstract:
  6. Declaration of callback functions - WDM Version
  7. Revision History:
  8. PP 1.01 01/19/1998
  9. PP 1.00 12/18/1998 Initial Version
  10. --*/
  11. // Include
  12. #include "common.h"
  13. #include "stccmd.h"
  14. #include "stccb.h"
  15. #include "stcusbnt.h"
  16. #include "usbcom.h"
  17. NTSTATUS
  18. CBCardPower(
  19. PSMARTCARD_EXTENSION SmartcardExtension)
  20. /*++
  21. CBCardPower:
  22. callback handler for SMCLIB RDF_CARD_POWER
  23. Arguments:
  24. SmartcardExtension context of call
  25. Return Value:
  26. STATUS_SUCCESS
  27. STATUS_NO_MEDIA
  28. STATUS_TIMEOUT
  29. STATUS_BUFFER_TOO_SMALL
  30. --*/
  31. {
  32. NTSTATUS NTStatus = STATUS_SUCCESS;
  33. UCHAR ATRBuffer[ ATR_SIZE ];
  34. ULONG Command,
  35. ATRLength;
  36. PREADER_EXTENSION ReaderExtension;
  37. SmartcardDebug( DEBUG_TRACE, ("%s!CBCardPower Enter\n",DRIVER_NAME ));
  38. ReaderExtension = SmartcardExtension->ReaderExtension;
  39. // discard old ATR
  40. SysFillMemory( SmartcardExtension->CardCapabilities.ATR.Buffer, 0x00, 0x40 );
  41. SmartcardExtension->CardCapabilities.ATR.Length = 0;
  42. SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
  43. Command = SmartcardExtension->MinorIoControlCode;
  44. switch ( Command )
  45. {
  46. case SCARD_WARM_RESET:
  47. // if the card was not powerd, fall through to cold reset
  48. if( SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_SWALLOWED )
  49. {
  50. // reset the card
  51. ATRLength = ATR_SIZE;
  52. NTStatus = STCReset(
  53. ReaderExtension,
  54. 0, // not used: ReaderExtension->Device,
  55. TRUE, // warm reset
  56. ATRBuffer,
  57. &ATRLength);
  58. break;
  59. }
  60. // warm reset not possible because card was not powerd
  61. case SCARD_COLD_RESET:
  62. // reset the card
  63. ATRLength = ATR_SIZE;
  64. NTStatus = STCReset(
  65. ReaderExtension,
  66. 0, // not used: ReaderExtension->Device,
  67. FALSE, // cold reset
  68. ATRBuffer,
  69. &ATRLength);
  70. break;
  71. case SCARD_POWER_DOWN:
  72. // discard old card status
  73. ATRLength = 0;
  74. NTStatus = STCPowerOff( ReaderExtension );
  75. if(NTStatus == STATUS_SUCCESS)
  76. {
  77. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_PRESENT;
  78. }
  79. break;
  80. }
  81. // finish the request
  82. if( NTStatus == STATUS_SUCCESS )
  83. {
  84. // update all neccessary data if an ATR was received
  85. if( ATRLength >= 2 )
  86. {
  87. // copy ATR to user buffer
  88. if( ATRLength <= SmartcardExtension->IoRequest.ReplyBufferLength )
  89. {
  90. SysCopyMemory(
  91. SmartcardExtension->IoRequest.ReplyBuffer,
  92. ATRBuffer,
  93. ATRLength);
  94. *SmartcardExtension->IoRequest.Information = ATRLength;
  95. }
  96. else
  97. {
  98. NTStatus = STATUS_BUFFER_TOO_SMALL;
  99. }
  100. // copy ATR to card capability buffer
  101. if( ATRLength <= MAXIMUM_ATR_LENGTH )
  102. {
  103. SysCopyMemory(
  104. SmartcardExtension->CardCapabilities.ATR.Buffer,
  105. ATRBuffer,
  106. ATRLength);
  107. SmartcardExtension->CardCapabilities.ATR.Length = ( UCHAR )ATRLength;
  108. // let the lib update the card capabilities
  109. NTStatus = SmartcardUpdateCardCapabilities( SmartcardExtension );
  110. }
  111. else
  112. {
  113. NTStatus = STATUS_BUFFER_TOO_SMALL;
  114. }
  115. if( NTStatus == STATUS_SUCCESS )
  116. {
  117. // set the stc registers
  118. CBSynchronizeSTC( SmartcardExtension );
  119. // set read timeout
  120. if( SmartcardExtension->CardCapabilities.Protocol.Selected == SCARD_PROTOCOL_T1 )
  121. {
  122. ReaderExtension->ReadTimeout =
  123. (ULONG) (SmartcardExtension->CardCapabilities.T1.BWT / 1000);
  124. }
  125. else
  126. {
  127. ReaderExtension->ReadTimeout =
  128. (ULONG) (SmartcardExtension->CardCapabilities.T0.WT / 1000);
  129. if(ReaderExtension->ReadTimeout < 50)
  130. {
  131. ReaderExtension->ReadTimeout = 50; // 50 ms minimum timeout
  132. }
  133. }
  134. }
  135. }
  136. }
  137. SmartcardDebug( DEBUG_TRACE,( "%s!CBCardPower Exit: %X\n", DRIVER_NAME,NTStatus ));
  138. return( NTStatus );
  139. }
  140. NTSTATUS
  141. CBSetProtocol(
  142. PSMARTCARD_EXTENSION SmartcardExtension
  143. )
  144. /*++
  145. CBSetProtocol:
  146. callback handler for SMCLIB RDF_SET_PROTOCOL
  147. Arguments:
  148. SmartcardExtension context of call
  149. Return Value:
  150. STATUS_SUCCESS
  151. STATUS_NO_MEDIA
  152. STATUS_TIMEOUT
  153. STATUS_BUFFER_TOO_SMALL
  154. STATUS_INVALID_DEVICE_STATE
  155. STATUS_INVALID_DEVICE_REQUEST
  156. --*/
  157. {
  158. NTSTATUS NTStatus = STATUS_PENDING;
  159. UCHAR PTSRequest[5],
  160. PTSReply[5];
  161. ULONG NewProtocol;
  162. PREADER_EXTENSION ReaderExtension;
  163. SmartcardDebug( DEBUG_TRACE, ("%s!CBSetProtocol Enter\n",DRIVER_NAME ));
  164. ReaderExtension = SmartcardExtension->ReaderExtension;
  165. NewProtocol = SmartcardExtension->MinorIoControlCode;
  166. // check if the card is already in specific state
  167. if( ( SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC ) &&
  168. ( SmartcardExtension->CardCapabilities.Protocol.Selected & NewProtocol ))
  169. {
  170. NTStatus = STATUS_SUCCESS;
  171. }
  172. // protocol supported?
  173. if( !( SmartcardExtension->CardCapabilities.Protocol.Supported & NewProtocol ) ||
  174. !( SmartcardExtension->ReaderCapabilities.SupportedProtocols & NewProtocol ))
  175. {
  176. NTStatus = STATUS_INVALID_DEVICE_REQUEST;
  177. }
  178. // send PTS
  179. while( NTStatus == STATUS_PENDING )
  180. {
  181. // set initial character of PTS
  182. PTSRequest[0] = 0xFF;
  183. // set the format character
  184. if(( NewProtocol & SCARD_PROTOCOL_T1 )&&
  185. (SmartcardExtension->CardCapabilities.Protocol.Supported & SCARD_PROTOCOL_T1 ))
  186. {
  187. PTSRequest[1] = 0x11;
  188. SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T1;
  189. }
  190. else
  191. {
  192. PTSRequest[1] = 0x10;
  193. SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0;
  194. }
  195. // PTS1 codes Fl and Dl
  196. PTSRequest[2] =
  197. SmartcardExtension->CardCapabilities.PtsData.Fl << 4 |
  198. SmartcardExtension->CardCapabilities.PtsData.Dl;
  199. // check character
  200. PTSRequest[3] = PTSRequest[0] ^ PTSRequest[1] ^ PTSRequest[2];
  201. // write PTSRequest
  202. NTStatus = IFWriteSTCData( ReaderExtension, PTSRequest, 4 );
  203. // get response
  204. if( NTStatus == STATUS_SUCCESS )
  205. {
  206. NTStatus = IFReadSTCData( ReaderExtension, PTSReply, 4 );
  207. if(( NTStatus == STATUS_SUCCESS ) && !SysCompareMemory( PTSRequest, PTSReply, 4))
  208. {
  209. // set the stc registers
  210. SmartcardExtension->CardCapabilities.Dl =
  211. SmartcardExtension->CardCapabilities.PtsData.Dl;
  212. SmartcardExtension->CardCapabilities.Fl =
  213. SmartcardExtension->CardCapabilities.PtsData.Fl;
  214. CBSynchronizeSTC( SmartcardExtension );
  215. // the card replied correctly to the PTS-request
  216. break;
  217. }
  218. }
  219. //
  220. // The card did either NOT reply or it replied incorrectly
  221. // so try default values
  222. //
  223. if( SmartcardExtension->CardCapabilities.PtsData.Type != PTS_TYPE_DEFAULT )
  224. {
  225. SmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_DEFAULT;
  226. SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET;
  227. NTStatus = CBCardPower( SmartcardExtension );
  228. if( NTStatus == STATUS_SUCCESS )
  229. {
  230. NTStatus = STATUS_PENDING;
  231. }
  232. else
  233. {
  234. NTStatus = STATUS_DEVICE_PROTOCOL_ERROR;
  235. }
  236. }
  237. }
  238. if( NTStatus == STATUS_TIMEOUT )
  239. {
  240. NTStatus = STATUS_IO_TIMEOUT;
  241. }
  242. if( NTStatus == STATUS_SUCCESS )
  243. {
  244. // card replied correctly to the PTS request
  245. if( SmartcardExtension->CardCapabilities.Protocol.Selected & SCARD_PROTOCOL_T1 )
  246. {
  247. ReaderExtension->ReadTimeout = SmartcardExtension->CardCapabilities.T1.BWT / 1000;
  248. }
  249. else
  250. {
  251. ULONG ClockRateFactor =
  252. SmartcardExtension->CardCapabilities.ClockRateConversion[SmartcardExtension->CardCapabilities.PtsData.Fl].F;
  253. // check for RFU value, and replace by default value
  254. if( !ClockRateFactor )
  255. ClockRateFactor = 372;
  256. ReaderExtension->ReadTimeout = 960
  257. * SmartcardExtension->CardCapabilities.T0.WI
  258. * ClockRateFactor
  259. / SmartcardExtension->CardCapabilities.PtsData.CLKFrequency;
  260. // We need to have a minimum timeout anyway
  261. if(ReaderExtension->ReadTimeout <50)
  262. {
  263. ReaderExtension->ReadTimeout =50; // 50 ms minimum timeout
  264. }
  265. }
  266. // indicate that the card is in specific mode
  267. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
  268. // return the selected protocol to the caller
  269. *(PULONG) SmartcardExtension->IoRequest.ReplyBuffer = SmartcardExtension->CardCapabilities.Protocol.Selected;
  270. *SmartcardExtension->IoRequest.Information = sizeof(SmartcardExtension->CardCapabilities.Protocol.Selected);
  271. }
  272. else
  273. {
  274. SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
  275. *(PULONG) SmartcardExtension->IoRequest.ReplyBuffer = 0;
  276. *SmartcardExtension->IoRequest.Information = 0;
  277. }
  278. SmartcardDebug( DEBUG_TRACE, ("%d!CBSetProtocol: Exit %X\n",DRIVER_NAME, NTStatus ));
  279. return( NTStatus );
  280. }
  281. NTSTATUS
  282. CBGenericIOCTL(
  283. PSMARTCARD_EXTENSION SmartcardExtension)
  284. /*++
  285. Description:
  286. Performs generic callbacks to the reader
  287. Arguments:
  288. SmartcardExtension context of the call
  289. Return Value:
  290. STATUS_SUCCESS
  291. --*/
  292. {
  293. NTSTATUS NTStatus;
  294. SmartcardDebug(
  295. DEBUG_TRACE,
  296. ( "%s!CBGenericIOCTL: Enter\n",
  297. DRIVER_NAME));
  298. //
  299. // get pointer to current IRP stack location
  300. //
  301. //
  302. // assume error
  303. //
  304. NTStatus = STATUS_INVALID_DEVICE_REQUEST;
  305. //
  306. // dispatch IOCTL
  307. //
  308. switch( SmartcardExtension->MajorIoControlCode )
  309. {
  310. case IOCTL_WRITE_STC_REGISTER:
  311. NTStatus = IFWriteSTCRegister(
  312. SmartcardExtension->ReaderExtension,
  313. *(SmartcardExtension->IoRequest.RequestBuffer), // Address
  314. (ULONG)(*(SmartcardExtension->IoRequest.RequestBuffer + 1)), // Size
  315. SmartcardExtension->IoRequest.RequestBuffer + 2); // Data
  316. *SmartcardExtension->IoRequest.Information = 1;
  317. if(NTStatus == STATUS_SUCCESS)
  318. {
  319. *(SmartcardExtension->IoRequest.ReplyBuffer) = 0;
  320. }
  321. else
  322. {
  323. *(SmartcardExtension->IoRequest.ReplyBuffer) = 1;
  324. }
  325. break;
  326. case IOCTL_READ_STC_REGISTER:
  327. NTStatus = IFReadSTCRegister(
  328. SmartcardExtension->ReaderExtension,
  329. *(SmartcardExtension->IoRequest.RequestBuffer), // Address
  330. (ULONG)(*(SmartcardExtension->IoRequest.RequestBuffer + 1)), // Size
  331. SmartcardExtension->IoRequest.ReplyBuffer); // Data
  332. if(NTStatus ==STATUS_SUCCESS)
  333. {
  334. *SmartcardExtension->IoRequest.Information =
  335. (ULONG)(*(SmartcardExtension->IoRequest.RequestBuffer + 1));
  336. }
  337. else
  338. {
  339. SmartcardExtension->IoRequest.Information = 0;
  340. }
  341. break;
  342. case IOCTL_WRITE_STC_DATA:
  343. NTStatus = IFWriteSTCData(
  344. SmartcardExtension->ReaderExtension,
  345. SmartcardExtension->IoRequest.RequestBuffer + 1, // Data
  346. (ULONG)(*(SmartcardExtension->IoRequest.RequestBuffer))); // Size
  347. *SmartcardExtension->IoRequest.Information = 1;
  348. if(NTStatus == STATUS_SUCCESS)
  349. {
  350. *(SmartcardExtension->IoRequest.ReplyBuffer) = 0;
  351. }
  352. else
  353. {
  354. *(SmartcardExtension->IoRequest.ReplyBuffer) = 1;
  355. }
  356. break;
  357. case IOCTL_READ_STC_DATA:
  358. NTStatus = IFReadSTCData(
  359. SmartcardExtension->ReaderExtension,
  360. SmartcardExtension->IoRequest.ReplyBuffer, // Data
  361. (ULONG)(*(SmartcardExtension->IoRequest.RequestBuffer))); // Size
  362. if(NTStatus ==STATUS_SUCCESS)
  363. {
  364. *SmartcardExtension->IoRequest.Information =
  365. (ULONG)(*(SmartcardExtension->IoRequest.RequestBuffer));
  366. }
  367. else
  368. {
  369. SmartcardExtension->IoRequest.Information = 0;
  370. }
  371. break;
  372. default:
  373. break;
  374. }
  375. SmartcardDebug(
  376. DEBUG_TRACE,
  377. ( "%s!CBGenericIOCTL: Exit\n",
  378. DRIVER_NAME));
  379. return( NTStatus );
  380. }
  381. NTSTATUS
  382. CBTransmit(
  383. PSMARTCARD_EXTENSION SmartcardExtension
  384. )
  385. /*++
  386. CBTransmit:
  387. callback handler for SMCLIB RDF_TRANSMIT
  388. Arguments:
  389. SmartcardExtension context of call
  390. Return Value:
  391. STATUS_SUCCESS
  392. STATUS_NO_MEDIA
  393. STATUS_TIMEOUT
  394. STATUS_INVALID_DEVICE_REQUEST
  395. --*/
  396. {
  397. NTSTATUS NTStatus = STATUS_SUCCESS;
  398. SmartcardDebug( DEBUG_TRACE, ("%s!CBTransmit Enter\n",DRIVER_NAME ));
  399. // dispatch on the selected protocol
  400. switch( SmartcardExtension->CardCapabilities.Protocol.Selected )
  401. {
  402. case SCARD_PROTOCOL_T0:
  403. NTStatus = CBT0Transmit( SmartcardExtension );
  404. break;
  405. case SCARD_PROTOCOL_T1:
  406. NTStatus = CBT1Transmit( SmartcardExtension );
  407. break;
  408. case SCARD_PROTOCOL_RAW:
  409. NTStatus = CBRawTransmit( SmartcardExtension );
  410. break;
  411. default:
  412. NTStatus = STATUS_INVALID_DEVICE_REQUEST;
  413. break;
  414. }
  415. SmartcardDebug( DEBUG_TRACE, ("%s!CBTransmit Exit: %X\n",DRIVER_NAME, NTStatus ));
  416. return( NTStatus );
  417. }
  418. NTSTATUS
  419. T0_ExchangeData(
  420. PREADER_EXTENSION ReaderExtension,
  421. PUCHAR pRequest,
  422. ULONG RequestLen,
  423. PUCHAR pReply,
  424. PULONG pReplyLen)
  425. /*++
  426. Routine Description:
  427. T=0 management
  428. Arguments:
  429. ReaderExtension Context of the call
  430. pRequest Request buffer
  431. RequestLen Request buffer length
  432. pReply Reply buffer
  433. pReplyLen Reply buffer length
  434. Return Value:
  435. STATUS_SUCCESS
  436. Status returned by IFReadSTCData or IFWriteSTCData
  437. --*/
  438. {
  439. NTSTATUS NTStatus = STATUS_SUCCESS;
  440. BOOLEAN Direction;
  441. UCHAR Ins,
  442. Pcb = 0;
  443. ULONG Len,
  444. DataIdx;
  445. // get direction
  446. Ins = pRequest[ INS_IDX ] & 0xFE;
  447. Len = pRequest[ P3_IDX ];
  448. if( RequestLen == 5 )
  449. {
  450. Direction = ISO_OUT;
  451. DataIdx = 0;
  452. // For an ISO OUT command Len=0 means that the host expect an
  453. // 256 byte answer
  454. if( !Len )
  455. {
  456. Len = 0x100;
  457. }
  458. // Add 2 for SW1 SW2
  459. Len+=2;
  460. }
  461. else
  462. {
  463. Direction = ISO_IN;
  464. DataIdx = 5;
  465. }
  466. // send header CLASS,INS,P1,P2,P3
  467. NTStatus = IFWriteSTCData( ReaderExtension, pRequest, 5 );
  468. if( NTStatus == STATUS_SUCCESS )
  469. {
  470. NTStatus = STATUS_MORE_PROCESSING_REQUIRED;
  471. }
  472. while( NTStatus == STATUS_MORE_PROCESSING_REQUIRED )
  473. {
  474. // PCB reading
  475. NTStatus = IFReadSTCData( ReaderExtension, &Pcb, 1 );
  476. if( NTStatus == STATUS_SUCCESS )
  477. {
  478. if( Pcb == 0x60 )
  479. {
  480. // null byte?
  481. NTStatus = STATUS_MORE_PROCESSING_REQUIRED;
  482. continue;
  483. }
  484. else if( ( Pcb & 0xFE ) == Ins )
  485. {
  486. // transfer all
  487. if( Direction == ISO_IN )
  488. {
  489. // write remaining data
  490. NTStatus = IFWriteSTCData( ReaderExtension, pRequest + DataIdx, Len );
  491. if( NTStatus == STATUS_SUCCESS )
  492. {
  493. // if all data successful written the status word is expected
  494. NTStatus = STATUS_MORE_PROCESSING_REQUIRED;
  495. Direction = ISO_OUT;
  496. DataIdx = 0;
  497. Len = 2;
  498. }
  499. }
  500. else
  501. {
  502. // read remaining data
  503. NTStatus = IFReadSTCData( ReaderExtension, pReply + DataIdx, Len );
  504. DataIdx += Len;
  505. }
  506. }
  507. else if( (( Pcb & 0xFE ) ^ Ins ) == 0xFE )
  508. {
  509. // transfer next
  510. if( Direction == ISO_IN )
  511. {
  512. // write next
  513. NTStatus = IFWriteSTCData( ReaderExtension, pRequest + DataIdx, 1 );
  514. if( NTStatus == STATUS_SUCCESS )
  515. {
  516. DataIdx++;
  517. // if all data successful written the status word is expected
  518. if( --Len == 0 )
  519. {
  520. Direction = ISO_OUT;
  521. DataIdx = 0;
  522. Len = 2;
  523. }
  524. NTStatus = STATUS_MORE_PROCESSING_REQUIRED;
  525. }
  526. }
  527. else
  528. {
  529. // read next
  530. NTStatus = IFReadSTCData( ReaderExtension, pReply + DataIdx, 1 );
  531. if( NTStatus == STATUS_SUCCESS )
  532. {
  533. NTStatus = STATUS_MORE_PROCESSING_REQUIRED;
  534. Len--;
  535. DataIdx++;
  536. }
  537. }
  538. }
  539. else if( (( Pcb & 0x60 ) == 0x60 ) || (( Pcb & 0x90 ) == 0x90 ) )
  540. {
  541. if( Direction == ISO_IN )
  542. {
  543. Direction = ISO_OUT;
  544. DataIdx = 0;
  545. }
  546. // SW1
  547. *pReply = Pcb;
  548. // read SW2 and leave
  549. NTStatus = IFReadSTCData( ReaderExtension, &Pcb, 1 );
  550. *(pReply + 1) = Pcb;
  551. DataIdx += 2;
  552. }
  553. else
  554. {
  555. NTStatus = STATUS_UNSUCCESSFUL;
  556. }
  557. }
  558. }
  559. if(( NTStatus == STATUS_SUCCESS ) && ( pReplyLen != NULL ))
  560. {
  561. *pReplyLen = DataIdx;
  562. }
  563. return( NTStatus );
  564. }
  565. NTSTATUS
  566. CBT0Transmit(
  567. PSMARTCARD_EXTENSION SmartcardExtension)
  568. /*++
  569. CBT0Transmit:
  570. finishes the callback RDF_TRANSMIT for the T0 protocol
  571. Arguments:
  572. SmartcardExtension context of call
  573. Return Value:
  574. STATUS_SUCCESS
  575. STATUS_NO_MEDIA
  576. STATUS_TIMEOUT
  577. STATUS_INVALID_DEVICE_REQUEST
  578. --*/
  579. {
  580. NTSTATUS NTStatus = STATUS_SUCCESS;
  581. SmartcardDebug( DEBUG_TRACE, ("%s!CBT0Transmit Enter\n",DRIVER_NAME ));
  582. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  583. // let the lib setup the T=1 APDU & check for errors
  584. NTStatus = SmartcardT0Request( SmartcardExtension );
  585. if( NTStatus == STATUS_SUCCESS )
  586. {
  587. NTStatus = T0_ExchangeData(
  588. SmartcardExtension->ReaderExtension,
  589. SmartcardExtension->SmartcardRequest.Buffer,
  590. SmartcardExtension->SmartcardRequest.BufferLength,
  591. SmartcardExtension->SmartcardReply.Buffer,
  592. &SmartcardExtension->SmartcardReply.BufferLength);
  593. if( NTStatus == STATUS_SUCCESS )
  594. {
  595. // let the lib evaluate the result & tansfer the data
  596. NTStatus = SmartcardT0Reply( SmartcardExtension );
  597. }
  598. }
  599. SmartcardDebug( DEBUG_TRACE,("%s!CBT0Transmit Exit: %X\n",DRIVER_NAME, NTStatus ));
  600. return( NTStatus );
  601. }
  602. NTSTATUS
  603. CBT1Transmit(
  604. PSMARTCARD_EXTENSION SmartcardExtension)
  605. /*++
  606. CBT1Transmit:
  607. finishes the callback RDF_TRANSMIT for the T1 protocol
  608. Arguments:
  609. SmartcardExtension context of call
  610. Return Value:
  611. STATUS_SUCCESS
  612. STATUS_NO_MEDIA
  613. STATUS_TIMEOUT
  614. STATUS_INVALID_DEVICE_REQUEST
  615. --*/
  616. {
  617. NTSTATUS NTStatus = STATUS_SUCCESS;
  618. SmartcardDebug( DEBUG_TRACE, ("%s!CBT1Transmit Enter\n",DRIVER_NAME ));
  619. // smclib workaround
  620. *(PULONG)&SmartcardExtension->IoRequest.ReplyBuffer[0] = 0x02;
  621. *(PULONG)&SmartcardExtension->IoRequest.ReplyBuffer[4] = sizeof( SCARD_IO_REQUEST );
  622. // use the lib support to construct the T=1 packets
  623. do {
  624. // no header for the T=1 protocol
  625. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  626. SmartcardExtension->T1.NAD = 0;
  627. // let the lib setup the T=1 APDU & check for errors
  628. NTStatus = SmartcardT1Request( SmartcardExtension );
  629. if( NTStatus == STATUS_SUCCESS )
  630. {
  631. // send command (don't calculate LRC because CRC may be used!)
  632. NTStatus = IFWriteSTCData(
  633. SmartcardExtension->ReaderExtension,
  634. SmartcardExtension->SmartcardRequest.Buffer,
  635. SmartcardExtension->SmartcardRequest.BufferLength);
  636. // extend read timeout if the card issued a WTX request
  637. if (SmartcardExtension->T1.Wtx)
  638. {
  639. SmartcardExtension->ReaderExtension->ReadTimeout =
  640. ( SmartcardExtension->T1.Wtx *
  641. SmartcardExtension->CardCapabilities.T1.BWT + 999L )/
  642. 1000L;
  643. }
  644. else
  645. {
  646. // restore timeout
  647. SmartcardExtension->ReaderExtension->ReadTimeout =
  648. (ULONG) (SmartcardExtension->CardCapabilities.T1.BWT / 1000);
  649. }
  650. // get response
  651. SmartcardExtension->SmartcardReply.BufferLength = 0;
  652. if( NTStatus == STATUS_SUCCESS )
  653. {
  654. NTStatus = IFReadSTCData(
  655. SmartcardExtension->ReaderExtension,
  656. SmartcardExtension->SmartcardReply.Buffer,
  657. 3);
  658. if( NTStatus == STATUS_SUCCESS )
  659. {
  660. ULONG Length;
  661. Length = (ULONG)SmartcardExtension->SmartcardReply.Buffer[ LEN_IDX ] + 1;
  662. if( Length + 3 < MIN_BUFFER_SIZE )
  663. {
  664. NTStatus = IFReadSTCData(
  665. SmartcardExtension->ReaderExtension,
  666. &SmartcardExtension->SmartcardReply.Buffer[ DATA_IDX ],
  667. Length);
  668. SmartcardExtension->SmartcardReply.BufferLength = Length + 3;
  669. }
  670. else
  671. {
  672. NTStatus = STATUS_BUFFER_TOO_SMALL;
  673. }
  674. }
  675. //
  676. // if STCRead detects an LRC error, ignore it (maybe CRC used). Timeouts will
  677. // be detected by the lib if len=0
  678. //
  679. if(( NTStatus == STATUS_CRC_ERROR ) || ( NTStatus == STATUS_IO_TIMEOUT ))
  680. {
  681. NTStatus = STATUS_SUCCESS;
  682. }
  683. if( NTStatus == STATUS_SUCCESS )
  684. {
  685. // let the lib evaluate the result & setup the next APDU
  686. NTStatus = SmartcardT1Reply( SmartcardExtension );
  687. }
  688. }
  689. }
  690. // continue if the lib wants to send the next packet
  691. } while( NTStatus == STATUS_MORE_PROCESSING_REQUIRED );
  692. if( NTStatus == STATUS_IO_TIMEOUT )
  693. {
  694. NTStatus = STATUS_DEVICE_PROTOCOL_ERROR;
  695. }
  696. SmartcardDebug( DEBUG_TRACE,( "%s!CBT1Transmit Exit: %X\n",DRIVER_NAME, NTStatus ));
  697. return ( NTStatus );
  698. }
  699. NTSTATUS
  700. CBRawTransmit(
  701. PSMARTCARD_EXTENSION SmartcardExtension)
  702. /*++
  703. CBRawTransmit:
  704. finishes the callback RDF_TRANSMIT for the RAW protocol
  705. Arguments:
  706. SmartcardExtension context of call
  707. Return Value:
  708. STATUS_UNSUCCESSFUL
  709. --*/
  710. {
  711. NTSTATUS NTStatus = STATUS_UNSUCCESSFUL;
  712. SmartcardDebug( DEBUG_TRACE, ("%s!CBRawTransmit Exit: %X\n",DRIVER_NAME, NTStatus ));
  713. return ( NTStatus );
  714. }
  715. NTSTATUS
  716. CBCardTracking(
  717. PSMARTCARD_EXTENSION SmartcardExtension)
  718. /*++
  719. CBCardTracking:
  720. callback handler for SMCLIB RDF_CARD_TRACKING. the requested event was
  721. validated by the smclib (i.e. a card removal request will only be passed
  722. if a card is present).
  723. for a win95 build STATUS_PENDING will be returned without any other action.
  724. for NT the cancel routine for the irp will be set to the drivers cancel
  725. routine.
  726. Arguments:
  727. SmartcardExtension context of call
  728. Return Value:
  729. STATUS_PENDING
  730. --*/
  731. {
  732. KIRQL CurrentIrql;
  733. SmartcardDebug(
  734. DEBUG_TRACE,
  735. ("%s!CBCardTracking Enter\n",
  736. DRIVER_NAME));
  737. // set cancel routine
  738. IoAcquireCancelSpinLock( &CurrentIrql );
  739. IoSetCancelRoutine(
  740. SmartcardExtension->OsData->NotificationIrp,
  741. StcUsbCancel);
  742. IoReleaseCancelSpinLock( CurrentIrql );
  743. SmartcardDebug(
  744. DEBUG_TRACE,
  745. ("%s!CBCardTracking Exit\n",
  746. DRIVER_NAME));
  747. return( STATUS_PENDING );
  748. }
  749. NTSTATUS
  750. CBUpdateCardState(
  751. PSMARTCARD_EXTENSION SmartcardExtension
  752. )
  753. /*++
  754. CBUpdateCardState:
  755. updates the variable CurrentState in SmartcardExtension
  756. Arguments:
  757. SmartcardExtension context of call
  758. Return Value:
  759. STATUS_SUCCESS
  760. --*/
  761. {
  762. NTSTATUS status = STATUS_SUCCESS;
  763. UCHAR cardStatus = 0;
  764. KIRQL irql;
  765. BOOLEAN stateChanged = FALSE;
  766. ULONG oldState;
  767. // read card state
  768. status = IFReadSTCRegister(
  769. SmartcardExtension->ReaderExtension,
  770. ADR_IO_CONFIG,
  771. 1,
  772. &cardStatus
  773. );
  774. oldState = SmartcardExtension->ReaderCapabilities.CurrentState;
  775. switch(status)
  776. {
  777. case STATUS_NO_MEDIA:
  778. SmartcardExtension->ReaderExtension->ErrorCounter = 0;
  779. SmartcardExtension->ReaderCapabilities.CurrentState =
  780. SCARD_ABSENT;
  781. break;
  782. case STATUS_MEDIA_CHANGED:
  783. SmartcardExtension->ReaderExtension->ErrorCounter = 0;
  784. SmartcardExtension->ReaderCapabilities.CurrentState =
  785. SCARD_PRESENT;
  786. break;
  787. case STATUS_SUCCESS:
  788. SmartcardExtension->ReaderExtension->ErrorCounter = 0;
  789. cardStatus &= M_SD;
  790. if( cardStatus == 0 )
  791. {
  792. SmartcardExtension->ReaderCapabilities.CurrentState =
  793. SCARD_ABSENT;
  794. }
  795. else if( SmartcardExtension->ReaderCapabilities.CurrentState <=
  796. SCARD_ABSENT )
  797. {
  798. SmartcardExtension->ReaderCapabilities.CurrentState =
  799. SCARD_PRESENT;
  800. }
  801. break;
  802. default:
  803. if( ++SmartcardExtension->ReaderExtension->ErrorCounter < ERROR_COUNTER_TRESHOLD )
  804. {
  805. // a unknown status was reported from the reader, so use the previous state
  806. SmartcardExtension->ReaderCapabilities.CurrentState = oldState;
  807. }
  808. else
  809. {
  810. SmartcardLogError(
  811. SmartcardExtension->OsData->DeviceObject,
  812. STATUS_DEVICE_DATA_ERROR,
  813. NULL,
  814. 0);
  815. // a report of SCARD_UNKNOWN will force the resource manager to
  816. // disconnect the reader
  817. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN;
  818. }
  819. break;
  820. }
  821. //
  822. // we need to update the card state if there was a card before hibernate
  823. // stand / by or when the current state has changed.
  824. //
  825. if (SmartcardExtension->ReaderExtension->CardPresent ||
  826. oldState <= SCARD_ABSENT &&
  827. SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT ||
  828. oldState > SCARD_ABSENT &&
  829. SmartcardExtension->ReaderCapabilities.CurrentState <= SCARD_ABSENT) {
  830. stateChanged = TRUE;
  831. SmartcardExtension->ReaderExtension->CardPresent = FALSE;
  832. }
  833. KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &irql);
  834. if(stateChanged && SmartcardExtension->OsData->NotificationIrp != NULL)
  835. {
  836. KIRQL CurrentIrql;
  837. PIRP pIrp;
  838. IoAcquireCancelSpinLock( &CurrentIrql );
  839. IoSetCancelRoutine( SmartcardExtension->OsData->NotificationIrp, NULL );
  840. IoReleaseCancelSpinLock( CurrentIrql );
  841. SmartcardExtension->OsData->NotificationIrp->IoStatus.Status =
  842. STATUS_SUCCESS;
  843. SmartcardExtension->OsData->NotificationIrp->IoStatus.Information = 0;
  844. SmartcardDebug(
  845. DEBUG_DRIVER,
  846. ("%s!CBUpdateCardState: Completing notification irp %lx\n",
  847. DRIVER_NAME,
  848. SmartcardExtension->OsData->NotificationIrp));
  849. pIrp = SmartcardExtension->OsData->NotificationIrp;
  850. SmartcardExtension->OsData->NotificationIrp = NULL;
  851. KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql);
  852. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  853. } else {
  854. KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, irql);
  855. }
  856. return status;
  857. }
  858. NTSTATUS
  859. CBSynchronizeSTC(
  860. PSMARTCARD_EXTENSION SmartcardExtension )
  861. /*++
  862. CBSynchronizeSTC:
  863. updates the card dependend data of the stc (wait times, ETU...)
  864. Arguments:
  865. SmartcardExtension context of call
  866. Return Value:
  867. STATUS_SUCCESS
  868. --*/
  869. {
  870. NTSTATUS NTStatus = STATUS_SUCCESS;
  871. PREADER_EXTENSION ReaderExtension;
  872. ULONG CWT,
  873. BWT,
  874. CGT,
  875. ETU;
  876. UCHAR Dl,
  877. Fl,
  878. N;
  879. PCLOCK_RATE_CONVERSION ClockRateConversion;
  880. PBIT_RATE_ADJUSTMENT BitRateAdjustment;
  881. ReaderExtension = SmartcardExtension->ReaderExtension;
  882. ClockRateConversion = SmartcardExtension->CardCapabilities.ClockRateConversion;
  883. BitRateAdjustment = SmartcardExtension->CardCapabilities.BitRateAdjustment;
  884. // cycle length
  885. Dl = SmartcardExtension->CardCapabilities.Dl;
  886. Fl = SmartcardExtension->CardCapabilities.Fl;
  887. ETU = ClockRateConversion[Fl & 0x0F].F;
  888. ETU /= BitRateAdjustment[ Dl & 0x0F ].DNumerator;
  889. ETU *= BitRateAdjustment[ Dl & 0x0F ].DDivisor;
  890. // ETU += (ETU % 2 == 0) ? 0 : 1;
  891. // a extra guard time of 0xFF means minimum delay in both directions
  892. N = SmartcardExtension->CardCapabilities.N;
  893. if( N == 0xFF )
  894. {
  895. N = 0;
  896. }
  897. // set character waiting & guard time
  898. switch ( SmartcardExtension->CardCapabilities.Protocol.Selected )
  899. {
  900. case SCARD_PROTOCOL_T0:
  901. CWT = 960 * SmartcardExtension->CardCapabilities.T0.WI;
  902. CGT = 14 + N; // 13 + N; cryptoflex error
  903. break;
  904. case SCARD_PROTOCOL_T1:
  905. CWT = 11 + ( 0x01 << SmartcardExtension->CardCapabilities.T1.CWI );
  906. BWT = 11 + ( 0x01 << SmartcardExtension->CardCapabilities.T1.BWI ) * 960;
  907. CGT = 15 + N ;//13 + N; // 12 + N; sicrypt error
  908. NTStatus = STCSetBWT( ReaderExtension, BWT * ETU );
  909. break;
  910. default:
  911. // restore default CGT
  912. CGT=13;
  913. STCSetCGT( ReaderExtension, CGT);
  914. NTStatus = STATUS_UNSUCCESSFUL;
  915. break;
  916. }
  917. if(( NTStatus == STATUS_SUCCESS ) && ETU )
  918. {
  919. NTStatus = STCSetETU( ReaderExtension, ETU );
  920. if( NTStatus == STATUS_SUCCESS )
  921. {
  922. NTStatus = STCSetCGT( ReaderExtension, CGT );
  923. if( NTStatus == STATUS_SUCCESS )
  924. {
  925. NTStatus = STCSetCWT( ReaderExtension, CWT * ETU );
  926. }
  927. }
  928. }
  929. return( NTStatus );
  930. }