예제 #1
0
NS_IMETHODIMP
RequestContextService::GetRequestContextFromLoadGroup(nsILoadGroup *aLoadGroup, nsIRequestContext **rc)
{
  nsresult rv;

  uint64_t rcID;
  rv = aLoadGroup->GetRequestContextID(&rcID);
  if (NS_FAILED(rv)) {
    return rv;
  }

  return GetRequestContext(rcID, rc);
}
예제 #2
0
/*++
Routine Description:

This callback is invoked on every inflight request when the device
is suspended or removed. Since our inflight read and write requests
are actually pending in the target device, we will just acknowledge
its presence. Until we acknowledge, complete, or requeue the requests
framework will wait before allowing the device suspend or remove to
proceed. When the underlying USB stack gets the request to suspend or
remove, it will fail all the pending requests.

Arguments:

Return Value:
None
--*/
VOID PSDrvEvtIoStop(__in WDFQUEUE Queue, __in WDFREQUEST Request, __in ULONG ActionFlags)
{
	PREQUEST_CONTEXT reqContext;

	UNREFERENCED_PARAMETER(Queue);

	reqContext=GetRequestContext(Request);

	if (ActionFlags & WdfRequestStopActionSuspend ) {
		WdfRequestStopAcknowledge(Request, FALSE); // Don't requeue
	} else if(ActionFlags & WdfRequestStopActionPurge) {
		WdfRequestCancelSentRequest(Request);
	}
	return;
}
예제 #3
0
/* EvtIoStop
Invoked for every inflight pipe write request.  The callback executes when:
1) libusbK will stop the queue because of queue policy changes.
2) The system requests stand-by
3) The device is removed
*/
VOID Queue_OnStop(
    __in WDFQUEUE Queue,
    __in WDFREQUEST Request,
    __in ULONG ActionFlags)
{
	PQUEUE_CONTEXT queueContext;
	PREQUEST_CONTEXT requestContext;

	if (Request == NULL || Queue == NULL)
	{
		USBERRN("Invalid wdf object.");
		return;
	}
	if ((queueContext = GetQueueContext(Queue)) == NULL)
	{
		USBERRN("Invalid queue context.");
		return;
	}
	if ((requestContext = GetRequestContext(Request)) == NULL)
	{
		USBERRN("Invalid request context.");
		return;
	}

	// None of the libusbK transfer functions set EvtRequestCancel, hence this should never happen.
	if (ActionFlags & WdfRequestStopRequestCancelable)
	{
		USBERRN("WdfRequestStopRequestCancelable! pipeID=%02Xh", queueContext->Info.EndpointAddress);
		WdfVerifierDbgBreakPoint();
		return;
	}

	if (ActionFlags & WdfRequestStopActionSuspend)
	{

		USBDBGN("StopAcknowledge for ActionSuspend. pipeID=%02Xh request=%p timeout=%d", 
			queueContext->Info.EndpointAddress, Request, requestContext->Timeout);

		WdfRequestStopAcknowledge(Request, FALSE);
	}
	else if(ActionFlags & WdfRequestStopActionPurge)
	{
		USBDBGN("CancelSentRequest for ActionPurge. pipeID=%02Xh request=%p timeout=%d", 
				queueContext->Info.EndpointAddress, Request, requestContext->Timeout);

		WdfRequestCancelSentRequest(Request);
	}
}
예제 #4
0
/* EvtIoResume
Invoked for pipe write requests which were "StopAcknowledge" in EvtIoStop.
This callback exucutes after the device has re-entered D0(working).
*/
VOID Queue_OnResume(WDFQUEUE Queue, WDFREQUEST Request)
{
	PQUEUE_CONTEXT queueContext;
	PREQUEST_CONTEXT requestContext;
	NTSTATUS status = STATUS_SUCCESS;

	if (Request == NULL || Queue == NULL)
	{
		USBERRN("Invalid wdf object.");
		return;
	}
	if ((queueContext = GetQueueContext(Queue)) == NULL)
	{
		USBERRN("Invalid queue context.");
		return;
	}
	if ((requestContext = GetRequestContext(Request)) == NULL)
	{
		USBERRN("Invalid request context.");
		return;
	}

	mXfer_HandlePipeResetScenarios(status, queueContext, requestContext);
}
예제 #5
0
VOID PipeQueue_OnIoControl(__in WDFQUEUE Queue,
						   __in WDFREQUEST Request,
						   __in size_t OutputBufferLength,
						   __in size_t InputBufferLength,
						   __in ULONG IoControlCode)
{
	NTSTATUS status;
	ULONG length = 0;
	PREQUEST_CONTEXT requestContext = GetRequestContext(Request);
	PQUEUE_CONTEXT queueContext = NULL;

	VALIDATE_REQUEST_CONTEXT(requestContext, status);
	if (!NT_SUCCESS(status)) goto Done;

	if ((queueContext = GetQueueContext(Queue)) == NULL)
	{
		status = STATUS_INVALID_DEVICE_REQUEST;
		USBERRN("Invalid queue context");
		goto Done;
	}

	switch(IoControlCode)
	{
	case LIBUSB_IOCTL_ISOCHRONOUS_READ:
	case LIBUSB_IOCTL_ISOCHRONOUS_WRITE:
	case LIBUSB_IOCTL_INTERRUPT_OR_BULK_WRITE:
	case LIBUSB_IOCTL_INTERRUPT_OR_BULK_READ:

		switch (queueContext->Info.PipeType)
		{
		case WdfUsbPipeTypeIsochronous:

			if (USB_ENDPOINT_DIRECTION_IN(queueContext->Info.EndpointAddress))
			{
				XferIsoRead(Queue, Request);
				return;
			}
			XferIsoWrite(Queue, Request);
			return;

		case WdfUsbPipeTypeBulk:
		case WdfUsbPipeTypeInterrupt:
			if(requestContext->Policies.RawIO)
			{
				if (USB_ENDPOINT_DIRECTION_IN(queueContext->Info.EndpointAddress))
					Xfer_ReadBulkRaw(Queue, Request);
				else
					Xfer_WriteBulkRaw(Queue, Request);
			}
			else
			{
				if (USB_ENDPOINT_DIRECTION_IN(queueContext->Info.EndpointAddress))
					Xfer_ReadBulk(Queue, Request);
				else
					Xfer_WriteBulk(Queue, Request);
			}
			return;

		default:
			status = STATUS_INVALID_PARAMETER;
			USBERRN("Invalid PipeType=%s\n", GetPipeTypeString(queueContext->Info.PipeType));
			break;
		}

	case LIBUSBK_IOCTL_ISOEX_READ:
	case LIBUSBK_IOCTL_ISOEX_WRITE:
		if (queueContext->Info.PipeType == WdfUsbPipeTypeIsochronous)
		{
			XferIsoEx(Queue, Request);
			return;
		}
		status = STATUS_INVALID_PARAMETER;
		USBERRN("Invalid PipeType=%s\n", GetPipeTypeString(queueContext->Info.PipeType));
		break;

		/*
		case LIBUSBK_IOCTL_AUTOISOEX_READ:
		case LIBUSBK_IOCTL_AUTOISOEX_WRITE:
			if (queueContext->Info.PipeType == WdfUsbPipeTypeIsochronous)
			{
				XferAutoIsoEx(Queue, Request);
				return;
			}
			status = STATUS_INVALID_PARAMETER;
			USBERRN("Invalid PipeType=%s\n", GetPipeTypeString(queueContext->Info.PipeType));
			break;
		*/

	case LIBUSB_IOCTL_SET_FEATURE:
	case LIBUSB_IOCTL_CLEAR_FEATURE:
	case LIBUSB_IOCTL_GET_DESCRIPTOR:
	case LIBUSB_IOCTL_SET_DESCRIPTOR:
	case LIBUSB_IOCTL_VENDOR_WRITE:
	case LIBUSB_IOCTL_VENDOR_READ:
	case LIBUSB_IOCTL_CONTROL_READ:
	case LIBUSB_IOCTL_CONTROL_WRITE:

		XferCtrl(Queue, Request, InputBufferLength, OutputBufferLength);
		return;

	default:

		USBERR("unknown IoControlCode %Xh (function=%04Xh)\n", IoControlCode, FUNCTION_FROM_CTL_CODE(IoControlCode));
		status = STATUS_INVALID_DEVICE_REQUEST;
		WdfRequestCompleteWithInformation(Request, status, 0);

		return;
	}

Done:
	WdfRequestCompleteWithInformation(Request, status, length);
	return;

}
예제 #6
0
파일: usbchief.c 프로젝트: LaneTee/usbchief
static VOID UsbChief_ReadEndPoint(IN WDFQUEUE Queue, IN WDFREQUEST Request,
			   IN ULONG totalLength)
{
	PMDL                    newMdl=NULL, requestMdl = NULL;
	PURB                    urb = NULL;
	WDFMEMORY               urbMemory;
	ULONG                   stageLength = 0;
	NTSTATUS                status;
	ULONG_PTR               virtualAddress = 0;
	PREQUEST_CONTEXT        rwContext = NULL;
	PFILE_CONTEXT           fileContext = NULL;
	WDFUSBPIPE              pipe;
	WDF_USB_PIPE_INFORMATION   pipeInfo;
	WDF_OBJECT_ATTRIBUTES   objectAttribs;
	USBD_PIPE_HANDLE        usbdPipeHandle;
	PDEVICE_CONTEXT         deviceContext;

	UsbChief_DbgPrint(DEBUG_RW, ("UsbChief_DispatchReadWrite - begins\n"));

	deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
	fileContext = GetFileContext(WdfRequestGetFileObject(Request));
	pipe = fileContext->Pipe;

	WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
	WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);

	rwContext = GetRequestContext(Request);

	status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
	if(!NT_SUCCESS(status)){
		UsbChief_DbgPrint(0, ("WdfRequestRetrieveOutputWdmMdl failed %x\n", status));
		goto Exit;
	}
	virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl);

	if (totalLength > MAX_TRANSFER_SIZE)
		stageLength = MAX_TRANSFER_SIZE;
	else
		stageLength = totalLength;

	newMdl = IoAllocateMdl((PVOID) virtualAddress, totalLength,
			       FALSE, FALSE, NULL);

	if (!newMdl) {
		UsbChief_DbgPrint(0, ("Failed to alloc mem for mdl\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	IoBuildPartialMdl(requestMdl, newMdl, (PVOID)virtualAddress,
			  stageLength);

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

	status = WdfMemoryCreate(&objectAttribs,
				 NonPagedPool,
				 POOL_TAG,
				 sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
				 &urbMemory,
				 (PVOID*) &urb);

	if (!NT_SUCCESS(status)) {
		UsbChief_DbgPrint(0, ("Failed to alloc mem for urb\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);

	UsbBuildInterruptOrBulkTransferRequest(urb,
					       sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
					       usbdPipeHandle,
					       NULL,
					       newMdl,
					       stageLength,
					       USBD_TRANSFER_DIRECTION_IN |
					       USBD_SHORT_TRANSFER_OK,
					       NULL);

	status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL  );
	if (!NT_SUCCESS(status)) {
		UsbChief_DbgPrint(0, ("Failed to format requset for urb\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto Exit;
	}
	WdfRequestSetCompletionRoutine(Request, UsbChief_ReadCompletion, NULL);

	rwContext->UrbMemory       = urbMemory;
	rwContext->Mdl             = newMdl;
	rwContext->Length          = totalLength - stageLength;
	rwContext->Numxfer         = 0;
	rwContext->VirtualAddress  = virtualAddress + stageLength;

	if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) {
		status = WdfRequestGetStatus(Request);
		ASSERT(!NT_SUCCESS(status));
	}

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

		if (newMdl != NULL) {
			IoFreeMdl(newMdl);
		}
	}
}
예제 #7
0
VOID
NdisprotSendComplete(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN PNET_BUFFER_LIST             pNetBufferList,
    IN ULONG                        SendCompleteFlags
    )
/*++

Routine Description:

    NDIS entry point called to signify completion of a packet send.
    We pick up and complete the Write IRP corresponding to this packet.

Arguments:

    ProtocolBindingContext - pointer to open context
    pNetBufferList - NetBufferList that completed send
    SendCompleteFlags - Specifies if the caller is at DISPATCH level

Return Value:

    None

--*/
{
    PNDISPROT_OPEN_CONTEXT      pOpenContext;
    PNET_BUFFER_LIST            CurrNetBufferList = NULL;
    PNET_BUFFER_LIST            NextNetBufferList;
    NDIS_STATUS                 CompletionStatus;
    BOOLEAN                     DispatchLevel;
    WDFREQUEST                  request;
    PREQUEST_CONTEXT            reqContext;


    pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
    NPROT_STRUCT_ASSERT(pOpenContext, oc);
    DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendCompleteFlags);


    for (CurrNetBufferList = pNetBufferList;
            CurrNetBufferList != NULL;
            CurrNetBufferList = NextNetBufferList)
    {
        NextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrNetBufferList);

        request = NPROT_REQUEST_FROM_SEND_NBL(CurrNetBufferList);
        reqContext = GetRequestContext(request);
        CompletionStatus = NET_BUFFER_LIST_STATUS(CurrNetBufferList);

        DEBUGP(DL_INFO, ("SendComplete: NetBufferList %p/IRP %p/Length %d "
                        "completed with status %x\n",
                        CurrNetBufferList, request, reqContext->Length,
                        CompletionStatus));

		//
        //  We are done with the NDIS_PACKET:
        //
        NPROT_DEREF_SEND_NBL(CurrNetBufferList, DispatchLevel);
        CurrNetBufferList = NULL;

        if (CompletionStatus == NDIS_STATUS_SUCCESS)
        {
            WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, reqContext->Length);
         }
        else
        {
            WdfRequestCompleteWithInformation(request, STATUS_UNSUCCESSFUL, 0);
        }

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, DispatchLevel);
        pOpenContext->PendedSendCount--;

        if ((NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_CLOSING))
                && (pOpenContext->PendedSendCount == 0))
        {
            NPROT_ASSERT(pOpenContext->ClosingEvent != NULL);
            NPROT_SIGNAL_EVENT(pOpenContext->ClosingEvent);
            pOpenContext->ClosingEvent = NULL;
        }
        NPROT_RELEASE_LOCK(&pOpenContext->Lock, DispatchLevel);

        NPROT_DEREF_OPEN(pOpenContext); // send complete - dequeued send IRP
    }

}
예제 #8
0
파일: Transfer.c 프로젝트: kcrazy/winekit
VOID
AmccPciEvtIoDefault(
    __in WDFQUEUE       Queue,
    __in WDFREQUEST     Request
    )
