From: Yunmi Ha Date: Wed, 8 Sep 2021 05:29:48 +0000 (+0900) Subject: Upgrade sensorhub modules including pedometer sensor X-Git-Tag: submit/tizen/20210908.064312^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c26533a08018cf9e76e7c12c54cba49b064ca181;p=platform%2Fhal%2Fbackend%2Femulator%2Fsensor-emulator.git Upgrade sensorhub modules including pedometer sensor Change-Id: I459f25679c366c387f7ac78680b4bf3837e737a0 Signed-off-by: Yunmi Ha --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ec97ed..0b410e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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}") diff --git a/packaging/hal-backend-sensor-emulator.spec b/packaging/hal-backend-sensor-emulator.spec index 353d666..cad49b1 100644 --- a/packaging/hal-backend-sensor-emulator.spec +++ b/packaging/hal-backend-sensor-emulator.spec @@ -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 diff --git a/src/hal-backend-sensor.cpp b/src/hal-backend-sensor.cpp index e9ed041..e53472f 100644 --- a/src/hal-backend-sensor.cpp +++ b/src/hal-backend-sensor.cpp @@ -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 devs; @@ -57,6 +58,7 @@ static int sensor_emulator_create(sensor_device_t **devices) { create_sensor("Light"); create_sensor("Proximity"); create_sensor("HRM"); + create_sensor("Sensorhub"); *devices = &devs[0]; return devs.size(); diff --git a/src/sensor_common.h b/src/sensor_common.h index b549c96..9c56c2f 100644 --- a/src/sensor_common.h +++ b/src/sensor_common.h @@ -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. @@ -15,14 +15,23 @@ * */ -#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 index a53a731..0000000 --- a/src/sensorhub/CMakeLists.txt +++ /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 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 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 index 0000000..ff0340c --- /dev/null +++ b/src/sensorhub/pedometer.cpp @@ -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 +//#include +#include +#include + +#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 index 0000000..130e46f --- /dev/null +++ b/src/sensorhub/sensorhub.cpp @@ -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 +#include +#include + +#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 index 0000000..98c5784 --- /dev/null +++ b/src/sensorhub/sensorhub.h @@ -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 +#include + +#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 active_sensors; + +private: + sensorhub_manager *manager; + sensorhub_controller *controller; + std::vector 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 index 0000000..2df8fc0 --- /dev/null +++ b/src/sensorhub/sensorhub_controller.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#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 index 0000000..cf07033 --- /dev/null +++ b/src/sensorhub/sensorhub_controller.h @@ -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 + +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 index 0000000..faa8981 --- /dev/null +++ b/src/sensorhub/sensorhub_manager.cpp @@ -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 +#include +#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 &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 index 0000000..a4bc6f7 --- /dev/null +++ b/src/sensorhub/sensorhub_manager.h @@ -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 +#include +#include + +#include "sensorhub_controller.h" +#include "sensorhub_sensor.h" + + +#define REGISTER_SENSORHUB_LIB(info, sensor_class) \ + static sensor_initializer 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 &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 m_id_sensors; + std::vector m_infos; +}; + +template +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 index 0000000..2f4b694 --- /dev/null +++ b/src/sensorhub/sensorhub_sensor.cpp @@ -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 +#include +#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(&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 index 0000000..cde7742 --- /dev/null +++ b/src/sensorhub/sensorhub_sensor.h @@ -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 +#include +#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> sensor_attribute_int_vec; +typedef std::vector> 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_ */