mavpwr.c

来自「基于EP7312的MP3播放器源代码,包括MCU和PC端代码.」· C语言 代码 · 共 1,127 行 · 第 1/3 页

C
1,127
字号
                    }

                    //
                    // We're done handling the device power state change.
                    //
                    break;
                }
            }

            //
            // We're done with this IRP.
            //
            break;
        }

        //
        // A power policy manager sends this IRP to determine whether it can
        // change the system or device power state, typically to go to sleep.
        //
        case IRP_MN_QUERY_POWER:
        {
            //
            // We do nothing special here, just let the PDO handle it.
            //
            IoCopyCurrentIrpStackLocationToNext(Irp);
            PoStartNextPowerIrp(Irp);
            ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject,
                                    Irp);

            //
            // Decrement the count of pending IRPs.
            //
            MavUsb_DecrementIoCount(DeviceObject);

            //
            // We're done with this IRP.
            //
            break;
        }

        //
        // Handle all other IRPs.
        //
        default:
        {
            //
            // All unhandled power messages are passed on to the PDO.
            //
            IoCopyCurrentIrpStackLocationToNext(Irp);
            PoStartNextPowerIrp(Irp);
            ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject,
                                    Irp);

            //
            // Decrement the count of pending IRPs.
            //
            MavUsb_DecrementIoCount(DeviceObject);
        }
    }

    //
    // Return the status.
    //
    return(ntStatus);
}

//****************************************************************************
//
// This is the completion routine set in a call to PoRequestPowerIrp() that
// was made in MavUsb_ProcessPowerIrp() in response to receiving an
// IRP_MN_SET_POWER of type 'SystemPowerState' when the device was not in a
// compatible device power state.  In this case, a pointer to the
// IRP_MN_SET_POWER IRP is saved into the FDO device extension
// (deviceExtension->PowerIrp), and then a call must be made to
// PoRequestPowerIrp() to put the device into a proper power state, and this
// routine is set as the completion routine.
//
// We decrement our pending io count and pass the saved IRP_MN_SET_POWER IRP
// on to the next driver.
//
// Arguments:
//
//     DeviceObject - Pointer to the device object for the class device.
//                    Note that we must get our own device object from the
//                    Context.
//
//     Context - Driver defined context, in this case our own functional
//               device object (FDO).
//
// Return Value:
//
//     The function value is the final status from the operation.
//
//****************************************************************************
NTSTATUS
MavUsb_PoRequestCompletion(IN PDEVICE_OBJECT DeviceObject,
                           IN UCHAR MinorFunction, IN POWER_STATE PowerState,
                           IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus)
{
    PIRP irp;
    PDEVICE_EXTENSION deviceExtension;
    PDEVICE_OBJECT deviceObject = Context;
    NTSTATUS ntStatus;

    //
    // Get a pointer to the device extension.
    //
    deviceExtension = deviceObject->DeviceExtension;

    //
    // Get the IRP we saved for later processing in MavUsb_ProcessPowerIrp()
    // when we decided to request the Power IRP that this routine is the
    // completion routine for.
    //
    irp = deviceExtension->PowerIrp;

    //
    // We will return the status set by the PDO for the power request we're
    // completing.
    //
    ntStatus = IoStatus->Status;

    //
    // We must pass down to the next driver in the stack.
    //
    IoCopyCurrentIrpStackLocationToNext(irp);

    //
    // Calling PoStartNextPowerIrp() indicates that the driver is finished
    // with the previous power IRP, if any, and is ready to handle the next
    // power IRP.  It must be called for every power IRP.  Although power IRPs
    // are completed only once, typically by the lowest-level driver for a
    // device, PoStartNextPowerIrp must be called for every stack location.
    // Drivers must call PoStartNextPowerIrp while the current IRP stack
    // location points to the current driver.  Therefore, this routine must be
    // called before IoCompleteRequest, IoSkipCurrentStackLocation, and
    // PoCallDriver.
    //
    PoStartNextPowerIrp(irp);

    //
    // PoCallDriver is used to pass any power IRPs to the PDO instead of
    // IoCallDriver.  When passing a power IRP down to a lower-level driver,
    // the caller should use IoSkipCurrentIrpStackLocation or
    // IoCopyCurrentIrpStackLocationToNext to copy the IRP to the next stack
    // location, then call PoCallDriver.  Use
    // IoCopyCurrentIrpStackLocationToNext if processing the IRP requires
    // setting a completion routine, or IoSkipCurrentStackLocation if no
    // completion routine is needed.
    //
    PoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);

    //
    // Decrement the count of pending IRPs.
    //
    MavUsb_DecrementIoCount(deviceObject);

    //
    // We're done handling the saved IRP.
    //
    deviceExtension->PowerIrp = NULL;

    //
    // Return the status.
    //
    return(ntStatus);
}

