Пример #1
0
//------------------------------------------------------------------------------
// Function: GetData
//
// This routine is called by worker thread to read a single sample, compare threshold
// and push it back to CLX. It simulates hardware thresholding by only generating data
// when the change of data is greater than threshold.
//
// Arguments:
//       None
//
// Return Value:
//      NTSTATUS code
//------------------------------------------------------------------------------
NTSTATUS
PrxDevice::GetData(
    )
{
    BOOLEAN DataReady = FALSE;
    FILETIME TimeStamp = {0};
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    // new sample?
    if (m_FirstSample != FALSE)
    {
        Status = GetPerformanceTime(&m_StartTime);
        if (!NT_SUCCESS(Status))
        {
            m_StartTime = 0;
            TraceError("COMBO %!FUNC! PRX GetPerformanceTime %!STATUS!", Status);
        }

        m_SampleCount = 0;

        DataReady = TRUE;
    }
    else
    {
        // Compare the change of detection state, and only push the data back to
        // clx. This is usually done in HW.
        if (m_CachedData.Detected != m_LastSample.Detected)
        {
            DataReady = TRUE;
        }
    }

    if (DataReady != FALSE)
    {
        // update last sample
        m_LastSample = m_CachedData;

        // push to clx
        InitPropVariantFromBoolean(m_LastSample.Detected, &(m_pData->List[PRX_DATA_DETECT].Value));
        InitPropVariantFromUInt32(m_LastSample.DistanceMillimeters, &(m_pData->List[PRX_DATA_DISTANCE].Value));

        GetSystemTimePreciseAsFileTime(&TimeStamp);
        InitPropVariantFromFileTime(&TimeStamp, &(m_pData->List[PRX_DATA_TIMESTAMP].Value));

        SensorsCxSensorDataReady(m_SensorInstance, m_pData);
        m_FirstSample = FALSE;
    }
    else
    {
        Status = STATUS_DATA_NOT_ACCEPTED;
        TraceInformation("COMBO %!FUNC! PRX Data did NOT meet the threshold");
    }

    SENSOR_FunctionExit(Status);
    return Status;
}
Пример #2
0
// This routine is called by worker thread to read a single sample and push it back 
// to CLX.
NTSTATUS CustomSensorDevice::GetData()
{
    PHardwareSimulator pSimulator = nullptr;
    FILETIME TimeStamp = {};
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    if (FALSE != m_FirstSample)
    {
        Status = GetPerformanceTime(&m_StartTime);
        if (!NT_SUCCESS(Status))
        {
            m_StartTime = 0;
            TraceError("CSTM %!FUNC! GetPerformanceTime %!STATUS!", Status);
        }
    }

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

    // push to clx
    InitPropVariantFromFloat(pSimulator->GetSample(), &(m_pData->List[CSTM_DATA_CO2_LEVEL_PERCENT].Value));

    GetSystemTimePreciseAsFileTime(&TimeStamp);
    InitPropVariantFromFileTime(&TimeStamp, &(m_pData->List[CSTM_DATA_TIMESTAMP].Value));

    SensorsCxSensorDataReady(m_SensorInstance, m_pData);
    m_FirstSample = FALSE;

Exit:
    SENSOR_FunctionExit(Status);

    return Status;
}
Пример #3
0
// This callback is called when interval wait time has expired and driver is ready
// to collect new sample. The callback reads current value,
// pushes it up to CLX framework, and schedule next wake up time.
VOID
CustomSensorDevice::OnTimerExpire(
    _In_ WDFTIMER Timer // WDF timer object
    )
{
    PCustomSensorDevice pDevice = nullptr;
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

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

    if (NT_SUCCESS(Status))
    {
        // Get data and push to clx
        WdfWaitLockAcquire(pDevice->m_Lock, NULL);
        Status = pDevice->GetData();
        if (!NT_SUCCESS(Status) && Status != STATUS_DATA_NOT_ACCEPTED)
        {
            TraceError("CSTM %!FUNC! GetCstmData Failed %!STATUS!", Status);
        }
        WdfWaitLockRelease(pDevice->m_Lock);

        // Schedule next wake up time
        if (FALSE != pDevice->m_PoweredOn &&
            FALSE != pDevice->m_Started)
        {
            LONGLONG WaitTimeHundredNanoseconds = 0;  // in unit of 100ns

            if (0 == pDevice->m_StartTime)
            {
                // in case we fail to get sensor start time, use static wait time
                WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
            }
            else
            {
                ULONG CurrentTimeMs = 0;

                // dynamically calculate wait time to avoid jitter
                Status = GetPerformanceTime(&CurrentTimeMs);
                if (!NT_SUCCESS(Status))
                {
                    TraceError("PED %!FUNC! GetPerformanceTime %!STATUS!", Status);
                    WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
                }
                else
                {
                    WaitTimeHundredNanoseconds = pDevice->m_Interval -
                        ((CurrentTimeMs - pDevice->m_StartTime) % pDevice->m_Interval);
                    WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(WaitTimeHundredNanoseconds);
                }
            }
            WdfTimerStart(pDevice->m_Timer, WaitTimeHundredNanoseconds);
        }
    }

    SENSOR_FunctionExit(Status);
}
Пример #4
0
// This routine is called by worker thread to read a single sample, compare threshold
// and push it back to CLX. It simulates hardware thresholding by only generating data
// when the change of data is greater than threshold.
NTSTATUS
PedometerDevice::GetData(
)
{
    PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);
    BOOLEAN DataReady = FALSE;
    NTSTATUS Status = STATUS_SUCCESS;
    ULONG CachedStepCountLimit = 0;
    ULONG LastStepCountLimit = 0;
    PedometerSample Sample = {};

    SENSOR_FunctionEnter();

    if (nullptr == pSimulator)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
        goto Exit;
    }

    Status = pSimulator->GetSample(&Sample);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! GetSample failed %!STATUS!", Status);
        goto Exit;
    }

    if (FALSE != m_FirstSample)
    {
        Status = GetPerformanceTime(&m_StartTime);
        if (!NT_SUCCESS(Status))
        {
            m_StartTime = 0;
            TraceError("PED %!FUNC! GetPerformanceTime failed %!STATUS!", Status);
        }

        m_SampleCount = 0;

        DataReady = TRUE;
    }
    else
    {
        if (0 == m_CachedThreshold || FALSE != Sample.IsFirstAfterReset)
        {
            // Streaming mode
            DataReady = TRUE;
        }
        else
        {
            if (FAILED(ULongAdd(Sample.UnknownStepCount, Sample.WalkingStepCount, &CachedStepCountLimit)) ||
                FAILED(ULongAdd(Sample.RunningStepCount, CachedStepCountLimit, &CachedStepCountLimit)))
            {
                // If an overflow happened, we assume we reached the threshold
                // in other words, there is no threshold value that can be larger
                // than an overflowed value.
                DataReady = TRUE;
            }
            else if (FAILED(ULongAdd(m_LastSample.UnknownStepCount, m_LastSample.WalkingStepCount, &LastStepCountLimit)) ||
                     FAILED(ULongAdd(m_LastSample.RunningStepCount, LastStepCountLimit, &LastStepCountLimit)))
            {
                // If an overflow happened, we assume we reached the threshold
                // in other words, there is no threshold value that can be larger
                // than an overflowed value.
                DataReady = TRUE;
            }
            else if ((LastStepCountLimit < m_CachedThreshold && CachedStepCountLimit >= m_CachedThreshold) ||
                     (FALSE != Sample.IsFirstAfterReset))
            {
                // Compare the change of data to threshold, and only push the data back to 
                // clx if the change exceeds threshold or if this is the first sample after reset. This is usually done in HW.
                DataReady = TRUE;
            }
        }
    }

    if (FALSE != DataReady)
    {
        // update last sample
        m_LastSample = Sample;

        // push to clx
        InitPropVariantFromBoolean(m_LastSample.IsFirstAfterReset, &(m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Value));
        InitPropVariantFromUInt32(PedometerStepType_Unknown, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Value));
        InitPropVariantFromInt64(m_LastSample.UnknownStepDurationMs, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Value));
        InitPropVariantFromUInt32(m_LastSample.UnknownStepCount, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Value));
        InitPropVariantFromUInt32(PedometerStepType_Walking, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Value));
        InitPropVariantFromInt64(m_LastSample.WalkingStepDurationMs, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Value));
        InitPropVariantFromUInt32(m_LastSample.WalkingStepCount, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Value));
        InitPropVariantFromUInt32(PedometerStepType_Running, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Value));
        InitPropVariantFromInt64(m_LastSample.RunningStepDurationMs, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Value));
        InitPropVariantFromUInt32(m_LastSample.RunningStepCount, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Value));

        // reset IsFirstAfterReset
        m_LastSample.IsFirstAfterReset = FALSE;

        InitPropVariantFromFileTime(&m_LastSample.Timestamp, &(m_pData->List[PEDOMETER_DATA_TIMESTAMP].Value));

        SensorsCxSensorDataReady(m_SensorInstance, m_pData);
        m_FirstSample = FALSE;
    }
    else
    {
        Status = STATUS_DATA_NOT_ACCEPTED;
        TraceInformation("PED %!FUNC! Data did NOT meet the threshold");
    }

    SENSOR_FunctionExit(Status);

