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.

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