Пример #1
0
// This callback is called when interval wait time has expired and driver is ready
// to collect new sample. The callback reads current value, compare value to threshold,
// pushes it up to CLX framework, and schedule next wake up time.
VOID ActivityDevice::OnTimerExpire(_In_ WDFTIMER timer)
{
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    PActivityDevice pDevice = GetActivityContextFromSensorInstance(WdfTimerGetParentObject(timer));
    if (nullptr == pDevice)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
    }
    else
    {
        // Get data and push to clx
        WdfWaitLockAcquire(pDevice->m_Lock, NULL);
        status = pDevice->GetData();
        if (!NT_SUCCESS(status) && STATUS_DATA_NOT_ACCEPTED != status)
        {
            TraceError("ACT %!FUNC! GetAccData Failed %!STATUS!", status);
        }
        WdfWaitLockRelease(pDevice->m_Lock);

        // Schedule next wake up time
        if (Act_Default_MinDataInterval_Ms <= pDevice->m_Interval &&
            FALSE != pDevice->m_PoweredOn &&
            FALSE != pDevice->m_Started)
        {
            WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval));
        }
    }

    SENSOR_FunctionExit(status);
}
Пример #2
0
VOID
SimSensorExpiredRequestTimer (
    WDFTIMER Timer
    )

/*++

Routine Description:

    This routine is invoked when a request timer expires. A scan of the pending
    queue to complete expired and satisfied requests is initiated.

Arguments:

    Timer - Supplies a handle to the timer which expired.

--*/

{

    PFDO_DATA DevExt;
    WDFDEVICE Device;

    DebugEnter();
    PAGED_CODE();

    Device = (WDFDEVICE)WdfTimerGetParentObject(Timer);
    DevExt = GetDeviceExtension(Device);
    WdfWaitLockAcquire(DevExt->QueueLock, NULL);
    SimSensorScanPendingQueue(Device);
    WdfWaitLockRelease(DevExt->QueueLock);

    DebugExit();
}
Пример #3
0
VOID
SimSensorTemperatureInterruptWorker (
    _In_ WDFWORKITEM WorkItem
    )

/*++

Routine Description:

    This routine is invoked to call into the device to notify it of a
    temperature change.

Arguments:

    WorkItem - Supplies a handle to this work item.

Return Value:

    None.

--*/

