cec: add GetDeviceCecVersion()/cec_get_device_cec_version() to the interface. mostly...
authorLars Op den Kamp <lars@opdenkamp.eu>
Sun, 30 Oct 2011 11:31:27 +0000 (12:31 +0100)
committerLars Op den Kamp <lars@opdenkamp.eu>
Sun, 30 Oct 2011 11:31:27 +0000 (12:31 +0100)
13 files changed:
include/cec.h
include/cecc.h
include/cectypes.h
src/lib/CECProcessor.cpp
src/lib/CECProcessor.h
src/lib/LibCEC.cpp
src/lib/LibCEC.h
src/lib/LibCECC.cpp
src/lib/devices/CECBusDevice.cpp
src/lib/devices/CECBusDevice.h
src/lib/implementations/CECCommandHandler.cpp
src/lib/implementations/CECCommandHandler.h
src/testclient/main.cpp

index 69f1941e8fdb77cd208cc8e68506f1d96b8dd397..68652b16feb83c5fc17013d30546e43fb01aea88 100644 (file)
@@ -139,6 +139,11 @@ namespace CEC
      * @see cec_switch_monitoring
      */
     virtual bool SwitchMonitoring(bool bEnable) = 0;
+
+    /*!
+     * @see cec_get_device_cec_version
+     */
+    virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress) = 0;
   };
 };
 
index c069b140dbd75da2d65d9fbec2f6c5d8c44e581e..f897e13632380e36e8931e17385a13a211f4fdae 100644 (file)
@@ -202,8 +202,10 @@ extern DECLSPEC int cec_set_logical_address(cec_logical_address myAddress, cec_l
 extern DECLSPEC int cec_set_physical_address(uint16_t iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS);
 
 /*!
- * @brief Display a message on the TV.
- * @brief The message to display.
+ * @brief Display a message on the device with the given logical address.
+ * @param iLogicalAddres The device to display the message on.
+ * @param duration The duration of the message
+ * @param strMessage The message to display.
  * @return True when the command was sent, false otherwise.
  */
 #ifdef __cplusplus
@@ -212,8 +214,24 @@ extern DECLSPEC int cec_set_osd_string(CEC::cec_logical_address iLogicalAddress,
 extern DECLSPEC int cec_set_osd_string(cec_logical_address iLogicalAddress, cec_display_control duration, const char *strMessage);
 #endif
 
+/*!
+ * @brief Enable or disable monitoring mode.
+ * @param bEnable True to enable, false to disable.
+ * @return True when switched successfully, false otherwise.
+ */
 extern DECLSPEC int cec_switch_monitoring(int bEnable);
 
+/*!
+ * @brief Get the CEC version of the device with the given logical address
+ * @param iLogicalAddress The device to get the CEC version for.
+ * @return The version or CEC_VERSION_UNKNOWN when the version couldn't be fetched.
+ */
+#ifdef __cplusplus
+extern DECLSPEC CEC::cec_version cec_get_device_cec_version(CEC::cec_logical_address iLogicalAddress);
+#else
+extern DECLSPEC cec_version cec_get_device_cec_version(cec_logical_address iLogicalAddress);
+#endif
+
 #ifdef __cplusplus
 };
 #endif
index 7fa70c7897034c3a8a5fcab34f5825c314c32644..6bad7692c803ff9dd3d7482736b68b55be783147 100644 (file)
@@ -97,13 +97,14 @@ typedef enum
   CEC_TRUE = 1
 } ECecBoolean;
 
