summaryrefslogtreecommitdiff
path: root/tvapi/libtv/tvin/CHDMIRxCEC.cpp (plain)
blob: 0b261d60b325bb692ed4c11f47d07f216eb22035
1
2#include "CHDMIRxCEC.h"
3#include <fcntl.h>
4#include <sys/ioctl.h>
5#include <errno.h>
6#include <CTvLog.h>
7
8#include "../tvconfig/tvconfig.h"
9
10#define CC_ENABLE_PRINT_MESSAGE (0)
11
12#define CS_HDMIRX_CEC_PATH "/dev/hdmirx0"
13
14CHDMIRxCEC::CHDMIRxCEC()
15{
16 int i = 0;
17
18 for (i = 0; i < CC_REQUEST_LIST_SIZE; i++) {
19 ClrReplyListItem(&mReplyList[i]);
20 memset((void *) &mMsgBuf[i], 0, sizeof(struct _cec_msg));
21 }
22
23 mModuleEnableFlag = -1;
24 mRequestPause = false;
25 mState = STATE_STOPED;
26
27 mpObserver = NULL;
28
29 for (i = 0; i < CC_SOURCE_DEV_REFRESH_CNT; i++) {
30 mSourceDevLogicAddrBuf[i] = -1;
31 mSourceDevRefreshBuf[i] = -1;
32 }
33
34 mSourceDevLogicAddrBuf[0] = E_LA_TV;
35 mSourceDevLogicAddrBuf[1] = E_LA_TV;
36 mSourceDevLogicAddrBuf[2] = E_LA_TV;
37
38 mSourceDevRefreshBuf[0] = E_LA_PLAYBACK1;
39 mSourceDevRefreshBuf[1] = E_LA_PLAYBACK2;
40 mSourceDevRefreshBuf[2] = E_LA_PLYBACK3;
41}
42
43CHDMIRxCEC::~CHDMIRxCEC()
44{
45}
46
47int CHDMIRxCEC::start()
48{
49 CMutex::Autolock _l (mLock);
50
51 if (GetModuleEnableFlag() == 0) {
52 return -1;
53 }
54
55 if (mState == STATE_STOPED) {
56 this->run();
57 }
58
59 return mState;
60}
61
62int CHDMIRxCEC::stop()
63{
64 CMutex::Autolock _l (mLock);
65
66 if (GetModuleEnableFlag() == 0) {
67 return -1;
68 }
69
70 if (mState == STATE_PAUSE) {
71 resume();
72 }
73
74 requestExit();
75 mState = STATE_STOPED;
76 return mState;
77}
78
79int CHDMIRxCEC::pause()
80{
81 CMutex::Autolock _l (mLock);
82
83 if (GetModuleEnableFlag() == 0) {
84 return -1;
85 }
86
87 mRequestPause = true;
88 return 0;
89}
90
91int CHDMIRxCEC::resume()
92{
93 CMutex::Autolock _l (mLock);
94
95 if (GetModuleEnableFlag() == 0) {
96 return -1;
97 }
98
99 ClearRxMessageBuffer();
100
101 mRequestPause = false;
102 mPauseCondition.signal();
103
104 ClearRxMessageBuffer();
105 return 0;
106}
107
108int CHDMIRxCEC::isAllowOperate(int source_input)
109{
110 if (GetModuleEnableFlag() == 0) {
111 return -1;
112 }
113
114 int source_port = CTvin::Tvin_GetSourcePortBySourceInput((tv_source_input_t)source_input);
115 if (CTvin::getInstance()->VDIN_GetPortConnect(source_port) == false) {
116 return -1;
117 }
118
119 return 0;
120}
121
122int CHDMIRxCEC::GetModuleEnableFlag()
123{
124 const char *config_value = NULL;
125
126 if (mModuleEnableFlag < 0) {
127 config_value = config_get_str(CFG_SECTION_TV, "tvin.hdmirx.cec.enable", "null");
128 if (strcasecmp(config_value, "null") == 0) {
129 mModuleEnableFlag = 0;
130 } else if (strcasecmp(config_value, "1") == 0 || strcasecmp(config_value, "true") == 0) {
131 mModuleEnableFlag = 1;
132 } else {
133 mModuleEnableFlag = 0;
134 }
135 }
136
137 return mModuleEnableFlag;
138}
139
140int CHDMIRxCEC::PrintMessage(const char *func_name, int data_type, struct _cec_msg *msg)
141{
142#ifdef CC_ENABLE_PRINT_MESSAGE
143 if (msg == NULL) {
144 LOGE("%s, msg is NULL\n", func_name);
145 return -1;
146 }
147
148 LOGD("%s, msg_len = %d\n", func_name, msg->msg_len);
149 LOGD("%s, msg addr 0x%02X\n", func_name, msg->addr);
150 LOGD("%s, msg cmd 0x%02X\n", func_name, msg->cmd);
151 for (int i = 0; i < msg->msg_len - 2; i++) {
152 if (data_type == 0) {
153 LOGD("%s, msg data[%d] = 0x%02X\n", func_name, i, msg->msg_data[i]);
154 } else {
155 LOGD("%s, msg data[%d] = %c\n", func_name, i, msg->msg_data[i]);
156 }
157 }
158#endif
159 return 0;
160}
161
162int CHDMIRxCEC::ClrReplyListItem(HDMIRxRequestReplyItem *reply_item)
163{
164 if (reply_item == NULL) {
165 return -1;
166 }
167
168 reply_item->WaitCmd = 0;
169 reply_item->WaitLogicAddr = 0;
170 reply_item->WaitTimeOut = 0;
171 reply_item->WaitFlag = 0;
172 reply_item->DataFlag = 0;
173 memset((void *) & (reply_item->msg), 0, sizeof(struct _cec_msg));
174
175 return 0;
176}
177
178int CHDMIRxCEC::CopyMessageData(unsigned char data_buf[], unsigned char msg_data[], int msg_len)
179{
180 if (data_buf == NULL) {
181 return 0;
182 }
183
184 memset((void *)data_buf, 0, CC_CEC_STREAM_SIZE);
185
186 if (msg_len > CC_CEC_STREAM_SIZE) {
187 return 0;
188 }
189
190 if (msg_len <= 2) {
191 return 0;
192 }
193
194 msg_len -= 2;
195
196 memcpy(data_buf, msg_data, msg_len);
197
198 return msg_len;
199}
200
201int CHDMIRxCEC::GetDeviceLogicAddr(int source_input)
202{
203 return mSourceDevLogicAddrBuf[source_input - SOURCE_HDMI1];
204}
205
206int CHDMIRxCEC::processRefreshSrcDevice(int source_input)
207{
208 int i = 0, physical_addr = 0;
209 int source_port_1 = 0, source_port_2 = 0;
210
211 if (source_input != SOURCE_HDMI1 && source_input != SOURCE_HDMI2 && source_input != SOURCE_HDMI3) {
212 return -1;
213 }
214
215 mSourceDevLogicAddrBuf[0] = E_LA_TV;
216 mSourceDevLogicAddrBuf[1] = E_LA_TV;
217 mSourceDevLogicAddrBuf[2] = E_LA_TV;
218
219 for (i = 0; i < CC_SOURCE_DEV_REFRESH_CNT; i++) {
220 if (mSourceDevRefreshBuf[i] < 0) {
221 continue;
222 }
223
224 physical_addr = 0;
225 if (SendGivePhysicalAddressMessage(source_input, mSourceDevRefreshBuf[i], &physical_addr) > 0) {
226 source_port_1 = CTvin::Tvin_GetSourcePortBySourceInput((tv_source_input_t)source_input);
227 source_port_2 = CTvin::Tvin_GetSourcePortByCECPhysicalAddress(physical_addr);
228 if (source_port_1 == source_port_2) {
229 mSourceDevLogicAddrBuf[source_input - SOURCE_HDMI1] = mSourceDevRefreshBuf[i];
230 break;
231 }
232 }
233 }
234
235 if (i == CC_SOURCE_DEV_REFRESH_CNT) {
236 return -1;
237 }
238
239 return 0;
240}
241
242int CHDMIRxCEC::ClearRxMessageBuffer()
243{
244 int m_cec_dev_fd = -1;
245
246 m_cec_dev_fd = open(CS_HDMIRX_CEC_PATH, O_RDWR);
247 if (m_cec_dev_fd < 0) {
248 LOGE("%s, Open file %s error: (%s)!\n", __FUNCTION__, CS_HDMIRX_CEC_PATH, strerror ( errno ));
249 return -1;
250 }
251
252 ioctl(m_cec_dev_fd, HDMI_IOC_CEC_CLEAR_BUFFER, NULL);
253
254 close(m_cec_dev_fd);
255 m_cec_dev_fd = -1;
256
257 return 0;
258}
259
260int CHDMIRxCEC::GetMessage(struct _cec_msg msg_buf[])
261{
262 int i = 0;
263 int m_cec_dev_fd = -1;
264 int msg_cnt = 0;
265
266 if (msg_buf == NULL) {
267 LOGE("%s, msg_buf is NULL\n", __FUNCTION__);
268 }
269
270 m_cec_dev_fd = open(CS_HDMIRX_CEC_PATH, O_RDWR);
271 if (m_cec_dev_fd < 0) {
272 LOGE("%s, Open file %s error: (%s)!\n", __FUNCTION__, CS_HDMIRX_CEC_PATH, strerror ( errno ));
273 return 0;
274 }
275
276 ioctl(m_cec_dev_fd, HDMI_IOC_CEC_GET_MSG_CNT, &msg_cnt);
277 if (msg_cnt > 0) {
278 LOGD("%s, msg_cnt = %d\n", __FUNCTION__, msg_cnt);
279
280 for (i = 0; i < msg_cnt; i++) {
281 ioctl(m_cec_dev_fd, HDMI_IOC_CEC_GET_MSG, &msg_buf[i]);
282 PrintMessage(__FUNCTION__, 0, &msg_buf[i]);
283 }
284 }
285
286 close(m_cec_dev_fd);
287 m_cec_dev_fd = -1;
288
289 return msg_cnt;
290}
291
292
293int CHDMIRxCEC::SendMessage(struct _cec_msg *msg)
294{
295 int m_cec_dev_fd = -1;
296
297 if (msg == NULL) {
298 LOGE("%s, msg is NULL\n", __FUNCTION__);
299 }
300
301 PrintMessage(__FUNCTION__, 0, msg);
302
303 m_cec_dev_fd = open(CS_HDMIRX_CEC_PATH, O_RDWR);
304 if (m_cec_dev_fd < 0) {
305 LOGE("%s, Open file %s error: (%s)!\n", __FUNCTION__, CS_HDMIRX_CEC_PATH, strerror ( errno ));
306 return -1;
307 }
308
309 ioctl(m_cec_dev_fd, HDMI_IOC_CEC_SENT_MSG, msg);
310
311 close(m_cec_dev_fd);
312 m_cec_dev_fd = -1;
313
314 return 0;
315}
316
317int CHDMIRxCEC::sendMessageAndWaitReply(struct _cec_msg *msg, struct _cec_msg *reply_msg, int WaitCmd, int timeout)
318{
319 int tmp_ret = 0, tmp_ind = 0;
320
321 tmp_ret = SendMessage(msg);
322 if (tmp_ret < 0) {
323 return tmp_ret;
324 }
325
326 reply_msg->msg_len = 0;
327
328 HDMIRxRequestReplyItem reply_item;
329 reply_item.WaitCmd = WaitCmd;
330 reply_item.WaitLogicAddr = msg->addr;
331 reply_item.WaitTimeOut = timeout;
332 reply_item.WaitFlag = 1;
333 reply_item.DataFlag = 0;
334
335 tmp_ind = addToRequestList(&reply_item);
336
337 mReplyLock[tmp_ind].lock();
338 mReplyList[tmp_ind].WaitReplyCondition.waitRelative(mReplyLock[tmp_ind], timeout);//wait reply
339 mReplyLock[tmp_ind].unlock();
340
341 if (mReplyList[tmp_ind].DataFlag == 1) {
342 PrintMessage(__FUNCTION__, 0, &mReplyList[tmp_ind].msg);
343 *reply_msg = mReplyList[tmp_ind].msg;
344 } else {
345 rmFromRequestList(tmp_ind);
346 return -1;
347 }
348
349 rmFromRequestList(tmp_ind);
350
351 return 0;
352}
353
354int CHDMIRxCEC::SendCustomMessage(int source_input, unsigned char data_buf[])
355{
356 CECMsgStream msg_stream;
357
358 if (isAllowOperate(source_input) < 0) {
359 return -1;
360 }
361
362 memcpy((void *)msg_stream.buf, data_buf, CC_CEC_STREAM_SIZE);
363 if (msg_stream.msg.msg_len > CC_CEC_STREAM_SIZE) {
364 return -1;
365 }
366
367 return SendMessage(&msg_stream.msg);
368}
369
370int CHDMIRxCEC::SendCustomMessageAndWaitReply(int source_input, unsigned char data_buf[], unsigned char reply_buf[], int WaitCmd, int timeout)
371{
372 CECMsgStream msg_stream;
373 struct _cec_msg reply_msg;
374
375 if (isAllowOperate(source_input) < 0) {
376 return -1;
377 }
378
379 memcpy((void *)msg_stream.buf, data_buf, CC_CEC_STREAM_SIZE);
380 if (msg_stream.msg.msg_len > CC_CEC_STREAM_SIZE) {
381 return -1;
382 }
383
384 if (sendMessageAndWaitReply(&msg_stream.msg, &reply_msg, WaitCmd, timeout) < 0) {
385 return -1;
386 }
387
388 return CopyMessageData(reply_buf, reply_msg.msg_data, reply_msg.msg_len);
389}
390
391int CHDMIRxCEC::SendBoradcastStandbyMessage(int source_input)
392{
393 struct _cec_msg msg;
394
395 if (isAllowOperate(source_input) < 0) {
396 return -1;
397 }
398
399 msg.addr = GetDeviceLogicAddr(source_input);
400 msg.cmd = E_MSG_STANDBY;
401 msg.msg_data[0] = 0;
402 msg.msg_len = 2;
403
404 return SendMessage(&msg);
405}
406
407int CHDMIRxCEC::SendGiveCECVersionMessage(int source_input, unsigned char data_buf[])
408{
409 struct _cec_msg msg, reply_msg;
410
411 if (isAllowOperate(source_input) < 0) {
412 return -1;
413 }
414
415 if (data_buf == NULL) {
416 return -1;
417 }
418
419 msg.addr = GetDeviceLogicAddr(source_input);
420 msg.cmd = E_MSG_GET_CEC_VERSION;
421 msg.msg_data[0] = 0;
422 msg.msg_len = 2;
423
424 if (sendMessageAndWaitReply(&msg, &reply_msg, E_MSG_CEC_VERSION, 2000) < 0) {
425 return -1;
426 }
427
428 return CopyMessageData(data_buf, reply_msg.msg_data, reply_msg.msg_len);
429}
430
431int CHDMIRxCEC::SendGiveDeviceVendorIDMessage(int source_input, unsigned char data_buf[])
432{
433 struct _cec_msg msg, reply_msg;
434
435 if (isAllowOperate(source_input) < 0) {
436 return -1;
437 }
438
439 if (data_buf == NULL) {
440 return -1;
441 }
442
443 msg.addr = GetDeviceLogicAddr(source_input);
444 msg.cmd = E_MSG_GIVE_DEVICE_VENDOR_ID;
445 msg.msg_data[0] = 0;
446 msg.msg_len = 2;
447
448 if (sendMessageAndWaitReply(&msg, &reply_msg, E_MSG_DEVICE_VENDOR_ID, 2000) < 0) {
449 return -1;
450 }
451
452 return CopyMessageData(data_buf, reply_msg.msg_data, reply_msg.msg_len);
453}
454
455int CHDMIRxCEC::SendGiveOSDNameMessage(int source_input, unsigned char data_buf[])
456{
457 struct _cec_msg msg, reply_msg;
458
459 if (isAllowOperate(source_input) < 0) {
460 return -1;
461 }
462
463 if (data_buf == NULL) {
464 return -1;
465 }
466
467 msg.addr = GetDeviceLogicAddr(source_input);
468 msg.cmd = E_MSG_OSDNT_GIVE_OSD_NAME;
469 msg.msg_data[0] = 0;
470 msg.msg_len = 2;
471
472 if (sendMessageAndWaitReply(&msg, &reply_msg, E_MSG_OSDNT_SET_OSD_NAME, 2000) < 0) {
473 return -1;
474 }
475
476 return CopyMessageData(data_buf, reply_msg.msg_data, reply_msg.msg_len);
477}
478
479int CHDMIRxCEC::SendGivePhysicalAddressMessage(int source_input, int logic_addr, int *physical_addr)
480{
481 struct _cec_msg msg, reply_msg;
482
483 if (isAllowOperate(source_input) < 0) {
484 return -1;
485 }
486
487 if (physical_addr == NULL) {
488 return -1;
489 }
490
491 msg.addr = logic_addr;
492 msg.cmd = E_MSG_GIVE_PHYSICAL_ADDRESS;
493 msg.msg_data[0] = 0;
494 msg.msg_len = 2;
495
496 if (sendMessageAndWaitReply(&msg, &reply_msg, E_MSG_REPORT_PHYSICAL_ADDRESS, 2000) < 0) {
497 return -1;
498 }
499
500 if (reply_msg.msg_len == 5) {
501 *physical_addr = 0;
502 *physical_addr |= reply_msg.msg_data[0] << 8;
503 *physical_addr |= reply_msg.msg_data[1];
504 return reply_msg.msg_len;
505 }
506
507 return -1;
508}
509
510int CHDMIRxCEC::SendSetMenuLanguageMessage(int source_input, unsigned char data_buf[])
511{
512 struct _cec_msg msg;
513
514 if (isAllowOperate(source_input) < 0) {
515 return -1;
516 }
517
518 if (data_buf == NULL) {
519 return -1;
520 }
521
522 msg.addr = GetDeviceLogicAddr(source_input);
523 msg.cmd = E_MSG_SET_MENU_LANGUAGE;
524 msg.msg_data[0] = data_buf[0];
525 msg.msg_data[1] = data_buf[1];
526 msg.msg_data[2] = data_buf[2];
527 msg.msg_len = 5;
528
529 return SendMessage(&msg);
530}
531
532int CHDMIRxCEC::SendVendorRemoteKeyDownMessage(int source_input, unsigned char key_val)
533{
534 struct _cec_msg msg;
535
536 if (isAllowOperate(source_input) < 0) {
537 return -1;
538 }
539
540 msg.addr = GetDeviceLogicAddr(source_input);
541 msg.cmd = E_MSG_VENDOR_RC_BUT_DOWN;
542 msg.msg_data[0] = key_val;
543 msg.msg_len = 3;
544
545 return SendMessage(&msg);
546}
547
548int CHDMIRxCEC::SendVendorRemoteKeyUpMessage(int source_input)
549{
550 struct _cec_msg msg;
551
552 if (isAllowOperate(source_input) < 0) {
553 return -1;
554 }
555
556 msg.addr = GetDeviceLogicAddr(source_input);
557 msg.cmd = E_MSG_VENDOR_RC_BUT_UP;
558 msg.msg_data[0] = 0;
559 msg.msg_len = 2;
560
561 return SendMessage(&msg);
562}
563
564int CHDMIRxCEC::rmFromRequestList(int index)
565{
566 mListLock.lock();
567
568 ClrReplyListItem(&mReplyList[index]);
569
570 mListLock.unlock();
571
572 return 0;
573}
574
575int CHDMIRxCEC::addToRequestList(HDMIRxRequestReplyItem *reply_item)
576{
577 int i = 0;
578
579 mListLock.lock();
580
581 for (i = 0; i < CC_REQUEST_LIST_SIZE; i++) {
582 if (mReplyList[i].WaitFlag == 0) {
583 mReplyList[i] = *reply_item;
584 mListLock.unlock();
585 return i;
586 }
587 }
588
589 mListLock.unlock();
590
591 return 0;
592}
593
594int CHDMIRxCEC::processData(int msg_cnt)
595{
596 int i = 0, j = 0;
597 CECMsgStream msg_stream;
598
599 for (i = 0; i < msg_cnt; i++) {
600 for (j = 0; j < CC_REQUEST_LIST_SIZE; j++) {
601 if (mReplyList[j].WaitFlag) {
602 if (mMsgBuf[i].cmd == mReplyList[j].WaitCmd && ((mMsgBuf[i].addr & 0xF0) >> 4) == mReplyList[j].WaitLogicAddr) {
603 mReplyList[j].DataFlag = 1;
604 mReplyList[j].msg = mMsgBuf[i];
605 PrintMessage(__FUNCTION__, 0, &mReplyList[j].msg);
606 mReplyList[j].WaitReplyCondition.signal();
607
608 return 0;
609 }
610 }
611 }
612
613 msg_stream.msg = mMsgBuf[i];
614 if (mpObserver != NULL) {
615 mpObserver->onHDMIRxCECMessage(msg_stream.msg.msg_len, msg_stream.buf);
616 }
617 }
618
619 return 0;
620}
621
622bool CHDMIRxCEC::threadLoop()
623{
624 int msg_cnt = 0;
625 int sleeptime = 200; //ms
626
627 mState = STATE_RUNNING;
628
629 while (!exitPending()) { //requietexit() or requietexitWait() not call
630 while (mRequestPause) {
631 mLock.lock();
632 mState = STATE_PAUSE;
633 mPauseCondition.wait(mLock); //first unlock,when return,lock again,so need,call unlock
634 mState = STATE_RUNNING;
635 mLock.unlock();
636 }
637
638 msg_cnt = GetMessage(mMsgBuf);
639
640 processData(msg_cnt);
641
642 if (!mRequestPause) {
643 usleep(sleeptime * 1000);
644 }
645 }
646
647 mState = STATE_STOPED;
648 //exit
649 //return true, run again, return false,not run.
650 return false;
651}
652