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)
-#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},
--- /dev/null
+/*
+ * 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__ */
{
#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"
#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_ */
--- /dev/null
+/*
+ * 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__ */
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"
%files
%manifest packaging/capi-system-sensor.manifest
%{_libdir}/libcapi-system-sensor.so.*
+%{_libdir}/libsensor-shared.so
%license LICENSE.APLv2
%files devel
--- /dev/null
+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})
--- /dev/null
+# 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}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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");
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+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})
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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]))
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
#include "spec_test.h"
#include "stress_test.h"
-#include "sensor_info.h"
+#include "sensor_info_list.h"
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;
}
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;
}
}
#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
++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;
}
++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])
++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;
}
++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]) {
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) {
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);
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);
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];
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)
#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)
{
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.");
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;
#include <glib.h>
#include <sensor.h>
-#include "sensor_info.h"
+#include "sensor_info_list.h"
static GMainLoop *loop;
static bool turned_on[40];
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]);
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) {
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;
}
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");
}