Example #1
0
VOID
UsbSamp_EvtReadWriteCompletion(
    _In_ WDFREQUEST                  Request,
    _In_ WDFIOTARGET                 Target,
    PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
    _In_ WDFCONTEXT                  Context
    )
/*++

Routine Description:

    This is the completion routine for reads/writes
    If the irp completes with success, we check if we
    need to recirculate this irp for another stage of
    transfer.

Arguments:

    Context - Driver supplied context
    Device - Device handle
    Request - Request handle
    Params - request completion params

Return Value:
    None

--*/
{
    PMDL                    requestMdl;
    WDFUSBPIPE              pipe;
    ULONG                   stageLength;
    NTSTATUS               status;
    PREQUEST_CONTEXT        rwContext;
    PURB                    urb;
    PCHAR                   operation;
    ULONG                   bytesReadWritten;
    ULONG                   maxTransferSize;
    PDEVICE_CONTEXT         deviceContext;

    rwContext = GetRequestContext(Request);
    deviceContext = Context;

    if (rwContext->Read) {
        operation = "Read";
    } 
    else {
        operation = "Write";
    }

    pipe = (WDFUSBPIPE) Target   ;
    status = CompletionParams->IoStatus.Status;

    if (!NT_SUCCESS(status)){
        //
        // Queue a workitem to reset the pipe because the completion could be
        // running at DISPATCH_LEVEL.
        //
        QueuePassiveLevelCallback(WdfIoTargetGetDevice(Target), pipe);
        goto End;
    }

    urb = (PURB) WdfMemoryGetBuffer(rwContext->UrbMemory, NULL);
    bytesReadWritten = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
    rwContext->Numxfer += bytesReadWritten;

    //
    // If there is anything left to transfer.
    //
    if (rwContext->Length == 0) {
        //
        // this is the last transfer
        //
        WdfRequestSetInformation(Request, rwContext->Numxfer);
        goto End;
    }

    //
    // Start another transfer
    //
    UsbSamp_DbgPrint(3, ("Stage next %s transfer...\n", operation));

    //
    // The transfer request is for totalLength. 
    // We can perform a max of maxTransfersize in each stage.
    //
    maxTransferSize = GetMaxTransferSize(pipe, deviceContext);

    if (rwContext->Length > maxTransferSize) {
        stageLength = maxTransferSize;
    }
    else {
        stageLength = rwContext->Length;
    }

    //
    // Following call is required to free any mapping made on the partial MDL
    // and reset internal MDL state.
    //
    MmPrepareMdlForReuse(rwContext->Mdl);

    if (rwContext->Read) {
        status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
        if (!NT_SUCCESS(status)){
            UsbSamp_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl for Read failed %x\n", status));
            goto End;
        }
    } 
    else {
        status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl);
        if (!NT_SUCCESS(status)){
            UsbSamp_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl for Write failed %x\n", status));
            goto End;
        }
    }

    IoBuildPartialMdl(requestMdl,
                      rwContext->Mdl,
                      (PVOID) rwContext->VirtualAddress,
                      stageLength);

    //
    // reinitialize the urb
    //
    urb->UrbBulkOrInterruptTransfer.TransferBufferLength = stageLength;

    rwContext->VirtualAddress += stageLength;
    rwContext->Length -= stageLength;

    //
    // Format the request to send a URB to a USB pipe.
    //
    status = WdfUsbTargetPipeFormatRequestForUrb(pipe,
                                Request,
                                rwContext->UrbMemory,
                                NULL);
    if (!NT_SUCCESS(status)) {
        UsbSamp_DbgPrint(1, ("Failed to format requset for urb\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto End;
    }

    WdfRequestSetCompletionRoutine(Request, UsbSamp_EvtReadWriteCompletion, deviceContext);

    //
    // Send the request asynchronously.
    //
    if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) {
        UsbSamp_DbgPrint(1, ("WdfRequestSend for %s failed\n", operation));
        status = WdfRequestGetStatus(Request);
        goto End;
    }

    //
    // Else when the request completes, this completion routine will be
    // called again.
    //
    return;

End:
    //
    // We are here because the request failed or some other call failed.
    // Dump the request context, complete the request and return.
    //
    DbgPrintRWContext(rwContext);

    IoFreeMdl(rwContext->Mdl);

    UsbSamp_DbgPrint(3, ("%s request completed with status 0x%x\n",
                                                    operation, status));

    WdfRequestComplete(Request, status);

    return;
}
Example #2
0
VOID
UsbSamp_EvtReadWriteCompletion(
    _In_ WDFREQUEST                  Request,
    _In_ WDFIOTARGET                 Target,
    PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
    _In_ WDFCONTEXT                  Context
    )
/*++

Routine Description:

    This is the completion routine for reads/writes
    If the irp completes with success, we check if we
    need to recirculate this irp for another stage of
    transfer.

Arguments:

    Context - Driver supplied context
    Device - Device handle
    Request - Request handle
    Params - request completion params

Return Value:
    None

--*/
{
    WDFUSBPIPE              pipe;
    ULONG                   stageLength = 0;
    NTSTATUS               status;
    PREQUEST_CONTEXT        rwContext;
    ULONG                   bytesReadWritten;
    WDFMEMORY_OFFSET       offset;
    PCHAR                   operation;
    PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams;
    PPIPE_CONTEXT           pipeContext;
    WDF_USB_PIPE_INFORMATION   pipeInfo;
    ULONG                   maxTransferSize;
    PDEVICE_CONTEXT         deviceContext;

    usbCompletionParams = CompletionParams->Parameters.Usb.Completion;
    rwContext = GetRequestContext(Request);
    deviceContext = Context;

    if (rwContext->Read) {
        operation = "Read";
        bytesReadWritten =  (ULONG)usbCompletionParams->Parameters.PipeRead.Length;
    } 
    else {
        operation = "Write";
        bytesReadWritten =  (ULONG)usbCompletionParams->Parameters.PipeWrite.Length;
    }

    pipe = (WDFUSBPIPE) Target;
    pipeContext = GetPipeContext(pipe);
    WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
    WdfUsbTargetPipeGetInformation(pipe,&pipeInfo);
    status = CompletionParams->IoStatus.Status;

    if (!NT_SUCCESS(status)){
        //
        // Queue a workitem to reset the pipe because the completion could be
        // running at DISPATCH_LEVEL.
        // TODO: preallocate per pipe workitem to avoid allocation failure.
        QueuePassiveLevelCallback(WdfIoTargetGetDevice(Target), pipe);
        goto End;
    }

    rwContext->Numxfer += bytesReadWritten;

    //
    // If there is anything left to transfer.
    //
    if (rwContext->Length == 0) {
        //
        // this is the last transfer
        //
        WdfRequestSetInformation(Request, rwContext->Numxfer);
        goto End;
    }

    //
    // Start another transfer
    //
    UsbSamp_DbgPrint(3, ("Stage next %s transfer...\n", operation));

    //
    // The transfer request is for totalLength. 
    // We can perform a max of maxTransfersize in each stage.
    //
    maxTransferSize = GetMaxTransferSize(pipe, deviceContext);

    if (rwContext->Length > maxTransferSize) {
       stageLength = maxTransferSize;    
    }
    else
    {
       stageLength = rwContext->Length;
    }

    offset.BufferOffset = rwContext->Numxfer;
    offset.BufferLength = stageLength;

    rwContext->Length -= stageLength;

    if (rwContext->Read) {

        status = WdfUsbTargetPipeFormatRequestForRead(
            pipe,
            Request,
            usbCompletionParams->Parameters.PipeRead.Buffer,
            &offset);

    } 
    else {

        status = WdfUsbTargetPipeFormatRequestForWrite(
            pipe,
            Request,
            usbCompletionParams->Parameters.PipeWrite.Buffer,
            &offset);

    }

    if (!NT_SUCCESS(status)) {
        UsbSamp_DbgPrint(1, ("WdfUsbTargetPipeFormat%sRequest failed 0x%x\n",
                                    operation, status));
        goto End;
    }

#if (NTDDI_VERSION >= NTDDI_WIN8)
    //
    // If the request is for a super speed bulk pipe with streams,
    // configure its urb's PipeHandle with its associated stream's PipeHandle
    //
    if(WdfUsbPipeTypeBulk == pipeInfo.PipeType &&
        pipeContext->StreamConfigured == TRUE) {
        ConfigureStreamPipeHandleForRequest(Request, pipe);
    }
#endif

    WdfRequestSetCompletionRoutine(
                            Request,
                            UsbSamp_EvtReadWriteCompletion,
                            deviceContext);

    //
    // Send the request asynchronously.
    //
    if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) {
        UsbSamp_DbgPrint(1, ("WdfRequestSend for %s failed\n", operation));
        status = WdfRequestGetStatus(Request);
        goto End;
    }

    //
    // Else when the request completes, this completion routine will be
    // called again.
    //
    return;

End:
    //
    // We are here because the request failed or some other call failed.
    // Dump the request context, complete the request and return.
    //
    DbgPrintRWContext(rwContext);

    UsbSamp_DbgPrint(3, ("%s request completed with status 0x%x\n",
                                                    operation, status));

    WdfRequestComplete(Request, status);

    return;
}
Example #3
0
VOID
ReadWriteCompletion(
    IN WDFREQUEST                  Request,
    IN WDFIOTARGET                 Target,
    PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
    IN WDFCONTEXT                  Context
    )
/*++

Routine Description:

    This is the completion routine for reads/writes
    If the irp completes with success, we check if we
    need to recirculate this irp for another stage of
    transfer.

Arguments:

    Context - Driver supplied context
    Device - Device handle
    Request - Request handle
    Params - request completion params

Return Value:
    None

--*/
{
    WDFUSBPIPE              pipe;
    ULONG                   stageLength;
    NTSTATUS               status;
    PREQUEST_CONTEXT        rwContext;
    ULONG                   bytesReadWritten;
    WDFMEMORY_OFFSET       offset;
    PCHAR                   operation;
    PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams;

    UNREFERENCED_PARAMETER(Context);
    rwContext = GetRequestContext(Request);

    usbCompletionParams = CompletionParams->Parameters.Usb.Completion;
    rwContext = GetRequestContext(Request);

    if (rwContext->Read) {
        operation = "Read";
        bytesReadWritten =  usbCompletionParams->Parameters.PipeRead.Length;
    } else {
        operation = "Write";
        bytesReadWritten =  usbCompletionParams->Parameters.PipeWrite.Length;
    }

    pipe = (WDFUSBPIPE) Target;
    status = CompletionParams->IoStatus.Status;

    if (!NT_SUCCESS(status)){
        //
        // Queue a workitem to reset the pipe because the completion could be
        // running at DISPATCH_LEVEL.
        // TODO: preallocate per pipe workitem to avoid allocation failure.
        QueuePassiveLevelCallback(WdfIoTargetGetDevice(Target), pipe);
        goto End;
    }

    rwContext->Numxfer += bytesReadWritten;

    //
    // If there is anything left to transfer.
    //
    if (rwContext->Length == 0) {
        //
        // this is the last transfer
        //
        WdfRequestSetInformation(Request, rwContext->Numxfer);
        goto End;
    }

    //
    // Start another transfer
    //
    kJtag_DbgPrint(3, ("Stage next %s transfer...\n", operation));

    if (rwContext->Length > MAX_TRANSFER_SIZE) {
        stageLength = MAX_TRANSFER_SIZE;
    }
    else {
        stageLength = rwContext->Length;
    }

    offset.BufferOffset = rwContext->Numxfer;
    offset.BufferLength = stageLength;

    rwContext->Length -= stageLength;

    if (rwContext->Read) {

        status = WdfUsbTargetPipeFormatRequestForRead(
            pipe,
            Request,
            usbCompletionParams->Parameters.PipeRead.Buffer,
            &offset);

    } else {

        status = WdfUsbTargetPipeFormatRequestForWrite(
            pipe,
            Request,
            usbCompletionParams->Parameters.PipeWrite.Buffer,
            &offset);

    }

    if (!NT_SUCCESS(status)) {
        kJtag_DbgPrint(1, ("WdfUsbTargetPipeFormat%sRequest failed 0x%x\n",
                                    operation, status));
        goto End;
    }

    WdfRequestSetCompletionRoutine(
                            Request,
                            ReadWriteCompletion,
                            NULL);

    //
    // Send the request asynchronously.
    //
    if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) {
        kJtag_DbgPrint(1, ("WdfRequestSend for %s failed\n", operation));
        status = WdfRequestGetStatus(Request);
        goto End;
    }

    //
    // Else when the request completes, this completion routine will be
    // called again.
    //
    return;

End:
    //
    // We are here because the request failed or some other call failed.
    // Dump the request context, complete the request and return.
    //
    DbgPrintRWContext(rwContext);

    kJtag_DbgPrint(3, ("%s request completed with status 0x%x\n",
                                                    operation, status));

    WdfRequestComplete(Request, status);

    return;
}