sensord: support external sensor feature 61/71161/1
authorkibak.yoon <kibak.yoon@samsung.com>
Tue, 24 May 2016 09:40:53 +0000 (18:40 +0900)
committerkibak.yoon <kibak.yoon@samsung.com>
Tue, 24 May 2016 09:40:53 +0000 (18:40 +0900)
Change-Id: I3649a0b017c6b94c98cc5c71ac3c776002ea0f43
Signed-off-by: kibak.yoon <kibak.yoon@samsung.com>
28 files changed:
src/client/command_channel.cpp
src/client/external_client.cpp [new file with mode: 0644]
src/client/external_data_channel.cpp [new file with mode: 0644]
src/client/external_data_channel.h [new file with mode: 0644]
src/client/external_sensor_manager.cpp [new file with mode: 0644]
src/client/external_sensor_manager.h [new file with mode: 0644]
src/client/sensor_event_listener.cpp
src/server/command_queue.cpp [new file with mode: 0644]
src/server/command_queue.h [new file with mode: 0644]
src/server/dbus_util.cpp [new file with mode: 0755]
src/server/dbus_util.h [new file with mode: 0644]
src/server/external_client_manager.cpp [new file with mode: 0644]
src/server/external_client_manager.h [new file with mode: 0644]
src/server/external_sensor.cpp [new file with mode: 0644]
src/server/external_sensor.h [new file with mode: 0644]
src/server/external_sensor_record.cpp [new file with mode: 0644]
src/server/external_sensor_record.h [new file with mode: 0644]
src/server/external_sensor_service.cpp [new file with mode: 0644]
src/server/external_sensor_service.h [new file with mode: 0644]
src/server/external_sensor_worker.cpp [new file with mode: 0644]
src/server/external_sensor_worker.h [new file with mode: 0644]
src/server/sensor_event_dispatcher.cpp
src/server/sensor_loader.cpp
src/server/sensor_loader.h
src/server/server.cpp
src/server/server.h
src/shared/command_common.h
src/shared/sensor_common.h

index 274552f..ff49a54 100644 (file)
@@ -79,6 +79,7 @@ bool command_channel::command_handler(cpacket *packet, void **return_payload)
 
 bool command_channel::create_channel(void)
 {
+       const int cllient_type = CLIENT_TYPE_SENSOR_CLIENT;
        if (!m_command_socket.create(SOCK_STREAM))
                return false;
 
@@ -89,6 +90,11 @@ bool command_channel::create_channel(void)
 
        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;
 }
 
diff --git a/src/client/external_client.cpp b/src/client/external_client.cpp
new file mode 100644 (file)
index 0000000..1a3e2da
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * 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;
+}
diff --git a/src/client/external_data_channel.cpp b/src/client/external_data_channel.cpp
new file mode 100644 (file)
index 0000000..70a7325
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * 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;
+}
diff --git a/src/client/external_data_channel.h b/src/client/external_data_channel.h
new file mode 100644 (file)
index 0000000..19a2a41
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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_ */
diff --git a/src/client/external_sensor_manager.cpp b/src/client/external_sensor_manager.cpp
new file mode 100644 (file)
index 0000000..e19b403
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * 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;
+}
diff --git a/src/client/external_sensor_manager.h b/src/client/external_sensor_manager.h
new file mode 100644 (file)
index 0000000..9259c2c
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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_ */
index 0215b29..3182b78 100644 (file)
@@ -380,6 +380,7 @@ void sensor_event_listener::listen_events(void)
 
 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;
 
