mavpwr.c

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

C
1,127
字号
    ntStatus = MavUsb_SelfRequestPowerIrp(DeviceObject, PowerState);

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

//****************************************************************************
//
// This routine is called by MavUsb_SelfSuspendOrActivate() to actually make
// the system request for a power down/up to PowerState.  It first checks to
// see if we are already in Powerstate and immediately returns SUCCESS with no
// further processing if so.
//
// Arguments:
//
//     DeviceObject - Pointer to the device object.
//
//     PowerState - power state requested, e.g PowerDeviceD0.
//
// Return Value:
//
//     The function value is the final status from the operation.
//
//****************************************************************************
NTSTATUS
MavUsb_SelfRequestPowerIrp(IN PDEVICE_OBJECT DeviceObject,
                           IN POWER_STATE PowerState)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension;
    PIRP pIrp = NULL;

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

    //
    // If we are already in the correct power state, then do nothing.
    //
    if(deviceExtension->CurrentDevicePowerState == PowerState.DeviceState)
    {
        //
        // Return success.
        //
        return(STATUS_SUCCESS);
    }

    //
    // Increment the count of pending IRPs.
    //
    MavUsb_IncrementIoCount(DeviceObject);

    //
    // Flag we're handling a self-generated power IRP.
    //
    deviceExtension->SelfPowerIrp = TRUE;

    //
    // Actually request the IRP.
    //
    ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
                                 IRP_MN_SET_POWER, PowerState,
                                 MavUsb_PoSelfRequestCompletion, DeviceObject,
                                 NULL);

    //
    // Make sure that the status was pending.
    //
    if(ntStatus == STATUS_PENDING)
    {
        //
        // We only need to wait for completion if we're powering up.
        //
        if((ULONG)PowerState.DeviceState < deviceExtension->PowerDownLevel)
        {
            //
            // Wait for the IRP to complete.
            //
            KeWaitForSingleObject(&deviceExtension->SelfRequestedPowerIrpEvent,
                                  Suspended, KernelMode, FALSE, NULL);
        }

        //
        // Set the status to success.
        //
        ntStatus = STATUS_SUCCESS;

        //
        // Indicate that we are no longer processing a self-power IRP.
        //
        deviceExtension->SelfPowerIrp = FALSE;
    }

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

//****************************************************************************
//
// This routine is called when the driver completes a self-originated power
// IRP that was generated by a call to BulkUsb_SelfSuspendOrActivate().
//
// We power down whenever the last pipe is closed and power up when the first
// pipe is opened.
//
// For power-up, we set an event in our FDO extension to signal this IRP done
// so the power request can be treated as a synchronous call.
//
// We need to know the device is powered up before opening the first pipe, for
// example.
//
// For power-down, we do not set the event, as no caller waits for power down
// complete.
//
// Arguments:
//
//     DeviceObject - Pointer to the device object for the class device.
//                    (Physical Device Object)
//
//     Context - Driver defined context, in this case our FDO (functional
//               device object)
//
// Return Value:
//
//     The function value is the final status from the operation.
//
//****************************************************************************
NTSTATUS
MavUsb_PoSelfRequestCompletion(IN PDEVICE_OBJECT DeviceObject,
                               IN UCHAR MinorFunction,
                               IN POWER_STATE PowerState, IN PVOID Context,
                               IN PIO_STATUS_BLOCK IoStatus)
{
    PDEVICE_OBJECT deviceObject = Context;
    PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
    NTSTATUS ntStatus = IoStatus->Status;

    //
    // We only need to set the event if we're powering up; no caller waits on
    // power down complete.
    //
    if((ULONG)PowerState.DeviceState < deviceExtension->PowerDownLevel)
    {
        //
        // Trigger self-requested power IRP completed event; the caller is
        // waiting for completion.
        //
        KeSetEvent(&deviceExtension->SelfRequestedPowerIrpEvent, 1, FALSE);
    }

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

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

//****************************************************************************
//
// This routine is called when an IRP_MN_SET_POWER of type 'DevicePowerState'
// has been received by MavUsb_ProcessPowerIrp().
//
// Arguments:
//
//     DeviceObject - Pointer to the device object for the class device.
//
//     DeviceState - Device specific power state to set the device in to.
//
// Return Value:
//
//     For requests to DeviceState D0 (fully on), returns TRUE to signal caller
//     that we must set a completion routine and finish there.
//
//****************************************************************************
BOOLEAN
MavUsb_SetDevicePowerState(IN PDEVICE_OBJECT DeviceObject,
                           IN DEVICE_POWER_STATE DeviceState)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension;
    BOOLEAN fRes = FALSE;

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

    //
    // Determine the power state we are changing to.
    //
    switch(DeviceState)
    {
        //
        // The device will be turning off.
        //
        case PowerDeviceD3:
        {
            //
            // Set the device power state.
            //
            deviceExtension->CurrentDevicePowerState = DeviceState;

            //
            // We're done handling this power state.
            //
            break;
        }

        //
        // Power states D1 and D2 translate to USB suspend.
        //
        case PowerDeviceD1:
        case PowerDeviceD2:
        {
            //
            // Set the device power state.
            //
            deviceExtension->CurrentDevicePowerState = DeviceState;

            //
            // We're done handling these power states.
            //
            break;
        }

        //
        // The device will be turning on.
        //
        case PowerDeviceD0:
        {
            //
            // We'll need to finish the rest in the completion routine; signal
            // caller we're going to D0 and will need to set a completion
            // routine.
            //
            fRes = TRUE;

            //
            // Caller will pass on to PDO (Physical Device Object).
            //
            break;
        }
    }

    //
    // Return the result.
    //
    return(fRes);
}