{

    PFDO_DATA DevExt;
    WDFDEVICE Device;

    Device = (WDFDEVICE)WdfWorkItemGetParentObject(WorkItem);
    DevExt = GetDeviceExtension(Device);
    WdfWaitLockAcquire(DevExt->QueueLock, NULL);
    SimSensorScanPendingQueue(Device);
    WdfWaitLockRelease(DevExt->QueueLock);
    return;
}
// This callback is called when the simulator wait time has expired and the simulator
// is ready to switch to the next sample. The callback updates the sample index and 
// schedules the next wake up time.
VOID
HardwareSimulator::OnTimerExpire(
    _In_ WDFTIMER Timer) // WDF timer object
{
    HardwareSimulator *pSimulator = nullptr;
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    pSimulator = GetHardwareSimulatorContextFromInstance(WdfTimerGetParentObject(Timer));
    if (nullptr == pSimulator)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("CSTM %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
    }

    if (NT_SUCCESS(Status))
    {
        // Increment the sample index, roll over if the index reach the end of the array
        WdfWaitLockAcquire(pSimulator->m_Lock, NULL);
        pSimulator->m_Index++;
        pSimulator->m_Index = pSimulator->m_Index % ARRAYSIZE(SimulatorData);
        WdfWaitLockRelease(pSimulator->m_Lock);

        WdfTimerStart(pSimulator->m_Timer, WDF_REL_TIMEOUT_IN_MS(SIMULATOR_HARDWARE_INTERVAL_MS));
    }

    SENSOR_FunctionExit(Status);
}
Пример #5
0
/*++

Routine Description:

    Write to mail box in a serialize manner

Arguments:

    DeviceContextPtr - Pointer to device context

    Channel - Mailbox Channel

    Value - Value to be written

    Request - Optional WDF request object associated with this mailbox 
        transaction

Return Value:

    NTSTATUS

--*/
_Use_decl_annotations_
NTSTATUS RpiqMailboxWrite (
    DEVICE_CONTEXT* DeviceContextPtr,
    ULONG Channel,
    ULONG Value,
    WDFREQUEST Request
    )
{
    NTSTATUS status;
    ULONG count = 0, reg;
    LARGE_INTEGER timeOut = { 0 };

    PAGED_CODE();
    
    WdfWaitLockAcquire(DeviceContextPtr->WriteLock, NULL);

    timeOut.QuadPart = WDF_REL_TIMEOUT_IN_MS(1);

    reg = READ_REGISTER_NOFENCE_ULONG(&DeviceContextPtr->Mailbox->Status);

    // Poll until mailbox is available. It doesn't seem like
    // the mailbox is full often so polling is sufficient for now
    // rather than enable mailbox empty interrupt
    while (reg & MAILBOX_STATUS_FULL) {
        if (count > MAX_POLL) {
            RPIQ_LOG_ERROR(
                "Exit Fail Status 0x%08x", 
                DeviceContextPtr->Mailbox->Status);
            status = STATUS_IO_TIMEOUT;
            goto End;
        }

        KeDelayExecutionThread(KernelMode, FALSE, &timeOut);
        reg = READ_REGISTER_NOFENCE_ULONG(&DeviceContextPtr->Mailbox->Status);
        ++count;
    }

    if (Request) {
        status = WdfRequestForwardToIoQueue(
            Request,
            DeviceContextPtr->ChannelQueue[Channel]);
        if (!NT_SUCCESS(status)) {
            RPIQ_LOG_ERROR(
                "WdfRequestForwardToIoQueue failed ( %!STATUS!)",
                status);
            goto End;
        }
    }

    WRITE_REGISTER_NOFENCE_ULONG(
        &DeviceContextPtr->Mailbox->Write, 
        (Value & ~MAILBOX_CHANNEL_MASK) | Channel);

    status = STATUS_SUCCESS;

End:
    WdfWaitLockRelease(DeviceContextPtr->WriteLock);

    return status;
}
Пример #6
0
// Called by Sensor CLX to clear all history stored in the sensor.
NTSTATUS ActivityDevice::OnClearHistory(_In_ SENSOROBJECT sensorInstance)
{
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
    if (nullptr == pDevice)
    {
        status = STATUS_INVALID_PARAMETER;
        TraceError("ACT %!FUNC! Sensor parameter is invalid. Failed %!STATUS!", status);
    }
    else
    {
        WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
        status = pDevice->ClearHistoryBuffer();
        if (!NT_SUCCESS(status))
        {
            TraceError("ACT %!FUNC! ClearHistoryBuffer Failed %!STATUS!", status);
        }
        WdfWaitLockRelease(pDevice->m_HistoryLock);
    }

    SENSOR_FunctionExit(status);
    return status;
}
NTSTATUS
DeviceContext::CommandNciWriteComplete(
    _In_ WDFREQUEST Request
    )
{
    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
    NTSTATUS status;

    WdfWaitLockAcquire(_ClientLock, nullptr);

    if (_NciWriteRequest == nullptr)
    {
        status = STATUS_INVALID_DEVICE_STATE;
        TRACE_LINE(LEVEL_ERROR, "No NCI write request is pending. %!STATUS!", status);
        WdfWaitLockRelease(_ClientLock);
        return status;
    }

    WDFREQUEST nciWriteRequest = _NciWriteRequest;
    _NciWriteRequest = nullptr;

    WdfWaitLockRelease(_ClientLock);

    // Complete NCI write I/O request.
    WdfRequestComplete(nciWriteRequest, STATUS_SUCCESS);

    // Complete I/O request.
    WdfRequestComplete(Request, STATUS_SUCCESS);

    TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE);
    return STATUS_SUCCESS;
}
// Called when a NciSim file handle is opened.
NTSTATUS
DeviceContext::ClientConnected(
    _In_ FileObjectContext* FileContext
    )
{
    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);

    WdfWaitLockAcquire(_ClientLock, nullptr);

    // Ensure there is only a single client connected at a time.
#ifdef WDF_IS_NOT_CALLING_FILE_CLOSE
    if (_CurrentSimClient)
    {
        WdfWaitLockRelease(_ClientLock);

        NTSTATUS status = STATUS_ACCESS_DENIED;
        TRACE_LINE(LEVEL_ERROR, "A client is already connected. %!STATUS!", status);
        return status;
    }
#endif

    _CurrentSimClient = FileContext;

    WdfWaitLockRelease(_ClientLock);

    TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE);
    return STATUS_SUCCESS;
}
Пример #9
0
_Use_decl_annotations_
NTSTATUS
SimBattQueryStatus (
    PVOID Context,
    ULONG BatteryTag,
    PBATTERY_STATUS BatteryStatus
    )

/*++

Routine Description:

    Called by the class driver to retrieve the batteries current status

    The battery class driver will serialize all requests it issues to
    the miniport for a given battery.

Arguments:

    Context - Supplies the miniport context value for battery

    BatteryTag - Supplies the tag of current battery

    BatteryStatus - Supplies a pointer to the structure to return the current
        battery status in

Return Value:

    Success if there is a battery currently installed, else no such device.

--*/

{
    PSIMBATT_FDO_DATA DevExt;
    NTSTATUS Status;

    DebugEnter();
    PAGED_CODE();

    DevExt = (PSIMBATT_FDO_DATA)Context;
    WdfWaitLockAcquire(DevExt->StateLock, NULL);
    if (BatteryTag != DevExt->BatteryTag) {
        Status = STATUS_NO_SUCH_DEVICE;
        goto QueryStatusEnd;
    }

    RtlCopyMemory(BatteryStatus,
                  &DevExt->State.BatteryStatus,
                  sizeof(BATTERY_STATUS));

    Status = STATUS_SUCCESS;

QueryStatusEnd:
    WdfWaitLockRelease(DevExt->StateLock);
    DebugExitStatus(Status);
    return Status;
}
Пример #10
0
_Use_decl_annotations_
NTSTATUS
SimBattSetStatusNotify (
    PVOID Context,
    ULONG BatteryTag,
    PBATTERY_NOTIFY BatteryNotify
    )

