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.

1001 lines
27 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation and Litronic, 1998 - 1999
  3. Module Name:
  4. L220Ser.c
  5. Abstract:
  6. This module contains the functions for the 220 serial smart card reader.
  7. Most functions herein will be called by the smart card lib.
  8. Environment:
  9. Kernel mode only.
  10. Notes:
  11. Revision History:
  12. - Created December 1996 by Klaus Schutz
  13. - Modified December 1997 by Brian Manahan for use with
  14. the 220 reader.
  15. --*/
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include "L220SCR.h"
  20. // Make functions pageable
  21. #pragma alloc_text(PAGEABLE, Lit220Command)
  22. #pragma alloc_text(PAGEABLE, Lit220SetProtocol)
  23. #pragma alloc_text(PAGEABLE, Lit220IoRequest)
  24. #pragma alloc_text(PAGEABLE, Lit220IoReply)
  25. NTSTATUS
  26. Lit220CardTracking(
  27. PSMARTCARD_EXTENSION SmartcardExtension
  28. )
  29. /*++
  30. Routine Description:
  31. The smart card lib requires to have this function. It is called
  32. to set up event tracking for card insertion and removal events.
  33. We set the cancel routine so the IRP can be canceled.
  34. We always return STATUS_PENDING and the Lit220NotifyCardChange
  35. will signal the completion when called from the Lit220InputFilter.
  36. Arguments:
  37. SmartcardExtension - pointer to the smart card data struct.
  38. Return Value:
  39. NTSTATUS
  40. --*/
  41. {
  42. KIRQL oldIrql;
  43. KIRQL oldOsDataIrql;
  44. //
  45. // Set the wait mask for the isr. The isr will complete the
  46. // user request.
  47. //
  48. SmartcardExtension->ReaderExtension->WaitMask |= WAIT_INSERTION; // WAIT_INSERTION - wait for insertion or removal
  49. //
  50. // Set cancel routine for the notification irp
  51. //
  52. KeAcquireSpinLock(
  53. &SmartcardExtension->OsData->SpinLock,
  54. &oldOsDataIrql
  55. );
  56. ASSERT (SmartcardExtension->OsData->NotificationIrp);
  57. if (SmartcardExtension->OsData->NotificationIrp) {
  58. IoAcquireCancelSpinLock(
  59. &oldIrql
  60. );
  61. IoSetCancelRoutine(
  62. SmartcardExtension->OsData->NotificationIrp,
  63. Lit220Cancel
  64. );
  65. IoReleaseCancelSpinLock(
  66. oldIrql
  67. );
  68. } else {
  69. SmartcardDebug(
  70. DEBUG_ERROR,
  71. ("%s!Lit220CardTracking: SmartcardExtension->OsData->NotificationIrp is NULL!!! This should not be.\n",
  72. DRIVER_NAME
  73. ));
  74. }
  75. KeReleaseSpinLock(
  76. &SmartcardExtension->OsData->SpinLock,
  77. oldOsDataIrql
  78. );
  79. SmartcardDebug(
  80. DEBUG_TRACE,
  81. ("%s!Lit220CardTracking: Exit, WaitMask %X, NotificationIRP %X\n",
  82. DRIVER_NAME,
  83. SmartcardExtension->ReaderExtension->WaitMask,
  84. SmartcardExtension->OsData->NotificationIrp
  85. ));
  86. return STATUS_PENDING;
  87. }
  88. NTSTATUS
  89. Lit220Command(
  90. IN PSMARTCARD_EXTENSION SmartcardExtension
  91. )
  92. /*++
  93. Routine Description:
  94. This routine sends a command to the reader.
  95. SerialIo is used to write the command to the reader synchronously.
  96. We then wait for an ACK from the reader (by waiting for a signal from
  97. the Lit220InputFilter) so we know it received the command OK.
  98. If data is expected we wait for the data event signal from the
  99. Lit220InputFilter to indicate that the data is ready.
  100. Arguments:
  101. DeviceObject - Pointer to the device object.
  102. Return Value:
  103. -
  104. --*/
  105. {
  106. PDEVICE_OBJECT deviceObject = SmartcardExtension->OsData->DeviceObject;
  107. PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
  108. PREADER_EXTENSION readerExtension = SmartcardExtension->ReaderExtension;
  109. ULONG i;
  110. NTSTATUS status = STATUS_UNSUCCESSFUL;
  111. LARGE_INTEGER timeout;
  112. ULONG localWaitMask;
  113. ULONG retry = 1;
  114. PAGED_CODE();
  115. SmartcardDebug(
  116. DEBUG_TRACE,
  117. ("%s!Lit220Command: Enter\n",
  118. DRIVER_NAME)
  119. );
  120. do{
  121. // Make sure the data & ack events are not signaled before we start
  122. // Clear the DataEvnt
  123. KeClearEvent(
  124. &readerExtension->DataEvnt
  125. );
  126. // Clear the AckEvnt
  127. KeClearEvent(
  128. &readerExtension->AckEvnt
  129. );
  130. readerExtension->ReceivedByteNo = 0;
  131. readerExtension->GotNack = FALSE;
  132. // We always exect an ACK back
  133. readerExtension->WaitMask |= WAIT_ACK;
  134. // We need to copy the wait mask because the wait mask might change
  135. // before we have a chance to check if we need to wait on it
  136. localWaitMask = readerExtension->WaitMask;
  137. //
  138. // Send the data to the reader
  139. //
  140. readerExtension->SerialIoControlCode = IOCTL_SMARTCARD_220_WRITE;
  141. // Use SerialIo to actually send the bytes to the reader
  142. status = Lit220SerialIo(
  143. SmartcardExtension
  144. );
  145. //
  146. // Set Timeout according the protocol
  147. //
  148. timeout.HighPart = -1;
  149. switch (SmartcardExtension->CardCapabilities.Protocol.Selected) {
  150. case SCARD_PROTOCOL_UNDEFINED:
  151. // 3 sec timeout for undefined protocol
  152. timeout.LowPart = (ULONG)
  153. (-30 * 1000 * 1000);
  154. break;
  155. case SCARD_PROTOCOL_T0:
  156. // For t=0 protocol we must set the timeout to a very large time. This
  157. // is becuase the card could ask for more time, but the reader must pay
  158. // keep paying attention to the card so it can not tell us that more time
  159. // is needed. Therefore we must trust the readers timeout, and trust that
  160. // it will NACK us if there is a problem.
  161. timeout.LowPart = (-10 * 1000 * 1000 * 100) + // Timeout 100 seconds
  162. (-10) * SmartcardExtension->CardCapabilities.T0.WT;
  163. break;
  164. case SCARD_PROTOCOL_T1:
  165. timeout.LowPart =
  166. SmartcardExtension->CardCapabilities.T1.BWT *
  167. (SmartcardExtension->T1.Wtx ? SmartcardExtension->T1.Wtx : 1);
  168. timeout.LowPart += SmartcardExtension->CardCapabilities.T1.CWT *
  169. SmartcardExtension->SmartcardReply.BufferLength;
  170. // Add a little extra time for reader to respond to the PC
  171. timeout.LowPart += 100 * 1000;
  172. // Convert timeout to NS
  173. timeout.LowPart *= -10;
  174. break;
  175. }
  176. ASSERT(timeout.LowPart != 0);
  177. //
  178. // Always for the ACK
  179. //
  180. status = KeWaitForSingleObject(
  181. &readerExtension->AckEvnt,
  182. Executive,
  183. KernelMode,
  184. FALSE,
  185. &timeout
  186. );
  187. // Did we actually get a nack instead of an ACK
  188. if (readerExtension->GotNack) {
  189. status = Lit220GetReaderError(SmartcardExtension);
  190. // GetReaderError will clear this flag, but I need to
  191. // preserve the fact that I got nacked so I must reset it.
  192. readerExtension->GotNack = TRUE;
  193. }
  194. //
  195. // Wait for the Data if requested
  196. //
  197. if ((localWaitMask & WAIT_DATA) && (status == STATUS_SUCCESS)) {
  198. // Wait for signal the data is ready (at least until we timeout)
  199. status = KeWaitForSingleObject(
  200. &readerExtension->DataEvnt,
  201. Executive,
  202. KernelMode,
  203. FALSE,
  204. &timeout
  205. );
  206. // Did we get NACKed?
  207. if (readerExtension->GotNack) {
  208. status = Lit220GetReaderError(SmartcardExtension);
  209. // GetReaderError will clear this flag, but I need to
  210. // preserve the fact that I got nacked so I must reset it.
  211. readerExtension->GotNack = TRUE;
  212. }
  213. }
  214. if (status == STATUS_TIMEOUT) {
  215. //
  216. // STATUS_TIMEOUT isn't correctly mapped
  217. // to a WIN32 error, that's why we change it here
  218. // to STATUS_IO_TIMEOUT
  219. //
  220. status = STATUS_IO_TIMEOUT;
  221. SmartcardDebug(
  222. DEBUG_ERROR,
  223. ("%s(Lit220Command): Operation timed-out\n",
  224. DRIVER_NAME)
  225. );
  226. }
  227. { // Sometimes after a command the reader is not reader to accept another command
  228. // so we need to wait for a short period of time for the reader to be ready. We need to
  229. // take this out as soon as the reader is fixed!
  230. LARGE_INTEGER WaitTime;
  231. WaitTime.HighPart = -1;
  232. WaitTime.LowPart = -10; // Wait 1uS
  233. KeDelayExecutionThread(
  234. KernelMode,
  235. FALSE,
  236. &WaitTime
  237. );
  238. }
  239. // If we failed because the reader did not give us any response resend the command.
  240. // The reader should respond.
  241. if ((status != STATUS_SUCCESS) && (!readerExtension->GotNack)) {
  242. SmartcardDebug(
  243. DEBUG_ERROR,
  244. ("%s(Lit220Command): Reader failed to respond! Retrying once more.\n",
  245. DRIVER_NAME)
  246. );
  247. } else {
  248. break;
  249. }
  250. } while (retry++ <= 2);
  251. SmartcardDebug(
  252. DEBUG_TRACE,
  253. ("%s!Lit220Command: Exit - status %X\n",
  254. DRIVER_NAME,
  255. status)
  256. );
  257. return status;
  258. }
  259. NTSTATUS
  260. Lit220SetProtocol(
  261. PSMARTCARD_EXTENSION SmartcardExtension
  262. )
  263. /*++
  264. Routine Description:
  265. This function sends a set mode command to the reader set the
  266. protocol and the parameters for the wait protocol.
  267. Arguments:
  268. SmartcardExtension - Pointer to the smart card data struct
  269. // Parameters are up to seven bytes as follows:
  270. //
  271. // Flags - Flags to indicate the presence or absence of the other parameters.
  272. // SETMODE_PROTOCOL, b0 - 1 if Protocol is present.
  273. // SETMODE_GT, b1 - 1 if GuardTime is present.
  274. // SETMODE_WI, b2 - 1 if WorkWaitTime is present.
  275. // SETMODE_BWI, b3 - 1 if BWI/CWI is present.
  276. // SETMODE_WTX, b4 - 1 if BlockWaitTimeExtension is present.
  277. // SETMODE_FI_DI, b5 - 1 if BaudRate is present.
  278. //
  279. // Protocol - possible values 00, 02, 10, 11, 12, 13
  280. // encodes T, C, CKS from the ATR
  281. // Use of this parameter may invoke a PTS request to the smartcard.
  282. // b4 - Protocol Type (0 for T=0, 1 for T=1)
  283. // b3 - 0
  284. // b2 - 1 for convert 6A to 6A 00 and FA to 6A 01 on output to PS/2.
  285. // b1 - 0 ( use to be Convention used (0 for direct, 1 for inverse))
  286. // b0 - Checksum type (0 for LRC, 1 for CRC)
  287. //
  288. // GuardTime - possible values 00 to FE (0 to 254 etu between two characters)
  289. // encodes N (Extra Guardtime) from ATR
  290. //
  291. // WorkWaitTime - possible values 00 to FF
  292. // encodes WI which is Work Waiting Time (character time-out for T=0)
  293. //
  294. // BWI/CWI - possible values 00 to FF
  295. // encodes BWI and CWI which are the Block and Char Wait Time
  296. // (block and character time-out for T=1)
  297. //
  298. // BlockWaitTimeExtension - possible values 00 to FF
  299. // encodes WTX which is the Block Waiting Time Extension.
  300. // 00 = no WTX is requested by the ICC.
  301. // vv is the multiplier of the BWT value
  302. //
  303. // BaudRate - possible values 00 to FF
  304. // encodes FI and DI in the same fashion as TA1 does.
  305. // FI is in the high nibble. DI is in the low nibble.
  306. // D and F can be looked up in a table in PC/SC part 2 sec. 4.4.3.
  307. // Use of this parameter may invoke a PTS request to the smartcard.
  308. Return Value:
  309. NTSTATUS
  310. --*/
  311. {
  312. PSMARTCARD_REQUEST smartcardRequest = &SmartcardExtension->SmartcardRequest;
  313. NTSTATUS status;
  314. DWORD bufLen = 0;
  315. PCHAR flags;
  316. PCHAR protoByte;
  317. PAGED_CODE();
  318. RtlZeroMemory(
  319. smartcardRequest->Buffer,
  320. 8
  321. );
  322. // Send a set mode command to the reader
  323. smartcardRequest->Buffer[bufLen++] = LIT220_READER_ATTENTION;
  324. smartcardRequest->Buffer[bufLen++] = LIT220_READER_ATTENTION;
  325. smartcardRequest->Buffer[bufLen++] = LIT220_SET_MODE;
  326. flags = &smartcardRequest->Buffer[bufLen++];
  327. *flags = 0;
  328. // Set the protocol
  329. protoByte = &smartcardRequest->Buffer[bufLen++];
  330. *protoByte = 0;
  331. *flags |= SETMODE_PROTOCOL;
  332. // Set the inverse convention bit
  333. if (SmartcardExtension->CardCapabilities.InversConvention) {
  334. // Set the bit in the protocol paramter
  335. *protoByte |= LIT220_READER_CONVENTION_INVERSE;
  336. }
  337. //
  338. // test if caller wants to have T=0 or T=1
  339. //
  340. if ((SmartcardExtension->MinorIoControlCode & SCARD_PROTOCOL_T1) &&
  341. (SmartcardExtension->CardCapabilities.Protocol.Supported & SCARD_PROTOCOL_T1)){
  342. SmartcardExtension->CardCapabilities.Protocol.Selected =
  343. SCARD_PROTOCOL_T1;
  344. // Setup set mode command with T=1 parameters for protocol
  345. *protoByte |= LIT220_READER_PROTOCOL_T1;
  346. if (SmartcardExtension->CardCapabilities.T1.EDC & T1_CRC_CHECK) {
  347. *protoByte |= LIT220_READER_CHECK_CRC;
  348. }
  349. // Set the guard time
  350. *flags |= SETMODE_GT;
  351. smartcardRequest->Buffer[bufLen++] =
  352. SmartcardExtension->CardCapabilities.N;
  353. // Set BWI and CWI
  354. *flags |= SETMODE_BWI;
  355. smartcardRequest->Buffer[bufLen++] =
  356. (SmartcardExtension->CardCapabilities.T1.BWI << 4) |
  357. (SmartcardExtension->CardCapabilities.T1.CWI);
  358. }
  359. else if ((SmartcardExtension->MinorIoControlCode & SCARD_PROTOCOL_T0) &&
  360. (SmartcardExtension->CardCapabilities.Protocol.Supported & SCARD_PROTOCOL_T0))
  361. {
  362. SmartcardExtension->CardCapabilities.Protocol.Selected =
  363. SCARD_PROTOCOL_T0;
  364. // Set the guard time
  365. *flags |= SETMODE_GT;
  366. smartcardRequest->Buffer[bufLen++] =
  367. SmartcardExtension->CardCapabilities.N;
  368. // Set WI
  369. *flags |= SETMODE_WI;
  370. smartcardRequest->Buffer[bufLen++] =
  371. SmartcardExtension->CardCapabilities.T0.WI;
  372. } else {
  373. SmartcardDebug(
  374. DEBUG_ERROR,
  375. ("%s!Lit220SetProtocol: Error invalid protocol selected\n",
  376. DRIVER_NAME)
  377. );
  378. SmartcardExtension->CardCapabilities.Protocol.Selected =
  379. SCARD_PROTOCOL_UNDEFINED;
  380. return STATUS_INVALID_PARAMETER;
  381. }
  382. // Set FI & DI for baud rate
  383. *flags |= SETMODE_FI_DI;
  384. smartcardRequest->Buffer[bufLen++] =
  385. (SmartcardExtension->CardCapabilities.PtsData.Fl << 4) |
  386. SmartcardExtension->CardCapabilities.PtsData.Dl;
  387. smartcardRequest->BufferLength = bufLen;
  388. SmartcardDebug(
  389. DEBUG_DRIVER,
  390. ("%s!Lit220SetProtocol - Sending SetMode command %x bytes, %X,%X,%X,%X,%X,%X,%X,%X,%X,%X\n",
  391. DRIVER_NAME,
  392. bufLen,
  393. smartcardRequest->Buffer[0],
  394. smartcardRequest->Buffer[1],
  395. smartcardRequest->Buffer[2],
  396. smartcardRequest->Buffer[3],
  397. smartcardRequest->Buffer[4],
  398. smartcardRequest->Buffer[5],
  399. smartcardRequest->Buffer[6],
  400. smartcardRequest->Buffer[7],
  401. smartcardRequest->Buffer[8],
  402. smartcardRequest->Buffer[9]
  403. ));
  404. status =Lit220Command(
  405. SmartcardExtension
  406. );
  407. if (status == STATUS_SUCCESS) {
  408. // now indicate that we're in specific mode
  409. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
  410. return status;
  411. }
  412. //TODO: handle rertying code without optimal setting if optimal fails
  413. if (SmartcardExtension->CardCapabilities.PtsData.Type !=
  414. PTS_TYPE_DEFAULT) {
  415. DWORD saveMinorCode = SmartcardExtension->MinorIoControlCode;
  416. SmartcardDebug(
  417. DEBUG_TRACE,
  418. ("%s!Lit220SetProtocol: PTS failed. Trying default parameters...\n",
  419. DRIVER_NAME,
  420. status)
  421. );
  422. //
  423. // The card did either NOT reply or it replied incorrectly
  424. // so try default values
  425. //
  426. SmartcardExtension->CardCapabilities.PtsData.Type =
  427. PTS_TYPE_DEFAULT;
  428. SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET;
  429. status = Lit220Power(SmartcardExtension);
  430. if (!NT_SUCCESS(status)) {
  431. return status;
  432. }
  433. SmartcardExtension->MinorIoControlCode = saveMinorCode;
  434. return Lit220SetProtocol(SmartcardExtension);
  435. }
  436. // the card failed the pts-request
  437. status = STATUS_DEVICE_PROTOCOL_ERROR;
  438. SmartcardDebug(
  439. DEBUG_TRACE,
  440. ("%s!Lit220SetProtocol: Exit with error.\n",
  441. DRIVER_NAME)
  442. );
  443. return status;
  444. }
  445. NTSTATUS
  446. Lit220Power(
  447. PSMARTCARD_EXTENSION SmartcardExtension
  448. )
  449. /*++
  450. Routine Description:
  451. This function sends an SCARD_COLD_RESET, SCARD_WARM_RESET or SCARD_POWER_DOWN
  452. to the reader. For cold or warm reset we set a flag indicating that an ATR
  453. is expected. Once the Lit220InputFilter receives the ATR it will update the
  454. card capabilites.
  455. Arguments:
  456. SmartcardExtension - Pointer to the smart card data struct
  457. Return Value:
  458. NTSTATUS
  459. --*/
  460. {
  461. PSMARTCARD_REQUEST smartcardRequest = &SmartcardExtension->SmartcardRequest;
  462. NTSTATUS status;
  463. SmartcardDebug(
  464. DEBUG_TRACE,
  465. ("%s!Lit220Power: Enter\n",
  466. DRIVER_NAME)
  467. );
  468. smartcardRequest->BufferLength = 0;
  469. // Make sure card is still present
  470. if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_ABSENT) {
  471. return STATUS_DEVICE_REMOVED;
  472. }
  473. //
  474. // Since power down triggers the UpdateSerialStatus function, we have
  475. // to inform it that we forced the change of the status and not the user
  476. // (who might have removed and inserted a card)
  477. //
  478. SmartcardExtension->ReaderExtension->PowerRequest = TRUE;
  479. switch(SmartcardExtension->MinorIoControlCode) {
  480. case SCARD_COLD_RESET:
  481. //
  482. // Send a power-on, if the reader is already off
  483. // it will perform a cold reset turning the power off
  484. // the back on again.
  485. //
  486. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  487. LIT220_READER_ATTENTION;
  488. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  489. LIT220_READER_ATTENTION;
  490. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  491. LIT220_CARD_POWER_ON;
  492. //
  493. // Power-on leads to an ATR
  494. //
  495. SmartcardExtension->ReaderExtension->WaitMask |= WAIT_DATA;
  496. SmartcardExtension->ReaderExtension->WaitForATR = TRUE;
  497. break;
  498. case SCARD_WARM_RESET:
  499. //
  500. // Send a reset to the reader (warm reset)
  501. //
  502. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  503. LIT220_READER_ATTENTION;
  504. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  505. LIT220_READER_ATTENTION;
  506. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  507. LIT220_RESET;
  508. //
  509. // Warm reset leads to an ATR
  510. //
  511. SmartcardExtension->ReaderExtension->WaitMask |= WAIT_DATA;
  512. SmartcardExtension->ReaderExtension->WaitForATR = TRUE;
  513. break;
  514. case SCARD_POWER_DOWN:
  515. //
  516. // Send a power down to the reader
  517. //
  518. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  519. LIT220_READER_ATTENTION;
  520. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  521. LIT220_READER_ATTENTION;
  522. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  523. LIT220_CARD_POWER_OFF;
  524. break;
  525. }
  526. // Send the command
  527. status = Lit220Command(
  528. SmartcardExtension
  529. );
  530. SmartcardExtension->ReaderExtension->PowerRequest = FALSE;
  531. if (status == STATUS_IO_TIMEOUT) {
  532. status = STATUS_UNRECOGNIZED_MEDIA;
  533. }
  534. if (status == STATUS_SUCCESS) {
  535. if (SmartcardExtension->MinorIoControlCode == SCARD_POWER_DOWN) {
  536. SmartcardExtension->ReaderCapabilities.CurrentState =
  537. SCARD_PRESENT;
  538. SmartcardExtension->CardCapabilities.Protocol.Selected =
  539. SCARD_PROTOCOL_UNDEFINED;
  540. }
  541. }
  542. SmartcardDebug(
  543. DEBUG_TRACE,
  544. ("%s!Lit220Power: Exit\n",
  545. DRIVER_NAME)
  546. );
  547. return status;
  548. }
  549. NTSTATUS
  550. Lit220IoRequest(
  551. PSMARTCARD_EXTENSION SmartcardExtension
  552. )
  553. /*++
  554. Routine Description:
  555. The routine handles IO request from the smartcard library.
  556. It sends the command to card and processes the reply.
  557. It may also be called from Lit220IoReply is more processing is
  558. required.
  559. Arguments:
  560. SmartcardExtension - Pointer to the smart card data struct
  561. Return Value:
  562. NTSTATUS
  563. --*/
  564. {
  565. NTSTATUS status;
  566. LENGTH length;
  567. // ULONG offset = 0;
  568. ULONG indx;
  569. PAGED_CODE();
  570. SmartcardDebug(
  571. DEBUG_TRACE,
  572. ("%s!Lit220IoRequest: Enter\n",
  573. DRIVER_NAME)
  574. );
  575. //
  576. // Tell the lib function how many bytes I need for the prologue
  577. //
  578. SmartcardExtension->SmartcardRequest.BufferLength = 5;
  579. switch (SmartcardExtension->CardCapabilities.Protocol.Selected) {
  580. case SCARD_PROTOCOL_RAW:
  581. SmartcardDebug(
  582. DEBUG_DRIVER,
  583. ("%s!Lit220IoRequest - SCARD_PROTOCOL_RAW\n",
  584. DRIVER_NAME)
  585. );
  586. status = SmartcardRawRequest(
  587. SmartcardExtension
  588. );
  589. break;
  590. case SCARD_PROTOCOL_T0:
  591. SmartcardDebug(
  592. DEBUG_DRIVER,
  593. ("%s!Lit220IoRequest - SCARD_PROTOCOL_T0\n",
  594. DRIVER_NAME)
  595. );
  596. status = SmartcardT0Request(
  597. SmartcardExtension
  598. );
  599. break;
  600. case SCARD_PROTOCOL_T1:
  601. SmartcardDebug(
  602. DEBUG_DRIVER,
  603. ("%s!Lit220IoRequest - SCARD_PROTOCOL_T1\n",
  604. DRIVER_NAME)
  605. );
  606. status = SmartcardT1Request(
  607. SmartcardExtension
  608. );
  609. break;
  610. default:
  611. {
  612. SmartcardDebug(
  613. DEBUG_ERROR,
  614. ("%s!Lit220IoRequest: Invalid Device Request - protocol selected = %X\n",
  615. DRIVER_NAME,
  616. SmartcardExtension->CardCapabilities.Protocol.Selected)
  617. );
  618. status = STATUS_INVALID_DEVICE_REQUEST;
  619. }
  620. }
  621. if (status == STATUS_SUCCESS) {
  622. // Add the send block command to the front of the buffer
  623. SmartcardExtension->SmartcardRequest.Buffer[0] =
  624. LIT220_READER_ATTENTION;
  625. SmartcardExtension->SmartcardRequest.Buffer[1] =
  626. LIT220_READER_ATTENTION;
  627. SmartcardExtension->SmartcardRequest.Buffer[2] =
  628. LIT220_SEND_BLOCK;
  629. length.l.l0 =
  630. SmartcardExtension->SmartcardRequest.BufferLength - 5;
  631. SmartcardExtension->SmartcardRequest.Buffer[3] =
  632. length.b.b1;
  633. SmartcardExtension->SmartcardRequest.Buffer[4] =
  634. length.b.b0;
  635. // We expect data back from this command
  636. SmartcardExtension->ReaderExtension->WaitMask |= WAIT_DATA;
  637. //
  638. // Send the command
  639. //
  640. status = Lit220Command(
  641. SmartcardExtension
  642. );
  643. }
  644. if (status == STATUS_SUCCESS) {
  645. // Process the reply
  646. status = Lit220IoReply(
  647. SmartcardExtension
  648. );
  649. }
  650. SmartcardDebug(
  651. DEBUG_TRACE,
  652. ("%s!Lit220IoRequest: Exit - status %X\n",
  653. DRIVER_NAME,
  654. status)
  655. );
  656. return status;
  657. }
  658. NTSTATUS
  659. Lit220IoReply(
  660. PSMARTCARD_EXTENSION SmartcardExtension
  661. )
  662. /*++
  663. Routine Description:
  664. Handles the reply from a smartcard command.
  665. If more processing is required it will call Lit220IoRequest
  666. to send another command.
  667. Arguments:
  668. Return Value:
  669. NTSTATUS
  670. --*/
  671. {
  672. NTSTATUS status;
  673. LENGTH length;
  674. ULONG indx;
  675. PAGED_CODE();
  676. // Check which protocol is being used so we know how to respond
  677. switch (SmartcardExtension->CardCapabilities.Protocol.Selected) {
  678. case SCARD_PROTOCOL_RAW:
  679. SmartcardDebug(
  680. DEBUG_DRIVER,
  681. ("%s!Lit220IoReply: - SCARD_PROTOCOL_RAW\n",
  682. DRIVER_NAME)
  683. );
  684. // Let the smartcard lib process the reply
  685. status = SmartcardRawReply(
  686. SmartcardExtension
  687. );
  688. break;
  689. case SCARD_PROTOCOL_T0:
  690. SmartcardDebug(
  691. DEBUG_DRIVER,
  692. ("%s!Lit220IoReply - SCARD_PROTOCOL_T0\n",
  693. DRIVER_NAME)
  694. );
  695. // The instruction seems to be tagged onto the front of the buffer
  696. // the smartcard library does not seem to like this so we must shift the buffer.
  697. for(indx=0;indx<SmartcardExtension->SmartcardReply.BufferLength;indx++){
  698. SmartcardExtension->SmartcardReply.Buffer[indx] =
  699. SmartcardExtension->SmartcardReply.Buffer[indx+1];
  700. }
  701. SmartcardExtension->SmartcardReply.BufferLength--;
  702. #if DBG // DbgPrint the buffer
  703. SmartcardDebug(
  704. DEBUG_DRIVER,
  705. ("%s!Lit220IoReply - Buffer - ",
  706. DRIVER_NAME)
  707. );
  708. for (indx=0; indx<SmartcardExtension->SmartcardReply.BufferLength; indx++){
  709. SmartcardDebug(
  710. DEBUG_DRIVER,
  711. ("%X, ",
  712. SmartcardExtension->SmartcardReply.Buffer[indx])
  713. );
  714. }
  715. SmartcardDebug(
  716. DEBUG_DRIVER,
  717. ("\n")
  718. );
  719. #endif
  720. // Let the smartcard lib process the reply
  721. status = SmartcardT0Reply(
  722. SmartcardExtension
  723. );
  724. break;
  725. case SCARD_PROTOCOL_T1:
  726. SmartcardDebug(
  727. DEBUG_DRIVER,
  728. ("%s!Lit220IoReply - SCARD_PROTOCOL_T1\n",
  729. DRIVER_NAME)
  730. );
  731. // Let the smartcard lib process the reply
  732. status = SmartcardT1Reply(
  733. SmartcardExtension
  734. );
  735. break;
  736. default:
  737. {
  738. SmartcardDebug(
  739. DEBUG_ERROR,
  740. ("%s!Lit220IoRequest: Invalid Device Request2 - protocol selected = %X\n",
  741. DRIVER_NAME,
  742. SmartcardExtension->CardCapabilities.Protocol.Selected)
  743. );
  744. return STATUS_INVALID_DEVICE_REQUEST;
  745. }
  746. }
  747. // If there is more work to be done send out another IoRequest.
  748. // The smartcard lib should have set up the buffers for the new
  749. // IO operation.
  750. if (status == STATUS_MORE_PROCESSING_REQUIRED) {
  751. status = Lit220IoRequest(
  752. SmartcardExtension
  753. );
  754. }
  755. SmartcardDebug(
  756. DEBUG_TRACE,
  757. ("%s!Lit220IoReply: - Exit - status %X\n",
  758. DRIVER_NAME,
  759. status)
  760. );
  761. return status;
  762. }