sensord: merge tizen 2.3 sensord into tizen branch
[platform/core/system/sensord.git] / src / ultraviolet / ultraviolet_sensor_hal.cpp
1 /*
2  * ultraviolet_sensor_hal
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 #include <fcntl.h>
20 #include <sys/stat.h>
21 #include <dirent.h>
22 #include <linux/input.h>
23 #include <csensor_config.h>
24 #include <ultraviolet_sensor_hal.h>
25 #include <sys/ioctl.h>
26 #include <fstream>
27
28 using std::ifstream;
29
30 #define SENSOR_TYPE_ULTRAVIOLET         "ULTRAVIOLET"
31 #define ELEMENT_NAME                    "NAME"
32 #define ELEMENT_VENDOR                  "VENDOR"
33 #define ELEMENT_RAW_DATA_UNIT   "RAW_DATA_UNIT"
34 #define ELEMENT_MIN_RANGE               "MIN_RANGE"
35 #define ELEMENT_MAX_RANGE               "MAX_RANGE"
36 #define ATTR_VALUE                              "value"
37
38 #define BIAS    1
39
40 ultraviolet_sensor_hal::ultraviolet_sensor_hal()
41 : m_polling_interval(POLL_1HZ_MS)
42 , m_ultraviolet(0)
43 , m_fired_time(0)
44 , m_node_handle(-1)
45 {
46         const string sensorhub_interval_node_name = "uv_poll_delay";
47         csensor_config &config = csensor_config::get_instance();
48
49         node_info_query query;
50         node_info info;
51
52         if (!find_model_id(SENSOR_TYPE_ULTRAVIOLET, m_model_id)) {
53                 ERR("Failed to find model id");
54                 throw ENXIO;
55
56         }
57
58         query.sensorhub_controlled = m_sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name);
59         query.sensor_type = SENSOR_TYPE_ULTRAVIOLET;
60         query.key = "uv_sensor";
61         query.iio_enable_node_name = "uv_enable";
62         query.sensorhub_interval_node_name = sensorhub_interval_node_name;
63
64         if (!get_node_info(query, info)) {
65                 ERR("Failed to get node info");
66                 throw ENXIO;
67         }
68
69         show_node_info(info);
70
71         m_data_node = info.data_node_path;
72         m_enable_node = info.enable_node_path;
73         m_interval_node = info.interval_node_path;
74
75         if (!config.get(SENSOR_TYPE_ULTRAVIOLET, m_model_id, ELEMENT_VENDOR, m_vendor)) {
76                 ERR("[VENDOR] is empty\n");
77                 throw ENXIO;
78         }
79
80         INFO("m_vendor = %s", m_vendor.c_str());
81
82         if (!config.get(SENSOR_TYPE_ULTRAVIOLET, m_model_id, ELEMENT_NAME, m_chip_name)) {
83                 ERR("[NAME] is empty\n");
84                 throw ENXIO;
85         }
86
87         INFO("m_chip_name = %s\n",m_chip_name.c_str());
88
89         double min_range;
90
91         if (!config.get(SENSOR_TYPE_ULTRAVIOLET, m_model_id, ELEMENT_MIN_RANGE, min_range)) {
92                 ERR("[MIN_RANGE] is empty\n");
93                 throw ENXIO;
94         }
95
96         m_min_range = (float)min_range;
97         INFO("m_min_range = %f\n",m_min_range);
98
99         double max_range;
100
101         if (!config.get(SENSOR_TYPE_ULTRAVIOLET, m_model_id, ELEMENT_MAX_RANGE, max_range)) {
102                 ERR("[MAX_RANGE] is empty\n");
103                 throw ENXIO;
104         }
105
106         m_max_range = (float)max_range;
107         INFO("m_max_range = %f\n",m_max_range);
108
109         double raw_data_unit;
110
111         if (!config.get(SENSOR_TYPE_ULTRAVIOLET, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
112                 ERR("[RAW_DATA_UNIT] is empty\n");
113                 throw ENXIO;
114         }
115
116         m_raw_data_unit = (float)(raw_data_unit);
117
118         if ((m_node_handle = open(m_data_node.c_str(),O_RDWR)) < 0) {
119                 ERR("Failed to open handle(%d)", m_node_handle);
120                 throw ENXIO;
121         }
122
123         int clockId = CLOCK_MONOTONIC;
124         if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0)
125                 ERR("Fail to set monotonic timestamp for %s", m_data_node.c_str());
126
127         INFO("m_raw_data_unit = %f\n", m_raw_data_unit);
128         INFO("ultraviolet_sensor_hal is created!\n");
129
130 }
131
132 ultraviolet_sensor_hal::~ultraviolet_sensor_hal()
133 {
134         close(m_node_handle);
135         m_node_handle = -1;
136
137         INFO("ultraviolet_sensor_hal is destroyed!\n");
138 }
139
140 string ultraviolet_sensor_hal::get_model_id(void)
141 {
142         return m_model_id;
143 }
144
145
146 sensor_type_t ultraviolet_sensor_hal::get_type(void)
147 {
148         return ULTRAVIOLET_SENSOR;
149 }
150
151 bool ultraviolet_sensor_hal::enable(void)
152 {
153         AUTOLOCK(m_mutex);
154
155         set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_UV_SENSOR);
156         set_interval(m_polling_interval);
157
158         m_fired_time = 0;
159         INFO("ultraviolet sensor real starting");
160         return true;
161 }
162
163 bool ultraviolet_sensor_hal::disable(void)
164 {
165         AUTOLOCK(m_mutex);
166
167         set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_UV_SENSOR);
168
169         INFO("ultraviolet sensor real stopping");
170         return true;
171 }
172
173 bool ultraviolet_sensor_hal::set_interval(unsigned long val)
174 {
175         unsigned long long polling_interval_ns;
176
177         AUTOLOCK(m_mutex);
178
179         polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
180
181         if (!set_node_value(m_interval_node, polling_interval_ns)) {
182                 ERR("Failed to set polling resource: %s\n", m_interval_node.c_str());
183                 return false;
184         }
185
186         INFO("Interval is changed from %dms to %dms]", m_polling_interval, val);
187         m_polling_interval = val;
188         return true;
189
190 }
191
192
193 bool ultraviolet_sensor_hal::update_value(bool wait)
194 {
195         int ultraviolet_raw = -1;
196         bool ultraviolet = false;
197         int read_input_cnt = 0;
198         const int INPUT_MAX_BEFORE_SYN = 10;
199         unsigned long long fired_time = 0;
200         bool syn = false;
201
202         struct input_event ultraviolet_event;
203         DBG("ultraviolet event detection!");
204
205         while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
206                 int len = read(m_node_handle, &ultraviolet_event, sizeof(ultraviolet_event));
207                 if (len != sizeof(ultraviolet_event)) {
208                         ERR("ultraviolet file read fail, read_len = %d\n",len);
209                         return false;
210                 }
211
212                 ++read_input_cnt;
213
214                 if (ultraviolet_event.type == EV_REL && ultraviolet_event.code == REL_MISC) {
215                         ultraviolet_raw = (int)ultraviolet_event.value - BIAS;
216                         ultraviolet = true;
217                 } else if (ultraviolet_event.type == EV_SYN) {
218                         syn = true;
219                         fired_time = sensor_hal::get_timestamp(&ultraviolet_event.time);
220                 } else {
221                         ERR("ultraviolet event[type = %d, code = %d] is unknown.", ultraviolet_event.type, ultraviolet_event.code);
222                         return false;
223                 }
224         }
225
226         AUTOLOCK(m_value_mutex);
227
228         if (ultraviolet)
229                 m_ultraviolet = ultraviolet_raw;
230
231         m_fired_time = fired_time;
232
233         DBG("m_ultraviolet = %d, time = %lluus", m_ultraviolet, m_fired_time);
234
235         return true;
236 }
237
238 bool ultraviolet_sensor_hal::is_data_ready(bool wait)
239 {
240         bool ret;
241         ret = update_value(wait);
242         return ret;
243 }
244
245 int ultraviolet_sensor_hal::get_sensor_data(sensor_data_t &data)
246 {
247         AUTOLOCK(m_value_mutex);
248         data.accuracy = SENSOR_ACCURACY_GOOD;
249         data.timestamp = m_fired_time ;
250         data.value_count = 1;
251         data.values[0] = (float) m_ultraviolet;
252
253         return 0;
254 }
255
256
257 bool ultraviolet_sensor_hal::get_properties(sensor_properties_t &properties)
258 {
259         properties.name = m_chip_name;
260         properties.vendor = m_vendor;
261         properties.min_range = m_min_range;
262         properties.max_range = m_max_range;
263         properties.min_interval = 1;
264         properties.resolution = m_raw_data_unit;
265         properties.fifo_count = 0;
266         properties.max_batch_count = 0;
267
268         return true;
269 }
270
271 extern "C" sensor_module* create(void)
272 {
273         ultraviolet_sensor_hal *sensor;
274
275         try {
276                 sensor = new(std::nothrow) ultraviolet_sensor_hal;
277         } catch (int err) {
278                 ERR("Failed to create module, err: %d, cause: %s", err, strerror(err));
279                 return NULL;
280         }
281
282         sensor_module *module = new(std::nothrow) sensor_module;
283         retvm_if(!module || !sensor, NULL, "Failed to allocate memory");
284
285         module->sensors.push_back(sensor);
286         return module;
287 }