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