/*++

Routine Description:

    Start the IRP on the device.  This driver allows only one I/O to
    be active on the adapter at any one time.  If multiple I/Os are sent
    to the driver, they will be queued and completed as they complete on
    the adapter (one IRP per interrupt).

Arguments:

    Queue - Default queue handle
    Request - Handle to the write request
    Parameters - Contains current stack location information from the IRP

Return Value:

    None

--*/
{
    PAMCC_DEVICE_EXTENSION    devExt;
    REQUEST_CONTEXT         * transfer;
    NTSTATUS                  status;
    size_t                    length;
    WDF_DMA_DIRECTION         direction;
    WDFDMATRANSACTION         dmaTransaction;
    WDF_REQUEST_PARAMETERS    params;

    WDF_REQUEST_PARAMETERS_INIT(&params);

    WdfRequestGetParameters(
        Request,
        &params
        );

    //
    // Get the device extension.
    //
    devExt = AmccPciGetDevExt(WdfIoQueueGetDevice( Queue ));

    //
    // Validate and gather parameters.
    //
    switch (params.Type) {

        case WdfRequestTypeRead:
            length    = params.Parameters.Read.Length;
            direction = WdfDmaDirectionReadFromDevice;
            break;

        case WdfRequestTypeWrite:
            length    = params.Parameters.Write.Length;
            direction = WdfDmaDirectionWriteToDevice;
            break;

        default:
            TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO,
                        "Request type not Read or Write\n");
            WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
            return;
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO,
                "Request %p: %s %d bytes",
                Request, (direction)?"Write":"Read", (ULONG)length);

    //
    // The length must be non-zero.
    //
    if (length == 0) {
        TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO,
                    "Zero transfer length input to read/write");
        WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
        return;
    }

    transfer = GetRequestContext(Request);

    //
    // Create new DmaRequst to conduct this DMA transaction.
    //
    status = WdfDmaTransactionCreate( devExt->DmaEnabler,
                                      WDF_NO_OBJECT_ATTRIBUTES,
                                      &dmaTransaction );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                    "WdfDmaRequestCreate failed: %X", status);
        WdfRequestComplete(Request, status);
        return;
    }

    //
    // Create new DmaTransaction.
    //
    status = WdfDmaTransactionInitializeUsingRequest( dmaTransaction,
                                                      Request,
                                                      AmccPciProgramDma,
                                                      direction );

    if(!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                    "WdfDmaRequestInitializeWithRequest failed: %X",
                    status);

        WdfObjectDelete(dmaTransaction);

        WdfRequestComplete(Request, status);
        return;
    }

    //
    // Fill transfer context structure
    //
    transfer->Request        = Request;
    transfer->DmaTransaction = dmaTransaction;

    //
    // Save the current Request as the "in-progress" request.
    //
    devExt->CurrentRequest = Request;

    //
    // Execute this dmaTransaction transaction.
    //
    status = WdfDmaTransactionExecute( dmaTransaction, WDF_NO_CONTEXT);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                    "WdfDmaTransactionExecute failed: %X",
                    status);

        WdfObjectDelete(dmaTransaction);
        WdfRequestComplete(Request, status);
        return;
    }

    return;
}
예제 #9
0
파일: PSDrvBulk.c 프로젝트: 3david/OpenNI
/*++
Routine Description:

This callback is invoked when the framework received  WdfRequestTypeRead or
WdfRequestTypeWrite 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
--*/
VOID ReadWriteBulkEndPoints(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG Length, IN WDF_REQUEST_TYPE RequestType)
{
    PMDL						newMdl = NULL;
	PMDL						requestMdl = NULL;
    PURB						urb = NULL;
    WDFMEMORY					urbMemory;
    ULONG						totalLength = Length;
    ULONG						stageLength = 0;
    ULONG						urbFlags = 0;
    NTSTATUS					status;
    ULONG_PTR					virtualAddress = 0;
    PREQUEST_CONTEXT			rwContext = NULL;
    PFILE_CONTEXT				fileContext = NULL;
    WDFUSBPIPE					pipe;
    WDF_USB_PIPE_INFORMATION	pipeInfo;
    WDF_OBJECT_ATTRIBUTES		objectAttribs;
    USBD_PIPE_HANDLE			usbdPipeHandle;
    PDEVICE_CONTEXT				deviceContext;
	WDF_REQUEST_SEND_OPTIONS	sendOptions;

    PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - begins\n"));

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

    if (totalLength > deviceContext->MaximumTransferSize)
	{
        PSDrv_DbgPrint(1, ("Transfer length (%d) is bigger then MaximumTransferSize (%d)!\n", totalLength, deviceContext->MaximumTransferSize));
        status = STATUS_INVALID_PARAMETER;
        goto Exit;
    }

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

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

    if((WdfUsbPipeTypeBulk != pipeInfo.PipeType) && (WdfUsbPipeTypeInterrupt != pipeInfo.PipeType))
	{
        PSDrv_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt! (PipeType = %d)\n", pipeInfo.PipeType));
        status = STATUS_INVALID_DEVICE_REQUEST;
        goto Exit;
    }

    rwContext = GetRequestContext(Request);

    if(RequestType == WdfRequestTypeRead)
	{
        status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
        if(!NT_SUCCESS(status))
		{
            PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl failed! (Status = %x)\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_IN;
        rwContext->Read = TRUE;
        PSDrv_DbgPrint(3, ("This is a read operation...\n"));
    }
	else
	{
        status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl);
        if(!NT_SUCCESS(status))
		{
			PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed! (Status = %x)\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
        rwContext->Read = FALSE;
        PSDrv_DbgPrint(3, ("This is a write operation...\n"));
    }


    urbFlags |= USBD_SHORT_TRANSFER_OK;

    virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl);

    // The transfer request is for totalLength. We can perform a max of MAX_TRANSFER_SIZE in each stage.
    if (totalLength > MAX_TRANSFER_SIZE)
	{
        stageLength = MAX_TRANSFER_SIZE;
    }
    else
	{
        stageLength = totalLength;
    }

    newMdl = IoAllocateMdl((PVOID)virtualAddress, totalLength, FALSE, FALSE, NULL);
    if (newMdl == NULL)
	{
        PSDrv_DbgPrint(1, ("IoAllocateMdl failed! (newMdl is NULL)\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    // Map the portion of user-buffer described by an mdl to another mdl
    IoBuildPartialMdl(requestMdl, newMdl, (PVOID)virtualAddress, stageLength);

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

    status = WdfMemoryCreate(&objectAttribs, NonPagedPool, POOL_TAG, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), &urbMemory, (PVOID*)&urb);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfMemoryCreate for urbMemory failed! (Status = %x)\n", status));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);

    UsbBuildInterruptOrBulkTransferRequest(urb, sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), usbdPipeHandle, NULL, newMdl, stageLength, urbFlags, NULL);

    status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL);
    if (!NT_SUCCESS(status))
	{
        PSDrv_DbgPrint(1, ("WdfUsbTargetPipeFormatRequestForUrb failed! (Status = %x)\n", status));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    WdfRequestSetCompletionRoutine(Request, ReadWriteCompletion, NULL);

    // Set REQUEST_CONTEXT parameters.
    rwContext->UrbMemory       = urbMemory;
    rwContext->Mdl             = newMdl;
    rwContext->Length          = totalLength - stageLength;
    rwContext->Numxfer         = 0;
    rwContext->VirtualAddress  = virtualAddress + stageLength;

	// Set the timeout
	if (fileContext->nTimeOut != 0)
	{
		WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT);
		WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_MS(fileContext->nTimeOut));

		PSDrv_DbgPrint(3, ("Pipe timeout is set to: %d\n", fileContext->nTimeOut));

		if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), &sendOptions))
		{
			status = WdfRequestGetStatus(Request);
			ASSERT(!NT_SUCCESS(status));
		}
	}
	else
	{
		if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS))
		{
			status = WdfRequestGetStatus(Request);
			ASSERT(!NT_SUCCESS(status));
		}
	}

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

        if (newMdl != NULL)
		{
            IoFreeMdl(newMdl);
        }
    }

    PSDrv_DbgPrint(3, ("ReadWriteBulkEndPoints - ends\n"));

    return;
}
예제 #10
0
파일: nonpnp.c 프로젝트: 340211173/Driver
VOID
FileEvtIoDeviceControl(
    IN WDFQUEUE         Queue,
    IN WDFREQUEST       Request,
    IN size_t            OutputBufferLength,
    IN size_t            InputBufferLength,
    IN ULONG            IoControlCode
    )
