2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <sys/types.h>
23 #include <linux/input.h>
24 #include <sys/ioctl.h>
30 #include <sensor_common.h>
31 #include <sensor_log.h>
32 #include "pressure_device.h"
34 #define SEA_LEVEL_RESOLUTION 0.01
35 #define SEA_LEVEL_PRESSURE 101325.0
36 #define SEA_LEVEL_EPSILON 0.00001
38 #define MODEL_NAME "BMP180"
39 #define VENDOR "BOSCH"
41 #define RAW_DATA_UNIT 0.01
42 #define MIN_INTERVAL 180
44 #define MAX_RANGE 1260
45 #define TEMPERATURE_RESOLUTION 0.002083
46 #define TEMPERATURE_OFFSET 42.5
47 #define MAX_BATCH_COUNT 50
49 #define SENSOR_NAME "SENSOR_PRESSURE"
50 #define SENSOR_TYPE_PRESSURE "PRESSURE"
52 #define INPUT_NAME "pressure_sensor"
53 #define PRESSURE_SENSORHUB_POLL_NODE_NAME "pressure_poll_delay"
55 static sensor_info_t sensor_info = {
58 type: SENSOR_DEVICE_PRESSURE,
59 event_type: (SENSOR_DEVICE_PRESSURE << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
60 model_name: MODEL_NAME,
64 resolution: RAW_DATA_UNIT,
65 min_interval: MIN_INTERVAL,
66 max_batch_count: MAX_BATCH_COUNT,
67 wakeup_supported: false
70 pressure_device::pressure_device()
74 , m_sea_level_pressure(SEA_LEVEL_PRESSURE)
75 , m_polling_interval(1000)
77 , m_sensorhub_controlled(false)
79 const std::string sensorhub_interval_node_name = PRESSURE_SENSORHUB_POLL_NODE_NAME;
81 node_info_query query;
84 query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
85 query.sensor_type = SENSOR_TYPE_PRESSURE;
86 query.key = INPUT_NAME;
87 query.iio_enable_node_name = "pressure_enable";
88 query.sensorhub_interval_node_name = sensorhub_interval_node_name;
90 if (!util::get_node_info(query, info)) {
91 _E("Failed to get node info");
95 util::show_node_info(info);
97 m_method = info.method;
98 m_data_node = info.data_node_path;
99 m_enable_node = info.enable_node_path;
100 m_interval_node = info.interval_node_path;
102 m_node_handle = open(m_data_node.c_str(), O_RDONLY);
104 if (m_node_handle < 0) {
105 _ERRNO(errno, _E, "pressure handle open fail for pressure sensor");
109 if (m_method == INPUT_EVENT_METHOD) {
110 if (!util::set_monotonic_clock(m_node_handle))
113 update_value = [=]() {
114 return this->update_value_input_event();
117 if (!info.buffer_length_node_path.empty())
118 util::set_node_value(info.buffer_length_node_path, 480);
120 if (!info.buffer_enable_node_path.empty())
121 util::set_node_value(info.buffer_enable_node_path, 1);
123 update_value = [=]() {
124 return this->update_value_iio();
128 _I("pressure_device is created!");
131 pressure_device::~pressure_device()
133 close(m_node_handle);
136 _I("pressure_device is destroyed!");
139 int pressure_device::get_poll_fd(void)
141 return m_node_handle;
144 int pressure_device::get_sensors(const sensor_info_t **sensors)
146 *sensors = &sensor_info;
151 bool pressure_device::enable(uint32_t id)
153 util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_PRESSURE_ENABLE_BIT);
154 set_interval(id, m_polling_interval);
157 _I("Enable pressure sensor");
161 bool pressure_device::disable(uint32_t id)
163 util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_PRESSURE_ENABLE_BIT);
165 _I("Disable pressure sensor");
169 bool pressure_device::set_interval(uint32_t id, unsigned long val)
171 unsigned long long polling_interval_ns;
173 polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
175 if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
176 _E("Failed to set polling resource: %s", m_interval_node.c_str());
180 _I("Interval is changed from %lu ms to %lu ms", m_polling_interval, val);
181 m_polling_interval = val;
185 bool pressure_device::update_value_input_event(void)
187 int pressure_raw[3] = {0, };
188 bool pressure = false;
189 bool sea_level = false;
190 bool temperature = false;
191 int read_input_cnt = 0;
192 const int INPUT_MAX_BEFORE_SYN = 10;
193 unsigned long long fired_time = 0;
196 struct input_event pressure_event;
197 _D("pressure event detection!");
199 while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
200 int len = read(m_node_handle, &pressure_event, sizeof(pressure_event));
201 if (len != sizeof(pressure_event)) {
202 _E("pressure_file read fail, read_len = %d\n", len);
208 if (pressure_event.type == EV_REL) {
209 switch (pressure_event.code) {
211 pressure_raw[0] = (int)pressure_event.value;
215 pressure_raw[1] = (int)pressure_event.value;
219 pressure_raw[2] = (int)pressure_event.value;
223 _E("pressure_event event[type = %d, code = %d] is unknown.", pressure_event.type, pressure_event.code);
227 } else if (pressure_event.type == EV_SYN) {
229 fired_time = util::get_timestamp(&pressure_event.time);
231 _E("pressure_event event[type = %d, code = %d] is unknown.", pressure_event.type, pressure_event.code);
237 _E("EV_SYN didn't come until %d inputs had come", read_input_cnt);
242 m_pressure = pressure_raw[0];
244 m_sea_level_pressure = pressure_raw[1];
246 m_temperature = pressure_raw[2];
248 m_fired_time = fired_time;
250 _D("m_pressure = %d, sea_level = %f, temperature = %d, time = %lluus", m_pressure, m_sea_level_pressure, m_temperature, m_fired_time);
255 bool pressure_device::update_value_iio(void)
260 int32_t sea_level_pressure;
262 } __attribute__((packed)) data;
266 pfd.fd = m_node_handle;
267 pfd.events = POLLIN | POLLERR;
270 int ret = poll(&pfd, 1, -1);
273 _ERRNO(errno, _E, "Failed to poll from m_node_handle:%d", m_node_handle);
276 _E("poll timeout m_node_handle:%d", m_node_handle);
280 if (pfd.revents & POLLERR) {
281 _E("poll exception occurred! m_node_handle:%d", m_node_handle);
285 if (!(pfd.revents & POLLIN)) {
286 _E("poll nothing to read! m_node_handle:%d, pfd.revents = %d", m_node_handle, pfd.revents);
290 int len = read(m_node_handle, &data, sizeof(data));
292 if (len != sizeof(data)) {
293 _E("Failed to read data, m_node_handle:%d read_len:%d", m_node_handle, len);
297 m_pressure = data.pressure;
298 m_temperature = data.temperature;
299 m_sea_level_pressure = (float)data.sea_level_pressure;
300 m_fired_time = NSEC_TO_MSEC(data.timestamp);
302 _I("m_pressure = %d, m_temperature = %d, m_sea_level_pressure = %f, time = %lluus", m_pressure, m_temperature, m_sea_level_pressure, m_fired_time);
307 int pressure_device::read_fd(uint32_t **ids)
309 if (!update_value()) {
310 _D("Failed to update value");
315 event_ids.push_back(sensor_info.id);
317 *ids = &event_ids[0];
319 return event_ids.size();
322 int pressure_device::get_data(uint32_t id, sensor_data_t **data, int *length)
324 sensor_data_t *sensor_data;
325 sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
326 retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
328 sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
329 sensor_data->timestamp = m_fired_time;
330 sensor_data->value_count = 3;
331 sensor_data->values[0] = m_pressure;
332 sensor_data->values[1] = (float)m_sea_level_pressure;
333 sensor_data->values[2] = m_temperature;
335 raw_to_base(sensor_data);
338 *length = sizeof(sensor_data_t);
343 void pressure_device::raw_to_base(sensor_data_t *data)
345 data->values[0] = data->values[0] * RAW_DATA_UNIT;
346 m_sea_level_pressure = data->values[1] * SEA_LEVEL_RESOLUTION;
347 data->values[1] = pressure_to_altitude(data->values[0]);
348 data->values[2] = data->values[2] * TEMPERATURE_RESOLUTION + TEMPERATURE_OFFSET;
351 float pressure_device::pressure_to_altitude(float pressure)
353 float sea_level_pressure = m_sea_level_pressure;
355 if (sea_level_pressure < SEA_LEVEL_EPSILON && sea_level_pressure > -SEA_LEVEL_EPSILON)
356 sea_level_pressure = SEA_LEVEL_PRESSURE * SEA_LEVEL_RESOLUTION;
358 return 44330.0f * (1.0f - pow(pressure/sea_level_pressure, 1.0f/5.255f));