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

📄 mavpnp.c

📁 基于EP7312的MP3播放器源代码,包括MCU和PC端代码.
💻 C
📖 第 1 页 / 共 3 页
字号:
//****************************************************************************
//
// MAVPNP.C - Routines to handle Plug-N-Play IRPs.
//
// Copyright (c) 2000 Cirrus Logic, Inc.
// Copyright (c) 1997-1998 Microsoft Corporation.  All Rights Reserved.
//   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//   KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//   IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
//   PURPOSE.
//
//****************************************************************************
#include "wdm.h"
#include "usbdi.h"
#include "usbdlib.h"
#include "mavusb.h"
#include "mavproto.h"

//****************************************************************************
//
// Dispatch table routine for IRP_MJ_PNP.  Process the Plug and Play IRPs sent
// to this device.
//
// Arguments:
//
//     DeviceObject - pointer to our FDO (Functional Device Object)
//
//     Irp - pointer to an I/O Request Packet
//
// Return Value:
//
//     NT status code
//
//****************************************************************************
NTSTATUS
MavUsb_ProcessPnPIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    PIO_STACK_LOCATION irpStack;
    PDEVICE_EXTENSION deviceExtension;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_OBJECT stackDeviceObject;
    KEVENT startDeviceEvent;

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

    //
    // Get a pointer to the current location in the IRP stack.  This is where
    // the function codes and parameters are located.
    //
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // Get a pointer to the PDO.
    //
    stackDeviceObject = deviceExtension->TopOfStackDeviceObject;

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

    //
    // Determine what to do based on the minor function in the IRP.
    //
    switch(irpStack->MinorFunction)
    {
        //
        // The PnP Manager sends this IRP after it has assigned resources, if
        // any, to the device.  The device may have been recently enumerated
        // and is being started for the first time, or the device may be
        // restarting after being stopped for resource reconfiguration.
        //
        case IRP_MN_START_DEVICE:
        {
            //
            // Initialize an event we can wait on for the PDO to be done with
            // this IRP.
            //
            KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
            IoCopyCurrentIrpStackLocationToNext(Irp);

            //
            // Set a completion routine so it can signal our event when the PDO
            // is done with the IRP.
            //
            IoSetCompletionRoutine(Irp, MavUsb_IrpCompletionRoutine,
                                   &startDeviceEvent, TRUE, TRUE, TRUE);

            //
            // Pass the IRP to the PDO.
            //
            ntStatus = IoCallDriver(stackDeviceObject, Irp);

            //
            // If PDO is not done yet, wait for the event to be set in our
            // completion routine.
            //
            if(ntStatus == STATUS_PENDING)
            {
                //
                // Wait for IRP to complete.
                //
                KeWaitForSingleObject(&startDeviceEvent, Suspended, KernelMode,
                                      FALSE, NULL);

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

            //
            // See if the PDO successfully handled the IRP.
            //
            if(NT_SUCCESS(ntStatus))
            {
                //
                // Now we're ready to do our own startup processing.  USB
                // client drivers such as us set up URBs (USB Request Packets)
                // to send requests to the host controller driver (HCD).  The
                // URB structure defines a format for all possible commands
                // that can be sent to a USB device.  Here, we request the
                // device descriptor and store it, and configure the device.
                //
                ntStatus = MavUsb_StartDevice(DeviceObject);

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

            //
            // Complete the IRP.
            //
            IoCompleteRequest(Irp, IO_NO_INCREMENT);

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

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

        //
        // The IRP_MN_QUERY_STOP_DEVICE/IRP_MN_STOP_DEVICE sequence only occurs
        // during "polite" shutdowns, such as the user explicitily requesting
        // the service be stopped in, or requesting unplug from the PnP tray
        // icon.  This sequence is NOT received during "impolite" shutdowns,
        // such as someone suddenly yanking the USB cord or otherwise
        // unexpectedly disabling/resetting the device.
        //
        // If a driver sets STATUS_SUCCESS for this IRP, the driver must not
        // start any operations on the device that would prevent that driver
        // from successfully completing an IRP_MN_STOP_DEVICE for the device.
        //
        // For mass storage devices such as disk drives, while the device is in
        // the stop-pending state, the driver holds IRPs that require access to
        // the device, but for most USB devices, there is no 'persistent
        // storage', so we will just refuse any more IO until restarted or the
        // stop is cancelled.
        //
        // If a driver in the device stack determines that the device cannot be
        // stopped for resource reconfiguration, the driver is not required to
        // pass the IRP down the device stack.  If a query-stop IRP fails, the
        // PnP Manager sends an IRP_MN_CANCEL_STOP_DEVICE to the device stack,
        // notifying the drivers for the device that the query has been
        // cancelled and that the device will not be stopped.
        //
        case IRP_MN_QUERY_STOP_DEVICE:
        {
            //
            // It is possible to receive this IRP when the device has not been
            // started (as on a boot device).
            //
            if(!deviceExtension->DeviceStarted)
            {
                //
                // If we've never been started, just pass it on.
                //
                IoSkipCurrentIrpStackLocation(Irp);
                ntStatus =
                    IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);

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

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

            //
            // Fail the request if we have any read/write IRPs pending.
            //
            if(deviceExtension->StagedIoPending)
            {
                ntStatus = STATUS_UNSUCCESSFUL;
            }
            else
            {
                //
                // We'll not veto it; pass it on and flag that stop was
                // requested.  Once StopDeviceRequested is set no new IOCTL or
                // read/write IRPs will be passed down the stack to lower
                // drivers; all will be quickly failed.
                //
                deviceExtension->StopDeviceRequested = TRUE;

                //
                // Set the IRP status to success.
                //
                Irp->IoStatus.Status = STATUS_SUCCESS;
            }

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

        //
        // The PnP Manager uses this IRP to inform the drivers for a device
        // that the device will not be stopped for resource reconfiguration.
        // This should only be received after a successful
        // IRP_MN_QUERY_STOP_DEVICE.
        //
        case IRP_MN_CANCEL_STOP_DEVICE:
        {
            //
            // It is possible to receive this IRP when the device has not been
            // started.
            //
            if(!deviceExtension->DeviceStarted)
            {
                //
                // If we've never been started, just pass it on.
                //
                IoSkipCurrentIrpStackLocation(Irp);
                ntStatus =
                    IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);

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

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

            //
            // Reset this flag so new IOCTL and IO IRP processing will be
            // re-enabled.
            //
            deviceExtension->StopDeviceRequested = FALSE;

            //
            // Set the IRP status to success.
            //
            Irp->IoStatus.Status = STATUS_SUCCESS;

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

        //
        // The PnP Manager sends this IRP to stop a device so it can
        // reconfigure its hardware resources.  The PnP Manager only sends this
        // IRP if a prior IRP_MN_QUERY_STOP_DEVICE completed successfully.
        //
        case IRP_MN_STOP_DEVICE:
        {
            //
            // Send the select configuration urb with a NULL pointer for the
            // configuration handle.  This closes the configuration and puts
            // the device in the 'unconfigured' state.
            //
            ntStatus = MavUsb_StopDevice(DeviceObject);

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

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

        //
        // In response to this IRP, drivers indicate whether the device can be
        // removed without disrupting the system.
        //
        // If a driver determines it is safe to remove the device, the driver
        // completes any outstanding I/O requests, arranges to hold any
        // subsequent read/write requests, and sets Irp->IoStatus.Status to
        // STATUS_SUCCESS.  Function and filter drivers then pass the IRP to
        // the next-lower driver in the device stack.  The underlying bus
        // driver calls IoCompleteRequest.
        //
        // If a driver sets STATUS_SUCCESS for this IRP, the driver must not
        // start any operations on the device that would prevent that driver
        // from successfully completing an IRP_MN_REMOVE_DEVICE for the device.
        // If a driver in the device stack determines that the device cannot be
        // removed, the driver is not required to pass the query-remove IRP
        // down the device stack.  If a query-remove IRP fails, the PnP Manager
        // sends an IRP_MN_CANCEL_REMOVE_DEVICE to the device stack, notifying
        // the drivers for the device that the query has been cancelled and
        // that the device will not be removed.
        //
        case IRP_MN_QUERY_REMOVE_DEVICE:
        {
            //
            // It is possible to receive this IRP when the device has not been
            // started.
            //
            if(!deviceExtension->DeviceStarted)
            {
                //
                // If we've never been started, just pass it on.
                //
                IoSkipCurrentIrpStackLocation(Irp);
                ntStatus =
                    IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);

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

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

            //
            // Once RemoveDeviceRequested is set no new IOCTL or read/write
            // IRPs will be passed down the stack to lower drivers; all will be

⌨️ 快捷键说明

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