Skip to content

Commit

Permalink
cec: replace the command handler directly after receiving a changed v…
Browse files Browse the repository at this point in the history
…endor id. change the primary type from recording device to playback device for panasonic TVs
  • Loading branch information
opdenkamp committed Jan 1, 2012
1 parent bed0f90 commit 3e61b35
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 32 deletions.
104 changes: 102 additions & 2 deletions src/lib/CECProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ bool CCECProcessor::Start(const char *strPort, uint16_t iBaudRate /* = 38400 */,
m_busDevices[m_logicalAddresses.primary]->m_strDeviceName = m_strDeviceName;

/* get the vendor id from the TV, so we are using the correct handler */
m_busDevices[CECDEVICE_TV]->GetVendorId();
m_busDevices[CECDEVICE_TV]->RequestVendorId();
ReplaceHandlers();

bReturn = SetHDMIPort(m_iBaseDevice, m_iHDMIPort, true);
Expand All @@ -181,7 +181,7 @@ bool CCECProcessor::Start(const char *strPort, uint16_t iBaudRate /* = 38400 */,
{
m_bInitialised = true;
m_busDevices[m_logicalAddresses.primary]->m_bActiveSource = true;
bReturn = m_busDevices[CECDEVICE_TV]->InitHandler();
bReturn = m_busDevices[CECDEVICE_TV]->ActivateSource();
}

if (bReturn)
Expand Down Expand Up @@ -239,6 +239,85 @@ bool CCECProcessor::FindLogicalAddressAudioSystem(void)
return TryLogicalAddress(CECDEVICE_AUDIOSYSTEM);
}

bool CCECProcessor::ChangeDeviceType(cec_device_type from, cec_device_type to)
{
bool bChanged(false);

CStdString strLog;
strLog.Format("changing device type '%s' into '%s'", ToString(from), ToString(to));
AddLog(CEC_LOG_NOTICE, strLog);

CLockObject lock(&m_mutex);
CCECBusDevice *previousDevice = GetDeviceByType(from);
m_logicalAddresses.primary = CECDEVICE_UNKNOWN;

for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
{
if (m_types.types[iPtr] == CEC_DEVICE_TYPE_RESERVED)
continue;

if (m_types.types[iPtr] == from)
{
bChanged = true;
m_types.types[iPtr] = to;
}
else if (m_types.types[iPtr] == to && bChanged)
{
m_types.types[iPtr] = CEC_DEVICE_TYPE_RESERVED;
}
}

if (bChanged)
{
FindLogicalAddresses();

CCECBusDevice *newDevice = GetDeviceByType(to);
if (previousDevice && newDevice)
{
newDevice->SetDeviceStatus(CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC);
previousDevice->SetDeviceStatus(CEC_DEVICE_STATUS_UNKNOWN);

newDevice->SetCecVersion(previousDevice->GetCecVersion(false));
previousDevice->SetCecVersion(CEC_VERSION_UNKNOWN);

newDevice->SetMenuLanguage(previousDevice->GetMenuLanguage(false));
cec_menu_language lang;
lang.device = previousDevice->GetLogicalAddress();
for (unsigned int iPtr = 0; iPtr < 4; iPtr++)
lang.language[iPtr] = '?';
lang.language[3] = 0;
previousDevice->SetMenuLanguage(lang);

newDevice->SetMenuState(previousDevice->GetMenuState());
previousDevice->SetMenuState(CEC_MENU_STATE_DEACTIVATED);

newDevice->SetOSDName(previousDevice->GetOSDName(false));
previousDevice->SetOSDName(ToString(previousDevice->GetLogicalAddress()));

newDevice->SetPhysicalAddress(previousDevice->GetPhysicalAddress(false));
previousDevice->SetPhysicalAddress(0xFFFF);

newDevice->SetPowerStatus(previousDevice->GetPowerStatus(false));
previousDevice->SetPowerStatus(CEC_POWER_STATUS_UNKNOWN);

newDevice->SetVendorId(previousDevice->GetVendorId(false));
previousDevice->SetVendorId(CEC_VENDOR_UNKNOWN);

if ((from == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || from == CEC_DEVICE_TYPE_RECORDING_DEVICE) &&
(to == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || to == CEC_DEVICE_TYPE_RECORDING_DEVICE))
{
((CCECPlaybackDevice *) newDevice)->SetDeckControlMode(((CCECPlaybackDevice *) previousDevice)->GetDeckControlMode());
((CCECPlaybackDevice *) previousDevice)->SetDeckControlMode(CEC_DECK_CONTROL_MODE_STOP);

((CCECPlaybackDevice *) newDevice)->SetDeckStatus(((CCECPlaybackDevice *) previousDevice)->GetDeckStatus());
((CCECPlaybackDevice *) previousDevice)->SetDeckStatus(CEC_DECK_INFO_STOP);
}
}
}

return true;
}

bool CCECProcessor::FindLogicalAddresses(void)
{
bool bReturn(true);
Expand Down Expand Up @@ -1005,6 +1084,27 @@ bool CCECProcessor::TransmitKeyRelease(cec_logical_address iDestination, bool bW
return m_busDevices[iDestination]->TransmitKeyRelease(bWait);
}

const char *CCECProcessor::ToString(const cec_device_type type)
{
switch (type)
{
case CEC_DEVICE_TYPE_AUDIO_SYSTEM:
return "audio system";
case CEC_DEVICE_TYPE_PLAYBACK_DEVICE:
return "playback device";
case CEC_DEVICE_TYPE_RECORDING_DEVICE:
return "recording device";
case CEC_DEVICE_TYPE_RESERVED:
return "reserved";
case CEC_DEVICE_TYPE_TUNER:
return "tuner";
case CEC_DEVICE_TYPE_TV:
return "TV";
default:
return "unknown";
}
}

const char *CCECProcessor::ToString(const cec_menu_state state)
{
switch (state)
Expand Down
2 changes: 2 additions & 0 deletions src/lib/CECProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ namespace CEC

bool SetLineTimeout(uint8_t iTimeout);

const char *ToString(const cec_device_type type);
const char *ToString(const cec_menu_state state);
const char *ToString(const cec_version version);
const char *ToString(const cec_power_status status);
Expand All @@ -124,6 +125,7 @@ namespace CEC
virtual void AddKey(void);
virtual void AddLog(cec_log_level level, const CStdString &strMessage);

virtual bool ChangeDeviceType(cec_device_type from, cec_device_type to);
virtual bool FindLogicalAddresses(void);
virtual bool SetAckMask(uint16_t iMask);

Expand Down
42 changes: 35 additions & 7 deletions src/lib/devices/CECBusDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,13 @@ bool CCECBusDevice::RequestCecVersion(void)

if (!MyLogicalAddressContains(m_iLogicalAddress))
{
m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting CEC version of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);

bReturn = m_handler->TransmitRequestCecVersion(GetMyLogicalAddress(), m_iLogicalAddress);
m_handler->MarkReady();
}
return bReturn;
}
Expand Down Expand Up @@ -213,14 +215,22 @@ bool CCECBusDevice::RequestMenuLanguage(void)
if (!MyLogicalAddressContains(m_iLogicalAddress) &&
!IsUnsupportedFeature(CEC_OPCODE_GET_MENU_LANGUAGE))
{
m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting menu language of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestMenuLanguage(GetMyLogicalAddress(), m_iLogicalAddress);
m_handler->MarkReady();
}
return bReturn;
}

