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.

2257 lines
61 KiB

  1. /*++
  2. Copyright (c) 1998 Gemplus Development
  3. Name:
  4. gprcmd.c
  5. Description:
  6. This is the module which holds the calls to the readers
  7. functions.
  8. Environment:
  9. Kernel Mode
  10. Revision History:
  11. 06/04/99: (Y. Nadeau + M. Veillette)
  12. - Code Review
  13. 12/03/99: V1.00.005 (Y. Nadeau)
  14. - Fix Set protocol to give reader the time to process the change
  15. 18/09/98: V1.00.004 (Y. Nadeau)
  16. - Correction for NT5 beta 3
  17. 06/05/98: V1.00.003 (P. Plouidy)
  18. - Power management for NT5
  19. 10/02/98: V1.00.002 (P. Plouidy)
  20. - Plug and Play for NT5
  21. 03/07/97: V1.00.001 (P. Plouidy)
  22. - Start of development.
  23. --*/
  24. //
  25. // Include section:
  26. // - stdio.h: standards definitons.
  27. // - ntddk.h: DDK Windows NT general definitons.
  28. // - ntdef.h: Windows NT general definitons.
  29. //
  30. #include <stdio.h>
  31. #include <ntddk.h>
  32. #include <ntdef.h>
  33. //
  34. // - gprcmd.h: common definition for this module.
  35. // - gprnt.h: public interface definition for the NT module.
  36. // - gprelcmd.h : elementary commands profile
  37. // - gemerror.h : Gemplus error codes
  38. #include "gprnt.h"
  39. #include "gprcmd.h"
  40. #include "gprelcmd.h"
  41. //
  42. // Master driver code to load in RAM
  43. //
  44. UCHAR MASTER_DRIVER[133]={
  45. 0xC2,0xB5,0x12,0x14,0xC6,0xFC,0x78,0x00,0x7B,0x00,0x90,0x07,0xDF,0xE0,0xD2,0xE4,
  46. 0xF0,0xEB,0xF8,0x12,0x14,0xD0,0x12,0x0D,0x9B,0x40,0x5C,0x0B,0xDC,0xF3,0xD2,0xB4,
  47. 0x90,0x07,0xDF,0xE0,0xC2,0xE4,0xF0,0x90,0x06,0xD4,0xE4,0xF5,0x15,0xF5,0x11,0xC2,
  48. 0x4D,0xA3,0x05,0x11,0x75,0x34,0x0A,0x75,0x37,0x00,0x75,0x38,0x40,0x12,0x0B,0x75,
  49. 0x20,0x20,0x3B,0xF0,0xA3,0x05,0x11,0x7B,0x01,0x12,0x0B,0x75,0x20,0x20,0x2F,0xF0,
  50. 0xA3,0x05,0x11,0x7C,0x03,0x33,0x33,0x50,0x01,0x0B,0xDC,0xFA,0x12,0x0B,0x75,0x20,
  51. 0x20,0x1C,0xF0,0xA3,0x05,0x11,0xDB,0xF4,0xE4,0x90,0x06,0xD4,0xF0,0x75,0x16,0x00,
  52. 0x75,0x15,0x00,0x12,0x14,0x15,0x22,0x74,0x0C,0x75,0x11,0x01,0x80,0xEB,0x74,0x0D,
  53. 0x75,0x11,0x01,0x80,0xE4
  54. };
  55. // Hard coded structure for different values of TA1.
  56. // eg. If TA= 0x92 is to set, this array of structure can be scanned and
  57. // for member variable TA1 = 0x92 and that values can be written to
  58. // approptiate location.
  59. // This is done in ConfigureTA1() function.
  60. struct tagCfgTa1
  61. {
  62. BYTE TA1;
  63. BYTE ETU1;
  64. BYTE ETU2;
  65. BYTE ETU1P;
  66. } cfg_ta1[] = {
  67. // { 0x15, 0x01, 0x01, 0x01 },
  68. // { 0x95, 0x01, 0x01, 0x01 },
  69. // { 0x25, 0x03, 0x02, 0x01 },
  70. // { 0x14, 0x05, 0x03, 0x01 },
  71. // { 0x35, 0x05, 0x03, 0x01 },
  72. // { 0xa5, 0x04, 0x02, 0x01 },
  73. // { 0x94, 0x07, 0x04, 0x02 },
  74. // { 0xb5, 0x07, 0x04, 0x02 },
  75. // { 0x24, 0x09, 0x04, 0x04 },
  76. // { 0x45, 0x09, 0x04, 0x04 },
  77. { 0x13, 0x0d, 0x06, 0x09 },
  78. { 0x34, 0x0d, 0x06, 0x09 },
  79. { 0x55, 0x0d, 0x06, 0x09 },
  80. { 0xa4, 0x0c, 0x06, 0x08 },
  81. { 0xc5, 0x0c, 0x06, 0x08 },
  82. { 0x65, 0x10, 0x08, 0x0c },
  83. { 0x93, 0x11, 0x09, 0x0d },
  84. { 0xb4, 0x11, 0x09, 0x0d },
  85. { 0xd5, 0x11, 0x09, 0x0d },
  86. { 0x23, 0x14, 0x0a, 0x10 },
  87. { 0x44, 0x14, 0x0a, 0x10 },
  88. { 0x12, 0x1c, 0x0e, 0x15 },
  89. { 0x33, 0x1c, 0x0e, 0x15 },
  90. { 0x54, 0x1c, 0x0e, 0x15 },
  91. { 0xa3, 0x1c, 0x0f, 0x15 },
  92. { 0xc4, 0x1c, 0x0f, 0x15 },
  93. { 0x64, 0x24, 0x12, 0x20 },
  94. { 0x92, 0x26, 0x14, 0x22 },
  95. { 0xb3, 0x26, 0x14, 0x22 },
  96. { 0xd4, 0x26, 0x14, 0x22 },
  97. { 0x22, 0x2b, 0x16, 0x27 },
  98. { 0x43, 0x2b, 0x16, 0x27 },
  99. { 0x11, 0x3b, 0x1e, 0x37 },
  100. { 0x32, 0x3b, 0x1e, 0x37 },
  101. { 0x53, 0x3b, 0x1e, 0x37 },
  102. // { 0x71, 0x55, 0x2b, 0x51 },
  103. // { 0x91, 0x55, 0x2b, 0x51 },
  104. { 0, 0, 0, 0 }
  105. };
  106. USHORT ATRLen (UCHAR *ATR, USHORT MaxChar)
  107. /*++
  108. Routine Description :
  109. Used to calculate the ATR length according to its content.
  110. Arguments
  111. ATR - string to analyze
  112. MaxChar - Maximum number of characters to verify.
  113. --*/
  114. {
  115. USHORT Len;
  116. UCHAR T0;
  117. UCHAR Yi;
  118. BOOLEAN EndInterChar;
  119. BOOLEAN TCKPresent=FALSE;
  120. T0 = ATR[1];
  121. Len= 2; // TS + T0
  122. Yi= (T0 & 0xF0);
  123. EndInterChar = FALSE;
  124. do
  125. {
  126. if (Yi & 0x10)
  127. {
  128. Len++; //TAi
  129. }
  130. if (Yi & 0x20)
  131. {
  132. Len++; //TBi
  133. }
  134. if (Yi & 0x40)
  135. {
  136. Len++; //TCi
  137. }
  138. if (Yi & 0x80)
  139. {
  140. if (Len < MaxChar) {
  141. Yi = ATR[Len];
  142. if((Yi & 0x0F)!=0)
  143. {
  144. TCKPresent=TRUE;
  145. }
  146. }
  147. Len++; //TDi
  148. }
  149. else
  150. {
  151. EndInterChar = TRUE;
  152. }
  153. } while((Len < MaxChar) && (EndInterChar == FALSE));
  154. Len = Len + (T0 & 0x0F);
  155. if(TCKPresent==TRUE)
  156. {
  157. Len = Len+1; //TCK
  158. }
  159. return (Len);
  160. }
  161. BOOLEAN NeedToSwitchWithoutPTS(
  162. BYTE *ATR,
  163. DWORD LengthATR
  164. )
  165. /*++
  166. Routine Description :
  167. Examine if ATR identifies a specific mode (presence of TA2).
  168. Arguments
  169. ATR - string to analyze
  170. LengthATR - Length of ATR.
  171. --*/
  172. {
  173. DWORD pos, len;
  174. // ATR[1] is T0. Examine precense of TD1.
  175. if (ATR[1] & 0x80)
  176. {
  177. // Find position of TD1.
  178. pos = 2;
  179. if (ATR[1] & 0x10)
  180. pos++;
  181. if (ATR[1] & 0x20)
  182. pos++;
  183. if (ATR[1] & 0x40)
  184. pos++;
  185. // Here ATR[pos] is TD1. Examine presence of TA2.
  186. if (ATR[pos] & 0x10)
  187. {
  188. // To be of any interest an ATR must contains at least
  189. // TS, T0, TA1, TD1, TA2 [+ T1 .. TK] [+ TCK]
  190. // Find the maximum length of uninteresting ATR.
  191. if (ATR[pos] & 0x0F)
  192. len = 5 + (ATR[1] & 0x0F);
  193. else
  194. len = 4 + (ATR[1] & 0x0F); // In protocol T=0 there is no TCK.
  195. if (LengthATR > len) // Interface bytes requires changes.
  196. if ((ATR[pos+1] & 0x10) == 0) // TA2 asks to use interface bytes.
  197. return TRUE;
  198. }
  199. }
  200. return FALSE;
  201. }
  202. NTSTATUS ValidateDriver( PSMARTCARD_EXTENSION pSmartcardExtension)
  203. /*++
  204. Routine Description :
  205. Validate the Master driver loaded in RAM at address 2100h
  206. Arguments
  207. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  208. --*/
  209. {
  210. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  211. NTSTATUS lStatus = STATUS_SUCCESS;
  212. UCHAR Vi[GPR_BUFFER_SIZE];
  213. UCHAR To;
  214. USHORT Lo;
  215. UCHAR Vo[GPR_BUFFER_SIZE];
  216. Vi[0] = 0x83; // DIR
  217. Vi[1] = 0x21; // ADR MSB
  218. Vi[2] = 0x00; // ADR LSB
  219. // Output variable initialisation
  220. Lo = GPR_BUFFER_SIZE;
  221. To = 0x00;
  222. Vo[0] = 0x00;
  223. // return a NTSTATUS
  224. lStatus = GprllTLVExchange (
  225. pReaderExt,
  226. VALIDATE_DRIVER_CMD,
  227. 3,
  228. Vi,
  229. &To,
  230. &Lo,
  231. Vo
  232. );
  233. return (lStatus);
  234. }
  235. NTSTATUS Update(
  236. PSMARTCARD_EXTENSION pSmartcardExtension,
  237. UCHAR Addr,
  238. UCHAR Value)
  239. /*++
  240. Routine Description :
  241. Write a value in RAM
  242. Arguments
  243. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  244. Addr: Address in RAM
  245. Value: Value to write
  246. --*/
  247. {
  248. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  249. NTSTATUS lStatus = STATUS_SUCCESS;
  250. UCHAR Vi[GPR_BUFFER_SIZE];
  251. UCHAR To;
  252. USHORT Lo;
  253. UCHAR Vo[GPR_BUFFER_SIZE];
  254. Vi[0]= 0x01;
  255. Vi[1]= Addr;
  256. Vi[2]= Value;
  257. // Output variable initialisation
  258. Lo = GPR_BUFFER_SIZE;
  259. To = 0x00;
  260. Vo[0] = 0x00;
  261. lStatus = GprllTLVExchange(
  262. pReaderExt,
  263. UPDATE_CMD,
  264. 0x03,
  265. Vi,
  266. &To,
  267. &Lo,
  268. Vo
  269. );
  270. return (lStatus);
  271. }
  272. NTSTATUS UpdateORL(
  273. PSMARTCARD_EXTENSION pSmartcardExtension,
  274. UCHAR Addr,
  275. UCHAR Value)
  276. /*++
  277. Routine Description :
  278. Write a value in RAM with OR mask
  279. Arguments
  280. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  281. --*/
  282. {
  283. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  284. NTSTATUS lStatus = STATUS_SUCCESS;
  285. UCHAR Vi[GPR_BUFFER_SIZE];
  286. UCHAR To;
  287. USHORT Lo;
  288. UCHAR Vo[GPR_BUFFER_SIZE];
  289. Vi[0]= 0x02;
  290. Vi[1]= Addr;
  291. // Output variable initialisation
  292. Lo = GPR_BUFFER_SIZE;
  293. To = 0x00;
  294. Vo[0] = 0x00;
  295. lStatus = GprllTLVExchange(
  296. pReaderExt,
  297. UPDATE_CMD,
  298. 0x02,
  299. Vi,
  300. &To,
  301. &Lo,
  302. Vo
  303. );
  304. if (STATUS_SUCCESS != lStatus)
  305. {
  306. return (lStatus);
  307. }
  308. Vi[0]= 0x01;
  309. Vi[1]= Addr;
  310. Vi[2] = Vo[1] | Value;
  311. // Output variable initialisation
  312. Lo = GPR_BUFFER_SIZE;
  313. To = 0x00;
  314. Vo[0] = 0x00;
  315. lStatus = GprllTLVExchange(
  316. pReaderExt,
  317. UPDATE_CMD,
  318. 0x03,
  319. Vi,
  320. &To,
  321. &Lo,
  322. Vo
  323. );
  324. return (lStatus);
  325. }
  326. NTSTATUS T0toT1( PSMARTCARD_EXTENSION pSmartcardExtension)
  327. /*++
  328. Routine Description :
  329. OS patch to put the reader in T1 mode
  330. Arguments
  331. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  332. --*/
  333. {
  334. NTSTATUS lStatus = STATUS_SUCCESS;
  335. // Verify each update to be done
  336. lStatus = Update(pSmartcardExtension,0x09,0x03);
  337. if (lStatus != STATUS_SUCCESS)
  338. {
  339. return (lStatus);
  340. }
  341. lStatus = Update(pSmartcardExtension,0x20,0x03);
  342. if (lStatus != STATUS_SUCCESS)
  343. {
  344. return (lStatus);
  345. }
  346. lStatus = Update(pSmartcardExtension,0x48,0x00);
  347. if (lStatus != STATUS_SUCCESS)
  348. {
  349. return (lStatus);
  350. }
  351. lStatus = Update(pSmartcardExtension,0x49,0x0F);
  352. if (lStatus != STATUS_SUCCESS)
  353. {
  354. return (lStatus);
  355. }
  356. lStatus = Update(pSmartcardExtension,0x4A,0x20);
  357. if (lStatus != STATUS_SUCCESS)
  358. {
  359. return (lStatus);
  360. }
  361. lStatus = Update(pSmartcardExtension,0x4B,0x0B);
  362. if (lStatus != STATUS_SUCCESS)
  363. {
  364. return (lStatus);
  365. }
  366. lStatus = Update(pSmartcardExtension,0x4C,0x40);
  367. if (lStatus != STATUS_SUCCESS)
  368. {
  369. return (lStatus);
  370. }
  371. lStatus = UpdateORL(pSmartcardExtension,0x2A,0x02);
  372. if (lStatus != STATUS_SUCCESS)
  373. {
  374. return (lStatus);
  375. }
  376. // Give the reader the time to process the change
  377. GprllWait(100);
  378. return (STATUS_SUCCESS);
  379. }
  380. NTSTATUS T1toT0( PSMARTCARD_EXTENSION pSmartcardExtension)
  381. /*++
  382. Routine Description :
  383. OS patch to put the reader in T0 mode
  384. Arguments
  385. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  386. --*/
  387. {
  388. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  389. NTSTATUS lStatus = STATUS_SUCCESS;
  390. lStatus = Update(pSmartcardExtension,0x09,0x02);
  391. if (lStatus != STATUS_SUCCESS)
  392. {
  393. return (lStatus);
  394. }
  395. lStatus = Update(pSmartcardExtension,0x20,0x02);
  396. if (lStatus != STATUS_SUCCESS)
  397. {
  398. return (lStatus);
  399. }
  400. // Give the reader the time to process the change
  401. GprllWait(100);
  402. return (STATUS_SUCCESS);
  403. }
  404. NTSTATUS IccColdReset(
  405. PSMARTCARD_EXTENSION pSmartcardExtension
  406. )
  407. /*++
  408. Routine Description :
  409. Cold reset function.
  410. The delay between the power down & the power up is strored
  411. in the PowerTimeout field of the READER_EXTENSION structure.
  412. The default value is 0.
  413. Arguments
  414. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  415. --*/
  416. {
  417. //
  418. // Local variables:
  419. // - pReaderExt holds the pointer to the current ReaderExtension structure
  420. // - lStatus holds the status to return.
  421. // - Vi Holds the input buffer of the TLV commnand.
  422. // - To holds the Tag of the returned TLV.
  423. // - Lo holds the Length of the buffer of the returned TLV.
  424. // - Vo holds the Buffer of the returned TLV.
  425. // - RespLen holds the Length of the buffer of the TLV returned by the power up command.
  426. // - Rbuff holds the buffer of the TLV returned by the power up command.
  427. //
  428. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  429. NTSTATUS lStatus = STATUS_SUCCESS;
  430. UCHAR Vi[GPR_BUFFER_SIZE];
  431. UCHAR To;
  432. USHORT Lo;
  433. UCHAR Vo[GPR_BUFFER_SIZE];
  434. USHORT RespLen;
  435. UCHAR RespBuff[GPR_BUFFER_SIZE];
  436. UCHAR BWTimeAdjust;
  437. USHORT MaxChar;
  438. // Send power on command (GprllTLVExchange: T= 20h, L = 0)
  439. // <= response
  440. // Output variable initialisation
  441. RespLen = GPR_BUFFER_SIZE;
  442. To = 0x00;
  443. RespBuff[0] = 0x00;
  444. lStatus = GprllTLVExchange(
  445. pReaderExt,
  446. OPEN_SESSION_CMD,
  447. 0x00,
  448. Vi,
  449. &To,
  450. &RespLen,
  451. RespBuff
  452. );
  453. if (lStatus != STATUS_SUCCESS)
  454. {
  455. return (lStatus);
  456. }
  457. // Correct the WTX pb
  458. // Get the value set by the reader
  459. Vi [0]=0x02;
  460. Vi [1]=0x4A;
  461. // Output variable initialisation
  462. Lo = GPR_BUFFER_SIZE;
  463. To = 0x00;
  464. Vo[0] = 0x00;
  465. lStatus = GprllTLVExchange(
  466. pReaderExt,
  467. UPDATE_CMD,
  468. 0x02,
  469. Vi,
  470. &To,
  471. &Lo,
  472. Vo
  473. );
  474. if (lStatus != STATUS_SUCCESS)
  475. {
  476. return (lStatus);
  477. }
  478. // adjust the value of the BWT
  479. if(Vo[1] >= 0x80)
  480. {
  481. BWTimeAdjust = 0xff;
  482. }
  483. else
  484. {
  485. BWTimeAdjust = Vo[1] * 2;
  486. }
  487. lStatus = Update(pSmartcardExtension,0x4A,BWTimeAdjust);
  488. if (lStatus == STATUS_SUCCESS)
  489. {
  490. // Get the ATR length from this function
  491. MaxChar = RespLen - 1;
  492. RespLen = ATRLen(RespBuff+1, MaxChar) + 1;
  493. //
  494. // Copy ATR to smart card struct (remove the reader status byte)
  495. // The lib needs the ATR for evaluation of the card parameters
  496. //
  497. // Verification if Response buffer is larger than ATR buffer.
  498. //
  499. if (
  500. (pSmartcardExtension->SmartcardReply.BufferSize >= (ULONG) (RespLen - 1)) &&
  501. (sizeof(pSmartcardExtension->CardCapabilities.ATR.Buffer) >= (ULONG)(RespLen - 1))
  502. )
  503. {
  504. RtlCopyMemory(
  505. pSmartcardExtension->SmartcardReply.Buffer,
  506. RespBuff + 1,
  507. RespLen - 1
  508. );
  509. pSmartcardExtension->SmartcardReply.BufferLength = (ULONG) (RespLen - 1);
  510. RtlCopyMemory(
  511. pSmartcardExtension->CardCapabilities.ATR.Buffer,
  512. pSmartcardExtension->SmartcardReply.Buffer,
  513. pSmartcardExtension->SmartcardReply.BufferLength
  514. );
  515. pSmartcardExtension->CardCapabilities.ATR.Length =
  516. (UCHAR) pSmartcardExtension->SmartcardReply.BufferLength ;
  517. pSmartcardExtension->CardCapabilities.Protocol.Selected =
  518. SCARD_PROTOCOL_UNDEFINED;
  519. // Parse the ATR string in order to check if it as valid
  520. // and to find out if the card uses invers convention
  521. lStatus = SmartcardUpdateCardCapabilities(pSmartcardExtension);
  522. if (lStatus == STATUS_SUCCESS)
  523. {
  524. RtlCopyMemory(
  525. pSmartcardExtension->IoRequest.ReplyBuffer,
  526. pSmartcardExtension->CardCapabilities.ATR.Buffer,
  527. pSmartcardExtension->CardCapabilities.ATR.Length
  528. );
  529. *pSmartcardExtension->IoRequest.Information =
  530. pSmartcardExtension->SmartcardReply.BufferLength;
  531. //
  532. // Implicite protocol and parameters selection?
  533. // Verify if TA2 require to switch in TA1
  534. //
  535. if ( NeedToSwitchWithoutPTS(
  536. pSmartcardExtension->CardCapabilities.ATR.Buffer,
  537. pSmartcardExtension->CardCapabilities.ATR.Length) == FALSE)
  538. {
  539. // send reader parameters
  540. IfdConfig(pSmartcardExtension, 0x11);
  541. }
  542. }
  543. }
  544. else
  545. {
  546. lStatus = STATUS_BUFFER_TOO_SMALL;
  547. }
  548. }
  549. return (lStatus);
  550. }
  551. NTSTATUS IccPowerDown(
  552. PSMARTCARD_EXTENSION pSmartcardExtension
  553. )
  554. /*++
  555. Routine Description : ICC power down function
  556. Arguments
  557. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  558. --*/
  559. {
  560. // Local variables:
  561. // - pReaderExt holds the pointer to the current ReaderExtension structure
  562. // - lStatus holds the status to return.
  563. // - Vi Holds the input buffer of the TLV commnand.
  564. // - To holds the Tag of the returned TLV.
  565. // - Lo holds the Length of the buffer of the returned TLV.
  566. // - Vo holds the Buffer of the returned TLV.
  567. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  568. NTSTATUS lStatus = STATUS_SUCCESS;
  569. UCHAR Vi[GPR_BUFFER_SIZE];
  570. UCHAR To;
  571. USHORT Lo;
  572. UCHAR Vo[GPR_BUFFER_SIZE];
  573. KIRQL irql;
  574. // Power down
  575. // Output variable initialisation
  576. Lo = GPR_BUFFER_SIZE;
  577. To = 0x00;
  578. Vo[0] = 0x00;
  579. lStatus = GprllTLVExchange(
  580. pReaderExt,
  581. CLOSE_SESSION_CMD,
  582. 0x00,
  583. Vi,
  584. &To,
  585. &Lo,
  586. Vo
  587. );
  588. if (lStatus == STATUS_SUCCESS)
  589. {
  590. KeAcquireSpinLock(&pSmartcardExtension->OsData->SpinLock,
  591. &irql);
  592. pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED;
  593. KeReleaseSpinLock(&pSmartcardExtension->OsData->SpinLock,
  594. irql);
  595. }
  596. return (lStatus);
  597. }
  598. NTSTATUS IccIsoOutput(
  599. PSMARTCARD_EXTENSION pSmartcardExtension,
  600. const UCHAR pCommand[5],
  601. USHORT *pRespLen,
  602. UCHAR pRespBuff[]
  603. )
  604. /*++
  605. Routine Description : This function sends an ISO OUT command to the card
  606. Arguments
  607. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  608. pCommand : Iso out command to send.
  609. pRespLen : in - maximum buffer size available
  610. out - returned buffer length.
  611. pRespBuff: returned buffer
  612. --*/
  613. {
  614. // Local variables:
  615. // - pReaderExt holds the pointer to the current ReaderExtension structure
  616. // - lStatus holds the status to return.
  617. // - Vi Holds the input buffer of the TLV commnand.
  618. // - To holds the Tag of the returned TLV.
  619. // - Lo holds the Length of the buffer of the returned TLV.
  620. // - Vo holds the Buffer of the returned TLV.
  621. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  622. NTSTATUS lStatus = STATUS_SUCCESS;
  623. UCHAR Vi[GPR_BUFFER_SIZE]= { 0x01 };
  624. UCHAR To;
  625. USHORT Lo;
  626. UCHAR Vo[GPR_BUFFER_SIZE];
  627. // The five command bytes are added in cmd buffer.
  628. RtlCopyMemory(Vi + 1, pCommand, 5);
  629. // The command is send to IFD.
  630. // Fields RespLen and RespBuff are updates
  631. // <= sResponse
  632. Lo = *pRespLen;
  633. To = 0x00;
  634. Vo[0] = 0x00;
  635. lStatus = GprllTLVExchange(
  636. pReaderExt,
  637. APDU_EXCHANGE_CMD,
  638. 6,
  639. Vi,
  640. &To,
  641. &Lo,
  642. Vo
  643. );
  644. if (lStatus != STATUS_SUCCESS)
  645. {
  646. *pRespLen = 0;
  647. }
  648. else
  649. {
  650. // To correct the bug of GPR400 version 1.0
  651. // If the response is 0xE7 then correct the response
  652. if (
  653. (Lo != 1) &&
  654. (pReaderExt->OsVersion<= 0x10 )&&
  655. (Vo[0]==0xE7)
  656. )
  657. {
  658. Lo = 0x03;
  659. }
  660. RtlCopyMemory(pRespBuff, Vo, Lo);
  661. *pRespLen = Lo;
  662. }
  663. return (lStatus);
  664. }
  665. NTSTATUS IccIsoInput(
  666. PSMARTCARD_EXTENSION pSmartcardExtension,
  667. const UCHAR pCommand[5],
  668. const UCHAR pData[],
  669. USHORT *pRespLen,
  670. BYTE pRespBuff[]
  671. )
  672. /*++
  673. Routine Description : This function sends an ISO IN command to the card
  674. Arguments
  675. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  676. pCommand : Iso out command to send.
  677. pData : data to send.
  678. pRespLen : in - maximum buffer size available
  679. out - returned buffer length.
  680. pRespBuff: returned buffer
  681. --*/
  682. {
  683. // Local variables:
  684. // - pReaderExt holds the pointer to the current ReaderExtension structure
  685. // - Ti holds the apdu command tag.
  686. // - Li holds the Iso out command length.
  687. // - Vi holds Icc ISO In command whose format is
  688. // <DIR=0x00> <CLA> <INS> <P1> <P2> <Length> [ Data ]
  689. // Length = Length + Dir + CLA + INS + P1 + P2
  690. // - To holds the response tag
  691. // - Lo holds th response buffer length.
  692. // - Vo holds the response buffer
  693. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  694. UCHAR Vi[GPR_BUFFER_SIZE] = { 0x00 };
  695. UCHAR Ti = APDU_EXCHANGE_CMD;
  696. UCHAR To;
  697. UCHAR Vo[GPR_BUFFER_SIZE];
  698. USHORT Li;
  699. USHORT Lo;
  700. NTSTATUS lStatus=STATUS_SUCCESS;
  701. // Length of the the TLV = Length of data + 6
  702. Li = pCommand[4]+6,
  703. // The five command bytes are added in cmd buffer.
  704. RtlCopyMemory(Vi + 1, pCommand, 5);
  705. //The data field is added.
  706. RtlCopyMemory(Vi + 6, pData, pCommand[4]);
  707. // The command is send to IFD.
  708. // Fields RespLen and RespBuff are updates
  709. // <= sResponse
  710. Lo = *pRespLen;
  711. lStatus = GprllTLVExchange(
  712. pReaderExt,
  713. Ti,
  714. Li,
  715. Vi,
  716. &To,
  717. &Lo,
  718. Vo
  719. );
  720. if (lStatus == STATUS_SUCCESS)
  721. {
  722. *pRespLen = Lo;
  723. RtlCopyMemory(pRespBuff, Vo, Lo);
  724. }
  725. else
  726. {
  727. *pRespLen = 0;
  728. }
  729. return (lStatus);
  730. }
  731. NTSTATUS IccIsoT1(
  732. PSMARTCARD_EXTENSION pSmartcardExtension,
  733. const USHORT Li,
  734. const UCHAR Vi[],
  735. USHORT *Lo,
  736. UCHAR Vo[]
  737. )
  738. /*++
  739. Routine Description : This function sends a T=1 frame to the card
  740. Arguments
  741. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  742. Li : Length of the frame to send.
  743. Vi : frame to send.
  744. Lo : in - maximum buffer size available
  745. out - Length of the response buffer.
  746. Vo : Response buffer.
  747. --*/
  748. {
  749. // Local variables:
  750. // - pReaderExt holds the pointer to the current ReaderExtension structure
  751. // - Ti Tag in TLV structure to send.
  752. // - To Tag in response TLV structure.
  753. UCHAR Ti = APDU_EXCHANGE_CMD;
  754. UCHAR To;
  755. NTSTATUS lStatus = STATUS_SUCCESS;
  756. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  757. To = 0x00;
  758. // Return value for To is not needed, The function GprllTLVExchange verify that
  759. // it corresponds to the Ti
  760. lStatus = GprllTLVExchange(
  761. pReaderExt,
  762. Ti,
  763. Li,
  764. Vi,
  765. &To,
  766. Lo,
  767. Vo
  768. );
  769. return (lStatus);
  770. }
  771. NTSTATUS IfdConfig(
  772. PSMARTCARD_EXTENSION pSmartcardExtension,
  773. UCHAR TA1
  774. )
  775. /*++
  776. Routine Description : This function Sets the correct internal values of the reader
  777. regarding the TA1 of the ATR.
  778. Arguments
  779. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  780. --*/
  781. {
  782. // Local variables:
  783. // - sResponse holds the called function responses.
  784. // - pReaderExt holds the pointer to the current ReaderExtension structure
  785. // - lStatus holds the status to return.
  786. // - Vi Holds the input buffer of the TLV commnand.
  787. // - To holds the Tag of the returned TLV.
  788. // - Lo holds the Length of the buffer of the returned TLV.
  789. // - Vo holds the Buffer of the returned TLV.
  790. //
  791. UCHAR Card_ETU1;
  792. UCHAR Card_ETU2;
  793. UCHAR Card_ETU1P;
  794. UCHAR Card_TA1;
  795. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  796. NTSTATUS lStatus = STATUS_SUCCESS;
  797. USHORT i = 0;
  798. // search TA1 parameters
  799. do {
  800. if ( TA1 == cfg_ta1[i].TA1 )
  801. {
  802. break;
  803. }
  804. i++;
  805. } while ( cfg_ta1[i].TA1 != 0 );
  806. if(cfg_ta1[i].TA1 != 0)
  807. {
  808. Card_TA1 = cfg_ta1[i].TA1;
  809. Card_ETU1 = cfg_ta1[i].ETU1;
  810. Card_ETU2 = cfg_ta1[i].ETU2;
  811. Card_ETU1P= cfg_ta1[i].ETU1P;
  812. }
  813. else
  814. {
  815. // Default value 9600
  816. Card_TA1 = 0x11;
  817. Card_ETU1 = 0x3B;
  818. Card_ETU2 = 0x1E;
  819. Card_ETU1P= 0x37;
  820. }
  821. // Verify each update to be done
  822. //Set the TA1
  823. lStatus = Update(pSmartcardExtension,0x32,Card_TA1);
  824. if (lStatus != STATUS_SUCCESS)
  825. {
  826. return (lStatus);
  827. }
  828. //Set the Card ETU1
  829. lStatus = Update(pSmartcardExtension,0x35,Card_ETU1);
  830. if (lStatus != STATUS_SUCCESS)
  831. {
  832. return (lStatus);
  833. }
  834. //Set the Card ETU2
  835. lStatus = Update(pSmartcardExtension,0x36,Card_ETU2);
  836. if (lStatus != STATUS_SUCCESS)
  837. {
  838. return (lStatus);
  839. }
  840. //Set the Card ETU1 P
  841. lStatus = Update(pSmartcardExtension,0x39,Card_ETU1P);
  842. if (lStatus != STATUS_SUCCESS)
  843. {
  844. return (lStatus);
  845. }
  846. //Set the Save TA1
  847. lStatus = Update(pSmartcardExtension,0x3A,Card_TA1);
  848. if (lStatus != STATUS_SUCCESS)
  849. {
  850. return (lStatus);
  851. }
  852. //Set the Save ETU1
  853. lStatus = Update(pSmartcardExtension,0x3D,Card_ETU1);
  854. if (lStatus != STATUS_SUCCESS)
  855. {
  856. return (lStatus);
  857. }
  858. //Set the Save ETU2
  859. lStatus = Update(pSmartcardExtension,0x3E,Card_ETU2);
  860. if (lStatus != STATUS_SUCCESS)
  861. {
  862. return (lStatus);
  863. }
  864. //Set the Save ETU1 P
  865. lStatus = Update(pSmartcardExtension,0x41,Card_ETU1P);
  866. if (lStatus != STATUS_SUCCESS)
  867. {
  868. return (lStatus);
  869. }
  870. // Give the reader the time to process the change
  871. GprllWait(100);
  872. return (STATUS_SUCCESS);
  873. }
  874. NTSTATUS IfdCheck(
  875. PSMARTCARD_EXTENSION pSmartcardExtension
  876. )
  877. /*++
  878. Routine Description : This function performs a software reset of the GPR400 using
  879. the Handshake register and TEST if hardware okay.
  880. Arguments
  881. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  882. --*/
  883. {
  884. // Local variables:
  885. // - pReaderExt holds the pointer to the current ReaderExtension structure
  886. // - HandShakeRegister
  887. //
  888. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  889. UCHAR HandShakeRegister;
  890. #if DBG
  891. SmartcardDebug(
  892. DEBUG_ERROR,
  893. ( "%s!IfdCheck: Enter\n",
  894. SC_DRIVER_NAME)
  895. );
  896. #endif
  897. // In the case that system reboot for Hibernate in
  898. // Power management. The GPR400 signal a device was been remove
  899. // but we have to request a second time to have the actual
  900. // state of the reader.
  901. HandShakeRegister = GprllReadRegister(pReaderExt,REGISTER_HANDSHAKE);
  902. SmartcardDebug(
  903. DEBUG_DRIVER,
  904. ("%s!IfdCheck: Read HandShakeRegister value:%x\n",
  905. SC_DRIVER_NAME, HandShakeRegister)
  906. );
  907. //Set to 1 the Master Reset bit from Handshake register
  908. GprllMaskHandshakeRegister(pReaderExt,0x01,1);
  909. //Wait 10 ms
  910. GprllWait(10);
  911. //Reset the Master Reset bit from Handshake register
  912. GprllMaskHandshakeRegister(pReaderExt,0x01,0);
  913. //Wait 80 ms
  914. GprllWait(80);
  915. HandShakeRegister = GprllReadRegister(pReaderExt,REGISTER_HANDSHAKE);
  916. SmartcardDebug(
  917. DEBUG_DRIVER,
  918. ("%s!IfdCheck: Read HandShakeRegister 2nd time value:%x\n",
  919. SC_DRIVER_NAME, HandShakeRegister)
  920. );
  921. if(HandShakeRegister != 0x80)
  922. {
  923. // Return reader IO problem
  924. return (STATUS_IO_DEVICE_ERROR);
  925. }
  926. return (STATUS_SUCCESS);
  927. }
  928. NTSTATUS IfdReset(
  929. PSMARTCARD_EXTENSION pSmartcardExtension
  930. )
  931. /*++
  932. Routine Description : This function performs a software reset of the GPR400 using
  933. the Handshake register.
  934. Arguments
  935. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  936. --*/
  937. {
  938. // Local variables:
  939. // - sResponse holds the called function responses.
  940. // - pReaderExt holds the pointer to the current ReaderExtension structure
  941. // - lStatus holds the status to return.
  942. // - Vi Holds the input buffer of the TLV commnand.
  943. // - To holds the Tag of the returned TLV.
  944. // - Lo holds the Length of the buffer of the returned TLV.
  945. // - Vo holds the Buffer of the returned TLV.
  946. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  947. NTSTATUS lStatus = STATUS_SUCCESS;
  948. UCHAR Vi[GPR_BUFFER_SIZE];
  949. UCHAR To;
  950. USHORT Lo;
  951. UCHAR Vo[GPR_BUFFER_SIZE];
  952. #if DBG
  953. SmartcardDebug(
  954. DEBUG_TRACE,
  955. ( "%s!IfdReset: Enter\n",
  956. SC_DRIVER_NAME)
  957. );
  958. #endif
  959. // In the case that system reboot for Hibernate in
  960. // Power management. The GPR400 signal a device was been remove
  961. // but we have to request a second time to have the actual
  962. // state of the reader.
  963. //Set to 1 the Master Reset bit from Handshake register
  964. GprllMaskHandshakeRegister(pReaderExt,0x01,1);
  965. //Wait 10 ms
  966. GprllWait(10);
  967. //Reset the Master Reset bit from Handshake register
  968. GprllMaskHandshakeRegister(pReaderExt,0x01,0);
  969. //Wait 80 ms
  970. GprllWait(80);
  971. //Read the GPR status
  972. Vi[0] = 0x00;
  973. Lo = GPR_BUFFER_SIZE;
  974. lStatus = GprllTLVExchange (
  975. pReaderExt,
  976. CHECK_AND_STATUS_CMD,
  977. 0x01,
  978. Vi,
  979. &To,
  980. &Lo,
  981. Vo
  982. );
  983. #if DBG
  984. SmartcardDebug(
  985. DEBUG_TRACE,
  986. ( "%s!IfdReset: GprllTLVExchange status= %x\n",
  987. SC_DRIVER_NAME, lStatus)
  988. );
  989. #endif
  990. if (lStatus != STATUS_SUCCESS)
  991. {
  992. SmartcardDebug(
  993. DEBUG_TRACE,
  994. ( "%s!IfdReset: GprllTLVExchange() failed! Leaving.....\n",
  995. SC_DRIVER_NAME)
  996. );
  997. return (lStatus);
  998. }
  999. //Memorize the GPR400 version
  1000. pReaderExt->OsVersion = Vo[1];
  1001. pSmartcardExtension->VendorAttr.IfdVersion.VersionMinor =
  1002. pReaderExt->OsVersion & 0x0f;
  1003. pSmartcardExtension->VendorAttr.IfdVersion.VersionMajor =
  1004. (pReaderExt->OsVersion & 0xf0) >> 4;
  1005. SmartcardDebug(
  1006. DEBUG_TRACE,
  1007. ( "%s!IfdReset: Loading Master driver...\n",
  1008. SC_DRIVER_NAME)
  1009. );
  1010. //Load the Master Driver in RAM at @2100h
  1011. Vi[0] = 0x02; // DIR
  1012. Vi[1] = 0x01 ; // ADR MSB
  1013. Vi[2] = 0x00 ; // ADR LSB
  1014. memcpy(&Vi[3], MASTER_DRIVER, sizeof(MASTER_DRIVER));
  1015. // Output variable initialisation
  1016. Lo = GPR_BUFFER_SIZE;
  1017. To = 0x00;
  1018. Vo[0] = 0x00;
  1019. lStatus = GprllTLVExchange (
  1020. pReaderExt,
  1021. LOAD_MEMORY_CMD,
  1022. sizeof(MASTER_DRIVER) + 3,
  1023. Vi,
  1024. &To,
  1025. &Lo,
  1026. Vo
  1027. );
  1028. if (lStatus != STATUS_SUCCESS)
  1029. {
  1030. SmartcardDebug(
  1031. DEBUG_TRACE,
  1032. ( "%s!IfdReset: GprllTLVExchange() failed! Leaving.....\n",
  1033. SC_DRIVER_NAME)
  1034. );
  1035. return (lStatus);
  1036. }
  1037. lStatus = ValidateDriver(pSmartcardExtension);
  1038. if (lStatus != STATUS_SUCCESS)
  1039. {
  1040. SmartcardDebug(
  1041. DEBUG_TRACE,
  1042. ( "%s!IfdReset: ValidateDriver() failed! Leaving.....\n",
  1043. SC_DRIVER_NAME)
  1044. );
  1045. return (lStatus);
  1046. }
  1047. return (STATUS_SUCCESS);
  1048. }
  1049. NTSTATUS IfdPowerDown(
  1050. PSMARTCARD_EXTENSION pSmartcardExtension
  1051. )
  1052. /*++
  1053. Routine Description :
  1054. This function powers down the IFD
  1055. Arguments
  1056. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  1057. --*/
  1058. {
  1059. // Local variables:
  1060. // - sResponse holds the called function responses.
  1061. // - pReaderExt holds the pointer to the current ReaderExtension structure
  1062. // - lStatus holds the status to return.
  1063. // - Vi Holds the input buffer of the TLV commnand.
  1064. // - To holds the Tag of the returned TLV.
  1065. // - Lo holds the Length of the buffer of the returned TLV.
  1066. // - Vo holds the Buffer of the returned TLV.
  1067. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  1068. NTSTATUS lStatus = STATUS_SUCCESS;
  1069. UCHAR Vi[GPR_BUFFER_SIZE];
  1070. UCHAR To;
  1071. USHORT Lo;
  1072. UCHAR Vo[GPR_BUFFER_SIZE];
  1073. // Put the GPR in Power-down mode (GprllTLVExchange T=0x40, L=1 and V=0x00)
  1074. // <== response of the GprllTLVExchange
  1075. Vi[0] = 0x00;
  1076. // Output variable initialisation
  1077. Lo = GPR_BUFFER_SIZE;
  1078. To = 0x00;
  1079. Vo[0] = 0x00;
  1080. lStatus = GprllTLVExchange(
  1081. pReaderExt,
  1082. POWER_DOWN_GPR_CMD,
  1083. 0x01,
  1084. Vi,
  1085. &To,
  1086. &Lo,
  1087. Vo
  1088. );
  1089. return (lStatus);
  1090. }
  1091. NTSTATUS GprCbReaderPower(
  1092. PSMARTCARD_EXTENSION SmartcardExtension
  1093. )
  1094. /*++
  1095. Routine Description :
  1096. This function is called by the Smart card library when a
  1097. IOCTL_SMARTCARD_POWER occurs.
  1098. This function provides 3 differents functionnality, depending of the minor
  1099. IOCTL value
  1100. - Cold reset (SCARD_COLD_RESET),
  1101. - Warm reset (SCARD_WARM_RESET),
  1102. - Power down (SCARD_POWER_DOWN).
  1103. Arguments
  1104. - SmartcardExtension is a pointer on the SmartCardExtension structure of
  1105. the current device.
  1106. --*/
  1107. {
  1108. NTSTATUS lStatus = STATUS_SUCCESS;
  1109. PREADER_EXTENSION pReader;
  1110. ASSERT(SmartcardExtension != NULL);
  1111. pReader = SmartcardExtension->ReaderExtension;
  1112. waitForIdleAndBlock(pReader);
  1113. switch(SmartcardExtension->MinorIoControlCode)
  1114. {
  1115. case SCARD_POWER_DOWN:
  1116. //Power down the ICC
  1117. lStatus = IccPowerDown(SmartcardExtension);
  1118. break;
  1119. case SCARD_COLD_RESET:
  1120. // Power up the ICC after a power down and a PowerTimeout waiting time.
  1121. lStatus = IccPowerDown(SmartcardExtension);
  1122. if(lStatus != STATUS_SUCCESS)
  1123. {
  1124. break;
  1125. }
  1126. // Waits for the Power Timeout to be elapsed before the reset command.
  1127. GprllWait(SmartcardExtension->ReaderExtension->PowerTimeOut);
  1128. case SCARD_WARM_RESET:
  1129. lStatus = IccColdReset(SmartcardExtension);
  1130. break;
  1131. default:
  1132. lStatus = STATUS_NOT_SUPPORTED;
  1133. }
  1134. setIdle(pReader);
  1135. return lStatus;
  1136. }
  1137. NTSTATUS GprCbTransmit(
  1138. PSMARTCARD_EXTENSION SmartcardExtension
  1139. )
  1140. /*++
  1141. Routine Description :
  1142. This function is called by the Smart card library when a
  1143. IOCTL_SMARTCARD_TRANSMIT occurs.
  1144. This function is used to transmit a command to the card.
  1145. Arguments
  1146. - SmartcardExtension is a pointer on the SmartCardExtension structure of
  1147. the current device.
  1148. --*/
  1149. {
  1150. NTSTATUS lStatus=STATUS_SUCCESS;
  1151. PUCHAR requestBuffer = SmartcardExtension->SmartcardRequest.Buffer;
  1152. PUCHAR replyBuffer = SmartcardExtension->SmartcardReply.Buffer;
  1153. PULONG requestLength = &SmartcardExtension->SmartcardRequest.BufferLength;
  1154. PULONG replyLength = &SmartcardExtension->SmartcardReply.BufferLength;
  1155. USHORT sRespLen;
  1156. UCHAR pRespBuff[GPR_BUFFER_SIZE];
  1157. PREADER_EXTENSION pReader;
  1158. ASSERT(SmartcardExtension != NULL);
  1159. *requestLength = 0;
  1160. sRespLen = 0;
  1161. pRespBuff[0] = 0x0;
  1162. pReader = SmartcardExtension->ReaderExtension;
  1163. waitForIdleAndBlock(pReader);
  1164. switch (SmartcardExtension->CardCapabilities.Protocol.Selected)
  1165. {
  1166. // Raw
  1167. case SCARD_PROTOCOL_RAW:
  1168. lStatus = STATUS_INVALID_DEVICE_STATE;
  1169. break;
  1170. // T=0
  1171. case SCARD_PROTOCOL_T0:
  1172. lStatus = SmartcardT0Request(SmartcardExtension);
  1173. if (lStatus != STATUS_SUCCESS)
  1174. {
  1175. setIdle(pReader);
  1176. return lStatus;
  1177. }
  1178. sRespLen = GPR_BUFFER_SIZE;
  1179. pRespBuff[0] = 0x0;
  1180. if (SmartcardExtension->T0.Le > 0)
  1181. {
  1182. // ISO OUT command if BufferLength = 5
  1183. lStatus = IccIsoOutput(
  1184. SmartcardExtension,
  1185. ( UCHAR *) SmartcardExtension->SmartcardRequest.Buffer,
  1186. &sRespLen,
  1187. pRespBuff
  1188. );
  1189. }
  1190. else
  1191. {
  1192. // ISO IN command if BufferLength >5 or BufferLength = 4
  1193. lStatus = IccIsoInput(
  1194. SmartcardExtension,
  1195. ( UCHAR *) SmartcardExtension->SmartcardRequest.Buffer,
  1196. ( UCHAR *) SmartcardExtension->SmartcardRequest.Buffer+5,
  1197. &sRespLen,
  1198. pRespBuff
  1199. );
  1200. }
  1201. if (lStatus != STATUS_SUCCESS)
  1202. {
  1203. setIdle(pReader);
  1204. return lStatus;
  1205. }
  1206. // Copy the response command without the reader status
  1207. // Verify if the buffer is large enough
  1208. if (SmartcardExtension->SmartcardReply.BufferSize >= (ULONG)(sRespLen - 1))
  1209. {
  1210. RtlCopyMemory(
  1211. SmartcardExtension->SmartcardReply.Buffer,
  1212. pRespBuff + 1,
  1213. sRespLen - 1);
  1214. SmartcardExtension->SmartcardReply.BufferLength =
  1215. (ULONG) (sRespLen - 1);
  1216. }
  1217. else
  1218. {
  1219. // SmartcardT0Reply must be called; prepare this call.
  1220. SmartcardExtension->SmartcardReply.BufferLength = 0;
  1221. }
  1222. lStatus = SmartcardT0Reply(SmartcardExtension);
  1223. break;
  1224. // T=1
  1225. case SCARD_PROTOCOL_T1:
  1226. do
  1227. {
  1228. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  1229. lStatus = SmartcardT1Request(SmartcardExtension);
  1230. if(lStatus != STATUS_SUCCESS)
  1231. {
  1232. setIdle(pReader);
  1233. return lStatus;
  1234. }
  1235. sRespLen = GPR_BUFFER_SIZE;
  1236. pRespBuff[0] = 0x0;
  1237. lStatus = IccIsoT1(
  1238. SmartcardExtension,
  1239. (USHORT) SmartcardExtension->SmartcardRequest.BufferLength,
  1240. (UCHAR *) SmartcardExtension->SmartcardRequest.Buffer,
  1241. &sRespLen,
  1242. pRespBuff);
  1243. if(lStatus != STATUS_SUCCESS)
  1244. {
  1245. // do not try to access the reader anymore.
  1246. if(lStatus == STATUS_DEVICE_REMOVED)
  1247. {
  1248. setIdle(pReader);
  1249. return lStatus;
  1250. }
  1251. // Let the SmartcardT1Reply determine the status
  1252. sRespLen = 1;
  1253. }
  1254. // Copy the response of the reader in the reply buffer
  1255. // Remove the status of the reader
  1256. // Verify if the buffer is large enough
  1257. if (SmartcardExtension->SmartcardReply.BufferSize >= (ULONG)(sRespLen - 1))
  1258. {
  1259. RtlCopyMemory(
  1260. SmartcardExtension->SmartcardReply.Buffer,
  1261. pRespBuff + 1 ,
  1262. sRespLen - 1
  1263. );
  1264. SmartcardExtension->SmartcardReply.BufferLength =
  1265. (ULONG) sRespLen - 1;
  1266. }
  1267. else
  1268. {
  1269. // SmartcardT1Reply must be called; prepare this call.
  1270. SmartcardExtension->SmartcardReply.BufferLength = 0;
  1271. }
  1272. lStatus = SmartcardT1Reply(SmartcardExtension);
  1273. } while(lStatus == STATUS_MORE_PROCESSING_REQUIRED);
  1274. break;
  1275. default:
  1276. lStatus = STATUS_INVALID_DEVICE_REQUEST;
  1277. break;
  1278. }
  1279. setIdle(pReader);
  1280. return lStatus;
  1281. }
  1282. NTSTATUS GprCbSetProtocol(
  1283. PSMARTCARD_EXTENSION SmartcardExtension
  1284. )
  1285. /*++
  1286. Routine Description :
  1287. This function is called by the Smart card library when a
  1288. IOCTL_SMARTCARD_SET_PROTOCOL occurs.
  1289. The minor IOCTL value holds the protocol to set.
  1290. Arguments
  1291. - SmartcardExtension is a pointer on the SmartCardExtension structure of
  1292. the current device.
  1293. --*/
  1294. {
  1295. NTSTATUS lStatus=STATUS_SUCCESS;
  1296. UCHAR Vi[GPR_BUFFER_SIZE];
  1297. UCHAR To;
  1298. USHORT Lo;
  1299. UCHAR Vo[GPR_BUFFER_SIZE];
  1300. READER_EXTENSION *pReaderExt = SmartcardExtension->ReaderExtension;
  1301. UCHAR PTS0=0;
  1302. UCHAR Value = 0;
  1303. PREADER_EXTENSION pReader;
  1304. KIRQL irql;
  1305. ASSERT(SmartcardExtension != NULL);
  1306. pReader = SmartcardExtension->ReaderExtension;
  1307. waitForIdleAndBlock(pReader);
  1308. // Check if the card is already in specific state
  1309. // and if the caller wants to have the already selected protocol.
  1310. // We return success if this is the case.
  1311. //
  1312. *SmartcardExtension->IoRequest.Information = 0x00;
  1313. if ( SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC &&
  1314. ( SmartcardExtension->CardCapabilities.Protocol.Selected &
  1315. SmartcardExtension->MinorIoControlCode
  1316. )
  1317. )
  1318. {
  1319. lStatus = STATUS_SUCCESS;
  1320. }
  1321. else
  1322. {
  1323. __try
  1324. {
  1325. if (SmartcardExtension->CardCapabilities.Protocol.Supported &
  1326. SmartcardExtension->MinorIoControlCode &
  1327. SCARD_PROTOCOL_T1)
  1328. {
  1329. // select T=1
  1330. SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T1;
  1331. PTS0= 0x11;
  1332. }
  1333. else if (SmartcardExtension->CardCapabilities.Protocol.Supported &
  1334. SmartcardExtension->MinorIoControlCode &
  1335. SCARD_PROTOCOL_T0)
  1336. {
  1337. // select T=0
  1338. SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0;
  1339. PTS0 = 0x10;
  1340. }
  1341. else
  1342. {
  1343. lStatus = STATUS_INVALID_DEVICE_REQUEST;
  1344. __leave;
  1345. }
  1346. // Send the PTS function
  1347. Vi[0] = 0xFF;
  1348. Vi[1] = PTS0;
  1349. Vi[2] = SmartcardExtension->CardCapabilities.PtsData.Fl <<4 |
  1350. SmartcardExtension->CardCapabilities.PtsData.Dl;
  1351. Vi[3] = (0xFF ^ PTS0) ^ Vi[2];
  1352. Lo = GPR_BUFFER_SIZE;
  1353. To = 0x00;
  1354. Vo[0] = 0x00;
  1355. // Status of the PTS could be STATUS SUCCESS
  1356. // or STATUS_DEVICE_PROTOCOL_ERROR if failed.
  1357. lStatus = GprllTLVExchange(
  1358. pReaderExt,
  1359. EXEC_MEMORY_CMD,
  1360. 0x04,
  1361. Vi,
  1362. &To,
  1363. &Lo,
  1364. Vo
  1365. );
  1366. #if DBG
  1367. SmartcardDebug(
  1368. DEBUG_TRACE,
  1369. ( "%s!IfdReset: GprCbSetProtocol status= %x\n",
  1370. SC_DRIVER_NAME, lStatus)
  1371. );
  1372. #endif
  1373. if (lStatus != STATUS_SUCCESS)
  1374. {
  1375. __leave;
  1376. }
  1377. // reader should reply status byte of 00 or 12
  1378. // the rest is other problem with no relation with
  1379. // the PTS negociation
  1380. lStatus = STATUS_SUCCESS;
  1381. // Put the reader in the right protocol
  1382. if (SmartcardExtension->CardCapabilities.Protocol.Selected == SCARD_PROTOCOL_T1)
  1383. {
  1384. lStatus = T0toT1(SmartcardExtension);
  1385. }
  1386. else
  1387. {
  1388. lStatus = T1toT0(SmartcardExtension);
  1389. }
  1390. if (lStatus != STATUS_SUCCESS)
  1391. {
  1392. __leave;
  1393. }
  1394. lStatus = IfdConfig(SmartcardExtension, 0x11);
  1395. if (lStatus != STATUS_SUCCESS)
  1396. {
  1397. __leave;
  1398. }
  1399. }
  1400. // we change the error code to a protocol error.
  1401. __finally
  1402. {
  1403. if (lStatus != STATUS_SUCCESS &&
  1404. lStatus != STATUS_INVALID_DEVICE_REQUEST
  1405. )
  1406. {
  1407. lStatus = STATUS_DEVICE_PROTOCOL_ERROR;
  1408. }
  1409. }
  1410. }
  1411. //
  1412. // Set the reply buffer length to sizeof(ULONG).
  1413. // Check if status SUCCESS, store the selected protocol.
  1414. //
  1415. KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
  1416. &irql);
  1417. if (lStatus == STATUS_SUCCESS)
  1418. {
  1419. *SmartcardExtension->IoRequest.Information =
  1420. sizeof(SmartcardExtension->CardCapabilities.Protocol.Selected);
  1421. *( PULONG) SmartcardExtension->IoRequest.ReplyBuffer =
  1422. SmartcardExtension->CardCapabilities.Protocol.Selected;
  1423. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
  1424. }
  1425. else
  1426. {
  1427. SmartcardExtension->CardCapabilities.Protocol.Selected =
  1428. SCARD_PROTOCOL_UNDEFINED;
  1429. *SmartcardExtension->IoRequest.Information = 0;
  1430. }
  1431. KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
  1432. irql);
  1433. setIdle(pReader);
  1434. return lStatus;
  1435. }
  1436. NTSTATUS AskForCardPresence(
  1437. PSMARTCARD_EXTENSION pSmartcardExtension
  1438. )
  1439. /*++
  1440. Routine Description :
  1441. This functions send a TLV command to the reader to know if there
  1442. is a card inserted.
  1443. The function does not wait to the answer. The treatment of the
  1444. answer is done in the interrupt routine.
  1445. Arguments
  1446. pSmartcardExtension: Pointer to the SmartcardExtension structure.
  1447. --*/
  1448. {
  1449. // Local variables:
  1450. // - pReaderExt holds the pointer to the current ReaderExtension structure
  1451. // - V holds the value for the TLV comand.
  1452. READER_EXTENSION *pReaderExt = pSmartcardExtension->ReaderExtension;
  1453. UCHAR V=0x02;
  1454. GprllSendCmd(pReaderExt,CHECK_AND_STATUS_CMD,1,&V);
  1455. return (STATUS_SUCCESS);
  1456. }
  1457. NTSTATUS SpecificTag(
  1458. PSMARTCARD_EXTENSION SmartcardExtension,
  1459. DWORD IoControlCode,
  1460. DWORD BufferInLen,
  1461. BYTE *BufferIn,
  1462. DWORD BufferOutLen,
  1463. BYTE *BufferOut,
  1464. DWORD *LengthOut
  1465. )
  1466. /*++
  1467. Routine Description :
  1468. This function is called when a specific Tag request occurs.
  1469. Arguments
  1470. - SmartcardExtension is a pointer on the SmartCardExtension structure of
  1471. the current device.
  1472. - IoControlCode holds the IOCTL value.
  1473. --*/
  1474. {
  1475. ULONG TagValue;
  1476. PREADER_EXTENSION pReaderExtension = SmartcardExtension->ReaderExtension;
  1477. //Set the reply buffer length to 0.
  1478. *LengthOut = 0;
  1479. //Verify the length of the Tag
  1480. //<== STATUS_BUFFER_TOO_SMALL
  1481. if (BufferInLen < (DWORD) sizeof(TagValue))
  1482. {
  1483. return(STATUS_BUFFER_TOO_SMALL);
  1484. }
  1485. TagValue = (ULONG) *((PULONG)BufferIn);
  1486. //Switch for the different IOCTL:
  1487. //Get the value of one tag (IOCTL_SMARTCARD_VENDOR_GET_ATTRIBUTE)
  1488. //Switch for the different Tags:
  1489. switch(IoControlCode)
  1490. {
  1491. case IOCTL_SMARTCARD_VENDOR_GET_ATTRIBUTE:
  1492. switch (TagValue)
  1493. {
  1494. // Power Timeout (SCARD_ATTR_SPEC_POWER_TIMEOUT)
  1495. // Verify the length of the output buffer.
  1496. // <== STATUS_BUFFER_TOO_SMALL
  1497. // Update the output buffer and the length.
  1498. // <== STATUS_SUCCESS
  1499. case SCARD_ATTR_SPEC_POWER_TIMEOUT:
  1500. if ( BufferOutLen < (DWORD) sizeof(pReaderExtension->PowerTimeOut))
  1501. {
  1502. return(STATUS_BUFFER_TOO_SMALL);
  1503. }
  1504. ASSERT(BufferOut != 0);
  1505. memcpy(
  1506. BufferOut,
  1507. &pReaderExtension->PowerTimeOut,
  1508. sizeof(pReaderExtension->PowerTimeOut)
  1509. );
  1510. *(LengthOut) =
  1511. (ULONG) sizeof(pReaderExtension->PowerTimeOut);
  1512. return STATUS_SUCCESS;
  1513. break;
  1514. // Command Timeout (SCARD_ATTR_SPEC_CMD_TIMEOUT)
  1515. // Verify the length of the output buffer.
  1516. // <== STATUS_BUFFER_TOO_SMALL
  1517. // Update the output buffer and the length.
  1518. // <== STATUS_SUCCESS
  1519. case SCARD_ATTR_SPEC_CMD_TIMEOUT:
  1520. if (BufferOutLen < (DWORD) sizeof(pReaderExtension->CmdTimeOut))
  1521. {
  1522. return(STATUS_BUFFER_TOO_SMALL);
  1523. }
  1524. ASSERT(BufferOut != 0);
  1525. memcpy(
  1526. BufferOut,
  1527. &pReaderExtension->CmdTimeOut,
  1528. sizeof(pReaderExtension->CmdTimeOut)
  1529. );
  1530. *(LengthOut) =
  1531. (ULONG) sizeof(pReaderExtension->CmdTimeOut);
  1532. return STATUS_SUCCESS;
  1533. break;
  1534. case SCARD_ATTR_MANUFACTURER_NAME:
  1535. if (BufferOutLen < ATTR_LENGTH)
  1536. {
  1537. return STATUS_BUFFER_TOO_SMALL;
  1538. }
  1539. // Copy the string of the Manufacturer Name
  1540. memcpy(
  1541. BufferOut,
  1542. ATTR_MANUFACTURER_NAME,
  1543. sizeof(ATTR_MANUFACTURER_NAME)
  1544. );
  1545. *(LengthOut) = (ULONG)sizeof(ATTR_MANUFACTURER_NAME);
  1546. return STATUS_SUCCESS;
  1547. break;
  1548. case SCARD_ATTR_ORIGINAL_FILENAME:
  1549. if (BufferOutLen < ATTR_LENGTH)
  1550. {
  1551. return STATUS_BUFFER_TOO_SMALL;
  1552. }
  1553. // Copy the string of the Original file name of the current driver
  1554. memcpy(
  1555. BufferOut,
  1556. ATTR_ORIGINAL_FILENAME,
  1557. sizeof(ATTR_ORIGINAL_FILENAME)
  1558. );
  1559. *(LengthOut) = (ULONG)sizeof(ATTR_ORIGINAL_FILENAME);
  1560. return STATUS_SUCCESS;
  1561. break;
  1562. // Unknown tag
  1563. // <== STATUS_NOT_SUPPORTED
  1564. default:
  1565. return STATUS_NOT_SUPPORTED;
  1566. break;
  1567. }
  1568. break;
  1569. // Set the value of one tag (IOCTL_SMARTCARD_VENDOR_SET_ATTRIBUTE)
  1570. // Switch for the different Tags:
  1571. case IOCTL_SMARTCARD_VENDOR_SET_ATTRIBUTE:
  1572. switch (TagValue)
  1573. {
  1574. // Power Timeout (SCARD_ATTR_SPEC_POWER_TIMEOUT)
  1575. // Verify the length of the input buffer.
  1576. // <== STATUS_BUFFER_TOO_SMALL
  1577. // Update the value.
  1578. // <== STATUS_SUCCESS
  1579. case SCARD_ATTR_SPEC_POWER_TIMEOUT:
  1580. if ( BufferInLen <
  1581. (DWORD) (sizeof(pReaderExtension->PowerTimeOut) +
  1582. sizeof(TagValue))
  1583. )
  1584. {
  1585. return(STATUS_BUFFER_TOO_SMALL);
  1586. }
  1587. ASSERT(BufferIn !=0);
  1588. memcpy(
  1589. &pReaderExtension->PowerTimeOut,
  1590. BufferIn + sizeof(TagValue),
  1591. sizeof(pReaderExtension->PowerTimeOut)
  1592. );
  1593. return STATUS_SUCCESS;
  1594. break;
  1595. // Command Timeout (SCARD_ATTR_SPEC_CMD_TIMEOUT)
  1596. // Verify the length of the input buffer.
  1597. // <== STATUS_BUFFER_TOO_SMALL
  1598. // Update the value.
  1599. // <== STATUS_SUCCESS
  1600. case SCARD_ATTR_SPEC_CMD_TIMEOUT:
  1601. if ( BufferInLen <
  1602. (DWORD) ( sizeof(pReaderExtension->CmdTimeOut) +
  1603. sizeof(TagValue))
  1604. )
  1605. {
  1606. return(STATUS_BUFFER_TOO_SMALL);
  1607. }
  1608. ASSERT(BufferIn != 0);
  1609. memcpy(
  1610. &pReaderExtension->CmdTimeOut,
  1611. BufferIn + sizeof(TagValue),
  1612. sizeof(pReaderExtension->CmdTimeOut)
  1613. );
  1614. return STATUS_SUCCESS;
  1615. break;
  1616. // Unknown tag
  1617. // <== STATUS_NOT_SUPPORTED
  1618. default:
  1619. return STATUS_NOT_SUPPORTED;
  1620. }
  1621. break;
  1622. default:
  1623. return STATUS_NOT_SUPPORTED;
  1624. }
  1625. }
  1626. NTSTATUS SwitchSpeed(
  1627. PSMARTCARD_EXTENSION SmartcardExtension,
  1628. ULONG BufferInLen,
  1629. PUCHAR BufferIn,
  1630. ULONG BufferOutLen,
  1631. PUCHAR BufferOut,
  1632. PULONG LengthOut
  1633. )
  1634. /*++
  1635. Routine Description:
  1636. This function is called when apps want to switch reader speed after a
  1637. proprietary switch speed (switch protocol) command has been sent to the
  1638. smart card.
  1639. Arguments:
  1640. SmartcardExtension - is a pointer on the SmartCardExtension structure of
  1641. the current device.
  1642. BufferInLen - holds the length of the input data.
  1643. BufferIn - holds the input data. TA1. If 0
  1644. BufferOutLen - holds the size of the output buffer.
  1645. BufferOut - the output buffer. Reader status code.
  1646. LengthOut - holds the length of the output data.
  1647. Return Value:
  1648. STATUS_SUCCESS - We could execute the request.
  1649. STATUS_BUFFER_TOO_SMALL - The output buffer is to small.
  1650. STATUS_NOT_SUPPORTED - We could not support the Ioctl specified.
  1651. --*/
  1652. {
  1653. NTSTATUS status;
  1654. BYTE NewTA1;
  1655. ULONG i;
  1656. ASSERT(SmartcardExtension != NULL);
  1657. *LengthOut = 0;
  1658. // Just checking if IOCTL exists.
  1659. if (BufferInLen == 0)
  1660. {
  1661. SmartcardDebug(
  1662. DEBUG_INFO,
  1663. ("%s!SwitchSpeed: Just checking IOCTL.\n",
  1664. SC_DRIVER_NAME)
  1665. );
  1666. return(STATUS_SUCCESS);
  1667. }
  1668. else
  1669. {
  1670. NewTA1 = BufferIn[0];
  1671. i = 0;
  1672. // Verify if this TA1 is support by the GPR400
  1673. do {
  1674. if ( NewTA1 == cfg_ta1[i].TA1 )
  1675. {
  1676. // TA1 Found!
  1677. break;
  1678. }
  1679. i++;
  1680. } while ( cfg_ta1[i].TA1 != 0 );
  1681. }
  1682. // If 0 means TA1 not found
  1683. if(cfg_ta1[i].TA1 != 0)
  1684. {
  1685. SmartcardDebug(
  1686. DEBUG_INFO,
  1687. ("%s!GDDK_0ASwitchSpeed: 0x%X\n",
  1688. SC_DRIVER_NAME, NewTA1)
  1689. );
  1690. status = IfdConfig(SmartcardExtension, NewTA1);
  1691. }
  1692. else
  1693. {
  1694. // TA1 not supported
  1695. return STATUS_NOT_SUPPORTED;
  1696. }
  1697. return status;
  1698. }
  1699. NTSTATUS GprCbVendorIoctl(
  1700. PSMARTCARD_EXTENSION SmartcardExtension
  1701. )
  1702. /*++
  1703. Routine Description :
  1704. This routine is called when a vendor IOCTL_SMARTCARD_ is send to the driver.
  1705. Arguments
  1706. - SmartcardExtension is a pointer on the SmartCardExtension structure of
  1707. the current device.
  1708. Return Value:
  1709. STATUS_SUCCESS - We could execute the request.
  1710. STATUS_BUFFER_TOO_SMALL - The output buffer is to small.
  1711. STATUS_NOT_SUPPORTED - We could not support the Ioctl specified.
  1712. --*/
  1713. {
  1714. PREADER_EXTENSION pReaderExtension = SmartcardExtension->ReaderExtension;
  1715. UCHAR To;
  1716. UCHAR Vo[GPR_BUFFER_SIZE];
  1717. USHORT Lo;
  1718. USHORT BufferInLen = 0;
  1719. NTSTATUS lStatus=STATUS_SUCCESS;
  1720. PREADER_EXTENSION pReader;
  1721. ASSERT(SmartcardExtension != NULL);
  1722. // Set the reply buffer length to 0.
  1723. *SmartcardExtension->IoRequest.Information = 0;
  1724. pReader = SmartcardExtension->ReaderExtension;
  1725. waitForIdleAndBlock(pReader);
  1726. //Switch for the different IOCTL:
  1727. switch(SmartcardExtension->MajorIoControlCode)
  1728. {
  1729. case IOCTL_SMARTCARD_VENDOR_GET_ATTRIBUTE:
  1730. case IOCTL_SMARTCARD_VENDOR_SET_ATTRIBUTE:
  1731. SpecificTag(
  1732. SmartcardExtension,
  1733. (ULONG) SmartcardExtension->MajorIoControlCode,
  1734. (ULONG) SmartcardExtension->IoRequest.RequestBufferLength,
  1735. (PUCHAR) SmartcardExtension->IoRequest.RequestBuffer,
  1736. (ULONG) SmartcardExtension->IoRequest.ReplyBufferLength,
  1737. (PUCHAR) SmartcardExtension->IoRequest.ReplyBuffer,
  1738. (PULONG) SmartcardExtension->IoRequest.Information
  1739. );
  1740. break;
  1741. // IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE:
  1742. // Translate the buffer to TLV and send it to the reader.
  1743. case IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE:
  1744. if(SmartcardExtension->IoRequest.ReplyBufferLength < 3)
  1745. {
  1746. setIdle(pReader);
  1747. return(STATUS_INVALID_BUFFER_SIZE);
  1748. }
  1749. BufferInLen = (SmartcardExtension->IoRequest.RequestBuffer[2]*0x100)
  1750. + SmartcardExtension->IoRequest.RequestBuffer[1];
  1751. if( (ULONG) BufferInLen > (SmartcardExtension->IoRequest.ReplyBufferLength - 3))
  1752. {
  1753. setIdle(pReader);
  1754. return(STATUS_INVALID_BUFFER_SIZE);
  1755. }
  1756. Lo = GPR_BUFFER_SIZE;
  1757. To = 0x00;
  1758. Vo[0] = 0x00;
  1759. lStatus = GprllTLVExchange(
  1760. pReaderExtension,
  1761. (const BYTE) SmartcardExtension->IoRequest.RequestBuffer[0],
  1762. (const USHORT) BufferInLen,
  1763. (const BYTE *) &(SmartcardExtension->IoRequest.RequestBuffer[3]),
  1764. &To,
  1765. &Lo,
  1766. Vo
  1767. );
  1768. if (lStatus != STATUS_SUCCESS)
  1769. {
  1770. setIdle(pReader);
  1771. return (lStatus);
  1772. }
  1773. // Check if there is enough space in the reply buffer
  1774. if((ULONG)(Lo+3) > SmartcardExtension->IoRequest.ReplyBufferLength)
  1775. {
  1776. setIdle(pReader);
  1777. return(STATUS_INVALID_BUFFER_SIZE);
  1778. }
  1779. else
  1780. {
  1781. ASSERT(SmartcardExtension->IoRequest.ReplyBuffer != 0);
  1782. SmartcardExtension->IoRequest.ReplyBuffer[0] = To;
  1783. SmartcardExtension->IoRequest.ReplyBuffer[1] = LOBYTE(Lo);
  1784. SmartcardExtension->IoRequest.ReplyBuffer[2] = HIBYTE(Lo);
  1785. memcpy((SmartcardExtension->IoRequest.ReplyBuffer)+3,Vo,Lo);
  1786. *(SmartcardExtension->IoRequest.Information) = (DWORD) (Lo + 3);
  1787. setIdle(pReader);
  1788. return(STATUS_SUCCESS);
  1789. }
  1790. //
  1791. // For IOCTL_SMARTCARD_VENDOR_SWITCH_SPEED
  1792. // Call the SwitchSpeed function
  1793. //
  1794. case IOCTL_SMARTCARD_VENDOR_SWITCH_SPEED:
  1795. lStatus = SwitchSpeed(
  1796. SmartcardExtension,
  1797. (ULONG) SmartcardExtension->IoRequest.RequestBufferLength,
  1798. (PUCHAR) SmartcardExtension->IoRequest.RequestBuffer,
  1799. (ULONG) SmartcardExtension->IoRequest.ReplyBufferLength,
  1800. (PUCHAR) SmartcardExtension->IoRequest.ReplyBuffer,
  1801. (PULONG) SmartcardExtension->IoRequest.Information
  1802. );
  1803. break;
  1804. default:
  1805. setIdle(pReader);
  1806. return STATUS_NOT_SUPPORTED;
  1807. }
  1808. setIdle(pReader);
  1809. return lStatus;
  1810. }
  1811. NTSTATUS GprCbSetupCardTracking(
  1812. PSMARTCARD_EXTENSION SmartcardExtension
  1813. )
  1814. /*++
  1815. Routine Description:
  1816. This function is called by the Smart card library when an
  1817. IOCTL_SMARTCARD_IS_PRESENT or IOCTL_SMARTCARD_IS_ABSENT occurs.
  1818. Arguments:
  1819. SmartcardExtension - is a pointer on the SmartCardExtension structure of
  1820. the current device.
  1821. Return Value:
  1822. STATUS_PENDING - The request is in a pending mode.
  1823. --*/
  1824. {
  1825. NTSTATUS NTStatus = STATUS_PENDING;
  1826. POS_DEP_DATA pOS = NULL;
  1827. KIRQL oldIrql;
  1828. ASSERT(SmartcardExtension != NULL);
  1829. //
  1830. //Initialize
  1831. //
  1832. pOS = SmartcardExtension->OsData;
  1833. //
  1834. //Set cancel routine for the notification IRP.
  1835. //
  1836. IoAcquireCancelSpinLock(&oldIrql);
  1837. IoSetCancelRoutine(
  1838. pOS->NotificationIrp,
  1839. GprCancelEventWait
  1840. );
  1841. IoReleaseCancelSpinLock(oldIrql);
  1842. NTStatus = STATUS_PENDING;
  1843. return (NTStatus);
  1844. }