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

📄 isopnp.c

📁 传说中的 usb 端口 驱动 源码 啊啊啊啊啊啊啊
💻 C
📖 第 1 页 / 共 5 页
字号:
    //
    nextStack = IoGetNextIrpStackLocation(irp);

    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;

    nextStack->Parameters.DeviceIoControl.IoControlCode =
        IOCTL_INTERNAL_USB_SUBMIT_URB;

    nextStack->Parameters.Others.Argument1 = Urb;

    // Set the completion routine, which will signal the event
    //
    IoSetCompletionRoutine(irp,
                           IsoUsb_SyncCompletionRoutine,
                           &localevent,
                           TRUE,    // InvokeOnSuccess
                           TRUE,    // InvokeOnError
                           TRUE);   // InvokeOnCancel



    // Pass the Irp & Urb down the stack
    //
    ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
                            irp);

    // If the request is pending, block until it completes
    //
    if (ntStatus == STATUS_PENDING)
    {
        LARGE_INTEGER timeout;

        // Specify a timeout of 5 seconds to wait for this call to complete.
        //
        timeout.QuadPart = -10000 * 5000;

        ntStatus = KeWaitForSingleObject(&localevent,
                                         Executive,
                                         KernelMode,
                                         FALSE,
                                         &timeout);

        if (ntStatus == STATUS_TIMEOUT)
        {
            ntStatus = STATUS_IO_TIMEOUT;

            // Cancel the Irp we just sent.
            //
            IoCancelIrp(irp);

            // And wait until the cancel completes
            //
            KeWaitForSingleObject(&localevent,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
        }
        else
        {
            ntStatus = irp->IoStatus.Status;
        }
    }

    // Done with the Irp, now free it.
    //
    IoFreeIrp(irp);

    IsoUsb_DbgPrint(2, ("exit:  IsoUsb_SyncSendUsbRequest %08X\n", ntStatus));

    return ntStatus;
}


NTSTATUS
IsoUsb_GetDescriptor (
    IN PDEVICE_OBJECT   DeviceObject,
    IN UCHAR            Recipient,
    IN UCHAR            DescriptorType,
    IN UCHAR            Index,
    IN USHORT           LanguageId,
    IN ULONG            RetryCount,
    IN ULONG            DescriptorLength,
    OUT PUCHAR         *Descriptor
    )
/*++

Routine Description:

    This routine attempts to retrieve a specified descriptor from the
    device.

    This routine must be called at IRQL PASSIVE_LEVEL

--*/
{
    USHORT      function;
    PURB        urb;
    NTSTATUS    ntStatus;

    IsoUsb_DbgPrint(2, ("enter: IsoUsb_GetDescriptor\n"));

    *Descriptor = NULL;

    // Set the URB function based on Recipient {Device, Interface, Endpoint}
    //
    switch (Recipient)
    {
        case USB_RECIPIENT_DEVICE:
            function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
            break;
        case USB_RECIPIENT_INTERFACE:
            function = URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE;
            break;
        case USB_RECIPIENT_ENDPOINT:
            function = URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT;
            break;
        default:
            return STATUS_INVALID_PARAMETER;
    }

    // Allocate a descriptor buffer
    //
    *Descriptor = ExAllocatePool(NonPagedPool,
                                 DescriptorLength);

    if (*Descriptor != NULL)
    {
        // Allocate a URB for the Get Descriptor request
        //
        urb = ExAllocatePool(NonPagedPool,
                             sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));

        if (urb != NULL)
        {
            do
            {
                // Initialize the URB
                //
                urb->UrbHeader.Function = function;
                urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
                urb->UrbControlDescriptorRequest.TransferBufferLength = DescriptorLength;
                urb->UrbControlDescriptorRequest.TransferBuffer = *Descriptor;
                urb->UrbControlDescriptorRequest.TransferBufferMDL = NULL;
                urb->UrbControlDescriptorRequest.UrbLink = NULL;
                urb->UrbControlDescriptorRequest.DescriptorType = DescriptorType;
                urb->UrbControlDescriptorRequest.Index = Index;
                urb->UrbControlDescriptorRequest.LanguageId = LanguageId;

                // Send the URB down the stack
                //
                ntStatus = IsoUsb_SyncSendUsbRequest(DeviceObject,
                                                     urb);

                if (NT_SUCCESS(ntStatus))
                {
                    // No error, make sure the length and type are correct
                    //
                    if ((DescriptorLength ==
                         urb->UrbControlDescriptorRequest.TransferBufferLength) &&
                        (DescriptorType ==
                         ((PUSB_COMMON_DESCRIPTOR)*Descriptor)->bDescriptorType))
                    {
                        // The length and type are correct, all done
                        //
                        break;
                    }
                    else
                    {
                        // No error, but the length or type is incorrect
                        //
                        ntStatus = STATUS_DEVICE_DATA_ERROR;
                    }
                }

            } while (RetryCount-- > 0);

            ExFreePool(urb);
        }
        else
        {
            // Failed to allocate the URB
            //
            ExFreePool(*Descriptor);
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        }
    }
    else
    {
        // Failed to allocate the descriptor buffer
        //
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    if (!NT_SUCCESS(ntStatus))
    {
        if (*Descriptor != NULL)
        {
            ExFreePool(*Descriptor);
            *Descriptor = NULL;
        }
    }

    IsoUsb_DbgPrint(2, ("exit:  IsoUsb_GetDescriptor %08X\n", ntStatus));

    return ntStatus;
}


