RDK Documentation (Open Sourced RDK Components)
Connection.cpp
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 
21 /**
22 * @defgroup hdmicec
23 * @{
24 * @defgroup ccec
25 * @{
26 **/
27 
28 
29 #include <stdio.h>
30 
31 #include "ccec/CECFrame.hpp"
32 #include "ccec/FrameListener.hpp"
33 #include "ccec/Connection.hpp"
34 #include "ccec/Util.hpp"
35 #include "ccec/Header.hpp"
36 
37 #include "Bus.hpp"
38 
40 
41 CCEC_BEGIN_NAMESPACE
42 
43 Connection::Connection(const LogicalAddress &source, bool opened, const std::string &name)
44 : name(name), source(source), bus(Bus::getInstance()), busFrameFilter(this->source), busFrameListener(*this, busFrameFilter)
45 {
46  if (opened) open();
47 }
48 
49 Connection::~Connection(void) {
50 
51 }
52 
53 /**
54  * @brief Open a connection to receive CEC packets from the bus.
55  *
56  * When a connection is opened without a given logical address this connection will pick up all messages destined
57  * to the host device, regardless what roles the device has. This is useful if the application wants to sniff all available
58  * CEC packets from the bus.
59  *
60  * @return None.
61  */
62 void Connection::open(void)
63 {
64  CCEC_LOG( LOG_DEBUG, "Connection::open with source [%s]\r\n", source.toString().c_str());
65  bus.addFrameListener(&busFrameListener);
66 }
67 
68 /**
69  * brief Close the CEC connection from bus so that the application will stop receiving CEC packets from the bus.
70  *
71  * @return None.
72  */
74 {
75  {AutoLock lock_(mutex);
76  frameListeners.clear();
77  }
78  bus.removeFrameListener(&busFrameListener);
79 }
80 
81 /**
82  * @brief This function is used to listen for CECFrame, which is a byte stream that contains raw bytes received from CEC bus.
83  *
84  * @param[in] listener A listener structure which need be added in the frameListeners Queue.
85  *
86  * @return None.
87  */
89 {
90  {AutoLock lock_(mutex);
91  frameListeners.push_back(listener);
92  }
93  CCEC_LOG( LOG_DEBUG, "Connection::addFrameListener::done\r\n");
94 
95 }
96 
97 /**
98  * @brief This function is used to remove the listener information from the queue.
99  *
100  * @param[in] listener Address of the pointer which need to be removed from the Queue.
101  *
102  * @return None.
103  */
105 {
106  { AutoLock lock_(mutex);
107  frameListeners.remove(listener);
108  }
109 
110 }
111 
112 /**
113  * @brief This function is used to send CEC frame to CEC Bus.
114  *
115  * @param[in] to Logical address of the connection where CEC frame can be sent.
116  * @param[in] frame CEC Frame which is a byte stream that contains raw bytes.
117  * @param[in] timeout It is an upper bound on the amount of time to wait so that the application will not hang during sending.
118  *
119  * @return None.
120  */
121 void Connection::sendTo(const LogicalAddress &to, const CECFrame &frame, int timeout)
122 {
123  CCEC_LOG( LOG_DEBUG, "Sending out from Connection\r\n");
124  CECFrame fullFrame;
125  Header header(source, to);
126  header.serialize(fullFrame);
127  fullFrame.append(frame);
128  send(fullFrame, timeout);
129 }
130 
131 /**
132  * @brief This function is used to send CEC frame to CEC Bus.
133  *
134  * @param[in] to Logical address of the connection where CEC frame can be sent.
135  * @param[in] frame CEC Frame which is a byte stream that contains raw bytes.
136  * @param[in] timeout It is an upper bound on the amount of time to wait so that the application will not hang during sending.
137  * @param[in] doThrow Throw an exception if the CEC frame is unable to send.
138  *
139  * @return None.
140  */
141 void Connection::sendTo(const LogicalAddress &to, const CECFrame &frame, int timeout, const Throw_e &doThrow)
142 {
143  CCEC_LOG( LOG_DEBUG, "Sending out from Connection\r\n");
144  CECFrame fullFrame;
145  Header header(source, to);
146  header.serialize(fullFrame);
147  fullFrame.append(frame);
148  try
149  {
150  send(fullFrame, timeout, doThrow);
151  }
152  catch(Exception &e)
153  {
154  //CCEC_LOG( LOG_EXP, "Catch and re-throw Exception from sendTo\r\n");
155  throw;
156  }
157 }
158 
159 /**
160  * @brief sends HDMI-CEC frame to CEC Bus using asynchronized method.
161  *
162  * @param[in] to Logical address of the connection where CEC frame can be sent.
163  * @param[in] frame CEC Frame which is a byte stream that contains raw bytes.
164  *
165  * @return None.
166  */
167 void Connection::sendToAsync(const LogicalAddress &to, const CECFrame &frame)
168 {
169  CECFrame fullFrame;
170  Header header(source, to);
171  header.serialize(fullFrame);
172  fullFrame.append(frame);
173  sendAsync(fullFrame);
174 }
175 
176 /**
177  * @brief This function is used to send CEC frame to CEC Bus.
178  *
179  * @param[in] frame CEC Frame which is a byte stream that contains raw bytes.
180  * @param[in] timeout It is an upper bound on the amount of time to wait so that the application will not hang during sending.
181  *
182  * @return None.
183  */
184 void Connection::send(const CECFrame &frame, int timeout)
185 {
186  CCEC_LOG( LOG_DEBUG, "Sending out from Connection with timeout %d ms\r\n", timeout);
187  //@TODO: Need to enforce frame's source == connection.source?
188  matchSource(frame);
189  try
190  {
191  bus.send(frame, timeout);
192  }
193  catch(Exception &e)
194  {
195  //CCEC_LOG( LOG_EXP, "Capturing Exception in send and Not sending upwards :: %s\r\n",e.what());
196  }
197 }
198 
199 /**
200  * @brief This function is used to send CEC frame to CEC Bus.
201  *
202  * @param[in] frame CEC Frame which is a byte stream that contains raw bytes.
203  * @param[in] timeout It is an upper bound on the amount of time to wait so that the application will not hang during sending.
204  * @param[in] doThrow Throw an exception if the CEC frame is unable to send.
205  *
206  * @return None.
207  */
208 void Connection::send(const CECFrame &frame, int timeout, const Throw_e &doThrow)
209 {
210  CCEC_LOG( LOG_DEBUG, "Sending out from Connection\r\n");
211  //@TODO: Need to enforce frame's source == connection.source?
212  matchSource(frame);
213  try
214  {
215  bus.send(frame, timeout);
216  }
217  catch(Exception &e)
218  {
219  //CCEC_LOG(LOG_EXP, "Catch and re-throw Exception from send\r\n");
220  throw;
221  }
222 }
223 
224 /**
225  * @brief This function is used to send poll message to the Bus.
226  *
227  * @param[in] logical address of Initiator, in case of poll the initiator and follower is same.
228 * @param[in] doThrow Throw an exception if there is NACK received.
229  *
230  * @return None.
231  */
232 void Connection::poll(const LogicalAddress &from, const Throw_e &doThrow)
233 {
234  CCEC_LOG( LOG_DEBUG, "Polling\r\n");
235  //@TODO: Need to enforce frame's source == connection.source?
236 
237  try
238  {
239  /* polling both initator and follower is same*/
240  bus.poll(from, from);
241  }
242  catch(Exception &e)
243  {
244  //CCEC_LOG(LOG_EXP, "Catch and re-throw Exception from send\r\n");
245  throw;
246  }
247 }
248 
249 /**
250  * @brief This function is used to send ping message to the Bus.
251  *
252  * @param[in] logical address of Initiator, in case of ping the initiator and follower should be different.
253 * @param[in] doThrow Throw an exception if there is NACK received.
254  *
255  * @return None.
256  */
257 void Connection::ping(const LogicalAddress &from, const LogicalAddress &to, const Throw_e &doThrow)
258 {
259  CCEC_LOG( LOG_DEBUG, "Polling\r\n");
260  //@TODO: Need to enforce frame's source == connection.source?
261 
262  try
263  {
264  /* Ping initator and follower should be different*/
265  bus.ping(from, to);
266  }
267  catch(Exception &e)
268  {
269  //CCEC_LOG(LOG_EXP, "Catch and re-throw Exception from send\r\n");
270  throw;
271  }
272 }
273 
274 
275 
276 /**
277  * @brief This function is used to send the CEC frame to physical CEC Bus using asynchronous method.
278  *
279  * @param[in] frame CEC Frame which is a byte stream that contains raw bytes.
280  *
281  * @return None.
282  */
283 void Connection::sendAsync(const CECFrame &frame)
284 {
285  CCEC_LOG( LOG_DEBUG, "Sending out from Connection\r\n");
286  matchSource(frame);
287  bus.sendAsync(frame);
288 }
289 
290 /**
291  * @brief Check the filtered is set for this connection.
292  *
293  * All incoming CECFrame arrived at the Physical CEC bus will be dispatched to all opened connections,
294  * based on the filtering criteria of the connection.
295  *
296  * @param[in] frame CEC Frame which is a byte stream that contains raw bytes.
297  *
298  * @return TRUE if the filter is set for the CEC Connection, otherwise return FALSE.
299  */
301 {
302  bool filtered = true;
303 
304  if (source == LogicalAddress(LogicalAddress::UNREGISTERED)) {
305  filtered = false;
306  }
307  else {
308  Header header(frame);
309  if ((header.to == LogicalAddress(LogicalAddress::BROADCAST)) ||
310  (header.to == source)) {
311  filtered = false;
312  }
313  else {
314  filtered = true;
315  }
316  }
317 
318  return filtered;
319 }
320 
321 /**
322  * @brief Notify to the application if CECFrame is received. The CEC frame contains the raw bytes.
323  *
324  * @param[in] frame CEC Frame which is a byte stream that contains raw bytes.
325  *
326  * @return None.
327  */
329 {
330  {AutoLock lock_(connection.mutex);
331  if (!filter.isFiltered(frame)) {
332  std::list<FrameListener *>::iterator list_it;
333  for(list_it = connection.frameListeners.begin(); list_it!= connection.frameListeners.end(); list_it++) {
334  CCEC_LOG( LOG_DEBUG, "connection [%s] frame Listeners notify Listener\r\n", connection.name.c_str());
335  (*list_it)->notify(frame);
336  }
337  }
338  else {
339  Header header(frame);
340  }
341  }
342 }
343 
344 /**
345  * @brief Match the source address and update the logical address for the Connection.
346  *
347  * @param[in] frame CEC Frame which is a byte stream that contains raw bytes.
348  *
349  * @return None.
350  */
352 {
353  //@TODO: use Header.from/to to do filtering, instead of raw bytes
354  if (Driver::getInstance().isValidLogicalAddress(source)) {
355  CCEC_LOG( LOG_DEBUG, "Mathing source to %s\r\n", source.toString().c_str());
356 
357  const uint8_t *buf = frame.getBuffer();
358  CCEC_LOG( LOG_DEBUG, "Has source to %x\r\n", (buf[0] >> 4) & 0x0F);
359 
360  if (((buf[0] >> 4) & 0x0F) != (source.toInt() & 0x0F)) {
361  CCEC_LOG( LOG_ERROR, "Altering Initiator to match connection source\r\n");
362  ((uint8_t *)buf)[0] = ((buf[0] & 0x0F) | ((source.toInt() & 0x0F) << 4));
363  }
364  }
365 }
366 
367 CCEC_END_NAMESPACE
368 
369 
370 /** @} */
371 /** @} */
CCEC_OSAL::AutoLock
Definition: Mutex.hpp:121
Connection::send
void send(const CECFrame &frame, int timeout, const Throw_e &doThrow)
This function is used to send CEC frame to CEC Bus.
Definition: Connection.cpp:208
_Throw_e
Definition: Exception.hpp:37
FrameListener
Definition: FrameListener.hpp:39
Bus::removeFrameListener
void removeFrameListener(FrameListener *listener)
This function is used to remove the listener.
Definition: Bus.cpp:222
Connection::close
void close(void)
Definition: Connection.cpp:73
LogicalAddress
Definition: Operands.hpp:409
Connection::ping
void ping(const LogicalAddress &from, const LogicalAddress &to, const Throw_e &doThrow)
This function is used to send ping message to the Bus.
Definition: Connection.cpp:257
Connection::open
void open(void)
Open a connection to receive CEC packets from the bus.
Definition: Connection.cpp:62
Bus::poll
void poll(const LogicalAddress &from, const LogicalAddress &to)
This function is used to poll the logical address and returns the ACK or NACK received from other dev...
Definition: Bus.cpp:396
Connection::poll
void poll(const LogicalAddress &from, const Throw_e &doThrow)
This function is used to send poll message to the Bus.
Definition: Connection.cpp:232
Connection::sendAsync
void sendAsync(const CECFrame &frame)
This function is used to send the CEC frame to physical CEC Bus using asynchronous method.
Definition: Connection.cpp:283
Connection::addFrameListener
void addFrameListener(FrameListener *listener)
This function is used to listen for CECFrame, which is a byte stream that contains raw bytes received...
Definition: Connection.cpp:88
Connection::removeFrameListener
void removeFrameListener(FrameListener *listener)
This function is used to remove the listener information from the queue.
Definition: Connection.cpp:104
Bus::sendAsync
void sendAsync(const CECFrame &frame)
This function is used to keep asynchronously sending the frame by keeping copy of cec frame in the qu...
Definition: Bus.cpp:373
Connection::sendToAsync
void sendToAsync(const LogicalAddress &to, const CECFrame &frame)
sends HDMI-CEC frame to CEC Bus using asynchronized method.
Definition: Connection.cpp:167
Header
Definition: Header.hpp:41
Connection::sendTo
void sendTo(const LogicalAddress &to, const CECFrame &frame, int timeout, const Throw_e &doThrow)
This function is used to send CEC frame to CEC Bus.
Definition: Connection.cpp:141
Connection::DefaultFilter::isFiltered
bool isFiltered(const CECFrame &frame)
Check the filtered is set for this connection.
Definition: Connection.cpp:300
Connection::matchSource
void matchSource(const CECFrame &frame)
Match the source address and update the logical address for the Connection.
Definition: Connection.cpp:351
Bus
Definition: Bus.hpp:53
Connection::DefaultFrameListener::notify
void notify(const CECFrame &frame) const
Notify to the application if CECFrame is received. The CEC frame contains the raw bytes.
Definition: Connection.cpp:328
Bus::addFrameListener
void addFrameListener(FrameListener *listener)
This function is used to add new listener for reading frames.
Definition: Bus.cpp:207
Bus::send
void send(const CECFrame &frame, int timeout=0)
This function is used to write the frame to the driver. If it fails, as it is a synchronous function,...
Definition: Bus.cpp:325
Exception
Definition: Exception.hpp:42
CECFrame
Definition: CECFrame.hpp:40
Bus::ping
void ping(const LogicalAddress &from, const LogicalAddress &to)
This function is used to ping devices, to know whether it present and returns the ACK or NACK receive...
Definition: Bus.cpp:423
CCEC_LOG
void CCEC_LOG(int level, const char *format ...)
This function is used to gets the logs depending on the level of log and print these to standard outp...
Definition: Util.cpp:120