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.

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