NTSTATUS
IsoUsb_GetDescriptors (
    IN PDEVICE_OBJECT   DeviceObject
    )
/*++

Routine Description:

    This routine is called at START_DEVICE time for the FDO to retrieve
    the Device and Configurations descriptors from the device and store
    them in the Device Extension.

    This routine must be called at PASSIVE_LEVEL.

--*/
{
    PDEVICE_EXTENSION   deviceExtension;
    PUCHAR              descriptor;
    ULONG               descriptorLength;
    NTSTATUS            ntStatus;

    IsoUsb_DbgPrint(2, ("enter: IsoUsb_GetDescriptors\n"));

    deviceExtension = DeviceObject->DeviceExtension;

    //
    // Get Device Descriptor
    //
    ntStatus = IsoUsb_GetDescriptor(DeviceObject,
                                     USB_RECIPIENT_DEVICE,
                                     USB_DEVICE_DESCRIPTOR_TYPE,
                                     0,  // Index
                                     0,  // LanguageId
                                     2,  // RetryCount
                                     sizeof(USB_DEVICE_DESCRIPTOR),
                                     &descriptor);

    if (!NT_SUCCESS(ntStatus))
    {
        IsoUsb_DbgPrint(1, ("Get Device Descriptor failed\n"));
        goto IsoUsb_GetDescriptorsDone;
    }

    ASSERT(deviceExtension->DeviceDescriptor == NULL);
    deviceExtension->DeviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)descriptor;

    //
    // Get Configuration Descriptor (just the Configuration Descriptor)
    //
    ntStatus = IsoUsb_GetDescriptor(DeviceObject,
                                     USB_RECIPIENT_DEVICE,
                                     USB_CONFIGURATION_DESCRIPTOR_TYPE,
                                     0,  // Index
                                     0,  // LanguageId
                                     2,  // RetryCount
                                     sizeof(USB_CONFIGURATION_DESCRIPTOR),
                                     &descriptor);

    if (!NT_SUCCESS(ntStatus))
    {
        IsoUsb_DbgPrint(1, ("Get Configuration Descriptor failed (1)\n"));
        goto IsoUsb_GetDescriptorsDone;
    }

    descriptorLength = ((PUSB_CONFIGURATION_DESCRIPTOR)descriptor)->wTotalLength;

    ExFreePool(descriptor);

    if (descriptorLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
    {
        ntStatus = STATUS_DEVICE_DATA_ERROR;
        IsoUsb_DbgPrint(1, ("Get Configuration Descriptor failed (2)\n"));
        goto IsoUsb_GetDescriptorsDone;
    }

    //
    // Get Configuration Descriptor (and Interface and Endpoint Descriptors)
    //
    ntStatus = IsoUsb_GetDescriptor(DeviceObject,
                                     USB_RECIPIENT_DEVICE,
                                     USB_CONFIGURATION_DESCRIPTOR_TYPE,
                                     0,  // Index
                                     0,  // LanguageId
                                     2,  // RetryCount
                                     descriptorLength,
                                     &descriptor);

    if (!NT_SUCCESS(ntStatus))
    {
        IsoUsb_DbgPrint(1, ("Get Configuration Descriptor failed (3)\n"));
        goto IsoUsb_GetDescriptorsDone;
    }

    ASSERT(deviceExtension->ConfigurationDescriptor == NULL);
    deviceExtension->ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)descriptor;

    if (deviceExtension->ConfigurationDescriptor->bmAttributes & REMOTE_WAKEUP_MASK)
    {
        //
        // this configuration supports remote wakeup
        //
        deviceExtension->WaitWakeEnable = 1;
    }
    else
    {
        deviceExtension->WaitWakeEnable = 0;
    }

