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

📄 usbios.c

📁 usb相关的
💻 C
📖 第 1 页 / 共 2 页
字号:
        // 16 times slower than normal.  To deal with this we schedule a DPC 
        // callback that will submit the bulk transfers when bandwidth 
        // reclamation is enabled.
	
        USBLS120_KdPrint( DBGLVL_HIGH,("Queuing Data Xfer DPC\n"));

        // Queue the DPC
        KeInsertQueueDpc(DeviceExtension->TransferDataDpc, Reference, 0 );

    } else {
        USBLS120_KdPrint( DBGLVL_HIGH,("Request completed successfully\n"));

        IoFreeIrp(Irp);
        ExFreePool(Urb);

        // Command phase completed successfully, with no data phase needed.
        // Notify port driver and return.
        IoPacket->Status = IO_STATUS_SUCCESS;
        DeviceExtension->CompleteRequest(IoPacket);
    }

    // All driver-orignated IRPs must return
    // STATUS_MORE_PROCESSING_REQUIRED.
    return STATUS_MORE_PROCESSING_REQUIRED;
}



VOID
USBLS120_TransferDataWorker(
    IN PVOID DeviceObject
    )
/*++
Routine Description:

    Worker function for resetting bulk pipe after stall.

 Arguments:

    DeviceObject - Previous device object.

Return Value:

    None.
--*/

{
    PDEVICE_EXTENSION DeviceExtension;

    USBLS120_KdPrint( DBGLVL_MEDIUM,("enter USBLS120_TransferDataError\n"));

    DeviceExtension = ((PDEVICE_OBJECT)(DeviceObject))->DeviceExtension;

    USBLS120_ResetPipe(
        (PDEVICE_OBJECT)(DeviceObject),
        (DeviceExtension->IoPacket->Flags & IO_FLAGS_DATA_IN) ? 
           &(DeviceExtension->UsbInterface->Pipes[DeviceExtension->DataInPipe]) : 
           &(DeviceExtension->UsbInterface->Pipes[DeviceExtension->DataOutPipe])
        );

    DeviceExtension->IoPacket->Status = IO_STATUS_DEVICE_ERROR;
    DeviceExtension->CompleteRequest(DeviceExtension->IoPacket);
    ExFreePool(DeviceExtension->WorkItem);
}




VOID 
USBLS120_TransferDataDPC(
    PKDPC Dpc,
    PVOID DeferredContext,
    PVOID SystemArgument1,
    PVOID SystemArgument2
    )
/*++
Routine Description:

    DPC handler used to schedule bulk data transfer to/from the device
    after command phase.

 Arguments:

    Dpc - DPC object.
    DeferredContext - N/A
    SystemArgument1 - Points to our Device Object
    SystemArgument2 - N/A

Return Value:

    None.
--*/
{
    PDEVICE_OBJECT DeviceObject;

    USBLS120_KdPrint( DBGLVL_HIGH,("enter USBLS120_TransferDataDPC\n"));

    DeviceObject = (PDEVICE_OBJECT)SystemArgument1;
    USBLS120_TransferData(DeviceObject);

    USBLS120_KdPrint( DBGLVL_HIGH,("exit USBLS120_TransferDataDPC\n"));
}



VOID 
USBLS120_TransferData(
    PDEVICE_OBJECT DeviceObject
    )
/*++
Routine Description:

    Schedules bulk data transfer to/from the device.

 Arguments:

    DeviceObject - FDO for USB storage device.

Return Value:

    None.
--*/
{
    PURB Urb;
    PIRP Irp;
    USBD_PIPE_HANDLE PipeHandle;
    PDEVICE_EXTENSION DeviceExtension;
    NTSTATUS ntStatus;
    BOOLEAN DataIn;
    PVOID DataBuffer;
    ULONG XferLength;
    PIO_STACK_LOCATION NextStack;
    BlockDev_Scatter_Gather * Sgd;

  
    USBLS120_KdPrint( DBGLVL_HIGH,("enter USBLS120_TransferData\n"));

    DeviceExtension = DeviceObject->DeviceExtension;
    Urb = DeviceExtension->Urb;
    Irp = DeviceExtension->Irp;

    // Figure out which direction we're going
    if ((DeviceExtension->IoPacket->Flags) & IO_FLAGS_DATA_IN)
        DataIn = TRUE;
    else
        DataIn = FALSE;


    // Use appropriate bulk pipe
    if (DataIn)
        PipeHandle = DeviceExtension->UsbInterface->Pipes[DeviceExtension->DataInPipe].PipeHandle;
    else
        PipeHandle = DeviceExtension->UsbInterface->Pipes[DeviceExtension->DataOutPipe].PipeHandle;
	

    // If we are doing scatter gather, we will need to find the current
    // SGD element and use its data buffer
    if (DeviceExtension->IoPacket->Flags & IO_FLAGS_SCATTER_GATHER) {

        // Retrieve the SGD list stored in the IoPacket
        Sgd = (BlockDev_Scatter_Gather *)(DeviceExtension->IoPacket->DataBuffer);

        // Extract SGD's data buffer pointer
        DataBuffer = (PVOID)Sgd[DeviceExtension->CurrentSGD].BD_SG_Buffer_Ptr;

        // SGD length is block count, need to convert to byte count
        // and increment the current SGD counter
        XferLength = Sgd[DeviceExtension->CurrentSGD++].BD_SG_Count *
                         DeviceExtension->IoPacket->BlockSize;

        USBLS120_KdPrint( DBGLVL_HIGH,("SGDBuffer=%x, BuffSize=%x\n", DataBuffer, XferLength));
    } else {

        // No SGD, just a flat linear data buffer
        DataBuffer = (PVOID)DeviceExtension->IoPacket->DataBuffer;
        XferLength = DeviceExtension->DataLeft;
    }
	
    // Keep track of how much data we have left to transfer
    DeviceExtension->DataLeft -= XferLength;
	
    // Build a URB for our bulk data transfer
    UsbBuildInterruptOrBulkTransferRequest(
        Urb,
        sizeof (struct _URB_BULK_OR_INTERRUPT_TRANSFER),
        PipeHandle,
        DataBuffer,
        NULL,
        XferLength,
        DataIn ? USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK :
            USBD_TRANSFER_DIRECTION_OUT,
        NULL
        );

    NextStack = IoGetNextIrpStackLocation(Irp);
    
    USBLS120_ASSERT(NextStack != NULL);
    USBLS120_ASSERT(DeviceObject->StackSize>1);

    NextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    NextStack->Parameters.Others.Argument1 = Urb;
    NextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
	
    IoSetCompletionRoutine(
        Irp,
        USBLS120_TransferDataComplete,
        (PVOID)DeviceObject, 
        TRUE,    // invoke on success
        TRUE,    // invoke on error
        TRUE     // invoke on cancellation of the Irp
        );

    USBLS120_IncrementIoCount(DeviceObject);

    // Pass Irp to the USB driver stack without checking status.
    // We don't look at the return status since we will 
    // always complete the IOS request in our
    // completion handler, regardless of status.

    // Call USB driver stack
    IoCallDriver(DeviceExtension->TopOfStackDeviceObject, Irp);
}

			
NTSTATUS
USBLS120_TransferDataComplete(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Reference
    )
