summaryrefslogtreecommitdiffstats
path: root/hal/windows/WindowsSensor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'hal/windows/WindowsSensor.cpp')
-rw-r--r--hal/windows/WindowsSensor.cpp184
1 files changed, 184 insertions, 0 deletions
diff --git a/hal/windows/WindowsSensor.cpp b/hal/windows/WindowsSensor.cpp
new file mode 100644
index 000000000..302ad7c48
--- /dev/null
+++ b/hal/windows/WindowsSensor.cpp
@@ -0,0 +1,184 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Hal.h"
+
+#include <sensorsapi.h>
+#include <sensors.h>
+#include <portabledevicetypes.h>
+
+#define MEAN_GRAVITY 9.80665
+#define DEFAULT_SENSOR_POLL 100
+
+using namespace mozilla::hal;
+
+namespace mozilla {
+namespace hal_impl {
+
+static RefPtr<ISensor> sAccelerometer;
+
+class SensorEvent final : public ISensorEvents {
+public:
+ SensorEvent() : mCount(0) {
+ }
+
+ // IUnknown interface
+
+ STDMETHODIMP_(ULONG) AddRef() {
+ return InterlockedIncrement(&mCount);
+ }
+
+ STDMETHODIMP_(ULONG) Release() {
+ ULONG count = InterlockedDecrement(&mCount);
+ if (!count) {
+ delete this;
+ return 0;
+ }
+ return count;
+ }
+
+ STDMETHODIMP QueryInterface(REFIID iid, void** ppv) {
+ if (iid == IID_IUnknown) {
+ *ppv = static_cast<IUnknown*>(this);
+ } else if (iid == IID_ISensorEvents) {
+ *ppv = static_cast<ISensorEvents*>(this);
+ } else {
+ return E_NOINTERFACE;
+ }
+ AddRef();
+ return S_OK;
+ }
+
+ // ISensorEvents interface
+
+ STDMETHODIMP OnEvent(ISensor *aSensor, REFGUID aId, IPortableDeviceValues *aData) {
+ return S_OK;
+ }
+
+ STDMETHODIMP OnLeave(REFSENSOR_ID aId) {
+ return S_OK;
+ }
+
+ STDMETHODIMP OnStateChanged(ISensor *aSensor, SensorState state) {
+ return S_OK;
+ }
+
+ STDMETHODIMP OnDataUpdated(ISensor *aSensor, ISensorDataReport *aReport) {
+ PROPVARIANT v;
+ HRESULT hr;
+ InfallibleTArray<float> values;
+
+ // X-axis acceleration in g's
+ hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_X_G, &v);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
+
+ // Y-axis acceleration in g's
+ hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Y_G, &v);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
+
+ // Z-axis acceleration in g's
+ hr = aReport->GetSensorValue(SENSOR_DATA_TYPE_ACCELERATION_Z_G, &v);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ values.AppendElement(float(-v.dblVal * MEAN_GRAVITY));
+
+ hal::SensorData sdata(hal::SENSOR_ACCELERATION,
+ PR_Now(),
+ values,
+ hal::SENSOR_ACCURACY_UNKNOWN);
+ hal::NotifySensorChange(sdata);
+
+ return S_OK;
+ }
+
+private:
+ ULONG mCount;
+};
+
+void
+EnableSensorNotifications(SensorType aSensor)
+{
+ if (aSensor != SENSOR_ACCELERATION) {
+ return;
+ }
+
+ if (sAccelerometer) {
+ return;
+ }
+
+ RefPtr<ISensorManager> manager;
+ if (FAILED(CoCreateInstance(CLSID_SensorManager, nullptr,
+ CLSCTX_INPROC_SERVER,
+ IID_ISensorManager,
+ getter_AddRefs(manager)))) {
+ return;
+ }
+
+ // accelerometer event
+
+ RefPtr<ISensorCollection> collection;
+ if (FAILED(manager->GetSensorsByType(SENSOR_TYPE_ACCELEROMETER_3D,
+ getter_AddRefs(collection)))) {
+ return;
+ }
+
+ ULONG count = 0;
+ collection->GetCount(&count);
+ if (!count) {
+ return;
+ }
+
+ RefPtr<ISensor> sensor;
+ collection->GetAt(0, getter_AddRefs(sensor));
+ if (!sensor) {
+ return;
+ }
+
+ // Set report interval to 100ms if possible.
+ // Default value depends on drivers.
+ RefPtr<IPortableDeviceValues> values;
+ if (SUCCEEDED(CoCreateInstance(CLSID_PortableDeviceValues, nullptr,
+ CLSCTX_INPROC_SERVER,
+ IID_IPortableDeviceValues,
+ getter_AddRefs(values)))) {
+ if (SUCCEEDED(values->SetUnsignedIntegerValue(
+ SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL,
+ DEFAULT_SENSOR_POLL))) {
+ RefPtr<IPortableDeviceValues> returns;
+ sensor->SetProperties(values, getter_AddRefs(returns));
+ }
+ }
+
+ RefPtr<SensorEvent> event = new SensorEvent();
+ RefPtr<ISensorEvents> sensorEvents;
+ if (FAILED(event->QueryInterface(IID_ISensorEvents,
+ getter_AddRefs(sensorEvents)))) {
+ return;
+ }
+
+ if (FAILED(sensor->SetEventSink(sensorEvents))) {
+ return;
+ }
+
+ sAccelerometer = sensor;
+}
+
+void
+DisableSensorNotifications(SensorType aSensor)
+{
+ if (aSensor == SENSOR_ACCELERATION && sAccelerometer) {
+ sAccelerometer->SetEventSink(nullptr);
+ sAccelerometer = nullptr;
+ }
+}
+
+} // hal_impl
+} // mozilla