Exemplo n.º 1
0
ULONG
HwSimReadComponent(
    _In_ WDFDEVICE Device
    )
/*++
Routine Description:

    This routine simulates the reading of data from a component

Arguments:

    Device - Handle to the framework device object

    Component - Component from which data is being read

Return Value:

    A ULONG value representing the data that was read from the component

--*/
{
    ULONG componentData;
    PHWSIM_CONTEXT devCtx;
    ULONG component = 0;
    
    Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry\n");

    devCtx = HwSimGetDeviceContext(Device);
    
    //
    // Verify that the device is powered on
    //
    if (FALSE == devCtx->DevicePoweredOn) {
        //
        // This means that our driver is attempting to read from the component
        // while the device is not powered on.
        //
        Trace(TRACE_LEVEL_ERROR, 
              "%!FUNC! - Expected device to be powered on, but it was not.");

        WdfVerifierDbgBreakPoint();
    }

    assert(devCtx->DevicePoweredOn);

    //
    // In this sample, component data is just a bit-wise complement of the 
    // component number.
    //
    componentData = ~component;
    
    Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Exit\n");
    
    return componentData;
}
Exemplo n.º 2
0
VOID
HwSimFStateChange(
    _In_ WDFDEVICE Device, 
    _In_ ULONG State
    )
/*++
Routine Description:

    This routine simulates a component changing its F-state

Arguments:

    Device - Handle to the framework device object

    State - New F-state for the component

Return Value:

    None

--*/
{
    PHWSIM_CONTEXT devCtx;

    devCtx = HwSimGetDeviceContext(Device);

    //
    // Verify that the device is powered on
    //
    if (FALSE == devCtx->DevicePoweredOn) {
        //
        // This means that our driver is handling an F state transition while 
        // device is not in D0.
        //
        Trace(TRACE_LEVEL_ERROR, 
              "%!FUNC! - Expected device to be powered on, but it was not.");

        WdfVerifierDbgBreakPoint();
    }

    ASSERT(devCtx->DevicePoweredOn);

    //
    // Put the component in the requested F-state
    //
    devCtx->ComponentFState = State;

    //
    // For an actual hardware, save any hardware state on Fx transition
    // and restore state on F0 transition.
    //
    
    return;
}
Exemplo n.º 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);
	}
}
Exemplo n.º 4
0
VOID
HwSimFStateChange(
    _In_ WDFDEVICE Device, 
    _In_ ULONG Component, 
    _In_ ULONG State
    )
/*++
Routine Description:

    This routine simulates a component changing its F-state

Arguments:

    Device - Handle to the framework device object

    Component - Index of the component whose F-state is changing

    State - New F-state for the component

Return Value:

    None

--*/
{
    PHWSIM_CONTEXT devCtx;

    devCtx = HwSimGetDeviceContext(Device);

    //
    // The caller should have ensured that this routine is called only when the
    // device is powered on. Verify this. If false, we'll generate a verifier 
    // breakpoint.
    //
    if (FALSE == devCtx->DevicePoweredOn) {
        Trace(TRACE_LEVEL_ERROR, 
              "%!FUNC! - Expected device to be powered on, but it was not.");
        WdfVerifierDbgBreakPoint();
    }

    //
    // Put the component in the requested F-state
    //
    devCtx->ComponentFState[Component] = State;
    return;
}
Exemplo n.º 5
0
VOID
tgwinkEvtIoRead(
    WDFQUEUE Queue,
    WDFREQUEST Request,
    size_t Length
    )
{
    NTSTATUS status;
    WDFMEMORY mem;
    WDF_REQUEST_PARAMETERS params;
    ULONG offset;
    ULONG result;
    PDEVICE_CONTEXT context;
    WDFDEVICE device;
    
    device = WdfIoQueueGetDevice(Queue);
    context = DeviceGetContext(device);

    WDF_REQUEST_PARAMETERS_INIT(&params);

    WdfRequestGetParameters(Request, &params);

    offset = (ULONG)params.Parameters.Read.DeviceOffset;

    status = WdfRequestRetrieveOutputMemory(Request, &mem);
    if (!NT_SUCCESS(status)) {
        KdPrint("tgwinkEvtIoRead could not get request memory buffer, status 0x%x\n", status);
        WdfVerifierDbgBreakPoint();
        WdfRequestCompleteWithInformation(Request, status, 0);
        return;
    }

    result = context->busInterface.GetBusData(context->busInterface.Context, PCI_WHICHSPACE_CONFIG, WdfMemoryGetBuffer(mem, NULL), offset, (ULONG)Length);

    WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, (ULONG_PTR)result);
}
Exemplo n.º 6
0
VOID
EchoEvtIoWrite(
    IN WDFQUEUE   Queue,
    IN WDFREQUEST Request,
    IN size_t     Length
    )
