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

📄 mavusb.c

📁 基于EP7312的MP3播放器源代码,包括MCU和PC端代码.
💻 C
📖 第 1 页 / 共 2 页
字号:
//****************************************************************************
//
// MAVUSB.C - Maverick(tm) USB Driver.
//
// 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"
#include "mavguid.h"

//****************************************************************************
//
// Installable driver initialization entry point.  This entry point is called
// directly by the I/O system.
//
// Arguments:
//
//     DriverObject - pointer to the driver object.
//
//     RegistryPath - pointer to a unicode string representing the path to
//                    the driver-specific key in the registry.
//
// Return Value:
//
//     STATUS_SUCCESS if successful,
//     STATUS_UNSUCCESSFUL otherwise
//
//****************************************************************************
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;

    //
    // Create dispatch points for create, close, unload.
    //
    DriverObject->MajorFunction[IRP_MJ_CREATE] = MavUsb_Create;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = MavUsb_Close;
    DriverObject->DriverUnload = MavUsb_Unload;

    //
    // User mode DeviceIoControl() calls will be routed here.
    //
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MavUsb_ProcessIOCTL;

    //
    // User mode ReadFile()/WriteFile() calls will be routed here.
    //
    DriverObject->MajorFunction[IRP_MJ_WRITE] = MavUsb_Write;
    DriverObject->MajorFunction[IRP_MJ_READ] = MavUsb_Read;

    //
    // routines for handling system PnP and power management requests
    //
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] =
        MavUsb_ProcessSysControlIrp;
    DriverObject->MajorFunction[IRP_MJ_PNP] = MavUsb_ProcessPnPIrp;
    DriverObject->MajorFunction[IRP_MJ_POWER] = MavUsb_ProcessPowerIrp;

    //
    // The Functional Device Object (FDO) will not be created for PNP devices
    // until this routine is called upon device plug-in.
    //
    DriverObject->DriverExtension->AddDevice = MavUsb_PnPAddDevice;

    //
    // Return success.
    //
    return(STATUS_SUCCESS);
}

//****************************************************************************
//
// Main dispatch table routine for IRP_MJ_SYSTEM_CONTROL IRPs.  We basically
// just pass these down to the PDO.
//
// Arguments:
//
//     DeviceObject - pointer to FDO device object
//
//     Irp - pointer to an I/O Request Packet
//
// Return Value:
//
//     Status returned from lower driver
//
//****************************************************************************
NTSTATUS
MavUsb_ProcessSysControlIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{

    PIO_STACK_LOCATION irpStack;
    PDEVICE_EXTENSION deviceExtension;
    NTSTATUS ntStatus = STATUS_SUCCESS;
    NTSTATUS waitStatus;
    PDEVICE_OBJECT stackDeviceObject;

    //
    // Set our status for this IRP to success.
    //
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

    //
    // 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 device extension.
    //
    deviceExtension = DeviceObject->DeviceExtension;

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

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

    //
    // Copy this IRP to the next location in the IRP stack.
    //
    IoCopyCurrentIrpStackLocationToNext(Irp);

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

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

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

//****************************************************************************
//
// Free all the allocated resources, etc.
//
// Arguments:
//
//     DriverObject - pointer to a driver object
//
// Return Value:
//
//     None.
//
//****************************************************************************
VOID
MavUsb_Unload(IN PDRIVER_OBJECT DriverObject)
{
    //
    // Free any global resources allocated in DriverEntry.  We have few or none
    // because for a PNP device, almost all allocation is done in
    // PnpAddDevice() and all freeing while handling IRP_MN_REMOVE_DEVICE.
    //
}

//****************************************************************************
//
// This routine is called to create and initialize a GUID-based symbolic link
// to our device to be used to open/create instances of us from user mode.
//
// Called from MavUsb_CreateDeviceObject() to create the link.
//
// Arguments:
//
//     DeviceObject - pointer to our Physical Device Object (PDO)
//
//     deviceLinkUnicodeString - Points to a unicode string structure
//                               allocated by the caller.
//
// If this routine is successful, it initializes the unicode string and
// allocates the string buffer containing the kernel-mode path to the symbolic
// link for this device interface.
//
// Return Value:
//
//     STATUS_SUCCESS if successful,
//     STATUS_UNSUCCESSFUL otherwise
//
//****************************************************************************
NTSTATUS
MavUsb_SymbolicLink(IN PDEVICE_OBJECT DeviceObject,
                    IN OUT PUNICODE_STRING deviceLinkUnicodeString)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;


    //
    // IoRegisterDeviceInterface registers device functionality (a device
    // interface) that a driver will enable for use by applications or other
    // system components.
    //
    ntStatus = IoRegisterDeviceInterface(DeviceObject,
                                         (LPGUID)&GUID_CLASS_MAVERICK,
                                         NULL, deviceLinkUnicodeString);

    //
    // See if it was successful.
    //
    if(NT_SUCCESS(ntStatus))
    {
        //
        // IoSetDeviceInterfaceState enables or disables a previously
        // registered device interface.  Applications and other system
        // components can open only interfaces that are enabled.
        //
        ntStatus = IoSetDeviceInterfaceState(deviceLinkUnicodeString, TRUE);
    }

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

//****************************************************************************
//
// Creates a Functional Device Object.
//
// Arguments:
//
//     DriverObject - pointer to the driver object for device
//
//     DeviceObject - pointer to DeviceObject pointer in which to return the
//                    created device object.
//
//     Instance - instance of the device create.
//
// Return Value:
//
//     STATUS_SUCCESS if successful,
//     STATUS_UNSUCCESSFUL otherwise
//
//****************************************************************************
NTSTATUS
MavUsb_CreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
                          IN PDEVICE_OBJECT PhysicalDeviceObject,
                          IN PDEVICE_OBJECT *DeviceObject)
{
    NTSTATUS ntStatus;
    UNICODE_STRING deviceLinkUnicodeString;
    PDEVICE_EXTENSION deviceExtension;
    USHORT i;

    //
    // Create the symbolic link for our device.
    //
    ntStatus = MavUsb_SymbolicLink(PhysicalDeviceObject,
                                   &deviceLinkUnicodeString);

    //
    // See if we were able to create the symbolic link.
    //
    if(NT_SUCCESS(ntStatus))
    {
        //
        // Create the device.
        //
        ntStatus = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION),
                                  NULL, FILE_DEVICE_UNKNOWN,
                                  FILE_AUTOGENERATED_DEVICE_NAME,
                                  FALSE, DeviceObject);

        //
        // See if we were able to create the device.
        //
        if(NT_SUCCESS(ntStatus))
        {
            //
            // Get a pointer to the device extension.
            //
            deviceExtension = (*DeviceObject)->DeviceExtension;
        }
        else
        {
            //
            // We could not create the device, so return the failure.
            //
            return(ntStatus);
        }

        //
        // Save the name of our functional device object link.  The name is
        // generated based on the driver's class GUID.
        //
        RtlCopyMemory(deviceExtension->DeviceLinkNameBuffer,
                      deviceLinkUnicodeString.Buffer,
                      deviceLinkUnicodeString.Length);

        //
        // This event is triggered when there is no pending IO of any kind and
        // device is removed.
        //
        KeInitializeEvent(&deviceExtension->RemoveEvent, NotificationEvent,
                          FALSE);

        //
        // This event is triggered when self-requested power irps complete.
        //
        KeInitializeEvent(&deviceExtension->SelfRequestedPowerIrpEvent,
                          NotificationEvent, FALSE);

        //
        // This event is triggered when there is no pending IO (pending IO
        // count == 1)
        //
        KeInitializeEvent(&deviceExtension->NoPendingIoEvent,
                          NotificationEvent, FALSE);

        //
        // This spinlock used to protect increment/decrement IO count logic.
        //
        KeInitializeSpinLock(&deviceExtension->IoCountSpinLock);

        //
        // Free buffer from unicode string we used to initialize interface.
        //
        RtlFreeUnicodeString(&deviceLinkUnicodeString);
    }

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

