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.

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