⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pwr.c

📁 usbhostDriver, 设计USB的目标就是使不同厂家所生产的设备可以在一个开放的体系下广泛的使用。该规范改进了便携商务或家用电脑的现有体系结构
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
**********************************************************************
*                          Micrium, Inc.
*                      949 Crestview Circle
*                     Weston,  FL 33327-1848
*
*                           uC/USB-Bulk
*
*             (c) Copyright 2003 - 2004, Micrium, Inc.
*                      All rights reserved.
*
***********************************************************************

----------------------------------------------------------------------
File        : pwr.c
Purpose     : Part of the USB bulk driver
---------------------------END-OF-HEADER------------------------------
*/

#include "Main.h"

typedef struct _WORKER_THREAD_CONTEXT {
  PDEVICE_OBJECT DeviceObject;
  PIRP           Irp;
  PIO_WORKITEM   WorkItem;
} WORKER_THREAD_CONTEXT, *PWORKER_THREAD_CONTEXT;

typedef struct _POWER_COMPLETION_CONTEXT {
  PDEVICE_OBJECT DeviceObject;
  PIRP           SIrp;
} POWER_COMPLETION_CONTEXT, *PPOWER_COMPLETION_CONTEXT;


/*++
 
Routine Description:

    This routine is the completion routine for device power DOWN irp.

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet
    DeviceExtension - pointer to device extension

Return Value:

    NT status value

--*/
NTSTATUS FinishDevPoDnIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,IN DEVICE_EXTENSION * DeviceExtension) {
  NTSTATUS           ntS;
  POWER_STATE        newState;
  PIO_STACK_LOCATION irpStack;

  //
  // initialize variables
  //
  ntS = Irp->IoStatus.Status;
  irpStack = IoGetCurrentIrpStackLocation(Irp);
  newState = irpStack->Parameters.Power.State;
  DPRINT(("FinishDevPoDnIrp - begins\n"));
  if(NT_SUCCESS(ntS) && irpStack->MinorFunction == IRP_MN_SET_POWER) {
    //
    // update the cache;
    //
    DPRINT(("updating cache..\n"));
    DeviceExtension->DevPower = newState.DeviceState;
    PoSetPowerState(DeviceObject, DevicePowerState, newState);
  }
  PoStartNextPowerIrp(Irp);
  DPRINT(("FinishDevPoDnIrp::"));
  DevIoDecrement(DeviceExtension);
  DPRINT(("FinishDevPoDnIrp - ends\n"));
  return STATUS_SUCCESS;
}

/*********************************************************************
*
* Routine Description:
*
*    This routine waits for the I/O in progress to finish and then
*    sends the device power irp (query/set) down the stack.
*
* Arguments:
*
*    DeviceObject - pointer to device object
*    Context - context passed to the work-item.
*
* Return Value:
* 
*   None
*/
VOID HoldIoRequestsWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context) {
  PIRP                   irp;
  NTSTATUS               ntS;
  DEVICE_EXTENSION *      deviceExtension;
  PWORKER_THREAD_CONTEXT context;

  DPRINT(("HoldIoRequestsWorkerRoutine - begins\n"));
  //
  // initialize variables
  //
  deviceExtension = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  context = (PWORKER_THREAD_CONTEXT) Context;
  irp = (PIRP) context->Irp;
  //
  // wait for I/O in progress to finish.
  // the stop event is signalled when the counter drops to 1.
  // invoke DevIoDecrement twice: once each for the S-Irp and D-Irp.
  //
  DPRINT(("HoldIoRequestsWorkerRoutine::"));
  DevIoDecrement(deviceExtension);
  DPRINT(("HoldIoRequestsWorkerRoutine::"));
  DevIoDecrement(deviceExtension);
  KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL);
  //
  // Increment twice to restore the count
  //
  DPRINT(("HoldIoRequestsWorkerRoutine::"));
  DevIoIncrement(deviceExtension);
  DPRINT(("HoldIoRequestsWorkerRoutine::"));
  DevIoIncrement(deviceExtension);
  // 
  // now send the Irp down
  //
  IoCopyCurrentIrpStackLocationToNext(irp);
  IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
                         deviceExtension, TRUE, TRUE, TRUE);
  ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
  if(!NT_SUCCESS(ntS)) {
    DPRINT(("Lower driver fail a power Irp\n"));
  }
  IoFreeWorkItem(context->WorkItem);
  ExFreePool((PVOID)context);
  DPRINT(("HoldIoRequestsWorkerRoutine - ends\n"));
}