/*++

Routine Description:

    Called by the class driver to set the capacity and power state levels
    at which the class driver requires notification.

    The battery class driver will serialize all requests it issues to
    the miniport for a given battery.

Arguments:

    Context - Supplies the miniport context value for battery

    BatteryTag - Supplies the tag of current battery

    BatteryNotify - Supplies a pointer to a structure containing the
        notification critera.

Return Value:

    Success if there is a battery currently installed, else no such device.

--*/

{
    PSIMBATT_FDO_DATA DevExt;
    NTSTATUS Status;

    UNREFERENCED_PARAMETER(BatteryNotify);

    DebugEnter();
    PAGED_CODE();

    DevExt = (PSIMBATT_FDO_DATA)Context;
    WdfWaitLockAcquire(DevExt->StateLock, NULL);
    if (BatteryTag != DevExt->BatteryTag) {
        Status = STATUS_NO_SUCH_DEVICE;
        goto SetStatusNotifyEnd;
    }

    Status = STATUS_NOT_SUPPORTED;

SetStatusNotifyEnd:
    WdfWaitLockRelease(DevExt->StateLock);
    DebugExitStatus(Status);
    return Status;
}
Пример #11
0
_Use_decl_annotations_
NTSTATUS
SimBattSetBatteryStatus (
    WDFDEVICE Device,
    PBATTERY_STATUS BatteryStatus
    )

/*++

Routine Description:

    Set the simulated battery status structure values.

Arguments:

    Device - Supplies the device to set data for.

    BatteryStatus - Supplies the new status data to set.

Return Value:

   NTSTATUS

--*/

{

    PSIMBATT_FDO_DATA DevExt;
    NTSTATUS Status;
    ULONG ValidPowerState;

    PAGED_CODE();

    Status = STATUS_INVALID_PARAMETER;
    DevExt = GetDeviceExtension(Device);
    ValidPowerState = BATTERY_CHARGING |
                      BATTERY_DISCHARGING |
                      BATTERY_CRITICAL |
                      BATTERY_POWER_ON_LINE;

    if ((BatteryStatus->PowerState & ~ValidPowerState) != 0) {
        goto SetBatteryStatusEnd;
    }

    WdfWaitLockAcquire(DevExt->StateLock, NULL);
    DevExt->State.BatteryStatus.PowerState = BatteryStatus->PowerState;
    DevExt->State.BatteryStatus.Capacity = BatteryStatus->Capacity;
    DevExt->State.BatteryStatus.Voltage = BatteryStatus->Voltage;
    DevExt->State.BatteryStatus.Rate = BatteryStatus->Rate;
    WdfWaitLockRelease(DevExt->StateLock);
    BatteryClassStatusNotify(DevExt->ClassHandle);
    Status = STATUS_SUCCESS;

SetBatteryStatusEnd:
    return Status;
}
Пример #12
0
NTSTATUS
ResetDevice(
    _In_ WDFDEVICE Device
    )
