Copy libsensor to API 44/277244/4
authorTaeminYeom <taemin.yeom@samsung.com>
Mon, 4 Jul 2022 05:49:07 +0000 (14:49 +0900)
committerTaeminYeom <taemin.yeom@samsung.com>
Wed, 6 Jul 2022 06:03:23 +0000 (15:03 +0900)
Change-Id: Ib82941e2ba6cbb6b7d360a095a1f390797d08e9a
Signed-off-by: TaeminYeom <taemin.yeom@samsung.com>
66 files changed:
CMakeLists.txt
include/sensor_info_list.h [moved from include/sensor_info.h with 95% similarity]
include/sensor_internal.h [new file with mode: 0644]
include/sensor_log.h
include/sensor_types.h [new file with mode: 0644]
packaging/capi-system-sensor.spec
src/api/CMakeLists.txt [new file with mode: 0644]
src/api/capi-system-sensor.pc.in [new file with mode: 0644]
src/api/fusion_util.c [moved from src/fusion_util.c with 100% similarity]
src/api/geomagnetic_field.c [moved from src/geomagnetic_field.c with 100% similarity]
src/api/sensor-internal.cpp [moved from src/sensor-internal.cpp with 100% similarity]
src/api/sensor.cpp [moved from src/sensor.cpp with 100% similarity]
src/api/sensor_internal.cpp [new file with mode: 0644]
src/api/sensor_listener.cpp [new file with mode: 0644]
src/api/sensor_listener.h [new file with mode: 0644]
src/api/sensor_manager.cpp [new file with mode: 0644]
src/api/sensor_manager.h [new file with mode: 0644]
src/api/sensor_manager_channel_handler.cpp [new file with mode: 0644]
src/api/sensor_manager_channel_handler.h [new file with mode: 0644]
src/api/sensor_provider.cpp [moved from src/sensor_provider.cpp with 100% similarity]
src/api/sensor_provider_channel_handler.cpp [new file with mode: 0644]
src/api/sensor_provider_channel_handler.h [new file with mode: 0644]
src/api/sensor_provider_internal.cpp [new file with mode: 0644]
src/api/sensor_provider_internal.h [new file with mode: 0644]
src/api/sensor_reader.cpp [new file with mode: 0644]
src/api/sensor_reader.h [new file with mode: 0644]
src/api/sensor_recorder/sensor_recorder.cpp [moved from src/sensor_recorder.cpp with 100% similarity]
src/api/sensor_recorder/sensor_recorder_dummy.cpp [moved from src/sensor_recorder_dummy.cpp with 100% similarity]
src/shared/CMakeLists.txt [new file with mode: 0644]
src/shared/accept_event_handler.cpp [new file with mode: 0644]
src/shared/accept_event_handler.h [new file with mode: 0644]
src/shared/cbase_lock.cpp [new file with mode: 0644]
src/shared/cbase_lock.h [new file with mode: 0644]
src/shared/channel.cpp [new file with mode: 0644]
src/shared/channel.h [new file with mode: 0644]
src/shared/channel_event_handler.cpp [new file with mode: 0644]
src/shared/channel_event_handler.h [new file with mode: 0644]
src/shared/channel_handler.h [new file with mode: 0644]
src/shared/cmutex.cpp [new file with mode: 0644]
src/shared/cmutex.h [new file with mode: 0644]
src/shared/command_types.h [new file with mode: 0644]
src/shared/event_handler.h [new file with mode: 0644]
src/shared/event_loop.cpp [new file with mode: 0644]
src/shared/event_loop.h [new file with mode: 0644]
src/shared/ipc_client.cpp [new file with mode: 0644]
src/shared/ipc_client.h [new file with mode: 0644]
src/shared/ipc_server.cpp [new file with mode: 0644]
src/shared/ipc_server.h [new file with mode: 0644]
src/shared/macro.h [new file with mode: 0644]
src/shared/message.cpp [new file with mode: 0644]
src/shared/message.h [new file with mode: 0644]
src/shared/sensor_info.cpp [new file with mode: 0644]
src/shared/sensor_info.h [new file with mode: 0644]
src/shared/sensor_types_private.h [new file with mode: 0644]
src/shared/sensor_utils.cpp [new file with mode: 0644]
src/shared/sensor_utils.h [new file with mode: 0644]
src/shared/seqpacket_socket.cpp [new file with mode: 0644]
src/shared/seqpacket_socket.h [new file with mode: 0644]
src/shared/socket.cpp [new file with mode: 0644]
src/shared/socket.h [new file with mode: 0644]
src/shared/stream_socket.cpp [new file with mode: 0644]
src/shared/stream_socket.h [new file with mode: 0644]
tests/main.c
tests/spec_test.c
tests/stress_test.c
tools/sensor-tool.c

