using namespace std;
using namespace PLATFORM;
-CCECProcessor::CCECProcessor(CLibCEC *controller, const libcec_configuration *configuration) :
+CCECProcessor::CCECProcessor(CLibCEC *controller, libcec_configuration *configuration) :
+ m_bConnectionOpened(false),
m_bInitialised(false),
m_communication(NULL),
m_controller(controller),
m_iRetryLineTimeout(3),
m_iLastTransmission(0)
{
- m_logicalAddresses.Clear();
CreateBusDevices();
m_configuration.Clear();
-
+ m_configuration.serverVersion = CEC_SERVER_VERSION_1_6_0;
SetConfiguration(configuration);
if (m_configuration.tvVendor != CEC_VENDOR_UNKNOWN)
m_busDevices[CECDEVICE_TV]->ReplaceHandler(false);
}
-CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, const cec_device_type_list &types, uint16_t iPhysicalAddress, cec_client_version clientVersion) :
+CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, const cec_device_type_list &types, uint16_t iPhysicalAddress) :
+ m_bConnectionOpened(false),
m_bInitialised(false),
m_communication(NULL),
m_controller(controller),
m_iLastTransmission(0)
{
m_configuration.Clear();
+ m_configuration.serverVersion = CEC_SERVER_VERSION_1_6_0;
// client version < 1.5.0
- m_configuration.clientVersion = clientVersion;
+ m_configuration.clientVersion = (uint32_t)CEC_CLIENT_VERSION_PRE_1_5;
snprintf(m_configuration.strDeviceName, 13, "%s", strDeviceName);
m_configuration.deviceTypes = types;
m_configuration.iPhysicalAddress = iPhysicalAddress;
if (m_configuration.deviceTypes.IsEmpty())
m_configuration.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
- m_logicalAddresses.Clear();
CreateBusDevices();
}
Close();
for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+ {
delete m_busDevices[iPtr];
+ m_busDevices[iPtr] = NULL;
+ }
}
void CCECProcessor::Close(void)
{
+ StopThread(false);
+ SetInitialised(false);
StopThread();
- CLockObject lock(m_mutex);
- if (m_communication)
+ bool bClose(false);
+ {
+ CLockObject lock(m_mutex);
+ bClose = m_bConnectionOpened;
+ m_bConnectionOpened = false;
+ }
+
+ if (bClose && m_communication)
{
+ m_communication->PersistConfiguration(&m_configuration);
m_communication->Close();
delete m_communication;
m_communication = NULL;
}
}
-bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint32_t iTimeoutMs)
+bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint32_t iTimeoutMs, bool bStartListening /* = true */)
{
bool bReturn(false);
- CLockObject lock(m_mutex);
- if (m_communication)
+ Close();
+
{
- CLibCEC::AddLog(CEC_LOG_WARNING, "existing connection handler found, deleting it");
- m_communication->Close();
- delete m_communication;
+ CLockObject lock(m_mutex);
+ if (m_bConnectionOpened)
+ {
+ CLibCEC::AddLog(CEC_LOG_ERROR, "connection already opened");
+ return false;
+ }
+ m_communication = new CUSBCECAdapterCommunication(this, strPort, iBaudRate);
+ m_bConnectionOpened = (m_communication != NULL);
}
- m_communication = new CUSBCECAdapterCommunication(this, strPort, iBaudRate);
-
/* check for an already opened connection */
if (m_communication->IsOpen())
{
return bReturn;
}
- uint64_t iNow = GetTimeMs();
- uint64_t iTarget = iTimeoutMs > 0 ? iNow + iTimeoutMs : iNow + CEC_DEFAULT_TRANSMIT_WAIT;
+ CTimeout timeout(iTimeoutMs > 0 ? iTimeoutMs : CEC_DEFAULT_TRANSMIT_WAIT);
/* open a new connection */
unsigned iConnectTry(0);
- while (iNow < iTarget && (bReturn = m_communication->Open(this, iTimeoutMs)) == false)
+ while (timeout.TimeLeft() > 0 && (bReturn = m_communication->Open((timeout.TimeLeft() / CEC_CONNECT_TRIES), false, bStartListening)) == false)
{
CLibCEC::AddLog(CEC_LOG_ERROR, "could not open a connection (try %d)", ++iConnectTry);
- Sleep(500);
- iNow = GetTimeMs();
+ m_communication->Close();
+ CEvent::Sleep(1000);
}
if (bReturn)
- CLibCEC::AddLog(CEC_LOG_NOTICE, "connected to the CEC adapter. firmware version = %d, client version = %s", m_communication->GetFirmwareVersion(), ToString(m_configuration.clientVersion));
+ {
+ m_configuration.iFirmwareVersion = m_communication->GetFirmwareVersion();
+ CLibCEC::AddLog(CEC_LOG_NOTICE, "connected to the CEC adapter. firmware version = %d, client version = %s", m_configuration.iFirmwareVersion, ToString((cec_client_version)m_configuration.clientVersion));
+ }
+
+ if (m_configuration.bGetSettingsFromROM == 1)
+ m_communication->GetConfiguration(&m_configuration);
return bReturn;
}
bool bReturn(false);
{
CLockObject lock(m_mutex);
- if (!m_logicalAddresses.IsEmpty())
- m_logicalAddresses.Clear();
+ if (!m_configuration.logicalAddresses.IsEmpty())
+ m_configuration.logicalAddresses.Clear();
if (!FindLogicalAddresses())
{
}
/* only set our OSD name for the primary device */
- m_busDevices[m_logicalAddresses.primary]->m_strDeviceName = m_configuration.strDeviceName;
+ m_busDevices[m_configuration.logicalAddresses.primary]->m_strDeviceName = m_configuration.strDeviceName;
+
+ /* make the primary device the active source if the option is set */
+ if (m_configuration.bActivateSource == 1)
+ m_busDevices[m_configuration.logicalAddresses.primary]->m_bActiveSource = true;
}
/* get the vendor id from the TV, so we are using the correct handler */
if (m_configuration.iPhysicalAddress != 0)
{
CLibCEC::AddLog(CEC_LOG_NOTICE, "setting the physical address to %4x", m_configuration.iPhysicalAddress);
- m_busDevices[m_logicalAddresses.primary]->m_iPhysicalAddress = m_configuration.iPhysicalAddress;
- if ((bReturn = m_busDevices[m_logicalAddresses.primary]->TransmitPhysicalAddress()) == false)
+ m_busDevices[m_configuration.logicalAddresses.primary]->m_iPhysicalAddress = m_configuration.iPhysicalAddress;
+ if ((bReturn = m_busDevices[m_configuration.logicalAddresses.primary]->TransmitPhysicalAddress()) == false)
CLibCEC::AddLog(CEC_LOG_ERROR, "unable to set the physical address to %4x", m_configuration.iPhysicalAddress);
}
else if (m_configuration.iPhysicalAddress == 0 && (bReturn = SetHDMIPort(m_configuration.baseDevice, m_configuration.iHDMIPort, true)) == false)
CLibCEC::AddLog(CEC_LOG_ERROR, "unable to set HDMI port %d on %s (%x)", m_configuration.iHDMIPort, ToString(m_configuration.baseDevice), (uint8_t)m_configuration.baseDevice);
- PowerOnDevices();
+ if (bReturn && m_configuration.bActivateSource == 1)
+ m_busDevices[m_configuration.logicalAddresses.primary]->ActivateSource();
SetInitialised(bReturn);
- CLibCEC::ConfigurationChanged(m_configuration);
+ if (bReturn)
+ CLibCEC::ConfigurationChanged(m_configuration);
return bReturn;
}
{
if (m_busDevices[address]->TryLogicalAddress())
{
- m_logicalAddresses.Set(address);
+ m_configuration.logicalAddresses.Set(address);
return true;
}
CLockObject lock(m_mutex);
CCECBusDevice *previousDevice = GetDeviceByType(from);
- m_logicalAddresses.primary = CECDEVICE_UNKNOWN;
+ m_configuration.logicalAddresses.primary = CECDEVICE_UNKNOWN;
for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
{
bool CCECProcessor::FindLogicalAddresses(void)
{
bool bReturn(true);
- m_logicalAddresses.Clear();
+ m_configuration.logicalAddresses.Clear();
if (m_configuration.deviceTypes.IsEmpty())
{
}
if (bReturn)
- SetAckMask(m_logicalAddresses.AckMask());
+ SetAckMask(m_configuration.logicalAddresses.AckMask());
return bReturn;
}
bool CCECProcessor::OnCommandReceived(const cec_command &command)
{
- m_commandBuffer.Push(command);
- return true;
+ return m_inBuffer.Push(command);
}
void *CCECProcessor::Process(void)
{
- cec_command command;
CLibCEC::AddLog(CEC_LOG_DEBUG, "processor thread started");
+ cec_command command;
+ command.Clear();
+
while (!IsStopped() && m_communication->IsOpen())
{
+ if (m_inBuffer.Pop(command, 500))
+ ParseCommand(command);
+
if (IsInitialised())
{
ReplaceHandlers();
- if (m_commandBuffer.Pop(command))
- ParseCommand(command);
m_controller->CheckKeypressTimeout();
}
- Sleep(5);
}
return NULL;
if (!IsRunning())
return bReturn;
- cec_logical_address addr = m_logicalAddresses.primary;
+ cec_logical_address addr = m_configuration.logicalAddresses.primary;
if (type != CEC_DEVICE_TYPE_RESERVED)
{
for (uint8_t iPtr = 0; iPtr <= 11; iPtr++)
{
- if (m_logicalAddresses[iPtr] && m_busDevices[iPtr]->m_type == type)
+ if (m_configuration.logicalAddresses[iPtr] && m_busDevices[iPtr]->m_type == type)
{
addr = (cec_logical_address) iPtr;
break;
{
bool bReturn(false);
- CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamPath);
+ // suppress polls when searching for a device
+ CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamPath, false, true);
if (device)
{
device->SetActiveSource();
bool CCECProcessor::SetActiveView(void)
{
+ CLibCEC::AddLog(CEC_LOG_WARNING, "deprecated method %s called", __FUNCTION__);
return SetActiveSource(m_configuration.deviceTypes.IsEmpty() ? CEC_DEVICE_TYPE_RESERVED : m_configuration.deviceTypes[0]);
}
bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort, bool bForce /* = false */)
{
bool bReturn(false);
- CLockObject lock(m_mutex);
- m_configuration.baseDevice = iBaseDevice;
- m_configuration.iHDMIPort = iPort;
+ // limit the HDMI port range to 1-15
+ if (iPort < 1)
+ iPort = 1;
+ if (iPort > 15)
+ iPort = 15;
+
+ {
+ CLockObject lock(m_mutex);
+ m_configuration.baseDevice = iBaseDevice;
+ m_configuration.iHDMIPort = iPort;
+ }
+
if (!IsRunning() && !bForce)
return true;
uint16_t iPhysicalAddress(0);
if (iBaseDevice > CECDEVICE_TV)
{
- lock.Unlock();
iPhysicalAddress = m_busDevices[iBaseDevice]->GetPhysicalAddress();
- lock.Lock();
}
if (iPhysicalAddress < 0xffff)
if (!bReturn)
CLibCEC::AddLog(CEC_LOG_ERROR, "failed to set the physical address");
else
- {
- lock.Unlock();
SetPhysicalAddress(iPhysicalAddress);
- }
return bReturn;
}
if (!IsRunning())
return false;
- if (!m_logicalAddresses.IsEmpty() && m_busDevices[m_logicalAddresses.primary])
- return m_busDevices[m_logicalAddresses.primary]->TransmitInactiveSource();
+ if (!m_configuration.logicalAddresses.IsEmpty() && m_busDevices[m_configuration.logicalAddresses.primary])
+ return m_busDevices[m_configuration.logicalAddresses.primary]->TransmitInactiveSource();
return false;
}
bool CCECProcessor::SetLogicalAddress(cec_logical_address iLogicalAddress)
{
CLockObject lock(m_mutex);
- if (m_logicalAddresses.primary != iLogicalAddress)
+ if (m_configuration.logicalAddresses.primary != iLogicalAddress)
{
CLibCEC::AddLog(CEC_LOG_NOTICE, "<< setting primary logical address to %1x", iLogicalAddress);
- m_logicalAddresses.primary = iLogicalAddress;
- m_logicalAddresses.Set(iLogicalAddress);
- return SetAckMask(m_logicalAddresses.AckMask());
+ m_configuration.logicalAddresses.primary = iLogicalAddress;
+ m_configuration.logicalAddresses.Set(iLogicalAddress);
+ return SetAckMask(m_configuration.logicalAddresses.AckMask());
}
return true;
{
for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
{
- if (m_logicalAddresses[iPtr])
+ if (m_configuration.logicalAddresses[iPtr])
m_busDevices[iPtr]->SetMenuState(state);
}
if (bSendUpdate)
- m_busDevices[m_logicalAddresses.primary]->TransmitMenuState(CECDEVICE_TV);
+ m_busDevices[m_configuration.logicalAddresses.primary]->TransmitMenuState(CECDEVICE_TV);
return true;
}
{
CLockObject lock(m_mutex);
m_configuration.iPhysicalAddress = iPhysicalAddress;
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "setting physical address to '%4x'", iPhysicalAddress);
- if (!m_logicalAddresses.IsEmpty())
+ if (!m_configuration.logicalAddresses.IsEmpty())
{
bool bWasActiveSource(false);
for (uint8_t iPtr = 0; iPtr < 15; iPtr++)
- if (m_logicalAddresses[iPtr])
+ if (m_configuration.logicalAddresses[iPtr])
{
bWasActiveSource |= m_busDevices[iPtr]->IsActiveSource();
m_busDevices[iPtr]->SetInactiveSource();
if (bEnable)
return SetAckMask(0);
else
- return SetAckMask(m_logicalAddresses.AckMask());
+ return SetAckMask(m_configuration.logicalAddresses.AckMask());
}
bool CCECProcessor::PollDevice(cec_logical_address iAddress)
{
if (iAddress != CECDEVICE_UNKNOWN && m_busDevices[iAddress])
{
- return m_logicalAddresses.primary == CECDEVICE_UNKNOWN ?
+ return m_configuration.logicalAddresses.primary == CECDEVICE_UNKNOWN ?
m_busDevices[iAddress]->TransmitPoll(iAddress) :
- m_busDevices[m_logicalAddresses.primary]->TransmitPoll(iAddress);
+ m_busDevices[m_configuration.logicalAddresses.primary]->TransmitPoll(iAddress);
}
return false;
}
return status;
}
-CCECBusDevice *CCECProcessor::GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress, bool bRefresh /* = false */) const
+CCECBusDevice *CCECProcessor::GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress, bool bRefresh /* = false */, bool bSuppressPoll /* = false */) const
{
- if (m_busDevices[m_logicalAddresses.primary]->GetPhysicalAddress(false) == iPhysicalAddress)
- return m_busDevices[m_logicalAddresses.primary];
+ if (m_busDevices[m_configuration.logicalAddresses.primary]->GetPhysicalAddress(false) == iPhysicalAddress)
+ return m_busDevices[m_configuration.logicalAddresses.primary];
CCECBusDevice *device = NULL;
for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
{
- if (m_busDevices[iPtr]->GetPhysicalAddress(bRefresh) == iPhysicalAddress)
+ if (m_busDevices[iPtr]->GetPhysicalAddress(bRefresh, bSuppressPoll) == iPhysicalAddress)
{
device = m_busDevices[iPtr];
break;
for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
{
- if (m_busDevices[iPtr]->m_type == type && m_logicalAddresses[iPtr])
+ if (m_busDevices[iPtr]->m_type == type && m_configuration.logicalAddresses[iPtr])
{
device = m_busDevices[iPtr];
break;
CCECBusDevice *CCECProcessor::GetPrimaryDevice(void) const
{
CCECBusDevice *device(NULL);
- cec_logical_address primary = m_logicalAddresses.primary;
+ cec_logical_address primary = m_configuration.logicalAddresses.primary;
if (primary != CECDEVICE_UNKNOWN)
device = m_busDevices[primary];
return device;
bool CCECProcessor::Transmit(const cec_command &data)
{
- cec_adapter_message_state retVal(ADAPTER_MESSAGE_STATE_UNKNOWN);
+ if (m_configuration.logicalAddresses[(uint8_t)data.destination])
+ {
+ CLibCEC::AddLog(CEC_LOG_WARNING, "not sending data to myself!");
+ return false;
+ }
+
+ uint8_t iMaxTries(0);
{
CLockObject lock(m_mutex);
+ if (IsStopped())
+ return false;
LogOutput(data);
m_iLastTransmission = GetTimeMs();
- if (!m_communication)
+ if (!m_communication || !m_communication->IsOpen())
+ {
+ CLibCEC::AddLog(CEC_LOG_ERROR, "cannot transmit command: connection closed");
return false;
- uint8_t iMaxTries = m_busDevices[data.initiator]->GetHandler()->GetTransmitRetries() + 1;
- retVal = m_communication->Write(data, iMaxTries, m_iLineTimeout, m_iRetryLineTimeout);
+ }
+ iMaxTries = m_busDevices[data.initiator]->GetHandler()->GetTransmitRetries() + 1;
}
- /* set to "not present" on failed ack */
- if (retVal == ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED &&
- data.destination != CECDEVICE_BROADCAST)
- m_busDevices[data.destination]->SetDeviceStatus(CEC_DEVICE_STATUS_NOT_PRESENT);
-
- return retVal == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ return m_communication->Write(data, iMaxTries, m_iStandardLineTimeout, m_iRetryLineTimeout)
+ == ADAPTER_MESSAGE_STATE_SENT_ACKED;
}
void CCECProcessor::TransmitAbort(cec_logical_address address, cec_opcode opcode, cec_abort_reason reason /* = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE */)
cec_command command;
// TODO
- cec_command::Format(command, m_logicalAddresses.primary, address, CEC_OPCODE_FEATURE_ABORT);
+ cec_command::Format(command, m_configuration.logicalAddresses.primary, address, CEC_OPCODE_FEATURE_ABORT);
command.parameters.PushBack((uint8_t)opcode);
command.parameters.PushBack((uint8_t)reason);
void CCECProcessor::ParseCommand(const cec_command &command)
{
CStdString dataStr;
- dataStr.Format(">> %1x%1x:%02x", command.initiator, command.destination, command.opcode);
+ dataStr.Format(">> %1x%1x", command.initiator, command.destination);
+ if (command.opcode_set == 1)
+ dataStr.AppendFormat(":%02x", command.opcode);
for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
dataStr.AppendFormat(":%02x", (unsigned int)command.parameters[iPtr]);
CLibCEC::AddLog(CEC_LOG_TRAFFIC, dataStr.c_str());
uint16_t CCECProcessor::GetPhysicalAddress(void) const
{
- if (!m_logicalAddresses.IsEmpty() && m_busDevices[m_logicalAddresses.primary])
- return m_busDevices[m_logicalAddresses.primary]->GetPhysicalAddress(false);
+ if (!m_configuration.logicalAddresses.IsEmpty() && m_busDevices[m_configuration.logicalAddresses.primary])
+ return m_busDevices[m_configuration.logicalAddresses.primary]->GetPhysicalAddress(false);
return false;
}
return m_busDevices[iDestination]->TransmitKeyRelease(bWait);
}
+bool CCECProcessor::EnablePhysicalAddressDetection(void)
+{
+ CLibCEC::AddLog(CEC_LOG_WARNING, "deprecated method %s called", __FUNCTION__);
+ uint16_t iPhysicalAddress = m_communication->GetPhysicalAddress();
+ if (iPhysicalAddress != 0)
+ {
+ m_configuration.bAutodetectAddress = 1;
+ m_configuration.iPhysicalAddress = iPhysicalAddress;
+ m_configuration.baseDevice = CECDEVICE_UNKNOWN;
+ m_configuration.iHDMIPort = 0;
+ return SetPhysicalAddress(iPhysicalAddress);
+ }
+ return false;
+}
+
bool CCECProcessor::StandbyDevices(cec_logical_address address /* = CECDEVICE_BROADCAST */)
{
if (address == CECDEVICE_BROADCAST && m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_0)
return "system audio mode status";
case CEC_OPCODE_SET_AUDIO_RATE:
return "set audio rate";
+ case CEC_OPCODE_NONE:
+ return "poll";
default:
return "UNKNOWN";
}
return "Philips";
case CEC_VENDOR_SONY:
return "Sony";
+ case CEC_VENDOR_TOSHIBA:
+ return "Toshiba";
default:
return "Unknown";
}
return "pre-1.5";
case CEC_CLIENT_VERSION_1_5_0:
return "1.5.0";
+ case CEC_CLIENT_VERSION_1_5_1:
+ return "1.5.1";
+ case CEC_CLIENT_VERSION_1_5_2:
+ return "1.5.2";
+ case CEC_CLIENT_VERSION_1_5_3:
+ return "1.5.3";
+ case CEC_CLIENT_VERSION_1_6_0:
+ return "1.6.0";
+ default:
+ return "Unknown";
+ }
+}
+
+const char *CCECProcessor::ToString(const cec_server_version version)
+{
+ switch (version)
+ {
+ case CEC_SERVER_VERSION_PRE_1_5:
+ return "pre-1.5";
+ case CEC_SERVER_VERSION_1_5_0:
+ return "1.5.0";
+ case CEC_SERVER_VERSION_1_5_1:
+ return "1.5.1";
+ case CEC_SERVER_VERSION_1_5_2:
+ return "1.5.2";
+ case CEC_SERVER_VERSION_1_5_3:
+ return "1.5.3";
+ case CEC_SERVER_VERSION_1_6_0:
+ return "1.6.0";
default:
return "Unknown";
}
}
}
-bool CCECProcessor::StartBootloader(void)
+bool CCECProcessor::StartBootloader(const char *strPort /* = NULL */)
{
- return m_communication->StartBootloader();
+ if (!m_communication && strPort)
+ {
+ bool bReturn(false);
+ IAdapterCommunication *comm = new CUSBCECAdapterCommunication(this, strPort);
+ CTimeout timeout(10000);
+ int iConnectTry(0);
+ while (timeout.TimeLeft() > 0 && (bReturn = comm->Open(NULL, (timeout.TimeLeft() / CEC_CONNECT_TRIES)), true) == false)
+ {
+ CLibCEC::AddLog(CEC_LOG_ERROR, "could not open a connection (try %d)", ++iConnectTry);
+ comm->Close();
+ Sleep(500);
+ }
+ if (comm->IsOpen())
+ {
+ bReturn = comm->StartBootloader();
+ delete comm;
+ }
+ return bReturn;
+ }
+ else
+ {
+ return m_communication->StartBootloader();
+ }
}
bool CCECProcessor::PingAdapter(void)
void CCECProcessor::HandlePoll(cec_logical_address initiator, cec_logical_address destination)
{
- m_busDevices[initiator]->HandlePoll(destination);
+ if (destination < CECDEVICE_BROADCAST)
+ m_busDevices[destination]->HandlePollFrom(initiator);
}
bool CCECProcessor::HandleReceiveFailed(cec_logical_address initiator)
bool CCECProcessor::SetConfiguration(const libcec_configuration *configuration)
{
- bool bReinit(false);
- bool bPhysicalAddressChanged(false);
- bool bHdmiPortChanged(false);
- bool bDeviceTypeChanged(false);
+ bool bReinit(false);
CCECBusDevice *primary = IsRunning() ? GetPrimaryDevice() : NULL;
- cec_device_type oldPrimaryType = primary ? primary->GetType() : CEC_DEVICE_TYPE_RECORDING_DEVICE;
+ cec_device_type oldPrimaryType = primary ? primary->GetType() : CEC_DEVICE_TYPE_RECORDING_DEVICE;
m_configuration.clientVersion = configuration->clientVersion;
// client version 1.5.0
// device types
- bDeviceTypeChanged |= IsRunning () && m_configuration.deviceTypes != configuration->deviceTypes;
+ bool bDeviceTypeChanged = IsRunning () && m_configuration.deviceTypes != configuration->deviceTypes;
m_configuration.deviceTypes = configuration->deviceTypes;
- // physical address
- bPhysicalAddressChanged |= IsRunning() && m_configuration.iPhysicalAddress != configuration->iPhysicalAddress;
- m_configuration.iPhysicalAddress = configuration->iPhysicalAddress;
+ bool bPhysicalAddressChanged(false);
- // base device
- bHdmiPortChanged |= IsRunning() && m_configuration.baseDevice != configuration->baseDevice;
- m_configuration.baseDevice = configuration->baseDevice;
+ // autodetect address
+ bool bPhysicalAutodetected(false);
+ if (IsRunning() && configuration->bAutodetectAddress == 1)
+ {
+ uint16_t iPhysicalAddress = m_communication->GetPhysicalAddress();
+ if (iPhysicalAddress != 0)
+ {
+ if (IsRunning())
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - autodetected physical address '%4x'", __FUNCTION__, iPhysicalAddress);
+ bPhysicalAddressChanged = (m_configuration.iPhysicalAddress != iPhysicalAddress);
+ m_configuration.iPhysicalAddress = iPhysicalAddress;
+ m_configuration.iHDMIPort = 0;
+ m_configuration.baseDevice = CECDEVICE_UNKNOWN;
+ bPhysicalAutodetected = true;
+ }
+ }
- // hdmi port
- bHdmiPortChanged |= IsRunning() && m_configuration.iHDMIPort != configuration->iHDMIPort;
- m_configuration.iHDMIPort = configuration->iHDMIPort;
+ // physical address
+ if (!bPhysicalAutodetected)
+ {
+ if (configuration->iPhysicalAddress != 0)
+ bPhysicalAddressChanged = IsRunning() && m_configuration.iPhysicalAddress != configuration->iPhysicalAddress;
+ if (bPhysicalAddressChanged)
+ {
+ if (IsRunning())
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - using physical address '%4x'", __FUNCTION__, configuration->iPhysicalAddress);
+ m_configuration.iPhysicalAddress = configuration->iPhysicalAddress;
+ }
+ }
- bReinit = bPhysicalAddressChanged || bHdmiPortChanged || bDeviceTypeChanged;
+ bool bHdmiPortChanged(false);
+ if (!bPhysicalAutodetected && !bPhysicalAddressChanged)
+ {
+ // base device
+ bHdmiPortChanged = IsRunning() && m_configuration.baseDevice != configuration->baseDevice;
+ if (IsRunning())
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - using base device '%x'", __FUNCTION__, (int)configuration->baseDevice);
+ m_configuration.baseDevice = configuration->baseDevice;
+
+ // hdmi port
+ bHdmiPortChanged |= IsRunning() && m_configuration.iHDMIPort != configuration->iHDMIPort;
+ if (IsRunning())
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - using HDMI port '%d'", __FUNCTION__, configuration->iHDMIPort);
+ m_configuration.iHDMIPort = configuration->iHDMIPort;
+ }
+ else
+ {
+ if (IsRunning())
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - resetting HDMI port and base device to defaults", __FUNCTION__);
+ m_configuration.baseDevice = CECDEVICE_UNKNOWN;
+ m_configuration.iHDMIPort = 0;
+ }
+
+ bReinit = bPhysicalAddressChanged || bHdmiPortChanged || bDeviceTypeChanged;
// device name
snprintf(m_configuration.strDeviceName, 13, "%s", configuration->strDeviceName);
}
// just copy these
+ m_configuration.clientVersion = configuration->clientVersion;
+ m_configuration.bUseTVMenuLanguage = configuration->bUseTVMenuLanguage;
+ m_configuration.bActivateSource = configuration->bActivateSource;
m_configuration.bGetSettingsFromROM = configuration->bGetSettingsFromROM;
m_configuration.powerOffDevices = configuration->powerOffDevices;
m_configuration.bPowerOffScreensaver = configuration->bPowerOffScreensaver;
m_configuration.bPowerOffOnStandby = configuration->bPowerOffOnStandby;
+ // client version 1.5.1
+ if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_5_1)
+ m_configuration.bSendInactiveSource = configuration->bSendInactiveSource;
+
+ // client version 1.6.0
+ if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_6_0)
+ {
+ m_configuration.bPowerOffDevicesOnStandby = configuration->bPowerOffDevicesOnStandby;
+ m_configuration.bShutdownOnStandby = configuration->bShutdownOnStandby;
+ }
+
// ensure that there is at least 1 device type set
if (m_configuration.deviceTypes.IsEmpty())
m_configuration.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
if (bReinit)
{
- if (bDeviceTypeChanged)
- return ChangeDeviceType(oldPrimaryType, m_configuration.deviceTypes[0]);
- else if (bPhysicalAddressChanged)
- return SetPhysicalAddress(m_configuration.iPhysicalAddress);
- else
+ if (bDeviceTypeChanged)
+ return ChangeDeviceType(oldPrimaryType, m_configuration.deviceTypes[0]);
+ else if (bPhysicalAddressChanged)
+ return SetPhysicalAddress(m_configuration.iPhysicalAddress);
+ else
return SetHDMIPort(m_configuration.baseDevice, m_configuration.iHDMIPort);
}
+ else if (m_configuration.bActivateSource == 1 && IsRunning() && !IsActiveSource(m_configuration.logicalAddresses.primary))
+ {
+ // activate the source if we're not already the active source
+ SetActiveSource(m_configuration.deviceTypes.types[0]);
+ }
return true;
}
bool CCECProcessor::GetCurrentConfiguration(libcec_configuration *configuration)
{
// client version 1.5.0
- configuration->clientVersion = m_configuration.clientVersion;
snprintf(configuration->strDeviceName, 13, "%s", m_configuration.strDeviceName);
configuration->deviceTypes = m_configuration.deviceTypes;
+ configuration->bAutodetectAddress = m_configuration.bAutodetectAddress;
configuration->iPhysicalAddress = m_configuration.iPhysicalAddress;
configuration->baseDevice = m_configuration.baseDevice;
configuration->iHDMIPort = m_configuration.iHDMIPort;
+ configuration->clientVersion = m_configuration.clientVersion;
+ configuration->serverVersion = m_configuration.serverVersion;
configuration->tvVendor = m_configuration.tvVendor;
- configuration->wakeDevices = m_configuration.wakeDevices;
+
configuration->bGetSettingsFromROM = m_configuration.bGetSettingsFromROM;
+ configuration->bUseTVMenuLanguage = m_configuration.bUseTVMenuLanguage;
+ configuration->bActivateSource = m_configuration.bActivateSource;
+ configuration->wakeDevices = m_configuration.wakeDevices;
configuration->powerOffDevices = m_configuration.powerOffDevices;
configuration->bPowerOffScreensaver = m_configuration.bPowerOffScreensaver;
configuration->bPowerOffOnStandby = m_configuration.bPowerOffOnStandby;
+ // client version 1.5.1
+ if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_5_1)
+ configuration->bSendInactiveSource = m_configuration.bSendInactiveSource;
+
+ // client version 1.5.3
+ if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_5_3)
+ configuration->logicalAddresses = m_configuration.logicalAddresses;
+
+ // client version 1.6.0
+ if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_6_0)
+ {
+ configuration->iFirmwareVersion = m_configuration.iFirmwareVersion;
+ configuration->bPowerOffDevicesOnStandby = m_configuration.bPowerOffDevicesOnStandby;
+ configuration->bShutdownOnStandby = m_configuration.bShutdownOnStandby;
+ }
+
return true;
}
{
return m_communication->PersistConfiguration(configuration);
}
+
+void CCECProcessor::RescanActiveDevices(void)
+{
+ for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+ m_busDevices[iPtr]->GetStatus(true);
+}
+
+bool CCECProcessor::GetDeviceInformation(const char *strPort, libcec_configuration *config, uint32_t iTimeoutMs /* = 10000 */)
+{
+ if (!OpenConnection(strPort, 38400, iTimeoutMs, false))
+ return false;
+
+ config->iFirmwareVersion = m_communication->GetFirmwareVersion();
+ config->iPhysicalAddress = m_communication->GetPhysicalAddress();
+
+ delete m_communication;
+ m_communication = NULL;
+ return true;
+}