IF("${SENSORHUB}" STREQUAL "ON")
FILE(GLOB_RECURSE SRCS ${SRCS} src/sensorhub/*.cpp)
ADD_DEFINITIONS(-DENABLE_SENSORHUB)
-ADD_SUBDIRECTORY(src/sensorhub)
ENDIF()
MESSAGE("Sources: ${SRCS}")
%{_hal_libdir}/udev/rules.d/99-sensor.rules
%{_hal_libdir}/udev/rules.d/99-sensorhub.rules
%{_hal_libdir}/*.so*
-%{_hal_libdir}/sensorhub/*.so*
%{_hal_licensedir}/%{name}/LICENSE.APLv2
#include "pressure/pressure_device.h"
#include "proxi/proxi_device.h"
#include "ultraviolet/uv_device.h"
+#include "sensorhub/sensorhub.h"
static std::vector<sensor_device_t> devs;
create_sensor<light_device>("Light");
create_sensor<proxi_device>("Proximity");
create_sensor<hrm_device>("HRM");
+ create_sensor<sensorhub_device>("Sensorhub");
*devices = &devs[0];
return devs.size();
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
*/
-#ifndef _SENSOR_COMMON_H_
-#define _SENSOR_COMMON_H_
+#ifndef __SENSOR_COMMON_H__
+#define __SENSOR_COMMON_H__
+#define SENSOR_LIB_SHIFT 16
#define SENSOR_EVENT_SHIFT 16
#define RAW_DATA_EVENT 0x0001
+#define SENSOR_DEVICE_ID(type, index) ((type) << SENSOR_LIB_SHIFT | (index))
+#define SENSOR_EVENT_TYPE(type) ((type) << SENSOR_EVENT_SHIFT | RAW_DATA_EVENT)
+#define SHORT_TO_UINT64(value, shift) (((unsigned long long)(value & 0xFFFF)) << shift)
+#define CONTEXT_SENSOR_ID 0xFFFF0001
+
+#define NS_TO_US(x) ((x) / 1000)
+
#define UNKNOWN_NAME "UNKNOWN"
+
enum sensorhub_enable_bit {
SENSORHUB_ACCELEROMETER_ENABLE_BIT = 0,
SENSORHUB_GYROSCOPE_ENABLE_BIT,
SENSORHUB_ENABLE_BIT_MAX,
};
-#endif /* _SENSOR_COMMON_H_ */
+
+#endif /* __SENSOR_COMMON_H__ */
+++ /dev/null
-IF("${BUILD_ARCH}" STREQUAL "x86")
- INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/libsensorhub-hal.i586.so DESTINATION ${HAL_LIBDIR}/sensorhub/ COMPONENT RuntimeLibraries)
-ENDIF()
-
-IF("${BUILD_ARCH}" STREQUAL "x86_64")
- INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/libsensorhub-hal.x86_64.so DESTINATION ${HAL_LIBDIR}/sensorhub/ COMPONENT RuntimeLibraries)
-ENDIF()
-
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <sensor_common.h>
+//#include <sensor/sensor_hal.h>
+#include <sensor_log.h>
+#include <util.h>
+
+#include "sensorhub_sensor.h"
+#include "sensorhub_manager.h"
+
+#define PEDOMETER_NAME "SENSOR_PEDOMETER"
+#define PAYLOAD_SFACTOR 84
+
+#define GENDER_MALE 1
+#define GENDER_FEMALE 2
+
+#define DEFAULT_HEIGHT 170
+#define DEFAULT_WEIGHT 65
+#define DEFAULT_GENDER GENDER_MALE
+#define DEFAULT_AGE 30
+
+#define GET_UINT8(data, cur) ((unsigned char)data[cur++])
+#define GET_UINT16(data, cur) get_uint(data, cur, 2)
+#define GET_UINT24(data, cur) get_uint(data, cur, 3)
+#define GET_UINT32(data, cur) get_uint(data, cur, 4)
+
+static const sensor_info_t sensor_info = {
+ id: SENSOR_DEVICE_ID(SHUB_LIB_PEDOMETER, 0x1),
+ name: PEDOMETER_NAME,
+ type: SENSOR_DEVICE_HUMAN_PEDOMETER,
+ event_type: SENSOR_EVENT_TYPE(SENSOR_DEVICE_HUMAN_PEDOMETER),
+ model_name: "Human Pedometer Sensor",
+ vendor: "Samsung Electronics",
+ min_range: 0,
+ max_range: 16777216, /* 2^24 */
+ resolution: 1,
+ min_interval: 0,
+ max_batch_count: 0,
+ wakeup_supported: true
+};
+
+enum value_index {
+ IDX_STEPS = 0,
+ IDX_WALK_STEPS,
+ IDX_RUN_STEPS,
+ IDX_DISTANCE,
+ IDX_CALORIES,
+ IDX_SPEED,
+ IDX_FREQUENCY,
+ IDX_STATE,
+ NUM_VALUES,
+ IDX_WALK_UP = NUM_VALUES,
+ IDX_WALK_DOWN,
+ IDX_RUN_UP,
+ IDX_RUN_DOWN,
+ IDX_STATE_EX,
+};
+
+/* SSP's step state protocol */
+enum ssp_step_state {
+ SSP_STEP_STATE_UNKNOWN = -1,
+ SSP_STEP_STATE_STOP,
+ SSP_STEP_STATE_MARK,
+ SSP_STEP_STATE_STROLL,
+ SSP_STEP_STATE_WALK,
+ SSP_STEP_STATE_RUN,
+ SSP_STEP_STATE_RUSH,
+ SSP_STEP_STATE_WALK_UP,
+ SSP_STEP_STATE_WALK_DOWN,
+ SSP_STEP_STATE_RUN_UP,
+ SSP_STEP_STATE_RUN_DOWN
+};
+
+/* SensorFW's step status protocol */
+enum step_state {
+ STEP_STATE_UNKNOWN = -1,
+ STEP_STATE_STOP,
+ STEP_STATE_WALK,
+ STEP_STATE_RUN,
+};
+
+static int convert_step_status(int sh_stat)
+{
+ switch (sh_stat) {
+ case SSP_STEP_STATE_STOP:
+ case SSP_STEP_STATE_MARK:
+ return STEP_STATE_STOP;
+
+ case SSP_STEP_STATE_STROLL:
+ case SSP_STEP_STATE_WALK:
+ case SSP_STEP_STATE_WALK_UP:
+ case SSP_STEP_STATE_WALK_DOWN:
+ return STEP_STATE_WALK;
+
+ case SSP_STEP_STATE_RUN:
+ case SSP_STEP_STATE_RUSH:
+ case SSP_STEP_STATE_RUN_UP:
+ case SSP_STEP_STATE_RUN_DOWN:
+ return STEP_STATE_RUN;
+
+ default:
+ return STEP_STATE_UNKNOWN;
+ }
+}
+
+static void get_date_and_time(int *base_date, int *base_time)
+{
+ struct timeval now;
+ struct tm tm_now;
+ time_t now_sec;
+
+ gettimeofday(&now, NULL);
+ now_sec = now.tv_sec;
+ gmtime_r(&now_sec, &tm_now);
+
+ *base_time = tm_now.tm_hour * 3600 + tm_now.tm_min * 60 + tm_now.tm_sec;
+ *base_date = now.tv_sec - *base_time;
+}
+
+static int add_date_to_ssp_time(int ssp_time, int base_date, int base_time)
+{
+ // SensorHub Patch 0301: if time stamp represents future, set it to current time
+ int diff = base_time - ssp_time;
+ if (diff < 0 && diff > -1500)
+ ssp_time = base_time;
+
+ if (ssp_time - base_time > 43200)
+ return ssp_time + base_date - 86400;
+
+ return ssp_time + base_date;
+}
+
+/* Big Endian */
+static unsigned int get_uint(const char *data, int &cursor, int bytes = 1)
+{
+ unsigned int sum = 0;
+ for (int i = 0; i < bytes; ++i) {
+ sum = (sum << 8) + (unsigned char)data[cursor++];
+ }
+ return sum;
+}
+
+class sh_pedometer_sensor : public sensorhub_sensor {
+public:
+ sh_pedometer_sensor();
+
+ bool enable(void);
+ bool disable(void);
+
+ int parse(const char *data, int data_len);
+ int get_data(sensor_data_t **data, int *length);
+
+ bool set_attribute_int(int32_t attribute, int32_t value);
+ bool set_attribute_str(int32_t key, char *value, int len);
+
+ bool flush(void);
+
+private:
+ int m_height;
+ int m_weight;
+ int m_gender;
+ int m_age;
+ bool m_is_sfactor;
+ sensor_data_t *m_data;
+
+ int parse_basic(const char *data, int data_len, int cursor);
+ int parse_extended(const char *data, int data_len, int cursor);
+ int parse_batch(const char *data, int data_len, int cursor);
+ int parse_scale_factor(const char *data, int data_len, int cursor);
+};
+
+sh_pedometer_sensor::sh_pedometer_sensor()
+: sensorhub_sensor(&sensor_info)
+, m_height(DEFAULT_HEIGHT)
+, m_weight(DEFAULT_WEIGHT)
+, m_gender(DEFAULT_GENDER)
+, m_age(DEFAULT_AGE)
+, m_is_sfactor(false)
+, m_data(NULL)
+{
+}
+
+bool sh_pedometer_sensor::enable(void)
+{
+ char cmd[] = {SHUB_INST_LIB_ADD, SHUB_LIB_PEDOMETER, 0, 0, 0};
+ cmd[2] = (char)m_height;
+ cmd[3] = (char)m_weight;
+ cmd[4] = (char)m_gender;
+
+ if (!m_controller) {
+ _E("Controller is not set : %s", PEDOMETER_NAME);
+ return false;
+ }
+
+ if (m_controller->send_sensorhub_data(cmd, sizeof(cmd)) < 0)
+ _E("sensor enable fail");
+
+ return sensorhub_sensor::enable();
+}
+
+bool sh_pedometer_sensor::disable(void)
+{
+ return sensorhub_sensor::enable(false, SHUB_LIB_PEDOMETER);
+}
+
+int sh_pedometer_sensor::parse(const char *data, int data_len)
+{
+ unsigned char mode;
+ int cursor = SHUB_IDX_LIBTYPE + 1;
+
+ free(m_data);
+ m_data = NULL;
+ m_is_sfactor = false;
+
+ /* Pedometer packet type ext: "1, 3, 3, 1, ..." */
+ if (data[SHUB_IDX_TYPE] == SHUB_TYPE_LIB_EXT)
+ ++cursor;
+
+ if (cursor >= data_len)
+ return -EINVAL;
+
+ mode = (unsigned char)data[cursor] & 0xE0;
+
+ if (mode == 0x80) {
+ _D("Extended pedometer packet");
+ return parse_extended(data, data_len, cursor);
+ } else if (mode == 0xc0) {
+ _D("Batch pedometer packet");
+ return parse_batch(data, data_len, cursor);
+ } else if (mode == 0xe0) {
+ _D("Scale factor");
+ return parse_scale_factor(data, data_len, cursor);
+ } else {
+ _D("Normal pedometer packet");
+ return parse_basic(data, data_len, cursor);
+ }
+}
+
+int sh_pedometer_sensor::parse_basic(const char *data, int data_len, int cursor)
+{
+ if (data_len - cursor < 15)
+ return -EINVAL;
+
+ sensor_pedometer_data_t *pedometer_data = (sensor_pedometer_data_t*)malloc(sizeof(sensor_pedometer_data_t));
+ retv_if(pedometer_data == NULL, -ENOMEM);
+
+ pedometer_data->values[IDX_WALK_STEPS] = (GET_UINT8(data, cursor) & 0x7F);
+ pedometer_data->values[IDX_RUN_STEPS] = GET_UINT8(data, cursor);
+
+ ++cursor; // Up & down step count
+
+ pedometer_data->values[IDX_STEPS] = GET_UINT16(data, cursor);
+ pedometer_data->values[IDX_DISTANCE] = GET_UINT16(data, cursor) / 100.0;
+ pedometer_data->values[IDX_SPEED] = GET_UINT8(data, cursor) / 10.0;
+ pedometer_data->values[IDX_STATE_EX] = data[cursor++];
+ pedometer_data->values[IDX_STATE] = convert_step_status((int)pedometer_data->values[IDX_STATE_EX]);
+ pedometer_data->values[IDX_CALORIES] = GET_UINT8(data, cursor) / 100.0;
+ pedometer_data->values[IDX_FREQUENCY] = GET_UINT8(data, cursor) / 10.0;
+
+ pedometer_data->values[IDX_WALK_UP] = GET_UINT8(data, cursor);
+ pedometer_data->values[IDX_WALK_DOWN] = GET_UINT8(data, cursor);
+ pedometer_data->values[IDX_RUN_UP] = GET_UINT8(data, cursor);
+ pedometer_data->values[IDX_RUN_DOWN] = GET_UINT8(data, cursor);
+
+ pedometer_data->diffs_count = 0;
+ pedometer_data->accuracy = SENSOR_ACCURACY_GOOD;
+ pedometer_data->timestamp = util::get_timestamp();
+ pedometer_data->value_count = NUM_VALUES;
+
+ m_data = (sensor_data_t *)pedometer_data;
+
+ return cursor;
+}
+
+int sh_pedometer_sensor::parse_extended(const char *data, int data_len, int cursor)
+{
+ ++cursor;
+
+ if (data_len - cursor < 32)
+ return -EINVAL;
+
+ sensor_pedometer_data_t *pedometer_data = (sensor_pedometer_data_t*)malloc(sizeof(sensor_pedometer_data_t));
+ retv_if(pedometer_data == NULL, -ENOMEM);
+
+ pedometer_data->values[IDX_WALK_STEPS] = GET_UINT24(data, cursor);
+ pedometer_data->values[IDX_RUN_STEPS] = GET_UINT24(data, cursor);
+
+ cursor += 3; // Up & down step count
+
+ pedometer_data->values[IDX_STEPS] = GET_UINT24(data, cursor);
+ pedometer_data->values[IDX_DISTANCE] = GET_UINT24(data, cursor) / 100.0;
+ pedometer_data->values[IDX_SPEED] = GET_UINT8(data, cursor) / 10.0;
+ pedometer_data->values[IDX_STATE_EX] = data[cursor++];
+ pedometer_data->values[IDX_STATE] = convert_step_status((int)pedometer_data->values[IDX_STATE_EX]);
+ pedometer_data->values[IDX_CALORIES] = GET_UINT16(data, cursor) / 10.0;
+ pedometer_data->values[IDX_FREQUENCY] = GET_UINT8(data, cursor) / 10.0;
+
+ pedometer_data->values[IDX_WALK_UP] = GET_UINT24(data, cursor);
+ pedometer_data->values[IDX_WALK_DOWN] = GET_UINT24(data, cursor);
+ pedometer_data->values[IDX_RUN_UP] = GET_UINT24(data, cursor);
+ pedometer_data->values[IDX_RUN_DOWN] = GET_UINT24(data, cursor);
+
+ pedometer_data->diffs_count = 0;
+ pedometer_data->accuracy = SENSOR_ACCURACY_GOOD;
+ pedometer_data->timestamp = util::get_timestamp();
+ pedometer_data->value_count = NUM_VALUES;
+
+ m_data = (sensor_data_t *)pedometer_data;
+
+ return cursor;
+}
+
+int sh_pedometer_sensor::parse_batch(const char *data, int data_len, int cursor)
+{
+ static const int BATCH_UNIT_SIZE = 20;
+ int cnt;
+ int base_date;
+ int base_time;
+
+ ++cursor;
+
+ if (!(cursor < data_len))
+ return -EINVAL;
+
+ cnt = GET_UINT8(data, cursor);
+ if (cnt == 0 || cnt > SENSOR_PEDOMETER_DATA_DIFFS_SIZE || cursor + BATCH_UNIT_SIZE * cnt > data_len)
+ return -EINVAL;
+
+ sensor_pedometer_data_t *pedometer_data = (sensor_pedometer_data_t*)malloc(sizeof(sensor_pedometer_data_t));
+ retv_if(pedometer_data == NULL, -ENOMEM);
+
+ pedometer_data->values[IDX_STATE] = STEP_STATE_UNKNOWN;
+ pedometer_data->values[IDX_STATE_EX] = SSP_STEP_STATE_UNKNOWN;
+ pedometer_data->values[IDX_FREQUENCY] = -1;
+ pedometer_data->diffs_count = cnt;
+
+ get_date_and_time(&base_date, &base_time);
+
+ pedometer_data->values[IDX_STEPS] = 0;
+ pedometer_data->values[IDX_WALK_STEPS] = 0;
+ pedometer_data->values[IDX_RUN_STEPS] = 0;
+ pedometer_data->values[IDX_DISTANCE] = 0;
+ pedometer_data->values[IDX_CALORIES] = 0;
+
+ pedometer_data->values[IDX_WALK_UP] = 0;
+ pedometer_data->values[IDX_WALK_DOWN] = 0;
+ pedometer_data->values[IDX_RUN_UP] = 0;
+ pedometer_data->values[IDX_RUN_DOWN] = 0;
+
+ for (cnt = 0; cnt < pedometer_data->diffs_count; ++cnt) {
+ pedometer_data->diffs[cnt].timestamp = add_date_to_ssp_time(GET_UINT32(data, cursor) / 1000, base_date, base_time);
+ pedometer_data->diffs[cnt].distance = GET_UINT16(data, cursor) / 100.0;
+ pedometer_data->diffs[cnt].calories = GET_UINT16(data, cursor) / 100.0;
+ pedometer_data->diffs[cnt].walk_steps = GET_UINT8(data, cursor);
+ pedometer_data->diffs[cnt].run_steps = GET_UINT16(data, cursor);
+
+ pedometer_data->diffs[cnt].walk_up_steps = GET_UINT8(data, cursor);
+ pedometer_data->diffs[cnt].walk_down_steps = GET_UINT8(data, cursor);
+ pedometer_data->diffs[cnt].run_up_steps = GET_UINT16(data, cursor);
+ pedometer_data->diffs[cnt].run_down_steps = GET_UINT16(data, cursor);
+
+ pedometer_data->diffs[cnt].speed = GET_UINT8(data, cursor) / 10.0;
+ pedometer_data->diffs[cnt].steps = GET_UINT16(data, cursor);
+
+ pedometer_data->values[IDX_STEPS] += pedometer_data->diffs[cnt].steps;
+ pedometer_data->values[IDX_WALK_STEPS] += pedometer_data->diffs[cnt].walk_steps;
+ pedometer_data->values[IDX_RUN_STEPS] += pedometer_data->diffs[cnt].run_steps;
+ pedometer_data->values[IDX_DISTANCE] += pedometer_data->diffs[cnt].distance;
+ pedometer_data->values[IDX_CALORIES] += pedometer_data->diffs[cnt].calories;
+
+ pedometer_data->values[IDX_WALK_UP] += pedometer_data->diffs[cnt].walk_up_steps;
+ pedometer_data->values[IDX_WALK_DOWN] += pedometer_data->diffs[cnt].walk_down_steps;
+ pedometer_data->values[IDX_RUN_UP] += pedometer_data->diffs[cnt].run_up_steps;
+ pedometer_data->values[IDX_RUN_DOWN] += pedometer_data->diffs[cnt].run_down_steps;
+ }
+
+ pedometer_data->values[IDX_SPEED] = pedometer_data->diffs[pedometer_data->diffs_count - 1].speed;
+ pedometer_data->accuracy = SENSOR_ACCURACY_GOOD;
+ pedometer_data->timestamp = util::get_timestamp();
+ pedometer_data->value_count = NUM_VALUES;
+
+ m_data = (sensor_data_t *)pedometer_data;
+
+ return cursor;
+}
+
+int sh_pedometer_sensor::parse_scale_factor(const char *data, int data_len, int cursor)
+{
+ /* Packet Format: 1, 1, 3, 0xe0, uint32_t * 20 */
+ retv_if(data_len < PAYLOAD_SFACTOR, -EINVAL);
+
+ /* Sensorhub Pedometer may emit its scale factor, an array 20 integer values.
+ Because this scale factor cannot be bundled in sensor_pedometer_data_t format,
+ as an walkaround, it is stored in sensorhub_data_t format instead.
+ sensord needs to hook this scale factor packet.
+ (Apps do not need to receive this scale factor.) */
+ sensorhub_data_t *sfactor_data = (sensorhub_data_t*)malloc(sizeof(sensorhub_data_t));
+ retv_if(sfactor_data == NULL, -ENOMEM);
+
+ sfactor_data->value_count = PAYLOAD_SFACTOR;
+ memcpy(sfactor_data->values, data, PAYLOAD_SFACTOR);
+
+ m_data = (sensor_data_t *)sfactor_data;
+ m_is_sfactor = true;
+
+ return PAYLOAD_SFACTOR;
+}
+
+int sh_pedometer_sensor::get_data(sensor_data_t **data, int *length)
+{
+ *data = m_data;
+ *length = m_is_sfactor ? sizeof(sensorhub_data_t) : sizeof(sensor_pedometer_data_t);
+ retv_if(*data == NULL, -EINVAL);
+ m_data = NULL;
+ return 0;
+}
+
+bool sh_pedometer_sensor::set_attribute_int(int32_t attribute, int32_t value)
+{
+ char cmd[3] = {SHUB_INST_LIB_PUTVALUE, 0, 0};
+
+ if (!m_controller) {
+ _E("Controller is not set : %s", PEDOMETER_NAME);
+ return false;
+ }
+
+ switch (attribute) {
+ case SENSOR_ATTR_PEDOMETER_HEIGHT:
+ cmd[1] = SHUB_PROP_USR_INFO_HEIGHT;
+ cmd[2] = m_height = value;
+ break;
+ case SENSOR_ATTR_PEDOMETER_WEIGHT:
+ cmd[1] = SHUB_PROP_USR_INFO_WEIGHT;
+ cmd[2] = m_weight = value;
+ break;
+ case SENSOR_ATTR_PEDOMETER_GENDER:
+ cmd[1] = SHUB_PROP_USR_INFO_GENDER;
+ cmd[2] = m_gender = value;
+ break;
+ case SENSOR_ATTR_PEDOMETER_AGE:
+ cmd[1] = SHUB_PROP_USR_INFO_AGE;
+ cmd[2] = m_age = value;
+ break;
+ case SENSOR_ATTR_PEDOMETER_FLUSH:
+ return flush();
+ default :
+ _E("Invalid attribute: %d, value: %d", attribute, value);
+ return false;
+}
+
+ if (m_controller->send_sensorhub_data(cmd, sizeof(cmd)) < 0)
+ return false;
+
+ sensorhub_sensor::set_attribute_int(attribute, value);
+ return true;
+}
+
+bool sh_pedometer_sensor::set_attribute_str(int32_t attribute, char *value, int len)
+{
+ /* TODO: handle scale factor */
+ return false;
+}
+
+bool sh_pedometer_sensor::flush(void)
+{
+ char cmd[] = {SHUB_INST_LIB_GETVALUE, SHUB_LIB_PEDOMETER, SHUB_EXT_CURRENT_INFO, 0};
+
+ if (!m_controller) {
+ _E("Controller is not set : %s", PEDOMETER_NAME);
+ return false;
+ }
+
+ if (m_controller->send_sensorhub_data(cmd, sizeof(cmd)) < 0)
+ return false;
+
+ return true;
+}
+
+REGISTER_SENSORHUB_LIB(sensor_info, sh_pedometer_sensor)
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <unistd.h>
+#include <algorithm>
+#include <sensor_log.h>
+
+#include "sensorhub.h"
+#include "sensor_common.h"
+#include "sensorhub_controller.h"
+#include "sensorhub_manager.h"
+
+sensorhub_device::sensorhub_device()
+{
+ controller = new(std::nothrow) sensorhub_controller;
+ if (!controller) {
+ _E("Failed to allocated memory");
+ throw;
+ }
+
+ manager = &sensorhub_manager::get_instance();
+ if (!manager) {
+ _E("Failed to allocated memory");
+ throw;
+ }
+ manager->set_controller(controller);
+
+ _I("sensorhub_device is created!");
+}
+
+sensorhub_device::~sensorhub_device()
+{
+ delete controller;
+ _I("sensorhub_device is destroyed!");
+}
+
+int sensorhub_device::get_poll_fd(void)
+{
+ return controller->get_poll_fd();
+}
+
+int sensorhub_device::get_sensors(const sensor_info_t **sensors)
+{
+ int size;
+
+ retvm_if(sensors == NULL || sensors == nullptr, -EINVAL, "sensorhub_device:NULL interface");
+
+ size = manager->get_sensor_infos(sensors);
+
+ return size;
+}
+
+bool sensorhub_device::enable(uint32_t id)
+{
+ controller->enable();
+ sensorhub_sensor *sensor = manager->get_sensor(id);
+
+ if (!sensor) {
+ _E("Failed to enable sensor(0x%x)", id);
+ return false;
+ }
+
+ return sensor->enable();
+}
+
+bool sensorhub_device::disable(uint32_t id)
+{
+ controller->disable();
+ sensorhub_sensor *sensor = manager->get_sensor(id);
+
+ if (!sensor) {
+ _E("Failed to disable sensor(0x%x)", id);
+ return false;
+ }
+
+ return sensor->disable();
+}
+
+bool sensorhub_device::set_interval(uint32_t id, unsigned long val)
+{
+ sensorhub_sensor *sensor = manager->get_sensor(id);
+
+ if (!sensor) {
+ _E("Failed to set interval to sensor(0x%x)", id);
+ return false;
+ }
+
+ return sensor->set_interval(val);
+}
+
+bool sensorhub_device::set_batch_latency(uint32_t id, unsigned long val)
+{
+ sensorhub_sensor *sensor = manager->get_sensor(id);
+
+ if (!sensor) {
+ _E("Failed to set batch latency to sensor(0x%x)", id);
+ return false;
+ }
+
+ return sensor->set_batch_latency(val);
+}
+
+bool sensorhub_device::set_attribute_int(uint32_t id, int32_t attribute, int32_t value)
+{
+ sensorhub_sensor *sensor = manager->get_sensor(id);
+
+ if (!sensor) {
+ _E("Failed to set attribute to sensor(0x%x)", id);
+ return false;
+ }
+
+ return sensor->set_attribute_int(attribute, value);
+}
+
+bool sensorhub_device::set_attribute_str(uint32_t id, int32_t attribute, char *value, int len)
+{
+ sensorhub_sensor *sensor = manager->get_sensor(id);
+
+ if (!sensor) {
+ _E("Failed to set attribute to sensor(0x%x)", id);
+ return false;
+ }
+
+ return sensor->set_attribute_str(attribute, value, len);
+}
+
+int sensorhub_device::read_fd(uint32_t **ids)
+{
+ sensorhub_data_t data;
+
+ // step 1
+ if (!controller->read_fd(data))
+ return 0;
+
+ // step 2
+ const char *hub_data = data.values;
+ int data_len = data.value_count;
+
+ // step 3
+ event_ids.clear();
+
+ /* Sensorhub Sensors */
+ while (data_len > 0) {
+ _D("Remaining data length: %d", data_len);
+ int parsed = parse(hub_data, data_len);
+ if (parsed <= 0) {
+ _I("Parsing failed");
+ break;
+ }
+
+ data_len -= parsed;
+ hub_data += parsed;
+ }
+
+ // step 4
+ int size = event_ids.size();
+
+ if (event_ids.empty())
+ return 0;
+
+ *ids = &event_ids[0];
+
+ return size;
+}
+
+int sensorhub_device::get_data(uint32_t id, sensor_data_t **data, int *length)
+{
+ int remains = 1;
+
+ sensorhub_sensor *sensor = manager->get_sensor(id);
+ if (!sensor) {
+ _E("Failed to get data from sensor(0x%x)", id);
+ return -EINVAL;
+ }
+
+ remains = sensor->get_data(data, length);
+
+ return remains;
+}
+
+bool sensorhub_device::flush(uint32_t id)
+{
+ sensorhub_sensor *sensor = manager->get_sensor(id);
+ if (!sensor) {
+ _E("Failed to get data from sensor(0x%x)", id);
+ return false;
+ }
+
+ return sensor->flush();
+}
+
+int sensorhub_device::parse(const char *hub_data, int data_len)
+{
+ return parse_data(hub_data, data_len);
+}
+
+int sensorhub_device::parse_data(const char *hub_data, int data_len)
+{
+ int size = 0;
+ char libtype;
+
+ libtype = hub_data[SHUB_IDX_LIBTYPE];
+ if (!manager->get_sensors(libtype, active_sensors)) {
+ _E("Unknown Sensorhub lib type: %d", libtype);
+ return -EINVAL;
+ }
+
+ for (auto const &sensor : active_sensors) {
+ size = sensor->parse(hub_data, data_len);
+ if (size <= 0)
+ break;
+
+ event_ids.push_back(sensor->get_id());
+ }
+
+ active_sensors.clear();
+
+ return size;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _SENSORHUB_DEVICE_H_
+#define _SENSORHUB_DEVICE_H_
+
+#include <vector>
+#include <hal/hal-sensor-types.h>
+
+#include "sensorhub_controller.h"
+#include "sensorhub_manager.h"
+
+class sensorhub_device : public sensor_device {
+public:
+ sensorhub_device();
+ virtual ~sensorhub_device();
+
+ int get_poll_fd(void);
+ int get_sensors(const sensor_info_t **sensors);
+
+ bool enable(uint32_t id);
+ bool disable(uint32_t id);
+
+ bool set_interval(uint32_t id, unsigned long val);
+ bool set_batch_latency(uint32_t id, unsigned long val);
+ bool set_attribute_int(uint32_t id, int32_t attribute, int32_t value);
+ bool set_attribute_str(uint32_t id, int32_t attribute, char *value, int len);
+
+ int read_fd(uint32_t **ids);
+ int get_data(uint32_t id, sensor_data_t **data, int *length);
+
+ bool flush(uint32_t id);
+
+ std::vector<sensorhub_sensor *> active_sensors;
+
+private:
+ sensorhub_manager *manager;
+ sensorhub_controller *controller;
+ std::vector<uint32_t> event_ids;
+
+ int parse(const char *hub_data, int data_len);
+ int parse_data(const char *hub_data, int data_len);
+};
+
+#endif /* _SENSORHUB_DEVICE_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <linux/input.h>
+#include <sys/ioctl.h>
+#include <fstream>
+
+#include <sensor_log.h>
+#include <util.h>
+#include "sensorhub_controller.h"
+
+#define EVENT_TYPE_SENSORHUB_DATA REL_RX
+#define EVENT_TYPE_LARGE_SENSORHUB_DATA REL_RY
+#define EVENT_TYPE_SENSORHUB_NOTI REL_RZ
+
+#define SSP_INPUT_NODE_NAME "ssp_context"
+#define SSPSENSORHUB_DEVICE "/dev/ssp_sensorhub"
+#define SENSORHUB_IOCTL_MAGIC 'S'
+#define IOCTL_READ_LARGE_SENSORHUB_DATA _IOR(SENSORHUB_IOCTL_MAGIC, 3, unsigned int)
+
+#define INJECTION_NODE_PATH "/run/sensord/sensorhub"
+#define INJECTION_ENABLE 1
+#define SENSOR_ATTR_SENSORHUB_INJECT_VALUE CONVERT_TYPE_ATTR(SENSOR_DEVICE_CONTEXT, 0x1)
+
+sensorhub_controller::sensorhub_controller()
+: m_enabled(false)
+, m_poll_node(-1)
+, m_data_node(-1)
+, m_injection_mode(false)
+{
+ /* initialize sensor_data for sensorhub */
+ m_pending_data.accuracy = SENSOR_ACCURACY_UNDEFINED;
+ m_pending_data.timestamp = 0;
+ m_pending_data.value_count = 0;
+ memset(m_pending_data.values, 0, sizeof(m_pending_data.values));
+
+ m_data.accuracy = SENSOR_ACCURACY_UNDEFINED;
+ m_data.timestamp = 0;
+ m_data.value_count = 0;
+ memset(m_data.values, 0, sizeof(m_data.values));
+
+ /* initialize polling node */
+ m_poll_node = open_input_node(SSP_INPUT_NODE_NAME);
+ if (m_poll_node < 0)
+ throw ENXIO;
+
+ /* initialize sensorhub input node */
+ if ((m_data_node = open(SSPSENSORHUB_DEVICE, O_RDWR)) < 0) {
+ _E("Open sensorhub device failed(%d)", m_data_node);
+ throw ENXIO;
+ }
+
+ _I("m_data_node = %s", SSPSENSORHUB_DEVICE);
+}
+
+sensorhub_controller::~sensorhub_controller()
+{
+ if (m_poll_node >= 0)
+ close(m_poll_node);
+
+ if (m_data_node >= 0)
+ close(m_data_node);
+}
+
+int sensorhub_controller::get_poll_fd(void)
+{
+ return m_poll_node;
+}
+
+bool sensorhub_controller::enable(void)
+{
+ if (m_enabled == 0)
+ _I("Enable Sensorhub");
+
+ m_enabled++;
+ return true;
+}
+
+bool sensorhub_controller::disable(void)
+{
+ if (m_enabled == 0) {
+ _E("sensorhub is already disabled");
+ return false;
+ }
+
+ if (m_enabled == 1)
+ _I("Disable Sensorhub");
+
+ m_enabled--;
+ return true;
+}
+
+int sensorhub_controller::open_input_node(const char* input_node)
+{
+ size_t length;
+ int fd = -1;
+ const char *dirname = "/dev/input";
+ char devname[PATH_MAX] = {0};
+ char *filename;
+ DIR *dir;
+ struct dirent *entry;
+
+ _I("======================start open_input_node=============================");
+
+ dir = opendir(dirname);
+
+ if (dir == NULL)
+ return -EINVAL;
+
+ strncpy(devname, dirname, strlen(dirname)+1);
+
+ filename = devname + strlen(devname);
+ *filename++ = '/';
+
+ while (true) {
+ entry = readdir(dir);
+ if (!entry) break;
+
+ if (entry->d_name[0] == '.' &&
+ (entry->d_name[1] == '\0' ||
+ (entry->d_name[1] == '.' && entry->d_name[2] == '\0')))
+ continue;
+
+ length = strlen(entry->d_name);
+ strncpy(filename, entry->d_name, length+1);
+
+ /* Need to be terminated with a null character */
+ filename[length] = '\0';
+
+ fd = open(devname, O_RDONLY);
+
+ if (fd < 0)
+ continue;
+
+ char name[80];
+ if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1)
+ name[0] = '\0';
+
+ if (!strcmp(name, input_node)) {
+ _I("m_poll_node = %s", devname);
+ break;
+ }
+
+ close(fd);
+ fd = -1;
+ }
+
+ closedir(dir);
+
+ if (fd < 0)
+ _E("couldn't find '%s' input device", input_node);
+
+ return fd;
+}
+
+bool sensorhub_controller::read_fd(sensorhub_data_t &data)
+{
+ const int INPUT_MAX_BEFORE_SYN = 10;
+ struct input_event sensorhub_input;
+ int read_input_cnt = 0;
+ int sensorhub_len = 0;
+ bool syn = false;
+
+ fd_set readfds, exceptfds;
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&exceptfds);
+
+ FD_SET(m_poll_node, &readfds);
+ FD_SET(m_poll_node, &exceptfds);
+
+ while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
+ int input_len = read(m_poll_node, &sensorhub_input, sizeof(sensorhub_input));
+
+ if (input_len != sizeof(sensorhub_input)) {
+ _E("sensorhub node read fail, read_len = %d", input_len);
+ return false;
+ }
+
+ ++read_input_cnt;
+
+ if (sensorhub_input.type == EV_REL) {
+ float value = sensorhub_input.value;
+
+ if (sensorhub_input.code == EVENT_TYPE_SENSORHUB_DATA) {
+ _D("EVENT_TYPE_SENSORHUB_DATA, value_count=%g", value);
+ m_pending_data.value_count = value;
+ sensorhub_len = read_sensorhub_data();
+
+ if (sensorhub_len == 0)
+ _E("No library data");
+ else if (sensorhub_len < 0)
+ _E("read_sensorhub_data() err(%d)", sensorhub_len);
+
+ } else if (sensorhub_input.code == EVENT_TYPE_LARGE_SENSORHUB_DATA) {
+ _D("EVENT_TYPE_LARGE_SENSORHUB_DATA, value_count=%g", value);
+ m_pending_data.value_count = value;
+ sensorhub_len = read_large_sensorhub_data();
+
+ if (sensorhub_len == 0)
+ _E("No large library data");
+ else if (sensorhub_len < 0)
+ _E("read_large_sensorhub_data() err(%d)", sensorhub_len);
+
+ }
+ } else if (sensorhub_input.type == EV_SYN) {
+ syn = true;
+
+ if (!m_enabled || (sensorhub_len <= 0))
+ break;
+
+ m_data = m_pending_data;
+ data = m_data;
+ _D("sensorhub event is received!");
+ } else {
+ _E("Unknown event (type=%d, code=%d)", sensorhub_input.type, sensorhub_input.code);
+ }
+ }
+
+ if (syn == false) {
+ _E("EV_SYN didn't come until %d inputs had come", read_input_cnt);
+ return false;
+ }
+
+ return true;
+}
+
+int sensorhub_controller::read_sensorhub_data(void)
+{
+ int ret = 0;
+
+ if (m_data_node < 0) {
+ _E("Invalid sensorhub fd(%d)", m_data_node);
+ return -ENODEV;
+ }
+
+read:
+ ret = read(m_data_node, m_pending_data.values, m_pending_data.value_count);
+
+ if (ret > 0) {
+ m_pending_data.value_count = ret;
+ print_sensorhub_data(__FUNCTION__, m_pending_data.values, m_pending_data.value_count);
+ } else if (ret < 0) {
+ if (errno == EINTR) {
+ _E("EINTR! retry read");
+ goto read;
+ }
+
+ _ERRNO(errno, _E, "Failed to read data");
+ return -errno;
+ }
+
+ return ret;
+}
+
+int sensorhub_controller::read_large_sensorhub_data(void)
+{
+ int ret = 0;
+
+ if (m_data_node < 0) {
+ _E("Invalid sensorhub fd(%d)", m_data_node);
+ return -ENODEV;
+ }
+
+ioctl:
+ ret = ioctl(m_data_node, IOCTL_READ_LARGE_SENSORHUB_DATA, m_pending_data.values);
+
+ if (ret > 0) {
+ m_pending_data.value_count = ret;
+ print_sensorhub_data(__FUNCTION__, m_pending_data.values, m_pending_data.value_count);
+ } else if (ret < 0) {
+ if (errno == EINTR) {
+ _I("EINTR! retry ioctl");
+ goto ioctl;
+ }
+
+ _ERRNO(errno, _E, "Failed to ioctl");
+ return -errno;
+ }
+
+ return ret;
+}
+
+int sensorhub_controller::send_sensorhub_data(const char *data, int data_len)
+{
+ int ret;
+
+ if (data_len <= 0) {
+ _E("Invalid data_len(%d)", data_len);
+ return -EINVAL;
+ }
+
+ if (m_data_node < 0) {
+ _E("Invalid sensorhub fd(%d)", m_data_node);
+ return -ENODEV;
+ }
+
+ if (m_injection_mode)
+ return -EPERM;
+
+ print_sensorhub_data(__FUNCTION__, data, data_len);
+
+write:
+ ret = write(m_data_node, data, data_len);
+ if (ret < 0) {
+ if (errno == EINTR) {
+ _I("EINTR! retry to write");
+ goto write;
+ }
+ _ERRNO(errno, _E, "Failed to write data");
+ }
+
+ return ret < 0 ? -errno : ret;
+}
+
+char *sensorhub_controller::base64_encode(const unsigned char *data, size_t input_length)
+{
+ const char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/'};
+ const int mod_table[] = {0, 2, 1};
+ int output_length = ((input_length - 1) / 3) * 4 + 5;
+
+ char *encoded_data = (char *)malloc(output_length);
+ if (encoded_data == NULL) return NULL;
+
+ for (size_t i = 0, j = 0; i < input_length;) {
+ uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0;
+ uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0;
+ uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0;
+
+ uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
+
+ encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
+ encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
+ }
+
+ for (int i = 0; i < mod_table[input_length % 3]; i++)
+ encoded_data[output_length - 2 - i] = '=';
+
+ encoded_data[output_length - 1] = '\0';
+
+ return encoded_data;
+}
+
+int sensorhub_controller::print_sensorhub_data(const char* name, const char *data, int length)
+{
+ const int LOG_SIZE_LIMIT = 100;
+
+ char buf[6];
+ char *log_str;
+
+ if ((length > LOG_SIZE_LIMIT) || (length <= 0)) {
+ _W("log size(%d) is exceptional!", length);
+ if (data[0] == 1 && data[1] == 1 && data[2] == 15) {
+ char *encoded_data = base64_encode((unsigned char *)data, length);
+ _W("%s", encoded_data);
+ free(encoded_data);
+ }
+ return -EINVAL;
+ }
+
+ int log_size = strlen(name) + 2 + sizeof(buf) * length + 1;
+
+ log_str = new(std::nothrow) char[log_size];
+ retvm_if(!log_str, -ENOMEM, "Failed to allocate memory");
+
+ memset(log_str, 0, log_size);
+
+ for (int i = 0; i < length; i++ ) {
+ if (i == 0) {
+ strncat(log_str, name, strlen(name)+1);
+ strncat(log_str, ": ", 2);
+ } else {
+ strncat(log_str, ", ", 2);
+ }
+
+ snprintf(buf, sizeof(buf), "%d", (signed char)data[i]);
+ strncat(log_str, buf, sizeof(buf));
+ }
+
+ _I("%s", log_str);
+ delete[] log_str;
+
+ return length;
+}
+
+
+bool sensorhub_controller::set_attribute(int32_t attribute, int32_t value)
+{
+ bool injection_mode = false;
+ std::string path = SSPSENSORHUB_DEVICE;
+ if (attribute != SENSOR_ATTR_SENSORHUB_INJECT_VALUE)
+ return false;
+
+ if (value == INJECTION_ENABLE) {
+ injection_mode = true;
+ path = INJECTION_NODE_PATH;
+ }
+
+ m_injection_mode = injection_mode;
+ m_data_node = open(path.c_str(), O_RDWR);
+ if (m_data_node < 0) {
+ _E("Open sensorhub device failed(%s)", path.c_str());
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _SENSORHUB_CONTROLLER_H_
+#define _SENSORHUB_CONTROLLER_H_
+
+#include <hal/hal-sensor-types.h>
+
+class sensorhub_controller {
+public:
+ sensorhub_controller();
+ virtual ~sensorhub_controller();
+
+ int open_input_node(const char* input_node);
+ int get_poll_fd(void);
+
+ bool enable(void);
+ bool disable(void);
+
+ bool read_fd(sensorhub_data_t &data);
+
+ int read_sensorhub_data(void);
+ int read_large_sensorhub_data(void);
+ int send_sensorhub_data(const char *data, int data_len);
+
+ bool set_attribute(int32_t attribute, int32_t value);
+
+private:
+ int m_enabled;
+ int m_poll_node;
+ int m_data_node;
+ bool m_injection_mode;
+
+ sensorhub_data_t m_pending_data;
+ sensorhub_data_t m_data;
+
+ int print_sensorhub_data(const char* name, const char *data, int length);
+ char *base64_encode(const unsigned char *data, size_t input_length);
+};
+
+#endif /* _SENSORHUB_CONTROLLER_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <sensor_common.h>
+#include <util.h>
+#include "sensorhub_controller.h"
+#include "sensorhub_manager.h"
+#include "sensorhub_sensor.h"
+
+sensorhub_manager::sensorhub_manager()
+{
+}
+
+sensorhub_manager::~sensorhub_manager()
+{
+ for (auto &it : m_id_sensors)
+ delete it.second;
+
+ m_id_sensors.clear();
+ m_infos.clear();
+}
+
+sensorhub_manager& sensorhub_manager::get_instance() {
+ static sensorhub_manager instance;
+ return instance;
+}
+
+bool sensorhub_manager::add_sensor(sensor_info_t info, sensorhub_sensor *sensor)
+{
+ m_infos.push_back(info);
+ m_id_sensors[info.id] = sensor;
+
+ return true;
+}
+
+void sensorhub_manager::set_controller(sensorhub_controller *controller)
+{
+ for (auto const &it : m_id_sensors) {
+ sensorhub_sensor *sensor = it.second;
+ sensor->set_controller(controller);
+ }
+}
+
+sensorhub_sensor *sensorhub_manager::get_sensor(uint32_t id)
+{
+ if (m_id_sensors.find(id) == m_id_sensors.end())
+ return NULL;
+
+ return m_id_sensors[id];
+}
+
+bool sensorhub_manager::get_sensors(char libtype, std::vector<sensorhub_sensor *> &sensors)
+{
+ char type;
+ sensorhub_sensor *sensor;
+
+ for (auto const &it : m_id_sensors) {
+ sensor = it.second;
+ if (!sensor)
+ continue;
+
+ type = (char)(sensor->get_id() >> SENSOR_LIB_SHIFT);
+
+ if (type == libtype)
+ sensors.push_back(sensor);
+ }
+
+ if (sensors.size() == 0)
+ return false;
+
+ return true;
+}
+
+int sensorhub_manager::get_sensor_infos(const sensor_info_t **sensors)
+{
+ int size;
+
+ if (m_infos.empty()) {
+ *sensors = 0;
+ return 0;
+ }
+
+ size = m_infos.size();
+ *sensors = &m_infos[0];
+
+ return size;
+}
+
+void sensorhub_manager::restore_sensors()
+{
+ for (auto &it : m_id_sensors) {
+ it.second->restore();
+ it.second->restore_attributes();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _SENSORHUB_MANAGER_H_
+#define _SENSORHUB_MANAGER_H_
+
+#include <map>
+#include <vector>
+#include <sensor_log.h>
+
+#include "sensorhub_controller.h"
+#include "sensorhub_sensor.h"
+
+
+#define REGISTER_SENSORHUB_LIB(info, sensor_class) \
+ static sensor_initializer<sensor_class> initializer_##sensor_class((info)); \
+
+class sensorhub_manager {
+public:
+ static sensorhub_manager& get_instance();
+ virtual ~sensorhub_manager();
+
+ sensorhub_sensor *get_sensor(uint32_t id);
+ bool get_sensors(char libtype, std::vector<sensorhub_sensor *> &sensors);
+ int get_sensor_infos(const sensor_info_t **sensors);
+
+ void set_controller(sensorhub_controller *controller);
+ bool add_sensor(sensor_info_t info, sensorhub_sensor *sensor);
+
+ void restore_sensors(void);
+
+private:
+ sensorhub_manager();
+
+ std::map<uint32_t, sensorhub_sensor *> m_id_sensors;
+ std::vector<sensor_info_t> m_infos;
+};
+
+template <typename T>
+class sensor_initializer {
+public:
+ sensor_initializer(sensor_info_t info)
+ {
+ T *sensor = new(std::nothrow) T();
+ if (!sensor) {
+ _E("Failed to allocate memory");
+ return;
+ }
+ sensorhub_manager::get_instance().add_sensor(info, sensor);
+ }
+ ~sensor_initializer() {}
+};
+
+#endif /* _SENSORHUB_MANAGER_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <sensor_log.h>
+#include <time.h>
+#include "sensorhub_controller.h"
+#include "sensorhub_sensor.h"
+
+sensorhub_sensor::sensorhub_sensor(const sensor_info_t *sensor_info)
+: m_sensor_info(sensor_info)
+, m_enabled(false)
+, m_restore_mode(false)
+{
+}
+
+sensorhub_sensor::~sensorhub_sensor()
+{
+ _I("%s is destroyed!", m_sensor_info->name);
+}
+
+int32_t sensorhub_sensor::get_id(void)
+{
+ return m_sensor_info->id;
+}
+
+void sensorhub_sensor::set_controller(sensorhub_controller *controller)
+{
+ m_controller = controller;
+}
+
+bool sensorhub_sensor::enable(void)
+{
+ m_enabled.store(true);
+ return true;
+}
+
+bool sensorhub_sensor::disable(void)
+{
+ m_enabled.store(false);
+ return true;
+}
+
+bool sensorhub_sensor::is_enabled(void)
+{
+ return m_enabled.load();
+}
+
+bool sensorhub_sensor::is_restore_mode(void)
+{
+ return m_restore_mode.load();
+}
+
+bool sensorhub_sensor::set_interval(unsigned long val)
+{
+ return false;
+}
+
+bool sensorhub_sensor::set_batch_latency(unsigned long val)
+{
+ return false;
+}
+
+bool sensorhub_sensor::set_attribute_int(int32_t attribute, int32_t value)
+{
+ if (is_restore_mode())
+ return false;
+
+ attributes_int.push_back(std::make_pair(attribute, value));
+ return true;
+}
+
+bool sensorhub_sensor::set_attribute_str(int32_t attribute, char *value, int len)
+{
+ attr_info info;
+
+ if (is_restore_mode())
+ return false;
+
+ info.value = value;
+ info.len = len;
+
+ attributes_str.push_back(std::make_pair(attribute, &info));
+ return true;
+}
+
+bool sensorhub_sensor::flush(void)
+{
+ return false;
+}
+
+bool sensorhub_sensor::enable(bool enbl, const char lib_id)
+{
+ struct cmd {
+ uint8_t inst;
+ uint8_t type;
+ uint8_t reserved[2];
+ } cmd = {enbl ? SHUB_INST_LIB_ADD : SHUB_INST_LIB_REMOVE, (uint8_t)lib_id, {0, 0}};
+
+ if (!m_controller) {
+ _E("Controller is not set : %d", lib_id);
+ return false;
+ }
+
+ if (m_controller->send_sensorhub_data(reinterpret_cast<char *>(&cmd), sizeof(struct cmd))) {
+ m_enabled.store(enbl);
+ if (!enbl) {
+ attributes_int.clear();
+ attributes_str.clear();
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void sensorhub_sensor::restore(void)
+{
+ if (!is_enabled())
+ return;
+
+ _I("Restart %s", m_sensor_info->name);
+ enable();
+}
+
+bool sensorhub_sensor::restore_attributes(void)
+{
+ if (!is_enabled())
+ return false;
+
+ _I("Restart attributes %s", m_sensor_info->name);
+
+ m_restore_mode.store(true);
+
+ for (auto it = attributes_int.begin(); it != attributes_int.end(); ++it) {
+ int attr = it->first;
+ int val = it->second;
+ if (!set_attribute_int(attr, val)) {
+ _E("Failed to set_attribute_int(%d, %d) for %s",
+ attr, val, m_sensor_info->name);
+ return false;
+ }
+ }
+
+ for (auto it = attributes_str.begin(); it != attributes_str.end(); ++it) {
+ int attr = it->first;
+ char *val = it->second->value;
+ int len = it->second->len;
+ if (!set_attribute_str(attr, val, len)) {
+ _E("Failed to set_attribute_str(%d, %s, %d) for %s",
+ attr, val, len, m_sensor_info->name);
+ return false;
+ }
+ }
+
+ m_restore_mode.store(false);
+ return true;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _SENSORHUB_SENSOR_H_
+#define _SENSORHUB_SENSOR_H_
+
+#include <atomic>
+#include <vector>
+#include "sensorhub_controller.h"
+
+#define SHUB_INST_LIB_GETVALUE (uint8_t)0x35
+#define SHUB_INST_LIB_PUTVALUE (uint8_t)0x36
+#define SHUB_INST_LIB_ADD (uint8_t)0x37
+#define SHUB_INST_LIB_REMOVE (uint8_t)0x38
+
+#define SHUB_PROP_USR_INFO_AGE 16
+#define SHUB_PROP_USR_INFO_HEIGHT 18
+#define SHUB_PROP_USR_INFO_WEIGHT 19
+#define SHUB_PROP_USR_INFO_GENDER 20
+
+#define SHUB_IDX_TYPE 1
+#define SHUB_IDX_LIBTYPE 2
+#define SHUB_TYPE_LIB_EXT 3
+#define SHUB_EXT_CURRENT_INFO 1
+
+#define SHUB_LIB_PEDOMETER 3
+#define SHUB_LIB_HRM_LED_GREEN_BATCH 28
+#define SHUB_LIB_HRM_BATCH 46
+
+struct attr_info {
+ char *value;
+ int len;
+};
+
+typedef std::vector<std::pair<int, int>> sensor_attribute_int_vec;
+typedef std::vector<std::pair<int, attr_info *>> sensor_attribute_str_vec;
+
+class sensorhub_sensor {
+public:
+ sensorhub_sensor(const sensor_info_t *sensor_info);
+ virtual ~sensorhub_sensor();
+
+ int32_t get_id(void);
+
+ virtual bool enable(void);
+ virtual bool disable(void);
+ virtual int parse(const char *hub_data, int data_len) = 0;
+ virtual int get_data(sensor_data_t **data, int *length) = 0;
+
+ void set_controller(sensorhub_controller *controller);
+
+ virtual bool set_interval(unsigned long val);
+ virtual bool set_batch_latency(unsigned long val);
+ virtual bool set_attribute_int(int32_t attribute, int32_t value);
+ virtual bool set_attribute_str(int32_t key, char *value, int len);
+
+ virtual bool flush(void);
+ virtual void restore(void);
+ virtual bool restore_attributes(void);
+
+ sensor_attribute_int_vec attributes_int;
+ sensor_attribute_str_vec attributes_str;
+
+protected:
+ const sensor_info_t *m_sensor_info{nullptr};
+ sensorhub_controller *m_controller{nullptr};
+
+ bool enable(bool enbl, const char lib_id);
+ bool is_enabled(void);
+ bool is_restore_mode(void);
+
+private:
+ std::atomic_bool m_enabled{false};
+ std::atomic_bool m_restore_mode{false};
+};
+
+#endif /* _SENSORHUB_SENSOR_H_ */