index 12faffe..c4964fb 100644 (file)
@@ -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)
similarity index 95%
rename from include/sensor_info.h
rename to include/sensor_info_list.h
index ee13601..99d6cd3 100644 (file)
@@ -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 (file)
index 0000000..477c8d7
--- /dev/null
@@ -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 <stdbool.h>
+#include <sys/types.h>
+#include <limits.h>
+
+/*header for common sensor type*/
+#include <sensor_types.h>
+
+#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__ */
index e70b435..3904e13 100644 (file)
@@ -22,11 +22,58 @@ extern "C"
 {
 #endif
 
-#include <dlog.h>
+#include <dlog/dlog.h>
+#include <sys/types.h>
 
-#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 (file)
index 0000000..a2028d3
--- /dev/null
@@ -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 <stddef.h>
+#include <stdint.h>
+#include <hal/hal-sensor-types.h>
+
+#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__ */
index 7a737c7..dd07e40 100644 (file)
@@ -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 (file)
index 0000000..2e70720
--- /dev/null
@@ -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 (file)
index 0000000..c7ebed2
--- /dev/null
@@ -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}
+
similarity index 100%
rename from src/fusion_util.c
rename to src/api/fusion_util.c
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 (file)
index 0000000..2c9b833
--- /dev/null
@@ -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 <sensor_internal.h>
+#include <sensor_types.h>
+#include <sensor_types_private.h>
+#include <sensor_utils.h>
+
+#include <channel_handler.h>
+#include <sensor_manager.h>
+#include <sensor_listener.h>
+#include <sensor_provider_internal.h>
+#include <sensor_log.h>
+#include <unordered_map>
+#include <regex>
+#include <thread>
+#include <cmutex.h>
+#include <command_types.h>
+
+#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<int, sensor::sensor_listener *> 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_info *>(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_info *>(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_info *>(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_info *>(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_info *>(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_info *>(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_info *>(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_info *>(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_info *>(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_info *>(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_info *>(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<sensord_provider_h>(p);
+       providerCnt++;
+       return OP_SUCCESS;
+}
+
+API int sensord_destroy_provider(sensord_provider_h provider)
+{
+       retvm_if(!provider, -EINVAL, "Invalid paramter");
+
+       delete static_cast<sensor::sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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<sensor_provider *>(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 (file)
index 0000000..7c3ab4b
--- /dev/null
@@ -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 <channel_handler.h>
+#include <sensor_log.h>
+#include <sensor_types.h>
+#include <command_types.h>
+#include <ipc_client.h>
+
+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_info *>(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_info *>(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<sensor_t>(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 (file)
index 0000000..aed8b11
--- /dev/null
@@ -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 <ipc_client.h>
+#include <channel.h>
+#include <channel_handler.h>
+#include <event_loop.h>
+#include <sensor_info.h>
+#include <sensor_types.h>
+#include <cmutex.h>
+#include <map>
+#include <atomic>
+#include <vector>
+
+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<bool> m_connected;
+       std::atomic<bool> m_started;
+       std::map<int, int> m_attributes_int;
+       std::map<int, std::vector<char>> 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 (file)
index 0000000..cec6260
--- /dev/null
@@ -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 <sensor_log.h>
+#include <sensor_info.h>
+#include <sensor_utils.h>
+#include <command_types.h>
+#include <ipc_client.h>
+#include <message.h>
+#include <channel.h>
+
+#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<sensor_info *> 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<sensor_info> &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_info *> sensor_manager::get_infos(const char *uri)
+{
+       std::vector<sensor_info *> 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 (file)
index 0000000..a825f3e
--- /dev/null
@@ -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 <channel.h>
+#include <sensor_info.h>
+#include <ipc_client.h>
+#include <event_loop.h>
+#include <list>
+#include <atomic>
+
+#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<sensor_info> &infos);
+       bool get_sensors_internal(void);
+
+       bool has_privilege(std::string &uri);
+       sensor_info *get_info(const char *uri);
+       std::vector<sensor_info *> 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<bool> m_connected;
+       channel_handler *m_handler;
+
+       std::list<sensor_info> 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 (file)
index 0000000..3feed82
--- /dev/null
@@ -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 <sensor_log.h>
+#include <command_types.h>
+#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 (file)
index 0000000..99f76ed
--- /dev/null
@@ -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 <sensor_internal.h>
+#include <sensor_manager.h>
+#include <channel_handler.h>
+#include <map>
+
+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<sensord_added_cb, void *> sensor_added_cb_list_t;
+       typedef std::map<sensord_removed_cb, void *> 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/api/sensor_provider_channel_handler.cpp b/src/api/sensor_provider_channel_handler.cpp
new file mode 100644 (file)
index 0000000..b39573b
--- /dev/null
@@ -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 <command_types.h>
+#include <sensor_log.h>
+#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 (file)
index 0000000..aa33006
--- /dev/null
@@ -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 <channel_handler.h>
+#include <sensor_internal.h>
+#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 (file)
index 0000000..30762c4
--- /dev/null
@@ -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 <message.h>
+#include <channel.h>
+#include <sensor_log.h>
+#include <sensor_types.h>
+#include <sensor_utils.h>
+#include <ipc_client.h>
+#include <command_types.h>
+#include <cfloat>
+#include <cmath>
+
+#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 (file)
index 0000000..e694b0e
--- /dev/null
@@ -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 <ipc_client.h>
+#include <channel.h>
+#include <channel_handler.h>
+#include <event_loop.h>
+#include <sensor_internal.h>
+#include <sensor_info.h>
+#include <sensor_types.h>
+#include <map>
+#include <atomic>
+
+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<bool> 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 (file)
index 0000000..bc3a7a1
--- /dev/null
@@ -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 <sensor_log.h>
+#include <sensor_types.h>
+#include <chrono>
+
+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<std::mutex> 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 (file)
index 0000000..010eb42
--- /dev/null
@@ -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 <glib.h>
+#include <event_loop.h>
+
+#include <thread>
+#include <atomic>
+#include <condition_variable>
+
+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<bool> m_running;
+};
+
+}
+
+#endif /* __SENSOR_READER_H__ */
diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b9b59ef
--- /dev/null
@@ -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 (file)
index 0000000..419d912
--- /dev/null
@@ -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 (file)
index 0000000..b732238
--- /dev/null
@@ -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 (file)
index 0000000..eafd601
--- /dev/null
@@ -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 <pthread.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <cbase_lock.h>
+#include <sensor_log.h>
+
+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 (file)
index 0000000..5c76040
--- /dev/null
@@ -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 <pthread.h>
+
+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 (file)
index 0000000..26b654c
--- /dev/null
@@ -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 <stdint.h>
+#include <unistd.h>
+#include <memory>
+#include <algorithm>
+
+#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<message> 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<message> 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<channel_event_handler *>(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<message> 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<void *>(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<const void *>(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 (file)
index 0000000..5af06da
--- /dev/null
@@ -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 <unistd.h>
+#include <atomic>
+#include <vector>
+
+#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<message> 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<uint64_t> m_pending_event_id;
+
+       std::atomic<bool> 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 (file)
index 0000000..460b6a0
--- /dev/null
@@ -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 (file)
index 0000000..85a3efd
--- /dev/null
@@ -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 <unordered_map>
+
+#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 (file)
index 0000000..abcab19
--- /dev/null
@@ -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 (file)
index 0000000..d3d19dd
--- /dev/null
@@ -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 <cmutex.h>
+#include <sensor_log.h>
+
+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 (file)
index 0000000..b6c3d4d
--- /dev/null
@@ -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 (file)
index 0000000..29aaf86
--- /dev/null
@@ -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 <sensor_types.h>
+#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 (file)
index 0000000..7d1696a
--- /dev/null
@@ -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 <stdint.h>
+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 (file)
index 0000000..720687b
--- /dev/null
@@ -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 <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/eventfd.h>
+#include <glib.h>
+
+#include <vector>
+#include <queue>
+
+#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*> channel_handler_release_list;
+static std::priority_queue<channel*> 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<channel*>().swap(channel_release_queue);
+       std::vector<channel_handler*>().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 (file)
index 0000000..aeae959
--- /dev/null
@@ -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 <stdint.h>
+#include <glib.h>
+#include <atomic>
+#include <map>
+
+#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<bool> m_running;
+       std::atomic<bool> m_terminating;
+       std::atomic<uint64_t> m_sequence;
+       std::map<uint64_t, handler_info *> 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 (file)
index 0000000..26c20a3
--- /dev/null
@@ -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 (file)
index 0000000..40d9182
--- /dev/null
@@ -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 <string>
+
+#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 (file)
index 0000000..d25a562
--- /dev/null
@@ -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 (file)
index 0000000..7e033d0
--- /dev/null
@@ -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 <string>
+
+#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 (file)
index 0000000..0ec7bcf
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#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 (file)
index 0000000..5f12d23
--- /dev/null
@@ -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 <sensor_log.h>
+#include <atomic>
+
+using namespace ipc;
+
+#define UNDEFINED_TYPE -2
+
+static std::atomic<uint64_t> 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<char *>(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 (file)
index 0000000..49055c3
--- /dev/null
@@ -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 <stdlib.h> /* size_t */
+#include <atomic>
+#include <memory>
+
+#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 <class... Args>
+       static std::shared_ptr<message> create(Args&&... args)
+               noexcept(noexcept(message(std::forward<Args>(args)...)))
+       {
+               return std::shared_ptr<message>(new (std::nothrow) message(std::forward<Args>(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 (file)
index 0000000..f060083
--- /dev/null
@@ -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 <sensor_types.h>
+#include <sensor_types_private.h>
+#include <sensor_log.h>
+#include <cfloat>
+#include <algorithm>
+#include <string>
+#include <cmath>
+
+#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<int *>(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<unsigned int *>(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<int64_t *>(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<float *>(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 (file)
index 0000000..cbd5406
--- /dev/null
@@ -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 <stdint.h>
+#include <string>
+#include <vector>
+#include <hal/hal-sensor-types.h>
+#include <sensor_types.h>
+
+namespace sensor {
+
+typedef std::vector<char> 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 (file)
index 0000000..b76a6fe
--- /dev/null
@@ -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 (file)
index 0000000..58a5978
--- /dev/null
@@ -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 <glib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stddef.h>
+#include <map>
+
+#include <sensor_log.h>
+#include <sensor_types.h>
+#include <sensor_types_private.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 256
+#endif
+
+/* TODO: move and define string type to sensor_type.h */
+static std::map<sensor_type_t, const char *> 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<std::string, sensor_type_t> &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<std::string, sensor_type_t> 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<std::string> sensor::utils::tokenize(const std::string &in, const char *delim)
+{
+       std::vector<std::string> 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 (file)
index 0000000..3497dc7
--- /dev/null
@@ -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 <time.h>
+#include <sensor_types.h>
+#include <string>
+#include <vector>
+
+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<std::string> 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 (file)
index 0000000..ad27394
--- /dev/null
@@ -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 <sys/types.h>
+#include <sys/socket.h>
+
+#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<const char *>(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<char *>(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 (file)
index 0000000..05c25d8
--- /dev/null
@@ -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 (file)
index 0000000..6d11076
--- /dev/null
@@ -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 <fcntl.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <systemd/sd-daemon.h>
+
+#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<struct sockaddr *>(&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<struct sockaddr *>(&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 (file)
index 0000000..e9b6b66
--- /dev/null
@@ -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 <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <string>
+#include <atomic>
+
+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<bool> 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 (file)
index 0000000..e583f26
--- /dev/null
@@ -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 <sys/types.h>
+#include <sys/socket.h>
+
+#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<const char *>(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<char *>(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 (file)
index 0000000..42af03e
--- /dev/null
@@ -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__ */
index 14287af..eb334d5 100644 (file)
@@ -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;
                }
        }
index 2315ad9..ac4aea9 100644 (file)
@@ -22,7 +22,7 @@
 #include <sensor.h>
 
 #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)
index bc83564..ee52617 100644 (file)
@@ -22,7 +22,7 @@
 #include <sensor.h>
 
 #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 <pid>)\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;
index 5ad4beb..06485f6 100644 (file)
@@ -4,7 +4,7 @@
 #include <glib.h>
 #include <sensor.h>
 
-#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");
                }