sensor-hal: rename interface of HAL for managing it easily
[platform/adaptation/tm1/sensor-hal-tm1.git] / src / hrm_led_red / bio_led_red_sensor_hal.cpp
1 /*
2  * bio_led_red_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 <bio_led_red_sensor_hal.h>
25 #include <sys/ioctl.h>
26 #include <fstream>
27
28 using std::ifstream;
29 using std::string;
30
31 #define SENSOR_TYPE_BIO_LED_RED "BIO_LED_RED"
32 #define ELEMENT_NAME                    "NAME"
33 #define ELEMENT_VENDOR                  "VENDOR"
34 #define ATTR_VALUE                              "value"
35 #define PATH_LED_RED_ENABLE             "/sys/class/sensors/hrm_sensor/led_current1";
36 #define LED_RED_ENABLE_VALUE    255
37
38 #define BIAS    1
39
40 bio_led_red_sensor_hal::bio_led_red_sensor_hal()
41 : m_polling_interval(POLL_1HZ_MS)
42 , m_bio_led_red(0)
43 , m_fired_time(0)
44 , m_node_handle(-1)
45 {
46         const string sensorhub_interval_node_name = "hrm_poll_delay";
47         csensor_config &config = csensor_config::get_instance();
48
49         node_info_query query;
50         node_info info;
51
52         if (!find_model_id(SENSOR_TYPE_BIO_LED_RED, m_model_id)) {
53                 ERR("Failed to find model id");
54                 throw ENXIO;
55
56         }
57
58         query.sensorhub_controlled = m_sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name);
59         query.sensor_type = SENSOR_TYPE_BIO_LED_RED;
60         query.key = "hrm_sensor";
61         query.iio_enable_node_name = "hrm_raw_enable";
62         query.sensorhub_interval_node_name = sensorhub_interval_node_name;
63
64         if (!get_node_info(query, info)) {
65                 ERR("Failed to get node info");
66                 throw ENXIO;
67         }
68
69         show_node_info(info);
70
71         m_data_node = info.data_node_path;
72         m_enable_node = info.enable_node_path;
73         m_interval_node = info.interval_node_path;
74
75         if (!config.get(SENSOR_TYPE_BIO_LED_RED, m_model_id, ELEMENT_VENDOR, m_vendor)) {
76                 ERR("[VENDOR] is empty\n");
77                 throw ENXIO;
78         }
79
80         INFO("m_vendor = %s", m_vendor.c_str());
81
82         if (!config.get(SENSOR_TYPE_BIO_LED_RED, m_model_id, ELEMENT_NAME, m_chip_name)) {
83                 ERR("[NAME] is empty\n");
84                 throw ENXIO;
85         }
86
87         INFO("m_chip_name = %s\n",m_chip_name.c_str());
88
89         if ((m_node_handle = open(m_data_node.c_str(),O_RDWR)) < 0) {
90                 ERR("Failed to open handle(%d)", m_node_handle);
91                 throw ENXIO;
92         }
93
94         int clockId = CLOCK_MONOTONIC;
95         if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0)
96                 ERR("Fail to set monotonic timestamp for %s", m_data_node.c_str());
97
98         INFO("bio_led_red_sensor_hal is created!\n");
99 }
100
101 bio_led_red_sensor_hal::~bio_led_red_sensor_hal()
102 {
103         close(m_node_handle);
104         m_node_handle = -1;
105
106         INFO("bio_led_red_sensor_hal is destroyed!\n");
107 }
108
109 string bio_led_red_sensor_hal::get_model_id(void)
110 {
111         return m_model_id;
112 }
113
114 sensor_hal_type_t bio_led_red_sensor_hal::get_type(void)
115 {
116         return SENSOR_HAL_TYPE_BIO_LED_RED;
117 }
118
119 bool bio_led_red_sensor_hal::enable(void)
120 {
121         AUTOLOCK(m_mutex);
122         const string led_red_enable_path = PATH_LED_RED_ENABLE;
123
124         set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_BIO_HRM_RAW_ENABLE_BIT);
125
126         if (!set_node_value(led_red_enable_path, LED_RED_ENABLE_VALUE)) {
127                 ERR("Failed to set led red enable node: %s", led_red_enable_path.c_str());
128                 return false;
129         }
130
131         set_interval(m_polling_interval);
132
133         m_fired_time = 0;
134         INFO("bio_led_red sensor starting");
135         return true;
136 }
137
138 bool bio_led_red_sensor_hal::disable(void)
139 {
140         AUTOLOCK(m_mutex);
141
142         set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_BIO_HRM_RAW_ENABLE_BIT);
143
144         INFO("bio_led_red sensor real stopping");
145         return true;
146 }
147
148 bool bio_led_red_sensor_hal::set_interval(unsigned long val)
149 {
150         unsigned long long polling_interval_ns;
151
152         AUTOLOCK(m_mutex);
153
154         polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
155
156         if (!set_node_value(m_interval_node, polling_interval_ns)) {
157                 ERR("Failed to set polling resource: %s\n", m_interval_node.c_str());
158                 return false;
159         }
160
161         INFO("Interval is changed from %dms to %dms]", m_polling_interval, val);
162         m_polling_interval = val;
163         return true;
164
165 }
166
167 bool bio_led_red_sensor_hal::update_value(void)
168 {
169         int bio_led_red_raw = -1;
170         bool bio_led_red = false;
171         int read_input_cnt = 0;
172         const int INPUT_MAX_BEFORE_SYN = 10;
173         unsigned long long fired_time = 0;
174         bool syn = false;
175
176         struct input_event bio_led_red_event;
177         DBG("bio_led_red event detection!");
178
179         while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
180                 int len = read(m_node_handle, &bio_led_red_event, sizeof(bio_led_red_event));
181                 if (len != sizeof(bio_led_red_event)) {
182                         ERR("bio_led_red file read fail, read_len = %d\n",len);
183                         return false;
184                 }
185
186                 ++read_input_cnt;
187
188                 if (bio_led_red_event.type == EV_REL && bio_led_red_event.code == REL_X) {
189                         bio_led_red_raw = (int)bio_led_red_event.value;
190                         bio_led_red = true;
191                 } else if (bio_led_red_event.type == EV_REL) {
192                         ERR("bio_led_red event[type = %d, code = %d] is skipped.", bio_led_red_event.type, bio_led_red_event.code);
193                 } else if (bio_led_red_event.type == EV_SYN) {
194                         syn = true;
195                         fired_time = sensor_hal_base::get_timestamp(&bio_led_red_event.time);
196                 } else {
197                         ERR("bio_led_red event[type = %d, code = %d] is unknown.", bio_led_red_event.type, bio_led_red_event.code);
198                         return false;
199                 }
200         }
201
202         AUTOLOCK(m_value_mutex);
203
204         if (bio_led_red)
205                 m_bio_led_red = bio_led_red_raw - BIAS;
206
207         m_fired_time = fired_time;
208
209         DBG("m_bio_led_red = %d, time = %lluus", m_bio_led_red, m_fired_time);
210
211         return true;
212 }
213
214 bool bio_led_red_sensor_hal::is_data_ready(void)
215 {
216         bool ret;
217         ret = update_value();
218         return ret;
219 }
220
221 int bio_led_red_sensor_hal::get_sensor_data(sensor_data_t &data)
222 {
223         AUTOLOCK(m_value_mutex);
224         data.accuracy = SENSOR_ACCURACY_GOOD;
225         data.timestamp = m_fired_time;
226         data.value_count = 1;
227         data.values[0] = (float) m_bio_led_red;
228
229         return 0;
230 }
231
232 bool bio_led_red_sensor_hal::get_properties(sensor_properties_s &properties)
233 {
234         properties.name = m_chip_name;
235         properties.vendor = m_vendor;
236         properties.min_range = 0.0f;
237         properties.max_range = 1.0f;
238         properties.min_interval = 1;
239         properties.resolution = 1.0f;
240         properties.fifo_count = 0;
241         properties.max_batch_count = 0;
242
243         return true;
244 }