2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <sys/types.h>
22 #include <linux/input.h>
24 #include <sensor_logs.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 MODEL_NAME "K2HH"
37 #define VENDOR "ST Microelectronics"
39 #define RAW_DATA_UNIT 0.122
40 #define MIN_INTERVAL 1
41 #define MAX_BATCH_COUNT 0
43 #define SENSORHUB_ACCELEROMETER_ENABLE_BIT 0
45 static const sensor_handle_t handle = {
47 name: "Accelerometer",
48 type: SENSOR_DEVICE_ACCELEROMETER,
49 event_type: (SENSOR_DEVICE_ACCELEROMETER << 16) | 0x0001,
50 model_name: MODEL_NAME,
52 min_range: MIN_RANGE(RESOLUTION) * RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(RAW_DATA_UNIT),
53 max_range: MAX_RANGE(RESOLUTION) * RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(RAW_DATA_UNIT),
54 resolution: RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(RAW_DATA_UNIT),
55 min_interval: MIN_INTERVAL,
56 max_batch_count: MAX_BATCH_COUNT,
57 wakeup_supported: false
60 std::vector<uint16_t> accel_device::event_ids;
62 accel_device::accel_device()
67 , m_polling_interval(0)
69 , m_sensorhub_controlled(false)
71 const std::string sensorhub_interval_node_name = "accel_poll_delay";
73 node_info_query query;
76 query.sensorhub_controlled = m_sensorhub_controlled = util::is_sensorhub_controlled(sensorhub_interval_node_name);
77 query.sensor_type = "ACCEL";
78 query.key = "accelerometer_sensor";
79 query.iio_enable_node_name = "accel_enable";
80 query.sensorhub_interval_node_name = sensorhub_interval_node_name;
82 if (!util::get_node_info(query, info)) {
83 ERR("Failed to get node info");
87 util::show_node_info(info);
89 m_data_node = info.data_node_path;
90 m_enable_node = info.enable_node_path;
91 m_interval_node = info.interval_node_path;
93 if ((m_node_handle = open(m_data_node.c_str(), O_RDWR)) < 0) {
94 ERR("accel handle open fail for accel processor, error:%s\n", strerror(errno));
98 INFO("accel_device is created!\n");
101 accel_device::~accel_device()
103 close(m_node_handle);
106 INFO("accel_device is destroyed!\n");
109 int accel_device::get_poll_fd()
111 return m_node_handle;
114 int accel_device::get_sensors(const sensor_handle_t **sensors)
121 bool accel_device::enable(uint16_t id)
123 util::set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_ACCELEROMETER_ENABLE_BIT);
124 set_interval(id, m_polling_interval);
127 INFO("Enable accelerometer sensor");
131 bool accel_device::disable(uint16_t id)
133 util::set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_ACCELEROMETER_ENABLE_BIT);
135 INFO("Disable accelerometer sensor");
139 bool accel_device::set_interval(uint16_t id, unsigned long val)
141 unsigned long long polling_interval_ns;
143 polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);
145 if (!util::set_node_value(m_interval_node, polling_interval_ns)) {
146 ERR("Failed to set polling resource: %s\n", m_interval_node.c_str());
150 INFO("Interval is changed from %dms to %dms]", m_polling_interval, val);
151 m_polling_interval = val;
155 bool accel_device::set_batch_latency(uint16_t id, unsigned long val)
160 bool accel_device::set_attribute(uint16_t id, int32_t attribute, int32_t value)
165 bool accel_device::set_attribute_str(uint16_t id, char *attribute, char *value, int value_len)
170 bool accel_device::update_value_input_event(void)
172 int accel_raw[3] = {0,};
174 int read_input_cnt = 0;
175 const int INPUT_MAX_BEFORE_SYN = 10;
176 unsigned long long fired_time = 0;
181 struct input_event accel_input;
182 DBG("accel event detection!");
184 while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
185 int len = read(m_node_handle, &accel_input, sizeof(accel_input));
186 if (len != sizeof(accel_input)) {
187 ERR("accel_file read fail, read_len = %d\n",len);
193 if (accel_input.type == EV_REL) {
194 switch (accel_input.code) {
196 accel_raw[0] = (int)accel_input.value;
200 accel_raw[1] = (int)accel_input.value;
204 accel_raw[2] = (int)accel_input.value;
208 ERR("accel_input event[type = %d, code = %d] is unknown.", accel_input.type, accel_input.code);
212 } else if (accel_input.type == EV_SYN) {
214 fired_time = util::get_timestamp(&accel_input.time);
216 ERR("accel_input event[type = %d, code = %d] is unknown.", accel_input.type, accel_input.code);
222 ERR("EV_SYN didn't come until %d inputs had come", read_input_cnt);
233 m_fired_time = fired_time;
235 DBG("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time);
240 int accel_device::read_fd(uint16_t **ids)
242 if (!update_value_input_event()) {
243 DBG("Failed to update value");
248 event_ids.push_back(handle.id);
250 *ids = &event_ids[0];
252 return event_ids.size();
255 int accel_device::get_data(uint16_t id, sensor_data_t **data, int *length)
258 sensor_data_t *sensor_data;
259 sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
261 sensor_data->accuracy = SENSOR_ACCURACY_GOOD;
262 sensor_data->timestamp = m_fired_time;
263 sensor_data->value_count = 3;
264 sensor_data->values[0] = m_x;
265 sensor_data->values[1] = m_y;
266 sensor_data->values[2] = m_z;
268 raw_to_base(sensor_data);
271 *length = sizeof(sensor_data_t);
276 bool accel_device::flush(uint16_t id)
281 void accel_device::raw_to_base(sensor_data_t *data)
283 data->value_count = 3;
284 data->values[0] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data->values[0] * RAW_DATA_UNIT);
285 data->values[1] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data->values[1] * RAW_DATA_UNIT);
286 data->values[2] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data->values[2] * RAW_DATA_UNIT);