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)
39 /* If channel->disconnect() is not explicitly called,
40 * listener will be restored */
41 m_listener->restore();
44 void read(ipc::channel *ch, ipc::message &msg)
46 switch (msg.header()->type) {
47 case CMD_LISTENER_EVENT:
48 if (m_listener->get_event_handler())
49 m_listener->get_event_handler()->read(ch, msg);
51 case CMD_LISTENER_ACC_EVENT:
52 if (m_listener->get_accuracy_handler())
53 m_listener->get_accuracy_handler()->read(ch, msg);
58 void read_complete(ipc::channel *ch) {}
59 void error_caught(ipc::channel *ch, int error) {}
62 sensor_listener *m_listener;
65 sensor_listener::sensor_listener(sensor_t sensor)
67 , m_sensor(reinterpret_cast<sensor_info *>(sensor))
80 sensor_listener::~sensor_listener()
85 bool sensor_listener::init(void)
87 m_client = new(std::nothrow) ipc::ipc_client(SENSOR_CHANNEL_PATH);
88 retvm_if(!m_client, false, "Failed to allocate memory");
90 m_handler = new(std::nothrow) listener_handler(this);
107 void sensor_listener::deinit(void)
117 m_attributes.clear();
120 int sensor_listener::get_id(void)
125 sensor_t sensor_listener::get_sensor(void)
127 return static_cast<sensor_t>(m_sensor);
130 void sensor_listener::restore(void)
132 ret_if(!is_connected());
133 retm_if(!connect(), "Failed to restore listener");
135 /* Restore attributes/status */
136 if (m_started.load())
139 auto interval = m_attributes.find(SENSORD_ATTRIBUTE_INTERVAL);
140 if (interval != m_attributes.end())
141 set_interval(m_attributes[SENSORD_ATTRIBUTE_INTERVAL]);
143 auto latency = m_attributes.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY);
144 if (latency != m_attributes.end())
145 set_max_batch_latency(m_attributes[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY]);
147 _D("Restored listener[%d]", get_id());
150 bool sensor_listener::connect(void)
152 m_cmd_channel = m_client->connect(NULL);
153 retvm_if(!m_cmd_channel, false, "Failed to connect to server");
155 m_evt_channel = m_client->connect(m_handler, &m_loop, false);
156 retvm_if(!m_evt_channel, false, "Failed to connect to server");
160 cmd_listener_connect_t buf = {0, };
162 memcpy(buf.sensor, m_sensor->get_uri().c_str(), m_sensor->get_uri().size());
163 msg.set_type(CMD_LISTENER_CONNECT);
164 msg.enclose((const char *)&buf, sizeof(buf));
165 m_evt_channel->send_sync(&msg);
167 m_evt_channel->read_sync(reply);
168 reply.disclose((char *)&buf);
170 m_id = buf.listener_id;
171 m_connected.store(true);
173 m_evt_channel->bind();
175 _D("Listener ID[%d]", get_id());
180 void sensor_listener::disconnect(void)
182 ret_if(!is_connected());
183 m_connected.store(false);
188 msg.set_type(CMD_LISTENER_DISCONNECT);
189 m_evt_channel->send_sync(&msg);
191 m_evt_channel->read_sync(reply);
192 m_evt_channel->disconnect();
194 delete m_evt_channel;
195 m_evt_channel = NULL;
197 m_cmd_channel->disconnect();
198 delete m_cmd_channel;
199 m_cmd_channel = NULL;
201 _I("Disconnected[%d]", get_id());
204 bool sensor_listener::is_connected(void)
206 return m_connected.load();
209 ipc::channel_handler *sensor_listener::get_event_handler(void)
211 return m_evt_handler;
214 void sensor_listener::set_event_handler(ipc::channel_handler *handler)
216 m_evt_handler = handler;
219 void sensor_listener::unset_event_handler(void)
221 delete m_evt_handler;
222 m_evt_handler = NULL;
225 ipc::channel_handler *sensor_listener::get_accuracy_handler(void)
227 return m_acc_handler;
230 void sensor_listener::set_accuracy_handler(ipc::channel_handler *handler)
232 m_acc_handler = handler;
235 void sensor_listener::unset_accuracy_handler(void)
237 delete m_acc_handler;
238 m_acc_handler = NULL;
241 int sensor_listener::start(void)
245 cmd_listener_start_t buf;
247 retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server");
249 buf.listener_id = m_id;
250 msg.set_type(CMD_LISTENER_START);
251 msg.enclose((char *)&buf, sizeof(buf));
253 m_cmd_channel->send_sync(&msg);
254 m_cmd_channel->read_sync(reply);
256 if (reply.header()->err < 0)
257 return reply.header()->err;
259 m_started.store(true);
264 int sensor_listener::stop(void)
268 cmd_listener_stop_t buf;
270 retvm_if(!m_cmd_channel, -EINVAL, "Failed to connect to server");
271 retvm_if(!m_started.load(), -EAGAIN, "Already stopped");
273 buf.listener_id = m_id;
274 msg.set_type(CMD_LISTENER_STOP);
275 msg.enclose((char *)&buf, sizeof(buf));
277 m_cmd_channel->send_sync(&msg);
278 m_cmd_channel->read_sync(reply);
280 if (reply.header()->err < 0)
281 return reply.header()->err;
283 m_started.store(false);
288 int sensor_listener::get_interval(void)
290 auto it = m_attributes.find(SENSORD_ATTRIBUTE_INTERVAL);
291 retv_if(it == m_attributes.end(), -1);
293 return m_attributes[SENSORD_ATTRIBUTE_INTERVAL];
296 int sensor_listener::get_max_batch_latency(void)
298 auto it = m_attributes.find(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY);
299 retv_if(it == m_attributes.end(), -1);
301 return m_attributes[SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY];
304 int sensor_listener::get_pause_policy(void)
306 auto it = m_attributes.find(SENSORD_ATTRIBUTE_PAUSE_POLICY);
307 retv_if(it == m_attributes.end(), -1);
309 return m_attributes[SENSORD_ATTRIBUTE_PAUSE_POLICY];
312 int sensor_listener::get_passive_mode(void)
314 auto it = m_attributes.find(SENSORD_ATTRIBUTE_PASSIVE_MODE);
315 retv_if(it == m_attributes.end(), -1);
317 return m_attributes[SENSORD_ATTRIBUTE_PASSIVE_MODE];
320 int sensor_listener::set_interval(unsigned int interval)
324 /* TODO: move this logic to server */
326 _interval = DEFAULT_INTERVAL;
327 else if (interval < (unsigned int)m_sensor->get_min_interval())
328 _interval = m_sensor->get_min_interval();
330 _interval = interval;
332 return set_attribute(SENSORD_ATTRIBUTE_INTERVAL, _interval);
335 int sensor_listener::set_max_batch_latency(unsigned int max_batch_latency)
337 return set_attribute(SENSORD_ATTRIBUTE_MAX_BATCH_LATENCY, max_batch_latency);
340 int sensor_listener::set_passive_mode(bool passive)
342 return set_attribute(SENSORD_ATTRIBUTE_PASSIVE_MODE, passive);
345 int sensor_listener::flush(void)
347 return set_attribute(SENSORD_ATTRIBUTE_FLUSH, 1);
350 int sensor_listener::set_attribute(int attribute, int value)
354 cmd_listener_attr_int_t buf;
356 retvm_if(!m_cmd_channel, false, "Failed to connect to server");
358 buf.listener_id = m_id;
359 buf.attribute = attribute;
361 msg.set_type(CMD_LISTENER_ATTR_INT);
362 msg.enclose((char *)&buf, sizeof(buf));
364 m_cmd_channel->send_sync(&msg);
365 m_cmd_channel->read_sync(reply);
367 if (reply.header()->err < 0)
368 return reply.header()->err;
370 m_attributes[attribute] = value;
375 int sensor_listener::set_attribute(int attribute, const char *value, int len)
379 cmd_listener_attr_str_t buf;
381 retvm_if(!m_cmd_channel, false, "Failed to connect to server");
383 msg.set_type(CMD_LISTENER_ATTR_STR);
384 buf.listener_id = m_id;
385 buf.attribute = attribute;
386 memcpy(buf.value, value, len);
389 msg.enclose((char *)&buf, sizeof(buf) + len);
391 m_cmd_channel->send_sync(&msg);
392 m_cmd_channel->read_sync(reply);
394 return reply.header()->err;
397 int sensor_listener::get_sensor_data(sensor_data_t *data)
401 cmd_listener_get_data_t buf;
403 retvm_if(!m_cmd_channel, false, "Failed to connect to server");
405 buf.listener_id = m_id;
406 msg.set_type(CMD_LISTENER_GET_DATA);
407 msg.enclose((char *)&buf, sizeof(buf));
409 m_cmd_channel->send_sync(&msg);
410 m_cmd_channel->read_sync(reply);
412 reply.disclose((char *)&buf);
413 int size = sizeof(sensor_data_t);
415 if (buf.len > size || buf.len < 0) {
417 data->value_count = 0;
418 /* TODO: it should return OP_ERROR */
422 memcpy(data, &buf.data, buf.len);