cec_menu_state CCECBusDevice::GetMenuState(void)
{
CLockObject lock(&m_mutex);
return m_menuState;
}

cec_logical_address CCECBusDevice::GetMyLogicalAddress(void) const
{
return m_processor->GetLogicalAddress();
Expand Down Expand Up @@ -255,10 +265,12 @@ bool CCECBusDevice::RequestOSDName(void)
if (!MyLogicalAddressContains(m_iLogicalAddress) &&
!IsUnsupportedFeature(CEC_OPCODE_GIVE_OSD_NAME))
{
m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting OSD name of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestOSDName(GetMyLogicalAddress(), m_iLogicalAddress);
m_handler->MarkReady();
}
return bReturn;
}
Expand All @@ -285,10 +297,12 @@ bool CCECBusDevice::RequestPhysicalAddress(void)

if (!MyLogicalAddressContains(m_iLogicalAddress))
{
m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting physical address of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestPhysicalAddress(GetMyLogicalAddress(), m_iLogicalAddress);
m_handler->MarkReady();
}
return bReturn;
}
Expand Down Expand Up @@ -317,10 +331,12 @@ bool CCECBusDevice::RequestPowerStatus(void)
if (!MyLogicalAddressContains(m_iLogicalAddress) &&
!IsUnsupportedFeature(CEC_OPCODE_GIVE_DEVICE_POWER_STATUS))
{
m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting power status of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestPowerStatus(GetMyLogicalAddress(), m_iLogicalAddress);
m_handler->MarkReady();
}
return bReturn;
}
Expand All @@ -347,10 +363,14 @@ bool CCECBusDevice::RequestVendorId(void)