/*++

Routine Description:

    This routine calls WdfUsbTargetDeviceResetPortSynchronously to reset the device if it's still
    connected.

Arguments:

    Device - Handle to a framework device

Return Value:

    NT status value

--*/
{
    PDEVICE_CONTEXT pDeviceContext;
    NTSTATUS status;
    
    PAGED_CODE();
 
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "--> ResetDevice\n");

    pDeviceContext = GetDeviceContext(Device);

    //
    // A NULL timeout indicates an infinite wake
    //
    status = WdfWaitLockAcquire(pDeviceContext->ResetDeviceWaitLock, NULL);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ResetDevice - could not acquire lock\n");
        return status;
    }

    StopAllPipes(pDeviceContext);
    
    status = WdfUsbTargetDeviceResetPortSynchronously(pDeviceContext->UsbDevice);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ResetDevice failed - 0x%x\n", status);
    }
    
    status = StartAllPipes(pDeviceContext);
    if (!NT_SUCCESS(status)) {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Failed to start all pipes - 0x%x\n", status);
    }
    
    WdfWaitLockRelease(pDeviceContext->ResetDeviceWaitLock);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "<-- ResetDevice\n");
    return status;
}
Пример #13
0
VOID
ToastMon_EvtIoTargetRemoveComplete(
    WDFIOTARGET IoTarget
)
/*++

Routine Description:

    Called when the Target device is removed ( either the target
    received IRP_MN_REMOVE_DEVICE or IRP_MN_SURPRISE_REMOVAL)

Arguments:

    IoTarget -

Return Value:


--*/
{
    PDEVICE_EXTENSION      deviceExtension;
    PTARGET_DEVICE_INFO    targetDeviceInfo = NULL;

    KdPrint((("Device Removal (remove complete) Notification\n")));

    PAGED_CODE();

    targetDeviceInfo = GetTargetDeviceInfo(IoTarget);
    deviceExtension = targetDeviceInfo->DeviceExtension;

    //
    // Stop the timer 
    //
    WdfTimerStop(targetDeviceInfo->TimerForPostingRequests, TRUE);

    //
    // Remove the target device from the collection and set Opened to FALSE to match
    // the state change (in the case of a surprise removal of the target, 
    // ToastMon_EvtIoTargetQueryRemove is not called so Opened is still TRUE).
    //
    WdfWaitLockAcquire(deviceExtension->TargetDeviceCollectionLock, NULL);

    WdfCollectionRemove(deviceExtension->TargetDeviceCollection, IoTarget);
    targetDeviceInfo->Opened = FALSE;
     
    WdfWaitLockRelease(deviceExtension->TargetDeviceCollectionLock);

    //
    // Finally delete the target.
    //
    WdfObjectDelete(IoTarget);

    return;

}
Пример #14
0
NTSTATUS
ToastMon_EvtIoTargetQueryRemove(
    WDFIOTARGET IoTarget
)
/*++

Routine Description:

    Called when the Target device receives IRP_MN_QUERY_REMOVE.
    This happens when somebody disables, ejects or uninstalls the target
    device driver in usermode. Here close the handle to the
    target device. If the system fails to remove the device for
    some reason, you will get RemoveCancelled callback where
    you can reopen and continue to interact with the target device.

Arguments:

    IoTarget -

Return Value:


--*/
{
    PTARGET_DEVICE_INFO         targetDeviceInfo = NULL;
    WDFWAITLOCK                 targetDeviceCollectionLock;

    PAGED_CODE();

    targetDeviceInfo = GetTargetDeviceInfo(IoTarget);

    KdPrint((("Device Removal (query remove) Notification\n")));

    //
    // Stop the timer 
    //

    WdfTimerStop(targetDeviceInfo->TimerForPostingRequests, TRUE);

    targetDeviceCollectionLock = targetDeviceInfo->DeviceExtension->TargetDeviceCollectionLock;

    //
    // The target is being query removed, set Opened to FALSE to match this state change.
    //
    WdfWaitLockAcquire(targetDeviceCollectionLock, NULL);
    targetDeviceInfo->Opened = FALSE;
    WdfWaitLockRelease(targetDeviceCollectionLock);

    WdfIoTargetCloseForQueryRemove(IoTarget);

    return STATUS_SUCCESS;

}
Пример #15
0
VOID
FilterEvtDeviceContextCleanup(
    IN WDFDEVICE Device
    )