/*++

Routine Description:

    This event is invoked when the framework receives IRP_MJ_WRITE request.
    This routine allocates memory buffer, copies the data from the request to it,
    and stores the buffer pointer in the queue-context with the length variable
    representing the buffers length. The actual completion of the request
    is defered to the periodic timer dpc.

Arguments:

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

    Request - Handle to a framework request object.

    Length  - number of bytes to be read.
              The default property of the queue is to not dispatch
              zero lenght read & write requests to the driver and
              complete is with status success. So we will never get
              a zero length request.

Return Value:

    VOID

--*/
{
    NTSTATUS Status;
    WDFMEMORY memory;
    PQUEUE_CONTEXT queueContext = QueueGetContext(Queue);
    PVOID writeBuffer = NULL;

    _Analysis_assume_(Length > 0);

    KdPrint(("EchoEvtIoWrite Called! Queue 0x%p, Request 0x%p Length %d\n",
             Queue,Request,Length));

    if( Length > MAX_WRITE_LENGTH ) {
        KdPrint(("EchoEvtIoWrite Buffer Length to big %d, Max is %d\n",
                 Length,MAX_WRITE_LENGTH));
        WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_OVERFLOW, 0L);
        return;
    }

    // Get the memory buffer
    Status = WdfRequestRetrieveInputMemory(Request, &memory);
    if( !NT_SUCCESS(Status) ) {
        KdPrint(("EchoEvtIoWrite Could not get request memory buffer 0x%x\n",
                 Status));
        WdfVerifierDbgBreakPoint();
        WdfRequestComplete(Request, Status);
        return;
    }

    // Release previous buffer if set
    if( queueContext->WriteMemory != NULL ) {
        WdfObjectDelete(queueContext->WriteMemory);
        queueContext->WriteMemory = NULL;
    }

    Status = WdfMemoryCreate(WDF_NO_OBJECT_ATTRIBUTES,
                             NonPagedPool,
                             'sam1',
                             Length,
                             &queueContext->WriteMemory,
                             &writeBuffer
                             );

    if(!NT_SUCCESS(Status)) {
        KdPrint(("EchoEvtIoWrite: Could not allocate %d byte buffer\n", Length));
        WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
        return;
    }


    // Copy the memory in
    Status = WdfMemoryCopyToBuffer( memory,
                                    0,  // offset into the source memory
                                    writeBuffer,
                                    Length );
    if( !NT_SUCCESS(Status) ) {
        KdPrint(("EchoEvtIoWrite WdfMemoryCopyToBuffer failed 0x%x\n", Status));
        WdfVerifierDbgBreakPoint();

        WdfObjectDelete(queueContext->WriteMemory);
        queueContext->WriteMemory = NULL;

        WdfRequestComplete(Request, Status);
        return;
    }

    // Set transfer information
    WdfRequestSetInformation(Request, (ULONG_PTR)Length);

    // Specify the request is cancelable
    WdfRequestMarkCancelable(Request, EchoEvtRequestCancel);

    // Defer the completion to another thread from the timer dpc
    queueContext->CurrentRequest = Request;
    queueContext->CurrentStatus  = Status;

    return;
}
Exemplo n.º 7
0
VOID
EchoEvtIoRead(
    IN WDFQUEUE   Queue,
    IN WDFREQUEST Request,
    IN size_t      Length
    )
