sensor hal for tw3
[platform/adaptation/tw3/sensor-hal-tw3.git] / src / hrm_raw / hrm_raw_device.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 #include "hrm_raw_device.h"
19
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <linux/input.h>
23
24 #include "macro.h"
25 #include "util.h"
26 #include "sensor_common.h"
27 #include "sensor_log.h"
28
29 #define MODEL_NAME "AD45251"
30 #define VENDOR "ANALOG DEVICES"
31 #define MIN_RANGE 0
32 #define MAX_RANGE 1000
33 #define RESOLUTION 1
34 #define RAW_DATA_UNIT 1
35 #define MIN_INTERVAL 1
36 #define MAX_BATCH_COUNT 0
37
38 #define SENSOR_NAME "SENSOR_HRM_RAW"
39 #define SENSOR_TYPE_HRM_RAW "HRM_RAW"
40
41 #define INPUT_NAME "hrm_raw_sensor"
42 #define HRM_SENSORHUB_POLL_NODE_NAME "hrm_poll_delay"
43
44 #define INDEX_HRM_RAW 0x1
45 #define INDEX_HRM_LED_GREEN 0x2
46
47 #define POLL_1HZ_MS 1000
48
49 #define INPUT_MAX_BEFORE_SYN 20
50 #define INPUT_EVENT_BIAS 1
51 #define INPUT_VALUE_COUNT 10
52 #define MAX_ID 0x3
53
54
55 static sensor_info_t sensor_info[] = {
56         {
57                 id: INDEX_HRM_RAW,
58                 name: SENSOR_NAME,
59                 type: SENSOR_DEVICE_HRM_RAW,
60                 event_type: (SENSOR_DEVICE_HRM_RAW << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
61                 model_name: MODEL_NAME,
62                 vendor: VENDOR,
63                 min_range: MIN_RANGE,
64                 max_range: MAX_RANGE,
65                 resolution: RAW_DATA_UNIT,
66                 min_interval: MIN_INTERVAL,
67                 max_batch_count: MAX_BATCH_COUNT,
68                 wakeup_supported: false
69         },
70         {
71                 id: INDEX_HRM_LED_GREEN,
72                 name: "HRM LED GREEN SENSOR",
73                 type: SENSOR_DEVICE_HRM_LED_GREEN,
74                 event_type: (SENSOR_DEVICE_HRM_LED_GREEN << SENSOR_EVENT_SHIFT) | RAW_DATA_EVENT,
75                 model_name: MODEL_NAME,
76                 vendor: VENDOR,
77                 min_range: MIN_RANGE,
78                 max_range: MAX_RANGE,
79                 resolution: RAW_DATA_UNIT,
80                 min_interval: MIN_INTERVAL,
81                 max_batch_count: MAX_BATCH_COUNT,
82                 wakeup_supported: false
83         }
84 };
85
86 hrm_raw_device::hrm_raw_device()
87 : m_node_handle(-1)
88 , m_data()
89 , m_polling_interval(POLL_1HZ_MS)
90 , m_raw_interval(POLL_1HZ_MS)
91 , m_led_green_interval(POLL_1HZ_MS)
92 , m_interval_supported(false)
93 , m_sensorhub_controlled(false)
94 , m_enable(0)
95 {
96         const std::string sensorhub_interval_node_name = HRM_SENSORHUB_POLL_NODE_NAME;
97
98         node_info_query query;
99         node_info info;
100
101         query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
102         query.sensor_type = SENSOR_TYPE_HRM_RAW;
103         query.key = INPUT_NAME;
104         query.iio_enable_node_name = "hrm_raw_enable";
105         query.sensorhub_interval_node_name = sensorhub_interval_node_name;
106
107         if (!util::get_node_info(query, info)) {
108                 _E("Failed to get node info");
109                 throw ENXIO;
110         }
111
112         util::show_node_info(info);
113
114         m_data_node = info.data_node_path;
115         m_enable_node = info.enable_node_path;
116         m_interval_node = info.interval_node_path;
117
118         if (access(m_interval_node.c_str(), F_OK) == 0)
119                 m_interval_supported = true;
120
121         m_node_handle = open(m_data_node.c_str(), O_RDONLY);
122
123         if (m_node_handle < 0) {
124                 _ERRNO(errno, _E, "Failed to open node[%s]", m_data_node.c_str());
125                 throw ENXIO;
126         }
127
128         if (!util::set_monotonic_clock(m_node_handle))
129                 throw ENXIO;
130
131         _I("hrm_raw_device is created");
132 }
133
134 hrm_raw_device::~hrm_raw_device()
135 {
136         close(m_node_handle);
137         m_node_handle = -1;
138
139         _I("hrm_raw_device is destroyed");
140 }
141
142 int hrm_raw_device::get_poll_fd(void)
143 {
144         return m_node_handle;
145 }
146
147 int hrm_raw_device::get_sensors(const sensor_info_t **sensors)
148 {
149         retvm_if(sensors == NULL || sensors == nullptr, SENSOR_ERROR_INVALID_PARAMETER, "%s:NULL interface", SENSOR_NAME);
150         *sensors = sensor_info;
151
152         return 2;
153 }
154
155 bool hrm_raw_device::enable(uint32_t id)
156 {
157         retvm_if(id == 0 || id > MAX_ID, false, "%s:Invalid ID Received", SENSOR_NAME);
158
159         ++m_enable;
160
161         if (m_enable > 1)
162                 return true;
163
164         util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_HRM_RAW_ENABLE_BIT);
165         if (m_interval_supported)
166                 set_interval(id, m_polling_interval);
167
168         m_data.timestamp = 0;
169         _I("Enable HRM Raw sensor");
170         return true;
171 }
172
173 bool hrm_raw_device::disable(uint32_t id)
174 {
175         retvm_if(id == 0 || id > MAX_ID, false, "%s:Invalid ID Received", SENSOR_NAME);
176
177         --m_enable;
178
179         if (m_enable > 0)
180                 return true;
181
182         util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_HRM_RAW_ENABLE_BIT);
183
184         m_enable = 0;
185         _I("Disable HRM Raw sensor");
186         return true;
187 }
188
189 bool hrm_raw_device::set_interval(uint32_t id, unsigned long val)
190 {
191         unsigned long interval = 100;
192         unsigned long long polling_interval_ns;
193         retvm_if(id == 0 || id > MAX_ID, false, "%s:Invalid ID Received", SENSOR_NAME);
194
195         if (!m_interval_supported)
196                 return true;
197
198         if (id == INDEX_HRM_LED_GREEN)
199                 interval = (val > m_raw_interval)?m_raw_interval:val;
200         else
201                 interval = (val > m_led_green_interval)?m_led_green_interval:val;
202
203         polling_interval_ns = ((unsigned long long)(interval) * 1000llu * 1000llu);
204
205         if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
206                 _E("Failed to set polling resource: %s", m_interval_node.c_str());
207                 return false;
208         }
209
210         _I("Interval is changed from %lu ms to %lu ms", m_polling_interval, interval);
211         m_polling_interval = interval;
212
213         if (id == INDEX_HRM_LED_GREEN)
214                 m_led_green_interval = val;
215         else
216                 m_raw_interval = val;
217
218         return true;
219 }
220
221 bool hrm_raw_device::update_value_input_event(void)
222 {
223         bool syn = false;
224         int read_input_cnt = 0;
225         int index = 0;
226         struct input_event hrm_raw_input;
227
228         while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
229                 int len = read(m_node_handle, &hrm_raw_input, sizeof(hrm_raw_input));
230                 if (len != sizeof(hrm_raw_input)) {
231                         _E("hrm_raw_file read fail, read_len = %d", len);
232                         return false;
233                 }
234
235                 ++read_input_cnt;
236
237                 if (hrm_raw_input.type == EV_REL) {
238                         index = hrm_raw_input.code - REL_X;
239
240                         /* Check an avaiable value REL_X(0x00) ~ REL_MISC(0x09) */
241                         if (index >= INPUT_VALUE_COUNT) {
242                                 _E("hrm_raw_input event[type = %d, code = %d] is unknown.", hrm_raw_input.type, index);
243                                 return false;
244                         }
245                         m_data.values[index] = (unsigned int)hrm_raw_input.value - INPUT_EVENT_BIAS;
246                         _I("SRINIEVENT: EV_REL input had come, val:%d, index[%d]", hrm_raw_input.value, index);
247                 } else if (hrm_raw_input.type == EV_SYN) {
248                         syn = true;
249                         m_data.timestamp = util::get_timestamp(&hrm_raw_input.time);
250                         m_data.value_count = INPUT_VALUE_COUNT;
251
252                         _I("SRINIEVENT: EV_SYN input had come, val:%d, index[%d]", hrm_raw_input.value, index);
253                 } else {
254                         _E("hrm_raw_input event[type = %d, code = %d] is unknown.", hrm_raw_input.type, hrm_raw_input.code);
255                         return false;
256                 }
257         }
258
259         if (!syn) {
260                 _E("EV_SYN didn't come until %d inputs had come", read_input_cnt);
261                 return false;
262         }
263         return true;
264 }
265
266 int hrm_raw_device::read_fd(uint32_t **ids)
267 {
268         retvm_if(ids == NULL || ids == nullptr, SENSOR_ERROR_INVALID_PARAMETER, "%s:NULL interface", SENSOR_NAME);
269
270         if (!update_value_input_event()) {
271                 _D("Failed to update value");
272                 return false;
273         }
274
275         event_ids.clear();
276
277         int size = ARRAY_SIZE(sensor_info);
278
279         for (int i = 0; i < size; ++i)
280                 event_ids.push_back(sensor_info[i].id);
281
282         *ids = &event_ids[0];
283
284         return event_ids.size();
285 }
286
287 int hrm_raw_device::get_data(uint32_t id, sensor_data_t **data, int *length)
288 {
289         int remains = 1;
290         sensor_data_t *sensor_data;
291         retvm_if(data == NULL || data == nullptr, SENSOR_ERROR_INVALID_PARAMETER, "%s:NULL data interface", SENSOR_NAME);
292         retvm_if(length == NULL || length == nullptr, SENSOR_ERROR_INVALID_PARAMETER, "%s:NULL length interface", SENSOR_NAME);
293         retvm_if(id == 0 || id > MAX_ID, SENSOR_ERROR_INVALID_PARAMETER, "%s:Invalid ID Received", SENSOR_NAME);
294
295         sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
296         retvm_if(!sensor_data, -ENOMEM, "Memory allocation failed");
297
298         sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
299         sensor_data->timestamp = m_data.timestamp;
300
301         if (id == INDEX_HRM_LED_GREEN) {
302                 sensor_data->value_count = 1;
303                 sensor_data->values[0] = m_data.values[5];
304         } else {
305                 sensor_data->value_count = m_data.value_count;
306                 memcpy(sensor_data->values, m_data.values, m_data.value_count * sizeof(m_data.values[0]));
307         }
308         _I("SRINIHAL: Sensor Data:%.2f, id: %d", sensor_data->values[0], id);
309         *data = sensor_data;
310         *length = sizeof(sensor_data_t);
311
312         return --remains;
313 }