/*++
Routine Description:

    This event is called when the framework receives IRP_MJ_DEVICE_CONTROL
    requests from the system.

Arguments:

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

    OutputBufferLength - length of the request's output buffer,
                        if an output buffer is available.
    InputBufferLength - length of the request's input buffer,
                        if an input buffer is available.

    IoControlCode - the driver-defined or system-defined I/O control code
                    (IOCTL) that is associated with the request.

Return Value:

   VOID

--*/
{
    NTSTATUS            status = STATUS_SUCCESS;// Assume success
    PCHAR               inBuf = NULL, outBuf = NULL; // pointer to Input and output buffer
    PCHAR               data = "this String is from Device Driver !!!";
    ULONG               datalen = (ULONG) strlen(data)+1;//Length of data including null
    PCHAR               buffer = NULL;
    PREQUEST_CONTEXT    reqContext = NULL;
    size_t               bufSize;

    UNREFERENCED_PARAMETER( Queue );

    PAGED_CODE();

    if(!OutputBufferLength || !InputBufferLength)
    {
        WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
        return;
    }

    //
    // Determine which I/O control code was specified.
    //

    switch (IoControlCode)
    {
    case IOCTL_NONPNP_METHOD_BUFFERED:


        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_BUFFERED\n");

        //
        // For bufffered ioctls WdfRequestRetrieveInputBuffer &
        // WdfRequestRetrieveOutputBuffer return the same buffer
        // pointer (Irp->AssociatedIrp.SystemBuffer), so read the
        // content of the buffer before writing to it.
        //
        status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize);
        if(!NT_SUCCESS(status)) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        ASSERT(bufSize == InputBufferLength);

        //
        // Read the input buffer content.
        // We are using the following function to print characters instead
        // TraceEvents with %s format because the string we get may or
        // may not be null terminated. The buffer may contain non-printable
        // characters also.
        //
        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User : %!HEXDUMP!\n",
                        log_xstr(inBuf, (USHORT)InputBufferLength)));
        PrintChars(inBuf, InputBufferLength  );


        status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufSize);
        if(!NT_SUCCESS(status)) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        ASSERT(bufSize == OutputBufferLength);

        //
        // Writing to the buffer over-writes the input buffer content
        //

        RtlCopyMemory(outBuf, data, OutputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data to User : %!HEXDUMP!\n",
                        log_xstr(outBuf, (USHORT)datalen)));
        PrintChars(outBuf, datalen  );

        //
        // Assign the length of the data copied to IoStatus.Information
        // of the request and complete the request.
        //
        WdfRequestSetInformation(Request,
                OutputBufferLength < datalen? OutputBufferLength:datalen);

        //
        // When the request is completed the content of the SystemBuffer
        // is copied to the User output buffer and the SystemBuffer is
        // is freed.
        //

       break;


    case IOCTL_NONPNP_METHOD_IN_DIRECT:


        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_IN_DIRECT\n");

        //
        // Get the Input buffer. WdfRequestRetrieveInputBuffer returns
        // Irp->AssociatedIrp.SystemBuffer.
        //
        status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize);
        if(!NT_SUCCESS(status)) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        ASSERT(bufSize == InputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User : %!HEXDUMP!\n",
                        log_xstr(inBuf, (USHORT)InputBufferLength)));
        PrintChars(inBuf, InputBufferLength);

        //
        // Get the output buffer. Framework calls MmGetSystemAddressForMdlSafe
        // on the Irp->MdlAddress and returns the system address.
        // Oddity: For this method, this buffer is intended for transfering data
        // from the application to the driver.
        //

        status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &bufSize);
        if(!NT_SUCCESS(status)) {
            break;
        }

        ASSERT(bufSize == OutputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User in OutputBuffer: %!HEXDUMP!\n",
                        log_xstr(buffer, (USHORT)OutputBufferLength)));
        PrintChars(buffer, OutputBufferLength);

        //
        // Return total bytes read from the output buffer.
        // Note OutputBufferLength = MmGetMdlByteCount(Irp->MdlAddress)
        //

        WdfRequestSetInformation(Request, OutputBufferLength);

        //
        // NOTE: Changes made to the  SystemBuffer are not copied
        // to the user input buffer by the I/O manager
        //

      break;

    case IOCTL_NONPNP_METHOD_OUT_DIRECT:


        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_OUT_DIRECT\n");

        //
        // Get the Input buffer. WdfRequestRetrieveInputBuffer returns
        // Irp->AssociatedIrp.SystemBuffer.
        //
        status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize);
        if(!NT_SUCCESS(status)) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        ASSERT(bufSize == InputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User : %!HEXDUMP!\n",
                        log_xstr(inBuf, (USHORT)InputBufferLength)));
        PrintChars(inBuf, InputBufferLength);

        //
        // Get the output buffer. Framework calls MmGetSystemAddressForMdlSafe
        // on the Irp->MdlAddress and returns the system address.
        // For this method, this buffer is intended for transfering data from the
        // driver to the application.
        //
        status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &bufSize);
        if(!NT_SUCCESS(status)) {
            break;
        }

        ASSERT(bufSize == OutputBufferLength);

        //
        // Write data to be sent to the user in this buffer
        //
        RtlCopyMemory(buffer, data, OutputBufferLength);

        Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data to User : %!HEXDUMP!\n",
                        log_xstr(buffer, (USHORT)datalen)));
        PrintChars(buffer, datalen);

        WdfRequestSetInformation(Request,
                    OutputBufferLength < datalen? OutputBufferLength: datalen);

        //
        // NOTE: Changes made to the  SystemBuffer are not copied
        // to the user input buffer by the I/O manager
        //

        break;

    case IOCTL_NONPNP_METHOD_NEITHER:
        {
            size_t inBufLength, outBufLength;

            //
            // The NonPnpEvtDeviceIoInCallerContext has already probe and locked the
            // pages and mapped the user buffer into system address space and
            // stored memory buffer pointers in the request context. We can get the
            // buffer pointer by calling WdfMemoryGetBuffer.
            //
            TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_NEITHER\n");

            reqContext = GetRequestContext(Request);

            inBuf = WdfMemoryGetBuffer(reqContext->InputMemoryBuffer, &inBufLength);
            outBuf = WdfMemoryGetBuffer(reqContext->OutputMemoryBuffer, &outBufLength);

            if(inBuf == NULL || outBuf == NULL) {
                status = STATUS_INVALID_PARAMETER;
            }

            ASSERT(inBufLength == InputBufferLength);
            ASSERT(outBufLength == OutputBufferLength);

            //
            // Now you can safely read the data from the buffer in any arbitrary
            // context.
            //
            Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data from User : %!HEXDUMP!\n",
                            log_xstr(inBuf, (USHORT)inBufLength)));
            PrintChars(inBuf, inBufLength);

            //
            // Write to the buffer in any arbitrary context.
            //
            RtlCopyMemory(outBuf, data, outBufLength);

            Hexdump((TRACE_LEVEL_VERBOSE,  DBG_IOCTL, "Data to User : %!HEXDUMP!\n",
                            log_xstr(outBuf, (USHORT)datalen)));
            PrintChars(outBuf, datalen);

            //
            // Assign the length of the data copied to IoStatus.Information
            // of the Irp and complete the Irp.
            //
            WdfRequestSetInformation(Request,
                    outBufLength < datalen? outBufLength:datalen);

            break;
        }
    default:

        //
        // The specified I/O control code is unrecognized by this driver.
        //
        status = STATUS_INVALID_DEVICE_REQUEST;
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ERROR: unrecognized IOCTL %x\n", IoControlCode);
        break;
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Completing Request %p with status %X",
                   Request, status );

    WdfRequestComplete( Request, status);

}
예제 #11
0
VOID XferCtrl (
    __in WDFQUEUE Queue,
    __in WDFREQUEST Request,
    __in size_t InputBufferLength,
    __in size_t OutputBufferLength)
{
	NTSTATUS                status;
	PDEVICE_CONTEXT         deviceContext;
	PREQUEST_CONTEXT        requestContext;
	WDFMEMORY				transferMemory;
	PWDF_USB_CONTROL_SETUP_PACKET setupPacket;
	WDF_REQUEST_SEND_OPTIONS sendOptions;
	WDFMEMORY_OFFSET		_transferOffset;
	PWDFMEMORY_OFFSET		transferOffset = &_transferOffset;

	UNREFERENCED_PARAMETER(InputBufferLength);
	UNREFERENCED_PARAMETER(OutputBufferLength);

	deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
	requestContext = GetRequestContext(Request);

	setupPacket = (PWDF_USB_CONTROL_SETUP_PACKET)&requestContext->IoControlRequest.control;
	USBDBG("bmDir=%s bmType=%s bmRecipient=%s bmReserved=%03u bRequest=%u wIndex=%u wValue=%u wLength=%u\n",
	       GetBmRequestDirString(setupPacket->Packet.bm.Request.Dir),
	       GetBmRequestTypeString(setupPacket->Packet.bm.Request.Type),
	       GetBmRequestRecipientString(setupPacket->Packet.bm.Request.Recipient),
	       setupPacket->Packet.bm.Request.Reserved,
	       setupPacket->Packet.bRequest,
	       setupPacket->Packet.wIndex.Value,
	       setupPacket->Packet.wValue.Value,
	       setupPacket->Packet.wLength);

	// If the device and config descriptor requests are not handled they will be the "true"
	// descriptors directly from the device. i.e. if the device has two unassociated interfaces
	// the composite layer will split it into two but each virtual device interface would show
	// both interface deacriptors.
	//
	if (setupPacket->Packet.bm.Request.Dir == BMREQUEST_DEVICE_TO_HOST &&
	        setupPacket->Packet.bm.Request.Type == BMREQUEST_STANDARD &&
	        setupPacket->Packet.bRequest == USB_REQUEST_GET_DESCRIPTOR)
	{
		UCHAR descriptorType = setupPacket->Packet.wValue.Bytes.HiByte;
		// UCHAR descriptorIndex = setupPacket->Packet.wValue.Bytes.LowByte;
		ULONG descriptorSize = 0;
		PVOID descriptorIn = NULL;
		PVOID outputBuffer = NULL;
		size_t outputBufferLength = 0;

		if (requestContext->IoControlCode == LIBUSB_IOCTL_GET_DESCRIPTOR)
		{
			switch(descriptorType)
			{
			case USB_DESCRIPTOR_TYPE_DEVICE:
				descriptorSize = sizeof(deviceContext->UsbDeviceDescriptor);
				descriptorIn = &deviceContext->UsbDeviceDescriptor;
				break;
			case USB_DESCRIPTOR_TYPE_CONFIGURATION:
				if (setupPacket->Packet.wValue.Bytes.LowByte == 0)
				{
					descriptorSize = deviceContext->ConfigurationDescriptorSize;
					descriptorIn = deviceContext->UsbConfigurationDescriptor;
				}
				else
				{
					// we only support the one for now. ;)
					WdfRequestCompleteWithInformation(Request, STATUS_NO_MORE_ENTRIES, 0);
					return;
				}
				break;
			}

			if (descriptorIn && descriptorSize)
			{
				// handle (or fail) this standard request here.
				status = WdfRequestRetrieveOutputBuffer(Request, 2, &outputBuffer, &outputBufferLength);
				if (NT_SUCCESS(status))
				{
					descriptorSize = (ULONG)min(descriptorSize, outputBufferLength);
					RtlCopyMemory(outputBuffer, descriptorIn, descriptorSize);
					WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, descriptorSize);
					return;
				}
				USBERR("WdfRequestRetrieveOutputBuffer failed. status=%Xh\n", status);
				WdfRequestCompleteWithInformation(Request, status, 0);
				return;
			}
		}
	}

	if (METHOD_FROM_CTL_CODE(requestContext->IoControlCode) == METHOD_BUFFERED &&
	        requestContext->RequestType == WdfRequestTypeWrite)
	{
		// support for some of the legacy LIBUSB_IOCTL codes which place the data input
		// buffer at the end of the libusb_request structure.
		status = WdfRequestRetrieveInputMemory(Request, &transferMemory);
		if (!NT_SUCCESS(status))
		{
			USBERR("WdfRequestRetrieveInputMemory failed. status=%Xh\n", status);
			goto Exit;
		}

		if (requestContext->Length < sizeof(libusb_request))
		{
			// this can never happen because the input buffer length is checked for
			// this by the default IoControl event.
			status = STATUS_BUFFER_TOO_SMALL;
			USBERR("input buffer length is less than sizeof(libusb_request) status=%Xh\n", status);
			goto Exit;
		}

		transferOffset->BufferOffset = sizeof(libusb_request);
		transferOffset->BufferLength = requestContext->Length - sizeof(libusb_request);

		if (transferOffset->BufferLength == 0)
		{
			// this is okay but no input data means transferOffset->BufferOffset is pointing
			// to invalid memory; because the length is also zero it is still most likely safe.
			transferOffset = NULL;
			transferMemory = NULL;
		}
	}
	else
	{
		// native control transfers are direct; data comes from/goes to the out buffer whether reading or writing.
		transferOffset = NULL;
		status = WdfRequestRetrieveOutputMemory(Request, &transferMemory);
		if (!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL)
		{
			USBERR("WdfRequestRetrieveOutputMemory failed. status=%Xh\n", status);
			goto Exit;
		}

		if (status == STATUS_BUFFER_TOO_SMALL)
		{
			// zero length transfer buffer, this is okay.
			transferMemory = NULL;
			USBMSG("zero-length transfer buffer\n");
		}
	}



	status = WdfUsbTargetDeviceFormatRequestForControlTransfer(
	             deviceContext->WdfUsbTargetDevice,
	             Request,
	             setupPacket,
	             transferMemory,
	             transferOffset);

	if (!NT_SUCCESS(status))
	{
		USBERR("WdfUsbTargetDeviceFormatRequestForControlTransfer failed. status=%Xh\n", status);
		goto Exit;
	}

	WdfRequestSetCompletionRoutine(Request,
	                               XferCtrlComplete,
	                               NULL);

	WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, 0);
	status = SetRequestTimeout(requestContext, Request, &sendOptions);
	if (!NT_SUCCESS(status))
	{
		USBERR("SetRequestTimeout failed. status=%Xh\n", status);
		goto Exit;
	}

	if (!WdfRequestSend(Request,
	                    WdfUsbTargetDeviceGetIoTarget(deviceContext->WdfUsbTargetDevice),
	                    &sendOptions))
	{
		status = WdfRequestGetStatus(Request);
		USBERR("WdfRequestSend failed. status=%Xh\n", status);
	}
	else
	{
		USBMSGN("[Ok] status=%Xh", status);
		return;
	}


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

	return;
}
net::URLRequestContextGetter *BrowserContextQt::GetMediaRequestContext()
{
    return GetRequestContext();
}
net::URLRequestContextGetter *BrowserContextQt::GetRequestContextForRenderProcess(int)
{
    return GetRequestContext();
}
net::URLRequestContextGetter *BrowserContextQt::GetMediaRequestContextForStoragePartition(const base::FilePath&, bool)
{
    return GetRequestContext();
}
예제 #15
0
파일: bulkrwr.c 프로젝트: KunYi/kJTAG
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;
}
예제 #16
0
파일: bulkrwr.c 프로젝트: KunYi/kJTAG
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;
}
예제 #17
0
VOID Xfer_ReadBulk (
    __in WDFQUEUE Queue,
    __in WDFREQUEST Request)
{
	NTSTATUS                status;
	PREQUEST_CONTEXT        requestContext = NULL;
	PQUEUE_CONTEXT			queueContext = NULL;
	PDEVICE_CONTEXT         deviceContext;
	ULONG					remainingLength;
	ULONG					stageLength = 0;
	ULONG					remainderLength = 0;
	WDF_REQUEST_SEND_OPTIONS sendOptions;
	PUCHAR					transferBuffer;


	deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
	requestContext = GetRequestContext(Request);

	VALIDATE_REQUEST_CONTEXT(requestContext, status);
	if (!NT_SUCCESS(status)) goto Exit;

	if ((queueContext = GetQueueContext(Queue)) == NULL)
	{
		status = STATUS_INVALID_DEVICE_REQUEST;
		USBERRN("Invalid queue context");
		goto Exit;
	}

	queueContext->Xfer.Transferred = 0;
	queueContext->Xfer.Length = requestContext->Length;

	if (!queueContext->OverMem)
	{
		status = STATUS_INVALID_DEVICE_REQUEST;
		USBERRN("Invalid queue context:OverMem");
		goto Exit;
	}

	if (!queueContext->Info.MaximumPacketSize)
	{
		status = STATUS_INVALID_BUFFER_SIZE;
		USBERRN("PipeID=%02Xh MaximumPacketSize=0", queueContext->Info.EndpointAddress);
		goto Exit;
	}

	// handle pipe reset scenarios: ResetPipeOnResume, AutoClearStall
	mXfer_HandlePipeResetScenarios(status, queueContext, requestContext);

	// Handle special case scenario where read length = 0
	if (!queueContext->Xfer.Length)
	{
		// if AllowPartialReads complete successfully for 0 bytes
		status = requestContext->Policies.AllowPartialReads ? STATUS_SUCCESS : STATUS_INVALID_BUFFER_SIZE;
		goto Exit;
	}

	// Init queue user memory
	status = GetTransferMemory(Request, requestContext->ActualRequestType, &queueContext->Xfer.UserMem);
	if (!NT_SUCCESS(status))
	{
		USBERR("GetTransferMemory failed. Status=%08Xh\n", status);
		goto Exit;
	}
	queueContext->Xfer.UserOfs.BufferOffset = 0;
	queueContext->Xfer.UserOfs.BufferLength = queueContext->Xfer.Length;

	// Check if there are bytes left over from a previous transfer.
	if (queueContext->OverOfs.BufferLength > 0)
	{
		// Copy partial read bytes bytes into UserMem
		remainingLength = queueContext->Xfer.Length - queueContext->Xfer.Transferred;
		stageLength = (ULONG)queueContext->OverOfs.BufferLength > remainingLength ? remainingLength : (ULONG)queueContext->OverOfs.BufferLength;
		transferBuffer = &queueContext->OverBuf[queueContext->OverOfs.BufferOffset];

		mXfer_CopyPartialReadToUserMemory(status, queueContext, transferBuffer, stageLength, goto Exit);

		USBDBGN("PipeID=%02Xh Transferred %u bytes from a previous partial read.",
		        queueContext->Info.EndpointAddress, queueContext->Xfer.Transferred);

		if (queueContext->Xfer.Transferred >= queueContext->Xfer.Length)
		{
			if (requestContext->Policies.AutoFlush)
			{
				// discard any extra partial read bytes
				queueContext->OverOfs.BufferLength = 0;
				queueContext->OverOfs.BufferOffset = 0;
			}

			USBMSGN("PipeID=%02Xh DoneReason: Transferred==Requested. Transferred=%u",
			        queueContext->Info.EndpointAddress,	queueContext->Xfer.Transferred);
			status = STATUS_SUCCESS;
			goto Exit;
		}

		/*
		It would seem if IgnoreShortPackets=FALSE we would complete the request here.
		However, WinUSB does not handle it this way and will still submit the request.
		*/
#if 0
		else if (!requestContext->Policies.IgnoreShortPackets)
		{
			USBMSGN("PipeID=%02Xh DoneReason: IgnoreShortPackets=FALSE. Transferred=%u",
			        queueContext->Info.EndpointAddress,	queueContext->Xfer.Transferred);
			status = STATUS_SUCCESS;
			goto Exit;
		}
#endif
	}
예제 #18
0
파일: bulkrwr.c 프로젝트: 340211173/Driver
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;
}
예제 #19
0
파일: PSDrvBulk.c 프로젝트: 3david/OpenNI
/*++
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
--*/
VOID ReadWriteCompletion(IN WDFREQUEST Request, IN WDFIOTARGET Target, PWDF_REQUEST_COMPLETION_PARAMS CompletionParams, IN WDFCONTEXT Context)
{
    PMDL                    requestMdl;
    WDFUSBPIPE              pipe;
    ULONG                   stageLength;
    NTSTATUS                status;
    PREQUEST_CONTEXT        rwContext;
    PURB                    urb;
    PCHAR                   operation;
    ULONG                   bytesReadWritten;

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

    PSDrv_DbgPrint(3, ("ReadWriteCompletion - begins\n"));

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

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

    if (!NT_SUCCESS(status))
	{
        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
    PSDrv_DbgPrint(3, ("Stage next %s transfer...\n", operation));

    if (rwContext->Length > MAX_TRANSFER_SIZE)
	{
        stageLength = MAX_TRANSFER_SIZE;
    }
    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))
		{
            PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl for Read failed! (Status = %x)\n", status));
            goto End;
        }
    }
	else
	{
        status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl);
        if(!NT_SUCCESS(status))
		{
            PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl for Write failed! (Status =  %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))
	{
        PSDrv_DbgPrint(1, ("WdfUsbTargetPipeFormatRequestForUrb failed! (Status = %x)\n", status));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto End;
    }

    WdfRequestSetCompletionRoutine(Request, ReadWriteCompletion, NULL);

    // Send the request asynchronously.
    if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS))
	{
        PSDrv_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.
    PSDrv_DbgPrint(3, ("ReadWriteCompletion - ends 1\n"));

    return;

End:
    // Dump the request context, complete the request and return.
	PSDrv_DbgPrint(3, ("rwContext->UrbMemory      = %p\n", rwContext->UrbMemory));
	PSDrv_DbgPrint(3, ("rwContext->Mdl            = %p\n", rwContext->Mdl));
	PSDrv_DbgPrint(3, ("rwContext->Length         = %d\n", rwContext->Length));
	PSDrv_DbgPrint(3, ("rwContext->Numxfer        = %d\n", rwContext->Numxfer));
	PSDrv_DbgPrint(3, ("rwContext->VirtualAddress = %p\n", rwContext->VirtualAddress));

    IoFreeMdl(rwContext->Mdl);

    PSDrv_DbgPrint(3, ("Bulk or Interrupt %s request has finished. (Status = %x)\n", operation, status));

    WdfRequestComplete(Request, status);

    PSDrv_DbgPrint(3, ("ReadWriteCompletion - ends 2\n"));

    return;
}
예제 #20
0
파일: bulkrwr.c 프로젝트: 340211173/Driver
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
    WdfRequestTypeWrite 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

