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