-typedef enum
-{
-  CEC_VERSION_1_2 = 0x01,
-  CEC_VERSION_1_2A = 0x02,
-  CEC_VERSION_1_3 = 0x03,
-  CEC_VERSION_1_3A = 0x04
-} ECecVersion;
+typedef enum cec_version
+{
+  CEC_VERSION_UNKNOWN = 0x00,
+  CEC_VERSION_1_2     = 0x01,
+  CEC_VERSION_1_2A    = 0x02,
+  CEC_VERSION_1_3     = 0x03,
+  CEC_VERSION_1_3A    = 0x04
+} cec_version;
 
 typedef enum
 {
index 3fb3bc299a3a5782fb2699293a4b982b12ad5e60..ce2432db179270fd0edadbf6792ce6d824a6e88c 100644 (file)
@@ -202,6 +202,11 @@ bool CCECProcessor::SwitchMonitoring(bool bEnable)
     return m_communication && m_communication->SetAckMask(0x1 << (uint8_t)m_iLogicalAddress);
 }
 
+cec_version CCECProcessor::GetDeviceCecVersion(cec_logical_address iAddress)
+{
+  return m_busDevices[iAddress]->GetCecVersion();
+}
+
 bool CCECProcessor::Transmit(const cec_command &data)
 {
   bool bReturn(false);
index fc9a2fa99123c18ddb6edbd07cead37e4d909356..5362bfceaedca0362c20f492e8559f28f61a3801 100644 (file)
@@ -61,6 +61,7 @@ namespace CEC
       virtual bool SetLogicalAddress(cec_logical_address iLogicalAddress);
       virtual bool SetPhysicalAddress(uint16_t iPhysicalAddress);
       virtual bool SwitchMonitoring(bool bEnable);
+      virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress);
 
       virtual cec_logical_address GetLogicalAddress(void) const { return m_iLogicalAddress; }
       virtual uint16_t GetPhysicalAddress(void) const;
index bf5de8a9e969b0c06730290c022ff4bd39f63fe0..eecde162bcd0080970536edd48871b2bf5443cee 100644 (file)
@@ -204,6 +204,13 @@ bool CLibCEC::SwitchMonitoring(bool bEnable)
   return m_cec ? m_cec->SwitchMonitoring(bEnable) : false;
 }
 
+cec_version CLibCEC::GetDeviceCecVersion(cec_logical_address iAddress)
+{
+  if (m_cec && iAddress >= CECDEVICE_TV && iAddress < CECDEVICE_BROADCAST)
+    return m_cec->GetDeviceCecVersion(iAddress);
+  return CEC_VERSION_UNKNOWN;
+}
+
 void CLibCEC::AddLog(cec_log_level level, const string &strMessage)
 {
   if (m_cec)
index 8873ff94b3898399572b0296c4dcc6b8df51b9a8..8d65a34c64324cd3ea559eb9df643066df019af8 100644 (file)
@@ -73,6 +73,7 @@ namespace CEC
       virtual bool SetInactiveView(void);
       virtual bool SetOSDString(cec_logical_address iLogicalAddress, cec_display_control duration, const char *strMessage);
       virtual bool SwitchMonitoring(bool bEnable);
+      virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress);
     //@}
 
       virtual void AddLog(cec_log_level level, const std::string &strMessage);
index 1f8416b0d573064c7811171ef75800be2307528b..cdc27783d018f2c1401ea4e1f94f4374310d9639 100644 (file)
@@ -187,4 +187,11 @@ int cec_switch_monitoring(int bEnable)
   return -1;
 }
 
+cec_version cec_get_device_cec_version(cec_logical_address iLogicalAddress)
+{
+  if (cec_parser)
+    return cec_parser->GetDeviceCecVersion(iLogicalAddress);
+  return CEC_VERSION_UNKNOWN;
+}
+
 //@}
index 75862b702179f2ad0314c9d348e8e15db8dfcfdc..5c73eb861db9fa64a82e8ce1ea1466283fbbba60 100644 (file)
@@ -45,13 +45,15 @@ CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogi
   m_processor(processor),
   m_iVendorId(0),
   m_iVendorClass(CEC_VENDOR_UNKNOWN),
-  m_iLastActive(0)
+  m_iLastActive(0),
+  m_cecVersion(CEC_VERSION_UNKNOWN)
 {
   m_handler = new CCECCommandHandler(this);
 }
 
 CCECBusDevice::~CCECBusDevice(void)
 {
+  m_condition.Broadcast();
   delete m_handler;
 }
 
