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