Ejemplo n.º 1
0
// Called by Sensor CLX to begin continously sampling the sensor.
NTSTATUS
CustomSensorDevice::OnStart(
    _In_ SENSOROBJECT SensorInstance // sensor device object
    )
{
    PHardwareSimulator pSimulator = nullptr;
    PCustomSensorDevice pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance);
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    if (nullptr == pDevice)
    {
        Status = STATUS_INVALID_PARAMETER;
        TraceError("PED %!FUNC! Sensor(%08X) parameter is invalid. Failed %!STATUS!", (INT)SensorInstance, Status);
    }

    if (NT_SUCCESS(Status))
    {
        // Get the simulator context
        pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
        if (nullptr == pSimulator)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
        }
    }

    if (NT_SUCCESS(Status))
    {
        // Start the simulator
        pSimulator->Start();

        pDevice->m_FirstSample = TRUE;

        // Start polling
        pDevice->m_Started = TRUE;

        InitPropVariantFromUInt32(SensorState_Active,
            &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));


        // Start the sample polling timer.
        // Note1: the WDF timer is only as precise as the system resolution allows it to be.
        // In the case of the CO2 sensor, the reporting interval is 200 milliseconds. The default 
        // system resolution (15.6 milliseconds) is therefore fine enough to guarantee an accurate sample 
        // reporting interval. Some sensors using a lower reporting interval may want to reduce the system 
        // time resolution by calling into timeBeginPeriod() before starting the polling timer.
        //
        // Important consideration: calling into timeBeginPeriod() should be used with care as it has 
        // an adverse on the system performance and power consumption.
        //
        // Note2: The polling timer is configured to allow for the first sample to be reported immediately.
        // Some hardware may want to delay the first sample report a little to account for hardware start time.
        WdfTimerStart(pDevice->m_Timer, 0);
    }

    SENSOR_FunctionExit(Status);
    return Status;
}
Ejemplo n.º 2
0
// Called by Sensor CLX to stop continously sampling the sensor.
NTSTATUS ActivityDevice::OnStop(_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
    {
        // Stop sensing
        pDevice->m_Started = FALSE;
        WdfTimerStop(pDevice->m_Timer, TRUE);
        InitPropVariantFromUInt32(SensorState_Idle, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
    
        // Stop simulation
        if (NULL != pDevice->m_SimulatorInstance)
        {
            PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
            if (nullptr != pSimulator)
            {
                pSimulator->Stop();
            }
        }
    }
    
    SENSOR_FunctionExit(status);
    return status;
}
Ejemplo n.º 3
0
// Called by Sensor CLX to begin keeping history
NTSTATUS
PedometerDevice::OnStartHistory(
    _In_ SENSOROBJECT SensorInstance // Sensor device object
    )
{
    PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
    NTSTATUS Status = STATUS_SUCCESS;
    PHardwareSimulator pSimulator = nullptr;

    SENSOR_FunctionEnter();

    if (nullptr == pDevice)
    {
        Status = STATUS_INVALID_PARAMETER;
        TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
        goto Exit;
    }

    if (FALSE == pDevice->m_HistorySupported)
    {
        Status = STATUS_NOT_SUPPORTED;
        TraceError("PED %!FUNC! History is not supported by the HW");
        goto Exit;
    }

    if (FALSE == pDevice->m_PoweredOn)
    {
        Status = STATUS_DEVICE_NOT_READY;
        TraceError("PED %!FUNC! Sensor is not powered on! %!STATUS!", Status);
        goto Exit;
    }

    pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);

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

    // Start the pedometer history
    Status = pSimulator->StartHistory();
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! Start History failed %!STATUS!", Status);
    }

Exit:
    SENSOR_FunctionExit(Status);
    return Status;
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
// Called by Sensor CLX to begin continuously sampling the sensor.
NTSTATUS
PedometerDevice::OnStart(
    _In_ SENSOROBJECT SensorInstance // Sensor device object
    )
{
    PHardwareSimulator pSimulator = nullptr;
    PPedometerDevice pDevice = GetPedometerContextFromSensorInstance(SensorInstance);
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    if (nullptr == pDevice)
    {
        Status = STATUS_INVALID_PARAMETER;
        TraceError("PED %!FUNC! Sensor(0x%p) parameter is invalid. Failed %!STATUS!", SensorInstance, Status);
        goto Exit;
    }

    // Get the simulator context
    pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
    if (nullptr == pSimulator)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
    }

    if (NT_SUCCESS(Status))
    {
        // Start the simulator
        pSimulator->Start();

        pDevice->m_FirstSample = TRUE;

        // Start polling

        pDevice->m_Started = TRUE;

        InitPropVariantFromUInt32(SensorState_Active,
            &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));

        // Start the sample polling timer.
        //
        // Note: The polling timer is configured to allow for the first sample to be reported immediately.
        // Some hardware may want to delay the first sample report a little to account for hardware start time.
        WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(Pedometer_Default_MinDataInterval_Ms));
    }