--*/
{
    PMDL                    newMdl=NULL, requestMdl = NULL;
    PURB                    urb = NULL;
    WDFMEMORY               urbMemory;
    ULONG                   totalLength = Length;
    ULONG                   stageLength = 0;
    ULONG                   urbFlags = 0;
    NTSTATUS                status;
    ULONG_PTR               virtualAddress = 0;
    PREQUEST_CONTEXT        rwContext = NULL;
    PFILE_CONTEXT           fileContext = NULL;
    WDFUSBPIPE              pipe;
    WDF_USB_PIPE_INFORMATION   pipeInfo;
    WDF_OBJECT_ATTRIBUTES   objectAttribs;
    USBD_PIPE_HANDLE        usbdPipeHandle;
    PDEVICE_CONTEXT         deviceContext;
    ULONG                   maxTransferSize;
    PPIPE_CONTEXT           pipeContext;

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

    if ((WdfUsbPipeTypeBulk != pipeInfo.PipeType) &&
            (WdfUsbPipeTypeInterrupt != pipeInfo.PipeType)) {
        UsbSamp_DbgPrint(1, ("Usbd pipe type is not bulk or interrupt\n"));
        status = STATUS_INVALID_DEVICE_REQUEST;
        goto Exit;

    }

    rwContext = GetRequestContext(Request);

    if (RequestType == WdfRequestTypeRead) {

        status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
        if (!NT_SUCCESS(status)){
            UsbSamp_DbgPrint(1, ("WdfRequestRetrieveOutputWdmMdl failed %x\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_IN;
        rwContext->Read = TRUE;
        UsbSamp_DbgPrint(3, ("Read operation\n"));

    } 
    else {
        status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl);
        if (!NT_SUCCESS(status)){
            UsbSamp_DbgPrint(1, ("WdfRequestRetrieveInputWdmMdl failed %x\n", status));
            goto Exit;
        }

        urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
        rwContext->Read = FALSE;
        UsbSamp_DbgPrint(3, ("Write operation\n"));
    }

    urbFlags |= USBD_SHORT_TRANSFER_OK;
    virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl);

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

    newMdl = IoAllocateMdl((PVOID) virtualAddress,
                           totalLength,
                           FALSE,
                           FALSE,
                           NULL);

    if (newMdl == NULL) {
        UsbSamp_DbgPrint(1, ("Failed to alloc mem for mdl\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    //
    // map the portion of user-buffer described by an mdl to another mdl
    //
    IoBuildPartialMdl(requestMdl,
                      newMdl,
                      (PVOID) virtualAddress,
                      stageLength);

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

    status = WdfUsbTargetDeviceCreateUrb(deviceContext->WdfUsbTargetDevice,
		                     &objectAttribs,
                             &urbMemory,
                             &urb);

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

#if (NTDDI_VERSION >= NTDDI_WIN8)
    if(WdfUsbPipeTypeBulk == pipeInfo.PipeType &&
        pipeContext->StreamConfigured == TRUE) {
        //
        // For super speed bulk pipe with streams, we specify one of its associated 
        // usbd pipe handles to format an URB for sending or receiving data. 
        // The usbd pipe handle is returned by the HCD via sucessful open-streams request
        //
        usbdPipeHandle = GetStreamPipeHandleFromBulkPipe(pipe);
    }
    else {
        usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);
    }
#else
    usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);
#endif

    UsbBuildInterruptOrBulkTransferRequest(urb,
                                           sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                                           usbdPipeHandle,
                                           NULL,
                                           newMdl,
                                           stageLength,
                                           urbFlags,
                                           NULL);

    status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL  );
    if (!NT_SUCCESS(status)) {
        UsbSamp_DbgPrint(1, ("Failed to format requset for urb\n"));
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }

    WdfRequestSetCompletionRoutine(Request, UsbSamp_EvtReadWriteCompletion, deviceContext);

    //
    // set REQUEST_CONTEXT  parameters.
    //
    rwContext->UrbMemory       = urbMemory;
    rwContext->Mdl             = newMdl;
    rwContext->Length          = totalLength - stageLength;
    rwContext->Numxfer         = 0;
    rwContext->VirtualAddress  = virtualAddress + stageLength;

    if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) {
        status = WdfRequestGetStatus(Request);
        NT_ASSERT(!NT_SUCCESS(status));
    }

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

        if (newMdl != NULL) {
            IoFreeMdl(newMdl);
        }
    }

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

    return;
}
예제 #21
0
파일: bulkrwr.c 프로젝트: 340211173/Driver
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;
}
예제 #22
0
파일: bulkrwr.c 프로젝트: 340211173/Driver
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;
}
예제 #23
0
파일: Transfer.c 프로젝트: kcrazy/winekit
VOID
AmccPciEvtInterruptDpc(
    __in WDFINTERRUPT WdfInterrupt,
    __in WDFOBJECT    WdfDevice
    )
