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