Adding AK8975 geo-sensor info in sensors.xml.in required by geo-plugin
[platform/core/system/sensord.git] / src / proxi / proxi_sensor_hal.cpp
1 /*
2  * sensord
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 <fstream>
21 #include <fcntl.h>
22 #include <sys/stat.h>
23 #include <sys/ioctl.h>
24 #include <dirent.h>
25 #include <linux/input.h>
26 #include <cconfig.h>
27 #include <proxi_sensor_hal.h>
28
29 using std::ifstream;
30 using config::CConfig;
31
32 #define NODE_NAME "name"
33 #define NODE_INPUT "input"
34 #define NODE_ENABLE "enable"
35 #define SENSOR_NODE "/sys/class/sensors/"
36 #define SENSORHUB_NODE "/sys/class/sensors/ssp_sensor/"
37 #define INPUT_DEVICE_NODE "/sys/class/input/"
38 #define DEV_INPUT_NODE "/dev/input/event/"
39
40 #define INITIAL_VALUE -1
41 #define INITIAL_TIME 0
42 #define PROXI_CODE      0x0019
43
44 #define SENSOR_TYPE_PROXI               "PROXI"
45 #define ELEMENT_NAME                    "NAME"
46 #define ELEMENT_VENDOR                  "VENDOR"
47 #define ATTR_VALUE                              "value"
48
49 #define INPUT_NAME      "proximity_sensor"
50
51 proxi_sensor_hal::proxi_sensor_hal()
52 : m_state(PROXIMITY_STATE_FAR)
53 , m_node_handle(INITIAL_VALUE)
54 , m_fired_time(INITIAL_TIME)
55 , m_sensorhub_supported(false)
56 {
57         if (!check_hw_node()) {
58                 ERR("check_hw_node() fail");
59                 throw ENXIO;
60         }
61
62         CConfig &config = CConfig::get_instance();
63
64         if (!config.get(SENSOR_TYPE_PROXI, m_model_id, ELEMENT_VENDOR, m_vendor)) {
65                 ERR("[VENDOR] is empty");
66                 throw ENXIO;
67         }
68
69         INFO("m_vendor = %s", m_vendor.c_str());
70
71         if (!config.get(SENSOR_TYPE_PROXI, m_model_id, ELEMENT_NAME, m_chip_name)) {
72                 ERR("[NAME] is empty");
73                 throw ENXIO;
74         }
75
76         INFO("m_chip_name = %s", m_chip_name.c_str());
77
78         if ((m_node_handle = open(m_resource.c_str(), O_RDWR)) < 0) {
79                 ERR("Failed to open handle(%d)", m_node_handle);
80                 throw ENXIO;
81         }
82
83         int clockId = CLOCK_MONOTONIC;
84
85         if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0) {
86                 ERR("Fail to set monotonic timestamp for %s", m_resource.c_str());
87                 throw ENXIO;
88         }
89
90         INFO("proxi_sensor_hal is created!");
91 }
92
93 proxi_sensor_hal::~proxi_sensor_hal()
94 {
95         close(m_node_handle);
96         m_node_handle = INITIAL_VALUE;
97
98         INFO("proxi_sensor_hal is destroyed!");
99 }
100
101 string proxi_sensor_hal::get_model_id(void)
102 {
103         return m_model_id;
104 }
105
106 sensor_type_t proxi_sensor_hal::get_type(void)
107 {
108         return PROXIMITY_SENSOR;
109 }
110
111 bool proxi_sensor_hal::enable_resource(string &resource_node, bool enable)
112 {
113         int prev_status, status;
114         FILE *fp = NULL;
115         fp = fopen(resource_node.c_str(), "r");
116
117         if (!fp) {
118                 ERR("Fail to open a resource file: %s", resource_node.c_str());
119                 return false;
120         }
121
122         if (fscanf(fp, "%d", &prev_status) < 0) {
123                 ERR("Failed to get data from %s", resource_node.c_str());
124                 fclose(fp);
125                 return false;
126         }
127
128         fclose(fp);
129
130         if (enable) {
131                 if (m_sensorhub_supported)
132                         status = prev_status | (1 << SENSORHUB_PROXIMITY_ENABLE_BIT);
133                 else
134                         status = 1;
135         } else {
136                 if (m_sensorhub_supported)
137                         status = prev_status ^ (1 << SENSORHUB_PROXIMITY_ENABLE_BIT);
138                 else
139                         status = 0;
140         }
141
142         fp = fopen(resource_node.c_str(), "w");
143
144         if (!fp) {
145                 ERR("Failed to open a resource file: %s", resource_node.c_str());
146                 return false;
147         }
148
149         if (fprintf(fp, "%d", status) < 0) {
150                 ERR("Failed to enable a resource file: %s", resource_node.c_str());
151                 fclose(fp);
152                 return false;
153         }
154
155         if (fp)
156                 fclose(fp);
157
158         return true;
159 }
160
161 bool proxi_sensor_hal::enable(void)
162 {
163         AUTOLOCK(m_mutex);
164
165         enable_resource(m_enable_resource, true);
166
167         m_fired_time = 0;
168         INFO("Proxi sensor real starting");
169         return true;
170 }
171
172 bool proxi_sensor_hal::disable(void)
173 {
174         AUTOLOCK(m_mutex);
175
176         enable_resource(m_enable_resource, false);
177         INFO("Proxi sensor real stopping");
178         return true;
179 }
180
181 bool proxi_sensor_hal::update_value(bool wait)
182 {
183         struct input_event proxi_event;
184         fd_set readfds, exceptfds;
185
186         FD_ZERO(&readfds);
187         FD_ZERO(&exceptfds);
188         FD_SET(m_node_handle, &readfds);
189         FD_SET(m_node_handle, &exceptfds);
190
191         int ret;
192         ret = select(m_node_handle + 1, &readfds, NULL, &exceptfds, NULL);
193
194         if (ret == -1) {
195                 ERR("select error:%s m_node_handle:d", strerror(errno), m_node_handle);
196                 return false;
197         } else if (!ret) {
198                 DBG("select timeout");
199                 return false;
200         }
201
202         if (FD_ISSET(m_node_handle, &exceptfds)) {
203                 ERR("select exception occurred!");
204                 return false;
205         }
206
207         if (FD_ISSET(m_node_handle, &readfds)) {
208                 INFO("proxi event detection!");
209                 int len = read(m_node_handle, &proxi_event, sizeof(proxi_event));
210
211                 if (len == -1) {
212                         DBG("read(m_node_handle) is error:%s.", strerror(errno));
213                         return false;
214                 }
215
216                 DBG("read event,  len : %d , type : %x , code : %x , value : %x", len, proxi_event.type, proxi_event.code, proxi_event.value);
217
218                 if ((proxi_event.type == EV_ABS) && (proxi_event.code == PROXI_CODE)) {
219                         AUTOLOCK(m_value_mutex);
220
221                         if (proxi_event.value == PROXIMITY_NODE_STATE_FAR) {
222                                 INFO("PROXIMITY_STATE_FAR state occured");
223                                 m_state = PROXIMITY_STATE_FAR;
224                         } else if (proxi_event.value == PROXIMITY_NODE_STATE_NEAR) {
225                                 INFO("PROXIMITY_STATE_NEAR state occured");
226                                 m_state = PROXIMITY_STATE_NEAR;
227                         } else {
228                                 ERR("PROXIMITY_STATE Unknown: %d", proxi_event.value);
229                                 return false;
230                         }
231
232                         m_fired_time = sensor_hal::get_timestamp(&proxi_event.time);
233                 } else {
234                         return false;
235                 }
236         } else {
237                 ERR("select nothing to read!!!");
238                 return false;
239         }
240
241         return true;
242 }
243
244 bool proxi_sensor_hal::is_data_ready(bool wait)
245 {
246         bool ret;
247         ret = update_value(wait);
248         return ret;
249 }
250
251 int proxi_sensor_hal::get_sensor_data(sensor_data_t &data)
252 {
253         AUTOLOCK(m_value_mutex);
254         data.data_accuracy = SENSOR_ACCURACY_UNDEFINED;
255         data.data_unit_idx = SENSOR_UNIT_STATE_ON_OFF;
256         data.timestamp = m_fired_time;
257         data.values_num = 1;
258         data.values[0] = m_state;
259         return 0;
260 }
261
262 bool proxi_sensor_hal::get_properties(sensor_properties_t &properties)
263 {
264         properties.sensor_unit_idx = SENSOR_UNIT_STATE_ON_OFF;
265         properties.sensor_min_range = 0;
266         properties.sensor_max_range = 1;
267         snprintf(properties.sensor_name,   sizeof(properties.sensor_name), "%s", m_chip_name.c_str());
268         snprintf(properties.sensor_vendor, sizeof(properties.sensor_vendor), "%s", m_vendor.c_str());
269         properties.sensor_resolution = 1;
270         return true;
271 }
272
273 bool proxi_sensor_hal::is_sensorhub_supported(void)
274 {
275         DIR *main_dir = NULL;
276         main_dir = opendir(SENSORHUB_NODE);
277
278         if (!main_dir) {
279                 INFO("Sensor Hub is not supported");
280                 return false;
281         }
282
283         INFO("It supports sensor hub");
284         closedir(main_dir);
285         return true;
286 }
287
288 bool proxi_sensor_hal::check_hw_node(void)
289 {
290         string name_node;
291         string hw_name;
292         DIR *main_dir = NULL;
293         struct dirent *dir_entry = NULL;
294         bool find_node = false;
295
296         INFO("======================start check_hw_node=============================");
297
298         m_sensorhub_supported = is_sensorhub_supported();
299         main_dir = opendir(SENSOR_NODE);
300
301         if (!main_dir) {
302                 ERR("Directory open failed to collect data");
303                 return false;
304         }
305
306         while ((!find_node) && (dir_entry = readdir(main_dir))) {
307                 if ((strncasecmp(dir_entry->d_name , ".", 1 ) != 0) && (strncasecmp(dir_entry->d_name , "..", 2 ) != 0) && (dir_entry->d_ino != 0)) {
308                         name_node = string(SENSOR_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME);
309
310                         ifstream infile(name_node.c_str());
311
312                         if (!infile)
313                                 continue;
314
315                         infile >> hw_name;
316
317                         if (CConfig::get_instance().is_supported(SENSOR_TYPE_PROXI, hw_name) == true) {
318                                 m_name = m_model_id = hw_name;
319                                 INFO("m_model_id = %s", m_model_id.c_str());
320                                 find_node = true;
321                                 break;
322                         }
323                 }
324         }
325
326         closedir(main_dir);
327
328         if (find_node) {
329                 main_dir = opendir(INPUT_DEVICE_NODE);
330
331                 if (!main_dir) {
332                         ERR("Directory open failed to collect data");
333                         return false;
334                 }
335
336                 find_node = false;
337
338                 while ((!find_node) && (dir_entry = readdir(main_dir))) {
339                         if (strncasecmp(dir_entry->d_name, NODE_INPUT, 5) == 0) {
340                                 name_node = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME);
341                                 ifstream infile(name_node.c_str());
342
343                                 if (!infile)
344                                         continue;
345
346                                 infile >> hw_name;
347
348                                 if (hw_name == string(INPUT_NAME)) {
349                                         INFO("name_node = %s", name_node.c_str());
350                                         DBG("Find H/W  for proxi_sensor");
351
352                                         find_node = true;
353                                         string dir_name;
354                                         dir_name = string(dir_entry->d_name);
355                                         unsigned found = dir_name.find_first_not_of(NODE_INPUT);
356                                         m_resource = string(DEV_INPUT_NODE) + dir_name.substr(found);
357
358                                         if (m_sensorhub_supported)
359                                                 m_enable_resource = string(SENSORHUB_NODE) + string(NODE_ENABLE);
360                                         else
361                                                 m_enable_resource = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_ENABLE);
362
363                                         break;
364                                 }
365                         }
366                 }
367
368                 closedir(main_dir);
369         }
370
371         if (find_node) {
372                 INFO("m_resource = %s", m_resource.c_str());
373                 INFO("m_enable_resource = %s", m_enable_resource.c_str());
374         }
375
376         return find_node;
377 }
378
379 extern "C" void *create(void)
380 {
381         proxi_sensor_hal *inst;
382
383         try {
384                 inst = new proxi_sensor_hal();
385         } catch (int err) {
386                 ERR("Failed to create proxi_sensor_hal class, errno : %d, errstr : %s", err, strerror(err));
387                 return NULL;
388         }
389
390         return (void *)inst;
391 }
392
393 extern "C" void destroy(void *inst)
394 {
395         delete (proxi_sensor_hal *)inst;
396 }