4 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 #include <sensor_common.h>
21 #include <command_common.h>
22 #include <external_sensor_worker.h>
23 #include <external_client_manager.h>
24 #include <external_sensor.h>
25 #include <external_sensor_service.h>
29 external_sensor_worker::cmd_handler_t external_sensor_worker::m_cmd_handlers[];
31 external_sensor_worker::external_sensor_worker(const csocket& socket)
32 : m_client_id(CLIENT_ID_INVALID)
35 , m_sensor_id(UNKNOWN_SENSOR)
37 static bool init = false;
44 m_worker.set_context(this);
45 m_worker.set_working(working);
46 m_worker.set_stopped(stopped);
49 external_sensor_worker::~external_sensor_worker()
54 bool external_sensor_worker::start(void)
56 return m_worker.start();
59 void external_sensor_worker::init_cmd_handlers(void)
61 m_cmd_handlers[CMD_EXT_GET_ID] = &external_sensor_worker::cmd_get_id;
62 m_cmd_handlers[CMD_EXT_CONNECT] = &external_sensor_worker::cmd_connect;
63 m_cmd_handlers[CMD_EXT_DISCONNECT] = &external_sensor_worker::cmd_disconnect;
64 m_cmd_handlers[CMD_EXT_POST] = &external_sensor_worker::cmd_post;
67 bool external_sensor_worker::working(void *ctx)
70 external_sensor_worker *inst = (external_sensor_worker *)ctx;
75 if (inst->m_socket.recv(&header, sizeof(header)) <= 0) {
78 _D("%s failed to receive header", info.c_str());
82 retvm_if(header.size == 0, false, "Invalid header size");
84 payload = new(std::nothrow) char[header.size];
85 retvm_if(!payload, false, "Failed to allocate memory");
87 if (inst->m_socket.recv(payload, header.size) <= 0) {
90 _D("%s failed to receive data of packet", info.c_str());
95 ret = inst->dispatch_command(header.cmd, payload);
102 bool external_sensor_worker::stopped(void *ctx)
105 external_sensor_worker *inst = (external_sensor_worker *)ctx;
107 inst->get_info(info);
108 _I("%s is stopped", info.c_str());
110 if (inst->m_client_id != CLIENT_ID_INVALID) {
111 _I("Client:%d leaves without disconnecting", inst->m_client_id);
112 if (get_client_manager().has_sensor_record(inst->m_client_id, inst->m_sensor_id)) {
113 _I("Removing sensor[%#x] record for client_id[%d]", inst->m_sensor_id, inst->m_client_id);
114 get_client_manager().remove_sensor_record(inst->m_client_id, inst->m_sensor_id);
117 inst->m_sensor->set_source_connected(false);
125 bool external_sensor_worker::dispatch_command(int cmd, void* payload)
129 if (!(cmd > 0 && cmd < CMD_EXT_CNT)) {
130 _E("Unknown command: %d", cmd);
132 cmd_handler_t cmd_handler;
133 cmd_handler = external_sensor_worker::m_cmd_handlers[cmd];
135 ret = (this->*cmd_handler)(payload);
141 bool external_sensor_worker::send_cmd_done(long value)
144 cmd_ext_done_t *cmd_ext_done;
146 ret_packet = new(std::nothrow) cpacket(sizeof(cmd_ext_done_t));
147 retvm_if(!ret_packet, false, "Failed to allocate memory");
149 ret_packet->set_cmd(CMD_EXT_DONE);
151 cmd_ext_done = (cmd_ext_done_t*)ret_packet->data();
152 cmd_ext_done->value = value;
154 if (m_socket.send(ret_packet->packet(), ret_packet->size()) <= 0) {
155 _E("Failed to send a cmd_done to client_id [%d] with value [%ld]", m_client_id, value);
164 bool external_sensor_worker::send_cmd_get_id_done(int client_id)
167 cmd_ext_get_id_done_t *cmd_ext_get_id_done;
169 ret_packet = new(std::nothrow) cpacket(sizeof(cmd_ext_get_id_done_t));
170 retvm_if(!ret_packet, false, "Failed to allocate memory");
172 ret_packet->set_cmd(CMD_EXT_GET_ID);
174 cmd_ext_get_id_done = (cmd_ext_get_id_done_t*)ret_packet->data();
175 cmd_ext_get_id_done->client_id = client_id;
177 if (m_socket.send(ret_packet->packet(), ret_packet->size()) <= 0) {
178 _E("Failed to send a cmd_get_id_done with client_id [%d]", client_id);
187 bool external_sensor_worker::send_cmd_connect_done(sensor_id_t sensor_id)
190 cmd_ext_connect_done_t *cmd_ext_connect_done;
192 ret_packet = new(std::nothrow) cpacket(sizeof(cmd_ext_connect_done_t));
193 retvm_if(!ret_packet, false, "Failed to allocate memory");
195 ret_packet->set_cmd(CMD_EXT_CONNECT);
197 cmd_ext_connect_done = (cmd_ext_connect_done_t*)ret_packet->data();
198 cmd_ext_connect_done->sensor_id = sensor_id;
200 if (m_socket.send(ret_packet->packet(), ret_packet->size()) <= 0) {
201 _E("Failed to send a cmd_connect done");
210 bool external_sensor_worker::cmd_get_id(void *payload)
212 cmd_ext_get_id_t *cmd = static_cast<cmd_ext_get_id_t *>(payload);
215 socklen_t opt_len = sizeof(cr);
217 if (getsockopt(m_socket.get_socket_fd(), SOL_SOCKET, SO_PEERCRED, &cr, &opt_len)) {
218 _E("Failed to get socket option with SO_PEERCRED");
222 client_id = get_client_manager().create_client_record();
224 if (client_id != MAX_HANDLE_REACHED) {
225 get_client_manager().set_client_info(client_id, cr.pid, cmd->name);
226 _I("New client id [%d] created", client_id);
229 if (!send_cmd_get_id_done(client_id))
230 _E("Failed to send cmd_done to a client");
235 bool external_sensor_worker::cmd_connect(void *payload)
237 cmd_ext_connect_t *cmd = static_cast<cmd_ext_connect_t *>(payload);
238 m_client_id = cmd->client_id;
240 external_sensor *sensor;
241 sensor = external_sensor_service::get_instance().get_sensor(string(cmd->key));
243 _E("No matched external sensor with key: %s", cmd->key);
247 if (!sensor->set_source_connected(true)) {
248 _E("External sensor(%s) is already connected", cmd->key);
253 m_sensor_id = sensor->get_id();
255 if (!get_client_manager().create_sensor_record(m_client_id, m_sensor_id)) {
256 _E("Failed to create sensor record for client: %d, sensor_id: %d", m_client_id, m_sensor_id);
257 m_sensor_id = UNKNOWN_SENSOR;
262 if (!send_cmd_connect_done(m_sensor_id))
263 _E("Failed to send cmd_connect_done to a client : %d", m_client_id);
268 bool external_sensor_worker::cmd_disconnect(void *payload)
270 long ret_value = OP_ERROR;
273 _E("External sensor is not connected");
274 ret_value = OP_ERROR;
278 if (!get_client_manager().remove_sensor_record(m_client_id, m_sensor_id)) {
279 _E("Failed to remove sensor record for client [%d]", m_client_id);
280 ret_value = OP_ERROR;
284 m_sensor->set_source_connected(false);
287 m_client_id = CLIENT_ID_INVALID;
288 m_sensor_id = UNKNOWN_SENSOR;
289 ret_value = OP_SUCCESS;
291 if (!send_cmd_done(ret_value))
292 _E("Failed to send cmd_done to a client");
294 if (ret_value == OP_SUCCESS)
300 bool external_sensor_worker::cmd_post(void *payload)
302 long ret_value = OP_SUCCESS;
303 cmd_ext_post_t *cmd = static_cast<cmd_ext_post_t *>(payload);
305 m_sensor->on_receive(cmd->timestamp, cmd->data, cmd->data_cnt);
307 if (!send_cmd_done(ret_value))
308 _E("Failed to send cmd_done to a client");
313 external_client_manager& external_sensor_worker::get_client_manager(void)
315 return external_client_manager::get_instance();
318 void external_sensor_worker::get_info(string &info)
320 const char *client_info = NULL;
322 if (m_client_id != CLIENT_ID_INVALID)
323 client_info = get_client_manager().get_client_info(m_client_id);
325 info = string("Command worker for ") + (client_info ? string(client_info) : string("Unknown"));