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.

765 lines
15 KiB

  1. /*++
  2. Copyright (c) 1997 SCM Microsystems, Inc.
  3. Module Name:
  4. StcCmd.c
  5. Abstract:
  6. Basic command functions for STC smartcard reader
  7. Environment:
  8. Revision History:
  9. PP 01.19.1999 1.01 Modification for PC/SC
  10. YL 1.00 Initial Version
  11. --*/
  12. #include "common.h"
  13. #include "StcCmd.h"
  14. #include "usbcom.h"
  15. #include "stcusbnt.h"
  16. const STC_REGISTER STCInitialize[] =
  17. {
  18. { ADR_SC_CONTROL, 0x01, 0x00 }, // reset
  19. { ADR_CLOCK_CONTROL, 0x01, 0x01 },
  20. { ADR_CLOCK_CONTROL, 0x01, 0x03 },
  21. { ADR_UART_CONTROL, 0x01, 0x27 },
  22. { ADR_UART_CONTROL, 0x01, 0x4F },
  23. { ADR_IO_CONFIG, 0x01, 0x02 }, // 0x10 eva board
  24. { ADR_FIFO_CONFIG, 0x01, 0x81 },
  25. { ADR_INT_CONTROL, 0x01, 0x11 },
  26. { 0x0E, 0x01, 0xC0 },
  27. { 0x00, 0x00, 0x00 },
  28. };
  29. const STC_REGISTER STCClose[] =
  30. {
  31. { ADR_INT_CONTROL, 0x01, 0x00 },
  32. { ADR_SC_CONTROL, 0x01, 0x00 }, // reset
  33. { ADR_UART_CONTROL, 0x01, 0x40 },
  34. { ADR_CLOCK_CONTROL, 0x01, 0x01 },
  35. { ADR_CLOCK_CONTROL, 0x01, 0x00 },
  36. { 0x00, 0x00, 0x00 },
  37. };
  38. NTSTATUS
  39. STCResetInterface(
  40. PREADER_EXTENSION ReaderExtension)
  41. /*++
  42. Description:
  43. Arguments:
  44. ReaderExtension context of call
  45. Return Value:
  46. --*/
  47. {
  48. NTSTATUS NtStatus = STATUS_SUCCESS;
  49. DWORD dwETU;
  50. dwETU = 0x7401 | 0x0080;
  51. NtStatus=IFWriteSTCRegister(
  52. ReaderExtension,
  53. ADR_ETULENGTH15,
  54. 2,
  55. (UCHAR *)&dwETU);
  56. return(NtStatus);
  57. }
  58. NTSTATUS
  59. STCReset(
  60. PREADER_EXTENSION ReaderExtension,
  61. UCHAR Device,
  62. BOOLEAN WarmReset,
  63. PUCHAR pATR,
  64. PULONG pATRLength)
  65. /*++
  66. Description:
  67. performs a reset of ICC
  68. Arguments:
  69. ReaderExtension context of call
  70. Device device requested
  71. WarmReset kind of ICC reset
  72. pATR ptr to ATR buffer, NULL if no ATR required
  73. pATRLength size of ATR buffer / length of ATR
  74. Return Value:
  75. STATUS_SUCCESS
  76. STATUS_NO_MEDIA
  77. STATUS_UNRECOGNIZED_MEDIA
  78. error values from IFRead / IFWrite
  79. --*/
  80. {
  81. NTSTATUS NTStatus = STATUS_SUCCESS;
  82. // set UART to autolearn mode
  83. NTStatus = STCInitUART( ReaderExtension, TRUE );
  84. if( NTStatus == STATUS_SUCCESS)
  85. {
  86. //
  87. // set default frequency for ATR
  88. //
  89. NTStatus = STCSetFDIV( ReaderExtension, FREQ_DIV );
  90. if( NTStatus == STATUS_SUCCESS && ( !WarmReset ))
  91. {
  92. //
  93. // deactivate contacts
  94. //
  95. NTStatus = STCPowerOff( ReaderExtension );
  96. }
  97. //
  98. // set power to card
  99. //
  100. if( NTStatus == STATUS_SUCCESS)
  101. {
  102. NTStatus = STCPowerOn( ReaderExtension );
  103. if( NTStatus == STATUS_SUCCESS)
  104. {
  105. NTStatus = STCReadATR( ReaderExtension, pATR, pATRLength );
  106. }
  107. }
  108. }
  109. if( NTStatus != STATUS_SUCCESS )
  110. {
  111. STCPowerOff( ReaderExtension );
  112. }
  113. return( NTStatus );
  114. }
  115. NTSTATUS
  116. STCReadATR(
  117. PREADER_EXTENSION ReaderExtension,
  118. PUCHAR pATR,
  119. PULONG pATRLen)
  120. /*++
  121. Description:
  122. Read and analize the ATR
  123. Arguments:
  124. ReaderExtension context of call
  125. pATR ptr to ATR buffer,
  126. pATRLen size of ATR buffer / length of ATR
  127. Return Value:
  128. --*/
  129. {
  130. NTSTATUS NTStatus = STATUS_SUCCESS;
  131. UCHAR T0_Yx,
  132. T0_K, // number of historical bytes
  133. Protocol;
  134. ULONG ATRLen;
  135. //
  136. // set read timeout for ATR
  137. //
  138. ReaderExtension->ReadTimeout = 250; // only 250ms for this firs ATR
  139. //
  140. // read TS if active low reset
  141. //
  142. NTStatus = IFReadSTCData( ReaderExtension, pATR, 1 );
  143. if( NTStatus == STATUS_IO_TIMEOUT )
  144. {
  145. ReaderExtension->ReadTimeout = 2500;
  146. NTStatus = STCSetRST( ReaderExtension, TRUE );
  147. if( NTStatus == STATUS_SUCCESS )
  148. {
  149. NTStatus = IFReadSTCData( ReaderExtension, pATR, 1 );
  150. }
  151. }
  152. Protocol = PROTOCOL_TO;
  153. ATRLen = 1;
  154. if( NTStatus == STATUS_SUCCESS )
  155. {
  156. // T0
  157. NTStatus = IFReadSTCData( ReaderExtension, pATR + ATRLen, 1 );
  158. ATRLen++;
  159. /* Convention management */
  160. if ( pATR[0] == 0x03 ) /* Direct convention */
  161. {
  162. pATR[0] = 0x3F;
  163. }
  164. if ( ( pATR[0] != 0x3F ) && ( pATR[0] != 0x3B ) )
  165. {
  166. NTStatus = STATUS_DATA_ERROR;
  167. }
  168. if( NTStatus == STATUS_SUCCESS )
  169. {
  170. ULONG Request;
  171. // number of historical bytes
  172. T0_K = (UCHAR) ( pATR[ATRLen-1] & 0x0F );
  173. // coding of TA, TB, TC, TD
  174. T0_Yx = (UCHAR) ( pATR[ATRLen-1] & 0xF0 ) >> 4;
  175. while(( NTStatus == STATUS_SUCCESS ) && T0_Yx )
  176. {
  177. UCHAR Mask;
  178. // evaluate presence of TA, TB, TC, TD
  179. Mask = T0_Yx;
  180. Request = 0;
  181. while( Mask )
  182. {
  183. if( Mask & 1 )
  184. {
  185. Request++;
  186. }
  187. Mask >>= 1;
  188. }
  189. NTStatus = IFReadSTCData( ReaderExtension, pATR + ATRLen, Request );
  190. ATRLen += Request;
  191. if( T0_Yx & TDx )
  192. {
  193. // high nibble of TD codes the next set of TA, TB, TC, TD
  194. T0_Yx = ( pATR[ATRLen-1] & 0xF0 ) >> 4;
  195. // low nibble of TD codes the protocol
  196. Protocol = pATR[ATRLen-1] & 0x0F;
  197. }
  198. else
  199. {
  200. break;
  201. }
  202. }
  203. if( NTStatus == STATUS_SUCCESS )
  204. {
  205. // historical bytes
  206. NTStatus = IFReadSTCData( ReaderExtension, pATR + ATRLen, T0_K );
  207. // check sum
  208. if( NTStatus == STATUS_SUCCESS )
  209. {
  210. ATRLen += T0_K;
  211. if( Protocol >= PROTOCOL_T1 )
  212. {
  213. NTStatus = IFReadSTCData( ReaderExtension, pATR + ATRLen, 1 );
  214. if( NTStatus == STATUS_SUCCESS )
  215. {
  216. ATRLen++;
  217. }
  218. else if( NTStatus == STATUS_IO_TIMEOUT )
  219. {
  220. // some cards don't support the TCK
  221. NTStatus = STATUS_SUCCESS;
  222. }
  223. }
  224. }
  225. }
  226. }
  227. }
  228. if( NTStatus == STATUS_IO_TIMEOUT )
  229. {
  230. NTStatus = STATUS_UNRECOGNIZED_MEDIA;
  231. }
  232. if(( NTStatus == STATUS_SUCCESS ) && ( pATRLen != NULL ))
  233. {
  234. *pATRLen = ATRLen;
  235. }
  236. return( NTStatus );
  237. }
  238. NTSTATUS
  239. STCPowerOff(
  240. PREADER_EXTENSION ReaderExtension )
  241. /*++
  242. Description:
  243. Deactivates the requested device
  244. Arguments:
  245. ReaderExtension context of call
  246. Return Value:
  247. STATUS_SUCCESS
  248. error values from IFRead / IFWrite
  249. --*/
  250. {
  251. NTSTATUS NTStatus = STATUS_SUCCESS;
  252. UCHAR SCCtrl;
  253. // clear SIM
  254. SCCtrl=0x11;
  255. NTStatus=IFWriteSTCRegister(
  256. ReaderExtension,
  257. ADR_INT_CONTROL,
  258. 1,
  259. &SCCtrl);
  260. SCCtrl = 0x00;
  261. NTStatus = IFWriteSTCRegister( ReaderExtension, ADR_SC_CONTROL, 1, &SCCtrl );
  262. return( NTStatus );
  263. }
  264. NTSTATUS
  265. STCPowerOn(
  266. PREADER_EXTENSION ReaderExtension )
  267. /*++
  268. Description:
  269. Deactivates the requested device
  270. Arguments:
  271. ReaderExtension context of call
  272. Return Value:
  273. STATUS_SUCCESS
  274. error values from IFRead / IFWrite
  275. --*/
  276. {
  277. NTSTATUS NTStatus = STATUS_SUCCESS;
  278. UCHAR SCCtrl,Byte;
  279. Byte = 0x02;
  280. NTStatus = IFWriteSTCRegister(
  281. ReaderExtension,
  282. ADR_IO_CONFIG,
  283. 1,
  284. &Byte
  285. );
  286. SCCtrl = 0x40; // vcc
  287. NTStatus = IFWriteSTCRegister( ReaderExtension, ADR_SC_CONTROL, 1, &SCCtrl );
  288. if( NTStatus == STATUS_SUCCESS )
  289. {
  290. SCCtrl = 0x41; // vpp
  291. NTStatus = IFWriteSTCRegister(
  292. ReaderExtension,
  293. ADR_SC_CONTROL,
  294. 1,
  295. &SCCtrl
  296. );
  297. // set SIM
  298. SCCtrl = 0x13;
  299. NTStatus=IFWriteSTCRegister(
  300. ReaderExtension,
  301. ADR_INT_CONTROL,
  302. 1,
  303. &SCCtrl);
  304. if( NTStatus == STATUS_SUCCESS )
  305. {
  306. SCCtrl = 0xD1; // vcc, clk, io
  307. NTStatus = IFWriteSTCRegister(
  308. ReaderExtension,
  309. ADR_SC_CONTROL,
  310. 1,
  311. &SCCtrl
  312. );
  313. }
  314. }
  315. return( NTStatus );
  316. }
  317. NTSTATUS
  318. STCSetRST(
  319. PREADER_EXTENSION ReaderExtension,
  320. BOOLEAN On)
  321. /*++
  322. Description:
  323. Arguments:
  324. ReaderExtension context of call
  325. Return Value:
  326. STATUS_SUCCESS
  327. error values from IFRead / IFWrite
  328. --*/
  329. {
  330. NTSTATUS NTStatus = STATUS_SUCCESS;
  331. UCHAR SCCtrl = 0;
  332. NTStatus = IFReadSTCRegister( ReaderExtension, ADR_SC_CONTROL, 1,&SCCtrl );
  333. if( NTStatus == STATUS_SUCCESS )
  334. {
  335. if( On )
  336. {
  337. SCCtrl |= 0x20;
  338. }
  339. else
  340. {
  341. SCCtrl &= ~0x20;
  342. }
  343. NTStatus = IFWriteSTCRegister(
  344. ReaderExtension,
  345. ADR_SC_CONTROL,
  346. 1,
  347. &SCCtrl
  348. );
  349. }
  350. return(NTStatus);
  351. }
  352. NTSTATUS
  353. STCConfigureSTC(
  354. PREADER_EXTENSION ReaderExtension,
  355. PSTC_REGISTER pConfiguration
  356. )
  357. {
  358. NTSTATUS NTStatus = STATUS_SUCCESS;
  359. UCHAR Value;
  360. do
  361. {
  362. if( pConfiguration->Register == ADR_INT_CONTROL )
  363. {
  364. // Read interrupt status register to acknoledge wrong states
  365. NTStatus = IFReadSTCRegister(
  366. ReaderExtension,
  367. ADR_INT_STATUS,
  368. 1,
  369. &Value
  370. );
  371. }
  372. Value = (UCHAR) pConfiguration->Value;
  373. NTStatus = IFWriteSTCRegister(
  374. ReaderExtension,
  375. pConfiguration->Register,
  376. pConfiguration->Size,
  377. (PUCHAR)&pConfiguration->Value
  378. );
  379. if (NTStatus == STATUS_NO_MEDIA)
  380. {
  381. // ignore that no card is in the reader
  382. NTStatus = STATUS_SUCCESS;
  383. }
  384. // delay to stabilize the oscilator clock:
  385. if( pConfiguration->Register == ADR_CLOCK_CONTROL )
  386. {
  387. SysDelay( 100 );
  388. }
  389. pConfiguration++;
  390. } while(NTStatus == STATUS_SUCCESS && pConfiguration->Size);
  391. return NTStatus;
  392. }
  393. NTSTATUS
  394. STCSetETU(
  395. PREADER_EXTENSION ReaderExtension,
  396. ULONG NewETU)
  397. /*++
  398. Description:
  399. Arguments:
  400. ReaderExtension context of call
  401. Return Value:
  402. STATUS_SUCCESS
  403. error values from IFRead / IFWrite
  404. --*/
  405. {
  406. NTSTATUS NTStatus = STATUS_DATA_ERROR;
  407. UCHAR ETU[2];
  408. SmartcardDebug(
  409. DEBUG_TRACE,
  410. ("%s!STCSetETU %d\n",
  411. DRIVER_NAME,
  412. NewETU));
  413. if( NewETU < 0x0FFF )
  414. {
  415. NTStatus = IFReadSTCRegister(
  416. ReaderExtension,
  417. ADR_ETULENGTH15,
  418. 2,
  419. ETU);
  420. if( NTStatus == STATUS_SUCCESS )
  421. {
  422. //
  423. // save all RFU bits
  424. //
  425. ETU[1] = (UCHAR) NewETU;
  426. ETU[0] = (UCHAR)(( ETU[0] & 0xF0 ) | ( NewETU >> 8 ));
  427. NTStatus = IFWriteSTCRegister(
  428. ReaderExtension,
  429. ADR_ETULENGTH15,
  430. 2,
  431. ETU);
  432. }
  433. }
  434. return(NTStatus);
  435. }
  436. NTSTATUS
  437. STCSetCGT(
  438. PREADER_EXTENSION ReaderExtension,
  439. ULONG NewCGT)
  440. /*++
  441. Description:
  442. Arguments:
  443. ReaderExtension context of call
  444. Return Value:
  445. STATUS_SUCCESS
  446. error values from IFRead / IFWrite
  447. --*/
  448. {
  449. NTSTATUS NTStatus = STATUS_DATA_ERROR;
  450. UCHAR CGT[2];
  451. SmartcardDebug(
  452. DEBUG_TRACE,
  453. ("%s!STCSetCGT %d\n",
  454. DRIVER_NAME,
  455. NewCGT));
  456. if( NewCGT < 0x01FF )
  457. {
  458. NTStatus = IFReadSTCRegister(
  459. ReaderExtension,
  460. ADR_CGT8,
  461. 2,
  462. CGT);
  463. if( NTStatus == STATUS_SUCCESS )
  464. {
  465. //
  466. // save all RFU bits
  467. //
  468. CGT[1] = ( UCHAR )NewCGT;
  469. CGT[0] = (UCHAR)(( CGT[0] & 0xFE ) | ( NewCGT >> 8 ));
  470. NTStatus = IFWriteSTCRegister(
  471. ReaderExtension,
  472. ADR_CGT8,
  473. 2,
  474. CGT);
  475. }
  476. }
  477. return(NTStatus);
  478. }
  479. NTSTATUS
  480. STCSetCWT(
  481. PREADER_EXTENSION ReaderExtension,
  482. ULONG NewCWT)
  483. /*++
  484. Description:
  485. Arguments:
  486. ReaderExtension context of call
  487. Return Value:
  488. STATUS_SUCCESS
  489. error values from IFRead / IFWrite
  490. --*/
  491. {
  492. NTSTATUS NTStatus = STATUS_SUCCESS;
  493. UCHAR CWT[4];
  494. SmartcardDebug(
  495. DEBUG_TRACE,
  496. ("%s!STCSetCWT %d\n",
  497. DRIVER_NAME,
  498. NewCWT));
  499. // little indians...
  500. CWT[0] = (( PUCHAR )&NewCWT )[3];
  501. CWT[1] = (( PUCHAR )&NewCWT )[2];
  502. CWT[2] = (( PUCHAR )&NewCWT )[1];
  503. CWT[3] = (( PUCHAR )&NewCWT )[0];
  504. NTStatus = IFWriteSTCRegister(
  505. ReaderExtension,
  506. ADR_CWT31,
  507. 4,
  508. CWT );
  509. return(NTStatus);
  510. }
  511. NTSTATUS
  512. STCSetBWT(
  513. PREADER_EXTENSION ReaderExtension,
  514. ULONG NewBWT)
  515. /*++
  516. Description:
  517. Arguments:
  518. ReaderExtension context of call
  519. Return Value:
  520. STATUS_SUCCESS
  521. error values from IFRead / IFWrite
  522. --*/
  523. {
  524. NTSTATUS NTStatus = STATUS_SUCCESS;
  525. UCHAR BWT[4];
  526. SmartcardDebug(
  527. DEBUG_TRACE,
  528. ("%s!STCSetBWT %d\n",
  529. DRIVER_NAME,
  530. NewBWT));
  531. // little indians...
  532. BWT[0] = (( PUCHAR )&NewBWT )[3];
  533. BWT[1] = (( PUCHAR )&NewBWT )[2];
  534. BWT[2] = (( PUCHAR )&NewBWT )[1];
  535. BWT[3] = (( PUCHAR )&NewBWT )[0];
  536. NTStatus = IFWriteSTCRegister(
  537. ReaderExtension,
  538. ADR_BWT31,
  539. 4,
  540. BWT );
  541. return(NTStatus);
  542. }
  543. NTSTATUS
  544. STCSetFDIV(
  545. PREADER_EXTENSION ReaderExtension,
  546. ULONG Factor)
  547. /*++
  548. Description:
  549. Arguments:
  550. ReaderExtension context of call
  551. Return Value:
  552. STATUS_SUCCESS
  553. error values from IFRead / IFWrite
  554. --*/
  555. {
  556. NTSTATUS NTStatus = STATUS_SUCCESS;
  557. UCHAR DIV = 0;
  558. NTStatus = IFReadSTCRegister(
  559. ReaderExtension,
  560. ADR_ETULENGTH15,
  561. 1,
  562. &DIV );
  563. if( NTStatus == STATUS_SUCCESS )
  564. {
  565. switch( Factor )
  566. {
  567. case 1:
  568. DIV &= ~M_DIV0;
  569. DIV &= ~M_DIV1;
  570. break;
  571. case 2:
  572. DIV |= M_DIV0;
  573. DIV &= ~M_DIV1;
  574. break;
  575. case 4 :
  576. DIV &= ~M_DIV0;
  577. DIV |= M_DIV1;
  578. break;
  579. case 8 :
  580. DIV |= M_DIV0;
  581. DIV |= M_DIV1;
  582. break;
  583. default :
  584. NTStatus = STATUS_DATA_ERROR;
  585. }
  586. if( NTStatus == STATUS_SUCCESS )
  587. {
  588. NTStatus = IFWriteSTCRegister(
  589. ReaderExtension,
  590. ADR_ETULENGTH15,
  591. 1,
  592. &DIV );
  593. }
  594. }
  595. return(NTStatus);
  596. }
  597. NTSTATUS
  598. STCInitUART(
  599. PREADER_EXTENSION ReaderExtension,
  600. BOOLEAN AutoLearn)
  601. /*++
  602. Description:
  603. Arguments:
  604. ReaderExtension context of call
  605. Return Value:
  606. STATUS_SUCCESS
  607. error values from IFRead / IFWrite
  608. --*/
  609. {
  610. NTSTATUS NTStatus = STATUS_SUCCESS;
  611. UCHAR Value;
  612. Value = AutoLearn ? 0x6F : 0x66;
  613. NTStatus = IFWriteSTCRegister(
  614. ReaderExtension,
  615. ADR_UART_CONTROL,
  616. 1,
  617. &Value );
  618. return( NTStatus );
  619. }
  620. //---------------------------------------- END OF FILE ----------------------------------------