/*++

Routine Description:

    DPC callback for ISR.

Arguments:

    WdfInterrupt - Handle to the framework interrupt object

    WdfDevice - Associated device object.

Return Value:

--*/
{
    PAMCC_DEVICE_EXTENSION   devExt;
    WDFREQUEST               request;
    REQUEST_CONTEXT        * transfer;
    NTSTATUS                 status;
    size_t                   transferred;
    BOOLEAN                  transactionComplete;

    UNREFERENCED_PARAMETER( WdfInterrupt );

    devExt = AmccPciGetDevExt(WdfDevice);

    //
    // Retreive request and transfer.
    //
    request  = devExt->CurrentRequest;
    transfer = GetRequestContext(request);

    //
    // Check to see if the request is cancelled by the system. While
    // we are DMAing a large buffer into multiple transaction,
    // there is good possibilty for the request to get cancelled because
    // the originator of the request exited or cancelled the I/O explicitly.
    //
    if(WdfRequestIsCanceled(request)) {
        TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO,
                                    "Aborted DMA transaction 0x%p",  request);
        WdfObjectDelete( transfer->DmaTransaction );
        devExt->CurrentRequest = NULL;
        WdfRequestComplete(request, STATUS_CANCELLED);
        return;
    }

    //
    // The boolean transactionComplete indicates whether the transaction has
    // exited the transfer state, e.g. no further transfers are scheduled.
    //
    // If transactionComplete == FALSE, then the next DMA transfer has been
    // scheduled, e.g. the next interrrupt will drive the ISR again.
    //
    // If transactionComplete == TRUE, then status indicates the reason;
    // SUCCESS is the nomative case, while non-SUCCESS indicates the
    // DMA transaction failed for "status" reason.
    //
    transactionComplete = WdfDmaTransactionDmaCompleted( transfer->DmaTransaction,
                                                     &status );

    if (transactionComplete) {

        ASSERT(status != STATUS_MORE_PROCESSING_REQUIRED);

        //
        // No more data: request is complete
        //
        TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO,
                    "Request %p completed: status %X",
                    request, status);

        //
        // Get the final bytes transferred count.
        //
        transferred =
            WdfDmaTransactionGetBytesTransferred( transfer->DmaTransaction );

        TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO,
                    "Bytes transfered %d", (int) transferred );

        //
        // Delete this DmaTransaction transaction.
        //
        WdfObjectDelete( transfer->DmaTransaction );

        //
        // Clean-up for this request.
        //
        devExt->CurrentRequest = NULL;

        //
        // Complete this IO request.
        //
        WdfRequestCompleteWithInformation( request,
                                           status,
                                           (NT_SUCCESS(status)) ?
                                           transferred : 0 );
    }

}
예제 #24
0
VOID PipeQueue_OnWrite(__in WDFQUEUE Queue,
					   __in WDFREQUEST Request,
					   __in size_t InputBufferLength)
{
	NTSTATUS				status = STATUS_SUCCESS;
	PDEVICE_CONTEXT         deviceContext;
	PREQUEST_CONTEXT		requestContext;
	PQUEUE_CONTEXT queueContext = NULL;

	UNREFERENCED_PARAMETER(InputBufferLength);

	deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
	requestContext = GetRequestContext(Request);

	VALIDATE_REQUEST_CONTEXT(requestContext, status);
	if (!NT_SUCCESS(status)) goto Done;

	if ((queueContext = GetQueueContext(Queue)) == NULL)
	{
		status = STATUS_INVALID_DEVICE_REQUEST;
		USBERRN("Invalid queue context");
		goto Done;
	}

	if (!queueContext->PipeHandle)
	{
		USBERR("null pipe handle\n");
		status = STATUS_INVALID_HANDLE;
		goto Done;
	}

	switch(queueContext->Info.PipeType)
	{
	case WdfUsbPipeTypeIsochronous:
		if (USB_ENDPOINT_DIRECTION_OUT(queueContext->Info.EndpointAddress))
		{
			XferIsoWrite(Queue, Request);
			return;
		}
		break;

	case WdfUsbPipeTypeBulk:
	case WdfUsbPipeTypeInterrupt:
		if (USB_ENDPOINT_DIRECTION_IN(queueContext->Info.EndpointAddress))
		{
			status = STATUS_INVALID_DEVICE_REQUEST;
			USBERRN("Cannot write to an IN pipe.");
			goto Done;
		}
		if(requestContext->Policies.RawIO)
			Xfer_WriteBulkRaw(Queue, Request);
		else
			Xfer_WriteBulk(Queue, Request);
	}

	status = STATUS_INVALID_DEVICE_REQUEST;
	USBERRN("PipeID=%02Xh Invalid request", queueContext->Info.EndpointAddress);

Done:
	WdfRequestCompleteWithInformation(Request, status, 0);

}
예제 #25
0
파일: client.c 프로젝트: kcrazy/winekit
__drv_sameIRQL
NTSTATUS
BthEchoCliOpenRemoteConnection(
    __in PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx,
    __in WDFFILEOBJECT FileObject,
    __in WDFREQUEST Request
    )
