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