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

📄 pwr.c

📁 usbhostDriver, 设计USB的目标就是使不同厂家所生产的设备可以在一个开放的体系下广泛的使用。该规范改进了便携商务或家用电脑的现有体系结构
💻 C
📖 第 1 页 / 共 3 页
字号:
          PoStartNextPowerIrp(Irp);
          Irp->IoStatus.Status = ntS;
          Irp->IoStatus.Information = 0;
          IoCompleteRequest(Irp, IO_NO_INCREMENT);
          DPRINT(("HandleDeviceSetPower::"));
          DevIoDecrement(deviceExtension);
          return ntS;
      } else {
        goto HandleDeviceSetPower_Exit;
      }
    } else if(PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState) {
      //
      // D0 -> D0
      // unblock the queue which may have been blocked processing
      // query irp
      //
      DPRINT(("A SetD0 request\n"));
      KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
      deviceExtension->QueueState = AllowRequests;
      KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
      ProcessQueuedRequests(deviceExtension);
    }   
    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,deviceExtension, TRUE, TRUE, TRUE);
    ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
    if(!NT_SUCCESS(ntS)) {
      DPRINT(("Lower drivers failed a power Irp\n"));
    }
  }
HandleDeviceSetPower_Exit:
  DPRINT(("HandleDeviceSetPower - ends\n"));
  return STATUS_PENDING;
}

/*++
 
Routine Description:

    The power dispatch routine.

Arguments:

    DeviceObject - pointer to a device object.

    Irp - pointer to an I/O Request Packet.

Return Value:

    NT status code

--*/
NTSTATUS BulkUsb_DispatchPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  NTSTATUS           ntS;
  PIO_STACK_LOCATION irpStack;
  DEVICE_EXTENSION *  deviceExtension;

  //
  // initialize the variables
  //

  irpStack = IoGetCurrentIrpStackLocation(Irp);
  deviceExtension = (DEVICE_EXTENSION *)DeviceObject->DeviceExtension;

  //
  // We don't queue power Irps, we'll only check if the
  // device was removed, otherwise we'll take appropriate
  // action and send it to the next lower driver. In general
  // drivers should not cause long delays while handling power
  // IRPs. If a driver cannot handle a power IRP in a brief time,
  // it should return STATUS_PENDING and queue all incoming
  // IRPs until the IRP completes.
  //

  if(Removed == deviceExtension->DeviceState) {
    //
    // Even if a driver fails the IRP, it must nevertheless call
    // PoStartNextPowerIrp to inform the Power Manager that it
    // is ready to handle another power IRP.
    //
    PoStartNextPowerIrp(Irp);
    Irp->IoStatus.Status = ntS = STATUS_DELETE_PENDING;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return ntS;
  }
  if(NotStarted == deviceExtension->DeviceState) {
    //
    // if the device is not started yet, pass it down
    //
    PoStartNextPowerIrp(Irp);
    IoSkipCurrentIrpStackLocation(Irp);
    return PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  }
  DPRINT(("BulkUsb_DispatchPower::"));
  DevIoIncrement(deviceExtension);
  switch (irpStack->MinorFunction) {
  case IRP_MN_SET_POWER:
    //
    // The Power Manager sends this IRP for one of the
    // following reasons:
    // 1) To notify drivers of a change to the system power state.
    // 2) To change the power state of a device for which
    //    the Power Manager is performing idle detection.
    // A driver sends IRP_MN_SET_POWER to change the power
    // state of its device if it's a power policy owner for the
    // device.
    //
    IoMarkIrpPending(Irp);
    switch(irpStack->Parameters.Power.Type) {
    case SystemPowerState:
      HandleSystemSetPower(DeviceObject, Irp);
      ntS = STATUS_PENDING;
      break;
    case DevicePowerState:
      HandleDeviceSetPower(DeviceObject, Irp);
      ntS = STATUS_PENDING;
      break;
    }
    break;
  case IRP_MN_QUERY_POWER:
    //
    // The Power Manager sends a power IRP with the minor
    // IRP code IRP_MN_QUERY_POWER to determine whether it
    // can safely change to the specified system power state
    // (S1-S5) and to allow drivers to prepare for such a change.
    // If a driver can put its device in the requested state,
    // it sets status to STATUS_SUCCESS and passes the IRP down.
    //
    IoMarkIrpPending(Irp);
    switch(irpStack->Parameters.Power.Type) {
    case SystemPowerState:
      HandleSystemQueryPower(DeviceObject, Irp);
      ntS = STATUS_PENDING;
      break;
    case DevicePowerState:
      HandleDeviceQueryPower(DeviceObject, Irp);
      ntS = STATUS_PENDING;
      break;
    }
    break;
  case IRP_MN_WAIT_WAKE:
    //
    // The minor power IRP code IRP_MN_WAIT_WAKE provides
    // for waking a device or waking the system. Drivers
    // of devices that can wake themselves or the system
    // send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE
    // only to devices that always wake the system, such as
    // the power-on switch.
    //
    IoMarkIrpPending(Irp);
    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine, 
                           deviceExtension, TRUE, TRUE, TRUE);
    PoStartNextPowerIrp(Irp);
    ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
    if(!NT_SUCCESS(ntS)) {
      DPRINT(("Lower drivers failed the wait-wake Irp"));
    }
    ntS = STATUS_PENDING;
    //
    // push back the count HERE and NOT in completion routine
    // a pending Wait Wake Irp should not impede stopping the device
    //
    DPRINT(("IRP_MN_WAIT_WAKE::"));
    DevIoDecrement(deviceExtension);
    break;
  case IRP_MN_POWER_SEQUENCE:
    //
    // A driver sends this IRP as an optimization to determine
    // whether its device actually entered a specific power state.
    // This IRP is optional. Power Manager cannot send this IRP.
    //
  default:
    PoStartNextPowerIrp(Irp);
    IoSkipCurrentIrpStackLocation(Irp);
    ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
    if(!NT_SUCCESS(ntS)) {
      DPRINT(("Lower drivers failed this Irp"));
    }
    DPRINT(("BulkUsb_DispatchPower::"));
    DevIoDecrement(deviceExtension);
    break;
  }
  return ntS;
}