/*++

Routine Description:

   EvtDeviceRemove event callback must perform any operations that are
   necessary before the specified device is removed. The framework calls
   the driver's EvtDeviceRemove callback when the PnP manager sends
   an IRP_MN_REMOVE_DEVICE request to the driver stack.

Arguments:

    Device - Handle to a framework device object.

Return Value:

    WDF status code

--*/
{
    ULONG   count;

    PAGED_CODE();

    KdPrint(("Entered FilterEvtDeviceContextCleanup\n"));

    WdfWaitLockAcquire(FilterDeviceCollectionLock, NULL);

    count = WdfCollectionGetCount(FilterDeviceCollection);

    if(count == 1)
    {
         //
         // We are the last instance. So let us delete the control-device
         // so that driver can unload when the FilterDevice is deleted.
         // We absolutely have to do the deletion of control device with
         // the collection lock acquired because we implicitly use this
         // lock to protect ControlDevice global variable. We need to make
         // sure another thread doesn't attempt to create while we are
         // deleting the device.
         //
         FilterDeleteControlDevice(Device);
     }

    WdfCollectionRemove(FilterDeviceCollection, Device);

    WdfWaitLockRelease(FilterDeviceCollectionLock);
}
Пример #16
0
// This callback is called when interval wait time has expired and driver is ready
// to collect new sample. The callback stores activity data in history buffer,
// and schedules next wake up time.
VOID ActivityDevice::OnHistoryTimerExpire(_In_ WDFTIMER historyTimer)
{
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    PActivityDevice pDevice = GetActivityContextFromSensorInstance(WdfTimerGetParentObject(historyTimer));
    if (nullptr == pDevice)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
    }
    else
    {
        ActivitySample data = {};
        if (NULL != pDevice->m_SimulatorInstance)
        {
            PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
            if (nullptr != pSimulator)
            {
                status = pSimulator->GetSample(&data);
            }
            else
            {
                status = STATUS_INVALID_PARAMETER;
            }
        }
        GetSystemTimePreciseAsFileTime(&(data.Timestamp));

        if (NT_SUCCESS(status))
        {
            // Add data to the buffer
            WdfWaitLockAcquire(pDevice->m_HistoryLock, NULL);
            status = pDevice->AddDataElementToHistoryBuffer(&data);
            if (!NT_SUCCESS(status))
            {
                TraceError("ACT %!FUNC! AddDataElementToHistoryBuffer Failed %!STATUS!", status);
            }
            WdfWaitLockRelease(pDevice->m_HistoryLock);
        }

        // Schedule next wake up time
        if (FALSE != pDevice->m_HistoryStarted)
        {
            WdfTimerStart(pDevice->m_HistoryTimer, WDF_REL_TIMEOUT_IN_MS(pDevice->m_HistoryIntervalInMs));
        }
    }

    SENSOR_FunctionExit(status);
}
// This routine returns the current sample from the driver at the current m_Index location.
// Returns one of the ABI::Windows::Devices::Sensors::SimpleOrientation enum values.
ABI::Windows::Devices::Sensors::SimpleOrientation HardwareSimulator::GetOrientation()
{
    ABI::Windows::Devices::Sensors::SimpleOrientation Sample = ABI::Windows::Devices::Sensors::SimpleOrientation::SimpleOrientation_Faceup;
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    WdfWaitLockAcquire(m_Lock, NULL);
    Sample = OrientationData[m_Index];
    WdfWaitLockRelease(m_Lock);

    SENSOR_FunctionExit(Status);

    return Sample;
}
Пример #18
0
NTSTATUS
OnEvtDeviceD0Entry (
  _In_ WDFDEVICE Device,
  _In_ WDF_POWER_DEVICE_STATE PreviousState
)
/*++

Routine Description:

    Called by the framework after entering D0 state.

Arguments:

    Device - WDFDEVICE framework handle to the bus FDO.

    PreviousState - The WDF_POWER_DEVICE_STATE from which the stack is
        making this transition.

Return Value:

    Returns STATUS_SUCCESS or an appropriate NTSTATUS code otherwise.

--*/
{
    PCONTROLLER_CONTEXT ControllerContext;

    TraceEntry();

    ControllerContext = DeviceGetControllerContext(Device);

    if (PreviousState > WdfPowerDeviceD1) { 
        DevicePerformSoftReset(Device);

        WdfWaitLockAcquire(ControllerContext->InitializeDefaultEndpointLock, NULL);
        ControllerContext->InitializeDefaultEndpoint = TRUE;
        WdfWaitLockRelease(ControllerContext->InitializeDefaultEndpointLock);
    }

    if (PreviousState == WdfPowerDeviceD3Final) {
        //
        // Notify UFX that HW is now ready
        //
        UfxDeviceNotifyHardwareReady(ControllerContext->UfxDevice);
    }

    TraceExit();
    return STATUS_SUCCESS;
}
// This routine returns the current sample from the driver at the current m_Index
// location
FLOAT
HardwareSimulator::GetSample()
{
    FLOAT Sample = 0.0f;
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    WdfWaitLockAcquire(m_Lock, NULL);
    Sample = SimulatorData[m_Index];
    WdfWaitLockRelease(m_Lock);

    SENSOR_FunctionExit(Status);

    return Sample;
}
// Called when a NciSim file handle is closed.
void
DeviceContext::ClientDisconnected(
    _In_ FileObjectContext* FileContext
    )
{
    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);

    WdfWaitLockAcquire(_ClientLock, nullptr);

    if (FileContext != _CurrentSimClient)
    {
        WdfWaitLockRelease(_ClientLock);
        TRACE_LINE(LEVEL_WARNING, "Incorrect client.");
        return;
    }

    _CurrentSimClient = nullptr;

    // Acquire the pending NCI write request (if any).
    WDFREQUEST nciWriteRequest = _NciWriteRequest;
    _NciWriteRequest = nullptr;

    // Acquire the sequence completed function (if any).
    PFN_NFC_CX_SEQUENCE_COMPLETION_ROUTINE sequenceCompleted = _SequenceCompleted;
    WDFCONTEXT sequenceCompletedContext = _SequenceCompletedContext;

    _SequenceCompleted = nullptr;
    _SequenceCompletedContext = nullptr;

    WdfWaitLockRelease(_ClientLock);

    if (nciWriteRequest)
    {
        TRACE_LINE(LEVEL_WARNING, "NCI write request was not completed by test client. Completing with error.");
        WdfRequestComplete(nciWriteRequest, STATUS_CONNECTION_DISCONNECTED);
    }

    if (sequenceCompleted)
    {
        // Complete the pending sequence handler, to help prevent the driver from getting into a blocked state.
        TRACE_LINE(LEVEL_INFO, "Completing leftover sequence handler.");
        sequenceCompleted(_Device, STATUS_SUCCESS, 0, sequenceCompletedContext);
    }

    TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE);
}
Пример #21
0
VOID
VIOSerialSendCtrlMsg(
    IN WDFDEVICE Device,
    IN ULONG id,
    IN USHORT event,
    IN USHORT value
)
{
    struct VirtIOBufferDescriptor sg;
    struct virtqueue *vq;
    UINT len;
    PPORTS_DEVICE pContext = GetPortsDevice(Device);
    VIRTIO_CONSOLE_CONTROL cpkt;

    if (!pContext->isHostMultiport)
    {
        return;
    }

    vq = pContext->c_ovq;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s vq = %p\n", __FUNCTION__, vq);

    cpkt.id = id;
    cpkt.event = event;
    cpkt.value = value;

    sg.physAddr = MmGetPhysicalAddress(&cpkt);
    sg.length = sizeof(cpkt);

    WdfWaitLockAcquire(pContext->COutVqLock, NULL);
    if(0 <= virtqueue_add_buf(vq, &sg, 1, 0, &cpkt, NULL, 0))
    {
        virtqueue_kick(vq);
        while(!virtqueue_get_buf(vq, &len))
        {
            LARGE_INTEGER interval;
            interval.QuadPart = -1;
            KeDelayExecutionThread(KernelMode, FALSE, &interval);
        }
    }
    WdfWaitLockRelease(pContext->COutVqLock);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__);
}
Пример #22
0
_Use_decl_annotations_
NTSTATUS
SimBattQueryTag (
    PVOID Context,
    PULONG BatteryTag
    )

