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
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
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
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; }
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
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; }
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; }
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; }
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; }