/*++

Routine Description:

    This event is called when the framework receives IRP_MJ_READ request.
    It will copy the content from the queue-context buffer to the request buffer.
    If the driver hasn't received any write request earlier, the read returns zero.

Arguments:

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

    Request - Handle to a framework request object.

    Length  - number of bytes to be read.
              The default property of the queue is to not dispatch
              zero lenght read & write requests to the driver and
              complete is with status success. So we will never get
              a zero length request.

Return Value:

    VOID

--*/
{
    NTSTATUS Status;
    PQUEUE_CONTEXT queueContext = QueueGetContext(Queue);
    WDFMEMORY memory;
    size_t writeMemoryLength;

    _Analysis_assume_(Length > 0);

    KdPrint(("EchoEvtIoRead Called! Queue 0x%p, Request 0x%p Length %d\n",
             Queue,Request,Length));
    //
    // No data to read
    //
    if( (queueContext->WriteMemory == NULL)  ) {
        WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, (ULONG_PTR)0L);
        return;
    }

    //
    // Read what we have
    //
    WdfMemoryGetBuffer(queueContext->WriteMemory, &writeMemoryLength);
    _Analysis_assume_(writeMemoryLength > 0);

    if( writeMemoryLength < Length ) {
        Length = writeMemoryLength;
    }

    //
    // Get the request memory
    //
    Status = WdfRequestRetrieveOutputMemory(Request, &memory);
    if( !NT_SUCCESS(Status) ) {
        KdPrint(("EchoEvtIoRead Could not get request memory buffer 0x%x\n", Status));
        WdfVerifierDbgBreakPoint();
        WdfRequestCompleteWithInformation(Request, Status, 0L);
        return;
    }

    // Copy the memory out
    Status = WdfMemoryCopyFromBuffer( memory, // destination
                             0,      // offset into the destination memory
                             WdfMemoryGetBuffer(queueContext->WriteMemory, NULL),
                             Length );
    if( !NT_SUCCESS(Status) ) {
        KdPrint(("EchoEvtIoRead: WdfMemoryCopyFromBuffer failed 0x%x\n", Status));
        WdfRequestComplete(Request, Status);
        return;
    }

    // Set transfer information
    WdfRequestSetInformation(Request, (ULONG_PTR)Length);

    // Mark the request is cancelable
    WdfRequestMarkCancelable(Request, EchoEvtRequestCancel);


    // Defer the completion to another thread from the timer dpc
    queueContext->CurrentRequest = Request;
    queueContext->CurrentStatus  = Status;

    return;
}
Exemplo n.º 8
0
VOID
SingleCompEvtIoDeviceControl(
    _In_ WDFQUEUE Queue,
    _In_ WDFREQUEST Request,
    _In_ size_t OutputBufferLength,
    _In_ size_t InputBufferLength,
    _In_ ULONG IoControlCode
    )
