4 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <linux/input.h>
23 #include <csensor_config.h>
24 #include <geo_sensor_hal.h>
25 #include <sys/ioctl.h>
31 #define SENSOR_TYPE_MAGNETIC "MAGNETIC"
32 #define ELEMENT_NAME "NAME"
33 #define ELEMENT_VENDOR "VENDOR"
34 #define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT"
35 #define ELEMENT_MIN_RANGE "MIN_RANGE"
36 #define ELEMENT_MAX_RANGE "MAX_RANGE"
37 #define ATTR_VALUE "value"
39 geo_sensor_hal::geo_sensor_hal()
46 , m_polling_interval(POLL_1HZ_MS)
48 const string sensorhub_interval_node_name = "mag_poll_delay";
49 csensor_config &config = csensor_config::get_instance();
51 node_info_query query;
54 if (!find_model_id(SENSOR_TYPE_MAGNETIC, m_model_id)) {
55 ERR("Failed to find model id");
59 query.sensorhub_controlled = m_sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name);
60 query.sensor_type = SENSOR_TYPE_MAGNETIC;
61 query.key = "geomagnetic_sensor";
62 query.iio_enable_node_name = "geomagnetic_enable";
63 query.sensorhub_interval_node_name = sensorhub_interval_node_name;
65 bool error = get_node_info(query, info);
67 query.key = "magnetic_sensor";
68 error |= get_node_info(query, info);
71 ERR("Failed to get node info");
77 m_data_node = info.data_node_path;
78 m_enable_node = info.enable_node_path;
79 m_interval_node = info.interval_node_path;
81 if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_VENDOR, m_vendor)) {
82 ERR("[VENDOR] is empty\n");
86 INFO("m_vendor = %s", m_vendor.c_str());
88 if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_NAME, m_chip_name)) {
89 ERR("[NAME] is empty\n");
93 INFO("m_chip_name = %s\n",m_chip_name.c_str());
97 if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_MIN_RANGE, min_range)) {
98 ERR("[MIN_RANGE] is empty\n");
102 m_min_range = (float)min_range;
103 INFO("m_min_range = %f\n",m_min_range);
107 if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_MAX_RANGE, max_range)) {
108 ERR("[MAX_RANGE] is empty\n");
112 m_max_range = (float)max_range;
113 INFO("m_max_range = %f\n",m_max_range);
115 double raw_data_unit;
117 if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
118 ERR("[RAW_DATA_UNIT] is empty\n");
122 m_raw_data_unit = (float)(raw_data_unit);
124 if ((m_node_handle = open(m_data_node.c_str(),O_RDWR)) < 0) {
125 ERR("Failed to open handle(%d)", m_node_handle);
129 int clockId = CLOCK_MONOTONIC;
130 if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0)
131 ERR("Fail to set monotonic timestamp for %s", m_data_node.c_str());
133 INFO("m_raw_data_unit = %f\n", m_raw_data_unit);
134 INFO("geo_sensor_hal is created!\n");
138 geo_sensor_hal::~geo_sensor_hal()
140 close(m_node_handle);
143 INFO("geo_sensor is destroyed!\n");
146 string geo_sensor_hal::get_model_id(void)
151 sensor_hal_type_t geo_sensor_hal::get_type(void)
153 return SENSOR_HAL_TYPE_GEOMAGNETIC;
156 bool geo_sensor_hal::enable(void)
160 set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_GEOMAGNETIC_ENABLE_BIT);
161 set_interval(m_polling_interval);
164 INFO("Geo sensor real starting");
168 bool geo_sensor_hal::disable(void)
172 set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_GEOMAGNETIC_ENABLE_BIT);
174 INFO("Geo sensor real stopping");
178 bool geo_sensor_hal::set_interval(unsigned long val)
180 unsigned long long polling_interval_ns;
184 polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
186 if (!set_node_value(m_interval_node, polling_interval_ns)) {
187 ERR("Failed to set polling resource: %s\n", m_interval_node.c_str());
191 INFO("Interval is changed from %dms to %dms]", m_polling_interval, val);
192 m_polling_interval = val;
196 bool geo_sensor_hal::update_value(bool wait)
198 int geo_raw[4] = {0,};
200 int read_input_cnt = 0;
201 const int INPUT_MAX_BEFORE_SYN = 10;
202 unsigned long long fired_time = 0;
205 x = y = z = hdst = false;
207 struct input_event geo_input;
208 DBG("geo event detection!");
210 while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
211 int len = read(m_node_handle, &geo_input, sizeof(geo_input));
212 if (len != sizeof(geo_input)) {
213 ERR("geo_file read fail, read_len = %d\n",len);
219 if (geo_input.type == EV_REL) {
220 switch (geo_input.code) {
222 geo_raw[0] = (int)geo_input.value;
226 geo_raw[1] = (int)geo_input.value;
230 geo_raw[2] = (int)geo_input.value;
234 geo_raw[3] = (int)geo_input.value;
238 ERR("geo_input event[type = %d, code = %d] is unknown.", geo_input.type, geo_input.code);
242 } else if (geo_input.type == EV_SYN) {
244 fired_time = get_timestamp(&geo_input.time);
246 ERR("geo_input event[type = %d, code = %d] is unknown.", geo_input.type, geo_input.code);
251 AUTOLOCK(m_value_mutex);
260 m_hdst = geo_raw[3] - 1; /* accuracy bias: -1 */
262 m_fired_time = fired_time;
264 DBG("m_x = %d, m_y = %d, m_z = %d, m_hdst = %d, time = %lluus", m_x, m_y, m_z, m_hdst, m_fired_time);
269 bool geo_sensor_hal::is_data_ready(bool wait)
272 ret = update_value(wait);
276 int geo_sensor_hal::get_sensor_data(sensor_data_t &data)
278 data.accuracy = (m_hdst == 1) ? 0 : m_hdst; /* hdst 0 and 1 are needed to calibrate */
279 data.timestamp = m_fired_time;
280 data.value_count = 3;
281 data.values[0] = (float)m_x;
282 data.values[1] = (float)m_y;
283 data.values[2] = (float)m_z;
287 bool geo_sensor_hal::get_properties(sensor_properties_s &properties)
289 properties.name = m_chip_name;
290 properties.vendor = m_vendor;
291 properties.min_range = m_min_range;
292 properties.max_range = m_max_range;
293 properties.min_interval = 1;
294 properties.resolution = m_raw_data_unit;
295 properties.fifo_count = 0;
296 properties.max_batch_count = 0;
300 extern "C" sensor_module* create(void)
302 geo_sensor_hal *sensor;
305 sensor = new(std::nothrow) geo_sensor_hal;
307 ERR("Failed to create module, err: %d, cause: %s", err, strerror(err));
311 sensor_module *module = new(std::nothrow) sensor_module;
312 retvm_if(!module || !sensor, NULL, "Failed to allocate memory");
314 module->sensors.push_back(sensor);