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

📄 isodev.c

📁 WINDDK开发代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 2000  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) 2000 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

--*/
{

    LONG                        i;
    NTSTATUS                    ntStatus;
    PFILE_OBJECT                fileObject;
    PDEVICE_EXTENSION           deviceExtension;
    PIO_STACK_LOCATION          irpStack;
    PFILE_OBJECT_CONTENT        fileObjectContent;
    PUSBD_INTERFACE_INFORMATION interface;


    i = 0;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpStack->FileObject;
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    PAGED_CODE();

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

    if(deviceExtension->DeviceState != Working) {

        ntStatus = STATUS_INVALID_DEVICE_STATE;
        goto IsoUsb_DispatchCreate_Exit;
    }

    if(deviceExtension->UsbInterface) {
    
        interface = deviceExtension->UsbInterface;    
    }
    else {

        IsoUsb_DbgPrint(1, ("UsbInterface not found\n"));

        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;
    }

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

    if(0 != fileObject->FileName.Length) {

        i = IsoUsb_ParseStringForPipeNumber(&fileObject->FileName);

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

        if((i < 0) || 
           (i >= (LONG)(deviceExtension->UsbInterface->NumberOfPipes))) {
    
            ntStatus = STATUS_INVALID_PARAMETER;

            IsoUsb_DbgPrint(1, ("invalid pipe number\n"));
            ExFreePool(fileObject->FsContext);
            fileObject->FsContext = NULL;
            goto IsoUsb_DispatchCreate_Exit;
        }

        fileObjectContent->PipeInformation = (PVOID) &interface->Pipes[i];
    }

    ntStatus = STATUS_SUCCESS;

    InterlockedIncrement(&deviceExtension->OpenHandleCount);
        
    //
    // 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(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

--*/
{
    NTSTATUS             ntStatus;
    PFILE_OBJECT         fileObject;
    PDEVICE_EXTENSION    deviceExtension;
    PIO_STACK_LOCATION   irpStack;
    PFILE_OBJECT_CONTENT fileObjectContent;
    
    PAGED_CODE();

    //
    // initialize variables
    //
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpStack->FileObject;
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    
    IsoUsb_DbgPrint(3, ("IsoUsb_DispatchClose - begins\n"));

    if(fileObject && fileObject->FsContext) {

        fileObjectContent = (PFILE_OBJECT_CONTENT) fileObject->FsContext;

        ASSERT(NULL == fileObjectContent->StreamInformation);

        ExFreePool(fileObjectContent);

        fileObject->FsContext = NULL;
    }

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

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

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    InterlockedDecrement(&deviceExtension->OpenHandleCount);

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

    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_ResetPipe(DeviceObject, pipe);
        }

        break;
    }

    case IOCTL_ISOUSB_GET_CONFIG_DESCRIPTOR:
    {
        ULONG length;

        if(deviceExtension->UsbConfigurationDescriptor) {

            length = deviceExtension->UsbConfigurationDescriptor->wTotalLength;

            if(outputBufferLength >= length) {

                RtlCopyMemory(ioBuffer,
                              deviceExtension->UsbConfigurationDescriptor,
                              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;
    }

    default :

        ntStatus = STATUS_INVALID_DEVICE_REQUEST;

        break;
    }

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

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

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

    return ntStatus;
}

LONG
IsoUsb_ParseStringForPipeNumber(
    IN PUNICODE_STRING PipeName
    )
/*++
 
Routine Description:

    This routine parses the PipeName for the Pipe#

Arguments:

    PipeName - Unicode string for the pipe name

Return Value:

    Pipe number

--*/
{
    LONG  bufferIndex;
    ULONG uval;
    ULONG umultiplier;

    if(PipeName->Length == 0) {

        return -1;
    }

    bufferIndex = (PipeName->Length / sizeof(WCHAR)) - 1;

    while((bufferIndex > -1) && 
          ((PipeName->Buffer[bufferIndex] < (WCHAR) '0')  ||
           (PipeName->Buffer[bufferIndex] > (WCHAR) '9')))           {
        
        bufferIndex--;
    }

    if(bufferIndex > -1) {

        uval = 0;
        umultiplier = 1;

        while((bufferIndex > -1) &&
              (PipeName->Buffer[bufferIndex] >= (WCHAR) '0') &&
              (PipeName->Buffer[bufferIndex] <= (WCHAR) '9'))        {

            uval += (umultiplier *
                     (ULONG) (PipeName->Buffer[bufferIndex] - (WCHAR) '0'));
            bufferIndex--;
            umultiplier *= 10;
        }

        return uval;
    }

    return -1;
}

NTSTATUS
IsoUsb_ResetPipe(
    IN PDEVICE_OBJECT         DeviceObject,
    IN PUSBD_PIPE_INFORMATION PipeInfo
    )
/*++
 
Routine Description:

    This routine submits an irp/urb pair synchronously
    with function code URB_FUNCTION_RESET_PIPE to reset
    the pipe

Arguments:

    DeviceObject - pointer to device object
    PipeInfo - pointer to USBD_PIPE_INFORMATION

Return Value:

    NT status value

--*/
{

⌨️ 快捷键说明

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