/*++
Routine Description:

    Callback invoked by WDFQUEUE for a Device Io Control request.

Arguments:

    Queue - Device I/O control queue
              
    Request - Device I/O control request

    OutputBufferLength - Output buffer length for the I/O control

    InputBufferLength - Input buffer length for the I/O control

    IoControlCode - I/O control code
                
--*/
{
    NTSTATUS status;
    PPOWERFX_READ_COMPONENT_OUTPUT outputBuffer = NULL;
    WDFDEVICE device = NULL;
    ULONG componentData;
    ULONG_PTR information = 0;
    FDO_DATA *fdoContext = NULL;
    
    //
    // When we complete the request, make sure we don't get the I/O manager to 
    // copy any more data to the client address space than what we write to the
    // output buffer. The only data that we write to the output buffer is the 
    // component data and the C_ASSERT below ensures that the output buffer does
    // not have room to contain anything other than that.
    //
    C_ASSERT(sizeof(componentData) == sizeof(*outputBuffer));

    UNREFERENCED_PARAMETER(OutputBufferLength);
    UNREFERENCED_PARAMETER(InputBufferLength);

    //
    // This is a power-managed queue. So our queue stop/start logic should have 
    // ensured that we are in the active condition when a request is dispatched
    // from this queue.
    //
    device = WdfIoQueueGetDevice(Queue);
    fdoContext = FdoGetContext(device);
    if (FALSE == fdoContext->IsActive) {
        Trace(TRACE_LEVEL_ERROR, 
              "%!FUNC! - IOCTL %d was dispatched from WDFQUEUE %p when the "
              "component was not in an active condition.",
              IOCTL_POWERFX_READ_COMPONENT,
              Queue);
        WdfVerifierDbgBreakPoint();
    }
    
    //
    // Validate Ioctl code
    //
    if (IOCTL_POWERFX_READ_COMPONENT != IoControlCode) {
        status = STATUS_NOT_SUPPORTED;
        Trace(TRACE_LEVEL_ERROR, 
              "%!FUNC! -Unsupported IoControlCode. Expected: %d. Actual: %d."
              " %!status!.", 
              IOCTL_POWERFX_READ_COMPONENT,
              IoControlCode,
              status);
        goto exit;
    }
    
    //
    // Get the output buffer
    //
    status = WdfRequestRetrieveOutputBuffer(Request,
                                            sizeof(*outputBuffer),
                                            (PVOID*) &outputBuffer,
                                            NULL // Length
                                            );
    if (FALSE == NT_SUCCESS(status)) {
        Trace(TRACE_LEVEL_ERROR, 
              "%!FUNC! - WdfRequestRetrieveOutputBuffer failed with %!status!.",
              status);
        goto exit;
    }
    
    //
    // Read the data from the component
    //
    componentData = HwSimReadComponent(device);
    outputBuffer->ComponentData = componentData;
    information = sizeof(*outputBuffer);
    
    status = STATUS_SUCCESS;
    
exit:
    //
    // Complete the request
    //
    WdfRequestCompleteWithInformation(Request, status, information);
    return;
}
Exemplo n.º 9
0
VOID
tgwinkEvtIoDeviceControl(
    _In_ WDFQUEUE Queue,
    _In_ WDFREQUEST Request,
    _In_ size_t OutputBufferLength,
    _In_ size_t InputBufferLength,
    _In_ ULONG IoControlCode
    )
{
    WDFMEMORY mem;
    NTSTATUS status;
    WDFDEVICE dev;
    PDEVICE_CONTEXT context;
    void *uBase = NULL;
    LARGE_INTEGER offset;
    size_t size;

    dev = WdfIoQueueGetDevice(Queue);
    context = DeviceGetContext(dev);

    switch (IoControlCode) {
    case IOCTL_TGWINK_SAY_HELLO:
        
        if (OutputBufferLength != 4) {
            WdfRequestComplete(Request, STATUS_BAD_DATA);
            break;
        }

        status = WdfRequestRetrieveOutputMemory(Request, &mem);
        if (!NT_SUCCESS(status)) {
            KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status);
            WdfVerifierDbgBreakPoint();
            WdfRequestComplete(Request, status);
            break;
        }

        *((DWORD32 *)(WdfMemoryGetBuffer(mem, NULL))) = 0x5a5aa5a5;
        WdfRequestComplete(Request, STATUS_SUCCESS);
        break;

    case IOCTL_TGWINK_MAP_BAR_0:
        if (sizeof(void *) > OutputBufferLength) {
            KdPrint("tgwinkEvtIoDeviceControl needs a larger buffer (%d > %d)!\n", sizeof(void *), OutputBufferLength);
            WdfRequestComplete(Request, STATUS_BUFFER_TOO_SMALL);
            break;
        }

        offset = context->bar[0].phyAddr;
        size = context->bar[0].length;

        status = ZwMapViewOfSection(context->hMemory, ZwCurrentProcess(), &uBase, 0, 0, &offset, &size, ViewUnmap, 0, PAGE_READWRITE);
        if (!NT_SUCCESS(status)) {

            KdPrint("tgwinkEvtIoDeviceControl could not map view of section, status ");
            switch (status) {
            case STATUS_CONFLICTING_ADDRESSES: 
                KdPrint("STATUS_CONFLICTING_ADDRESSES\n"); 
                break;
            case STATUS_INVALID_PAGE_PROTECTION: 
                KdPrint("STATUS_INVALID_PAGE_PROTECTION\n"); 
                break;
            case STATUS_SECTION_PROTECTION: 
                KdPrint("STATUS_SECTION_PROTECTION\n"); 
                break;
            default: 
                KdPrint("0x % x\n", status); 
                break;
            }
            WdfRequestComplete(Request, status);
            break;
        }

        status = WdfRequestRetrieveOutputMemory(Request, &mem);
        if (!NT_SUCCESS(status)) {
            KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status);
            WdfVerifierDbgBreakPoint();
            WdfRequestComplete(Request, status);
            break;
        }

        *((void **)(WdfMemoryGetBuffer(mem, NULL))) = uBase;

        WdfRequestComplete(Request, STATUS_SUCCESS);
        break;

    case IOCTL_TGWINK_READ_PHYS:
    {
        PVOID buf;
        ULONG_PTR page, ofs, vtgt = 0;
        SIZE_T vsz = 0;

        if (InputBufferLength != sizeof(PVOID)) {
            KdPrint("tgwinkEvtIoDeviceControl requires a %d-byte buffer for this ioctl (got %d)\n", sizeof(PVOID), OutputBufferLength);
            WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
            break;
        }
        
        status = WdfRequestRetrieveInputBuffer(Request, sizeof(PVOID), &buf, NULL);
        if (!NT_SUCCESS(status)) {
            KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status);
            WdfRequestComplete(Request, status);
            break;
        }

        ofs = *((ULONG_PTR *)buf);
        page = ofs & ~0xfff;
        vsz = OutputBufferLength + (page ^ ofs);
        buf = NULL;

        status = WdfRequestRetrieveOutputMemory(Request, &mem);
        if (!NT_SUCCESS(status)) {
            KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status);
            WdfRequestComplete(Request, status);
            break;
        }

        status = ZwMapViewOfSection(context->hMemory, (HANDLE)-1, (PVOID *)&vtgt, 0, 0, (PLARGE_INTEGER)&page, &vsz, ViewUnmap, 0, PAGE_READONLY);
        if (!NT_SUCCESS(status)) {
            KdPrint("tgwinkEvtIoDeviceControl could not map view of physical memory section, status 0x%x\n", status);
            WdfRequestComplete(Request, status);
            break;
        }

        ofs -= page;
        status = WdfMemoryCopyFromBuffer(mem, 0, (PVOID)(vtgt + ofs), OutputBufferLength);
        if (!NT_SUCCESS(status)) {
            KdPrint("tgwinkEvtIoDeviceControl failed to copy data from memory to buffer, status 0x%x\n", status);
            WdfRequestComplete(Request, status);
            break;
        }

        status = ZwUnmapViewOfSection((HANDLE)-1, (PVOID)vtgt);
        if (!NT_SUCCESS(status)) {
            KdPrint("tgwinkEvtIoDeviceControl failed to unmap view of physical memory section, status 0x%x\n", status);
            WdfRequestComplete(Request, status);
            break;
        }
    
        WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, OutputBufferLength);
    } break;

    case IOCTL_TGWINK_PEND_INTR:
    {
        WdfWaitLockAcquire(context->nnLock, NULL);
        if (context->notifyNext) {
            PINTERRUPT_CONTEXT pCtx = InterruptGetContext(context->hIrq);
            status = WdfRequestRetrieveOutputMemory(Request, &mem);
            if (!NT_SUCCESS(status)) {
                KdPrint("tgwinkEvtIoDeviceControl failed to retrieve output memory, status 0x%x\n", status);
                WdfRequestComplete(Request, status);
            }
            status = WdfMemoryCopyFromBuffer(mem, 0, &pCtx->serial, 8);
            if (!NT_SUCCESS(status)) {
                KdPrint("tgwinkEvtIoDeviceControl failed to copy interrupt number to buffer, status 0x%x\n", status);
                WdfRequestComplete(Request, status);
            }
            WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 8);
            context->notifyNext = 0;
            KdPrint("tgwinkEvtIoDeviceControl satisfied interrupt notification request synchronously.\n");
            //WdfInterruptEnable(context->hIrq);
        } else {
            KdPrint("tgwinkEvtIoDeviceControl forwarding PEND_INTR request to notification queue\n");
            WdfRequestForwardToIoQueue(Request, context->NotificationQueue);
        }
        WdfWaitLockRelease(context->nnLock);
    } break;

    default:
        WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
    }
}