WindowsSensor.cpp 4.4 KB

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