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