sensord: add/change enums and types for avoiding build-break
[platform/core/system/sensord.git] / src / 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 <sys/ioctl.h>
25 #include <pressure_sensor_hal.h>
26 #include <fstream>
27 #include <string>
28 #include <iio_common.h>
29
30 using std::ifstream;
31 using std::string;
32
33 #define SENSOR_TYPE_PRESSURE    "PRESSURE"
34 #define ELEMENT_NAME                    "NAME"
35 #define ELEMENT_VENDOR                  "VENDOR"
36 #define ELEMENT_RAW_DATA_UNIT   "RAW_DATA_UNIT"
37 #define ELEMENT_RESOLUTION              "RESOLUTION"
38 #define ELEMENT_MIN_RANGE               "MIN_RANGE"
39 #define ELEMENT_MAX_RANGE               "MAX_RANGE"
40 #define ELEMENT_TEMPERATURE_RESOLUTION  "TEMPERATURE_RESOLUTION"
41 #define ELEMENT_TEMPERATURE_OFFSET              "TEMPERATURE_OFFSET"
42 #define ATTR_VALUE                              "value"
43
44 #define SEA_LEVEL_PRESSURE 101325.0
45
46 #define EVENT_EN_NODE   "events/in_pressure_mag_either_en"
47 #define PRESSURE_SCALE  "/in_pressure_scale"
48 #define PRESSURE_RAW    "/in_pressure_raw"
49 #define TEMP_OFFSET             "/in_temp_offset"
50 #define TEMP_SCALE              "/in_temp_scale"
51 #define TEMP_RAW                "/in_temp_raw"
52 #define NO_FLAG                 0
53 #define TIMEOUT                 1
54
55 pressure_sensor_hal::pressure_sensor_hal()
56 : m_pressure(0)
57 , m_temperature(0)
58 , m_polling_interval(POLL_1HZ_MS)
59 , m_fired_time(0)
60 , m_node_handle(-1)
61 {
62         const string sensorhub_interval_node_name = "pressure_poll_delay";
63         csensor_config &config = csensor_config::get_instance();
64
65         node_path_info_query query;
66         node_path_info info;
67         int input_method = IIO_METHOD;
68
69         if (!get_model_properties(SENSOR_TYPE_PRESSURE, m_model_id, input_method)) {
70                 ERR("Failed to find model_properties");
71                 throw ENXIO;
72
73         }
74
75         query.input_method = input_method;
76         query.sensorhub_controlled = m_sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name);
77         query.sensor_type = SENSOR_TYPE_PRESSURE;
78         query.input_event_key = "pressure_sensor";
79         query.iio_enable_node_name = EVENT_EN_NODE;
80         query.sensorhub_interval_node_name = sensorhub_interval_node_name;
81
82         if (!get_node_path_info(query, info)) {
83                 ERR("Failed to get node info");
84                 throw ENXIO;
85         }
86         m_data_node = info.data_node_path;
87         m_pressure_dir = info.base_dir;
88         m_enable_node = info.enable_node_path;
89         m_pressure_node = m_pressure_dir + string(PRESSURE_RAW);
90         m_temp_node = m_pressure_dir + string(TEMP_RAW);
91
92         INFO("m_data_node:%s",m_data_node.c_str());
93         INFO("m_pressure_dir:%s",m_pressure_dir.c_str());
94         INFO("m_enable_node:%s",m_enable_node.c_str());
95
96         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_VENDOR, m_vendor)) {
97                 ERR("[VENDOR] is empty\n");
98                 throw ENXIO;
99         }
100
101         INFO("m_vendor = %s", m_vendor.c_str());
102
103         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_NAME, m_chip_name)) {
104                 ERR("[NAME] is empty\n");
105                 throw ENXIO;
106         }
107
108         INFO("m_chip_name = %s", m_chip_name.c_str());
109
110         double min_range;
111
112         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MIN_RANGE, min_range)) {
113                 ERR("[MIN_RANGE] is empty\n");
114                 throw ENXIO;
115         }
116
117         m_min_range = (float)min_range;
118         INFO("m_min_range = %f\n",m_min_range);
119
120         double max_range;
121
122         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MAX_RANGE, max_range)) {
123                 ERR("[MAX_RANGE] is empty\n");
124                 throw ENXIO;
125         }
126
127         m_max_range = (float)max_range;
128         INFO("m_max_range = %f\n",m_max_range);
129
130         double raw_data_unit;
131
132         if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
133                 ERR("[RAW_DATA_UNIT] is empty\n");
134                 throw ENXIO;
135         }
136
137         m_raw_data_unit = (float)(raw_data_unit);
138         INFO("m_raw_data_unit = %f\n", m_raw_data_unit);
139
140         string file_name;
141
142         file_name = m_pressure_dir + string(TEMP_SCALE);
143         if (!read_node_value<int>(file_name, m_temp_scale))
144                 throw ENXIO;
145
146         file_name = m_pressure_dir + string(TEMP_OFFSET);
147         if (!read_node_value<float>(file_name, m_temp_offset))
148                 throw ENXIO;
149
150         file_name = m_pressure_dir + string(PRESSURE_SCALE);
151         if (!read_node_value<int>(file_name, m_pressure_scale))
152                 throw ENXIO;
153
154         INFO("Temperature scale:%d", m_temp_scale);
155         INFO("Temperature offset:%f", m_temp_offset);
156         INFO("Pressure scale:%d", m_pressure_scale);
157
158         int fd, ret;
159         fd = open(m_data_node.c_str(), NO_FLAG);
160         if (fd == -1) {
161                 ERR("Could not open event resource");
162                 throw ENXIO;
163         }
164
165         ret = ioctl(fd, IOCTL_IIO_EVENT_FD, &m_node_handle);
166
167         close(fd);
168
169         if ((ret == -1) || (m_node_handle == -1)) {
170                 ERR("Failed to retrieve node handle from event node: %s", m_data_node.c_str());
171                 throw ENXIO;
172         }
173
174         INFO("pressure_sensor_hal is created!\n");
175 }
176
177 pressure_sensor_hal::~pressure_sensor_hal()
178 {
179         close(m_node_handle);
180         m_node_handle = -1;
181
182         INFO("pressure_sensor_hal is destroyed!\n");
183 }
184
185 string pressure_sensor_hal::get_model_id(void)
186 {
187         return m_model_id;
188 }
189
190 sensor_type_t pressure_sensor_hal::get_type(void)
191 {
192         return PRESSURE_SENSOR;
193 }
194
195 bool pressure_sensor_hal::enable(void)
196 {
197         AUTOLOCK(m_mutex);
198         update_sysfs_num(m_enable_node.c_str(), true);
199         set_interval(m_polling_interval);
200
201         m_fired_time = 0;
202         INFO("Pressure sensor real starting");
203         return true;
204 }
205
206 bool pressure_sensor_hal::disable(void)
207 {
208         AUTOLOCK(m_mutex);
209
210         update_sysfs_num(m_enable_node.c_str(), false);
211
212         INFO("Pressure sensor real stopping");
213         return true;
214 }
215
216 bool pressure_sensor_hal::set_interval(unsigned long val)
217 {
218         INFO("set_interval not supported");
219         return true;
220 }
221
222 bool pressure_sensor_hal::update_value(bool wait)
223 {
224         iio_event_t pressure_event;
225         fd_set readfds, exceptfds;
226         struct timeval tv;
227         int raw_pressure_count;
228         int raw_temp_count;
229         int ret;
230
231         FD_ZERO(&readfds);
232         FD_ZERO(&exceptfds);
233         FD_SET(m_node_handle, &readfds);
234         FD_SET(m_node_handle, &exceptfds);
235
236         if (wait) {
237                 tv.tv_sec = TIMEOUT;
238                 tv.tv_usec = 0;
239         }
240         else {
241                 tv.tv_sec = 0;
242                 tv.tv_usec = 0;
243         }
244
245         ret = select(m_node_handle + 1, &readfds, NULL, &exceptfds, &tv);
246
247         if (ret == -1) {
248                 ERR("select error:%s m_node_handle:d", strerror(errno), m_node_handle);
249                 return false;
250         }
251         else if (!ret) {
252                 DBG("select timeout");
253                 return false;
254         }
255
256         if (FD_ISSET(m_node_handle, &exceptfds)) {
257                 ERR("select exception occurred!");
258                 return false;
259         }
260
261         if (FD_ISSET(m_node_handle, &readfds)) {
262                 INFO("pressure event detection!");
263                 int len = read(m_node_handle, &pressure_event, sizeof(pressure_event));
264
265                 if (len == -1) {
266                         ERR("Error in read(m_event_fd):%s.", strerror(errno));
267                         return false;
268                 }
269                 m_fired_time = pressure_event.timestamp;
270                 if (!read_node_value<int>(m_pressure_node, raw_pressure_count))
271                         return false;
272                 if (!read_node_value<int>(m_temp_node, raw_temp_count))
273                         return false;
274                 m_pressure = ((float)raw_pressure_count)/((float)m_pressure_scale);
275                 m_temperature = m_temp_offset + ((float)raw_temp_count)/((float)m_temp_scale);
276         }
277         else {
278                 ERR("No pressure event data available to read");
279                 return false;
280         }
281         return true;
282
283 }
284
285 bool pressure_sensor_hal::is_data_ready(bool wait)
286 {
287         bool ret;
288         ret = update_value(wait);
289         return ret;
290 }
291
292 int pressure_sensor_hal::get_sensor_data(sensor_data_t &data)
293 {
294         AUTOLOCK(m_value_mutex);
295         data.accuracy = SENSOR_ACCURACY_GOOD;
296         data.timestamp = m_fired_time ;
297         data.value_count = 3;
298         data.values[0] = m_pressure;
299         data.values[1] = SEA_LEVEL_PRESSURE;
300         data.values[2] = m_temperature;
301
302         return 0;
303 }
304
305
306 bool pressure_sensor_hal::get_properties(sensor_properties_s &properties)
307 {
308         properties.name = m_chip_name;
309         properties.vendor = m_vendor;
310         properties.min_range = m_min_range;
311         properties.max_range = m_max_range;
312         properties.min_interval = 1;
313         properties.resolution = m_raw_data_unit;
314         properties.fifo_count = 0;
315         properties.max_batch_count = 0;
316         return true;
317 }
318
319 extern "C" void *create(void)
320 {
321         pressure_sensor_hal *inst;
322
323         try {
324                 inst = new pressure_sensor_hal();
325         } catch (int err) {
326                 ERR("pressure_sensor_hal class create fail , errno : %d , errstr : %s\n", err, strerror(err));
327                 return NULL;
328         }
329
330         return (void*)inst;
331 }
332
333 extern "C" void destroy(void *inst)
334 {
335         delete (pressure_sensor_hal*)inst;
336 }