@@ -396,6 +397,11 @@ bool sensor_event_listener::create_event_channel(void)
                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) {
diff --git a/src/server/command_queue.cpp b/src/server/command_queue.cpp
new file mode 100644 (file)
index 0000000..0eadaab
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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;
+}
diff --git a/src/server/command_queue.h b/src/server/command_queue.h
new file mode 100644 (file)
index 0000000..d5ab195
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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
diff --git a/src/server/dbus_util.cpp b/src/server/dbus_util.cpp
new file mode 100755 (executable)
index 0000000..df1ade0
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * 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);
+}
diff --git a/src/server/dbus_util.h b/src/server/dbus_util.h
new file mode 100644 (file)
index 0000000..ce4ad54
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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_ */
diff --git a/src/server/external_client_manager.cpp b/src/server/external_client_manager.cpp
new file mode 100644 (file)
index 0000000..a19d502
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * 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;
+}
diff --git a/src/server/external_client_manager.h b/src/server/external_client_manager.h
new file mode 100644 (file)
index 0000000..9934d8d
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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_ */
diff --git a/src/server/external_sensor.cpp b/src/server/external_sensor.cpp
new file mode 100644 (file)
index 0000000..9046739
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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;
+}
diff --git a/src/server/external_sensor.h b/src/server/external_sensor.h
new file mode 100644 (file)
index 0000000..c52b325
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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_ */
diff --git a/src/server/external_sensor_record.cpp b/src/server/external_sensor_record.cpp
new file mode 100644 (file)
index 0000000..98d3c79
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * 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();
+}
+
diff --git a/src/server/external_sensor_record.h b/src/server/external_sensor_record.h
new file mode 100644 (file)
index 0000000..9b85640
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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_ */
diff --git a/src/server/external_sensor_service.cpp b/src/server/external_sensor_service.cpp
new file mode 100644 (file)
index 0000000..c7d1e8e
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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;
+}
diff --git a/src/server/external_sensor_service.h b/src/server/external_sensor_service.h
new file mode 100644 (file)
index 0000000..28b1aa4
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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_ */
+
diff --git a/src/server/external_sensor_worker.cpp b/src/server/external_sensor_worker.cpp
new file mode 100644 (file)
index 0000000..9bc46fb
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * 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"));
+}
diff --git a/src/server/external_sensor_worker.h b/src/server/external_sensor_worker.h
new file mode 100644 (file)
index 0000000..982dd09
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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_ */
index 03c4798..eeb4236 100644 (file)
@@ -22,6 +22,7 @@
 #include <sensor_event_dispatcher.h>
 #include <sensor_log.h>
 #include <thread>
+#include <vector>
 
 using std::thread;
 using std::vector;
index d43ac62..5e0e0f9 100644 (file)
@@ -26,6 +26,7 @@
 #include <sensor_log.h>
 #include <physical_sensor.h>
 #include <virtual_sensor.h>
+#include <external_sensor.h>
 #include <unordered_set>
 #include <algorithm>
 #include <memory>
@@ -254,6 +255,30 @@ void sensor_loader::create_virtual_sensors(const char *name)
 }
 
 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;
index 3312c1d..c10c4bb 100644 (file)
@@ -48,6 +48,7 @@ private:
        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);
index e3c902b..684b265 100644 (file)
 #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;
 
@@ -75,8 +77,6 @@ int server::get_systemd_socket(const char *name)
 
 void server::accept_command_channel(void)
 {
-       command_worker *cmd_worker;
-
        _I("Command channel acceptor is started");
 
        while (m_running) {
@@ -102,15 +102,8 @@ void server::accept_command_channel(void)
                /* 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");
@@ -143,12 +136,77 @@ void server::accept_event_channel(void)
 
                _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");
index e285cde..8f9daf7 100644 (file)
@@ -58,6 +58,9 @@ private:
        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 */
index 3346654..3973a92 100644 (file)
@@ -22,6 +22,8 @@
 
 #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"
@@ -50,6 +52,16 @@ enum packet_type_t {
        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;
@@ -127,6 +139,36 @@ typedef struct  {
 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 {
@@ -134,6 +176,19 @@ 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_ */
index d505918..a1c0541 100644 (file)
@@ -116,6 +116,11 @@ enum sensor_permission_t {
        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;