Exit:
    SENSOR_FunctionExit(Status);
    return Status;
}
Ejemplo n.º 6
0
// Called by Sensor CLX to stop continously sampling the sensor.
NTSTATUS
CustomSensorDevice::OnStop(
    _In_ SENSOROBJECT SensorInstance // sensor device object
    )
{
    PHardwareSimulator pSimulator = nullptr;
    PCustomSensorDevice pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance);
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();
    
    if (nullptr == pDevice)
    {
        Status = STATUS_INVALID_PARAMETER;
        TraceError("CSTM %!FUNC! Sensor(%08X) parameter is invalid. Failed %!STATUS!", (INT) SensorInstance, Status);
    }

    if (NT_SUCCESS(Status))
    {
        // Stop polling

        pDevice->m_Started = FALSE;

        // Waiting for the callback to complete, then stopping the timer
        WdfTimerStop(pDevice->m_Timer, TRUE);

        InitPropVariantFromUInt32(SensorState_Idle,
            &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));

        // Stop the simulator
        pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
        if (nullptr == pSimulator)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            TraceError("CSTM %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
            goto Exit;
        }

        pSimulator->Stop();
    }

Exit:
    SENSOR_FunctionExit(Status);

    return Status;
}
Ejemplo n.º 7
0
// Called by Sensor CLX to begin continously sampling the sensor.
NTSTATUS ActivityDevice::OnStart(_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
    {
        if (FALSE == pDevice->m_PoweredOn)
        {
            status = STATUS_DEVICE_NOT_READY;
            TraceError("ACT %!FUNC! Sensor is not powered on! %!STATUS!", status);
        }
        else
        {
            // Start simulation
            if (NULL != pDevice->m_SimulatorInstance)
            {
                PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
                if (nullptr != pSimulator)
                {
                    pSimulator->Start();
                }
            }

            // Start sensing
            pDevice->m_FirstSample = TRUE;
            pDevice->m_Started = TRUE;
            InitPropVariantFromUInt32(SensorState_Active, &(pDevice->m_pProperties->List[SENSOR_PROPERTY_STATE].Value));
            WdfTimerStart(pDevice->m_Timer, WDF_REL_TIMEOUT_IN_MS(Act_Default_MinDataInterval_Ms));
        }
    }

    SENSOR_FunctionExit(status);
    return status;
}
Ejemplo n.º 8
0
// Resets the pedometer to its initial values.
VOID
PedometerDevice::ResetPedometer()
{
    NTSTATUS Status = STATUS_SUCCESS;
    PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);

    SENSOR_FunctionEnter();

    if (nullptr == pSimulator)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("PED %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
    }
    else
    {
        // Reset the pedometer
        pSimulator->Reset();
    }

    SENSOR_FunctionExit(Status);
}
Ejemplo n.º 9
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;
}
// This static routine performs simulator initialization. The routine creates a 
// timer object that periodically updates the m_Index location 
NTSTATUS
HardwareSimulator::Initialize(
    _In_ WDFDEVICE Device,               // WDF device representing the sensor
    _Out_ WDFOBJECT *SimulatorInstance)   // Instance of the WDF object for the simulator
{
    PHardwareSimulator pSimulator = nullptr;
    NTSTATUS Status = STATUS_SUCCESS;
    WDF_OBJECT_ATTRIBUTES HardwareSimulatorAttributes = {};

    SENSOR_FunctionEnter();

    // Create WDFOBJECT for the hardware simulator
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&HardwareSimulatorAttributes, HardwareSimulator);
    HardwareSimulatorAttributes.ParentObject = Device;

    Status = WdfObjectCreate(&HardwareSimulatorAttributes, SimulatorInstance);
    if (!NT_SUCCESS(Status))
    {
        TraceError("CSTM %!FUNC! WdfObjectCreate failed %!STATUS!", Status);
        goto Exit;
    }

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

    pSimulator->InitializeInternal(*SimulatorInstance);

