RDK Documentation (Open Sourced RDK Components)
DriverImpl.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 <stdlib.h>
30 #include <stdio.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <sys/select.h>
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <iostream>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <stdlib.h>
42 
43 #include "osal/EventQueue.hpp"
44 #include "osal/Exception.hpp"
45 #include "ccec/Util.hpp"
46 #include "ccec/Exception.hpp"
47 #include "DriverImpl.hpp"
48 #include "ccec/OpCode.hpp"
49 
51 
52 CCEC_BEGIN_NAMESPACE
53 
54 #include "ccec/driver/hdmi_cec_driver.h"
55 
56 size_t write(const unsigned char *buf, size_t len);
57 
58 void DriverImpl::DriverReceiveCallback(int handle, void *callbackData, unsigned char *buf, int len)
59 {
60  CECFrame *frame = new CECFrame();
61  frame->append((unsigned char *)buf, (size_t)len);
62 
63  CCEC_LOG( LOG_DEBUG, ">>>>>>> >>>>> >>>> >> >> >\r\n");
64 
65  dump_buffer((unsigned char*)buf,len);
66 
67  CCEC_LOG(LOG_DEBUG, "==========================\r\n");
68 
69  try {
70  static_cast<DriverImpl &>(Driver::getInstance()).getIncomingQueue(handle).offer(frame);
71  }
72  catch(...) {
73  CCEC_LOG( LOG_EXP, "Exception during frame offer...discarding\r\n");
74  }
75  CCEC_LOG( LOG_DEBUG, "frame offered\r\n");
76 }
77 
78 void DriverImpl::DriverTransmitCallback(int handle, void *callbackData, int result)
79 {
80  if (HDMI_CEC_IO_SUCCESS != result) {
81  CCEC_LOG( LOG_DEBUG, "======== HdmiCecSetTxCallback received. Result: %d\r\n", result);
82  }
83 }
84 
85 DriverImpl::DriverImpl() : status(CLOSED), nativeHandle(0)
86 {
87  CCEC_LOG( LOG_DEBUG, "Creating DriverImpl done\r\n");
88 }
89 
90 DriverImpl::~DriverImpl()
91 {
92  {AutoLock lock_(mutex);
93  if (status != CLOSED) {
94  this->close();
95  }
96  }
97 }
98 
99 void DriverImpl::open(void) throw(InvalidStateException, IOException)
100 {
101  {AutoLock lock_(mutex);
102  if (status != CLOSED) {
103  #if 0
104  throw InvalidStateException();
105  #else
106  return;
107  #endif
108  }
109 
110  int err = HdmiCecOpen(&nativeHandle);
111  if (err != HDMI_CEC_IO_SUCCESS) {
112  throw IOException();
113  }
114 
115  HdmiCecSetRxCallback(nativeHandle, DriverReceiveCallback, 0);
116  HdmiCecSetTxCallback(nativeHandle, DriverTransmitCallback, 0);
117  status = OPENED;
118  }
119 }
120 
121 void DriverImpl::close(void) throw(InvalidStateException, IOException)
122 {
123 
124  {AutoLock lock_(mutex);
125  if (status != OPENED) {
126  #if 0
127  throw InvalidStateException();
128  #else
129  return;
130  #endif
131  }
132  status = CLOSING;
133 
134  /* Use NULL as sentinel */
135  rQueue.offer(0);
136 
137  int err = HdmiCecClose(nativeHandle);
138  if (err != HDMI_CEC_IO_SUCCESS) {
139  throw IOException();
140  }
141 
142  status = CLOSED;
143  }
144 }
145 
146 void DriverImpl::read(CECFrame &frame) throw(InvalidStateException, IOException)
147 {
148  {AutoLock lock_(mutex);
149  if (status != OPENED) {
150  throw InvalidStateException();
151  }
152  }
153 
154  CCEC_LOG( LOG_DEBUG, "DriverImpl::Read()\r\n");
155 
156  bool backToPoll = false;
157  do {
158  backToPoll = false;
159 
160  CECFrame * inFrame = rQueue.poll();
161 
162  if (inFrame != 0) {
163  frame = *inFrame;
164  delete inFrame;
165  }
166  else {AutoLock lock_(mutex);
167 
168  if (status != OPENED) {
169  /* Flush and return */
170  while (rQueue.size() > 0) {
171  inFrame = rQueue.poll();
172  frame = *inFrame;
173  delete inFrame;
174  }
175  throw InvalidStateException();
176  }
177  else {
178  backToPoll = true;
179  }
180  }
181  } while(backToPoll);
182 }
183 
184 /*
185  * Only 1 write is allowed at a time. Queue the write request and wait for response.
186  */
187 void DriverImpl::writeAsync(const CECFrame &frame) throw(InvalidStateException, IOException, CECNoAckException)
188 {
189 
190  const uint8_t *buf = NULL;
191  size_t length = 0;
192 
193  frame.getBuffer(&buf, &length);
194  {AutoLock lock_(mutex);
195  if (status != OPENED) {
196  throw InvalidStateException();
197  }
198  CCEC_LOG( LOG_DEBUG, "DriverImpl::write to call HdmiCecTxAsync\r\n");
199 
200  int err = HdmiCecTxAsync(nativeHandle, buf, length);
201 
202  CCEC_LOG( LOG_DEBUG, ">>>>>>> >>>>> >>>> >> >> >\r\n");
203 
204  dump_buffer((unsigned char*)buf,length);
205 
206  CCEC_LOG(LOG_DEBUG, "==========================\r\n");
207 
208  CCEC_LOG( LOG_DEBUG, "DriverImpl:: call HdmiCecTxAsync %x\r\n", err);
209 
210  if (err != HDMI_CEC_IO_SUCCESS) {
211  throw IOException();
212  }
213 
214  }
215 
216  CCEC_LOG( LOG_DEBUG, "Send Async Completed\r\n");
217 }
218 
219 
220 /*
221  * Only 1 write is allowed at a time. Queue the write request and wait for response.
222  */
223 void DriverImpl::write(const CECFrame &frame) throw(InvalidStateException, IOException, CECNoAckException)
224 {
225 
226  const uint8_t *buf = NULL;
227  size_t length = 0;
228 
229  frame.getBuffer(&buf, &length);
230 
231  {AutoLock lock_(mutex);
232  if (status != OPENED) {
233  throw InvalidStateException();
234  }
235  int sendResult = HDMI_CEC_IO_SUCCESS;
236  CCEC_LOG( LOG_DEBUG, "DriverImpl::write to call HdmiCecTx\r\n");
237 
238  int err = HdmiCecTx(nativeHandle, buf, length, &sendResult);
239 
240  CCEC_LOG( LOG_DEBUG, ">>>>>>> >>>>> >>>> >> >> >\r\n");
241 
242  dump_buffer((unsigned char*)buf,length);
243 
244  CCEC_LOG(LOG_DEBUG, "==========================\r\n");
245 
246  CCEC_LOG( LOG_DEBUG, "DriverImpl:: call HdmiCecTx DONE %x, result %x\r\n", err, sendResult);
247 
248  if (err != HDMI_CEC_IO_SUCCESS) {
249  throw IOException();
250  }
251 
252  if (sendResult != HDMI_CEC_IO_SUCCESS) {
253  if ((sendResult == HDMI_CEC_IO_INVALID_STATE) ||
254  (sendResult == HDMI_CEC_IO_INVALID_ARGUMENT) ||
255  (sendResult == HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE) ||
256  (sendResult == HDMI_CEC_IO_SENT_FAILED) ||
257  (sendResult == HDMI_CEC_IO_GENERAL_ERROR) )
258  {
259  throw IOException();
260  }
261  }
262 
263  if (((frame.at(0) & 0x0F) != 0x0F) && sendResult == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) {
264  throw CECNoAckException();
265  }
266  /* CEC CTS 9-3-3 -Ensure that the DUT will accept a negatively for broadcat report physical address msg and retry atleast once */
267  else if (((frame.at(0) & 0x0F) == 0x0F) && (length > 1) && ((frame.at(1) & 0xFF) == REPORT_PHYSICAL_ADDRESS ) && (sendResult == HDMI_CEC_IO_SENT_BUT_NOT_ACKD))
268  {
269 
270  throw CECNoAckException();
271  }
272  }
273 
274  CCEC_LOG( LOG_DEBUG, "Send Completed\r\n");
275 }
276 
277 int DriverImpl::getLogicalAddress(int devType)
278 {
279  {AutoLock lock_(mutex);
280  int logicalAddress = 0;
281  CCEC_LOG( LOG_DEBUG, "DriverImpl::getLogicalAddress called for devType : %d \r\n", devType);
282 
283  HdmiCecGetLogicalAddress(nativeHandle,devType,&logicalAddress);
284 
285  CCEC_LOG( LOG_DEBUG, "DriverImpl::getLogicalAddress got logical Address : %d \r\n", logicalAddress);
286  return logicalAddress;
287  }
288 }
289 
290 void DriverImpl::getPhysicalAddress(unsigned int *physicalAddress)
291 {
292  {AutoLock lock_(mutex);
293  CCEC_LOG( LOG_DEBUG, "DriverImpl::getPhysicalAddress called \r\n");
294 
295  HdmiCecGetPhysicalAddress(nativeHandle,physicalAddress);
296 
297  CCEC_LOG( LOG_DEBUG, "DriverImpl::getPhysicalAddress got physical Address : %x \r\n", *physicalAddress);
298  return ;
299  }
300 }
301 
302 
303 void DriverImpl::removeLogicalAddress(const LogicalAddress &source)
304 {
305 // int LA[15] = {0};
306  {AutoLock lock_(mutex);
307  if (status != OPENED) {
308  throw InvalidStateException();
309  }
310 
311  logicalAddresses.remove(source);
312  HdmiCecRemoveLogicalAddress(nativeHandle, source.toInt());
313  }
314 }
315 
316 bool DriverImpl::addLogicalAddress(const LogicalAddress &source)
317 {
318  {AutoLock lock_(mutex);
319 
320  if (status != OPENED) {
321  throw InvalidStateException();
322  }
323 
324  int retErr = HdmiCecAddLogicalAddress(nativeHandle, source.toInt());
325 
326  if (retErr == HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE) {
328  }
329  else if (retErr == HDMI_CEC_IO_GENERAL_ERROR) {
330  throw IOException();
331  }
332  else {
333  logicalAddresses.push_back(source);
334  }
335  }
336 
337  return true;
338 }
339 
340 bool DriverImpl::isValidLogicalAddress(const LogicalAddress & source) const
341 {
342  bool found = false;
343  std::list<LogicalAddress>::const_iterator it;
344  for (it = logicalAddresses.begin(); it != logicalAddresses.end(); it++) {
345  if(*it == source) {
346  found = true;
347  break;
348  }
349  }
350 
351  return found;
352 }
353 
354 void DriverImpl::poll(const LogicalAddress &from, const LogicalAddress &to)
356 {
357  uint8_t firstByte = (((from.toInt() & 0x0F) << 4) | (to.toInt() & 0x0F));
358  CCEC_LOG( LOG_DEBUG, "$$$$$$$$$$$$$$$$$$$$ POST POLL [%s] [%s]$$$$$$$$$$$$$$$$$$$$$\r\n", from.toString().c_str(), to.toString().c_str());
359 
360  {
361  CECFrame frame;
362  frame.append(firstByte);
363  write(frame);
364  }
365 
366 #if 0
367  {
368  /* Send a Poll so indicate there is a device present */
369  CECFrame *frame = new CECFrame();
370  frame->append(firstByte);
371  rQueue.offer(frame);
372  }
373 #endif
374 }
375 
376 DriverImpl::IncomingQueue & DriverImpl::getIncomingQueue(int nativeHandle)
377 {
378  if (status != OPENED) {
379  throw InvalidStateException();
380  }
381 
382  return rQueue;
383 }
384 
385 CCEC_END_NAMESPACE
386 
387 
388 /** @} */
389 /** @} */
CCEC_OSAL::AutoLock
Definition: Mutex.hpp:121
HdmiCecSetRxCallback
int HdmiCecSetRxCallback(int handle, HdmiCecRxCallback_t cbfunc, void *data)
Sets CEC packet Receive callback.
Definition: hdmi_cec_driver.c:242
CECNoAckException
Definition: Exception.hpp:52
DriverImpl
Definition: DriverImpl.hpp:48
HdmiCecClose
int HdmiCecClose(int handle)
close an instance of CEC driver. This function should close the currently opened driver instance.
Definition: hdmi_cec_driver.c:106
EventQueue.hpp
This file defines interface of EventQueue class.
HdmiCecOpen
int HdmiCecOpen(int *handle)
opens an instance of CEC driver. This function should be call once before the functions in this API...
Definition: hdmi_cec_driver.c:68
IOException
Definition: Exception.hpp:71
dump_buffer
void dump_buffer(unsigned char *buf, int len)
This function is used to print the content of log buffer in hexadecimal format.
Definition: Util.cpp:142
LogicalAddress
Definition: Operands.hpp:409
HdmiCecGetLogicalAddress
int HdmiCecGetLogicalAddress(int handle, int devType, int *logicalAddresses)
Get the Logical Addresses claimed by host device.
Definition: hdmi_cec_driver.c:179
CCEC_OSAL::EventQueue
Definition: EventQueue.hpp:62
HdmiCecTx
int HdmiCecTx(int handle, const unsigned char *buf, int len, int *result)
Writes CEC packet onto bus.
Definition: hdmi_cec_driver.c:284
InvalidStateException
Definition: Exception.hpp:81
HdmiCecTxAsync
int HdmiCecTxAsync(int handle, const unsigned char *buf, int len)
Writes CEC packet onto bus asynchronously.
Definition: hdmi_cec_driver.c:268
HdmiCecGetPhysicalAddress
void HdmiCecGetPhysicalAddress(int handle, unsigned int *physicalAddresses)
Get the Physical Address obtained by the driver.
Definition: hdmi_cec_driver.c:211
CCEC_OSAL::EventQueue::offer
void offer(E element)
send an event to the queue.
Definition: EventQueue.hpp:167
HdmiCecRemoveLogicalAddress
int HdmiCecRemoveLogicalAddress(int handle, int logicalAddresses)
Clear the Logical Addresses claimed by host device.
Definition: hdmi_cec_driver.c:172
AddressNotAvailableException
Definition: Exception.hpp:99
HdmiCecAddLogicalAddress
int HdmiCecAddLogicalAddress(int handle, int logicalAddresses)
Add one Logical Addresses to be used by host device.
Definition: hdmi_cec_driver.c:146
HdmiCecSetTxCallback
int HdmiCecSetTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void *data)
Sets CEC packet Transmit callback.
Definition: hdmi_cec_driver.c:255
CECFrame
Definition: CECFrame.hpp:40
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