1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/hal/windows/WindowsSensor.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,184 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "Hal.h" 1.9 + 1.10 +#include <sensorsapi.h> 1.11 +#include <sensors.h> 1.12 +#include <portabledevicetypes.h> 1.13 + 1.14 +#define MEAN_GRAVITY 9.80665 1.15 +#define DEFAULT_SENSOR_POLL 100 1.16 + 1.17 +using namespace mozilla::hal; 1.18 + 1.19 +namespace mozilla { 1.20 +namespace hal_impl { 1.21 + 1.22 +static nsRefPtr<ISensor> sAccelerometer; 1.23 + 1.24 +class SensorEvent MOZ_FINAL : public ISensorEvents { 1.25 +public: 1.26 + SensorEvent() : mCount(0) { 1.27 + } 1.28 + 1.29 + // IUnknown interface 1.30 + 1.31 + STDMETHODIMP_(ULONG) AddRef() { 1.32 + return InterlockedIncrement(&mCount); 1.33 + } 1.34 + 1.35 + STDMETHODIMP_(ULONG) Release() { 1.36 + ULONG count = InterlockedDecrement(&mCount); 1.37 + if (!count) { 1.38 + delete this; 1.39 + return 0; 1.40 + } 1.41 + return count; 1.42 + } 1.43 + 1.44 + STDMETHODIMP QueryInterface(REFIID iid, void** ppv) { 1.45 + if (iid == IID_IUnknown) { 1.46 + *ppv = static_cast<IUnknown*>(this); 1.47 + } else if (iid == IID_ISensorEvents) { 1.48 + *ppv = static_cast<ISensorEvents*>(this); 1.49 + } else { 1.50 + return E_NOINTERFACE; 1.51 + } 1.52 + AddRef(); 1.53 + return S_OK; 1.54 + } 1.55 + 1.56 + // ISensorEvents interface 1.57 + 1.58 + STDMETHODIMP OnEvent(ISensor *aSensor, REFGUID aId, IPortableDeviceValues *aData) { 1.59 + return S_OK; 1.60 + } 1.61 + 1.62 + STDMETHODIMP OnLeave(REFSENSOR_ID aId) { 1.63 + return S_OK; 1.64 + } 1.65 + 1.66 + STDMETHODIMP OnStateChanged(ISensor *aSensor, SensorState state) { 1.67 + return S_OK; 1.68 + } 1.69 + 1.70 + STDMETHODIMP OnDataUpdated(ISensor *aSensor, ISensorDataReport *aReport) { 1.71 + PROPVARIANT v; 1.72 + HRESULT hr; 1.73 + InfallibleTArray<float> values; 1.74 + 1.75 + // X-axis acceleration in g's 1.76 + hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_X_G, &v); 1.77 + if (FAILED(hr)) { 1.78 + return hr; 1.79 + } 1.80 + values.AppendElement(float(-v.dblVal * MEAN_GRAVITY)); 1.81 + 1.82 + // Y-axis acceleration in g's 1.83 + hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Y_G, &v); 1.84 + if (FAILED(hr)) { 1.85 + return hr; 1.86 + } 1.87 + values.AppendElement(float(-v.dblVal * MEAN_GRAVITY)); 1.88 + 1.89 + // Z-axis acceleration in g's 1.90 + hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Z_G, &v); 1.91 + if (FAILED(hr)) { 1.92 + return hr; 1.93 + } 1.94 + values.AppendElement(float(-v.dblVal * MEAN_GRAVITY)); 1.95 + 1.96 + hal::SensorData sdata(hal::SENSOR_ACCELERATION, 1.97 + PR_Now(), 1.98 + values, 1.99 + hal::SENSOR_ACCURACY_UNKNOWN); 1.100 + hal::NotifySensorChange(sdata); 1.101 + 1.102 + return S_OK; 1.103 + } 1.104 + 1.105 +private: 1.106 + ULONG mCount; 1.107 +}; 1.108 + 1.109 +void 1.110 +EnableSensorNotifications(SensorType aSensor) 1.111 +{ 1.112 + if (aSensor != SENSOR_ACCELERATION) { 1.113 + return; 1.114 + } 1.115 + 1.116 + if (sAccelerometer) { 1.117 + return; 1.118 + } 1.119 + 1.120 + nsRefPtr<ISensorManager> manager; 1.121 + if (FAILED(CoCreateInstance(CLSID_SensorManager, nullptr, 1.122 + CLSCTX_INPROC_SERVER, 1.123 + IID_ISensorManager, 1.124 + getter_AddRefs(manager)))) { 1.125 + return; 1.126 + } 1.127 + 1.128 + // accelerometer event 1.129 + 1.130 + nsRefPtr<ISensorCollection> collection; 1.131 + if (FAILED(manager->GetSensorsByType(SENSOR_TYPE_ACCELEROMETER_3D, 1.132 + getter_AddRefs(collection)))) { 1.133 + return; 1.134 + } 1.135 + 1.136 + ULONG count = 0; 1.137 + collection->GetCount(&count); 1.138 + if (!count) { 1.139 + return; 1.140 + } 1.141 + 1.142 + nsRefPtr<ISensor> sensor; 1.143 + collection->GetAt(0, getter_AddRefs(sensor)); 1.144 + if (!sensor) { 1.145 + return; 1.146 + } 1.147 + 1.148 + // Set report interval to 100ms if possible. 1.149 + // Default value depends on drivers. 1.150 + nsRefPtr<IPortableDeviceValues> values; 1.151 + if (SUCCEEDED(CoCreateInstance(CLSID_PortableDeviceValues, nullptr, 1.152 + CLSCTX_INPROC_SERVER, 1.153 + IID_IPortableDeviceValues, 1.154 + getter_AddRefs(values)))) { 1.155 + if (SUCCEEDED(values->SetUnsignedIntegerValue( 1.156 + SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, 1.157 + DEFAULT_SENSOR_POLL))) { 1.158 + nsRefPtr<IPortableDeviceValues> returns; 1.159 + sensor->SetProperties(values, getter_AddRefs(returns)); 1.160 + } 1.161 + } 1.162 + 1.163 + nsRefPtr<SensorEvent> event = new SensorEvent(); 1.164 + nsRefPtr<ISensorEvents> sensorEvents; 1.165 + if (FAILED(event->QueryInterface(IID_ISensorEvents, 1.166 + getter_AddRefs(sensorEvents)))) { 1.167 + return; 1.168 + } 1.169 + 1.170 + if (FAILED(sensor->SetEventSink(sensorEvents))) { 1.171 + return; 1.172 + } 1.173 + 1.174 + sAccelerometer = sensor; 1.175 +} 1.176 + 1.177 +void 1.178 +DisableSensorNotifications(SensorType aSensor) 1.179 +{ 1.180 + if (aSensor == SENSOR_ACCELERATION && sAccelerometer) { 1.181 + sAccelerometer->SetEventSink(nullptr); 1.182 + sAccelerometer = nullptr; 1.183 + } 1.184 +} 1.185 + 1.186 +} // hal_impl 1.187 +} // mozilla