bool command_channel::create_channel(void)
{
+ const int cllient_type = CLIENT_TYPE_SENSOR_CLIENT;
if (!m_command_socket.create(SOCK_STREAM))
return false;
m_command_socket.set_connection_mode();
+ if (m_command_socket.send(&cllient_type, sizeof(cllient_type)) <= 0) {
+ _E("Failed to send client type in client %s, command socket fd[%d]", get_client_name(), m_command_socket.get_socket_fd());
+ return false;
+ }
+
return true;
}
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <sensor_common.h>
+#include <command_common.h>
+#include <sensor_internal.h>
+#include <external_sensor_manager.h>
+#include <external_data_channel.h>
+#include <cmutex.h>
+
+using std::vector;
+using std::string;
+
+static cmutex lock;
+
+static void clean_up(void);
+static void restore_session(void);
+
+class initiator {
+public:
+ initiator()
+ {
+ external_sensor_manager::get_instance().set_hup_observer(restore_session);
+ }
+};
+
+static initiator g_initiator;
+
+void clean_up(void)
+{
+ vector<int> handles;
+
+ external_sensor_manager::get_instance().get_all_handles(handles);
+
+ auto it_handle = handles.begin();
+
+ while (it_handle != handles.end()) {
+ sensord_external_disconnect(*it_handle);
+ ++it_handle;
+ }
+}
+
+void restore_session(void)
+{
+ AUTOLOCK(lock);
+
+ _I("Trying to restore external source session for %s", get_client_name());
+
+ external_data_channel *data_channel;
+ int client_id;
+
+ external_sensor_manager::get_instance().close_data_channel();
+ external_sensor_manager::get_instance().set_client_id(CLIENT_ID_INVALID);
+
+ vector<int> handles;
+
+ external_sensor_manager::get_instance().get_all_handles(handles);
+
+ bool first_connection = true;
+
+ auto it_handle = handles.begin();
+
+ while (it_handle != handles.end()) {
+ data_channel = new(std::nothrow) external_data_channel();
+ retm_if(!data_channel, "Failed to allocate memory");
+
+ if (!data_channel->create_channel()) {
+ _E("%s failed to create data channel", get_client_name());
+ delete data_channel;
+ goto FAILED;
+ }
+
+ external_sensor_manager::get_instance().add_data_channel(*it_handle, data_channel);
+
+ if (first_connection) {
+ first_connection = false;
+ if (!data_channel->cmd_get_id(client_id)) {
+ _E("Failed to get client id");
+ goto FAILED;
+ }
+
+ external_sensor_manager::get_instance().set_client_id(client_id);
+ external_sensor_manager::get_instance().start_command_listener();
+ }
+
+ data_channel->set_client_id(client_id);
+
+ sensor_id_t dummy;
+ if (!data_channel->cmd_connect(external_sensor_manager::get_instance().get_key(*it_handle), dummy)) {
+ _E("Sending cmd_connect(%s) failed for %s", external_sensor_manager::get_instance().get_key(*it_handle).c_str(), get_client_name());
+ goto FAILED;
+ }
+
+ ++it_handle;
+ }
+
+ _I("Succeeded to restore external source session for %s", get_client_name());
+
+ return;
+
+FAILED:
+ external_sensor_manager::get_instance().clear();
+ _E("Failed to restore external source session for %s", get_client_name());
+}
+
+API int sensord_external_connect(const char *key, sensor_external_command_cb_t cb, void *user_data)
+{
+ external_data_channel *channel = NULL;
+ int handle;
+ int client_id;
+ bool first_connection = false;
+
+ retvm_if(!key, OP_ERROR, "client %s passes null key", get_client_name());
+
+ AUTOLOCK(lock);
+
+ handle = external_sensor_manager::get_instance().create_handle();
+
+ // lazy loading after creating static variables
+ atexit(clean_up);
+
+ if (handle == MAX_HANDLE) {
+ _E("Maximum number of handles reached, key %s in client %s", key, get_client_name());
+ return OP_ERROR;
+ }
+
+ channel = new(std::nothrow) external_data_channel();
+ if (!channel) {
+ _E("Failed to allocated memory");
+ external_sensor_manager::get_instance().delete_handle(handle);
+ return OP_ERROR;
+ }
+
+ if (!channel->create_channel()) {
+ _E("%s failed to create data channel for %s", get_client_name(), key);
+ external_sensor_manager::get_instance().delete_handle(handle);
+ delete channel;
+ return OP_ERROR;
+ }
+
+ external_sensor_manager::get_instance().add_data_channel(handle, channel);
+
+ if (!external_sensor_manager::get_instance().has_client_id()) {
+ first_connection = true;
+ if (!channel->cmd_get_id(client_id)) {
+ _E("Sending cmd_get_id() failed for %s", key);
+ external_sensor_manager::get_instance().close_data_channel(handle);
+ external_sensor_manager::get_instance().delete_handle(handle);
+ return OP_ERROR;
+ }
+
+ external_sensor_manager::get_instance().set_client_id(client_id);
+ _I("%s gets client_id [%d]", get_client_name(), client_id);
+ external_sensor_manager::get_instance().start_command_listener();
+ _I("%s starts listening command with client_id [%d]", get_client_name(), client_id);
+ }
+
+ client_id = external_sensor_manager::get_instance().get_client_id();
+ channel->set_client_id(client_id);
+
+ sensor_id_t sensor;
+
+ if (!channel->cmd_connect(key, sensor)) {
+ _E("Failed to connect %s for %s", key, get_client_name());
+ external_sensor_manager::get_instance().close_data_channel(handle);
+ external_sensor_manager::get_instance().delete_handle(handle);
+
+ if (first_connection) {
+ external_sensor_manager::get_instance().set_client_id(CLIENT_ID_INVALID);
+ external_sensor_manager::get_instance().stop_command_listener();
+ }
+
+ return OP_ERROR;
+ }
+
+ _I("%s[%d] connects with %s[%d]", get_client_name(), client_id, key, handle);
+
+ external_sensor_manager::get_instance().set_handle(handle, sensor, string(key), (void *)cb, user_data);
+
+ return handle;
+}
+
+API bool sensord_external_disconnect(int handle)
+{
+ external_data_channel *channel;
+
+ AUTOLOCK(lock);
+
+ retvm_if(!external_sensor_manager::get_instance().is_valid(handle), false, "Handle %d is not valid for %s",
+ handle, get_client_name());
+
+ if (!external_sensor_manager::get_instance().get_data_channel(handle, &channel)) {
+ _E("client %s failed to get data channel", get_client_name());
+ return false;
+ }
+
+ _I("%s disconnects with %s[%d]", get_client_name(), external_sensor_manager::get_instance().get_key(handle).c_str(), handle);
+
+ if (!external_sensor_manager::get_instance().delete_handle(handle))
+ return false;
+
+ if (!channel->cmd_disconnect()) {
+ _E("Sending cmd_disconnect() failed for %s", get_client_name());
+ return false;
+ }
+
+ external_sensor_manager::get_instance().close_data_channel(handle);
+
+ if (!external_sensor_manager::get_instance().is_active()) {
+ _I("Stop listening command for client %s with client id [%d]", get_client_name(), external_sensor_manager::get_instance().get_client_id());
+ external_sensor_manager::get_instance().set_client_id(CLIENT_ID_INVALID);
+ external_sensor_manager::get_instance().stop_command_listener();
+ }
+
+ return true;
+}
+
+API bool sensord_external_post(int handle, unsigned long long timestamp, const float* data, int data_cnt)
+{
+ external_data_channel *channel;
+
+ retvm_if(((data_cnt <= 0) || (data_cnt > POST_DATA_LEN_MAX)), false,
+ "data_cnt(%d) is invalid for %s", data_cnt, get_client_name());
+
+ AUTOLOCK(lock);
+
+ retvm_if(!external_sensor_manager::get_instance().is_valid(handle), false, "Handle %d is not valid for %s",
+ handle, get_client_name());
+
+ if (!external_sensor_manager::get_instance().get_data_channel(handle, &channel)) {
+ _E("client %s failed to get data channel", get_client_name());
+ return false;
+ }
+
+ if (!channel->cmd_post(timestamp, data, data_cnt)) {
+ _E("Failed to post data:%#x, data_cnt:%d", data, data_cnt);
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 <command_common.h>
+#include <sensor_types.h>
+#include <external_data_channel.h>
+
+using std::string;
+
+external_data_channel::external_data_channel()
+: m_client_id(CLIENT_ID_INVALID)
+, m_sensor_id(UNKNOWN_SENSOR)
+{
+}
+
+external_data_channel::~external_data_channel()
+{
+ m_socket.close();
+}
+
+bool external_data_channel::command_handler(cpacket *packet, void **return_payload)
+{
+ packet_header header;
+ char *buffer = NULL;
+
+ if (!m_socket.is_valid()) {
+ _E("Socket(%d) is not valid for client %s", m_socket.get_socket_fd(), get_client_name());
+ return false;
+ }
+
+ if (!packet->size()) {
+ _E("Packet is not valid for client %s", get_client_name());
+ return false;
+ }
+
+ if (m_socket.send(packet->packet(), packet->size()) <= 0) {
+ m_socket.close();
+ _E("Failed to send command in client %s", get_client_name());
+ return false;
+ }
+
+ if (m_socket.recv(&header, sizeof(header)) <= 0) {
+ m_socket.close();
+ _E("Failed to receive header for command packet in client %s", get_client_name());
+ return false;
+ }
+
+ buffer = new(std::nothrow) char[header.size];
+ retvm_if(!buffer, false, "Failed to allocate memory");
+
+ if (m_socket.recv(buffer, header.size) <= 0) {
+ m_socket.close();
+ _E("Failed to receive command packet in client %s", get_client_name());
+ delete[] buffer;
+ return false;
+ }
+
+ *return_payload = buffer;
+
+ return true;
+}
+
+bool external_data_channel::create_channel(void)
+{
+ const int client_type = CLIENT_TYPE_EXTERNAL_SOURCE;
+
+ if (!m_socket.create(SOCK_STREAM)) {
+ _E("Failed to create external data channel for client %s", get_client_name());
+ return false;
+ }
+
+ if (!m_socket.connect(COMMAND_CHANNEL_PATH)) {
+ _E("Failed to connect external data channel for client %s, command socket fd[%d]", get_client_name(), m_socket.get_socket_fd());
+ return false;
+ }
+
+ m_socket.set_connection_mode();
+
+ if (m_socket.send(&client_type, sizeof(client_type)) <= 0) {
+ _E("Failed to send client type in client %s, command socket fd[%d]", get_client_name(), m_socket.get_socket_fd());
+ return false;
+ }
+
+ return true;
+}
+
+void external_data_channel::set_client_id(int client_id)
+{
+ m_client_id = client_id;
+}
+
+bool external_data_channel::cmd_get_id(int &client_id)
+{
+ cpacket *packet;
+ cmd_ext_get_id_t *cmd_ext_get_id;
+ cmd_ext_get_id_done_t *cmd_ext_get_id_done;
+
+ packet = new(std::nothrow) cpacket(sizeof(cmd_ext_get_id_t));
+ retvm_if(!packet, false, "Failed to allocate memory");
+
+ packet->set_cmd(CMD_EXT_GET_ID);
+
+ cmd_ext_get_id = (cmd_ext_get_id_t *)packet->data();
+
+ get_proc_name(getpid(), cmd_ext_get_id->name);
+
+ _I("%s send cmd_get_id()", get_client_name());
+
+ if (!command_handler(packet, (void **)&cmd_ext_get_id_done)) {
+ _E("Client %s failed to send/receive command", get_client_name());
+ delete packet;
+ return false;
+ }
+
+ if (cmd_ext_get_id_done->client_id < 0) {
+ _E("Client %s failed to get client_id[%d] from server",
+ get_client_name(), cmd_ext_get_id_done->client_id);
+ delete[] (char *)cmd_ext_get_id_done;
+ delete packet;
+ return false;
+ }
+
+ client_id = cmd_ext_get_id_done->client_id;
+
+ delete[] (char *)cmd_ext_get_id_done;
+ delete packet;
+
+ return true;
+}
+
+bool external_data_channel::cmd_connect(const string &key, sensor_id_t &sensor_id)
+{
+ cpacket *packet;
+ cmd_ext_connect_t *cmd_ext_connect;
+ cmd_ext_connect_done_t *cmd_ext_connect_done;
+
+ int key_size = key.size();
+
+ if ((key_size == 0) || (key_size >= NAME_MAX)) {
+ _I("Key(%s) is not valid", key.c_str());
+ return false;
+ }
+
+ packet = new(std::nothrow) cpacket(sizeof(cmd_ext_connect_t));
+ retvm_if(!packet, false, "Failed to allocate memory");
+
+ packet->set_cmd(CMD_EXT_CONNECT);
+
+ cmd_ext_connect = (cmd_ext_connect_t *)packet->data();
+ cmd_ext_connect->client_id = m_client_id;
+ strncpy(cmd_ext_connect->key, key.c_str(), NAME_MAX-1);
+
+ _I("%s send cmd_get_connect(key = %s, client_id = %d)", get_client_name(), key.c_str(), m_client_id);
+
+ if (!command_handler(packet, (void **)&cmd_ext_connect_done)) {
+ _E("Client %s failed to send/receive command", get_client_name());
+ delete packet;
+ return false;
+ }
+
+ if (cmd_ext_connect_done->sensor_id == UNKNOWN_SENSOR) {
+ _E("Client %s failed to connect to external sensor", get_client_name());
+ delete[] (char *)cmd_ext_connect_done;
+ delete packet;
+ return false;
+ }
+
+ m_sensor_id = sensor_id = cmd_ext_connect_done->sensor_id;
+
+ delete[] (char *)cmd_ext_connect_done;
+ delete packet;
+
+ return true;
+}
+
+bool external_data_channel::cmd_disconnect(void)
+{
+ cpacket *packet;
+ cmd_ext_done_t *cmd_ext_done;
+
+ packet = new(std::nothrow) cpacket(sizeof(cmd_ext_disconnect_t));
+ retvm_if(!packet, false, "Failed to allocate memory");
+
+ packet->set_cmd(CMD_EXT_DISCONNECT);
+
+ _I("%s send cmd_disconnect(client_id=%d)", get_client_name(), m_client_id);
+
+ if (!command_handler(packet, (void **)&cmd_ext_done)) {
+ _E("Client %s failed to send/receive command with client_id [%d]",
+ get_client_name(), m_client_id);
+ delete packet;
+ return false;
+ }
+
+ if (cmd_ext_done->value < 0) {
+ _E("Client %s got error[%d] from server with client_id [%d]",
+ get_client_name(), cmd_ext_done->value, m_client_id);
+
+ delete[] (char *)cmd_ext_done;
+ delete packet;
+ return false;
+ }
+
+ delete[] (char *)cmd_ext_done;
+ delete packet;
+
+ m_socket.close();
+ m_client_id = CLIENT_ID_INVALID;
+ return true;
+}
+
+bool external_data_channel::cmd_post(unsigned long long timestamp, const float *data, int data_cnt)
+{
+ cpacket *packet;
+ cmd_ext_post_t *cmd_ext_post;
+ cmd_done_t *cmd_done;
+
+ packet = new(std::nothrow) cpacket(sizeof(cmd_ext_post_t) + sizeof(float) * data_cnt);
+ retvm_if(!packet, false, "Failed to allocate memory");
+
+ packet->set_cmd(CMD_EXT_POST);
+
+ cmd_ext_post = (cmd_ext_post_t*)packet->data();
+ cmd_ext_post->timestamp = timestamp;
+ cmd_ext_post->data_cnt = data_cnt;
+ memcpy(cmd_ext_post->data, data, sizeof(float) * data_cnt);
+
+ _I("%s send cmd_post(client_id=%d, data = %#x, data_cnt = %d)",
+ get_client_name(), m_client_id, data, data_cnt);
+
+ if (!command_handler(packet, (void **)&cmd_done)) {
+ _E("%s failed to send/receive command with client_id [%d]",
+ get_client_name(), m_client_id);
+ delete packet;
+ return false;
+ }
+
+ if (cmd_done->value < 0) {
+ _E("%s got error[%d] from server with client_id [%d]",
+ get_client_name(), cmd_done->value, m_client_id);
+
+ delete[] (char *)cmd_done;
+ delete packet;
+ return false;
+ }
+
+ delete[] (char *)cmd_done;
+ delete packet;
+
+ return true;
+}
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 _EXTERNAL_DATA_CHANNEL_H_
+#define _EXTERNAL_DATA_CHANNEL_H_
+
+#include <string>
+#include <csocket.h>
+
+class cpacket;
+
+class external_data_channel {
+public:
+ external_data_channel();
+ ~external_data_channel();
+
+ bool create_channel(void);
+ void set_client_id(int client_id);
+ bool cmd_get_id(int &client_id);
+ bool cmd_connect(const std::string &key, sensor_id_t &sensor_id);
+ bool cmd_disconnect(void);
+ bool cmd_post(unsigned long long timestamp, const float *data, int data_cnt);
+private:
+ csocket m_socket;
+ int m_client_id;
+ sensor_id_t m_sensor_id;
+ bool command_handler(cpacket *packet, void **return_payload);
+};
+
+#endif /* _EXTERNAL_DATA_CHANNEL_H_ */
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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_common.h>
+#include <command_common.h>
+#include <external_sensor_manager.h>
+#include <external_data_channel.h>
+#include <poller.h>
+#include <thread>
+
+using std::pair;
+using std::vector;
+using std::thread;
+using std::string;
+
+external_sensor_manager::external_sensor_manager()
+: m_client_id(CLIENT_ID_INVALID)
+, m_poller(NULL)
+, m_thread_state(THREAD_STATE_TERMINATE)
+, m_hup_observer(NULL)
+{
+}
+
+external_sensor_manager::~external_sensor_manager()
+{
+ stop_command_listener();
+}
+
+external_sensor_manager& external_sensor_manager::get_instance(void)
+{
+ static external_sensor_manager inst;
+ return inst;
+}
+
+int external_sensor_manager::create_handle(void)
+{
+ sensor_ext_handle_info handle_info;
+ int handle = 0;
+
+ AUTOLOCK(m_handle_info_lock);
+
+ while (m_sensor_handle_infos.count(handle) > 0)
+ handle++;
+
+ if (handle >= MAX_HANDLE) {
+ _E("Handles of client %s are full", get_client_name());
+ return MAX_HANDLE_REACHED;
+ }
+
+ handle_info.m_handle = handle;
+ handle_info.m_sensor = UNKNOWN_SENSOR;
+ handle_info.m_cb = NULL;
+ handle_info.m_user_data = NULL;
+
+ m_sensor_handle_infos.insert(pair<int, sensor_ext_handle_info>(handle, handle_info));
+
+ return handle;
+}
+
+bool external_sensor_manager::delete_handle(int handle)
+{
+ AUTOLOCK(m_handle_info_lock);
+
+ auto it_handle = m_sensor_handle_infos.find(handle);
+
+ if (it_handle == m_sensor_handle_infos.end()) {
+ _E("Handle[%d] is not found for client %s", handle, get_client_name());
+ return false;
+ }
+
+ m_sensor_handle_map.erase(it_handle->second.m_sensor);
+ m_sensor_handle_infos.erase(it_handle);
+
+ return true;
+}
+
+bool external_sensor_manager::set_handle(int handle, sensor_id_t sensor, const string& key, void* cb, void* user_data)
+{
+ AUTOLOCK(m_handle_info_lock);
+
+ auto it_handle = m_sensor_handle_infos.find(handle);
+
+ if (it_handle == m_sensor_handle_infos.end()) {
+ _E("Handle[%d] is not found for client %s", handle, get_client_name());
+ return false;
+ }
+
+ it_handle->second.m_sensor = sensor;
+ it_handle->second.m_key = key;
+ it_handle->second.m_cb = cb;
+ it_handle->second.m_user_data = user_data;
+
+ m_sensor_handle_map.insert(pair<sensor_id_t, int>(sensor, handle));
+
+ return true;
+}
+
+bool external_sensor_manager::get_sensor(int handle, sensor_id_t &sensor)
+{
+ AUTOLOCK(m_handle_info_lock);
+
+ auto it_handle = m_sensor_handle_infos.find(handle);
+
+ if (it_handle == m_sensor_handle_infos.end()) {
+ _E("Handle[%d] is not found for client %s", handle, get_client_name());
+ return false;
+ }
+
+ sensor = it_handle->second.m_sensor;
+
+ return true;
+}
+
+int external_sensor_manager::get_handle(sensor_id_t sensor)
+{
+ AUTOLOCK(m_handle_info_lock);
+
+ auto it_handle = m_sensor_handle_map.find(sensor);
+
+ if (it_handle == m_sensor_handle_map.end()) {
+ _E("Handle is not found for client %s with sensor: %d", get_client_name(), sensor);
+ return -1;
+ }
+
+ return it_handle->second;
+}
+
+bool external_sensor_manager::get_handle_info(int handle, const sensor_ext_handle_info*& handle_info)
+{
+ AUTOLOCK(m_handle_info_lock);
+
+ auto it_handle = m_sensor_handle_infos.find(handle);
+
+ if (it_handle == m_sensor_handle_infos.end()) {
+ _E("Handle[%d] is not found for client %s", handle, get_client_name());
+ return false;
+ }
+
+ handle_info = &(it_handle->second);
+ return true;
+}
+
+string external_sensor_manager::get_key(int handle)
+{
+ AUTOLOCK(m_handle_info_lock);
+
+ auto it_handle = m_sensor_handle_infos.find(handle);
+
+ if (it_handle == m_sensor_handle_infos.end()) {
+ return string("INVALID_KEY");
+ }
+
+ return it_handle->second.m_key;
+}
+
+bool external_sensor_manager::has_client_id(void)
+{
+ return (m_client_id != CLIENT_ID_INVALID);
+}
+
+int external_sensor_manager::get_client_id(void)
+{
+ return m_client_id;
+}
+
+void external_sensor_manager::set_client_id(int client_id)
+{
+ m_client_id = client_id;
+}
+
+bool external_sensor_manager::add_data_channel(int handle, external_data_channel *channel)
+{
+ auto it_channel = m_data_channels.find(handle);
+
+ if (it_channel != m_data_channels.end()) {
+ _E("%s alreay has data_channel for %s", get_client_name(), get_key(handle).c_str());
+ return false;
+ }
+
+ m_data_channels.insert(pair<int, external_data_channel *>(handle, channel));
+ return true;
+}
+
+bool external_sensor_manager::get_data_channel(int handle, external_data_channel **channel)
+{
+ auto it_channel = m_data_channels.find(handle);
+
+ if (it_channel == m_data_channels.end()) {
+ _E("%s doesn't have data_channel for %s", get_client_name(), get_key(handle).c_str());
+ return false;
+ }
+
+ *channel = it_channel->second;
+
+ return true;
+}
+
+bool external_sensor_manager::close_data_channel(void)
+{
+ auto it_channel = m_data_channels.begin();
+
+ if (it_channel != m_data_channels.end()) {
+ delete it_channel->second;
+ ++it_channel;
+ }
+
+ m_data_channels.clear();
+
+ return true;
+}
+
+bool external_sensor_manager::close_data_channel(int handle)
+{
+ auto it_channel = m_data_channels.find(handle);
+
+ if (it_channel == m_data_channels.end()) {
+ _E("%s doesn't have data_channel for %s", get_client_name(), get_key(handle).c_str());
+ return false;
+ }
+
+ delete it_channel->second;
+
+ m_data_channels.erase(it_channel);
+
+ return true;
+}
+
+bool external_sensor_manager::is_valid(int handle)
+{
+ AUTOLOCK(m_handle_info_lock);
+
+ auto it_handle = m_sensor_handle_infos.find(handle);
+
+ if (it_handle == m_sensor_handle_infos.end())
+ return false;
+
+ return true;
+}
+
+bool external_sensor_manager::is_active(void)
+{
+ AUTOLOCK(m_handle_info_lock);
+
+ return !m_sensor_handle_infos.empty();
+}
+
+void external_sensor_manager::get_all_handles(vector<int> &handles)
+{
+ AUTOLOCK(m_handle_info_lock);
+
+ auto it_handle = m_sensor_handle_infos.begin();
+
+ while (it_handle != m_sensor_handle_infos.end()) {
+ handles.push_back(it_handle->first);
+ ++it_handle;
+ }
+}
+
+bool external_sensor_manager::create_command_channel(void)
+{
+ const int client_type = CLIENT_TYPE_EXTERNAL_SOURCE;
+ int client_id;
+ channel_ready_t channel_ready;
+
+ if (!m_command_socket.create(SOCK_SEQPACKET))
+ return false;
+
+ if (!m_command_socket.connect(EVENT_CHANNEL_PATH)) {
+ _E("Failed to connect command channel for client %s, command socket fd[%d]", get_client_name(), m_command_socket.get_socket_fd());
+ return false;
+ }
+
+ m_command_socket.set_connection_mode();
+
+ if (m_command_socket.send(&client_type, sizeof(client_type)) <= 0) {
+ _E("Failed to send client type in client %s, event socket fd[%d]", get_client_name(), m_command_socket.get_socket_fd());
+ return false;
+ }
+
+ client_id = get_client_id();
+
+ if (m_command_socket.send(&client_id, sizeof(client_id)) <= 0) {
+ _E("Failed to send client id for client %s on command socket[%d]", get_client_name(), m_command_socket.get_socket_fd());
+ return false;
+ }
+
+ if (m_command_socket.recv(&channel_ready, sizeof(channel_ready)) <= 0) {
+ _E("%s failed to recv command channel ready packet on command socket[%d] with client id [%d]",
+ get_client_name(), m_command_socket.get_socket_fd(), client_id);
+ return false;
+ }
+
+ if ((channel_ready.magic != CHANNEL_MAGIC_NUM) || (channel_ready.client_id != client_id)) {
+ _E("Command channel ready packet is wrong, magic = %#x, client id = %d",
+ channel_ready.magic, channel_ready.client_id);
+ return false;
+ }
+
+ _I("Command channel is established for client %s on socket[%d] with client id : %d",
+ get_client_name(), m_command_socket.get_socket_fd(), client_id);
+
+ return true;
+}
+
+void external_sensor_manager::close_command_channel(void)
+{
+ m_command_socket.close();
+}
+
+bool external_sensor_manager::start_command_listener(void)
+{
+ if (!create_command_channel()) {
+ _E("Command channel is not established for %s", get_client_name());
+ return false;
+ }
+
+ m_command_socket.set_transfer_mode();
+
+ m_poller = new(std::nothrow) poller(m_command_socket.get_socket_fd());
+ retvm_if(!m_poller, false, "Failed to allocate memory");
+
+ set_thread_state(THREAD_STATE_START);
+
+ thread listener(&external_sensor_manager::listen_command, this);
+ listener.detach();
+
+ return true;
+}
+
+void external_sensor_manager::stop_command_listener(void)
+{
+ const int THREAD_TERMINATING_TIMEOUT = 2;
+
+ ulock u(m_thread_mutex);
+
+ if (m_thread_state != THREAD_STATE_TERMINATE) {
+ m_thread_state = THREAD_STATE_STOP;
+
+ _D("%s is waiting listener thread[state: %d] to be terminated", get_client_name(), m_thread_state);
+ if (m_thread_cond.wait_for(u, std::chrono::seconds(THREAD_TERMINATING_TIMEOUT))
+ == std::cv_status::timeout)
+ _E("Fail to stop listener thread after waiting %d seconds", THREAD_TERMINATING_TIMEOUT);
+ else
+ _D("Listener thread for %s is terminated", get_client_name());
+ }
+}
+
+void external_sensor_manager::set_thread_state(thread_state state)
+{
+ lock l(m_thread_mutex);
+ m_thread_state = state;
+}
+
+bool external_sensor_manager::get_cb_info(sensor_id_t sensor, char* data, int data_cnt, command_cb_info &cb_info)
+{
+ int handle;
+ const sensor_ext_handle_info *handle_info;
+
+ AUTOLOCK(m_handle_info_lock);
+
+ handle = get_handle(sensor);
+
+ if (handle < 0)
+ return false;
+
+ get_handle_info(handle, handle_info);
+
+ cb_info.handle = handle_info->m_handle;
+ cb_info.sensor = handle_info->m_sensor;
+ cb_info.cb = handle_info->m_cb;
+ cb_info.data = data;
+ cb_info.data_cnt = data_cnt;
+ cb_info.user_data = handle_info->m_user_data;
+
+ return true;
+}
+
+bool external_sensor_manager::sensor_command_poll(void* buffer, int buffer_len, struct epoll_event &event)
+{
+ ssize_t len;
+
+ len = m_command_socket.recv(buffer, buffer_len);
+
+ if (!len) {
+ if (!m_poller->poll(event))
+ return false;
+ len = m_command_socket.recv(buffer, buffer_len);
+
+ if (len <= 0) {
+ _I("%s failed to read after poll!", get_client_name());
+ return false;
+ }
+ } else if (len < 0) {
+ _I("%s failed to recv command from command socket", get_client_name());
+ return false;
+ }
+
+ return true;
+}
+
+void external_sensor_manager::post_callback_to_main_loop(command_cb_info* cb_info)
+{
+ g_idle_add_full(G_PRIORITY_DEFAULT, callback_dispatcher, cb_info, NULL);
+}
+
+void external_sensor_manager::handle_command(sensor_id_t sensor, char* data, int data_cnt)
+{
+ command_cb_info *cb_info = NULL;
+
+ { /* scope for the lock */
+ AUTOLOCK(m_handle_info_lock);
+
+ cb_info = new(std::nothrow) command_cb_info;
+ if (!cb_info) {
+ _E("Failed to allocate memory");
+ delete[] data;
+ }
+
+ if (!get_cb_info(sensor, data, data_cnt, *cb_info)) {
+ delete[] data;
+ delete cb_info;
+ _E("Sensor %d is not connected, so command is discarded", sensor);
+ return;
+ }
+ }
+
+ if (cb_info)
+ post_callback_to_main_loop(cb_info);
+}
+
+void external_sensor_manager::listen_command(void)
+{
+ external_command_header_t command_header;
+ struct epoll_event event;
+ event.events = EPOLLIN | EPOLLPRI;
+
+ do {
+ lock l(m_thread_mutex);
+ if (m_thread_state == THREAD_STATE_START) {
+ if (!sensor_command_poll(&command_header, sizeof(command_header), event)) {
+ _I("Failed to poll command header");
+ break;
+ }
+
+ char *command = new(std::nothrow) char[command_header.command_len];
+ if (!command) {
+ _E("Failed to allocated memory");
+ break;
+ }
+
+ if (!sensor_command_poll(command, command_header.command_len, event)) {
+ _I("Failed to poll command data");
+ delete []command;
+ break;
+ }
+
+ handle_command(command_header.sensor_id, command, command_header.command_len);
+ } else {
+ break;
+ }
+ } while (true);
+
+ if (m_poller != NULL) {
+ delete m_poller;
+ m_poller = NULL;
+ }
+
+ close_command_channel();
+
+ { /* the scope for the lock */
+ lock l(m_thread_mutex);
+ m_thread_state = THREAD_STATE_TERMINATE;
+ m_thread_cond.notify_one();
+ }
+
+ _I("Command listener thread is terminated.");
+
+ if (has_client_id() && (event.events & EPOLLHUP)) {
+ if (m_hup_observer)
+ m_hup_observer();
+ }
+}
+
+bool external_sensor_manager::is_valid_callback(const command_cb_info *cb_info)
+{
+ sensor_id_t sensor;
+
+ if (!external_sensor_manager::get_instance().get_sensor(cb_info->handle, sensor))
+ return false;
+
+ return (cb_info->sensor == sensor);
+}
+
+gboolean external_sensor_manager::callback_dispatcher(gpointer data)
+{
+ const command_cb_info *cb_info = reinterpret_cast<const command_cb_info*>(data);
+
+ if (external_sensor_manager::get_instance().is_valid_callback(cb_info)) {
+ reinterpret_cast<sensor_external_command_cb_t>(cb_info->cb)(cb_info->handle, cb_info->data, cb_info->data_cnt, cb_info->user_data);
+ } else {
+ _W("Discard invalid callback cb(%#x)(%d, %#x, %d, %#x)",
+ cb_info->cb, cb_info->handle, cb_info->data, cb_info->data_cnt, cb_info->user_data);
+ }
+
+ delete[] cb_info->data;
+ delete cb_info;
+
+/*
+* To be called only once, it returns false
+*/
+ return false;
+}
+
+void external_sensor_manager::clear(void)
+{
+ close_command_channel();
+ stop_command_listener();
+ close_data_channel();
+ m_sensor_handle_infos.clear();
+ set_client_id(CLIENT_ID_INVALID);
+}
+
+void external_sensor_manager::set_hup_observer(hup_observer_t observer)
+{
+ m_hup_observer = observer;
+}
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 _EXTERNAL_SENSOR_MANAGER_H_
+#define _EXTERNAL_SENSOR_MANAGER_H_
+
+#include <glib.h>
+#include <sys/epoll.h>
+#include <sensor_common.h>
+#include <csocket.h>
+#include <cmutex.h>
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <mutex>
+#include <condition_variable>
+
+class external_data_channel;
+class poller;
+
+class sensor_ext_handle_info {
+public:
+ int m_handle;
+ sensor_id_t m_sensor;
+ std::string m_key;
+ void *m_cb;
+ void *m_user_data;
+};
+
+typedef struct {
+ int handle;
+ sensor_id_t sensor;
+ char *data;
+ int data_cnt;
+ void *cb;
+ void *user_data;
+} command_cb_info;
+
+class external_sensor_manager {
+public:
+ typedef void (*hup_observer_t)(void);
+
+ static external_sensor_manager& get_instance(void);
+ int create_handle(void);
+ bool delete_handle(int handle);
+
+ bool set_handle(int handle, sensor_id_t sensor, const std::string& key, void* cb, void* user_data);
+
+ bool get_sensor(int handle, sensor_id_t &sensor_id);
+ int get_handle(sensor_id_t sensor);
+ bool get_handle_info(int handle, const sensor_ext_handle_info*& handle_info);
+ std::string get_key(int handle);
+
+ bool has_client_id(void);
+ int get_client_id(void);
+ void set_client_id(int client_id);
+
+ bool add_data_channel(int handle, external_data_channel *channel);
+ bool get_data_channel(int handle, external_data_channel **channel);
+ bool close_data_channel(void);
+ bool close_data_channel(int handle);
+
+ bool is_valid(int handle);
+ bool is_active(void);
+
+ void get_all_handles(std::vector<int> &handles);
+
+ bool start_command_listener(void);
+ void stop_command_listener(void);
+ void clear(void);
+
+ void set_hup_observer(hup_observer_t observer);
+private:
+ enum thread_state {
+ THREAD_STATE_START,
+ THREAD_STATE_STOP,
+ THREAD_STATE_TERMINATE,
+ };
+
+ typedef std::lock_guard<std::mutex> lock;
+ typedef std::unique_lock<std::mutex> ulock;
+
+ external_sensor_manager();
+ ~external_sensor_manager();
+
+ external_sensor_manager(const external_sensor_manager&) {};
+ external_sensor_manager& operator=(const external_sensor_manager&);
+
+ bool create_command_channel(void);
+ void close_command_channel(void);
+ void set_thread_state(thread_state state);
+
+ bool sensor_command_poll(void* buffer, int buffer_len, struct epoll_event &event);
+
+ bool get_cb_info(sensor_id_t sensor, char* data, int data_cnt, command_cb_info &cb_info);
+ void post_callback_to_main_loop(command_cb_info* cb_info);
+ void handle_command(sensor_id_t sensor, char* data, int data_cnt);
+ void listen_command(void);
+
+ bool is_valid_callback(const command_cb_info *cb_info);
+ static gboolean callback_dispatcher(gpointer data);
+
+ int m_client_id;
+
+ csocket m_command_socket;
+ poller *m_poller;
+
+ cmutex m_handle_info_lock;
+
+ thread_state m_thread_state;
+ std::mutex m_thread_mutex;
+ std::condition_variable m_thread_cond;
+
+ hup_observer_t m_hup_observer;
+
+ std::unordered_map<int, sensor_ext_handle_info> m_sensor_handle_infos;
+ std::unordered_map<sensor_id_t, int> m_sensor_handle_map;
+ std::unordered_map<int, external_data_channel*> m_data_channels;
+};
+#endif /* _EXTERNAL_SENSOR_MANAGER_H_ */
bool sensor_event_listener::create_event_channel(void)
{
+ const int client_type = CLIENT_TYPE_SENSOR_CLIENT;
int client_id;
channel_ready_t event_channel_ready;
return false;
}
+ if (m_event_socket.send(&client_type, sizeof(client_type)) <= 0) {
+ _E("Failed to send client type in client %s, event socket fd[%d]", get_client_name(), m_event_socket.get_socket_fd());
+ return false;
+ }
+
client_id = m_client_info.get_client_id();
if (m_event_socket.send(&client_id, sizeof(client_id)) <= 0) {
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <sensor_log.h>
+#include <command_queue.h>
+
+command_queue& command_queue::get_instance(void)
+{
+ static command_queue inst;
+ return inst;
+}
+
+void command_queue::push(std::shared_ptr<external_command_t> &command)
+{
+ lock l(m_mutex);
+
+ bool wake = m_queue.empty();
+
+ if (m_queue.size() >= QUEUE_FULL_SIZE) {
+ _E("Queue is full, drop it!");
+ } else {
+ m_queue.push(command);
+ }
+
+ if (wake)
+ m_cond_var.notify_one();
+}
+
+std::shared_ptr<external_command_t> command_queue::pop(void)
+{
+ ulock u(m_mutex);
+
+ while (m_queue.empty())
+ m_cond_var.wait(u);
+
+ std::shared_ptr<external_command_t> command = m_queue.front();
+ m_queue.pop();
+ return command;
+}
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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_QUEUE_H_
+#define _COMMAND_QUEUE_H_
+
+#include <command_common.h>
+#include <queue>
+#include <mutex>
+#include <condition_variable>
+#include <memory>
+
+class command_queue {
+private:
+ command_queue() {};
+ ~command_queue() {};
+ command_queue(const command_queue&) {};
+ command_queue& operator=(const command_queue&);
+
+ static const unsigned int QUEUE_FULL_SIZE = 1000;
+
+ std::queue<std::shared_ptr<external_command_t>> m_queue;
+ std::mutex m_mutex;
+ std::condition_variable m_cond_var;
+
+ typedef std::lock_guard<std::mutex> lock;
+ typedef std::unique_lock<std::mutex> ulock;
+public:
+ static command_queue& get_instance();
+ void push(std::shared_ptr<external_command_t> &command);
+ std::shared_ptr<external_command_t> pop(void);
+};
+
+#endif
--- /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.
+ *
+ */
+
+#include <sensor_log.h>
+#include <dbus_util.h>
+#include <gio/gio.h>
+
+static int wrist_up_total_cnt;
+static int wrist_up_lcdon_cnt;
+
+static GDBusNodeInfo *introspection_data = NULL;
+static guint owner_id;
+
+static const gchar introspection_xml[] =
+"<node>"
+" <interface name='org.tizen.system.sensord'>"
+" <method name='check_privilege'>"
+" <arg type='i' name='response' direction='out'/>"
+" </method>"
+" <method name='wristup_lcdon_cnt'>"
+" <arg type='i' name='response' direction='out'/>"
+" </method>"
+" <method name='wristup_total_cnt'>"
+" <arg type='i' name='response' direction='out'/>"
+" </method>"
+" </interface>"
+"</node>";
+
+static void method_call_handler(GDBusConnection *conn,
+ const gchar *sender, const gchar *object_path,
+ const gchar *iface_name, const gchar *method_name,
+ GVariant *parameters, GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = DBUS_INIT;
+
+ if (g_strcmp0(method_name, "check_privilege") == 0) {
+ _D("check_privilege called");
+ ret = DBUS_SUCCESS;
+ } else if (g_strcmp0(method_name, "wristup_lcdon_cnt") == 0) {
+ _D("wristup_lcdon_cnt called, %d", wrist_up_lcdon_cnt);
+ ret = wrist_up_lcdon_cnt;
+ } else if (g_strcmp0(method_name, "wristup_total_cnt") == 0) {
+ _D("wristup_total_cnt called, %d", wrist_up_total_cnt);
+ ret = wrist_up_total_cnt;
+ } else {
+ _D("No matched method call");
+ ret = DBUS_FAILED;
+ }
+
+ g_dbus_method_invocation_return_value(invocation,
+ g_variant_new("(i)", ret));
+}
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+ method_call_handler,
+ NULL,
+ NULL
+};
+
+static void on_bus_acquired(GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ guint registration_id;
+
+ if (!connection) {
+ _E("connection is null");
+ return;
+ }
+
+ registration_id = g_dbus_connection_register_object(connection,
+ SENSORD_OBJECT_PATH,
+ introspection_data->interfaces[0],
+ &interface_vtable,
+ NULL, /* user_data */
+ NULL, /* user_data_free_func */
+ NULL); /* GError** */
+
+ if (registration_id == 0)
+ _E("Failed to g_dbus_connection_register_object");
+
+ _I("Gdbus method call registrated");
+}
+
+static void on_name_acquired(GDBusConnection *conn,
+ const gchar *name, gpointer user_data)
+{
+}
+
+static void on_name_lost(GDBusConnection *conn,
+ const gchar *name, gpointer user_data)
+{
+ _E("Dbus name is lost!");
+}
+
+int get_lcdon_count(void)
+{
+ return wrist_up_lcdon_cnt;
+}
+
+void increase_lcdon_count(void)
+{
+ wrist_up_lcdon_cnt++;
+}
+
+void reset_lcdon_count(void)
+{
+ wrist_up_lcdon_cnt = 0;
+}
+
+int get_total_count(void)
+{
+ return wrist_up_total_cnt;
+}
+
+void increase_total_count(void)
+{
+ wrist_up_total_cnt++;
+}
+
+void reset_total_count(void)
+{
+ wrist_up_total_cnt = 0;
+}
+
+void init_dbus(void)
+{
+ g_type_init();
+
+ introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, NULL);
+ if (introspection_data == NULL) {
+ _E("Failed to init g_dbus_node_info_new_for_xml");
+ return;
+ }
+
+ owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+ SENSORD_BUS_NAME,
+ (GBusNameOwnerFlags) (G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT
+ | G_BUS_NAME_OWNER_FLAGS_REPLACE),
+ on_bus_acquired,
+ on_name_acquired,
+ on_name_lost,
+ NULL,
+ NULL);
+ wrist_up_total_cnt = 0;
+ wrist_up_lcdon_cnt = 0;
+}
+
+void fini_dbus(void)
+{
+ if (owner_id != 0)
+ g_bus_unown_name(owner_id);
+
+ if (introspection_data)
+ g_dbus_node_info_unref(introspection_data);
+}
--- /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 _DBUS_UTIL_H_
+#define _DBUS_UTIL_H_
+
+#define SENSORD_BUS_NAME "org.tizen.system.sensord"
+#define SENSORD_OBJECT_PATH "/Org/Tizen/System/SensorD"
+#define SENSORD_INTERFACE_NAME SENSORD_BUS_NAME
+
+enum dbus_ret {
+ DBUS_INIT = -1,
+ DBUS_FAILED = 0,
+ DBUS_SUCCESS = 1
+};
+
+int get_lcdon_count(void);
+void increase_lcdon_count(void);
+void reset_lcdon_count(void);
+
+int get_total_count(void);
+void increase_total_count(void);
+void reset_total_count(void);
+
+void init_dbus(void);
+void fini_dbus(void);
+
+#endif /* SENSORD_GDBUS_H_ */
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 <command_common.h>
+#include <external_client_manager.h>
+#include <sensor_common.h>
+
+using std::shared_ptr;
+using std::make_shared;
+using std::pair;
+using std::string;
+
+external_client_manager::external_client_manager()
+{
+}
+external_client_manager::~external_client_manager()
+{
+}
+
+external_client_manager& external_client_manager::get_instance(void)
+{
+ static external_client_manager instance;
+ return instance;
+}
+
+int external_client_manager::create_client_record(void)
+{
+ AUTOLOCK(m_mutex);
+
+ int client_id = 0;
+
+ shared_ptr<external_sensor_record> client_record = make_shared<external_sensor_record>();
+
+ while (m_clients.count(client_id) > 0)
+ client_id++;
+
+ if (client_id == MAX_HANDLE) {
+ _E("Sensor records of clients are full");
+ return MAX_HANDLE_REACHED;
+ }
+
+ client_record->set_client_id(client_id);
+
+ m_clients.insert(pair<int, shared_ptr<external_sensor_record>>(client_id, client_record));
+
+ return client_id;
+}
+
+bool external_client_manager::remove_client_record(int client_id)
+{
+ AUTOLOCK(m_mutex);
+
+ if (!m_clients.erase(client_id)) {
+ _E("Client[%d] is not found", client_id);
+ return false;
+ }
+
+ _I("Client record for client[%d] is removed from external client manager", client_id);
+ return true;
+}
+
+bool external_client_manager::has_client_record(int client_id)
+{
+ AUTOLOCK(m_mutex);
+
+ auto it_record = m_clients.find(client_id);
+
+ return (it_record != m_clients.end());
+}
+
+void external_client_manager::set_client_info(int client_id, pid_t pid, const string &name)
+{
+ AUTOLOCK(m_mutex);
+
+ auto it_record = m_clients.find(client_id);
+
+ if (it_record == m_clients.end()) {
+ _E("Client[%d] is not found", client_id);
+ return;
+ }
+
+ it_record->second->set_client_info(pid, name);
+
+ return;
+}
+
+const char* external_client_manager::get_client_info(int client_id)
+{
+ AUTOLOCK(m_mutex);
+
+ auto it_record = m_clients.find(client_id);
+
+ if (it_record == m_clients.end()) {
+ _D("Client[%d] is not found", client_id);
+ return NULL;
+ }
+
+ return it_record->second->get_client_info();
+}
+
+bool external_client_manager::create_sensor_record(int client_id, sensor_id_t sensor)
+{
+ AUTOLOCK(m_mutex);
+
+ auto it_record = m_clients.find(client_id);
+
+ if (it_record == m_clients.end()) {
+ _E("Client record[%d] is not registered", client_id);
+ return false;
+ }
+
+ return it_record->second->add_usage(sensor);
+}
+
+bool external_client_manager::remove_sensor_record(int client_id, sensor_id_t sensor)
+{
+ AUTOLOCK(m_mutex);
+
+ auto it_record = m_clients.find(client_id);
+
+ if (it_record == m_clients.end()) {
+ _E("Client[%d] is not found", client_id);
+ return false;
+ }
+
+ if (!it_record->second->remove_usage(sensor))
+ return false;
+
+ if (!it_record->second->has_usage())
+ remove_client_record(client_id);
+
+ return true;
+}
+
+bool external_client_manager::has_sensor_record(int client_id, sensor_id_t sensor)
+{
+ AUTOLOCK(m_mutex);
+
+ auto it_record = m_clients.find(client_id);
+
+ if (it_record == m_clients.end()) {
+ _D("Client[%d] is not found", client_id);
+ return false;
+ }
+
+ return it_record->second->has_usage(sensor);
+}
+
+bool external_client_manager::has_sensor_record(int client_id)
+{
+ AUTOLOCK(m_mutex);
+
+ auto it_record = m_clients.find(client_id);
+
+ if (it_record == m_clients.end()) {
+ _D("Client[%d] is not found", client_id);
+ return false;
+ }
+
+ return it_record->second->has_usage();
+}
+
+bool external_client_manager::get_listener_socket(sensor_id_t sensor, csocket &sock)
+{
+ AUTOLOCK(m_mutex);
+
+ auto it_record = m_clients.begin();
+
+ while (it_record != m_clients.end()) {
+ if (it_record->second->has_usage(sensor)) {
+ it_record->second->get_command_socket(sock);
+ return true;
+ }
+
+ ++it_record;
+ }
+
+ return false;
+}
+
+bool external_client_manager::get_command_socket(int client_id, csocket &socket)
+{
+ AUTOLOCK(m_mutex);
+
+ auto it_record = m_clients.find(client_id);
+
+ if (it_record == m_clients.end()) {
+ _E("Client[%d] is not found", client_id);
+ return false;
+ }
+
+ it_record->second->get_command_socket(socket);
+
+ return true;
+}
+
+bool external_client_manager::set_command_socket(int client_id, const csocket &socket)
+{
+ AUTOLOCK(m_mutex);
+
+ auto it_record = m_clients.find(client_id);
+
+ if (it_record == m_clients.end()) {
+ _E("Client[%d] is not found", client_id);
+ return false;
+ }
+
+ it_record->second->set_command_socket(socket);
+
+ return true;
+}
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 _EXTERNAL_CLIENT_MANAGER_H_
+#define _EXTERNAL_CLIENT_MANAGER_H_
+
+#include <external_sensor_record.h>
+#include <cmutex.h>
+#include <unordered_map>
+#include <memory>
+
+class external_client_manager {
+public:
+ static external_client_manager& get_instance(void);
+ int create_client_record(void);
+ bool remove_client_record(int client_id);
+ bool has_client_record(int client_id);
+
+ void set_client_info(int client_id, pid_t pid, const std::string &name);
+ const char* get_client_info(int client_id);
+
+ bool create_sensor_record(int client_id, sensor_id_t sensor);
+ bool remove_sensor_record(int client_id, sensor_id_t sensor);
+ bool has_sensor_record(int client_id, sensor_id_t sensor);
+ bool has_sensor_record(int client_id);
+
+ bool get_listener_socket(sensor_id_t sensor, csocket &sock);
+ bool get_command_socket(int client_id, csocket &sock);
+ bool set_command_socket(int client_id, const csocket &sock);
+private:
+ external_client_manager();
+ ~external_client_manager();
+ external_client_manager(const external_client_manager&) {};
+ external_client_manager& operator=(const external_client_manager&);
+
+ std::unordered_map<int, std::shared_ptr<external_sensor_record>> m_clients;
+ cmutex m_mutex;
+};
+#endif /* _EXTERNAL_CLIENT_MANAGER_H_ */
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 <external_sensor.h>
+#include <external_sensor_service.h>
+#include <sensor_event_queue.h>
+#include <command_queue.h>
+
+using std::string;
+using std::shared_ptr;
+using std::make_shared;
+
+external_sensor::external_sensor()
+: m_source_connected(false)
+{
+}
+
+external_sensor::~external_sensor()
+{
+ unregister_key();
+}
+
+bool external_sensor::register_key(const string &key)
+{
+ m_key = key;
+ return external_sensor_service::get_instance().register_sensor(this);
+}
+
+bool external_sensor::unregister_key(void)
+{
+ return external_sensor_service::get_instance().unregister_sensor(this);
+}
+
+string external_sensor::get_key(void)
+{
+ return m_key;
+}
+
+bool external_sensor::set_source_connected(bool connected)
+{
+ AUTOLOCK(m_source_mutex);
+
+ if (m_source_connected && connected) {
+ _E("Source is already connected");
+ return false;
+ }
+
+ m_source_connected = connected;
+ return true;
+}
+
+bool external_sensor::get_source_connected(void)
+{
+ AUTOLOCK(m_source_mutex);
+
+ return m_source_connected;
+}
+
+int external_sensor::set_attribute(int32_t attribute, char *value, int value_size)
+{
+ shared_ptr<external_command_t> external_command = make_shared<external_command_t>();
+
+ external_command->header.sensor_id = get_id();
+ external_command->header.command_len = value_size;
+ external_command->command.assign(value, value + value_size);
+
+ command_queue::get_instance().push(external_command);
+
+ return 0;
+}
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 _EXTERNAL_SENSOR_H_
+#define _EXTERNAL_SENSOR_H_
+
+#include <sensor_base.h>
+#include <sensor_common.h>
+#include <cmutex.h>
+#include <string>
+
+class external_sensor : public sensor_base {
+public:
+ external_sensor();
+ virtual ~external_sensor();
+ int send_data(const char* data, int data_cnt);
+ std::string get_key(void);
+ bool set_source_connected(bool connected);
+ bool get_source_connected(void);
+ virtual void on_receive(unsigned long long timestamp, const float* data, int data_cnt) = 0;
+ virtual int set_attribute(int32_t attribute, char *value, int value_size);
+protected:
+ bool register_key(const std::string &key);
+private:
+ bool unregister_key(void);
+
+ std::string m_key;
+ bool m_source_connected;
+ cmutex m_source_mutex;
+};
+#endif /* _EXTERNAL_SENSOR_H_ */
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 <external_sensor_record.h>
+
+using std::string;
+
+external_sensor_record::external_sensor_record()
+: m_client_id(0)
+, m_pid(-1)
+{
+}
+
+external_sensor_record::~external_sensor_record()
+{
+ close_command_socket();
+}
+
+bool external_sensor_record::add_usage(sensor_id_t sensor)
+{
+ if (!m_usages.insert(sensor).second) {
+ _E("Sensor[%#x] is already registered", sensor);
+ return false;
+ }
+
+ return true;
+}
+
+bool external_sensor_record::remove_usage(sensor_id_t sensor)
+{
+ if (!m_usages.erase(sensor)) {
+ _E("Sensor[%#x] is not found", sensor);
+ return false;
+ }
+
+ return true;
+}
+
+bool external_sensor_record::has_usage(void)
+{
+ return !m_usages.empty();
+}
+
+bool external_sensor_record::has_usage(sensor_id_t sensor)
+{
+ auto it_usage = m_usages.find(sensor);
+
+ return (it_usage != m_usages.end());
+}
+
+void external_sensor_record::set_client_id(int client_id)
+{
+ m_client_id = client_id;
+}
+
+void external_sensor_record::set_client_info(pid_t pid, const string &name)
+{
+ char client_info[NAME_MAX + 32];
+ m_pid = pid;
+
+ snprintf(client_info, sizeof(client_info), "%s[pid=%d, id=%d]", name.c_str(), m_pid, m_client_id);
+ m_client_info.assign(client_info);
+}
+
+const char* external_sensor_record::get_client_info(void)
+{
+ return m_client_info.c_str();
+}
+
+void external_sensor_record::set_command_socket(const csocket &socket)
+{
+ m_command_socket = socket;
+}
+
+void external_sensor_record::get_command_socket(csocket &socket)
+{
+ socket = m_command_socket;
+}
+
+bool external_sensor_record::close_command_socket(void)
+{
+ return m_command_socket.close();
+}
+
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 _EXTERNAL_SENSOR_RECORD_H_
+#define _EXTERNAL_SENSOR_RECORD_H_
+
+#include <csocket.h>
+#include <sensor_common.h>
+#include <string>
+#include <unordered_set>
+
+class external_sensor_record {
+public:
+ external_sensor_record();
+ ~external_sensor_record();
+
+ void set_client_id(int client_id);
+
+ void set_client_info(pid_t pid, const std::string &name);
+ const char* get_client_info(void);
+
+ bool has_usage(void);
+ bool has_usage(sensor_id_t sensor);
+
+ bool add_usage(sensor_id_t sensor);
+ bool remove_usage(sensor_id_t sensor);
+
+ void set_command_socket(const csocket &socket);
+ void get_command_socket(csocket &socket);
+ bool close_command_socket(void);
+
+private:
+ int m_client_id;
+ pid_t m_pid;
+ std::string m_client_info;
+ csocket m_command_socket;
+ std::unordered_set<sensor_id_t> m_usages;
+};
+
+#endif /* _EXTERNAL_SENSOR_RECORD_H_ */
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 <external_sensor_service.h>
+#include <external_sensor.h>
+#include <external_client_manager.h>
+#include <command_queue.h>
+#include <thread>
+
+using std::thread;
+using std::pair;
+using std::string;
+using std::shared_ptr;
+
+external_sensor_service::external_sensor_service()
+{
+}
+
+external_sensor_service::~external_sensor_service()
+{
+}
+
+external_sensor_service& external_sensor_service::get_instance(void)
+{
+ static external_sensor_service instance;
+ return instance;
+}
+
+bool external_sensor_service::run(void)
+{
+ thread dispatcher(&external_sensor_service::dispatch_command, this);
+ dispatcher.detach();
+
+ return true;
+}
+
+external_client_manager& external_sensor_service::get_client_manager(void)
+{
+ return external_client_manager::get_instance();
+}
+
+void external_sensor_service::accept_command_channel(csocket client_socket)
+{
+ thread th = thread([&, client_socket]() mutable {
+ int client_id;
+ channel_ready_t command_channel_ready;
+ external_client_manager& client_manager = get_client_manager();
+
+ client_socket.set_connection_mode();
+
+ if (client_socket.recv(&client_id, sizeof(client_id)) <= 0) {
+ _E("Failed to receive client id on socket fd[%d]", client_socket.get_socket_fd());
+ return;
+ }
+
+ client_socket.set_transfer_mode();
+
+ if (!client_manager.set_command_socket(client_id, client_socket)) {
+ _E("Failed to store event socket[%d] for %s", client_socket.get_socket_fd(),
+ client_manager.get_client_info(client_id));
+ return;
+ }
+
+ command_channel_ready.magic = CHANNEL_MAGIC_NUM;
+ command_channel_ready.client_id = client_id;
+
+ _I("Command channel is accepted for %s on socket[%d]",
+ client_manager.get_client_info(client_id), client_socket.get_socket_fd());
+
+ if (client_socket.send(&command_channel_ready, sizeof(command_channel_ready)) <= 0) {
+ _E("Failed to send command channel_ready packet to %s on socket fd[%d]",
+ client_manager.get_client_info(client_id), client_socket.get_socket_fd());
+ return;
+ }
+ });
+
+ th.detach();
+}
+
+void external_sensor_service::dispatch_command(void)
+{
+ while (true) {
+ shared_ptr<external_command_t> command = command_queue::get_instance().pop();
+ csocket client_sock;
+ sensor_id_t sensor_id = command->header.sensor_id;
+ bool ret;
+
+ ret = external_client_manager::get_instance().get_listener_socket(sensor_id, client_sock);
+
+ if (!ret) {
+ _E("Failed to get listener socket for sensor[%d]", sensor_id);
+ continue;
+ }
+
+ if (client_sock.send(&(command->header), sizeof(command->header)) <= 0) {
+ _E("Failed to send command header to the client of sensor[%d]", sensor_id);
+ continue;
+ }
+
+ if (client_sock.send(command->command.data(), command->header.command_len) <= 0) {
+ _E("Failed to send command header to the client of sensor[%d]", sensor_id);
+ continue;
+ }
+ }
+}
+
+bool external_sensor_service::register_sensor(external_sensor *sensor)
+{
+ if (!m_external_sensors.insert(pair<string, external_sensor*>(sensor->get_key(), sensor)).second) {
+ _E("Failed to register sensor, key: %s", sensor->get_key().c_str());
+ return false;
+ }
+
+ return true;
+}
+
+bool external_sensor_service::unregister_sensor(external_sensor *sensor)
+{
+ if (!m_external_sensors.erase(sensor->get_key())) {
+ _E("Failed to unregister sensor, key: %s", sensor->get_key().c_str());
+ return false;
+ }
+
+ return true;
+}
+
+external_sensor* external_sensor_service::get_sensor(const string& key)
+{
+ auto it_sensor = m_external_sensors.find(key);
+
+ if (it_sensor == m_external_sensors.end()) {
+ _E("Sensor(key:%s) is not found", key.c_str());
+ return NULL;
+ }
+
+ return it_sensor->second;
+}
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 _EXTERNAL_SENSOR_SERVICE_H_
+#define _EXTERNAL_SENSOR_SERVICE_H_
+
+#include <external_sensor.h>
+#include <csocket.h>
+#include <string>
+#include <unordered_map>
+
+class external_client_manager;
+
+class external_sensor_service {
+public:
+ static external_sensor_service& get_instance();
+ bool register_sensor(external_sensor *sensor);
+ bool unregister_sensor(external_sensor *sensor);
+ external_sensor* get_sensor(const std::string& key);
+
+ void accept_command_channel(csocket client_socket);
+ bool run(void);
+private:
+ external_sensor_service();
+ ~external_sensor_service();
+ external_sensor_service(const external_sensor_service&) {};
+ external_sensor_service& operator=(const external_sensor_service&);
+
+ static external_client_manager& get_client_manager(void);
+
+ void dispatch_command(void);
+
+ std::unordered_map<std::string, external_sensor*> m_external_sensors;
+};
+#endif /* _EXTERNAL_SENSOR_SERVICE_H_ */
+
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <sensor_common.h>
+#include <command_common.h>
+#include <external_sensor_worker.h>
+#include <external_client_manager.h>
+#include <external_sensor.h>
+#include <external_sensor_service.h>
+
+using std::string;
+
+external_sensor_worker::cmd_handler_t external_sensor_worker::m_cmd_handlers[];
+
+external_sensor_worker::external_sensor_worker(const csocket& socket)
+: m_client_id(CLIENT_ID_INVALID)
+, m_socket(socket)
+, m_sensor(NULL)
+, m_sensor_id(UNKNOWN_SENSOR)
+{
+ static bool init = false;
+
+ if (!init) {
+ init_cmd_handlers();
+ init = true;
+ }
+
+ m_worker.set_context(this);
+ m_worker.set_working(working);
+ m_worker.set_stopped(stopped);
+}
+
+external_sensor_worker::~external_sensor_worker()
+{
+ m_socket.close();
+}
+
+bool external_sensor_worker::start(void)
+{
+ return m_worker.start();
+}
+
+void external_sensor_worker::init_cmd_handlers(void)
+{
+ m_cmd_handlers[CMD_EXT_GET_ID] = &external_sensor_worker::cmd_get_id;
+ m_cmd_handlers[CMD_EXT_CONNECT] = &external_sensor_worker::cmd_connect;
+ m_cmd_handlers[CMD_EXT_DISCONNECT] = &external_sensor_worker::cmd_disconnect;
+ m_cmd_handlers[CMD_EXT_POST] = &external_sensor_worker::cmd_post;
+}
+
+bool external_sensor_worker::working(void *ctx)
+{
+ bool ret;
+ external_sensor_worker *inst = (external_sensor_worker *)ctx;
+
+ packet_header header;
+ char *payload;
+
+ if (inst->m_socket.recv(&header, sizeof(header)) <= 0) {
+ string info;
+ inst->get_info(info);
+ _D("%s failed to receive header", info.c_str());
+ return false;
+ }
+
+ if (header.size > 0) {
+ payload = new(std::nothrow) char[header.size];
+ retvm_if(!payload, false, "Failed to allocate memory");
+
+ if (inst->m_socket.recv(payload, header.size) <= 0) {
+ string info;
+ inst->get_info(info);
+ _D("%s failed to receive data of packet", info.c_str());
+ delete[] payload;
+ return false;
+ }
+ } else {
+ payload = NULL;
+ }
+
+ ret = inst->dispatch_command(header.cmd, payload);
+
+ if (payload)
+ delete[] payload;
+
+ return ret;
+}
+
+bool external_sensor_worker::stopped(void *ctx)
+{
+ string info;
+ external_sensor_worker *inst = (external_sensor_worker *)ctx;
+
+ inst->get_info(info);
+ _I("%s is stopped", info.c_str());
+
+ if (inst->m_client_id != CLIENT_ID_INVALID) {
+ _I("Client:%d leaves without disconnecting", inst->m_client_id);
+ if (get_client_manager().has_sensor_record(inst->m_client_id, inst->m_sensor_id)) {
+ _I("Removing sensor[%#x] record for client_id[%d]", inst->m_sensor_id, inst->m_client_id);
+ get_client_manager().remove_sensor_record(inst->m_client_id, inst->m_sensor_id);
+
+ if (inst->m_sensor)
+ inst->m_sensor->set_source_connected(false);
+ }
+ }
+
+ delete inst;
+ return true;
+}
+
+bool external_sensor_worker::dispatch_command(int cmd, void* payload)
+{
+ int ret = false;
+
+ if (!(cmd > 0 && cmd < CMD_EXT_CNT)) {
+ _E("Unknown command: %d", cmd);
+ } else {
+ cmd_handler_t cmd_handler;
+ cmd_handler = external_sensor_worker::m_cmd_handlers[cmd];
+ if (cmd_handler)
+ ret = (this->*cmd_handler)(payload);
+ }
+
+ return ret;
+}
+
+bool external_sensor_worker::send_cmd_done(long value)
+{
+ cpacket* ret_packet;
+ cmd_ext_done_t *cmd_ext_done;
+
+ ret_packet = new(std::nothrow) cpacket(sizeof(cmd_ext_done_t));
+ retvm_if(!ret_packet, false, "Failed to allocate memory");
+
+ ret_packet->set_cmd(CMD_EXT_DONE);
+
+ cmd_ext_done = (cmd_ext_done_t*)ret_packet->data();
+ cmd_ext_done->value = value;
+
+ if (m_socket.send(ret_packet->packet(), ret_packet->size()) <= 0) {
+ _E("Failed to send a cmd_done to client_id [%d] with value [%ld]", m_client_id, value);
+ delete ret_packet;
+ return false;
+ }
+
+ delete ret_packet;
+ return true;
+}
+
+bool external_sensor_worker::send_cmd_get_id_done(int client_id)
+{
+ cpacket* ret_packet;
+ cmd_ext_get_id_done_t *cmd_ext_get_id_done;
+
+ ret_packet = new(std::nothrow) cpacket(sizeof(cmd_ext_get_id_done_t));
+ retvm_if(!ret_packet, false, "Failed to allocate memory");
+
+ ret_packet->set_cmd(CMD_EXT_GET_ID);
+
+ cmd_ext_get_id_done = (cmd_ext_get_id_done_t*)ret_packet->data();
+ cmd_ext_get_id_done->client_id = client_id;
+
+ if (m_socket.send(ret_packet->packet(), ret_packet->size()) <= 0) {
+ _E("Failed to send a cmd_get_id_done with client_id [%d]", client_id);
+ delete ret_packet;
+ return false;
+ }
+
+ delete ret_packet;
+ return true;
+}
+
+bool external_sensor_worker::send_cmd_connect_done(sensor_id_t sensor_id)
+{
+ cpacket* ret_packet;
+ cmd_ext_connect_done_t *cmd_ext_connect_done;
+
+ ret_packet = new(std::nothrow) cpacket(sizeof(cmd_ext_connect_done_t));
+ retvm_if(!ret_packet, false, "Failed to allocate memory");
+
+ ret_packet->set_cmd(CMD_EXT_CONNECT);
+
+ cmd_ext_connect_done = (cmd_ext_connect_done_t*)ret_packet->data();
+ cmd_ext_connect_done->sensor_id = sensor_id;
+
+ if (m_socket.send(ret_packet->packet(), ret_packet->size()) <= 0) {
+ _E("Failed to send a cmd_connect done");
+ delete ret_packet;
+ return false;
+ }
+
+ delete ret_packet;
+ return true;
+}
+
+bool external_sensor_worker::cmd_get_id(void *payload)
+{
+ cmd_ext_get_id_t *cmd = static_cast<cmd_ext_get_id_t *>(payload);
+ int client_id;
+ struct ucred cr;
+ socklen_t opt_len = sizeof(cr);
+
+ if (getsockopt(m_socket.get_socket_fd(), SOL_SOCKET, SO_PEERCRED, &cr, &opt_len)) {
+ _E("Failed to get socket option with SO_PEERCRED");
+ return false;
+ }
+
+ client_id = get_client_manager().create_client_record();
+
+ if (client_id != MAX_HANDLE_REACHED) {
+ get_client_manager().set_client_info(client_id, cr.pid, cmd->name);
+ _I("New client id [%d] created", client_id);
+ }
+
+ if (!send_cmd_get_id_done(client_id))
+ _E("Failed to send cmd_done to a client");
+
+ return true;
+}
+
+bool external_sensor_worker::cmd_connect(void *payload)
+{
+ cmd_ext_connect_t *cmd = static_cast<cmd_ext_connect_t *>(payload);
+ m_client_id = cmd->client_id;
+
+ external_sensor *sensor;
+ sensor = external_sensor_service::get_instance().get_sensor(string(cmd->key));
+ if (!sensor) {
+ _E("No matched external sensor with key: %s", cmd->key);
+ goto out;
+ }
+
+ if (!sensor->set_source_connected(true)) {
+ _E("External sensor(%s) is already connected", cmd->key);
+ goto out;
+ }
+
+ m_sensor = sensor;
+ m_sensor_id = sensor->get_id();
+
+ if (!get_client_manager().create_sensor_record(m_client_id, m_sensor_id)) {
+ _E("Failed to create sensor record for client: %d, sensor_id: %d", m_client_id, m_sensor_id);
+ m_sensor_id = UNKNOWN_SENSOR;
+ goto out;
+ }
+
+out:
+ if (!send_cmd_connect_done(m_sensor_id))
+ _E("Failed to send cmd_connect_done to a client : %d", m_client_id);
+
+ return true;
+}
+
+bool external_sensor_worker::cmd_disconnect(void *payload)
+{
+ long ret_value = OP_ERROR;
+
+ if (!m_sensor) {
+ _E("External sensor is not connected");
+ ret_value = OP_ERROR;
+ goto out;
+ }
+
+ if (!get_client_manager().remove_sensor_record(m_client_id, m_sensor_id)) {
+ _E("Failed to remove sensor record for client [%d]", m_client_id);
+ ret_value = OP_ERROR;
+ goto out;
+ }
+
+ m_sensor->set_source_connected(false);
+
+ m_sensor = NULL;
+ m_client_id = CLIENT_ID_INVALID;
+ m_sensor_id = UNKNOWN_SENSOR;
+ ret_value = OP_SUCCESS;
+out:
+ if (!send_cmd_done(ret_value))
+ _E("Failed to send cmd_done to a client");
+
+ if (ret_value == OP_SUCCESS)
+ return false;
+
+ return true;
+}
+
+bool external_sensor_worker::cmd_post(void *payload)
+{
+ long ret_value = OP_SUCCESS;
+ cmd_ext_post_t *cmd = static_cast<cmd_ext_post_t *>(payload);
+
+ m_sensor->on_receive(cmd->timestamp, cmd->data, cmd->data_cnt);
+
+ if (!send_cmd_done(ret_value))
+ _E("Failed to send cmd_done to a client");
+
+ return true;
+}
+
+external_client_manager& external_sensor_worker::get_client_manager(void)
+{
+ return external_client_manager::get_instance();
+}
+
+void external_sensor_worker::get_info(string &info)
+{
+ const char *client_info = NULL;
+
+ if (m_client_id != CLIENT_ID_INVALID)
+ client_info = get_client_manager().get_client_info(m_client_id);
+
+ info = string("Command worker for ") + (client_info ? string(client_info) : string("Unknown"));
+}
--- /dev/null
+/*
+ * sensord
+ *
+ * Copyright (c) 2015 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 _EXTERNAL_SENSOR_WORKER_H_
+#define _EXTERNAL_SENSOR_WORKER_H_
+
+#include <worker_thread.h>
+#include <csocket.h>
+#include <sensor_common.h>
+#include <string>
+
+class external_client_manager;
+class external_sensor;
+
+class external_sensor_worker {
+private:
+ typedef bool (external_sensor_worker::*cmd_handler_t)(void *payload);
+
+ int m_client_id;
+ csocket m_socket;
+ worker_thread m_worker;
+ external_sensor *m_sensor;
+ sensor_id_t m_sensor_id;
+ static cmd_handler_t m_cmd_handlers[CMD_EXT_CNT];
+
+ static void init_cmd_handlers(void);
+ static bool working(void *ctx);
+ static bool stopped(void *ctx);
+
+ bool dispatch_command(int cmd, void *payload);
+
+ bool send_cmd_done(long value);
+ bool send_cmd_get_id_done(int client_id);
+ bool send_cmd_connect_done(sensor_id_t sensor_id);
+
+ bool cmd_get_id(void *payload);
+ bool cmd_connect(void *payload);
+ bool cmd_disconnect(void *payload);
+ bool cmd_post(void *payload);
+
+ static external_client_manager& get_client_manager(void);
+
+ void get_info(std::string &info);
+public:
+ external_sensor_worker(const csocket& socket);
+ ~external_sensor_worker();
+
+ bool start(void);
+};
+
+#endif /* _EXTERNAL_SENSOR_WORKER_H_ */
#include <sensor_event_dispatcher.h>
#include <sensor_log.h>
#include <thread>
+#include <vector>
using std::thread;
using std::vector;
#include <sensor_log.h>
#include <physical_sensor.h>
#include <virtual_sensor.h>
+#include <external_sensor.h>
#include <unordered_set>
#include <algorithm>
#include <memory>
}
template <typename _sensor>
+void sensor_loader::create_external_sensors(const char *name)
+{
+ int32_t index;
+ sensor_type_t type;
+ external_sensor *instance;
+
+ instance = dynamic_cast<external_sensor *>(create_sensor<_sensor>());
+ if (!instance) {
+ _E("Memory allocation failed[%s]", name);
+ return;
+ }
+
+ std::shared_ptr<sensor_base> sensor(instance);
+ type = sensor->get_type();
+ index = (int32_t)(m_sensors.count(type));
+
+ sensor->set_id((int64_t)type << SENSOR_TYPE_SHIFT | index);
+
+ m_sensors.insert(std::make_pair(type, sensor));
+
+ _I("created [%s] sensor", sensor->get_name());
+}
+
+template <typename _sensor>
sensor_base* sensor_loader::create_sensor(void)
{
sensor_base *instance = NULL;
void create_sensors(void);
template <typename _sensor> void create_physical_sensors(sensor_type_t type);
template <typename _sensor> void create_virtual_sensors(const char *name);
+ template <typename _sensor> void create_external_sensors(const char *name);
template <typename _sensor> sensor_base* create_sensor(void);
void show_sensor_info(void);
#include <sensor_loader.h>
#include <command_common.h>
#include <command_worker.h>
+#include <external_sensor_worker.h>
+#include <external_sensor_service.h>
#include <thread>
#include <sensor_event_poller.h>
#include <client_info_manager.h>
-#define SYSTEMD_SOCKET_MAX 2
+#define SYSTEMD_SOCKET_MAX 2
using std::thread;
void server::accept_command_channel(void)
{
- command_worker *cmd_worker;
-
_I("Command channel acceptor is started");
while (m_running) {
/* TODO: if socket is closed, it should be erased */
client_command_sockets.push_back(client_command_socket);
- cmd_worker = new(std::nothrow) command_worker(client_command_socket);
-
- if (!cmd_worker) {
- _E("Failed to allocate memory");
- break;
- }
-
- if (!cmd_worker->start())
- delete cmd_worker;
+ thread worker_dispatcher(&server::dispatch_worker, this, client_command_socket);
+ worker_dispatcher.detach();
}
_I("Command channel acceptor is terminated");
_D("New client(socket_fd : %d) connected", client_event_socket.get_socket_fd());
- sensor_event_dispatcher::get_instance().accept_event_connections(client_event_socket);
+ thread event_channel_creator(&server::dispatch_event_channel_creator, this, client_event_socket);
+ event_channel_creator.detach();
}
_I("Event channel acceptor is terminated");
}
+void server::dispatch_worker(csocket socket)
+{
+ int worker_type;
+
+ if (socket.recv(&worker_type, sizeof(worker_type)) <= 0) {
+ _E("Failed to get worker type");
+ socket.close();
+ return;
+ }
+
+ if (worker_type == CLIENT_TYPE_SENSOR_CLIENT) {
+ command_worker *worker;
+ worker = new(std::nothrow) command_worker(socket);
+
+ if (!worker) {
+ _E("Failed to allocate memory");
+ socket.close();
+ return;
+ }
+
+ if (!worker->start()) {
+ _E("Failed to start command worker");
+ delete worker;
+ }
+ } else if (worker_type == CLIENT_TYPE_EXTERNAL_SOURCE) {
+ external_sensor_worker *worker;
+ worker = new(std::nothrow) external_sensor_worker(socket);
+
+ if (!worker) {
+ _E("Failed to allocate memory");
+ socket.close();
+ return;
+ }
+
+ if (!worker->start()) {
+ _E("Failed to start external worker");
+ delete worker;
+ }
+ } else {
+ _E("Not supported worker type: %d", worker_type);
+ socket.close();
+ }
+}
+
+void server::dispatch_event_channel_creator(csocket socket)
+{
+ int client_type;
+
+ if (socket.recv(&client_type, sizeof(client_type)) <= 0) {
+ _E("Failed to get client type");
+ socket.close();
+ return;
+ }
+
+ if (client_type == CLIENT_TYPE_SENSOR_CLIENT) {
+ sensor_event_dispatcher::get_instance().accept_event_connections(socket);
+ } else if (client_type == CLIENT_TYPE_EXTERNAL_SOURCE) {
+ external_sensor_service::get_instance().accept_command_channel(socket);
+ } else {
+ _E("Not supported client type: %d", client_type);
+ socket.close();
+ }
+}
+
void server::poll_event(void)
{
_I("Event poller is started");
void accept_command_channel(void);
void accept_event_channel(void);
+ void dispatch_worker(csocket socket);
+ void dispatch_event_channel_creator(csocket socket);
+
void close_socket(void);
/* TODO: move to socket class */
#include <cpacket.h>
#include <sensor_common.h>
+#include <string>
+#include <vector>
#define COMMAND_CHANNEL_PATH "/tmp/sensord_command_socket\0"
#define EVENT_CHANNEL_PATH "/tmp/sensord_event_socket\0"
CMD_CNT,
};
+enum ext_packet_type_t {
+ CMD_EXT_DONE = -1,
+ CMD_EXT_NONE = 0,
+ CMD_EXT_GET_ID,
+ CMD_EXT_CONNECT,
+ CMD_EXT_DISCONNECT,
+ CMD_EXT_POST,
+ CMD_EXT_CNT,
+};
+
typedef struct {
char name[NAME_MAX];
} cmd_get_id_t;
typedef struct {
} cmd_flush_t;
+typedef struct {
+ char name[NAME_MAX];
+} cmd_ext_get_id_t;
+
+typedef struct {
+ int client_id;
+ char key[NAME_MAX];
+} cmd_ext_connect_t;
+
+typedef struct {
+} cmd_ext_disconnect_t;
+
+typedef struct {
+ unsigned long long timestamp;
+ int data_cnt;
+ float data[0];
+} cmd_ext_post_t;
+
+typedef struct {
+ long value;
+} cmd_ext_done_t;
+
+typedef struct {
+ int client_id;
+} cmd_ext_get_id_done_t;
+
+typedef struct {
+ sensor_id_t sensor_id;
+} cmd_ext_connect_done_t;
+
#define CHANNEL_MAGIC_NUM 0xCAFECAFE
typedef struct {
int client_id;
} channel_ready_t;
+typedef struct external_command_header_t {
+ sensor_id_t sensor_id;
+ int command_len;
+} external_command_header_t;
+
+typedef struct external_command_t {
+ external_command_header_t header;
+ std::vector<char> command;
+} external_command_t;
+
typedef void *(*cmd_func_t)(void *data, void *cb_data);
+#define COMMAND_LEN_MAX (10*1024)
+#define POST_DATA_LEN_MAX (10*1024)
+
#endif /* _COMMAND_COMMON_H_ */
SENSOR_PERMISSION_BIO = (1 << 1)
};
+enum client_type_t {
+ CLIENT_TYPE_SENSOR_CLIENT = 1,
+ CLIENT_TYPE_EXTERNAL_SOURCE,
+};
+
typedef struct sensor_event_t {
unsigned int event_type;
sensor_id_t sensor_id;