badd9bd308397dcd29bcb3ab95855ca95b98c88d
[platform/adaptation/tm1/sensor-hal-tm1.git] / src / plugins / pressure / pressure_sensor_hal.cpp
1 /*
2  * pressure_sensor_hal
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <fcntl.h>
20 #include <sys/stat.h>
21 #include <dirent.h>
22 #include <linux/input.h>
23 #include <csensor_config.h>
24 #include <pressure_sensor_hal.h>
25 #include <sys/ioctl.h>
26 #include <fstream>
27 #include <algorithm>
28
29 using std::ifstream;
30 using std::string;
31
32 #define SENSOR_TYPE_PRESSURE            "PRESSURE"
33 #define ELEMENT_NAME                    "NAME"
34 #define ELEMENT_VENDOR                  "VENDOR"
35 #define ELEMENT_RAW_DATA_UNIT   "RAW_DATA_UNIT"
36 #define ELEMENT_RESOLUTION              "RESOLUTION"
37 #define ELEMENT_MIN_RANGE               "MIN_RANGE"
38 #define ELEMENT_MAX_RANGE               "MAX_RANGE"
39 #define ELEMENT_TEMPERATURE_RESOLUTION  "TEMPERATURE_RESOLUTION"
40 #define ELEMENT_TEMPERATURE_OFFSET              "TEMPERATURE_OFFSET"
41 #define ATTR_VALUE                              "value"
42
43 #define SEA_LEVEL_PRESSURE 101325.0
44 #define SEA_LEVEL_RESOLUTION 0.01
45
46 pressure_sensor_hal::pressure_sensor_hal()
47 : m_pressure(0)
48 , m_sea_level_pressure(SEA_LEVEL_PRESSURE)
49 , m_temperature(0)
50 , m_polling_interval(POLL_1HZ_MS)
51 , m_fired_time(0)
52 , m_node_handle(-1)
53 {
54         const string sensorhub_interval_node_name = "pressure_poll_delay";
55         csensor_config &config = csensor_config::get_instance();
56
57         node_info_query query;
58         node_info info;
59
60         if (!find_model_id(SENSOR_TYPE_PRESSURE, m_model_id)) {
61                 ERR("Failed to find model id");
62                 throw ENXIO;
63
64         }
65
66         query.sensorhub_controlled = m_sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name);
67         query.sensor_type = SENSOR_TYPE_PRESSURE;
68         query.key = "pressure_sensor";
69         query.iio_enable_node_name = "pressure_enable";
70         query.sensorhub_interval_node_name = sensorhub_interval_node_name;
71
72         bool error = get_node_info(query, info);
73
74         query.key = "barometer_sensor";
75         error |= get_node_info(query, info);
76
77         if (!error) {
78                 ERR("Failed to get node info");
79                 throw ENXIO;
80         }
81
82         show_node_info(info);
83
84         m_data_node = info.data_node_path;
85         m_enable_node = info.enable_node_path;
86         m_interval_node = info.interval_node_path;
87
88         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_VENDOR, m_vendor)) {
89                 ERR("[VENDOR] is empty\n");
90                 throw ENXIO;
91         }
92
93         INFO("m_vendor = %s", m_vendor.c_str());
94
95         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_NAME, m_chip_name)) {
96                 ERR("[NAME] is empty\n");
97                 throw ENXIO;
98         }
99
100         INFO("m_chip_name = %s", m_chip_name.c_str());
101
102         double min_range;
103
104         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MIN_RANGE, min_range)) {
105                 ERR("[MIN_RANGE] is empty\n");
106                 throw ENXIO;
107         }
108
109         m_min_range = (float)min_range;
110         INFO("m_min_range = %f\n",m_min_range);
111
112         double max_range;
113
114         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MAX_RANGE, max_range)) {
115                 ERR("[MAX_RANGE] is empty\n");
116                 throw ENXIO;
117         }
118
119         m_max_range = (float)max_range;
120         INFO("m_max_range = %f\n",m_max_range);
121
122         double raw_data_unit;
123
124         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
125                 ERR("[RAW_DATA_UNIT] is empty\n");
126                 throw ENXIO;
127         }
128
129         m_raw_data_unit = (float)(raw_data_unit);
130         INFO("m_raw_data_unit = %f\n", m_raw_data_unit);
131
132         double resolution;
133
134         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_RESOLUTION, resolution)) {
135                 ERR("[RESOLUTION] is empty\n");
136                 throw ENXIO;
137         }
138
139         m_resolution = (float)resolution;
140         INFO("m_resolution = %f\n", m_resolution);
141
142         double temperature_resolution;
143
144         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_TEMPERATURE_RESOLUTION, temperature_resolution)) {
145                 ERR("[TEMPERATURE_RESOLUTION] is empty\n");
146                 throw ENXIO;
147         }
148
149         m_temperature_resolution = (float)temperature_resolution;
150         INFO("m_temperature_resolution = %f\n", m_temperature_resolution);
151
152         double temperature_offset;
153
154         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_TEMPERATURE_OFFSET, temperature_offset)) {
155                 ERR("[TEMPERATURE_OFFSET] is empty\n");
156                 throw ENXIO;
157         }
158
159         m_temperature_offset = (float)temperature_offset;
160         INFO("m_temperature_offset = %f\n", m_temperature_offset);
161
162         if ((m_node_handle = open(m_data_node.c_str(),O_RDWR)) < 0) {
163                 ERR("Failed to open handle(%d)", m_node_handle);
164                 throw ENXIO;
165         }
166
167         int clockId = CLOCK_MONOTONIC;
168         if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0)
169                 ERR("Fail to set monotonic timestamp for %s", m_data_node.c_str());
170
171         INFO("pressure_sensor_hal is created!\n");
172 }
173
174 pressure_sensor_hal::~pressure_sensor_hal()
175 {
176         close(m_node_handle);
177         m_node_handle = -1;
178
179         INFO("pressure_sensor_hal is destroyed!\n");
180 }
181
182 string pressure_sensor_hal::get_model_id(void)
183 {
184         return m_model_id;
185 }
186
187 sensor_hal_type_t pressure_sensor_hal::get_type(void)
188 {
189         return SENSOR_HAL_TYPE_PRESSURE;
190 }
191
192 bool pressure_sensor_hal::enable(void)
193 {
194         AUTOLOCK(m_mutex);
195
196         set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_PRESSURE_ENABLE_BIT);
197
198         set_interval(m_polling_interval);
199
200         m_fired_time = 0;
201         INFO("Pressure sensor real starting");
202         return true;
203 }
204
205 bool pressure_sensor_hal::disable(void)
206 {
207         AUTOLOCK(m_mutex);
208
209         set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_PRESSURE_ENABLE_BIT);
210
211         INFO("Pressure sensor real stopping");
212         return true;
213 }
214
215 bool pressure_sensor_hal::set_interval(unsigned long val)
216 {
217         unsigned long long polling_interval_ns;
218
219         AUTOLOCK(m_mutex);
220
221         polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
222
223         if (!set_node_value(m_interval_node, polling_interval_ns)) {
224                 ERR("Failed to set polling resource: %s\n", m_interval_node.c_str());
225                 return false;
226         }
227
228         INFO("Interval is changed from %dms to %dms]", m_polling_interval, val);
229         m_polling_interval = val;
230         return true;
231 }
232
233 bool pressure_sensor_hal::update_value(void)
234 {
235         int pressure_raw[3] = {0,};
236         bool pressure = false;
237         bool sea_level = false;
238         bool temperature = false;
239         int read_input_cnt = 0;
240         const int INPUT_MAX_BEFORE_SYN = 10;
241         unsigned long long fired_time = 0;
242         bool syn = false;
243
244         struct input_event pressure_event;
245         DBG("pressure event detection!");
246
247         while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
248                 int len = read(m_node_handle, &pressure_event, sizeof(pressure_event));
249                 if (len != sizeof(pressure_event)) {
250                         ERR("pressure_file read fail, read_len = %d\n",len);
251                         return false;
252                 }
253
254                 ++read_input_cnt;
255
256                 if (pressure_event.type == EV_REL) {
257                         switch (pressure_event.code) {
258                                 case REL_X:
259                                 case REL_HWHEEL:
260                                         pressure_raw[0] = (int)pressure_event.value;
261                                         pressure = true;
262                                         break;
263                                 case REL_Y:
264                                 case REL_DIAL:
265                                         pressure_raw[1] = (int)pressure_event.value;
266                                         sea_level = true;
267                                         break;
268                                 case REL_Z:
269                                 case REL_WHEEL:
270                                         pressure_raw[2] = (int)pressure_event.value;
271                                         temperature = true;
272                                         break;
273                                 default:
274                                         ERR("pressure_event event[type = %d, code = %d] is unknown.", pressure_event.type, pressure_event.code);
275                                         return false;
276                                         break;
277                         }
278                 } else if (pressure_event.type == EV_SYN) {
279                         syn = true;
280                         fired_time = sensor_hal_base::get_timestamp(&pressure_event.time);
281                 } else {
282                         ERR("pressure_event event[type = %d, code = %d] is unknown.", pressure_event.type, pressure_event.code);
283                         return false;
284                 }
285         }
286
287         AUTOLOCK(m_value_mutex);
288
289         if (pressure)
290                 m_pressure = pressure_raw[0];
291         if (sea_level)
292                 m_sea_level_pressure = pressure_raw[1];
293         if (temperature)
294                 m_temperature = pressure_raw[2];
295
296         m_fired_time = fired_time;
297
298         DBG("m_pressure = %d, sea_level = %d, temperature = %d, time = %lluus", m_pressure, m_sea_level_pressure, m_temperature, m_fired_time);
299
300         return true;
301 }
302
303 bool pressure_sensor_hal::is_data_ready(void)
304 {
305         bool ret;
306         ret = update_value();
307         return ret;
308 }
309
310
311 float pressure_sensor_hal::pressure_to_altitude(float pressure)
312 {
313         return 44330.0f * (1.0f - pow(pressure/m_sea_level_pressure, 1.0f/5.255f));
314 }
315
316 void pressure_sensor_hal::raw_to_base(sensor_data_t &data)
317 {
318         data.values[0] = data.values[0] * m_resolution;
319         m_sea_level_pressure = data.values[1] * SEA_LEVEL_RESOLUTION;
320         data.values[1] = pressure_to_altitude(data.values[0]);
321         data.values[2] = data.values[2] * m_temperature_resolution + m_temperature_offset;
322         data.value_count = 3;
323 }
324
325 int pressure_sensor_hal::get_sensor_data(sensor_data_t &data)
326 {
327         AUTOLOCK(m_value_mutex);
328         data.accuracy = SENSOR_ACCURACY_GOOD;
329         data.timestamp = m_fired_time ;
330         data.value_count = 3;
331         data.values[0] = m_pressure;
332         data.values[1] = m_sea_level_pressure;
333         data.values[2] = m_temperature;
334
335         raw_to_base(data);
336
337         return 0;
338 }
339
340 bool pressure_sensor_hal::get_properties(sensor_properties_s &properties)
341 {
342         properties.name = m_chip_name;
343         properties.vendor = m_vendor;
344         properties.min_range = m_min_range;
345         properties.max_range = m_max_range;
346         properties.min_interval = 1;
347         properties.resolution = m_raw_data_unit;
348         properties.fifo_count = 0;
349         properties.max_batch_count = 0;
350         return true;
351 }