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