RDK Documentation (Open Sourced RDK Components)
DeviceManager.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 devmgr
25 * @{
26 **/
27 
28 
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 #include "ccec/LibCCEC.hpp"
33 #include "ccec/Assert.hpp"
34 #include "ccec/Messages.hpp"
35 #include "ccec/Connection.hpp"
36 #include "ccec/MessageEncoder.hpp"
37 #include "ccec/MessageDecoder.hpp"
38 #include "ccec/MessageProcessor.hpp"
39 #include "ccec/Util.hpp"
40 #include "ccec/Host.hpp"
41 
42 static CECHost_Err_t CECHost_HDMI_HotplugCallback_(int32_t connect);
43 static CECHost_Err_t CECHost_PowerStateCallback_ (int32_t curState, int32_t newState);
44 static CECHost_Err_t CECHost_DevMgrStatusCallback_(bool ipStatus,bool* opStatus);
45 static CECHost_Err_t CECHost_OSDNameCallback_(uint8_t *name, size_t len);
46 static CECHost_Err_t CECHost_PolicyCallback_(CECHost_Policy_t policy);
47 
48 
49 /*Avoiding currently unused variables and function to avoid compilation warnings*/
50 #if 0
51 /*Temporary change to allow power sync test*/
52 static int file_exists(const char *filename)
53 {
54  struct stat st;
55  memset(&st,0,sizeof(st));
56 
57  if (0 == stat(filename,&st))
58  {
59  if (S_ISREG(st.st_mode))
60  {
61  return 1;
62  }
63  }
64  return 0;
65 }
66 
67 static bool devMgrStatus = false;
68 static int32_t cecClntRefCounter = 0;
69 static pthread_mutex_t devMgrMutex = PTHREAD_MUTEX_INITIALIZER;
70 static CECHost_Policy_t policy = {
71  /*Default Policy*/
72  /*.turnOffTv = */0,
73  /*.turnOffSTB = */0,
74 };
75 #endif
76 
77 
78 /*
79  * Context/Cache
80  */
81 static Connection *conn_ = 0;
82 static int32_t isConnected = 0;
83 static PhysicalAddress phy(0,0,0,0);
84 static int32_t powerState = CECHost_POWERSTATE_STANDBY;
85 
86 #define MAX_LOGICAL_ADDRESS 14
87 #define MAX_LENGTH_OF_OSD_NAME 15
88 
89 /*
90  * *_Simple() are internal helper functions.
91  */
92 static std::string CECHost_GetOSDName_Simple(void)
93 {
94  uint8_t name[OSDName::MAX_LEN + 1] = {0};
95  size_t len = OSDName::MAX_LEN;
96  if (CECHost_GetOSDName(name, &len) == CECHost_ERR_NONE) {
97  /* NULL terminate the name for simplicity */
98  name[len] = '\0';
99  return (char *)name;
100  }
101  else {
102  return "SettopBox";
103  }
104 }
105 
106 static int32_t CECHost_IsActive_Simple(void)
107 {
108  int32_t active = 0;
109  CECHost_Err_t err = CECHost_IsActive(&active);
110  if ((err == CECHost_ERR_NONE) && active) {
111  return 1;
112  }
113  else {
114  return 0;
115  }
116 }
117 
118 static int32_t CECHost_HDMI_IsConnected_Simple(uint8_t *byte0 = 0, uint8_t *byte1 = 0, uint8_t *byte2 = 0, uint8_t *byte3 = 0)
119 {
120  int32_t connected = 0;
121  CECHost_Err_t err = CECHost_IsHdmiOutputConnected(&connected);
122  if ((err == CECHost_ERR_NONE) && connected) {
123  return 1;
124  }
125  else {
126  return 0;
127  }
128 }
129 
130 static int32_t CECHost_GetPowerState_Simple(void)
131 {
132  int32_t state = 0;
133  CECHost_Err_t ret = CECHost_GetPowerState(&state);
134  if (ret == CECHost_ERR_NONE) {
135  state = ((state == CECHost_POWERSTATE_ON) ? PowerStatus::ON : PowerStatus::STANDBY);
136  }
137  else {
138  state = PowerStatus::STANDBY;
139  }
140 
141  return state;
142 }
143 
145 {
146  public:
147  DevMgrProcessor(Connection &conn) : conn(conn) {}
148 
149  virtual void process (const RequestActiveSource &msg, const Header &header) {
150  if (!(header.from == LogicalAddress(LogicalAddress::BROADCAST))) {
151  {
152  if (CECHost_IsActive_Simple() && (CECHost_HDMI_CONNECTED == isConnected)) {
153  CCEC_LOG( LOG_DEBUG, "DevMgrProcessor:: Reporting ActiveSource\r\n");
154  conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(ActiveSource(phy)));
155  }
156  }
157  }
158  }
159 
160  virtual void process (const GiveOSDName &msg, const Header &header) {
161  if (!(header.from == LogicalAddress(LogicalAddress::BROADCAST))) {
162  CCEC_LOG( LOG_DEBUG, "DevMgrProcessor:: Reporting OSDName\r\n");
163  {
164  conn.sendTo(header.from, MessageEncoder().encode(SetOSDName(OSDName("STBSTB"))));
165  }
166  }
167  }
168 
169  virtual void process (const GiveDeviceVendorID &msg, const Header &header) {
170  if (!(header.from == LogicalAddress(LogicalAddress::BROADCAST))) {
171  {
172  CCEC_LOG( LOG_DEBUG, "DevMgrProcessor:: Reporting DeviceVendorID\r\n");
173  conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(DeviceVendorID(VendorID(0x0F, 0x0A, 0x0B))));
174  }
175  }
176  }
177 
178 
179  virtual void process (const GiveDevicePowerStatus &msg, const Header &header) {
180  if (!(header.from == LogicalAddress(LogicalAddress::BROADCAST))) {
181  {
182  CCEC_LOG( LOG_DEBUG, "DevMgrProcessor:: Reporting DevicePowerStatus\r\n");
183  conn.sendTo(header.from, MessageEncoder().encode(ReportPowerStatus(PowerStatus(powerState))));
184  }
185  }
186  }
187 
188  virtual void process (const GetCECVersion &msg, const Header &header) {
189  if (!(header.from == LogicalAddress(LogicalAddress::BROADCAST))) {
190  CCEC_LOG( LOG_DEBUG, "DevMgrProcessor:: Reporting CECVersion\r\n");
191  conn.sendTo(header.from, MessageEncoder().encode(CECVersion(Version::V_1_3a)));
192  }
193  }
194 
195  virtual void process (const GivePhysicalAddress &msg, const Header &header) {
196  if (!(header.from == LogicalAddress(LogicalAddress::BROADCAST))) {
197  {
198  CCEC_LOG( LOG_DEBUG, "DevMgrProcessor:: Reporting PhysicalAddress\r\n");
199  conn.sendTo(LogicalAddress(LogicalAddress::BROADCAST), MessageEncoder().encode(ReportPhysicalAddress(phy, DeviceType(DeviceType::TUNER))));
200  }
201  }
202  }
203 
204  virtual void process (const Standby &msg, const Header &header) {
205  }
206 
207  virtual void process (const SetMenuLanguage &msg, const Header &header) {
208  }
209 
210  virtual void process (const GetMenuLanguage &msg, const Header &header) {
211  }
212 
213  virtual void process (const ReportPowerStatus &msg, const Header &header) {
214  }
215 
216  virtual void process (const SetOSDName &msg, const Header &header) {
217  }
218 
219  private:
220  Connection &conn;
221 
222 };
223 
225 {
226 public:
227  DevMgrFrameListener(MessageProcessor &processor) : processor(processor) {}
228  void notify(const CECFrame &in) const {
229  MessageDecoder(processor).decode(in);
230  }
231  ~DevMgrFrameListener() {}
232 private:
233  MessageProcessor &processor;
234 };
235 
236 int main(int argc, char *argv[])
237 {
238  setvbuf(stdout, NULL, _IOLBF, 0);
240  CECHost_LoadPlugin();
241  CECHost_Init("CECDevMgr");
242 
243  CECHost_Callback_t cb = {
244  NULL,
245  CECHost_PowerStateCallback_,
246  NULL,
247  NULL,
248  NULL,
249  };
250 
252 
253  {
254  int32_t connected;
255  CCEC_LOG( LOG_WARN, "Calling CECHost_IsHdmiOutputConnected\r\n");
256  if (CECHost_IsHdmiOutputConnected(&connected) == CECHost_ERR_NONE) {
257  if (connected)
258  isConnected = CECHost_HDMI_CONNECTED;
259  else
260  isConnected = CECHost_HDMI_DISCONNECTED;
261  uint8_t byte0, byte1, byte2, byte3;
262  if (CECHost_GetHdmiOuputPhysicalAddress(&byte0, &byte1, &byte2, &byte3) == CECHost_ERR_NONE) {
263  phy = PhysicalAddress(byte0, byte1, byte2, byte3);
264  CCEC_LOG( LOG_WARN, "PhysicalAddress : %s\n", phy.toString().c_str());
265  }
266  else {
267  CCEC_LOG( LOG_WARN, "PhysicalAddress cannot be obtained: \n");
268  }
269  }
270 
271 
272  CCEC_LOG( LOG_WARN, "Calling CECHost_GetPowerState\r\n");
273  int32_t state;
274  if (CECHost_GetPowerState(&state) == CECHost_ERR_NONE) {
275  powerState = state;
276  }
277  else {
278  CCEC_LOG( LOG_WARN,"PowerState cannot be obtained: \n");
279  }
280 
281  }
282 
283  LibCCEC::getInstance().init("CECDevMgr");
284  Connection conn(LogicalAddress::TUNER_1, false, "CECDevMgr::Connection::");
285  conn_ = &conn;
286  conn.open();
287  {
288  DevMgrProcessor proc(conn);
289  DevMgrFrameListener frameListener(proc);
290  conn.addFrameListener(&frameListener);
291 
292  LogicalAddress source;
293  //CECHost_DeviceStatus_t devStatus;
294  while(1) {
295  static int j = 0 ;
296  /*Heart Beat in appx 150s*/
297  CCEC_LOG( LOG_WARN, "DevMgr Heartbeating %d\r\n", j++);
298  sleep(10); //imp: Need to recalculate sleep time once doNotPoll flag is disabled.
299  }
300  }
301 
302  conn.close();
303 
305 
306  CECHost_Term();
307  CECHost_UnloadPlugin();
308 
309 }
310 
311 static CECHost_Err_t CECHost_HDMI_HotplugCallback_(int32_t connect)
312 {
313  CCEC_LOG( LOG_WARN, "Dev Manager received Hot plug event \r\n");
314 
315  if(CECHost_HDMI_CONNECTED == connect)
316  {
317  uint8_t byte0, byte1, byte2, byte3;
318  if (CECHost_GetHdmiOuputPhysicalAddress(&byte0, &byte1, &byte2, &byte3) == CECHost_ERR_NONE) {
319  phy = PhysicalAddress(byte0, byte1, byte2, byte3);
320  CCEC_LOG( LOG_WARN, "PhysicalAddress : %s\n", phy.toString().c_str());
321  }
322  else {
323  CCEC_LOG( LOG_WARN, "PhysicalAddress cannot be obtained: \n");
324  }
325  isConnected = 1;
326  }
327  else {
328  isConnected = 0;
329  }
330  return CECHost_ERR_NONE;
331 
332 }
333 
334 
335 
336 static CECHost_Err_t CECHost_PowerStateCallback_(int32_t curState, int32_t newState)
337 {
338  if (newState == CECHost_POWERSTATE_ON) {
339  CCEC_LOG( LOG_DEBUG, "DevMgrProcessor:: Send ImageViewOn and ActiveSource\r\n");
340  conn_->sendTo(LogicalAddress::TV, MessageEncoder().encode(ImageViewOn()), 5000);
341  conn_->sendTo(LogicalAddress::TV, MessageEncoder().encode(ActiveSource(phy)), 5000);
342  }
343  else {
344  CCEC_LOG( LOG_DEBUG, "DevMgrProcessor:: Send InActiveSource\r\n");
345  conn_->sendToAsync(LogicalAddress::TV, MessageEncoder().encode(InActiveSource(phy)));
346  }
347 
348  powerState = newState;
349  return CECHost_ERR_NONE;
350 }
351 
352 /** @} */
353 
CECHost_GetPowerState
CECHost_Err_t CECHost_GetPowerState(int32_t *state)
This function is used to get the state of power whether it is ON or in STANDBY state.
Definition: Host.cpp:174
OSDName
Definition: Operands.hpp:135
CECHost_IsActive
CECHost_Err_t CECHost_IsActive(int32_t *active)
This function is used to check whether host device is active or not.
Definition: Host.cpp:231
MessageProcessor
The MessageProcessor class implements a set of overloaded process() methods, with each handling a spe...
Definition: MessageProcessor.hpp:58
GetCECVersion
Definition: Messages.hpp:161
VendorID
Definition: Operands.hpp:288
LibCCEC::getInstance
static LibCCEC & getInstance(void)
This function is used to create the instance for CEC.
Definition: LibCCEC.cpp:61
GiveOSDName
Definition: Messages.hpp:220
CECHost_IsHdmiOutputConnected
CECHost_Err_t CECHost_IsHdmiOutputConnected(int32_t *connect)
This function is used to check whether the HDMI output is connected or not.
Definition: Host.cpp:159
GiveDevicePowerStatus
Definition: Messages.hpp:334
FrameListener
Definition: FrameListener.hpp:39
SetOSDName
Definition: Messages.hpp:226
LibCCEC::init
void init(const char *name=0)
This function is used to initialize CEC by starting the driver and doing host-specific initialization...
Definition: LibCCEC.cpp:84
Connection
The connection class provides APIs that allows the application to access CEC Bus. A connection is a t...
Definition: Connection.hpp:57
DeviceVendorID
Definition: Messages.hpp:311
DevMgrProcessor
Definition: DeviceManager.cpp:144
LogicalAddress
Definition: Operands.hpp:409
Connection::open
void open(void)
Open a connection to receive CEC packets from the bus.
Definition: Connection.cpp:62
CECHost_GetHdmiOuputPhysicalAddress
CECHost_Err_t CECHost_GetHdmiOuputPhysicalAddress(uint8_t *byte0, uint8_t *byte1, uint8_t *byte2, uint8_t *byte3)
This function is used to get the physical address of the HDMI output port byte by byte.
Definition: Host.cpp:144
PhysicalAddress
Definition: Operands.hpp:314
GivePhysicalAddress
Definition: Messages.hpp:272
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
check_cec_log_status
void check_cec_log_status(void)
This function is used to get the cec log from the log file and checks the level of log received.
Definition: Util.cpp:75
CECHost_Term
CECHost_Err_t CECHost_Term(void)
This function is used to de-initialize CEC host device, disconnects and terminates the CEC connection...
Definition: Host.cpp:116
DeviceType
Definition: Operands.hpp:211
SetMenuLanguage
Definition: Messages.hpp:190
CECHost_SetCallback
CECHost_Err_t CECHost_SetCallback(CECHost_Callback_t cb)
This function is used to set the callback function. It is called by Device Manager application to set...
Definition: Host.cpp:130
Standby
Definition: Messages.hpp:155
MessageDecoder
When receiving the message, the raw bytes arrived in a CECFrame are converted to the corresponding Hi...
Definition: MessageDecoder.hpp:45
CECHost_GetOSDName
CECHost_Err_t CECHost_GetOSDName(uint8_t *name, size_t *len)
This function is used to get OSD name of Host module. Here 'buf' need not to be null terminated....
Definition: Host.cpp:216
MessageEncoder
High-level messages are encoded by the MessageEncoder into raw bytes and placed in a CECFrame.
Definition: MessageEncoder.hpp:46
CECHost_Init
CECHost_Err_t CECHost_Init(const char *name)
This function is used to initialize CEC host device by registering event handlers and calls like stat...
Definition: Host.cpp:101
ActiveSource
The Message API allows the application to send or receive high-level CEC message construct instead of...
Definition: Messages.hpp:88
GetMenuLanguage
Definition: Messages.hpp:214
DevMgrFrameListener
Definition: DeviceManager.cpp:224
GiveDeviceVendorID
Definition: Messages.hpp:305
PowerStatus
Definition: Operands.hpp:564
ReportPhysicalAddress
Definition: Messages.hpp:278
InActiveSource
Definition: Messages.hpp:125
RequestActiveSource
Definition: Messages.hpp:149
ImageViewOn
Definition: Messages.hpp:112
ReportPowerStatus
Definition: Messages.hpp:340
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
_CECHost_Callback_t
Definition: Host.hpp:102
LibCCEC::term
void term(void)
This function is used to stop CEC by terminating the connection and stoping the driver.
Definition: LibCCEC.cpp:111
_CECHost_Policy_t
Definition: Host.hpp:58
CECVersion
Definition: Messages.hpp:167