4 * Copyright (c) 2017 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_listener.h"
22 #include <channel_handler.h>
23 #include <sensor_log.h>
24 #include <sensor_types.h>
25 #include <command_types.h>
26 #include <ipc_client.h>
28 using namespace sensor;
30 class listener_handler : public ipc::channel_handler
33 listener_handler(sensor_listener *listener)
34 : m_listener(listener)
36 void connected(ipc::channel *ch) {}
37 void disconnected(ipc::channel *ch)
40 /* If channel->disconnect() is not explicitly called,
41 * listener will be restored */
42 m_listener->restore();
45 void read(ipc::channel *ch, ipc::message &msg)
47 switch (msg.header()->type) {
48 case CMD_LISTENER_EVENT:
49 if (m_listener->get_event_handler())
50 m_listener->get_event_handler()->read(ch, msg);
52 case CMD_LISTENER_ACC_EVENT:
53 if (m_listener->get_accuracy_handler())
54 m_listener->get_accuracy_handler()->read(ch, msg);
59 void read_complete(ipc::channel *ch) {}
60 void error_caught(ipc::channel *ch, int error) {}
63 sensor_listener *m_listener;
66 sensor_listener::sensor_listener(sensor_t sensor)
68 , m_sensor(reinterpret_cast<sensor_info *>(sensor))
81 sensor_listener::~sensor_listener()
86 bool sensor_listener::init(void)
88 m_client = new(std::nothrow) ipc::ipc_client(SENSOR_CHANNEL_PATH);
89 retvm_if(!m_client, false, "Failed to allocate memory");
91 m_handler = new(std::nothrow) listener_handler(this);
108 void sensor_listener::deinit(void)
118 m_attributes.clear();
121 int sensor_listener::get_id(void)
126 sensor_t sensor_listener::get_sensor(void)
128 return static_cast<sensor_t>(m_sensor);
131 void sensor_listener::restore(void)
133 ret_if(!is_connected());
134 retm_if(!connect(), "Failed to restore listener");
136 /* Restore attributes/status */
137 if (m_started.load())
140 auto interval = m_attributes.find(SENSORD_ATTRIBUTE_INTERVAL);
141 if (interval != m_attributes.end())
142 set_interval(m_attributes[SENSORD_ATTRIBUTE_INTERVAL]);
144 auto latency = m_attributes.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY);
145 if (latency != m_attributes.end())
146 set_max_batch_latency(m_attributes[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY]);
148 _D("Restored listener[%d]", get_id());
151 bool sensor_listener::connect(void)
153 m_cmd_channel = m_client->connect(NULL);
154 retvm_if(!m_cmd_channel, false, "Failed to connect to server");
156 m_evt_channel = m_client->connect(m_handler, &m_loop, false);
157 retvm_if(!m_evt_channel, false, "Failed to connect to server");
161 cmd_listener_connect_t buf = {0, };
163 memcpy(buf.sensor, m_sensor->get_uri().c_str(), m_sensor->get_uri().size());
164 msg.set_type(CMD_LISTENER_CONNECT);
165 msg.enclose((const char *)&buf, sizeof(buf));
166 m_evt_channel->send_sync(&msg);
168 m_evt_channel->read_sync(reply);
169 reply.disclose((char *)&buf);
171 m_id = buf.listener_id;
172 m_connected.store(true);
174 m_evt_channel->bind();
176 _I("Connected listener[%d] with sensor[%s]", get_id(), m_sensor->get_uri().c_str());
181 void sensor_listener::disconnect(void)
183 ret_if(!is_connected());
184 m_connected.store(false);
186 m_evt_channel->disconnect();
187 delete m_evt_channel;
188 m_evt_channel = NULL;
190 m_cmd_channel->disconnect();
191 delete m_cmd_channel;
192 m_cmd_channel = NULL;
194 _I("Disconnected[%d]", get_id());
197 bool sensor_listener::is_connected(void)
199 return m_connected.load();
202 ipc::channel_handler *sensor_listener::get_event_handler(void)
204 return m_evt_handler;
207 void sensor_listener::set_event_handler(ipc::channel_handler *handler)
209 m_evt_handler = handler;
212 void sensor_listener::unset_event_handler(void)
214 delete m_evt_handler;
215 m_evt_handler = NULL;
218 ipc::channel_handler *sensor_listener::get_accuracy_handler(void)
220 return m_acc_handler;
223 void sensor_listener::set_accuracy_handler(ipc::channel_handler *handler)
225 m_acc_handler = handler;
228 void sensor_listener::unset_accuracy_handler(void)
230 delete m_acc_handler;
231 m_acc_handler = NULL;
234 int sensor_listener::start(void)
238 cmd_listener_start_t buf;
240 retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server");
242 buf.listener_id = m_id;
243 msg.set_type(CMD_LISTENER_START);
244 msg.enclose((char *)&buf, sizeof(buf));
246 m_cmd_channel->send_sync(&msg);
247 m_cmd_channel->read_sync(reply);
249 if (reply.header()->err < 0) {
250 _E("Failed to start listener[%d], sensor[%s]", get_id(), m_sensor->get_uri().c_str());
251 return reply.header()->err;
254 m_started.store(true);
256 _I("Listener[%d] started", get_id());
261 int sensor_listener::stop(void)
265 cmd_listener_stop_t buf;
267 retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server");
268 retvm_if(!m_started.load(), -EAGAIN, "Already stopped");
270 buf.listener_id = m_id;
271 msg.set_type(CMD_LISTENER_STOP);
272 msg.enclose((char *)&buf, sizeof(buf));
274 m_cmd_channel->send_sync(&msg);
275 m_cmd_channel->read_sync(reply);
277 if (reply.header()->err < 0) {
278 _E("Failed to stop listener[%d], sensor[%s]", get_id(), m_sensor->get_uri().c_str());
279 return reply.header()->err;
282 m_started.store(false);
284 _I("Listener[%d] stopped", get_id());
289 int sensor_listener::get_interval(void)
291 auto it = m_attributes.find(SENSORD_ATTRIBUTE_INTERVAL);
292 retv_if(it == m_attributes.end(), -1);
294 return m_attributes[SENSORD_ATTRIBUTE_INTERVAL];
297 int sensor_listener::get_max_batch_latency(void)
299 auto it = m_attributes.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY);
300 retv_if(it == m_attributes.end(), -1);
302 return m_attributes[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY];
305 int sensor_listener::get_pause_policy(void)
307 auto it = m_attributes.find(SENSORD_ATTRIBUTE_PAUSE_POLICY);
308 retv_if(it == m_attributes.end(), -1);
310 return m_attributes[SENSORD_ATTRIBUTE_PAUSE_POLICY];
313 int sensor_listener::get_passive_mode(void)
315 auto it = m_attributes.find(SENSORD_ATTRIBUTE_PASSIVE_MODE);
316 retv_if(it == m_attributes.end(), -1);
318 return m_attributes[SENSORD_ATTRIBUTE_PASSIVE_MODE];
321 int sensor_listener::set_interval(unsigned int interval)
325 /* TODO: move this logic to server */
327 _interval = DEFAULT_INTERVAL;
328 else if (interval < (unsigned int)m_sensor->get_min_interval())
329 _interval = m_sensor->get_min_interval();
331 _interval = interval;
333 _I("Listener[%d] set interval[%u]", get_id(), _interval);
335 return set_attribute(SENSORD_ATTRIBUTE_INTERVAL, _interval);
338 int sensor_listener::set_max_batch_latency(unsigned int max_batch_latency)
340 _I("Listener[%d] set max batch latency[%u]", get_id(), max_batch_latency);
342 return set_attribute(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY, max_batch_latency);
345 int sensor_listener::set_passive_mode(bool passive)
347 _I("Listener[%d] set passive mode[%d]", get_id(), passive);
349 return set_attribute(SENSORD_ATTRIBUTE_PASSIVE_MODE, passive);
352 int sensor_listener::flush(void)
354 _I("Listener[%d] flushes", get_id());
356 return set_attribute(SENSORD_ATTRIBUTE_FLUSH, 1);
359 int sensor_listener::set_attribute(int attribute, int value)
363 cmd_listener_attr_int_t buf;
365 retvm_if(!m_cmd_channel, false, "Failed to connect to server");
367 buf.listener_id = m_id;
368 buf.attribute = attribute;
370 msg.set_type(CMD_LISTENER_ATTR_INT);
371 msg.enclose((char *)&buf, sizeof(buf));
373 m_cmd_channel->send_sync(&msg);
374 m_cmd_channel->read_sync(reply);
376 if (reply.header()->err < 0)
377 return reply.header()->err;
379 m_attributes[attribute] = value;
384 int sensor_listener::set_attribute(int attribute, const char *value, int len)
388 cmd_listener_attr_str_t buf;
390 retvm_if(!m_cmd_channel, false, "Failed to connect to server");
392 msg.set_type(CMD_LISTENER_ATTR_STR);
393 buf.listener_id = m_id;
394 buf.attribute = attribute;
395 memcpy(buf.value, value, len);
398 msg.enclose((char *)&buf, sizeof(buf) + len);
400 m_cmd_channel->send_sync(&msg);
401 m_cmd_channel->read_sync(reply);
403 return reply.header()->err;
406 int sensor_listener::get_sensor_data(sensor_data_t *data)
410 cmd_listener_get_data_t buf;
412 retvm_if(!m_cmd_channel, false, "Failed to connect to server");
414 buf.listener_id = m_id;
415 msg.set_type(CMD_LISTENER_GET_DATA);
416 msg.enclose((char *)&buf, sizeof(buf));
418 m_cmd_channel->send_sync(&msg);
419 m_cmd_channel->read_sync(reply);
421 reply.disclose((char *)&buf);
422 int size = sizeof(sensor_data_t);
424 if (buf.len > size || buf.len < 0) {
426 data->value_count = 0;
427 /* TODO: it should return OP_ERROR */
431 memcpy(data, &buf.data, buf.len);
433 _D("Listener[%d] read sensor data", get_id());