hal/windows/WindowsSensor.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "Hal.h"
     7 #include <sensorsapi.h>
     8 #include <sensors.h>
     9 #include <portabledevicetypes.h>
    11 #define MEAN_GRAVITY 9.80665
    12 #define DEFAULT_SENSOR_POLL 100
    14 using namespace mozilla::hal;
    16 namespace mozilla {
    17 namespace hal_impl {
    19 static nsRefPtr<ISensor> sAccelerometer;
    21 class SensorEvent MOZ_FINAL : public ISensorEvents {
    22 public:
    23   SensorEvent() : mCount(0) {
    24   }
    26   // IUnknown interface
    28   STDMETHODIMP_(ULONG) AddRef() {
    29     return InterlockedIncrement(&mCount);
    30   }
    32   STDMETHODIMP_(ULONG) Release() {
    33     ULONG count = InterlockedDecrement(&mCount);
    34     if (!count) {
    35       delete this;
    36       return 0;
    37     }
    38     return count;
    39   }
    41   STDMETHODIMP QueryInterface(REFIID iid, void** ppv) {
    42     if (iid == IID_IUnknown) {
    43       *ppv = static_cast<IUnknown*>(this);
    44     } else if (iid == IID_ISensorEvents) {
    45       *ppv = static_cast<ISensorEvents*>(this);
    46     } else {
    47       return E_NOINTERFACE;
    48     }
    49     AddRef();
    50     return S_OK;
    51   }
    53   // ISensorEvents interface
    55   STDMETHODIMP OnEvent(ISensor *aSensor, REFGUID aId, IPortableDeviceValues *aData) {
    56     return S_OK;
    57   }
    59   STDMETHODIMP OnLeave(REFSENSOR_ID aId) {
    60     return S_OK;
    61   }
    63   STDMETHODIMP OnStateChanged(ISensor *aSensor, SensorState state) {
    64     return S_OK;
    65   }
    67   STDMETHODIMP OnDataUpdated(ISensor *aSensor, ISensorDataReport *aReport) {
    68     PROPVARIANT v;
    69     HRESULT hr;
    70     InfallibleTArray<float> values;
    72     // X-axis acceleration in g's
    73     hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_X_G, &v);
    74     if (FAILED(hr)) {
    75       return hr;
    76     }
    77     values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
    79     // Y-axis acceleration in g's
    80     hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Y_G, &v);
    81     if (FAILED(hr)) {
    82       return hr;
    83     }
    84     values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
    86     // Z-axis acceleration in g's
    87     hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Z_G, &v);
    88     if (FAILED(hr)) {
    89       return hr;
    90     }
    91     values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
    93     hal::SensorData sdata(hal::SENSOR_ACCELERATION,
    94                           PR_Now(),
    95                           values,
    96                           hal::SENSOR_ACCURACY_UNKNOWN);
    97     hal::NotifySensorChange(sdata);
    99     return S_OK;
   100   }
   102 private:
   103   ULONG mCount;
   104 };
   106 void
   107 EnableSensorNotifications(SensorType aSensor)
   108 {
   109   if (aSensor != SENSOR_ACCELERATION) {
   110     return;
   111   }
   113   if (sAccelerometer) {
   114     return;
   115   }
   117   nsRefPtr<ISensorManager> manager;
   118   if (FAILED(CoCreateInstance(CLSID_SensorManager, nullptr,
   119                               CLSCTX_INPROC_SERVER,
   120                               IID_ISensorManager, 
   121                               getter_AddRefs(manager)))) {
   122     return;
   123   }
   125   // accelerometer event
   127   nsRefPtr<ISensorCollection> collection;
   128   if (FAILED(manager->GetSensorsByType(SENSOR_TYPE_ACCELEROMETER_3D,
   129                                        getter_AddRefs(collection)))) {
   130     return;
   131   }
   133   ULONG count = 0;
   134   collection->GetCount(&count);
   135   if (!count) {
   136     return;
   137   }
   139   nsRefPtr<ISensor> sensor;
   140   collection->GetAt(0, getter_AddRefs(sensor));
   141   if (!sensor) {
   142     return;
   143   }
   145   // Set report interval to 100ms if possible. 
   146   // Default value depends on drivers.
   147   nsRefPtr<IPortableDeviceValues> values;
   148   if (SUCCEEDED(CoCreateInstance(CLSID_PortableDeviceValues, nullptr,
   149                                  CLSCTX_INPROC_SERVER,
   150                                  IID_IPortableDeviceValues,
   151                                  getter_AddRefs(values)))) {
   152     if (SUCCEEDED(values->SetUnsignedIntegerValue(
   153                     SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL,
   154                     DEFAULT_SENSOR_POLL))) {
   155       nsRefPtr<IPortableDeviceValues> returns;
   156       sensor->SetProperties(values, getter_AddRefs(returns));
   157     }
   158   }
   160   nsRefPtr<SensorEvent> event = new SensorEvent();
   161   nsRefPtr<ISensorEvents> sensorEvents;
   162   if (FAILED(event->QueryInterface(IID_ISensorEvents,
   163                                    getter_AddRefs(sensorEvents)))) {
   164     return;
   165   }
   167   if (FAILED(sensor->SetEventSink(sensorEvents))) {
   168     return;
   169   }
   171   sAccelerometer = sensor;
   172 }
   174 void
   175 DisableSensorNotifications(SensorType aSensor)
   176 {
   177   if (aSensor == SENSOR_ACCELERATION && sAccelerometer) {
   178     sAccelerometer->SetEventSink(nullptr);
   179     sAccelerometer = nullptr;
   180   }
   181 }
   183 } // hal_impl
   184 } // mozilla

mercurial