/*++

Routine Description:

    This routine is called to get the value of the current battery tag.

Arguments:

    Context - Supplies the miniport context value for battery

    BatteryTag - Supplies a pointer to a ULONG to receive the battery tag.

Return Value:

    NTSTATUS

--*/

{
    PSIMBATT_FDO_DATA DevExt;
    NTSTATUS Status;

    DebugEnter();
    PAGED_CODE();

    DevExt = (PSIMBATT_FDO_DATA)Context;
    WdfWaitLockAcquire(DevExt->StateLock, NULL);
    *BatteryTag = DevExt->BatteryTag;
    WdfWaitLockRelease(DevExt->StateLock);
    if (*BatteryTag == BATTERY_TAG_INVALID) {
        Status = STATUS_NO_SUCH_DEVICE;
    } else {
        Status = STATUS_SUCCESS;
    }

    DebugExitStatus(Status);
    return Status;
}
NTSTATUS
DeviceContext::CommandSequenceHandlerComplete(
    _In_ WDFREQUEST Request
    )
{
    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
    NTSTATUS status;

    // Get request's parameters.
    NciSimSequenceHandlerComplete* params;
    status = WdfRequestRetrieveInputBuffer(Request, sizeof(NciSimSequenceHandlerComplete), reinterpret_cast<void**>(&params), nullptr);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "WdfRequestRetrieveInputBuffer failed. %!STATUS!", status);
        return status;
    }

    WdfWaitLockAcquire(_ClientLock, nullptr);

    // Acquire the sequence completed function.
    PFN_NFC_CX_SEQUENCE_COMPLETION_ROUTINE sequenceCompleted = _SequenceCompleted;
    WDFCONTEXT sequenceCompletedContext = _SequenceCompletedContext;

    _SequenceCompleted = nullptr;
    _SequenceCompletedContext = nullptr;

    WdfWaitLockRelease(_ClientLock);

    // Ensure there is a sequence handler pending.
    if (!sequenceCompleted)
    {
        status = STATUS_INVALID_DEVICE_STATE;
        TRACE_LINE(LEVEL_ERROR, "No sequence completion routine is pending. %!STATUS!", status);
        return status;
    }

    // Call the sequence completed function.
    sequenceCompleted(_Device, params->Status, params->Flags, sequenceCompletedContext);

    // Complete I/O request.
    WdfRequestComplete(Request, STATUS_SUCCESS);

    TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE);
    return STATUS_SUCCESS;
}
// Called when NfcCx has an NCI packet it wishes to sent to the device.
void
DeviceContext::WriteNciPacket(
    _In_ WDFREQUEST Request
    )
{
    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
    NTSTATUS status;

    // Get NCI packet.
    void* nciBuffer;
    size_t nciLength;
    status = WdfRequestRetrieveInputBuffer(Request, 0, &nciBuffer, &nciLength);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "Failed to read input buffer. %!STATUS!", status);
        WdfRequestComplete(Request, status);
        return;
    }

    WdfWaitLockAcquire(_ClientLock, nullptr);

    if (_NciWriteRequest != nullptr)
    {
        status = STATUS_INVALID_DEVICE_STATE;
        TRACE_LINE(LEVEL_ERROR, "A pending NCI write already exists. %!STATUS!", status);
        WdfWaitLockRelease(_ClientLock);
        WdfRequestComplete(Request, status);
        return;
    }

    // Post NCI write callback.
    status = _ApiCallbacksManager.PostNciWriteCallback(nciBuffer, nciLength);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "CallbacksManager::PostNciWriteCallback failed. %!STATUS!", status);
        WdfWaitLockRelease(_ClientLock);
        WdfRequestComplete(Request, status);
        return;
    }

    _NciWriteRequest = Request;

    WdfWaitLockRelease(_ClientLock);
    TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE);
}
Пример #25
0
_Use_decl_annotations_
NTSTATUS
SimBattSetBatteryEstimatedTime (
    WDFDEVICE Device,
    ULONG EstimatedTime
    )

