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.

976 lines
28 KiB

  1. /*++
  2. Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
  3. Module Name:
  4. PscrCmd.c
  5. Abstract:
  6. Basic command functions for SCM PSCR smartcard reader
  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 delay for read/write removed
  17. --*/
  18. #if defined( SMCLIB_VXD )
  19. #include <Pscr95.h>
  20. #else // SMCLIB_VXD
  21. #include <PscrNT.h>
  22. #endif // SMCLIB_VXD
  23. #include <PscrRdWr.h>
  24. #include <PscrCmd.h>
  25. NTSTATUS
  26. CmdResetInterface(
  27. PREADER_EXTENSION ReaderExtension
  28. )
  29. /*++
  30. CmdResetInterface:
  31. Performs a reset of the reader interface (NOT of the PCMCIA controller)
  32. - flush available data
  33. - set RESET bit
  34. - perform a buffer size exchange between reader & host
  35. - enables interrupts for freeze events
  36. - disables default PTS
  37. Arguments:
  38. ReaderExtension context of call
  39. Return Value:
  40. STATUS_SUCCESS
  41. STATUS_IO_DEVICE_ERROR
  42. --*/
  43. {
  44. NTSTATUS NTStatus = STATUS_SUCCESS;
  45. ULONG IOBytes;
  46. UCHAR Len,
  47. Tag,
  48. Cnt,
  49. InData[ TLV_BUFFER_SIZE ];
  50. PPSCR_REGISTERS IOBase;
  51. UCHAR EnableInterrupts[] = { 0x28, 0x01, 0x01};
  52. IOBase = ReaderExtension->IOBase;
  53. // discard any data
  54. PscrFlushInterface( ReaderExtension );
  55. // reset reader
  56. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_RESET_BIT );
  57. SysDelay( DELAY_WRITE_PSCR_REG );
  58. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
  59. NTStatus = PscrWait( ReaderExtension, PSCR_DATA_AVAIL_BIT );
  60. // read & check vendor string
  61. if ( NT_SUCCESS( NTStatus )) {
  62. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
  63. SysDelay( DELAY_WRITE_PSCR_REG );
  64. //
  65. // get actual len from TLV list
  66. //
  67. READ_PORT_UCHAR( &IOBase->SizeMSReg );
  68. READ_PORT_UCHAR( &IOBase->SizeLSReg );
  69. Tag = READ_PORT_UCHAR( &IOBase->DataReg );
  70. Len = READ_PORT_UCHAR( &IOBase->DataReg );
  71. //
  72. // avoid overwrite of buffer
  73. //
  74. if ( Len > TLV_BUFFER_SIZE ) {
  75. Len = TLV_BUFFER_SIZE;
  76. }
  77. for ( Cnt = 0; Cnt < Len; Cnt++ ) {
  78. InData[ Cnt ] = READ_PORT_UCHAR( &IOBase->DataReg );
  79. }
  80. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
  81. //
  82. // check vendor string
  83. //
  84. if ( SysCompareMemory(
  85. InData,
  86. PSCR_ID_STRING,
  87. sizeof( PSCR_ID_STRING )
  88. )) {
  89. NTStatus = STATUS_IO_DEVICE_ERROR;
  90. } else {
  91. //
  92. // vendor string was correct, check buffer size
  93. //
  94. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_SIZE_READ_BIT );
  95. NTStatus = PscrWait( ReaderExtension, PSCR_DATA_AVAIL_BIT );
  96. //
  97. // reader ready to transfer interface buffer size
  98. //
  99. if ( NT_SUCCESS( NTStatus )) {
  100. //
  101. // set size read & host control
  102. //
  103. WRITE_PORT_UCHAR(
  104. &IOBase->CmdStatusReg,
  105. PSCR_SIZE_READ_BIT | PSCR_HOST_CONTROL_BIT
  106. );
  107. SysDelay( DELAY_WRITE_PSCR_REG );
  108. //
  109. // read buffer length
  110. //
  111. Len = READ_PORT_UCHAR( &IOBase->SizeMSReg );
  112. Len = READ_PORT_UCHAR( &IOBase->SizeLSReg );
  113. for ( Cnt = 0; Cnt < Len; Cnt++ ) {
  114. InData[ Cnt ] = READ_PORT_UCHAR( &IOBase->DataReg );
  115. }
  116. //
  117. // transfer of interface buffer size okay
  118. //
  119. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
  120. SysDelay( DELAY_WRITE_PSCR_REG );
  121. //
  122. // notify the reader about the supported buffer size
  123. //
  124. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
  125. SysDelay( DELAY_WRITE_PSCR_REG );
  126. WRITE_PORT_UCHAR( &IOBase->SizeMSReg, 0 );
  127. WRITE_PORT_UCHAR( &IOBase->SizeLSReg, 2 );
  128. //
  129. // Write the same data buffer size as the one we just got.
  130. //
  131. WRITE_PORT_UCHAR( &IOBase->DataReg, InData[ 0 ] );
  132. WRITE_PORT_UCHAR( &IOBase->DataReg, InData[ 1 ] );
  133. //
  134. // store the size to report to the lib
  135. // The maximum buffer size of the reader is to betrieved with
  136. // ((ULONG)InData[ 1 ] << 8) | InData[ 0 ]
  137. //
  138. ReaderExtension->MaxIFSD = 254;
  139. //
  140. // let the reader process the size write command
  141. //
  142. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_SIZE_WRITE_BIT );
  143. NTStatus = PscrWait( ReaderExtension, PSCR_FREE_BIT );
  144. }
  145. }
  146. }
  147. //
  148. // clean up any host control settings
  149. //
  150. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
  151. //
  152. // enable interrupts
  153. //
  154. CmdSetInterfaceParameter(
  155. ReaderExtension,
  156. ReaderExtension->Device,
  157. EnableInterrupts,
  158. sizeof( EnableInterrupts )
  159. );
  160. return( NTStatus );
  161. }
  162. NTSTATUS
  163. CmdReset(
  164. PREADER_EXTENSION ReaderExtension,
  165. UCHAR Device,
  166. BOOLEAN WarmReset,
  167. PUCHAR pATR,
  168. PULONG pATRLength
  169. )
  170. /*++
  171. CmdReset:
  172. performs a reset of the reader / ICC
  173. Arguments:
  174. ReaderExtension context of call
  175. Device device requested ( ICC_1, ICC_2, PSCR )
  176. WarmReset kind of ICC reset
  177. pATR ptr to ATR buffer, NULL if no ATR required
  178. pATRLength size of ATR buffer / length of ATR
  179. Return Value:
  180. STATUS_SUCCESS
  181. STATUS_NO_MEDIA
  182. STATUS_UNRECOGNIZED_MEDIA
  183. error values from PscrRead / PscrWrite
  184. --*/
  185. {
  186. NTSTATUS NTStatus = STATUS_SUCCESS;
  187. UCHAR IOData[ MAX_T1_BLOCK_SIZE ],
  188. P2;
  189. USHORT ICCStatus;
  190. ULONG IOBytes;
  191. // ATR from the smartcard requestet? P2 = 1
  192. P2 = 0;
  193. if (( pATR != NULL ) && ( pATRLength != NULL )) {
  194. if ( *pATRLength > 0 )
  195. P2 = 0x01;
  196. }
  197. // build the RESET command.
  198. IOData[ PSCR_NAD ] = NAD_TO_PSCR;
  199. IOData[ PSCR_PCB ] = PCB_DEFAULT;
  200. IOData[ PSCR_LEN ] = 0x05;
  201. if ( WarmReset == TRUE ) {
  202. IOData[ PSCR_INF+0 ] = CLA_WARM_RESET;
  203. IOData[ PSCR_INF+1 ] = INS_WARM_RESET;
  204. } else {
  205. IOData[ PSCR_INF+0 ] = CLA_RESET;
  206. IOData[ PSCR_INF+1 ] = INS_RESET;
  207. }
  208. IOData[ PSCR_INF+2 ] = Device;
  209. IOData[ PSCR_INF+3 ] = P2;
  210. IOData[ PSCR_INF+4 ] = 0x00;
  211. // write command
  212. NTStatus = PscrWrite(
  213. ReaderExtension,
  214. IOData,
  215. 8,
  216. &IOBytes
  217. );
  218. if ( NT_SUCCESS( NTStatus )) {
  219. // read data
  220. IOBytes = 0;
  221. NTStatus = PscrRead(
  222. ReaderExtension,
  223. IOData,
  224. MAX_T1_BLOCK_SIZE,
  225. &IOBytes
  226. );
  227. // error detection
  228. if ( NT_SUCCESS( NTStatus )) {
  229. //
  230. // the location of the error code in the buffer
  231. // is: ( data ) - STATUS_MSB - STATUS_LSB - EPILOGUE
  232. //
  233. ICCStatus = (( USHORT )IOData[ IOBytes-PSCR_EPILOGUE_LENGTH-2 ]) << 8;
  234. ICCStatus |= ( USHORT )IOData[ IOBytes-PSCR_EPILOGUE_LENGTH-1 ];
  235. switch ( ICCStatus ) {
  236. case PSCR_SW_SYNC_ATR_SUCCESS:
  237. case PSCR_SW_ASYNC_ATR_SUCCESS:
  238. break;
  239. case PSCR_SW_NO_ICC:
  240. NTStatus = STATUS_NO_MEDIA;
  241. break;
  242. case PSCR_SW_NO_PROTOCOL:
  243. case PSCR_SW_NO_ATR:
  244. case PSCR_SW_NO_ATR_OR_PROTOCOL:
  245. case PSCR_SW_NO_ATR_OR_PROTOCOL2:
  246. case PSCR_SW_ICC_NOT_ACTIVE:
  247. case PSCR_SW_NON_SUPPORTED_PROTOCOL:
  248. case PSCR_SW_PROTOCOL_ERROR:
  249. default:
  250. NTStatus = STATUS_UNRECOGNIZED_MEDIA;
  251. }
  252. //
  253. // copy ATR if required
  254. //
  255. if ( NT_SUCCESS( NTStatus )) {
  256. if ( P2 == 0x01 ) {
  257. IOBytes -= PSCR_PROLOGUE_LENGTH + PSCR_EPILOGUE_LENGTH;
  258. if ( IOBytes > *pATRLength ) {
  259. IOBytes = *pATRLength;
  260. }
  261. SysCopyMemory(
  262. pATR,
  263. &IOData[ PSCR_PROLOGUE_LENGTH ],
  264. IOBytes
  265. );
  266. *pATRLength = IOBytes;
  267. }
  268. }
  269. }
  270. }
  271. return( NTStatus );
  272. }
  273. NTSTATUS
  274. CmdDeactivate(
  275. PREADER_EXTENSION ReaderExtension,
  276. UCHAR Device
  277. )
  278. /*++
  279. CmdDeactivate:
  280. Deactivates the requested device
  281. Arguments:
  282. ReaderExtension context of call
  283. Device requested device
  284. Return Value:
  285. STATUS_SUCCESS
  286. error values from PscrRead / PscrWrite
  287. --*/
  288. {
  289. NTSTATUS NTStatus = STATUS_SUCCESS;
  290. UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
  291. ULONG IOBytes;
  292. //
  293. // build the DEACTIVATE command.
  294. //
  295. IOData[ PSCR_NAD ] = NAD_TO_PSCR;
  296. IOData[ PSCR_PCB ] = PCB_DEFAULT;
  297. IOData[ PSCR_LEN ] = 0x05;
  298. IOData[ PSCR_INF+0 ] = CLA_DEACTIVATE;
  299. IOData[ PSCR_INF+1 ] = INS_DEACTIVATE;
  300. IOData[ PSCR_INF+2 ] = Device;
  301. IOData[ PSCR_INF+3 ] = 0x00;
  302. IOData[ PSCR_INF+4 ] = 0x00;
  303. //
  304. // write command
  305. //
  306. NTStatus = PscrWrite(
  307. ReaderExtension,
  308. IOData,
  309. 8,
  310. &IOBytes
  311. );
  312. if ( NT_SUCCESS( NTStatus )) {
  313. //
  314. // read data to trap communication errors
  315. //
  316. IOBytes = 0;
  317. NTStatus = PscrRead(
  318. ReaderExtension,
  319. IOData,
  320. MAX_T1_BLOCK_SIZE,
  321. &IOBytes
  322. );
  323. }
  324. return( NTStatus );
  325. }
  326. NTSTATUS
  327. CmdReadBinary(
  328. PREADER_EXTENSION ReaderExtension,
  329. USHORT Offset,
  330. PUCHAR pBuffer,
  331. PULONG pBufferLength
  332. )
  333. /*++
  334. CmdReadBinary:
  335. read binary data from an PSCR data file
  336. Arguments:
  337. ReaderExtension context of call
  338. Offset offset in file
  339. pBuffer ptr to data buffer
  340. pBufferLength length of buffer / number of bytes read
  341. Return Value:
  342. STATUS_SUCCESS
  343. STATUS_UNSUCCESSFUL
  344. error values from PscrRead / PscrWrite
  345. --*/
  346. {
  347. NTSTATUS NTStatus = STATUS_SUCCESS;
  348. UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
  349. USHORT ICCStatus;
  350. ULONG IOBytes;
  351. //
  352. // check parameters
  353. //
  354. if (( pBuffer == NULL ) || ( pBufferLength == NULL)) {
  355. NTStatus = STATUS_INVALID_PARAMETER;
  356. } else {
  357. //
  358. // build the READ BINARY command
  359. //
  360. IOData[ PSCR_NAD] = NAD_TO_PSCR;
  361. IOData[ PSCR_PCB] = PCB_DEFAULT;
  362. IOData[ PSCR_LEN] = 0x05;
  363. IOData[ PSCR_INF+0 ] = CLA_READ_BINARY;
  364. IOData[ PSCR_INF+1 ] = INS_READ_BINARY;
  365. IOData[ PSCR_INF+2 ] = HIBYTE( Offset );
  366. IOData[ PSCR_INF+3 ] = LOBYTE( Offset );
  367. IOData[ PSCR_INF+4 ] = 0x00;
  368. //
  369. // write command
  370. //
  371. NTStatus = PscrWrite(
  372. ReaderExtension,
  373. IOData,
  374. 8,
  375. &IOBytes
  376. );
  377. if ( NT_SUCCESS( NTStatus )) {
  378. //
  379. // read data
  380. //
  381. IOBytes = 0;
  382. NTStatus = PscrRead(
  383. ReaderExtension,
  384. IOData,
  385. MAX_T1_BLOCK_SIZE,
  386. &IOBytes
  387. );
  388. if ( NT_SUCCESS( NTStatus )) {
  389. //
  390. // error check
  391. //
  392. ICCStatus =
  393. ((USHORT)IOData[ IOBytes-2-PSCR_EPILOGUE_LENGTH ]) << 8;
  394. ICCStatus |=
  395. (USHORT)IOData[ IOBytes-1-PSCR_EPILOGUE_LENGTH ];
  396. switch ( ICCStatus ) {
  397. case PSCR_SW_FILE_NO_ACCEPPTED_AUTH:
  398. case PSCR_SW_FILE_NO_ACCESS:
  399. case PSCR_SW_FILE_BAD_OFFSET:
  400. case PSCR_SW_END_OF_FILE_READ:
  401. NTStatus = STATUS_UNSUCCESSFUL;
  402. break;
  403. default:
  404. break;
  405. }
  406. //
  407. // copy data
  408. //
  409. if ( NT_SUCCESS( NTStatus )) {
  410. if ( *pBufferLength <
  411. IOBytes-PSCR_PROLOGUE_LENGTH-PSCR_STATUS_LENGTH ) {
  412. NTStatus = STATUS_BUFFER_TOO_SMALL;
  413. } else {
  414. ( *pBufferLength ) =
  415. IOBytes-PSCR_PROLOGUE_LENGTH-PSCR_STATUS_LENGTH;
  416. SysCopyMemory(
  417. pBuffer,
  418. &IOData[ PSCR_PROLOGUE_LENGTH ],
  419. *pBufferLength
  420. );
  421. }
  422. }
  423. }
  424. }
  425. }
  426. return( NTStatus );
  427. }
  428. NTSTATUS
  429. CmdSelectFile(
  430. PREADER_EXTENSION ReaderExtension,
  431. USHORT FileId
  432. )
  433. /*++
  434. CmdSelectFile:
  435. selects a file/directoy of the reader
  436. Arguments:
  437. ReaderExtension context of call
  438. FileId ID of file
  439. Return Value:
  440. STATUS_SUCCESS
  441. STATUS_UNSUCCESSFUL
  442. error values from PscrRead / PscrWrite
  443. --*/
  444. {
  445. NTSTATUS NTStatus = STATUS_SUCCESS;
  446. UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
  447. USHORT ICCStatus;
  448. ULONG IOBytes;
  449. //
  450. // build the SELECT FILE command
  451. //
  452. IOData[ PSCR_NAD ] = NAD_TO_PSCR;
  453. IOData[ PSCR_PCB ] = PCB_DEFAULT;
  454. IOData[ PSCR_LEN ] = 0x07;
  455. IOData[ PSCR_INF+0 ] = CLA_SELECT_FILE;
  456. IOData[ PSCR_INF+1 ] = INS_SELECT_FILE;
  457. IOData[ PSCR_INF+2 ] = 0x00;
  458. IOData[ PSCR_INF+3 ] = 0x00;
  459. IOData[ PSCR_INF+4 ] = 0x02;
  460. IOData[ PSCR_INF+5 ] = HIBYTE( FileId );
  461. IOData[ PSCR_INF+6 ] = LOBYTE( FileId );
  462. //
  463. // write command
  464. //
  465. NTStatus = PscrWrite(
  466. ReaderExtension,
  467. IOData,
  468. 10,
  469. &IOBytes
  470. );
  471. if ( NT_SUCCESS( NTStatus )) {
  472. //
  473. // get the response of the reader
  474. //
  475. IOBytes = 0;
  476. NTStatus = PscrRead(
  477. ReaderExtension,
  478. IOData,
  479. MAX_T1_BLOCK_SIZE,
  480. &IOBytes
  481. );
  482. if ( NT_SUCCESS( NTStatus )) {
  483. //
  484. // check errors
  485. //
  486. ICCStatus =
  487. ((USHORT)IOData[ IOBytes-2-PSCR_EPILOGUE_LENGTH ]) << 8;
  488. ICCStatus |=
  489. (USHORT)IOData[ IOBytes-1-PSCR_EPILOGUE_LENGTH ];
  490. if ( ICCStatus == PSCR_SW_FILE_NOT_FOUND ) {
  491. NTStatus = STATUS_UNSUCCESSFUL;
  492. }
  493. }
  494. }
  495. return( NTStatus );
  496. }
  497. NTSTATUS
  498. CmdSetInterfaceParameter(
  499. PREADER_EXTENSION ReaderExtension,
  500. UCHAR Device,
  501. PUCHAR pTLVList,
  502. UCHAR TLVListLen
  503. )
  504. /*++
  505. CmdSetInterfaceParameter:
  506. Sets the interface pareameter of the ICC interface to the values specified
  507. in the TLV list
  508. Arguments:
  509. ReaderExtension context of call
  510. Device device
  511. pTLVList ptr to list of tag-len-value's specified by caller
  512. TLVListLen length of list
  513. Return Value:
  514. STATUS_SUCCESS
  515. STATUS_INVALID_PARAMETER
  516. STATUS_INVALID_DEVICE_STATE
  517. error values from PscrRead / PscrWrite
  518. --*/
  519. {
  520. NTSTATUS NTStatus = STATUS_SUCCESS;
  521. UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
  522. USHORT ICCStatus;
  523. ULONG IOBytes;
  524. //
  525. // check parameter
  526. //
  527. if ( pTLVList == NULL ) {
  528. NTStatus = STATUS_INVALID_PARAMETER;
  529. } else {
  530. //
  531. // build the SET INTERFACE PARAMETER command
  532. //
  533. IOData[ PSCR_NAD ] = NAD_TO_PSCR;
  534. IOData[ PSCR_PCB ] = PCB_DEFAULT;
  535. IOData[ PSCR_LEN ] = 0x05 + TLVListLen;
  536. IOData[ PSCR_INF+0 ] = CLA_SET_INTERFACE_PARAM;
  537. IOData[ PSCR_INF+1 ] = INS_SET_INTERFACE_PARAM;
  538. IOData[ PSCR_INF+2 ] = Device;
  539. IOData[ PSCR_INF+3 ] = 0x00;
  540. IOData[ PSCR_INF+4 ] = TLVListLen;
  541. SysCopyMemory( &IOData[ PSCR_INF+5 ], pTLVList, TLVListLen );
  542. //
  543. // write command
  544. //
  545. NTStatus = PscrWrite(
  546. ReaderExtension,
  547. IOData,
  548. 8 + TLVListLen,
  549. &IOBytes
  550. );
  551. if ( NT_SUCCESS( NTStatus )) {
  552. // do an dummy read to catch errors.
  553. IOBytes = 0;
  554. NTStatus = PscrRead(
  555. ReaderExtension,
  556. IOData,
  557. MAX_T1_BLOCK_SIZE,
  558. &IOBytes
  559. );
  560. if ( NT_SUCCESS( NTStatus )) {
  561. // check error
  562. ICCStatus =
  563. ((USHORT)IOData[ IOBytes - 2 - PSCR_EPILOGUE_LENGTH ]) << 8;
  564. ICCStatus |=
  565. (USHORT)IOData[ IOBytes - 1 - PSCR_EPILOGUE_LENGTH ];
  566. if ( ICCStatus != 0x9000 ) {
  567. NTStatus = STATUS_INVALID_DEVICE_STATE;
  568. }
  569. }
  570. }
  571. }
  572. return( NTStatus );
  573. }
  574. NTSTATUS
  575. CmdReadStatusFile (
  576. PREADER_EXTENSION ReaderExtension,
  577. UCHAR Device,
  578. PUCHAR pTLVList,
  579. PULONG pTLVListLen
  580. )
  581. /*++
  582. CmdReadStatusFile:
  583. read the status file of the requested device from the reader filesystem
  584. Arguments:
  585. ReaderExtension context of call
  586. Device requested device
  587. pTLVList ptr to list (i.e. the status file)
  588. pTLVListLen length of buffer / returned list
  589. Return Value:
  590. STATUS_SUCCESS
  591. STATUS_BUFFER_TOO_SMALL
  592. error values from PscrRead / PscrWrite
  593. --*/
  594. {
  595. NTSTATUS NTStatus = STATUS_UNSUCCESSFUL;
  596. UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
  597. ULONG IOBytes;
  598. // select ICC status file if it's not the active file
  599. if ( ReaderExtension->StatusFileSelected == FALSE ) {
  600. // select master file on reader
  601. NTStatus = CmdSelectFile( ReaderExtension, FILE_MASTER );
  602. // select ICC directory
  603. if ( NT_SUCCESS( NTStatus )) {
  604. if ( Device != DEVICE_ICC1 ) {
  605. NTStatus = STATUS_UNSUCCESSFUL;
  606. } else {
  607. NTStatus = CmdSelectFile(
  608. ReaderExtension,
  609. FILE_ICC1_DIR
  610. );
  611. // select status file
  612. if ( NT_SUCCESS( NTStatus )) {
  613. NTStatus = CmdSelectFile(
  614. ReaderExtension,
  615. FILE_ICC1_DIR_STATUS
  616. );
  617. if ( NT_SUCCESS( NTStatus )) {
  618. ReaderExtension->StatusFileSelected = TRUE;
  619. }
  620. }
  621. }
  622. }
  623. }
  624. // read status file if successful selected
  625. if ( ReaderExtension->StatusFileSelected == TRUE ) {
  626. IOBytes = MAX_T1_BLOCK_SIZE;
  627. NTStatus = CmdReadBinary(
  628. ReaderExtension,
  629. 0,
  630. IOData,
  631. &IOBytes
  632. );
  633. // copy data to user buffer
  634. if ( NT_SUCCESS( NTStatus )) {
  635. if (( pTLVList != NULL ) && ( IOBytes < *pTLVListLen )) {
  636. *pTLVListLen = IOBytes;
  637. SysCopyMemory( pTLVList, IOData, IOBytes );
  638. } else {
  639. NTStatus = STATUS_BUFFER_TOO_SMALL;
  640. }
  641. }
  642. }
  643. return( NTStatus );
  644. }
  645. NTSTATUS
  646. CmdGetFirmwareRevision (
  647. PREADER_EXTENSION ReaderExtension
  648. )
  649. /*++
  650. CmdGetFirmwareRevision:
  651. get the firmware revision of the reader. Ther firmware revision is found
  652. in the PSCR configuration file (ID 0x0020) in the master directory.
  653. The tag of the revision is 0x0F, and the value is coded as an ASCII string,
  654. p.E. "2.20"
  655. Arguments:
  656. ReaderExtension context of call
  657. Return Value:
  658. STATUS_SUCCESS
  659. error values from PscrRead / PscrWrite
  660. --*/
  661. {
  662. NTSTATUS NTStatus = STATUS_SUCCESS;
  663. UCHAR TLVList[ MAX_T1_BLOCK_SIZE ],
  664. Len;
  665. char Revision[ 0x10 ],
  666. UpdateKey[ 0x10 ];
  667. ULONG IOBytes;
  668. //
  669. // select master file on reader
  670. //
  671. NTStatus = CmdSelectFile( ReaderExtension, FILE_MASTER );
  672. //
  673. // select pscr configuration file
  674. //
  675. if ( NT_SUCCESS( NTStatus )) {
  676. NTStatus = CmdSelectFile( ReaderExtension, FILE_PSCR_CONFIG );
  677. //
  678. // read confiuration file
  679. //
  680. if ( NT_SUCCESS( NTStatus )) {
  681. IOBytes = MAX_T1_BLOCK_SIZE;
  682. NTStatus = CmdReadBinary(
  683. ReaderExtension,
  684. 0,
  685. TLVList,
  686. &IOBytes
  687. );
  688. //
  689. // get the value of revison
  690. //
  691. if ( NT_SUCCESS( NTStatus )) {
  692. Len = sizeof(Revision);
  693. CmdGetTagValue(
  694. TAG_SOFTWARE_REV,
  695. TLVList,
  696. IOBytes,
  697. &Len,
  698. Revision
  699. );
  700. //
  701. // the coding is always X.YY (in ASCII), so we can get the numeric
  702. // values hardcoded by taking the low nibbles of the char's.
  703. //
  704. ReaderExtension->FirmwareMajor = Revision[0] & 0x0F;
  705. ReaderExtension->FirmwareMinor = ( Revision[2] & 0x0F ) << 4;
  706. ReaderExtension->FirmwareMinor |= Revision[3] & 0x0F;
  707. //
  708. // get value of update key
  709. //
  710. Len = sizeof(UpdateKey);
  711. CmdGetTagValue(
  712. TAG_UPDATE_KEY,
  713. TLVList,
  714. IOBytes,
  715. &Len,
  716. UpdateKey
  717. );
  718. ReaderExtension->UpdateKey = UpdateKey[0];
  719. }
  720. }
  721. }
  722. ReaderExtension->StatusFileSelected = FALSE;
  723. return( NTStatus );
  724. }
  725. NTSTATUS
  726. CmdPscrCommand (
  727. PREADER_EXTENSION ReaderExtension,
  728. PUCHAR pInData,
  729. ULONG InDataLen,
  730. PUCHAR pOutData,
  731. ULONG OutDataLen,
  732. PULONG pNBytes
  733. )
  734. /*++
  735. CmdPscrCommand:
  736. send a command transparent to the reader
  737. Arguments:
  738. ReaderExtension context of call
  739. pInData, ptr to input buffer
  740. InDataLen, len of input buffer
  741. pOutData, ptr to output buffer
  742. OutDataLen, len of output buffer
  743. pNBytes number of bytes transferred
  744. Return Value:
  745. STATUS_SUCCESS
  746. STATUS_INVALID_PARAMETER
  747. error values from PscrRead / PscrWrite
  748. --*/
  749. {
  750. NTSTATUS NTStatus = STATUS_SUCCESS;
  751. UCHAR IOData[ MAX_T1_BLOCK_SIZE ] = { 0};
  752. ULONG IOBytes;
  753. //
  754. // the function is used for generic ioctl's, so carful ALL
  755. // parametes will be checked!
  756. //
  757. if ( ( pInData == NULL ) ||
  758. ( pOutData == NULL ) ||
  759. ( pNBytes == NULL ) ||
  760. (InDataLen == 0 ) ||
  761. (OutDataLen == 0 )
  762. ) {
  763. NTStatus = STATUS_INVALID_PARAMETER;
  764. } else {
  765. IOBytes = 0;
  766. NTStatus = PscrWriteDirect(
  767. ReaderExtension,
  768. pInData,
  769. InDataLen,
  770. &IOBytes
  771. );
  772. if ( NT_SUCCESS( NTStatus )) {
  773. //
  774. // get result. ignore all reader errors
  775. //
  776. IOBytes = 0;
  777. NTStatus = PscrRead(
  778. ReaderExtension,
  779. IOData,
  780. MAX_T1_BLOCK_SIZE,
  781. &IOBytes
  782. );
  783. //
  784. // tranfer data
  785. //
  786. if ( IOBytes > OutDataLen ) {
  787. NTStatus = STATUS_BUFFER_TOO_SMALL;
  788. } else {
  789. *pNBytes = IOBytes;
  790. SysCopyMemory( pOutData, IOData, IOBytes );
  791. }
  792. }
  793. }
  794. return( NTStatus );
  795. }
  796. NTSTATUS
  797. CmdGetTagValue (
  798. UCHAR Tag,
  799. PUCHAR pTLVList,
  800. ULONG TLVListLen,
  801. PUCHAR pTagLen,
  802. PVOID pTagVal
  803. )
  804. /*++
  805. CmdGetTagValue:
  806. scans a TLV list for the value of a user specified tag
  807. it is assumed, the caller knows the kind of the requested
  808. field, so only the ptr to the buffer will be checked
  809. Arguments:
  810. Tag requested Tag
  811. pTLVList ptr to list
  812. TLVListLen length of list
  813. pTagLen ptr to length
  814. pTagVal ptr to value
  815. Return Value:
  816. STATUS_SUCCESS
  817. STATUS_UNSUCCESSFUL
  818. STATUS_INVALID_PARAMETER
  819. --*/
  820. {
  821. NTSTATUS NTStatus = STATUS_SUCCESS;
  822. ULONG Idx;
  823. UCHAR maxLen = *pTagLen;
  824. //
  825. // step through the given list
  826. //
  827. if (( pTLVList != NULL ) && ( pTagVal != NULL ) && ( pTagLen != NULL )) {
  828. //
  829. // look for requested tag
  830. //
  831. Idx = 0;
  832. while ( Idx < TLVListLen ) {
  833. if ( pTLVList[ Idx ] == Tag ) {
  834. //
  835. // ASSUMED THE CALLER KNOWS KIND OF FIELD!!!
  836. //
  837. if (pTLVList[Idx+1] > maxLen) {
  838. NTStatus = STATUS_UNSUCCESSFUL;
  839. break;
  840. }
  841. *pTagLen = pTLVList[ Idx + 1 ];
  842. SysCopyMemory(
  843. pTagVal,
  844. &pTLVList[ Idx+2 ],
  845. pTLVList[ Idx+1 ]
  846. );
  847. break;
  848. }
  849. Idx += pTLVList[ Idx+1 ] + 2;
  850. }
  851. if ( Idx >= TLVListLen ) {
  852. NTStatus = STATUS_UNSUCCESSFUL;
  853. }
  854. } else {
  855. NTStatus = STATUS_INVALID_PARAMETER;
  856. }
  857. return( NTStatus );
  858. }
  859. // ------------------------------- END OF FILE -------------------------------