/*********************************************************************
* Routine Description:
*
*    This routine is called on query or set power DOWN irp for the device.
*    This routine queues a workitem.
* Arguments:
*    DeviceObject - pointer to device object
*    Irp - I/O request packet
*
* Return Value:
*    NT status value
*/
NTSTATUS HoldIoRequests(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) {
  NTSTATUS               ntS;
  PIO_WORKITEM           item;
  DEVICE_EXTENSION *      deviceExtension;
  PWORKER_THREAD_CONTEXT context;
  //
  // initialize variables
  //
  deviceExtension = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  DPRINT(("HoldIoRequests - begins\n"));
  deviceExtension->QueueState = HoldRequests;
  context = ExAllocatePool(NonPagedPool, sizeof(WORKER_THREAD_CONTEXT));
  if(context) {
    item = IoAllocateWorkItem(DeviceObject);
    context->Irp = Irp;
    context->DeviceObject = DeviceObject;
    context->WorkItem = item;
    if(item) {
      IoMarkIrpPending(Irp);
      IoQueueWorkItem(item, HoldIoRequestsWorkerRoutine,
                      DelayedWorkQueue, context);
      
      ntS = STATUS_PENDING;
    } else {
      DPRINT(("Failed to allocate memory for workitem\n"));
      ExFreePool(context);
      ntS = STATUS_INSUFFICIENT_RESOURCES;
    }
  } else {
    DPRINT(("Failed to alloc memory for worker thread context\n"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
  }
  DPRINT(("HoldIoRequests - ends\n"));
  return ntS;
}


/*++

Routine Description:

  This routine services irps of minor type IRP_MN_QUERY_POWER
  for the device power state

Arguments:

  DeviceObject - pointer to device object
  Irp - I/O request packet sent by the power manager

Return Value:

  NT status value

--*/
NTSTATUS HandleDeviceQueryPower(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
  NTSTATUS           ntS;
  DEVICE_EXTENSION *  deviceExtension;
  PIO_STACK_LOCATION irpStack;
  DEVICE_POWER_STATE deviceState;

  DPRINT(("HandleDeviceQueryPower - begins\n"));
  //
  // initialize variables
  //
  deviceExtension = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  irpStack = IoGetCurrentIrpStackLocation(Irp);
  deviceState = irpStack->Parameters.Power.State.DeviceState;
  DPRINT(("Query for device power state D%X\n"
          "Current device power state D%X\n",
          deviceState - 1,
          deviceExtension->DevPower - 1));
  if(deviceExtension->WaitWakeEnable &&
    deviceState > deviceExtension->DeviceCapabilities.DeviceWake) {
    PoStartNextPowerIrp(Irp);
    Irp->IoStatus.Status = ntS = STATUS_INVALID_DEVICE_STATE;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    DPRINT(("HandleDeviceQueryPower::"));
    DevIoDecrement(deviceExtension);
    return ntS;
  }
  if(deviceState < deviceExtension->DevPower) {
    ntS = STATUS_SUCCESS;
  } else {
    ntS = HoldIoRequests(DeviceObject, Irp);
    if(STATUS_PENDING == ntS) {
      return ntS;
    }
  }
  //
  // on error complete the Irp.
  // on success pass it to the lower layers
  //
  PoStartNextPowerIrp(Irp);
  Irp->IoStatus.Status = ntS;
  Irp->IoStatus.Information = 0;
  if(!NT_SUCCESS(ntS)) {
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
  } else {
    IoSkipCurrentIrpStackLocation(Irp);
    ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  }
  DPRINT(("HandleDeviceQueryPower::"));
  DevIoDecrement(deviceExtension);
  DPRINT(("HandleDeviceQueryPower - ends\n"));
  return ntS;
}

/*********************************************************************
*
* Routine Description:
*
*  This is the PoRequest - completion routine for the device power irp.
*  This routine is responsible for completing the system power irp, 
*  received as a context.
*
* Arguments:
*
*  DeviceObject - pointer to device object
*  MinorFunction - minor function of the irp.
*  PowerState - power state of the irp.
*  Context - context passed to the completion routine.
*  IoStatus - status of the device power irp.
*
* Return Value:
*
*  None
*/
VOID DevPoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction,
                            IN POWER_STATE PowerState, IN PVOID Context,IN PIO_STATUS_BLOCK IoStatus) {
  PIRP                      sIrp;
  DEVICE_EXTENSION *         deviceExtension;
  PPOWER_COMPLETION_CONTEXT powerContext;
  
  //
  // initialize variables
  //
  powerContext = (PPOWER_COMPLETION_CONTEXT) Context;
  sIrp = powerContext->SIrp;
  deviceExtension = powerContext->DeviceObject->DeviceExtension;
  DPRINT(("DevPoCompletionRoutine - begins\n"));
  //
  // copy the D-Irp status into S-Irp
  //
  sIrp->IoStatus.Status = IoStatus->Status;
  //
  // complete the system Irp
  //
  PoStartNextPowerIrp(sIrp);
  sIrp->IoStatus.Information = 0;
  IoCompleteRequest(sIrp, IO_NO_INCREMENT);
  //
  // cleanup
  //
  DPRINT(("DevPoCompletionRoutine::"));
  DevIoDecrement(deviceExtension);
  ExFreePool(powerContext);
  DPRINT(("DevPoCompletionRoutine - ends\n"));
}

/*********************************************************************
*
* Routine Description:
*  This routine is invoked from the completion routine of the system power
*  irp. This routine will PoRequest a device power irp. The system irp is 
*  passed as a context to the the device power irp.
*
* Arguments:
*
*  DeviceObject - pointer to device object
*  SIrp - system power irp.
*
* Return Value:
*
*  None
*/
VOID SendDeviceIrp(IN PDEVICE_OBJECT DeviceObject,IN PIRP SIrp) {
  NTSTATUS                  ntS;
  POWER_STATE               powState;
  DEVICE_EXTENSION *         deviceExtension;
  PIO_STACK_LOCATION        irpStack;
  SYSTEM_POWER_STATE        systemState;
  DEVICE_POWER_STATE        devState;
  PPOWER_COMPLETION_CONTEXT powerContext;
  
  //
  // initialize variables
  //
  irpStack = IoGetCurrentIrpStackLocation(SIrp);
  systemState = irpStack->Parameters.Power.State.SystemState;
  deviceExtension = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  DPRINT(("SendDeviceIrp - begins\n"));
  //
  // Read out the D-IRP out of the S->D mapping array captured in QueryCap's.
  // we can choose deeper sleep states than our mapping but never choose
  // lighter ones.
  //

  devState = deviceExtension->DeviceCapabilities.DeviceState[systemState];
  powState.DeviceState = devState;
  powerContext = (POWER_COMPLETION_CONTEXT*)ExAllocatePool(NonPagedPool,sizeof(POWER_COMPLETION_CONTEXT));
  if(!powerContext) {
    DPRINT(("Failed to alloc memory for powerContext\n"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
  } else {
    powerContext->DeviceObject = DeviceObject;
    powerContext->SIrp = SIrp;
    //
    // in win2k PoRequestPowerIrp can take fdo or pdo.
    //
    ntS = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,  irpStack->MinorFunction,
                            powState, (PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine,powerContext, NULL);
  }
  if(!NT_SUCCESS(ntS)) {
    if(powerContext) {
      ExFreePool(powerContext);
    }
    PoStartNextPowerIrp(SIrp);
    SIrp->IoStatus.Status = ntS;
    SIrp->IoStatus.Information = 0;
    IoCompleteRequest(SIrp, IO_NO_INCREMENT);
    DPRINT(("SendDeviceIrp::"));
    DevIoDecrement(deviceExtension);
  }
  DPRINT(("SendDeviceIrp - ends\n"));
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -