Example #1
0
NTSTATUS
kmdf1394_AsyncWrite (
                     IN WDFDEVICE             Device,
                     IN WDFREQUEST         Request,
                     IN PASYNC_WRITE       AsyncWrite)
/*++

Routine Description:

    Async Write routine.

Arguments:

    Device - the current WDFDEVICE Object.

    Request - the current request.

    AsyncWrite - the Data buffer from usermode to be worked on.

Return Value:

    VOID
--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device);
    PIRB pIrb = NULL;
    PMDL   pMdl = NULL;
    WDFIOTARGET ioTarget = NULL;
    WDFMEMORY Memory;

    ENTER("kmdf1394_AsyncWrite");

    ioTarget = deviceExtension->StackIoTarget;


    pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV);
    if (!pIrb) 
    {
        TRACE(TL_ERROR, ("Failed to allocate pIrb!\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory (pIrb, sizeof (IRB));
    pIrb->FunctionNumber = REQUEST_ASYNC_WRITE;
    pIrb->Flags = 0;
    pIrb->u.AsyncWrite.DestinationAddress = AsyncWrite->DestinationAddress;
    pIrb->u.AsyncWrite.nNumberOfBytesToWrite = AsyncWrite->nNumberOfBytesToWrite;
    pIrb->u.AsyncWrite.nBlockSize = AsyncWrite->nBlockSize;
    pIrb->u.AsyncWrite.fulFlags = AsyncWrite->fulFlags;

    if (AsyncWrite->bGetGeneration) 
    {
        TRACE(
            TL_TRACE, 
            ("Retrieved Generation Count = 0x%x\n", 
            pIrb->u.AsyncRead.ulGeneration));

        pIrb->u.AsyncRead.ulGeneration = deviceExtension->GenerationCount;
    }
    else 
    {
        pIrb->u.AsyncRead.ulGeneration = AsyncWrite->ulGeneration;
    }

    pMdl = IoAllocateMdl (
        AsyncWrite->Data,
        AsyncWrite->nNumberOfBytesToWrite,
        FALSE,
        FALSE,
        NULL);
    if(NULL == pMdl) 
    {
        TRACE(TL_ERROR, ("Failed to allocate mdl!\n"));

        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    MmBuildMdlForNonPagedPool (pMdl);

    pIrb->u.AsyncWrite.Mdl = pMdl;

    //
    // We need to create a WDF Memory object for the IRB to nestle in
    // for an async request.
    //
    ntStatus = WdfMemoryCreatePreallocated (
        WDF_NO_OBJECT_ATTRIBUTES,
        pIrb,
        sizeof (IRB),
        &Memory);

    if (!NT_SUCCESS (ntStatus))
    {
        TRACE (
            TL_ERROR,
            ("Failed WdfMemoryCreate %d\n", 
            ntStatus));

        IoFreeMdl (pIrb->u.AsyncWrite.Mdl);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

        return ntStatus;
    }

    WdfRequestSetCompletionRoutine (
        Request, 
        kmdf1394_AsyncWriteCompletion, 
        Memory);

    ntStatus = kmdf1394_SubmitIrpAsync (ioTarget, Request, Memory);
    if (!NT_SUCCESS(ntStatus)) 
    {
        if (ntStatus != STATUS_INVALID_GENERATION) 
        {
            TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", ntStatus));
        }
        else
        {
            TRACE (TL_ERROR, ("Invalid Generation count\n"));
        }

        IoFreeMdl (pIrb->u.AsyncWrite.Mdl);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        WdfObjectDelete (Memory);
    }

    EXIT("kmdf1394_AsyncWrite", ntStatus);
    return ntStatus;
} // kmdf1394_AsyncWrite
Example #2
0
NTSTATUS
kmdf1394_AsyncStream (
                      IN WDFDEVICE Device,
                      IN WDFREQUEST Request,
                      IN OUT PASYNC_STREAM AsyncStream)
/*++

Routine Description:

    Async Stream routine.

Arguments:

    Device - the current WDFDEVICE Object.

    Request - the current request.

    AsyncStream - the Data buffer from usermode to be worked on.

Return Value:

    VOID
--*/
{
    NTSTATUS    ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION  deviceExtension = GetDeviceContext (Device);
    PIRB pIrb = NULL;
    WDFIOTARGET ioTarget = deviceExtension->StackIoTarget;
    WDFMEMORY Memory;
    PMDL pMdl = NULL;

    ENTER("kmdf1394_AsyncStream");

    pIrb = ExAllocatePoolWithTag(NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV);
    if (!pIrb)
    {
        TRACE(TL_ERROR, ("Failed to allocate pIrb!\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    } 

    RtlZeroMemory (pIrb, sizeof (IRB));
    pIrb->FunctionNumber = REQUEST_ASYNC_STREAM;
    pIrb->Flags = 0;
    pIrb->u.AsyncStream.nNumberOfBytesToStream = \
        AsyncStream->nNumberOfBytesToStream;
    pIrb->u.AsyncStream.fulFlags = AsyncStream->fulFlags;
    pIrb->u.AsyncStream.ulTag = AsyncStream->ulTag;
    pIrb->u.AsyncStream.nChannel = AsyncStream->nChannel;
    pIrb->u.AsyncStream.ulSynch = AsyncStream->ulSynch;
    pIrb->u.AsyncStream.nSpeed = (UCHAR) AsyncStream->nSpeed;

    pMdl = IoAllocateMdl (
        AsyncStream->Data,
        AsyncStream->nNumberOfBytesToStream,
        FALSE,
        FALSE,
        NULL);
    if (!pMdl) 
    {
        TRACE(TL_ERROR, ("Failed to allocate pMdl!\n"));

        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    MmBuildMdlForNonPagedPool(pMdl);

    pIrb->u.AsyncStream.Mdl = pMdl;

    //
    // We need to create a WDF Memory object for the IRB to nestle in
    // for an async request.
    //
    ntStatus = WdfMemoryCreatePreallocated (
        WDF_NO_OBJECT_ATTRIBUTES,
        pIrb,
        sizeof (IRB),
        &Memory);
    if (!NT_SUCCESS (ntStatus))
    {
        TRACE (
            TL_ERROR,
            ("Failed WdfMemoryCreate %d\n", 
            ntStatus));

        IoFreeMdl (pIrb->u.AsyncStream.Mdl);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

        return ntStatus;
    }

    WdfRequestSetCompletionRoutine (
        Request, 
        kmdf1394_AsyncStreamCompletion, 
        Memory);

    ntStatus = kmdf1394_SubmitIrpAsync (ioTarget, Request, Memory);
    if (!NT_SUCCESS(ntStatus)) 
    {
        TRACE(TL_ERROR, ("SubmitIrpAsync failed = 0x%x\n", ntStatus));

        IoFreeMdl (pIrb->u.AsyncStream.Mdl);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        WdfObjectDelete (Memory);
    }

    EXIT("kmdf1394_AsyncStream", ntStatus);
    return ntStatus;
} // kmdf1394_AsyncStream
Example #3
0
NTSTATUS
kmdf1394_AllocateAddressRange (
                               IN WDFDEVICE Device,
                               IN WDFREQUEST Request,
                               IN OUT PALLOCATE_ADDRESS_RANGE AllocateAddrRange)
/*++

Routine Description:

    Allocate Address Range routine.

Arguments:

    Device - the current WDFDEVICE Object.

    Request - the current request.

    AllocateAddressRange - the Data buffer from usermode to be worked on.

Return Value:

    VOID
--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_EXTENSION deviceExtension = GetDeviceContext(Device);
    PIRB pIrb = NULL;
    PASYNC_ADDRESS_DATA pAsyncAddressData = NULL;
    ULONG nPages;
    WDFMEMORY Memory;
    CONTEXT_BUNDLE ContextBundle;

    ENTER("kmdf1394_AllocateAddressRange");

    pIrb = ExAllocatePoolWithTag (NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV);
    if (!pIrb)
    {
        TRACE(TL_ERROR, ("Failed to allocate pIrb!\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    } 

    ContextBundle.Context0 = AllocateAddrRange;

    pAsyncAddressData = ExAllocatePoolWithTag (
        NonPagedPool,
        sizeof(ASYNC_ADDRESS_DATA),
        POOLTAG_KMDF_VDEV);
    if (!pAsyncAddressData)
    {
        TRACE(TL_ERROR, ("Failed to allocate pAsyncAddressData!\n"));

        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    ContextBundle.Context1 = pAsyncAddressData;

    pAsyncAddressData->Buffer = ExAllocatePoolWithTag (
        NonPagedPool, 
        AllocateAddrRange->nLength, 
        POOLTAG_KMDF_VDEV);
    if (!pAsyncAddressData->Buffer) 
    {
        TRACE(TL_ERROR, ("Failed to allocate Buffer!\n"));

        ExFreePoolWithTag (pAsyncAddressData, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    if ((0 == AllocateAddrRange->MaxSegmentSize) || 
        (PAGE_SIZE == AllocateAddrRange->MaxSegmentSize))
    {
        nPages = \
            ADDRESS_AND_SIZE_TO_SPAN_PAGES (
            AllocateAddrRange->Data, 
            AllocateAddrRange->nLength);
    }
    else
    {
        nPages = \
            (AllocateAddrRange->nLength % AllocateAddrRange->MaxSegmentSize) ? \
            AllocateAddrRange->nLength / AllocateAddrRange->MaxSegmentSize + 1 : \
            AllocateAddrRange->nLength / AllocateAddrRange->MaxSegmentSize;
    }

    pAsyncAddressData->AddressRange = ExAllocatePoolWithTag (
        NonPagedPool,
        sizeof(ADDRESS_RANGE)*nPages,
        POOLTAG_KMDF_VDEV);
    if (!pAsyncAddressData->AddressRange) 
    {
        TRACE(TL_ERROR, ("Failed to allocate AddressRange!\n"));

        ExFreePoolWithTag(pAsyncAddressData->Buffer, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag(pAsyncAddressData, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag(pIrb, POOLTAG_KMDF_VDEV);

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    pAsyncAddressData->pMdl = IoAllocateMdl (
        pAsyncAddressData->Buffer,
        AllocateAddrRange->nLength,
        FALSE,
        FALSE,
        NULL);

    if (!pAsyncAddressData->pMdl) 
    {
        TRACE(TL_ERROR, ("Failed to create pMdl!\n"));

        ExFreePoolWithTag (pAsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pAsyncAddressData->Buffer, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pAsyncAddressData, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    MmBuildMdlForNonPagedPool (pAsyncAddressData->pMdl);

    TRACE(TL_TRACE, ("pMdl = 0x%x\n", pAsyncAddressData->pMdl));

    //
    // copy over the contents of data to our driver buffer
    //
    RtlCopyMemory (
        pAsyncAddressData->Buffer, 
        AllocateAddrRange->Data, 
        AllocateAddrRange->nLength);

    pAsyncAddressData->nLength = AllocateAddrRange->nLength;

    RtlZeroMemory (pIrb, sizeof (IRB));
    pIrb->FunctionNumber = REQUEST_ALLOCATE_ADDRESS_RANGE;
    pIrb->Flags = 0;
    pIrb->u.AllocateAddressRange.Mdl = pAsyncAddressData->pMdl;
    pIrb->u.AllocateAddressRange.fulFlags = AllocateAddrRange->fulFlags;
    pIrb->u.AllocateAddressRange.nLength = AllocateAddrRange->nLength;
    pIrb->u.AllocateAddressRange.MaxSegmentSize = \
        AllocateAddrRange->MaxSegmentSize;
    pIrb->u.AllocateAddressRange.fulAccessType = \
        AllocateAddrRange->fulAccessType;
    pIrb->u.AllocateAddressRange.fulNotificationOptions = \
        AllocateAddrRange->fulNotificationOptions;


    pIrb->u.AllocateAddressRange.Callback = NULL;
    pIrb->u.AllocateAddressRange.Context = NULL;

    pIrb->u.AllocateAddressRange.Required1394Offset = \
        AllocateAddrRange->Required1394Offset;
    pIrb->u.AllocateAddressRange.FifoSListHead = NULL;
    pIrb->u.AllocateAddressRange.FifoSpinLock = NULL;
    pIrb->u.AllocateAddressRange.AddressesReturned = 0;
    pIrb->u.AllocateAddressRange.p1394AddressRange = \
        pAsyncAddressData->AddressRange;
    pIrb->u.AllocateAddressRange.DeviceExtension = deviceExtension;

    //
    // We need to create a WDF Memory object for the IRB to nestle in
    // for an async request.
    //
    ntStatus = WdfMemoryCreatePreallocated (
        WDF_NO_OBJECT_ATTRIBUTES,
        pIrb,
        sizeof (IRB),
        &Memory);
    if (!NT_SUCCESS (ntStatus))
    {
        TRACE (
            TL_ERROR,
            ("Failed WdfMemoryCreate %d\n", 
            ntStatus));

        IoFreeMdl (pAsyncAddressData->pMdl);
        ExFreePoolWithTag (pAsyncAddressData->AddressRange, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pAsyncAddressData->Buffer, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pAsyncAddressData, POOLTAG_KMDF_VDEV);
        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

        return ntStatus;
    }

    ContextBundle.Context2 = Memory;
    ContextBundle.Context3 = deviceExtension;

    WdfRequestSetCompletionRoutine (
        Request, 
        kmdf1394_AllocateAddressRangeCompletion, 
        &ContextBundle);

    ntStatus = kmdf1394_SubmitIrpAsync (
        deviceExtension->StackIoTarget, 
        Request, 
        Memory);

    EXIT ("kmdf1394_AllocateAddressRange", ntStatus);
    return ntStatus;
} //kmdf1394_AllocateAddressRange
Example #4
0
VOID
ReadWriteBulkEndPoints(
    _In_ WDFQUEUE         Queue,
    _In_ WDFREQUEST       Request,
    _In_ ULONG            Length,
    _In_ WDF_REQUEST_TYPE RequestType
    )
/*++

Routine Description:

    This callback is invoked when the framework received  WdfRequestTypeRead or
    RP_MJ_WRITE request. This read/write is performed in stages of
    maximum transfer size. Once a stage of transfer is complete, then the
    request is circulated again, until the requested length of transfer is
    performed.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.

    Request - Handle to a framework request object. This one represents
              the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework.

    Length - Length of the input/output buffer.

Return Value:

   VOID

--*/
{
    size_t                totalLength = Length;
    size_t                stageLength = 0;
    NTSTATUS              status;
    PVOID                 virtualAddress = 0;
    PREQUEST_CONTEXT      rwContext = NULL;
    PFILE_CONTEXT         fileContext = NULL;
    WDFUSBPIPE            pipe;
    WDF_USB_PIPE_INFORMATION pipeInfo;
    WDFMEMORY             reqMemory;
    WDFMEMORY_OFFSET      offset;
    WDF_OBJECT_ATTRIBUTES objectAttribs;
    PDEVICE_CONTEXT       deviceContext;
    PPIPE_CONTEXT         pipeContext;

    ULONG                 maxTransferSize;
 
    UsbSamp_DbgPrint(3, ("UsbSamp_DispatchReadWrite - begins\n"));

    //
    // First validate input parameters.
    //
    deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));

    if (totalLength > deviceContext->MaximumTransferSize) {
        UsbSamp_DbgPrint(1, ("Transfer length > circular buffer\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    if ((RequestType != WdfRequestTypeRead) &&
        (RequestType != WdfRequestTypeWrite)) {
        UsbSamp_DbgPrint(1, ("RequestType has to be either Read or Write\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    //
    // Get the pipe associate with this request.
    //
    fileContext = GetFileContext(WdfRequestGetFileObject(Request));
    pipe = fileContext->Pipe;
    pipeContext = GetPipeContext(pipe);
    WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
    WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);

    rwContext = GetRequestContext(Request);

    if (RequestType == WdfRequestTypeRead) {
        status = WdfRequestRetrieveOutputBuffer(Request, Length, &virtualAddress, &totalLength);
        rwContext->Read = TRUE;

    } 
    else { //Write

        status = WdfRequestRetrieveInputBuffer(Request, Length, &virtualAddress, &totalLength);
        rwContext->Read = FALSE;
    }

    if (!NT_SUCCESS(status)){
        UsbSamp_DbgPrint(1, ("WdfRequestRetrieveInputBuffer failed\n"));
        goto Exit;
    }

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

    if (totalLength > maxTransferSize) {
        stageLength = maxTransferSize;
    }
    else {
        stageLength = totalLength;   
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
    objectAttribs.ParentObject = Request;
    status = WdfMemoryCreatePreallocated(&objectAttribs,
                                         virtualAddress,
                                         totalLength,
                                         &reqMemory);
    if (!NT_SUCCESS(status)){
        UsbSamp_DbgPrint(1, ("WdfMemoryCreatePreallocated failed\n"));
        goto Exit;
    }

    offset.BufferOffset = 0;
    offset.BufferLength = stageLength;

    //
    // The framework format call validates to make sure that you are reading or
    // writing to the right pipe type, sets the appropriate transfer flags,
    // creates an URB and initializes the request.
    //
    if (RequestType == WdfRequestTypeRead) {

        UsbSamp_DbgPrint(3, ("Read operation\n"));
        status = WdfUsbTargetPipeFormatRequestForRead(pipe,
                                                      Request,
                                                      reqMemory,
                                                      &offset);
    } 
    else {

        UsbSamp_DbgPrint(3, ("Write operation\n"));
        status = WdfUsbTargetPipeFormatRequestForWrite(pipe,
                                                       Request,
                                                       reqMemory,
                                                       &offset);
    }

    if (!NT_SUCCESS(status)) {
        UsbSamp_DbgPrint(1, ("WdfUsbTargetPipeFormatRequest failed 0x%x\n", status));
        goto Exit;
    }

#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);
    //
    // set REQUEST_CONTEXT parameters.
    //
    rwContext->Length  = (ULONG)totalLength - (ULONG)stageLength;
    rwContext->Numxfer = 0;

    //
    // Send the request asynchronously.
    //
    if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) {
        UsbSamp_DbgPrint(1, ("WdfRequestSend failed\n"));
        status = WdfRequestGetStatus(Request);
        goto Exit;
    }


Exit:
    if (!NT_SUCCESS(status)) {
        WdfRequestCompleteWithInformation(Request, status, 0);
    }

    UsbSamp_DbgPrint(3, ("UsbSamp_DispatchReadWrite - ends\n"));

    return;
}
Example #5
0
NTSTATUS
kmdf1394_AsyncLock (
                    IN WDFDEVICE         Device,
                    IN WDFREQUEST     Request,
                    IN OUT PASYNC_LOCK   AsyncLock)
/*++

Routine Description:

    Async Lock routine.

Arguments:

    Device - the current WDFDEVICE Object.

    Request - the current request.

    AsyncLock - the Data buffer from usermode to be worked on.

Return Value:

    VOID
--*/
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PIRB pIrb = NULL;
    WDFMEMORY Memory;
    PDEVICE_EXTENSION  deviceExtension = GetDeviceContext (Device);
    WDFIOTARGET ioTarget = NULL;

    ENTER ("kmdf1394_AsyncLock");

    ioTarget = deviceExtension->StackIoTarget;

    pIrb = ExAllocatePoolWithTag (NonPagedPool, sizeof(IRB), POOLTAG_KMDF_VDEV);
    if (!pIrb) 
    {
        TRACE(TL_ERROR, ("Failed to allocate pIrb!\n"));
        return STATUS_INSUFFICIENT_RESOURCES;  
    } 

    RtlZeroMemory (pIrb, sizeof (IRB));
    pIrb->FunctionNumber = REQUEST_ASYNC_LOCK;
    pIrb->Flags = 0;
    pIrb->u.AsyncLock.DestinationAddress = AsyncLock->DestinationAddress;
    pIrb->u.AsyncLock.nNumberOfArgBytes = AsyncLock->nNumberOfArgBytes;
    pIrb->u.AsyncLock.nNumberOfDataBytes = AsyncLock->nNumberOfDataBytes;
    pIrb->u.AsyncLock.fulTransactionType = AsyncLock->fulTransactionType;
    pIrb->u.AsyncLock.fulFlags = AsyncLock->fulFlags;
    pIrb->u.AsyncLock.Arguments[0] = AsyncLock->Arguments[0];
    pIrb->u.AsyncLock.Arguments[1] = AsyncLock->Arguments[1];
    pIrb->u.AsyncLock.DataValues[0] = AsyncLock->DataValues[0];
    pIrb->u.AsyncLock.DataValues[1] = AsyncLock->DataValues[1];
    pIrb->u.AsyncLock.pBuffer = AsyncLock->Buffer;

    if (AsyncLock->bGetGeneration) 
    {
        pIrb->u.AsyncLock.ulGeneration = deviceExtension->GenerationCount;

        TRACE(
            TL_TRACE, 
            ("Retrieved Generation Count = 0x%x\n", 
            pIrb->u.AsyncLock.ulGeneration));
    }
    else 
    {
        pIrb->u.AsyncLock.ulGeneration = AsyncLock->ulGeneration;
    }

    //
    // We need to create a WDF Memory object for the IRB to nestle in
    // for an async request.
    //
    ntStatus = WdfMemoryCreatePreallocated (
        WDF_NO_OBJECT_ATTRIBUTES,
        pIrb,
        sizeof (IRB),
        &Memory);
    if (!NT_SUCCESS (ntStatus))
    {
        TRACE (
            TL_ERROR,
            ("Failed WdfMemoryCreate %d\n", 
            ntStatus));

        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);

        return ntStatus;
    }

    WdfRequestSetCompletionRoutine (
        Request, 
        kmdf1394_AsyncLockCompletion, 
        Memory);


    ntStatus = kmdf1394_SubmitIrpAsync (ioTarget, Request, Memory);
    if (!NT_SUCCESS(ntStatus)) 
    {
        if (STATUS_INVALID_GENERATION == ntStatus) 
        {
            TRACE (TL_ERROR, ("Invalid Geneation count\n"));
        }
        else
        {
            TRACE(TL_ERROR, ("SubmitIrpSync failed = 0x%x\n", ntStatus));
        }

        ExFreePoolWithTag (pIrb, POOLTAG_KMDF_VDEV);
        WdfObjectDelete (Memory);
    }

    EXIT("kmdf1394_AsyncLock", ntStatus);
    return ntStatus;
} // kmdf1394_AsyncLock
Example #6
0
NTSTATUS
BthEchoSharedSendBrbAsync(
    _In_ WDFIOTARGET IoTarget,
    _In_ WDFREQUEST Request,
    _In_ PBRB Brb,
    _In_ size_t BrbSize,
    _In_ PFN_WDF_REQUEST_COMPLETION_ROUTINE ComplRoutine,
    _In_opt_ WDFCONTEXT Context
)
/*++

Routine Description:

    This routine formats a request with brb and sends it asynchronously

Arguments:

    IoTarget - Target to send the brb to
    Request - request object to be formatted with brb
    Brb - Brb to be sent
    BrbSize - size of the Brb data structure
    ComplRoutine - WDF completion routine for the request
                   This must be specified because we are formatting the request
                   and hence not using SEND_AND_FORGET flag
    Context - (optional) context to be passed in to the completion routine

Return Value:

    Success implies that request was sent correctly and completion routine will be called
    for it,
    failure implies it was not sent and caller should complete the request

Notes:

    This routine does not call WdfRequestReuse on the Request passed in.
    Caller must do so before passing in the request, if it is reusing the request.

    This routine does not complete the request in case of failure.
    Caller must complete the request in case of failure.

--*/
{
    NTSTATUS status         = BTH_ERROR_SUCCESS;
    WDF_OBJECT_ATTRIBUTES attributes;
    WDFMEMORY memoryArg1    = NULL;

    if (BrbSize <= 0)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_CONT_READER,
                    "BrbSize has invalid value: %I64d\n",
                    BrbSize
                   );

        status = STATUS_INVALID_PARAMETER;

        goto exit;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = Request;

    status = WdfMemoryCreatePreallocated(
                 &attributes,
                 Brb,
                 BrbSize,
                 &memoryArg1
             );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_UTIL,
                    "Creating preallocted memory for Brb 0x%p failed, Request to be formatted 0x%p, "
                    "Status code %!STATUS!\n",
                    Brb,
                    Request,
                    status
                   );

        goto exit;
    }

    status = WdfIoTargetFormatRequestForInternalIoctlOthers(
                 IoTarget,
                 Request,
                 IOCTL_INTERNAL_BTH_SUBMIT_BRB,
                 memoryArg1,
                 NULL, //OtherArg1Offset
                 NULL, //OtherArg2
                 NULL, //OtherArg2Offset
                 NULL, //OtherArg4
                 NULL  //OtherArg4Offset
             );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_UTIL,
                    "Formatting request 0x%p with Brb 0x%p failed, Status code %!STATUS!\n",
                    Request,
                    Brb,
                    status
                   );

        goto exit;
    }

    //
    // Set a CompletionRoutine callback function.
    //
    WdfRequestSetCompletionRoutine(
        Request,
        ComplRoutine,
        Context
    );

    if (FALSE == WdfRequestSend(
                Request,
                IoTarget,
                NULL
            ))
    {
        status = WdfRequestGetStatus(Request);

        TraceEvents(TRACE_LEVEL_ERROR, DBG_UTIL,
                    "Request send failed for request 0x%p, Brb 0x%p, Status code %!STATUS!\n",
                    Request,
                    Brb,
                    status
                   );

        goto exit;
    }

exit:
    return status;
}
NTSTATUS
FormatRequestWithBrb(
    _In_ WDFIOTARGET IoTarget,
    _In_ WDFREQUEST Request,
    _In_ PBRB Brb,
    _In_ size_t BrbSize
    )
/*++

Description:

    This routine formats are WDFREQUEST with the passed in BRB

Arguments:

    IoTarget - Target to which request will be sent
    Request - Request to be formattted
    Brb - BRB to format the request with
    BrbSize - size of the BRB

--*/
{
    NTSTATUS status         = BTH_ERROR_SUCCESS;
    WDF_OBJECT_ATTRIBUTES attributes;
    WDFMEMORY memoryArg1    = NULL;

    if (BrbSize <= 0) 
    {        
        TraceEvents(TRACE_LEVEL_ERROR, DBG_UTIL, 
            "BrbSize has an invalid value: %I64d\n",
            BrbSize
            );

        status = STATUS_INVALID_PARAMETER;

        goto exit;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
    attributes.ParentObject = Request;

    status = WdfMemoryCreatePreallocated(
        &attributes,
        Brb,
        BrbSize,
        &memoryArg1
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_UTIL, 
            "Creating preallocted memory for Brb 0x%p failed, Request to be formatted 0x%p, "
            "Status code %!STATUS!\n",
            Brb,
            Request,
            status
            );

        goto exit;
    }

    status = WdfIoTargetFormatRequestForInternalIoctlOthers(
        IoTarget,
        Request,
        IOCTL_INTERNAL_BTH_SUBMIT_BRB,
        memoryArg1,
        NULL, //OtherArg1Offset
        NULL, //OtherArg2
        NULL, //OtherArg2Offset
        NULL, //OtherArg4
        NULL  //OtherArg4Offset
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_UTIL, 
            "Formatting request 0x%p with Brb 0x%p failed, Status code %!STATUS!\n",
            Request,
            Brb,
            status
            );

        goto exit;
    }
exit:
    return status;
}
Example #8
0
NTSTATUS
I2COpen(
    _In_ PDEVICE_CONTEXT DeviceContext
)
/*++

Routine Description:

    This routine opens a handle to the I2C controller.

Arguments:

    DeviceContext - a pointer to the device context

Return Value:

    NTSTATUS

--*/
{
    TRACE_FUNC_ENTRY(TRACE_I2C);

    PAGED_CODE();

    NTSTATUS status;
    WDF_IO_TARGET_OPEN_PARAMS openParams;
    WDF_OBJECT_ATTRIBUTES requestAttributes;
    WDF_OBJECT_ATTRIBUTES workitemAttributes;
    WDF_WORKITEM_CONFIG workitemConfig;

    // Create the device path using the connection ID.
    DECLARE_UNICODE_STRING_SIZE(DevicePath, RESOURCE_HUB_PATH_SIZE);

    RESOURCE_HUB_CREATE_PATH_FROM_ID(
        &DevicePath,
        DeviceContext->I2CConnectionId.LowPart,
        DeviceContext->I2CConnectionId.HighPart);

    TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_I2C,
        "Opening handle to I2C target via %wZ", &DevicePath);

    status = WdfIoTargetCreate(DeviceContext->Device, WDF_NO_OBJECT_ATTRIBUTES, &DeviceContext->I2CIoTarget);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C,
            "WdfIoTargetCreate failed - %!STATUS!", status);
        goto Exit;
    }

    // Open a handle to the I2C controller.
    WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(
        &openParams,
        &DevicePath,
        (GENERIC_READ | GENERIC_WRITE));

    openParams.ShareAccess = 0;
    openParams.CreateDisposition = FILE_OPEN;
    openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL;

    status = WdfIoTargetOpen(DeviceContext->I2CIoTarget, &openParams);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C,
            "Failed to open I2C I/O target - %!STATUS!", status);
        goto Exit;
    }

    // Create a WDFMEMORY object. Do call WdfMemoryAssignBuffer before use it,
    status = WdfMemoryCreatePreallocated(
        WDF_NO_OBJECT_ATTRIBUTES,
        static_cast<PVOID>(&status), // initial value does not matter
        sizeof(status),
        &DeviceContext->I2CMemory);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C,
            "WdfMemoryCreatePreallocated failed with status %!STATUS!", status);
        goto Exit;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&requestAttributes);
    requestAttributes.ParentObject = DeviceContext->I2CIoTarget;

    for (ULONG i = 0; i < I2CRequestSourceMax; i++)
    {
        status = WdfRequestCreate(&requestAttributes, DeviceContext->I2CIoTarget, &DeviceContext->OutgoingRequests[i]);
        if (!NT_SUCCESS(status))
        {
            TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C,
                "WdfRequestCreate failed with status %!STATUS!", status);
            goto Exit;
        }
    }

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&workitemAttributes, WORKITEM_CONTEXT);
    workitemAttributes.ParentObject = DeviceContext->I2CIoTarget;

    WDF_WORKITEM_CONFIG_INIT(&workitemConfig, EvtWorkItemGetStatus);
    status = WdfWorkItemCreate(&workitemConfig, &workitemAttributes, &DeviceContext->I2CWorkItemGetStatus);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C,
            "WdfWorkItemCreate failed with status %!STATUS!", status);
        goto Exit;
    }

    WDF_WORKITEM_CONFIG_INIT(&workitemConfig, EvtWorkItemGetControl);
    status = WdfWorkItemCreate(&workitemConfig, &workitemAttributes, &DeviceContext->I2CWorkItemGetControl);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, TRACE_I2C,
            "WdfWorkItemCreate failed with status %!STATUS!", status);
        goto Exit;
    }

Exit:
    TRACE_FUNC_EXIT(TRACE_I2C);
    return status;
}
Example #9
0
VOID
ReadWriteBulkEndPoints(
    IN WDFQUEUE         Queue,
    IN WDFREQUEST       Request,
    IN ULONG            Length,
    IN WDF_REQUEST_TYPE RequestType
    )
/*++

Routine Description:

    This callback is invoked when the framework received  WdfRequestTypeRead or
    RP_MJ_WRITE request. This read/write is performed in stages of
    MAX_TRANSFER_SIZE. Once a stage of transfer is complete, then the
    request is circulated again, until the requested length of transfer is
    performed.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.

    Request - Handle to a framework request object. This one represents
              the WdfRequestTypeRead/WdfRequestTypeWrite IRP received by the framework.

    Length - Length of the input/output buffer.

Return Value:

   VOID

--*/
{
    size_t                totalLength = Length;
    size_t                stageLength = 0;
    NTSTATUS              status;
    PVOID                 virtualAddress = 0;
    PREQUEST_CONTEXT      rwContext = NULL;
    PFILE_CONTEXT         fileContext = NULL;
    WDFUSBPIPE            pipe;
    WDFMEMORY             reqMemory;
    WDFMEMORY_OFFSET      offset;
    WDF_OBJECT_ATTRIBUTES objectAttribs;
    PDEVICE_CONTEXT       deviceContext;

    kJtag_DbgPrint(3, ("kJtag_DispatchReadWrite - begins\n"));

    //
    // First validate input parameters.
    //
    deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));

    if (totalLength > deviceContext->MaximumTransferSize) {
        kJtag_DbgPrint(1, ("Transfer length > circular buffer\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    if ((RequestType != WdfRequestTypeRead) &&
        (RequestType != WdfRequestTypeWrite)) {
        kJtag_DbgPrint(1, ("RequestType has to be either Read or Write\n"));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

    //
    // Get the pipe associate with this request.
    //
    fileContext = GetFileContext(WdfRequestGetFileObject(Request));
    pipe = fileContext->Pipe;

    rwContext = GetRequestContext(Request);

    if(RequestType == WdfRequestTypeRead) {
        status = WdfRequestRetrieveOutputBuffer(Request, Length, &virtualAddress, &totalLength);
        rwContext->Read = TRUE;

    } else { //Write

        status = WdfRequestRetrieveInputBuffer(Request, Length, &virtualAddress, &totalLength);
        rwContext->Read = FALSE;
    }

    if(!NT_SUCCESS(status)){
        kJtag_DbgPrint(1, ("WdfRequestRetrieveInputBuffer failed\n"));
        goto Exit;
    }

    //
    // If the totalLength exceeds MAX_TRANSFER_SIZE, we will break
    // that into multiple transfer of size no more than MAX_TRANSFER_SIZE
    // in each stage.
    //
    if (totalLength > MAX_TRANSFER_SIZE) {
        stageLength = MAX_TRANSFER_SIZE;
    }
    else {
        stageLength = totalLength;
    }

    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
    objectAttribs.ParentObject = Request;
    status = WdfMemoryCreatePreallocated(&objectAttribs,
                                         virtualAddress,
                                         totalLength,
                                         &reqMemory);
    if(!NT_SUCCESS(status)){
        kJtag_DbgPrint(1, ("WdfMemoryCreatePreallocated failed\n"));
        goto Exit;
    }

    offset.BufferOffset = 0;
    offset.BufferLength = stageLength;

    //
    // The framework format call validates to make sure that you are reading or
    // writing to the right pipe type, sets the appropriate transfer flags,
    // creates an URB and initializes the request.
    //
    if(RequestType == WdfRequestTypeRead) {

        kJtag_DbgPrint(3, ("Read operation\n"));
        status = WdfUsbTargetPipeFormatRequestForRead(pipe,
                                                      Request,
                                                      reqMemory,
                                                      &offset);
    } else {

        kJtag_DbgPrint(3, ("Write operation\n"));
        status = WdfUsbTargetPipeFormatRequestForWrite(pipe,
                                                       Request,
                                                       reqMemory,
                                                       &offset);
    }

    if (!NT_SUCCESS(status)) {
        kJtag_DbgPrint(1, ("WdfUsbTargetPipeFormatRequest failed 0x%x\n", status));
        goto Exit;
    }

    WdfRequestSetCompletionRoutine(
                            Request,
                            ReadWriteCompletion,
                            NULL);
    //
    // set REQUEST_CONTEXT parameters.
    //
    rwContext->Length  = totalLength - stageLength;
    rwContext->Numxfer = 0;

    //
    // Send the request asynchronously.
    //
    if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) {
        kJtag_DbgPrint(1, ("WdfRequestSend failed\n"));
        status = WdfRequestGetStatus(Request);
        goto Exit;
    }


Exit:
    if (!NT_SUCCESS(status)) {
        WdfRequestCompleteWithInformation(Request, status, 0);
    }

    kJtag_DbgPrint(3, ("kJtag_DispatchReadWrite - ends\n"));

    return;
}
Example #10
0
NTSTATUS EvtDeviceAdd(
                      IN WDFDRIVER  Driver,
                      IN PWDFDEVICE_INIT  DeviceInit
                      )
{
  NTSTATUS status;
  WDFDEVICE device;									// Device object
  PDEVICE_CONTEXT devCtx = NULL;					// Pointer to a device context
  WDF_OBJECT_ATTRIBUTES attributes;					// Object attribute
  WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;	// PNP Power event callback
  WDF_DEVICE_PNP_CAPABILITIES pnpCapabilities;		//

  UNREFERENCED_PARAMETER(Driver);

  /*Set the callback functions that will be executed on PNP and Power events*/
  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);	// Init pnpPowerCallbacks
  pnpPowerCallbacks.EvtDevicePrepareHardware = EvtDevicePrepareHardware;
  pnpPowerCallbacks.EvtDeviceD0Entry = EvtDeviceD0Entry;
  pnpPowerCallbacks.EvtDeviceD0Exit = EvtDeviceD0Exit;
  WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);	// Setup pnpPowerCallbacks

  WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);	// Buffered IO type

  /*Initialize storage for the device context*/
  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);

  /*Create a device instance.*/
  status = WdfDeviceCreate(&DeviceInit, &attributes, &device);  
  if(!NT_SUCCESS(status))
  {
    KdPrint((__DRIVER_NAME
      "WdfDeviceCreate failed with status 0x%08x\n", status));
    return status;
  }

  /*Set the PNP capabilities of our device. we don't want an annoying
    popup if the device is pulled out of the USB slot.*/
  WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCapabilities);
  pnpCapabilities.Removable = WdfTrue;				// Can hot-unplug
  pnpCapabilities.SurpriseRemovalOK = WdfTrue;		//
  WdfDeviceSetPnpCapabilities(device, &pnpCapabilities);
  
  devCtx = GetDeviceContext(device);

  /*Create a WDF memory object for the memory that is occupied by the
    WdfMemLEDArrayState variable in the device context.
    this way we have the value itself handy for debugging purposes, and
    we have a WDF memory handle that can be used for passing to the low
    level USB functions.
    this alleviates the need to getting the buffer at run time.*/
  status = WdfMemoryCreatePreallocated(WDF_NO_OBJECT_ATTRIBUTES,
                           &devCtx->D0LEDArrayState,
                           sizeof(devCtx->D0LEDArrayState),
                           &devCtx->WdfMemLEDArrayState);	// for Debbug 
  if(!NT_SUCCESS(status))
  {
    KdPrint((__DRIVER_NAME
      "WdfMemoryCreatePreallocated failed with status 0x%08x\n", status));
    return status;
  }

  // Create Queues for handling IO request
  status = CreateQueues(device, devCtx);
  if(!NT_SUCCESS(status))
    return status;

  // Create Device Interface
  status = WdfDeviceCreateDeviceInterface(device, &GUID_DEV_IF_LEDSCTRL, NULL);
  if(!NT_SUCCESS(status))
  {
    KdPrint((__DRIVER_NAME
      "WdfDeviceCreateDeviceInterface failed with status 0x%08x\n", status));
    return status;
  }

  return status;
  
}