Leaked source code of windows server 2003
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.

856 lines
27 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) SCM Microsystems, 1998 - 1999
  6. //
  7. // File: stccmd.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #if defined( SMCLIB_VXD )
  11. #include "Driver98.h"
  12. #include "Serial98.h"
  13. #else
  14. #include "DriverNT.h"
  15. #include "SerialNT.h"
  16. #endif // SMCLIB_VXD
  17. #include "SerialIF.h"
  18. #include "STCCmd.h"
  19. #include "STC.h"
  20. const STC_REGISTER STCInitialize[] =
  21. {
  22. { ADR_SC_CONTROL, 0x01, 0x00 }, // reset
  23. { ADR_CLOCK_CONTROL, 0x01, 0x01 },
  24. { ADR_CLOCK_CONTROL, 0x01, 0x03 },
  25. { ADR_UART_CONTROL, 0x01, 0x27 },
  26. { ADR_UART_CONTROL, 0x01, 0x4F },
  27. { ADR_IO_CONFIG, 0x01, 0x02 }, // 0x10 eva board
  28. { ADR_FIFO_CONFIG, 0x01, 0x81 },
  29. { ADR_INT_CONTROL, 0x01, 0x11 },
  30. { 0x0E, 0x01, 0xC0 },
  31. { 0x00, 0x00, 0x00 },
  32. };
  33. const STC_REGISTER STCClose[] =
  34. {
  35. { ADR_INT_CONTROL, 0x01, 0x00 },
  36. { ADR_SC_CONTROL, 0x01, 0x00 }, // reset
  37. { ADR_UART_CONTROL, 0x01, 0x40 },
  38. { ADR_CLOCK_CONTROL, 0x01, 0x01 },
  39. { ADR_CLOCK_CONTROL, 0x01, 0x00 },
  40. { 0x00, 0x00, 0x00 },
  41. };
  42. NTSTATUS
  43. STCReset(
  44. PREADER_EXTENSION ReaderExtension,
  45. UCHAR Device,
  46. BOOLEAN WarmReset,
  47. PUCHAR pATR,
  48. PULONG pATRLength
  49. )
  50. /*++
  51. STCReset:
  52. performs a reset of ICC
  53. Arguments:
  54. ReaderExtension context of call
  55. Device device requested ( ICC_1, ICC_2, PSCR )
  56. WarmReset kind of ICC reset
  57. pATR ptr to ATR buffer, NULL if no ATR required
  58. pATRLength size of ATR buffer / length of ATR
  59. Return Value:
  60. STATUS_SUCCESS
  61. STATUS_NO_MEDIA
  62. STATUS_UNRECOGNIZED_MEDIA
  63. error values from IFRead / IFWrite
  64. --*/
  65. {
  66. NTSTATUS NTStatus = STATUS_SUCCESS;
  67. // set UART to autolearn mode
  68. NTStatus = STCInitUART( ReaderExtension, TRUE );
  69. if( NTStatus == STATUS_SUCCESS)
  70. {
  71. //
  72. // set default frequency for ATR
  73. //
  74. NTStatus = STCSetFDIV( ReaderExtension, FREQ_DIV );
  75. if( NTStatus == STATUS_SUCCESS && ( !WarmReset ))
  76. {
  77. //
  78. // deactivate contacts
  79. //
  80. NTStatus = STCPowerOff( ReaderExtension );
  81. }
  82. if( NTStatus == STATUS_SUCCESS)
  83. {
  84. //
  85. // set power to card
  86. //
  87. if( NTStatus == STATUS_SUCCESS)
  88. {
  89. NTStatus = STCPowerOn( ReaderExtension );
  90. if( NTStatus == STATUS_SUCCESS)
  91. {
  92. NTStatus = STCReadATR( ReaderExtension, pATR, pATRLength );
  93. }
  94. }
  95. }
  96. }
  97. if( NTStatus != STATUS_SUCCESS )
  98. {
  99. STCPowerOff( ReaderExtension );
  100. }
  101. return( NTStatus );
  102. }
  103. NTSTATUS
  104. STCReadATR(
  105. PREADER_EXTENSION ReaderExtension,
  106. PUCHAR pATR,
  107. PULONG pATRLen
  108. )
  109. {
  110. NTSTATUS NTStatus = STATUS_SUCCESS;
  111. UCHAR T0_Yx, T0_K, Protocol;
  112. ULONG ATRLen, BufferLength;
  113. ReaderExtension->ReadTimeout = 250;
  114. // read TS if active low reset
  115. BufferLength = *pATRLen;
  116. NTStatus = STCReadICC1(
  117. ReaderExtension,
  118. pATR,
  119. &BufferLength,
  120. 1
  121. );
  122. if( NTStatus == STATUS_IO_TIMEOUT )
  123. {
  124. NTStatus = STCSetRST( ReaderExtension, TRUE );
  125. if( NTStatus == STATUS_SUCCESS )
  126. {
  127. BufferLength = *pATRLen;
  128. NTStatus = STCReadICC1(
  129. ReaderExtension,
  130. pATR,
  131. &BufferLength,
  132. 1
  133. );
  134. }
  135. }
  136. ReaderExtension->ReadTimeout = 1200;
  137. Protocol = PROTOCOL_TO;
  138. ATRLen = 1;
  139. if( NTStatus == STATUS_SUCCESS )
  140. {
  141. BufferLength = *pATRLen - ATRLen;
  142. NTStatus = STCReadICC1(
  143. ReaderExtension,
  144. pATR + ATRLen,
  145. &BufferLength,
  146. 1
  147. );
  148. ATRLen++;
  149. if ( pATR[0] == 0x03 ) /* Direct convention */
  150. {
  151. pATR[0] = 0x3F;
  152. }
  153. if ( ( pATR[0] != 0x3F ) && ( pATR[0] != 0x3B ) )
  154. {
  155. NTStatus = STATUS_DATA_ERROR;
  156. }
  157. if( NTStatus == STATUS_SUCCESS )
  158. {
  159. ULONG Request;
  160. // number of historical bytes
  161. T0_K = (UCHAR) ( pATR[ATRLen-1] & 0x0F );
  162. // coding of TA, TB, TC, TD
  163. T0_Yx = (UCHAR) ( pATR[ATRLen-1] & 0xF0 ) >> 4;
  164. while(( NTStatus == STATUS_SUCCESS ) && T0_Yx )
  165. {
  166. UCHAR Mask;
  167. // evaluate presence of TA, TB, TC, TD
  168. Mask = T0_Yx;
  169. Request = 0;
  170. while( Mask )
  171. {
  172. if( Mask & 1 )
  173. {
  174. Request++;
  175. }
  176. Mask >>= 1;
  177. }
  178. BufferLength = *pATRLen - ATRLen;
  179. NTStatus = STCReadICC1(
  180. ReaderExtension,
  181. pATR + ATRLen,
  182. &BufferLength,
  183. Request
  184. );
  185. ATRLen += Request;
  186. if( T0_Yx & TDx )
  187. {
  188. // high nibble of TD codes the next set of TA, TB, TC, TD
  189. T0_Yx = ( pATR[ATRLen-1] & 0xF0 ) >> 4;
  190. // low nibble of TD codes the protocol
  191. Protocol = pATR[ATRLen-1] & 0x0F;
  192. }
  193. else
  194. {
  195. break;
  196. }
  197. }
  198. if( NTStatus == STATUS_SUCCESS )
  199. {
  200. // historical bytes
  201. BufferLength = *pATRLen - ATRLen;
  202. NTStatus = STCReadICC1(
  203. ReaderExtension,
  204. pATR + ATRLen,
  205. &BufferLength,
  206. T0_K
  207. );
  208. // check sum
  209. if( NTStatus == STATUS_SUCCESS )
  210. {
  211. ATRLen += T0_K;
  212. if( Protocol == PROTOCOL_T1 )
  213. {
  214. BufferLength = *pATRLen - ATRLen;
  215. NTStatus = STCReadICC1(
  216. ReaderExtension,
  217. pATR + ATRLen,
  218. &BufferLength,
  219. 1
  220. );
  221. if( NTStatus == STATUS_SUCCESS )
  222. {
  223. ATRLen++;
  224. }
  225. else if( NTStatus == STATUS_IO_TIMEOUT )
  226. {
  227. // some cards don't support the TCK
  228. NTStatus = STATUS_SUCCESS;
  229. }
  230. }
  231. }
  232. }
  233. }
  234. }
  235. if( NTStatus == STATUS_IO_TIMEOUT )
  236. {
  237. NTStatus = STATUS_UNRECOGNIZED_MEDIA;
  238. }
  239. if(NTStatus == STATUS_SUCCESS && pATRLen != NULL)
  240. {
  241. *pATRLen = ATRLen;
  242. }
  243. return( NTStatus );
  244. }
  245. NTSTATUS
  246. STCWriteICC1(
  247. PREADER_EXTENSION ReaderExtension,
  248. PUCHAR Data,
  249. ULONG DataLen
  250. )
  251. /*++
  252. Routine Description:
  253. Arguments:
  254. Return Value:
  255. --*/
  256. {
  257. NTSTATUS NTStatus = STATUS_SUCCESS;
  258. ULONG BytesWritten = 0, Partial;
  259. USHORT SW = 0;
  260. UCHAR IOData[STC_BUFFER_SIZE + 10];
  261. do
  262. {
  263. if(DataLen - BytesWritten > STC_BUFFER_SIZE - PACKET_OVERHEAD)
  264. {
  265. Partial = STC_BUFFER_SIZE - PACKET_OVERHEAD;
  266. }
  267. else
  268. {
  269. Partial = DataLen - BytesWritten;
  270. }
  271. IOData[NAD_IDX] = HOST_TO_ICC1;
  272. IOData[PCB_IDX] = PCB;
  273. IOData[LEN_IDX] = (UCHAR) Partial;
  274. SysCopyMemory(
  275. &IOData[DATA_IDX],
  276. Data + BytesWritten,
  277. Partial
  278. );
  279. IOData[Partial + 3] = IFCalcLRC(IOData, Partial + 3);
  280. NTStatus = IFWrite(
  281. ReaderExtension,
  282. IOData,
  283. Partial + 4
  284. );
  285. if( NTStatus == STATUS_SUCCESS )
  286. {
  287. // read the status back from the reader
  288. NTStatus = IFRead(
  289. ReaderExtension,
  290. IOData,
  291. 6
  292. );
  293. if(NTStatus == STATUS_SUCCESS &&
  294. *(PUSHORT) &IOData[DATA_IDX] != SW_SUCCESS ) {
  295. SmartcardDebug(
  296. DEBUG_ERROR,
  297. ("SCMSTCS!STCWriteICC1: Reader reported error %x\n",
  298. *(PUSHORT) &IOData[DATA_IDX])
  299. );
  300. NTStatus = STATUS_UNSUCCESSFUL;
  301. }
  302. }
  303. BytesWritten += Partial;
  304. } while(BytesWritten < DataLen && NTStatus == STATUS_SUCCESS);
  305. return NTStatus;
  306. }
  307. NTSTATUS
  308. STCReadICC1(
  309. PREADER_EXTENSION ReaderExtension,
  310. PUCHAR InData,
  311. PULONG InDataLen,
  312. ULONG BytesRead
  313. )
  314. {
  315. NTSTATUS NTStatus = STATUS_SUCCESS;
  316. UCHAR IOData[ STC_BUFFER_SIZE ];
  317. ULONG Total = 0;
  318. while(NTStatus == STATUS_SUCCESS && Total < BytesRead)
  319. {
  320. // read head
  321. NTStatus = IFRead( ReaderExtension, &IOData[0], 3 );
  322. if(NTStatus == STATUS_SUCCESS && IOData[LEN_IDX] < STC_BUFFER_SIZE - 4)
  323. {
  324. // read tail
  325. NTStatus = IFRead(
  326. ReaderExtension,
  327. &IOData[DATA_IDX],
  328. IOData[LEN_IDX] + 1
  329. );
  330. if( NTStatus == STATUS_SUCCESS )
  331. {
  332. if (IOData[NAD_IDX] == STC1_TO_HOST) {
  333. //
  334. // this is not good. We want to read smart card data,
  335. // but the reader sent us a status packet, which can
  336. // only mean that something went wrong
  337. //
  338. SmartcardDebug(
  339. DEBUG_ERROR,
  340. ( "SCMSTCS!STCReadICC1: Reader reported error %x\n",
  341. *(PUSHORT) &IOData[DATA_IDX])
  342. );
  343. NTStatus = STATUS_DEVICE_PROTOCOL_ERROR;
  344. break;
  345. }
  346. if (Total + IOData[LEN_IDX] > *InDataLen) {
  347. NTStatus = STATUS_BUFFER_TOO_SMALL;
  348. break;
  349. }
  350. SysCopyMemory( &InData[ Total ], &IOData[ DATA_IDX ], IOData[ LEN_IDX ] );
  351. Total += IOData[ LEN_IDX ];
  352. }
  353. }
  354. }
  355. *InDataLen = Total;
  356. return NTStatus;
  357. }
  358. NTSTATUS
  359. STCPowerOff( PREADER_EXTENSION ReaderExtension )
  360. /*++
  361. STCPowerOff:
  362. Deactivates the requested device
  363. Arguments:
  364. ReaderExtension context of call
  365. Return Value:
  366. STATUS_SUCCESS
  367. error values from IFRead / IFWrite
  368. --*/
  369. {
  370. NTSTATUS NTStatus = STATUS_SUCCESS;
  371. UCHAR SCCtrl;
  372. SCCtrl = 0x00;
  373. NTStatus = STCWriteSTCRegister( ReaderExtension, ADR_SC_CONTROL, 1, &SCCtrl );
  374. return( NTStatus );
  375. }
  376. NTSTATUS
  377. STCPowerOn( PREADER_EXTENSION ReaderExtension )
  378. /*++
  379. STCPowerOn:
  380. Deactivates the requested device
  381. Arguments:
  382. ReaderExtension context of call
  383. Return Value:
  384. STATUS_SUCCESS
  385. error values from IFRead / IFWrite
  386. --*/
  387. {
  388. NTSTATUS NTStatus = STATUS_SUCCESS;
  389. UCHAR SCCtrl;
  390. SCCtrl = 0x40; // vcc
  391. NTStatus = STCWriteSTCRegister( ReaderExtension, ADR_SC_CONTROL, 1, &SCCtrl );
  392. if( NTStatus == STATUS_SUCCESS )
  393. {
  394. SCCtrl = 0x41; // vpp
  395. NTStatus = STCWriteSTCRegister( ReaderExtension, ADR_SC_CONTROL, 1, &SCCtrl );
  396. if( NTStatus == STATUS_SUCCESS )
  397. {
  398. SCCtrl=0xD1; // vcc, clk, io
  399. NTStatus = STCWriteSTCRegister( ReaderExtension, ADR_SC_CONTROL, 1, &SCCtrl );
  400. }
  401. }
  402. return( NTStatus );
  403. }
  404. NTSTATUS
  405. STCSetRST(
  406. PREADER_EXTENSION ReaderExtension,
  407. BOOLEAN On
  408. )
  409. {
  410. NTSTATUS NTStatus = STATUS_SUCCESS;
  411. UCHAR SCCtrl;
  412. NTStatus = STCReadSTCRegister( ReaderExtension, ADR_SC_CONTROL, 1,&SCCtrl );
  413. if( NTStatus == STATUS_SUCCESS )
  414. {
  415. if( On )
  416. {
  417. SCCtrl |= 0x20;
  418. }
  419. else
  420. {
  421. SCCtrl &= ~0x20;
  422. }
  423. NTStatus = STCWriteSTCRegister( ReaderExtension, ADR_SC_CONTROL, 1,&SCCtrl );
  424. }
  425. return(NTStatus);
  426. }
  427. NTSTATUS
  428. STCConfigureSTC(
  429. PREADER_EXTENSION ReaderExtension,
  430. PSTC_REGISTER pConfiguration
  431. )
  432. {
  433. NTSTATUS NTStatus = STATUS_SUCCESS;
  434. UCHAR Value;
  435. do
  436. {
  437. if( pConfiguration->Register == ADR_INT_CONTROL )
  438. {
  439. // Read interrupt status register to acknoledge wrong states
  440. NTStatus = STCReadSTCRegister( ReaderExtension,ADR_INT_STATUS,1,&Value );
  441. }
  442. Value = (UCHAR)pConfiguration->Value;
  443. NTStatus = STCWriteSTCRegister(
  444. ReaderExtension,
  445. pConfiguration->Register,
  446. pConfiguration->Size,
  447. (PUCHAR)&pConfiguration->Value
  448. );
  449. // delay to stabilize the oscilator clock:
  450. if( pConfiguration->Register == ADR_CLOCK_CONTROL )
  451. {
  452. SysDelay( 50 );
  453. }
  454. pConfiguration++;
  455. } while(( NTStatus == STATUS_SUCCESS ) && ( pConfiguration->Size ));
  456. return (NTStatus);
  457. }
  458. NTSTATUS STCReadSTCRegister(
  459. PREADER_EXTENSION ReaderExtension,
  460. UCHAR Address,
  461. ULONG Size,
  462. PUCHAR pValue
  463. )
  464. {
  465. NTSTATUS NTStatus = STATUS_SUCCESS;
  466. UCHAR IOData[ STC_BUFFER_SIZE ] =
  467. {
  468. HOST_TO_STC1,
  469. PCB,
  470. 6,
  471. CLA_READ_REGISTER,
  472. INS_READ_REGISTER,
  473. 0x00,
  474. Address,
  475. 0x00,
  476. (UCHAR) Size
  477. };
  478. IOData[ 9 ] = IFCalcLRC( IOData, 9 );
  479. NTStatus = IFWrite( ReaderExtension, IOData, 10 );
  480. ASSERT(NTStatus == STATUS_SUCCESS);
  481. if( NTStatus == STATUS_SUCCESS )
  482. {
  483. NTStatus = IFRead( ReaderExtension, IOData, Size + 2 + 4 );
  484. if( NTStatus == STATUS_SUCCESS )
  485. {
  486. //
  487. // check return code & size
  488. //
  489. USHORT shrtBuf;
  490. RtlRetrieveUshort(&shrtBuf, &IOData[DATA_IDX + Size]);
  491. if( shrtBuf == SW_SUCCESS )
  492. {
  493. SysCopyMemory( pValue, &IOData[ DATA_IDX ] , Size );
  494. }
  495. else
  496. {
  497. ASSERT(FALSE);
  498. NTStatus = STATUS_DATA_ERROR;
  499. }
  500. }
  501. }
  502. return( NTStatus );
  503. }
  504. NTSTATUS
  505. STCWriteSTCRegister(
  506. PREADER_EXTENSION ReaderExtension,
  507. UCHAR Address,
  508. ULONG Size,
  509. PUCHAR pValue
  510. )
  511. {
  512. NTSTATUS NTStatus = STATUS_SUCCESS;
  513. UCHAR IOData[STC_BUFFER_SIZE] =
  514. {
  515. HOST_TO_STC1,
  516. PCB,
  517. (UCHAR)( 5+Size ),
  518. CLA_WRITE_REGISTER,
  519. INS_WRITE_REGISTER,
  520. 0x00,
  521. Address,
  522. (UCHAR) Size
  523. };
  524. SysCopyMemory( &IOData[ 8 ], pValue, Size );
  525. IOData[ 8+Size ] = IFCalcLRC( IOData, 8 + Size );
  526. NTStatus = IFWrite( ReaderExtension, IOData, 9 + Size );
  527. if( NTStatus == STATUS_SUCCESS )
  528. {
  529. NTStatus = IFRead( ReaderExtension, IOData, 6 );
  530. if(( NTStatus == STATUS_SUCCESS ) && ( *(PUSHORT)&IOData[ DATA_IDX ] != 0x0090 ))
  531. {
  532. NTStatus = STATUS_DATA_ERROR;
  533. }
  534. }
  535. return( NTStatus );
  536. }
  537. NTSTATUS
  538. STCSetETU(
  539. PREADER_EXTENSION ReaderExtension,
  540. ULONG NewETU
  541. )
  542. {
  543. NTSTATUS NTStatus = STATUS_DATA_ERROR;
  544. UCHAR ETU[2];
  545. if( NewETU < 0x0FFF )
  546. {
  547. NTStatus = STCReadSTCRegister(
  548. ReaderExtension,
  549. ADR_ETULENGTH15,
  550. 1,
  551. ETU
  552. );
  553. if( NTStatus == STATUS_SUCCESS )
  554. {
  555. //
  556. // save all RFU bits
  557. //
  558. ETU[1] = (UCHAR) NewETU;
  559. ETU[0] = (UCHAR)(( ETU[0] & 0xF0 ) | ( NewETU >> 8 ));
  560. NTStatus = STCWriteSTCRegister(
  561. ReaderExtension,
  562. ADR_ETULENGTH15,
  563. 2,
  564. ETU
  565. );
  566. }
  567. }
  568. return(NTStatus);
  569. }
  570. NTSTATUS
  571. STCSetCGT(
  572. PREADER_EXTENSION ReaderExtension,
  573. ULONG NewCGT
  574. )
  575. {
  576. NTSTATUS NTStatus = STATUS_DATA_ERROR;
  577. UCHAR CGT[2];
  578. if( NewCGT < 0x01FF )
  579. {
  580. NTStatus = STCReadSTCRegister(
  581. ReaderExtension,
  582. ADR_CGT8,
  583. 2,
  584. CGT
  585. );
  586. if( NTStatus == STATUS_SUCCESS )
  587. {
  588. //
  589. // save all RFU bits
  590. //
  591. CGT[1] = ( UCHAR )NewCGT;
  592. CGT[0] = (UCHAR)(( CGT[0] & 0xFE ) | ( NewCGT >> 8 ));
  593. NTStatus = STCWriteSTCRegister(
  594. ReaderExtension,
  595. ADR_CGT8,
  596. 2,
  597. CGT
  598. );
  599. }
  600. }
  601. return(NTStatus);
  602. }
  603. NTSTATUS
  604. STCSetCWT(
  605. PREADER_EXTENSION ReaderExtension,
  606. ULONG NewCWT
  607. )
  608. {
  609. NTSTATUS NTStatus = STATUS_SUCCESS;
  610. UCHAR CWT[4];
  611. // little indians...
  612. CWT[0] = (( PUCHAR )&NewCWT )[3];
  613. CWT[1] = (( PUCHAR )&NewCWT )[2];
  614. CWT[2] = (( PUCHAR )&NewCWT )[1];
  615. CWT[3] = (( PUCHAR )&NewCWT )[0];
  616. NTStatus = STCWriteSTCRegister( ReaderExtension, ADR_CWT31, 4, CWT );
  617. return(NTStatus);
  618. }
  619. NTSTATUS
  620. STCSetBWT(
  621. PREADER_EXTENSION ReaderExtension,
  622. ULONG NewBWT
  623. )
  624. {
  625. NTSTATUS NTStatus = STATUS_SUCCESS;
  626. UCHAR BWT[4];
  627. // little indians...
  628. BWT[0] = (( PUCHAR )&NewBWT )[3];
  629. BWT[1] = (( PUCHAR )&NewBWT )[2];
  630. BWT[2] = (( PUCHAR )&NewBWT )[1];
  631. BWT[3] = (( PUCHAR )&NewBWT )[0];
  632. NTStatus = STCWriteSTCRegister( ReaderExtension, ADR_BWT31, 4, BWT );
  633. return(NTStatus);
  634. }
  635. NTSTATUS
  636. STCSetFDIV(
  637. PREADER_EXTENSION ReaderExtension,
  638. ULONG Factor
  639. )
  640. {
  641. NTSTATUS NTStatus = STATUS_SUCCESS;
  642. UCHAR DIV;
  643. NTStatus = STCReadSTCRegister( ReaderExtension, ADR_ETULENGTH15, 1, &DIV );
  644. if( NTStatus == STATUS_SUCCESS )
  645. {
  646. switch( Factor )
  647. {
  648. case 1:
  649. DIV &= ~M_DIV0;
  650. DIV &= ~M_DIV1;
  651. break;
  652. case 2:
  653. DIV |= M_DIV0;
  654. DIV &= ~M_DIV1;
  655. break;
  656. case 4 :
  657. DIV &= ~M_DIV0;
  658. DIV |= M_DIV1;
  659. break;
  660. case 8 :
  661. DIV |= M_DIV0;
  662. DIV |= M_DIV1;
  663. break;
  664. default :
  665. NTStatus = STATUS_DATA_ERROR;
  666. }
  667. if( NTStatus == STATUS_SUCCESS )
  668. {
  669. NTStatus = STCWriteSTCRegister( ReaderExtension, ADR_ETULENGTH15, 1, &DIV );
  670. }
  671. }
  672. return(NTStatus);
  673. }
  674. NTSTATUS
  675. STCInitUART(
  676. PREADER_EXTENSION ReaderExtension,
  677. BOOLEAN AutoLearn
  678. )
  679. {
  680. NTSTATUS NTStatus = STATUS_SUCCESS;
  681. UCHAR Value;
  682. Value = AutoLearn ? 0x6F : 0x66;
  683. NTStatus = STCWriteSTCRegister( ReaderExtension, ADR_UART_CONTROL, 1, &Value );
  684. return( NTStatus );
  685. }
  686. NTSTATUS
  687. STCGetFirmwareRevision(
  688. PREADER_EXTENSION ReaderExtension
  689. )
  690. {
  691. NTSTATUS NTStatus = STATUS_SUCCESS;
  692. UCHAR IOData[ STC_BUFFER_SIZE ] =
  693. {
  694. HOST_TO_STC1,
  695. PCB,
  696. 6,
  697. CLA_READ_FIRMWARE_REVISION,
  698. INS_READ_FIRMWARE_REVISION,
  699. 0x00,
  700. 0x00,
  701. 0x00,
  702. 0x02
  703. };
  704. IOData[ 9 ] = IFCalcLRC( IOData, 9 );
  705. NTStatus = IFWrite( ReaderExtension, IOData, 10 );
  706. if( NTStatus == STATUS_SUCCESS )
  707. {
  708. NTStatus = IFRead( ReaderExtension, IOData, 6 );
  709. if( NTStatus == STATUS_SUCCESS )
  710. {
  711. ReaderExtension->FirmwareMajor = IOData[ DATA_IDX ];
  712. ReaderExtension->FirmwareMinor = IOData[ DATA_IDX + 1 ];
  713. }
  714. }
  715. return( STATUS_SUCCESS );
  716. }
  717. //---------------------------------------- END OF FILE ----------------------------------------