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.

2702 lines
68 KiB

  1. /*++
  2. Copyright (c) 1998 Gemplus Development
  3. Name:
  4. GNTSCR0A.C (Gemplus NT Smart Card Reader module for GCR410P )
  5. Description :
  6. This is the main module which holds the main functions for a standard NT driver
  7. Environment:
  8. Kernel mode
  9. Revision History :
  10. dd/mm/yy
  11. 13/03/98: V1.00.001 (GPZ)
  12. - Start of development. Pnp support.
  13. 14/04/98: V1.00.002 (GPZ)
  14. - Updated for Power Management support.
  15. 19/05/98: V1.00.003 (GPZ)
  16. - Updated for the GemCore 1.11-3 version.
  17. 28/05/98: V1.00.004 (GPZ)
  18. - The reference to PRTL_REMOVE_LOCK is removed.
  19. 03/06/98: V1.00.005 (GPZ)
  20. - After a power down, the card state is updated.
  21. 08/06/98: V1.00.006 (GPZ)
  22. 18/06/98: V1.00.007 (GPZ)
  23. - The functions which use KeAcquireSpinLock/KeAcquireCancelSpinlock
  24. must be NOT PAGEABLE.
  25. - Modification of GCR410PPnPDeviceControl.
  26. - Modification of GCR410PPowerDeviceControl to support completly the
  27. request of the power management.
  28. 16/07/98: V1.00.008 (GPZ)
  29. - To update the card state, we use a System Worker Thread which is called
  30. like a callback function only when an RING Irq occurs. The thread terminates
  31. immediately.
  32. 17/07/98: V1.00.009 (GPZ)
  33. - The Interface state is set to true at the end of StartDevice.
  34. 06/08/98: V1.00.010 (GPZ)
  35. - If the StartDevice failed and the serial port is openned, we close
  36. the serial port instead of call the WaitForDeviceRemoval function.
  37. 11/09/98: V1.00.011 (GPZ)
  38. - GCR410PDeviceControl, GCR410PPnPDeviceControl and GCR410PPowerDeviceControl
  39. updated to block all incoming Ioctls as long as the reader is
  40. in stand by/hibernation mode.
  41. - All functions which use SpinLock cannot be Pageable.
  42. 13/09/98: V1.00.012 (GPZ)
  43. - Check if the CardStatus thread runs before to close the serial port.
  44. --*/
  45. #include <stdio.h>
  46. #include "gntscr.h"
  47. #include "gntscr0a.h"
  48. #include "gntser.h"
  49. //
  50. // Pragma section:
  51. //
  52. #pragma alloc_text(INIT,DriverEntry)
  53. #pragma alloc_text(PAGEABLE,GCR410PStartSerialEventTracking)
  54. #pragma alloc_text(PAGEABLE,GCR410PStopSerialEventTracking)
  55. #pragma alloc_text(PAGEABLE,GCR410PAddDevice)
  56. #pragma alloc_text(PAGEABLE,GCR410PCreateDevice)
  57. #pragma alloc_text(PAGEABLE,GCR410PStartDevice)
  58. #pragma alloc_text(PAGEABLE,GCR410PStopDevice)
  59. #pragma alloc_text(PAGEABLE,GCR410PRemoveDevice)
  60. #pragma alloc_text(PAGEABLE,GCR410PDriverUnload)
  61. #if DBG
  62. #pragma optimize ("",off)
  63. #endif
  64. //
  65. // Constant section:
  66. // - GCR410P_DRIVER_VERSION is the current version of the driver
  67. // - MAX_DEVICES is the maximum number of devices (and instances) we want
  68. // to support
  69. //
  70. #define GCR410P_DRIVER_VERSION 0x0112
  71. //ISV
  72. #define MAX_DEVICES 50
  73. //
  74. // Global variable section:
  75. // - ulMaximalBaudRate defines the maximal baud rate for the reader.
  76. // - bDevicePort is an array of boolean to signals if a device is
  77. // already created.
  78. //
  79. ULONG
  80. ulMaximalBaudRate;
  81. BOOLEAN bDevicePort[MAX_DEVICES];
  82. NTSTATUS
  83. DriverEntry(
  84. IN PDRIVER_OBJECT DriverObject,
  85. IN PUNICODE_STRING RegistryPath
  86. )
  87. /*++
  88. Routine Description:
  89. This routine is called at system initialization time to initialize
  90. this driver.
  91. Arguments:
  92. DriverObject - supplies the driver object.
  93. RegistryPath - supplies the registry path for this driver.
  94. Return Value:
  95. STATUS_SUCCESS - We could initialize at least one device.
  96. --*/
  97. {
  98. NTSTATUS status;
  99. RTL_QUERY_REGISTRY_TABLE paramTable[4];
  100. UNICODE_STRING driverPath;
  101. WCHAR buffer[MAXIMUM_FILENAME_LENGTH];
  102. SmartcardDebug(
  103. DEBUG_DRIVER,
  104. ("%s!DriverEntry: Enter - version: %X - %s %s\n",
  105. SC_DRIVER_NAME,
  106. GCR410P_DRIVER_VERSION,
  107. __DATE__,
  108. __TIME__)
  109. );
  110. //
  111. // we do some stuff in this driver that
  112. // assumes a single digit port number
  113. //
  114. // Initialize the Driver Object with driver's entry points
  115. //
  116. DriverObject->DriverUnload = GCR410PDriverUnload;
  117. DriverObject->DriverExtension->AddDevice = GCR410PAddDevice;
  118. DriverObject->MajorFunction[IRP_MJ_CREATE] = GCR410PCreateClose;
  119. DriverObject->MajorFunction[IRP_MJ_CLOSE] = GCR410PCreateClose;
  120. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = GCR410PCleanup;
  121. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = GCR410PDeviceControl;
  122. DriverObject->MajorFunction[IRP_MJ_PNP] = GCR410PPnPDeviceControl;
  123. DriverObject->MajorFunction[IRP_MJ_POWER] = GCR410PPowerDeviceControl;
  124. //
  125. // Read in the the driver registry path "MaximalBaudRate".
  126. //
  127. ulMaximalBaudRate = 0;
  128. RtlZeroMemory(paramTable,sizeof(paramTable));
  129. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  130. paramTable[0].Name = L"MaximalBaudRate";
  131. paramTable[0].EntryContext = &ulMaximalBaudRate;
  132. paramTable[0].DefaultType = REG_DWORD;
  133. paramTable[0].DefaultData = &ulMaximalBaudRate;
  134. paramTable[0].DefaultLength = sizeof(ULONG);
  135. driverPath.Buffer = buffer;
  136. driverPath.MaximumLength = sizeof(buffer);
  137. driverPath.Length = 0;
  138. RtlCopyUnicodeString(&driverPath,RegistryPath);
  139. status = RtlQueryRegistryValues(
  140. RTL_REGISTRY_ABSOLUTE,
  141. driverPath.Buffer,
  142. &paramTable[0],
  143. NULL,
  144. NULL
  145. );
  146. if ((ulMaximalBaudRate != 9600lu) && (ulMaximalBaudRate != 19200lu) &&
  147. (ulMaximalBaudRate != 38400lu)
  148. ) {
  149. ulMaximalBaudRate = IFD_STANDARD_BAUD_RATE;
  150. }
  151. SmartcardDebug(
  152. DEBUG_DRIVER,
  153. ("%s!DriverEntry: Exit\n",
  154. SC_DRIVER_NAME)
  155. );
  156. return STATUS_SUCCESS;
  157. }
  158. NTSTATUS
  159. GCR410PAddDevice(
  160. IN PDRIVER_OBJECT DriverObject,
  161. IN PDEVICE_OBJECT PhysicalDeviceObject
  162. )
  163. /*++
  164. Routine Description:
  165. This is the add-device routine.
  166. Arguments:
  167. DriverObject - points to the driver object representing the driver.
  168. PhysicalDeviceObject - points to the PDO for the PnP device being added.
  169. Return Value:
  170. STATUS_SUCCESS - We could initialize at least one device.
  171. STATUS_UNSUCCESSFUL - We cannot connect the device to PDO.
  172. --*/
  173. {
  174. NTSTATUS status;
  175. PDEVICE_OBJECT DeviceObject = NULL;
  176. PAGED_CODE();
  177. ASSERT(DriverObject != NULL);
  178. ASSERT(PhysicalDeviceObject != NULL);
  179. SmartcardDebug(
  180. DEBUG_DRIVER,
  181. ("%s!GCR410PAddDevice: Enter\n",
  182. SC_DRIVER_NAME)
  183. );
  184. __try {
  185. PDEVICE_EXTENSION deviceExtension;
  186. //
  187. // Try to create a device .
  188. //
  189. status = GCR410PCreateDevice(
  190. DriverObject,
  191. PhysicalDeviceObject,
  192. &DeviceObject
  193. );
  194. if (status != STATUS_SUCCESS) {
  195. SmartcardDebug(
  196. DEBUG_ERROR,
  197. ("%s!GCR410PAddDevice: GCR410PCreateDevice=%X(hex)\n",
  198. SC_DRIVER_NAME,
  199. status)
  200. );
  201. __leave;
  202. }
  203. //
  204. // Attach the PhysicalDeviceObject to the new created device.
  205. //
  206. deviceExtension = DeviceObject->DeviceExtension;
  207. ATTACHED_DEVICE_OBJECT = IoAttachDeviceToDeviceStack(
  208. DeviceObject,
  209. PhysicalDeviceObject
  210. );
  211. if (ATTACHED_DEVICE_OBJECT == NULL) {
  212. SmartcardLogError(
  213. DriverObject,
  214. GEM_CANT_CONNECT_TO_ASSIGNED_PORT,
  215. NULL,
  216. 0
  217. );
  218. status = STATUS_UNSUCCESSFUL;
  219. __leave;
  220. }
  221. //
  222. // Register our new device object
  223. //
  224. status = IoRegisterDeviceInterface(
  225. PhysicalDeviceObject,
  226. &SmartCardReaderGuid,
  227. NULL,
  228. &deviceExtension->PnPDeviceName
  229. );
  230. ASSERT(status == STATUS_SUCCESS);
  231. DeviceObject->Flags |= DO_BUFFERED_IO;
  232. DeviceObject->Flags |= DO_POWER_PAGABLE;
  233. DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  234. }
  235. __finally {
  236. if (status != STATUS_SUCCESS) {
  237. GCR410PRemoveDevice(DeviceObject);
  238. }
  239. }
  240. SmartcardDebug(
  241. DEBUG_DRIVER,
  242. ("%s!GCR410PAddDevice: Exit=%X(hex)\n",
  243. SC_DRIVER_NAME,
  244. status
  245. )
  246. );
  247. return status;
  248. }
  249. NTSTATUS
  250. GCR410PCreateDevice(
  251. IN PDRIVER_OBJECT DriverObject,
  252. IN PDEVICE_OBJECT PhysicalDeviceObject,
  253. OUT PDEVICE_OBJECT *DeviceObject
  254. )
  255. /*++
  256. Routine Description:
  257. This routine creates an object for the physical device specified and
  258. sets up the deviceExtension.
  259. Arguments:
  260. DriverObject - points to the driver object representing the driver.
  261. PhysicalDeviceObject - points to the PDO for the PnP device being added.
  262. DeviceObject - the device created.
  263. Return Value:
  264. STATUS_SUCCESS - device created.
  265. --*/
  266. {
  267. PDEVICE_EXTENSION deviceExtension;
  268. NTSTATUS status = STATUS_SUCCESS;
  269. ULONG nDeviceNumber;
  270. PREADER_EXTENSION readerExtension;
  271. PSMARTCARD_EXTENSION smartcardExtension;
  272. PAGED_CODE();
  273. ASSERT(DriverObject != NULL);
  274. ASSERT(PhysicalDeviceObject != NULL);
  275. *DeviceObject = NULL;
  276. SmartcardDebug(
  277. DEBUG_DRIVER,
  278. ("%s!GCR410PCreateDevice: Enter\n",
  279. SC_DRIVER_NAME)
  280. );
  281. for( nDeviceNumber = 0; nDeviceNumber < MAX_DEVICES; nDeviceNumber++ ) {
  282. if (bDevicePort[nDeviceNumber] == FALSE) {
  283. bDevicePort[nDeviceNumber] = TRUE;
  284. break;
  285. }
  286. }
  287. if (nDeviceNumber == MAX_DEVICES) {
  288. status = STATUS_INSUFFICIENT_RESOURCES;
  289. SmartcardDebug(
  290. DEBUG_ERROR,
  291. ("%s!GCR410PCreateDevice: Insufficient ressources\n",
  292. SC_DRIVER_NAME)
  293. );
  294. SmartcardLogError(
  295. DriverObject,
  296. GEM_CANT_CREATE_MORE_DEVICES,
  297. NULL,
  298. 0
  299. );
  300. return STATUS_INSUFFICIENT_RESOURCES;
  301. }
  302. //
  303. // Try to create a new device smart card object
  304. //
  305. status = IoCreateDevice(
  306. DriverObject,
  307. sizeof(DEVICE_EXTENSION),
  308. NULL,
  309. FILE_DEVICE_SMARTCARD,
  310. 0,
  311. TRUE,
  312. DeviceObject
  313. );
  314. SmartcardDebug(
  315. DEBUG_TRACE,
  316. ("%s!GCR410PCreateDevice: IoCreateDevice status =%X(hex)\n",
  317. SC_DRIVER_NAME,
  318. status)
  319. );
  320. if (!NT_SUCCESS(status)) {
  321. SmartcardLogError(
  322. DriverObject,
  323. GEM_CANT_CREATE_DEVICE,
  324. NULL,
  325. 0
  326. );
  327. return status;
  328. }
  329. ASSERT(*DeviceObject != NULL);
  330. //
  331. // Now we have a pointer on the new device.
  332. //
  333. deviceExtension = (*DeviceObject)->DeviceExtension;
  334. ASSERT(deviceExtension != NULL);
  335. // This event signals Start/Stop notification
  336. KeInitializeEvent(
  337. &deviceExtension->ReaderStarted,
  338. NotificationEvent,
  339. FALSE
  340. );
  341. // This event signals that the serial driver has been closed
  342. KeInitializeEvent(
  343. &deviceExtension->SerialCloseDone,
  344. NotificationEvent,
  345. TRUE
  346. );
  347. // This event signals that the card status thread is scheduled
  348. KeInitializeEvent(
  349. &deviceExtension->CardStatusNotInUse,
  350. NotificationEvent,
  351. TRUE
  352. );
  353. // Used to keep track of open close calls
  354. deviceExtension->ReaderOpen = FALSE;
  355. // SpinLock used to manage the card state
  356. KeInitializeSpinLock(&deviceExtension->SpinLock);
  357. // Thread that waits the device removal
  358. deviceExtension->CloseSerial = IoAllocateWorkItem(
  359. *DeviceObject
  360. );
  361. // Thread which will be called when a card state change will occur.
  362. deviceExtension->CardStateChange = IoAllocateWorkItem(
  363. *DeviceObject
  364. );
  365. // We try to allocate memory for the ReaderExtension struct.
  366. smartcardExtension = &deviceExtension->SmartcardExtension;
  367. smartcardExtension->ReaderExtension = ExAllocatePool(
  368. NonPagedPool,
  369. sizeof(READER_EXTENSION)
  370. );
  371. if (deviceExtension->SmartcardExtension.ReaderExtension == NULL ||
  372. deviceExtension->CardStateChange == NULL ||
  373. deviceExtension->CloseSerial == NULL) {
  374. SmartcardLogError(
  375. DriverObject,
  376. GEM_NO_MEMORY,
  377. NULL,
  378. 0
  379. );
  380. return STATUS_INSUFFICIENT_RESOURCES;
  381. }
  382. readerExtension = smartcardExtension->ReaderExtension;
  383. RtlZeroMemory(
  384. readerExtension,
  385. sizeof(READER_EXTENSION)
  386. );
  387. // Write the version of the lib we use to the smartcard extension
  388. smartcardExtension->Version = SMCLIB_VERSION;
  389. // Now let the lib allocate the buffer for data transmission
  390. smartcardExtension->SmartcardRequest.BufferSize = MIN_BUFFER_SIZE;
  391. smartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
  392. status = SmartcardInitialize(smartcardExtension);
  393. SmartcardDebug(
  394. DEBUG_TRACE,
  395. ("%s!GCR410PCreateDevice: SmartcardInitialize=%lX(hex)\n",
  396. SC_DRIVER_NAME,
  397. status)
  398. );
  399. if (status != STATUS_SUCCESS) {
  400. SmartcardLogError(
  401. DriverObject,
  402. (smartcardExtension->OsData ? GEM_WRONG_LIB_VERSION : GEM_NO_MEMORY),
  403. NULL,
  404. 0
  405. );
  406. return status;
  407. }
  408. smartcardExtension->VendorAttr.UnitNo = nDeviceNumber;
  409. // Save the deviceObject
  410. deviceExtension->SmartcardExtension.OsData->DeviceObject = *DeviceObject;
  411. //
  412. // Set up the call back functions
  413. // (nota: RDF_CARD_EJECT and RDF_READER_SWALLOW are not supported)
  414. //
  415. smartcardExtension->ReaderFunction[RDF_TRANSMIT] = GDDK_0ATransmit;
  416. smartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = GDDK_0ASetProtocol;
  417. smartcardExtension->ReaderFunction[RDF_CARD_POWER] = GDDK_0AReaderPower;
  418. smartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = GDDK_0ACardTracking;
  419. smartcardExtension->ReaderFunction[RDF_IOCTL_VENDOR] = GDDK_0AVendorIoctl;
  420. // save the current power state of the reader
  421. smartcardExtension->ReaderExtension->ReaderPowerState =
  422. PowerReaderWorking;
  423. SmartcardDebug(
  424. DEBUG_DRIVER,
  425. ("%s!GCR410PCreateDevice: Exit=%X(hex)\n",
  426. SC_DRIVER_NAME,
  427. status)
  428. );
  429. return status;
  430. }
  431. NTSTATUS
  432. GCR410PStartDevice(
  433. IN PDEVICE_OBJECT DeviceObject
  434. )
  435. /*++
  436. Routine Description:
  437. Open the serial device, start card tracking and register our
  438. device interface. If any of the calls here fails we don't care
  439. to rollback since a stop will be called later which we then
  440. use to clean up.
  441. --*/
  442. {
  443. NTSTATUS status;
  444. PIRP irp;
  445. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  446. PAGED_CODE();
  447. SmartcardDebug(
  448. DEBUG_DRIVER,
  449. ("%s!GCR410PStartDevice: Enter\n",
  450. SC_DRIVER_NAME)
  451. );
  452. irp = IoAllocateIrp(
  453. (CCHAR) (DeviceObject->StackSize + 1),
  454. FALSE
  455. );
  456. ASSERT(irp != NULL);
  457. if (irp == NULL) {
  458. SmartcardDebug(
  459. DEBUG_ERROR,
  460. ("%s!GCR410PStartDevice: IoAllocateIrp failed!\n",
  461. SC_DRIVER_NAME)
  462. );
  463. SmartcardLogError(
  464. DeviceObject,
  465. GEM_NO_MEMORY,
  466. NULL,
  467. 0
  468. );
  469. return STATUS_NO_MEMORY;
  470. }
  471. __try {
  472. PIO_STACK_LOCATION irpStack;
  473. IO_STATUS_BLOCK ioStatusBlock;
  474. //
  475. // Open the underlying serial driver.
  476. // This is necessary for two reasons:
  477. // a) The serial driver can't be used without opening it
  478. // b) The call will go through serenum first which informs
  479. // it to stop looking/polling for new devices.
  480. //
  481. irp->UserIosb = &ioStatusBlock;
  482. IoSetNextIrpStackLocation(irp);
  483. irpStack = IoGetCurrentIrpStackLocation(irp);
  484. irpStack->MajorFunction = IRP_MJ_CREATE;
  485. irpStack->Parameters.Create.Options = 0;
  486. irpStack->Parameters.Create.ShareAccess = 0;
  487. irpStack->Parameters.Create.FileAttributes = 0;
  488. irpStack->Parameters.Create.EaLength = 0;
  489. status = GCR410PCallSerialDriver(
  490. ATTACHED_DEVICE_OBJECT,
  491. irp
  492. );
  493. if (status != STATUS_SUCCESS) {
  494. if (status == STATUS_SHARED_IRQ_BUSY) {
  495. SmartcardLogError(
  496. DeviceObject,
  497. GEM_SHARED_IRQ_BUSY,
  498. NULL,
  499. 0
  500. );
  501. }
  502. __leave;
  503. }
  504. // The serial port is openned
  505. KeClearEvent(&deviceExtension->SerialCloseDone);
  506. // Open the communication with the reader
  507. status = GDDK_0AOpenChannel(
  508. &deviceExtension->SmartcardExtension,
  509. deviceExtension->SmartcardExtension.VendorAttr.UnitNo, //Device number
  510. deviceExtension->SmartcardExtension.VendorAttr.UnitNo,
  511. ulMaximalBaudRate
  512. );
  513. SmartcardDebug(
  514. DEBUG_TRACE,
  515. ("%s!GCR410PStartDevice: GDDK_0AOpenChannel=%X(hex)\n",
  516. SC_DRIVER_NAME,
  517. status)
  518. );
  519. if (status != STATUS_SUCCESS) {
  520. if (status == STATUS_BAD_DEVICE_TYPE) {
  521. SmartcardLogError(
  522. DeviceObject,
  523. GEM_IFD_BAD_VERSION,
  524. NULL,
  525. 0
  526. );
  527. } else {
  528. SmartcardLogError(
  529. DeviceObject,
  530. GEM_IFD_COMMUNICATION_ERROR,
  531. NULL,
  532. 0
  533. );
  534. }
  535. __leave;
  536. }
  537. // Start the serial event tracking (DSR and RING events)
  538. status = GCR410PStartSerialEventTracking(&deviceExtension->SmartcardExtension);
  539. if (status != STATUS_SUCCESS) {
  540. SmartcardLogError(
  541. DeviceObject,
  542. GEM_START_SERIAL_EVENT_TRACKING_FAILED,
  543. NULL,
  544. 0
  545. );
  546. __leave;
  547. }
  548. // Set the Device Interface state to True
  549. status = IoSetDeviceInterfaceState(
  550. &deviceExtension->PnPDeviceName,
  551. TRUE
  552. );
  553. if (status != STATUS_SUCCESS) {
  554. SmartcardDebug(
  555. DEBUG_ERROR,
  556. ("%s!GCR410PStartDevice: IoSetDeviceInterfaceState failed!\n",
  557. SC_DRIVER_NAME)
  558. );
  559. SmartcardLogError(
  560. DeviceObject,
  561. GEM_SET_DEVICE_INTERFACE_STATE_FAILED,
  562. NULL,
  563. 0
  564. );
  565. __leave;
  566. }
  567. // Set the ReaderStarted event.
  568. KeSetEvent(&deviceExtension->ReaderStarted,0,FALSE);
  569. }
  570. __finally {
  571. if (status != STATUS_SUCCESS) {
  572. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  573. SmartcardDebug(
  574. DEBUG_ERROR,
  575. ("%s!GCR410PStartDevice: failed!\n",
  576. SC_DRIVER_NAME)
  577. );
  578. // If we have failed, then we call the StopDevice to undo all we have done here.
  579. GCR410PStopDevice(DeviceObject);
  580. }
  581. IoFreeIrp(irp);
  582. }
  583. SmartcardDebug(
  584. DEBUG_DRIVER,
  585. ("%s!GCR410PStartDevice: Exit=%X(hex)\n",
  586. SC_DRIVER_NAME,
  587. status)
  588. );
  589. return status;
  590. }
  591. VOID
  592. GCR410PStopDevice(
  593. IN PDEVICE_OBJECT DeviceObject
  594. )
  595. /*++
  596. Routine Description:
  597. Finishes card tracking requests and closes the connection to the
  598. serial driver.
  599. --*/
  600. {
  601. PDEVICE_EXTENSION deviceExtension;
  602. PSMARTCARD_EXTENSION smartcardExtension;
  603. LARGE_INTEGER timeout;
  604. PAGED_CODE();
  605. ASSERT(DeviceObject != NULL);
  606. deviceExtension = DeviceObject->DeviceExtension;
  607. smartcardExtension = &deviceExtension->SmartcardExtension;
  608. ASSERT(smartcardExtension != NULL);
  609. SmartcardDebug(
  610. DEBUG_DRIVER,
  611. ("%s!GCR410PStopDevice: Enter\n",
  612. SC_DRIVER_NAME)
  613. );
  614. // If the serial port is not yet closed.
  615. if (KeReadStateEvent(&deviceExtension->SerialCloseDone) == 0l) {
  616. NTSTATUS status;
  617. // Close the communication with the reader
  618. status = GDDK_0ACloseChannel(
  619. smartcardExtension
  620. );
  621. SmartcardDebug(
  622. DEBUG_TRACE,
  623. ("%s!GCR410PStopDevice: GDDK_0ACloseChannel=%X(hex)\n",
  624. SC_DRIVER_NAME,
  625. status)
  626. );
  627. // test if we ever started event tracking
  628. if (smartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask == 0) {
  629. // We 'only' need to close the serial port
  630. GCR410PCloseSerialPort(DeviceObject, NULL);
  631. } else {
  632. // We now inform the serial driver that we're not longer
  633. // interested in serial events. This will also free the irp
  634. // we use for those io-completions
  635. // This will also create an event which will close the serial port.
  636. status = GCR410PStopSerialEventTracking(smartcardExtension);
  637. // now wait until the connection to serial is closed
  638. // timeout.QuadPart = -((LONGLONG) HOR3COMM_CHAR_TIME*10*1000);
  639. status = KeWaitForSingleObject(
  640. &deviceExtension->SerialCloseDone,
  641. Executive,
  642. KernelMode,
  643. FALSE,
  644. NULL
  645. );
  646. //ASSERT(status == STATUS_SUCCESS);
  647. if(status != STATUS_SUCCESS)
  648. {
  649. SmartcardDebug(
  650. DEBUG_DRIVER,
  651. ("%s!GCR410PStopDevice: Failed waiting to close...\n",
  652. SC_DRIVER_NAME)
  653. );
  654. }
  655. }
  656. }
  657. SmartcardDebug(
  658. DEBUG_DRIVER,
  659. ("%s!GCR410PStopDevice: Exit\n",
  660. SC_DRIVER_NAME)
  661. );
  662. }
  663. NTSTATUS
  664. GCR410PDeviceControl(
  665. PDEVICE_OBJECT DeviceObject,
  666. PIRP Irp
  667. )
  668. /*++
  669. Routine Description:
  670. This is our IOCTL dispatch function
  671. --*/
  672. {
  673. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  674. NTSTATUS status = STATUS_SUCCESS;
  675. KIRQL irql;
  676. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  677. LARGE_INTEGER timeout;
  678. SmartcardDebug(
  679. DEBUG_DRIVER,
  680. ("%s!GCR410PDeviceControl: Enter\n",
  681. SC_DRIVER_NAME)
  682. );
  683. if (smartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask == 0)
  684. {
  685. SmartcardDebug(
  686. DEBUG_ERROR,
  687. ( "%s!GCR410PDeviceControl: Exit (Reader was removed or power down!)\n",
  688. SC_DRIVER_NAME)
  689. );
  690. // the wait mask is set to 0 whenever the device was either
  691. // surprise-removed or politely removed
  692. status = STATUS_DEVICE_REMOVED;
  693. return status;
  694. }
  695. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  696. if (deviceExtension->IoCount == 0) {
  697. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  698. //timeout.QuadPart = -((LONGLONG) HOR3COMM_CHAR_TIME*10*1000);
  699. status = KeWaitForSingleObject(
  700. &deviceExtension->ReaderStarted,
  701. Executive,
  702. KernelMode,
  703. FALSE,
  704. NULL
  705. );
  706. ASSERT(status == STATUS_SUCCESS);
  707. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  708. }
  709. ASSERT(deviceExtension->IoCount >= 0);
  710. deviceExtension->IoCount++;
  711. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  712. status = SmartcardAcquireRemoveLockWithTag(smartcardExtension, 'tcoI');
  713. if (status != STATUS_SUCCESS) {
  714. // the device has been removed. Fail the call
  715. Irp->IoStatus.Information = 0;
  716. Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
  717. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  718. return STATUS_DEVICE_REMOVED;
  719. }
  720. status = SmartcardDeviceControl(
  721. &(deviceExtension->SmartcardExtension),
  722. Irp
  723. );
  724. SmartcardReleaseRemoveLockWithTag(smartcardExtension, 'tcoI');
  725. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  726. deviceExtension->IoCount--;
  727. ASSERT(deviceExtension->IoCount >= 0);
  728. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  729. SmartcardDebug(
  730. DEBUG_DRIVER,
  731. ("%s!GCR410PDeviceControl: Exit=%X(hex)\n",
  732. SC_DRIVER_NAME,
  733. status)
  734. );
  735. return status;
  736. }
  737. VOID
  738. GCR410PCloseSerialPort(
  739. IN PDEVICE_OBJECT DeviceObject,
  740. IN PVOID Context
  741. )
  742. /*++
  743. Routine Description:
  744. This function closes the connection to the serial driver when the reader
  745. has been removed (unplugged). This function runs as a system thread at
  746. IRQL == PASSIVE_LEVEL. It waits for the remove event that is set by
  747. the IoCompletionRoutine
  748. Arguments:
  749. DeviceObject - is a pointer to the device.
  750. Return Value:
  751. Nothing
  752. --*/
  753. {
  754. PDEVICE_EXTENSION deviceExtension;
  755. NTSTATUS status;
  756. PIRP irp;
  757. PIO_STACK_LOCATION irpStack;
  758. IO_STATUS_BLOCK ioStatusBlock;
  759. LARGE_INTEGER timeout;
  760. SmartcardDebug(
  761. DEBUG_DRIVER,
  762. ("%s!GCR410PCloseSerialPort: Enter\n",
  763. SC_DRIVER_NAME)
  764. );
  765. ASSERT(DeviceObject!=NULL);
  766. deviceExtension = DeviceObject->DeviceExtension;
  767. ASSERT(KeReadStateEvent(&deviceExtension->SerialCloseDone) == 0l);
  768. //
  769. // first mark this device as 'gone'.
  770. // This will prevent that someone can re-open the device
  771. // We intentionally ignore possible errors
  772. //
  773. IoSetDeviceInterfaceState(
  774. &deviceExtension->PnPDeviceName,
  775. FALSE
  776. );
  777. // wait until the card status thread is running
  778. //timeout.QuadPart = -((LONGLONG) HOR3COMM_CHAR_TIME*10*1000);
  779. status = KeWaitForSingleObject(
  780. &deviceExtension->CardStatusNotInUse,
  781. Executive,
  782. KernelMode,
  783. FALSE,
  784. NULL
  785. );
  786. ASSERT(status == STATUS_SUCCESS);
  787. if(status != STATUS_SUCCESS)
  788. {
  789. SmartcardDebug(
  790. DEBUG_DRIVER,
  791. ("%s!GCR410PCloseSerialPort: Failed waiting to stop thread...\n",
  792. SC_DRIVER_NAME)
  793. );
  794. }
  795. irp = IoAllocateIrp(
  796. (CCHAR) (DeviceObject->StackSize + 1),
  797. FALSE
  798. );
  799. ASSERT(irp != NULL);
  800. if (irp) {
  801. IoSetNextIrpStackLocation(irp);
  802. // We send down a close to the serial driver. This close goes
  803. // througt Serenum first which will trigger it to start looking
  804. // for changes on the com-port. Since our device is gone it will
  805. // call the device removal event of our PnP dispatch.
  806. irp->UserIosb = &ioStatusBlock;
  807. irpStack = IoGetCurrentIrpStackLocation(irp);
  808. irpStack->MajorFunction = IRP_MJ_CLOSE;
  809. status = GCR410PCallSerialDriver(
  810. deviceExtension->SmartcardExtension.ReaderExtension->AttachedDeviceObject,
  811. irp
  812. );
  813. SmartcardDebug(
  814. DEBUG_TRACE,
  815. ("%s!GCR410PCloseSerialPort: Send IRP_MJ_CLOSE to the serial device=%lX\n",
  816. SC_DRIVER_NAME,
  817. status)
  818. );
  819. IoFreeIrp(irp);
  820. }
  821. // Informs that the serial port is closed
  822. KeSetEvent(
  823. &deviceExtension->SerialCloseDone,
  824. 0,
  825. FALSE
  826. );
  827. SmartcardDebug(
  828. DEBUG_DRIVER,
  829. ("%s!GCR410PCloseSerialPort: Exit\n",
  830. SC_DRIVER_NAME)
  831. );
  832. }
  833. VOID
  834. GCR410PWaitForCardStateChange(
  835. IN PDEVICE_OBJECT DeviceObject,
  836. IN PVOID Context
  837. )
  838. /*++
  839. Routine Description:
  840. This function send a command to the reader to known the card status. This
  841. function runs as a system thread at IRQL == PASSIVE_LEVEL. It waits for
  842. the CardStateChange event that it set by the IoCompletionRoutine.
  843. Arguments:
  844. DeviceObject - is a pointer to the device.
  845. Return Value:
  846. Nothing
  847. --*/
  848. {
  849. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  850. PSMARTCARD_EXTENSION smartcardExtension;
  851. SmartcardDebug(
  852. DEBUG_TRACE,
  853. ( "%s!GCR410PWaitForCardStateChange: Enter\n",
  854. SC_DRIVER_NAME)
  855. );
  856. smartcardExtension = &deviceExtension->SmartcardExtension;
  857. ASSERT(smartcardExtension != NULL);
  858. //ISV
  859. // If device is not ready - do not run exchange!
  860. if(smartcardExtension->ReaderExtension->ReaderPowerState != PowerReaderWorking)
  861. {
  862. SmartcardDebug(
  863. DEBUG_ERROR,
  864. ( "%s!GCR410PWaitForCardStateChange: Exit (reader is not ready yet!)\n",
  865. SC_DRIVER_NAME)
  866. );
  867. // Informs that the card status update is done
  868. KeSetEvent(
  869. &deviceExtension->CardStatusNotInUse,
  870. 0,
  871. FALSE
  872. );
  873. return;
  874. }
  875. // Protect the exchange
  876. GDDK_0ALockExchange(smartcardExtension);
  877. if (GDDK_0AUpdateCardStatus(smartcardExtension) == STATUS_SUCCESS) {
  878. // Complete the card tracking except if we are in a
  879. // power up - power down cycle (Power Management)
  880. if (smartcardExtension->ReaderExtension->PowerRequest == FALSE) {
  881. GCR410PCompleteCardTracking(smartcardExtension);
  882. }
  883. }
  884. GDDK_0AUnlockExchange(smartcardExtension);
  885. SmartcardDebug(
  886. DEBUG_TRACE,
  887. ( "%s!GCR410PWaitForCardStateChange: Exit\n",
  888. SC_DRIVER_NAME)
  889. );
  890. // Informs that the card status update is done
  891. KeSetEvent(
  892. &deviceExtension->CardStatusNotInUse,
  893. 0,
  894. FALSE
  895. );
  896. }
  897. NTSTATUS
  898. GCR410PIoCompletion(
  899. IN PDEVICE_OBJECT DeviceObject,
  900. IN PIRP Irp,
  901. IN PKEVENT Event
  902. )
  903. /*++
  904. Routine Description:
  905. Completion routine for an Irp sent to the serial driver.
  906. It sets only an event that we can use to wait for.
  907. --*/
  908. {
  909. UNREFERENCED_PARAMETER (DeviceObject);
  910. if (Irp->Cancel) {
  911. Irp->IoStatus.Status = STATUS_CANCELLED;
  912. } else {
  913. Irp->IoStatus.Status = STATUS_MORE_PROCESSING_REQUIRED;
  914. }
  915. KeSetEvent (Event, 0, FALSE);
  916. return STATUS_MORE_PROCESSING_REQUIRED;
  917. }
  918. NTSTATUS
  919. GCR410PCallSerialDriver(
  920. IN PDEVICE_OBJECT DeviceObject,
  921. IN PIRP Irp
  922. )
  923. /*++
  924. Routine Description:
  925. Send an Irp to the serial driver.
  926. --*/
  927. {
  928. NTSTATUS status = STATUS_SUCCESS;
  929. KEVENT Event;
  930. // Copy our stack location to the next.
  931. IoCopyCurrentIrpStackLocationToNext(Irp);
  932. //
  933. // initialize an event for process synchronization. The event is passed
  934. // to our completion routine and will be set when the serial driver is done
  935. //
  936. KeInitializeEvent(
  937. &Event,
  938. NotificationEvent,
  939. FALSE
  940. );
  941. // Our IoCompletionRoutine sets only our event
  942. IoSetCompletionRoutine (
  943. Irp,
  944. GCR410PIoCompletion,
  945. &Event,
  946. TRUE,
  947. TRUE,
  948. TRUE
  949. );
  950. if (IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_POWER) {
  951. status = PoCallDriver(DeviceObject, Irp);
  952. } else {
  953. // Call the serial driver
  954. status = IoCallDriver(DeviceObject, Irp);
  955. }
  956. // Wait until the serial driver has processed the Irp
  957. if (status == STATUS_PENDING) {
  958. KeWaitForSingleObject(
  959. &Event,
  960. Executive,
  961. KernelMode,
  962. FALSE,
  963. NULL
  964. );
  965. status = Irp->IoStatus.Status;
  966. }
  967. return status;
  968. }
  969. NTSTATUS
  970. GCR410PPnPDeviceControl(
  971. IN PDEVICE_OBJECT DeviceObject,
  972. IN PIRP Irp
  973. )
  974. /*++
  975. Routine Description:
  976. --*/
  977. {
  978. NTSTATUS status = STATUS_SUCCESS;
  979. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  980. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  981. PREADER_EXTENSION readerExtension = smartcardExtension->ReaderExtension;
  982. PDEVICE_OBJECT AttachedDeviceObject;
  983. PIO_STACK_LOCATION irpStack;
  984. BOOLEAN deviceRemoved = FALSE, irpSkipped = FALSE;
  985. KIRQL irql;
  986. SmartcardDebug(
  987. DEBUG_DRIVER,
  988. ( "%s!GCR410PPnPDeviceControl: Enter\n",
  989. SC_DRIVER_NAME)
  990. );
  991. status = SmartcardAcquireRemoveLockWithTag(smartcardExtension, ' PnP');
  992. ASSERT(status == STATUS_SUCCESS);
  993. if (status != STATUS_SUCCESS) {
  994. Irp->IoStatus.Information = 0;
  995. Irp->IoStatus.Status = status;
  996. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  997. return status;
  998. }
  999. AttachedDeviceObject = ATTACHED_DEVICE_OBJECT;
  1000. Irp->IoStatus.Information = 0;
  1001. irpStack = IoGetCurrentIrpStackLocation(Irp);
  1002. // Now look what the PnP manager wants...
  1003. switch(irpStack->MinorFunction)
  1004. {
  1005. case IRP_MN_START_DEVICE:
  1006. SmartcardDebug(
  1007. DEBUG_DRIVER,
  1008. ("%s!GCR410PPnPDeviceControl: IRP_MN_START_DEVICE\n",
  1009. SC_DRIVER_NAME)
  1010. );
  1011. // We have to call the underlying driver first
  1012. status = GCR410PCallSerialDriver(AttachedDeviceObject, Irp);
  1013. ASSERT(NT_SUCCESS(status));
  1014. if (NT_SUCCESS(status)) {
  1015. status = GCR410PStartDevice(DeviceObject);
  1016. }
  1017. break;
  1018. case IRP_MN_QUERY_STOP_DEVICE:
  1019. SmartcardDebug(
  1020. DEBUG_DRIVER,
  1021. ("%s!GCR410PPnPDeviceControl: IRP_MN_QUERY_STOP_DEVICE\n",
  1022. SC_DRIVER_NAME)
  1023. );
  1024. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  1025. if (deviceExtension->IoCount > 0) {
  1026. // we refuse to stop if we have pending io
  1027. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  1028. status = STATUS_DEVICE_BUSY;
  1029. } else {
  1030. // stop processing requests
  1031. KeClearEvent(&deviceExtension->ReaderStarted);
  1032. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  1033. status = GCR410PCallSerialDriver(AttachedDeviceObject, Irp);
  1034. }
  1035. break;
  1036. case IRP_MN_CANCEL_STOP_DEVICE:
  1037. SmartcardDebug(
  1038. DEBUG_DRIVER,
  1039. ("%s!GCR410PPnPDeviceControl: IRP_MN_CANCEL_STOP_DEVICE\n",
  1040. SC_DRIVER_NAME)
  1041. );
  1042. status = GCR410PCallSerialDriver(
  1043. AttachedDeviceObject,
  1044. Irp
  1045. );
  1046. if (status == STATUS_SUCCESS) {
  1047. // we can continue to process requests
  1048. KeSetEvent(&deviceExtension->ReaderStarted, 0, FALSE);
  1049. }
  1050. break;
  1051. case IRP_MN_STOP_DEVICE:
  1052. SmartcardDebug(
  1053. DEBUG_DRIVER,
  1054. ("%s!GCR410PPnPDeviceControl: IRP_MN_STOP_DEVICE\n",
  1055. SC_DRIVER_NAME)
  1056. );
  1057. GCR410PStopDevice(DeviceObject);
  1058. //
  1059. // we don't do anything since a stop is only used
  1060. // to reconfigure hw-resources like interrupts and io-ports
  1061. //
  1062. status = GCR410PCallSerialDriver(
  1063. AttachedDeviceObject,
  1064. Irp
  1065. );
  1066. break;
  1067. case IRP_MN_QUERY_REMOVE_DEVICE:
  1068. SmartcardDebug(
  1069. DEBUG_DRIVER,
  1070. ("%s!GCR410PPnPDeviceControl: IRP_MN_QUERY_REMOVE_DEVICE\n",
  1071. SC_DRIVER_NAME)
  1072. );
  1073. // disable the reader
  1074. status = IoSetDeviceInterfaceState(
  1075. &deviceExtension->PnPDeviceName,
  1076. FALSE
  1077. );
  1078. ASSERT(NT_SUCCESS(status));
  1079. if (!NT_SUCCESS(status)) {
  1080. break;
  1081. }
  1082. // now look if someone is currently connected to us
  1083. if (deviceExtension->ReaderOpen) {
  1084. //
  1085. // someone is connected, fail the call
  1086. // we will enable the device interface in
  1087. // IRP_MN_CANCEL_REMOVE_DEVICE again
  1088. //
  1089. status = STATUS_UNSUCCESSFUL;
  1090. break;
  1091. }
  1092. // pass the call to the next driver in the stack
  1093. status = GCR410PCallSerialDriver(AttachedDeviceObject, Irp);
  1094. break;
  1095. case IRP_MN_CANCEL_REMOVE_DEVICE:
  1096. SmartcardDebug(
  1097. DEBUG_DRIVER,
  1098. ("%s!GCR410PPnPDeviceControl: IRP_MN_CANCEL_REMOVE_DEVICE\n",
  1099. SC_DRIVER_NAME)
  1100. );
  1101. status = GCR410PCallSerialDriver(
  1102. AttachedDeviceObject,
  1103. Irp
  1104. );
  1105. // reenable the interface only in case that the reader is
  1106. // still connected. This covers the following case:
  1107. // hibernate machine, disconnect reader, wake up, stop device
  1108. // (from task bar) and stop fails since an app. holds the device open
  1109. //
  1110. if (status == STATUS_SUCCESS &&
  1111. readerExtension->SerialConfigData.SerialWaitMask != 0)
  1112. {
  1113. status = IoSetDeviceInterfaceState(
  1114. &deviceExtension->PnPDeviceName,
  1115. TRUE
  1116. );
  1117. ASSERT(status == STATUS_SUCCESS);
  1118. }
  1119. break;
  1120. case IRP_MN_REMOVE_DEVICE:
  1121. SmartcardDebug(
  1122. DEBUG_DRIVER,
  1123. ("%s!GCR410PPnPDeviceControl: IRP_MN_REMOVE_DEVICE\n",
  1124. SC_DRIVER_NAME)
  1125. );
  1126. GCR410PRemoveDevice(DeviceObject);
  1127. status = GCR410PCallSerialDriver(
  1128. AttachedDeviceObject,
  1129. Irp
  1130. );
  1131. deviceRemoved = TRUE;
  1132. break;
  1133. default:
  1134. // This is an Irp that is only useful for underlying drivers
  1135. SmartcardDebug(
  1136. DEBUG_DRIVER,
  1137. ("%s!GCR410PnPDeviceControl: IRP_MN_...%lx\n",
  1138. SC_DRIVER_NAME,
  1139. irpStack->MinorFunction)
  1140. );
  1141. IoSkipCurrentIrpStackLocation(Irp);
  1142. status = IoCallDriver(AttachedDeviceObject, Irp);
  1143. irpSkipped = TRUE;
  1144. break;
  1145. }
  1146. if (irpSkipped == FALSE) {
  1147. Irp->IoStatus.Status = status;
  1148. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1149. }
  1150. if (deviceRemoved == FALSE) {
  1151. SmartcardReleaseRemoveLockWithTag(smartcardExtension, ' PnP');
  1152. }
  1153. SmartcardDebug(
  1154. DEBUG_DRIVER,
  1155. ( "%s!GCR410PPnPDeviceControl: Exit=%X(hex)\n",
  1156. SC_DRIVER_NAME,
  1157. status)
  1158. );
  1159. return status;
  1160. }
  1161. VOID
  1162. GCR410PSystemPowerCompletion(
  1163. IN PDEVICE_OBJECT DeviceObject,
  1164. IN UCHAR MinorFunction,
  1165. IN POWER_STATE PowerState,
  1166. IN PIRP Irp,
  1167. IN PIO_STATUS_BLOCK IoStatus
  1168. )
  1169. /*++
  1170. Routine Description:
  1171. This function is called when the underlying stacks
  1172. completed the power transition.
  1173. --*/
  1174. {
  1175. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1176. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  1177. UNREFERENCED_PARAMETER (MinorFunction);
  1178. SmartcardDebug(
  1179. DEBUG_DRIVER,
  1180. ( "%s!GCR410PSystemPowerCompletion: Enter\n",
  1181. SC_DRIVER_NAME)
  1182. );
  1183. Irp->IoStatus.Information = 0;
  1184. Irp->IoStatus.Status = IoStatus->Status;
  1185. SmartcardReleaseRemoveLockWithTag(smartcardExtension, 'rwoP');
  1186. if (PowerState.SystemState == PowerSystemWorking) {
  1187. PoSetPowerState (
  1188. DeviceObject,
  1189. SystemPowerState,
  1190. PowerState
  1191. );
  1192. }
  1193. PoStartNextPowerIrp(Irp);
  1194. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1195. SmartcardDebug(
  1196. DEBUG_DRIVER,
  1197. ( "%s!GCR410PSystemPowerCompletion: Exit\n",
  1198. SC_DRIVER_NAME)
  1199. );
  1200. }
  1201. NTSTATUS
  1202. GCR410PDevicePowerCompletion (
  1203. IN PDEVICE_OBJECT DeviceObject,
  1204. IN PIRP Irp,
  1205. IN PSMARTCARD_EXTENSION SmartcardExtension
  1206. )
  1207. /*++
  1208. Routine Description:
  1209. This routine is called after the underlying stack powered
  1210. UP the serial port, so it can be used again.
  1211. --*/
  1212. {
  1213. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1214. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1215. NTSTATUS status;
  1216. SmartcardDebug(
  1217. DEBUG_DRIVER,
  1218. ( "%s!GCR410PDevicePowerCompletion: Enter\n",
  1219. SC_DRIVER_NAME)
  1220. );
  1221. //ISV
  1222. // We've got power up request, so...
  1223. // Report everybody that reader is powered up again!
  1224. SmartcardExtension->ReaderExtension->ReaderPowerState =
  1225. PowerReaderWorking;
  1226. // Restore the communication with the reader
  1227. status = GDDK_0ARestoreCommunication(SmartcardExtension);
  1228. //
  1229. // We issue a power request in order to figure out
  1230. // what the actual card status is
  1231. //
  1232. SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET;
  1233. GDDK_0AReaderPower(SmartcardExtension);
  1234. //
  1235. // If a card was present before power down or now there is
  1236. // a card in the reader, we complete any pending card monitor
  1237. // request, since we do not really know what card is now in the
  1238. // reader.
  1239. //
  1240. if(SmartcardExtension->ReaderExtension->CardPresent ||
  1241. SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT) {
  1242. GCR410PCompleteCardTracking(SmartcardExtension);
  1243. }
  1244. SmartcardReleaseRemoveLockWithTag(SmartcardExtension, 'rwoP');
  1245. // inform the power manager of our state.
  1246. PoSetPowerState (
  1247. DeviceObject,
  1248. DevicePowerState,
  1249. irpStack->Parameters.Power.State
  1250. );
  1251. PoStartNextPowerIrp(Irp);
  1252. // signal that we can process ioctls again
  1253. KeSetEvent(&deviceExtension->ReaderStarted, 0, FALSE);
  1254. SmartcardDebug(
  1255. DEBUG_DRIVER,
  1256. ( "%s!GCR410PDevicePowerCompletion: Exit\n",
  1257. SC_DRIVER_NAME)
  1258. );
  1259. return STATUS_SUCCESS;
  1260. }
  1261. NTSTATUS
  1262. GCR410PPowerDeviceControl(
  1263. IN PDEVICE_OBJECT DeviceObject,
  1264. IN PIRP Irp
  1265. )
  1266. /*++
  1267. Routine Description:
  1268. The power dispatch routine.
  1269. This driver is the power policy owner of the device stack,
  1270. because this driver knows about the connected reader.
  1271. Therefor this driver will translate system power states
  1272. to device power states.
  1273. Arguments:
  1274. DeviceObject - pointer to a device object.
  1275. Irp - pointer to an I/O Request Packet.
  1276. Return Value:
  1277. NT status code
  1278. --*/
  1279. {
  1280. NTSTATUS status = STATUS_SUCCESS;
  1281. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1282. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1283. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  1284. PDEVICE_OBJECT AttachedDeviceObject;
  1285. POWER_STATE powerState;
  1286. ACTION action;
  1287. SmartcardDebug(
  1288. DEBUG_ERROR,
  1289. ("%s!GCR410PPowerDeviceControl: Enter\n",
  1290. SC_DRIVER_NAME)
  1291. );
  1292. SmartcardDebug(
  1293. DEBUG_ERROR,
  1294. ("%s!GCR410PPowerDeviceControl: Irp = %lx\n",
  1295. SC_DRIVER_NAME,
  1296. Irp)
  1297. );
  1298. status = SmartcardAcquireRemoveLockWithTag(smartcardExtension, 'rwoP');
  1299. ASSERT(status == STATUS_SUCCESS);
  1300. if (!NT_SUCCESS(status)) {
  1301. PoStartNextPowerIrp(Irp);
  1302. Irp->IoStatus.Status = status;
  1303. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1304. return status;
  1305. }
  1306. AttachedDeviceObject = ATTACHED_DEVICE_OBJECT;
  1307. switch (irpStack->Parameters.Power.Type) {
  1308. case DevicePowerState:
  1309. if (irpStack->MinorFunction == IRP_MN_SET_POWER) {
  1310. switch (irpStack->Parameters.Power.State.DeviceState) {
  1311. case PowerDeviceD0:
  1312. // Turn on the reader
  1313. SmartcardDebug(
  1314. DEBUG_ERROR,
  1315. ("%s!GCR410PPowerDeviceControl: PowerDevice D0\n",
  1316. SC_DRIVER_NAME)
  1317. );
  1318. //
  1319. // First, we send down the request to the bus, in order
  1320. // to power on the port. When the request completes,
  1321. // we turn on the reader
  1322. //
  1323. IoCopyCurrentIrpStackLocationToNext(Irp);
  1324. IoSetCompletionRoutine (
  1325. Irp,
  1326. GCR410PDevicePowerCompletion,
  1327. smartcardExtension,
  1328. TRUE,
  1329. TRUE,
  1330. TRUE
  1331. );
  1332. action = WaitForCompletion;
  1333. break;
  1334. case PowerDeviceD3:
  1335. // Turn off the reader
  1336. SmartcardDebug(
  1337. DEBUG_ERROR,
  1338. ("%s!GCR410PPowerDeviceControl: PowerDevice D3\n",
  1339. SC_DRIVER_NAME)
  1340. );
  1341. PoSetPowerState (
  1342. DeviceObject,
  1343. DevicePowerState,
  1344. irpStack->Parameters.Power.State
  1345. );
  1346. // save the current card state
  1347. smartcardExtension->ReaderExtension->CardPresent =
  1348. smartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT;
  1349. if (smartcardExtension->ReaderExtension->CardPresent) {
  1350. smartcardExtension->MinorIoControlCode = SCARD_POWER_DOWN;
  1351. status = GDDK_0AReaderPower(smartcardExtension);
  1352. ASSERT(status == STATUS_SUCCESS);
  1353. }
  1354. //
  1355. // If there is a pending card tracking request, setting
  1356. // this flag will prevent completion of the request
  1357. // when the system will be waked up again.
  1358. //
  1359. smartcardExtension->ReaderExtension->PowerRequest = TRUE;
  1360. // save the current power state of the reader
  1361. smartcardExtension->ReaderExtension->ReaderPowerState =
  1362. PowerReaderOff;
  1363. action = SkipRequest;
  1364. break;
  1365. default:
  1366. ASSERT(FALSE);
  1367. action = SkipRequest;
  1368. break;
  1369. }
  1370. } else {
  1371. ASSERT(FALSE);
  1372. action = SkipRequest;
  1373. }
  1374. break;
  1375. case SystemPowerState: {
  1376. //
  1377. // The system wants to change the power state.
  1378. // We need to translate the system power state to
  1379. // a corresponding device power state.
  1380. //
  1381. POWER_STATE_TYPE powerType = DevicePowerState;
  1382. ASSERT(smartcardExtension->ReaderExtension->ReaderPowerState !=
  1383. PowerReaderUnspecified);
  1384. switch (irpStack->MinorFunction) {
  1385. KIRQL irql;
  1386. case IRP_MN_QUERY_POWER:
  1387. SmartcardDebug(
  1388. DEBUG_ERROR,
  1389. ("%s!GCR410PPowerDeviceControl: Query Power\n",
  1390. SC_DRIVER_NAME)
  1391. );
  1392. switch (irpStack->Parameters.Power.State.SystemState) {
  1393. case PowerSystemMaximum:
  1394. case PowerSystemWorking:
  1395. case PowerSystemSleeping1:
  1396. case PowerSystemSleeping2:
  1397. break;
  1398. case PowerSystemSleeping3:
  1399. case PowerSystemHibernate:
  1400. case PowerSystemShutdown:
  1401. KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
  1402. if (deviceExtension->IoCount == 0) {
  1403. // Block any further ioctls
  1404. KeClearEvent(&deviceExtension->ReaderStarted);
  1405. } else {
  1406. // can't go to sleep mode since the reader is busy.
  1407. status = STATUS_DEVICE_BUSY;
  1408. }
  1409. KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
  1410. break;
  1411. }
  1412. action = CompleteRequest;
  1413. break;
  1414. case IRP_MN_SET_POWER:
  1415. SmartcardDebug(
  1416. DEBUG_ERROR,
  1417. ("%s!GCR410PPowerDeviceControl: PowerSystem S%d\n",
  1418. SC_DRIVER_NAME,
  1419. irpStack->Parameters.Power.State.SystemState - 1)
  1420. );
  1421. switch (irpStack->Parameters.Power.State.SystemState) {
  1422. case PowerSystemMaximum:
  1423. case PowerSystemWorking:
  1424. case PowerSystemSleeping1:
  1425. case PowerSystemSleeping2:
  1426. if (smartcardExtension->ReaderExtension->ReaderPowerState ==
  1427. PowerReaderWorking) {
  1428. // We're already in the right state
  1429. KeSetEvent(&deviceExtension->ReaderStarted,0,FALSE);
  1430. action = CompleteRequest;
  1431. break;
  1432. }
  1433. // wake up the underlying stack...
  1434. powerState.DeviceState = PowerDeviceD0;
  1435. action = MarkPending;
  1436. break;
  1437. case PowerSystemSleeping3:
  1438. case PowerSystemHibernate:
  1439. case PowerSystemShutdown:
  1440. if (smartcardExtension->ReaderExtension->ReaderPowerState ==
  1441. PowerReaderOff) {
  1442. // We're already in the right state
  1443. action = CompleteRequest;
  1444. break;
  1445. }
  1446. powerState.DeviceState = PowerDeviceD3;
  1447. // first, inform the power manager of our new state.
  1448. PoSetPowerState (
  1449. DeviceObject,
  1450. SystemPowerState,
  1451. powerState
  1452. );
  1453. action = MarkPending;
  1454. break;
  1455. default:
  1456. ASSERT(FALSE);
  1457. action = CompleteRequest;
  1458. break;
  1459. }
  1460. }
  1461. }
  1462. break;
  1463. default:
  1464. ASSERT(FALSE);
  1465. action = CompleteRequest;
  1466. break;
  1467. }
  1468. switch (action) {
  1469. case CompleteRequest:
  1470. Irp->IoStatus.Status = status;
  1471. Irp->IoStatus.Information = 0;
  1472. SmartcardReleaseRemoveLockWithTag(smartcardExtension, 'rwoP');
  1473. PoStartNextPowerIrp(Irp);
  1474. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1475. break;
  1476. case MarkPending:
  1477. Irp->IoStatus.Status = STATUS_PENDING;
  1478. IoMarkIrpPending(Irp);
  1479. status = PoRequestPowerIrp (
  1480. DeviceObject,
  1481. IRP_MN_SET_POWER,
  1482. powerState,
  1483. GCR410PSystemPowerCompletion,
  1484. Irp,
  1485. NULL
  1486. );
  1487. ASSERT(status == STATUS_PENDING);
  1488. break;
  1489. case SkipRequest:
  1490. SmartcardReleaseRemoveLockWithTag(smartcardExtension, 'rwoP');
  1491. PoStartNextPowerIrp(Irp);
  1492. IoSkipCurrentIrpStackLocation(Irp);
  1493. status = PoCallDriver(AttachedDeviceObject, Irp);
  1494. break;
  1495. case WaitForCompletion:
  1496. status = PoCallDriver(AttachedDeviceObject, Irp);
  1497. break;
  1498. default:
  1499. ASSERT(FALSE);
  1500. break;
  1501. }
  1502. SmartcardDebug(
  1503. DEBUG_DRIVER,
  1504. ("%s!GCR410PPowerDeviceControl: Exit %lx\n",
  1505. SC_DRIVER_NAME,
  1506. status)
  1507. );
  1508. return status;
  1509. }
  1510. NTSTATUS
  1511. GCR410PCreateClose(
  1512. IN PDEVICE_OBJECT DeviceObject,
  1513. IN PIRP Irp
  1514. )
  1515. /*++
  1516. Routine Description:
  1517. This routine is called by the I/O system when the device is opened or closed.
  1518. Arguments:
  1519. DeviceObject - Pointer to device object for this miniport
  1520. Irp - IRP involved.
  1521. Return Value:
  1522. STATUS_SUCCESS.
  1523. --*/
  1524. {
  1525. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1526. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1527. NTSTATUS status = STATUS_SUCCESS;
  1528. SmartcardDebug(
  1529. DEBUG_DRIVER,
  1530. ("%s!GCR410PCreateClose: Enter\n",
  1531. SC_DRIVER_NAME)
  1532. );
  1533. __try {
  1534. if (irpStack->MajorFunction == IRP_MJ_CREATE) {
  1535. status = SmartcardAcquireRemoveLockWithTag(
  1536. &deviceExtension->SmartcardExtension,'lCrC');
  1537. if (status != STATUS_SUCCESS) {
  1538. status = STATUS_DEVICE_REMOVED;
  1539. __leave;
  1540. }
  1541. // test if the device has been opened already
  1542. if (InterlockedCompareExchange(
  1543. &deviceExtension->ReaderOpen,
  1544. TRUE,
  1545. FALSE) == FALSE) {
  1546. SmartcardDebug(
  1547. DEBUG_DRIVER,
  1548. ("%s!TLP3CreateClose: Open\n",
  1549. DRIVER_NAME)
  1550. );
  1551. } else {
  1552. // the device is already in use
  1553. status = STATUS_UNSUCCESSFUL;
  1554. // release the lock
  1555. SmartcardReleaseRemoveLockWithTag(
  1556. &deviceExtension->SmartcardExtension,'lCrC');
  1557. }
  1558. } else {
  1559. SmartcardDebug(
  1560. DEBUG_DRIVER,
  1561. ("%s!GCR410PCreateClose: Close\n",
  1562. DRIVER_NAME)
  1563. );
  1564. SmartcardReleaseRemoveLockWithTag(
  1565. &deviceExtension->SmartcardExtension,'lCrC');
  1566. deviceExtension->ReaderOpen = FALSE;
  1567. }
  1568. }
  1569. __finally {
  1570. Irp->IoStatus.Status = status;
  1571. Irp->IoStatus.Information = 0;
  1572. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1573. }
  1574. SmartcardDebug(
  1575. DEBUG_DRIVER,
  1576. ("%s!GCR410PCreateClose: Exit\n",
  1577. SC_DRIVER_NAME)
  1578. );
  1579. return status;
  1580. }
  1581. NTSTATUS
  1582. GCR410PCancel(
  1583. IN PDEVICE_OBJECT DeviceObject,
  1584. IN PIRP Irp
  1585. )
  1586. /*++
  1587. Routine Description:
  1588. This routine is called by the I/O system when the irp should be cancelled.
  1589. Arguments:
  1590. DeviceObject - is a pointer to the device.
  1591. Irp - holds the Irp involved.
  1592. Return Value:
  1593. STATUS_CANCELLED - the Irp is cancelled.
  1594. --*/
  1595. {
  1596. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1597. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  1598. SmartcardDebug(
  1599. DEBUG_TRACE,
  1600. ("%s!GCR410PCancel: Enter\n",
  1601. DRIVER_NAME)
  1602. );
  1603. ASSERT(Irp == smartcardExtension->OsData->NotificationIrp);
  1604. IoReleaseCancelSpinLock(
  1605. Irp->CancelIrql
  1606. );
  1607. GCR410PCompleteCardTracking(smartcardExtension);
  1608. SmartcardDebug(
  1609. DEBUG_TRACE,
  1610. ("%s!GCR410PCancel: Exit\n",
  1611. DRIVER_NAME)
  1612. );
  1613. return STATUS_CANCELLED;
  1614. }
  1615. NTSTATUS
  1616. GCR410PCleanup(
  1617. IN PDEVICE_OBJECT DeviceObject,
  1618. IN PIRP Irp
  1619. )
  1620. /*++
  1621. Routine Description:
  1622. This routine is called by the I/O system when the device is closed.
  1623. Arguments:
  1624. DeviceObject - is a pointer to the device.
  1625. Irp - holds the Irp involved.
  1626. Return Value:
  1627. STATUS_SUCCESS - the request is completed
  1628. --*/
  1629. {
  1630. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1631. PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
  1632. NTSTATUS status = STATUS_SUCCESS;
  1633. SmartcardDebug(
  1634. DEBUG_TRACE,
  1635. ("%s!GCR410PCleanup: Enter\n",
  1636. DRIVER_NAME)
  1637. );
  1638. ASSERT(Irp != smartcardExtension->OsData->NotificationIrp);
  1639. // We need to complete the notification irp
  1640. GCR410PCompleteCardTracking(smartcardExtension);
  1641. SmartcardDebug(
  1642. DEBUG_DRIVER,
  1643. ("%s!GCR410PCleanup: Completing IRP %lx\n",
  1644. DRIVER_NAME,
  1645. Irp)
  1646. );
  1647. Irp->IoStatus.Information = 0;
  1648. Irp->IoStatus.Status = STATUS_SUCCESS;
  1649. IoCompleteRequest(
  1650. Irp,
  1651. IO_NO_INCREMENT
  1652. );
  1653. SmartcardDebug(
  1654. DEBUG_TRACE,
  1655. ("%s!GCR410PCleanup: Exit\n",
  1656. DRIVER_NAME)
  1657. );
  1658. return STATUS_SUCCESS;
  1659. }
  1660. VOID
  1661. GCR410PRemoveDevice(
  1662. PDEVICE_OBJECT DeviceObject
  1663. )
  1664. /*++
  1665. Routine Description:
  1666. Remove the device from the system.
  1667. --*/
  1668. {
  1669. PDEVICE_EXTENSION deviceExtension;
  1670. PSMARTCARD_EXTENSION smartcardExtension;
  1671. PAGED_CODE();
  1672. SmartcardDebug(
  1673. DEBUG_DRIVER,
  1674. ( "%s!GCR410PRemoveDevice: Enter\n",
  1675. SC_DRIVER_NAME)
  1676. );
  1677. ASSERT(DeviceObject != NULL);
  1678. if (DeviceObject == NULL) {
  1679. SmartcardDebug(
  1680. DEBUG_TRACE,
  1681. ( "%s!GCR410PRemoveDevice: Exit immediatly (no device to remove)\n",
  1682. SC_DRIVER_NAME)
  1683. );
  1684. return;
  1685. }
  1686. deviceExtension = DeviceObject->DeviceExtension;
  1687. smartcardExtension = &deviceExtension->SmartcardExtension;
  1688. if (smartcardExtension->OsData) {
  1689. // complete pending card tracking requests (if any)
  1690. GCR410PCompleteCardTracking(smartcardExtension);
  1691. ASSERT(smartcardExtension->OsData->NotificationIrp == NULL);
  1692. // Wait until we can safely unload the device
  1693. SmartcardReleaseRemoveLockAndWait(smartcardExtension);
  1694. }
  1695. ASSERT(smartcardExtension->VendorAttr.UnitNo < MAX_DEVICES);
  1696. ASSERT(bDevicePort[smartcardExtension->VendorAttr.UnitNo] == TRUE);
  1697. // Mark this slot as available
  1698. //bDevicePort[smartcardExtension->VendorAttr.UnitNo] = FALSE;
  1699. GCR410PStopDevice(DeviceObject);
  1700. if (deviceExtension->SmartcardExtension.ReaderExtension &&
  1701. deviceExtension->SmartcardExtension.ReaderExtension->AttachedDeviceObject) {
  1702. IoDetachDevice(
  1703. deviceExtension->SmartcardExtension.ReaderExtension->AttachedDeviceObject
  1704. );
  1705. SmartcardDebug(
  1706. DEBUG_TRACE,
  1707. ( "%s!GCR410PRemoveDevice: IoDetachDevice\n",
  1708. SC_DRIVER_NAME)
  1709. );
  1710. }
  1711. if(deviceExtension->PnPDeviceName.Buffer) {
  1712. RtlFreeUnicodeString(&deviceExtension->PnPDeviceName);
  1713. }
  1714. if(smartcardExtension->OsData) {
  1715. SmartcardExit(smartcardExtension);
  1716. }
  1717. if (smartcardExtension->ReaderExtension) {
  1718. ExFreePool(smartcardExtension->ReaderExtension);
  1719. }
  1720. if (deviceExtension->CloseSerial) {
  1721. IoFreeWorkItem(deviceExtension->CloseSerial);
  1722. }
  1723. if (deviceExtension->CardStateChange) {
  1724. IoFreeWorkItem(deviceExtension->CardStateChange);
  1725. }
  1726. IoDeleteDevice(DeviceObject);
  1727. DeviceObject=NULL;
  1728. SmartcardDebug(
  1729. DEBUG_INFO,
  1730. ( "%s!GCR410PRemoveDevice: Exit\n",
  1731. SC_DRIVER_NAME)
  1732. );
  1733. }
  1734. VOID
  1735. GCR410PDriverUnload(
  1736. IN PDRIVER_OBJECT DriverObject
  1737. )
  1738. /*++
  1739. Routine Description:
  1740. The driver unload routine. This is called by the I/O system when the
  1741. device is unloaded from memory.
  1742. Arguments:
  1743. DriverObject - is a pointer to the driver object for this device.
  1744. Return Value:
  1745. Nothing
  1746. --*/
  1747. {
  1748. PAGED_CODE();
  1749. SmartcardDebug(
  1750. DEBUG_INFO,
  1751. ("%s!GCR410PDriverUnload\n",
  1752. SC_DRIVER_NAME)
  1753. );
  1754. }
  1755. NTSTATUS
  1756. GCR410PStartSerialEventTracking(
  1757. PSMARTCARD_EXTENSION SmartcardExtension
  1758. )
  1759. /*++
  1760. Routine Description:
  1761. This routine initialized serial event tracking. It calls the serial driver to
  1762. set a wait mask for RING and DSR tracking. After that it installs a completion
  1763. routine to be called when RING or DSR is signaled.
  1764. Arguments:
  1765. SmartcardExtension - is a pointer on the SmartCardExtension structure of
  1766. the current device.
  1767. Return Value:
  1768. Nothing
  1769. --*/
  1770. {
  1771. NTSTATUS status;
  1772. PREADER_EXTENSION readerExtension = SmartcardExtension->ReaderExtension;
  1773. IO_STATUS_BLOCK ioStatus;
  1774. KEVENT event;
  1775. PAGED_CODE();
  1776. SmartcardDebug(
  1777. DEBUG_TRACE,
  1778. ( "%s!GCR410PStartSerialEventTracking: Enter\n",
  1779. SC_DRIVER_NAME)
  1780. );
  1781. KeInitializeEvent(
  1782. &event,
  1783. NotificationEvent,
  1784. FALSE
  1785. );
  1786. readerExtension->SerialConfigData.SerialWaitMask =
  1787. SERIAL_EV_DSR | SERIAL_EV_RING;
  1788. // Send a wait mask to the serial driver. This call only sets the
  1789. // wait mask. We want to be informed when the RING or DSR chnages its state.
  1790. readerExtension->SerialStatusIrp = IoBuildDeviceIoControlRequest(
  1791. IOCTL_SERIAL_SET_WAIT_MASK,
  1792. readerExtension->AttachedDeviceObject,
  1793. &readerExtension->SerialConfigData.SerialWaitMask,
  1794. sizeof(readerExtension->SerialConfigData.SerialWaitMask),
  1795. NULL,
  1796. 0,
  1797. FALSE,
  1798. &event,
  1799. &ioStatus
  1800. );
  1801. if (readerExtension->SerialStatusIrp == NULL) {
  1802. return STATUS_INSUFFICIENT_RESOURCES;
  1803. }
  1804. status = IoCallDriver(
  1805. readerExtension->AttachedDeviceObject,
  1806. readerExtension->SerialStatusIrp
  1807. );
  1808. if (status == STATUS_PENDING) {
  1809. KeWaitForSingleObject(
  1810. &event,
  1811. Suspended,
  1812. KernelMode,
  1813. FALSE,
  1814. NULL
  1815. );
  1816. //ASSERT (STATUS_SUCCESS == status);
  1817. status = ioStatus.Status;
  1818. }
  1819. if (status == STATUS_SUCCESS) {
  1820. PIO_STACK_LOCATION irpSp;
  1821. readerExtension->SerialStatusIrp = IoAllocateIrp(
  1822. (CCHAR) (SmartcardExtension->OsData->DeviceObject->StackSize + 1),
  1823. FALSE
  1824. );
  1825. if (readerExtension->SerialStatusIrp == NULL) {
  1826. return STATUS_INSUFFICIENT_RESOURCES;
  1827. }
  1828. irpSp = IoGetNextIrpStackLocation( readerExtension->SerialStatusIrp );
  1829. irpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  1830. irpSp->Parameters.DeviceIoControl.InputBufferLength = 0;
  1831. irpSp->Parameters.DeviceIoControl.OutputBufferLength =
  1832. sizeof(readerExtension->SerialConfigData.SerialWaitMask);
  1833. irpSp->Parameters.DeviceIoControl.IoControlCode =
  1834. IOCTL_SERIAL_WAIT_ON_MASK;
  1835. readerExtension->SerialStatusIrp->AssociatedIrp.SystemBuffer =
  1836. &readerExtension->SerialConfigData.SerialWaitMask;
  1837. // We simulate a callback now that triggers the card supervision
  1838. SmartcardExtension->ReaderExtension->GetModemStatus = FALSE;
  1839. GCR410PSerialEvent(
  1840. SmartcardExtension->OsData->DeviceObject,
  1841. readerExtension->SerialStatusIrp,
  1842. SmartcardExtension
  1843. );
  1844. status = STATUS_SUCCESS;
  1845. }
  1846. SmartcardDebug(
  1847. DEBUG_TRACE,
  1848. ( "%s!GCR410PStartSerialEventTracking: Exit\n",
  1849. SC_DRIVER_NAME)
  1850. );
  1851. return status;
  1852. }
  1853. NTSTATUS
  1854. GCR410PStopSerialEventTracking(
  1855. PSMARTCARD_EXTENSION SmartcardExtension
  1856. )
  1857. /*++
  1858. Routine Description:
  1859. This routine disabled the serial event tracking. It calls the serial driver to
  1860. set a wait mask to 0.
  1861. Arguments:
  1862. SmartcardExtension - is a pointer on the SmartCardExtension structure of
  1863. the current device.
  1864. Return Value:
  1865. Nothing
  1866. --*/
  1867. {
  1868. NTSTATUS status;
  1869. PREADER_EXTENSION readerExtension = SmartcardExtension->ReaderExtension;
  1870. IO_STATUS_BLOCK ioStatus;
  1871. KEVENT event;
  1872. PIRP irp;
  1873. PAGED_CODE();
  1874. SmartcardDebug(
  1875. DEBUG_TRACE,
  1876. ( "%s!GCR410PStopSerialEventTracking: Enter\n",
  1877. SC_DRIVER_NAME)
  1878. );
  1879. KeInitializeEvent(
  1880. &event,
  1881. NotificationEvent,
  1882. FALSE
  1883. );
  1884. readerExtension->SerialConfigData.SerialWaitMask = 0;
  1885. irp = IoBuildDeviceIoControlRequest(
  1886. IOCTL_SERIAL_SET_WAIT_MASK,
  1887. readerExtension->AttachedDeviceObject,
  1888. &readerExtension->SerialConfigData.SerialWaitMask,
  1889. sizeof(readerExtension->SerialConfigData.SerialWaitMask),
  1890. NULL,
  1891. 0,
  1892. FALSE,
  1893. &event,
  1894. &ioStatus
  1895. );
  1896. if (irp == NULL) {
  1897. SmartcardDebug(
  1898. DEBUG_ERROR,
  1899. ( "%s!GCR410PStopSerialEventTracking: Insufficient resources\n",
  1900. SC_DRIVER_NAME)
  1901. );
  1902. return STATUS_INSUFFICIENT_RESOURCES;
  1903. }
  1904. status = IoCallDriver(
  1905. readerExtension->AttachedDeviceObject,
  1906. irp
  1907. );
  1908. if (status == STATUS_PENDING) {
  1909. KeWaitForSingleObject(
  1910. &event,
  1911. Suspended,
  1912. KernelMode,
  1913. FALSE,
  1914. NULL
  1915. );
  1916. //ASSERT (STATUS_SUCCESS == status);
  1917. status = ioStatus.Status;
  1918. }
  1919. SmartcardDebug(
  1920. DEBUG_INFO,
  1921. ( "%s!GCR410PStopSerialEventTracking: Exit\n",
  1922. SC_DRIVER_NAME)
  1923. );
  1924. return status;
  1925. }
  1926. VOID
  1927. GCR410PCompleteCardTracking(
  1928. IN PSMARTCARD_EXTENSION SmartcardExtension
  1929. )
  1930. {
  1931. KIRQL ioIrql, keIrql;
  1932. PIRP notificationIrp;
  1933. IoAcquireCancelSpinLock(&ioIrql);
  1934. KeAcquireSpinLock(
  1935. &SmartcardExtension->OsData->SpinLock,
  1936. &keIrql
  1937. );
  1938. notificationIrp = SmartcardExtension->OsData->NotificationIrp;
  1939. SmartcardExtension->OsData->NotificationIrp = NULL;
  1940. KeReleaseSpinLock(
  1941. &SmartcardExtension->OsData->SpinLock,
  1942. keIrql
  1943. );
  1944. if (notificationIrp) {
  1945. IoSetCancelRoutine(
  1946. notificationIrp,
  1947. NULL
  1948. );
  1949. }
  1950. IoReleaseCancelSpinLock(ioIrql);
  1951. if (notificationIrp) {
  1952. SmartcardDebug(
  1953. DEBUG_INFO,
  1954. ("%s!GCR410PCompleteCardTracking: Completing NotificationIrp %lxh\n",
  1955. DRIVER_NAME,
  1956. notificationIrp)
  1957. );
  1958. // finish the request
  1959. if (notificationIrp->Cancel) {
  1960. notificationIrp->IoStatus.Status = STATUS_CANCELLED;
  1961. } else {
  1962. notificationIrp->IoStatus.Status = STATUS_SUCCESS;
  1963. }
  1964. notificationIrp->IoStatus.Information = 0;
  1965. IoCompleteRequest(
  1966. notificationIrp,
  1967. IO_NO_INCREMENT
  1968. );
  1969. }
  1970. }
  1971. NTSTATUS
  1972. GCR410PSerialEvent(
  1973. IN PDEVICE_OBJECT DeviceObject,
  1974. IN PIRP Irp,
  1975. IN PSMARTCARD_EXTENSION SmartcardExtension
  1976. )
  1977. /*++
  1978. Routine Description:
  1979. This routine is called in two cases:
  1980. a) RING signaled (card inserted or removed)
  1981. b) DSR changed (reader has been removed)
  1982. For a) we update the card status and complete outstanding card tracking
  1983. requests.
  1984. For b) we start to unload the driver
  1985. This function calls itself using IoCompletion. In the 'first' callback
  1986. the serial driver only tells us that something has changed. We set up a
  1987. call for 'what has changed' (GetModemStatus) which then call this function
  1988. again.
  1989. When we updated everything and we don't unload the driver card tracking is
  1990. is started again.
  1991. Arguments:
  1992. Device Object - is a pointer on the current device object
  1993. Irp - is a pointer on the current irp.
  1994. SmartcardExtension - is a pointer on the SmartCardExtension structure of
  1995. the current device.
  1996. Return Value:
  1997. STATUS_MORE_PROCESSING_REQUIRED - we need more process to complet the request.
  1998. STATUS_SUCCESS - completed
  1999. --*/
  2000. {
  2001. NTSTATUS status;
  2002. SmartcardDebug(
  2003. DEBUG_TRACE,
  2004. ( "%s!GCR410PSerialEvent: Enter\n",
  2005. SC_DRIVER_NAME)
  2006. );
  2007. if (SmartcardExtension->ReaderExtension->GetModemStatus) {
  2008. SmartcardDebug(
  2009. DEBUG_TRACE,
  2010. ( "%s!GCR410PSerialEvent: Modem status=%X(hex)\n",
  2011. SC_DRIVER_NAME,
  2012. SmartcardExtension->ReaderExtension->ModemStatus)
  2013. );
  2014. if ((SmartcardExtension->ReaderExtension->ModemStatus & SERIAL_DSR_STATE) == 0) {
  2015. PDEVICE_EXTENSION deviceExtension;
  2016. SmartcardDebug(
  2017. DEBUG_INFO,
  2018. ( "%s!GCR410PSerialEvent: Reader removed\n",
  2019. SC_DRIVER_NAME)
  2020. );
  2021. deviceExtension = SmartcardExtension->OsData->DeviceObject->DeviceExtension;
  2022. // We set the mask to zero to signal that we can release the irp that
  2023. // we use for the serial events.
  2024. SmartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask = 0;
  2025. //ISV
  2026. SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN;
  2027. } else {
  2028. PDEVICE_EXTENSION deviceExtension=
  2029. SmartcardExtension->OsData->DeviceObject->DeviceExtension;
  2030. SmartcardDebug(
  2031. DEBUG_TRACE,
  2032. ( "%s!GCR410PSerialEvent: cardStateChange\n",
  2033. SC_DRIVER_NAME)
  2034. );
  2035. ASSERT(KeReadStateEvent(&deviceExtension->SerialCloseDone) == 0l);
  2036. if (KeReadStateEvent(&deviceExtension->CardStatusNotInUse) != 0L) {
  2037. // Informs that the card status update is running
  2038. KeClearEvent(&deviceExtension->CardStatusNotInUse);
  2039. // Schedule the card status thread
  2040. IoQueueWorkItem(
  2041. deviceExtension->CardStateChange,
  2042. (PIO_WORKITEM_ROUTINE) GCR410PWaitForCardStateChange,
  2043. CriticalWorkQueue,
  2044. NULL
  2045. );
  2046. }
  2047. }
  2048. }
  2049. // If the reader is disconnected
  2050. if (SmartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask == 0) {
  2051. PDEVICE_EXTENSION deviceExtension=
  2052. SmartcardExtension->OsData->DeviceObject->DeviceExtension;
  2053. ASSERT(KeReadStateEvent(&deviceExtension->SerialCloseDone) == 0l);
  2054. //Schedule our remove thread
  2055. IoQueueWorkItem(
  2056. deviceExtension->CloseSerial,
  2057. (PIO_WORKITEM_ROUTINE) GCR410PCloseSerialPort,
  2058. CriticalWorkQueue,
  2059. NULL
  2060. );
  2061. SmartcardDebug(
  2062. DEBUG_INFO,
  2063. ( "%s!GCR410PSerialEvent: Exit (release IRP)\n",
  2064. SC_DRIVER_NAME)
  2065. );
  2066. //
  2067. // We don't need the IRP anymore, so free it and tell the
  2068. // io subsystem not to touch it anymore by returning the value below
  2069. //
  2070. IoFreeIrp(Irp);
  2071. return STATUS_MORE_PROCESSING_REQUIRED;
  2072. }
  2073. if (SmartcardExtension->ReaderExtension->GetModemStatus == FALSE) {
  2074. //
  2075. // Setup call for device control to get modem status.
  2076. //
  2077. PIO_STACK_LOCATION irpStack;
  2078. irpStack = IoGetNextIrpStackLocation(
  2079. SmartcardExtension->ReaderExtension->SerialStatusIrp
  2080. );
  2081. irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  2082. irpStack->MinorFunction = 0UL;
  2083. irpStack->Parameters.DeviceIoControl.OutputBufferLength =
  2084. sizeof(SmartcardExtension->ReaderExtension->ModemStatus);
  2085. irpStack->Parameters.DeviceIoControl.IoControlCode =
  2086. IOCTL_SERIAL_GET_MODEMSTATUS;
  2087. SmartcardExtension->ReaderExtension->SerialStatusIrp->AssociatedIrp.SystemBuffer =
  2088. &SmartcardExtension->ReaderExtension->ModemStatus;
  2089. SmartcardExtension->ReaderExtension->GetModemStatus = TRUE;
  2090. } else {
  2091. PIO_STACK_LOCATION irpStack;
  2092. // Setup call for device control to wait for a serial event
  2093. irpStack = IoGetNextIrpStackLocation(
  2094. SmartcardExtension->ReaderExtension->SerialStatusIrp
  2095. );
  2096. irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  2097. irpStack->MinorFunction = 0UL;
  2098. irpStack->Parameters.DeviceIoControl.OutputBufferLength =
  2099. sizeof(SmartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask);
  2100. irpStack->Parameters.DeviceIoControl.IoControlCode =
  2101. IOCTL_SERIAL_WAIT_ON_MASK;
  2102. SmartcardExtension->ReaderExtension->SerialStatusIrp->AssociatedIrp.SystemBuffer =
  2103. &SmartcardExtension->ReaderExtension->SerialConfigData.SerialWaitMask;
  2104. SmartcardExtension->ReaderExtension->GetModemStatus = FALSE;
  2105. }
  2106. IoSetCompletionRoutine(
  2107. SmartcardExtension->ReaderExtension->SerialStatusIrp,
  2108. GCR410PSerialEvent,
  2109. SmartcardExtension,
  2110. TRUE,
  2111. TRUE,
  2112. TRUE
  2113. );
  2114. status = IoCallDriver(
  2115. SmartcardExtension->ReaderExtension->AttachedDeviceObject,
  2116. SmartcardExtension->ReaderExtension->SerialStatusIrp
  2117. );
  2118. return STATUS_MORE_PROCESSING_REQUIRED;
  2119. }