#if DBG
    DumpDeviceDesc(deviceExtension->DeviceDescriptor);
    DumpConfigDesc(deviceExtension->ConfigurationDescriptor);
#endif

IsoUsb_GetDescriptorsDone:

    IsoUsb_DbgPrint(2, ("exit:  IsoUsb_GetDescriptors %08X\n", ntStatus));

    return ntStatus;
}


PUSBD_INTERFACE_LIST_ENTRY
IsoUsb_BuildInterfaceList (
    PUSB_CONFIGURATION_DESCRIPTOR   ConfigurationDescriptor
    )
/*++

Routine Description:

    This routine builds an array of USBD_INTERFACE_LIST_ENTRY structures
    from a Configuration Descriptor.  This array will then be suitable
    for use in a call to USBD_CreateConfigurationRequestEx().

    It is the responsibility of the caller to free the returned array
    of USBD_INTERFACE_LIST_ENTRY structures.

--*/
{
    PUSBD_INTERFACE_LIST_ENTRY  interfaceList;
    PUSB_INTERFACE_DESCRIPTOR   interfaceDescriptor;
    ULONG                       numInterfaces;
    ULONG                       numInterfacesFound;
    ULONG                       interfaceNumber;

    interfaceList = NULL;

    numInterfaces = ConfigurationDescriptor->bNumInterfaces;

    if (numInterfaces > 0)
    {
        // Allocate a USBD_INTERFACE_LIST_ENTRY structure for each
        // Interface in the Configuration Descriptor, plus one more to
        // null terminate the array.
        //
        interfaceList = ExAllocatePool(NonPagedPool,
                                       (numInterfaces + 1) *
                                       sizeof(USBD_INTERFACE_LIST_ENTRY));

        if (interfaceList)
        {
            // Parse out the Interface Descriptor for Alternate
            // Interface setting zero for each Interface from the
            // Configuration Descriptor.
            //
            // Note that some devices have been implemented which do
            // not consecutively number their Interface Descriptors.
            //
            // interfaceNumber may increment and skip an interface
            // number without incrementing numInterfacesFound.
            //
            numInterfacesFound = 0;

            interfaceNumber = 0;

            // Note that this also null terminates the list.
            //
            RtlZeroMemory(interfaceList,
                          (numInterfaces + 1) *
                          sizeof(USBD_INTERFACE_LIST_ENTRY));

            while (numInterfacesFound < numInterfaces)
            {
                interfaceDescriptor =  USBD_ParseConfigurationDescriptorEx(
                    ConfigurationDescriptor,
                    ConfigurationDescriptor,
                    interfaceNumber,    // InterfaceNumber
                    0,                  // AlternateSetting Zero
                    -1,                 // InterfaceClass, don't care
                    -1,                 // InterfaceSubClass, don't care
                    -1                  // InterfaceProtocol, don't care
                    );

                if (interfaceDescriptor)
                {
                    interfaceList[numInterfacesFound].InterfaceDescriptor =
                        interfaceDescriptor;

                    numInterfacesFound++;
                }

                interfaceNumber++;

                // Prevent an endless loop due to an incorrectly formed
                // Configuration Descriptor.  The maximum interface
                // number is 255.

                if (interfaceNumber > 256)
                {
                    ExFreePool(interfaceList);

                    return NULL;
                }
            }
        }
    }

    ASSERT(interfaceList);
    return interfaceList;
}


NTSTATUS
IsoUsb_SelectConfiguration (
    IN PDEVICE_OBJECT   DeviceObject
    )
/*++

Routine Description:

    This routine is called at START_DEVICE time for the FDO to configure
    the device, i.e. to send an URB_FUNCTION_SELECT_CONFIGURATION
    request down the driver stack for the device.

    It assumes that the Configuration Descriptor has already been
    successfully retrieved from the device and stored in the Device
    Extension.

--*/
{
    PDEVICE_EXTENSION               deviceExtension;
    PUSB_CONFIGURATION_DESCRIPTOR   configurationDescriptor;
    ULONG                           numInterfaces;
    PUSBD_INTERFACE_LIST_ENTRY      interfaceList;
    PURB                            urb;
    PUSBD_INTERFACE_INFORMATION     interfaceInfo;
    PUSBD_INTERFACE_INFORMATION *   interfaceInfoList;
    ULONG                           i;
    ULONG                           j;
    NTSTATUS                        ntStatus;

    IsoUsb_DbgPrint(2, ("enter: IsoUsb_SelectConfiguration\n"));

    deviceExtension = DeviceObject->DeviceExtension;

⌨️ 快捷键说明

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