if (!MyLogicalAddressContains(m_iLogicalAddress))
{
m_handler->MarkBusy();
CStdString strLog;
strLog.Format("<< requesting vendor ID of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
AddLog(CEC_LOG_NOTICE, strLog);
bReturn = m_handler->TransmitRequestVendorId(GetMyLogicalAddress(), m_iLogicalAddress);
m_handler->MarkReady();

ReplaceHandler(true);
}
return bReturn;
}
Expand Down Expand Up @@ -600,16 +620,23 @@ void CCECBusDevice::SetPowerStatus(const cec_power_status powerStatus)
}
}

bool CCECBusDevice::ReplaceHandler(bool bInitHandler /* = true */)
bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */)
{
CLockObject lock(&m_mutex);
CLockObject handlerLock(&m_handlerMutex);

if (m_vendor != m_handler->GetVendorId())
{
CStdString strLog;
if (m_handler->InUse())
{
strLog.Format("handler for device '%s' (%x) is being used. not replacing the command handler", GetLogicalAddressName(), GetLogicalAddress());
m_processor->AddLog(CEC_LOG_DEBUG, strLog);
return false;
}

strLog.Format("replacing the command handler for device '%s' (%x)", GetLogicalAddressName(), GetLogicalAddress());
m_processor->AddLog(CEC_LOG_DEBUG, strLog);
delete m_handler;

switch (m_vendor)
Expand All @@ -628,22 +655,23 @@ bool CCECBusDevice::ReplaceHandler(bool bInitHandler /* = true */)
break;
}

if (bInitHandler && m_processor->GetLogicalAddresses().IsSet(m_iLogicalAddress) && m_processor->IsInitialised())
m_handler->InitHandler();
m_handler->InitHandler();

if (bActivateSource && m_processor->GetLogicalAddresses().IsSet(m_iLogicalAddress) && m_processor->IsInitialised())
m_handler->ActivateSource();
}

return true;
}

bool CCECBusDevice::SetVendorId(uint64_t iVendorId, bool bInitHandler /* = true */)
bool CCECBusDevice::SetVendorId(uint64_t iVendorId)
{
bool bVendorChanged(false);

{
CLockObject lock(&m_mutex);
bVendorChanged = (m_vendor != (cec_vendor_id)iVendorId);
m_vendor = (cec_vendor_id)iVendorId;
ReplaceHandler(bInitHandler);
}

CStdString strLog;
Expand Down Expand Up @@ -874,10 +902,10 @@ void CCECBusDevice::SetUnsupportedFeature(cec_opcode opcode)
m_unsupportedFeatures.insert(opcode);
}

bool CCECBusDevice::InitHandler(void)
bool CCECBusDevice::ActivateSource(void)
{
CLockObject lock(&m_mutex);
return m_handler->InitHandler();
return m_handler->ActivateSource();
}

//@}
5 changes: 3 additions & 2 deletions src/lib/devices/CECBusDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace CEC
virtual cec_logical_address GetLogicalAddress(void) const { return m_iLogicalAddress; }
virtual const char* GetLogicalAddressName(void) const;
virtual cec_menu_language & GetMenuLanguage(bool bUpdate = false);
virtual cec_menu_state GetMenuState(void);
virtual cec_logical_address GetMyLogicalAddress(void) const;
virtual uint16_t GetMyPhysicalAddress(void) const;
virtual CStdString GetOSDName(bool bUpdate = false);
Expand All @@ -80,7 +81,7 @@ namespace CEC
virtual void SetInactiveSource(void);
virtual void SetActiveSource(void);
virtual bool TryLogicalAddress(void);
virtual bool InitHandler(void);
virtual bool ActivateSource(void);

virtual void SetDeviceStatus(const cec_bus_device_status newStatus);
virtual void SetPhysicalAddress(uint16_t iNewAddress);
Expand All @@ -89,7 +90,7 @@ namespace CEC
virtual void SetMenuLanguage(const cec_menu_language &menuLanguage);
virtual void SetOSDName(CStdString strName);
virtual void SetMenuState(const cec_menu_state state);
virtual bool SetVendorId(uint64_t iVendorId, bool bInitHandler = true);
virtual bool SetVendorId(uint64_t iVendorId);
virtual void SetPowerStatus(const cec_power_status powerStatus);

virtual bool TransmitActiveSource(void);
Expand Down

0 comments on commit 3e61b35

Please sign in to comment.