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.

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