sensor-hal-tm1: sync with sensor-hal-tw1 HAL
[platform/adaptation/tm1/sensor-hal-tm1.git] / src / util.cpp
1 /*
2  * Copyright (c) 2016 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 <unistd.h>
19 #include <dirent.h>
20 #include <string.h>
21 #include <fstream>
22 #include <util.h>
23 #include <sensor_log.h>
24
25 using std::ifstream;
26 using std::ofstream;
27 using std::fstream;
28 using std::string;
29
30 #define PREFIX_EVENT "event"
31
32 static bool get_event_num(const string &input_path, string &event_num)
33 {
34         const string event_prefix = PREFIX_EVENT;
35         DIR *dir = NULL;
36         struct dirent dir_entry;
37         struct dirent *result = NULL;
38         std::string node_name;
39         int error;
40         bool find = false;
41
42         dir = opendir(input_path.c_str());
43         if (!dir) {
44                 ERR("Failed to open dir: %s", input_path.c_str());
45                 return false;
46         }
47
48         int prefix_size = event_prefix.size();
49
50         while (true) {
51                 error = readdir_r(dir, &dir_entry, &result);
52
53                 if (error != 0)
54                         continue;
55
56                 if (result == NULL)
57                         break;
58
59                 node_name = std::string(dir_entry.d_name);
60
61                 if (node_name.compare(0, prefix_size, event_prefix) != 0)
62                         continue;
63
64                 event_num = node_name.substr(prefix_size, node_name.size() - prefix_size);
65                 find = true;
66                 break;
67         }
68
69         closedir(dir);
70
71         return find;
72 }
73
74 static bool get_iio_node_info(const string& enable_node_name, const string& device_num, node_info &info)
75 {
76         const string base_dir = string("/sys/bus/iio/devices/iio:device") + device_num + string("/");
77
78         info.data_node_path = string("/dev/iio:device") + device_num;
79         info.enable_node_path = base_dir + enable_node_name;
80         info.interval_node_path = base_dir + string("sampling_frequency");
81         info.buffer_enable_node_path = base_dir + string("buffer/enable");
82         info.buffer_length_node_path = base_dir + string("buffer/length");
83         info.trigger_node_path = base_dir + string("trigger/current_trigger");
84
85         return true;
86 }
87
88 static bool get_sensorhub_iio_node_info(const string &interval_node_name, const string& device_num, node_info &info)
89 {
90         const string base_dir = string("/sys/bus/iio/devices/iio:device") + device_num + string("/");
91         const string hub_dir = "/sys/class/sensors/ssp_sensor/";
92
93         info.data_node_path = string("/dev/iio:device") + device_num;
94         info.enable_node_path = hub_dir + string("enable");
95         info.interval_node_path = hub_dir + interval_node_name;
96         info.buffer_enable_node_path = base_dir + string("buffer/enable");
97         info.buffer_length_node_path = base_dir + string("buffer/length");
98         return true;
99 }
100
101 static bool get_input_event_node_info(const string& device_num, node_info &info)
102 {
103         string base_dir;
104         string event_num;
105
106         base_dir = string("/sys/class/input/input") + device_num + string("/");
107
108         if (!get_event_num(base_dir, event_num))
109                 return false;
110
111         info.data_node_path = string("/dev/input/event") + event_num;
112
113         info.enable_node_path = base_dir + string("enable");
114         info.interval_node_path = base_dir + string("poll_delay");
115         return true;
116 }
117
118 static bool get_sensorhub_input_event_node_info(const string &interval_node_name, const string& device_num, node_info &info)
119 {
120         const string base_dir = "/sys/class/sensors/ssp_sensor/";
121         string event_num;
122
123         string input_dir = string("/sys/class/input/input") + device_num + string("/");
124
125         if (!get_event_num(input_dir, event_num))
126                 return false;
127
128         info.data_node_path = string("/dev/input/event") + event_num;
129         info.enable_node_path = base_dir + string("enable");
130         info.interval_node_path = base_dir + interval_node_name;
131         return true;
132 }
133
134 static bool get_node_value(const string &node_path, int &value)
135 {
136         ifstream node(node_path, ifstream::binary);
137
138         if (!node)
139                 return false;
140
141         node >> value;
142
143         return true;
144 }
145
146 static bool get_input_method(const string &key, int &method, string &device_num)
147 {
148         input_method_info input_info[2] = {
149                 {INPUT_EVENT_METHOD, "/sys/class/input/", "input"},
150                 {IIO_METHOD, "/sys/bus/iio/devices/", "iio:device"}
151         };
152
153         const int input_info_len = sizeof(input_info)/sizeof(input_info[0]);
154         size_t prefix_size;
155         std::string name_node, name;
156         std::string d_name;
157         DIR *dir = NULL;
158         struct dirent dir_entry;
159         struct dirent *result = NULL;
160         int error;
161         bool find = false;
162
163         for (int i = 0; i < input_info_len; ++i) {
164
165                 prefix_size = input_info[i].prefix.size();
166
167                 dir = opendir(input_info[i].dir_path.c_str());
168                 if (!dir) {
169                         ERR("Failed to open dir: %s", input_info[i].dir_path.c_str());
170                         return false;
171                 }
172
173                 find = false;
174
175                 while (true) {
176                         error = readdir_r(dir, &dir_entry, &result);
177
178                         if (error != 0)
179                                 continue;
180
181                         if (result == NULL)
182                                 break;
183
184                         d_name = std::string(dir_entry.d_name);
185
186                         if (d_name.compare(0, prefix_size, input_info[i].prefix) != 0)
187                                 continue;
188
189                         name_node = input_info[i].dir_path + d_name + string("/name");
190
191                         ifstream infile(name_node.c_str());
192                         if (!infile)
193                                 continue;
194
195                         infile >> name;
196
197                         if (name != key)
198                                 continue;
199
200                         device_num = d_name.substr(prefix_size, d_name.size() - prefix_size);
201                         find = true;
202                         method = input_info[i].method;
203                         break;
204                 }
205
206                 closedir(dir);
207
208                 if (find)
209                         break;
210         }
211
212         return find;
213 }
214
215 bool util::set_monotonic_clock(int fd)
216 {
217 #ifdef EVIOCSCLOCKID
218         int clockId = CLOCK_MONOTONIC;
219         if (ioctl(fd, EVIOCSCLOCKID, &clockId) != 0) {
220                 _E("Fail to set monotonic timestamp for fd[%d]", fd);
221                 return false;
222         }
223 #endif
224         return true;
225 }
226
227 bool util::set_enable_node(const string &node_path, bool sensorhub_controlled, bool enable, int enable_bit)
228 {
229         int prev_status, status;
230
231         if (!get_node_value(node_path, prev_status)) {
232                 ERR("Failed to get node: %s", node_path.c_str());
233                 return false;
234         }
235
236         int _enable_bit = sensorhub_controlled ? enable_bit : 0;
237
238         if (enable)
239                 status = prev_status | (1 << _enable_bit);
240         else
241                 status = prev_status & (~(1 << _enable_bit));
242
243         if (!set_node_value(node_path, status)) {
244                 ERR("Failed to set node: %s", node_path.c_str());
245                 return false;
246         }
247
248         return true;
249 }
250
251 unsigned long long util::get_timestamp(void)
252 {
253         struct timespec t;
254         clock_gettime(CLOCK_MONOTONIC, &t);
255         return ((unsigned long long)(t.tv_sec)*1000000000LL + t.tv_nsec) / 1000;
256 }
257
258 unsigned long long util::get_timestamp(timeval *t)
259 {
260         if (!t) {
261                 ERR("t is NULL");
262                 return 0;
263         }
264
265         return ((unsigned long long)(t->tv_sec)*1000000LL +t->tv_usec);
266 }
267
268 bool util::is_sensorhub_controlled(const string &key)
269 {
270         string key_node = string("/sys/class/sensors/ssp_sensor/") + key;
271
272         if (access(key_node.c_str(), F_OK) == 0)
273                 return true;
274
275         return false;
276 }
277
278 bool util::get_node_info(const node_info_query &query, node_info &info)
279 {
280         int method;
281         string device_num;
282
283         if (!get_input_method(query.key, method, device_num)) {
284                 ERR("Failed to get input method for %s", query.key.c_str());
285                 return false;
286         }
287
288         info.method = method;
289
290         if (method == IIO_METHOD) {
291                 if (query.sensorhub_controlled)
292                         return get_sensorhub_iio_node_info(query.sensorhub_interval_node_name, device_num, info);
293                 else
294                         return get_iio_node_info(query.iio_enable_node_name, device_num, info);
295         } else {
296                 if (query.sensorhub_controlled)
297                         return get_sensorhub_input_event_node_info(query.sensorhub_interval_node_name, device_num, info);
298                 else
299                         return get_input_event_node_info(device_num, info);
300         }
301 }
302
303 void util::show_node_info(node_info &info)
304 {
305         if (info.data_node_path.size())
306                 INFO("Data node: %s", info.data_node_path.c_str());
307         if (info.enable_node_path.size())
308                 INFO("Enable node: %s", info.enable_node_path.c_str());
309         if (info.interval_node_path.size())
310                 INFO("Interval node: %s", info.interval_node_path.c_str());
311         if (info.buffer_enable_node_path.size())
312                 INFO("Buffer enable node: %s", info.buffer_enable_node_path.c_str());
313         if (info.buffer_length_node_path.size())
314                 INFO("Buffer length node: %s", info.buffer_length_node_path.c_str());
315         if (info.trigger_node_path.size())
316                 INFO("Trigger node: %s", info.trigger_node_path.c_str());
317 }
318
319 bool util::set_node_value(const string &node_path, int value)
320 {
321         ofstream node(node_path, ofstream::binary);
322
323         if (!node)
324                 return false;
325
326         node << value;
327
328         return true;
329 }
330
331 bool util::set_node_value(const string &node_path, unsigned long long value)
332 {
333         ofstream node(node_path, ofstream::binary);
334
335         if (!node)
336                 return false;
337
338         node << value;
339
340         return true;
341 }