WindowsSensor.cpp (4312B)
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/. */ 4 5 #include "Hal.h" 6 7 #include <sensorsapi.h> 8 #include <sensors.h> 9 #include <portabledevicetypes.h> 10 11 #define MEAN_GRAVITY 9.80665 12 #define DEFAULT_SENSOR_POLL 100 13 14 using namespace mozilla::hal; 15 16 namespace mozilla { 17 namespace hal_impl { 18 19 constinit static RefPtr<ISensor> sAccelerometer; 20 21 class SensorEvent final : public ISensorEvents { 22 public: 23 SensorEvent() : mCount(0) {} 24 25 // IUnknown interface 26 27 STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&mCount); } 28 29 STDMETHODIMP_(ULONG) Release() { 30 ULONG count = InterlockedDecrement(&mCount); 31 if (!count) { 32 delete this; 33 return 0; 34 } 35 return count; 36 } 37 38 STDMETHODIMP QueryInterface(REFIID iid, void** ppv) { 39 if (iid == IID_IUnknown) { 40 *ppv = static_cast<IUnknown*>(this); 41 } else if (iid == IID_ISensorEvents) { 42 *ppv = static_cast<ISensorEvents*>(this); 43 } else { 44 return E_NOINTERFACE; 45 } 46 AddRef(); 47 return S_OK; 48 } 49 50 // ISensorEvents interface 51 52 STDMETHODIMP OnEvent(ISensor* aSensor, REFGUID aId, 53 IPortableDeviceValues* aData) { 54 return S_OK; 55 } 56 57 STDMETHODIMP OnLeave(REFSENSOR_ID aId) { return S_OK; } 58 59 STDMETHODIMP OnStateChanged(ISensor* aSensor, SensorState state) { 60 return S_OK; 61 } 62 63 STDMETHODIMP OnDataUpdated(ISensor* aSensor, ISensorDataReport* aReport) { 64 PROPVARIANT v; 65 HRESULT hr; 66 nsTArray<float> values; 67 68 // X-axis acceleration in g's 69 hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_X_G, &v); 70 if (FAILED(hr)) { 71 return hr; 72 } 73 values.AppendElement(float(-v.dblVal * MEAN_GRAVITY)); 74 75 // Y-axis acceleration in g's 76 hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Y_G, &v); 77 if (FAILED(hr)) { 78 return hr; 79 } 80 values.AppendElement(float(-v.dblVal * MEAN_GRAVITY)); 81 82 // Z-axis acceleration in g's 83 hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Z_G, &v); 84 if (FAILED(hr)) { 85 return hr; 86 } 87 values.AppendElement(float(-v.dblVal * MEAN_GRAVITY)); 88 89 hal::SensorData sdata(hal::SENSOR_ACCELERATION, PR_Now(), values); 90 hal::NotifySensorChange(sdata); 91 92 return S_OK; 93 } 94 95 private: 96 ULONG mCount; 97 }; 98 99 void EnableSensorNotifications(SensorType aSensor) { 100 if (aSensor != SENSOR_ACCELERATION) { 101 return; 102 } 103 104 if (sAccelerometer) { 105 return; 106 } 107 108 RefPtr<ISensorManager> manager; 109 if (FAILED(CoCreateInstance(CLSID_SensorManager, nullptr, 110 CLSCTX_INPROC_SERVER, IID_ISensorManager, 111 getter_AddRefs(manager)))) { 112 return; 113 } 114 115 // accelerometer event 116 117 RefPtr<ISensorCollection> collection; 118 if (FAILED(manager->GetSensorsByType(SENSOR_TYPE_ACCELEROMETER_3D, 119 getter_AddRefs(collection)))) { 120 return; 121 } 122 123 ULONG count = 0; 124 collection->GetCount(&count); 125 if (!count) { 126 return; 127 } 128 129 RefPtr<ISensor> sensor; 130 collection->GetAt(0, getter_AddRefs(sensor)); 131 if (!sensor) { 132 return; 133 } 134 135 // Set report interval to 100ms if possible. 136 // Default value depends on drivers. 137 RefPtr<IPortableDeviceValues> values; 138 if (SUCCEEDED(CoCreateInstance( 139 CLSID_PortableDeviceValues, nullptr, CLSCTX_INPROC_SERVER, 140 IID_IPortableDeviceValues, getter_AddRefs(values)))) { 141 if (SUCCEEDED(values->SetUnsignedIntegerValue( 142 SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, DEFAULT_SENSOR_POLL))) { 143 RefPtr<IPortableDeviceValues> returns; 144 sensor->SetProperties(values, getter_AddRefs(returns)); 145 } 146 } 147 148 RefPtr<SensorEvent> event = new SensorEvent(); 149 RefPtr<ISensorEvents> sensorEvents; 150 if (FAILED(event->QueryInterface(IID_ISensorEvents, 151 getter_AddRefs(sensorEvents)))) { 152 return; 153 } 154 155 if (FAILED(sensor->SetEventSink(sensorEvents))) { 156 return; 157 } 158 159 sAccelerometer = sensor; 160 } 161 162 void DisableSensorNotifications(SensorType aSensor) { 163 if (aSensor == SENSOR_ACCELERATION && sAccelerometer) { 164 sAccelerometer->SetEventSink(nullptr); 165 sAccelerometer = nullptr; 166 } 167 } 168 169 } // namespace hal_impl 170 } // namespace mozilla