//****************************************************************************
//
// This routine is called when An IRP_MN_SET_POWER of type 'DevicePowerState'
// has been received by MavUsb_ProcessPowerIrp(), and that routine has
// determined:
//     1) the request is for full powerup (to PowerDeviceD0), and
//     2) We are not already in that state
// A call is then made to PoRequestPowerIrp() with this routine set as the
// completion routine.
//
// Arguments:
//
//     DeviceObject - Pointer to the device object for the class device.
//
//     Irp - IRP completed.
//
//     Context - Driver defined context.
//
// Return Value:
//
//     The function value is the final status from the operation.
//
//****************************************************************************
NTSTATUS
MavUsb_PowerIrp_Complete(IN PDEVICE_OBJECT NullDeviceObject, IN PIRP Irp,
                         IN PVOID Context)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_OBJECT deviceObject;
    PIO_STACK_LOCATION irpStack;
    PDEVICE_EXTENSION deviceExtension;

    //
    // Get a pointer to the the device object.
    //
    deviceObject = (PDEVICE_OBJECT)Context;

    //
    // Get a pointer to the device extension.
    //
    deviceExtension = deviceObject->DeviceExtension;

    //
    // If the lower driver returned PENDING, mark our stack location as pending
    // also.
    //
    if(Irp->PendingReturned)
    {
        IoMarkIrpPending(Irp);
    }

    //
    // Get a pointer to the current location on the IRP stack.
    //
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // Now that we know we've let the lower drivers do what was needed to power
    // up, we can set our device extension flags accordingly.
    //
    deviceExtension->CurrentDevicePowerState = PowerDeviceD0;

    //
    // Set the status in the IRP.
    //
    Irp->IoStatus.Status = ntStatus;

    //
    // Decrement the count of pending IRPs.
    //
    MavUsb_DecrementIoCount(deviceObject);

    //
    // Return the status.
    //
    return(ntStatus);
}

//****************************************************************************
//
// Called on MavUsb_PnPAddDevice() to power down until needed (i.e., until a
// pipe is actually opened).
//
// Called on MavUsb_Create() to power up device to D0 before opening 1st pipe.
//
// Called on MavUsb_Close() to power down device if this is the last pipe.
//
// Arguments:
//
//     DeviceObject - Pointer to the device object
//
//     fSuspend - TRUE to Suspend, FALSE to activate.
//
// Return Value:
//
//     If the operation is not attemtped, SUCCESS is returned.
//
//     If the operation is attemtped, the value is the final status from the
//     operation.
//
//****************************************************************************
NTSTATUS
MavUsb_SelfSuspendOrActivate(IN PDEVICE_OBJECT DeviceObject,
                             IN BOOLEAN fSuspend)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    POWER_STATE PowerState;
    PDEVICE_EXTENSION deviceExtension;

    //
    // Get a pointer to the device extension.
    //
    deviceExtension = DeviceObject->DeviceExtension;

    //
    // Can't accept request if:
    //  1) device is removed,
    //  2) has never been started,
    //  3) is stopped,
    //  4) has a remove request pending,
    //  5) has a stop device pending.
    //
    if(!MavUsb_CanAcceptIoRequests(DeviceObject))
    {
        //
        // Indicate that a delete is pending.
        //
        return(STATUS_DELETE_PENDING);
    }

    //
    // Don't do anything if any System-generated Device PnP IRPs are pending.
    //
    if(deviceExtension->PowerIrp != NULL)
    {
        //
        // Return success.
        //
        return(STATUS_SUCCESS);
    }

    //
    // Don't do anything if any self-generated Device PnP IRPs are pending
    //
    if(deviceExtension->SelfPowerIrp)
    {
        //
        // Return success.
        //
        return(STATUS_SUCCESS);
    }

    //
    // Don't auto-suspend if any pipes are open.
    //
    if(fSuspend && (deviceExtension->OpenPipeCount != 0))
    {
        //
        // Return success.
        //
        return(STATUS_SUCCESS);
    }

    //
    // Don't auto-activate if no pipes are open.
    //
    if(!fSuspend && (deviceExtension->OpenPipeCount == 0))
    {
        //
        // Return success.
        //
        return(STATUS_SUCCESS);
    }

    //
    // Don't do anything if registry
    // CurrentControlSet\Services\BulkUsb\Parameters\PowerDownLevel
    // has been set to zero, PowerDeviceD0 (1), or a bogus high value.
    //
    if((deviceExtension->PowerDownLevel == PowerDeviceD0) ||
       (deviceExtension->PowerDownLevel == PowerDeviceUnspecified) ||
       (deviceExtension->PowerDownLevel >= PowerDeviceMaximum))
    {
        //
        // Return success.
        //
        return(STATUS_SUCCESS);
    }

    //
    // If we should suspend, then set our device state to the power down level.
    //
    if(fSuspend)
    {
        PowerState.DeviceState = deviceExtension->PowerDownLevel;
    }

    //
    // Otherwise, set our device state to D0.
    //
    else
    {
        PowerState.DeviceState = PowerDeviceD0;
    }

    //
    // Self request a power state change to the desired power state.
    //

⌨️ 快捷键说明

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