/*********************************************************************
 
Routine Description:

    This routine removes the irp from the queue and completes it with
    STATUS_CANCELLED

Arguments:

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

Return Value:

    None.

--*/
VOID CancelQueued(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) {
  DEVICE_EXTENSION * deviceExtension;
  KIRQL             oldIrql;

  //
  // initialize variables
  //
  deviceExtension = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  oldIrql = Irp->CancelIrql;
  DPRINT(("CancelQueued - begins\n"));
  //
  // Release the cancel spin lock
  //
  IoReleaseCancelSpinLock(Irp->CancelIrql);
  //
  // Acquire the queue lock
  //
  KeAcquireSpinLockAtDpcLevel(&deviceExtension->QueueLock);
  //
  // Remove the cancelled Irp from queue and release the lock
  //
  RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
  //
  // complete with STATUS_CANCELLED
  //
  Irp->IoStatus.Status = STATUS_CANCELLED;
  Irp->IoStatus.Information = 0;
  IoCompleteRequest(Irp, IO_NO_INCREMENT);
  DPRINT(("CancelQueued - ends\n"));
  return;
}


/*********************************************************************
* 
* Routine Description:
*    Queue the Irp in the device queue
*
* Arguments:
*    DeviceExtension - pointer to device extension
*    Irp - I/O request packet.
*
* Return Value:
*    NT status value
*/
NTSTATUS QueueRequest( IN OUT DEVICE_EXTENSION * DeviceExtension, IN PIRP Irp ) {
  KIRQL    oldIrql;
  NTSTATUS ntS;
  //
  // initialize variables
  //
  ntS = STATUS_PENDING;
  DPRINT(("QueueRequests - begins\n"));
  ASSERT(HoldRequests == DeviceExtension->QueueState);
  KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
  InsertTailList(&DeviceExtension->NewRequestsQueue, &Irp->Tail.Overlay.ListEntry);
  IoMarkIrpPending(Irp);
  //
  // Set the cancel routine
  //
  IoSetCancelRoutine(Irp, CancelQueued);
  KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
  DPRINT(("QueueRequests - ends\n"));
  return ntS;
}


/*++
 
Routine Description:

    This routine cancels the Wait Wake request.

Arguments:

    DeviceExtension - pointer to the device extension

Return Value:

    None.

--*/

VOID CancelWaitWake(IN DEVICE_EXTENSION * DeviceExtension) {
  PIRP Irp;

  DPRINT(("CancelWaitWake - begins\n"));
  Irp = (PIRP) InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL);
  if(Irp) {
    IoCancelIrp(Irp);
    if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1)) {
      PoStartNextPowerIrp(Irp);
      Irp->IoStatus.Status = STATUS_CANCELLED;
      Irp->IoStatus.Information = 0;
      IoCompleteRequest(Irp, IO_NO_INCREMENT);
    }    
  }
  DPRINT(("CancelWaitWake - ends\n"));
}



/*********************************************************************
*
*       WWIrpCompletionFunc
*
* Function description
*   ???
*/
void WWIrpCompletionFunc(IN PDEVICE_OBJECT pDevObj, IN UCHAR MinorFunction,
                    IN POWER_STATE PowerState, IN void* pContext, IN PIO_STATUS_BLOCK IoStatus)
{
  DEVICE_EXTENSION * pDevExt = (DEVICE_EXTENSION*) pContext;
  DevIoDecrement(pDevExt);
  return;
}


/*++
 
Routine Description:

    This is the PoRequest completion routine for the wait wake irp.

Arguments:

    DeviceObject - pointer to device object
    MinorFunction - irp minor function
    PowerState - power state of the irp.
    Context - context passed to the completion routine.
    IoStatus - status block.

Return Value:

    None

--*/
VOID WaitWakeCallback(IN PDEVICE_OBJECT DeviceObject,IN UCHAR MinorFunction,
                      IN POWER_STATE PowerState,IN PVOID Context,IN PIO_STATUS_BLOCK IoStatus) {
  NTSTATUS               ntS;
  POWER_STATE            powerState;
  DEVICE_EXTENSION *      deviceExtension;

  DPRINT(("WaitWakeCallback - begins\n"));
  deviceExtension = (DEVICE_EXTENSION *) Context;
  InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0);
  if(!NT_SUCCESS(IoStatus->Status)) {
    return;
  }
  //
  // wake up the device
  //
  if(deviceExtension->DevPower == PowerDeviceD0) {
    DPRINT(("device already powered up...\n"));
    return;
  }
  DPRINT(("WaitWakeCallback::"));
  DevIoIncrement(deviceExtension);
  powerState.DeviceState = PowerDeviceD0;
  ntS = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject, IRP_MN_SET_POWER, powerState, 
                           WWIrpCompletionFunc, deviceExtension, NULL);
  if(deviceExtension->WaitWakeEnable) {
    IssueWaitWake(deviceExtension);
  }
  DPRINT(("WaitWakeCallback - ends\n"));
  return;
}


⌨️ 快捷键说明

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