dmgrdisp.c

来自「这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统」· C语言 代码 · 共 535 行 · 第 1/2 页

C
535
字号
/**
 * dmgrdisp.c - USB driver stack project for Windows NT 4.0
 *
 * Copyright (c) 2002-2004 Zhiming  mypublic99@yahoo.com
 *
 * This program/include file is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program/include file is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program (in the main directory of the distribution, the file
 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
 * Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "usbdriver.h"

VOID
disp_urb_completion(PURB purb, PVOID context)
{
    PUSB_DEV_MANAGER dev_mgr;
    ULONG ctrl_code;
    NTSTATUS status;
    PDEVEXT_HEADER dev_hdr;

    UNREFERENCED_PARAMETER(context);

    if (purb == NULL)
        return;

    ctrl_code = (ULONG) purb->reference;
    dev_mgr = (PUSB_DEV_MANAGER) purb->context;

    // at this stage, the irp can not be canceled since the urb
    // won't be found in any queue and the irp is not in any queue.
    // see line 4685 in hub.c
    // Sometimes, it may be very fast to enter this routine before 
    // the dev_mgr_register_irp to be called in dispatch routine in
    // usb2.0 environment as
    // we did in usb1.1 driver. We can not simply add a loop to wait 
    // for the dispatch thread to add the irp to the list, because
    // here we are at DPC level higher than the dispatch thread
    // running level. And the solution is to register the irp 
    // before the urb is scheduled instead of registering it after
    // urb is scheduled.
    if (purb->pirp)
    {
        PIO_STACK_LOCATION irp_stack;
        dev_mgr_remove_irp(dev_mgr, purb->pirp);

        status = purb->status;
        irp_stack = IoGetCurrentIrpStackLocation(purb->pirp);

        if (purb->status != STATUS_SUCCESS)
        {
            purb->pirp->IoStatus.Information = 0;
        }
        else
        {
            // currently only IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL
            // are allowed. And we do not need to set information
            // for IRP_MJ_INTERNAL_DEVICE_CONTROL
            if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
                purb->pirp->IoStatus.Information = purb->data_length;
        }
        purb->pirp->IoStatus.Status = status;
        if (irp_stack)
        {
            dev_hdr = irp_stack->DeviceObject->DeviceExtension;
            if (dev_hdr->start_io)
            {
                IoStartNextPacket(irp_stack->DeviceObject, TRUE);
            }
        }
        IoCompleteRequest(purb->pirp, IO_NO_INCREMENT);
    }
    return;
}

VOID
disp_noio_urb_completion(PURB purb, PVOID context)
{
    PUSB_CTRL_SETUP_PACKET psetup;
    PURB purb2;
    PUSB_DEV_MANAGER dev_mgr;
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION irp_stack;
    PDEVEXT_HEADER dev_hdr;

    if (purb == NULL)
        return;

    psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet;

    if ((psetup->bmRequestType == 0x2) &&
        (psetup->bRequest == USB_REQ_CLEAR_FEATURE) &&
        (psetup->wIndex == 0))       //reset pipe
    {
        purb2 = (PURB) context;
    }
    else
    {
        purb2 = purb;
    }

    if (purb2->pirp == NULL)
        return;

    dev_mgr = (PUSB_DEV_MANAGER) purb2->context;

    dev_mgr_remove_irp(dev_mgr, purb2->pirp);

    if (purb->status != STATUS_SUCCESS)
        status = STATUS_IO_DEVICE_ERROR;

    purb2->pirp->IoStatus.Information = 0;
    purb2->pirp->IoStatus.Status = status;
    irp_stack = IoGetCurrentIrpStackLocation(purb->pirp);
    if (irp_stack)
    {
        dev_hdr = irp_stack->DeviceObject->DeviceExtension;
        if (dev_hdr->start_io)
        {
            IoStartNextPacket(irp_stack->DeviceObject, TRUE);
        }
    }
    IoCompleteRequest(purb2->pirp, IO_NO_INCREMENT);
    return;
}

//this function is called by the hcd's 
//dispatch when they have done their job.
NTSTATUS
dev_mgr_dispatch(IN PUSB_DEV_MANAGER dev_mgr, IN PIRP irp)
{
    PIO_STACK_LOCATION irp_stack;
    NTSTATUS status;
    ULONG ctrl_code;
    USE_NON_PENDING_IRQL;

    if (dev_mgr == NULL || irp == NULL)
    {
        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
    }

    status = STATUS_SUCCESS;
    irp_stack = IoGetCurrentIrpStackLocation(irp);
    ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;

    switch (irp_stack->MajorFunction)
    {
    case IRP_MJ_CREATE:
        {
            InterlockedIncrement(&dev_mgr->open_count);
            EXIT_DISPATCH(STATUS_SUCCESS, irp);
        }
    case IRP_MJ_CLOSE:
        {
            InterlockedDecrement(&dev_mgr->open_count);
            EXIT_DISPATCH(STATUS_SUCCESS, irp);
        }
    case IRP_MJ_INTERNAL_DEVICE_CONTROL:
    case IRP_MJ_DEVICE_CONTROL:
        {
            switch (ctrl_code)
            {
            case IOCTL_GET_DEV_COUNT:
                {
                    LONG dev_count;

                    irp->IoStatus.Information = 0;
                    if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }

                    KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
                    dev_count = usb_count_list(&dev_mgr->dev_list);
                    KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);

                    *((PLONG) irp->AssociatedIrp.SystemBuffer) = dev_count;
                    irp->IoStatus.Information = sizeof(LONG);
                    EXIT_DISPATCH(STATUS_SUCCESS, irp);
                }
            case IOCTL_ENUM_DEVICES:
                {
                    PLIST_ENTRY pthis, pnext;
                    LONG dev_count, array_size, i, j = 0;
                    PUSB_DEV pdev;
                    PENUM_DEV_ARRAY peda;

                    irp->IoStatus.Information = 0;
                    if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(LONG))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }
                    if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ENUM_DEV_ARRAY))
                    {
                        EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
                    }
                    array_size = *((PULONG) irp->AssociatedIrp.SystemBuffer);

                    KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql);
                    dev_count = usb_count_list(&dev_mgr->dev_list);
                    dev_count = dev_count > array_size ? array_size : dev_count;
                    peda = (PENUM_DEV_ARRAY) irp->AssociatedIrp.SystemBuffer;
                    RtlZeroMemory(peda, sizeof(ENUM_DEV_ARRAY) + (dev_count - 1) * sizeof(ENUM_DEV_ELEMENT));

                    if (dev_count)
                    {
                        ListFirst(&dev_mgr->dev_list, pthis);
                        for(i = 0, j = 0; i < dev_count; i++)
                        {
                            pdev = struct_ptr(pthis, USB_DEV, dev_link);
                            ListNext(&dev_mgr->dev_list, pthis, pnext);
                            pthis = pnext;

                            lock_dev(pdev, FALSE);
                            if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
                            {
                                unlock_dev(pdev, FALSE);
                                continue;
                            }

                            if (dev_state(pdev) < USB_DEV_STATE_ADDRESSED)
                            {
                                unlock_dev(pdev, FALSE);
                                continue;
                            }

                            peda->dev_arr[i].dev_handle = (pdev->dev_id << 16);
                            //may not get the desc yet
                            if (pdev->pusb_dev_desc)
                            {
                                peda->dev_arr[i].product_id = pdev->pusb_dev_desc->idProduct;
                                peda->dev_arr[i].vendor_id = pdev->pusb_dev_desc->idVendor;
                            }
                            else
                            {
                                peda->dev_arr[i].product_id = 0xffff;
                                peda->dev_arr[i].vendor_id = 0xffff;
                            }
                            peda->dev_arr[i].dev_addr = pdev->dev_addr;
                            unlock_dev(pdev, FALSE);
                            j++;
                        }
                    }
                    peda->dev_count = dev_count ? j : 0;
                    KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql);

                    irp->IoStatus.Information =
                        sizeof(ENUM_DEV_ARRAY) + (dev_count - 1) * sizeof(ENUM_DEV_ELEMENT);
                    EXIT_DISPATCH(STATUS_SUCCESS, irp);
                }
            case IOCTL_GET_DEV_DESC:
                {
                    GET_DEV_DESC_REQ gddr;
                    PUSB_DESC_HEADER pusb_desc_header;
                    PUSB_DEV pdev;
                    LONG buf_size;

                    if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(GET_DEV_DESC_REQ))

⌨️ 快捷键说明

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