Exit:

    SENSOR_FunctionExit(Status);

    return Status;
}
Ejemplo n.º 11
0
// This routine is called by the framework when the PnP manager is revoking
// ownership of our resources. This may be in response to either
// IRP_MN_STOP_DEVICE or IRP_MN_REMOVE_DEVICE. This routine is responsible for
// performing cleanup of resources allocated in PrepareHardware callback.
// This callback is invoked before passing  the request down to the lower driver.
// This routine will also be invoked by the framework if the prepare hardware
// callback returns a failure.
NTSTATUS
CustomSensorDevice::OnReleaseHardware(
    _In_ WDFDEVICE Device,                       // Supplies a handle to the framework device object
    _In_ WDFCMRESLIST /*ResourcesTranslated*/)   // Supplies a handle to a collection of framework
// resource objects. This collection identifies the translated
// (system-physical) hardware resources that have been assigned to the
// device. The resources appear from the CPU's point of view.
{
    PHardwareSimulator pSimulator = nullptr;
    PCustomSensorDevice pDevice = nullptr;
    SENSOROBJECT SensorInstance = nullptr;
    ULONG SensorInstanceCount = 1;    // only expect 1 sensor instance
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    // Get sensor instance
    Status = SensorsCxDeviceGetSensorList(Device, &SensorInstance, &SensorInstanceCount);
    if (!NT_SUCCESS(Status) ||
            0 == SensorInstanceCount ||
            NULL == SensorInstance)
    {
        Status = STATUS_INVALID_PARAMETER;
        TraceError("CSTM %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status);
        goto Exit;
    }

    pDevice = GetCustomSensorContextFromSensorInstance(SensorInstance);
    if (nullptr == pDevice)
    {
        Status = STATUS_INVALID_PARAMETER;
        TraceError("CSTM %!FUNC! GetCustomSensorContextFromSensorInstance failed %!STATUS!", Status);
        goto Exit;
    }

    // Delete lock
    if (pDevice->m_Lock)
    {
        WdfObjectDelete(pDevice->m_Lock);
        pDevice->m_Lock = NULL;
    }

    // Cleanup the CO2 simulator
    pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
    if (nullptr == pSimulator)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        TraceError("CSTM %!FUNC! GetHardwareSimulatorContextFromInstance failed %!STATUS!", Status);
        goto Exit;
    }

    pSimulator->Cleanup();

    // Delete hardware simulator instance
    if (NULL != pDevice->m_SimulatorInstance)
    {
        WdfObjectDelete(pDevice->m_SimulatorInstance);
        pDevice->m_SimulatorInstance = NULL;
    }

    // Delete sensor instance
    if (NULL != pDevice->m_SensorInstance)
    {
        WdfObjectDelete(pDevice->m_SensorInstance);
    }

Exit:
    SENSOR_FunctionExit(Status);
    return Status;
}
Ejemplo n.º 12
0
// This routine is called by the framework when the PnP manager is revoking
// ownership of our resources. This may be in response to either
// IRP_MN_STOP_DEVICE or IRP_MN_REMOVE_DEVICE. This routine is responsible for
// performing cleanup of resources allocated in PrepareHardware callback.
// This callback is invoked before passing  the request down to the lower driver.
// This routine will also be invoked by the framework if the prepare hardware
// callback returns a failure.
NTSTATUS ActivityDevice::OnReleaseHardware(
    _In_ WDFDEVICE device,                      // Supplies a handle to the framework device object
    _In_ WDFCMRESLIST /*ResourcesTranslated*/)  // Supplies a handle to a collection of framework
                                                // resource objects. This collection identifies the translated
                                                // (system-physical) hardware resources that have been assigned to the
                                                // device. The resources appear from the CPU's point of view.
{
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    // Get sensor instance
    SENSOROBJECT sensorInstance = NULL;
    ULONG sensorInstanceCount = 1;    // only expect 1 sensor instance

    status = SensorsCxDeviceGetSensorList(device, &sensorInstance, &sensorInstanceCount);
    if (!NT_SUCCESS(status) || sensorInstanceCount == 0 || sensorInstance == NULL)
    {
        status = STATUS_INVALID_PARAMETER;
        TraceError("ACT %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", status);
    }
    else
    {
        PActivityDevice pDevice = GetActivityContextFromSensorInstance(sensorInstance);
        if (nullptr == pDevice)
        {
            status = STATUS_INVALID_PARAMETER;
            TraceError("ACT %!FUNC! GetActivityContextFromSensorInstance failed %!STATUS!", status);
        }
        else
        {
            // Cleanup activity simulator
            if (NULL != pDevice->m_SimulatorInstance)
            {
                PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(pDevice->m_SimulatorInstance);
                if (nullptr != pSimulator)
                {
                    pSimulator->Deinitialize();
                }
                // Continue tearing down
                WdfObjectDelete(pDevice->m_SimulatorInstance);
                pDevice->m_SimulatorInstance = NULL;
            }

            // Close handle to history retrieval thread
            if (NULL != pDevice->m_hThread)
            {
                SetEvent(pDevice->m_ExitEvent);

                DWORD result = WaitForSingleObjectEx(pDevice->m_hThread, Act_TimeoutForHistoryThread_Ms, FALSE);
                if (WAIT_OBJECT_0 != result)
                {
                    // continue tearing down
                    status = NTSTATUS_FROM_WIN32(result);
                    TraceError("ACT %!FUNC! WaitForSingleObjectEx failed %!STATUS!", status);
                }

                CloseHandle(pDevice->m_hThread);
                pDevice->m_hThread = NULL;
            }

            // Close handle to exit event
            if (NULL != pDevice->m_ExitEvent)
            {
                CloseHandle(pDevice->m_ExitEvent);
                pDevice->m_ExitEvent = NULL;
            }

            // Delete history lock
            if (NULL != pDevice->m_HistoryLock)
            {
                WdfObjectDelete(pDevice->m_HistoryLock);
                pDevice->m_HistoryLock = NULL;
            }

            // Delete lock
            if (NULL != pDevice->m_Lock)
            {
                WdfObjectDelete(pDevice->m_Lock);
                pDevice->m_Lock = NULL;
            }

            // Delete sensor instance.
            if (NULL != pDevice->m_SensorInstance)
            {
                // Memory created by WdfMemoryCreate with m_SensorInstance as parent object will be
                // destroyed automatically when m_SensorInstance is deleted. pDevice will be no longer
                // accessible at beyond this point.
                WdfObjectDelete(pDevice->m_SensorInstance);
                pDevice = nullptr;
            }
        }
    }
 
    SENSOR_FunctionExit(status);
    return status;
}
Ejemplo n.º 13
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 ActivityDevice::GetData()
{
    BOOLEAN dataReady = FALSE;
    NTSTATUS status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    if (NULL != m_SimulatorInstance)
    {
        // Use simulator to get m_pFiltered Sample
        PHardwareSimulator pSimulator = GetHardwareSimulatorContextFromInstance(m_SimulatorInstance);
        if (nullptr != pSimulator)
        {
            status = pSimulator->GetSample(m_pFilteredSample);
        }
        else
        {
            status = STATUS_INVALID_PARAMETER;
        }
    }
    
    if (NT_SUCCESS(status))
    {
        status = CollectionsListSortSubscribedActivitiesByConfidence(m_pThresholds, m_pFilteredSample);
        if (!NT_SUCCESS(status))
        {
            TraceError("ACT %!FUNC! CollectionsListSortSubscribedActivitiesByConfidence failed! %!STATUS!", status);
        }
        else
        {
            // new sample?
            if (FALSE != m_FirstSample)
            {
                dataReady = TRUE;
            }
            else
            {
                dataReady = EvaluateActivityThresholds(m_pFilteredSample, m_pLastSample, m_pThresholds);
            }
        }
    }

    if (FALSE != dataReady)
    {
        // update last sample
        FILETIME TimeStamp = {};
        memcpy_s(m_pLastSample, m_pFilteredSample->AllocatedSizeInBytes, m_pFilteredSample, m_pFilteredSample->AllocatedSizeInBytes);
        GetSystemTimePreciseAsFileTime(&TimeStamp);
        InitPropVariantFromFileTime(&TimeStamp, &(m_pLastSample->List[ACTIVITY_DATA_TIMESTAMP].Value));

        // push to clx
        SensorsCxSensorDataReady(m_SensorInstance, m_pLastSample);
        m_FirstSample = FALSE;
    }
    else
    {
        status = STATUS_DATA_NOT_ACCEPTED;
        TraceInformation("ACT %!FUNC! Data did NOT meet the threshold");
    }

    SENSOR_FunctionExit(status);
    return status;
}
Ejemplo n.º 14
0
// This routine is called by the framework when the PnP manager is revoking
// ownership of our resources. This may be in response to either
// IRP_MN_STOP_DEVICE or IRP_MN_REMOVE_DEVICE. This routine is responsible for
// performing cleanup of resources allocated in PrepareHardware callback.
// This callback is invoked before passing  the request down to the lower driver.
// This routine will also be invoked by the framework if the prepare hardware
// callback returns a failure.
//
// Argument:
//      Device: IN: Supplies a handle to the framework device object
//      ResourcesTranslated: IN: Supplies a handle to a collection of framework
//          resource objects. This collection identifies the translated
//          (system-physical) hardware resources that have been assigned to the
//          device. The resources appear from the CPU's point of view.
//
// Return Value:
//      NTSTATUS code
//------------------------------------------------------------------------------
NTSTATUS
PedometerDevice::OnReleaseHardware(
    _In_ WDFDEVICE Device,                      // Supplies a handle to the framework device object
    _In_ WDFCMRESLIST /*ResourcesTranslated*/)  // Supplies a handle to a collection of framework
                                                // resource objects. This collection identifies the translated
                                                // (system-physical) hardware resources that have been assigned to the
                                                // device. The resources appear from the CPU's point of view.
{
    PHardwareSimulator pSimulator = nullptr;
    PPedometerDevice pDevice = nullptr;
    SENSOROBJECT SensorInstance = nullptr;
    ULONG SensorInstanceCount = 1;    // only expect 1 sensor instance
    NTSTATUS Status = STATUS_SUCCESS;

    SENSOR_FunctionEnter();

    // Get sensor instance
    Status = SensorsCxDeviceGetSensorList(Device, &SensorInstance, &SensorInstanceCount);
    if (!NT_SUCCESS(Status) ||
        0 == SensorInstanceCount ||
        NULL == SensorInstance)
    {
        Status = STATUS_INVALID_PARAMETER;
        TraceError("PED %!FUNC! SensorsCxDeviceGetSensorList failed %!STATUS!", Status);
        goto Exit;
    }

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

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

    // Close handle to history retrieval thread
    if (NULL != pDevice->m_hThread)
    {
        pSimulator->SignalReadCancellation();

        DWORD result = WaitForSingleObjectEx(pDevice->m_hThread, Pedometer_TimeoutForHistoryThread_Ms, FALSE);
        if (WAIT_OBJECT_0 != result)
        {
            TraceError("PED %!FUNC! WaitForSingleObjectEx failed with error %d", result);
            goto Exit;
        }

        CloseHandle(pDevice->m_hThread);
        pDevice->m_hThread = NULL;
    }


    // Delete lock
    if (NULL != pDevice->m_Lock)
    {
        WdfObjectDelete(pDevice->m_Lock);
        pDevice->m_Lock = NULL;
    }    
    
    // Cleanup the pedometer simulator
    pSimulator->Cleanup();

    // Delete hardware simulator instance
    if (NULL != pDevice->m_SimulatorInstance)
    {
        WdfObjectDelete(pDevice->m_SimulatorInstance);
        pDevice->m_SimulatorInstance = NULL;
    }

    // Delete sensor instance
    if (NULL != pDevice->m_SensorInstance)
    {
        WdfObjectDelete(pDevice->m_SensorInstance);
    }
  
Exit:
    SENSOR_FunctionExit(Status);
    return Status;
}
Ejemplo n.º 15
0
// This routine initializes the sensor to its default properties
NTSTATUS
PedometerDevice::Initialize(
    _In_ WDFDEVICE Device, // WDFDEVICE object
    _In_ SENSOROBJECT SensorInstance // SENSOROBJECT for each sensor instance
    )
{
    ULONG Size = 0;
    WDF_OBJECT_ATTRIBUTES MemoryAttributes;
    WDFMEMORY MemoryHandle = NULL;
    FILETIME Time = {};
    WDF_OBJECT_ATTRIBUTES TimerAttributes;
    WDF_TIMER_CONFIG TimerConfig;
    NTSTATUS Status = STATUS_SUCCESS;
    PHardwareSimulator pSimulator = nullptr;
    ULONG HistorySizeInRecords = 0;

    SENSOR_FunctionEnter();

    // Store device and instance
    m_FxDevice = Device;
    m_SensorInstance = SensorInstance;
    m_Started = FALSE;
    m_HistoryRetrievalStarted = FALSE;

    // Initialize the pedometer simulator
    Status = HardwareSimulator::Initialize(Device, &m_SimulatorInstance);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! HardwareSimulator::Initialize failed %!STATUS!", Status);
        goto Exit;
    }

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

    // Create Lock
    Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &m_Lock);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! WdfWaitLockCreate failed %!STATUS!", Status);
        goto Exit;
    }

    // Create timer object for polling sensor samples
    WDF_TIMER_CONFIG_INIT(&TimerConfig, PedometerDevice::OnTimerExpire);
    WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes);
    TimerAttributes.ParentObject = SensorInstance;
    TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive;

    Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &m_Timer);
    if (!NT_SUCCESS(Status))
    {
        TraceError("PED %!FUNC! WdfTimerCreate failed %!STATUS!", Status);
        goto Exit;
    }

    // Supported Data-Fields
    Size = SENSOR_PROPERTY_LIST_SIZE(PEDOMETER_DATAFIELD_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pSupportedDataFields));
    if (!NT_SUCCESS(Status) || nullptr == m_pSupportedDataFields)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_PROPERTY_LIST_INIT(m_pSupportedDataFields, Size);
    m_pSupportedDataFields->Count = PEDOMETER_DATAFIELD_COUNT;

    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_TIMESTAMP] = PKEY_SensorData_Timestamp;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_FIRST_AFTER_RESET] = PKEY_SensorData_PedometerReset;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_TYPE] = PKEY_SensorData_PedometerStepType;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_COUNT] = PKEY_SensorData_PedometerStepCount;
    m_pSupportedDataFields->List[PEDOMETER_DATAFIELD_STEP_DURATION] = PKEY_SensorData_PedometerStepDuration_Ms;

    // Data
    Size = SENSOR_COLLECTION_LIST_SIZE(PEDOMETER_DATA_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pData));
    if (!NT_SUCCESS(Status) || nullptr == m_pData)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pData, Size);
    m_pData->Count = PEDOMETER_DATA_COUNT;

    m_pData->List[PEDOMETER_DATA_TIMESTAMP].Key = PKEY_SensorData_Timestamp;
    GetSystemTimePreciseAsFileTime(&Time);
    InitPropVariantFromFileTime(&Time, &(m_pData->List[PEDOMETER_DATA_TIMESTAMP].Value));

    m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Key = PKEY_SensorData_PedometerReset;
    InitPropVariantFromBoolean(FALSE, &(m_pData->List[PEDOMETER_DATA_FIRST_AFTER_RESET].Value));

    m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType;
    InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Unknown), &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_TYPE].Value));

    m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(600, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_COUNT].Value));

    m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms;
    InitPropVariantFromInt64(123, &(m_pData->List[PEDOMETER_DATA_UNKNOWN_STEP_DURATION].Value));

    m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType;
    InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Walking), &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_TYPE].Value));

    m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(700, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_COUNT].Value));

    m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms;
    InitPropVariantFromInt64(456, &(m_pData->List[PEDOMETER_DATA_WALKING_STEP_DURATION].Value));

    m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Key = PKEY_SensorData_PedometerStepType;
    InitPropVariantFromUInt32(static_cast<ULONG>(PedometerStepType_Running), &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_TYPE].Value));

    m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(800, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_COUNT].Value));

    m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Key = PKEY_SensorData_PedometerStepDuration_Ms;
    InitPropVariantFromInt64(789, &(m_pData->List[PEDOMETER_DATA_RUNNING_STEP_DURATION].Value));

    m_LastSample.Timestamp = Time;
    m_LastSample.UnknownStepCount = 0;
    m_LastSample.UnknownStepDurationMs = 0;
    m_LastSample.WalkingStepCount = 0;
    m_LastSample.WalkingStepDurationMs = 0;
    m_LastSample.RunningStepCount = 0;
    m_LastSample.RunningStepDurationMs = 0;
    m_LastSample.IsFirstAfterReset = FALSE;

    // Get the History Size to populate 'PKEY_SensorHistory_MaxSize_Bytes'
    // Typically the size needed to store a history record on the hardware is 
    // smaller than the size needed to represent a history record as a 
    // SENSOR_COLLECTION_LIST (collection of SENSOR_VALUE_PAIRs)
    // To be able to accurately represent the size of the history on the 
    // hardware (simulator in this case), get the number of records that the HW  
    // can store and multiply it with the marshalled size of 
    // SENSOR_COLLECTION_LIST needed to represent a single record.

    HistorySizeInRecords = pSimulator->GetHistorySizeInRecords();
    m_HistorySupported = (HistorySizeInRecords > 0) ? TRUE : FALSE;

    // Pedometer History format is exactly same as it's data sample.
    // so, we can simply reuse the 'm_pData' to compute the marshalled size
    // History Retrieval is not WOW64 compatible and hence will not involve 
    // serializing the collections list. Should Use 
    // CollectionsListGetMarshalledSizeWithoutSerialization  instead of 
    // CollectionsListGetMarshalledSize when dealing with History Collection list.
    m_HistoryMarshalledRecordSize = CollectionsListGetMarshalledSizeWithoutSerialization(m_pData);

    // Sensor Enumeration Properties
    Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_ENUMERATION_PROPERTIES_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes,
        PagedPool,
        SENSOR_POOL_TAG_PEDOMETER,
        Size,
        &MemoryHandle,
        reinterpret_cast<PVOID*>(&m_pEnumerationProperties));
    if (!NT_SUCCESS(Status) || nullptr == m_pEnumerationProperties)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pEnumerationProperties, Size);
    m_pEnumerationProperties->Count = SENSOR_ENUMERATION_PROPERTIES_COUNT;

    m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Key = DEVPKEY_Sensor_Type;
    InitPropVariantFromCLSID(GUID_SensorType_Pedometer,
        &(m_pEnumerationProperties->List[SENSOR_TYPE_GUID].Value));

    m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Key = DEVPKEY_Sensor_Manufacturer;
    InitPropVariantFromString(L"Microsoft",
        &(m_pEnumerationProperties->List[SENSOR_MANUFACTURER].Value));

    m_pEnumerationProperties->List[SENSOR_MODEL].Key = DEVPKEY_Sensor_Model;
    InitPropVariantFromString(L"PEDOMETER",
        &(m_pEnumerationProperties->List[SENSOR_MODEL].Value));

    m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Key = DEVPKEY_Sensor_PersistentUniqueId;
    InitPropVariantFromCLSID(GUID_PedometerDevice_UniqueID,
        &(m_pEnumerationProperties->List[SENSOR_PERSISTENT_UNIQUEID].Value));

    m_pEnumerationProperties->List[SENSOR_CATEGORY].Key = DEVPKEY_Sensor_Category;
    InitPropVariantFromCLSID(GUID_SensorCategory_Motion,
        &(m_pEnumerationProperties->List[SENSOR_CATEGORY].Value));

    m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Key = DEVPKEY_Sensor_IsPrimary;
    InitPropVariantFromBoolean(FALSE,
        &(m_pEnumerationProperties->List[SENSOR_ISPRIMARY].Value)); // This value should be set to TRUE if multiple pedometers
                                                                    // exist on the system and this sensor is the primary sensor

    m_pEnumerationProperties->List[SENSOR_POWER].Key = PKEY_Sensor_Power_Milliwatts;
    InitPropVariantFromFloat(Pedometer_Default_Power_Milliwatts,
        &(m_pEnumerationProperties->List[SENSOR_POWER].Value));

    m_pEnumerationProperties->List[SENSOR_MAX_HISTORYSIZE].Key = PKEY_SensorHistory_MaxSize_Bytes;
    InitPropVariantFromUInt32(((FALSE != m_HistorySupported) ?
        (SENSOR_COLLECTION_LIST_HEADER_SIZE + ((m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) * HistorySizeInRecords)) :
        0),
        &(m_pEnumerationProperties->List[SENSOR_MAX_HISTORYSIZE].Value));

    m_pEnumerationProperties->List[SENSOR_SUPPORTED_STEPTYPES].Key = PKEY_SensorData_SupportedStepTypes;
    InitPropVariantFromUInt32(PedometerStepType_Unknown | PedometerStepType_Walking | PedometerStepType_Running,
        &(m_pEnumerationProperties->List[SENSOR_SUPPORTED_STEPTYPES].Value));

    // Sensor Properties
    m_Interval = Pedometer_Default_MinDataInterval_Ms;

    Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_COMMON_PROPERTIES_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pProperties));
    if (!NT_SUCCESS(Status) || nullptr == m_pProperties)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pProperties, Size);
    m_pProperties->Count = SENSOR_COMMON_PROPERTIES_COUNT;

    m_pProperties->List[SENSOR_PROPERTY_STATE].Key = PKEY_Sensor_State;
    InitPropVariantFromUInt32(SensorState_Initializing, 
                              &(m_pProperties->List[SENSOR_PROPERTY_STATE].Value));

    m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Key = PKEY_Sensor_MinimumDataInterval_Ms;
    InitPropVariantFromUInt32(Pedometer_Default_MinDataInterval_Ms, 
                              &(m_pProperties->List[SENSOR_PROPERTY_MIN_INTERVAL].Value));

    m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Key = PKEY_Sensor_MaximumDataFieldSize_Bytes;
    InitPropVariantFromUInt32(CollectionsListGetMarshalledSize(m_pData), 
                              &(m_pProperties->List[SENSOR_PROPERTY_MAX_DATAFIELDSIZE].Value));

    m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Key = PKEY_Sensor_Type;
    InitPropVariantFromCLSID(GUID_SensorType_Pedometer, 
                                 &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_TYPE].Value));

    m_pProperties->List[SENSOR_PROPERTY_SENSOR_POWER].Key = PKEY_Sensor_Power_Milliwatts;
    InitPropVariantFromFloat(Pedometer_Default_Power_Milliwatts,
                                &(m_pProperties->List[SENSOR_PROPERTY_SENSOR_POWER].Value));

    m_pProperties->List[SENSOR_PROPERTY_MAX_HISTORYSIZE].Key = PKEY_SensorHistory_MaxSize_Bytes;
    InitPropVariantFromUInt32(((FALSE != m_HistorySupported) ?
                                (SENSOR_COLLECTION_LIST_HEADER_SIZE + ((m_HistoryMarshalledRecordSize - SENSOR_COLLECTION_LIST_HEADER_SIZE) * HistorySizeInRecords)) :
                                0),
                                &(m_pProperties->List[SENSOR_PROPERTY_MAX_HISTORYSIZE].Value));

    m_pProperties->List[SENSOR_PROPERTY_HISTORY_INTERVAL].Key = PKEY_SensorHistory_Interval_Ms;
    InitPropVariantFromUInt32(pSimulator->GetHistoryIntervalInMs(),
                                &(m_pProperties->List[SENSOR_PROPERTY_HISTORY_INTERVAL].Value));

    m_pProperties->List[SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE].Key = PKEY_SensorHistory_MaximumRecordSize_Bytes;
    InitPropVariantFromUInt32(m_HistoryMarshalledRecordSize,
        &(m_pProperties->List[SENSOR_PROPERTY_MAX_HISTROYRECORDSIZE].Value));

    m_pProperties->List[SENSOR_PROPERTY_SUPPORTED_STEPTYPES].Key = PKEY_SensorData_SupportedStepTypes;
    InitPropVariantFromUInt32(PedometerStepType_Unknown | PedometerStepType_Walking | PedometerStepType_Running,
        &(m_pProperties->List[SENSOR_PROPERTY_SUPPORTED_STEPTYPES].Value));

    // Data field properties
    Size = SENSOR_COLLECTION_LIST_SIZE(SENSOR_DATA_FIELD_PROPERTY_COUNT);
    
    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes, 
                             PagedPool, 
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pDataFieldProperties));
    if (!NT_SUCCESS(Status) || nullptr == m_pDataFieldProperties)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pDataFieldProperties, Size);
    m_pDataFieldProperties->Count = SENSOR_DATA_FIELD_PROPERTY_COUNT;

    m_pDataFieldProperties->List[SENSOR_RESOLUTION].Key = PKEY_SensorDataField_Resolution;
    InitPropVariantFromInt64(PedometerDevice_StepCount_Resolution,
                             &(m_pDataFieldProperties->List[SENSOR_RESOLUTION].Value));

    m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Key = PKEY_SensorDataField_RangeMinimum;
    InitPropVariantFromUInt32(PedometerDevice_StepCount_Minimum,
                             &(m_pDataFieldProperties->List[SENSOR_MIN_RANGE].Value));

    m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Key = PKEY_SensorDataField_RangeMaximum;
    InitPropVariantFromUInt32(PedometerDevice_StepCount_Maximum,
                             &(m_pDataFieldProperties->List[SENSOR_MAX_RANGE].Value));

    // Set default threshold
    m_FirstSample = TRUE;

    Size = SENSOR_COLLECTION_LIST_SIZE(PEDOMETER_THRESHOLD_COUNT);

    MemoryHandle = NULL;
    WDF_OBJECT_ATTRIBUTES_INIT(&MemoryAttributes);
    MemoryAttributes.ParentObject = SensorInstance;
    Status = WdfMemoryCreate(&MemoryAttributes,
                             PagedPool,
                             SENSOR_POOL_TAG_PEDOMETER,
                             Size,
                             &MemoryHandle,
                             reinterpret_cast<PVOID*>(&m_pThresholds));
    if (!NT_SUCCESS(Status) || nullptr == m_pThresholds)
    {
        TraceError("PED %!FUNC! WdfMemoryCreate failed %!STATUS!", Status);
        goto Exit;
    }

    SENSOR_COLLECTION_LIST_INIT(m_pThresholds, Size);
    m_pThresholds->Count = PEDOMETER_THRESHOLD_COUNT;

    m_pThresholds->List[PEDOMETER_THRESHOLD_STEP_COUNT].Key = PKEY_SensorData_PedometerStepCount;
    InitPropVariantFromUInt32(Pedometer_Default_Threshold_StepCount,
                             &(m_pThresholds->List[PEDOMETER_THRESHOLD_STEP_COUNT].Value));

    m_CachedThreshold = Pedometer_Default_Threshold_StepCount;
Exit:
    SENSOR_FunctionExit(Status);
    return Status;
}
Ejemplo n.º 16
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;
}