Merge "Adding AK8975 geo-sensor info in sensors.xml.in required by geo-plugin" into...
[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 #include <iio_common.h>
29
30 using std::ifstream;
31 using config::CConfig;
32
33 #define INITIAL_VALUE -1
34 #define INITIAL_TIME 0
35
36 #define SENSOR_TYPE_PROXI               "PROXI"
37 #define ELEMENT_NAME                    "NAME"
38 #define ELEMENT_VENDOR                  "VENDOR"
39 #define ATTR_VALUE                              "value"
40
41 #define INPUT_NAME      "proximity_sensor"
42
43 #define NO_FLAG                 0
44 #define ENABLE_VAL              true
45 #define DISABLE_VAL             false
46
47 proxi_sensor_hal::proxi_sensor_hal()
48 : m_state(PROXIMITY_STATE_FAR)
49 , m_node_handle(INITIAL_VALUE)
50 , m_fired_time(INITIAL_TIME)
51 , m_sensorhub_supported(false)
52 {
53         int fd, ret;
54
55         if (!check_hw_node())
56         {
57                 ERR("check_hw_node() fail");
58                 throw ENXIO;
59         }
60
61         CConfig &config = CConfig::get_instance();
62
63         if (!config.get(SENSOR_TYPE_PROXI, m_model_id, ELEMENT_VENDOR, m_vendor))
64         {
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         {
73                 ERR("[NAME] is empty");
74                 throw ENXIO;
75         }
76
77         INFO("m_chip_name = %s", m_chip_name.c_str());
78
79         fd = open(m_event_resource.c_str(), NO_FLAG);
80         if (fd == -1)
81         {
82                 ERR("Could not open event resource");
83                 throw ENXIO;
84         }
85
86         ret = ioctl(fd, IOCTL_IIO_EVENT_FD, &m_event_fd);
87
88         close(fd);
89
90         if ((ret == -1) || (m_event_fd == -1))
91         {
92                 ERR("Failed to retrieve event fd");
93                 throw ENXIO;
94         }
95
96         INFO("proxi_sensor_hal is created!");
97 }
98
99 proxi_sensor_hal::~proxi_sensor_hal()
100 {
101         close(m_event_fd);
102         INFO("proxi_sensor_hal is destroyed!");
103 }
104
105 string proxi_sensor_hal::get_model_id(void)
106 {
107         return m_model_id;
108 }
109
110 sensor_type_t proxi_sensor_hal::get_type(void)
111 {
112         return PROXIMITY_SENSOR;
113 }
114
115 bool proxi_sensor_hal::enable_resource(bool enable)
116 {
117         update_sysfs_num(m_enable_resource.c_str(), enable);
118         return true;
119 }
120
121 bool proxi_sensor_hal::enable(void)
122 {
123         AUTOLOCK(m_mutex);
124
125         enable_resource(ENABLE_VAL);
126
127         m_fired_time = 0;
128         INFO("Proximity sensor real starting");
129         return true;
130 }
131
132 bool proxi_sensor_hal::disable(void)
133 {
134         AUTOLOCK(m_mutex);
135
136         enable_resource(DISABLE_VAL);
137
138         INFO("Proximity sensor real stopping");
139         return true;
140 }
141
142 bool proxi_sensor_hal::update_value(bool wait)
143 {
144         iio_event_t proxi_event;
145         fd_set readfds, exceptfds;
146
147         FD_ZERO(&readfds);
148         FD_ZERO(&exceptfds);
149         FD_SET(m_event_fd, &readfds);
150         FD_SET(m_event_fd, &exceptfds);
151
152         int ret;
153         ret = select(m_event_fd + 1, &readfds, NULL, &exceptfds, NULL);
154
155         if (ret == -1)
156         {
157                 ERR("select error:%s m_event_fd:d", strerror(errno), m_event_fd);
158                 return false;
159         }
160         else if (!ret)
161         {
162                 DBG("select timeout");
163                 return false;
164         }
165
166         if (FD_ISSET(m_event_fd, &exceptfds))
167         {
168                 ERR("select exception occurred!");
169                 return false;
170         }
171
172         if (FD_ISSET(m_event_fd, &readfds))
173         {
174                 INFO("proximity event detection!");
175                 int len = read(m_event_fd, &proxi_event, sizeof(proxi_event));
176
177                 if (len == -1)
178                 {
179                         DBG("Error in read(m_event_fd):%s.", strerror(errno));
180                         return false;
181                 }
182
183                 ull_bytes_t ev_data;
184                 ev_data.num = proxi_event.event_id;
185                 if (ev_data.bytes[CH_TYPE] == PROXIMITY_TYPE)
186                 {
187                         AUTOLOCK(m_value_mutex);
188                         int temp;
189                         temp = GET_DIR_VAL(ev_data.bytes[DIRECTION]);
190                         if (temp == PROXIMITY_NODE_STATE_FAR)
191                         {
192                                 INFO("PROXIMITY_STATE_FAR state occurred");
193                                 m_state = PROXIMITY_STATE_FAR;
194                         }
195                         else if (temp == PROXIMITY_NODE_STATE_NEAR)
196                         {
197                                 INFO("PROXIMITY_STATE_NEAR state occurred");
198                                 m_state = PROXIMITY_STATE_NEAR;
199                         }
200                         else
201                         {
202                                 ERR("PROXIMITY_STATE Unknown: %d", proxi_event.event_id);
203                                 return false;
204                         }
205                 }
206                 m_fired_time = proxi_event.timestamp;
207         }
208         else
209         {
210                 ERR("No proximity event data available to read");
211                 return false;
212         }
213
214         return true;
215 }
216
217 bool proxi_sensor_hal::is_data_ready(bool wait)
218 {
219         bool ret;
220         ret = update_value(wait);
221         return ret;
222 }
223
224 int proxi_sensor_hal::get_sensor_data(sensor_data_t &data)
225 {
226         AUTOLOCK(m_value_mutex);
227         data.data_accuracy = SENSOR_ACCURACY_UNDEFINED;
228         data.data_unit_idx = SENSOR_UNIT_STATE_ON_OFF;
229         data.timestamp = m_fired_time;
230         data.values_num = 1;
231         data.values[0] = (float)(m_state);
232         return 0;
233 }
234
235 bool proxi_sensor_hal::get_properties(sensor_properties_t &properties)
236 {
237         properties.sensor_unit_idx = SENSOR_UNIT_STATE_ON_OFF;
238         properties.sensor_min_range = 0;
239         properties.sensor_max_range = 1;
240         snprintf(properties.sensor_name,   sizeof(properties.sensor_name), "%s", m_chip_name.c_str());
241         snprintf(properties.sensor_vendor, sizeof(properties.sensor_vendor), "%s", m_vendor.c_str());
242         properties.sensor_resolution = 1;
243         return true;
244 }
245
246 bool proxi_sensor_hal::is_sensorhub_supported(void)
247 {
248         return false;
249 }
250
251 bool proxi_sensor_hal::check_hw_node(void)
252 {
253         string name_node;
254         string hw_name;
255         string file_name;
256         DIR *main_dir = NULL;
257         struct dirent *dir_entry = NULL;
258         bool find_node = false;
259
260         INFO("======================start check_hw_node=============================");
261
262         m_sensorhub_supported = is_sensorhub_supported();
263         main_dir = opendir(IIO_DIR);
264
265         if (!main_dir)
266         {
267                 ERR("Could not open IIO directory\n");
268                 return false;
269         }
270
271         while (!find_node)
272         {
273                 dir_entry = readdir(main_dir);
274                 if(dir_entry == NULL)
275                         break;
276
277                 if ((strncasecmp(dir_entry->d_name , ".", 1 ) != 0) && (strncasecmp(dir_entry->d_name , "..", 2 ) != 0) && (dir_entry->d_ino != 0))
278                 {
279                         file_name = string(IIO_DIR) + string(dir_entry->d_name) + string(NAME_NODE);
280
281                         ifstream infile(file_name.c_str());
282
283                         if (!infile)
284                                 continue;
285
286                         infile >> hw_name;
287
288                         if (strncmp(dir_entry->d_name, IIO_DEV_BASE_NAME, IIO_DEV_STR_LEN) == 0)
289                         {
290                                 if (CConfig::get_instance().is_supported(SENSOR_TYPE_PROXI, hw_name) == true)
291                                 {
292                                         m_name = m_model_id = hw_name;
293                                         m_proxi_dir = string(dir_entry->d_name);
294                                         m_enable_resource = string(IIO_DIR) + m_proxi_dir + string(EVENT_DIR) + string(EVENT_EN_NODE);
295                                         m_event_resource = string(DEV_DIR) + m_proxi_dir;
296
297                                         INFO("m_enable_resource = %s", m_enable_resource.c_str());
298                                         INFO("m_model_id = %s", m_model_id.c_str());
299                                         INFO("m_proxi_dir = %s", m_proxi_dir.c_str());
300                                         INFO("m_event_resource = %s", m_event_resource.c_str());
301
302                                         find_node = true;
303                                         break;
304                                 }
305                         }
306                 }
307         }
308
309         closedir(main_dir);
310         return find_node;
311 }
312
313 extern "C" void *create(void)
314 {
315         proxi_sensor_hal *inst;
316
317         try
318         {
319                 inst = new proxi_sensor_hal();
320         }
321         catch (int err)
322         {
323                 ERR("Failed to create proxi_sensor_hal class, errno : %d, errstr : %s", err, strerror(err));
324                 return NULL;
325         }
326
327         return (void *)inst;
328 }
329
330 extern "C" void destroy(void *inst)
331 {
332         delete (proxi_sensor_hal *)inst;
333 }