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 "CECDeviceMap.h"
36 
37 #include "CECAudioSystem.h"
38 #include "CECPlaybackDevice.h"
39 #include "CECRecordingDevice.h"
40 #include "CECTuner.h"
41 #include "CECTV.h"
42 #include "CECProcessor.h"
43 #include "CECTypeUtils.h"
44 
45 using namespace CEC;
46 
CCECDeviceMap(CCECProcessor * processor)47 CCECDeviceMap::CCECDeviceMap(CCECProcessor *processor) :
48     m_processor(processor)
49 {
50   for (uint8_t iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_BROADCAST; iPtr++)
51   {
52     switch(iPtr)
53     {
54     case CECDEVICE_AUDIOSYSTEM:
55       m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECAudioSystem(processor, (cec_logical_address) iPtr)));
56       break;
57     case CECDEVICE_PLAYBACKDEVICE1:
58     case CECDEVICE_PLAYBACKDEVICE2:
59     case CECDEVICE_PLAYBACKDEVICE3:
60       m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECPlaybackDevice(processor, (cec_logical_address) iPtr)));
61       break;
62     case CECDEVICE_RECORDINGDEVICE1:
63     case CECDEVICE_RECORDINGDEVICE2:
64     case CECDEVICE_RECORDINGDEVICE3:
65       m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECRecordingDevice(processor, (cec_logical_address) iPtr)));
66       break;
67     case CECDEVICE_TUNER1:
68     case CECDEVICE_TUNER2:
69     case CECDEVICE_TUNER3:
70     case CECDEVICE_TUNER4:
71       m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECTuner(processor, (cec_logical_address) iPtr)));
72       break;
73     case CECDEVICE_TV:
74       m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECTV(processor, (cec_logical_address) iPtr)));
75       break;
76     default:
77       m_busDevices.insert(std::make_pair<cec_logical_address, CCECBusDevice *>((cec_logical_address)iPtr, new CCECBusDevice(processor, (cec_logical_address) iPtr)));
78       break;
79     }
80   }
81 }
~CCECDeviceMap(void)82 CCECDeviceMap::~CCECDeviceMap(void)
83 {
84   Clear();
85 }
86 
Begin(void)87 CECDEVICEMAP::iterator CCECDeviceMap::Begin(void)
88 {
89   return m_busDevices.begin();
90 }
91 
End(void)92 CECDEVICEMAP::iterator CCECDeviceMap::End(void)
93 {
94   return m_busDevices.end();
95 }
96 
ResetDeviceStatus(void)97 void CCECDeviceMap::ResetDeviceStatus(void)
98 {
99   for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
100     it->second->ResetDeviceStatus();
101 }
102 
operator [](cec_logical_address iAddress) const103 CCECBusDevice *CCECDeviceMap::operator[] (cec_logical_address iAddress) const
104 {
105   return At(iAddress);
106 }
107 
operator [](uint8_t iAddress) const108 CCECBusDevice *CCECDeviceMap::operator[] (uint8_t iAddress) const
109 {
110   return At(iAddress);
111 }
112 
At(cec_logical_address iAddress) const113 CCECBusDevice *CCECDeviceMap::At(cec_logical_address iAddress) const
114 {
115   return At((uint8_t) iAddress);
116 }
117 
At(uint8_t iAddress) const118 CCECBusDevice *CCECDeviceMap::At(uint8_t iAddress) const
119 {
120   CECDEVICEMAP::const_iterator it = m_busDevices.find((cec_logical_address)iAddress);
121   if (it != m_busDevices.end())
122     return it->second;
123   return NULL;
124 }
125 
Clear(void)126 void CCECDeviceMap::Clear(void)
127 {
128   for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
129     delete it->second;
130   m_busDevices.clear();
131 }
132 
GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress,bool bSuppressUpdate)133 CCECBusDevice *CCECDeviceMap::GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress, bool bSuppressUpdate /* = true */)
134 {
135   CCECBusDevice *device(NULL);
136 
137   // check each device until we found a match
138   for (CECDEVICEMAP::iterator it = m_busDevices.begin(); !device && it != m_busDevices.end(); it++)
139   {
140     if (it->second->GetPhysicalAddress(m_processor->GetLogicalAddress(), bSuppressUpdate) == iPhysicalAddress)
141       device = it->second;
142   }
143 
144   return device;
145 }
146 
Get(CECDEVICEVEC & devices) const147 void CCECDeviceMap::Get(CECDEVICEVEC &devices) const
148 {
149   for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
150     devices.push_back(it->second);
151 }
152 
GetByLogicalAddresses(CECDEVICEVEC & devices,const cec_logical_addresses & addresses)153 void CCECDeviceMap::GetByLogicalAddresses(CECDEVICEVEC &devices, const cec_logical_addresses &addresses)
154 {
155   for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
156   {
157     if (addresses.IsSet(it->first))
158       devices.push_back(it->second);
159   }
160 }
161 
GetByType(const cec_device_type type,CECDEVICEVEC & devices) const162 void CCECDeviceMap::GetByType(const cec_device_type type, CECDEVICEVEC &devices) const
163 {
164   for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
165     if (it->second->GetType() == type)
166       devices.push_back(it->second);
167 }
168 
GetLibCECControlled(CECDEVICEVEC & devices) const169 void CCECDeviceMap::GetLibCECControlled(CECDEVICEVEC &devices) const
170 {
171   for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
172     if (it->second->IsHandledByLibCEC())
173       devices.push_back(it->second);
174 }
175 
GetActive(CECDEVICEVEC & devices) const176 void CCECDeviceMap::GetActive(CECDEVICEVEC &devices) const
177 {
178   for (auto it = m_busDevices.begin(); it != m_busDevices.end(); ++it)
179   {
180     auto dev = it->second;
181     if (!!dev && dev->IsActive(false)) {
182         devices.push_back(it->second);
183     }
184   }
185 }
186 
IsActiveType(const cec_device_type type,bool suppressPoll) const187 bool CCECDeviceMap::IsActiveType(const cec_device_type type, bool suppressPoll /* = true */) const
188 {
189   for (auto it = m_busDevices.begin(); it != m_busDevices.end(); ++it)
190   {
191     auto dev = it->second;
192     if (!!dev &&
193         (dev->GetType() == type) &&
194         (dev->IsActive(suppressPoll))) {
195         return true;
196     }
197   }
198   return false;
199 }
200 
GetPowerOffDevices(const libcec_configuration & configuration,CECDEVICEVEC & devices) const201 void CCECDeviceMap::GetPowerOffDevices(const libcec_configuration &configuration, CECDEVICEVEC &devices) const
202 {
203   for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
204   {
205     if (configuration.powerOffDevices[(uint8_t)it->first])
206       devices.push_back(it->second);
207   }
208 }
209 
GetWakeDevices(const libcec_configuration & configuration,CECDEVICEVEC & devices) const210 void CCECDeviceMap::GetWakeDevices(const libcec_configuration &configuration, CECDEVICEVEC &devices) const
211 {
212   for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
213   {
214     if (configuration.wakeDevices[(uint8_t)it->first])
215       devices.push_back(it->second);
216   }
217 }
218 
GetActiveSource(void) const219 CCECBusDevice *CCECDeviceMap::GetActiveSource(void) const
220 {
221   for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
222   {
223     if (it->second->IsActiveSource())
224       return it->second;
225   }
226   return NULL;
227 }
228 
ResetActiveSourceSent(void)229 void CCECDeviceMap::ResetActiveSourceSent(void)
230 {
231   for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
232     it->second->SetActiveSourceSent(false);
233 }
234 
FilterLibCECControlled(CECDEVICEVEC & devices)235 void CCECDeviceMap::FilterLibCECControlled(CECDEVICEVEC &devices)
236 {
237   CECDEVICEVEC newDevices;
238   for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
239   {
240     if ((*it)->IsHandledByLibCEC())
241       newDevices.push_back(*it);
242   }
243   devices = newDevices;
244 }
245 
FilterActive(CECDEVICEVEC & devices)246 void CCECDeviceMap::FilterActive(CECDEVICEVEC &devices)
247 {
248   CECDEVICEVEC newDevices;
249   for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
250   {
251     cec_bus_device_status status = (*it)->GetCurrentStatus();
252     if (status == CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC ||
253         status == CEC_DEVICE_STATUS_PRESENT)
254       newDevices.push_back(*it);
255   }
256   devices = newDevices;
257 }
258 
FilterTypes(const cec_device_type_list & types,CECDEVICEVEC & devices)259 void CCECDeviceMap::FilterTypes(const cec_device_type_list &types, CECDEVICEVEC &devices)
260 {
261   cec_device_type_list t(types);//silly, but needed to retain abi
262   CECDEVICEVEC newDevices;
263   for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
264   {
265     if (t.IsSet((*it)->GetType()))
266       newDevices.push_back(*it);
267   }
268   devices = newDevices;
269 }
270 
FilterType(const cec_device_type type,CECDEVICEVEC & devices)271 void CCECDeviceMap::FilterType(const cec_device_type type, CECDEVICEVEC &devices)
272 {
273   CECDEVICEVEC newDevices;
274   for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
275   {
276     if ((*it)->GetType() == type)
277       newDevices.push_back(*it);
278   }
279   devices = newDevices;
280 }
281 
ToLogicalAddresses(const CECDEVICEVEC & devices)282 cec_logical_addresses CCECDeviceMap::ToLogicalAddresses(const CECDEVICEVEC &devices)
283 {
284   cec_logical_addresses addresses;
285   addresses.Clear();
286   for (CECDEVICEVEC::const_iterator it = devices.begin(); it != devices.end(); it++)
287     addresses.Set((*it)->GetLogicalAddress());
288   return addresses;
289 }
290 
GetChildrenOf(CECDEVICEVEC & devices,CCECBusDevice * device) const291 void CCECDeviceMap::GetChildrenOf(CECDEVICEVEC& devices, CCECBusDevice* device) const
292 {
293   devices.clear();
294   if (!device)
295     return;
296 
297   uint16_t iPA = device->GetCurrentPhysicalAddress();
298 
299   for (CECDEVICEMAP::const_iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
300   {
301     uint16_t iCurrentPA = it->second->GetCurrentPhysicalAddress();
302     if (CCECTypeUtils::PhysicalAddressIsIncluded(iPA, iCurrentPA))
303       devices.push_back(it->second);
304   }
305 }
306 
SignalAll(cec_opcode opcode)307 void CCECDeviceMap::SignalAll(cec_opcode opcode)
308 {
309   for (CECDEVICEMAP::iterator it = m_busDevices.begin(); it != m_busDevices.end(); it++)
310     it->second->SignalOpcode(opcode);
311 }
312