/*++
Routine Description:

    Completion handler for bulk data transfer

 Arguments:

    DeviceObject - Previous device object in the stack.
    Irp - Irp being completed.
    Reference - Our device object.

Return Value:

    NTSTATUS value.
--*/

{
    NTSTATUS NtStatus;
    PURB Urb;
    PIO_STACK_LOCATION irpStack;
    PDEVICE_EXTENSION DeviceExtension;

    USBLS120_KdPrint( DBGLVL_HIGH,("enter USBLS120_TransferDataComplete\n"));

    DeviceExtension = ((PDEVICE_OBJECT)(Reference))->DeviceExtension;

    Urb = DeviceExtension->Urb;

    USBLS120_DecrementIoCount((PDEVICE_OBJECT)(Reference));
	    
    USBLS120_KdPrint(
        DBGLVL_HIGH,
        ("TransferLength=%x, Urb Status=%x, Irp Status = %x\n",
        Urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
        Urb->UrbHeader.Status, 
        Irp->IoStatus.Status));

    NtStatus = Irp->IoStatus.Status;

    if (!NT_SUCCESS(NtStatus)) {
        //Device failed Data Transfer

        IoFreeIrp(Irp);
        ExFreePool(Urb);

        // Check if we need to clear stalled pipe
        if (USBD_HALTED(Urb->UrbHeader.Status)) {

            // Reset pipe can only be done at passive level, so we need
            // to schedule a work item to do it.
            DeviceExtension->WorkItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
		
            if (DeviceExtension->WorkItem) {
                USBLS120_KdPrint( DBGLVL_HIGH,("Scheduling DPC to reset endpoint\n"));

                // Schedule a work-item to reset the pipe
                ExInitializeWorkItem(
                    DeviceExtension->WorkItem,
                    USBLS120_TransferDataWorker,
                    Reference
                    );

                ExQueueWorkItem(
                    DeviceExtension->WorkItem,
                    DelayedWorkQueue
                    );

                return STATUS_MORE_PROCESSING_REQUIRED;

            } else {
                // Can't reset pipe because we can't allocate work-item
                USBLS120_KdPrint( DBGLVL_MINIMUM,("Failed to allocate work-item to reset pipe!!\n"));
                TRAP();
            }
        }

        USBLS120_KdPrint( DBGLVL_MINIMUM,("Completing IOPACKET with error\n"));

        // Complete request with error
        DeviceExtension->IoPacket->Status = IO_STATUS_DEVICE_ERROR;
        DeviceExtension->CompleteRequest(DeviceExtension->IoPacket);

        return STATUS_MORE_PROCESSING_REQUIRED;
    }

    //
    // Transfer succeeded
    //

    // Do we have more data to transfer?
    if (DeviceExtension->DataLeft) {
        // Transfer the next SGD
        USBLS120_TransferData((PDEVICE_OBJECT)(Reference));
    } else {

        USBLS120_KdPrint( DBGLVL_HIGH,("Completing IOP successfully\n"));

        IoFreeIrp(Irp);
        ExFreePool(Urb);
        DeviceExtension->IoPacket->Status = IO_STATUS_SUCCESS;
        DeviceExtension->CompleteRequest(DeviceExtension->IoPacket);
    }

    return STATUS_MORE_PROCESSING_REQUIRED;
}



⌨️ 快捷键说明

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