Upgrade sensorhub modules including pedometer sensor 78/263678/2 accepted/tizen/unified/20210909.002346 submit/tizen/20210908.064312
authorYunmi Ha <yunmi.ha@samsung.com>
Wed, 8 Sep 2021 05:29:48 +0000 (14:29 +0900)
committerYunmi Ha <yunmi.ha@samsung.com>
Wed, 8 Sep 2021 05:33:29 +0000 (14:33 +0900)
Change-Id: I459f25679c366c387f7ac78680b4bf3837e737a0
Signed-off-by: Yunmi Ha <yunmi.ha@samsung.com>
16 files changed:
CMakeLists.txt
packaging/hal-backend-sensor-emulator.spec
src/hal-backend-sensor.cpp
src/sensor_common.h
src/sensorhub/CMakeLists.txt [deleted file]
src/sensorhub/libsensorhub-hal.i586.so [deleted file]
src/sensorhub/libsensorhub-hal.x86_64.so [deleted file]
src/sensorhub/pedometer.cpp [new file with mode: 0644]
src/sensorhub/sensorhub.cpp [new file with mode: 0644]
src/sensorhub/sensorhub.h [new file with mode: 0644]
src/sensorhub/sensorhub_controller.cpp [new file with mode: 0644]
src/sensorhub/sensorhub_controller.h [new file with mode: 0644]
src/sensorhub/sensorhub_manager.cpp [new file with mode: 0644]
src/sensorhub/sensorhub_manager.h [new file with mode: 0644]
src/sensorhub/sensorhub_sensor.cpp [new file with mode: 0644]
src/sensorhub/sensorhub_sensor.h [new file with mode: 0644]

index 2ec97ed3d775242a8608a4ac98aa670dea4cb447..0b410e422291846700148c2a38c7986ad0d45f95 100644 (file)
@@ -155,7 +155,6 @@ ENDIF()
 IF("${SENSORHUB}" STREQUAL "ON")
 FILE(GLOB_RECURSE SRCS ${SRCS} src/sensorhub/*.cpp)
 ADD_DEFINITIONS(-DENABLE_SENSORHUB)
-ADD_SUBDIRECTORY(src/sensorhub)
 ENDIF()
 
 MESSAGE("Sources: ${SRCS}")
index 353d66604f44a8bbf9d384ea1edd1d312a2ef8bd..cad49b160fa8bbf8cee53f99dfc10a78071b2e49 100644 (file)
@@ -52,5 +52,4 @@ install -m 0644 %SOURCE2 %{buildroot}%{_hal_libdir}/udev/rules.d
 %{_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
index e9ed04165ea9e637ccfb6aac23674fa5a217454c..e53472ff23af9b93bb7f2677598035cb4914c845 100644 (file)
@@ -29,6 +29,7 @@
 #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;
 
@@ -57,6 +58,7 @@ static int sensor_emulator_create(sensor_device_t **devices) {
   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();
index b549c96b43bd460ea1b2162e20cd7ef9964767ee..9c56c2f105d0ccd70f2c6ed3a7180d7e7950044c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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,
@@ -53,4 +62,5 @@ enum sensorhub_enable_bit {
        SENSORHUB_ENABLE_BIT_MAX,
 };
 
-#endif /* _SENSOR_COMMON_H_ */
+
+#endif /* __SENSOR_COMMON_H__ */
diff --git a/src/sensorhub/CMakeLists.txt b/src/sensorhub/CMakeLists.txt
deleted file mode 100644 (file)
index a53a731..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-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()
-
diff --git a/src/sensorhub/libsensorhub-hal.i586.so b/src/sensorhub/libsensorhub-hal.i586.so
deleted file mode 100755 (executable)
index eb249e6..0000000
Binary files a/src/sensorhub/libsensorhub-hal.i586.so and /dev/null differ
diff --git a/src/sensorhub/libsensorhub-hal.x86_64.so b/src/sensorhub/libsensorhub-hal.x86_64.so
deleted file mode 100755 (executable)
index 7176b1d..0000000
Binary files a/src/sensorhub/libsensorhub-hal.x86_64.so and /dev/null differ
diff --git a/src/sensorhub/pedometer.cpp b/src/sensorhub/pedometer.cpp
new file mode 100644 (file)
index 0000000..ff0340c
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+ * 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)
diff --git a/src/sensorhub/sensorhub.cpp b/src/sensorhub/sensorhub.cpp
new file mode 100644 (file)
index 0000000..130e46f
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * 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;
+}
diff --git a/src/sensorhub/sensorhub.h b/src/sensorhub/sensorhub.h
new file mode 100644 (file)
index 0000000..98c5784
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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_ */
diff --git a/src/sensorhub/sensorhub_controller.cpp b/src/sensorhub/sensorhub_controller.cpp
new file mode 100644 (file)
index 0000000..2df8fc0
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ * 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;
+}
diff --git a/src/sensorhub/sensorhub_controller.h b/src/sensorhub/sensorhub_controller.h
new file mode 100644 (file)
index 0000000..cf07033
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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_ */
diff --git a/src/sensorhub/sensorhub_manager.cpp b/src/sensorhub/sensorhub_manager.cpp
new file mode 100644 (file)
index 0000000..faa8981
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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();
+       }
+}
diff --git a/src/sensorhub/sensorhub_manager.h b/src/sensorhub/sensorhub_manager.h
new file mode 100644 (file)
index 0000000..a4bc6f7
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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_ */
diff --git a/src/sensorhub/sensorhub_sensor.cpp b/src/sensorhub/sensorhub_sensor.cpp
new file mode 100644 (file)
index 0000000..2f4b694
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * 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;
+}
diff --git a/src/sensorhub/sensorhub_sensor.h b/src/sensorhub/sensorhub_sensor.h
new file mode 100644 (file)
index 0000000..cde7742
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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_ */