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.

1345 lines
34 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation and Litronic, 1998 - 1999
  3. Module Name:
  4. L220SCR.c - Main module for Driver
  5. Abstract:
  6. Author:
  7. Brian Manahan
  8. Environment:
  9. Kernel mode
  10. Revision History :
  11. --*/
  12. #include <stdio.h>
  13. #include "L220SCR.h"
  14. // Make functions pageable
  15. #pragma alloc_text(PAGEABLE, Lit220IsCardPresent)
  16. #pragma alloc_text(PAGEABLE, Lit220Initialize)
  17. #pragma alloc_text(PAGEABLE, Lit220ConfigureSerialPort)
  18. #pragma alloc_text(PAGEABLE, Lit220CreateClose)
  19. #pragma alloc_text(PAGEABLE, Lit220Unload)
  20. #pragma alloc_text(PAGEABLE, Lit220InitializeInputFilter)
  21. #if DBG
  22. #pragma optimize ("", off)
  23. #endif
  24. BOOLEAN
  25. Lit220IsCardPresent(
  26. IN PSMARTCARD_EXTENSION SmartcardExtension
  27. )
  28. /*++
  29. Routine Description:
  30. This routine checks if a card is in the socket. It is only done
  31. when the driver starts to set the intial state. After that the
  32. reader will tell us when the status changes.
  33. It makes synchronous calls to the serial port.
  34. --*/
  35. {
  36. PSMARTCARD_REQUEST smartcardRequest = &SmartcardExtension->SmartcardRequest;
  37. NTSTATUS status;
  38. PAGED_CODE();
  39. SmartcardDebug(
  40. DEBUG_TRACE,
  41. ("%s!Lit220IsCardPresent: Enter\n",
  42. DRIVER_NAME)
  43. );
  44. smartcardRequest->BufferLength = 0;
  45. //
  46. // Send a get reader status to see if a card is inserted
  47. //
  48. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  49. LIT220_READER_ATTENTION;
  50. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  51. LIT220_READER_ATTENTION;
  52. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  53. LIT220_GET_READER_STATUS;
  54. //
  55. // We Expect to get a response
  56. //
  57. SmartcardExtension->ReaderExtension->WaitMask |= WAIT_DATA;
  58. // Send the command
  59. status = Lit220Command(
  60. SmartcardExtension
  61. );
  62. if (status != STATUS_SUCCESS) {
  63. return FALSE;
  64. }
  65. // Check if length is correct
  66. if (SmartcardExtension->SmartcardReply.BufferLength != LIT220_READER_STATUS_LEN) {
  67. SmartcardDebug(
  68. DEBUG_ERROR,
  69. ("%s!Lit220IsCardPresent: Reader response - bufLen %X, should be %X\n",
  70. DRIVER_NAME,
  71. SmartcardExtension->SmartcardReply.BufferLength,
  72. LIT220_READER_STATUS_LEN)
  73. );
  74. return FALSE;
  75. }
  76. // Check status byte to see if card is inserted
  77. if (SmartcardExtension->SmartcardReply.Buffer[0] & LIT220_STATUS_CARD_INSERTED) {
  78. SmartcardDebug(
  79. DEBUG_DRIVER,
  80. ("%s!Lit220IsCardPresent: Card is inserted\n",
  81. DRIVER_NAME)
  82. );
  83. return TRUE;
  84. }
  85. SmartcardDebug(
  86. DEBUG_DRIVER,
  87. ("%s!Lit220IsCardPresent: Card is not inserted\n",
  88. DRIVER_NAME)
  89. );
  90. return FALSE;
  91. }
  92. NTSTATUS
  93. Lit220Initialize(
  94. IN PSMARTCARD_EXTENSION SmartcardExtension
  95. )
  96. /*++
  97. Routine Description:
  98. This routine initializes the reader for use.
  99. It sets up the serial communications, checks to make sure our
  100. reader is attached, checks if a card is inserted or not and
  101. sets up the input filter for receiving bytes from the reader
  102. asynchronously.
  103. --*/
  104. {
  105. PREADER_EXTENSION readerExtension;
  106. NTSTATUS status;
  107. PAGED_CODE();
  108. SmartcardDebug(
  109. DEBUG_TRACE,
  110. ("%s!Lit220Initialize: Enter - SmartcardExtension %X\n",
  111. DRIVER_NAME,
  112. SmartcardExtension)
  113. );
  114. readerExtension = SmartcardExtension->ReaderExtension;
  115. //
  116. // Set the serial config data
  117. //
  118. // We always talk to the at 57600 no matter what speed the reader talks to the card
  119. readerExtension->SerialConfigData.BaudRate.BaudRate = 57600;
  120. readerExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2;
  121. readerExtension->SerialConfigData.LineControl.Parity = EVEN_PARITY;
  122. readerExtension->SerialConfigData.LineControl.WordLength = SERIAL_DATABITS_8;
  123. //
  124. // set timeouts
  125. //
  126. readerExtension->SerialConfigData.Timeouts.ReadIntervalTimeout = 10;
  127. readerExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = 1;
  128. readerExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = 1;
  129. //
  130. // set special characters
  131. //
  132. readerExtension->SerialConfigData.SerialChars.ErrorChar = 0;
  133. readerExtension->SerialConfigData.SerialChars.EofChar = 0;
  134. readerExtension->SerialConfigData.SerialChars.EventChar = 0;
  135. readerExtension->SerialConfigData.SerialChars.XonChar = 0;
  136. readerExtension->SerialConfigData.SerialChars.XoffChar = 0;
  137. readerExtension->SerialConfigData.SerialChars.BreakChar = 0xFF;
  138. //
  139. // Set handflow
  140. //
  141. readerExtension->SerialConfigData.HandFlow.XonLimit = 0;
  142. readerExtension->SerialConfigData.HandFlow.XoffLimit = 0;
  143. readerExtension->SerialConfigData.HandFlow.FlowReplace = SERIAL_XOFF_CONTINUE ;
  144. readerExtension->SerialConfigData.HandFlow.ControlHandShake = 0;
  145. //
  146. // Now setup default the card state
  147. //
  148. SmartcardExtension->ReaderCapabilities.CurrentState = (ULONG) SCARD_UNKNOWN;
  149. //
  150. // Set the MechProperties
  151. //
  152. SmartcardExtension->ReaderCapabilities.MechProperties = 0;
  153. try {
  154. //
  155. // Configure the serial port
  156. //
  157. status = Lit220ConfigureSerialPort(
  158. SmartcardExtension
  159. );
  160. if (status != STATUS_SUCCESS) {
  161. SmartcardLogError(
  162. SmartcardExtension->OsData->DeviceObject,
  163. LIT220_SERIAL_COMUNICATION_FAILURE,
  164. NULL,
  165. 0
  166. );
  167. SmartcardDebug(DEBUG_ERROR,
  168. ("%s!Lit220Initialize: ConfiguringSerialPort failed %X\n",
  169. DRIVER_NAME,
  170. status)
  171. );
  172. leave;
  173. }
  174. //
  175. // Initailize the input filter now
  176. //
  177. status = Lit220InitializeInputFilter(
  178. SmartcardExtension
  179. );
  180. if (status != STATUS_SUCCESS) {
  181. SmartcardLogError(
  182. SmartcardExtension->OsData->DeviceObject,
  183. LIT220_SERIAL_COMUNICATION_FAILURE,
  184. NULL,
  185. 0
  186. );
  187. SmartcardDebug(DEBUG_ERROR,
  188. ("%s!Lit220Initialize: Lit220InitializeInputFilter failed %X\n",
  189. DRIVER_NAME, status)
  190. );
  191. leave;
  192. }
  193. //
  194. // Now check if the card is inserted
  195. //
  196. if (Lit220IsCardPresent(SmartcardExtension)) {
  197. // Card is inserted
  198. SmartcardExtension->ReaderCapabilities.CurrentState =
  199. SCARD_SWALLOWED;
  200. SmartcardExtension->CardCapabilities.Protocol.Selected =
  201. SCARD_PROTOCOL_UNDEFINED;
  202. SmartcardExtension->ReaderExtension->CardIn = TRUE;
  203. } else {
  204. // Card is not inserted
  205. SmartcardExtension->ReaderCapabilities.CurrentState =
  206. SCARD_ABSENT;
  207. SmartcardExtension->CardCapabilities.Protocol.Selected =
  208. SCARD_PROTOCOL_UNDEFINED;
  209. SmartcardExtension->ReaderExtension->CardIn = FALSE;
  210. }
  211. }
  212. finally
  213. {
  214. SmartcardDebug(DEBUG_TRACE,
  215. ("%s!Lit220Initialize: Exit - status %X\n",
  216. DRIVER_NAME, status)
  217. );
  218. }
  219. return status;
  220. }
  221. NTSTATUS
  222. Lit220ConfigureSerialPort(
  223. PSMARTCARD_EXTENSION SmartcardExtension
  224. )
  225. /*++
  226. Routine Description:
  227. This routine will appropriately configure the serial port.
  228. It makes synchronous calls to the serial port.
  229. Arguments:
  230. SmartcardExtension - Pointer to smart card struct
  231. Return Value:
  232. NTSTATUS
  233. --*/
  234. {
  235. PSERIAL_READER_CONFIG configData = &SmartcardExtension->ReaderExtension->SerialConfigData;
  236. NTSTATUS status = STATUS_SUCCESS;
  237. LARGE_INTEGER WaitTime;
  238. PSERIALPERF_STATS perfData;
  239. USHORT indx;
  240. PUCHAR request = SmartcardExtension->SmartcardRequest.Buffer;
  241. PAGED_CODE();
  242. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  243. SmartcardExtension->SmartcardReply.BufferLength =
  244. SmartcardExtension->SmartcardReply.BufferSize;
  245. for (indx = 0; NT_SUCCESS(status); indx++) {
  246. switch (indx) {
  247. case 0:
  248. //
  249. // Set up baudrate for the Lit220 reader
  250. //
  251. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  252. IOCTL_SERIAL_SET_BAUD_RATE;
  253. SmartcardExtension->SmartcardRequest.Buffer =
  254. (PUCHAR) &configData->BaudRate;
  255. SmartcardExtension->SmartcardRequest.BufferLength =
  256. sizeof(SERIAL_BAUD_RATE);
  257. break;
  258. case 1:
  259. //
  260. // Set up line control parameters
  261. //
  262. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  263. IOCTL_SERIAL_SET_LINE_CONTROL;
  264. SmartcardExtension->SmartcardRequest.Buffer =
  265. (PUCHAR) &configData->LineControl;
  266. SmartcardExtension->SmartcardRequest.BufferLength =
  267. sizeof(SERIAL_LINE_CONTROL);
  268. break;
  269. case 2:
  270. //
  271. // Set serial special characters
  272. //
  273. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  274. IOCTL_SERIAL_SET_CHARS;
  275. SmartcardExtension->SmartcardRequest.Buffer =
  276. (PUCHAR) &configData->SerialChars;
  277. SmartcardExtension->SmartcardRequest.BufferLength =
  278. sizeof(SERIAL_CHARS);
  279. break;
  280. case 3:
  281. //
  282. // Set up timeouts
  283. //
  284. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  285. IOCTL_SERIAL_SET_TIMEOUTS;
  286. SmartcardExtension->SmartcardRequest.Buffer =
  287. (PUCHAR) &configData->Timeouts;
  288. SmartcardExtension->SmartcardRequest.BufferLength =
  289. sizeof(SERIAL_TIMEOUTS);
  290. break;
  291. case 4:
  292. //
  293. // Set flowcontrol and handshaking
  294. //
  295. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  296. IOCTL_SERIAL_SET_HANDFLOW;
  297. SmartcardExtension->SmartcardRequest.Buffer =
  298. (PUCHAR) &configData->HandFlow;
  299. SmartcardExtension->SmartcardRequest.BufferLength =
  300. sizeof(SERIAL_HANDFLOW);
  301. break;
  302. case 5:
  303. //
  304. // Set break off
  305. //
  306. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  307. IOCTL_SERIAL_SET_BREAK_OFF;
  308. break;
  309. case 6:
  310. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  311. IOCTL_SERIAL_SET_DTR;
  312. break;
  313. case 7:
  314. // 500ms delay before we send the next command
  315. // To give the reader a chance to calm down after we started it.
  316. WaitTime.HighPart = -1;
  317. WaitTime.LowPart = -500 * 10000;
  318. KeDelayExecutionThread(
  319. KernelMode,
  320. FALSE,
  321. &WaitTime
  322. );
  323. // Clear possible error condition with the serial port
  324. perfData =
  325. (PSERIALPERF_STATS) SmartcardExtension->SmartcardReply.Buffer;
  326. // we have to call GetCommStatus to reset the error condition
  327. SmartcardExtension->ReaderExtension->SerialIoControlCode =
  328. IOCTL_SERIAL_GET_COMMSTATUS;
  329. SmartcardExtension->SmartcardRequest.BufferLength = 0;
  330. SmartcardExtension->SmartcardReply.BufferLength =
  331. sizeof(SERIAL_STATUS);
  332. break;
  333. case 8:
  334. return STATUS_SUCCESS;
  335. }
  336. // Send the command to the serial driver
  337. status = Lit220SerialIo(SmartcardExtension);
  338. //
  339. // restore pointer to original request buffer
  340. //
  341. SmartcardExtension->SmartcardRequest.Buffer = request;
  342. }
  343. return status;
  344. }
  345. NTSTATUS
  346. Lit220CreateClose(
  347. IN PDEVICE_OBJECT DeviceObject,
  348. IN PIRP Irp
  349. )
  350. /*++
  351. Routine Description:
  352. This routine is called by the I/O system when the device is opened or closed.
  353. Arguments:
  354. DeviceObject - Pointer to device object for this miniport
  355. Irp - IRP involved.
  356. Return Value:
  357. STATUS_SUCCESS.
  358. --*/
  359. {
  360. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  361. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  362. NTSTATUS status = STATUS_SUCCESS;
  363. if (irpStack->MajorFunction == IRP_MJ_CREATE) {
  364. status = SmartcardAcquireRemoveLockWithTag(
  365. &deviceExtension->SmartcardExtension,
  366. 'lCrC'
  367. );
  368. if (status != STATUS_SUCCESS) {
  369. status = STATUS_DEVICE_REMOVED;
  370. } else {
  371. // test if the device has been opened already
  372. if (InterlockedCompareExchange(
  373. &deviceExtension->ReaderOpen,
  374. TRUE,
  375. FALSE) == FALSE) {
  376. SmartcardDebug(
  377. DEBUG_DRIVER,
  378. ("%s!Lit220CreateClose: Open\n",
  379. DRIVER_NAME)
  380. );
  381. } else {
  382. // the device is already in use
  383. status = STATUS_UNSUCCESSFUL;
  384. // release the lock
  385. SmartcardReleaseRemoveLockWithTag(
  386. &deviceExtension->SmartcardExtension,
  387. 'lCrC'
  388. );
  389. }
  390. }
  391. } else {
  392. SmartcardDebug(
  393. DEBUG_DRIVER,
  394. ("%s!Lit220CreateClose: Close\n",
  395. DRIVER_NAME)
  396. );
  397. SmartcardReleaseRemoveLockWithTag(
  398. &deviceExtension->SmartcardExtension,
  399. 'lCrC'
  400. );
  401. deviceExtension->ReaderOpen = FALSE;
  402. }
  403. Irp->IoStatus.Status = status;
  404. Irp->IoStatus.Information = 0;
  405. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  406. return status;
  407. }
  408. NTSTATUS
  409. Lit220Cancel(
  410. IN PDEVICE_OBJECT DeviceObject,
  411. IN PIRP Irp
  412. )
  413. /*++
  414. Routine Description:
  415. This routine is called by the I/O system
  416. when the irp should be cancelled
  417. Arguments:
  418. DeviceObject - Pointer to device object for this miniport
  419. Irp - IRP involved.
  420. Return Value:
  421. STATUS_CANCELLED
  422. --*/
  423. {
  424. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  425. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  426. SmartcardDebug(
  427. DEBUG_TRACE,
  428. ("%s!Lit220Cancel: Enter\n",
  429. DRIVER_NAME)
  430. );
  431. ASSERT(Irp == smartcardExtension->OsData->NotificationIrp);
  432. IoReleaseCancelSpinLock(
  433. Irp->CancelIrql
  434. );
  435. Lit220CompleteCardTracking(
  436. smartcardExtension
  437. );
  438. SmartcardDebug(
  439. DEBUG_TRACE,
  440. ("%s!Lit220Cancel: Exit\n",
  441. DRIVER_NAME)
  442. );
  443. return STATUS_CANCELLED;
  444. }
  445. NTSTATUS
  446. Lit220Cleanup(
  447. IN PDEVICE_OBJECT DeviceObject,
  448. IN PIRP Irp
  449. )
  450. /*++
  451. Routine Description:
  452. This routine is called by the I/O system when the calling thread terminates
  453. or when the irp should be cancelled
  454. Arguments:
  455. DeviceObject - Pointer to device object for this miniport
  456. Irp - IRP involved.
  457. Return Value:
  458. STATUS_CANCELLED
  459. --*/
  460. {
  461. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  462. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  463. PREADER_EXTENSION ReaderExtension = smartcardExtension->ReaderExtension;
  464. NTSTATUS status = STATUS_SUCCESS;
  465. KIRQL oldOsDataIrql;
  466. SmartcardDebug(
  467. DEBUG_TRACE,
  468. ("%s!Lit220Cleanup: Enter\n",
  469. DRIVER_NAME)
  470. );
  471. Lit220CompleteCardTracking(smartcardExtension);
  472. SmartcardDebug(
  473. DEBUG_DRIVER,
  474. ("%s!Lit220Cleanup: Completing IRP %lx\n",
  475. DRIVER_NAME,
  476. Irp)
  477. );
  478. Irp->IoStatus.Information = 0;
  479. Irp->IoStatus.Status = STATUS_SUCCESS;
  480. IoCompleteRequest(
  481. Irp,
  482. IO_NO_INCREMENT
  483. );
  484. SmartcardDebug(
  485. DEBUG_TRACE,
  486. ("%s!Lit220Cleanup: Exit\n",
  487. DRIVER_NAME)
  488. );
  489. return STATUS_SUCCESS;
  490. }
  491. VOID
  492. Lit220Unload(
  493. IN PDRIVER_OBJECT DriverObject
  494. )
  495. /*++
  496. Routine Description:
  497. The driver unload routine. This is called by the I/O system
  498. when the device is unloaded from memory.
  499. Arguments:
  500. DriverObject - Pointer to driver object created by system.
  501. Return Value:
  502. STATUS_SUCCESS.
  503. --*/
  504. {
  505. PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
  506. NTSTATUS status;
  507. PAGED_CODE();
  508. SmartcardDebug(
  509. DEBUG_TRACE,
  510. ("%s!Lit220Unload: Enter\n",
  511. DRIVER_NAME)
  512. );
  513. //
  514. // All the device objects should be gone.
  515. //
  516. ASSERT (NULL == DriverObject->DeviceObject);
  517. //
  518. // Here we free any resources allocated in DriverEntry
  519. //
  520. SmartcardDebug(
  521. DEBUG_TRACE,
  522. ("%s!Lit220Unload: Exit\n",
  523. DRIVER_NAME)
  524. );
  525. }
  526. NTSTATUS
  527. Lit220SerialIo(
  528. IN PSMARTCARD_EXTENSION SmartcardExtension
  529. )
  530. /*++
  531. Routine Description:
  532. This routine sends IOCTL's to the serial driver. It waits on for their
  533. completion, and then returns.
  534. Arguments:
  535. Return Value:
  536. NTSTATUS
  537. --*/
  538. {
  539. NTSTATUS status;
  540. ULONG currentByte = 0;
  541. DWORD indx;
  542. PDEVICE_EXTENSION devExt = SmartcardExtension->OsData->DeviceObject->DeviceExtension;
  543. if (KeReadStateEvent(&devExt->SerialCloseDone)) {
  544. //
  545. // we have no connection to serial, fail the call
  546. // this could be the case if the reader was removed
  547. // during stand by / hibernation
  548. //
  549. return STATUS_UNSUCCESSFUL;
  550. }
  551. //
  552. // Check if the buffers are large enough
  553. //
  554. ASSERT(SmartcardExtension->SmartcardReply.BufferLength <=
  555. SmartcardExtension->SmartcardReply.BufferSize);
  556. ASSERT(SmartcardExtension->SmartcardRequest.BufferLength <=
  557. SmartcardExtension->SmartcardRequest.BufferSize);
  558. if (SmartcardExtension->SmartcardReply.BufferLength >
  559. SmartcardExtension->SmartcardReply.BufferSize ||
  560. SmartcardExtension->SmartcardRequest.BufferLength >
  561. SmartcardExtension->SmartcardRequest.BufferSize) {
  562. SmartcardLogError(
  563. SmartcardExtension->OsData->DeviceObject,
  564. LIT220_BUFFER_TOO_SMALL,
  565. NULL,
  566. 0
  567. );
  568. return STATUS_BUFFER_TOO_SMALL;
  569. }
  570. do {
  571. IO_STATUS_BLOCK ioStatus;
  572. KEVENT event;
  573. PIRP irp;
  574. PIO_STACK_LOCATION irpNextStack;
  575. PUCHAR requestBuffer = NULL;
  576. PUCHAR replyBuffer = SmartcardExtension->SmartcardReply.Buffer;
  577. ULONG requestBufferLength = 0;
  578. ULONG replyBufferLength = SmartcardExtension->SmartcardReply.BufferLength;
  579. KeInitializeEvent(
  580. &event,
  581. NotificationEvent,
  582. FALSE
  583. );
  584. if (SmartcardExtension->ReaderExtension->SerialIoControlCode ==
  585. IOCTL_SMARTCARD_220_WRITE) {
  586. //
  587. // If we write data to the smart card we only write byte by byte,
  588. // because we have to insert a delay between every sent byte
  589. //
  590. requestBufferLength =
  591. SmartcardExtension->SmartcardRequest.BufferLength;
  592. requestBuffer =
  593. SmartcardExtension->SmartcardRequest.Buffer;
  594. #if DBG // DbgPrint the buffer
  595. SmartcardDebug(
  596. DEBUG_DRIVER,
  597. ("%s!Lit220SerialIo - Sending Buffer - ",
  598. DRIVER_NAME)
  599. );
  600. for (indx=0; indx<requestBufferLength; indx++){
  601. SmartcardDebug(
  602. DEBUG_DRIVER,
  603. ("%X, ",
  604. requestBuffer[indx])
  605. );
  606. }
  607. SmartcardDebug(
  608. DEBUG_DRIVER,
  609. ("\n")
  610. );
  611. #endif
  612. } else {
  613. requestBufferLength =
  614. SmartcardExtension->SmartcardRequest.BufferLength;
  615. requestBuffer =
  616. (requestBufferLength ?
  617. SmartcardExtension->SmartcardRequest.Buffer : NULL);
  618. }
  619. //
  620. // Build irp to be sent to serial driver
  621. //
  622. irp = IoBuildDeviceIoControlRequest(
  623. SmartcardExtension->ReaderExtension->SerialIoControlCode,
  624. SmartcardExtension->ReaderExtension->ConnectedSerialPort,
  625. requestBuffer,
  626. requestBufferLength,
  627. replyBuffer,
  628. replyBufferLength,
  629. FALSE,
  630. &event,
  631. &ioStatus
  632. );
  633. ASSERT(irp != NULL);
  634. if (irp == NULL) {
  635. return STATUS_INSUFFICIENT_RESOURCES;
  636. }
  637. irpNextStack = IoGetNextIrpStackLocation(irp);
  638. switch (SmartcardExtension->ReaderExtension->SerialIoControlCode) {
  639. //
  640. // The serial driver trasfers data from/to irp->AssociatedIrp.SystemBuffer
  641. //
  642. case IOCTL_SMARTCARD_220_WRITE:
  643. irpNextStack->MajorFunction = IRP_MJ_WRITE;
  644. irpNextStack->Parameters.Write.Length =
  645. SmartcardExtension->SmartcardRequest.BufferLength;
  646. break;
  647. case IOCTL_SMARTCARD_220_READ:
  648. irpNextStack->MajorFunction = IRP_MJ_READ;
  649. irpNextStack->Parameters.Read.Length =
  650. SmartcardExtension->SmartcardReply.BufferLength;
  651. break;
  652. }
  653. // Send the command to the serial driver
  654. status = IoCallDriver(
  655. SmartcardExtension->ReaderExtension->ConnectedSerialPort,
  656. irp
  657. );
  658. if (status == STATUS_PENDING) {
  659. // Wait for the command to complete
  660. KeWaitForSingleObject(
  661. &event,
  662. Suspended,
  663. KernelMode,
  664. FALSE,
  665. NULL
  666. );
  667. status = ioStatus.Status;
  668. }
  669. } while (status == STATUS_MORE_PROCESSING_REQUIRED);
  670. return status;
  671. }
  672. NTSTATUS
  673. Lit220InitializeInputFilter(
  674. PSMARTCARD_EXTENSION SmartcardExtension
  675. )
  676. /*++
  677. Routine Description:
  678. This routine initialized input filter. It calls the serial driver to
  679. set a wait mask for character input or DSR change. After that it installs a completion
  680. routine to be called when a character is received or when DSR changes.
  681. The completion routine for the wait is Lit220SerialEventCallback and that IRP will
  682. run until the device is ready to be removed.
  683. Arguments:
  684. SmartcardExtension - Pointer to our smartcard structure
  685. Return Value:
  686. NTSTATUS
  687. --*/
  688. {
  689. NTSTATUS status;
  690. PREADER_EXTENSION readerExtension = SmartcardExtension->ReaderExtension;
  691. PAGED_CODE();
  692. // Set the WaitMask
  693. SmartcardExtension->ReaderExtension->SerialConfigData.WaitMask =
  694. SERIAL_EV_RXCHAR | SERIAL_EV_DSR;
  695. KeInitializeEvent(
  696. &SmartcardExtension->ReaderExtension->CardStatus.Event,
  697. NotificationEvent,
  698. FALSE
  699. );
  700. try {
  701. //
  702. // Send a wait mask to the serial driver.
  703. // This call only sets the wait mask.
  704. // We want to be informed if a character is received
  705. //
  706. SmartcardExtension->ReaderExtension->CardStatus.Irp = IoBuildDeviceIoControlRequest(
  707. IOCTL_SERIAL_SET_WAIT_MASK,
  708. SmartcardExtension->ReaderExtension->ConnectedSerialPort,
  709. &SmartcardExtension->ReaderExtension->SerialConfigData.WaitMask,
  710. sizeof(SmartcardExtension->ReaderExtension->SerialConfigData.WaitMask),
  711. NULL,
  712. 0,
  713. FALSE,
  714. &(SmartcardExtension->ReaderExtension->CardStatus.Event),
  715. &(SmartcardExtension->ReaderExtension->CardStatus.IoStatus)
  716. );
  717. if (SmartcardExtension->ReaderExtension->CardStatus.Irp == NULL) {
  718. SmartcardDebug(
  719. DEBUG_DRIVER,
  720. ("%s!Lit220InitializeCardTracking: Error STATUS_INSUFFICIENT_RESOURCES\n",
  721. DRIVER_NAME);
  722. );
  723. status = STATUS_INSUFFICIENT_RESOURCES;
  724. leave;
  725. }
  726. // Call the serial driver
  727. status = IoCallDriver(
  728. SmartcardExtension->ReaderExtension->ConnectedSerialPort,
  729. SmartcardExtension->ReaderExtension->CardStatus.Irp,
  730. );
  731. if (status == STATUS_SUCCESS) {
  732. KIRQL oldIrql;
  733. LARGE_INTEGER delayPeriod;
  734. PIO_STACK_LOCATION irpSp;
  735. //
  736. // Now tell the serial driver that we want to be informed
  737. // if a character is received or DSR changes
  738. //
  739. readerExtension->CardStatus.Irp = IoAllocateIrp(
  740. (CCHAR) (SmartcardExtension->OsData->DeviceObject->StackSize + 1),
  741. FALSE
  742. );
  743. if (readerExtension->CardStatus.Irp == NULL) {
  744. return STATUS_INSUFFICIENT_RESOURCES;
  745. }
  746. irpSp = IoGetNextIrpStackLocation( readerExtension->CardStatus.Irp );
  747. irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  748. irpSp->Parameters.DeviceIoControl.InputBufferLength = 0;
  749. irpSp->Parameters.DeviceIoControl.OutputBufferLength =
  750. sizeof(readerExtension->SerialConfigData.WaitMask);
  751. irpSp->Parameters.DeviceIoControl.IoControlCode =
  752. IOCTL_SERIAL_WAIT_ON_MASK;
  753. readerExtension->CardStatus.Irp->AssociatedIrp.SystemBuffer =
  754. &readerExtension->SerialConfigData.WaitMask;
  755. //
  756. // this artificial delay is necessary to make this driver work
  757. // with digi board cards
  758. //
  759. delayPeriod.HighPart = -1;
  760. delayPeriod.LowPart = 100l * 1000 * (-10);
  761. KeDelayExecutionThread(
  762. KernelMode,
  763. FALSE,
  764. &delayPeriod
  765. );
  766. // We simulate a callback now that triggers the card supervision
  767. Lit220SerialEventCallback(
  768. SmartcardExtension->OsData->DeviceObject,
  769. SmartcardExtension->ReaderExtension->CardStatus.Irp,
  770. SmartcardExtension
  771. );
  772. status = STATUS_SUCCESS;
  773. }
  774. }
  775. finally {
  776. if (status != STATUS_SUCCESS) {
  777. SmartcardDebug(
  778. DEBUG_ERROR,
  779. ("%s(Lit220InitializeInputFilter): Initialization failed - stauts %X\n",
  780. DRIVER_NAME,
  781. status)
  782. );
  783. // Clear the WaitMask since we did not get the call out that does the wait
  784. SmartcardExtension->ReaderExtension->SerialConfigData.WaitMask =
  785. 0;
  786. }
  787. }
  788. return status;
  789. }
  790. NTSTATUS
  791. Lit220SystemControl(
  792. IN PDEVICE_OBJECT DeviceObject,
  793. IN PIRP Irp
  794. )
  795. /*++
  796. Routine Description:
  797. Arguments:
  798. DeviceObject - Pointer to device object for this miniport
  799. Irp - IRP involved.
  800. Return Value:
  801. STATUS_SUCCESS.
  802. --*/
  803. {
  804. PDEVICE_EXTENSION DeviceExtension;
  805. PSMARTCARD_EXTENSION SmartcardExtension;
  806. PREADER_EXTENSION ReaderExtension;
  807. NTSTATUS status = STATUS_SUCCESS;
  808. DeviceExtension = DeviceObject->DeviceExtension;
  809. SmartcardExtension = &DeviceExtension->SmartcardExtension;
  810. ReaderExtension = SmartcardExtension->ReaderExtension;
  811. IoSkipCurrentIrpStackLocation(Irp);
  812. status = IoCallDriver(ReaderExtension->BusDeviceObject, Irp);
  813. return status;
  814. }
  815. NTSTATUS
  816. Lit220DeviceControl(
  817. PDEVICE_OBJECT DeviceObject,
  818. PIRP Irp
  819. )
  820. /*++
  821. Routine Description:
  822. This is the main entry point for the PCSC resource manager.
  823. We pass all commands to the smartcard libary and let the smartcard
  824. library call us directly when needed (If device is ready to receive
  825. calls).
  826. If the device is not ready we will hold the IRP until we get a signal
  827. that it is safe to send IRPs again.
  828. If the device is removed we return an error instead of calling the
  829. smartcard library.
  830. Arguments:
  831. Return Value:
  832. NTSTATUS
  833. --*/
  834. {
  835. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  836. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  837. PREADER_EXTENSION ReaderExtension = smartcardExtension->ReaderExtension;
  838. NTSTATUS status;
  839. KIRQL irql;
  840. SmartcardDebug(
  841. DEBUG_DRIVER,
  842. ("%s(Lit220DeviceControl): Enter DeviceObject %X, Irp %X\n",
  843. DRIVER_NAME,
  844. DeviceObject,
  845. Irp)
  846. );
  847. if (smartcardExtension->ReaderExtension->SerialConfigData.WaitMask == 0) {
  848. //
  849. // the wait mask is set to 0 whenever the device was either
  850. // surprise-removed or politely removed
  851. //
  852. status = STATUS_DEVICE_REMOVED;
  853. }
  854. // Increment the IRP count
  855. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  856. if (deviceExtension->IoCount == 0) {
  857. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  858. status = KeWaitForSingleObject(
  859. &deviceExtension->ReaderStarted,
  860. Executive,
  861. KernelMode,
  862. FALSE,
  863. NULL
  864. );
  865. ASSERT(status == STATUS_SUCCESS);
  866. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  867. }
  868. ASSERT(deviceExtension->IoCount >= 0);
  869. deviceExtension->IoCount++;
  870. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  871. status = SmartcardAcquireRemoveLockWithTag(
  872. smartcardExtension,
  873. 'tcoI');
  874. if ((status != STATUS_SUCCESS) || (ReaderExtension->DeviceRemoved)) {
  875. // the device has been removed. Fail the call
  876. Irp->IoStatus.Information = 0;
  877. Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
  878. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  879. SmartcardReleaseRemoveLockWithTag(
  880. smartcardExtension,
  881. 'tcoI');
  882. return STATUS_DEVICE_REMOVED;
  883. }
  884. ASSERT(deviceExtension->SmartcardExtension.ReaderExtension->ReaderPowerState ==
  885. PowerReaderWorking);
  886. //
  887. // We are in the common situation where we send the IRP
  888. // to the smartcard lib to handle it.
  889. //
  890. status = SmartcardDeviceControl(
  891. &(deviceExtension->SmartcardExtension),
  892. Irp
  893. );
  894. SmartcardReleaseRemoveLockWithTag(
  895. smartcardExtension,
  896. 'tcoI');
  897. // Decrement the IRP count
  898. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  899. deviceExtension->IoCount--;
  900. ASSERT(deviceExtension->IoCount >= 0);
  901. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  902. SmartcardDebug(
  903. DEBUG_TRACE,
  904. ("%s!Lit220DeviceControl: Exit %X\n",
  905. DRIVER_NAME, status)
  906. );
  907. return status;
  908. }
  909. NTSTATUS
  910. Lit220GetReaderError(
  911. PSMARTCARD_EXTENSION SmartcardExtension
  912. )
  913. /*++
  914. Routine Description:
  915. This routine checks the status of the previous error to determine the
  916. correct error code to return.
  917. The default error is timeout if we cannot determine the error from the
  918. reader.
  919. --*/
  920. {
  921. static ULONG PreventReentry = FALSE;
  922. PSMARTCARD_REQUEST smartcardRequest = &SmartcardExtension->SmartcardRequest;
  923. NTSTATUS status = STATUS_TIMEOUT;
  924. LARGE_INTEGER WaitTime;
  925. KIRQL irql;
  926. // Sometimes after a command the reader is not reader to accept another command
  927. // so we need to wait for a short period of time for the reader to be ready. We need to
  928. // take this out as soon as the reader is fixed!
  929. WaitTime.HighPart = -1;
  930. WaitTime.LowPart = -10 * 1000 * 1000; // Wait 1S for reader to recover from error.
  931. KeDelayExecutionThread(
  932. KernelMode,
  933. FALSE,
  934. &WaitTime
  935. );
  936. // Prevent a nack from this call from recursively calling itself
  937. if (InterlockedExchange(
  938. &PreventReentry,
  939. TRUE))
  940. {
  941. // Default error to timeout if reader keeps failing our calls
  942. return STATUS_TIMEOUT;
  943. }
  944. SmartcardDebug(
  945. DEBUG_TRACE,
  946. ("%s!Lit220GetReaderError: Enter\n",
  947. DRIVER_NAME)
  948. );
  949. smartcardRequest->BufferLength = 0;
  950. //
  951. // Send a get reader status to see if a card is inserted
  952. //
  953. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  954. LIT220_READER_ATTENTION;
  955. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  956. LIT220_READER_ATTENTION;
  957. smartcardRequest->Buffer[smartcardRequest->BufferLength++] =
  958. LIT220_GET_READER_STATUS;
  959. //
  960. // We Expect to get a response
  961. //
  962. SmartcardExtension->ReaderExtension->WaitMask |= WAIT_DATA;
  963. // Send the command
  964. status = Lit220Command(
  965. SmartcardExtension
  966. );
  967. if (status == STATUS_SUCCESS) {
  968. // Check if length is correct
  969. if (SmartcardExtension->SmartcardReply.BufferLength != LIT220_READER_STATUS_LEN) {
  970. // Return a status timeout because the reader failed to respond
  971. status = STATUS_TIMEOUT;
  972. }
  973. if (status == STATUS_SUCCESS) {
  974. // Check the error byte to see if there was a protocol error
  975. // otherwise assume timeout
  976. if (SmartcardExtension->SmartcardReply.Buffer[1] & 0x04) {
  977. status = STATUS_TIMEOUT;
  978. } else {
  979. status = STATUS_DEVICE_PROTOCOL_ERROR;
  980. }
  981. // Check status byte to see if card is inserted
  982. // and send a notification accordingly
  983. if (SmartcardExtension->SmartcardReply.Buffer[0] & LIT220_STATUS_CARD_INSERTED) {
  984. Lit220NotifyCardChange(
  985. SmartcardExtension,
  986. TRUE
  987. );
  988. } else {
  989. Lit220NotifyCardChange(
  990. SmartcardExtension,
  991. FALSE
  992. );
  993. }
  994. }
  995. }
  996. InterlockedExchange(
  997. &PreventReentry,
  998. FALSE);
  999. return status;
  1000. }