cec: get the vendor id of the TV before allocating logical addresses, so we can deter...
authorLars Op den Kamp <lars@opdenkamp.eu>
Sun, 10 Jun 2012 09:14:45 +0000 (11:14 +0200)
committerLars Op den Kamp <lars@opdenkamp.eu>
Sun, 10 Jun 2012 09:14:45 +0000 (11:14 +0200)
src/lib/CECClient.cpp
src/lib/CECClient.h
src/lib/CECProcessor.cpp
src/lib/devices/CECBusDevice.cpp
src/lib/implementations/CECCommandHandler.h
src/lib/implementations/RLCommandHandler.cpp
src/lib/implementations/SLCommandHandler.cpp
src/lib/implementations/VLCommandHandler.cpp
src/lib/implementations/VLCommandHandler.h

index ae0b9f6e0c7408c5a73758c43db5d37cfc5cc08a..7cf542bd1766ee445214d6cd718ee4c3b8a28a11 100644 (file)
@@ -37,6 +37,7 @@
 #include "devices/CECPlaybackDevice.h"
 #include "devices/CECAudioSystem.h"
 #include "devices/CECTV.h"
+#include "implementations/CECCommandHandler.h"
 
 using namespace CEC;
 using namespace PLATFORM;
@@ -120,9 +121,6 @@ bool CCECClient::OnRegister(void)
   // set the physical address
   SetPhysicalAddress(m_configuration);
 
-  // ensure that we know the vendor id of the TV, so we are using the correct handler
-  m_processor->GetTV()->GetVendorId(GetPrimaryLogicalAdddress());
-
   // make the primary device the active source if the option is set
   if (m_configuration.bActivateSource == 1)
     GetPrimaryDevice()->ActivateSource();
@@ -250,11 +248,40 @@ bool CCECClient::SetPhysicalAddress(const uint16_t iPhysicalAddress)
   return true;
 }
 
+void CCECClient::SetSupportedDeviceTypes(void)
+{
+  cec_device_type_list types;
+  types.Clear();
+
+  // get the command handler for the tv
+  CCECCommandHandler *tvHandler = m_processor->GetTV()->GetHandler();
+  if (!tvHandler)
+    return;
+
+  // check all device types
+  for (uint8_t iPtr = 0; iPtr < 5; iPtr++)
+  {
+    if (m_configuration.deviceTypes.types[iPtr] == CEC_DEVICE_TYPE_RESERVED)
+      continue;
+
+    // get the supported device type. the handler will replace types it doesn't support by one it does support
+    cec_device_type type = tvHandler->GetReplacementDeviceType(m_configuration.deviceTypes.types[iPtr]);
+    if (!types.IsSet(type))
+      types.Add(type);
+  }
+
+  // set the new type list
+  m_configuration.deviceTypes = types;
+}
+
 bool CCECClient::AllocateLogicalAddresses(void)
 {
   // reset all previous LAs that were set
   m_configuration.logicalAddresses.Clear();
 
+  // get the supported device types from the command handler of the TV
+  SetSupportedDeviceTypes();
+
   // display an error if no device types are set
   if (m_configuration.deviceTypes.IsEmpty())
   {
index 3d812f0ff9377e574d3448aa125b58607ce0fb32..87a4b7fbaf071d9067ea897dc1ca8f9ac1fb7233 100644 (file)
@@ -292,6 +292,11 @@ namespace CEC
      */
     virtual bool AutodetectPhysicalAddress(void);
 
+    /*!
+     * @brief Replaces all device types in m_configuration by types that are supported by the command handler of the TV
+     */
+    virtual void SetSupportedDeviceTypes(void);
+
     CCECProcessor *                         m_processor;      /**< a pointer to the processor */
     libcec_configuration                    m_configuration;  /**< the configuration of this client */
     bool                                    m_bInitialised;   /**< true when initialised, false otherwise */
index 0012a53d289f52591cb398f4c1bf1d152a68a120..034c7e660c56de66d1702781d5f636b3716a71fe 100644 (file)
@@ -645,6 +645,9 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
     return false;
   }
 
+  // ensure that we know the vendor id of the TV
+  GetTV()->GetVendorId(CECDEVICE_UNREGISTERED);
+
   // unregister the client first if it's already been marked as registered
   if (client->IsRegistered())
     UnregisterClient(client);
@@ -720,6 +723,14 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
     client->Alert(CEC_ALERT_SERVICE_DEVICE, param);
   }
 
