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.

1249 lines
43 KiB

  1. /*****************************************************************************
  2. @doc INT EXT
  3. ******************************************************************************
  4. * $ProjectName: $
  5. * $ProjectRevision: $
  6. *-----------------------------------------------------------------------------
  7. * $Source: z:/pr/cmbp0/sw/cmbp0.ms/rcs/cmbp0pnp.c $
  8. * $Revision: 1.4 $
  9. *-----------------------------------------------------------------------------
  10. * $Author: TBruendl $
  11. *-----------------------------------------------------------------------------
  12. * History: see EOF
  13. *-----------------------------------------------------------------------------
  14. *
  15. * Copyright 2000 OMNIKEY AG
  16. ******************************************************************************/
  17. #include <cmbp0wdm.h>
  18. #include <cmbp0pnp.h>
  19. #include <cmbp0scr.h>
  20. #include <cmbp0log.h>
  21. #ifndef NT4
  22. /*****************************************************************************
  23. Routine Description:
  24. ???
  25. Arguments:
  26. Return Value:
  27. ******************************************************************************/
  28. NTSTATUS CMMOB_AddDevice(
  29. IN PDRIVER_OBJECT DriverObject,
  30. IN PDEVICE_OBJECT PhysicalDeviceObject
  31. )
  32. {
  33. NTSTATUS NTStatus;
  34. PDEVICE_OBJECT DeviceObject = NULL;
  35. SmartcardDebug(DEBUG_TRACE,
  36. ("%s!AddDevice: Enter\n",DRIVER_NAME));
  37. try
  38. {
  39. PDEVICE_EXTENSION DeviceExtension;
  40. NTStatus = CMMOB_CreateDevice(DriverObject, PhysicalDeviceObject, &DeviceObject);
  41. if (NTStatus != STATUS_SUCCESS)
  42. {
  43. leave;
  44. }
  45. DeviceExtension = DeviceObject->DeviceExtension;
  46. DeviceExtension->AttachedDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject,
  47. PhysicalDeviceObject);
  48. if (DeviceExtension->AttachedDeviceObject == NULL)
  49. {
  50. NTStatus = STATUS_UNSUCCESSFUL;
  51. leave;
  52. }
  53. DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  54. /*
  55. // This is not used in this driver, this is only to learn more
  56. // about powermanagment via debug outputs
  57. //
  58. // Get a copy of the physical device's capabilities into a
  59. // DEVICE_CAPABILITIES struct in our device extension;
  60. // We are most interested in learning which system power states
  61. // are to be mapped to which device power states for handling
  62. // IRP_MJ_SET_POWER Irps.
  63. //
  64. NTStatus = CMMOB_QueryCapabilities(DeviceExtension->AttachedDeviceObject, &DeviceExtension->DeviceCapabilities);
  65. if (NTStatus != STATUS_SUCCESS)
  66. {
  67. leave;
  68. }
  69. */
  70. }
  71. finally
  72. {
  73. if (NTStatus != STATUS_SUCCESS)
  74. {
  75. CMMOB_UnloadDevice(DeviceObject);
  76. }
  77. }
  78. SmartcardDebug(DEBUG_TRACE,
  79. ("%s!AddDevice: Exit %x\n",DRIVER_NAME,NTStatus));
  80. return NTStatus;
  81. }
  82. /*****************************************************************************
  83. Routine Description:
  84. This routine generates an internal IRP from this driver to the PDO
  85. to obtain information on the Physical Device Object's capabilities.
  86. We are most interested in learning which system power states
  87. are to be mapped to which device power states for honoring IRP_MJ_SET_POWER Irps.
  88. This is a blocking call which waits for the IRP completion routine
  89. to set an event on finishing.
  90. Arguments:
  91. DeviceObject - Physical DeviceObject for this USB controller.
  92. Return Value:
  93. NTSTATUS value from the IoCallDriver() call.
  94. *****************************************************************************/
  95. NTSTATUS CMMOB_QueryCapabilities(
  96. IN PDEVICE_OBJECT AttachedDeviceObject,
  97. IN PDEVICE_CAPABILITIES DeviceCapabilities
  98. )
  99. {
  100. NTSTATUS NTStatus;
  101. PIO_STACK_LOCATION IrpStack;
  102. PIRP Irp;
  103. // This is a DDK-defined DBG-only macro that ASSERTS we are not running pageable code
  104. // at higher than APC_LEVEL.
  105. PAGED_CODE();
  106. // Build an IRP for us to generate an internal query request to the PDO
  107. Irp = IoAllocateIrp(AttachedDeviceObject->StackSize, FALSE);
  108. if (Irp == NULL)
  109. {
  110. return STATUS_INSUFFICIENT_RESOURCES;
  111. }
  112. //
  113. // Preinit the device capability structures appropriately.
  114. //
  115. RtlZeroMemory( DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
  116. DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
  117. DeviceCapabilities->Version = 1;
  118. DeviceCapabilities->Address = -1;
  119. DeviceCapabilities->UINumber = -1;
  120. // IoGetNextIrpStackLocation gives a higher level driver access to the next-lower
  121. // driver's I/O stack location in an IRP so the caller can set it up for the lower driver.
  122. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  123. ASSERT (IrpStack != NULL);
  124. // Set parameters for query capabilities
  125. IrpStack->MajorFunction= IRP_MJ_PNP;
  126. IrpStack->MinorFunction= IRP_MN_QUERY_CAPABILITIES;
  127. // Set our pointer to the DEVICE_CAPABILITIES struct
  128. IrpStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
  129. // preset the irp to report not supported
  130. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  131. // Call the PCMCIA driver
  132. NTStatus = CMMOB_CallPcmciaDriver (AttachedDeviceObject, Irp);
  133. // Free allocated IRP
  134. IoFreeIrp(Irp);
  135. return NTStatus;
  136. }
  137. /*****************************************************************************
  138. Routine Description:
  139. Send an Irp to the pcmcia driver and wait until the pcmcia driver has
  140. finished the request.
  141. To make sure that the pcmcia driver will not complete the Irp we first
  142. initialize an event and set our own completion routine for the Irp.
  143. When the pcmcia driver has processed the Irp the completion routine will
  144. set the event and tell the IO manager that more processing is required.
  145. By waiting for the event we make sure that we continue only if the pcmcia
  146. driver has processed the Irp completely.
  147. Arguments:
  148. DeviceObject context of call
  149. Irp Irp to send to the pcmcia driver
  150. Return Value:
  151. NTStatus returned by the pcmcia driver
  152. ******************************************************************************/
  153. NTSTATUS CMMOB_CallPcmciaDriver(
  154. IN PDEVICE_OBJECT AttachedDeviceObject,
  155. IN PIRP Irp
  156. )
  157. {
  158. NTSTATUS NTStatus = STATUS_SUCCESS;
  159. PIO_STACK_LOCATION IrpStack, IrpNextStack;
  160. KEVENT Event;
  161. /*
  162. SmartcardDebug(DEBUG_TRACE,
  163. ("%s!CMMOB_CallPcmciaDriver: Enter\n",DRIVER_NAME ));
  164. */
  165. //
  166. // Prepare everything to call the underlying driver
  167. //
  168. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  169. IrpNextStack = IoGetNextIrpStackLocation(Irp);
  170. //
  171. // Copy our stack to the next stack location.
  172. //
  173. *IrpNextStack = *IrpStack;
  174. //
  175. // initialize an event for process synchronization. the event is passed
  176. // to our completion routine and will be set if the pcmcia driver is done
  177. //
  178. KeInitializeEvent(&Event,
  179. NotificationEvent,
  180. FALSE);
  181. //
  182. // Our IoCompletionRoutine sets only our event
  183. //
  184. IoSetCompletionRoutine (Irp,
  185. CMMOB_PcmciaCallComplete,
  186. &Event,
  187. TRUE,
  188. TRUE,
  189. TRUE);
  190. //
  191. // Call the pcmcia driver
  192. //
  193. if (IrpStack->MajorFunction == IRP_MJ_POWER)
  194. {
  195. NTStatus = PoCallDriver(AttachedDeviceObject,Irp);
  196. }
  197. else
  198. {
  199. NTStatus = IoCallDriver(AttachedDeviceObject,Irp);
  200. }
  201. //
  202. // Wait until the pcmcia driver has processed the Irp
  203. //
  204. if (NTStatus == STATUS_PENDING)
  205. {
  206. NTStatus = KeWaitForSingleObject(&Event,
  207. Executive,
  208. KernelMode,
  209. FALSE,
  210. NULL);
  211. if (NTStatus == STATUS_SUCCESS)
  212. {
  213. NTStatus = Irp->IoStatus.Status;
  214. }
  215. }
  216. /*
  217. SmartcardDebug(DEBUG_TRACE,
  218. ("%s!CMMOB_CallPcmciaDriver: Exit %x\n",DRIVER_NAME,NTStatus));
  219. */
  220. return NTStatus;
  221. }
  222. /*****************************************************************************
  223. Routine Description:
  224. Completion routine for an Irp sent to the pcmcia driver. The event will
  225. be set to notify that the pcmcia driver is done. The routine will not
  226. 'complete' the Irp, so the caller of CMMOB_CallPcmciaDriver can continue.
  227. Arguments:
  228. DeviceObject context of call
  229. Irp Irp to complete
  230. Event Used by CMMOB_CallPcmciaDriver for process synchronization
  231. Return Value:
  232. STATUS_CANCELLED Irp was cancelled by the IO manager
  233. STATUS_MORE_PROCESSING_REQUIRED Irp will be finished by caller of
  234. CMMOB_CallPcmciaDriver
  235. ******************************************************************************/
  236. NTSTATUS CMMOB_PcmciaCallComplete (
  237. IN PDEVICE_OBJECT DeviceObject,
  238. IN PIRP Irp,
  239. IN PKEVENT Event
  240. )
  241. {
  242. UNREFERENCED_PARAMETER (DeviceObject);
  243. if (Irp->Cancel)
  244. {
  245. Irp->IoStatus.Status = STATUS_CANCELLED;
  246. }
  247. KeSetEvent (Event, 0, FALSE);
  248. return STATUS_MORE_PROCESSING_REQUIRED;
  249. }
  250. /*****************************************************************************
  251. Routine Description:
  252. driver callback for pnp manager
  253. Request: Action:
  254. IRP_MN_START_DEVICE Notify the pcmcia driver about the new device
  255. and start the device
  256. IRP_MN_STOP_DEVICE Free all resources used by the device and tell
  257. the pcmcia driver that the device was stopped
  258. IRP_MN_QUERY_REMOVE_DEVICE If the device is opened (i.e. in use) an error will
  259. be returned to prevent the PnP manager to stop
  260. the driver
  261. IRP_MN_CANCEL_REMOVE_DEVICE just notify that we can continue without any
  262. restrictions
  263. IRP_MN_REMOVE_DEVICE notify the pcmcia driver that the device was
  264. removed, stop & unload the device
  265. All other requests will be passed to the pcmcia driver to ensure correct processing.
  266. Arguments:
  267. Device Object context of call
  268. Irp irp from the PnP manager
  269. Return Value:
  270. STATUS_SUCCESS
  271. STATUS_UNSUCCESSFUL
  272. NTStatus returned by pcmcia driver
  273. ******************************************************************************/
  274. NTSTATUS CMMOB_PnPDeviceControl(
  275. IN PDEVICE_OBJECT DeviceObject,
  276. IN PIRP Irp
  277. )
  278. {
  279. NTSTATUS NTStatus = STATUS_SUCCESS;
  280. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  281. PIO_STACK_LOCATION IrpStack;
  282. PDEVICE_OBJECT AttachedDeviceObject;
  283. PDEVICE_CAPABILITIES DeviceCapabilities;
  284. KIRQL irql;
  285. LONG i;
  286. BOOLEAN irpSkipped = FALSE;
  287. SmartcardDebug(DEBUG_TRACE,
  288. ("%s!PnPDeviceControl: Enter\n",DRIVER_NAME ));
  289. NTStatus = SmartcardAcquireRemoveLock(&DeviceExtension->SmartcardExtension);
  290. ASSERT(NTStatus == STATUS_SUCCESS);
  291. if (NTStatus != STATUS_SUCCESS)
  292. {
  293. Irp->IoStatus.Information = 0;
  294. Irp->IoStatus.Status = NTStatus;
  295. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  296. return NTStatus;
  297. }
  298. AttachedDeviceObject = DeviceExtension->AttachedDeviceObject;
  299. // Irp->IoStatus.Information = 0;
  300. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  301. //
  302. // Now look what the PnP manager wants...
  303. //
  304. #ifdef DBG
  305. if (IrpStack->MinorFunction <= IRP_PNP_MN_FUNC_MAX)
  306. {
  307. SmartcardDebug(DEBUG_DRIVER,
  308. ("%s!PnPDeviceControl: %s received\n",DRIVER_NAME,
  309. szPnpMnFuncDesc[IrpStack->MinorFunction] ));
  310. }
  311. #endif
  312. switch (IrpStack->MinorFunction)
  313. {
  314. case IRP_MN_START_DEVICE:
  315. //
  316. // We have to call the underlying driver first
  317. //
  318. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject,Irp);
  319. if (NT_SUCCESS(NTStatus))
  320. {
  321. //
  322. // Now we should connect to our resources (Irql, Io etc.)
  323. //
  324. NTStatus = CMMOB_StartDevice(DeviceObject,
  325. &IrpStack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0]);
  326. }
  327. break;
  328. case IRP_MN_QUERY_STOP_DEVICE:
  329. KeAcquireSpinLock(&DeviceExtension->SpinLockIoCount, &irql);
  330. if (DeviceExtension->lIoCount > 0)
  331. {
  332. // we refuse to stop if we have pending io
  333. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  334. NTStatus = STATUS_DEVICE_BUSY;
  335. }
  336. else
  337. {
  338. // stop processing requests
  339. KeClearEvent(&DeviceExtension->ReaderStarted);
  340. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  341. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  342. }
  343. break;
  344. case IRP_MN_CANCEL_STOP_DEVICE:
  345. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  346. ASSERT(NTStatus == STATUS_SUCCESS);
  347. // we can continue to process requests
  348. DeviceExtension->lIoCount = 0;
  349. KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
  350. break;
  351. case IRP_MN_STOP_DEVICE:
  352. //
  353. // Stop the device. Aka disconnect from our resources
  354. //
  355. CMMOB_StopDevice(DeviceObject);
  356. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  357. break;
  358. case IRP_MN_QUERY_REMOVE_DEVICE:
  359. //
  360. // Remove our device
  361. //
  362. if (DeviceExtension->lOpenCount > 0)
  363. {
  364. NTStatus = STATUS_UNSUCCESSFUL;
  365. }
  366. else
  367. {
  368. if (DeviceExtension->OSVersion == OS_Windows2000)
  369. {
  370. NTStatus = IoSetDeviceInterfaceState(&DeviceExtension->PnPDeviceName,
  371. FALSE);
  372. ASSERT(NTStatus == STATUS_SUCCESS);
  373. if (NTStatus != STATUS_SUCCESS)
  374. {
  375. break;
  376. }
  377. }
  378. DeviceExtension->fRemovePending = TRUE;
  379. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  380. }
  381. break;
  382. case IRP_MN_CANCEL_REMOVE_DEVICE:
  383. //
  384. // Removal of device has been cancelled
  385. //
  386. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  387. if (NTStatus == STATUS_SUCCESS)
  388. {
  389. if (DeviceExtension->OSVersion == OS_Windows2000)
  390. {
  391. NTStatus = IoSetDeviceInterfaceState(&DeviceExtension->PnPDeviceName,
  392. TRUE);
  393. }
  394. }
  395. ASSERT(NTStatus == STATUS_SUCCESS);
  396. DeviceExtension->fRemovePending = FALSE;
  397. break;
  398. case IRP_MN_REMOVE_DEVICE:
  399. //
  400. // Remove our device
  401. //
  402. DeviceExtension->fRemovePending = TRUE;
  403. CMMOB_StopDevice(DeviceObject);
  404. CMMOB_UnloadDevice(DeviceObject);
  405. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  406. // this is set in CMMOB_UnloadDevice
  407. // DeviceExtension->fDeviceRemoved = TRUE;
  408. break;
  409. case IRP_MN_QUERY_CAPABILITIES:
  410. //
  411. // Query device capabilities
  412. //
  413. //
  414. // Get the packet.
  415. //
  416. DeviceCapabilities=IrpStack->Parameters.DeviceCapabilities.Capabilities;
  417. if (DeviceCapabilities->Version < 1 ||
  418. DeviceCapabilities->Size < sizeof(DEVICE_CAPABILITIES))
  419. {
  420. //
  421. // We don't support this version. Fail the requests
  422. //
  423. NTStatus = STATUS_UNSUCCESSFUL;
  424. break;
  425. }
  426. //
  427. // Set the capabilities.
  428. //
  429. // We cannot wake the system.
  430. DeviceCapabilities->SystemWake = PowerSystemUnspecified;
  431. DeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
  432. // We have no latencies
  433. DeviceCapabilities->D1Latency = 0;
  434. DeviceCapabilities->D2Latency = 0;
  435. DeviceCapabilities->D3Latency = 0;
  436. // No locking or ejection
  437. DeviceCapabilities->LockSupported = FALSE;
  438. DeviceCapabilities->EjectSupported = FALSE;
  439. // Device can be physically removed.
  440. DeviceCapabilities->Removable = TRUE;
  441. // No docking device
  442. DeviceCapabilities->DockDevice = FALSE;
  443. // Device can not be removed any time
  444. // it has a removable media
  445. DeviceCapabilities->SurpriseRemovalOK = FALSE;
  446. //
  447. // Call the next lower driver
  448. //
  449. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  450. //
  451. // Now look at the relation system state / device state
  452. //
  453. {
  454. SmartcardDebug( DEBUG_DRIVER,
  455. ("%s!PnPDeviceControl: systemstate to devicestate mapping\n",DRIVER_NAME ));
  456. for (i=1; i<PowerSystemMaximum; i++)
  457. {
  458. SmartcardDebug(DEBUG_DRIVER,
  459. ("%s!PnPDeviceControl: %s -> %s\n",DRIVER_NAME,
  460. szSystemPowerState[i],szDevicePowerState[DeviceCapabilities->DeviceState[i]] ));
  461. if (DeviceCapabilities->DeviceState[i] != PowerDeviceD3 &&
  462. (DeviceCapabilities->DeviceState[i] != PowerDeviceD0 ||
  463. i >= PowerSystemSleeping3))
  464. {
  465. DeviceCapabilities->DeviceState[i]=PowerDeviceD3;
  466. SmartcardDebug(DEBUG_DRIVER,
  467. ("%s!PnPDeviceControl: altered to %s -> %s\n",DRIVER_NAME,
  468. szSystemPowerState[i],szDevicePowerState[DeviceCapabilities->DeviceState[i]] ));
  469. }
  470. }
  471. }
  472. // Store DeviceCapabilities in our DeviceExtension for later use
  473. RtlCopyMemory(&DeviceExtension->DeviceCapabilities,DeviceCapabilities,
  474. sizeof(DeviceExtension->DeviceCapabilities));
  475. break;
  476. case IRP_MN_QUERY_DEVICE_RELATIONS:
  477. //
  478. // Query device relations
  479. //
  480. SmartcardDebug(DEBUG_DRIVER,
  481. ("%s!PnPDeviceControl: Requested relation = %s\n",DRIVER_NAME,
  482. szDeviceRelation[IrpStack->Parameters.QueryDeviceRelations.Type] ));
  483. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  484. irpSkipped = TRUE;
  485. break;
  486. default:
  487. //
  488. // This might be an Irp that is only useful
  489. // for the underlying bus driver
  490. //
  491. NTStatus = CMMOB_CallPcmciaDriver(AttachedDeviceObject, Irp);
  492. irpSkipped = TRUE;
  493. break;
  494. }
  495. if(!irpSkipped) {
  496. Irp->IoStatus.Status = NTStatus;
  497. }
  498. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  499. if (DeviceExtension->fDeviceRemoved == FALSE)
  500. {
  501. SmartcardReleaseRemoveLock(&DeviceExtension->SmartcardExtension);
  502. }
  503. SmartcardDebug(DEBUG_TRACE,
  504. ( "%s!PnPDeviceControl: Exit %x\n",DRIVER_NAME,NTStatus));
  505. return NTStatus;
  506. }
  507. /*****************************************************************************
  508. Routine Description:
  509. This function is called when the underlying stacks
  510. completed the power transition.
  511. ******************************************************************************/
  512. VOID CMMOB_SystemPowerCompletion(
  513. IN PDEVICE_OBJECT DeviceObject,
  514. IN UCHAR MinorFunction,
  515. IN POWER_STATE PowerState,
  516. IN PKEVENT Event,
  517. IN PIO_STATUS_BLOCK IoStatus
  518. )
  519. {
  520. UNREFERENCED_PARAMETER (DeviceObject);
  521. UNREFERENCED_PARAMETER (MinorFunction);
  522. UNREFERENCED_PARAMETER (PowerState);
  523. SmartcardDebug(DEBUG_TRACE,
  524. ("%s!SystemPowerCompletion: Enter\n",DRIVER_NAME));
  525. SmartcardDebug(DEBUG_DRIVER,
  526. ("%s!SystemPowerCompletion: Status of completed IRP = %x\n",DRIVER_NAME,IoStatus->Status));
  527. KeSetEvent(Event, 0, FALSE);
  528. SmartcardDebug(DEBUG_TRACE,
  529. ("%s!SystemPowerCompletion: Exit\n",DRIVER_NAME));
  530. }
  531. /*****************************************************************************
  532. Routine Description:
  533. This routine is called after the underlying stack powered
  534. UP the serial port, so it can be used again.
  535. ******************************************************************************/
  536. NTSTATUS CMMOB_DevicePowerCompletion (
  537. IN PDEVICE_OBJECT DeviceObject,
  538. IN PIRP Irp,
  539. IN PSMARTCARD_EXTENSION SmartcardExtension
  540. )
  541. {
  542. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  543. PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
  544. NTSTATUS NTStatus;
  545. UCHAR state;
  546. SmartcardDebug(DEBUG_TRACE,
  547. ("%s!DevicePowerCompletion: Enter\n",DRIVER_NAME));
  548. SmartcardDebug(DEBUG_DRIVER,
  549. ("%s!DevicePowerCompletion: IRQL %i\n",DRIVER_NAME,KeGetCurrentIrql()));
  550. //
  551. // If a card was present before power down or now there is
  552. // a card in the reader, we complete any pending card monitor
  553. // request, since we do not really know what card is now in the
  554. // reader.
  555. //
  556. if (SmartcardExtension->ReaderExtension->fCardPresent ||
  557. SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT)
  558. {
  559. SmartcardExtension->ReaderExtension->ulOldCardState = UNKNOWN;
  560. SmartcardExtension->ReaderExtension->ulNewCardState = UNKNOWN;
  561. }
  562. KeSetEvent(&DeviceExtension->CanRunUpdateThread, 0, FALSE);
  563. // save the current power state of the reader
  564. SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderWorking;
  565. SmartcardReleaseRemoveLock(SmartcardExtension);
  566. // inform the power manager of our state.
  567. PoSetPowerState (DeviceObject,
  568. DevicePowerState,
  569. IrpStack->Parameters.Power.State);
  570. SmartcardDebug( DEBUG_DRIVER,
  571. ("%s!DevicePowerCompletion: called PoSetPowerState with %s\n",DRIVER_NAME,
  572. szDevicePowerState[IrpStack->Parameters.Power.State.DeviceState] ));
  573. PoStartNextPowerIrp(Irp);
  574. // signal that we can process ioctls again
  575. DeviceExtension->lIoCount = 0;
  576. KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
  577. SmartcardDebug(DEBUG_TRACE,
  578. ("%s!DevicePowerCompletion: Exit\n",DRIVER_NAME));
  579. return STATUS_SUCCESS;
  580. }
  581. typedef enum _ACTION
  582. {
  583. Undefined = 0,
  584. SkipRequest,
  585. WaitForCompletion,
  586. CompleteRequest,
  587. MarkPending
  588. } ACTION;
  589. /*****************************************************************************
  590. Routine Description:
  591. The power dispatch routine.
  592. This driver is the power policy owner of the device stack,
  593. because this driver knows about the connected reader.
  594. Therefor this driver will translate system power states
  595. to device power states.
  596. Arguments:
  597. DeviceObject - pointer to a device object.
  598. Irp - pointer to an I/O Request Packet.
  599. Return Value:
  600. NT NTStatus code
  601. ******************************************************************************/
  602. NTSTATUS CMMOB_PowerDeviceControl (
  603. IN PDEVICE_OBJECT DeviceObject,
  604. IN PIRP Irp
  605. )
  606. {
  607. NTSTATUS NTStatus = STATUS_SUCCESS;
  608. PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
  609. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  610. PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension;
  611. POWER_STATE DesiredPowerState;
  612. KIRQL irql;
  613. ACTION action;
  614. KEVENT event;
  615. SmartcardDebug(DEBUG_TRACE,
  616. ( "%s!PowerDeviceControl: Enter\n",DRIVER_NAME));
  617. SmartcardDebug(DEBUG_DRIVER,
  618. ( "%s!PowerDeviceControl: IRQL %i\n",DRIVER_NAME,KeGetCurrentIrql()));
  619. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  620. NTStatus = SmartcardAcquireRemoveLock(SmartcardExtension);
  621. ASSERT(NTStatus == STATUS_SUCCESS);
  622. if (NTStatus!=STATUS_SUCCESS)
  623. {
  624. Irp->IoStatus.Status = NTStatus;
  625. Irp->IoStatus.Information = 0;
  626. PoStartNextPowerIrp(Irp);
  627. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  628. return NTStatus;
  629. }
  630. ASSERT(SmartcardExtension->ReaderExtension->ReaderPowerState !=
  631. PowerReaderUnspecified);
  632. #ifdef DBG
  633. if (IrpStack->MinorFunction <= IRP_POWER_MN_FUNC_MAX)
  634. {
  635. SmartcardDebug(DEBUG_DRIVER,
  636. ("%s!PowerDeviceControl: %s received\n",DRIVER_NAME,
  637. szPowerMnFuncDesc[IrpStack->MinorFunction] ));
  638. }
  639. #endif
  640. switch (IrpStack->MinorFunction)
  641. {
  642. // ------------------
  643. // IRP_MN_QUERY_POWER
  644. // ------------------
  645. case IRP_MN_QUERY_POWER:
  646. //
  647. // A power policy manager sends this IRP to determine whether it can change
  648. // the system or device power state, typically to go to sleep.
  649. //
  650. switch (IrpStack->Parameters.Power.Type)
  651. {
  652. // +++++++++++++++++++
  653. // SystemPowerState
  654. // +++++++++++++++++++
  655. case SystemPowerState:
  656. SmartcardDebug( DEBUG_DRIVER,
  657. ("%s!PowerDeviceControl: SystemPowerState = %s\n",DRIVER_NAME,
  658. szSystemPowerState [IrpStack->Parameters.Power.State.SystemState] ));
  659. switch (IrpStack->Parameters.Power.State.SystemState)
  660. {
  661. case PowerSystemWorking:
  662. action = SkipRequest;
  663. break;
  664. case PowerSystemSleeping1:
  665. case PowerSystemSleeping2:
  666. case PowerSystemSleeping3:
  667. case PowerSystemHibernate:
  668. if (DeviceExtension->OSVersion == OS_Windows98 ||
  669. DeviceExtension->OSVersion == OS_Windows95 ||
  670. DeviceExtension->OSVersion == OS_Unspecified )
  671. {
  672. // can't go to sleep mode since with this OSs
  673. // the reader doesn't work any more after wakeup.
  674. NTStatus = STATUS_UNSUCCESSFUL;
  675. action = CompleteRequest;
  676. }
  677. else
  678. {
  679. KeAcquireSpinLock(&DeviceExtension->SpinLockIoCount, &irql);
  680. if (DeviceExtension->lIoCount == 0)
  681. {
  682. // Block any further ioctls
  683. KeClearEvent(&DeviceExtension->ReaderStarted);
  684. action = SkipRequest;
  685. }
  686. else
  687. {
  688. // can't go to sleep mode since the reader is busy.
  689. NTStatus = STATUS_DEVICE_BUSY;
  690. action = CompleteRequest;
  691. }
  692. KeReleaseSpinLock(&DeviceExtension->SpinLockIoCount, irql);
  693. }
  694. break;
  695. case PowerSystemShutdown:
  696. action = SkipRequest;
  697. break;
  698. }
  699. break;
  700. // ++++++++++++++++++
  701. // DevicePowerState
  702. // ++++++++++++++++++
  703. case DevicePowerState:
  704. // For requests to D1, D2, or D3 ( sleep or off states ),
  705. // sets DeviceExtension->CurrentDevicePowerState to DeviceState immediately.
  706. // This enables any code checking state to consider us as sleeping or off
  707. // already, as this will imminently become our state.
  708. SmartcardDebug(DEBUG_DRIVER,
  709. ("%s!PowerDeviceControl: DevicePowerState = %s\n",DRIVER_NAME,
  710. szDevicePowerState[IrpStack->Parameters.Power.State.DeviceState] ));
  711. action = SkipRequest;
  712. break;
  713. }
  714. break; /* IRP_MN_QUERY_POWER */
  715. // ------------------
  716. // IRP_MN_SET_POWER
  717. // ------------------
  718. case IRP_MN_SET_POWER:
  719. // The system power policy manager sends this IRP to set the system power state.
  720. // A device power policy manager sends this IRP to set the device power state for a device.
  721. // Set Irp->IoStatus.Status to STATUS_SUCCESS to indicate that the device
  722. // has entered the requested state. Drivers cannot fail this IRP.
  723. ASSERT(SmartcardExtension->ReaderExtension->ReaderPowerState != PowerReaderUnspecified);
  724. switch (IrpStack->Parameters.Power.Type)
  725. {
  726. // +++++++++++++++++++
  727. // SystemPowerState
  728. // +++++++++++++++++++
  729. case SystemPowerState:
  730. // Get input system power state
  731. SmartcardDebug( DEBUG_DRIVER,
  732. ("%s!PowerDeviceControl: SystemPowerState = %s\n",DRIVER_NAME,
  733. szSystemPowerState[IrpStack->Parameters.Power.State.SystemState] ));
  734. // determine desired device powerstate
  735. DesiredPowerState.DeviceState=DeviceExtension->DeviceCapabilities.DeviceState[IrpStack->Parameters.Power.State.SystemState];
  736. SmartcardDebug( DEBUG_DRIVER,
  737. ("%s!PowerDeviceControl: DesiredDevicePowerState = %s\n",DRIVER_NAME,
  738. szDevicePowerState[DesiredPowerState.DeviceState] ));
  739. switch (DesiredPowerState.DeviceState)
  740. {
  741. case PowerDeviceD0:
  742. if (SmartcardExtension->ReaderExtension->ReaderPowerState == PowerReaderWorking)
  743. {
  744. // We're already in the right state
  745. KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
  746. action = SkipRequest;
  747. break;
  748. }
  749. // wake up the underlying stack...
  750. action = MarkPending;
  751. SmartcardDebug( DEBUG_DRIVER,
  752. ("%s!PowerDeviceControl: setting DevicePowerState = %s\n",DRIVER_NAME,
  753. szDevicePowerState[DesiredPowerState.DeviceState] ));
  754. break;
  755. case PowerDeviceD1:
  756. case PowerDeviceD2:
  757. case PowerDeviceD3:
  758. DesiredPowerState.DeviceState = PowerDeviceD3;
  759. if (SmartcardExtension->ReaderExtension->ReaderPowerState == PowerReaderOff)
  760. {
  761. // We're already in the right state
  762. KeClearEvent(&DeviceExtension->ReaderStarted);
  763. action = SkipRequest;
  764. break;
  765. }
  766. action = MarkPending;
  767. SmartcardDebug( DEBUG_DRIVER,
  768. ("%s!PowerDeviceControl: setting DevicePowerState = %s\n",DRIVER_NAME,
  769. szDevicePowerState[DesiredPowerState.DeviceState] ));
  770. break;
  771. default:
  772. action = SkipRequest;
  773. break;
  774. }
  775. break;
  776. // ++++++++++++++++++
  777. // DevicePowerState
  778. // ++++++++++++++++++
  779. case DevicePowerState:
  780. SmartcardDebug(DEBUG_DRIVER,
  781. ("%s!PowerDeviceControl: DevicePowerState = %s\n",DRIVER_NAME,
  782. szDevicePowerState[IrpStack->Parameters.Power.State.DeviceState] ));
  783. switch (IrpStack->Parameters.Power.State.DeviceState)
  784. {
  785. case PowerDeviceD0:
  786. // Turn on the reader
  787. SmartcardDebug(DEBUG_DRIVER,
  788. ("%s!PowerDeviceControl: PowerDevice D0\n",DRIVER_NAME));
  789. //
  790. // start update thread be signal that it should not run now
  791. // this thread should be started in completion rourine
  792. // but there we have a wrong IRQL for creating a thread
  793. //
  794. KeClearEvent(&DeviceExtension->CanRunUpdateThread);
  795. NTStatus = CMMOB_StartCardTracking(DeviceObject);
  796. if (NTStatus != STATUS_SUCCESS)
  797. {
  798. SmartcardDebug(DEBUG_ERROR,
  799. ("%s!StartCardTracking failed ! %lx\n",DRIVER_NAME,NTStatus));
  800. }
  801. //
  802. // First, we send down the request to the bus, in order
  803. // to power on the port. When the request completes,
  804. // we turn on the reader
  805. //
  806. IoCopyCurrentIrpStackLocationToNext(Irp);
  807. IoSetCompletionRoutine (Irp,
  808. CMMOB_DevicePowerCompletion,
  809. SmartcardExtension,
  810. TRUE,
  811. TRUE,
  812. TRUE);
  813. action = WaitForCompletion;
  814. break;
  815. case PowerDeviceD1:
  816. case PowerDeviceD2:
  817. case PowerDeviceD3:
  818. // Turn off the reader
  819. SmartcardDebug(DEBUG_DRIVER,
  820. ("%s!PowerDeviceControl: PowerDevice D3\n",DRIVER_NAME));
  821. PoSetPowerState (DeviceObject,
  822. DevicePowerState,
  823. IrpStack->Parameters.Power.State);
  824. // Block any further ioctls
  825. KeClearEvent(&DeviceExtension->ReaderStarted);
  826. // stop the update thread
  827. CMMOB_StopCardTracking(DeviceObject);
  828. // save the current card state
  829. SmartcardExtension->ReaderExtension->fCardPresent =
  830. SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT;
  831. if (SmartcardExtension->ReaderExtension->fCardPresent)
  832. {
  833. SmartcardExtension->MinorIoControlCode = SCARD_POWER_DOWN;
  834. NTStatus = CMMOB_PowerOffCard(SmartcardExtension);
  835. ASSERT(NTStatus == STATUS_SUCCESS);
  836. }
  837. // save the current power state of the reader
  838. SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderOff;
  839. action = SkipRequest;
  840. break;
  841. default:
  842. action = SkipRequest;
  843. break;
  844. }
  845. break;
  846. } /* case irpStack->Parameters.Power.Type */
  847. break; /* IRP_MN_SET_POWER */
  848. default:
  849. SmartcardDebug(DEBUG_DRIVER,
  850. ("%s!PowerDeviceControl: unhandled POWER IRP received\n",DRIVER_NAME));
  851. //
  852. // All unhandled power messages are passed on to the PDO
  853. //
  854. action = SkipRequest;
  855. break;
  856. } /* irpStack->MinorFunction */
  857. switch (action)
  858. {
  859. case CompleteRequest:
  860. SmartcardReleaseRemoveLock(SmartcardExtension);
  861. PoStartNextPowerIrp(Irp);
  862. Irp->IoStatus.Status = NTStatus;
  863. Irp->IoStatus.Information = 0;
  864. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  865. break;
  866. case MarkPending:
  867. // initialize the event we need in the completion function
  868. KeInitializeEvent(&event,
  869. NotificationEvent,
  870. FALSE);
  871. // request the device power irp
  872. NTStatus = PoRequestPowerIrp (DeviceObject,
  873. IRP_MN_SET_POWER,
  874. DesiredPowerState,
  875. CMMOB_SystemPowerCompletion,
  876. &event,
  877. NULL);
  878. SmartcardDebug( DEBUG_DRIVER,
  879. ("%s!PowerDeviceControl: called PoRequestPowerIrp with %s\n",DRIVER_NAME,
  880. szDevicePowerState[DesiredPowerState.DeviceState] ));
  881. ASSERT(NTStatus == STATUS_PENDING);
  882. if (NTStatus == STATUS_PENDING)
  883. {
  884. // wait until the device power irp completed
  885. NTStatus = KeWaitForSingleObject(&event,
  886. Executive,
  887. KernelMode,
  888. FALSE,
  889. NULL);
  890. }
  891. // this is a bug fix for Win 98
  892. // PoRequestPowerIrp did not send us a PowerIrp
  893. if (NTStatus == STATUS_SUCCESS &&
  894. ((DesiredPowerState.DeviceState != PowerDeviceD0 &&
  895. SmartcardExtension->ReaderExtension->ReaderPowerState == PowerReaderWorking) ||
  896. (DesiredPowerState.DeviceState == PowerDeviceD0 &&
  897. SmartcardExtension->ReaderExtension->ReaderPowerState == PowerReaderOff)))
  898. {
  899. SmartcardDebug( DEBUG_DRIVER,
  900. ("%s!PowerDeviceControl: PoRequestPowerIrp didn't set Device State properly\n",DRIVER_NAME ));
  901. switch (DesiredPowerState.DeviceState)
  902. {
  903. case PowerDeviceD0:
  904. // Turn on the reader
  905. SmartcardDebug(DEBUG_DRIVER,
  906. ("%s!PowerDeviceControl: PowerDevice D0\n",DRIVER_NAME));
  907. NTStatus = CMMOB_StartCardTracking(DeviceObject);
  908. if (NTStatus != STATUS_SUCCESS)
  909. {
  910. SmartcardDebug(DEBUG_ERROR,
  911. ("%s!StartCardTracking failed ! %lx\n",DRIVER_NAME,NTStatus));
  912. }
  913. //
  914. // If a card was present before power down or now there is
  915. // a card in the reader, we complete any pending card monitor
  916. // request, since we do not really know what card is now in the
  917. // reader.
  918. //
  919. if (SmartcardExtension->ReaderExtension->fCardPresent ||
  920. SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT)
  921. {
  922. SmartcardExtension->ReaderExtension->ulOldCardState = UNKNOWN;
  923. SmartcardExtension->ReaderExtension->ulNewCardState = UNKNOWN;
  924. }
  925. // signal that we can process ioctls again
  926. DeviceExtension->lIoCount = 0;
  927. KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
  928. // inform the power manager of our state.
  929. PoSetPowerState (DeviceObject,
  930. DevicePowerState,
  931. DesiredPowerState);
  932. // save the current power state of the reader
  933. SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderWorking;
  934. SmartcardDebug(DEBUG_DRIVER,
  935. ("%s!PowerDeviceControl: reader started\n",DRIVER_NAME));
  936. break;
  937. case PowerDeviceD1:
  938. case PowerDeviceD2:
  939. case PowerDeviceD3:
  940. // Turn off the reader
  941. SmartcardDebug(DEBUG_DRIVER,
  942. ("%s!PowerDeviceControl: PowerDevice D3\n",DRIVER_NAME));
  943. // inform the power manager of our state.
  944. PoSetPowerState (DeviceObject,
  945. DevicePowerState,
  946. DesiredPowerState);
  947. // Block any further ioctls
  948. KeClearEvent(&DeviceExtension->ReaderStarted);
  949. // stop the update thread
  950. CMMOB_StopCardTracking(DeviceObject);
  951. // save the current card state
  952. SmartcardExtension->ReaderExtension->fCardPresent =
  953. SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT;
  954. if (SmartcardExtension->ReaderExtension->fCardPresent)
  955. {
  956. SmartcardExtension->MinorIoControlCode = SCARD_POWER_DOWN;
  957. NTStatus = CMMOB_PowerOffCard(SmartcardExtension);
  958. ASSERT(NTStatus == STATUS_SUCCESS);
  959. }
  960. // save the current power state of the reader
  961. SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderOff;
  962. SmartcardDebug(DEBUG_DRIVER,
  963. ("%s!PowerDeviceControl: reader stopped\n",DRIVER_NAME));
  964. break;
  965. default:
  966. break;
  967. }
  968. }
  969. if (NTStatus == STATUS_SUCCESS)
  970. {
  971. SmartcardReleaseRemoveLock(SmartcardExtension);
  972. PoStartNextPowerIrp(Irp);
  973. IoSkipCurrentIrpStackLocation(Irp);
  974. NTStatus = PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
  975. }
  976. else
  977. {
  978. SmartcardReleaseRemoveLock(SmartcardExtension);
  979. PoStartNextPowerIrp(Irp);
  980. Irp->IoStatus.Status = NTStatus;
  981. Irp->IoStatus.Information = 0;
  982. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  983. }
  984. break;
  985. case SkipRequest:
  986. SmartcardReleaseRemoveLock(SmartcardExtension);
  987. PoStartNextPowerIrp(Irp);
  988. IoSkipCurrentIrpStackLocation(Irp);
  989. NTStatus = PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
  990. break;
  991. case WaitForCompletion:
  992. NTStatus = PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
  993. break;
  994. default:
  995. SmartcardReleaseRemoveLock(SmartcardExtension);
  996. PoStartNextPowerIrp(Irp);
  997. IoSkipCurrentIrpStackLocation(Irp);
  998. NTStatus = PoCallDriver(DeviceExtension->AttachedDeviceObject, Irp);
  999. break;
  1000. }
  1001. SmartcardDebug(DEBUG_TRACE,
  1002. ("%s!PowerDeviceControl: Exit %lx\n",DRIVER_NAME,NTStatus));
  1003. return NTStatus;
  1004. }
  1005. #endif
  1006. /*****************************************************************************
  1007. * History:
  1008. * $Log: cmbp0pnp.c $
  1009. * Revision 1.4 2000/08/24 09:05:12 TBruendl
  1010. * No comment given
  1011. *
  1012. * Revision 1.3 2000/07/27 13:53:01 WFrischauf
  1013. * No comment given
  1014. *
  1015. *
  1016. ******************************************************************************/