@@ -70,6 +72,33 @@ void CCECBusDevice::AddLog(cec_log_level level, const CStdString &strMessage)
   m_processor->AddLog(level, strMessage);
 }
 
+void CCECBusDevice::SetCecVersion(cec_version newVersion)
+{
+  CStdString strLog;
+  m_cecVersion = newVersion;
+
+  switch (newVersion)
+  {
+  case CEC_VERSION_1_2:
+    strLog.Format("device %d reports CEC version 1.2", m_iLogicalAddress);
+    break;
+  case CEC_VERSION_1_2A:
+    strLog.Format("device %d reports CEC version 1.2a", m_iLogicalAddress);
+    break;
+  case CEC_VERSION_1_3:
+    strLog.Format("device %d reports CEC version 1.3", m_iLogicalAddress);
+    break;
+  case CEC_VERSION_1_3A:
+    strLog.Format("device %d reports CEC version 1.3a", m_iLogicalAddress);
+    break;
+  default:
+    strLog.Format("device %d reports an unknown CEC version", m_iLogicalAddress);
+    m_cecVersion = CEC_VERSION_UNKNOWN;
+    break;
+  }
+  AddLog(CEC_LOG_DEBUG, strLog);
+}
+
 void CCECBusDevice::SetVendorId(const cec_datapacket &data)
 {
   if (data.size < 3)
@@ -125,6 +154,7 @@ bool CCECBusDevice::HandleCommand(const cec_command &command)
   CLockObject lock(&m_mutex);
   m_iLastActive = GetTimeMs();
   m_handler->HandleCommand(command);
+  m_condition.Signal();
   return true;
 }
 
@@ -313,6 +343,21 @@ bool CCECBusDevice::BroadcastActiveSource(void)
   return m_processor->Transmit(command);
 }
 
+cec_version CCECBusDevice::GetCecVersion(void)
+{
+  if (m_cecVersion == CEC_VERSION_UNKNOWN)
+  {
+    AddLog(CEC_LOG_NOTICE, "<< requesting CEC version");
+    cec_command command;
+    cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_CEC_VERSION);
+    CLockObject lock(&m_mutex);
+    if (m_processor->Transmit(command))
+      m_condition.Wait(&m_mutex, 1000);
+  }
+
+  return m_cecVersion;
+}
+
 const char *CCECBusDevice::CECVendorIdToString(const uint64_t iVendorId)
 {
   switch (iVendorId)
index 227f14d40ec2e4b2177f763a06b961891feb9789..4b6aa677e4254e6252498d01e713ec44188b9fc2 100644 (file)
@@ -53,6 +53,7 @@ namespace CEC
     virtual cec_logical_address GetMyLogicalAddress(void) const;
     virtual uint16_t GetMyPhysicalAddress(void) const;
 
+    virtual void SetCecVersion(cec_version newVersion);
     virtual void SetVendorId(const cec_datapacket &data);
     virtual void SetVendorId(uint64_t iVendorId, uint8_t iVendorClass = 0);
     virtual const char *GetVendorName(void) const { return CECVendorIdToString(m_iVendorId); }
@@ -67,6 +68,7 @@ namespace CEC
     virtual CCECProcessor *GetProcessor() const { return m_processor; }
     virtual CCECCommandHandler *GetHandler(void) const { return m_handler; };
 
+    virtual cec_version GetCecVersion(void);
     virtual void PollVendorId(void);
     virtual bool PowerOn(void);
     virtual bool Standby(void);
@@ -93,6 +95,8 @@ namespace CEC
     uint64_t            m_iVendorId;
     uint8_t             m_iVendorClass;
     uint64_t            m_iLastActive;
+    cec_version         m_cecVersion;
     CMutex              m_mutex;
+    CCondition          m_condition;
   };
 };