Exit:
    return Status;
}
Пример #5
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
PedometerDevice::OnTimerExpire(
    _In_ WDFTIMER Timer // WDF timer object
    )
{
    PPedometerDevice pDevice = nullptr;
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    pDevice = GetPedometerContextFromSensorInstance(WdfTimerGetParentObject(Timer));
    if (nullptr == pDevice)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("PED %!FUNC! GetPedometerContextFromSensorInstance failed %!STATUS!", Status);
        goto Exit;
    }

    // Get data and push to clx
    WdfWaitLockAcquire(pDevice->m_Lock, NULL);
    Status = pDevice->GetData();
    if (!NT_SUCCESS(Status) && Status != STATUS_DATA_NOT_ACCEPTED)
    {
        TraceError("PED %!FUNC! GetData Failed %!STATUS!", Status);
    }
    WdfWaitLockRelease(pDevice->m_Lock);

    // Schedule next wake up time
    if (FALSE != pDevice->m_PoweredOn &&
        FALSE != pDevice->m_Started)
    {
        LONGLONG WaitTimeHundredNanoseconds = 0;  // in unit of 100ns

        if (0 == pDevice->m_StartTime)
        {
            // in case we fail to get sensor start time, use static wait time
            WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
        }
        else
        {
            ULONG CurrentTimeMs = 0;

            // dynamically calculate wait time to avoid jitter
            Status = GetPerformanceTime (&CurrentTimeMs);
            if (!NT_SUCCESS(Status))
            {
                TraceError("PED %!FUNC! GetPerformanceTime %!STATUS!", Status);
                WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(pDevice->m_Interval);
            }
            else
            {
                pDevice->m_SampleCount++;
                if (CurrentTimeMs > (pDevice->m_StartTime + (pDevice->m_Interval * (pDevice->m_SampleCount + 1))))
                {
                    // If we skipped two or more beats, reschedule the timer with a zero due time to catch up on missing samples
                    WaitTimeHundredNanoseconds = 0;
                }
                else
                {
                    WaitTimeHundredNanoseconds = (pDevice->m_StartTime +
                        (pDevice->m_Interval * (pDevice->m_SampleCount + 1))) - CurrentTimeMs;
                }
                WaitTimeHundredNanoseconds = WDF_REL_TIMEOUT_IN_MS(WaitTimeHundredNanoseconds);
            }
        }
        WdfTimerStart(pDevice->m_Timer, WaitTimeHundredNanoseconds);
    }

Exit:

    SENSOR_FunctionExit(Status);
}