1 /*
2  * This file is part of the libCEC(R) library.
3  *
4  * libCEC(R) is Copyright (C) 2011-2015 Pulse-Eight Limited.  All rights reserved.
5  * libCEC(R) is an original work, containing original code.
6  *
7  * libCEC(R) is a trademark of Pulse-Eight Limited.
8  *
9  * This program is dual-licensed; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301  USA
23  *
24  *
25  * Alternatively, you can license this library under a commercial license,
26  * please contact Pulse-Eight Licensing for more information.
27  *
28  * For more information contact:
29  * Pulse-Eight Licensing       <license@pulse-eight.com>
30  *     http://www.pulse-eight.com/
31  *     http://www.pulse-eight.net/
32  */
33 
34 #include "env.h"
35 #include "RLCommandHandler.h"
36 
37 #include "p8-platform/util/timeutils.h"
38 #include "devices/CECBusDevice.h"
39 #include "CECProcessor.h"
40 #include "LibCEC.h"
41 #include "CECClient.h"
42 
43 using namespace CEC;
44 using namespace P8PLATFORM;
45 
46 #define RL_KEY_TOP_MENU           0x10
47 #define RL_KEY_DVD_MENU           0x11
48 
CRLCommandHandler(CCECBusDevice * busDevice,int32_t iTransmitTimeout,int32_t iTransmitWait,int8_t iTransmitRetries,int64_t iActiveSourcePending)49 CRLCommandHandler::CRLCommandHandler(CCECBusDevice *busDevice,
50                                      int32_t iTransmitTimeout /* = CEC_DEFAULT_TRANSMIT_TIMEOUT */,
51                                      int32_t iTransmitWait /* = CEC_DEFAULT_TRANSMIT_WAIT */,
52                                      int8_t iTransmitRetries /* = CEC_DEFAULT_TRANSMIT_RETRIES */,
53                                      int64_t iActiveSourcePending /* = 0 */) :
54     CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending)
55 {
56   m_vendorId = CEC_VENDOR_TOSHIBA;
57 }
58 
InitHandler(void)59 bool CRLCommandHandler::InitHandler(void)
60 {
61   if (m_bHandlerInited)
62     return true;
63   m_bHandlerInited = true;
64 
65   if (m_busDevice->GetLogicalAddress() != CECDEVICE_TV)
66     return true;
67 
68   CCECBusDevice *primary = m_processor->GetPrimaryDevice();
69   if (primary && primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED)
70   {
71     /* imitate Toshiba devices */
72     if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
73     {
74       primary->SetVendorId(CEC_VENDOR_TOSHIBA);
75       primary->ReplaceHandler(false);
76     }
77 
78     if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
79     {
80       /* send the vendor id */
81       primary->TransmitVendorID(CECDEVICE_BROADCAST, false, false);
82     }
83   }
84 
85   return true;
86 }
87 
HandleDeviceVendorCommandWithId(const cec_command & command)88 int CRLCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command)
89 {
90   if (!m_processor->IsHandledByLibCEC(command.destination) && command.destination != CECDEVICE_BROADCAST)
91     return CEC_ABORT_REASON_INVALID_OPERAND;
92 
93   if (command.parameters.size < 4)
94     return CEC_ABORT_REASON_INVALID_OPERAND;
95 
96   // check whether the vendor id matches
97   if (command.parameters[0] != 0x00 ||
98       command.parameters[1] != 0x00 ||
99       command.parameters[2] != 0x39)
100     return CEC_ABORT_REASON_INVALID_OPERAND;
101 
102   bool bHandled(false);
103   CECClientPtr client = m_processor->GetClient(command.destination);
104   if (client)
105   {
106     switch (command.parameters[3])
107     {
108     // user control pressed
109     case CEC_OPCODE_USER_CONTROL_PRESSED:
110       if (command.parameters.size == 5)
111       {
112         bHandled = true;
113         switch (command.parameters[4])
114         {
115         // top menu
116         case RL_KEY_TOP_MENU:
117           client->SetCurrentButton(CEC_USER_CONTROL_CODE_TOP_MENU);
118           break;
119         // dvd menu
120         case RL_KEY_DVD_MENU:
121           client->SetCurrentButton(CEC_USER_CONTROL_CODE_DVD_MENU);
122           break;
123         default:
124           bHandled = false;
125           break;
126         }
127       }
128       break;
129     // user control released
130     case CEC_OPCODE_USER_CONTROL_RELEASE:
131       client->AddKey();
132       bHandled = true;
133       break;
134     default:
135       break;
136     }
137   }
138 
139   return bHandled ?
140       COMMAND_HANDLED :
141       CCECCommandHandler::HandleDeviceVendorCommandWithId(command);
142 }
143