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

📄 mavocrw.c

📁 基于EP7312的MP3播放器源代码,包括MCU和PC端代码.
💻 C
📖 第 1 页 / 共 2 页
字号:
//****************************************************************************
//
// MAVOCRW.C - Routines to handle IRP_MJ_CREATE, IRP_MJ_CLOSE, IRP_MJ_READ,
//             and IRP_MJ_WRITE.
//
// 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 "../../player/usbven.h"

//****************************************************************************
//
// This is the dispatch table routine for IRP_MJ_CREATE.  It's the entry point
// for CreateFile() calls.  User mode apps may open "<name genned fron GUID>".
//
// Arguments:
//
//     DeviceObject - pointer to our FDO (Functional Device Object)
//
//     Irp - pointer to the IRP
//
// Return Value:
//
//     NT status code
//
//****************************************************************************
NTSTATUS
MavUsb_Create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension;

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

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

    //
    // Can't accept a new IO 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 device is pending.
        //
        ntStatus = STATUS_DELETE_PENDING;
    }

    //
    // Only allow two opens.
    //
    else if(deviceExtension->OpenPipeCount == 2)
    {
        //
        // Indicate that the device is busy.
        //
        ntStatus = STATUS_DEVICE_BUSY;
    }

    //
    // Open the device.
    //
    else
    {
        //
        // Indicate that the device is open.
        //
        deviceExtension->OpenPipeCount++;

        //
        // See if this is the first open on the device.
        //
        if(deviceExtension->OpenPipeCount == 1)
        {
            //
            // Power up the device if its not in D0.
            //
            MavUsb_SelfSuspendOrActivate(DeviceObject, FALSE);

            //
            // Send a connect message to the device.
            //
            if(MavUsb_VendorConnect(DeviceObject) != STATUS_SUCCESS)
            {
                //
                // Power down the device.
                //
                MavUsb_SelfSuspendOrActivate(DeviceObject, TRUE);

                //
                // Indicate that the device is not open.
                //
                deviceExtension->OpenPipeCount--;

                //
                // Indicate that there was a device IO error.
                //
                ntStatus = STATUS_IO_DEVICE_ERROR;
            }
        }
    }

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

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

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

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

//****************************************************************************
//
// This is the dispatch table routine for IRP_MJ_CLOSE.  It handles user mode
// CloseHandle() calls.
//
// Arguments:
//
//     DeviceObject - pointer to our FDO (Functional Device Object)
//
//     Irp - pointer to the IRP
//
// Return Value:
//
//     NT status code
//
//****************************************************************************
NTSTATUS
MavUsb_Close(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    PDEVICE_EXTENSION deviceExtension;

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

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

    //
    // Indicate that the device is not open.
    //
    deviceExtension->OpenPipeCount--;

    //
    // Send a disconnect message to the device if this is the last opened
    // handle.
    //
    if(deviceExtension->OpenPipeCount == 0)
    {
        MavUsb_VendorDisconnect(DeviceObject);
    }

    //
    // Set the status in the IRP.
    //
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;

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

    //
    // Power down the device if this was the last opened handle.
    //
    if(deviceExtension->OpenPipeCount == 0)
    {
        MavUsb_SelfSuspendOrActivate(DeviceObject, TRUE);
    }

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

    //
    // Success.
    //
    return(STATUS_SUCCESS);
}

