cec: simplified AddLog() method
[deb_libcec.git] / src / lib / devices / CECBusDevice.cpp
CommitLineData
e9de9629
LOK
1/*
2 * This file is part of the libCEC(R) library.
3 *
4 * libCEC(R) is Copyright (C) 2011 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 *
23 *
24 * Alternatively, you can license this library under a commercial license,
25 * please contact Pulse-Eight Licensing for more information.
26 *
27 * For more information contact:
28 * Pulse-Eight Licensing <license@pulse-eight.com>
29 * http://www.pulse-eight.com/
30 * http://www.pulse-eight.net/
31 */
32
33#include "CECBusDevice.h"
eafa9d46
LOK
34#include "../CECProcessor.h"
35#include "../implementations/ANCommandHandler.h"
36#include "../implementations/CECCommandHandler.h"
37#include "../implementations/SLCommandHandler.h"
11621576 38#include "../implementations/VLCommandHandler.h"
5477a250 39#include "../LibCEC.h"
e9de9629
LOK
40
41using namespace CEC;
f00ff009 42using namespace PLATFORM;
e9de9629 43
03ae897d 44#define ToString(p) m_processor->ToString(p)
c4098482 45
e9de9629 46CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogicalAddress, uint16_t iPhysicalAddress) :
c4098482 47 m_type(CEC_DEVICE_TYPE_RESERVED),
e9de9629 48 m_iPhysicalAddress(iPhysicalAddress),
9dc04b07 49 m_iStreamPath(0),
e9de9629 50 m_iLogicalAddress(iLogicalAddress),
e55f3f70 51 m_powerStatus(CEC_POWER_STATUS_UNKNOWN),
e9de9629 52 m_processor(processor),
c4098482 53 m_vendor(CEC_VENDOR_UNKNOWN),
b64db02e 54 m_bReplaceHandler(false),
4abd6768 55 m_menuState(CEC_MENU_STATE_ACTIVATED),
8747dd4f 56 m_bActiveSource(false),
6a1c0009 57 m_iLastActive(0),
2efa39b7 58 m_iLastPowerStateUpdate(0),
f8ae3295 59 m_cecVersion(CEC_VERSION_UNKNOWN),
f00ff009 60 m_deviceStatus(CEC_DEVICE_STATUS_UNKNOWN)
e9de9629
LOK
61{
62 m_handler = new CCECCommandHandler(this);
51b2a094 63
a3269a0a
LOK
64 for (unsigned int iPtr = 0; iPtr < 4; iPtr++)
65 m_menuLanguage.language[iPtr] = '?';
66 m_menuLanguage.language[3] = 0;
67 m_menuLanguage.device = iLogicalAddress;
1fcf5a3f 68
c4098482 69 m_strDeviceName = ToString(m_iLogicalAddress);
e9de9629
LOK
70}
71
72CCECBusDevice::~CCECBusDevice(void)
73{
74 delete m_handler;
75}
76
93729720 77bool CCECBusDevice::HandleCommand(const cec_command &command)
f8513317 78{
7f919115
LOK
79 bool bHandled(false);
80
81 /* update "last active" */
8fa35473 82 {
f00ff009 83 CLockObject lock(m_mutex);
8fa35473 84 m_iLastActive = GetTimeMs();
f4b7b1dc
LOK
85
86 if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
87 m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
8fa35473
LOK
88 }
89
7f919115
LOK
90 /* handle the command */
91 bHandled = m_handler->HandleCommand(command);
8fa35473 92
7f919115
LOK
93 /* change status to present */
94 if (bHandled)
8d915412 95 {
f00ff009 96 CLockObject lock(m_mutex);
8fa35473 97 if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
8d915412 98 {
8fa35473 99 if (m_deviceStatus != CEC_DEVICE_STATUS_PRESENT)
5477a250 100 CLibCEC::AddLog(CEC_LOG_DEBUG, "device %s (%x) status changed to present after command %s", GetLogicalAddressName(), (uint8_t)GetLogicalAddress(), ToString(command.opcode));
8fa35473 101 m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
8d915412 102 }
8d915412 103 }
7f919115
LOK
104
105 return bHandled;
93729720
LOK
106}
107
93729720
LOK
108bool CCECBusDevice::PowerOn(void)
109{
5477a250 110 CLibCEC::AddLog(CEC_LOG_DEBUG, "<< powering on '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
00762a71 111
b64db02e 112 if (m_handler->TransmitImageViewOn(GetMyLogicalAddress(), m_iLogicalAddress))
5e5637c6 113 {
9bc8934c 114 {
f00ff009 115 CLockObject lock(m_mutex);
fe6f8e37
LOK
116// m_powerStatus = CEC_POWER_STATUS_UNKNOWN;
117 m_powerStatus = CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON;
9bc8934c 118 }
fe6f8e37
LOK
119// cec_power_status status = GetPowerStatus();
120// if (status == CEC_POWER_STATUS_STANDBY || status == CEC_POWER_STATUS_UNKNOWN)
121// {
122// /* sending the normal power on command appears to have failed */
123// CStdString strLog;
124// strLog.Format("<< sending power on keypress to '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
5477a250 125// CLibCEC::AddLog(CEC_LOG_DEBUG, strLog.c_str());
fe6f8e37
LOK
126//
127// TransmitKeypress(CEC_USER_CONTROL_CODE_POWER);
128// return TransmitKeyRelease();
129// }
5e5637c6 130 return true;
f437e4be
LOK
131 }
132
00762a71 133 return false;
93729720
LOK
134}
135
136bool CCECBusDevice::Standby(void)
137{
5477a250 138 CLibCEC::AddLog(CEC_LOG_DEBUG, "<< putting '%s' (%X) in standby mode", GetLogicalAddressName(), m_iLogicalAddress);
8fa35473 139 return m_handler->TransmitStandby(GetMyLogicalAddress(), m_iLogicalAddress);
93729720
LOK
140}
141
142/** @name Getters */
143//@{
7f919115 144cec_version CCECBusDevice::GetCecVersion(bool bUpdate /* = false */)
93729720 145{
97fc4ffb
LOK
146 bool bRequestUpdate(false);
147 {
f00ff009 148 CLockObject lock(m_mutex);
97fc4ffb
LOK
149 bRequestUpdate = (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
150 (bUpdate || m_cecVersion == CEC_VERSION_UNKNOWN));
151 }
152
153 if (bRequestUpdate)
f294b22f 154 RequestCecVersion();
f294b22f 155
f00ff009 156 CLockObject lock(m_mutex);
f294b22f
LOK
157 return m_cecVersion;
158}
159
160bool CCECBusDevice::RequestCecVersion(void)
161{
162 bool bReturn(false);
b64db02e 163
81a1e39d 164 if (!MyLogicalAddressContains(m_iLogicalAddress))
93729720 165 {
3e61b350 166 m_handler->MarkBusy();
5477a250 167 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< requesting CEC version of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
8fa35473
LOK
168
169 bReturn = m_handler->TransmitRequestCecVersion(GetMyLogicalAddress(), m_iLogicalAddress);
3e61b350 170 m_handler->MarkReady();
93729720 171 }
f294b22f 172 return bReturn;
93729720
LOK
173}
174
62f5527d
LOK
175const char* CCECBusDevice::GetLogicalAddressName(void) const
176{
c4098482 177 return ToString(m_iLogicalAddress);
62f5527d
LOK
178}
179
7f919115 180cec_menu_language &CCECBusDevice::GetMenuLanguage(bool bUpdate /* = false */)
93729720 181{
97fc4ffb
LOK
182 bool bRequestUpdate(false);
183 {
f00ff009 184 CLockObject lock(m_mutex);
97fc4ffb
LOK
185 bRequestUpdate = (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
186 (bUpdate || !strcmp(m_menuLanguage.language, "???")));
187 }
188
189 if (bRequestUpdate)
f294b22f 190 RequestMenuLanguage();
5e5637c6 191
f00ff009 192 CLockObject lock(m_mutex);
f294b22f
LOK
193 return m_menuLanguage;
194}
195
196bool CCECBusDevice::RequestMenuLanguage(void)
197{
198 bool bReturn(false);
b64db02e 199
4d738fe3
LOK
200 if (!MyLogicalAddressContains(m_iLogicalAddress) &&
201 !IsUnsupportedFeature(CEC_OPCODE_GET_MENU_LANGUAGE))
93729720 202 {
3e61b350 203 m_handler->MarkBusy();
5477a250 204 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< requesting menu language of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
8fa35473 205 bReturn = m_handler->TransmitRequestMenuLanguage(GetMyLogicalAddress(), m_iLogicalAddress);
3e61b350 206 m_handler->MarkReady();
93729720 207 }
f294b22f 208 return bReturn;
93729720
LOK
209}
210
3e61b350
LOK
211cec_menu_state CCECBusDevice::GetMenuState(void)
212{
f00ff009 213 CLockObject lock(m_mutex);
3e61b350
LOK
214 return m_menuState;
215}
216
93729720
LOK
217cec_logical_address CCECBusDevice::GetMyLogicalAddress(void) const
218{
219 return m_processor->GetLogicalAddress();
f8513317
LOK
220}
221
e9de9629
LOK
222uint16_t CCECBusDevice::GetMyPhysicalAddress(void) const
223{
224 return m_processor->GetPhysicalAddress();
225}
226
7f919115 227CStdString CCECBusDevice::GetOSDName(bool bUpdate /* = false */)
ed21be2a 228{
97fc4ffb
LOK
229 bool bRequestUpdate(false);
230 {
f00ff009 231 CLockObject lock(m_mutex);
97fc4ffb
LOK
232 bRequestUpdate = (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
233 (bUpdate || m_strDeviceName.Equals(ToString(m_iLogicalAddress))) &&
234 m_type != CEC_DEVICE_TYPE_TV);
235 }
236
237 if (bRequestUpdate)
5e5637c6
LOK
238 RequestOSDName();
239
f00ff009 240 CLockObject lock(m_mutex);
ed21be2a
LOK
241 return m_strDeviceName;
242}
243
244bool CCECBusDevice::RequestOSDName(void)
245{
246 bool bReturn(false);
b64db02e 247
4d738fe3
LOK
248 if (!MyLogicalAddressContains(m_iLogicalAddress) &&
249 !IsUnsupportedFeature(CEC_OPCODE_GIVE_OSD_NAME))
ed21be2a 250 {
3e61b350 251 m_handler->MarkBusy();
5477a250 252 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< requesting OSD name of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
8fa35473 253 bReturn = m_handler->TransmitRequestOSDName(GetMyLogicalAddress(), m_iLogicalAddress);
3e61b350 254 m_handler->MarkReady();
ed21be2a
LOK
255 }
256 return bReturn;
257}
258
7f919115 259uint16_t CCECBusDevice::GetPhysicalAddress(bool bUpdate /* = false */)
16b1e052 260{
97fc4ffb 261 bool bRequestUpdate(false);
16b1e052 262 {
f00ff009 263 CLockObject lock(m_mutex);
97fc4ffb
LOK
264 bRequestUpdate = (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
265 (m_iPhysicalAddress == 0xFFFF || bUpdate));
16b1e052
LOK
266 }
267
97fc4ffb 268 if (bRequestUpdate && !RequestPhysicalAddress())
5477a250 269 CLibCEC::AddLog(CEC_LOG_ERROR, "failed to request the physical address");
97fc4ffb 270
f00ff009 271 CLockObject lock(m_mutex);
16b1e052
LOK
272 return m_iPhysicalAddress;
273}
274
275bool CCECBusDevice::RequestPhysicalAddress(void)
276{
277 bool bReturn(false);
b64db02e 278
16b1e052
LOK
279 if (!MyLogicalAddressContains(m_iLogicalAddress))
280 {
3e61b350 281 m_handler->MarkBusy();
5477a250 282 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< requesting physical address of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
8fa35473 283 bReturn = m_handler->TransmitRequestPhysicalAddress(GetMyLogicalAddress(), m_iLogicalAddress);
3e61b350 284 m_handler->MarkReady();
16b1e052
LOK
285 }
286 return bReturn;
287}
288
7f919115 289cec_power_status CCECBusDevice::GetPowerStatus(bool bUpdate /* = false */)
e9de9629 290{
97fc4ffb
LOK
291 bool bRequestUpdate(false);
292 {
f00ff009 293 CLockObject lock(m_mutex);
97fc4ffb 294 bRequestUpdate = (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
c8f0eef0 295 (bUpdate || m_powerStatus == CEC_POWER_STATUS_UNKNOWN ||
2efa39b7
LOK
296 m_powerStatus == CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON ||
297 m_powerStatus == CEC_POWER_STATUS_IN_TRANSITION_ON_TO_STANDBY ||
298 GetTimeMs() - m_iLastPowerStateUpdate >= CEC_POWER_STATE_REFRESH_TIME));
97fc4ffb
LOK
299 }
300
301 if (bRequestUpdate)
f294b22f 302 RequestPowerStatus();
5e5637c6 303
f00ff009 304 CLockObject lock(m_mutex);
f294b22f
LOK
305 return m_powerStatus;
306}
307
308bool CCECBusDevice::RequestPowerStatus(void)
309{
310 bool bReturn(false);
b64db02e 311
4d738fe3
LOK
312 if (!MyLogicalAddressContains(m_iLogicalAddress) &&
313 !IsUnsupportedFeature(CEC_OPCODE_GIVE_DEVICE_POWER_STATUS))
93729720 314 {
3e61b350 315 m_handler->MarkBusy();
5477a250 316 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< requesting power status of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
8fa35473 317 bReturn = m_handler->TransmitRequestPowerStatus(GetMyLogicalAddress(), m_iLogicalAddress);
3e61b350 318 m_handler->MarkReady();
93729720 319 }
f294b22f
LOK
320 return bReturn;
321}
93729720 322
7f919115 323cec_vendor_id CCECBusDevice::GetVendorId(bool bUpdate /* = false */)
f294b22f 324{
97fc4ffb
LOK
325 bool bRequestUpdate(false);
326 {
f00ff009 327 CLockObject lock(m_mutex);
97fc4ffb
LOK
328 bRequestUpdate = (GetStatus() == CEC_DEVICE_STATUS_PRESENT &&
329 (bUpdate || m_vendor == CEC_VENDOR_UNKNOWN));
330 }
331
332 if (bRequestUpdate)
f294b22f 333 RequestVendorId();
5e5637c6 334
f00ff009 335 CLockObject lock(m_mutex);
f294b22f 336 return m_vendor;
e9de9629
LOK
337}
338
f294b22f 339bool CCECBusDevice::RequestVendorId(void)
a3269a0a 340{
f294b22f 341 bool bReturn(false);
b64db02e 342
81a1e39d 343 if (!MyLogicalAddressContains(m_iLogicalAddress))
a3269a0a 344 {
3e61b350 345 m_handler->MarkBusy();
5477a250 346 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< requesting vendor ID of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
8fa35473 347 bReturn = m_handler->TransmitRequestVendorId(GetMyLogicalAddress(), m_iLogicalAddress);
3e61b350
LOK
348 m_handler->MarkReady();
349
350 ReplaceHandler(true);
a3269a0a 351 }
f294b22f 352 return bReturn;
93729720
LOK
353}
354
7f919115 355const char *CCECBusDevice::GetVendorName(bool bUpdate /* = false */)
c4098482 356{
7f919115 357 return ToString(GetVendorId(bUpdate));
c4098482
LOK
358}
359
93729720
LOK
360bool CCECBusDevice::MyLogicalAddressContains(cec_logical_address address) const
361{
362 return m_processor->HasLogicalAddress(address);
a3269a0a
LOK
363}
364
9fd73dd4
LOK
365bool CCECBusDevice::NeedsPoll(void)
366{
367 bool bSendPoll(false);
368 switch (m_iLogicalAddress)
369 {
370 case CECDEVICE_PLAYBACKDEVICE3:
371 if (m_processor->m_busDevices[CECDEVICE_PLAYBACKDEVICE2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
372 bSendPoll = true;
373 break;
374 case CECDEVICE_PLAYBACKDEVICE2:
375 if (m_processor->m_busDevices[CECDEVICE_PLAYBACKDEVICE1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
376 bSendPoll = true;
377 break;
378 case CECDEVICE_RECORDINGDEVICE3:
379 if (m_processor->m_busDevices[CECDEVICE_RECORDINGDEVICE2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
380 bSendPoll = true;
381 break;
382 case CECDEVICE_RECORDINGDEVICE2:
383 if (m_processor->m_busDevices[CECDEVICE_RECORDINGDEVICE1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
384 bSendPoll = true;
385 break;
386 case CECDEVICE_TUNER4:
387 if (m_processor->m_busDevices[CECDEVICE_TUNER3]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
388 bSendPoll = true;
389 break;
390 case CECDEVICE_TUNER3:
391 if (m_processor->m_busDevices[CECDEVICE_TUNER2]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
392 bSendPoll = true;
393 break;
394 case CECDEVICE_TUNER2:
395 if (m_processor->m_busDevices[CECDEVICE_TUNER1]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
396 bSendPoll = true;
397 break;
398 case CECDEVICE_AUDIOSYSTEM:
399 case CECDEVICE_PLAYBACKDEVICE1:
400 case CECDEVICE_RECORDINGDEVICE1:
401 case CECDEVICE_TUNER1:
402 case CECDEVICE_TV:
403 bSendPoll = true;
404 break;
405 default:
406 break;
407 }
408
409 return bSendPoll;
410}
411
412cec_bus_device_status CCECBusDevice::GetStatus(bool bForcePoll /* = false */)
f8ae3295 413{
f00ff009 414 CLockObject lock(m_mutex);
b750a5c3
LOK
415 if (m_deviceStatus != CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC &&
416 (m_deviceStatus == CEC_DEVICE_STATUS_UNKNOWN || bForcePoll))
f8ae3295 417 {
f00ff009 418 lock.Unlock();
9fd73dd4
LOK
419 bool bPollAcked(false);
420 if (bForcePoll || NeedsPoll())
421 bPollAcked = m_processor->PollDevice(m_iLogicalAddress);
95a73fa7
LOK
422
423 lock.Lock();
424 m_deviceStatus = bPollAcked ? CEC_DEVICE_STATUS_PRESENT : CEC_DEVICE_STATUS_NOT_PRESENT;
f8ae3295
LOK
425 }
426
427 return m_deviceStatus;
428}
429
93729720
LOK
430//@}
431
432/** @name Setters */
433//@{
e55f3f70 434void CCECBusDevice::SetCecVersion(const cec_version newVersion)
6a1c0009 435{
6a1c0009 436 m_cecVersion = newVersion;
5477a250 437 CLibCEC::AddLog(CEC_LOG_DEBUG, "%s (%X): CEC version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(newVersion));
6a1c0009
LOK
438}
439
93729720
LOK
440void CCECBusDevice::SetMenuLanguage(const cec_menu_language &language)
441{
f00ff009 442 CLockObject lock(m_mutex);
93729720
LOK
443 if (language.device == m_iLogicalAddress)
444 {
5477a250 445 CLibCEC::AddLog(CEC_LOG_DEBUG, ">> %s (%X): menu language set to '%s'", GetLogicalAddressName(), m_iLogicalAddress, language.language);
93729720
LOK
446 m_menuLanguage = language;
447 }
448}
449
15d1a84c
LOK
450void CCECBusDevice::SetOSDName(CStdString strName)
451{
f00ff009 452 CLockObject lock(m_mutex);
15d1a84c
LOK
453 if (m_strDeviceName != strName)
454 {
5477a250 455 CLibCEC::AddLog(CEC_LOG_DEBUG, ">> %s (%X): osd name set to '%s'", GetLogicalAddressName(), m_iLogicalAddress, strName.c_str());
15d1a84c
LOK
456 m_strDeviceName = strName;
457 }
458}
459
28fa6c97
LOK
460void CCECBusDevice::SetMenuState(const cec_menu_state state)
461{
f00ff009 462 CLockObject lock(m_mutex);
28fa6c97
LOK
463 if (m_menuState != state)
464 {
5477a250 465 CLibCEC::AddLog(CEC_LOG_DEBUG, ">> %s (%X): menu state set to '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_menuState));
28fa6c97
LOK
466 m_menuState = state;
467 }
468}
469
3fd2a2b8 470void CCECBusDevice::SetInactiveSource(void)
7856411b 471{
3fd2a2b8 472 {
f00ff009 473 CLockObject lock(m_mutex);
3fd2a2b8
LOK
474 m_bActiveSource = false;
475 }
476
477 if (MyLogicalAddressContains(m_iLogicalAddress))
478 SetPowerStatus(CEC_POWER_STATUS_STANDBY);
7856411b
LOK
479}
480
37b0c572 481void CCECBusDevice::SetActiveSource(void)
7856411b 482{
f00ff009 483 CLockObject lock(m_mutex);
ff684fef 484 if (!m_bActiveSource)
5477a250 485 CLibCEC::AddLog(CEC_LOG_DEBUG, "making %s (%x) the active source", GetLogicalAddressName(), m_iLogicalAddress);
7856411b
LOK
486
487 for (int iPtr = 0; iPtr < 16; iPtr++)
488 if (iPtr != m_iLogicalAddress)
3fd2a2b8 489 m_processor->m_busDevices[iPtr]->SetInactiveSource();
7856411b
LOK
490
491 m_bActiveSource = true;
492 m_powerStatus = CEC_POWER_STATUS_ON;
493}
494
93fff5c1
LOK
495bool CCECBusDevice::TryLogicalAddress(void)
496{
5477a250 497 CLibCEC::AddLog(CEC_LOG_DEBUG, "trying logical address '%s'", GetLogicalAddressName());
93fff5c1
LOK
498
499 m_processor->SetAckMask(0x1 << m_iLogicalAddress);
500 if (!TransmitPoll(m_iLogicalAddress))
501 {
5477a250 502 CLibCEC::AddLog(CEC_LOG_NOTICE, "using logical address '%s'", GetLogicalAddressName());
93fff5c1
LOK
503 SetDeviceStatus(CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC);
504
505 return true;
506 }
507
5477a250 508 CLibCEC::AddLog(CEC_LOG_DEBUG, "logical address '%s' already taken", GetLogicalAddressName());
93fff5c1
LOK
509 SetDeviceStatus(CEC_DEVICE_STATUS_PRESENT);
510 return false;
511}
512
513void CCECBusDevice::SetDeviceStatus(const cec_bus_device_status newStatus)
514{
f00ff009 515 CLockObject lock(m_mutex);
93fff5c1
LOK
516 switch (newStatus)
517 {
518 case CEC_DEVICE_STATUS_UNKNOWN:
519 m_iStreamPath = 0;
520 m_powerStatus = CEC_POWER_STATUS_UNKNOWN;
521 m_vendor = CEC_VENDOR_UNKNOWN;
522 m_menuState = CEC_MENU_STATE_ACTIVATED;
523 m_bActiveSource = false;
93fff5c1
LOK
524 m_iLastActive = 0;
525 m_cecVersion = CEC_VERSION_UNKNOWN;
526 m_deviceStatus = newStatus;
527 break;
528 case CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC:
529 m_iStreamPath = 0;
530 m_powerStatus = CEC_POWER_STATUS_ON;
531 m_vendor = CEC_VENDOR_UNKNOWN;
532 m_menuState = CEC_MENU_STATE_ACTIVATED;
533 m_bActiveSource = false;
93fff5c1
LOK
534 m_iLastActive = 0;
535 m_cecVersion = CEC_VERSION_1_3A;
536 m_deviceStatus = newStatus;
537 break;
538 case CEC_DEVICE_STATUS_PRESENT:
539 case CEC_DEVICE_STATUS_NOT_PRESENT:
540 m_deviceStatus = newStatus;
541 break;
542 }
543}
544
9dc04b07 545void CCECBusDevice::SetPhysicalAddress(uint16_t iNewAddress)
93729720 546{
f00ff009 547 CLockObject lock(m_mutex);
b8176e3c 548 if (iNewAddress > 0 && m_iPhysicalAddress != iNewAddress)
93729720 549 {
5477a250 550 CLibCEC::AddLog(CEC_LOG_DEBUG, ">> %s (%X): physical address changed from %04x to %04x", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress, iNewAddress);
93729720
LOK
551 m_iPhysicalAddress = iNewAddress;
552 }
553}
554
9dc04b07
LOK
555void CCECBusDevice::SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress /* = 0 */)
556{
f00ff009 557 CLockObject lock(m_mutex);
9dc04b07
LOK
558 if (iNewAddress > 0)
559 {
5477a250 560 CLibCEC::AddLog(CEC_LOG_DEBUG, ">> %s (%X): stream path changed from %04x to %04x", GetLogicalAddressName(), m_iLogicalAddress, iOldAddress == 0 ? m_iStreamPath : iOldAddress, iNewAddress);
9dc04b07 561 m_iStreamPath = iNewAddress;
96274140
LOK
562
563 if (iNewAddress > 0)
81a1e39d 564 {
f00ff009 565 lock.Unlock();
96274140 566 SetPowerStatus(CEC_POWER_STATUS_ON);
81a1e39d 567 }
9dc04b07
LOK
568 }
569}
570
e55f3f70
LOK
571void CCECBusDevice::SetPowerStatus(const cec_power_status powerStatus)
572{
f00ff009 573 CLockObject lock(m_mutex);
b0271d54
LOK
574 if (m_powerStatus != powerStatus)
575 {
2efa39b7 576 m_iLastPowerStateUpdate = GetTimeMs();
5477a250 577 CLibCEC::AddLog(CEC_LOG_DEBUG, ">> %s (%X): power status changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_powerStatus), ToString(powerStatus));
b0271d54
LOK
578 m_powerStatus = powerStatus;
579 }
e55f3f70
LOK
580}
581
3e61b350 582bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */)
e9de9629 583{
f00ff009
LOK
584 CLockObject lock(m_mutex);
585 CLockObject handlerLock(m_handlerMutex);
d211708b 586
b64db02e 587 if (m_vendor != m_handler->GetVendorId())
e9de9629 588 {
2e49a6e4 589 if (CCECCommandHandler::HasSpecificHandler(m_vendor))
3e61b350 590 {
2e49a6e4
LOK
591 CStdString strLog;
592 if (m_handler->InUse())
593 {
5477a250 594 CLibCEC::AddLog(CEC_LOG_DEBUG, "handler for device '%s' (%x) is being used. not replacing the command handler", GetLogicalAddressName(), GetLogicalAddress());
2e49a6e4
LOK
595 return false;
596 }
81a1e39d 597
5477a250 598 CLibCEC::AddLog(CEC_LOG_DEBUG, "replacing the command handler for device '%s' (%x)", GetLogicalAddressName(), GetLogicalAddress());
2e49a6e4 599 delete m_handler;
d211708b 600
2e49a6e4
LOK
601 switch (m_vendor)
602 {
603 case CEC_VENDOR_SAMSUNG:
604 m_handler = new CANCommandHandler(this);
605 break;
606 case CEC_VENDOR_LG:
607 m_handler = new CSLCommandHandler(this);
608 break;
609 case CEC_VENDOR_PANASONIC:
610 m_handler = new CVLCommandHandler(this);
611 break;
612 default:
613 m_handler = new CCECCommandHandler(this);
614 break;
615 }
b64db02e 616
2e49a6e4
LOK
617 m_handler->SetVendorId(m_vendor);
618 m_handler->InitHandler();
3e61b350 619
ff684fef 620 if (bActivateSource && m_processor->GetLogicalAddresses().IsSet(m_iLogicalAddress) && m_processor->IsInitialised() && IsActiveSource())
2e49a6e4
LOK
621 m_handler->ActivateSource();
622 }
e9de9629
LOK
623 }
624
b64db02e
LOK
625 return true;
626}
627
3e61b350 628bool CCECBusDevice::SetVendorId(uint64_t iVendorId)
b64db02e
LOK
629{
630 bool bVendorChanged(false);
631
632 {
f00ff009 633 CLockObject lock(m_mutex);
b64db02e
LOK
634 bVendorChanged = (m_vendor != (cec_vendor_id)iVendorId);
635 m_vendor = (cec_vendor_id)iVendorId;
b64db02e 636 }
8d915412 637
5477a250 638 CLibCEC::AddLog(CEC_LOG_DEBUG, "%s (%X): vendor = %s (%06x)", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_vendor), m_vendor);
8fa35473
LOK
639
640 return bVendorChanged;
e9de9629 641}
93729720 642//@}
e9de9629 643
93729720
LOK
644/** @name Transmit methods */
645//@{
646bool CCECBusDevice::TransmitActiveSource(void)
0f23c85c 647{
8fa35473 648 bool bSendActiveSource(false);
0f23c85c 649
8747dd4f 650 {
f00ff009 651 CLockObject lock(m_mutex);
8fa35473 652 if (m_powerStatus != CEC_POWER_STATUS_ON)
5477a250 653 CLibCEC::AddLog(CEC_LOG_DEBUG, "<< %s (%X) is not powered on", GetLogicalAddressName(), m_iLogicalAddress);
8fa35473
LOK
654 else if (m_bActiveSource)
655 {
5477a250 656 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> broadcast (F): active source (%4x)", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
8fa35473
LOK
657 bSendActiveSource = true;
658 }
659 else
5477a250 660 CLibCEC::AddLog(CEC_LOG_DEBUG, "<< %s (%X) is not the active source", GetLogicalAddressName(), m_iLogicalAddress);
8747dd4f
LOK
661 }
662
b64db02e
LOK
663 if (bSendActiveSource)
664 {
b64db02e 665 m_handler->TransmitImageViewOn(m_iLogicalAddress, CECDEVICE_TV);
468a1414 666 m_handler->TransmitActiveSource(m_iLogicalAddress, m_iPhysicalAddress);
b64db02e
LOK
667 return true;
668 }
669
670 return false;
0f23c85c
LOK
671}
672
29912296 673bool CCECBusDevice::TransmitCECVersion(cec_logical_address dest)
0f23c85c 674{
8fa35473
LOK
675 cec_version version;
676 {
f00ff009 677 CLockObject lock(m_mutex);
5477a250 678 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> %s (%X): cec version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_cecVersion));
8fa35473
LOK
679 version = m_cecVersion;
680 }
0f23c85c 681
8fa35473 682 return m_handler->TransmitCECVersion(m_iLogicalAddress, dest, version);
0f23c85c
LOK
683}
684
ab27363d 685bool CCECBusDevice::TransmitInactiveSource(void)
93729720 686{
8fa35473
LOK
687 uint16_t iPhysicalAddress;
688 {
f00ff009 689 CLockObject lock(m_mutex);
5477a250 690 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> broadcast (F): inactive source", GetLogicalAddressName(), m_iLogicalAddress);
8fa35473
LOK
691 iPhysicalAddress = m_iPhysicalAddress;
692 }
93729720 693
8fa35473 694 return m_handler->TransmitInactiveSource(m_iLogicalAddress, iPhysicalAddress);
93729720
LOK
695}
696
29912296 697bool CCECBusDevice::TransmitMenuState(cec_logical_address dest)
0f23c85c 698{
8fa35473
LOK
699 cec_menu_state menuState;
700 {
f00ff009 701 CLockObject lock(m_mutex);
5477a250 702 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> %s (%X): menu state '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_menuState));
8fa35473
LOK
703 menuState = m_menuState;
704 }
0f23c85c 705
8fa35473 706 return m_handler->TransmitMenuState(m_iLogicalAddress, dest, menuState);
0f23c85c
LOK
707}
708
29912296 709bool CCECBusDevice::TransmitOSDName(cec_logical_address dest)
0f23c85c 710{
8fa35473
LOK
711 CStdString strDeviceName;
712 {
f00ff009 713 CLockObject lock(m_mutex);
5477a250 714 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> %s (%X): OSD name '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, m_strDeviceName.c_str());
8fa35473
LOK
715 strDeviceName = m_strDeviceName;
716 }
0f23c85c 717
8fa35473 718 return m_handler->TransmitOSDName(m_iLogicalAddress, dest, strDeviceName);
0f23c85c
LOK
719}
720
38bdb943
LOK
721bool CCECBusDevice::TransmitOSDString(cec_logical_address dest, cec_display_control duration, const char *strMessage)
722{
4d738fe3
LOK
723 if (!IsUnsupportedFeature(CEC_OPCODE_SET_OSD_STRING))
724 {
5477a250 725 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> %s (%X): display OSD message '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, strMessage);
4d738fe3
LOK
726 return m_handler->TransmitOSDString(m_iLogicalAddress, dest, duration, strMessage);
727 }
728 return false;
38bdb943
LOK
729}
730
29912296 731bool CCECBusDevice::TransmitPhysicalAddress(void)
0f23c85c 732{
8fa35473
LOK
733 uint16_t iPhysicalAddress;
734 cec_device_type type;
735 {
f00ff009 736 CLockObject lock(m_mutex);
8fa35473
LOK
737 if (m_iPhysicalAddress == 0xffff)
738 return false;
2bdfdeef 739
5477a250 740 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> broadcast (F): physical adddress %4x", GetLogicalAddressName(), m_iLogicalAddress, m_iPhysicalAddress);
8fa35473
LOK
741 iPhysicalAddress = m_iPhysicalAddress;
742 type = m_type;
743 }
0f23c85c 744
8fa35473 745 return m_handler->TransmitPhysicalAddress(m_iLogicalAddress, iPhysicalAddress, type);
0f23c85c
LOK
746}
747
93729720 748bool CCECBusDevice::TransmitPoll(cec_logical_address dest)
57f45e6c
LOK
749{
750 bool bReturn(false);
93729720
LOK
751 if (dest == CECDEVICE_UNKNOWN)
752 dest = m_iLogicalAddress;
f8513317 753
b750a5c3
LOK
754 CCECBusDevice *destDevice = m_processor->m_busDevices[dest];
755 if (destDevice->m_deviceStatus == CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC)
756 return bReturn;
757
5477a250 758 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> %s (%X): POLL", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest);
8fa35473 759 bReturn = m_handler->TransmitPoll(m_iLogicalAddress, dest);
5477a250 760 CLibCEC::AddLog(CEC_LOG_DEBUG, bReturn ? ">> POLL sent" : ">> POLL not sent");
8fa35473 761
f00ff009 762 CLockObject lock(m_mutex);
1674de37 763 if (bReturn)
8fa35473 764 {
1674de37 765 m_iLastActive = GetTimeMs();
b750a5c3 766 destDevice->m_deviceStatus = CEC_DEVICE_STATUS_PRESENT;
8fa35473 767 }
b750a5c3
LOK
768 else
769 destDevice->m_deviceStatus = CEC_DEVICE_STATUS_NOT_PRESENT;
1674de37 770
57f45e6c
LOK
771 return bReturn;
772}
93729720
LOK
773
774bool CCECBusDevice::TransmitPowerState(cec_logical_address dest)
775{
8fa35473
LOK
776 cec_power_status state;
777 {
f00ff009 778 CLockObject lock(m_mutex);
5477a250 779 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> %s (%X): %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_powerStatus));
8fa35473
LOK
780 state = m_powerStatus;
781 }
93729720 782
8fa35473 783 return m_handler->TransmitPowerState(m_iLogicalAddress, dest, state);
93729720
LOK
784}
785
fe6f8e37 786bool CCECBusDevice::TransmitVendorID(cec_logical_address dest, bool bSendAbort /* = true */)
93729720 787{
8fa35473
LOK
788 uint64_t iVendorId;
789 {
f00ff009 790 CLockObject lock(m_mutex);
8fa35473
LOK
791 iVendorId = (uint64_t)m_vendor;
792 }
793
794 if (iVendorId == CEC_VENDOR_UNKNOWN)
c4098482 795 {
fe6f8e37
LOK
796 if (bSendAbort)
797 {
5477a250 798 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> %s (%X): vendor id feature abort", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest);
fe6f8e37
LOK
799 m_processor->TransmitAbort(dest, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
800 }
c4098482
LOK
801 return false;
802 }
803 else
804 {
5477a250 805 CLibCEC::AddLog(CEC_LOG_NOTICE, "<< %s (%X) -> %s (%X): vendor id %s (%x)", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString((cec_vendor_id)iVendorId), iVendorId);
8fa35473 806 return m_handler->TransmitVendorID(m_iLogicalAddress, iVendorId);
c4098482 807 }
93729720 808}
a33794d8 809
4bec9d79 810bool CCECBusDevice::TransmitKeypress(cec_user_control_code key, bool bWait /* = true */)
a33794d8 811{
4bec9d79 812 return m_handler->TransmitKeypress(m_processor->GetLogicalAddress(), m_iLogicalAddress, key, bWait);
a33794d8
LOK
813}
814
4bec9d79 815bool CCECBusDevice::TransmitKeyRelease(bool bWait /* = true */)
a33794d8 816{
4bec9d79 817 return m_handler->TransmitKeyRelease(m_processor->GetLogicalAddress(), m_iLogicalAddress, bWait);
a33794d8 818}
4d738fe3
LOK
819
820bool CCECBusDevice::IsUnsupportedFeature(cec_opcode opcode) const
821{
822 return m_unsupportedFeatures.find(opcode) != m_unsupportedFeatures.end();
823}
824
825void CCECBusDevice::SetUnsupportedFeature(cec_opcode opcode)
826{
827 m_unsupportedFeatures.insert(opcode);
828}
b64db02e 829
3e61b350 830bool CCECBusDevice::ActivateSource(void)
b64db02e 831{
f00ff009 832 CLockObject lock(m_mutex);
3e61b350 833 return m_handler->ActivateSource();
b64db02e
LOK
834}
835
93729720 836//@}