cec: display an alert message when the firmware of the adapter can be upgraded. bugzi...
[deb_libcec.git] / src / lib / CECProcessor.cpp
index 1c92bb1ba8b94b6f0bffcd443c618275b4750ed3..272723ed48e46567222e92d55ca6f7077167eb31 100644 (file)
@@ -61,7 +61,7 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, libcec_configuration *configur
 {
   CreateBusDevices();
   m_configuration.Clear();
-  m_configuration.serverVersion = CEC_SERVER_VERSION_1_6_2;
+  m_configuration.serverVersion = LIBCEC_VERSION_CURRENT;
   SetConfiguration(configuration);
 
   if (m_configuration.tvVendor != CEC_VENDOR_UNKNOWN)
@@ -79,7 +79,7 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, con
     m_iLastTransmission(0)
 {
   m_configuration.Clear();
-  m_configuration.serverVersion    = CEC_SERVER_VERSION_1_6_2;
+  m_configuration.serverVersion    = LIBCEC_VERSION_CURRENT;
 
   // client version < 1.5.0
   m_configuration.clientVersion    = (uint32_t)CEC_CLIENT_VERSION_PRE_1_5;
@@ -96,34 +96,34 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, con
 
 void CCECProcessor::CreateBusDevices(void)
 {
-  for (int iPtr = 0; iPtr < 16; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_BROADCAST; iPtr++)
   {
     switch(iPtr)
     {
     case CECDEVICE_AUDIOSYSTEM:
-      m_busDevices[iPtr] = new CCECAudioSystem(this, (cec_logical_address) iPtr, CEC_INVALID_PHYSICAL_ADDRESS);
+      m_busDevices[iPtr] = new CCECAudioSystem(this, (cec_logical_address) iPtr);
       break;
     case CECDEVICE_PLAYBACKDEVICE1:
     case CECDEVICE_PLAYBACKDEVICE2:
     case CECDEVICE_PLAYBACKDEVICE3:
-      m_busDevices[iPtr] = new CCECPlaybackDevice(this, (cec_logical_address) iPtr, CEC_INVALID_PHYSICAL_ADDRESS);
+      m_busDevices[iPtr] = new CCECPlaybackDevice(this, (cec_logical_address) iPtr);
       break;
     case CECDEVICE_RECORDINGDEVICE1:
     case CECDEVICE_RECORDINGDEVICE2:
     case CECDEVICE_RECORDINGDEVICE3:
-      m_busDevices[iPtr] = new CCECRecordingDevice(this, (cec_logical_address) iPtr, CEC_INVALID_PHYSICAL_ADDRESS);
+      m_busDevices[iPtr] = new CCECRecordingDevice(this, (cec_logical_address) iPtr);
       break;
     case CECDEVICE_TUNER1:
     case CECDEVICE_TUNER2:
     case CECDEVICE_TUNER3:
     case CECDEVICE_TUNER4:
-      m_busDevices[iPtr] = new CCECTuner(this, (cec_logical_address) iPtr, CEC_INVALID_PHYSICAL_ADDRESS);
+      m_busDevices[iPtr] = new CCECTuner(this, (cec_logical_address) iPtr);
       break;
     case CECDEVICE_TV:
-      m_busDevices[iPtr] = new CCECTV(this, (cec_logical_address) iPtr, CEC_PHYSICAL_ADDRESS_TV);
+      m_busDevices[iPtr] = new CCECTV(this, (cec_logical_address) iPtr);
       break;
     default:
-      m_busDevices[iPtr] = new CCECBusDevice(this, (cec_logical_address) iPtr, CEC_INVALID_PHYSICAL_ADDRESS);
+      m_busDevices[iPtr] = new CCECBusDevice(this, (cec_logical_address) iPtr);
       break;
     }
   }
@@ -133,7 +133,7 @@ CCECProcessor::~CCECProcessor(void)
 {
   Close();
 
-  for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_BROADCAST; iPtr++)
   {
     delete m_busDevices[iPtr];
     m_busDevices[iPtr] = NULL;
@@ -193,7 +193,7 @@ bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint
     m_configuration.iFirmwareBuildDate = m_communication->GetFirmwareBuildDate();
     CStdString strLog;
     strLog.Format("connected to the CEC adapter. libCEC version = %s, client version = %s, firmware version = %d", ToString((cec_server_version)m_configuration.serverVersion), ToString((cec_client_version)m_configuration.clientVersion), m_configuration.iFirmwareVersion);
-    if (m_configuration.iFirmwareBuildDate != CEC_DEFAULT_FIRMWARE_BUILD_DATE)
+    if (m_configuration.iFirmwareBuildDate != CEC_FW_BUILD_UNKNOWN)
     {
       time_t buildTime = (time_t)m_configuration.iFirmwareBuildDate;
       strLog.AppendFormat(", firmware build date: %s", asctime(gmtime(&buildTime)));
@@ -203,6 +203,17 @@ bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint
     CLibCEC::AddLog(CEC_LOG_NOTICE, strLog);
   }
 
+  if (!m_communication->IsRunningLatestFirmware())
+  {
+    const char *strUpgradeMessage = "The firmware of this adapter can be upgraded. Please visit http://blog.pulse-eight.com/ for more information.";
+    CLibCEC::AddLog(CEC_LOG_WARNING, strUpgradeMessage);
+    CLibCEC::Alert(CEC_ALERT_SERVICE_DEVICE, libcec_parameter(strUpgradeMessage));
+  }
+  else
+  {
+    CLibCEC::AddLog(CEC_LOG_DEBUG, "the adapter is using the latest (known) firmware version");
+  }
+
   if (m_configuration.bGetSettingsFromROM == 1)
   {
     libcec_configuration config;
@@ -212,7 +223,7 @@ bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint
     CLockObject lock(m_mutex);
     if (!config.deviceTypes.IsEmpty())
       m_configuration.deviceTypes = config.deviceTypes;
-    if (config.iPhysicalAddress > 0)
+    if (IsValidPhysicalAddress(config.iPhysicalAddress))
       m_configuration.iPhysicalAddress = config.iPhysicalAddress;
     snprintf(m_configuration.strDeviceName, 13, "%s", config.strDeviceName);
   }
@@ -259,7 +270,7 @@ bool CCECProcessor::Initialise(void)
     memcpy(language.language, m_configuration.strDeviceLanguage, 3);
     language.language[3] = 0;
 
-    for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
+    for (uint8_t iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
     {
       if (m_configuration.logicalAddresses[iPtr])
       {
@@ -272,15 +283,19 @@ bool CCECProcessor::Initialise(void)
   /* get the vendor id from the TV, so we are using the correct handler */
   m_busDevices[CECDEVICE_TV]->GetVendorId();
 
-  if (m_configuration.iPhysicalAddress != 0)
+  if (IsValidPhysicalAddress(m_configuration.iPhysicalAddress))
   {
-    CLibCEC::AddLog(CEC_LOG_NOTICE, "setting the physical address to %4x", m_configuration.iPhysicalAddress);
+    CLibCEC::AddLog(CEC_LOG_NOTICE, "setting the physical address to %04X", m_configuration.iPhysicalAddress);
     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);
+      CLibCEC::AddLog(CEC_LOG_ERROR, "unable to set the physical address to %04X", m_configuration.iPhysicalAddress);
+  }
+  else
+  {
+    if (!SetHDMIPort(m_configuration.baseDevice, m_configuration.iHDMIPort, true))
+      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);
+    bReturn = true;
   }
-  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 (bReturn && m_configuration.bActivateSource == 1)
     m_busDevices[m_configuration.logicalAddresses.primary]->ActivateSource();
@@ -374,7 +389,7 @@ bool CCECProcessor::ChangeDeviceType(cec_device_type from, cec_device_type to)
   CCECBusDevice *previousDevice = GetDeviceByType(from);
   m_configuration.logicalAddresses.primary = CECDEVICE_UNKNOWN;
 
-  for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+  for (uint8_t iPtr = 0; iPtr < 5; iPtr++)
   {
     if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_RESERVED)
       continue;
@@ -446,7 +461,7 @@ bool CCECProcessor::FindLogicalAddresses(void)
     return false;
   }
 
-  for (unsigned int iPtr = 0; iPtr < 5; iPtr++)
+  for (uint8_t iPtr = 0; iPtr < 5; iPtr++)
   {
     if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_RESERVED)
       continue;
@@ -473,7 +488,7 @@ void CCECProcessor::ReplaceHandlers(void)
 {
   if (!IsInitialised())
     return;
-  for (uint8_t iPtr = 0; iPtr <= CECDEVICE_PLAYBACKDEVICE3; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_PLAYBACKDEVICE3; iPtr++)
     m_busDevices[iPtr]->ReplaceHandler(m_bInitialised);
 }
 
@@ -516,7 +531,7 @@ bool CCECProcessor::SetActiveSource(cec_device_type type /* = CEC_DEVICE_TYPE_RE
 
   if (type != CEC_DEVICE_TYPE_RESERVED)
   {
-    for (uint8_t iPtr = 0; iPtr <= 11; iPtr++)
+    for (uint8_t iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_PLAYBACKDEVICE3; iPtr++)
     {
       if (m_configuration.logicalAddresses[iPtr] && m_busDevices[iPtr]->m_type == type)
       {
@@ -527,7 +542,7 @@ bool CCECProcessor::SetActiveSource(cec_device_type type /* = CEC_DEVICE_TYPE_RE
   }
 
   m_busDevices[addr]->SetActiveSource();
-  if (m_busDevices[addr]->GetPhysicalAddress() != CEC_INVALID_PHYSICAL_ADDRESS)
+  if (IsValidPhysicalAddress(m_busDevices[addr]->GetPhysicalAddress()))
     bReturn = m_busDevices[addr]->ActivateSource();
 
   return bReturn;
@@ -607,15 +622,14 @@ bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort,
   bool bReturn(false);
 
   // limit the HDMI port range to 1-15
-  if (iPort < 1)
-      iPort = 1;
-  if (iPort > 15)
-      iPort = 15;
+  if (iPort < CEC_MIN_HDMI_PORTNUMBER ||
+      iPort > CEC_MAX_HDMI_PORTNUMBER)
+    return bReturn;
 
   {
     CLockObject lock(m_mutex);
     m_configuration.baseDevice = iBaseDevice;
-    m_configuration.iHDMIPort = iPort;
+    m_configuration.iHDMIPort  = iPort;
   }
 
   if (!IsRunning() && !bForce)
@@ -625,9 +639,7 @@ bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort,
 
   uint16_t iPhysicalAddress(0);
   if (iBaseDevice > CECDEVICE_TV)
-  {
-    iPhysicalAddress = m_busDevices[iBaseDevice]->GetPhysicalAddress();
-  }
+    iPhysicalAddress = m_busDevices[iBaseDevice]->GetPhysicalAddress(false);
 
   if (iPhysicalAddress <= CEC_MAX_PHYSICAL_ADDRESS)
   {
@@ -644,16 +656,19 @@ bool CCECProcessor::SetHDMIPort(cec_logical_address iBaseDevice, uint8_t iPort,
   }
 
   if (!bReturn)
-    CLibCEC::AddLog(CEC_LOG_ERROR, "failed to set the physical address");
-  else
-    SetPhysicalAddress(iPhysicalAddress);
+  {
+    CLibCEC::AddLog(CEC_LOG_WARNING, "failed to set the physical address to %04X, setting it to the default value %04X", iPhysicalAddress, CEC_DEFAULT_PHYSICAL_ADDRESS);
+    iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS;
+  }
+
+  SetPhysicalAddress(iPhysicalAddress);
 
   return bReturn;
 }
 
 bool CCECProcessor::PhysicalAddressInUse(uint16_t iPhysicalAddress)
 {
-  for (unsigned int iPtr = 0; iPtr < 15; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
   {
     if (m_busDevices[iPtr]->GetPhysicalAddress() == iPhysicalAddress)
       return true;
@@ -699,7 +714,7 @@ bool CCECProcessor::SetLogicalAddress(cec_logical_address iLogicalAddress)
 
 bool CCECProcessor::SetMenuState(cec_menu_state state, bool bSendUpdate /* = true */)
 {
-  for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
   {
     if (m_configuration.logicalAddresses[iPtr])
       m_busDevices[iPtr]->SetMenuState(state);
@@ -721,12 +736,12 @@ bool CCECProcessor::SetPhysicalAddress(uint16_t iPhysicalAddress, bool bSendUpda
   {
     CLockObject lock(m_mutex);
     m_configuration.iPhysicalAddress = iPhysicalAddress;
-    CLibCEC::AddLog(CEC_LOG_DEBUG, "setting physical address to '%4x'", iPhysicalAddress);
+    CLibCEC::AddLog(CEC_LOG_DEBUG, "setting physical address to '%04X'", iPhysicalAddress);
 
     if (!m_configuration.logicalAddresses.IsEmpty())
     {
       bool bWasActiveSource(false);
-      for (uint8_t iPtr = 0; iPtr < 15; iPtr++)
+      for (uint8_t iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
         if (m_configuration.logicalAddresses[iPtr])
         {
           bWasActiveSource |= m_busDevices[iPtr]->IsActiveSource();
@@ -741,7 +756,7 @@ bool CCECProcessor::SetPhysicalAddress(uint16_t iPhysicalAddress, bool bSendUpda
     }
   }
 
-  for (uint8_t iPtr = 0; iPtr < 15; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
     if (sendUpdatesTo[iPtr])
       m_busDevices[iPtr]->TransmitPhysicalAddress();
 
@@ -791,7 +806,7 @@ bool CCECProcessor::PollDevice(cec_logical_address iAddress)
 
 uint8_t CCECProcessor::VolumeUp(bool bSendRelease /* = true */)
 {
-  uint8_t status = 0;
+  uint8_t status(CEC_AUDIO_VOLUME_STATUS_UNKNOWN);
   if (IsPresentDevice(CECDEVICE_AUDIOSYSTEM))
     status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeUp(bSendRelease);
 
@@ -800,7 +815,7 @@ uint8_t CCECProcessor::VolumeUp(bool bSendRelease /* = true */)
 
 uint8_t CCECProcessor::VolumeDown(bool bSendRelease /* = true */)
 {
-  uint8_t status = 0;
+  uint8_t status(CEC_AUDIO_VOLUME_STATUS_UNKNOWN);
   if (IsPresentDevice(CECDEVICE_AUDIOSYSTEM))
     status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->VolumeDown(bSendRelease);
 
@@ -809,7 +824,7 @@ uint8_t CCECProcessor::VolumeDown(bool bSendRelease /* = true */)
 
 uint8_t CCECProcessor::MuteAudio(bool bSendRelease /* = true */)
 {
-  uint8_t status = 0;
+  uint8_t status(CEC_AUDIO_VOLUME_STATUS_UNKNOWN);
   if (IsPresentDevice(CECDEVICE_AUDIOSYSTEM))
     status = ((CCECAudioSystem *)m_busDevices[CECDEVICE_AUDIOSYSTEM])->MuteAudio(bSendRelease);
 
@@ -820,12 +835,8 @@ CCECBusDevice *CCECProcessor::GetDeviceByPhysicalAddress(uint16_t iPhysicalAddre
 {
   CCECBusDevice *device(NULL);
 
-  // invalid PA
-  if (iPhysicalAddress == CEC_INVALID_PHYSICAL_ADDRESS)
-    return device;
-
   // check each device until we found a match
-  for (unsigned int iPtr = 0; !device && iPtr < 16; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; !device && iPtr < CECDEVICE_BROADCAST; iPtr++)
   {
     if (m_busDevices[iPtr]->GetPhysicalAddress(bSuppressUpdate) == iPhysicalAddress)
       device = m_busDevices[iPtr];
@@ -838,7 +849,7 @@ CCECBusDevice *CCECProcessor::GetDeviceByType(cec_device_type type) const
 {
   CCECBusDevice *device = NULL;
 
-  for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
   {
     if (m_busDevices[iPtr]->m_type == type && m_configuration.logicalAddresses[iPtr])
     {
@@ -915,7 +926,7 @@ cec_power_status CCECProcessor::GetDevicePowerStatus(cec_logical_address iAddres
 
 cec_logical_address CCECProcessor::GetActiveSource(bool bRequestActiveSource /* = true */)
 {
-  for (uint8_t iPtr = 0; iPtr <= 11; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_PLAYBACKDEVICE3; iPtr++)
   {
     if (m_busDevices[iPtr]->IsActiveSource())
       return (cec_logical_address)iPtr;
@@ -1011,7 +1022,7 @@ cec_logical_addresses CCECProcessor::GetActiveDevices(void)
 {
   cec_logical_addresses addresses;
   addresses.Clear();
-  for (unsigned int iPtr = 0; iPtr < 15; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
   {
     if (m_busDevices[iPtr]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
       addresses.Set((cec_logical_address) iPtr);
@@ -1026,7 +1037,7 @@ bool CCECProcessor::IsPresentDevice(cec_logical_address address)
 
 bool CCECProcessor::IsPresentDeviceType(cec_device_type type)
 {
-  for (unsigned int iPtr = 0; iPtr < 15; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
   {
     if (m_busDevices[iPtr]->GetType() == type && m_busDevices[iPtr]->GetStatus() == CEC_DEVICE_STATUS_PRESENT)
       return true;
@@ -1061,12 +1072,12 @@ bool CCECProcessor::EnablePhysicalAddressDetection(void)
 {
   CLibCEC::AddLog(CEC_LOG_WARNING, "deprecated method %s called", __FUNCTION__);
   uint16_t iPhysicalAddress = m_communication->GetPhysicalAddress();
-  if (iPhysicalAddress != 0)
+  if (IsValidPhysicalAddress(iPhysicalAddress))
   {
     m_configuration.bAutodetectAddress = 1;
-    m_configuration.iPhysicalAddress = iPhysicalAddress;
-    m_configuration.baseDevice = CECDEVICE_UNKNOWN;
-    m_configuration.iHDMIPort = 0;
+    m_configuration.iPhysicalAddress   = iPhysicalAddress;
+    m_configuration.baseDevice         = CECDEVICE_UNKNOWN;
+    m_configuration.iHDMIPort          = CEC_HDMI_PORTNUMBER_NONE;
     return SetPhysicalAddress(iPhysicalAddress);
   }
   return false;
@@ -1077,7 +1088,7 @@ bool CCECProcessor::StandbyDevices(cec_logical_address address /* = CECDEVICE_BR
   if (address == CECDEVICE_BROADCAST && m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_0)
   {
     bool bReturn(true);
-    for (uint8_t iPtr = 0; iPtr <= 0xF; iPtr++)
+    for (uint8_t iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_BROADCAST; iPtr++)
     {
       if (m_configuration.powerOffDevices[iPtr])
       {
@@ -1096,7 +1107,7 @@ bool CCECProcessor::PowerOnDevices(cec_logical_address address /* = CECDEVICE_BR
   if (address == CECDEVICE_BROADCAST && m_configuration.clientVersion >= CEC_CLIENT_VERSION_1_5_0)
   {
     bool bReturn(true);
-    for (uint8_t iPtr = 0; iPtr <= 0xF; iPtr++)
+    for (uint8_t iPtr = CECDEVICE_TV; iPtr <= CECDEVICE_BROADCAST; iPtr++)
     {
       if (m_configuration.wakeDevices[iPtr])
       {
@@ -1272,6 +1283,8 @@ const char *CCECProcessor::ToString(const cec_deck_info status)
     return "info index search reverse";
   case CEC_DECK_INFO_OTHER_STATUS:
     return "other";
+  case CEC_DECK_INFO_OTHER_STATUS_LG:
+    return "LG other";
   default:
     return "unknown";
   }
@@ -1405,6 +1418,20 @@ const char *CCECProcessor::ToString(const cec_opcode opcode)
     return "system audio mode status";
   case CEC_OPCODE_SET_AUDIO_RATE:
     return "set audio rate";
+  case CEC_OPCODE_START_ARC:
+    return "start ARC";
+  case CEC_OPCODE_REPORT_ARC_STARTED:
+    return "report ARC started";
+  case CEC_OPCODE_REPORT_ARC_ENDED:
+    return "report ARC ended";
+  case CEC_OPCODE_REQUEST_ARC_START:
+    return "request ARC start";
+  case CEC_OPCODE_REQUEST_ARC_END:
+    return "request ARC end";
+  case CEC_OPCODE_END_ARC:
+    return "end ARC";
+  case CEC_OPCODE_CDC:
+    return "CDC";
   case CEC_OPCODE_NONE:
     return "poll";
   default:
@@ -1510,9 +1537,9 @@ const char *CCECProcessor::ToString(const cec_server_version version)
 
 bool CCECProcessor::StartBootloader(const char *strPort /* = NULL */)
 {
+  bool bReturn(false);
   if (!m_communication && strPort)
   {
-    bool bReturn(false);
     IAdapterCommunication *comm = new CUSBCECAdapterCommunication(this, strPort);
     CTimeout timeout(CEC_DEFAULT_CONNECT_TIMEOUT);
     int iConnectTry(0);
@@ -1531,8 +1558,12 @@ bool CCECProcessor::StartBootloader(const char *strPort /* = NULL */)
   }
   else
   {
-    return m_communication->StartBootloader();
+    m_communication->StartBootloader();
+    Close();
+    bReturn = true;
   }
+
+  return bReturn;
 }
 
 bool CCECProcessor::PingAdapter(void)
@@ -1580,34 +1611,34 @@ bool CCECProcessor::SetConfiguration(const libcec_configuration *configuration)
   if (IsRunning() && configuration->bAutodetectAddress == 1)
   {
     uint16_t iPhysicalAddress = m_communication->GetPhysicalAddress();
-    if (iPhysicalAddress != 0)
+    if (IsValidPhysicalAddress(iPhysicalAddress))
     {
       if (IsRunning())
-        CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - autodetected physical address '%4x'", __FUNCTION__, iPhysicalAddress);
+        CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - autodetected physical address '%04X'", __FUNCTION__, iPhysicalAddress);
       else
-        CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - using physical address '%x'", __FUNCTION__, iPhysicalAddress);
+        CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - using physical address '%04X'", __FUNCTION__, iPhysicalAddress);
       bPhysicalAddressChanged = (m_configuration.iPhysicalAddress != iPhysicalAddress);
       m_configuration.iPhysicalAddress = iPhysicalAddress;
-      m_configuration.iHDMIPort = 0;
-      m_configuration.baseDevice = CECDEVICE_UNKNOWN;
-      bPhysicalAutodetected = true;
+      m_configuration.iHDMIPort        = CEC_HDMI_PORTNUMBER_NONE;
+      m_configuration.baseDevice       = CECDEVICE_UNKNOWN;
+      bPhysicalAutodetected            = true;
     }
   }
 
   // physical address
   if (!bPhysicalAutodetected)
   {
-    if (configuration->iPhysicalAddress != 0)
-      bPhysicalAddressChanged = IsRunning() && m_configuration.iPhysicalAddress != configuration->iPhysicalAddress;
+    uint16_t iPhysicalAddress(IsValidPhysicalAddress(configuration->iPhysicalAddress) ? configuration->iPhysicalAddress : CEC_PHYSICAL_ADDRESS_TV);
+    bPhysicalAddressChanged = IsRunning() && m_configuration.iPhysicalAddress != iPhysicalAddress;
     if (bPhysicalAddressChanged)
     {
-      CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - physical address '%x'", __FUNCTION__, configuration->iPhysicalAddress);
-      m_configuration.iPhysicalAddress = configuration->iPhysicalAddress;
+      CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - physical address '%04X'", __FUNCTION__, iPhysicalAddress);
+      m_configuration.iPhysicalAddress = iPhysicalAddress;
     }
   }
 
   bool bHdmiPortChanged(false);
-  if (!bPhysicalAutodetected && !bPhysicalAddressChanged)
+  if (!bPhysicalAutodetected && !IsValidPhysicalAddress(configuration->iPhysicalAddress))
   {
     // base device
     bHdmiPortChanged = IsRunning() && m_configuration.baseDevice != configuration->baseDevice;
@@ -1623,7 +1654,7 @@ bool CCECProcessor::SetConfiguration(const libcec_configuration *configuration)
   {
     CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - resetting HDMI port and base device to defaults", __FUNCTION__);
     m_configuration.baseDevice = CECDEVICE_UNKNOWN;
-    m_configuration.iHDMIPort  = 0;
+    m_configuration.iHDMIPort  = CEC_HDMI_PORTNUMBER_NONE;
   }
 
   bReinit = bPhysicalAddressChanged || bHdmiPortChanged || bDeviceTypeChanged;
@@ -1683,18 +1714,15 @@ bool CCECProcessor::SetConfiguration(const libcec_configuration *configuration)
   if (m_configuration.deviceTypes.IsEmpty())
     m_configuration.deviceTypes.Add(CEC_DEVICE_TYPE_RECORDING_DEVICE);
 
-  // persist the configuration
-  if (IsRunning())
-    m_communication->PersistConfiguration(&m_configuration);
-
+  bool bReturn(true);
   if (bReinit || m_configuration.logicalAddresses.IsEmpty())
   {
     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);
+      bReturn = ChangeDeviceType(oldPrimaryType, m_configuration.deviceTypes[0]);
+    else if (IsValidPhysicalAddress(m_configuration.iPhysicalAddress))
+      bReturn = SetPhysicalAddress(m_configuration.iPhysicalAddress);
+    else if (m_configuration.baseDevice != CECDEVICE_UNKNOWN && m_configuration.iHDMIPort != CEC_HDMI_PORTNUMBER_NONE)
+      bReturn = SetHDMIPort(m_configuration.baseDevice, m_configuration.iHDMIPort);
   }
   else if (m_configuration.bActivateSource == 1 && IsRunning() && !IsActiveSource(m_configuration.logicalAddresses.primary))
   {
@@ -1702,7 +1730,11 @@ bool CCECProcessor::SetConfiguration(const libcec_configuration *configuration)
     SetActiveSource(m_configuration.deviceTypes.types[0]);
   }
 
-  return true;
+  // persist the configuration
+  if (IsRunning())
+    m_communication->PersistConfiguration(&m_configuration);
+
+  return bReturn;
 }
 
 bool CCECProcessor::GetCurrentConfiguration(libcec_configuration *configuration)
@@ -1763,7 +1795,7 @@ bool CCECProcessor::PersistConfiguration(libcec_configuration *configuration)
 
 void CCECProcessor::RescanActiveDevices(void)
 {
-  for (unsigned int iPtr = 0; iPtr < CECDEVICE_BROADCAST; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
     m_busDevices[iPtr]->GetStatus(true);
 }
 
@@ -1782,7 +1814,13 @@ bool CCECProcessor::GetDeviceInformation(const char *strPort, libcec_configurati
 bool CCECProcessor::TransmitPendingActiveSourceCommands(void)
 {
   bool bReturn(true);
-  for (unsigned int iPtr = 0; iPtr < CECDEVICE_BROADCAST; iPtr++)
+  for (uint8_t iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
     bReturn &= m_busDevices[iPtr]->TransmitPendingActiveSourceCommands();
   return bReturn;
 }
+
+bool CCECProcessor::IsValidPhysicalAddress(uint16_t iPhysicalAddress)
+{
+  return iPhysicalAddress >= CEC_MIN_PHYSICAL_ADDRESS &&
+         iPhysicalAddress <= CEC_MAX_PHYSICAL_ADDRESS;
+}