//****************************************************************************
//
// This is the IRP_MJ_READ routine set in our dispatch table; ReadFile() calls
// from user mode ultimately land here.
//
// Arguments:
//
//     DeviceObject - pointer to the device object for this instance of the
//                    device.
//
//     IRP - pointer to the IRP_MJ_READ
//
// Return Value:
//
//     NT status code
//
//****************************************************************************
NTSTATUS
MavUsb_Read(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    PDEVICE_EXTENSION deviceExtension;
    NTSTATUS ntStatus;
    USBD_PIPE_HANDLE pipeHandle;
    PURB urb;
    PMDL mdl;
    PVOID va;
    ULONG size, offset, length, readsize;

    //
    // Set the initial status in the IRP to pending.
    //
    Irp->IoStatus.Information = STATUS_PENDING;

    //
    // Set the initial count of byte read to zero.
    //
    Irp->IoStatus.Information = 0;

    //
    // Can't accept a new IO 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))
    {
        //
        // Set the status in the IRP to delete pending.
        //
        Irp->IoStatus.Status = STATUS_DELETE_PENDING;

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

        //
        // Return a delete pending status.
        //
        return(STATUS_DELETE_PENDING);
    }

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

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

    //
    // Get the length of the requested transfer.  The MDL address could be NULL
    // for a zero length request.
    //
    if(Irp->MdlAddress)
    {
        length = MmGetMdlByteCount(Irp->MdlAddress);
    }
    else
    {
        length = 0;
    }

    //
    // If the length of the transfer is zero, then return success.
    //
    if(length == 0)
    {
        //
        // Set the status in the IRP to success.
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;

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

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

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

    //
    // Get the virtual address for the buffer described by the input IRP's MDL.
    //
    va = MmGetMdlVirtualAddress(Irp->MdlAddress);

    //
    // Allocate memory for the URB to be sent to the USB driver.
    //
    urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB) + 4);
    if(!urb)
    {
        //
        // Set the status in the IRP to insufficient resources.
        //
        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;

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

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

        //
        // Return an insufficient resources status.
        //
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    //
    // Indicate that a staged IO operation is pending.
    //
    deviceExtension->StagedIoPending = TRUE;

    //
    // Send read requests to the device until we've filled the entire data
    // buffer.
    //
    offset = 0;
    while(offset != length)
    {
        //
        // Make sure that we can still send IO requests.
        //
        if(!MavUsb_CanAcceptIoRequests(DeviceObject))
        {
            break;
        }

        //
        // Determine the length of the next read.
        //
        if((offset + 16384) > length)
        {
            readsize = length - offset;
        }
        else
        {
            readsize = 16384;
        }

        //
        // Build the URB for the vendor read request.
        //
        size = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST);
        UsbBuildVendorRequest(urb, URB_FUNCTION_VENDOR_DEVICE, (USHORT)size,
                              USBD_TRANSFER_DIRECTION_IN |
                              USBD_SHORT_TRANSFER_OK, 0, USB_Vendor_Read,
                              (USHORT)readsize, 0, urb + 1, NULL, 4, NULL);

        //
        // Send the vendor read command to the USB driver.
        //
        ntStatus = MavUsb_CallUSBD(DeviceObject, urb);
        if(!NT_SUCCESS(ntStatus))
        {
            break;
        }

        //
        // Get the length of the read from the result of the vendor command.
        //
        readsize = *((ULONG *)(urb + 1));

        //
        // Stop reading if the size of the read is zero.
        //
        if(readsize == 0)
        {
            break;
        }

        //
        // Allocate an MDL to describe the portion of the buffer for this bulk
        // transfer.
        //
        mdl = IoAllocateMdl(va, length, FALSE, FALSE, NULL);
        if(!mdl)
        {
            break;
        }

        //
        // Map the next portion of the read buffer to receive the data from
        // this read.
        //
        IoBuildPartialMdl(Irp->MdlAddress, mdl, (PUCHAR)va + offset, readsize);

        //
        // Get the pipe handle for the bulk in pipe.
        //
        pipeHandle = deviceExtension->UsbInterface->Pipes[0].PipeHandle;

        //
        // Build the URB for the bulk in transfer request.
        //
        size = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
        UsbBuildInterruptOrBulkTransferRequest(urb, (USHORT)size, pipeHandle,
                                               NULL, mdl, readsize,
                                               USBD_TRANSFER_DIRECTION_IN |
                                               USBD_SHORT_TRANSFER_OK, NULL);

        //
        // Send this bulk in transfer request to the USB driver.
        //
        ntStatus = MavUsb_CallUSBD(DeviceObject, urb);

        //
        // Free the MDL,
        //
        IoFreeMdl(mdl);

        //
        // Stop reading if the bulk in transfer request failed.
        //
        if(!NT_SUCCESS(ntStatus))
        {
            break;
        }

        //
        // Increment the buffer pointer.
        //
        offset += readsize;

⌨️ 快捷键说明

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