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.

1014 lines
33 KiB

  1. /*++
  2. Module Name:
  3. L220FLTR.c
  4. Abstract:
  5. This module contains the input filter routine and the notification
  6. procedure for insertion/removal events.
  7. Environment:
  8. Kernel mode only.
  9. Notes:
  10. Revision History:
  11. - Created December 1996 by Klaus Schutz (kschutz)
  12. - Modified December 1997 by Brian Manahan for use with
  13. our 220 reader.
  14. --*/
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "L220SCR.h"
  19. #pragma alloc_text(PAGEABLE, Lit220StartTimer)
  20. #pragma alloc_text(PAGEABLE, Lit220StopTimer)
  21. static DWORD bTrue = TRUE;
  22. static DWORD bFalse = FALSE;
  23. BOOLEAN
  24. Lit220InputFilter(
  25. IN BYTE SmartcardByte,
  26. IN PSMARTCARD_EXTENSION smartcardExtension
  27. )
  28. /*++
  29. Routine Description:
  30. This routine is processes each byte from the serial port.
  31. Lit220SerialEventCallback call this function when it receives a byte
  32. of data from the serial port. For card insertion/removal it will call the
  33. Lit220NotifyCardChange to process the notificiation.
  34. If an ACK is received it will signal the Lit220SendCommand so it can continue.
  35. After a data block is received it will signal the Lit220SendCommand
  36. to notifiy that the data is ready.
  37. --*/
  38. {
  39. PREADER_EXTENSION readerExtension = smartcardExtension->ReaderExtension;
  40. PDEVICE_EXTENSION deviceExtension = smartcardExtension->OsData->DeviceObject->DeviceExtension;
  41. LONG semState;
  42. BOOLEAN retVal = TRUE;
  43. KIRQL irql;
  44. //
  45. // The first byte of each packet identifies the packet-type
  46. // A packet containing data starts with the packet-type and then
  47. // 2 bytes of packet length.
  48. //
  49. if (++readerExtension->ReceivedByteNo == 1) {
  50. readerExtension->GotLengthB0 = FALSE;
  51. readerExtension->GotLengthB1 = FALSE;
  52. readerExtension->DataByteNo = 0;
  53. switch (SmartcardByte) {
  54. case LIT220_READER_TYPE:
  55. // Prepare for reader type input
  56. readerExtension->GotLengthB0 = TRUE;
  57. readerExtension->GotLengthB1 = TRUE;
  58. readerExtension->DataLength.l.l0 =
  59. LIT220_READER_TYPE_LEN;
  60. break;
  61. case LIT220_READER_STATUS:
  62. // Prepare for reader status input
  63. readerExtension->GotLengthB0 = TRUE;
  64. readerExtension->GotLengthB1 = TRUE;
  65. readerExtension->DataLength.l.l0 =
  66. LIT220_READER_STATUS_LEN;
  67. break;
  68. case LIT220_RECEIVE_BLOCK:
  69. // If a smart card was already inserted in the boot phase
  70. // the reader sends only the ATR but no CARD_IN - msg.
  71. // We fix that missing msg here.
  72. //
  73. KeAcquireSpinLock(&smartcardExtension->OsData->SpinLock,
  74. &irql);
  75. if (smartcardExtension->ReaderCapabilities.CurrentState == SCARD_UNKNOWN) {
  76. smartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED;
  77. }
  78. KeReleaseSpinLock(&smartcardExtension->OsData->SpinLock,
  79. irql);
  80. break;
  81. case LIT220_CARD_IN:
  82. Lit220NotifyCardChange(
  83. smartcardExtension,
  84. TRUE
  85. );
  86. readerExtension->ReceivedByteNo = 0;
  87. break;
  88. case LIT220_CARD_OUT:
  89. Lit220NotifyCardChange(
  90. smartcardExtension,
  91. FALSE
  92. );
  93. readerExtension->ReceivedByteNo = 0;
  94. break;
  95. case LIT220_ACK:
  96. case KBD_ACK: // Also allow kdb_ack for the case for getting keyboard attention
  97. readerExtension->GotNack = FALSE;
  98. readerExtension->ReceivedByteNo = 0;
  99. // Check if anyone needs to be singaled for this event.
  100. // The Lit220SendCommand waits for the ACK signal so it knows
  101. // when it can continue.
  102. if (readerExtension->WaitMask & WAIT_ACK) {
  103. // Only signal once
  104. readerExtension->WaitMask &= ~WAIT_ACK;
  105. // Signal the AckEvnt
  106. KeSetEvent(
  107. &readerExtension->AckEvnt,
  108. 0,
  109. FALSE
  110. );
  111. }
  112. break;
  113. case LIT220_NACK:
  114. SmartcardDebug(
  115. DEBUG_ERROR,
  116. ("%s!Lit220InteruptService: LIT220_NACK\n",
  117. DRIVER_NAME)
  118. );
  119. Lit220ProcessNack(smartcardExtension);
  120. break;
  121. default:
  122. readerExtension->ReceivedByteNo = 0;
  123. SmartcardDebug(
  124. DEBUG_ERROR,
  125. ("%s!Lit220InteruptService: Invalid PacketType %xh\n",
  126. DRIVER_NAME,
  127. SmartcardByte)
  128. );
  129. // Return false so the rest of this bad buffer
  130. // will not be sent to us.
  131. retVal = FALSE;
  132. // We want to force a NACK so the
  133. // the state of the card being inserted or not
  134. // is re-checked
  135. Lit220ProcessNack(smartcardExtension);
  136. }
  137. return retVal;
  138. }
  139. //
  140. // Get length-byte-0 from reader
  141. //
  142. if (readerExtension->ReceivedByteNo == 2 &&
  143. readerExtension->GotLengthB0 == FALSE) {
  144. readerExtension->DataLength.b.b1 = SmartcardByte;
  145. readerExtension->GotLengthB0 = TRUE;
  146. return TRUE;
  147. }
  148. //
  149. // Get length-byte-1 from reader
  150. //
  151. if (readerExtension->ReceivedByteNo == 3 &&
  152. readerExtension->GotLengthB1 == FALSE) {
  153. readerExtension->DataLength.b.b0 = SmartcardByte;
  154. readerExtension->GotLengthB1 = TRUE;
  155. //
  156. // test if the reader has sent a zero-length block of data
  157. //
  158. if (readerExtension->DataLength.l.l0 == 0) {
  159. readerExtension->ReceivedByteNo = 0;
  160. readerExtension->WaitForATR = FALSE;
  161. SmartcardDebug(
  162. DEBUG_ERROR,
  163. ("%s!SmartcardInterruptService: Zero length block received\n",
  164. DRIVER_NAME)
  165. );
  166. }
  167. if (readerExtension->DataLength.l.l0 >
  168. smartcardExtension->SmartcardReply.BufferSize) {
  169. readerExtension->ReceivedByteNo = 0;
  170. readerExtension->WaitForATR = FALSE;
  171. SmartcardDebug(
  172. DEBUG_ERROR,
  173. ("%s!SmartcardInterruptService: Reply buffer not large enough\n",
  174. DRIVER_NAME)
  175. );
  176. }
  177. return TRUE;
  178. }
  179. //
  180. // store data from reader
  181. //
  182. if ((readerExtension->DataByteNo < readerExtension->DataLength.l.l0) &&
  183. (readerExtension->DataByteNo < smartcardExtension->SmartcardReply.BufferSize))
  184. {
  185. smartcardExtension->SmartcardReply.Buffer[readerExtension->DataByteNo++] =
  186. SmartcardByte;
  187. } else {
  188. SmartcardDebug(
  189. DEBUG_ERROR,
  190. ("%s!SmartcardInterruptService: DataByteNo %X too large buffer %X, %X bytest expected\n",
  191. DRIVER_NAME,
  192. readerExtension->DataByteNo,
  193. smartcardExtension->SmartcardReply.BufferSize,
  194. readerExtension->DataLength.l.l0)
  195. );
  196. }
  197. ASSERT(readerExtension->DataByteNo <= readerExtension->DataLength.l.l0);
  198. //
  199. // Have we received all the bytes in the packet yet?
  200. //
  201. if (readerExtension->DataByteNo == readerExtension->DataLength.l.l0) {
  202. // Stop the input timeout timer
  203. // schedule our remove thread
  204. Lit220ScheduleTimer(
  205. smartcardExtension,
  206. Lit220StopTimer
  207. );
  208. smartcardExtension->SmartcardReply.BufferLength =
  209. readerExtension->DataByteNo;
  210. readerExtension->ReceivedByteNo = 0;
  211. if (readerExtension->WaitForATR) {
  212. //
  213. // Transfer ATR to smartcard-struct
  214. //
  215. smartcardExtension->CardCapabilities.ATR.Length =
  216. (UCHAR) (readerExtension->DataByteNo % (SCARD_ATR_LENGTH + 1));
  217. readerExtension->WaitForATR = FALSE;
  218. if (smartcardExtension->CardCapabilities.ATR.Length >
  219. smartcardExtension->SmartcardReply.BufferLength)
  220. {
  221. SmartcardDebug(
  222. DEBUG_ERROR,
  223. ("%s!SmartcardInterruptService: SmarcardReply buffer too small for ATR\n",
  224. DRIVER_NAME)
  225. );
  226. } else {
  227. RtlCopyMemory(
  228. smartcardExtension->CardCapabilities.ATR.Buffer,
  229. smartcardExtension->SmartcardReply.Buffer,
  230. smartcardExtension->CardCapabilities.ATR.Length
  231. );
  232. SmartcardUpdateCardCapabilities(
  233. smartcardExtension
  234. );
  235. }
  236. }
  237. // Check if anyone needs to be singaled for this event.
  238. // The Lit220SendCommand waits for the DataEvnt signal so it knows
  239. // when the data has been received.
  240. if (readerExtension->WaitMask & WAIT_DATA) {
  241. //
  242. // Do any necessary post proccessing after we have receive the packet
  243. //
  244. if (smartcardExtension->OsData->CurrentIrp != NULL) {
  245. NTSTATUS status = STATUS_SUCCESS;
  246. switch (smartcardExtension->MajorIoControlCode) {
  247. case IOCTL_SMARTCARD_POWER:
  248. if (smartcardExtension->ReaderExtension->GotNack) {
  249. status = STATUS_NO_MEDIA;
  250. break;
  251. }
  252. switch(smartcardExtension->MinorIoControlCode) {
  253. case SCARD_COLD_RESET:
  254. case SCARD_WARM_RESET:
  255. if (smartcardExtension->IoRequest.ReplyBufferLength <
  256. smartcardExtension->CardCapabilities.ATR.Length) {
  257. status = STATUS_BUFFER_TOO_SMALL;
  258. } else {
  259. //
  260. // copy ATR to user buffer
  261. //
  262. if (smartcardExtension->CardCapabilities.ATR.Length <=
  263. sizeof(smartcardExtension->CardCapabilities.ATR.Buffer))
  264. {
  265. RtlCopyMemory(
  266. smartcardExtension->IoRequest.ReplyBuffer,
  267. &smartcardExtension->CardCapabilities.ATR.Buffer,
  268. smartcardExtension->CardCapabilities.ATR.Length
  269. );
  270. //
  271. // length of buffer
  272. //
  273. *(smartcardExtension->IoRequest.Information) =
  274. smartcardExtension->CardCapabilities.ATR.Length;
  275. }
  276. }
  277. break;
  278. case SCARD_POWER_DOWN:
  279. KeAcquireSpinLock(&smartcardExtension->OsData->SpinLock,
  280. &irql);
  281. if (smartcardExtension->ReaderCapabilities.CurrentState != SCARD_ABSENT) {
  282. smartcardExtension->ReaderCapabilities.CurrentState =
  283. SCARD_SWALLOWED;
  284. smartcardExtension->CardCapabilities.Protocol.Selected =
  285. SCARD_PROTOCOL_UNDEFINED;
  286. }
  287. KeReleaseSpinLock(&smartcardExtension->OsData->SpinLock,
  288. irql);
  289. break;
  290. }
  291. break;
  292. case IOCTL_SMARTCARD_SET_PROTOCOL:
  293. if (smartcardExtension->ReaderExtension->GotNack) {
  294. smartcardExtension->CardCapabilities.Protocol.Selected =
  295. SCARD_PROTOCOL_UNDEFINED;
  296. status = STATUS_NO_MEDIA;
  297. break;
  298. }
  299. //
  300. // protocol has been changed successfully
  301. //
  302. KeAcquireSpinLock(&smartcardExtension->OsData->SpinLock,
  303. &irql);
  304. if (smartcardExtension->ReaderCapabilities.CurrentState != SCARD_ABSENT) {
  305. smartcardExtension->ReaderCapabilities.CurrentState =
  306. SCARD_SPECIFIC;
  307. }
  308. KeReleaseSpinLock(&smartcardExtension->OsData->SpinLock,
  309. irql);
  310. //
  311. // Tell the caller what the current protocol is.
  312. //
  313. *(PULONG) smartcardExtension->IoRequest.ReplyBuffer =
  314. smartcardExtension->CardCapabilities.Protocol.Selected;
  315. *(smartcardExtension->IoRequest.Information) =
  316. sizeof(ULONG);
  317. break;
  318. }
  319. }
  320. // Only signal once
  321. readerExtension->WaitMask &= ~WAIT_DATA;
  322. // Signal the DataEvnt
  323. KeSetEvent(
  324. &readerExtension->DataEvnt,
  325. 0,
  326. FALSE
  327. );
  328. }
  329. }
  330. return TRUE;
  331. }
  332. VOID
  333. Lit220ProcessNack(
  334. PSMARTCARD_EXTENSION SmartcardExtension
  335. )
  336. /*++
  337. Routine Description:
  338. This routine handles everything that needs to be done when we have an error
  339. with the reader. The state of the input filter is reset. All signals that
  340. the Lit220Command function may be waiting on are fired. The flag GotNack is
  341. set which will trigger Lit220Command to resync with the reader (get the last
  342. error and refresh the card inserted state).
  343. --*/
  344. {
  345. PREADER_EXTENSION readerExtension = SmartcardExtension->ReaderExtension;
  346. // Set GotNack so we know something went wrong
  347. readerExtension->GotNack = TRUE;
  348. // Reset the input state of the filter
  349. readerExtension->ReceivedByteNo = 0;
  350. //
  351. // Signal the ACK and data semaphores and set error code
  352. // This will keep the Lit220SendCommand from having to
  353. // wait for a timeout to continue when something goes wrong.
  354. //
  355. if (readerExtension->WaitMask & WAIT_ACK) {
  356. // Signal the AckEvnt
  357. KeSetEvent(
  358. &readerExtension->AckEvnt,
  359. 0,
  360. FALSE
  361. );
  362. }
  363. if (readerExtension->WaitMask & WAIT_DATA) {
  364. // Signal the DataEvnt
  365. KeSetEvent(
  366. &readerExtension->DataEvnt,
  367. 0,
  368. FALSE
  369. );
  370. }
  371. //
  372. // Reset WaitMask since the card has nacked the command
  373. //
  374. readerExtension->WaitMask &= (WAIT_INSERTION | WAIT_REMOVAL);
  375. }
  376. VOID
  377. Lit220NotifyCardChange(
  378. IN PSMARTCARD_EXTENSION smartcardExtension,
  379. IN DWORD CardInserted
  380. )
  381. /*++
  382. Routine Description:
  383. This routine runs at DISPATCH_LEVEL IRQL to finish processing
  384. a card insertion/removal event. It is queued in the smartcard filter
  385. and notifies a caller of an insertion/removal event.
  386. --*/
  387. {
  388. PREADER_EXTENSION readerExtension = smartcardExtension->ReaderExtension;
  389. KIRQL oldOsDataIrql;
  390. if (readerExtension->CardIn == CardInserted) {
  391. return;
  392. }
  393. readerExtension->CardIn = CardInserted;
  394. KeAcquireSpinLock(
  395. &smartcardExtension->OsData->SpinLock,
  396. &oldOsDataIrql
  397. );
  398. if (CardInserted) {
  399. // Set the default state for the new card
  400. smartcardExtension->ReaderCapabilities.CurrentState =
  401. SCARD_SWALLOWED;
  402. smartcardExtension->CardCapabilities.Protocol.Selected =
  403. SCARD_PROTOCOL_UNDEFINED;
  404. } else {
  405. // Reset card state to reflect the card removal
  406. smartcardExtension->ReaderCapabilities.CurrentState =
  407. SCARD_ABSENT;
  408. smartcardExtension->CardCapabilities.Protocol.Selected =
  409. SCARD_PROTOCOL_UNDEFINED;
  410. smartcardExtension->CardCapabilities.ATR.Length = 0;
  411. }
  412. if (readerExtension->WaitMask & WAIT_INSERTION) {
  413. // We only make this notification once
  414. readerExtension->WaitMask &= ~WAIT_INSERTION;
  415. }
  416. Lit220CompleteCardTracking(smartcardExtension);
  417. KeReleaseSpinLock(
  418. &smartcardExtension->OsData->SpinLock,
  419. oldOsDataIrql
  420. );
  421. }
  422. VOID
  423. Lit220CompleteCardTracking(
  424. IN PSMARTCARD_EXTENSION SmartcardExtension
  425. )
  426. {
  427. KIRQL oldIrql;
  428. PIRP notificationIrp;
  429. SmartcardDebug(
  430. DEBUG_TRACE,
  431. ("%s!Lit220CompleteCardTracking: Enter\n",
  432. DRIVER_NAME)
  433. );
  434. IoAcquireCancelSpinLock(&oldIrql);
  435. notificationIrp = InterlockedExchangePointer(
  436. &(SmartcardExtension->OsData->NotificationIrp),
  437. NULL
  438. );
  439. if (notificationIrp) {
  440. IoSetCancelRoutine(
  441. notificationIrp,
  442. NULL
  443. );
  444. }
  445. IoReleaseCancelSpinLock(oldIrql);
  446. if (notificationIrp) {
  447. // finish the request
  448. if (notificationIrp->Cancel) {
  449. notificationIrp->IoStatus.Status = STATUS_CANCELLED;
  450. } else {
  451. notificationIrp->IoStatus.Status = STATUS_SUCCESS;
  452. }
  453. notificationIrp->IoStatus.Information = 0;
  454. IoCompleteRequest(
  455. notificationIrp,
  456. IO_NO_INCREMENT
  457. );
  458. }
  459. }
  460. NTSTATUS
  461. Lit220SerialEventCallback(
  462. IN PDEVICE_OBJECT DeviceObject,
  463. IN PIRP Irp,
  464. IN PSMARTCARD_EXTENSION SmartcardExtension
  465. )
  466. /*++
  467. Routine Description:
  468. This routine is first called as the deferred procedure when a character is received
  469. or when DSR changes its status.
  470. It first calls the serial driver to get the modem status to see if the events was
  471. due to DSR changing (meaning the reader has been removed).
  472. If DSR did not change it then checks the input queue size and reads the characters in
  473. the input queue. It then sends the input characters to the input filter for processing.
  474. Finally it calls the serial driver again to start new cts tracking (starting all over again).
  475. This routine gets continually called back from itself until the driver is ready
  476. to unload (indicated by the WaitMask set to 0).
  477. When the WaitMask is set to 0 it frees this IRP and signals the Lit220WaitForRemoval thread
  478. to close the serial port.
  479. --*/
  480. {
  481. NTSTATUS status;
  482. PIO_STACK_LOCATION irpStack;
  483. DWORD indx;
  484. KIRQL irql;
  485. PDEVICE_EXTENSION deviceExtension = SmartcardExtension->OsData->DeviceObject->DeviceExtension;
  486. SmartcardExtension->ReaderExtension->SerialEventState++;
  487. //
  488. // First check to see we are being unloaded
  489. //
  490. if (SmartcardExtension->ReaderExtension->SerialConfigData.WaitMask == 0) {
  491. SmartcardDebug(
  492. DEBUG_DRIVER,
  493. ("%s!Lit220SerialEventCallback: WAIT MASK 0 UNLOADING !!!!\n",
  494. DRIVER_NAME)
  495. );
  496. KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
  497. &irql);
  498. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN;
  499. KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
  500. irql);
  501. //
  502. // If the WaitMask is 0 then the driver is about to unload and we've
  503. // been called because the unload function has directed the serial
  504. // driver to complete the outstanding io completion.
  505. //
  506. // schedule our remove thread
  507. IoQueueWorkItem(
  508. deviceExtension->WorkItem,
  509. (PIO_WORKITEM_ROUTINE) Lit220CloseSerialPort,
  510. DelayedWorkQueue,
  511. NULL
  512. );
  513. //
  514. // We don't need the IRP anymore, so free it and tell the
  515. // io subsystem not to touch it anymore by returning the value below
  516. //
  517. IoFreeIrp(Irp);
  518. return STATUS_MORE_PROCESSING_REQUIRED;
  519. }
  520. // Get next stack location for next IRP
  521. irpStack = IoGetNextIrpStackLocation(
  522. SmartcardExtension->ReaderExtension->CardStatus.Irp
  523. );
  524. if (irpStack == NULL) {
  525. // Fatal Error
  526. SmartcardDebug(
  527. DEBUG_ERROR,
  528. ("%s!Lit220SerialEventCallback: Error IoGetNextIrpStackLocation returned NULL - exiting.\n",
  529. DRIVER_NAME)
  530. );
  531. return STATUS_SUCCESS;
  532. }
  533. switch (SmartcardExtension->ReaderExtension->SerialEventState) {
  534. case 1:
  535. //
  536. // First we send a get modem status
  537. //
  538. irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  539. irpStack->MinorFunction = 0UL;
  540. irpStack->Parameters.DeviceIoControl.OutputBufferLength =
  541. sizeof(SmartcardExtension->ReaderExtension->ModemStatus);
  542. irpStack->Parameters.DeviceIoControl.IoControlCode =
  543. IOCTL_SERIAL_GET_MODEMSTATUS;
  544. SmartcardExtension->ReaderExtension->CardStatus.Irp->AssociatedIrp.SystemBuffer =
  545. &SmartcardExtension->ReaderExtension->ModemStatus;
  546. break;
  547. case 2:
  548. //
  549. // Check modem status if DSR = 0 then unload driver if not
  550. // then get queuestatus
  551. //
  552. if ((SmartcardExtension->ReaderExtension->ModemStatus & SERIAL_DSR_STATE) == 0) {
  553. // DSR is 0 this means the reader has been removed
  554. SmartcardDebug(
  555. DEBUG_DRIVER,
  556. ("%s!Lit220SerialEventCallback: DSR = 0 signaling to close device\n",
  557. DRIVER_NAME)
  558. );
  559. KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
  560. &irql);
  561. SmartcardExtension->ReaderExtension->SerialConfigData.WaitMask = 0;
  562. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN;
  563. KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
  564. irql);
  565. // schedule our remove thread
  566. IoQueueWorkItem(
  567. deviceExtension->WorkItem,
  568. (PIO_WORKITEM_ROUTINE) Lit220CloseSerialPort,
  569. DelayedWorkQueue,
  570. NULL
  571. );
  572. //
  573. // We don't need the IRP anymore, so free it and tell the
  574. // io subsystem not to touch it anymore by returning the value below
  575. //
  576. IoFreeIrp(Irp);
  577. return STATUS_MORE_PROCESSING_REQUIRED;
  578. } else {
  579. // Device is not removed - there must be a character ready
  580. // Read the data into our temporary buffer. The temporary buffer
  581. // is large enough to read whatever the reader can send us a one time.
  582. // The character interval timeout will stop the read at the end of whatever
  583. // the reader sends us.
  584. SmartcardExtension->ReaderExtension->SerialStatus.AmountInInQueue =
  585. sizeof(SmartcardExtension->ReaderExtension->TempXferBuf);
  586. // Read the characters
  587. irpStack->MajorFunction = IRP_MJ_READ;
  588. irpStack->Parameters.Read.Length =
  589. sizeof(SmartcardExtension->ReaderExtension->TempXferBuf);
  590. irpStack->MinorFunction = 0UL;
  591. SmartcardExtension->ReaderExtension->CardStatus.Irp->AssociatedIrp.SystemBuffer =
  592. SmartcardExtension->ReaderExtension->TempXferBuf;
  593. }
  594. break;
  595. case 3:
  596. //
  597. // Send the characers we read to the input filter then setup for read input
  598. // queue again (in case some characters came in while we were processing the
  599. // ones we just read).
  600. //
  601. for (indx = 0; indx < Irp->IoStatus.Information; indx++) {
  602. if (!Lit220InputFilter(
  603. SmartcardExtension->ReaderExtension->TempXferBuf[indx],
  604. SmartcardExtension
  605. ))
  606. {
  607. // An invalid character was received so stop sending the rest of
  608. // the data to the filter because it is probably corrupted.
  609. break;
  610. }
  611. }
  612. // Check if we are in the middle of a block of data
  613. if (SmartcardExtension->ReaderExtension->ReceivedByteNo != 0) {
  614. // Start the timeout timer. If we don't get the rest of this
  615. // data block in a few seconds we will timeout. This prevents
  616. // communication problems between the reader and the PC causing
  617. // locking up a T=0 card for too long.
  618. Lit220ScheduleTimer(
  619. SmartcardExtension,
  620. Lit220StartTimer
  621. );
  622. }
  623. //
  624. // Read done - start all over again with the wait_on_mask
  625. //
  626. irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  627. irpStack->MinorFunction = 0UL;
  628. irpStack->Parameters.DeviceIoControl.OutputBufferLength =
  629. sizeof(SmartcardExtension->ReaderExtension->SerialConfigData.WaitMask);
  630. irpStack->Parameters.DeviceIoControl.IoControlCode =
  631. IOCTL_SERIAL_WAIT_ON_MASK;
  632. SmartcardExtension->ReaderExtension->CardStatus.Irp->AssociatedIrp.SystemBuffer =
  633. &SmartcardExtension->ReaderExtension->SerialConfigData.WaitMask;
  634. // Reset SerialEventState value
  635. SmartcardExtension->ReaderExtension->SerialEventState = 0;
  636. break;
  637. default:
  638. SmartcardDebug(
  639. DEBUG_ERROR,
  640. ("%s!Lit220SerialEventCallback: Error SerialEventState is out of bounds - resetting to 0\n",
  641. DRIVER_NAME)
  642. );
  643. //
  644. // We should never get here, but if we do we should try to recover the
  645. // best we can by setting up for the wait_on_mask.
  646. //
  647. // Reset value
  648. SmartcardExtension->ReaderExtension->SerialEventState = 0;
  649. // Setup for next callback
  650. irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  651. irpStack->MinorFunction = 0UL;
  652. irpStack->Parameters.DeviceIoControl.OutputBufferLength =
  653. sizeof(SmartcardExtension->ReaderExtension->SerialConfigData.WaitMask);
  654. irpStack->Parameters.DeviceIoControl.IoControlCode =
  655. IOCTL_SERIAL_WAIT_ON_MASK;
  656. SmartcardExtension->ReaderExtension->CardStatus.Irp->AssociatedIrp.SystemBuffer =
  657. &SmartcardExtension->ReaderExtension->SerialConfigData.WaitMask;
  658. }
  659. // We always call this same function when we complete a call
  660. IoSetCompletionRoutine(
  661. SmartcardExtension->ReaderExtension->CardStatus.Irp,
  662. Lit220SerialEventCallback,
  663. SmartcardExtension,
  664. TRUE,
  665. TRUE,
  666. TRUE
  667. );
  668. // Call the serial driver
  669. status = IoCallDriver(
  670. SmartcardExtension->ReaderExtension->ConnectedSerialPort,
  671. SmartcardExtension->ReaderExtension->CardStatus.Irp
  672. );
  673. // Return STATUS_MORE_PROCESSING_REQUIRED so our IRP stays around
  674. return STATUS_MORE_PROCESSING_REQUIRED;
  675. }
  676. VOID
  677. Lit220ScheduleTimer(
  678. IN PSMARTCARD_EXTENSION SmartcardExtension,
  679. IN PIO_WORKITEM_ROUTINE Routine
  680. )
  681. {
  682. PIO_WORKITEM workItem = IoAllocateWorkItem(
  683. SmartcardExtension->OsData->DeviceObject
  684. );
  685. if (workItem != NULL) {
  686. IoQueueWorkItem(
  687. workItem,
  688. Routine,
  689. CriticalWorkQueue,
  690. workItem
  691. );
  692. }
  693. }
  694. VOID
  695. Lit220StartTimer(
  696. IN PDEVICE_OBJECT DeviceObject,
  697. IN PIO_WORKITEM WorkItem
  698. )
  699. /*++
  700. Routine Description:
  701. This routine starts the timeout timer. The function is executed as a worker
  702. thread so IoStartTimer does not get called at the wrong IRQL.
  703. --*/
  704. {
  705. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  706. PAGED_CODE();
  707. deviceExtension->EntryCount = 0;
  708. IoStartTimer(DeviceObject);
  709. IoFreeWorkItem(WorkItem);
  710. }
  711. VOID
  712. Lit220StopTimer(
  713. IN PDEVICE_OBJECT DeviceObject,
  714. IN PIO_WORKITEM WorkItem
  715. )
  716. /*++
  717. Routine Description:
  718. This routine stops the timeout timer. The function is executed as a worker
  719. thread so IoStopTimer does not get called at the wrong IRQL.
  720. --*/
  721. {
  722. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  723. PAGED_CODE();
  724. IoStopTimer(DeviceObject);
  725. IoFreeWorkItem(WorkItem);
  726. }
  727. VOID
  728. Lit220ReceiveBlockTimeout(
  729. IN PDEVICE_OBJECT DeviceObject,
  730. IN PVOID Context
  731. )
  732. /*++
  733. Routine Description:
  734. This routine is timeout callback. A timeout is setup every time we get an
  735. incomplete block of data. Once we receive the complete block the timeout
  736. will be canceled. The type of timer we use for the timeout gets called
  737. once every second. We want to time out after a few seconds, so we keep track
  738. of how many time we get called and then timeout after we have been called
  739. 5 times.
  740. --*/
  741. {
  742. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  743. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  744. PREADER_EXTENSION readerExtension = smartcardExtension->ReaderExtension;
  745. if (readerExtension->DataByteNo == readerExtension->DataLength.l.l0) {
  746. // Stop the timer we got all the bytes we need
  747. Lit220ScheduleTimer(
  748. smartcardExtension,
  749. Lit220StopTimer
  750. );
  751. return;
  752. }
  753. if (++deviceExtension->EntryCount >= 5) {
  754. SmartcardDebug(
  755. DEBUG_ERROR,
  756. ("%s!Lit220ReceiveBlockTimeout: Communication with reader timed-out\n",
  757. DRIVER_NAME)
  758. );
  759. // Process the timeout
  760. Lit220ProcessNack(smartcardExtension);
  761. // A timeout has occured schedule worker thread to
  762. // stop the timer
  763. Lit220ScheduleTimer(
  764. smartcardExtension,
  765. Lit220StopTimer
  766. );
  767. deviceExtension->EntryCount = 0;
  768. }
  769. }