+  // ensure that the command handler for the TV is initialised
+  if (bReturn)
+  {
+    CCECCommandHandler *handler = GetTV()->GetHandler();
+    if (handler)
+      handler->InitHandler();
+  }
+
   return bReturn;
 }
 
index 686988cd0568dbcff9c3463fc8dc242339405863..6fd077050038c492f2df72cba371f5edd43dab66 100644 (file)
@@ -133,10 +133,14 @@ bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */)
 
   if (bInitHandler)
   {
-    m_handler->InitHandler();
+    CCECBusDevice *primary = GetProcessor()->GetPrimaryDevice();
+    if (primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED)
+    {
+      m_handler->InitHandler();
 
-    if (bActivateSource && IsHandledByLibCEC() && IsActiveSource())
-      m_handler->ActivateSource();
+      if (bActivateSource && IsHandledByLibCEC() && IsActiveSource())
+        m_handler->ActivateSource();
+    }
   }
 
   MarkReady();
index 6e0121fdee49886dc4b3db09b47465d8175aa9e6..3a9bd6f1a3370bcc367bb611183cc2d6f9f691b2 100644 (file)
@@ -163,6 +163,8 @@ namespace CEC
     virtual void SignalOpcode(cec_opcode opcode);
 
     virtual bool ActiveSourcePending(void);
+    virtual bool SupportsDeviceType(const cec_device_type UNUSED(type)) const { return true; };
+    cec_device_type GetReplacementDeviceType(const cec_device_type type) const { return type; }
 
   protected:
     virtual bool HandleActiveSource(const cec_command &command);
