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.
21 #include <linux/input.h>
22 #include <csensor_config.h>
23 #include <accel_sensor_hal.h>
28 #define GRAVITY 9.80665
30 #define RAW_DATA_TO_G_UNIT(X) (((float)(X))/((float)G_TO_MG))
31 #define RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(X) (GRAVITY * (RAW_DATA_TO_G_UNIT(X)))
33 #define MIN_RANGE(RES) (-((1 << (RES))/2))
34 #define MAX_RANGE(RES) (((1 << (RES))/2)-1)
36 #define SENSOR_TYPE_ACCEL "ACCEL"
37 #define ELEMENT_NAME "NAME"
38 #define ELEMENT_VENDOR "VENDOR"
39 #define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT"
40 #define ELEMENT_RESOLUTION "RESOLUTION"
42 #define ATTR_VALUE "value"
44 #define INPUT_NAME "accelerometer_sensor"
45 #define ACCEL_SENSORHUB_POLL_NODE_NAME "accel_poll_delay"
47 #define SCAN_EL_DIR "scan_elements/"
48 #define SCALE_AVAILABLE_NODE "in_accel_scale_available"
49 #define ACCEL_RINGBUF_LEN 32
51 #define MSEC_TO_FREQ(VAL) ((SEC_MSEC) / (VAL))
52 #define NSEC_TO_MUSEC(VAL) ((VAL) / 1000)
54 accel_sensor_hal::accel_sensor_hal()
59 , m_polling_interval(POLL_1HZ_MS)
62 const string sensorhub_interval_node_name = "accel_poll_delay";
63 csensor_config &config = csensor_config::get_instance();
65 node_path_info_query query;
67 int input_method = IIO_METHOD;
69 if (!get_model_properties(SENSOR_TYPE_ACCEL, m_model_id, input_method)) {
70 ERR("Failed to find model_properties");
74 query.input_method = input_method;
75 query.sensorhub_controlled = m_sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name);
76 query.sensor_type = SENSOR_TYPE_ACCEL;
77 query.input_event_key = "accelerometer_sensor";
78 query.iio_enable_node_name = "accel_enable";
79 query.sensorhub_interval_node_name = sensorhub_interval_node_name;
81 if (!get_node_path_info(query, info)) {
82 ERR("Failed to get node info");
86 show_node_path_info(info);
88 m_data_node = info.data_node_path;
89 m_interval_node = info.interval_node_path;
90 m_accel_dir = info.base_dir;
91 m_trigger_path = info.trigger_node_path;
92 m_buffer_enable_node_path = info.buffer_enable_node_path;
93 m_buffer_length_node_path = info.buffer_length_node_path;
94 m_available_freq_node_path = info.available_freq_node_path;
95 m_available_scale_node_path = m_accel_dir + string(SCALE_AVAILABLE_NODE);
97 if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_VENDOR, m_vendor)) {
98 ERR("[VENDOR] is empty\n");
102 INFO("m_vendor = %s", m_vendor.c_str());
104 if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_NAME, m_chip_name)) {
105 ERR("[NAME] is empty\n");
109 INFO("m_chip_name = %s\n",m_chip_name.c_str());
111 if (input_method == IIO_METHOD) {
112 m_trigger_name = m_model_id + "-trigger";
113 if (!verify_iio_trigger(m_trigger_name)) {
114 ERR("Failed verify trigger");
117 string scan_dir = m_accel_dir + "scan_elements/";
118 if (!get_generic_channel_names(scan_dir, string("_type"), m_generic_channel_names))
119 ERR ("Failed to find any input channels");
122 INFO ("generic channel names:");
123 for (vector <string>::iterator it = m_generic_channel_names.begin();
124 it != m_generic_channel_names.end(); ++it) {
125 INFO ("%s", it->c_str());
132 if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_RESOLUTION, resolution)) {
133 ERR("[RESOLUTION] is empty\n");
137 m_resolution = (int)resolution;
139 INFO("m_resolution = %d\n",m_resolution);
141 double raw_data_unit;
143 if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) {
144 ERR("[RAW_DATA_UNIT] is empty\n");
148 m_raw_data_unit = (float)(raw_data_unit);
150 m_node_handle = open(m_data_node.c_str(), O_RDONLY | O_NONBLOCK);
151 if (m_node_handle < 0) {
152 ERR("accel handle open fail for accel processor, error:%s\n", strerror(errno));
156 if (setup_channels() == true)
157 INFO("IIO channel setup successful");
159 ERR("IIO channel setup failed");
163 // int clockId = CLOCK_MONOTONIC;
164 // if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0) {
165 // ERR("Fail to set monotonic timestamp for %s", m_data_node.c_str());
169 INFO("m_raw_data_unit = %f\n", m_raw_data_unit);
170 INFO("accel_sensor is created!\n");
173 accel_sensor_hal::~accel_sensor_hal()
175 enable_resource(false);
179 close(m_node_handle);
182 INFO("accel_sensor is destroyed!\n");
185 string accel_sensor_hal::get_model_id(void)
190 sensor_type_t accel_sensor_hal::get_type(void)
192 return ACCELEROMETER_SENSOR;
195 bool accel_sensor_hal::add_accel_channels_to_array(void)
198 m_channels = (struct channel_parameters*) malloc(sizeof(struct channel_parameters) * m_generic_channel_names.size());
199 for (vector <string>::iterator it = m_generic_channel_names.begin();
200 it != m_generic_channel_names.end(); ++it) {
201 if (add_channel_to_array(m_accel_dir.c_str(), it->c_str() , &m_channels[i++]) < 0) {
202 ERR("Failed to add channel %s to channel array", it->c_str());
209 bool accel_sensor_hal::setup_channels(void)
214 enable_resource(true);
216 if (!add_accel_channels_to_array()) {
217 ERR("Failed to add channels to array!");
221 INFO("Sorting channels by index");
222 sort_channels_by_index(m_channels, m_generic_channel_names.size());
223 INFO("Sorting channels by index completed");
225 m_scan_size = get_channel_array_size(m_channels, m_generic_channel_names.size());
226 if (m_scan_size == 0) {
227 ERR("Channel array size is zero");
231 m_data = new (std::nothrow) char[m_scan_size * ACCEL_RINGBUF_LEN];
232 if (m_data == NULL) {
233 ERR("Couldn't create data buffer\n");
238 fp = fopen(m_available_freq_node_path.c_str(), "r");
240 ERR("Fail to open available frequencies file:%s\n", m_available_freq_node_path.c_str());
244 for (i = 0; i < MAX_FREQ_COUNT; i++)
245 m_sample_freq[i] = 0;
249 while (fscanf(fp, "%d", &freq) > 0)
250 m_sample_freq[i++] = freq;
252 m_sample_freq_count = i;
254 fp = fopen(m_available_scale_node_path.c_str(), "r");
256 ERR("Fail to open available scale factors file:%s\n", m_available_scale_node_path.c_str());
260 for (i = 0; i < MAX_SCALING_COUNT; i++)
261 m_scale_factor[i] = 0;
265 while (fscanf(fp, "%lf", &sf) > 0)
266 m_scale_factor[i++] = sf;
268 m_scale_factor_count = i;
273 void accel_sensor_hal::decode_data(void)
275 AUTOLOCK(m_value_mutex);
277 m_x = convert_bytes_to_int(*(unsigned short int *)(m_data + m_channels[0].buf_index), &m_channels[0]);
278 m_y = convert_bytes_to_int(*(unsigned short int *)(m_data + m_channels[1].buf_index), &m_channels[1]);
279 m_z = convert_bytes_to_int(*(unsigned short int *)(m_data + m_channels[2].buf_index), &m_channels[2]);
281 long long int val = *(long long int *)(m_data + m_channels[3].buf_index);
282 if ((val >> m_channels[3].valid_bits) & 1)
283 val = (val & m_channels[3].mask) | ~m_channels[3].mask;
285 m_fired_time = (unsigned long long int)(NSEC_TO_MUSEC(val));
286 DBG("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time);
288 bool accel_sensor_hal::setup_trigger(const char* trig_name, bool verify)
292 ret = update_sysfs_string(m_trigger_path.c_str(), trig_name);
294 ERR("failed to write to current_trigger,%s,%s\n", m_trigger_path.c_str(), trig_name);
297 INFO("current_trigger setup successfully\n");
301 bool accel_sensor_hal::setup_buffer(int enable)
304 ret = update_sysfs_num(m_buffer_length_node_path.c_str(), ACCEL_RINGBUF_LEN, true);
306 ERR("failed to write to buffer/length\n");
309 INFO("buffer/length setup successfully\n");
311 ret = update_sysfs_num(m_buffer_enable_node_path.c_str(), enable, true);
313 ERR("failed to write to buffer/enable\n");
318 INFO("buffer enabled\n");
320 INFO("buffer disabled\n");
324 bool accel_sensor_hal::enable_resource(bool enable)
328 setup_trigger(m_trigger_name.c_str(), enable);
330 setup_trigger("NULL", enable);
332 for (vector <string>::iterator it = m_generic_channel_names.begin();
333 it != m_generic_channel_names.end(); ++it) {
334 temp = m_accel_dir + string(SCAN_EL_DIR) + *it + string("_en");
335 if (update_sysfs_num(temp.c_str(), enable) < 0)
338 setup_buffer(enable);
342 bool accel_sensor_hal::enable(void)
346 if (!enable_resource(true))
349 set_interval(m_polling_interval);
352 INFO("Accel sensor real starting");
356 bool accel_sensor_hal::disable(void)
360 if (!enable_resource(false))
363 INFO("Accel sensor real stopping");
367 bool accel_sensor_hal::set_interval(unsigned long ms_interval)
371 freq = (int)(MSEC_TO_FREQ(ms_interval));
373 for (i=0; i < m_sample_freq_count; i++) {
374 if (freq == m_sample_freq[i]) {
375 if (update_sysfs_num(m_interval_node.c_str(), freq, true) == 0) {
376 INFO("Interval is changed from %lums to %lums]", m_polling_interval, ms_interval);
377 m_polling_interval = ms_interval;
381 ERR("Failed to set data %lu\n", ms_interval);
387 DBG("The interval not supported: %lu\n", ms_interval);
388 ERR("Failed to set data %lu\n", ms_interval);
392 bool accel_sensor_hal::update_value(bool wait)
397 const int TIMEOUT = 1000;
399 pfd.fd = m_node_handle;
402 poll(&pfd, 1, TIMEOUT);
406 read_size = read(m_node_handle, m_data, ACCEL_RINGBUF_LEN * m_scan_size);
407 if (read_size <= 0) {
408 ERR("Accel:No data available\n");
412 for (i = 0; i < (read_size / m_scan_size); i++)
418 bool accel_sensor_hal::is_data_ready(bool wait)
421 ret = update_value(wait);
425 int accel_sensor_hal::get_sensor_data(sensor_data_t &data)
427 AUTOLOCK(m_value_mutex);
429 data.accuracy = SENSOR_ACCURACY_GOOD;
430 data.timestamp = m_fired_time;
431 data.value_count = 3;
432 data.values[0] = m_x;
433 data.values[1] = m_y;
434 data.values[2] = m_z;
439 bool accel_sensor_hal::get_properties(sensor_properties_s &properties)
441 properties.name = m_chip_name;
442 properties.vendor = m_vendor;
443 properties.min_range = MIN_RANGE(m_resolution)* RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit);
444 properties.max_range = MAX_RANGE(m_resolution)* RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit);
445 properties.min_interval = 1;
446 properties.resolution = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit);
447 properties.fifo_count = 0;
448 properties.max_batch_count = 0;
452 extern "C" void *create(void)
454 accel_sensor_hal *inst;
457 inst = new accel_sensor_hal();
459 ERR("accel_sensor class create fail , errno : %d , errstr : %s\n", err, strerror(err));
466 extern "C" void destroy(void *inst)
468 delete (accel_sensor_hal*)inst;