/*++

Description:

    This routine is invoked by BthEchoCliEvtDeviceFileCreate.
    In this routine we send down open channel BRB.

    This routine allocates open channel BRB. If the request
    is sent down successfully completion routine needs to free
    this BRB.
    
Arguments:

    __in PBTHECHOSAMPLE_CLIENT_CONTEXT DevCtx - 
    __in WDFFILEOBJECT FileObject - 
    __in WDFREQUEST Request - 

Return Value:

    NTSTATUS Status code.

--*/
{
    NTSTATUS status;
    WDFOBJECT connectionObject;    
    struct _BRB_L2CA_OPEN_CHANNEL *brb = NULL;
    PBTHECHO_CONNECTION connection = NULL;
    PBTHECHOSAMPLE_CLIENT_FILE_CONTEXT fileCtx = GetFileContext(FileObject);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CONNECT, 
        "Connect request");        

    //
    // Create the connection object that would store information
    // about the open channel
    //
    // Set file object as the parent for this connection object
    //
    status = BthEchoConnectionObjectCreate(
        &DevCtx->Header,
        FileObject, //parent
        &connectionObject
        );

    if (!NT_SUCCESS(status))
    {
        goto exit;
    }

    connection = GetConnectionObjectContext(connectionObject);

    connection->ConnectionState = ConnectionStateConnecting;

    //
    // Get the BRB from request context and initialize it as
    // BRB_L2CA_OPEN_CHANNEL BRB
    //
    brb = (struct _BRB_L2CA_OPEN_CHANNEL *)GetRequestContext(Request);

    DevCtx->Header.ProfileDrvInterface.BthReuseBrb(
        (PBRB)brb, 
        BRB_L2CA_OPEN_CHANNEL
        );
    
    brb->Hdr.ClientContext[0] = connection;
    brb->BtAddress = DevCtx->ServerBthAddress;
    brb->Psm = fileCtx->ServerPsm;

    brb->ChannelFlags = CF_ROLE_EITHER;

    brb->ConfigOut.Flags = 0;
    brb->ConfigIn.Flags = 0;

    brb->ConfigOut.Flags |= CFG_MTU;
    brb->ConfigOut.Mtu.Max = L2CAP_DEFAULT_MTU;
    brb->ConfigOut.Mtu.Min = L2CAP_MIN_MTU;
    brb->ConfigOut.Mtu.Preferred = L2CAP_DEFAULT_MTU;

    brb->ConfigIn.Flags = CFG_MTU;
    brb->ConfigIn.Mtu.Max = brb->ConfigOut.Mtu.Max;
    brb->ConfigIn.Mtu.Min = brb->ConfigOut.Mtu.Min;
    brb->ConfigIn.Mtu.Preferred = brb->ConfigOut.Mtu.Max;

    //
    // Get notificaiton about remote disconnect 
    //
    brb->CallbackFlags = CALLBACK_DISCONNECT;                                                   

    brb->Callback = &BthEchoCliIndicationCallback;
    brb->CallbackContext = connection;
    brb->ReferenceObject = (PVOID) WdfDeviceWdmGetDeviceObject(DevCtx->Header.Device);
    brb->IncomingQueueDepth = 50;

    status = BthEchoSharedSendBrbAsync(
        DevCtx->Header.IoTarget,
        Request,
        (PBRB) brb,
        sizeof(*brb),
        BthEchoCliRemoteConnectCompletion,
        brb    //Context
        );

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_CONNECT, 
            "Sending brb for opening connection failed, returning status code %!STATUS!\n", status);

        goto exit;
    }            