index 9643ee50f5f4c4bbdc339c342936317d81a8e5b9..b913c322be41e4ab17fa2af264c02f6db0fe25a0 100644 (file)
@@ -42,14 +42,6 @@ CRLCommandHandler::CRLCommandHandler(CCECBusDevice *busDevice) :
     CCECCommandHandler(busDevice)
 {
   m_vendorId = CEC_VENDOR_TOSHIBA;
-  CCECBusDevice *primary = m_processor->GetPrimaryDevice();
-
-  /* imitate Toshiba devices */
-  if (primary && m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
-  {
-    primary->SetVendorId(CEC_VENDOR_TOSHIBA);
-    primary->ReplaceHandler(false);
-  }
 }
 
 bool CRLCommandHandler::InitHandler(void)
@@ -58,12 +50,21 @@ bool CRLCommandHandler::InitHandler(void)
     return true;
   m_bHandlerInited = true;
 
-  if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
+  CCECBusDevice *primary = m_processor->GetPrimaryDevice();
+  if (primary && primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED)
   {
-    CCECBusDevice *primary = m_processor->GetPrimaryDevice();
+    /* imitate Toshiba devices */
+    if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
+    {
+      primary->SetVendorId(CEC_VENDOR_TOSHIBA);
+      primary->ReplaceHandler(false);
+    }
 
-    /* send the vendor id */
-    primary->TransmitVendorID(CECDEVICE_BROADCAST);
+    if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
+    {
+      /* send the vendor id */
+      primary->TransmitVendorID(CECDEVICE_BROADCAST);
+    }
   }
 
   return true;
index 46ef3d75b3334f1f03c8cd9f63eac28543ff3b4e..6066d3b9bb21dbf03591d8f7b0a3ef7057ae2bba 100644 (file)
@@ -62,14 +62,6 @@ CSLCommandHandler::CSLCommandHandler(CCECBusDevice *busDevice) :
     m_bActiveSourceSent(false)
 {
   m_vendorId = CEC_VENDOR_LG;
-  CCECBusDevice *primary = m_processor->GetPrimaryDevice();
-
-  /* imitate LG devices */
-  if (primary && m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
-  {
-    primary->SetVendorId(CEC_VENDOR_LG);
-    primary->ReplaceHandler(false);
-  }
 
   /* LG devices don't always reply to CEC version requests, so just set it to 1.3a */
   m_busDevice->SetCecVersion(CEC_VERSION_1_3A);
@@ -87,16 +79,25 @@ bool CSLCommandHandler::InitHandler(void)
     return true;
   m_bHandlerInited = true;
 
-  if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
+  CCECBusDevice *primary = m_processor->GetPrimaryDevice();
+  if (primary && primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED)
   {
-    CCECBusDevice *primary = m_processor->GetPrimaryDevice();
+    /* imitate LG devices */
+    if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
+    {
+      primary->SetVendorId(CEC_VENDOR_LG);
+      primary->ReplaceHandler(false);
+    }
 
-    /* start as 'in transition standby->on' */
-    primary->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
-    primary->TransmitPowerState(CECDEVICE_TV);
+    if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
+    {
+      /* start as 'in transition standby->on' */
+      primary->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
+      primary->TransmitPowerState(CECDEVICE_TV);
 
-    /* send the vendor id */
-    primary->TransmitVendorID(CECDEVICE_BROADCAST);
+      /* send the vendor id */
+      primary->TransmitVendorID(CECDEVICE_BROADCAST);
+    }
   }
 
   return true;
index 06468f890d46126cd4b6c75258ca4edb272a80bb..3d96004a7f401bdbf5874ac1a0cf69484b74b857 100644 (file)
@@ -52,24 +52,26 @@ CVLCommandHandler::CVLCommandHandler(CCECBusDevice *busDevice) :
     m_bPowerUpEventReceived(false)
 {
   m_vendorId = CEC_VENDOR_PANASONIC;
-
-  /* use the VL commandhandler for the primary device that is handled by libCEC */
-  if (busDevice->GetLogicalAddress() == CECDEVICE_TV)
-  {
-    CCECBusDevice *primary = m_processor->GetPrimaryDevice();
-    if (primary && m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
-    {
-      primary->SetVendorId(CEC_VENDOR_PANASONIC);
-      primary->ReplaceHandler(false);
-    }
-  }
 }
 
 bool CVLCommandHandler::InitHandler(void)
 {
   CCECBusDevice *primary = m_processor->GetPrimaryDevice();
-  if (primary->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE)
-    return m_processor->GetPrimaryClient()->ChangeDeviceType(CEC_DEVICE_TYPE_RECORDING_DEVICE, CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+  if (primary && primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED)
+  {
+    /* use the VL commandhandler for the primary device that is handled by libCEC */
+    if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV)
+    {
+      if (primary && m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress())
+      {
+        primary->SetVendorId(CEC_VENDOR_PANASONIC);
+        primary->ReplaceHandler(false);
+      }
+    }
+
+    if (primary->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE)
+      return m_processor->GetPrimaryClient()->ChangeDeviceType(CEC_DEVICE_TYPE_RECORDING_DEVICE, CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+  }
 
   return CCECCommandHandler::InitHandler();
 }
index d24ea3d93ad9470fa66fb0c7f16e89fab701c94e..f2bfc7ec7a0a7c9ead58845636d206a81fb9acfe 100644 (file)
@@ -48,6 +48,8 @@ namespace CEC
     bool TransmitPendingActiveSourceCommands(void);
 
     bool PowerUpEventReceived(void);
+    bool SupportsDeviceType(const cec_device_type type) const { return type != CEC_DEVICE_TYPE_RECORDING_DEVICE; };
+    cec_device_type GetReplacementDeviceType(const cec_device_type type) const { return type == CEC_DEVICE_TYPE_RECORDING_DEVICE ? CEC_DEVICE_TYPE_PLAYBACK_DEVICE : type; }
 
   private:
     PLATFORM::CMutex m_mutex;