index e1d34f688acd8f62492a4700b9a0626addc1a6a3..790b631b25694b86a930fb7b996f413de2b49a51 100644 (file)
@@ -49,6 +49,9 @@ bool CCECCommandHandler::HandleCommand(const cec_command &command)
   {
     switch(command.opcode)
     {
+    case CEC_OPCODE_CEC_VERSION:
+      HandleDeviceCecVersion(command);
+      break;
     case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
       HandleGivePhysicalAddress(command);
       break;
@@ -125,13 +128,25 @@ bool CCECCommandHandler::HandleCommand(const cec_command &command)
   return bHandled;
 }
 
+bool CCECCommandHandler::HandleDeviceCecVersion(const cec_command &command)
+{
+  if (command.parameters.size == 1)
+  {
+    CCECBusDevice *device = GetDevice(command.initiator);
+    if (device)
+      device->SetCecVersion((cec_version) command.parameters[0]);
+  }
+
+  return true;
+}
+
 bool CCECCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command)
 {
   CCECBusDevice *device = GetDevice(command.initiator);
   if (device)
     device->SetVendorId(command.parameters);
 
-  return false;
+  return true;
 }
 
 bool CCECCommandHandler::HandleDeviceVendorId(const cec_command &command)
@@ -140,7 +155,7 @@ bool CCECCommandHandler::HandleDeviceVendorId(const cec_command &command)
   if (device)
     device->SetVendorId(command.parameters);
 
-  return false;
+  return true;
 }
 
 bool CCECCommandHandler::HandleGetCecVersion(const cec_command &command)
index 0da4dede4cc27b9748b99497b2af9fbd85344595..aa5940c47ed327691a3f5f4873c93d7a50540bd8 100644 (file)
@@ -47,6 +47,7 @@ namespace CEC
     virtual cec_vendor_id GetVendorId(void) { return CEC_VENDOR_UNKNOWN; };
 
   protected:
+    bool HandleDeviceCecVersion(const cec_command &command);
     bool HandleDeviceVendorCommandWithId(const cec_command &command);
     bool HandleDeviceVendorId(const cec_command &command);
     bool HandleGetCecVersion(const cec_command &command);
index 9cb32bf167849d06a829aa5256a421a8ff31629b..b8482d7fd422f83593ba17ce8fbddff7ee3e008e 100644 (file)
@@ -218,6 +218,9 @@ void show_console_help(void)
   "osd {addr} {string}       set OSD message on the specified device." << endl <<
   "[osd 0 Test Message]      displays 'Test Message' on the TV" << endl <<
   endl <<
+  "ver {addr}                get the CEC version of the specified device." << endl <<
+  "[ver 0]                   get the CEC version of the TV" << endl <<
+  endl <<
   "[mon] {1|0}               enable or disable CEC bus monitoring." << endl <<
   "[log] {1 - 31}            change the log level. see cectypes.h for values." << endl <<
   "[ping]                    send a ping command to the CEC adapter." << endl <<
@@ -489,6 +492,36 @@ int main (int argc, char *argv[])
         {
           parser->StartBootloader();
         }
+        else if (command == "ver")
+        {
+          CStdString strDev;
+          if (GetWord(input, strDev))
+          {
+            int iDev = atoi(strDev);
+            if (iDev >= 0 && iDev < 15)
+            {
+              cec_version iVersion = parser->GetDeviceCecVersion((cec_logical_address) iDev);
+              switch (iVersion)
+              {
+              case CEC_VERSION_1_2:
+                cout << "CEC version 1.2" << endl;
+                break;
+              case CEC_VERSION_1_2A:
+                cout << "CEC version 1.2a" << endl;
+                break;
+              case CEC_VERSION_1_3:
+                cout << "CEC version 1.3" << endl;
+                break;
+              case CEC_VERSION_1_3A:
+                cout << "CEC version 1.3a" << endl;
+                break;
+              default:
+                cout << "unknown CEC version" << endl;
+                break;
+              }
+            }
+          }
+        }
         else if (command == "r")
         {
           cout << "closing the connection" << endl;