4 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <linux/input.h>
23 #include <csensor_config.h>
24 #include <pressure_sensor_hal.h>
25 #include <sys/ioctl.h>
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"
43 #define SEA_LEVEL_PRESSURE 101325.0
44 #define SEA_LEVEL_RESOLUTION 0.01
46 pressure_sensor_hal::pressure_sensor_hal()
48 , m_sea_level_pressure(SEA_LEVEL_PRESSURE)
50 , m_polling_interval(POLL_1HZ_MS)
54 const string sensorhub_interval_node_name = "pressure_poll_delay";
55 csensor_config &config = csensor_config::get_instance();
57 node_info_query query;
60 if (!find_model_id(SENSOR_TYPE_PRESSURE, m_model_id)) {
61 ERR("Failed to find model id");
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;
72 bool error = get_node_info(query, info);
74 query.key = "barometer_sensor";
75 error |= get_node_info(query, info);
78 ERR("Failed to get node info");
84 m_data_node = info.data_node_path;
85 m_enable_node = info.enable_node_path;
86 m_interval_node = info.interval_node_path;
88 if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_VENDOR, m_vendor)) {
89 ERR("[VENDOR] is empty\n");
93 INFO("m_vendor = %s", m_vendor.c_str());
95 if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_NAME, m_chip_name)) {
96 ERR("[NAME] is empty\n");
100 INFO("m_chip_name = %s", m_chip_name.c_str());
104 if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MIN_RANGE, min_range)) {
105 ERR("[MIN_RANGE] is empty\n");
109 m_min_range = (float)min_range;
110 INFO("m_min_range = %f\n",m_min_range);
114 if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MAX_RANGE, max_range)) {
115 ERR("[MAX_RANGE] is empty\n");
119 m_max_range = (float)max_range;
120 INFO("m_max_range = %f\n",m_max_range);
122 double raw_data_unit;
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");
129 m_raw_data_unit = (float)(raw_data_unit);
130 INFO("m_raw_data_unit = %f\n", m_raw_data_unit);
134 if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_RESOLUTION, resolution)) {
135 ERR("[RESOLUTION] is empty\n");
139 m_resolution = (float)resolution;
140 INFO("m_resolution = %f\n", m_resolution);
142 double temperature_resolution;
144 if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_TEMPERATURE_RESOLUTION, temperature_resolution)) {
145 ERR("[TEMPERATURE_RESOLUTION] is empty\n");
149 m_temperature_resolution = (float)temperature_resolution;
150 INFO("m_temperature_resolution = %f\n", m_temperature_resolution);
152 double temperature_offset;
154 if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_TEMPERATURE_OFFSET, temperature_offset)) {
155 ERR("[TEMPERATURE_OFFSET] is empty\n");
159 m_temperature_offset = (float)temperature_offset;
160 INFO("m_temperature_offset = %f\n", m_temperature_offset);
162 if ((m_node_handle = open(m_data_node.c_str(),O_RDWR)) < 0) {
163 ERR("Failed to open handle(%d)", m_node_handle);
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());
171 INFO("pressure_sensor_hal is created!\n");
174 pressure_sensor_hal::~pressure_sensor_hal()
176 close(m_node_handle);
179 INFO("pressure_sensor_hal is destroyed!\n");
182 string pressure_sensor_hal::get_model_id(void)
187 sensor_hal_type_t pressure_sensor_hal::get_type(void)
189 return SENSOR_HAL_TYPE_PRESSURE;
192 bool pressure_sensor_hal::enable(void)
196 set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_PRESSURE_ENABLE_BIT);
198 set_interval(m_polling_interval);
201 INFO("Pressure sensor real starting");
205 bool pressure_sensor_hal::disable(void)
209 set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_PRESSURE_ENABLE_BIT);
211 INFO("Pressure sensor real stopping");
215 bool pressure_sensor_hal::set_interval(unsigned long val)
217 unsigned long long polling_interval_ns;
221 polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
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());
228 INFO("Interval is changed from %dms to %dms]", m_polling_interval, val);
229 m_polling_interval = val;
233 bool pressure_sensor_hal::update_value(void)
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;
244 struct input_event pressure_event;
245 DBG("pressure event detection!");
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);
256 if (pressure_event.type == EV_REL) {
257 switch (pressure_event.code) {
260 pressure_raw[0] = (int)pressure_event.value;
265 pressure_raw[1] = (int)pressure_event.value;
270 pressure_raw[2] = (int)pressure_event.value;
274 ERR("pressure_event event[type = %d, code = %d] is unknown.", pressure_event.type, pressure_event.code);
278 } else if (pressure_event.type == EV_SYN) {
280 fired_time = sensor_hal_base::get_timestamp(&pressure_event.time);
282 ERR("pressure_event event[type = %d, code = %d] is unknown.", pressure_event.type, pressure_event.code);
287 AUTOLOCK(m_value_mutex);
290 m_pressure = pressure_raw[0];
292 m_sea_level_pressure = pressure_raw[1];
294 m_temperature = pressure_raw[2];
296 m_fired_time = fired_time;
298 DBG("m_pressure = %d, sea_level = %d, temperature = %d, time = %lluus", m_pressure, m_sea_level_pressure, m_temperature, m_fired_time);
303 bool pressure_sensor_hal::is_data_ready(void)
306 ret = update_value();
311 float pressure_sensor_hal::pressure_to_altitude(float pressure)
313 return 44330.0f * (1.0f - pow(pressure/m_sea_level_pressure, 1.0f/5.255f));
316 void pressure_sensor_hal::raw_to_base(sensor_data_t &data)
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;
325 int pressure_sensor_hal::get_sensor_data(sensor_data_t &data)
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;
340 bool pressure_sensor_hal::get_properties(sensor_properties_s &properties)
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;