//****************************************************************************
//
// Passes a URB to the USBD class driver.  The client device driver passes USB
// request block (URB) structures to the class driver as a parameter in an IRP
// with Irp->MajorFunction set to IRP_MJ_INTERNAL_DEVICE_CONTROL and the next
// IRP stack location Parameters.DeviceIoControl.IoControlCode field set to
// IOCTL_INTERNAL_USB_SUBMIT_URB.
//
// Arguments:
//
//     DeviceObject - pointer to the physical device object (PDO)
//
//     Urb - pointer to an already-formatted Urb request block
//
// Return Value:
//
//     STATUS_SUCCESS if successful,
//     STATUS_UNSUCCESSFUL otherwise
//
//****************************************************************************
NTSTATUS
MavUsb_CallUSBD(IN PDEVICE_OBJECT DeviceObject, IN PURB Urb)
{
    NTSTATUS ntStatus, status = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension;
    PIRP irp;
    KEVENT event;
    IO_STATUS_BLOCK ioStatus;
    PIO_STACK_LOCATION nextStack;

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

    //
    // Initialize the completion event.
    //
    KeInitializeEvent(&event, NotificationEvent, FALSE);

    //
    // Build the IRP.
    //
    irp =
        IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
                                      deviceExtension->TopOfStackDeviceObject,
                                      NULL, 0, NULL, 0, TRUE, &event,
                                      &ioStatus);

    //
    // As an alternative, we could call KeDelayExecutionThread, wait for some
    // period of time, and try again....but we keep it simple for right now.
    //
    if(!irp)
    {
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    //
    // Get the next location on the IRP stack.
    //
    nextStack = IoGetNextIrpStackLocation(irp);

    //
    // Place the URB in the arguments of the next location in the IRP stack.
    //
    nextStack->Parameters.Others.Argument1 = Urb;

    //
    // Send the IRP to the PDO.
    //
    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);

    //
    // See if the status is pending.
    //
    if(ntStatus == STATUS_PENDING)
    {
        //
        // The status is pending, so wait for the IRP to complete.
        //
        KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
    }
    else
    {
        //
        // Set the status in the IO block.
        //
        ioStatus.Status = ntStatus;
    }

    //
    // USBD maps the error code for us.
    //
    ntStatus = ioStatus.Status;

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

//****************************************************************************
//
// Initializes a given instance of the device on the USB and selects and saves
// the configuration.
//
// Arguments:
//
//     DeviceObject - pointer to the physical device object for this instance
//                    of the device.
//
// Return Value:
//
//     NT status code
//
//****************************************************************************
NTSTATUS
MavUsb_ConfigureDevice(IN PDEVICE_OBJECT DeviceObject)

⌨️ 快捷键说明

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