From 6e0837fbecf9d4201f6d4a79973f3059a1bcd996 Mon Sep 17 00:00:00 2001 From: TaeminYeom Date: Mon, 4 Jul 2022 14:49:07 +0900 Subject: [PATCH] Copy libsensor to API Change-Id: Ib82941e2ba6cbb6b7d360a095a1f390797d08e9a Signed-off-by: TaeminYeom --- CMakeLists.txt | 47 +- include/{sensor_info.h => sensor_info_list.h} | 6 +- include/sensor_internal.h | 545 +++++++++ include/sensor_log.h | 58 +- include/sensor_types.h | 294 +++++ packaging/capi-system-sensor.spec | 5 +- src/api/CMakeLists.txt | 58 + src/api/capi-system-sensor.pc.in | 14 + src/{ => api}/fusion_util.c | 0 src/{ => api}/geomagnetic_field.c | 0 src/{ => api}/sensor-internal.cpp | 0 src/{ => api}/sensor.cpp | 0 src/api/sensor_internal.cpp | 1197 ++++++++++++++++++++ src/api/sensor_listener.cpp | 723 ++++++++++++ src/api/sensor_listener.h | 115 ++ src/api/sensor_manager.cpp | 401 +++++++ src/api/sensor_manager.h | 90 ++ src/api/sensor_manager_channel_handler.cpp | 113 ++ src/api/sensor_manager_channel_handler.h | 64 ++ src/{ => api}/sensor_provider.cpp | 0 src/api/sensor_provider_channel_handler.cpp | 116 ++ src/api/sensor_provider_channel_handler.h | 63 ++ src/api/sensor_provider_internal.cpp | 224 ++++ src/api/sensor_provider_internal.h | 77 ++ src/api/sensor_reader.cpp | 88 ++ src/api/sensor_reader.h | 53 + src/{ => api/sensor_recorder}/sensor_recorder.cpp | 0 .../sensor_recorder}/sensor_recorder_dummy.cpp | 0 src/shared/CMakeLists.txt | 19 + src/shared/accept_event_handler.cpp | 51 + src/shared/accept_event_handler.h | 42 + src/shared/cbase_lock.cpp | 156 +++ src/shared/cbase_lock.h | 90 ++ src/shared/channel.cpp | 388 +++++++ src/shared/channel.h | 82 ++ src/shared/channel_event_handler.cpp | 93 ++ src/shared/channel_event_handler.h | 55 + src/shared/channel_handler.h | 44 + src/shared/cmutex.cpp | 71 ++ src/shared/cmutex.h | 45 + src/shared/command_types.h | 135 +++ src/shared/event_handler.h | 49 + src/shared/event_loop.cpp | 357 ++++++ src/shared/event_loop.h | 111 ++ src/shared/ipc_client.cpp | 86 ++ src/shared/ipc_client.h | 50 + src/shared/ipc_server.cpp | 117 ++ src/shared/ipc_server.h | 59 + src/shared/macro.h | 70 ++ src/shared/message.cpp | 132 +++ src/shared/message.h | 81 ++ src/shared/sensor_info.cpp | 420 +++++++ src/shared/sensor_info.h | 109 ++ src/shared/sensor_types_private.h | 43 + src/shared/sensor_utils.cpp | 287 +++++ src/shared/sensor_utils.h | 46 + src/shared/seqpacket_socket.cpp | 95 ++ src/shared/seqpacket_socket.h | 41 + src/shared/socket.cpp | 456 ++++++++ src/shared/socket.h | 83 ++ src/shared/stream_socket.cpp | 104 ++ src/shared/stream_socket.h | 41 + tests/main.c | 10 +- tests/spec_test.c | 28 +- tests/stress_test.c | 6 +- tools/sensor-tool.c | 18 +- 66 files changed, 8438 insertions(+), 83 deletions(-) rename include/{sensor_info.h => sensor_info_list.h} (95%) create mode 100644 include/sensor_internal.h create mode 100644 include/sensor_types.h create mode 100644 src/api/CMakeLists.txt create mode 100644 src/api/capi-system-sensor.pc.in rename src/{ => api}/fusion_util.c (100%) rename src/{ => api}/geomagnetic_field.c (100%) rename src/{ => api}/sensor-internal.cpp (100%) rename src/{ => api}/sensor.cpp (100%) create mode 100644 src/api/sensor_internal.cpp create mode 100644 src/api/sensor_listener.cpp create mode 100644 src/api/sensor_listener.h create mode 100644 src/api/sensor_manager.cpp create mode 100644 src/api/sensor_manager.h create mode 100644 src/api/sensor_manager_channel_handler.cpp create mode 100644 src/api/sensor_manager_channel_handler.h rename src/{ => api}/sensor_provider.cpp (100%) create mode 100644 src/api/sensor_provider_channel_handler.cpp create mode 100644 src/api/sensor_provider_channel_handler.h create mode 100644 src/api/sensor_provider_internal.cpp create mode 100644 src/api/sensor_provider_internal.h create mode 100644 src/api/sensor_reader.cpp create mode 100644 src/api/sensor_reader.h rename src/{ => api/sensor_recorder}/sensor_recorder.cpp (100%) rename src/{ => api/sensor_recorder}/sensor_recorder_dummy.cpp (100%) create mode 100644 src/shared/CMakeLists.txt create mode 100644 src/shared/accept_event_handler.cpp create mode 100644 src/shared/accept_event_handler.h create mode 100644 src/shared/cbase_lock.cpp create mode 100644 src/shared/cbase_lock.h create mode 100644 src/shared/channel.cpp create mode 100644 src/shared/channel.h create mode 100644 src/shared/channel_event_handler.cpp create mode 100644 src/shared/channel_event_handler.h create mode 100644 src/shared/channel_handler.h create mode 100644 src/shared/cmutex.cpp create mode 100644 src/shared/cmutex.h create mode 100644 src/shared/command_types.h create mode 100644 src/shared/event_handler.h create mode 100644 src/shared/event_loop.cpp create mode 100644 src/shared/event_loop.h create mode 100644 src/shared/ipc_client.cpp create mode 100644 src/shared/ipc_client.h create mode 100644 src/shared/ipc_server.cpp create mode 100644 src/shared/ipc_server.h create mode 100644 src/shared/macro.h create mode 100644 src/shared/message.cpp create mode 100644 src/shared/message.h create mode 100644 src/shared/sensor_info.cpp create mode 100644 src/shared/sensor_info.h create mode 100644 src/shared/sensor_types_private.h create mode 100644 src/shared/sensor_utils.cpp create mode 100644 src/shared/sensor_utils.h create mode 100644 src/shared/seqpacket_socket.cpp create mode 100644 src/shared/seqpacket_socket.h create mode 100644 src/shared/socket.cpp create mode 100644 src/shared/socket.h create mode 100644 src/shared/stream_socket.cpp create mode 100644 src/shared/stream_socket.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 12faffe..c4964fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,62 +1,29 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(capi-system-sensor) +PROJECT(capi-system-sensor-main) INCLUDE(GNUInstallDirs) -SET(DEPENDENTS "dlog sensor hal-api-sensor capi-base-common") - -IF("${SENSOR_RECORDER}" STREQUAL "on") - SET(DEPENDENTS "${DEPENDENTS} context-sensor-recorder-client") -ENDIF() - SET(VERSION ${FULLVER}) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) -SET(PC_NAME ${PROJECT_NAME}) -SET(PC_DESCRIPTION "Sensor C-API library") -SET(PC_INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/sensor") -SET(PC_DEPENDENTS "${DEPENDENTS}") -SET(PC_LIBDIR "${CMAKE_INSTALL_LIBDIR}") -SET(PC_LDFLAGS "-l${PROJECT_NAME}") - INCLUDE_DIRECTORIES(include ${CMAKE_CURRENT_SOURCE_DIR}) # Build options -INCLUDE(FindPkgConfig) -PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED ${DEPENDENTS}) - FOREACH(flag ${${PROJECT_NAME}_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIC -Wall -Werror -g -fdump-rtl-expand") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIC -Wall -g -fdump-rtl-expand") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fPIC -std=c++0x") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}") # Internal Logging Option #ADD_DEFINITIONS("-DTIZEN_DEBUG") -# Compile Source files -SET(SOURCES src/sensor.cpp - src/sensor_provider.cpp - src/sensor-internal.cpp - src/geomagnetic_field.c - src/fusion_util.c) - -IF("${SENSOR_RECORDER}" STREQUAL "on") - SET(SOURCES ${SOURCES} src/sensor_recorder.cpp) -ELSE() - SET(SOURCES ${SOURCES} src/sensor_recorder_dummy.cpp) -ENDIF() - -ADD_LIBRARY(${PROJECT_NAME} SHARED ${SOURCES}) - -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${${PROJECT_NAME}_LDFLAGS}) -SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${FULLVER} SOVERSION ${MAJORVER} CLEAN_DIRECT_OUTPUT 1) -CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc @ONLY) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -INSTALL(FILES include/sensor.h include/sensor-internal.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sensor) -INSTALL(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - +ADD_SUBDIRECTORY(src/shared) +ADD_SUBDIRECTORY(src/api) ADD_SUBDIRECTORY(tests) ADD_SUBDIRECTORY(tools) + +INSTALL(FILES include/sensor.h include/sensor-internal.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sensor) diff --git a/include/sensor_info.h b/include/sensor_info_list.h similarity index 95% rename from include/sensor_info.h rename to include/sensor_info_list.h index ee13601..99d6cd3 100644 --- a/include/sensor_info.h +++ b/include/sensor_info_list.h @@ -1,13 +1,13 @@ -#define SENSOR_NUM (sizeof(sensor_infos) / sizeof(sensor_infos[0])) +#define SENSOR_NUM (sizeof(sensor_info_lists) / sizeof(sensor_info_lists[0])) -struct sensor_info { +struct sensor_info_list { sensor_type_e type; const char* name; const char* alias; int value_num; }; -static const struct sensor_info sensor_infos[] = { +static const struct sensor_info_list sensor_info_lists[] = { {SENSOR_ALL, "All", "ALL", 0}, {SENSOR_ACCELEROMETER, "Accelerometer", "ACCEL", 3}, {SENSOR_GRAVITY, "Gravity sensor", "GRAVITY", 3}, diff --git a/include/sensor_internal.h b/include/sensor_internal.h new file mode 100644 index 0000000..477c8d7 --- /dev/null +++ b/include/sensor_internal.h @@ -0,0 +1,545 @@ +/* + * sensord + * + * Copyright (c) 2014 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 __SENSORD_INTERNAL_H__ +#define __SENSORD_INTERNAL_H__ + +#ifndef API +#define API __attribute__((visibility("default"))) +#endif + +#include +#include +#include + +/*header for common sensor type*/ +#include + +#define SENSOR_BATCH_LATENCY_DEFAULT UINT_MAX + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void (*sensor_cb_t)(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data); +typedef void (*sensor_events_cb_t)(sensor_t sensor, unsigned int event_type, sensor_data_t events[], int events_count, void *user_data); +typedef void (*sensorhub_cb_t)(sensor_t sensor, unsigned int event_type, sensorhub_data_t *data, void *user_data); +typedef void (*sensor_accuracy_changed_cb_t) (sensor_t sensor, unsigned long long timestamp, int accuracy, void *user_data); +typedef void (*sensor_attribute_int_changed_cb_t)(sensor_t sensor, int attribute, int value, void *user_data); +typedef void (*sensor_attribute_str_changed_cb_t)(sensor_t sensor, int attribute, const char *value, int len, void *user_data); + +/** + * @brief Get the list of available sensors of a certain type, use ALL_SENSOR to get all the sensors. + * + * @param[in] type the type of sensors requested. + * @param[out] list the list of sensors matching the asked type, the caller should explicitly free this list. + * @param[out] sensor count the count of sensors contained in the list. + * @return true on success, otherwise false. + */ +bool sensord_get_sensor_list(sensor_type_t type, sensor_t **list, int *sensor_count); + +/** + * @brief Get the default sensor for a given type. + * + * @param[in] type the type of a sensor requested. + * @return the default sensor matching the asked type on success, otherwise NULL. + */ +sensor_t sensord_get_sensor(sensor_type_t type); + +/** + * @brief Get the list of available sensors of a certain type, use ALL_SENSOR to get all the sensors. + * + * @param[in] type the type of sensors requested. + * @param[out] list the list of sensors matching the asked type, the caller should explicitly free this list. + * @param[out] sensor count the count of sensors contained in the list. + * @return 0 on success, otherwise a negative error value + * @retval 0 Successful + * @retval -EPERM Operation not permitted + * @retval -EACCES Permission denied + * @retval -ENODATA NO sensor available + */ +int sensord_get_sensors(sensor_type_t type, sensor_t **list, int *sensor_count); + +/** + * @brief Get the default sensor for a given type. + * + * @param[in] type the type of a sensor requested. + * @param[out] a sensor matching the asked type. + * @return 0 on success, otherwise a negative error value + * @retval 0 Successful + * @retval -EPERM Operation not permitted + * @retval -EACCES Permission denied + */ +int sensord_get_default_sensor(sensor_type_t type, sensor_t *sensor); + +/** + * @brief Get the type of this sensor. + * + * @param[in] sensor a sensor to get type. + * @param[out] type the type of this sensor. + * @return return true on success, otherwise false. + */ +bool sensord_get_type(sensor_t sensor, sensor_type_t *type); + +/** + * @brief Get the URI string of this sensor. + * + * @param[in] sensor a sensor to get uri. + * @return the name string of this sensor on success, otherwise NULL. + */ +const char* sensord_get_uri(sensor_t sensor); + +/** + * @brief Get the name string of this sensor. + * + * @param[in] sensor a sensor to get name. + * @return the name string of this sensor on success, otherwise NULL. + */ +const char* sensord_get_name(sensor_t sensor); + +/** + * @brief Get the vendor string of this sensor. + * + * @param[in] sensor a sensor to get vendor. + * @return the vendor string of this sensor on success, otherwise NULL. + */ +const char* sensord_get_vendor(sensor_t sensor); + +/** + * @brief Get the privilege of this sensor. + * + * @param[in] sensor a sensor to get privilege. + * @param[out] privilege the privilege of this sensor. + * @return true on success, otherwise false. + */ +bool sensord_get_privilege(sensor_t sensor, sensor_privilege_t *privilege); + +/** + * @brief Get the minimum range of this sensor in the sensor's unit. + * + * @param[in] sensor a sensor to get minimum range. + * @param[out] min_range the minimum range of this sensor in the sensor's unit. + * @return true on success, otherwise false. + */ +bool sensord_get_min_range(sensor_t sensor, float *min_range); + +/** + * @brief Get the maximum range of this sensor in the sensor's unit. + * + * @param[in] sensor a sensor to get maximum range. + * @param[out] max_range the maximum range of this sensor in the sensor's unit. + * @return true on success, otherwise false. + */ +bool sensord_get_max_range(sensor_t sensor, float *max_range); + +/** + * @brief Get the resolution of this sensor in the sensor's unit. + * + * @param[in] sensor a sensor to get resolution. + * @param[out] resolution the resolution of this sensor in the sensor's unit. + * @return true on success, otherwise false. + */ +bool sensord_get_resolution(sensor_t sensor, float *resolution); + +/** + * @brief Get the minimum interval allowed between two events in microsecond or zero if this sensor only returns a value when the data it's measuring changes. + * + * @param[in] sensor a sensor to get minimum interval. + * @param[out] min_interval the minimum interval of this sensor. + * @return true on success, otherwise false. + */ +bool sensord_get_min_interval(sensor_t sensor, int *min_interval); + +/** + * @brief Get the number of events reserved for this sensor in the batch mode FIFO. + * + * @param[in] sensor a sensor to get the number of fifo count + * @param[out] fifo_count the number of events reserved for this sensor in the batch mode FIFO + * @return true on success, otherwise false + */ +bool sensord_get_fifo_count(sensor_t sensor, int *fifo_count); + +/** + * @brief Get the maximum number of events of this sensor that could be batched. If this value is zero it indicates that batch mode is not supported for this sensor. + * + * @param[in] sensor a sensor to the maximum number of events that could be batched. + * @param[out] max_batch_count the maximum number of events of this sensor that could be batched. + * @return true on success, otherwise false. + */ +bool sensord_get_max_batch_count(sensor_t sensor, int *max_batch_count); + +/** + * @brief Get the supported event types of this sensor. + * + * @param[in] sensor a sensor to get the supported event types. + * @param[out] event_types the array containing supported event types of this sensor, the caller should explicitly free this array. + * @param[out] count the count of the supported event types of this sensor. + * @return true on success, otherwise false. + */ +bool sensord_get_supported_event_types(sensor_t sensor, unsigned int **event_types, int *count); + +/** + * @brief Check a given event type is supporeted by this sensor. + * + * @param[in] sensor a sensor to check a given event type is supporeted. + * @param[out] event_type an event type to be checked whether supported or not. + * @param[out] supported whether a given event is supported or not in this sensor. + * @return true on success, otherwise false. + */ +bool sensord_is_supported_event_type(sensor_t sensor, unsigned int event_type, bool *supported); + +/** + * @brief Check a wakeup supported or not by this sensor. + * + * @param[in] sensor a sensor to check a given event type is supporeted. + * @return true on success, otherwise false. + */ +bool sensord_is_wakeup_supported(sensor_t sensor); + +/** + * @brief Connect a given sensor and get a handle of a given sensor. + * + * @param[in] sensor a sensor to connect + * @return a handle of a given sensor on success, otherwise negative value + */ +int sensord_connect(sensor_t sensor); + +/** + * @brief Disconnect a given sensor. + * + * @param[in] handle a handle to disconnect. + * @return true on success, otherwise false. + */ +bool sensord_disconnect(int handle); + +/** + * @brief Register a callback with a connected sensor for a given event_type. This callback will be called when a given event occurs in a connected sensor. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] event_type an event type to register + * @param[in] interval The desired interval between two consecutive events in microseconds. This is only a hint to the system so events may be received faster or slower than the specified interval. + * It can be one of SENSOR_INTERVAL_NORMAL, SENSOR_INTERVAL_FASTEST or the interval in microseconds. + * @param[in] max_batch_latency An event in the batch can be delayed by at most max_batch_latency microseconds. If this is set to zero, batch mode is disabled. + * @param[in] cb a callback which is called when a given event occurs + * @param[in] user_data the callback is called with user_data + * @return true on success, otherwise false. + */ +bool sensord_register_event(int handle, unsigned int event_type, unsigned int interval, unsigned int max_batch_latency, sensor_cb_t cb, void *user_data); + +/** + * @brief Register a callback with a connected sensor for a given event_type. This callback will be called when a given event occurs in a connected sensor. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] event_type an event type to register + * @param[in] max_batch_latency An event in the batch can be delayed by at most max_batch_latency microseconds. If this is set to zero, batch mode is disabled. + * @param[in] cb a callback which is called when a given event occurs + * @param[in] user_data the callback is called with user_data + * @return true on success, otherwise false. + */ +bool sensord_register_events(int handle, unsigned int event_type, unsigned int max_batch_latency, sensor_events_cb_t cb, void *user_data); + +/** + * @brief Register a callback with a connected context sensor for a given event_type. This callback will be called when a given event occurs in a connected context sensor. + * + * @param[in] handle a handle represensting a connected context sensor. + * @param[in] event_type an event type to register + * @param[in] interval The desired interval between two consecutive events in microseconds. This is only a hint to the system so events may be received faster or slower than the specified interval. + * It can be one of SENSOR_INTERVAL_NORMAL, SENSOR_INTERVAL_FASTEST or the interval in microseconds. + * @param[in] max_batch_latency An event in the batch can be delayed by at most max_batch_latency microseconds. If this is set to zero, batch mode is disabled. + * @param[in] cb a callback which is called when a given event occurs + * @param[in] user_data the callback is called with user_data + * @return true on success, otherwise false. + */ +bool sensord_register_hub_event(int handle, unsigned int event_type, unsigned int interval, unsigned int max_batch_latency, sensorhub_cb_t cb, void *user_data); + +/** + * @brief Unregister a event with a connected sensor. After unregistering, that event will not be sent. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] event_type an event type to unregister. + * @return true on success, otherwise false. + */ +bool sensord_unregister_event(int handle, unsigned int event_type); + +/** + * @brief Unregister a event with a connected sensor. After unregistering, that event will not be sent. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] event_type an event type to unregister. + * @return true on success, otherwise false. + */ +bool sensord_unregister_events(int handle, unsigned int event_type); + +/** + * @brief Register a callback with a connected sensor. This callback will be called when the accuracy of a sensor has changed. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] cb a callback which is called when he accuracy of a sensor has changed. + * @param[in] user_data the callback is called with user_data + * @return true on success, otherwise false. + */ +bool sensord_register_accuracy_cb(int handle, sensor_accuracy_changed_cb_t cb, void *user_data); + +/** + * @brief Unregister a callback with a connected sensor. After unregistering, sensor_accuray_change_cb will not be called. + * + * @param[in] handle a handle represensting a connected sensor. + * @return true on success, otherwise false. + */ +bool sensord_unregister_accuracy_cb(int handle); + +/** + * @brief Register a callback with a connected sensor. This callback will be called when attributes of a sensor has changed. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] cb a callback which is called when he attributes of a sensor has changed. + * @param[in] user_data the callback is called with user_data + * @return true on success, otherwise false. + */ +bool sensord_register_attribute_int_changed_cb(int handle, sensor_attribute_int_changed_cb_t cb, void *user_data); + +/** + * @brief Unregister a callback with a connected sensor. After unregistering, sensor_attribute_int_changed_cb will not be called. + * + * @param[in] handle a handle represensting a connected sensor. + * @return true on success, otherwise false. + */ +bool sensord_unregister_attribute_int_changed_cb(int handle); + +/** + * @brief Register a callback with a connected sensor. This callback will be called when attributes of a sensor has changed. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] cb a callback which is called when he attributes of a sensor has changed. + * @param[in] user_data the callback is called with user_data + * @return true on success, otherwise false. + */ +bool sensord_register_attribute_str_changed_cb(int handle, sensor_attribute_str_changed_cb_t cb, void *user_data); + +/** + * @brief Unregister a callback with a connected sensor. After unregistering, sensor_attribute_str_changed_cb will not be called. + * + * @param[in] handle a handle represensting a connected sensor. + * @return true on success, otherwise false. + */ +bool sensord_unregister_attribute_str_changed_cb(int handle); + +/** + * @brief Start listening events with a connected sensor. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] option either one of SENSOR_OPTION_DEFAULT and SENSOR_OPTION_ALWAYS_ON. + * with SENSOR_OPTION_DEFAULT, it stops to listening events when LCD is off or in power save mode. + * with SENSOR_OPTION_ALWAYS_ON, it continues to listening events even when LCD is off or in power save mode. + * @return true on success, otherwise false. + */ +bool sensord_start(int handle, int option); + +/** + * @brief Stop listening events with a connected sensor. + * + * @param[in] handle a handle represensting a connected sensor. + * @return true on success, otherwise false. + */ +bool sensord_stop(int handle); + +/** + * @brief Change the interval of a specifed event type in a connected sensor. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] event_type an event type to change interval. + * @param[in] interval The desired interval between two consecutive events in microseconds. This is only a hint to the system so events may be received faster or slower than the specified interval. + * It can be one of SENSOR_INTERVAL_NORMAL, SENSOR_INTERVAL_FASTEST or the interval in microseconds. + * @return true on success, otherwise false. + */ +bool sensord_change_event_interval(int handle, unsigned int event_type, unsigned int interval); + +/** + * @brief Change the max batch latency of a specifed event type in a connected sensor. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] event_type an event type to change max batch latency + * @param[in] max_batch_latency an event in the batch can be delayed by at most max_batch_latency microseconds. If this is set to zero, batch mode is disabled. + * @return true on success, otherwise false. + */ +bool sensord_change_event_max_batch_latency(int handle, unsigned int event_type, unsigned int max_batch_latency); + +/** + * @brief Change the option of a connected sensor. + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] option either one of SENSOR_OPTION_DEFAULT and SENSOR_OPTION_ALWAYS_ON. + * with SENSOR_OPTION_DEFAULT, it stops to listening events when LCD is off or in power save mode. + * with SENSOR_OPTION_ALWAYS_ON, it continues to listening events even when LCD is off or in power save mode. + * @return true on success, otherwise false. + */ +bool sensord_set_option(int handle, int option); + +/* + * @brief Set the attribute to a connected sensor + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] attribute an attribute to change + * @param[in] value an attribute value + * @return 0 on success, otherwise a negative error value + * @retval 0 Successful + * @retval -EINVAL Invalid parameter + * @retval -EPERM Operation not permitted + */ +int sensord_set_attribute_int(int handle, int attribute, int value); + +/* + * @brief Get the attribute to a connected sensor + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] attribute an attribute to get value + * @param[out] value an attribute value + * @return 0 on success, otherwise a negative error value + * @retval 0 Successful + * @retval -EINVAL Invalid parameter + * @retval -EPERM Operation not permitted + */ +int sensord_get_attribute_int(int handle, int attribute, int* value); + +/** + * @brief Set the attribute to a connected sensor + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] attribute an attribute to change + * @param[in] value an attribute value + * @param[in] value_len the length of value + * @return 0 on success, otherwise a negative error value + * @retval 0 Successful + * @retval -EINVAL Invalid parameter + * @retval -EPERM Operation not permitted + */ +int sensord_set_attribute_str(int handle, int attribute, const char *value, int len); + +/** + * @brief Get the attribute to a connected sensor + * + * @param[in] handle a handle represensting a connected sensor. + * @param[in] attribute an attribute to get value + * @param[out] value an attribute value, the caller should explicitly free this value + * @param[out] len the length of value + * @return 0 on success, otherwise a negative error value + * @retval 0 Successful + * @retval -EINVAL Invalid parameter + * @retval -EPERM Operation not permitted + */ +int sensord_get_attribute_str(int handle, int attribute, char **value, int *len); + +/** + * @brief Send data to sensorhub + * + * @param[in] handle a handle represensting a connected context sensor. + * @param[in] data it holds data to send to sensorhub + * @param[in] data_len the length of data + * @return true on success, otherwise false. + */ +bool sensord_send_sensorhub_data(int handle, const char *data, int data_len); +bool sensord_send_command(int handle, const char *command, int command_len); + +/** + * @brief get sensor data from a connected sensor + * + * @param[in] handle a handle represensting a connected context sensor. + * @param[in] data_id it specifies data to get + * @param[out] sensor_data data from connected sensor + * @return true on success, otherwise false. + */ +bool sensord_get_data(int handle, unsigned int data_id, sensor_data_t* sensor_data); + +/** + * @brief get sensor data from a connected sensor + * + * @param[in] handle a handle represensting a connected context sensor. + * @param[in] data_id it specifies data to get + * @param[out] sensor_data the data list from connected sensor, the caller should explicitly free this list. + * @param[out] count the count of data contained in the list. + * @return true on success, otherwise false. + */ +bool sensord_get_data_list(int handle, unsigned int data_id, sensor_data_t** sensor_data, int* count); + +/** + * @brief flush sensor data from a connected sensor + * + * @param[in] handle a handle represensting a connected context sensor. + * @return true on success, otherwise false. + */ +bool sensord_flush(int handle); + +bool sensord_set_passive_mode(int handle, bool passive); + + +/* Sensor Internal API using URI */ +int sensord_get_default_sensor_by_uri(const char *uri, sensor_t *sensor); +int sensord_get_sensors_by_uri(const char *uri, sensor_t **list, int *sensor_count); + +typedef void (*sensord_added_cb)(const char *uri, void *user_data); +int sensord_add_sensor_added_cb(sensord_added_cb callback, void *user_data); +int sensord_remove_sensor_added_cb(sensord_added_cb callback); + +typedef void (*sensord_removed_cb)(const char *uri, void *user_data); +int sensord_add_sensor_removed_cb(sensord_removed_cb callback, void *user_data); +int sensord_remove_sensor_removed_cb(sensord_removed_cb callback); + +/* Sensor provider */ +typedef void *sensord_provider_h; +int sensord_create_provider(const char *uri, sensord_provider_h *provider); +int sensord_destroy_provider(sensord_provider_h provider); +int sensord_add_provider(sensord_provider_h provider); +int sensord_remove_provider(sensord_provider_h provider); + +int sensord_provider_set_name(sensord_provider_h provider, const char *name); +int sensord_provider_set_vendor(sensord_provider_h provider, const char *vendor); +int sensord_provider_set_range(sensord_provider_h provider, float min_range, float max_range); +int sensord_provider_set_resolution(sensord_provider_h provider, float resolution); + +typedef void (*sensord_provider_start_cb)(sensord_provider_h provider, void *user_data); +int sensord_provider_set_start_cb(sensord_provider_h provider, sensord_provider_start_cb callback, void *user_data); + +typedef void (*sensord_provider_stop_cb)(sensord_provider_h provider, void *user_data); +int sensord_provider_set_stop_cb(sensord_provider_h provider, sensord_provider_stop_cb callback, void *user_data); + +typedef void (*sensord_provider_interval_changed_cb)(sensord_provider_h provider, unsigned int interval_ms, void *user_data); +int sensord_provider_set_interval_changed_cb(sensord_provider_h provider, sensord_provider_interval_changed_cb callback, void *user_data); + +typedef void (*sensord_provider_attribute_str_cb)(sensord_provider_h provider, int attribute, const char *value, int count, void *user_data); +int sensord_provider_set_attribute_str_cb(sensord_provider_h provider, sensord_provider_attribute_str_cb callback, void *user_data); + +int sensord_provider_publish(sensord_provider_h provider, sensor_data_t data); +int sensord_provider_publish_events(sensord_provider_h provider, sensor_data_t events[], int count); + +/* Deprecated */ +typedef void (*sensor_external_command_cb_t)(int handle, const char* data, int data_cnt, void *user_data); +int sensord_external_connect(const char *key, sensor_external_command_cb_t cb, void *user_data); +bool sensord_external_disconnect(int handle); +bool sensord_external_post(int handle, unsigned long long timestamp, const float* data, int data_cnt); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __SENSORD_INTERNAL_H__ */ diff --git a/include/sensor_log.h b/include/sensor_log.h index e70b435..3904e13 100644 --- a/include/sensor_log.h +++ b/include/sensor_log.h @@ -22,11 +22,58 @@ extern "C" { #endif -#include +#include +#include -#undef LOG_TAG +#ifdef LOG_TAG + #undef LOG_TAG +#endif #define LOG_TAG "TIZEN_SYSTEM_SENSOR" +/* Logging and Error Handling */ +#define _I SLOGI +#define _D SLOGD +#define _W SLOGW +#define _E SLOGE +#define _SI SECURE_SLOGI +#define _SD SECURE_SLOGD +#define _SW SECURE_SLOGW +#define _SE SECURE_SLOGE + +#define _ERRNO(errno, tag, fmt, arg...) \ + do { \ + char buf[1024]; \ + char *error = strerror_r(errno, buf, 1024); \ + if (!error) { \ + _E("Failed to strerror_r()"); \ + break; \ + } \ + tag(fmt" (%s[%d])", ##arg, error, errno); \ + } while (0) + +#define warn_if(expr, fmt, arg...) \ + do { if (expr) { _E(fmt, ##arg); } } while (0) + +#define ret_if(expr) \ + do { if (expr) { return; } } while (0) + +#define retv_if(expr, val) \ + do { if (expr) { return (val); } } while (0) + +#define retm_if(expr, fmt, arg...) \ + do { if (expr) { _E(fmt, ##arg); return; } } while (0) + +#define retvm_if(expr, val, fmt, arg...) \ + do { if (expr) { _E(fmt, ##arg); return (val); } } while (0) + +#define LOG_DUMP(fp, fmt, arg...) \ + do { if (fp) fprintf(fp, fmt, ##arg); else _E(fmt, ##arg); } while (0) + +#define log_oom() ({ \ + _E("Out of memory"); \ + -ENOMEM;}) + + #define _MSG_SENSOR_ERROR_IO_ERROR "Io Error" #define _MSG_SENSOR_ERROR_INVALID_PARAMETER "Invalid Parameter" #define _MSG_SENSOR_ERROR_OUT_OF_MEMORY "Out of Memory" @@ -36,13 +83,8 @@ extern "C" #define _E_MSG(err) SLOGE(_MSG_##err "(0x%08x)", (err)) -#define _E(fmt, args...) LOGE(fmt, ##args) -#define _W(fmt, args...) LOGW(fmt, ##args) -#define _I(fmt, args...) LOGI(fmt, ##args) -#define _D(fmt, args...) LOGD(fmt, ##args) - #ifdef __cplusplus } #endif -#endif /*_SENSOR_LOG_H_*/ +#endif /* _SENSOR_LOG_H_ */ diff --git a/include/sensor_types.h b/include/sensor_types.h new file mode 100644 index 0000000..a2028d3 --- /dev/null +++ b/include/sensor_types.h @@ -0,0 +1,294 @@ +/* + * sensord + * + * 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 __SENSOR_TYPES_H__ +#define __SENSOR_TYPES_H__ + +/* TODO: It is for compatibility with capi-system-sensor */ +#define __SENSOR_COMMON_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef OP_SUCCESS +#define OP_SUCCESS 0 +#endif +#ifndef OP_ERROR +#define OP_ERROR -1 +#endif +#ifndef OP_DEFAULT +#define OP_DEFAULT 1 +#endif +#ifndef OP_CONTINUE +#define OP_CONTINUE 2 +#endif +#ifndef NAME_MAX +#define NAME_MAX 256 +#endif + +#define SENSOR_TYPE_SHIFT 32 +#define SENSOR_EVENT_SHIFT 16 +#define SENSOR_INDEX_MASK 0xFFFFFFFF + +#define CONVERT_ID_TYPE(id) ((id) >> SENSOR_TYPE_SHIFT) +#define CONVERT_TYPE_EVENT(type) ((type) << SENSOR_EVENT_SHIFT | 0x1) + +#define MICROSECONDS(tv) ((tv.tv_sec * 1000000ll) + tv.tv_usec) + +#define SENSOR_UNKNOWN_TYPE "http://tizen.org/sensor/unknown" +#define SENSOR_UNKNOWN_NAME "Unknown" + +typedef int64_t sensor_id_t; +typedef void *sensor_t; + +typedef enum sensor_type_t { + UNKNOWN_SENSOR = -2, + ALL_SENSOR = -1, + ACCELEROMETER_SENSOR = 0, + GRAVITY_SENSOR, + LINEAR_ACCEL_SENSOR, + GEOMAGNETIC_SENSOR, + ROTATION_VECTOR_SENSOR, + ORIENTATION_SENSOR, + GYROSCOPE_SENSOR, + LIGHT_SENSOR, + PROXIMITY_SENSOR, + PRESSURE_SENSOR, + ULTRAVIOLET_SENSOR, + TEMPERATURE_SENSOR, + HUMIDITY_SENSOR, + HRM_SENSOR, + BIO_HRM_SENSOR = HRM_SENSOR, + HRM_LED_GREEN_SENSOR, + BIO_LED_GREEN_SENSOR = HRM_LED_GREEN_SENSOR, + HRM_LED_IR_SENSOR, + BIO_LED_IR_SENSOR = HRM_LED_IR_SENSOR, + HRM_LED_RED_SENSOR, + BIO_LED_RED_SENSOR = HRM_LED_RED_SENSOR, + GYROSCOPE_UNCAL_SENSOR, + GEOMAGNETIC_UNCAL_SENSOR, + GYROSCOPE_RV_SENSOR, + GEOMAGNETIC_RV_SENSOR, + + GYROSCOPE_ORIENTATION_SENSOR = 100, + GEOMAGNETIC_ORIENTATION_SENSOR = 105, + + SIGNIFICANT_MOTION_SENSOR = 0x100, //256 + + HRM_BATCH_SENSOR = 0x200, //512 + HRM_LED_GREEN_BATCH_SENSOR, + + HUMAN_PEDOMETER_SENSOR = 0x300, //768 + HUMAN_SLEEP_MONITOR_SENSOR, + HUMAN_SLEEP_DETECTOR_SENSOR, + SLEEP_DETECTOR_SENSOR = HUMAN_SLEEP_DETECTOR_SENSOR, + HUMAN_STRESS_MONITOR_SENSOR, + STRESS_MONITOR_SENSOR = HUMAN_STRESS_MONITOR_SENSOR, + + LIDAR_SENSOR = 1000, + + EXERCISE_WALKING_SENSOR = 0x400, //1024 + EXERCISE_RUNNING_SENSOR, + EXERCISE_HIKING_SENSOR, + EXERCISE_CYCLING_SENSOR, + EXERCISE_ELLIPTICAL_SENSOR, + EXERCISE_INDOOR_CYCLING_SENSOR, + EXERCISE_ROWING_SENSOR, + EXERCISE_STEPPER_SENSOR, + + DATA_JOURNAL_SENSOR = 0x500, + // 0x500~0x600 Reserved (1280 ~ 1536) + + EXTERNAL_EXERCISE_SENSOR = 0x800, //2048 + EXERCISE_SENSOR = EXTERNAL_EXERCISE_SENSOR, + + FUSION_SENSOR = 0x900, //2304 + AUTO_ROTATION_SENSOR, + AUTO_BRIGHTNESS_SENSOR, + MYOTEST_SENSOR, + + GESTURE_MOVEMENT_SENSOR = 0x1200, //4608 + GESTURE_WRIST_UP_SENSOR, + GESTURE_WRIST_DOWN_SENSOR, + GESTURE_MOVEMENT_STATE_SENSOR, + GESTURE_PICK_UP_SENSOR, + GESTURE_FACE_DOWN_SENSOR, + + ACTIVITY_TRACKER_SENSOR = 0x1A00, //6656 + ACTIVITY_LEVEL_MONITOR_SENSOR, + GPS_BATCH_SENSOR, + PPG_BATCH_SENSOR, + GPS_TIMESYNC_SENSOR, + + HRM_CTRL_SENSOR = 0x1A80, //6784 + REG_CTRL_SENSOR, + GPS_CTRL_SENSOR, + + WEAR_STATUS_SENSOR = 0x2000, //8192 + WEAR_ON_MONITOR_SENSOR, + NO_MOVE_DETECTOR_SENSOR, + RESTING_HR_SENSOR, + STEP_LEVEL_MONITOR_SENSOR, + EXERCISE_STANDALONE_SENSOR, + EXERCISE_COACH_SENSOR = EXERCISE_STANDALONE_SENSOR, + EXERCISE_HR_SENSOR, + WORKOUT_SENSOR, + AUTOSESSION_EXERCISE_SENSOR = WORKOUT_SENSOR, + CYCLE_MONITOR_SENSOR, + STAIR_TRACKER_SENSOR, + PRESSURE_INDICATOR_SENSOR, + PRESSURE_ALERT_SENSOR, + HR_CALORIE_SENSOR, + SWIMMING_TRACKER_SENSOR, + STRESS_TRACKER_SENSOR, + FAKE_MOTION_SENSOR, + GEOFENCE_SENSOR, + SWIMMING_OUTDOOR_SENSOR, + AUTO_SWIMMING_SENSOR, + INACTIVITY_DETECTOR_SENSOR, + HRM_BP_SENSOR, + ECG_SENSOR, + FALL_DETECTION_SENSOR, + + CONTEXT_SENSOR = 0x7000, //28,672 + MOTION_SENSOR, + PIR_SENSOR, + PIR_LONG_SENSOR, + DUST_SENSOR, + THERMOMETER_SENSOR, + PEDOMETER_SENSOR, + FLAT_SENSOR, + HRM_RAW_SENSOR, + BIO_SENSOR = HRM_RAW_SENSOR, + TILT_SENSOR, + RV_RAW_SENSOR, + GSR_SENSOR, + SIMSENSE_SENSOR, + PPG_SENSOR, + + CUSTOM_SENSOR = 0X9000, //36,864 +} sensor_type_t; + +typedef struct sensor_info2_t { + uint32_t id; + sensor_type_t type; + const char *uri; + const char *vendor; + float min_range; + float max_range; + float resolution; + int min_interval; + int max_interval; + int max_batch_count; + bool wakeup_supported; + const char *privilege; + void *reserved[8]; +} sensor_info2_t; + +typedef enum sensor_privilege_t { + SENSOR_PRIVILEGE_PUBLIC = 0, +} sensor_privilege_t; + +typedef struct sensor_event_t { + unsigned int event_type; + sensor_id_t sensor_id; + unsigned int data_length; + sensor_data_t *data; +} sensor_event_t; + +/* + * To prevent naming confliction as using same enums as sensor CAPI use + */ +#ifndef __SENSOR_H__ +enum sensor_option_t { + SENSOR_OPTION_DEFAULT = 0, + SENSOR_OPTION_ON_IN_SCREEN_OFF = 1, + SENSOR_OPTION_ON_IN_POWERSAVE_MODE = 2, + SENSOR_OPTION_ALWAYS_ON = SENSOR_OPTION_ON_IN_SCREEN_OFF | SENSOR_OPTION_ON_IN_POWERSAVE_MODE, + SENSOR_OPTION_END +}; + +typedef enum sensor_option_t sensor_option_e; +#endif + +enum sensord_attribute_e { + SENSORD_ATTRIBUTE_AXIS_ORIENTATION = 1, + SENSORD_ATTRIBUTE_PAUSE_POLICY, + SENSORD_ATTRIBUTE_INTERVAL = 0x10, + SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY, + SENSORD_ATTRIBUTE_PASSIVE_MODE, + SENSORD_ATTRIBUTE_FLUSH, + // 0x50~0x80 Reserved +}; + +enum sensord_axis_e { + SENSORD_AXIS_DEVICE_ORIENTED = 1, + SENSORD_AXIS_DISPLAY_ORIENTED, +}; + +enum sensord_pause_e { + SENSORD_PAUSE_NONE = 0, + SENSORD_PAUSE_ON_DISPLAY_OFF = 1, + SENSORD_PAUSE_ON_POWERSAVE_MODE = 2, + SENSORD_PAUSE_ALL = 3, + SENSORD_PAUSE_END, +}; + +enum poll_interval_t { + POLL_100HZ_MS = 10, + POLL_50HZ_MS = 20, + POLL_25HZ_MS = 40, + POLL_20HZ_MS = 50, + POLL_10HZ_MS = 100, + POLL_5HZ_MS = 200, + POLL_1HZ_MS = 1000, + POLL_MAX_HZ_MS = 255000, +}; + +#define DEFAULT_INTERVAL POLL_10HZ_MS + +enum sensor_interval_t { + SENSOR_INTERVAL_FASTEST = POLL_100HZ_MS, + SENSOR_INTERVAL_NORMAL = POLL_5HZ_MS, +}; + +enum proxi_change_state { + PROXIMITY_STATE_NEAR = 0, + PROXIMITY_STATE_FAR = 1, +}; + +enum auto_rotation_state { + AUTO_ROTATION_DEGREE_UNKNOWN = 0, + AUTO_ROTATION_DEGREE_0, + AUTO_ROTATION_DEGREE_90, + AUTO_ROTATION_DEGREE_180, + AUTO_ROTATION_DEGREE_270, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __SENSOR_TYPES_H__ */ diff --git a/packaging/capi-system-sensor.spec b/packaging/capi-system-sensor.spec index 7a737c7..dd07e40 100644 --- a/packaging/capi-system-sensor.spec +++ b/packaging/capi-system-sensor.spec @@ -14,7 +14,9 @@ Source0: %{name}-%{version}.tar.gz BuildRequires: cmake BuildRequires: pkgconfig(dlog) -BuildRequires: pkgconfig(sensor) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(libsystemd) +BuildRequires: pkgconfig(libtzplatform-config) BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(hal-api-sensor) %if "%{?SENSOR_RECORDER}" == "on" @@ -99,6 +101,7 @@ find . -name '*.gcno' -exec cp --parents '{}' "$gcno_obj_dir" ';' %files %manifest packaging/capi-system-sensor.manifest %{_libdir}/libcapi-system-sensor.so.* +%{_libdir}/libsensor-shared.so %license LICENSE.APLv2 %files devel diff --git a/src/api/CMakeLists.txt b/src/api/CMakeLists.txt new file mode 100644 index 0000000..2e70720 --- /dev/null +++ b/src/api/CMakeLists.txt @@ -0,0 +1,58 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(capi-system-sensor) +INCLUDE(GNUInstallDirs) + +SET(DEPENDENTS "dlog hal-api-sensor capi-base-common") + +IF("${SENSOR_RECORDER}" STREQUAL "on") + SET(DEPENDENTS "${DEPENDENTS} context-sensor-recorder-client") +ENDIF() + +SET(VERSION ${FULLVER}) +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +SET(PC_NAME ${PROJECT_NAME}) +SET(PC_DESCRIPTION "Sensor C-API library") +SET(PC_INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/sensor") +SET(PC_DEPENDENTS "${DEPENDENTS}") +SET(PC_LIBDIR "${CMAKE_INSTALL_LIBDIR}") +SET(PC_LDFLAGS "-l${PROJECT_NAME}") + +INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR}/src/shared + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# Build options +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED ${DEPENDENTS}) + +FOREACH(flag ${${PROJECT_NAME}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIC -Wall -g -fdump-rtl-expand") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fPIC -std=c++0x") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}") + +# Internal Logging Option +#ADD_DEFINITIONS("-DTIZEN_DEBUG") + +# Compile Source files +FILE(GLOB SOURCES *.c *.cpp) + +IF("${SENSOR_RECORDER}" STREQUAL "on") + SET(SOURCES ${SOURCES} sensor_recorder/sensor_recorder.cpp) +ELSE() + SET(SOURCES ${SOURCES} sensor_recorder/sensor_recorder_dummy.cpp) +ENDIF() + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SOURCES}) + +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${${PROJECT_NAME}_LDFLAGS} "sensor-shared") +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${FULLVER} SOVERSION ${MAJORVER} CLEAN_DIRECT_OUTPUT 1) +CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +INSTALL(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/src/api/capi-system-sensor.pc.in b/src/api/capi-system-sensor.pc.in new file mode 100644 index 0000000..c7ebed2 --- /dev/null +++ b/src/api/capi-system-sensor.pc.in @@ -0,0 +1,14 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@PREFIX@/bin +libdir=@PC_LIBDIR@ +includedir=@PC_INCLUDEDIR@ + +Name: @PC_NAME@ +Description: @PC_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_DEPENDENTS@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir} + diff --git a/src/fusion_util.c b/src/api/fusion_util.c similarity index 100% rename from src/fusion_util.c rename to src/api/fusion_util.c diff --git a/src/geomagnetic_field.c b/src/api/geomagnetic_field.c similarity index 100% rename from src/geomagnetic_field.c rename to src/api/geomagnetic_field.c diff --git a/src/sensor-internal.cpp b/src/api/sensor-internal.cpp similarity index 100% rename from src/sensor-internal.cpp rename to src/api/sensor-internal.cpp diff --git a/src/sensor.cpp b/src/api/sensor.cpp similarity index 100% rename from src/sensor.cpp rename to src/api/sensor.cpp diff --git a/src/api/sensor_internal.cpp b/src/api/sensor_internal.cpp new file mode 100644 index 0000000..2c9b833 --- /dev/null +++ b/src/api/sensor_internal.cpp @@ -0,0 +1,1197 @@ +/* + * sensord + * + * Copyright (c) 2013 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 +#include +#include +#include + +#include "sensor_reader.h" + +#define CONVERT_OPTION_TO_PAUSE_POLICY(option) ((option) ^ 0b11) +#define MAX_LISTENER 100 +#define MAX_PROVIDER 20 + +using namespace sensor; + +typedef struct { + int listener_id; + sensor_info *sensor; + void* cb; + char* data; + size_t data_size; + void *user_data; +} callback_info_s; + +typedef GSourceFunc callback_dispatcher_t; + +static sensor::sensor_manager manager; +static std::unordered_map listeners; +static cmutex lock; +static uint providerCnt = 0; + +static gboolean sensor_events_callback_dispatcher(gpointer data) +{ + int event_type = 0; + callback_info_s *info = (callback_info_s *)data; + + AUTOLOCK(lock); + + if (info->sensor) + event_type = CONVERT_TYPE_EVENT(info->sensor->get_type()); + + if (info->cb && info->sensor && listeners.find(info->listener_id) != listeners.end()) { + size_t element_size = sizeof(sensor_data_t); + size_t count = info->data_size / element_size; + ((sensor_events_cb_t)info->cb)(info->sensor, event_type, (sensor_data_t*)info->data, count, info->user_data); + } + + delete [] info->data; + delete info; + return FALSE; +} + +static gboolean sensor_event_callback_dispatcher(gpointer data) +{ + int event_type = 0; + callback_info_s *info = (callback_info_s *)data; + + AUTOLOCK(lock); + + if (info->sensor) + event_type = CONVERT_TYPE_EVENT(info->sensor->get_type()); + + if (info->cb && info->sensor && listeners.find(info->listener_id) != listeners.end()) { + ((sensor_cb_t)info->cb)(info->sensor, event_type, (sensor_data_t*)info->data, info->user_data); + } + + delete [] info->data; + delete info; + return FALSE; +} + +static gboolean sensor_accuracy_changed_callback_dispatcher(gpointer data) +{ + callback_info_s *info = (callback_info_s *)data; + + AUTOLOCK(lock); + + if (info->cb && info->sensor && listeners.find(info->listener_id) != listeners.end()) { + sensor_data_t * sensor_data = (sensor_data_t *)info->data; + ((sensor_accuracy_changed_cb_t)info->cb)(info->sensor, sensor_data->timestamp, sensor_data->accuracy, info->user_data); + } + + delete [] info->data; + delete info; + return FALSE; +} + +static gboolean sensor_attribute_int_changed_callback_dispatcher(gpointer data) +{ + callback_info_s *info = (callback_info_s *)data; + + AUTOLOCK(lock); + + if (info->cb && info->sensor && listeners.find(info->listener_id) != listeners.end()) { + cmd_listener_attr_int_t *d = (cmd_listener_attr_int_t *)info->data; + ((sensor_attribute_int_changed_cb_t)info->cb)(info->sensor, d->attribute, d->value, info->user_data); + } + + delete [] info->data; + delete info; + return FALSE; +} + +static gboolean sensor_attribute_str_changed_callback_dispatcher(gpointer data) +{ + callback_info_s *info = (callback_info_s *)data; + + AUTOLOCK(lock); + + if (info->cb && info->sensor && listeners.find(info->listener_id) != listeners.end()) { + cmd_listener_attr_str_t *d = (cmd_listener_attr_str_t *)info->data; + ((sensor_attribute_str_changed_cb_t)info->cb)(info->sensor, d->attribute, d->value, d->len, info->user_data); + } + + delete [] info->data; + delete info; + return FALSE; +} + +class sensor_listener_channel_handler : public ipc::channel_handler +{ +public: + sensor_listener_channel_handler(int id, sensor_t sensor, void* cb, void *user_data, callback_dispatcher_t dispatcher) + : m_listener_id(id) + , m_sensor(reinterpret_cast(sensor)) + , m_cb(cb) + , m_user_data(user_data) + , m_dispatcher(dispatcher) + {} + + void connected(ipc::channel *ch) {} + void disconnected(ipc::channel *ch) {} + void read(ipc::channel *ch, ipc::message &msg) + { + callback_info_s *info; + auto size = msg.size(); + char *data = new(std::nothrow) char[size]; + if (data == NULL) + return; + memcpy(data, msg.body(), size); + + info = new(std::nothrow) callback_info_s(); + info->listener_id = m_listener_id; + info->cb = m_cb; + info->sensor = m_sensor; + info->data = data; + info->data_size = size; + info->user_data = m_user_data; + + g_idle_add(m_dispatcher, info); + } + + void read_complete(ipc::channel *ch) {} + void error_caught(ipc::channel *ch, int error) {} + void set_handler(int num, ipc::channel_handler* handler) {} + void disconnect(void) {} + +private: + int m_listener_id; + sensor_info *m_sensor; + void* m_cb; + void *m_user_data; + callback_dispatcher_t m_dispatcher; +}; + +/* + * TO-DO-LIST: + * 1. power save option / lcd vconf : move to server + * 2. thread-safe : ipc_client + */ + +API int sensord_get_sensors(sensor_type_t type, sensor_t **list, int *count) +{ + return sensord_get_sensors_by_uri(utils::get_uri(type), list, count); +} + +API int sensord_get_default_sensor(sensor_type_t type, sensor_t *sensor) +{ + return sensord_get_default_sensor_by_uri(utils::get_uri(type), sensor); +} + +API bool sensord_get_type(sensor_t sensor, sensor_type_t *type) +{ + retvm_if(!type, false, "Invalid type"); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%p]", sensor); + + *type = static_cast(sensor)->get_type(); + + return true; +} + +API const char* sensord_get_uri(sensor_t sensor) +{ + retvm_if(!manager.connect(), NULL, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), NULL, + "Invalid sensor[%p]", sensor); + + return static_cast(sensor)->get_uri().c_str(); +} + +API const char* sensord_get_name(sensor_t sensor) +{ + retvm_if(!manager.connect(), NULL, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), NULL, + "Invalid sensor[%p]", sensor); + + return static_cast(sensor)->get_model().c_str(); +} + +API const char* sensord_get_vendor(sensor_t sensor) +{ + retvm_if(!manager.connect(), NULL, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), NULL, + "Invalid sensor[%p]", sensor); + + return static_cast(sensor)->get_vendor().c_str(); +} + +API bool sensord_get_min_range(sensor_t sensor, float *min_range) +{ + retvm_if(!min_range, false, "Invalid paramter"); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%p]", sensor); + + *min_range = static_cast(sensor)->get_min_range(); + + return true; +} + +API bool sensord_get_max_range(sensor_t sensor, float *max_range) +{ + retvm_if(!max_range, false, "Invalid parameter"); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%p]", sensor); + + *max_range = static_cast(sensor)->get_max_range(); + + return true; +} + +API bool sensord_get_resolution(sensor_t sensor, float *resolution) +{ + retvm_if(!resolution, false, "Invalid parameter"); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%p]", sensor); + + *resolution = static_cast(sensor)->get_resolution(); + + return true; +} + +API bool sensord_get_min_interval(sensor_t sensor, int *min_interval) +{ + retvm_if(!min_interval, false, "Invalid parameter"); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%p]", sensor); + + *min_interval = static_cast(sensor)->get_min_interval(); + + return true; +} + +API bool sensord_get_fifo_count(sensor_t sensor, int *fifo_count) +{ + retvm_if(!fifo_count, false, "Invalid parameter"); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%p]", sensor); + + *fifo_count = 0; + + return true; +} + +API bool sensord_get_max_batch_count(sensor_t sensor, int *max_batch_count) +{ + retvm_if(!max_batch_count, false, "Invalid parameter"); + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%p]", sensor); + + *max_batch_count = static_cast(sensor)->get_max_batch_count(); + + return true; +} + +API bool sensord_is_wakeup_supported(sensor_t sensor) +{ + retvm_if(!manager.connect(), false, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), false, + "Invalid sensor[%p]", sensor); + + return static_cast(sensor)->is_wakeup_supported(); +} + +API int sensord_connect(sensor_t sensor) +{ + AUTOLOCK(lock); + + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + retvm_if(!manager.is_supported(sensor), -EINVAL, + "Invalid sensor[%p]", sensor); + retvm_if(listeners.size() > MAX_LISTENER, -EPERM, "Exceeded the maximum listener"); + + sensor::sensor_listener *listener; + static sensor_reader reader; + + listener = new(std::nothrow) sensor::sensor_listener(sensor, reader.get_event_loop()); + retvm_if(!listener, -ENOMEM, "Failed to allocate memory"); + + listeners[listener->get_id()] = listener; + + _D("Connect[%d]", listener->get_id()); + + return listener->get_id(); +} + +API bool sensord_disconnect(int handle) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + retvm_if(!listener, false, "Invalid handle[%d]", handle); + + _D("Disconnect[%d]", listener->get_id()); + + delete listener; + listeners.erase(handle); + + if (listeners.empty()) + manager.disconnect(); + + return true; +} + +static inline bool sensord_register_event_impl(int handle, unsigned int event_type, + unsigned int interval, unsigned int max_batch_latency, void* cb, bool is_events_callback, void *user_data) +{ + sensor::sensor_listener *listener; + int prev_interval; + int prev_max_batch_latency; + sensor_listener_channel_handler *handler; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + prev_interval = listener->get_interval(); + prev_max_batch_latency = listener->get_max_batch_latency(); + + if (listener->set_interval(interval) < 0) { + _E("Failed to set interval"); + return false; + } + + if (listener->set_max_batch_latency(max_batch_latency) < 0) { + listener->set_interval(prev_interval); + _E("Failed to set max_batch_latency"); + return false; + } + + if (is_events_callback) { + handler = new(std::nothrow)sensor_listener_channel_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_events_callback_dispatcher); + } else { + handler = new(std::nothrow)sensor_listener_channel_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_event_callback_dispatcher); + } + + if (!handler) { + listener->set_max_batch_latency(prev_max_batch_latency); + listener->set_interval(prev_interval); + _E("Failed to allocate memory"); + return false; + } + + listener->set_event_handler(handler); + + _D("Register event[%d]", listener->get_id()); + + return true; +} + +API bool sensord_register_event(int handle, unsigned int event_type, + unsigned int interval, unsigned int max_batch_latency, sensor_cb_t cb, void *user_data) +{ + return sensord_register_event_impl(handle, event_type, interval, max_batch_latency, (void*)cb, false, user_data); +} + +static inline bool sensord_unregister_event_imple(int handle) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + listener->unset_event_handler(); + + _D("Unregister event[%d]", listener->get_id()); + + return true; +} + +API bool sensord_unregister_event(int handle, unsigned int event_type) +{ + return sensord_unregister_event_imple(handle); +} + +API bool sensord_register_events(int handle, unsigned int event_type, unsigned int max_batch_latency, sensor_events_cb_t cb, void *user_data) +{ + return sensord_register_event_impl(handle, event_type, 0, max_batch_latency, (void*)cb, true, user_data); +} + +API bool sensord_unregister_events(int handle, unsigned int event_type) +{ + return sensord_unregister_event_imple(handle); +} + +API bool sensord_register_accuracy_cb(int handle, sensor_accuracy_changed_cb_t cb, void *user_data) +{ + sensor::sensor_listener *listener; + sensor_listener_channel_handler *handler; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + handler = new(std::nothrow) sensor_listener_channel_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_accuracy_changed_callback_dispatcher); + retvm_if(!handler, false, "Failed to allocate memory"); + + listener->set_accuracy_handler(handler); + + return true; +} + +API bool sensord_unregister_accuracy_cb(int handle) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + listener->unset_accuracy_handler(); + + return true; +} + +API bool sensord_register_attribute_int_changed_cb(int handle, sensor_attribute_int_changed_cb_t cb, void *user_data) +{ + sensor::sensor_listener *listener; + sensor_listener_channel_handler *handler; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + handler = new(std::nothrow) sensor_listener_channel_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_attribute_int_changed_callback_dispatcher); + retvm_if(!handler, false, "Failed to allocate memory"); + + listener->set_attribute_int_changed_handler(handler); + + return true; +} + +API bool sensord_unregister_attribute_int_changed_cb(int handle) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + listener->unset_attribute_int_changed_handler(); + + return true; +} + +API bool sensord_register_attribute_str_changed_cb(int handle, sensor_attribute_str_changed_cb_t cb, void *user_data) +{ + sensor::sensor_listener *listener; + sensor_listener_channel_handler *handler; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + handler = new(std::nothrow) sensor_listener_channel_handler(handle, listener->get_sensor(), (void *)cb, user_data, sensor_attribute_str_changed_callback_dispatcher); + retvm_if(!handler, false, "Failed to allocate memory"); + + listener->set_attribute_str_changed_handler(handler); + + return true; +} + +API bool sensord_unregister_attribute_str_changed_cb(int handle) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + listener->unset_attribute_str_changed_handler(); + + return true; +} + +API bool sensord_start(int handle, int option) +{ + sensor::sensor_listener *listener; + int prev_pause; + int pause; + int interval, batch_latency; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + pause = CONVERT_OPTION_TO_PAUSE_POLICY(option); + prev_pause = listener->get_pause_policy(); + + if (listener->set_attribute(SENSORD_ATTRIBUTE_PAUSE_POLICY, pause) < 0) { + _E("Failed to set pause policy[%d]", pause); + return false; + } + + if (listener->start() < 0) { + listener->set_attribute(SENSORD_ATTRIBUTE_PAUSE_POLICY, prev_pause); + _E("Failed to start listener"); + return false; + } + + interval = listener->get_interval(); + if (interval > 0) + listener->set_interval(interval); + + batch_latency = listener->get_max_batch_latency(); + if (batch_latency != SENSOR_BATCH_LATENCY_DEFAULT) + listener->set_max_batch_latency(batch_latency); + + _D("Start[%d] with the interval[%d] batch_latency[%d]", + listener->get_id(), interval, batch_latency); + + return true; +} + +API bool sensord_stop(int handle) +{ + int ret; + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + ret = listener->stop(); + + if (ret == -EAGAIN || ret == OP_SUCCESS) + return true; + + _D("Stop[%d]", listener->get_id()); + + return false; +} + +API bool sensord_change_event_interval(int handle, unsigned int event_type, unsigned int interval) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->set_interval(interval) < 0) { + _E("Failed to set interval to listener"); + return false; + } + + _D("Set interval[%d, %d]", listener->get_id(), interval); + + return true; +} + +API bool sensord_change_event_max_batch_latency(int handle, unsigned int event_type, unsigned int max_batch_latency) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->set_max_batch_latency(max_batch_latency) < 0) { + _E("Failed to set max_batch_latency to listener"); + return false; + } + + _D("Set max batch latency[%d, %u]", listener->get_id(), max_batch_latency); + + return true; +} + +API bool sensord_set_option(int handle, int option) +{ + sensor::sensor_listener *listener; + int pause; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + pause = CONVERT_OPTION_TO_PAUSE_POLICY(option); + + if (listener->set_attribute(SENSORD_ATTRIBUTE_PAUSE_POLICY, pause) < 0) { + _E("Failed to set option[%d(%d)] to listener", option, pause); + return false; + } + + _D("Set pause option[%d, %d]", listener->get_id(), pause); + + return true; +} + +API int sensord_set_attribute_int(int handle, int attribute, int value) +{ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), -EINVAL, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->set_attribute(attribute, value) < 0) { + _E("Failed to set attribute[%d, %d]", attribute, value); + return -EIO; + } + + _D("Set attribute[%d, %d, %d]", listener->get_id(), attribute, value); + + return OP_SUCCESS; +} + +API int sensord_get_attribute_int(int handle, int attribute, int* value) +{ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), -EINVAL, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->get_attribute(attribute, value) < 0) { + _E("Failed to get attribute[%d]", attribute); + return -EIO; + } + + _D("Get attribute[%d, %d, %d]", listener->get_id(), attribute, *value); + + return OP_SUCCESS; +} + +API int sensord_set_attribute_str(int handle, int attribute, const char *value, int len) +{ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), -EINVAL, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->set_attribute(attribute, value, len) < 0) { + _E("Failed to set attribute[%d, %s]", attribute, value); + return -EIO; + } + _D("Set attribute ID[%d], attr[%d], len[%d]", listener->get_id(), attribute, len); + + return OP_SUCCESS; +} + +API int sensord_get_attribute_str(int handle, int attribute, char **value, int* len) +{ + sensor::sensor_listener *listener; + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), -EINVAL, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->get_attribute(attribute, value, len) < 0) { + _E("Failed to get attribute[%d]", attribute); + return -EIO; + } + _D("Get attribute ID[%d], attr[%d], len[%d]", listener->get_id(), attribute, *len); + + return OP_SUCCESS; +} + +API bool sensord_get_data(int handle, unsigned int data_id, sensor_data_t* sensor_data) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->get_sensor_data(sensor_data) < 0) { + _E("Failed to get sensor data from listener"); + return false; + } + + return true; +} + +API bool sensord_get_data_list(int handle, unsigned int data_id, sensor_data_t** sensor_data, int* count) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->get_sensor_data_list(sensor_data, count) < 0) { + _E("Failed to get sensor data from listener"); + return false; + } + + return true; +} + +API bool sensord_flush(int handle) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->flush() < 0) { + _E("Failed to flush sensor"); + return false; + } + + return true; +} + +API bool sensord_set_passive_mode(int handle, bool passive) +{ + sensor::sensor_listener *listener; + + AUTOLOCK(lock); + + auto it = listeners.find(handle); + retvm_if(it == listeners.end(), false, "Invalid handle[%d]", handle); + + listener = it->second; + + if (listener->set_passive_mode(passive) < 0) { + _E("Failed to set passive mode"); + return false; + } + + return true; +} + +/* Sensor Internal API using URI */ +API int sensord_get_default_sensor_by_uri(const char *uri, sensor_t *sensor) +{ + retvm_if(!sensor, -EINVAL, "Invalid parameter"); + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + + return manager.get_sensor(uri, sensor); +} + +API int sensord_get_sensors_by_uri(const char *uri, sensor_t **list, int *count) +{ + retvm_if((!list || !count), -EINVAL, "Invalid parameter"); + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + + return manager.get_sensors(uri, list, count); +} + +API int sensord_add_sensor_added_cb(sensord_added_cb callback, void *user_data) +{ + retvm_if(!callback, -EINVAL, "Invalid paramter"); + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + + manager.add_sensor_added_cb(callback, user_data); + return OP_SUCCESS; +} + +API int sensord_remove_sensor_added_cb(sensord_added_cb callback) +{ + retvm_if(!callback, -EINVAL, "Invalid paramter"); + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + + manager.remove_sensor_added_cb(callback); + return OP_SUCCESS; +} + +API int sensord_add_sensor_removed_cb(sensord_removed_cb callback, void *user_data) +{ + retvm_if(!callback, -EINVAL, "Invalid paramter"); + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + + manager.add_sensor_removed_cb(callback, user_data); + return OP_SUCCESS; +} + +API int sensord_remove_sensor_removed_cb(sensord_removed_cb callback) +{ + retvm_if(!callback, -EINVAL, "Invalid paramter"); + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + + manager.remove_sensor_removed_cb(callback); + return OP_SUCCESS; +} + +/* Sensor provider */ +API int sensord_create_provider(const char *uri, sensord_provider_h *provider) +{ + retvm_if(providerCnt >= MAX_PROVIDER, -EPERM, "Exceeded the maximum provider"); + retvm_if(!provider, -EINVAL, "Invalid paramter"); + + std::string str_uri(uri); + retvm_if(str_uri.find(PREDEFINED_TYPE_URI) != std::string::npos, + -EINVAL, "Invalid URI format[%s]", uri); + + static std::regex uri_regex(SENSOR_URI_REGEX, std::regex::optimize); + retvm_if(!std::regex_match(uri, uri_regex), + -EINVAL, "Invalid URI format[%s]", uri); + + sensor_provider *p; + + p = new(std::nothrow) sensor_provider(uri); + retvm_if(!p, -ENOMEM, "Failed to allocate memory"); + + *provider = static_cast(p); + providerCnt++; + return OP_SUCCESS; +} + +API int sensord_destroy_provider(sensord_provider_h provider) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + + delete static_cast(provider); + providerCnt--; + return OP_SUCCESS; +} + +API int sensord_add_provider(sensord_provider_h provider) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + + int ret; + sensor_provider *p = static_cast(provider); + + ret = p->connect(); + retv_if(ret < 0, ret); + + ret = manager.add_sensor(p); + if (ret < 0) { + p->disconnect(); + return ret; + } + + return OP_SUCCESS; +} + +API int sensord_remove_provider(sensord_provider_h provider) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + retvm_if(!manager.connect(), -EIO, "Failed to connect"); + + int ret; + sensor_provider *p = static_cast(provider); + + if (!p->disconnect()) + return OP_ERROR; + + ret = manager.remove_sensor(p); + if (ret < 0) { + p->connect(); + return OP_ERROR; + } + + return OP_SUCCESS; +} + +API int sensord_provider_set_name(sensord_provider_h provider, const char *name) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + + sensor_provider *p = static_cast(provider); + + sensor_info *info = p->get_sensor_info(); + info->set_model(name); + + return OP_SUCCESS; +} + +API int sensord_provider_set_vendor(sensord_provider_h provider, const char *vendor) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + + sensor_provider *p = static_cast(provider); + + sensor_info *info = p->get_sensor_info(); + info->set_vendor(vendor); + + return OP_SUCCESS; +} + +API int sensord_provider_set_range(sensord_provider_h provider, float min_range, float max_range) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + + sensor_provider *p = static_cast(provider); + + sensor_info *info = p->get_sensor_info(); + info->set_min_range(min_range); + info->set_max_range(max_range); + + return OP_SUCCESS; +} + +API int sensord_provider_set_resolution(sensord_provider_h provider, float resolution) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + + sensor_provider *p = static_cast(provider); + + sensor_info *info = p->get_sensor_info(); + info->set_resolution(resolution); + + return OP_SUCCESS; +} + +API int sensord_provider_set_start_cb(sensord_provider_h provider, sensord_provider_start_cb callback, void *user_data) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + retvm_if(!callback, -EINVAL, "Invalid paramter"); + + sensor_provider *p = static_cast(provider); + + p->set_start_cb(callback, user_data); + + return OP_SUCCESS; +} + +API int sensord_provider_set_stop_cb(sensord_provider_h provider, sensord_provider_stop_cb callback, void *user_data) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + retvm_if(!callback, -EINVAL, "Invalid paramter"); + + sensor_provider *p = static_cast(provider); + + p->set_stop_cb(callback, user_data); + + return OP_SUCCESS; +} + +API int sensord_provider_set_interval_changed_cb(sensord_provider_h provider, sensord_provider_interval_changed_cb callback, void *user_data) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + retvm_if(!callback, -EINVAL, "Invalid paramter"); + + sensor_provider *p = static_cast(provider); + + p->set_interval_cb(callback, user_data); + + return OP_SUCCESS; +} + +API int sensord_provider_set_attribute_str_cb(sensord_provider_h provider, sensord_provider_attribute_str_cb callback, void *user_data) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + retvm_if(!callback, -EINVAL, "Invalid paramter"); + + sensor_provider *p = static_cast(provider); + + p->set_attribute_str_cb(callback, user_data); + + return OP_SUCCESS; +} + +API int sensord_provider_publish(sensord_provider_h provider, sensor_data_t data) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + + sensor_provider *p = static_cast(provider); + + /* TODO: synchronous call is enough? */ + return p->publish(data); +} + +API int sensord_provider_publish_events(sensord_provider_h provider, sensor_data_t events[], int count) +{ + retvm_if(!provider, -EINVAL, "Invalid paramter"); + + sensor_provider *p = static_cast(provider); + + return p->publish(events, count); +}; + +/* deperecated */ +API sensor_t sensord_get_sensor(sensor_type_t type) +{ + sensor_t sensor; + + if (sensord_get_default_sensor(type, &sensor) < 0) + return NULL; + + return sensor; +} + +/* deprecated */ +API bool sensord_get_sensor_list(sensor_type_t type, sensor_t **list, int *sensor_count) +{ + return (sensord_get_sensors(type, list, sensor_count) == OP_SUCCESS); +} + +/* deprecated */ +API bool sensord_register_hub_event(int handle, unsigned int event_type, + unsigned int interval, unsigned int max_batch_latency, sensorhub_cb_t cb, void *user_data) +{ + return false; +} + +/* deprecated */ +API bool sensord_get_supported_event_types(sensor_t sensor, unsigned int **event_types, int *count) +{ + /* + * 1. check parameter + * 2. if there is no sensor, return false + * 3. memory allocation + */ + return true; +} + +/* deprecated(BUT it is used in C-API....) */ +API bool sensord_is_supported_event_type(sensor_t sensor, unsigned int event_type, bool *supported) +{ + if (!manager.is_supported(sensor)) + *supported = false; + else + *supported = true; + + return true; +} + +/* deprecated */ +API bool sensord_send_sensorhub_data(int handle, const char *data, int data_len) +{ + return (sensord_set_attribute_str(handle, 0, data, data_len) == OP_SUCCESS); +} + +/* deprecated */ +API bool sensord_send_command(int handle, const char *command, int command_len) +{ + return (sensord_set_attribute_str(handle, 0, command, command_len) == OP_SUCCESS); +} + +/* deprecated */ +API bool sensord_get_privilege(sensor_t sensor, sensor_privilege_t *privilege) +{ + *privilege = SENSOR_PRIVILEGE_PUBLIC; + + return true; +} + +/* deprecated */ +API int sensord_external_connect(const char *key, sensor_external_command_cb_t cb, void *user_data) +{ + /* + * 1. check parameter + * 2. create handle in this client + * 3. first connection(client) + * 4. cmd_connect for external sensor with key + */ + retvm_if(!key, -EINVAL, "Invalid key"); + return 0; +} + +/* deprecated */ +API bool sensord_external_disconnect(int handle) +{ + /* + * 1. check parameter + * 2. create handle in this client + * 3. first connection(client) + * 4. cmd_connect for external sensor with key + * 5. disconnect this handle + * 6. if there is no active sensor, remove client id and stop listener + */ + return true; +} + +/* deprecated */ +API bool sensord_external_post(int handle, unsigned long long timestamp, const float* data, int data_cnt) +{ + /* + * 1. check parameter + * 1.1 (data_cnt <= 0) || (data_cnt > POST_DATA_LEN_MAX)), return false + * 2. cmd_post + */ + + return true; +} + diff --git a/src/api/sensor_listener.cpp b/src/api/sensor_listener.cpp new file mode 100644 index 0000000..7c3ab4b --- /dev/null +++ b/src/api/sensor_listener.cpp @@ -0,0 +1,723 @@ +/* + * sensord + * + * 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. + * 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_listener.h" + +#include +#include +#include +#include +#include + +using namespace sensor; + +class listener_handler : public ipc::channel_handler +{ +public: + listener_handler(sensor_listener *listener) + : m_listener(listener) + { + evt_handler[0] = evt_handler[1] = evt_handler[2] = evt_handler[3] = NULL; + } + + void connected(ipc::channel *ch) {} + void disconnected(ipc::channel *ch) + { + /* If channel->disconnect() is not explicitly called, + * listener will be restored */ + if (m_listener) + m_listener->restore(); + } + + void disconnect(void) + { + m_listener = NULL; + } + + void read(ipc::channel *ch, ipc::message &msg) + { + ipc::channel_handler *handler = NULL; + switch (msg.header()->type) { + case CMD_LISTENER_EVENT: + handler = evt_handler[0]; + if (handler) + handler->read(ch, msg); + break; + case CMD_LISTENER_ACC_EVENT: + handler = evt_handler[1]; + if (handler) + handler->read(ch, msg); + break; + case CMD_LISTENER_SET_ATTR_INT: + handler = evt_handler[2]; + if (handler) + handler->read(ch, msg); + break; + case CMD_LISTENER_SET_ATTR_STR: + handler = evt_handler[3]; + if (handler) + handler->read(ch, msg); + break; + case CMD_LISTENER_CONNECTED: + // Do nothing + break; + default: + _W("Invalid command message"); + } + } + + void set_handler(int num, ipc::channel_handler* handler) { + evt_handler[num] = handler; + } + + void read_complete(ipc::channel *ch) {} + void error_caught(ipc::channel *ch, int error) {} + +private: + ipc::channel_handler *evt_handler[4]; + sensor_listener *m_listener; +}; + +sensor_listener::sensor_listener(sensor_t sensor) +: m_id(0) +, m_sensor(reinterpret_cast(sensor)) +, m_client(NULL) +, m_cmd_channel(NULL) +, m_evt_channel(NULL) +, m_handler(NULL) +, m_evt_handler(NULL) +, m_acc_handler(NULL) +, m_attr_int_changed_handler(NULL) +, m_attr_str_changed_handler(NULL) +, m_connected(false) +, m_started(false) +{ + init(); +} + +sensor_listener::sensor_listener(sensor_t sensor, ipc::event_loop *loop) +: m_id(0) +, m_sensor(reinterpret_cast(sensor)) +, m_client(NULL) +, m_cmd_channel(NULL) +, m_evt_channel(NULL) +, m_handler(NULL) +, m_evt_handler(NULL) +, m_acc_handler(NULL) +, m_attr_int_changed_handler(NULL) +, m_attr_str_changed_handler(NULL) +, m_loop(loop) +, m_connected(false) +, m_started(false) +{ + init(); +} + +sensor_listener::~sensor_listener() +{ + deinit(); +} + +bool sensor_listener::init(void) +{ + m_client = new(std::nothrow) ipc::ipc_client(SENSOR_CHANNEL_PATH); + retvm_if(!m_client, false, "Failed to allocate memory"); + + m_handler = new(std::nothrow) listener_handler(this); + if (!m_handler) { + _E("Failed to allocate memory"); + delete m_client; + return false; + } + + if (!connect()) { + delete m_handler; + delete m_client; + m_handler = NULL; + m_client = NULL; + return false; + } + + return true; +} + +void sensor_listener::deinit(void) +{ + AUTOLOCK(lock); + _D("Deinitializing.."); + stop(); + disconnect(); + + unset_event_handler(); + unset_accuracy_handler(); + unset_attribute_int_changed_handler(); + unset_attribute_str_changed_handler(); + + m_handler->disconnect(); + m_loop->add_channel_handler_release_list(m_handler); + m_handler = NULL; + + delete m_client; + m_client = NULL; + + m_attributes_int.clear(); + m_attributes_str.clear(); + _D("Deinitialized.."); +} + +int sensor_listener::get_id(void) +{ + return m_id; +} + +sensor_t sensor_listener::get_sensor(void) +{ + return static_cast(m_sensor); +} + +void sensor_listener::restore(void) +{ + if (lock.try_lock()) + return; + + m_cmd_channel->disconnect(); + delete m_cmd_channel; + m_cmd_channel = NULL; + + retm_if(!connect(), "Failed to restore listener"); + + _D("Restoring sensor listener"); + + /* Restore attributes/status */ + if (m_started.load()) + start(); + + auto interval = m_attributes_int.find(SENSORD_ATTRIBUTE_INTERVAL); + if (interval != m_attributes_int.end()) + set_interval(m_attributes_int[SENSORD_ATTRIBUTE_INTERVAL]); + + auto latency = m_attributes_int.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY); + if (latency != m_attributes_int.end()) + set_max_batch_latency(m_attributes_int[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY]); + + auto power = m_attributes_int.find(SENSORD_ATTRIBUTE_PAUSE_POLICY); + if (power != m_attributes_int.end()) + set_attribute(SENSORD_ATTRIBUTE_PAUSE_POLICY, m_attributes_int[SENSORD_ATTRIBUTE_PAUSE_POLICY]); + + _D("Restored listener[%d]", get_id()); + lock.unlock(); +} + +bool sensor_listener::connect(void) +{ + m_cmd_channel = m_client->connect(NULL); + retvm_if(!m_cmd_channel, false, "Failed to connect to server"); + + m_evt_channel = m_client->connect(m_handler, m_loop, false); + retvm_if(!m_evt_channel, false, "Failed to connect to server"); + + ipc::message msg; + ipc::message reply; + cmd_listener_connect_t buf = {0, }; + + memcpy(buf.sensor, m_sensor->get_uri().c_str(), m_sensor->get_uri().size()); + msg.set_type(CMD_LISTENER_CONNECT); + msg.enclose((const char *)&buf, sizeof(buf)); + m_evt_channel->send_sync(msg); + + m_evt_channel->read_sync(reply); + reply.disclose((char *)&buf, sizeof(buf)); + + m_id = buf.listener_id; + m_connected.store(true); + + m_evt_channel->bind(); + + _I("Connected listener[%d] with sensor[%s]", get_id(), m_sensor->get_uri().c_str()); + + return true; +} + +void sensor_listener::disconnect(void) +{ + ret_if(!is_connected()); + m_connected.store(false); + + _D("Disconnecting.."); + + m_loop->add_channel_release_queue(m_evt_channel); + m_evt_channel = NULL; + + m_cmd_channel->disconnect(); + delete m_cmd_channel; + m_cmd_channel = NULL; + + _I("Disconnected[%d]", get_id()); +} + +bool sensor_listener::is_connected(void) +{ + return m_connected.load(); +} + +ipc::channel_handler *sensor_listener::get_event_handler(void) +{ + return m_evt_handler; +} + +void sensor_listener::set_event_handler(ipc::channel_handler *handler) +{ + m_handler->set_handler(0, handler); + if (m_evt_handler) + m_loop->add_channel_handler_release_list(m_evt_handler); + m_evt_handler = handler; +} + +void sensor_listener::unset_event_handler(void) +{ + if (m_evt_handler) { + m_handler->set_handler(0, NULL); + m_loop->add_channel_handler_release_list(m_evt_handler); + m_evt_handler = NULL; + } +} + +ipc::channel_handler *sensor_listener::get_accuracy_handler(void) +{ + return m_acc_handler; +} + +void sensor_listener::set_accuracy_handler(ipc::channel_handler *handler) +{ + m_handler->set_handler(1, handler); + if (m_acc_handler) + m_loop->add_channel_handler_release_list(m_acc_handler); + m_acc_handler = handler; +} + +void sensor_listener::unset_accuracy_handler(void) +{ + if (m_acc_handler) { + m_handler->set_handler(1, NULL); + m_loop->add_channel_handler_release_list(m_acc_handler); + m_acc_handler = NULL; + } +} + +ipc::channel_handler *sensor_listener::get_attribute_int_changed_handler(void) +{ + return m_attr_int_changed_handler; +} + +void sensor_listener::set_attribute_int_changed_handler(ipc::channel_handler *handler) +{ + m_handler->set_handler(2, handler); + if (m_attr_int_changed_handler) + m_loop->add_channel_handler_release_list(m_attr_int_changed_handler); + m_attr_int_changed_handler = handler; +} + +void sensor_listener::unset_attribute_int_changed_handler(void) +{ + if (m_attr_int_changed_handler) { + m_handler->set_handler(2, NULL); + m_loop->add_channel_handler_release_list(m_attr_int_changed_handler); + m_attr_int_changed_handler = NULL; + } +} + +ipc::channel_handler *sensor_listener::get_attribute_str_changed_handler(void) +{ + return m_attr_str_changed_handler; +} + +void sensor_listener::set_attribute_str_changed_handler(ipc::channel_handler *handler) +{ + m_handler->set_handler(3, handler); + if (m_attr_str_changed_handler) + m_loop->add_channel_handler_release_list(m_attr_str_changed_handler); + m_attr_str_changed_handler = handler; +} + +void sensor_listener::unset_attribute_str_changed_handler(void) +{ + if (m_attr_str_changed_handler) { + m_handler->set_handler(3, NULL); + m_loop->add_channel_handler_release_list(m_attr_str_changed_handler); + m_attr_str_changed_handler = NULL; + } +} + +int sensor_listener::start(void) +{ + ipc::message msg; + ipc::message reply; + cmd_listener_start_t buf = {0, }; + + retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server"); + + buf.listener_id = m_id; + msg.set_type(CMD_LISTENER_START); + msg.enclose((char *)&buf, sizeof(buf)); + + m_cmd_channel->send_sync(msg); + m_cmd_channel->read_sync(reply); + + if (reply.header()->err < 0) { + _E("Failed to start listener[%d], sensor[%s]", get_id(), m_sensor->get_uri().c_str()); + return reply.header()->err; + } + + m_started.store(true); + + _I("Listener[%d] started", get_id()); + + return OP_SUCCESS; +} + +int sensor_listener::stop(void) +{ + ipc::message msg; + ipc::message reply; + cmd_listener_stop_t buf = {0, }; + + retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server"); + retvm_if(!m_started.load(), -EAGAIN, "Already stopped"); + + buf.listener_id = m_id; + msg.set_type(CMD_LISTENER_STOP); + msg.enclose((char *)&buf, sizeof(buf)); + + m_cmd_channel->send_sync(msg); + m_cmd_channel->read_sync(reply); + + if (reply.header()->err < 0) { + _E("Failed to stop listener[%d]", get_id()); + return reply.header()->err; + } + + m_started.store(false); + + _I("Listener[%d] stopped", get_id()); + + return OP_SUCCESS; +} + +int sensor_listener::get_interval(void) +{ + auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_INTERVAL); + retv_if(it == m_attributes_int.end(), -1); + + return m_attributes_int[SENSORD_ATTRIBUTE_INTERVAL]; +} + +int sensor_listener::get_max_batch_latency(void) +{ + auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY); + retv_if(it == m_attributes_int.end(), -1); + + return m_attributes_int[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY]; +} + +int sensor_listener::get_pause_policy(void) +{ + auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_PAUSE_POLICY); + retv_if(it == m_attributes_int.end(), -1); + + return m_attributes_int[SENSORD_ATTRIBUTE_PAUSE_POLICY]; +} + +int sensor_listener::get_passive_mode(void) +{ + auto it = m_attributes_int.find(SENSORD_ATTRIBUTE_PASSIVE_MODE); + retv_if(it == m_attributes_int.end(), -1); + + return m_attributes_int[SENSORD_ATTRIBUTE_PASSIVE_MODE]; +} + +int sensor_listener::set_interval(unsigned int interval) +{ + int _interval; + + /* TODO: move this logic to server */ + if (interval == 0) + _interval = DEFAULT_INTERVAL; + else if (interval < (unsigned int)m_sensor->get_min_interval()) + _interval = m_sensor->get_min_interval(); + else + _interval = interval; + + _I("Listener[%d] set interval[%u]", get_id(), _interval); + + /* If it is not started, store the value only */ + if (!m_started.load()) { + m_attributes_int[SENSORD_ATTRIBUTE_INTERVAL] = _interval; + return OP_SUCCESS; + } + + return set_attribute(SENSORD_ATTRIBUTE_INTERVAL, _interval); +} + +int sensor_listener::set_max_batch_latency(unsigned int max_batch_latency) +{ + _I("Listener[%d] set max batch latency[%u]", get_id(), max_batch_latency); + + /* If it is not started, store the value only */ + if (!m_started.load()) { + m_attributes_int[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY] = max_batch_latency; + return OP_SUCCESS; + } + + return set_attribute(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY, max_batch_latency); +} + +int sensor_listener::set_passive_mode(bool passive) +{ + _I("Listener[%d] set passive mode[%d]", get_id(), passive); + + return set_attribute(SENSORD_ATTRIBUTE_PASSIVE_MODE, passive); +} + +int sensor_listener::flush(void) +{ + _I("Listener[%d] flushes", get_id()); + + return set_attribute(SENSORD_ATTRIBUTE_FLUSH, 1); +} + +int sensor_listener::set_attribute(int attribute, int value) +{ + ipc::message msg; + ipc::message reply; + cmd_listener_attr_int_t buf = {0, }; + + retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server"); + + buf.listener_id = m_id; + buf.attribute = attribute; + buf.value = value; + msg.set_type(CMD_LISTENER_SET_ATTR_INT); + msg.enclose((char *)&buf, sizeof(buf)); + + m_cmd_channel->send_sync(msg); + m_cmd_channel->read_sync(reply); + + if (reply.header()->err < 0) + return reply.header()->err; + + if (attribute != SENSORD_ATTRIBUTE_FLUSH) { + update_attribute(attribute, value); + } + + return OP_SUCCESS; +} + +int sensor_listener::get_attribute(int attribute, int* value) +{ + ipc::message msg; + ipc::message reply; + cmd_listener_attr_int_t buf = {0, }; + + retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server"); + + buf.listener_id = m_id; + buf.attribute = attribute; + msg.set_type(CMD_LISTENER_GET_ATTR_INT); + msg.enclose((char *)&buf, sizeof(buf)); + + m_cmd_channel->send_sync(msg); + m_cmd_channel->read_sync(reply); + + if (reply.header()->err < 0) { + return reply.header()->err; + } + + if (reply.header()->length && reply.body()) { + *value = ((cmd_listener_attr_int_t *)reply.body())->value; + return OP_SUCCESS; + } + + return OP_ERROR; +} + +void sensor_listener::update_attribute(int attribute, int value) +{ + AUTOLOCK(lock); + m_attributes_int[attribute] = value; + _I("Update_attribute(int) listener[%d] attribute[%d] value[%d] attributes size[%d]", get_id(), attribute, value, m_attributes_int.size()); +} + +int sensor_listener::set_attribute(int attribute, const char *value, int len) +{ + ipc::message msg; + ipc::message reply; + cmd_listener_attr_str_t *buf; + size_t size; + + retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server"); + + size = sizeof(cmd_listener_attr_str_t) + len; + + buf = (cmd_listener_attr_str_t *) new(std::nothrow) char[size]; + retvm_if(!buf, -ENOMEM, "Failed to allocate memory"); + + msg.set_type(CMD_LISTENER_SET_ATTR_STR); + buf->listener_id = m_id; + buf->attribute = attribute; + + memcpy(buf->value, value, len); + buf->len = len; + + msg.enclose((char *)buf, size); + + m_cmd_channel->send_sync(msg); + m_cmd_channel->read_sync(reply); + + /* Message memory is released automatically after sending message, + so it doesn't need to free memory */ + + delete [] buf; + + if (reply.header()->err < 0) + return reply.header()->err; + + update_attribute(attribute, value, len); + + return OP_SUCCESS; +} + +int sensor_listener::get_attribute(int attribute, char **value, int* len) +{ + ipc::message msg; + ipc::message reply; + cmd_listener_attr_str_t buf = {0, }; + + buf.listener_id = m_id; + buf.attribute = attribute; + + msg.set_type(CMD_LISTENER_GET_ATTR_STR); + msg.enclose((char *)&buf, sizeof(buf)); + m_cmd_channel->send_sync(msg); + + m_cmd_channel->read_sync(reply); + if (reply.header()->err < 0) { + return reply.header()->err; + } + + if (reply.header()->length && reply.body()) { + cmd_listener_attr_str_t * recv_buf = (cmd_listener_attr_str_t *)reply.body(); + char* p = (char *)recv_buf->value; + *len = recv_buf->len; + *value = (char *) malloc(*len); + std::copy(p, p + recv_buf->len, *value); + return OP_SUCCESS; + } + + return OP_ERROR; +} + +void sensor_listener::update_attribute(int attribute, const char *value, int len) +{ + AUTOLOCK(lock); + m_attributes_str[attribute].clear(); + m_attributes_str[attribute].insert(m_attributes_str[attribute].begin(), value, value + len); + _I("Update_attribute(str) listener[%d] attribute[%d] value[%s] attributes size[%zu]", get_id(), attribute, value, m_attributes_int.size()); +} + +int sensor_listener::get_sensor_data(sensor_data_t *data) +{ + ipc::message msg; + ipc::message reply; + cmd_listener_get_data_t buf = {0, }; + + retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server"); + + buf.listener_id = m_id; + msg.set_type(CMD_LISTENER_GET_DATA); + msg.enclose((char *)&buf, sizeof(buf)); + + m_cmd_channel->send_sync(msg); + m_cmd_channel->read_sync(reply); + + if (reply.header()->err < 0) { + return OP_ERROR; + } + + reply.disclose((char *)&buf, sizeof(buf)); + int size = sizeof(sensor_data_t); + + if (buf.len > size || buf.len <= 0) { + data->accuracy = -1; + data->value_count = 0; + return OP_ERROR; + } + + memcpy(data, &buf.data, buf.len); + + _D("Listener[%d] read sensor data", get_id()); + + return OP_SUCCESS; +} + +int sensor_listener::get_sensor_data_list(sensor_data_t **data, int *count) +{ + ipc::message msg; + ipc::message reply; + cmd_listener_get_data_list_t buf = {0, }; + + retvm_if(!m_cmd_channel, -EIO, "Failed to connect to server"); + + buf.listener_id = m_id; + msg.set_type(CMD_LISTENER_GET_DATA_LIST); + msg.enclose((char *)&buf, sizeof(buf)); + + m_cmd_channel->send_sync(msg); + m_cmd_channel->read_sync(reply); + + if (reply.header()->err < 0) { + return reply.header()->err; + } + + size_t size = reply.size(); + cmd_listener_get_data_list_t* reply_buf = (cmd_listener_get_data_list_t *) new(std::nothrow) char[size]; + + retvm_if(!reply_buf, -ENOMEM, "Failed to allocate memory"); + + reply.disclose((char *)reply_buf, size); + + if (reply_buf->len <= 0) { + delete [] reply_buf; + return OP_ERROR; + } + + *count = reply_buf->data_count; + *data = (sensor_data_t*) malloc(reply_buf->len); + + if (!(*data)) { + _E("Memory allocation failed"); + delete [] reply_buf; + return -ENOMEM; + } + + memcpy(*data, reply_buf->data, reply_buf->len); + + _D("Listener[%d] read sensor data list", get_id()); + delete [] reply_buf; + return OP_SUCCESS; +} diff --git a/src/api/sensor_listener.h b/src/api/sensor_listener.h new file mode 100644 index 0000000..aed8b11 --- /dev/null +++ b/src/api/sensor_listener.h @@ -0,0 +1,115 @@ +/* + * sensord + * + * 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. + * 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 __SENSOR_LISTENER_H__ +#define __SENSOR_LISTENER_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sensor { + +class sensor_listener { +public: + sensor_listener(sensor_t sensor); + sensor_listener(sensor_t sensor, ipc::event_loop *loop); + virtual ~sensor_listener(); + + int get_id(void); + sensor_t get_sensor(void); + + ipc::channel_handler *get_event_handler(void); + ipc::channel_handler *get_accuracy_handler(void); + ipc::channel_handler *get_attribute_int_changed_handler(void); + ipc::channel_handler *get_attribute_str_changed_handler(void); + + /* TODO: modify the listener so that it can register multiple handlers(1:n) */ + void set_event_handler(ipc::channel_handler *handler); + void set_accuracy_handler(ipc::channel_handler *handler); + void set_attribute_int_changed_handler(ipc::channel_handler *handler); + void set_attribute_str_changed_handler(ipc::channel_handler *handler); + + void unset_event_handler(void); + void unset_accuracy_handler(void); + void unset_attribute_int_changed_handler(void); + void unset_attribute_str_changed_handler(void); + + int start(void); + int stop(void); + + int get_interval(void); + int get_max_batch_latency(void); + int get_pause_policy(void); + int get_passive_mode(void); + + int set_interval(unsigned int interval); + int set_max_batch_latency(unsigned int max_batch_latency); + int set_passive_mode(bool passive); + int set_attribute(int attribute, int value); + int get_attribute(int attribute, int* value); + void update_attribute(int attribute, int value); + int set_attribute(int attribute, const char *value, int len); + int get_attribute(int attribute, char **value, int *len); + void update_attribute(int attribute, const char *value, int len); + int get_sensor_data(sensor_data_t *data); + int get_sensor_data_list(sensor_data_t **data, int *count); + int flush(void); + + void restore(void); + +private: + bool init(void); + void deinit(void); + + bool connect(void); + void disconnect(void); + bool is_connected(void); + + int m_id; + sensor_info *m_sensor; + + ipc::ipc_client *m_client; + ipc::channel *m_cmd_channel; + ipc::channel *m_evt_channel; + ipc::channel_handler *m_handler; + ipc::channel_handler *m_evt_handler; + ipc::channel_handler *m_acc_handler; + ipc::channel_handler *m_attr_int_changed_handler; + ipc::channel_handler *m_attr_str_changed_handler; + + ipc::event_loop *m_loop { nullptr }; + std::atomic m_connected; + std::atomic m_started; + std::map m_attributes_int; + std::map> m_attributes_str; + + cmutex lock; +}; + +} + +#endif /* __SENSOR_LISTENER_H__ */ diff --git a/src/api/sensor_manager.cpp b/src/api/sensor_manager.cpp new file mode 100644 index 0000000..cec6260 --- /dev/null +++ b/src/api/sensor_manager.cpp @@ -0,0 +1,401 @@ +/* + * sensord + * + * 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. + * 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_manager.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "sensor_manager_channel_handler.h" + +using namespace sensor; + +sensor_manager::sensor_manager() +: m_client(NULL) +, m_cmd_channel(NULL) +, m_mon_channel(NULL) +, m_connected(false) +, m_handler(NULL) +{ + init(); +} + +sensor_manager::~sensor_manager() +{ + deinit(); +} + +int sensor_manager::get_sensor(const char *uri, sensor_t *sensor) +{ + if (!is_supported(uri)) { + *sensor = NULL; + _D("Not supported URI [%s]\n", uri); + return -ENODATA; + } + + sensor_info *info = get_info(uri); + retvm_if(!info, -EACCES, "There is no accessible sensor for uri[%s]", uri); + + *sensor = (sensor_t)info; + return OP_SUCCESS; +} + +int sensor_manager::get_sensors(const char *uri, sensor_t **list, int *count) +{ + retv_if(!is_supported(uri), -ENODATA); + + std::vector infos; + int size; + + infos = get_infos(uri); + size = infos.size(); + retvm_if(size == 0, -EACCES, "There is no accessible sensors for uri[%s]", uri); + + *list = (sensor_t *)malloc(sizeof(sensor_info *) * size); + retvm_if(!*list, -ENOMEM, "Failed to allocate memory"); + + for (int i = 0; i < size; ++i) + *(*list + i) = infos[i]; + + *count = size; + return OP_SUCCESS; +} + +bool sensor_manager::is_supported(sensor_t sensor) +{ + retvm_if(!sensor, false, "Invalid sensor"); + + for (auto it = m_sensors.begin(); it != m_sensors.end(); ++it) { + if (&*it == sensor) + return true; + } + + return false; +} + +bool sensor_manager::is_supported(const char *uri) +{ + if (strncmp(uri, utils::get_uri(ALL_SENSOR), strlen(utils::get_uri(ALL_SENSOR))) == 0) + return true; + + for (auto it = m_sensors.begin(); it != m_sensors.end(); ++it) { + if ((*it).get_uri() == uri) + return true; + + std::size_t found = (*it).get_uri().find_last_of("/"); + if (found == std::string::npos) + continue; + + if ((*it).get_uri().substr(0, found) == uri) + return true; + } + + return false; +} + +int sensor_manager::add_sensor(sensor_info &info) +{ + retv_if(is_supported(info.get_uri().c_str()), OP_ERROR); + + m_sensors.push_back(info); + + _I("Added sensor[%s]", info.get_uri().c_str()); + + return OP_SUCCESS; +} + +int sensor_manager::add_sensor(sensor_provider *provider) +{ + retvm_if(!provider, -EINVAL, "Invalid parameter"); + return add_sensor(*(provider->get_sensor_info())); +} + +int sensor_manager::remove_sensor(const char *uri) +{ + for (auto it = m_sensors.begin(); it != m_sensors.end(); ++it) { + if ((*it).get_uri() == uri) { + m_sensors.erase(it); + _I("Removed sensor[%s]", uri); + + return OP_SUCCESS; + } + } + + return OP_ERROR; +} + +int sensor_manager::remove_sensor(sensor_provider *provider) +{ + retvm_if(!provider, -EINVAL, "Invalid parameter"); + return remove_sensor(provider->get_uri()); +} + +void sensor_manager::add_sensor_added_cb(sensord_added_cb cb, void *user_data) +{ + m_handler->add_sensor_added_cb(cb, user_data); +} + +void sensor_manager::remove_sensor_added_cb(sensord_added_cb cb) +{ + m_handler->remove_sensor_added_cb(cb); +} + +void sensor_manager::add_sensor_removed_cb(sensord_removed_cb cb, void *user_data) +{ + m_handler->add_sensor_removed_cb(cb, user_data); +} + +void sensor_manager::remove_sensor_removed_cb(sensord_removed_cb cb) +{ + m_handler->remove_sensor_removed_cb(cb); +} + +bool sensor_manager::init(void) +{ + m_client = new(std::nothrow) ipc::ipc_client(SENSOR_CHANNEL_PATH); + retvm_if(!m_client, false, "Failed to allocate memory"); + + m_handler = new(std::nothrow) channel_handler(this); + if (!m_handler) { + delete m_client; + m_client = NULL; + return false; + } + + return true; +} + +void sensor_manager::deinit(void) +{ + disconnect(); + + delete m_handler; + m_handler = NULL; + + delete m_client; + m_client = NULL; +} + +bool sensor_manager::connect_channel(void) +{ + ipc::message msg; + + m_cmd_channel = m_client->connect(NULL); + retvm_if(!m_cmd_channel, false, "Failed to connect to server"); + + m_mon_channel = m_client->connect(m_handler, &m_loop); + retvm_if(!m_mon_channel, false, "Failed to connect to server"); + + msg.set_type(CMD_MANAGER_CONNECT); + m_mon_channel->send_sync(msg); + + m_connected.store(true); + + _D("Connected"); + return true; +} + +bool sensor_manager::connect(void) +{ + retv_if(is_connected(), true); + retv_if(!connect_channel(), false); + + return get_sensors_internal(); +} + +void sensor_manager::disconnect(void) +{ + ret_if(!is_connected()); + m_connected.store(false); + + m_mon_channel->disconnect(); + delete m_mon_channel; + m_mon_channel = NULL; + + m_cmd_channel->disconnect(); + delete m_cmd_channel; + m_cmd_channel = NULL; + + _D("Disconnected"); +} + +bool sensor_manager::is_connected(void) +{ + return m_connected.load(); +} + +void sensor_manager::restore(void) +{ + ret_if(!is_connected()); + + m_cmd_channel->disconnect(); + delete m_cmd_channel; + m_cmd_channel = NULL; + + m_connected.store(false); + retm_if(!connect_channel(), "Failed to restore manager"); + + _D("Restored manager"); +} + +void sensor_manager::decode_sensors(const char *buf, std::list &infos) +{ + int count = 0; + sensor_info info; + const int32_t *size; + const char *data; + cmd_manager_sensor_list_t *raw; + + raw = (cmd_manager_sensor_list_t *)buf; + count = raw->sensor_cnt; + size = (const int32_t *)raw->data; + data = (const char *)raw->data + sizeof(int32_t); + + for (int i = 0; i < count; ++i) { + info.clear(); + info.deserialize(data, size[0]); + infos.push_back(info); + + size = (const int32_t *)((const char *)data + size[0]); + data = (const char *)size + sizeof(int32_t); + } + + _D("Sensor count : %d", count); +} + +bool sensor_manager::get_sensors_internal(void) +{ + retvm_if(!is_connected(), false, "Failed to get sensors"); + + bool ret; + ipc::message msg; + ipc::message reply; + char buf[MAX_BUF_SIZE]; + + msg.set_type(CMD_MANAGER_SENSOR_LIST); + + ret = m_cmd_channel->send_sync(msg); + retvm_if(!ret, false, "Failed to send message"); + + ret = m_cmd_channel->read_sync(reply); + retvm_if(!ret, false, "Failed to receive message"); + + reply.disclose(buf, MAX_BUF_SIZE); + + if (!m_sensors.empty()) + m_sensors.clear(); + + decode_sensors(buf, m_sensors); + + return true; +} + +bool sensor_manager::has_privilege(std::string &uri) +{ + retvm_if(!is_connected(), false, "Failed to get sensors"); + + bool ret; + ipc::message msg; + ipc::message reply; + cmd_has_privilege_t buf = {0, }; + + msg.set_type(CMD_HAS_PRIVILEGE); + memcpy(buf.sensor, uri.c_str(), uri.size()); + msg.enclose((const char *)&buf, sizeof(buf)); + + ret = m_cmd_channel->send_sync(msg); + retvm_if(!ret, false, "Failed to send message"); + + ret = m_cmd_channel->read_sync(reply); + retvm_if(!ret, false, "Failed to receive message"); + + if (reply.header()->err == OP_SUCCESS) + return true; + + _W("This client doesn't have the privilege for sensor[%s]", uri.c_str()); + + return false; +} + +sensor_info *sensor_manager::get_info(const char *uri) +{ + if (strncmp(uri, utils::get_uri(ALL_SENSOR), strlen(utils::get_uri(ALL_SENSOR))) == 0) + return &m_sensors.front(); + + for (auto it = m_sensors.begin(); it != m_sensors.end(); ++it) { + if ((*it).get_uri() != uri) + continue; + + if ((*it).get_privilege().empty() || has_privilege((*it).get_uri())) + return &*it; + + return NULL; + } + + for (auto it = m_sensors.begin(); it != m_sensors.end(); ++it) { + std::size_t found = (*it).get_uri().find_last_of("/"); + if (found == std::string::npos) + continue; + if ((*it).get_uri().substr(0, found) != uri) + continue; + + if ((*it).get_privilege().empty() || has_privilege((*it).get_uri())) + return &*it; + } + + return NULL; +} + +std::vector sensor_manager::get_infos(const char *uri) +{ + std::vector infos; + bool all = false; + + if (strncmp(uri, utils::get_uri(ALL_SENSOR), strlen(utils::get_uri(ALL_SENSOR))) == 0) + all = true; + + for (auto it = m_sensors.begin(); it != m_sensors.end(); ++it) { + if ((*it).get_uri() != uri) + continue; + + if ((*it).get_privilege().empty() || has_privilege((*it).get_uri())) + infos.push_back(&*it); + + return infos; + } + + for (auto it = m_sensors.begin(); it != m_sensors.end(); ++it) { + std::size_t found = (*it).get_uri().find_last_of("/"); + if (!all && found == std::string::npos) + continue; + if (!all && (*it).get_uri().substr(0, found) != uri) + continue; + + if ((*it).get_privilege().empty() || has_privilege((*it).get_uri())) + infos.push_back(&*it); + } + + return infos; +} + diff --git a/src/api/sensor_manager.h b/src/api/sensor_manager.h new file mode 100644 index 0000000..a825f3e --- /dev/null +++ b/src/api/sensor_manager.h @@ -0,0 +1,90 @@ +/* + * sensord + * + * 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. + * 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 __SENSOR_MANAGER_H__ +#define __SENSOR_MANAGER_H__ + +#include +#include +#include +#include +#include +#include + +#include "sensor_internal.h" +#include "sensor_provider_internal.h" + +namespace sensor { + +class sensor_manager { +public: + sensor_manager(); + virtual ~sensor_manager(); + + bool connect(void); + void disconnect(void); + void restore(void); + + int get_sensor(const char *uri, sensor_t *sensor); + int get_sensors(const char *uri, sensor_t **list, int *count); + + bool is_supported(sensor_t sensor); + bool is_supported(const char *uri); + + /* sensor provider */ + int add_sensor(sensor_info &info); + int add_sensor(sensor_provider *provider); + int remove_sensor(const char *uri); + int remove_sensor(sensor_provider *provider); + + void add_sensor_added_cb(sensord_added_cb cb, void *user_data); + void remove_sensor_added_cb(sensord_added_cb cb); + + void add_sensor_removed_cb(sensord_removed_cb cb, void *user_data); + void remove_sensor_removed_cb(sensord_removed_cb cb); + +private: + class channel_handler; + + bool init(void); + void deinit(void); + + bool connect_channel(void); + bool is_connected(void); + + void decode_sensors(const char *buf, std::list &infos); + bool get_sensors_internal(void); + + bool has_privilege(std::string &uri); + sensor_info *get_info(const char *uri); + std::vector get_infos(const char *uri); + + ipc::ipc_client *m_client; + ipc::channel *m_cmd_channel; /* get sensor information */ + ipc::channel *m_mon_channel; /* monitor sensors dinamically added/removed */ + ipc::event_loop m_loop; + std::atomic m_connected; + channel_handler *m_handler; + + std::list m_sensors; +}; + +} + +#endif /* __SENSOR_MANAGER_H__ */ diff --git a/src/api/sensor_manager_channel_handler.cpp b/src/api/sensor_manager_channel_handler.cpp new file mode 100644 index 0000000..3feed82 --- /dev/null +++ b/src/api/sensor_manager_channel_handler.cpp @@ -0,0 +1,113 @@ +/* + * sensord + * + * 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. + * 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_manager_channel_handler.h" + +#include +#include +#include "sensor_manager.h" + +using namespace sensor; + +sensor_manager::channel_handler::channel_handler(sensor_manager *manager) +: m_manager(manager) +{ +} + +void sensor_manager::channel_handler::connected(ipc::channel *ch) +{ +} + +void sensor_manager::channel_handler::disconnected(ipc::channel *ch) +{ + /* If channel->disconnect() is not explicitly called, it will be restored */ + m_manager->restore(); +} + +void sensor_manager::channel_handler::read(ipc::channel *ch, ipc::message &msg) +{ + switch (msg.header()->type) { + case CMD_MANAGER_SENSOR_ADDED: + on_sensor_added(ch, msg); + break; + case CMD_MANAGER_SENSOR_REMOVED: + on_sensor_removed(ch, msg); + break; + } +} + +void sensor_manager::channel_handler::read_complete(ipc::channel *ch) +{ +} + +void sensor_manager::channel_handler::error_caught(ipc::channel *ch, int error) +{ +} + +void sensor_manager::channel_handler::on_sensor_added(ipc::channel *ch, ipc::message &msg) +{ + ret_if(msg.header()->err < OP_SUCCESS); + + sensor_info info; + info.clear(); + info.deserialize(msg.body(), msg.size()); + + m_manager->add_sensor(info); + + auto it = m_sensor_added_callbacks.begin(); + while (it != m_sensor_added_callbacks.end()) { + it->first(info.get_uri().c_str(), it->second); + ++it; + } +} + +void sensor_manager::channel_handler::on_sensor_removed(ipc::channel *ch, ipc::message &msg) +{ + ret_if(msg.header()->err < 0); + char uri[NAME_MAX] = {0, }; + + msg.disclose(uri, NAME_MAX); + m_manager->remove_sensor(uri); + + auto it = m_sensor_removed_callbacks.begin(); + while (it != m_sensor_removed_callbacks.end()) { + it->first(uri, it->second); + ++it; + } +} + +void sensor_manager::channel_handler::add_sensor_added_cb(sensord_added_cb cb, void *user_data) +{ + m_sensor_added_callbacks.emplace(cb, user_data); +} + +void sensor_manager::channel_handler::remove_sensor_added_cb(sensord_added_cb cb) +{ + m_sensor_added_callbacks.erase(cb); +} + +void sensor_manager::channel_handler::add_sensor_removed_cb(sensord_removed_cb cb, void *user_data) +{ + m_sensor_removed_callbacks.emplace(cb, user_data); +} + +void sensor_manager::channel_handler::remove_sensor_removed_cb(sensord_removed_cb cb) +{ + m_sensor_removed_callbacks.erase(cb); +} diff --git a/src/api/sensor_manager_channel_handler.h b/src/api/sensor_manager_channel_handler.h new file mode 100644 index 0000000..99f76ed --- /dev/null +++ b/src/api/sensor_manager_channel_handler.h @@ -0,0 +1,64 @@ +/* + * sensord + * + * 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. + * 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 __SENSOR_MANAGER_CHANNEL_HANDLER__ +#define __SENSOR_MANAGER_CHANNEL_HANDLER__ + +#include +#include +#include +#include + +namespace sensor { + +class sensor_manager::channel_handler : public ipc::channel_handler +{ +public: + channel_handler(sensor_manager *manager); + + void connected(ipc::channel *ch); + void disconnected(ipc::channel *ch); + void read(ipc::channel *ch, ipc::message &msg); + void read_complete(ipc::channel *ch); + void error_caught(ipc::channel *ch, int error); + + void on_sensor_added(ipc::channel *ch, ipc::message &msg); + void on_sensor_removed(ipc::channel *ch, ipc::message &msg); + + void add_sensor_added_cb(sensord_added_cb cb, void *user_data); + void remove_sensor_added_cb(sensord_added_cb cb); + + void add_sensor_removed_cb(sensord_removed_cb cb, void *user_data); + void remove_sensor_removed_cb(sensord_removed_cb cb); + + void set_handler(int num, ipc::channel_handler* handler) {} + void disconnect(void) {} + +private: + typedef std::map sensor_added_cb_list_t; + typedef std::map sensor_removed_cb_list_t; + + sensor_manager *m_manager; + sensor_added_cb_list_t m_sensor_added_callbacks; + sensor_removed_cb_list_t m_sensor_removed_callbacks; +}; + +} + +#endif /* __SENSOR_MANAGER_CHANNEL_HANDLER__ */ diff --git a/src/sensor_provider.cpp b/src/api/sensor_provider.cpp similarity index 100% rename from src/sensor_provider.cpp rename to src/api/sensor_provider.cpp diff --git a/src/api/sensor_provider_channel_handler.cpp b/src/api/sensor_provider_channel_handler.cpp new file mode 100644 index 0000000..b39573b --- /dev/null +++ b/src/api/sensor_provider_channel_handler.cpp @@ -0,0 +1,116 @@ +/* + * sensord + * + * 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. + * 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_provider_channel_handler.h" + +#include +#include +#include "sensor_provider_internal.h" + +using namespace sensor; + +sensor_provider::channel_handler::channel_handler(sensor_provider *provider) +: m_provider(provider) +, m_start_cb(NULL) +, m_stop_cb(NULL) +, m_interval_changed_cb(NULL) +, m_attribute_str_cb(NULL) +, m_start_user_data(NULL) +, m_stop_user_data(NULL) +, m_interval_changed_user_data(NULL) +, m_attribute_str_user_data(NULL) +{ +} + +void sensor_provider::channel_handler::connected(ipc::channel *ch) +{ + _I("Connected"); +} + +void sensor_provider::channel_handler::disconnected(ipc::channel *ch) +{ + /* TODO */ + /* m_provider->restore(); */ +} + +void sensor_provider::channel_handler::read(ipc::channel *ch, ipc::message &msg) +{ + switch (msg.type()) { + case CMD_PROVIDER_START: + if (m_start_cb) + m_start_cb(m_provider, m_start_user_data); + break; + case CMD_PROVIDER_STOP: + if (m_stop_cb) + m_stop_cb(m_provider, m_stop_user_data); + break; + case CMD_PROVIDER_ATTR_INT: + cmd_provider_attr_int_t buf; + msg.disclose((char *)&buf, sizeof(buf)); + + if (buf.attribute == SENSORD_ATTRIBUTE_INTERVAL && m_interval_changed_cb) + m_interval_changed_cb(m_provider, buf.value, m_interval_changed_user_data); + break; + case CMD_PROVIDER_ATTR_STR: + cmd_provider_attr_str_t *attr; + + attr = (cmd_provider_attr_str_t *) new(std::nothrow) char[msg.size()]; + retm_if(!attr, "Failed to allocate memory"); + + msg.disclose((char *)attr, msg.size()); + + if (m_attribute_str_cb) + m_attribute_str_cb(m_provider, attr->attribute, attr->value, attr->len, m_attribute_str_user_data); + + delete [] attr; + break; + } +} + +void sensor_provider::channel_handler::read_complete(ipc::channel *ch) +{ +} + +void sensor_provider::channel_handler::error_caught(ipc::channel *ch, int error) +{ +} + +void sensor_provider::channel_handler::set_start_cb(sensord_provider_start_cb cb, void *user_data) +{ + m_start_cb = cb; + m_start_user_data = user_data; +} + +void sensor_provider::channel_handler::set_stop_cb(sensord_provider_stop_cb cb, void *user_data) +{ + m_stop_cb = cb; + m_stop_user_data = user_data; +} + +void sensor_provider::channel_handler::set_interval_cb(sensord_provider_interval_changed_cb cb, void *user_data) +{ + m_interval_changed_cb = cb; + m_interval_changed_user_data = user_data; +} + +void sensor_provider::channel_handler::set_attribute_str_cb(sensord_provider_attribute_str_cb cb, void *user_data) +{ + m_attribute_str_cb = cb; + m_attribute_str_user_data = user_data; +} diff --git a/src/api/sensor_provider_channel_handler.h b/src/api/sensor_provider_channel_handler.h new file mode 100644 index 0000000..aa33006 --- /dev/null +++ b/src/api/sensor_provider_channel_handler.h @@ -0,0 +1,63 @@ +/* + * sensord + * + * 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. + * 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 __SENSOR_PROVIDER_CHANNEL_HANDLER__ +#define __SENSOR_PROVIDER_CHANNEL_HANDLER__ + +#include +#include +#include "sensor_provider_internal.h" + +namespace sensor { + +class sensor_provider::channel_handler : public ipc::channel_handler +{ +public: + channel_handler(sensor_provider *provider); + + void connected(ipc::channel *ch); + void disconnected(ipc::channel *ch); + void read(ipc::channel *ch, ipc::message &msg); + + void read_complete(ipc::channel *ch); + void error_caught(ipc::channel *ch, int error); + + void set_start_cb(sensord_provider_start_cb cb, void *user_data); + void set_stop_cb(sensord_provider_stop_cb cb, void *user_data); + void set_interval_cb(sensord_provider_interval_changed_cb cb, void *user_data); + void set_attribute_str_cb(sensord_provider_attribute_str_cb cb, void *user_data); + void set_handler(int num, ipc::channel_handler* handler) {} + void disconnect(void) {} +private: + sensor_provider *m_provider; + + sensord_provider_start_cb m_start_cb; + sensord_provider_stop_cb m_stop_cb; + sensord_provider_interval_changed_cb m_interval_changed_cb; + sensord_provider_attribute_str_cb m_attribute_str_cb; + + void *m_start_user_data; + void *m_stop_user_data; + void *m_interval_changed_user_data; + void *m_attribute_str_user_data; +}; + +} + +#endif /* __SENSOR_PROVIDER_CHANNEL_HANDLER__ */ diff --git a/src/api/sensor_provider_internal.cpp b/src/api/sensor_provider_internal.cpp new file mode 100644 index 0000000..30762c4 --- /dev/null +++ b/src/api/sensor_provider_internal.cpp @@ -0,0 +1,224 @@ +/* + * sensord + * + * 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. + * 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_provider_internal.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sensor_provider_channel_handler.h" + +#define DEFAULT_RESOLUTION 0.1 + +using namespace sensor; + +sensor_provider::sensor_provider(const char *uri) +: m_client(NULL) +, m_channel(NULL) +, m_handler(NULL) +, m_connected(false) +{ + init(uri); +} + +sensor_provider::~sensor_provider() +{ + deinit(); +} + +bool sensor_provider::init(const char *uri) +{ + m_client = new(std::nothrow) ipc::ipc_client(SENSOR_CHANNEL_PATH); + retvm_if(!m_client, false, "Failed to allocate memory"); + + m_handler = new(std::nothrow) channel_handler(this); + if (!m_handler) { + delete m_client; + return false; + } + + m_sensor.set_uri(uri); + m_sensor.set_min_range(-FLT_MAX); + m_sensor.set_max_range(FLT_MAX); + m_sensor.set_resolution(DEFAULT_RESOLUTION); + /* TODO: temporary walkaround */ + const char *priv = sensor::utils::get_privilege(uri); + m_sensor.set_privilege(priv); + + return true; +} + +void sensor_provider::deinit(void) +{ + disconnect(); + + delete m_handler; + m_handler = NULL; + + delete m_client; + m_client = NULL; +} + +const char *sensor_provider::get_uri(void) +{ + return m_sensor.get_uri().c_str(); +} + +sensor_info *sensor_provider::get_sensor_info(void) +{ + return &m_sensor; +} + +int sensor_provider::serialize(sensor_info *info, char **bytes) +{ + int size; + raw_data_t *raw = new(std::nothrow) raw_data_t; + retvm_if(!raw, -ENOMEM, "Failed to allocated memory"); + + info->serialize(*raw); + + *bytes = (char *) malloc(raw->size()); + + if (!(*bytes)) { + delete(raw); + _E("Failed to allocate memory"); + return -ENOMEM; + } + + std::copy(raw->begin(), raw->end(), *bytes); + + size = raw->size(); + delete raw; + + return size; +} + +int sensor_provider::send_sensor_info(sensor_info *info) +{ + char *bytes; + int size; + + size = serialize(info, &bytes); + if (size < 0) + return OP_ERROR; + + ipc::message msg((const char *)bytes, size); + msg.set_type(CMD_PROVIDER_CONNECT); + + m_channel->send_sync(msg); + + return OP_SUCCESS; +} + +int sensor_provider::connect(void) +{ + m_channel = m_client->connect(m_handler, &m_loop); + retvm_if(!m_channel, -EIO, "Failed to connect to server"); + + /* serialize and send sensor info */ + send_sensor_info(get_sensor_info()); + + /* check error */ + ipc::message reply; + m_channel->read_sync(reply); + retv_if(reply.header()->err < 0, reply.header()->err); + + m_connected.store(true); + + _I("Provider URI[%s]", get_uri()); + + return OP_SUCCESS; +} + +bool sensor_provider::disconnect(void) +{ + retv_if(!is_connected(), false); + m_connected.store(false); + + m_channel->disconnect(); + delete m_channel; + m_channel = NULL; + + _I("Disconnected[%s]", get_uri()); + + return true; +} + +void sensor_provider::restore(void) +{ + ret_if(!is_connected()); + retm_if(!connect(), "Failed to restore provider"); + + _D("Restored provider[%s]", get_uri()); +} + +int sensor_provider::publish(const sensor_data_t &data) +{ + ipc::message msg; + msg.set_type(CMD_PROVIDER_PUBLISH); + msg.enclose((const void *)(&data), sizeof(data)); + + m_channel->send_sync(msg); + + return OP_SUCCESS; +} + +int sensor_provider::publish(const sensor_data_t data[], const int count) +{ + ipc::message msg; + msg.set_type(CMD_PROVIDER_PUBLISH); + msg.enclose((const void *)data, sizeof(sensor_data_t) * count); + + m_channel->send_sync(msg); + + return OP_SUCCESS; +} + +bool sensor_provider::is_connected(void) +{ + return m_connected.load(); +} + +void sensor_provider::set_start_cb(sensord_provider_start_cb cb, void *user_data) +{ + m_handler->set_start_cb(cb, user_data); +} + +void sensor_provider::set_stop_cb(sensord_provider_stop_cb cb, void *user_data) +{ + m_handler->set_stop_cb(cb, user_data); +} + +void sensor_provider::set_interval_cb(sensord_provider_interval_changed_cb cb, void *user_data) +{ + m_handler->set_interval_cb(cb, user_data); +} + +void sensor_provider::set_attribute_str_cb(sensord_provider_attribute_str_cb cb, void *user_data) +{ + m_handler->set_attribute_str_cb(cb, user_data); +} + diff --git a/src/api/sensor_provider_internal.h b/src/api/sensor_provider_internal.h new file mode 100644 index 0000000..e694b0e --- /dev/null +++ b/src/api/sensor_provider_internal.h @@ -0,0 +1,77 @@ +/* + * sensord + * + * 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. + * 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 __SENSOR_PROVIDER_INTERNAL_H__ +#define __SENSOR_PROVIDER_INTERNAL_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sensor { + +class sensor_provider { +public: + sensor_provider(const char *uri); + virtual ~sensor_provider(); + + const char *get_uri(void); + sensor_info *get_sensor_info(void); + + int connect(void); + bool disconnect(void); + void restore(void); + + void set_start_cb(sensord_provider_start_cb cb, void *user_data); + void set_stop_cb(sensord_provider_stop_cb cb, void *user_data); + void set_interval_cb(sensord_provider_interval_changed_cb cb, void *user_data); + void set_attribute_str_cb(sensord_provider_attribute_str_cb cb, void *user_data); + + int publish(const sensor_data_t &data); + int publish(const sensor_data_t data[], const int count); + +private: + class channel_handler; + + bool init(const char *uri); + void deinit(void); + + bool is_connected(void); + + int serialize(sensor_info *info, char **bytes); + int send_sensor_info(sensor_info *info); + + sensor_info m_sensor; + + ipc::ipc_client *m_client; + ipc::channel *m_channel; + ipc::event_loop m_loop; + channel_handler *m_handler; + std::atomic m_connected; +}; + +} + +#endif /* __SENSOR_PROVIDER_INTERNAL_H__ */ diff --git a/src/api/sensor_reader.cpp b/src/api/sensor_reader.cpp new file mode 100644 index 0000000..bc3a7a1 --- /dev/null +++ b/src/api/sensor_reader.cpp @@ -0,0 +1,88 @@ +/* + * sensord + * + * Copyright (c) 2018 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_reader.h" + +#include +#include +#include + +using namespace sensor; + +sensor_reader::sensor_reader() +: m_reader(NULL) +, m_loop(NULL) +, m_event_loop(NULL) +, m_mutex() +, m_cond() +, m_running(false) +{ + m_event_loop = new(std::nothrow) ipc::event_loop(); + m_reader = new(std::nothrow) std::thread(&sensor::sensor_reader::read_event, this); + m_reader->detach(); + + if (!m_running) + wait_for_preparation(); + + _I("Created"); +} + +sensor_reader::~sensor_reader() +{ + _I("Destroying.."); + retm_if(!m_reader, "Invalid reader"); + + m_running = false; + + m_event_loop->stop(); + + delete m_reader; + m_reader = NULL; + + delete m_event_loop; + m_event_loop = NULL; + + _I("Destroyed"); +} + +ipc::event_loop *sensor_reader::get_event_loop(void) +{ + retvm_if(!m_event_loop, NULL, "Invalid context"); + + return m_event_loop; +} + +void sensor_reader::wait_for_preparation(void) +{ + std::unique_lock lock(m_mutex); + m_cond.wait_for(lock, std::chrono::seconds(1)); +} + +void sensor_reader::read_event(void) +{ + _I("RUN"); + m_loop = g_main_loop_new(g_main_context_new(), false); + m_event_loop->set_mainloop(m_loop); + + m_cond.notify_one(); + m_running = true; + + if (!m_event_loop->run()) + _E("Failed to run event loop"); +} diff --git a/src/api/sensor_reader.h b/src/api/sensor_reader.h new file mode 100644 index 0000000..010eb42 --- /dev/null +++ b/src/api/sensor_reader.h @@ -0,0 +1,53 @@ +/* + * sensord + * + * Copyright (c) 2018 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 __SENSOR_READER_H__ +#define __SENSOR_READER_H__ + +#include +#include + +#include +#include +#include + +namespace sensor { + +class sensor_reader { +public: + sensor_reader(); + ~sensor_reader(); + + ipc::event_loop *get_event_loop(void); + +private: + void wait_for_preparation(void); + void read_event(void); + + std::thread *m_reader; + GMainLoop *m_loop; + ipc::event_loop *m_event_loop; + std::mutex m_mutex; + std::condition_variable m_cond; + std::atomic m_running; +}; + +} + +#endif /* __SENSOR_READER_H__ */ diff --git a/src/sensor_recorder.cpp b/src/api/sensor_recorder/sensor_recorder.cpp similarity index 100% rename from src/sensor_recorder.cpp rename to src/api/sensor_recorder/sensor_recorder.cpp diff --git a/src/sensor_recorder_dummy.cpp b/src/api/sensor_recorder/sensor_recorder_dummy.cpp similarity index 100% rename from src/sensor_recorder_dummy.cpp rename to src/api/sensor_recorder/sensor_recorder_dummy.cpp diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt new file mode 100644 index 0000000..b9b59ef --- /dev/null +++ b/src/shared/CMakeLists.txt @@ -0,0 +1,19 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(sensor-shared CXX) + +SET(DEPENDENTS "dlog libsystemd glib-2.0 gio-2.0 vconf libtzplatform-config") + +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(SHARED_PKGS REQUIRED ${DEPENDENTS}) + +FOREACH(flag ${SHARED_PKGS_CFLAGS}) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}") +ENDFOREACH(flag) +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +FILE(GLOB_RECURSE SRCS *.cpp) +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${SHARED_PKGS_LDFLAGS}) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/src/shared/accept_event_handler.cpp b/src/shared/accept_event_handler.cpp new file mode 100644 index 0000000..419d912 --- /dev/null +++ b/src/shared/accept_event_handler.cpp @@ -0,0 +1,51 @@ +/* + * sensord + * + * 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. + * 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 "accept_event_handler.h" + +#include "sensor_log.h" +#include "ipc_server.h" + +using namespace ipc; + +accept_event_handler::accept_event_handler(ipc_server *server) +: m_server(server) +{ +} + +bool accept_event_handler::handle(int fd, event_condition condition, void **data) +{ + retv_if((condition & (EVENT_HUP)), false); + + stream_socket *cli_sock = new(std::nothrow) stream_socket(); + retvm_if(!cli_sock, false, "Failed to allocate memory"); + + m_server->accept(*cli_sock); + + channel *_ch = new(std::nothrow) channel(cli_sock); + if (!_ch) { + delete cli_sock; + _E("Failed to allocate memory"); + return false; + } + + m_server->register_channel(cli_sock->get_fd(), _ch); + + return true; +} diff --git a/src/shared/accept_event_handler.h b/src/shared/accept_event_handler.h new file mode 100644 index 0000000..b732238 --- /dev/null +++ b/src/shared/accept_event_handler.h @@ -0,0 +1,42 @@ +/* + * sensord + * + * 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. + * 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 __ACCEPT_EVENT_HANDLER__ +#define __ACCEPT_EVENT_HANDLER__ + +#include "event_handler.h" + +namespace ipc { + +class ipc_server; + +class accept_event_handler : public event_handler +{ +public: + accept_event_handler(ipc_server *server); + + bool handle(int fd, event_condition condition, void **data); + +private: + ipc_server *m_server; +}; + +} + +#endif /* __ACCEPT_EVENT_HANDLER__ */ diff --git a/src/shared/cbase_lock.cpp b/src/shared/cbase_lock.cpp new file mode 100644 index 0000000..eafd601 --- /dev/null +++ b/src/shared/cbase_lock.cpp @@ -0,0 +1,156 @@ +/* + * sensord + * + * Copyright (c) 2013 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 + +using namespace sensor; + +cbase_lock::cbase_lock() +{ + m_history_mutex = PTHREAD_MUTEX_INITIALIZER; +} + +cbase_lock::~cbase_lock() +{ + pthread_mutex_destroy(&m_history_mutex); +} + +void cbase_lock::lock(lock_type type, const char* expr, const char *module, const char *func, int line) +{ + int ret = 0; + char m_curent_info[OWNER_INFO_LEN]; + struct timeval sv; + unsigned long long lock_waiting_start_time = 0; + unsigned long long lock_acquired_time = 0; + unsigned long long waiting_time = 0; + + snprintf(m_curent_info, OWNER_INFO_LEN, "%s:%s(%d)", module, func, line); + + if (type == LOCK_TYPE_MUTEX) + ret = try_lock_impl(); + else if (type == LOCK_TYPE_READ) + ret = try_read_lock_impl(); + else if (type == LOCK_TYPE_WRITE) + ret = try_write_lock_impl(); + + if (ret == 0) { + pthread_mutex_lock(&m_history_mutex); + snprintf(m_owner_info, OWNER_INFO_LEN, "%s", m_curent_info); + pthread_mutex_unlock(&m_history_mutex); + return; + } + + gettimeofday(&sv, NULL); + lock_waiting_start_time = MICROSECONDS(sv); + + pthread_mutex_lock(&m_history_mutex); + _I("%s is waiting for getting %s(%p) owned in %s", + m_curent_info, expr, this, m_owner_info); + pthread_mutex_unlock(&m_history_mutex); + + if (type == LOCK_TYPE_MUTEX) + lock_impl(); + else if (type == LOCK_TYPE_READ) + read_lock_impl(); + else if (type == LOCK_TYPE_WRITE) + write_lock_impl(); + + gettimeofday(&sv, NULL); + lock_acquired_time = MICROSECONDS(sv); + + waiting_time = lock_acquired_time - lock_waiting_start_time; + + pthread_mutex_lock(&m_history_mutex); + _I("%s acquires lock after waiting %lluus, %s(%p) was previously owned in %s", + m_curent_info, waiting_time, expr, this, m_owner_info); + snprintf(m_owner_info, OWNER_INFO_LEN, "%s", m_curent_info); + pthread_mutex_unlock(&m_history_mutex); +} + +void cbase_lock::lock(lock_type type) +{ + if (type == LOCK_TYPE_MUTEX) + lock_impl(); + else if (type == LOCK_TYPE_READ) + read_lock_impl(); + else if (type == LOCK_TYPE_WRITE) + write_lock_impl(); +} + +void cbase_lock::unlock(void) +{ + unlock_impl(); +} + +int cbase_lock::lock_impl(void) +{ + return 0; +} + +int cbase_lock::read_lock_impl(void) +{ + return 0; +} + +int cbase_lock::write_lock_impl(void) +{ + return 0; +} + +int cbase_lock::try_lock_impl(void) +{ + return 0; +} + +int cbase_lock::try_read_lock_impl(void) +{ + return 0; +} + +int cbase_lock::try_write_lock_impl(void) +{ + return 0; +} + +int cbase_lock::unlock_impl(void) +{ + return 0; +} + +Autolock::Autolock(cbase_lock &m, lock_type type, const char* expr, const char *module, const char *func, int line) +: m_lock(m) +{ + m_lock.lock(type, expr, module, func, line); +} + +Autolock::Autolock(cbase_lock &m, lock_type type) +: m_lock(m) +{ + m_lock.lock(type); +} + +Autolock::~Autolock() +{ + m_lock.unlock(); +} diff --git a/src/shared/cbase_lock.h b/src/shared/cbase_lock.h new file mode 100644 index 0000000..5c76040 --- /dev/null +++ b/src/shared/cbase_lock.h @@ -0,0 +1,90 @@ +/* + * sensord + * + * Copyright (c) 2013 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 _CBASE_LOCK_H_ +#define _CBASE_LOCK_H_ + +#include + +namespace sensor { + +enum lock_type { + LOCK_TYPE_MUTEX, + LOCK_TYPE_READ, + LOCK_TYPE_WRITE, +}; + +#ifndef MICROSECONDS +#define MICROSECONDS(tv) ((tv.tv_sec * 1000000ll) + tv.tv_usec) +#endif + +#ifdef _LOCK_DEBUG +#define AUTOLOCK(x) Autolock x##_autolock((x), LOCK_TYPE_MUTEX, #x, __MODULE__, __func__, __LINE__) +#define AUTOLOCK_R(x) Autolock x##_autolock_r((x), LOCK_TYPE_READ, #x, __MODULE__, __func__, __LINE__) +#define AUTOLOCK_W(x) Autolock x##_autolock_w((x), LOCK_TYPE_WRITE, #x, __MODULE__, __func__, __LINE__) +#define LOCK(x) (x).lock(#x, __MODULE__, __func__, __LINE__) +#define LOCK_R(x) (x).lock(LOCK_TYPE_READ, #x, __MODULE__, __func__, __LINE__) +#define LOCK_W(x) (x).lock(LOCK_TYPE_WRITE, #x, __MODULE__, __func__, __LINE__) +#define UNLOCK(x) (x).unlock() +#else +#define AUTOLOCK(x) Autolock x##_autolock((x), LOCK_TYPE_MUTEX) +#define AUTOLOCK_R(x) Autolock x##_autolock_r((x), LOCK_TYPE_READ) +#define AUTOLOCK_W(x) Autolock x##_autolock_w((x), LOCK_TYPE_WRITE) +#define LOCK(x) (x).lock() +#define LOCK_R(x) (x).lock(LOCK_TYPE_READ) +#define LOCK_W(x) (x).lock(LOCK_TYPE_WRITE) +#define UNLOCK(x) (x).unlock() +#endif + +class cbase_lock { +public: + cbase_lock(); + virtual ~cbase_lock(); + + void lock(lock_type type, const char* expr, const char *module, const char *func, int line); + void lock(lock_type type); + void unlock(void); + +protected: + virtual int lock_impl(void); + virtual int read_lock_impl(void); + virtual int write_lock_impl(void); + + virtual int try_lock_impl(void); + virtual int try_read_lock_impl(void); + virtual int try_write_lock_impl(void); + + virtual int unlock_impl(void); +private: + pthread_mutex_t m_history_mutex; + static const int OWNER_INFO_LEN = 256; + char m_owner_info[OWNER_INFO_LEN]; +}; + +class Autolock { +private: + cbase_lock& m_lock; +public: + Autolock(cbase_lock &m, lock_type type, const char* expr, const char *module, const char *func, int line); + Autolock(cbase_lock &m, lock_type type); + ~Autolock(); +}; +} + +#endif /* _CBASE_LOCK_H_ */ diff --git a/src/shared/channel.cpp b/src/shared/channel.cpp new file mode 100644 index 0000000..26b654c --- /dev/null +++ b/src/shared/channel.cpp @@ -0,0 +1,388 @@ +/* + * sensord + * + * 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. + * 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 "channel.h" + +#include +#include +#include +#include + +#include "sensor_log.h" +#include "channel_event_handler.h" + +#define SYSTEMD_SOCK_BUF_SIZE (128*1024) + +using namespace ipc; +using namespace sensor; + +class send_event_handler : public event_handler +{ +public: + send_event_handler(channel *ch, std::shared_ptr msg) + : m_ch(ch) + , m_msg(msg) + { } + + virtual ~send_event_handler() + { + if (m_ch) { + m_ch->remove_pending_event_id(m_event_id); + } + } + + bool handle(int fd, event_condition condition, void** data) + { + if (!m_ch) { + return false; + } + + m_ch->remove_pending_event_id(m_event_id); + + if (!m_ch->is_connected()) { + return false; + } + + if (condition & (EVENT_IN | EVENT_HUP)) { + return false; + } + + if (!m_ch->send_sync(*m_msg)) { + return false; + } + + return false; + } + +private: + channel *m_ch; + std::shared_ptr m_msg; +}; + +class read_event_handler : public event_handler +{ +public: + read_event_handler(channel *ch) + : m_ch(ch) + { } + + bool handle(int fd, event_condition condition, void **data) + { + if (!m_ch) { + return false; + } + + m_ch->remove_pending_event_id(m_event_id); + + if (!m_ch->is_connected()) { + return false; + } + + if (condition & (EVENT_OUT | EVENT_HUP)) { + return false; + } + + message msg; + if (!m_ch->read_sync(msg, false)) { + return false; + } + + return false; + } + +private: + channel *m_ch; +}; + +channel::channel(socket *sock) +: m_fd(sock->get_fd()) +, m_event_id(0) +, m_socket(sock) +, m_handler(NULL) +, m_loop(NULL) +, m_connected(false) +{ + _D("Create[%p]", this); +} + +channel::~channel() +{ + _D("Destroy[%p]", this); + if (is_connected()) { + disconnect(); + } +} + +uint64_t channel::bind(void) +{ + retv_if(!m_loop, 0); + channel_event_handler* handler = dynamic_cast(m_handler); + + if (!handler) { + _E("Failed to bind channel[%p] : handler[%p]", this, m_handler); + m_event_id = 0; + return 0; + } + m_event_id = m_loop->add_event(m_socket->get_fd(), + (EVENT_IN | EVENT_HUP | EVENT_NVAL), handler); + + _D("Bind channel[%p] : handler[%p] event_id[%llu]", this, m_handler, m_event_id); + return m_event_id; +} + +uint64_t channel::bind(channel_handler *handler, event_loop *loop, bool loop_bind) +{ + m_handler = handler; + m_loop = loop; + m_connected.store(true); + + if (m_handler) + m_handler->connected(this); + + if (loop_bind) + bind(); + + return m_event_id; +} + +uint64_t channel::connect(channel_handler *handler, event_loop *loop, bool loop_bind) +{ + if (!m_socket->connect()) + return false; + + if (handler) + bind(handler, loop, loop_bind); + + _D("Connect channel[%p] : event id[%llu]", this, m_event_id); + return m_event_id; +} + +void channel::disconnect(void) +{ + AUTOLOCK(m_cmutex); + if (!is_connected()) { + _D("Channel[%p] is not connected", this); + return; + } + + m_connected.store(false); + + _D("Disconnect channel[%p]", this); + + if (m_handler) { + _D("Disconnect channel[%p] handler[%p]", this, m_handler); + m_handler->disconnected(this); + if (!m_loop) + delete m_handler; + m_handler = NULL; + } + + if (m_loop) { + for(auto id : m_pending_event_id) { + _D("Remove channel[%p] pending event id[%llu]", this, id); + m_loop->remove_event(id); + } + _D("Remove channel[%p] event[%llu]",this, m_event_id); + m_loop->remove_event(m_event_id); + m_event_id = 0; + } + + if (m_socket) { + _D("Release channel[%p] socket[%d]", this, m_socket->get_fd()); + delete m_socket; + m_socket = NULL; + } + _D("Channel[%p] is disconnected", this); +} + +bool channel::send(std::shared_ptr msg) +{ + int retry_cnt = 0; + int cur_buffer_size = 0; + + retv_if(!m_loop, false); + + while (retry_cnt < 3) { + cur_buffer_size = m_socket->get_current_buffer_size(); + if (cur_buffer_size <= SYSTEMD_SOCK_BUF_SIZE) + break; + usleep(3000); + retry_cnt++; + } + retvm_if(retry_cnt >= 3, false, "Socket buffer[%d] is exceeded", cur_buffer_size); + + send_event_handler *handler = new(std::nothrow) send_event_handler(this, msg); + retvm_if(!handler, false, "Failed to allocate memory"); + + uint64_t event_id = m_loop->add_event(m_socket->get_fd(), (EVENT_OUT | EVENT_HUP | EVENT_NVAL), handler); + if (event_id == 0) { + _D("Failed to add send event handler"); + delete handler; + return false; + } + + m_pending_event_id.push_back(event_id); + return true; +} + +bool channel::send_sync(message &msg) +{ + AUTOLOCK(m_cmutex); + if (!is_connected()) { + _D("Channel is not connected"); + return false; + } + + retvm_if(msg.size() >= MAX_MSG_CAPACITY, true, "Invaild message size[%u]", msg.size()); + + ssize_t size = 0; + char *buf = msg.body(); + + /* header */ + size = m_socket->send(reinterpret_cast(msg.header()), + sizeof(message_header), true); + retvm_if(size <= 0, false, "Failed to send header"); + + /* if body size is zero, skip to send body message */ + retv_if(msg.size() == 0, true); + + /* body */ + size = m_socket->send(buf, msg.size(), true); + retvm_if(size <= 0, false, "Failed to send body"); + + return true; +} + +bool channel::read(void) +{ + retv_if(!m_loop, false); + + read_event_handler *handler = new(std::nothrow) read_event_handler(this); + retvm_if(!handler, false, "Failed to allocate memory"); + + uint64_t event_id = m_loop->add_event(m_socket->get_fd(), (EVENT_IN | EVENT_HUP | EVENT_NVAL), handler); + if (event_id == 0) { + _D("Failed to add read event handler"); + delete handler; + return false; + } + + m_pending_event_id.push_back(event_id); + return true; +} + +bool channel::read_sync(message &msg, bool select) +{ + AUTOLOCK(m_cmutex); + if (!is_connected()) { + _D("Channel is not connected"); + return false; + } + + message_header header; + ssize_t size = 0; + char buf[MAX_MSG_CAPACITY]; + + /* header */ + size = m_socket->recv(&header, sizeof(message_header), select); + if (size <= 0) + return false; + + /* check error from header */ + if (m_handler && header.err != 0) { + m_handler->error_caught(this, header.err); + msg.header()->err = header.err; + return true; + } + + /* body */ + if (header.length >= MAX_MSG_CAPACITY) { + _E("header.length error %u", header.length); + return false; + } + + if (header.length > 0) { + size = m_socket->recv(&buf, header.length, select); + if (size <= 0) + return false; + } + + buf[header.length] = '\0'; + msg.enclose(reinterpret_cast(buf), header.length); + msg.set_type(header.type); + msg.header()->err = header.err; + + if (m_handler) + m_handler->read(this, msg); + + return true; +} + +bool channel::is_connected(void) +{ + return m_connected.load(); +} + +bool channel::set_option(int type, int value) +{ + switch (type) { + case SO_SNDBUF: + m_socket->set_buffer_size(type, value); + break; + case SO_RCVBUF: + m_socket->set_buffer_size(type, value); + break; + default: + break; + } + + return true; +} + +bool channel::get_option(int type, int &value) const +{ + switch (type) { + case 0: + value = m_socket->get_current_buffer_size(); + break; + case SO_SNDBUF: + value = m_socket->get_buffer_size(type); + break; + case SO_RCVBUF: + value = m_socket->get_buffer_size(type); + break; + default: + break; + } + + return true; +} + +int channel::get_fd(void) const +{ + return m_fd; +} + +void channel::remove_pending_event_id(uint64_t id) +{ + auto it = std::find(m_pending_event_id.begin(), m_pending_event_id.end(), id); + if (it != m_pending_event_id.end()) { + m_pending_event_id.erase(it); + } +} diff --git a/src/shared/channel.h b/src/shared/channel.h new file mode 100644 index 0000000..5af06da --- /dev/null +++ b/src/shared/channel.h @@ -0,0 +1,82 @@ +/* + * sensord + * + * 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. + * 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 __CHANNEL_H__ +#define __CHANNEL_H__ + +#include +#include +#include + +#include "socket.h" +#include "message.h" +#include "event_loop.h" +#include "channel_handler.h" +#include "cmutex.h" + +namespace ipc { + +class channel_handler; + +class channel { +public: + /* move owernership of the socket to the channel */ + channel(socket *sock); + ~channel(); + + uint64_t bind(void); + uint64_t bind(channel_handler *handler, event_loop *loop, bool loop_bind); + + uint64_t connect(channel_handler *handler, event_loop *loop, bool loop_bind); + void disconnect(void); + + bool is_connected(void); + + bool send(std::shared_ptr msg); + bool send_sync(message &msg); + + bool read(void); + bool read_sync(message &msg, bool select = true); + + bool get_option(int type, int &value) const; + bool set_option(int type, int value); + + int get_fd(void) const; + void remove_pending_event_id(uint64_t id); + + event_loop *loop() + { + return m_loop; + } + +private: + int m_fd; + uint64_t m_event_id; + socket *m_socket; + channel_handler *m_handler; + event_loop *m_loop; + std::vector m_pending_event_id; + + std::atomic m_connected; + sensor::cmutex m_cmutex; +}; + +} + +#endif /* __CHANNEL_H__ */ diff --git a/src/shared/channel_event_handler.cpp b/src/shared/channel_event_handler.cpp new file mode 100644 index 0000000..460b6a0 --- /dev/null +++ b/src/shared/channel_event_handler.cpp @@ -0,0 +1,93 @@ +/* + * sensord + * + * 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. + * 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 "channel_event_handler.h" + +#include "channel.h" +#include "channel_handler.h" +#include "sensor_log.h" + +using namespace ipc; + +channel_event_handler::channel_event_handler(channel *ch, channel_handler *handler) +: m_ch(ch) +, m_handler(handler) +{ + _D("Create[%p]", this); +} + +channel_event_handler::~channel_event_handler() +{ + _D("Destroy[%p]", this); + m_ch = NULL; + m_handler = NULL; +} + +bool channel_event_handler::handle(int fd, event_condition condition, void **data) +{ + message msg; + + if (!m_ch || !m_ch->is_connected()) + return false; + + if (condition & (EVENT_HUP)) { + //delete m_ch in g_io_handler to prevent double delete. + if (data) + *data = m_ch; + m_ch = NULL; + return false; + } + + if (!m_ch->read_sync(msg, false)) { + m_ch = NULL; + return false; + } + + return true; +} + +void channel_event_handler::connected(channel *ch) +{ + if (m_handler) + m_handler->connected(ch); +} + +void channel_event_handler::disconnected(channel *ch) +{ + if (m_handler) + m_handler->disconnected(ch); +} + +void channel_event_handler::read(channel *ch, message &msg) +{ + if (m_handler) + m_handler->read(ch, msg); +} + +void channel_event_handler::read_complete(channel *ch) +{ + if (m_handler) + m_handler->read_complete(ch); +} + +void channel_event_handler::error_caught(channel *ch, int error) +{ + if (m_handler) + m_handler->error_caught(ch, error); +} diff --git a/src/shared/channel_event_handler.h b/src/shared/channel_event_handler.h new file mode 100644 index 0000000..85a3efd --- /dev/null +++ b/src/shared/channel_event_handler.h @@ -0,0 +1,55 @@ +/* + * sensord + * + * 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. + * 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 __CHANNEL_EVENT_HANDLER_H__ +#define __CHANNEL_EVENT_HANDLER_H__ + +#include + +#include "event_handler.h" +#include "channel_handler.h" + +namespace ipc { + +class channel; + +class channel_event_handler : public event_handler, public channel_handler { +public: + channel_event_handler(channel *ch, channel_handler *handler); + virtual ~channel_event_handler(); + + bool handle(int fd, event_condition condition, void **data); + + void connected(channel *ch); + void disconnected(channel *ch); + void read(channel *ch, message &msg); + void read_complete(channel *ch); + void error_caught(channel *ch, int error); + + void set_handler(int num, channel_handler* handler) {} + void disconnect(void) {} + +private: + channel *m_ch; + channel_handler *m_handler; +}; + +} + +#endif /* __CHANNEL_EVENT_HANDLER_H__ */ diff --git a/src/shared/channel_handler.h b/src/shared/channel_handler.h new file mode 100644 index 0000000..abcab19 --- /dev/null +++ b/src/shared/channel_handler.h @@ -0,0 +1,44 @@ +/* + * sensord + * + * 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. + * 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 __CHANNEL_HANDLER_H__ +#define __CHANNEL_HANDLER_H__ + +namespace ipc { + +class channel; +class message; +class channel_handler; + +class channel_handler { +public: + virtual ~channel_handler() {} + + virtual void connected(channel *ch) = 0; + virtual void disconnected(channel *ch) = 0; + virtual void disconnect(void) = 0; + virtual void read(channel *ch, message &msg) = 0; + virtual void read_complete(channel *ch) = 0; + virtual void error_caught(channel *ch, int error) = 0; + virtual void set_handler(int num, channel_handler* handler) = 0; +}; + +} + +#endif /* __CHANNEL_HANDLER_H__ */ diff --git a/src/shared/cmutex.cpp b/src/shared/cmutex.cpp new file mode 100644 index 0000000..d3d19dd --- /dev/null +++ b/src/shared/cmutex.cpp @@ -0,0 +1,71 @@ +/* + * sensord + * + * Copyright (c) 2013 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 + +using namespace sensor; + +cmutex::cmutex() +{ + pthread_mutexattr_t mutex_attr; + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m_mutex, &mutex_attr); + pthread_mutexattr_destroy(&mutex_attr); +} + +cmutex::~cmutex() +{ + pthread_mutex_destroy(&m_mutex); +} + +void cmutex::lock(void) +{ +#ifdef _LOCK_DEBUG + cbase_lock::lock(LOCK_TYPE_MUTEX, "mutex", __MODULE__, __func__, __LINE__); +#else + cbase_lock::lock(LOCK_TYPE_MUTEX); +#endif +} + +void cmutex::lock(const char* expr, const char *module, const char *func, int line) +{ + cbase_lock::lock(LOCK_TYPE_MUTEX, expr, module, func, line); +} + +int cmutex::try_lock(void) +{ + return try_lock_impl(); +} + +int cmutex::lock_impl(void) +{ + return pthread_mutex_lock(&m_mutex); +} + +int cmutex::try_lock_impl(void) +{ + return pthread_mutex_trylock(&m_mutex); +} + +int cmutex::unlock_impl(void) +{ + return pthread_mutex_unlock(&m_mutex); +} diff --git a/src/shared/cmutex.h b/src/shared/cmutex.h new file mode 100644 index 0000000..b6c3d4d --- /dev/null +++ b/src/shared/cmutex.h @@ -0,0 +1,45 @@ +/* + * sensord + * + * Copyright (c) 2013 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 _CMUTEX_H_ +#define _CMUTEX_H_ + +#include "cbase_lock.h" +namespace sensor { + +class cmutex : public cbase_lock { +public: + cmutex(); + virtual ~cmutex(); + + void lock(void); + void lock(const char* expr, const char *module, const char *func, int line); + int try_lock(void); + +protected: + int lock_impl(void); + int try_lock_impl(void); + int unlock_impl(void); + +private: + pthread_mutex_t m_mutex; +}; + +} +#endif /* _CMUTEX_H_ */ diff --git a/src/shared/command_types.h b/src/shared/command_types.h new file mode 100644 index 0000000..29aaf86 --- /dev/null +++ b/src/shared/command_types.h @@ -0,0 +1,135 @@ +/* + * sensord + * + * 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 __COMMAND_TYPES_H__ +#define __COMMAND_TYPES_H__ + +#include +#include "sensor_info.h" + +#define SENSOR_CHANNEL_PATH "/run/.sensord.socket" +#define MAX_BUF_SIZE (16*1024) + +/* TODO: OOP - create serializer interface */ +enum cmd_type_e { + CMD_DONE = -1, + CMD_NONE = 0, + + /* Manager */ + CMD_MANAGER_CONNECT = 0x100, + CMD_MANAGER_SENSOR_LIST, + CMD_MANAGER_SENSOR_ADDED, + CMD_MANAGER_SENSOR_REMOVED, + + /* Listener */ + CMD_LISTENER_EVENT = 0x200, + CMD_LISTENER_ACC_EVENT, + CMD_LISTENER_CONNECT, + CMD_LISTENER_START, + CMD_LISTENER_STOP, + CMD_LISTENER_SET_ATTR_INT, + CMD_LISTENER_SET_ATTR_STR, + CMD_LISTENER_GET_DATA, + CMD_LISTENER_GET_ATTR_INT, + CMD_LISTENER_GET_ATTR_STR, + CMD_LISTENER_GET_DATA_LIST, + CMD_LISTENER_CONNECTED, + + /* Provider */ + CMD_PROVIDER_CONNECT = 0x300, + CMD_PROVIDER_START, + CMD_PROVIDER_STOP, + CMD_PROVIDER_ATTR_INT, + CMD_PROVIDER_PUBLISH, + CMD_PROVIDER_ATTR_STR, + + /* Etc */ + CMD_HAS_PRIVILEGE = 0x1000, + + CMD_CNT, +}; + +typedef struct { + int sensor_cnt; + char data[0]; +} cmd_manager_sensor_list_t; + +typedef struct { + int listener_id; + char sensor[NAME_MAX]; +} cmd_listener_connect_t; + +typedef struct { + int listener_id; +} cmd_listener_start_t; + +typedef struct { + int listener_id; +} cmd_listener_stop_t; + +typedef struct { + int listener_id; + int attribute; + int value; +} cmd_listener_attr_int_t; + +typedef struct { + int listener_id; + int attribute; + int len; + char value[0]; +} cmd_listener_attr_str_t; + +typedef struct { + int listener_id; + int len; + sensor_data_t data; +} cmd_listener_get_data_t; + +typedef struct { + int listener_id; + int len; + int data_count; + sensor_data_t data[0]; +} cmd_listener_get_data_list_t; + +typedef struct { + char info[0]; +} cmd_provider_connect_t; + +typedef struct { + sensor_data_t data; +} cmd_provider_publish_t; + +typedef struct { + int attribute; + int value; +} cmd_provider_attr_int_t; + +typedef struct { + int attribute; + int len; + char value[0]; +} cmd_provider_attr_str_t; + +typedef struct { + char sensor[NAME_MAX]; +} cmd_has_privilege_t ; + +#endif /* __COMMAND_TYPES_H__ */ diff --git a/src/shared/event_handler.h b/src/shared/event_handler.h new file mode 100644 index 0000000..7d1696a --- /dev/null +++ b/src/shared/event_handler.h @@ -0,0 +1,49 @@ +/* + * sensord + * + * 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. + * 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 __EVENT_HANDLER_H__ +#define __EVENT_HANDLER_H__ + +#include +namespace ipc { + +typedef unsigned int event_condition; + +class event_handler { +public: + event_handler() + : m_event_id(0) + { + } + + virtual ~event_handler() {} + + virtual bool handle(int fd, event_condition condition, void **data) = 0; + void set_event_id(uint64_t event_id) + { + m_event_id = event_id; + } + +protected: + uint64_t m_event_id; +}; + +} + +#endif /* __EVENT_HANDLER_H__ */ diff --git a/src/shared/event_loop.cpp b/src/shared/event_loop.cpp new file mode 100644 index 0000000..720687b --- /dev/null +++ b/src/shared/event_loop.cpp @@ -0,0 +1,357 @@ +/* + * sensord + * + * 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. + * 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 "event_loop.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "channel_event_handler.h" +#include "sensor_log.h" +#include "event_handler.h" +#include "channel.h" + +#define BAD_HANDLE 0 + +using namespace ipc; +using namespace sensor; + +static std::vector channel_handler_release_list; +static std::priority_queue channel_release_queue; +static sensor::cmutex release_lock; + +static void release_res() +{ + AUTOLOCK(release_lock); + + channel *prev = NULL, *current = NULL; + while (!channel_release_queue.empty()) { + current = channel_release_queue.top(); + if (prev != current) + delete current; + prev = current; + channel_release_queue.pop(); + } + + for (auto &it : channel_handler_release_list) + delete it; + + /* To reduce memory allocation, swap to new data structure. + This prevents occasional over-allocation of memory. */ + std::priority_queue().swap(channel_release_queue); + std::vector().swap(channel_handler_release_list); +} + +static gboolean g_io_handler(GIOChannel *ch, GIOCondition condition, gpointer data) +{ + uint64_t id; + int fd; + bool term; + bool ret; + event_loop *loop; + event_handler *handler; + unsigned int cond; + + cond = (unsigned int)condition; + + if (cond & (G_IO_HUP)) + cond &= ~(G_IO_IN | G_IO_OUT); + + handler_info *info = (handler_info *)data; + loop = info->loop; + handler = info->handler; + retvm_if(!loop || !handler, FALSE, "Invalid event info"); + + id = info->id; + fd = info->fd; + term = loop->is_terminator(fd); + + if (cond & G_IO_NVAL) + return G_SOURCE_REMOVE; + + void *addr = NULL; + ret = handler->handle(fd, (event_condition)cond, &addr); + + if (!ret && !term) { + LOCK(release_lock); + channel_release_queue.push((channel*)addr); + UNLOCK(release_lock); + if (!addr) + loop->remove_event(id); + ret = G_SOURCE_REMOVE; + } else { + ret = G_SOURCE_CONTINUE; + } + + release_res(); + + return ret; +} + +static gint on_timer(gpointer data) +{ + event_loop *loop = (event_loop *)data; + loop->stop(); + + return FALSE; +} + +event_loop::event_loop() +: m_mainloop(NULL) +, m_running(false) +, m_terminating(false) +, m_sequence(1) +, m_term_fd(-1) +{ + m_mainloop = g_main_loop_new(NULL, FALSE); +} + +event_loop::event_loop(GMainLoop *mainloop) +: m_mainloop(NULL) +, m_running(true) +, m_terminating(false) +, m_sequence(1) +, m_term_fd(-1) +{ + m_mainloop = mainloop; +} + +event_loop::~event_loop() +{ + if (m_term_fd != -1) + close(m_term_fd); + + _D("Destoryed"); +} + +void event_loop::set_mainloop(GMainLoop *mainloop) +{ + retm_if(!mainloop, "Invalid mainloop"); + + m_mainloop = mainloop; +} + +uint64_t event_loop::add_event(const int fd, const event_condition cond, event_handler *handler) +{ + AUTOLOCK(m_cmutex); + GIOChannel *ch = NULL; + GSource *src = NULL; + + retvm_if(m_terminating.load(), BAD_HANDLE, + "Failed to add event, because event_loop is being terminated"); + + ch = g_io_channel_unix_new(fd); + retvm_if(!ch, BAD_HANDLE, "Failed to create g_io_channel_unix_new"); + + src = g_io_create_watch(ch, (GIOCondition)(cond)); + if (!src) { + g_io_channel_unref(ch); + _E("Failed to create g_io_create_watch"); + return BAD_HANDLE; + } + + uint64_t id = m_sequence++; + if (m_sequence == 0) { + m_sequence = 1; + } + + handler_info *info = new(std::nothrow) handler_info(id, fd, ch, src, handler, this); + retvm_if(!info, BAD_HANDLE, "Failed to allocate memory"); + + handler->set_event_id(id); + g_source_set_callback(src, (GSourceFunc) g_io_handler, info, NULL); + g_source_attach(src, g_main_loop_get_context(m_mainloop)); + + m_handlers[id] = info; + + /* _D("Added event[%llu], fd[%d]", id, fd); */ + return id; +} + +struct idler_data { + void (*m_fn)(size_t, void*); + void* m_data; +}; + +size_t event_loop::add_idle_event(unsigned int priority, void (*fn)(size_t, void*), void* data) +{ + AUTOLOCK(m_cmutex); + GSource *src; + + retvm_if(m_terminating.load(), 0, + "Failed to remove event, because event_loop is terminated"); + + src = g_idle_source_new(); + retvm_if(!src, 0, "Failed to allocate memory"); + + idler_data *id = new idler_data(); + id->m_fn = fn; + id->m_data = data; + + g_source_set_callback(src, [](gpointer gdata) -> gboolean { + idler_data *id = (idler_data *)gdata; + id->m_fn((size_t)id, id->m_data); + delete id; + return G_SOURCE_REMOVE; + }, id, NULL); + + g_source_attach(src, g_main_loop_get_context (m_mainloop)); + g_source_unref(src); + + return (size_t)id; +} + +bool event_loop::remove_event(uint64_t id) +{ + AUTOLOCK(m_cmutex); + auto it = m_handlers.find(id); + retv_if(it == m_handlers.end(), false); + + release_info(it->second); + m_handlers.erase(id); + + /* _D("Removed event[%llu]", id); */ + return true; +} + +void event_loop::remove_all_events(void) +{ + AUTOLOCK(m_cmutex); + auto it = m_handlers.begin(); + while (it != m_handlers.end()) { + release_info(it->second); + it = m_handlers.erase(it); + } +} + +void event_loop::release_info(handler_info *info) +{ + retm_if(!info->g_ch || info->id == 0, "Invalid handler information"); + /* _D("Releasing event..[%llu]", info->id); */ + + g_source_destroy(info->g_src); + g_source_unref(info->g_src); + + g_io_channel_unref(info->g_ch); + + info->g_ch = NULL; + delete info->handler; + info->handler = NULL; + + delete info; + + /* _D("Released event[%llu]", info->id); */ +} + +void event_loop::add_channel_release_queue(channel *ch) +{ + AUTOLOCK(release_lock); + channel_release_queue.push(ch); +} + +void event_loop::add_channel_handler_release_list(channel_handler *handler) +{ + AUTOLOCK(release_lock); + channel_handler_release_list.push_back(handler); +} + +class terminator : public event_handler +{ +public: + terminator(event_loop *loop) + : m_loop(loop) + { } + + bool handle(int fd, event_condition condition, void **data) + { + m_loop->terminate(); + return false; + } + +private: + event_loop *m_loop; +}; + +bool event_loop::run(int timeout) +{ + retvm_if(!m_mainloop, false, "Invalid GMainLoop"); + retvm_if(is_running(), false, "Already started"); + + if (timeout > 0) { + GSource *src = g_timeout_source_new(timeout); + g_source_set_callback(src, on_timer, this, NULL); + g_source_attach(src, g_main_loop_get_context(m_mainloop)); + g_source_unref(src); + } + + m_term_fd = eventfd(0, EFD_CLOEXEC); + retv_if(m_term_fd == -1, false); + + terminator *handler = new(std::nothrow) terminator(this); + retvm_if(!handler, false, "Failed to allocate memory"); + + add_event(m_term_fd, EVENT_IN | EVENT_HUP | EVENT_NVAL, handler); + + m_running.store(true); + + _I("Started"); + g_main_loop_run(m_mainloop); + + return true; +} + +void event_loop::stop(void) +{ + ret_if(!is_running() || m_terminating.load()); + + terminate(); +} + +void event_loop::terminate(void) +{ + remove_all_events(); + + if (m_mainloop) { + g_main_loop_quit(m_mainloop); + g_main_loop_unref(m_mainloop); + m_mainloop = NULL; + } + + m_running.store(false); + m_terminating.store(false); + + _I("Terminated"); +} + +bool event_loop::is_running(void) +{ + return m_running.load(); +} + +bool event_loop::is_terminator(int fd) +{ + return (m_term_fd == fd); +} diff --git a/src/shared/event_loop.h b/src/shared/event_loop.h new file mode 100644 index 0000000..aeae959 --- /dev/null +++ b/src/shared/event_loop.h @@ -0,0 +1,111 @@ +/* + * sensord + * + * 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. + * 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 __EVENT_LOOP_H__ +#define __EVENT_LOOP_H__ + +#include +#include +#include +#include + +#include "event_handler.h" +#include "cmutex.h" + +namespace ipc { + +class channel; +class channel_handler; + +enum event_condition_e { + EVENT_IN = G_IO_IN, + EVENT_OUT = G_IO_OUT, + EVENT_HUP = G_IO_HUP, + EVENT_NVAL = G_IO_NVAL, +}; + +/* move it to file */ +class idle_handler { + virtual ~idle_handler(); + bool handle(int fd); +}; + +class event_loop; + +class handler_info { +public: + handler_info(uint64_t _id, int _fd, GIOChannel *_ch, GSource *_src, event_handler *_handler, event_loop *_loop) + : id(_id) + , fd(_fd) + , g_ch(_ch) + , g_src(_src) + , handler(_handler) + , loop(_loop) + {} + + uint64_t id; + int fd; + GIOChannel *g_ch; + GSource *g_src; + event_handler *handler; + event_loop *loop; +}; + +class event_loop { +public: + typedef unsigned int event_condition; + typedef bool (*idle_cb)(void *); + + event_loop(); + event_loop(GMainLoop *mainloop); + ~event_loop(); + + void set_mainloop(GMainLoop *mainloop); + + uint64_t add_event(const int fd, const event_condition cond, event_handler *handler); + size_t add_idle_event(unsigned int priority, void (*fn)(size_t, void*), void* data); + + bool remove_event(uint64_t id); + void remove_all_events(void); + void release_info(handler_info *info); + + void add_channel_release_queue(channel *ch); + void add_channel_handler_release_list(channel_handler *handler); + + bool run(int timeout = 0); + void stop(void); + void terminate(void); + + bool is_running(void); + bool is_terminator(int fd); + +private: + GMainLoop *m_mainloop; + std::atomic m_running; + std::atomic m_terminating; + std::atomic m_sequence; + std::map m_handlers; + + int m_term_fd; + sensor::cmutex m_cmutex; +}; + +} + +#endif /* __EVENT_LOOP_H__ */ diff --git a/src/shared/ipc_client.cpp b/src/shared/ipc_client.cpp new file mode 100644 index 0000000..26c20a3 --- /dev/null +++ b/src/shared/ipc_client.cpp @@ -0,0 +1,86 @@ +/* + * sensord + * + * 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. + * 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 "ipc_client.h" + +#include "sensor_log.h" +#include "stream_socket.h" +#include "event_handler.h" +#include "channel_event_handler.h" + +using namespace ipc; + +ipc_client::ipc_client(const std::string &path) +{ + m_path = path; +} + +ipc_client::~ipc_client() +{ +} + +bool ipc_client::set_option(int option, int value) +{ + return true; +} + +bool ipc_client::set_option(const std::string &option, int value) +{ + return true; +} + +channel *ipc_client::connect(channel_handler *handler) +{ + return connect(handler, NULL); +} + +channel *ipc_client::connect(channel_handler *handler, event_loop *loop, bool bind) +{ + socket *sock = NULL; + channel *ch = NULL; + channel_event_handler *ev_handler = NULL; + + sock = new(std::nothrow) stream_socket(); + retvm_if(!sock, NULL, "Failed to allocate memory"); + + if (!sock->create(m_path)) { + delete sock; + return NULL; + } + + ch = new(std::nothrow) channel(sock); + if (!ch) { + delete sock; + _E("Failed to allocate memory"); + return NULL; + } + + ev_handler = new(std::nothrow) channel_event_handler(ch, handler); + if (!ev_handler) { + delete ch; + _E("Failed to allocate memory"); + return NULL; + } + + uint64_t id = ch->connect(ev_handler, loop, bind); + + _D("Connected[%llu]", id); + + return ch; +} diff --git a/src/shared/ipc_client.h b/src/shared/ipc_client.h new file mode 100644 index 0000000..40d9182 --- /dev/null +++ b/src/shared/ipc_client.h @@ -0,0 +1,50 @@ +/* + * sensord + * + * 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. + * 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 __IPC_CLIENT_H__ +#define __IPC_CLIENT_H__ + +#include + +#include "channel.h" +#include "channel_handler.h" +#include "event_loop.h" + +namespace ipc { + +class ipc_client { +public: + ipc_client(const std::string &path); + ~ipc_client(); + + bool set_option(int option, int value); + bool set_option(const std::string &option, int value); + + /* call channel->disconnect() after you have used it */ + channel *connect(channel_handler *handler); + /* TODO: remove bind parameter */ + channel *connect(channel_handler *handler, event_loop *loop, bool bind = true); + +private: + std::string m_path; +}; + +} + +#endif /* __IPC_CLIENT_H__ */ diff --git a/src/shared/ipc_server.cpp b/src/shared/ipc_server.cpp new file mode 100644 index 0000000..d25a562 --- /dev/null +++ b/src/shared/ipc_server.cpp @@ -0,0 +1,117 @@ +/* + * sensord + * + * 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. + * 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 "ipc_server.h" + +#include "channel.h" +#include "sensor_log.h" +#include "event_loop.h" +#include "channel_event_handler.h" +#include "accept_event_handler.h" + +using namespace ipc; + +#define MAX_CONNECTIONS 1000 + +ipc_server::ipc_server(const std::string &path) +: m_event_loop(NULL) +, m_handler(NULL) +, m_accept_handler(NULL) +{ + m_accept_sock.create(path); +} + +ipc_server::~ipc_server() +{ +} + +bool ipc_server::set_option(int option, int value) +{ + /* TODO */ + return true; +} + +bool ipc_server::set_option(const std::string &option, int value) +{ + /* TODO */ + return true; +} + +void ipc_server::accept(ipc::socket &cli_sock) +{ + m_accept_sock.accept(cli_sock); + + _D("Accepted[%d]", cli_sock.get_fd()); +} + +bool ipc_server::bind(channel_handler *handler, event_loop *loop) +{ + m_handler = handler; + m_event_loop = loop; + + m_accept_sock.bind(); + m_accept_sock.listen(MAX_CONNECTIONS); + + register_acceptor(); + + _D("Bound[%d]", m_accept_sock.get_fd()); + return true; +} + +void ipc_server::register_channel(int fd, channel *ch) +{ + channel_event_handler *ev_handler = new(std::nothrow) channel_event_handler(ch, m_handler); + retm_if(!ev_handler, "Failed to allocate memory"); + + uint64_t id = ch->bind(ev_handler, m_event_loop, true); + + if (id == 0) { + _E("Failed to register channel"); + delete ev_handler; + return; + } + + _D("Register channel[%p] : event_id[%llu]", ch, id); +} + +void ipc_server::register_acceptor(void) +{ + int fd = m_accept_sock.get_fd(); + + m_accept_handler = new(std::nothrow) accept_event_handler(this); + retm_if(!m_accept_handler, "Failed to allocate memory"); + + uint64_t id = m_event_loop->add_event(fd, + (event_condition)(EVENT_IN | EVENT_HUP | EVENT_NVAL), m_accept_handler); + + if (id == 0) { + _D("Failed to add accept event handler"); + delete m_accept_handler; + m_accept_handler = NULL; + } +} + +bool ipc_server::close(void) +{ + m_accept_sock.close(); + + m_handler = NULL; + + return true; +} diff --git a/src/shared/ipc_server.h b/src/shared/ipc_server.h new file mode 100644 index 0000000..7e033d0 --- /dev/null +++ b/src/shared/ipc_server.h @@ -0,0 +1,59 @@ +/* + * sensord + * + * 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. + * 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 __IPC_SERVER_H__ +#define __IPC_SERVER_H__ + +#include + +#include "stream_socket.h" +#include "channel.h" +#include "channel_handler.h" +#include "accept_event_handler.h" +#include "event_loop.h" + +namespace ipc { + +class ipc_server { +public: + ipc_server(const std::string &path); + ~ipc_server(); + + bool set_option(int option, int value); + bool set_option(const std::string &option, int value); + + bool bind(channel_handler *handler, event_loop *loop); + bool close(void); + + /* TODO: only accept_handler should use these functions */ + void accept(ipc::socket &cli_sock); + void register_channel(int fd, channel *ch); + void register_acceptor(void); + +private: + stream_socket m_accept_sock; + + event_loop *m_event_loop; + channel_handler *m_handler; + accept_event_handler *m_accept_handler; +}; + +} + +#endif /* __IPC_SERVER_H__ */ diff --git a/src/shared/macro.h b/src/shared/macro.h new file mode 100644 index 0000000..0ec7bcf --- /dev/null +++ b/src/shared/macro.h @@ -0,0 +1,70 @@ +/* + * sensord + * + * Copyright (c) 2014 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. + * + */ + +#pragma once + +#include +#include +#include + +#define _cleanup_(x) __attribute__((cleanup(x))) + +static inline void __freep(void *p) +{ + free(*(void**) p); +} + +static inline void __closep(int *fd) +{ + if (*fd >= 0) + close(*fd); +} + +static inline void __fclosep(FILE **f) +{ + if (*f) + fclose(*f); +} + +static inline void int_to_bytes(int value, int width, char data[]) +{ + /* Big-endian */ + for (int i = width - 1; i >= 0; i--) { + data[i] = (value & 0xff); + value = value >> 8; + } +} + +static inline unsigned int bytes_to_uint(char data[], int &cursor, int width) +{ + unsigned int sum = 0; + + /* Big-endian */ + for (int i = 0; i < width; ++i) + sum = (sum << 8) + (unsigned char)data[cursor++]; + + return sum; +} + +#define _cleanup_free_ _cleanup_(__freep) +#define _cleanup_close_ _cleanup_(__closep) +#define _cleanup_fclose_ _cleanup_(__fclosep) +#define GET_BYTES(value, width, data) int_to_bytes(value, width, data) +#define GET_UINT(data, cursor, width) bytes_to_uint(data, cursor, width) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) diff --git a/src/shared/message.cpp b/src/shared/message.cpp new file mode 100644 index 0000000..5f12d23 --- /dev/null +++ b/src/shared/message.cpp @@ -0,0 +1,132 @@ +/* + * sensord + * + * 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. + * 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 "message.h" + +#include +#include + +using namespace ipc; + +#define UNDEFINED_TYPE -2 + +static std::atomic sequence(0); + +message::message(size_t capacity) + : m_size(0) + , m_capacity(capacity) + , m_msg((char *)malloc(sizeof(char) * capacity)) +{ + m_header.id = sequence++; + m_header.type = UNDEFINED_TYPE; + m_header.length = m_size; + m_header.err = 0; +} + +message::message(const void *msg, size_t sz) + : m_size(sz) + , m_capacity(sz) + , m_msg((char *)msg) +{ + m_header.id = sequence++; + m_header.type = UNDEFINED_TYPE; + m_header.length = m_size; + m_header.err = 0; +} + +message::message(const message &msg) + : m_size(msg.m_size) + , m_capacity(msg.m_capacity) + , m_msg((char *)malloc(sizeof(char) * msg.m_capacity)) +{ + ::memcpy(&m_header, &msg.m_header, sizeof(message_header)); + ::memcpy(m_msg, msg.m_msg, msg.m_size); +} + +message::message(int error) + : m_size(0) + , m_capacity(0) + , m_msg(NULL) +{ + m_header.id = sequence++; + m_header.type = UNDEFINED_TYPE; + m_header.length = 0; + m_header.err = error; +} + +message::~message() +{ + if (m_msg) { + free(m_msg); + m_msg = NULL; + } +} + +void message::enclose(const void *msg, const size_t sz) +{ + if (!msg || sz == 0) + return; + + if (m_capacity < sz) + return; + + ::memcpy(reinterpret_cast(m_msg), msg, sz); + m_size = sz; + m_header.length = sz; +} + +void message::enclose(int error) +{ + m_header.err = error; + m_header.length = 0; + m_size = 0; +} + +void message::disclose(void *msg, const size_t size) +{ + if (!msg || !m_msg || m_size > size) + return; + + ::memcpy(msg, m_msg, m_size); +} + +uint32_t message::type(void) +{ + return m_header.type; +} + +void message::set_type(uint32_t msg_type) +{ + m_header.type = msg_type; +} + +size_t message::size(void) +{ + return m_size; +} + +message_header *message::header(void) +{ + return &m_header; +} + +char *message::body(void) +{ + return m_msg; +} diff --git a/src/shared/message.h b/src/shared/message.h new file mode 100644 index 0000000..49055c3 --- /dev/null +++ b/src/shared/message.h @@ -0,0 +1,81 @@ +/* + * sensord + * + * 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. + * 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 __MESSAGE_H__ +#define __MESSAGE_H__ + +#include /* size_t */ +#include +#include + +#define MAX_MSG_CAPACITY (32*1024) +#define MAX_HEADER_RESERVED 3 + +namespace ipc { + +typedef struct message_header { + uint64_t id { 0 }; + uint32_t type { 0 }; + size_t length { 0 }; + int32_t err { 0 }; + void *ancillary[MAX_HEADER_RESERVED] { nullptr }; +} message_header; + +class message { +public: + template + static std::shared_ptr create(Args&&... args) + noexcept(noexcept(message(std::forward(args)...))) + { + return std::shared_ptr(new (std::nothrow) message(std::forward(args)...)); + } + + message(size_t capacity = MAX_MSG_CAPACITY); + message(const void *msg, size_t size); + message(const message &msg); + message(int err); + ~message(); + + void enclose(const void *msg, const size_t size); + void enclose(int error); + void disclose(void *msg, const size_t size); + + uint32_t type(void); + void set_type(uint32_t type); + + size_t size(void); + + void ref(void); + void unref(void); + int ref_count(void); + + message_header *header(void); + char *body(void); + +private: + message_header m_header; + size_t m_size; + size_t m_capacity; + + char *m_msg; +}; + +} + +#endif /* __MESSAGE_H__ */ diff --git a/src/shared/sensor_info.cpp b/src/shared/sensor_info.cpp new file mode 100644 index 0000000..f060083 --- /dev/null +++ b/src/shared/sensor_info.cpp @@ -0,0 +1,420 @@ +/* + * sensord + * + * 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. + * 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_info.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "sensor_utils.h" + +#define MIN_RANGE -FLT_MAX +#define MAX_RANGE FLT_MAX + +using namespace sensor; + +sensor_info::sensor_info() +: m_type(UNKNOWN_SENSOR) +, m_uri(SENSOR_UNKNOWN_NAME) +, m_model(SENSOR_UNKNOWN_NAME) +, m_vendor(SENSOR_UNKNOWN_NAME) +, m_min_range(0) +, m_max_range(0) +, m_resolution(0) +, m_min_interval(0) +, m_max_interval(0) +, m_max_batch_count(0) +, m_wakeup_supported(false) +, m_privilege("") +{ +} + +sensor_info::sensor_info(const sensor_info &info) +: m_type(info.m_type) +, m_uri(info.m_uri) +, m_model(info.m_model) +, m_vendor(info.m_vendor) +, m_min_range(info.m_min_range) +, m_max_range(info.m_max_range) +, m_resolution(info.m_resolution) +, m_min_interval(info.m_min_interval) +, m_max_interval(info.m_max_interval) +, m_max_batch_count(info.m_max_batch_count) +, m_wakeup_supported(info.m_wakeup_supported) +, m_privilege(info.m_privilege) +{ +} + +sensor_info::sensor_info(const sensor_info_t &info) +{ + /* TODO: HAL should change name from single name to URI */ + const char *type = sensor::utils::get_uri((sensor_type_t)info.type); + std::string uri(type); + uri.append("/").append(info.name); + + set_type((sensor_type_t)info.type); + set_uri(uri.c_str()); + set_model(info.model_name); + set_vendor(info.vendor); + set_min_range(info.min_range); + set_max_range(info.max_range); + set_resolution(info.resolution); + set_min_interval(info.min_interval); + set_max_interval(info.max_interval); + set_max_batch_count(info.max_batch_count); + set_wakeup_supported(info.wakeup_supported); + /* TODO: sensor_info_t should have privilege string */ + set_privilege(""); +} + +sensor_info::sensor_info(const sensor_info2_t &info) +{ + std::string uri(info.uri); + std::size_t found = uri.find_last_of("/\\"); + + set_type(info.type); + set_uri(uri.c_str()); + set_model(uri.substr(found + 1, uri.length()).c_str()); + set_vendor(info.vendor); + set_min_range(info.min_range); + set_max_range(info.max_range); + set_resolution(info.resolution); + set_min_interval(info.min_interval); + set_max_interval(info.max_interval); + set_max_batch_count(info.max_batch_count); + set_wakeup_supported(info.wakeup_supported); + set_privilege(info.privilege); +} + +sensor_type_t sensor_info::get_type(void) +{ + return m_type; +} + +std::string &sensor_info::get_uri(void) +{ + return m_uri; +} + +std::string &sensor_info::get_model(void) +{ + return m_model; +} + +std::string &sensor_info::get_vendor(void) +{ + return m_vendor; +} + +float sensor_info::get_min_range(void) +{ + return m_min_range; +} + +float sensor_info::get_max_range(void) +{ + return m_max_range; +} + +float sensor_info::get_resolution(void) +{ + return m_resolution; +} + +int sensor_info::get_min_interval(void) +{ + return m_min_interval; +} + +int sensor_info::get_max_interval(void) +{ + return m_max_interval; +} + +int sensor_info::get_max_batch_count(void) +{ + return m_max_batch_count; +} + +bool sensor_info::is_wakeup_supported(void) +{ + return m_wakeup_supported; +} + +std::string &sensor_info::get_privilege(void) +{ + return m_privilege; +} + +void sensor_info::set_type(sensor_type_t type) +{ + m_type = type; +} + +void sensor_info::set_uri(const char *name) +{ + m_uri = name; +} + +void sensor_info::set_model(const char *model) +{ + m_model = model; +} + +void sensor_info::set_vendor(const char *vendor) +{ + m_vendor = vendor; +} + +void sensor_info::set_min_range(float min_range) +{ + m_min_range = min_range; + + if (!std::isnormal(m_min_range)) + m_min_range = 0; /* set value to 0 when the value is NaN, infinity, zero or subnormal */ + if (m_min_range < MIN_RANGE) + m_min_range = MIN_RANGE; + if (m_min_range > MAX_RANGE) + m_min_range = MAX_RANGE; +} + +void sensor_info::set_max_range(float max_range) +{ + m_max_range = max_range; + + if (!std::isnormal(m_max_range)) + m_max_range = 0; /* set value to 0 when the value is NaN, infinity, zero or subnormal */ + if (m_max_range < MIN_RANGE) + m_max_range = MIN_RANGE; + if (m_max_range > MAX_RANGE) + m_max_range = MAX_RANGE; +} + +void sensor_info::set_resolution(float resolution) +{ + m_resolution = resolution; +} + +void sensor_info::set_min_interval(int min_interval) +{ + m_min_interval = min_interval; +} + +void sensor_info::set_max_interval(int max_interval) +{ + m_max_interval = max_interval; +} + +void sensor_info::set_max_batch_count(int max_batch_count) +{ + m_max_batch_count = max_batch_count; +} + +void sensor_info::set_wakeup_supported(bool supported) +{ + m_wakeup_supported = supported; +} + +void sensor_info::set_privilege(const char *privilege) +{ + m_privilege = privilege; +} + +void sensor_info::add_privilege(const char *privilege) +{ + if (!m_privilege.empty()) + m_privilege.append(PRIV_DELIMITER); + m_privilege.append(privilege); +} + +void sensor_info::serialize(raw_data_t &data) +{ + put(data, m_type); + put(data, m_uri); + put(data, m_model); + put(data, m_vendor); + put(data, m_min_range); + put(data, m_max_range); + put(data, m_resolution); + put(data, m_min_interval); + //put(data, m_max_interval); to do + put(data, m_max_batch_count); + put(data, m_wakeup_supported); + put(data, m_privilege); +} + +void sensor_info::deserialize(const char *data, int data_len) +{ + int type; + + raw_data_t raw_data(&data[0], &data[data_len]); + auto it = raw_data.begin(); + it = get(it, type); + m_type = (sensor_type_t)type; + + it = get(it, m_uri); + it = get(it, m_model); + it = get(it, m_vendor); + it = get(it, m_min_range); + it = get(it, m_max_range); + it = get(it, m_resolution); + it = get(it, m_min_interval); + //it = get(it, m_max_interval); to do + it = get(it, m_max_batch_count); + it = get(it, m_wakeup_supported); + it = get(it, m_privilege); +} + +void sensor_info::show(void) +{ + _I("URI = %s", m_uri.c_str()); + _I("Model = %s", m_model.c_str()); + _I("Vendor = %s", m_vendor.c_str()); + _I("Min_range = %f", m_min_range); + _I("Max_range = %f", m_max_range); + _I("Resolution = %f", m_resolution); + _I("Min_interval = %d", m_min_interval); + _I("Max_batch_count = %d", m_max_batch_count); + _I("Wakeup_supported = %d", m_wakeup_supported); + _I("Privilege = %s", m_privilege.c_str()); +} + +void sensor_info::clear(void) +{ + m_type = UNKNOWN_SENSOR; + m_uri.clear(); + m_model.clear(); + m_vendor.clear(); + m_min_range = 0.0f; + m_max_range = 0.0f; + m_resolution = 0.0f; + m_min_interval = 0; + m_max_interval = 0; + m_max_batch_count = 0; + m_wakeup_supported = false; + m_privilege.clear(); +} + +void sensor_info::put(raw_data_t &data, int value) +{ + char buffer[sizeof(value)]; + + int *temp = reinterpret_cast(buffer); + *temp = value; + + copy(&buffer[0], &buffer[sizeof(buffer)], back_inserter(data)); +} + +void sensor_info::put(raw_data_t &data, unsigned int value) +{ + char buffer[sizeof(value)]; + + unsigned int *temp = reinterpret_cast(buffer); + *temp = value; + + copy(&buffer[0], &buffer[sizeof(buffer)], back_inserter(data)); +} + +void sensor_info::put(raw_data_t &data, int64_t value) +{ + char buffer[sizeof(value)]; + + int64_t *temp = reinterpret_cast(buffer); + *temp = value; + + copy(&buffer[0], &buffer[sizeof(buffer)], back_inserter(data)); +} + +void sensor_info::put(raw_data_t &data, float value) +{ + char buffer[sizeof(value)]; + + float *temp = reinterpret_cast(buffer); + *temp = value; + + copy(&buffer[0], &buffer[sizeof(buffer)], back_inserter(data)); +} + +void sensor_info::put(raw_data_t &data, std::string &value) +{ + put(data, (int) value.size()); + + copy(value.begin(), value.end(), back_inserter(data)); +} + +void sensor_info::put(raw_data_t &data, bool value) +{ + char buffer[sizeof(value)]; + + bool *temp = (bool *) buffer; + *temp = value; + + copy(&buffer[0], &buffer[sizeof(buffer)], back_inserter(data)); +} + +raw_data_iterator sensor_info::get(raw_data_iterator it, int &value) +{ + copy(it, it + sizeof(value), (char*) &value); + + return it + sizeof(value); +} + +raw_data_iterator sensor_info::get(raw_data_iterator it, unsigned int &value) +{ + copy(it, it + sizeof(value), (char*) &value); + + return it + sizeof(value); +} + +raw_data_iterator sensor_info::get(raw_data_iterator it, int64_t &value) +{ + copy(it, it + sizeof(value), (char*) &value); + + return it + sizeof(value); +} + +raw_data_iterator sensor_info::get(raw_data_iterator it, float &value) +{ + copy(it, it + sizeof(value), (char*) &value); + + return it + sizeof(value); +} + +raw_data_iterator sensor_info::get(raw_data_iterator it, std::string &value) +{ + int len; + + it = get(it, len); + + copy(it, it + len, back_inserter(value)); + + return it + len; +} + +raw_data_iterator sensor_info::get(raw_data_iterator it, bool &value) +{ + copy(it, it + sizeof(value), (char*) &value); + + return it + sizeof(value); +} diff --git a/src/shared/sensor_info.h b/src/shared/sensor_info.h new file mode 100644 index 0000000..cbd5406 --- /dev/null +++ b/src/shared/sensor_info.h @@ -0,0 +1,109 @@ +/* + * sensord + * + * 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. + * 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 __SENSOR_INFO_H__ +#define __SENSOR_INFO_H__ + +#include +#include +#include +#include +#include + +namespace sensor { + +typedef std::vector raw_data_t; +typedef raw_data_t::iterator raw_data_iterator; + +/* TODO: builder */ +class sensor_info { +public: + sensor_info(); + sensor_info(const sensor_info &info); + sensor_info(const sensor_info_t &info); + sensor_info(const sensor_info2_t &info); + + /* TODO: it would be better to return type(URI) */ + sensor_type_t get_type(void); + std::string &get_uri(void); + std::string &get_model(void); + std::string &get_vendor(void); + float get_min_range(void); + float get_max_range(void); + float get_resolution(void); + int get_min_interval(void); + int get_max_interval(void); + int get_max_batch_count(void); + bool is_wakeup_supported(void); + std::string &get_privilege(void); + + void set_type(sensor_type_t type); + void set_uri(const char *name); + void set_model(const char *name); + void set_vendor(const char *vendor); + void set_min_range(float min_range); + void set_max_range(float max_range); + void set_resolution(float resolution); + void set_min_interval(int min_interval); + void set_max_interval(int max_interval); + void set_max_batch_count(int max_batch_count); + void set_wakeup_supported(bool supported); + void set_privilege(const char *privilege); + void add_privilege(const char *privilege); + + void clear(void); + + void serialize(raw_data_t &data); + void deserialize(const char *data, int data_len); + void show(void); + +private: + sensor_type_t m_type; + std::string m_uri; + std::string m_model; + std::string m_vendor; + float m_min_range; + float m_max_range; + float m_resolution; + int m_min_interval; + int m_max_interval; + int m_max_batch_count; + bool m_wakeup_supported; + std::string m_privilege; + + /* TODO: use template */ + void put(raw_data_t &data, int value); + void put(raw_data_t &data, unsigned int value); + void put(raw_data_t &data, int64_t value); + void put(raw_data_t &data, float value); + void put(raw_data_t &data, std::string &value); + void put(raw_data_t &data, bool value); + + /* TODO: use template */ + raw_data_iterator get(raw_data_iterator it, int &value); + raw_data_iterator get(raw_data_iterator it, unsigned int &value); + raw_data_iterator get(raw_data_iterator it, int64_t &value); + raw_data_iterator get(raw_data_iterator it, float &value); + raw_data_iterator get(raw_data_iterator it, std::string &value); + raw_data_iterator get(raw_data_iterator it, bool &value); +}; + +} + +#endif /* __SENSOR_INFO_H__ */ diff --git a/src/shared/sensor_types_private.h b/src/shared/sensor_types_private.h new file mode 100644 index 0000000..b76a6fe --- /dev/null +++ b/src/shared/sensor_types_private.h @@ -0,0 +1,43 @@ +/* + * sensord + * + * 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. + * 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 __SENSOR_TYPES_PRIVATE__ +#define __SENSOR_TYPES_PRIVATE__ + +#define URI_REGEX(CATEGORY) R"~(^http:\/\/[\w-]+(\.[\w-]+)*\/)~" CATEGORY R"~(\/(general|healthinfo)\/[\w-]+(\.[\w-]+)*(\/[\w-]+(\.[\w-]+)*)$)~" +#define SENSOR_URI_REGEX URI_REGEX("sensor") + +#define PREDEFINED_TYPE_URI "http://tizen.org/sensor/" + +#define PRIV_DELIMITER ";" +#define URI_DELIMITER "/" + +#define PRIVILEGE_HEALTHINFO_STR "healthinfo" +#define PRIVILEGE_HEALTHINFO_URI "http://tizen.org/privilege/healthinfo" + +#define PRIVILEGE_LOCATION_STR "location" +#define PRIVILEGE_LOCATION_URI "http://tizen.org/privilege/location" + +#define PRIVILEGE_PLATFORM_STR "platform" +#define PRIVILEGE_PLATFORM_URI "http://tizen.org/privilege/internal/default/platform" + +#define URI_PRIV_INDEX 4 +#define URI_SENSOR_TYPE_INDEX 5 + +#endif /* __SENSOR_TYPES_PRIVATE__ */ diff --git a/src/shared/sensor_utils.cpp b/src/shared/sensor_utils.cpp new file mode 100644 index 0000000..58a5978 --- /dev/null +++ b/src/shared/sensor_utils.cpp @@ -0,0 +1,287 @@ +/* + * sensord + * + * 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. + * 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_utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef PATH_MAX +#define PATH_MAX 256 +#endif + +/* TODO: move and define string type to sensor_type.h */ +static std::map types = { + {UNKNOWN_SENSOR, "http://tizen.org/sensor/general/unknown"}, + {ALL_SENSOR, "http://tizen.org/sensor/general/all"}, + {ACCELEROMETER_SENSOR, "http://tizen.org/sensor/general/accelerometer"}, + {GRAVITY_SENSOR, "http://tizen.org/sensor/general/gravity"}, + {LINEAR_ACCEL_SENSOR, "http://tizen.org/sensor/general/linear_acceleration"}, + {GEOMAGNETIC_SENSOR, "http://tizen.org/sensor/general/magnetic"}, + {ROTATION_VECTOR_SENSOR, "http://tizen.org/sensor/general/rotation_vector"}, + {ORIENTATION_SENSOR, "http://tizen.org/sensor/general/orientation"}, + {GYROSCOPE_SENSOR, "http://tizen.org/sensor/general/gyroscope"}, + {LIGHT_SENSOR, "http://tizen.org/sensor/general/light"}, + {PROXIMITY_SENSOR, "http://tizen.org/sensor/general/proximity"}, + {PRESSURE_SENSOR, "http://tizen.org/sensor/general/pressure"}, + {ULTRAVIOLET_SENSOR, "http://tizen.org/sensor/general/ultraviolet"}, + {TEMPERATURE_SENSOR, "http://tizen.org/sensor/general/temperature"}, + {HUMIDITY_SENSOR, "http://tizen.org/sensor/general/humidity"}, + {HRM_SENSOR, "http://tizen.org/sensor/healthinfo/heart_rate_monitor"}, + {HRM_LED_GREEN_SENSOR, "http://tizen.org/sensor/healthinfo/heart_rate_monitor.led_green"}, + {HRM_LED_IR_SENSOR, "http://tizen.org/sensor/healthinfo/heart_rate_monitor.led_ir"}, + {HRM_LED_RED_SENSOR, "http://tizen.org/sensor/healthinfo/heart_rate_monitor.led_red"}, + {GYROSCOPE_UNCAL_SENSOR, "http://tizen.org/sensor/general/gyroscope.uncalibrated"}, + {GEOMAGNETIC_UNCAL_SENSOR, "http://tizen.org/sensor/general/geomagnetic.uncalibrated"}, + {GYROSCOPE_RV_SENSOR, "http://tizen.org/sensor/general/gyroscope_rotation_vector"}, + {GEOMAGNETIC_RV_SENSOR, "http://tizen.org/sensor/general/geomagnetic_rotation_vector"}, + {GYROSCOPE_ORIENTATION_SENSOR, "http://tizen.org/sensor/general/gyroscope_orientation"}, + {GEOMAGNETIC_ORIENTATION_SENSOR, "http://tizen.org/sensor/general/geomagnetic_orientation"}, + + {SIGNIFICANT_MOTION_SENSOR, "http://tizen.org/sensor/general/significant_motion"}, + + {HRM_BATCH_SENSOR, "http://tizen.org/sensor/healthinfo/heart_rate_monitor.batch"}, + {HRM_LED_GREEN_BATCH_SENSOR, "http://tizen.org/sensor/healthinfo/heart_rate_monitor.led_green.batch"}, + + {HUMAN_PEDOMETER_SENSOR, "http://tizen.org/sensor/healthinfo/human_pedometer"}, + {HUMAN_SLEEP_MONITOR_SENSOR, "http://tizen.org/sensor/healthinfo/human_sleep_monitor"}, + {HUMAN_SLEEP_DETECTOR_SENSOR, "http://tizen.org/sensor/healthinfo/human_sleep_detector"}, + {HUMAN_STRESS_MONITOR_SENSOR, "http://tizen.org/sensor/healthinfo/human_stress_monitor"}, + + {LIDAR_SENSOR, "http://tizen.org/sensor/general/lidar"}, + + {EXERCISE_WALKING_SENSOR, "http://tizen.org/sensor/healthinfo/exercise.walking"}, + {EXERCISE_RUNNING_SENSOR, "http://tizen.org/sensor/healthinfo/exercise.running"}, + {EXERCISE_HIKING_SENSOR, "http://tizen.org/sensor/healthinfo/exercise.hiking"}, + {EXERCISE_CYCLING_SENSOR, "http://tizen.org/sensor/healthinfo/exercise.cycling"}, + {EXERCISE_ELLIPTICAL_SENSOR, "http://tizen.org/sensor/healthinfo/exercise.elliptical"}, + {EXERCISE_INDOOR_CYCLING_SENSOR, "http://tizen.org/sensor/healthinfo/exercise.indoor_cycling"}, + {EXERCISE_ROWING_SENSOR, "http://tizen.org/sensor/healthinfo/exercise.rowing"}, + {EXERCISE_STEPPER_SENSOR, "http://tizen.org/sensor/healthinfo/exercise.stepper"}, + + + {FUSION_SENSOR, "http://tizen.org/sensor/general/fusion"}, + {AUTO_ROTATION_SENSOR, "http://tizen.org/sensor/general/auto_rotation"}, + {AUTO_BRIGHTNESS_SENSOR, "http://tizen.org/sensor/general/auto_brightness"}, + + {GESTURE_MOVEMENT_SENSOR, "http://tizen.org/sensor/general/gesture_movement"}, + {GESTURE_WRIST_UP_SENSOR, "http://tizen.org/sensor/general/gesture_wrist_up"}, + {GESTURE_WRIST_DOWN_SENSOR, "http://tizen.org/sensor/general/gesture_wrist_down"}, + {GESTURE_MOVEMENT_STATE_SENSOR, "http://tizen.org/sensor/general/gesture_movement_state"}, + {GESTURE_PICK_UP_SENSOR, "http://tizen.org/sensor/general/gesture_pick_up"}, + {GESTURE_FACE_DOWN_SENSOR, "http://tizen.org/sensor/general/gesture_face_down"}, + + {ACTIVITY_TRACKER_SENSOR, "http://tizen.org/sensor/general/activity_tracker"}, + {ACTIVITY_LEVEL_MONITOR_SENSOR, "http://tizen.org/sensor/general/activity_level_monitor"}, + {GPS_BATCH_SENSOR, "http://tizen.org/sensor/location/gps_batch"}, + {PPG_BATCH_SENSOR, "http://tizen.org/sensor/healthinfo/ppg_batch"}, + {GPS_TIMESYNC_SENSOR, "http://tizen.org/sensor/location/gps_timesync"}, + + {HRM_CTRL_SENSOR, "http://tizen.org/sensor/general/hrm_ctrl"}, + {REG_CTRL_SENSOR, "http://tizen.org/sensor/general/reg_ctrl"}, + {GPS_CTRL_SENSOR, "http://tizen.org/sensor/general/gps_ctrl"}, + + {WEAR_STATUS_SENSOR, "http://tizen.org/sensor/general/wear_status"}, + {WEAR_ON_MONITOR_SENSOR, "http://tizen.org/sensor/general/wear_on_monitor"}, + {NO_MOVE_DETECTOR_SENSOR, "http://tizen.org/sensor/general/no_move_detector"}, + {RESTING_HR_SENSOR, "http://tizen.org/sensor/healthinfo/resting_hr"}, + {STEP_LEVEL_MONITOR_SENSOR, "http://tizen.org/sensor/healthinfo/step_level_monitor"}, + {EXERCISE_STANDALONE_SENSOR, "http://tizen.org/sensor/healthinfo/exercise_standalone"}, + {EXERCISE_HR_SENSOR, "http://tizen.org/sensor/healthinfo/exercise_hr"}, + {WORKOUT_SENSOR, "http://tizen.org/sensor/healthinfo/workout"}, + {CYCLE_MONITOR_SENSOR, "http://tizen.org/sensor/healthinfo/cycle_monitor"}, + {STAIR_TRACKER_SENSOR, "http://tizen.org/sensor/healthinfo/stair_tracker"}, + {PRESSURE_INDICATOR_SENSOR, "http://tizen.org/sensor/general/pressure_indicator"}, + {PRESSURE_ALERT_SENSOR, "http://tizen.org/sensor/general/pressure_alert"}, + {HR_CALORIE_SENSOR, "http://tizen.org/sensor/healthinfo/hr_calorie"}, + {SWIMMING_TRACKER_SENSOR, "http://tizen.org/sensor/healthinfo/swimming_tracker"}, + {SWIMMING_OUTDOOR_SENSOR, "http://tizen.org/sensor/healthinfo/swimming_outdoor"}, + {AUTO_SWIMMING_SENSOR, "http://tizen.org/sensor/healthinfo/auto_swimming"}, + {INACTIVITY_DETECTOR_SENSOR, "http://tizen.org/sensor/general/inactivity_detector"}, + {STRESS_TRACKER_SENSOR, "http://tizen.org/sensor/healthinfo/stress_tracker"}, + {FAKE_MOTION_SENSOR, "http://tizen.org/sensor/general/fake_motion"}, + {GEOFENCE_SENSOR, "http://tizen.org/sensor/general/geofence"}, + {INACTIVITY_DETECTOR_SENSOR, "http://tizen.org/sensor/healthinfo/inactivity_detector"}, + {HRM_BP_SENSOR, "http://tizen.org/sensor/healthinfo/hrm_bp"}, + {ECG_SENSOR, "http://tizen.org/sensor/healthinfo/ecg"}, + {FALL_DETECTION_SENSOR, "http://tizen.org/sensor/general/fall_detection"}, + + {CONTEXT_SENSOR, "http://tizen.org/sensor/general/context"}, + {MOTION_SENSOR, "http://tizen.org/sensor/general/motion"}, + {PIR_SENSOR, "http://tizen.org/sensor/general/pir"}, + {PIR_LONG_SENSOR, "http://tizen.org/sensor/general/pir_long"}, + {DUST_SENSOR, "http://tizen.org/sensor/general/dust"}, + {THERMOMETER_SENSOR, "http://tizen.org/sensor/general/thermometer"}, + {PEDOMETER_SENSOR, "http://tizen.org/sensor/healthinfo/pedometer"}, + {FLAT_SENSOR, "http://tizen.org/sensor/general/flat"}, + {HRM_RAW_SENSOR, "http://tizen.org/sensor/healthinfo/hrm_raw"}, + {TILT_SENSOR, "http://tizen.org/sensor/general/tilt"}, + {RV_RAW_SENSOR, "http://tizen.org/sensor/general/rv_raw"}, + {GSR_SENSOR, "http://tizen.org/sensor/healthinfo/gsr"}, + {SIMSENSE_SENSOR, "http://tizen.org/sensor/healthinfo/simsense"}, + {PPG_SENSOR, "http://tizen.org/sensor/healthinfo/ppg"}, +}; + +const char *sensor::utils::get_uri(sensor_type_t type) +{ + auto it = types.find(type); + if (it == types.end()) + return types[UNKNOWN_SENSOR]; + return it->second; +} + +const char *sensor::utils::get_privilege(std::string uri) +{ + std::size_t start = 0; + std::size_t end = uri.length(); + std::size_t size = uri.size(); + + for (int i = 0; i < URI_PRIV_INDEX; ++i) { + retv_if(start >= uri.length(), ""); + start = uri.find(URI_DELIMITER, start + 1); + retv_if(start == std::string::npos, ""); + } + + end = uri.find(URI_DELIMITER, start + 1); + retv_if(end == std::string::npos, ""); + + size = end - (start + 1); + + if (uri.substr(start + 1, size) == PRIVILEGE_HEALTHINFO_STR) + return PRIVILEGE_HEALTHINFO_URI; + else if (uri.substr(start + 1, size) == PRIVILEGE_LOCATION_STR) + return PRIVILEGE_LOCATION_URI; + else if (uri.substr(start + 1, size) == PRIVILEGE_PLATFORM_STR) + return PRIVILEGE_PLATFORM_URI; + + return ""; +} + +static void init_types(std::map &sensor_types) +{ + ret_if(!sensor_types.empty()); + + for (auto it = types.begin(); it != types.end(); ++it) { + std::string uri(it->second); + std::size_t found = uri.find_last_of("/"); + std::size_t len = uri.length() - (found + 1); + + sensor_types.emplace(uri.substr(found + 1, len), it->first); + } +} + +sensor_type_t sensor::utils::get_type(std::string uri) +{ + static std::map sensor_types; + init_types(sensor_types); + + std::size_t start = 0; + std::size_t end = uri.length(); + std::size_t size = uri.size(); + + for (int i = 0; i < URI_SENSOR_TYPE_INDEX; ++i) { + retv_if(start >= uri.length(), UNKNOWN_SENSOR); + start = uri.find(URI_DELIMITER, start + 1); + retv_if(start == std::string::npos, UNKNOWN_SENSOR); + } + + end = uri.find(URI_DELIMITER, start + 1); + retv_if(end == std::string::npos, UNKNOWN_SENSOR); + + size = end - (start + 1); + + auto it = sensor_types.find(uri.substr(start + 1, size)); + retv_if(it == sensor_types.end(), UNKNOWN_SENSOR); + + return it->second; +} + +unsigned long long sensor::utils::get_timestamp(void) +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return ((unsigned long long)(t.tv_sec)*1000000000LL + t.tv_nsec) / 1000; +} + +unsigned long long sensor::utils::get_timestamp(timeval *t) +{ + if (!t) + return 0; + + return ((unsigned long long)(t->tv_sec)*1000000LL +t->tv_usec); +} + +bool sensor::utils::get_proc_name(pid_t pid, char *process_name) +{ + char buf[NAME_MAX]; + + if (snprintf(buf, sizeof(buf), "%d process", pid) < 1) { + return false; + } + + strncpy(process_name, buf, NAME_MAX-1); + process_name[NAME_MAX-1] = '\0'; + + return true; +} + +const char* sensor::utils::get_client_name(void) +{ + const int pid_string_size = 10; + static pid_t pid = -1; + static char client_name[NAME_MAX + pid_string_size]; + + char proc_name[NAME_MAX]; + + if (pid == -1) + { + pid = getpid(); + get_proc_name(pid, proc_name); + snprintf(client_name, sizeof(client_name), "%s(%d)", proc_name, pid); + } + + return client_name; +} + +std::vector sensor::utils::tokenize(const std::string &in, const char *delim) +{ + std::vector tokens; + char *input = g_strdup(in.c_str()); + + char *save = NULL; + char *token = strtok_r(input, delim, &save); + + while (token != NULL) { + tokens.push_back(token); + token = strtok_r(NULL, delim, &save); + } + + g_free(input); + return tokens; +} diff --git a/src/shared/sensor_utils.h b/src/shared/sensor_utils.h new file mode 100644 index 0000000..3497dc7 --- /dev/null +++ b/src/shared/sensor_utils.h @@ -0,0 +1,46 @@ +/* + * sensord + * + * 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. + * 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 __SENSOR_UTILS_H__ +#define __SENSOR_UTILS_H__ + +#include +#include +#include +#include + +namespace sensor { + +namespace utils { + const char *get_uri(sensor_type_t type); + const char *get_privilege(std::string uri); + sensor_type_t get_type(std::string uri); + + unsigned long long get_timestamp(void); + unsigned long long get_timestamp(timeval *t); + + const char* get_client_name(void); + bool get_proc_name(pid_t pid, char *process_name); + + std::vector tokenize(const std::string &in, const char *delim); +} + +} + +#endif /* __SENSOR_UTILS_H__ */ diff --git a/src/shared/seqpacket_socket.cpp b/src/shared/seqpacket_socket.cpp new file mode 100644 index 0000000..ad27394 --- /dev/null +++ b/src/shared/seqpacket_socket.cpp @@ -0,0 +1,95 @@ +/* + * sensord + * + * 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. + * 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 "seqpacket_socket.h" + +#include +#include + +#include "sensor_log.h" + +using namespace ipc; + +seqpacket_socket::seqpacket_socket() +: socket() +{ +} + +seqpacket_socket::~seqpacket_socket() +{ +} + +bool seqpacket_socket::create(const std::string &path) +{ + return socket::create_by_type(path, SOCK_SEQPACKET); +} + +ssize_t seqpacket_socket::on_send(const void *buffer, size_t size) const +{ + ssize_t err, len; + + do { + len = ::send(socket::get_fd(), + reinterpret_cast(buffer), + size, + socket::get_mode()); + + err = len < 0 ? errno : 0; + } while (err == EINTR); + + if (err) { + _ERRNO(errno, _E, "Failed to send(%d, %p, %u) = %d", + socket::get_fd(), buffer, size, len); + } + + return err == 0 ? len : -err; +} + +ssize_t seqpacket_socket::on_recv(void *buffer, size_t size) const +{ + ssize_t err, len; + + do { + len = ::recv(socket::get_fd(), + reinterpret_cast(buffer), + size, + socket::get_mode()); + + if (len > 0) { + err = 0; + } else if (len == 0) { + _E("Failed to recv(%d, %p , %u) = %d, because the peer performed shutdown!", + socket::get_fd(), buffer, size, len); + err = 1; + } else { + err = errno; + } + } while (err == EINTR); + + if ((err == EAGAIN) || (err == EWOULDBLOCK)) + return 0; + + if (err) { + _ERRNO(errno, _E, "Failed to recv(%d, %p, %u) = %d", + socket::get_fd(), buffer, size, len); + } + + return err == 0 ? len : -err; +} + diff --git a/src/shared/seqpacket_socket.h b/src/shared/seqpacket_socket.h new file mode 100644 index 0000000..05c25d8 --- /dev/null +++ b/src/shared/seqpacket_socket.h @@ -0,0 +1,41 @@ +/* + * sensord + * + * 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. + * 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 __SEQPACKET_SOCKET_H__ +#define __SEQPACKET_SOCKET_H__ + +#include "socket.h" + +namespace ipc { + +class seqpacket_socket : public socket { +public: + seqpacket_socket(); + ~seqpacket_socket(); + + bool create(const std::string &path); + +private: + ssize_t on_send(const void *buffer, size_t size) const; + ssize_t on_recv(void *buffer, size_t size) const; +}; + +} + +#endif /* __SEQPACKET_SOCKET_H__ */ diff --git a/src/shared/socket.cpp b/src/shared/socket.cpp new file mode 100644 index 0000000..6d11076 --- /dev/null +++ b/src/shared/socket.cpp @@ -0,0 +1,456 @@ +/* + * sensord + * + * 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. + * 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 "socket.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "sensor_log.h" + +#define SOCK_TIMEOUT 10 + +using namespace ipc; + +static bool set_close_on_exec(int fd) +{ + if (::fcntl(fd, F_SETFL, FD_CLOEXEC) == -1) + return false; + + return true; +} + +static int create_systemd_socket(const std::string &path, int type) +{ + int n; + int listening; + + listening = (type == SOCK_STREAM) ? 1 : -1; + + n = sd_listen_fds(0); + retvm_if(n < 0, -EPERM, "Failed to listen fds from systemd"); + + for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; ++fd) { + if (sd_is_socket_unix(fd, type, listening, path.c_str(), 0) > 0) { + set_close_on_exec(fd); + return fd; + } + } + + return -EPERM; +} + +static int create_unix_socket(int type) +{ + int sock_fd = ::socket(AF_UNIX, type, 0); + + if (sock_fd < 0) { + _ERRNO(errno, _E, "Failed to create socket"); + return -EPERM; + } + + set_close_on_exec(sock_fd); + + int optval = 1; + if (::setsockopt(sock_fd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) { + _ERRNO(errno, _E, "Failed to create socket[%d]", sock_fd); + ::close(sock_fd); + return -EPERM; + } + + return sock_fd; +} + +static bool select_fds(int fd, fd_set *read_fds, fd_set *write_fds, const int timeout) +{ + struct timeval tv; + int err; + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + while (true) { + err = ::select(fd + 1, read_fds, write_fds, NULL, &tv); + if (err <= 0) + return false; + + if (read_fds && FD_ISSET(fd, read_fds)) + break; + if (write_fds && FD_ISSET(fd, write_fds)) + break; + } + + return true; +} + +socket::socket() +: m_sock_fd(-1) +, m_mode(MSG_DONTWAIT | MSG_NOSIGNAL) +, m_listening(false) +{ +} + +socket::socket(int sock_fd) +: m_sock_fd(sock_fd) +, m_mode(MSG_DONTWAIT | MSG_NOSIGNAL) +, m_listening(false) +{ +} + +socket::socket(const socket &sock) +: m_sock_fd(-1) +, m_mode(MSG_DONTWAIT | MSG_NOSIGNAL) +, m_listening(false) +{ + if (this == &sock) + return; + + m_sock_fd = sock.m_sock_fd; + m_mode = sock.m_mode; + m_listening.store(sock.m_listening); +} + +socket::~socket() +{ + close(); +} + +bool socket::connect(void) +{ + sockaddr_un addr; + fd_set write_fds; + FD_ZERO(&write_fds); + FD_SET(m_sock_fd, &write_fds); + + retvm_if(m_path.size() >= sizeof(sockaddr_un::sun_path), false, + "Failed to create socket[%s]", m_path.c_str()); + + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, m_path.c_str(), sizeof(sockaddr_un::sun_path)); + addr.sun_path[m_path.size()] = '\0'; + + if (::connect(m_sock_fd, + reinterpret_cast(&addr), + sizeof(struct sockaddr_un)) < 0) { + _ERRNO(errno, _E, "Failed to connect() for socket[%d]", m_sock_fd); + close(); + return false; + } + + if (!select_fds(m_sock_fd, NULL, &write_fds, SOCK_TIMEOUT)) { + _E("Failed to select for socket[%d]", m_sock_fd); + close(); + return false; + } + + if (!has_connected()) { + close(); + return false; + } + + return true; +} + +bool socket::bind(void) +{ + sockaddr_un addr; + int file_mode; + + retvm_if(m_path.size() >= sizeof(sockaddr_un::sun_path), false, + "Failed to create socket[%s]", m_path.c_str()); + retv_if(m_listening.load(), true); + + if (!access(m_path.c_str(), F_OK)) + unlink(m_path.c_str()); + + addr.sun_family = AF_UNIX; + ::strncpy(addr.sun_path, m_path.c_str(), sizeof(sockaddr_un::sun_path)); + addr.sun_path[m_path.size()] = '\0'; + + if (::bind(m_sock_fd, + reinterpret_cast(&addr), + sizeof(struct sockaddr_un)) < 0) { + _ERRNO(errno, _E, "Failed to bind for socket[%d]", m_sock_fd); + close(); + return false; + } + + /* TODO: Is this really necessary? */ + file_mode = (S_IRWXU | S_IRWXG | S_IRWXO); + if (chmod(m_path.c_str(), file_mode) < 0) { + _ERRNO(errno, _E, "Failed to create socket[%d]", m_sock_fd); + close(); + return false; + } + + return true; +} + +bool socket::listen(const int max_connections) +{ + retv_if(m_listening.load(), true); + + if (::listen(m_sock_fd, max_connections) < 0) { + _ERRNO(errno, _E, "Failed to listen() for socket[%d]", m_sock_fd); + close(); + return false; + } + + m_listening.store(true); + + _D("Listened[%d]", m_sock_fd); + + return true; +} + +bool socket::accept(socket &client_sock) +{ + int fd; + fd_set read_fds; + FD_ZERO(&read_fds); + FD_SET(m_sock_fd, &read_fds); + + fd = ::accept(m_sock_fd, NULL, NULL); + + if (fd < 0) { + _ERRNO(errno, _E, "Failed to accept[%d]", m_sock_fd); + return false; + } + + set_close_on_exec(fd); + client_sock.set_fd(fd); + /* TODO : socket type should be adjusted here */ + + return true; +} + +bool socket::close(void) +{ + retv_if(m_sock_fd < 0, false); + + if (::close(m_sock_fd) < 0) + return false; + + _D("Closed[%d]", m_sock_fd); + + m_sock_fd = -1; + m_listening.store(false); + + return true; +} + +int socket::get_fd(void) const +{ + return m_sock_fd; +} + +void socket::set_fd(int sock_fd) +{ + m_sock_fd = sock_fd; +} + +int socket::get_mode(void) const +{ + return m_mode; +} + +bool socket::set_mode(int mode) +{ + /* TODO : implement send/recv message mode */ + return true; +} + +bool socket::create(const std::string &path) +{ + return false; +} + +ssize_t socket::send(const void *buffer, size_t size, bool select) const +{ + if (select) { + fd_set write_fds; + FD_ZERO(&write_fds); + FD_SET(m_sock_fd, &write_fds); + + if (!select_fds(m_sock_fd, NULL, &write_fds, SOCK_TIMEOUT)) { + _E("Failed to send message(timeout)"); + return 0; + } + } + + return on_send(buffer, size); +} + +ssize_t socket::recv(void* buffer, size_t size, bool select) const +{ + if (select) { + fd_set read_fds; + FD_ZERO(&read_fds); + FD_SET(m_sock_fd, &read_fds); + + if (!select_fds(m_sock_fd, &read_fds, NULL, SOCK_TIMEOUT)) { + _E("Failed to receive message(timeout)"); + return 0; + } + } + + return on_recv(buffer, size); +} + +bool socket::create_by_type(const std::string &path, int type) +{ + m_sock_fd = ::create_systemd_socket(path, type); + if (m_sock_fd < 0) + m_sock_fd = create_unix_socket(type); + else + m_listening.store(true); + + retvm_if((m_sock_fd < 0), false, "Failed to create socket"); + + /* non-blocking mode */ + retvm_if(!set_blocking_mode(false), false, "Failed to set non-blocking mode"); + /* recv timeout */ + retvm_if(!set_recv_timeout(1), false, "Failed to set timeout"); + /* TODO */ + /*retvm_if(!set_reuse_addr(), false, "Failed to reuse address"); */ + + m_path = path; + + return true; +} + +int socket::get_sock_type(void) +{ + socklen_t opt_len; + int sock_type; + opt_len = sizeof(sock_type); + + retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd); + + if (getsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &sock_type, &opt_len) < 0) { + _ERRNO(errno, _E, "Failed to getsockopt from socket[%d]", m_sock_fd); + return false; + } + + return sock_type; +} + +bool socket::set_recv_timeout(int sec) +{ + struct timeval timeout = {sec, 0}; + + retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd); + + if (setsockopt(m_sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) { + _ERRNO(errno, _E, "Failed to setsockopt[%d]", m_sock_fd); + return false; + } + + return true; +} + +bool socket::set_sock_type(int type) +{ + socklen_t opt_len; + opt_len = sizeof(type); + + retvm_if(m_sock_fd < 0, false, "Invalid socket[%d]", m_sock_fd); + + if (setsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &type, opt_len) < 0) { + _ERRNO(errno, _E, "Failed to setsockopt[%d]", m_sock_fd); + return false; + } + + return true; +} + +bool socket::set_blocking_mode(bool blocking) +{ + int flags; + + flags = fcntl(m_sock_fd, F_GETFL); + retvm_if(flags == -1, false, "Failed to fcntl(F_GETFL)[%d]", m_sock_fd); + + flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); + + flags = fcntl(m_sock_fd, F_SETFL, flags); + retvm_if(flags == -1, false, "Failed to fcntl(F_SETFL)[%d]", m_sock_fd); + + return true; +} + +bool socket::has_connected(void) +{ + int so_error; + socklen_t len = sizeof(so_error); + + if (getsockopt(m_sock_fd, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) { + _E("Failed to call getsockopt[%d]", m_sock_fd); + return false; + } + + if (so_error) { + _E("Failed to connect[%d] : %d", m_sock_fd, so_error); + return false; + } + + return true; +} + +bool socket::set_buffer_size(int type, int size) +{ + retv_if(m_sock_fd < 0, false); + + int ret = 0; + + ret = setsockopt(m_sock_fd, SOL_SOCKET, type, &size, sizeof(size)); + retvm_if(ret < 0, false, "Failed to call setsocketopt()"); + + return true; +} + +int socket::get_buffer_size(int type) +{ + retv_if(m_sock_fd < 0, false); + + int ret = 0; + int buf_size = 0; + socklen_t len; + + ret = getsockopt(m_sock_fd, SOL_SOCKET, type, &buf_size, &len); + retvm_if(ret < 0, -EPERM, "Failed to call getsocketopt()"); + + return buf_size; +} + +int socket::get_current_buffer_size(void) +{ + retv_if(m_sock_fd < 0, false); + + int queue_size = 0; + ioctl(m_sock_fd, TIOCOUTQ, &queue_size); + + return queue_size; +} + diff --git a/src/shared/socket.h b/src/shared/socket.h new file mode 100644 index 0000000..e9b6b66 --- /dev/null +++ b/src/shared/socket.h @@ -0,0 +1,83 @@ +/* + * sensord + * + * 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. + * 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 __SOCKET_H__ +#define __SOCKET_H__ + +#include +#include +#include +#include +#include + +namespace ipc { + +class socket { +public: + socket(); + socket(int sock_fd); + socket(const socket &sock); + virtual ~socket(); + + virtual bool create(const std::string &path); + + bool connect(void); + bool bind(void); + bool listen(const int max_connections); + bool accept(socket &client_sock); + + bool close(void); + + int get_fd(void) const; + void set_fd(int sock_fd); + + int get_mode(void) const; + bool set_mode(int mode); + + bool set_blocking_mode(bool blocking); + bool set_recv_timeout(int timeout); + + /* type : SO_SNDBUF, SO_RCVBUF */ + bool set_buffer_size(int type, int size); + int get_buffer_size(int type); + int get_current_buffer_size(void); + + ssize_t send(const void *buffer, size_t size, bool select = false) const; + ssize_t recv(void* buffer, size_t size, bool select = false) const; + +protected: + bool create_by_type(const std::string &path, int type); + +private: + virtual ssize_t on_send(const void *buffer, size_t size) const = 0; + virtual ssize_t on_recv(void* buffer, size_t size) const = 0; + + int get_sock_type(void); + bool set_sock_type(int type); + bool has_connected(void); + + int m_sock_fd; + int m_mode; + std::atomic m_listening; + std::string m_path; +}; + +} + +#endif /* __SOCKET_H__ */ diff --git a/src/shared/stream_socket.cpp b/src/shared/stream_socket.cpp new file mode 100644 index 0000000..e583f26 --- /dev/null +++ b/src/shared/stream_socket.cpp @@ -0,0 +1,104 @@ +/* + * sensord + * + * 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. + * 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 "stream_socket.h" + +#include +#include + +#include "sensor_log.h" + +#define SLEEP_10_MS usleep(10000) + +using namespace ipc; + +stream_socket::stream_socket() +: socket() +{ +} + +stream_socket::~stream_socket() +{ +} + +bool stream_socket::create(const std::string &path) +{ + return socket::create_by_type(path, SOCK_STREAM); +} + +ssize_t stream_socket::on_send(const void *buffer, size_t size) const +{ + ssize_t len = 0; + size_t total_size = 0; + + do { + len = ::send(get_fd(), + reinterpret_cast(buffer) + total_size, + size - total_size, get_mode()); + + if (len < 0) { + if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) { + SLEEP_10_MS; + continue; + } + + _ERRNO(errno, _E, "Failed to send(%d, %p, %u, %u) = %d", + get_fd(), buffer, total_size, size - total_size, len); + return -errno; + } + + total_size += len; + } while (total_size < size); + + return total_size; +} + +ssize_t stream_socket::on_recv(void *buffer, size_t size) const +{ + ssize_t len = 0; + size_t total_size = 0; + + do { + len = ::recv(get_fd(), + reinterpret_cast(buffer) + total_size, + size - total_size, + socket::get_mode()); + + if (len == 0) { + _E("Failed to recv(%d, %p + %x, %u) = %d, because the peer performed shutdown", + get_fd(), buffer, total_size, size - total_size, len); + return -1; + } + + if (len < 0) { + if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) { + SLEEP_10_MS; + continue; + } + + _ERRNO(errno, _E, "Failed to recv(%d, %p, %u, %u) = %d", + get_fd(), buffer, total_size, size - total_size, len); + return -errno; + } + + total_size += len; + } while (total_size < size); + + return total_size; +} diff --git a/src/shared/stream_socket.h b/src/shared/stream_socket.h new file mode 100644 index 0000000..42af03e --- /dev/null +++ b/src/shared/stream_socket.h @@ -0,0 +1,41 @@ +/* + * sensord + * + * 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. + * 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 __STREAM_SOCKET_H__ +#define __STREAM_SOCKET_H__ + +#include "socket.h" + +namespace ipc { + +class stream_socket : public socket { +public: + stream_socket(); + ~stream_socket(); + + bool create(const std::string &path); + +private: + ssize_t on_send(const void *buffer, size_t size) const; + ssize_t on_recv(void *buffer, size_t size) const; +}; + +} + +#endif /* __STREAM_SOCKET_H__ */ diff --git a/tests/main.c b/tests/main.c index 14287af..eb334d5 100644 --- a/tests/main.c +++ b/tests/main.c @@ -26,7 +26,7 @@ #include "spec_test.h" #include "stress_test.h" -#include "sensor_info.h" +#include "sensor_info_list.h" static void usage(void) { @@ -40,9 +40,9 @@ static void usage(void) printf("\tspec : verifying measured value of range\n"); printf("\tstress : giving stress to sensord\n"); printf("[-s|--sensor_type] : (default is all in spec, accelerometer in stress)\n"); - printf("\t0 : %s (It is valid in only spec test, not stress test)\n", sensor_infos[0].name); + printf("\t0 : %s (It is valid in only spec test, not stress test)\n", sensor_info_lists[0].name); for (int i = 1; i < SENSOR_NUM; ++i) { - printf("\t%d : %s\n", i, sensor_infos[i].name); + printf("\t%d : %s\n", i, sensor_info_lists[i].name); } printed = true; } @@ -95,9 +95,9 @@ int main(int argc, char *argv[]) if (sensor_type) { bool supported; int ret; - ret = sensor_is_supported(sensor_infos[sensor_type].type, &supported); + ret = sensor_is_supported(sensor_info_lists[sensor_type].type, &supported); if (ret < 0 || !supported) { - printf("%s is not supported in this device.\n", sensor_infos[sensor_type].name); + printf("%s is not supported in this device.\n", sensor_info_lists[sensor_type].name); return 0; } } diff --git a/tests/spec_test.c b/tests/spec_test.c index 2315ad9..ac4aea9 100644 --- a/tests/spec_test.c +++ b/tests/spec_test.c @@ -22,7 +22,7 @@ #include #include "spec_test.h" -#include "sensor_info.h" +#include "sensor_info_list.h" #define TEST_COUNT_ONE 100 #define TEST_COUNT_ALL 1000 @@ -48,7 +48,7 @@ static void sensor_one_callback(sensor_h sensor, sensor_event_s events[], int ev ++callback_count; for (int i = 1; i < SENSOR_NUM; ++i){ - if (sensor_infos[i].type == type){ + if (sensor_info_lists[i].type == type){ num = i; break; } @@ -59,10 +59,10 @@ static void sensor_one_callback(sensor_h sensor, sensor_event_s events[], int ev ++called_num[num]; int value_count; - if (events[i].value_count < sensor_infos[num].value_num) + if (events[i].value_count < sensor_info_lists[num].value_num) value_count = events[i].value_count; else - value_count = sensor_infos[num].value_num; + value_count = sensor_info_lists[num].value_num; for (int j = 0; j < value_count; ++j) { if (events[i].values[j] < min_range[num] || events[i].values[j] > max_range[num]) @@ -112,7 +112,7 @@ static void sensor_all_callback(sensor_h sensor, sensor_event_s events[], int ev ++callback_count; for (int i = 1; i < SENSOR_NUM; ++i){ - if (sensor_infos[i].type == type){ + if (sensor_info_lists[i].type == type){ num = i; break; } @@ -123,10 +123,10 @@ static void sensor_all_callback(sensor_h sensor, sensor_event_s events[], int ev ++called_num[num]; int value_count; - if (events[i].value_count < sensor_infos[num].value_num) + if (events[i].value_count < sensor_info_lists[num].value_num) value_count = events[i].value_count; else - value_count = sensor_infos[num].value_num; + value_count = sensor_info_lists[num].value_num; for (int j = 0; j < value_count; ++j) { if (events[i].values[j] < min_range[num] || events[i].values[j] > max_range[num]) { @@ -166,8 +166,8 @@ static int create_sensor_listener(int num, sensor_h *sensor, sensor_listener_h * bool supported; int ret = 0; float min, max; - const char *name = sensor_infos[num].name; - sensor_type_e type = sensor_infos[num].type; + const char *name = sensor_info_lists[num].name; + sensor_type_e type = sensor_info_lists[num].type; ret = sensor_is_supported(type, &supported); if (ret < 0) { @@ -255,7 +255,7 @@ static void spec_test_one(int type) printf("=====================================\n"); double rate = (double) (called_num[type] - miss[type]) / called_num[type] * 100; - printf("%s : %d / %d \n", sensor_infos[type].name, called_num[type] - miss[type], called_num[type]); + printf("%s : %d / %d \n", sensor_info_lists[type].name, called_num[type] - miss[type], called_num[type]); if (rate >= PASS) printf("PASS %.2lf%%\n", rate); @@ -302,7 +302,7 @@ static void spec_test_all(void) if (turned_on[i]) { if (called_num[i]) { rate = (double) (called_num[i] - miss[i]) / called_num[i] * 100; - printf("%s : %d / %d \n", sensor_infos[i].name, called_num[i] - miss[i], called_num[i]); + printf("%s : %d / %d \n", sensor_info_lists[i].name, called_num[i] - miss[i], called_num[i]); if (rate >= PASS) printf("PASS %.2lf%%\n", rate); @@ -310,7 +310,7 @@ static void spec_test_all(void) printf("FAIL %.2lf%%\n", rate); } else { - printf("%s value change was not occurred.\n", sensor_infos[i].name); + printf("%s value change was not occurred.\n", sensor_info_lists[i].name); } } total_miss += miss[i]; @@ -329,14 +329,14 @@ static void spec_test_all(void) for (int i = 1; i < SENSOR_NUM; ++i) { if (turned_on[i] == false) - printf("%s\n", sensor_infos[i].name); + printf("%s\n", sensor_info_lists[i].name); } } void spec_test(int type) { printf("=====================================\n"); - printf("Sensor spec test (%s)\n", sensor_infos[type].name); + printf("Sensor spec test (%s)\n", sensor_info_lists[type].name); printf("=====================================\n"); if (type == 0) diff --git a/tests/stress_test.c b/tests/stress_test.c index bc83564..ee52617 100644 --- a/tests/stress_test.c +++ b/tests/stress_test.c @@ -22,7 +22,7 @@ #include #include "stress_test.h" -#include "sensor_info.h" +#include "sensor_info_list.h" void sensor_events_callback(sensor_h sensor, sensor_event_s events[], int events_count, void *user_data) { @@ -35,7 +35,7 @@ void sensor_listener_set_accuracy_callback(sensor_h sensor, unsigned long long t void stress_test(int type) { printf("=====================================\n"); - printf("Sensor stress test (%s)\n", sensor_infos[type].name); + printf("Sensor stress test (%s)\n", sensor_info_lists[type].name); printf("=====================================\n"); printf("Testing... Check sensord memory. (e.g. memps -s )\n"); printf("If you need, additional execution of this stress test binary in another shell can add more stress to the sensord.\n."); @@ -45,7 +45,7 @@ void stress_test(int type) sensor_event_s* events; int ret, count; while (1) { - ret = sensor_get_default_sensor(sensor_infos[type].type, &sh); + ret = sensor_get_default_sensor(sensor_info_lists[type].type, &sh); if (ret < 0) { printf("fail \"get_default_sensor\": %d \n", ret); break; diff --git a/tools/sensor-tool.c b/tools/sensor-tool.c index 5ad4beb..06485f6 100644 --- a/tools/sensor-tool.c +++ b/tools/sensor-tool.c @@ -4,7 +4,7 @@ #include #include -#include "sensor_info.h" +#include "sensor_info_list.h" static GMainLoop *loop; static bool turned_on[40]; @@ -16,19 +16,19 @@ static void sensor_callback(sensor_h sensor, sensor_event_s events[], int events int num = 0; for (int i = 1; i < SENSOR_NUM; ++i){ - if (sensor_infos[i].type == type){ + if (sensor_info_lists[i].type == type){ num = i; break; } } - g_print("[%s] : ", sensor_infos[num].alias); + g_print("[%s] : ", sensor_info_lists[num].alias); for (int i = 0; i < events_count; ++i) { int value_count; - if (events[i].value_count < sensor_infos[num].value_num) + if (events[i].value_count < sensor_info_lists[num].value_num) value_count = events[i].value_count; else - value_count = sensor_infos[num].value_num; + value_count = sensor_info_lists[num].value_num; for (int j = 0; j < value_count; ++j) g_print("%f ", events[i].values[j]); @@ -42,8 +42,8 @@ static int create_sensor_listener(int num, int interval, sensor_h *sensor, senso bool supported; int ret; float min, max; - const char *name = sensor_infos[num].name; - sensor_type_e type = sensor_infos[num].type; + const char *name = sensor_info_lists[num].name; + sensor_type_e type = sensor_info_lists[num].type; sensor_is_supported(type, &supported); if (!supported) { @@ -80,7 +80,7 @@ static void usage(void) printf("[-i|--interval] : The default is 10ms. range : 10 ~ 1000ms\n"); printf("[-s|--sensor_type] : The default is all\n"); for (int i = 0; i < SENSOR_NUM; ++i) { - printf("\t%d : %s\n", i, sensor_infos[i].name); + printf("\t%d : %s\n", i, sensor_info_lists[i].name); } printed = true; } @@ -141,7 +141,7 @@ int main(int argc, char *argv[]) for (int i = 1; i < SENSOR_NUM; ++i) { if (!turned_on[i]) continue; - printf("%s : [%s]\n", sensor_infos[i].name, sensor_infos[i].alias); + printf("%s : [%s]\n", sensor_info_lists[i].name, sensor_info_lists[i].alias); } printf("\n"); } -- 2.7.4