{
CreateBusDevices();
m_configuration.Clear();
- m_configuration.serverVersion = CEC_SERVER_VERSION_1_6_0;
+ m_configuration.serverVersion = CEC_SERVER_VERSION_1_6_1;
SetConfiguration(configuration);
if (m_configuration.tvVendor != CEC_VENDOR_UNKNOWN)
m_iLastTransmission(0)
{
m_configuration.Clear();
- m_configuration.serverVersion = CEC_SERVER_VERSION_1_6_0;
+ m_configuration.serverVersion = CEC_SERVER_VERSION_1_6_1;
// client version < 1.5.0
m_configuration.clientVersion = (uint32_t)CEC_CLIENT_VERSION_PRE_1_5;
if (bClose && m_communication)
{
- m_communication->PersistConfiguration(&m_configuration);
- m_communication->Close();
delete m_communication;
m_communication = NULL;
}
m_bConnectionOpened = (m_communication != NULL);
}
- /* check for an already opened connection */
- if (m_communication->IsOpen())
- {
- CLibCEC::AddLog(CEC_LOG_ERROR, "connection already opened");
- return bReturn;
- }
-
CTimeout timeout(iTimeoutMs > 0 ? iTimeoutMs : CEC_DEFAULT_TRANSMIT_WAIT);
/* open a new connection */
unsigned iConnectTry(0);
- while (timeout.TimeLeft() > 0 && (bReturn = m_communication->Open(this, (timeout.TimeLeft() / CEC_CONNECT_TRIES), false, bStartListening)) == 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);
m_communication->Close();
if (bReturn)
{
m_configuration.iFirmwareVersion = m_communication->GetFirmwareVersion();
+ uint32_t iBuildDate = m_communication->GetFirmwareBuildDate();
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 (iBuildDate > 0)
+ {
+ time_t buildTime = (time_t)iBuildDate;
+ CLibCEC::AddLog(CEC_LOG_NOTICE, "Firmware build date: %s", asctime(localtime(&buildTime)));
+ }
+
}
if (m_configuration.bGetSettingsFromROM == 1)
- m_communication->GetConfiguration(&m_configuration);
+ {
+ libcec_configuration config;
+ config.Clear();
+ m_communication->GetConfiguration(&config);
+
+ CLockObject lock(m_mutex);
+ if (!config.deviceTypes.IsEmpty())
+ m_configuration.deviceTypes = config.deviceTypes;
+ if (config.iPhysicalAddress > 0)
+ m_configuration.iPhysicalAddress = config.iPhysicalAddress;
+ snprintf(m_configuration.strDeviceName, 13, "%s", config.strDeviceName);
+ }
return bReturn;
}
bool CCECProcessor::IsInitialised(void)
{
- CLockObject lock(m_mutex);
+ CLockObject lock(m_threadMutex);
return m_bInitialised;
}
/* 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;
+
+ /* set the default menu language for devices we control */
+ cec_menu_language language;
+ language.device = m_configuration.logicalAddresses.primary;
+ memcpy(language.language, m_configuration.strDeviceLanguage, 3);
+ language.language[3] = 0;
+
+ for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
+ {
+ if (m_configuration.logicalAddresses[iPtr])
+ {
+ language.device = (cec_logical_address) iPtr;
+ m_busDevices[iPtr]->SetMenuLanguage(language);
+ }
+ }
}
/* get the vendor id from the TV, so we are using the correct handler */
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);
- if (m_configuration.bActivateSource == 1)
+ if (bReturn && m_configuration.bActivateSource == 1)
m_busDevices[m_configuration.logicalAddresses.primary]->ActivateSource();
SetInitialised(bReturn);
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);
{
bool bReturn(false);
- CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamPath);
+ // suppress polls when searching for a device
+ CCECBusDevice *device = GetDeviceByPhysicalAddress(iStreamPath, false, true);
if (device)
{
device->SetActiveSource();
SetActiveView();
if (bReturn)
- CLibCEC::ConfigurationChanged(m_configuration);
+ {
+ libcec_configuration config;
+ {
+ CLockObject lock(m_mutex);
+ config = m_configuration;
+ }
+
+ PersistConfiguration(&config);
+ CLibCEC::ConfigurationChanged(config);
+ }
return bReturn;
}
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_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;
return false;
}
+CStdString CCECProcessor::GetDeviceName(void) const
+{
+ CStdString strName;
+ strName = m_configuration.strDeviceName;
+ return strName;
+}
+
uint64_t CCECProcessor::GetDeviceVendorId(cec_logical_address iAddress)
{
if (m_busDevices[iAddress])
bool CCECProcessor::IsActiveSource(cec_logical_address iAddress)
{
- return m_busDevices[iAddress]->IsActiveSource();
+ return iAddress > CECDEVICE_TV && iAddress < CECDEVICE_BROADCAST ?
+ m_busDevices[iAddress]->IsActiveSource() :
+ false;
}
bool CCECProcessor::Transmit(const cec_command &data)
iMaxTries = m_busDevices[data.initiator]->GetHandler()->GetTransmitRetries() + 1;
}
- return m_communication->Write(data, iMaxTries, m_iStandardLineTimeout, m_iRetryLineTimeout)
- == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ bool bRetry(true);
+ uint8_t iTries(0);
+ uint8_t iLineTimeout = m_iStandardLineTimeout;
+ cec_adapter_message_state adapterState = ADAPTER_MESSAGE_STATE_UNKNOWN;
+
+ while (bRetry && ++iTries < iMaxTries)
+ {
+ if (m_busDevices[data.initiator]->IsUnsupportedFeature(data.opcode))
+ return false;
+
+ adapterState = m_communication->Write(data, bRetry, iLineTimeout);
+ iLineTimeout = m_iRetryLineTimeout;
+ }
+
+ return adapterState == ADAPTER_MESSAGE_STATE_SENT_ACKED;
}
void CCECProcessor::TransmitAbort(cec_logical_address address, cec_opcode opcode, cec_abort_reason reason /* = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE */)
bool CCECProcessor::SetAckMask(uint16_t iMask)
{
- return m_communication->SetAckMask(iMask);
+ return m_communication ? m_communication->SetAckMask(iMask) : false;
}
bool CCECProcessor::TransmitKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = true */)
for (uint8_t iPtr = 0; iPtr <= 0xF; iPtr++)
{
if (m_configuration.powerOffDevices[iPtr])
+ {
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - putting '%s' in standby mode", __FUNCTION__, ToString((cec_logical_address)iPtr));
bReturn &= m_busDevices[iPtr]->Standby();
+ }
}
return bReturn;
}
bool bReturn(true);
for (uint8_t iPtr = 0; iPtr <= 0xF; iPtr++)
{
- if (m_configuration.powerOffDevices[iPtr])
+ if (m_configuration.wakeDevices[iPtr])
+ {
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - powering on '%s'", __FUNCTION__, ToString((cec_logical_address)iPtr));
bReturn &= m_busDevices[iPtr]->PowerOn();
+ }
}
return bReturn;
}
return "1.5.3";
case CEC_CLIENT_VERSION_1_6_0:
return "1.6.0";
+ case CEC_CLIENT_VERSION_1_6_1:
+ return "1.6.1";
+ case CEC_CLIENT_VERSION_1_6_2:
+ return "1.6.2";
default:
return "Unknown";
}
return "1.5.3";
case CEC_SERVER_VERSION_1_6_0:
return "1.6.0";
+ case CEC_SERVER_VERSION_1_6_1:
+ return "1.6.1";
+ case CEC_SERVER_VERSION_1_6_2:
+ return "1.6.2";
default:
return "Unknown";
}
}
-void *CCECBusScan::Process(void)
-{
- CCECBusDevice *device(NULL);
- uint8_t iCounter(0);
-
- while (!IsStopped())
- {
- if (++iCounter < 10)
- {
- Sleep(1000);
- continue;
- }
- for (unsigned int iPtr = 0; iPtr <= 11 && !IsStopped(); iPtr++)
- {
- device = m_processor->m_busDevices[iPtr];
- WaitUntilIdle();
- if (device && device->GetStatus(true) == CEC_DEVICE_STATUS_PRESENT)
- {
- WaitUntilIdle();
- if (!IsStopped())
- device->GetVendorId();
-
- WaitUntilIdle();
- if (!IsStopped())
- device->GetPowerStatus(true);
- }
- }
- }
-
- return NULL;
-}
-
-void CCECBusScan::WaitUntilIdle(void)
-{
- if (IsStopped())
- return;
-
- int32_t iWaitTime = 3000 - (int32_t)(GetTimeMs() - m_processor->GetLastTransmission());
- while (iWaitTime > 0)
- {
- Sleep(iWaitTime);
- iWaitTime = 3000 - (int32_t)(GetTimeMs() - m_processor->GetLastTransmission());
- }
-}
-
bool CCECProcessor::StartBootloader(const char *strPort /* = NULL */)
{
if (!m_communication && strPort)
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)
+ while (timeout.TimeLeft() > 0 && (bReturn = comm->Open(timeout.TimeLeft() / CEC_CONNECT_TRIES, true)) == false)
{
CLibCEC::AddLog(CEC_LOG_ERROR, "could not open a connection (try %d)", ++iConnectTry);
comm->Close();
void CCECProcessor::HandlePoll(cec_logical_address initiator, cec_logical_address destination)
{
- m_busDevices[destination]->HandlePoll(initiator);
+ if (destination < CECDEVICE_BROADCAST)
+ m_busDevices[destination]->HandlePollFrom(initiator);
}
bool CCECProcessor::HandleReceiveFailed(cec_logical_address initiator)
CCECBusDevice *primary = IsRunning() ? GetPrimaryDevice() : NULL;
cec_device_type oldPrimaryType = primary ? primary->GetType() : CEC_DEVICE_TYPE_RECORDING_DEVICE;
m_configuration.clientVersion = configuration->clientVersion;
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - using client version '%s'", __FUNCTION__, ToString((cec_client_version)configuration->clientVersion));
// client version 1.5.0
// device types
bool bDeviceTypeChanged = IsRunning () && m_configuration.deviceTypes != configuration->deviceTypes;
m_configuration.deviceTypes = configuration->deviceTypes;
+ if (bDeviceTypeChanged)
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - using primary device type '%s'", __FUNCTION__, ToString(configuration->deviceTypes[0]));
bool bPhysicalAddressChanged(false);
{
if (IsRunning())
CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - autodetected physical address '%4x'", __FUNCTION__, iPhysicalAddress);
+ else
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - using physical address '%x'", __FUNCTION__, iPhysicalAddress);
bPhysicalAddressChanged = (m_configuration.iPhysicalAddress != iPhysicalAddress);
m_configuration.iPhysicalAddress = iPhysicalAddress;
m_configuration.iHDMIPort = 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);
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - physical address '%x'", __FUNCTION__, configuration->iPhysicalAddress);
m_configuration.iPhysicalAddress = configuration->iPhysicalAddress;
}
}
{
// 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);
+ 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);
+ 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__);
+ 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
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - using OSD name '%s'", __FUNCTION__, configuration->strDeviceName);
snprintf(m_configuration.strDeviceName, 13, "%s", configuration->strDeviceName);
if (primary && !primary->GetOSDName().Equals(m_configuration.strDeviceName))
{
}
// tv vendor id override
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - vendor id '%s'", __FUNCTION__, ToString((cec_vendor_id)configuration->tvVendor));
if (m_configuration.tvVendor != configuration->tvVendor)
{
m_configuration.tvVendor= configuration->tvVendor;
}
// just copy these
- m_configuration.clientVersion = configuration->clientVersion;
m_configuration.bUseTVMenuLanguage = configuration->bUseTVMenuLanguage;
m_configuration.bActivateSource = configuration->bActivateSource;
m_configuration.bGetSettingsFromROM = configuration->bGetSettingsFromROM;
// client version 1.6.0
if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_6_0)
+ {
m_configuration.bPowerOffDevicesOnStandby = configuration->bPowerOffDevicesOnStandby;
+ m_configuration.bShutdownOnStandby = configuration->bShutdownOnStandby;
+ }
+
+ // client version 1.6.2
+ if (configuration->clientVersion >= CEC_CLIENT_VERSION_1_6_2)
+ {
+ snprintf(m_configuration.strDeviceLanguage, 3, "%s", configuration->strDeviceLanguage);
+ }
// 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)
+ // persist the configuration
+ if (IsRunning())
+ m_communication->PersistConfiguration(&m_configuration);
+
+ if (bReinit || m_configuration.logicalAddresses.IsEmpty())
{
if (bDeviceTypeChanged)
return ChangeDeviceType(oldPrimaryType, m_configuration.deviceTypes[0]);
{
configuration->iFirmwareVersion = m_configuration.iFirmwareVersion;
configuration->bPowerOffDevicesOnStandby = m_configuration.bPowerOffDevicesOnStandby;
+ configuration->bShutdownOnStandby = m_configuration.bShutdownOnStandby;
}
return true;
bool CCECProcessor::CanPersistConfiguration(void)
{
- return m_communication->GetFirmwareVersion() >= 2;
+ return m_communication ? m_communication->GetFirmwareVersion() >= 2 : false;
}
bool CCECProcessor::PersistConfiguration(libcec_configuration *configuration)
{
- return m_communication->PersistConfiguration(configuration);
+ return m_communication ? m_communication->PersistConfiguration(configuration) : false;
}
void CCECProcessor::RescanActiveDevices(void)
{
- for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+ for (unsigned int iPtr = 0; iPtr < CECDEVICE_BROADCAST; iPtr++)
m_busDevices[iPtr]->GetStatus(true);
}
m_communication = NULL;
return true;
}
+
+bool CCECProcessor::TransmitPendingActiveSourceCommands(void)
+{
+ bool bReturn(true);
+ for (unsigned int iPtr = 0; iPtr < CECDEVICE_BROADCAST; iPtr++)
+ bReturn &= m_busDevices[iPtr]->TransmitPendingActiveSourceCommands();
+ return bReturn;
+}