/*++

Routine Description:

    Set the simulated battery estimated charge/run time. The value
    SIMBATT_RATE_CALCULATE causes the estimated time to be calculated based on
    charge/discharge status, the charge/discharge rate, the current capacity,
    and the last full charge capacity.

Arguments:

    Device - Supplies the device to set data for.

    EstimatedTime - Supplies the new estimated run/charge time to set.

Return Value:

   NTSTATUS

--*/

{

    PSIMBATT_FDO_DATA DevExt;

    PAGED_CODE();

    DevExt = GetDeviceExtension(Device);
    WdfWaitLockAcquire(DevExt->StateLock, NULL);
    DevExt->State.EstimatedTime = EstimatedTime;
    WdfWaitLockRelease(DevExt->StateLock);
    return STATUS_SUCCESS;
}
void
DeviceContext::SequenceHandler(
    _In_ NFC_CX_SEQUENCE Sequence,
    _In_ PFN_NFC_CX_SEQUENCE_COMPLETION_ROUTINE CompletionRoutine,
    _In_opt_ WDFCONTEXT CompletionContext
    )
{
    TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE);
    NTSTATUS status;

    WdfWaitLockAcquire(_ClientLock, nullptr);

    if (!_CurrentSimClient)
    {
        // There currently isn't a connected client. So just complete the sequence handler immediately.
        // This helps improve the robustness of the driver if a test fails.
        TRACE_LINE(LEVEL_INFO, "Leftover sequence handler.");
        WdfWaitLockRelease(_ClientLock);
        CompletionRoutine(_Device, STATUS_SUCCESS, 0, CompletionContext);
        return;
    }

    // Notify the test process that a sequence handler was invoked.
    status = _ApiCallbacksManager.PostSequenceHandlerCallback(Sequence);
    if (!NT_SUCCESS(status))
    {
        TRACE_LINE(LEVEL_ERROR, "CallbacksManager::PostSequenceHandlerCallback failed. %!STATUS!", status);
        WdfWaitLockRelease(_ClientLock);
        CompletionRoutine(_Device, status, 0, CompletionContext);
        return;
    }

    _SequenceCompleted = CompletionRoutine;
    _SequenceCompletedContext = CompletionContext;

    WdfWaitLockRelease(_ClientLock);
    TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE);
}
Пример #27
0
_Use_decl_annotations_
NTSTATUS
SimBattSetBatteryTemperature (
    WDFDEVICE Device,
    ULONG Temperature
    )

/*++

Routine Description:

    Set the simulated battery temperature value.

Arguments:

    Device - Supplies the device to set data for.

    Temperature - Supplies the new temperature to set.

Return Value:

   NTSTATUS

--*/

{

    PSIMBATT_FDO_DATA DevExt;

    PAGED_CODE();

    DevExt = GetDeviceExtension(Device);
    WdfWaitLockAcquire(DevExt->StateLock, NULL);
    DevExt->State.Temperature = Temperature;
    WdfWaitLockRelease(DevExt->StateLock);
    return STATUS_SUCCESS;
}
Пример #28
0
NTSTATUS
TchStandbyDevice(
   IN VOID *ControllerContext,
   IN SPB_CONTEXT *SpbContext
   )
/*++

Routine Description:

   Disables multi-touch scanning to conserve power

Arguments:

   ControllerContext - Touch controller context
   
   SpbContext - A pointer to the current i2c context

Return Value:

   NTSTATUS indicating success or failure

--*/
{
    RMI4_CONTROLLER_CONTEXT* controller;
    NTSTATUS status;

    controller = (RMI4_CONTROLLER_CONTEXT*) ControllerContext;

    //
    // Interrupts are now disabled but the ISR may still be
    // executing, so grab the controller lock to ensure ISR
    // is finished touching HW and controller state.
    //
    WdfWaitLockAcquire(controller->ControllerLock, NULL);

    //
    // Put the chip in sleep mode
    //
    status = RmiChangeSleepState(
        ControllerContext,
        SpbContext,
        RMI4_F11_DEVICE_CONTROL_SLEEP_MODE_SLEEPING);

    if (!NT_SUCCESS(status))
    {
        Trace(
            TRACE_LEVEL_ERROR,
            TRACE_FLAG_POWER,
            "Error sleeping touch controller - %!STATUS!",
            status);
    }

    controller->DevicePowerState = PowerDeviceD3;

    //
    // Invalidate state
    //
    controller->TouchesReported = 0;
    controller->TouchesTotal = 0;
    controller->Cache.FingerSlotValid = 0;
    controller->Cache.FingerSlotDirty = 0;
    controller->Cache.FingerDownCount = 0;

    WdfWaitLockRelease(controller->ControllerLock);

    return STATUS_SUCCESS;
}
Пример #29
0
NTSTATUS
ToastMon_PnpNotifyInterfaceChange(
    IN  PDEVICE_INTERFACE_CHANGE_NOTIFICATION NotificationStruct,
    IN  PVOID                        Context
    )