exit:

    if(!NT_SUCCESS(status))
    {
        if (connection)
        {
            //
            // Set the right state to facilitate debugging
            //
            connection->ConnectionState = ConnectionStateConnectFailed;            
        }

        //
        // In case of failure of this routine we will fail
        // Create which will delete file object and since connection object
        // is child of the file object, it will be deleted too
        //
    }
    
    return status;
}
예제 #26
0
파일: usbchief.c 프로젝트: LaneTee/usbchief
static VOID UsbChief_ReadCompletion(IN WDFREQUEST Request, IN WDFIOTARGET Target,
			     PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
			     IN WDFCONTEXT Context)
{
	PMDL requestMdl;
	WDFUSBPIPE pipe;
	ULONG stageLength;
	NTSTATUS status;
	PREQUEST_CONTEXT rwContext;
	PURB urb;
	ULONG bytesRead;

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

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

	if (!NT_SUCCESS(status)){
		UsbChief_QueuePassiveLevelCallback(WdfIoTargetGetDevice(Target), pipe);
		goto End;
	}

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

	if (rwContext->Length == 0) {
		WdfRequestSetInformation(Request, rwContext->Numxfer);
		goto End;
	}

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

	UsbChief_DbgPrint(DEBUG_RW, ("Stage next Read transfer... %d bytes remaing\n", rwContext->Length));
	MmPrepareMdlForReuse(rwContext->Mdl);

	status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
	if(!NT_SUCCESS(status)){
		UsbChief_DbgPrint(0, ("WdfRequestRetrieveOutputWdmMdl for Read failed %x\n", status));
		goto End;
	}

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

	urb->UrbBulkOrInterruptTransfer.TransferBufferLength = stageLength;

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

	status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request,
						     rwContext->UrbMemory, NULL);
	if (!NT_SUCCESS(status)) {
		UsbChief_DbgPrint(0, ("Failed to format requset for urb\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto End;
	}

	WdfRequestSetCompletionRoutine(Request, UsbChief_ReadCompletion, NULL);

	if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS)) {
		UsbChief_DbgPrint(0, ("WdfRequestSend for Read failed\n"));
		status = WdfRequestGetStatus(Request);
		goto End;
	}
	return;

End:
	IoFreeMdl(rwContext->Mdl);

	UsbChief_DbgPrint(DEBUG_RW, ("Read request completed with status 0x%x\n", status));
	WdfRequestComplete(Request, status);
}