//****************************************************************************
//
// This routine generates an internal IRP from this driver to the lower
// portion of the driver stack to obtain information on the Device Object's
// capabilities.  We are most interested in learning which system power states
// are to be mapped to which device power states for honoring IRP_MJ_SET_POWER
// IRPs.
//
// This is a blocking call which waits for the IRP completion routine to set
// an event on finishing.
//
// Arguments:
//
//     LowerDeviceObject - DeviceObject beneath this driver in the stack.
//
// Return Value:
//
//     NTSTATUS value from the IoCallDriver() call.
//
//****************************************************************************
NTSTATUS
MavUsb_QueryCapabilities(IN PDEVICE_OBJECT LowerDeviceObject,
                         IN PDEVICE_CAPABILITIES DeviceCapabilities)
{
    PIO_STACK_LOCATION nextStack;
    PIRP irp;
    NTSTATUS ntStatus;
    KEVENT event;

    //
    // This is a DDK-defined DBG-only macro that ASSERTS we are not running
    // pageable code at higher than APC_LEVEL.
    //
    PAGED_CODE();

    //
    // Build an IRP for us to generate an internal query request to the PDO.
    //
    irp = IoAllocateIrp(LowerDeviceObject->StackSize, FALSE);
    if(!irp)
    {
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    //
    // Preinit the device capability structures appropriately.
    //
    RtlZeroMemory(DeviceCapabilities, sizeof(DEVICE_CAPABILITIES));
    DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
    DeviceCapabilities->Version = 1;
    DeviceCapabilities->Address = -1;
    DeviceCapabilities->UINumber = -1;

    //
    // IoGetNextIrpStackLocation gives a higher level driver access to the
    // next-lower driver's I/O stack location in an IRP so the caller can set
    // it up for the lower driver.
    //
    nextStack = IoGetNextIrpStackLocation(irp);
    nextStack->MajorFunction= IRP_MJ_PNP;
    nextStack->MinorFunction= IRP_MN_QUERY_CAPABILITIES;

    //
    // Init an event to tell us when the completion routine's been called.
    //
    KeInitializeEvent(&event, NotificationEvent, FALSE);

    //
    // Set a completion routine so it can signal our event when the next lower
    // driver is done with the IRP.
    //
    IoSetCompletionRoutine(irp, MavUsb_IrpCompletionRoutine, &event, TRUE,
                           TRUE, TRUE);

    //
    // Set our pointer to the DEVICE_CAPABILITIES struct.
    //
    nextStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;

    //
    // Preset the IRP to report not supported.
    //
    irp->IoStatus.Status = STATUS_NOT_SUPPORTED;

    //
    // Pass the IRP to the lower level device object.
    //
    ntStatus = IoCallDriver(LowerDeviceObject, irp);

    //
    // See if we need to wait for the IRP to complete.
    //
    if(ntStatus == STATUS_PENDING)
    {
        //
        // Wait for the IRP to complete.
        //
        KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);

        //
        // Get the status from the IRP.
        //
        ntStatus = irp->IoStatus.Status;
    }

    //
    // Free the IRP.
    //
    IoFreeIrp(irp);

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

⌨️ 快捷键说明

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