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

📄 isodev.c

📁 传说中的 usb 端口 驱动 源码 啊啊啊啊啊啊啊
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 2004  Microsoft Corporation

Module Name:

    isodev.c

Abstract:

    This file contains dispatch routines for create and close.

    This file also contains routines to selectively suspend the device.
    The selective suspend feature is usb specific and not hardware
    specific.

Environment:

    Kernel mode

Notes:

    Copyright (c) 2004 Microsoft Corporation.
    All Rights Reserved.

--*/

#include "isousb.h"
#include "isopnp.h"
#include "isopwr.h"
#include "isodev.h"
#include "isousr.h"
#include "isowmi.h"
#include "isorwr.h"
#include "isostrm.h"

NTSTATUS
IsoUsb_DispatchCreate(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
/*++

Routine Description:

    Dispatch routine for create.

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet.

Return Value:

    NT status value

--*/
{
    PDEVICE_EXTENSION       deviceExtension;
    PIO_STACK_LOCATION      irpStack;
    PFILE_OBJECT            fileObject;
    PFILE_OBJECT_CONTENT    fileObjectContent;
    LONG                    i;
    NTSTATUS                ntStatus;

    PAGED_CODE();

    //
    // initialize variables
    //
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    irpStack = IoGetCurrentIrpStackLocation(Irp);

    fileObject = irpStack->FileObject;

    IsoUsb_DbgPrint(3, ("IsoUsb_DispatchCreate - begins\n"));

    if (deviceExtension->DeviceState != Working)
    {
        ntStatus = STATUS_INVALID_DEVICE_STATE;
        goto IsoUsb_DispatchCreate_Exit;
    }

    if (fileObject)
    {
        fileObject->FsContext = NULL;
    }
    else
    {
        ntStatus = STATUS_INVALID_PARAMETER;
        goto IsoUsb_DispatchCreate_Exit;
    }

    fileObject->FsContext = ExAllocatePool(NonPagedPool,
                                           sizeof(FILE_OBJECT_CONTENT));

    if (NULL == fileObject->FsContext)
    {
        IsoUsb_DbgPrint(1, ("failed to alloc memory for FILE_OBJECT_CONTENT\n"));

        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        goto IsoUsb_DispatchCreate_Exit;
    }

    // Exclude configuration changes while trying to open a pipe
    //
    KeWaitForSingleObject(&deviceExtension->ConfigurationSemaphore,
                          Executive,
                          KernelMode,
                          FALSE,
                          NULL);

    fileObjectContent = (PFILE_OBJECT_CONTENT) fileObject->FsContext;
    fileObjectContent->PipeInformation = NULL;
    fileObjectContent->StreamInformation = NULL;

    if (fileObject->FileName.Length != 0)
    {
        // Convert the pipe name string into a pipe number
        //
        i = IsoUsb_ParseStringForPipeNumber(&fileObject->FileName);

        IsoUsb_DbgPrint(3, ("create request for pipe # %X\n", i));

        // Bounds check the pipe number
        //
        if ((i < 0) || (i >= (LONG)(deviceExtension->NumberOfPipes)))
        {
            // Failure opening a pipe
            //
            IsoUsb_DbgPrint(1, ("invalid pipe number\n"));

            ExFreePool(fileObject->FsContext);

            fileObject->FsContext = NULL;

            ntStatus = STATUS_INVALID_PARAMETER;
        }
        else
        {
            // Success opening a pipe
            //
            fileObjectContent->PipeInformation =
                (PVOID) deviceExtension->PipeInformation[i];

            InterlockedIncrement(&deviceExtension->OpenHandleCount);

            ntStatus = STATUS_SUCCESS;
        }
    }
    else
    {
        // No pipe name string, Success opening entire device
        //
        InterlockedIncrement(&deviceExtension->OpenHandleCount);

        ntStatus = STATUS_SUCCESS;
    }

    KeReleaseSemaphore(&deviceExtension->ConfigurationSemaphore,
                       IO_NO_INCREMENT,
                       1,
                       FALSE);

    // The device is idle if it has no open handles or pending PnP Irps.
    // Since we just received an open handle request, cancel idle req.
    //
    if (NT_SUCCESS(ntStatus) && deviceExtension->SSEnable)
    {
        CancelSelectSuspend(deviceExtension);
    }

IsoUsb_DispatchCreate_Exit:

    Irp->IoStatus.Status = ntStatus;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    IsoUsb_DbgPrint(3, ("IsoUsb_DispatchCreate - ends\n"));

    return ntStatus;
}

NTSTATUS
IsoUsb_DispatchClose(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
/*++

Routine Description:

    Dispatch routine for close.

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet

Return Value:

    NT status value

--*/
{
    PDEVICE_EXTENSION       deviceExtension;
    PIO_STACK_LOCATION      irpStack;
    PFILE_OBJECT            fileObject;
    PFILE_OBJECT_CONTENT    fileObjectContent;


    NTSTATUS                ntStatus;

    PAGED_CODE();

    //
    // initialize variables
    //
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    irpStack = IoGetCurrentIrpStackLocation(Irp);

    fileObject = irpStack->FileObject;

    IsoUsb_DbgPrint(3, ("IsoUsb_DispatchClose - begins\n"));

    KeWaitForSingleObject(&deviceExtension->ConfigurationSemaphore,
                          Executive,
                          KernelMode,
                          FALSE,
                          NULL);

    if (fileObject && fileObject->FsContext)
    {
        fileObjectContent = (PFILE_OBJECT_CONTENT) fileObject->FsContext;

        ASSERT(NULL == fileObjectContent->StreamInformation);

        ExFreePool(fileObjectContent);

        fileObject->FsContext = NULL;
    }

    InterlockedDecrement(&deviceExtension->OpenHandleCount);

    KeReleaseSemaphore(&deviceExtension->ConfigurationSemaphore,
                       IO_NO_INCREMENT,
                       1,
                       FALSE);

    //
    // set ntStatus to STATUS_SUCCESS
    //
    ntStatus = STATUS_SUCCESS;

    Irp->IoStatus.Status = ntStatus;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    IsoUsb_DbgPrint(3, ("IsoUsb_DispatchClose - ends\n"));

    return ntStatus;
}


NTSTATUS
IsoUsb_IoctlSelectAltInterface(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    )
/*++

Routine Description:

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet

Return Value:

    NT status value

--*/
{
    PDEVICE_EXTENSION       deviceExtension;
    PIO_STACK_LOCATION      irpStack;
    PFILE_OBJECT            fileObject;
    PFILE_OBJECT_CONTENT    fileObjectContent;
    PUCHAR                  ioBuffer;
    ULONG                   inputBufferLength;
    UCHAR                   interfaceNumber;
    UCHAR                   alternateSetting;
    NTSTATUS                ntStatus;

    deviceExtension = DeviceObject->DeviceExtension;

    irpStack = IoGetCurrentIrpStackLocation(Irp);

    ioBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;

    inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;

    if (inputBufferLength != 2 * sizeof(UCHAR))
    {
        return STATUS_INVALID_BUFFER_SIZE;
    }

    interfaceNumber = ioBuffer[0];

    alternateSetting = ioBuffer[1];

    // Exclude other configuration changes and handle opens.
    //
    KeWaitForSingleObject(&deviceExtension->ConfigurationSemaphore,
                          Executive,
                          KernelMode,
                          FALSE,
                          NULL);

    fileObject = irpStack->FileObject;

    fileObjectContent = (PFILE_OBJECT_CONTENT) fileObject->FsContext;

    // Make sure there is only one handle open (i.e. the one that is
    // being used to issue this request) and it is for the entire
    // device, not for a pipe.
    //
    if (deviceExtension->OpenHandleCount == 1 &&
        fileObjectContent->PipeInformation == NULL)
    {
        ntStatus = IsoUsb_SelectAlternateInterface(DeviceObject,
                                                   interfaceNumber,
                                                   alternateSetting);
    }
    else
    {
        ntStatus = STATUS_DEVICE_BUSY;
    }

    // Allow other configuration changes and handle opens.
    //
    KeReleaseSemaphore(&deviceExtension->ConfigurationSemaphore,
                       IO_NO_INCREMENT,
                       1,
                       FALSE);

    return ntStatus;
}


NTSTATUS
IsoUsb_DispatchDevCtrl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

    Dispatch routine for IRP_MJ_DEVICE_CONTROL

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet

Return Value:

    NT status value

--*/
{
    ULONG              code;
    PVOID              ioBuffer;
    ULONG              inputBufferLength;
    ULONG              outputBufferLength;
    ULONG              info;
    NTSTATUS           ntStatus;
    PFILE_OBJECT       fileObject;
    PDEVICE_EXTENSION  deviceExtension;
    PIO_STACK_LOCATION irpStack;

    //
    // initialize variables
    //
    info = 0;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpStack->FileObject;
    code = irpStack->Parameters.DeviceIoControl.IoControlCode;
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    ioBuffer           = Irp->AssociatedIrp.SystemBuffer;
    inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    if(deviceExtension->DeviceState != Working) {

        IsoUsb_DbgPrint(1, ("Invalid device state\n"));

        Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
        Irp->IoStatus.Information = info;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return ntStatus;
    }

    IsoUsb_DbgPrint(3, ("IsoUsb_DispatchDevCtrl::"));
    IsoUsb_IoIncrement(deviceExtension);

    //
    // make sure that the selective suspend request has been completed.
    //
    if(deviceExtension->SSEnable) {

        //
        // It is true that the client driver cancelled the selective suspend
        // request in the dispatch routine for create.
        // But there is no guarantee that it has indeed been completed.
        // so wait on the NoIdleReqPendEvent and proceed only if this event
        // is signalled.
        //
        IsoUsb_DbgPrint(3, ("Waiting on the IdleReqPendEvent\n"));

        KeWaitForSingleObject(&deviceExtension->NoIdleReqPendEvent,
                              Executive,
                              KernelMode,
                              FALSE,
                              NULL);
    }

    switch(code) {

    case IOCTL_ISOUSB_RESET_PIPE:
    {
        PUSBD_PIPE_INFORMATION pipe;

        pipe = NULL;

        if(fileObject && fileObject->FsContext) {

            pipe = (PUSBD_PIPE_INFORMATION)
                   ((PFILE_OBJECT_CONTENT)fileObject->FsContext)->PipeInformation;
        }

        if(pipe == NULL) {

            ntStatus = STATUS_INVALID_PARAMETER;
        }
        else {

            ntStatus = IsoUsb_AbortResetPipe(DeviceObject,
                                             pipe->PipeHandle,
                                             TRUE);
        }

        break;
    }

    case IOCTL_ISOUSB_GET_CONFIG_DESCRIPTOR:
    {
        ULONG length;

        if(deviceExtension->ConfigurationDescriptor) {

            length = deviceExtension->ConfigurationDescriptor->wTotalLength;

            if(outputBufferLength >= length) {

                RtlCopyMemory(ioBuffer,
                              deviceExtension->ConfigurationDescriptor,
                              length);

                info = length;

                ntStatus = STATUS_SUCCESS;
            }
            else {

                ntStatus = STATUS_INVALID_BUFFER_SIZE;
            }
        }
        else {

            ntStatus = STATUS_UNSUCCESSFUL;
        }

        break;
    }

    case IOCTL_ISOUSB_RESET_DEVICE:

        ntStatus = IsoUsb_ResetDevice(DeviceObject);

        break;

    case IOCTL_ISOUSB_START_ISO_STREAM:

        ntStatus = IsoUsb_StartIsoStream(DeviceObject, Irp);

        return STATUS_SUCCESS;

    case IOCTL_ISOUSB_STOP_ISO_STREAM:
    {

        PFILE_OBJECT_CONTENT fileObjectContent;

        if(fileObject && fileObject->FsContext) {

            fileObjectContent = (PFILE_OBJECT_CONTENT)
                                fileObject->FsContext;

            ntStatus = IsoUsb_StopIsoStream(
                            DeviceObject,
                            InterlockedExchangePointer(
                            &fileObjectContent->StreamInformation,
                            NULL),
                            Irp);
        }
        else {

            ntStatus = STATUS_UNSUCCESSFUL;
        }

        break;
    }

    case IOCTL_ISOUSB_SELECT_ALT_INTERFACE:

        ntStatus = IsoUsb_IoctlSelectAltInterface(DeviceObject, Irp);

        break;

⌨️ 快捷键说明

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