/*++

Routine Description:

    This routine is the PnP "interface change notification" callback routine.

    This gets called on a Toaster triggered device interface arrival or
    removal.
      - Interface arrival corresponds to a Toaster device being STARTED
      - Interface removal corresponds to a Toaster device being REMOVED

    On arrival:
      - Create a IoTarget and open it by using the symboliclink. WDF will
         Register for EventCategoryTargetDeviceChange notification on the fileobject
        so it can cleanup whenever associated device is removed.

    On removal:
      - This callback is a NO-OP for interface removal because framework registers
      for PnP EventCategoryTargetDeviceChange callbacks and
      uses that callback to clean up when the associated toaster device goes
      away.

Arguments:

    NotificationStruct  - Structure defining the change.

    Context -    pointer to the device extension.
                 (supplied as the "context" when we
                  registered for this callback)
Return Value:

    STATUS_SUCCESS - always, even if something goes wrong

    status is only used during query removal notifications and the OS ignores other
    cases

--*/
{
    NTSTATUS                    status = STATUS_SUCCESS;
    PDEVICE_EXTENSION           deviceExtension = Context;
    WDFIOTARGET                 ioTarget;

    PAGED_CODE();

    KdPrint(("Entered ToastMon_PnpNotifyInterfaceChange\n"));

    //
    // Verify that interface class is a toaster device interface.
    //
    ASSERT(IsEqualGUID( (LPGUID)&(NotificationStruct->InterfaceClassGuid),
                      (LPGUID)&GUID_DEVINTERFACE_TOASTER));

    //
    // Check the callback event.
    //
    if(IsEqualGUID( (LPGUID)&(NotificationStruct->Event),
                     (LPGUID)&GUID_DEVICE_INTERFACE_ARRIVAL )) {

        KdPrint(("Arrival Notification\n"));

        status = Toastmon_OpenDevice((WDFDEVICE)deviceExtension->WdfDevice,
                                                (PUNICODE_STRING)NotificationStruct->SymbolicLinkName,
                                                &ioTarget);
        if (!NT_SUCCESS(status)) {
            KdPrint( ("Unable to open control device 0x%x\n", status));
            return status;
        }

        //
        // Add this one to the collection.
        //
        WdfWaitLockAcquire(deviceExtension->TargetDeviceCollectionLock, NULL);

        //
        // WdfCollectionAdd takes a reference on the request object and removes
        // it when you call WdfCollectionRemove.
        //
        status = WdfCollectionAdd(deviceExtension->TargetDeviceCollection, ioTarget);
        if (!NT_SUCCESS(status)) {
            KdPrint( ("WdfCollectionAdd failed 0x%x\n", status));
            WdfObjectDelete(ioTarget); // Delete will also close the target
        }

        WdfWaitLockRelease(deviceExtension->TargetDeviceCollectionLock);


    } else {

        KdPrint(("Removal Interface Notification\n"));
    }
    return STATUS_SUCCESS;
}
Пример #30
0
VOID
ToastMon_EvtIoTargetRemoveCanceled(
    WDFIOTARGET IoTarget
    )
/*++

Routine Description:

    Called when the Target device received IRP_MN_CANCEL_REMOVE.
    This happens if another app or driver talking to the target
    device doesn't close handle or veto query-remove notification.

Arguments:

    IoTarget -

Return Value:


--*/
{
    PTARGET_DEVICE_INFO         targetDeviceInfo = NULL;
    WDFWAITLOCK                 targetDeviceCollectionLock;
    WDF_IO_TARGET_OPEN_PARAMS   openParams;
    NTSTATUS status;

    PAGED_CODE();

    KdPrint((("Device Removal (remove cancelled) Notification\n")));

    targetDeviceInfo = GetTargetDeviceInfo(IoTarget);

    //
    // Reopen the Target.
    //
    WDF_IO_TARGET_OPEN_PARAMS_INIT_REOPEN(&openParams);

    status = WdfIoTargetOpen(IoTarget, &openParams);

    if (!NT_SUCCESS(status)) {
        KdPrint(("WdfIoTargetOpen failed 0x%x\n", status));
        WdfObjectDelete(IoTarget);
        return;
    }

    targetDeviceCollectionLock = targetDeviceInfo->DeviceExtension->TargetDeviceCollectionLock;

    //
    // The query remove has failed and the target has been successfully reopened. Set Opened
    // back to TRUE to reflect the state change.
    //
    WdfWaitLockAcquire(targetDeviceCollectionLock, NULL);
    targetDeviceInfo->Opened = TRUE;
    WdfWaitLockRelease(targetDeviceCollectionLock);


    //
    // Restart the timer.
    //
    WdfTimerStart(targetDeviceInfo->TimerForPostingRequests,
                                        WDF_REL_TIMEOUT_IN_SEC(1));

}