cec: added PollDevice()/cec_poll_device()
authorLars Op den Kamp <lars@opdenkamp.eu>
Sat, 5 Nov 2011 12:11:33 +0000 (13:11 +0100)
committerLars Op den Kamp <lars@opdenkamp.eu>
Sat, 5 Nov 2011 12:19:58 +0000 (13:19 +0100)
12 files changed:
include/cec.h
include/cecc.h
include/cectypes.h
src/lib/AdapterCommunication.cpp
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/testclient/main.cpp

index 19bc4d35e74fbe130ddc73aa5650f9b7f52e8261..c1aad1cb5602774d669603d883a4bfb7f3b2d22c 100644 (file)
@@ -164,6 +164,11 @@ namespace CEC
      * @see cec_get_device_power_status
      */
     virtual cec_power_status GetDevicePowerStatus(cec_logical_address iAddress) = 0;
+
+    /*!
+     * @see cec_poll_device
+     */
+    virtual bool PollDevice(cec_logical_address iAddress) = 0;
   };
 };
 
index e1c2942d877ef9b2d678270ebd2066daf4dc8295..8a06956223177874ab30e6663a4104bb17a25818 100644 (file)
@@ -271,6 +271,17 @@ extern DECLSPEC CEC::cec_power_status cec_get_device_power_status(CEC::cec_logic
 extern DECLSPEC cec_power_status cec_get_device_power_status(cec_logical_address iLogicalAddress);
 #endif
 
+/*!
+ * @brief Sends a POLL message to a device.
+ * @param iAddress The device to send the message to.
+ * @return True if the POLL was acked, false otherwise.
+ */
+#ifdef __cplusplus
+extern DECLSPEC int cec_poll_device(CEC::cec_logical_address iLogicalAddress);
+#else
+extern DECLSPEC int cec_poll_device(cec_logical_address iLogicalAddress);
+#endif
+
 #ifdef __cplusplus
 };
 #endif
index 3879a616f633a2daf3a381c1af383914ed3feada..9481a1f3eb79f7f59e11ec8d5b026ccec8761906 100644 (file)
@@ -526,7 +526,8 @@ typedef enum cec_opcode
   CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72,
   CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70,
   CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E,
-  CEC_OPCODE_SET_AUDIO_RATE = 0x9A
+  CEC_OPCODE_SET_AUDIO_RATE = 0x9A,
+  CEC_OPCODE_NONE = 0xFD /* when this opcode is set, no opcode will be sent to the device. this is one of the reserved numbers */
 } cec_opcode;
 
 typedef enum cec_log_level
@@ -671,10 +672,13 @@ typedef struct cec_command
   static void format(cec_command &command, cec_logical_address initiator, cec_logical_address destination, cec_opcode opcode)
   {
     command.clear();
-    command.initiator        = initiator;
-    command.destination      = destination;
-    command.opcode           = opcode;
-    command.opcode_set       = 1;
+    command.initiator    = initiator;
+    command.destination  = destination;
+    if (opcode != CEC_OPCODE_NONE)
+    {
+      command.opcode     = opcode;
+      command.opcode_set = 1;
+    }
   }
 
   void push_back(uint8_t data)
index 661478396a58a8ce09f7d5ac992a45ffd27f7e0f..9b4490b7316dbf4d386bc2ac0ce3b51e0054f3b9 100644 (file)
@@ -56,29 +56,32 @@ CCECAdapterMessage::CCECAdapterMessage(const cec_command &command)
 
   // add source and destination
   push_back(MSGSTART);
-  push_escaped(MSGCODE_TRANSMIT);
+  push_escaped(command.opcode_set == 0 ? (uint8_t)MSGCODE_TRANSMIT_EOM : (uint8_t)MSGCODE_TRANSMIT);
   push_back(((uint8_t)command.initiator << 4) + (uint8_t)command.destination);
   push_back(MSGEND);
 
   // add opcode
-  push_back(MSGSTART);
-  push_escaped(command.parameters.empty() ? (uint8_t)MSGCODE_TRANSMIT_EOM : (uint8_t)MSGCODE_TRANSMIT);
-  push_back((uint8_t) command.opcode);
-  push_back(MSGEND);
-
-  // add parameters
-  for (int8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
+  if (command.opcode_set == 1)
   {
     push_back(MSGSTART);
+    push_escaped(command.parameters.empty() ? (uint8_t)MSGCODE_TRANSMIT_EOM : (uint8_t)MSGCODE_TRANSMIT);
+    push_back((uint8_t) command.opcode);
+    push_back(MSGEND);
 
-    if (iPtr == command.parameters.size - 1)
-      push_escaped( MSGCODE_TRANSMIT_EOM);
-    else
-      push_escaped(MSGCODE_TRANSMIT);
+    // add parameters
+    for (int8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
+    {
+      push_back(MSGSTART);
 
-    push_escaped(command.parameters[iPtr]);
+      if (iPtr == command.parameters.size - 1)
+        push_escaped( MSGCODE_TRANSMIT_EOM);
+      else
+        push_escaped(MSGCODE_TRANSMIT);
 
-    push_back(MSGEND);
+      push_escaped(command.parameters[iPtr]);
+
+      push_back(MSGEND);
+    }
   }
 
   // set timeout
index f781b6fb58b94f99f970a8eb2248937f958aa1cc..49b3bd2e35a11e5727e0f4c4f850b878999cc440 100644 (file)
@@ -156,7 +156,9 @@ bool CCECProcessor::SetInactiveView(void)
 void CCECProcessor::LogOutput(const cec_command &data)
 {
   CStdString strTx;
-  strTx.Format("<< %02x:%02x", ((uint8_t)data.initiator << 4) + (uint8_t)data.destination, (uint8_t)data.opcode);
+  strTx.Format("<< %02x", ((uint8_t)data.initiator << 4) + (uint8_t)data.destination);
+  if (data.opcode_set)
+      strTx.AppendFormat(":%02x", (uint8_t)data.opcode);
 
   for (uint8_t iPtr = 0; iPtr < data.parameters.size; iPtr++)
     strTx.AppendFormat(":%02x", data.parameters[iPtr]);
@@ -200,6 +202,13 @@ bool CCECProcessor::SwitchMonitoring(bool bEnable)
     return SetAckMask(0x1 << (uint8_t)m_iLogicalAddress);
 }
 
+bool CCECProcessor::PollDevice(cec_logical_address iAddress)
+{
+  if (iAddress != CECDEVICE_UNKNOWN && m_busDevices[iAddress])
+    return m_busDevices[iAddress]->PollDevice();
+  return false;
+}
+
 cec_version CCECProcessor::GetDeviceCecVersion(cec_logical_address iAddress)
 {
   return m_busDevices[iAddress]->GetCecVersion();
index d865167e114ff6e9332682a665c8873e31e30c9d..ea61365c18959b74bb663dda90b9a5d85692287b 100644 (file)
@@ -68,6 +68,7 @@ namespace CEC
       virtual bool SetLogicalAddress(cec_logical_address iLogicalAddress);
       virtual bool SetPhysicalAddress(uint16_t iPhysicalAddress);
       virtual bool SwitchMonitoring(bool bEnable);
+      virtual bool PollDevice(cec_logical_address iAddress);
 
       virtual bool Transmit(const cec_command &data);
       virtual bool Transmit(CCECAdapterMessage *output);
index 95e2a2e42e72d1a5cadb37f2be924c207a19a322..aff5776727b895272060c66d6beb7ce1e852cc19 100644 (file)
@@ -215,6 +215,13 @@ cec_power_status CLibCEC::GetDevicePowerStatus(cec_logical_address iAddress)
   return CEC_POWER_STATUS_UNKNOWN;
 }
 
+bool CLibCEC::PollDevice(cec_logical_address iAddress)
+{
+  if (m_cec && iAddress >= CECDEVICE_TV && iAddress < CECDEVICE_BROADCAST)
+    return m_cec->PollDevice(iAddress);
+  return false;
+}
+
 void CLibCEC::AddLog(cec_log_level level, const string &strMessage)
 {
   if (m_cec)
index 0b43aa46c4e1125a95639677e75bd8b87151a3bc..bd3ca600cd7bdd4817090d0e4770d2f54bc8e30f 100644 (file)
@@ -78,6 +78,7 @@ namespace CEC
       virtual bool GetDeviceMenuLanguage(cec_logical_address iAddress, cec_menu_language *language);
       virtual uint64_t GetDeviceVendorId(cec_logical_address iAddress);
       virtual cec_power_status GetDevicePowerStatus(cec_logical_address iAddress);
+      virtual bool PollDevice(cec_logical_address iAddress);
     //@}
 
       virtual void AddLog(cec_log_level level, const std::string &strMessage);
index a3be5f3bea89df0498af40851132a293f4ce6040..09b40dba942af682b6a6ae3d41dce3520e5cdbc8 100644 (file)
@@ -222,4 +222,11 @@ cec_power_status cec_get_device_power_status(cec_logical_address iLogicalAddress
   return CEC_POWER_STATUS_UNKNOWN;
 }
 
+int cec_poll_device(cec_logical_address iLogicalAddress)
+{
+  if (cec_parser)
+    return cec_parser->PollDevice(iLogicalAddress);
+  return -1;
+}
+
 //@}
index 0678ce393ef8dfe3a1825e8904940af6a9de6b12..5a56dc4baaae6b757cd8c037bb9cb37d3fdbdb1c 100644 (file)
@@ -433,3 +433,20 @@ cec_power_status CCECBusDevice::GetPowerStatus(bool bRefresh /* = true */)
 
   return m_powerStatus;
 }
+
+bool CCECBusDevice::PollDevice(void)
+{
+  bool bReturn(false);
+
+  CStdString strLog;
+  strLog.Format("<< sending POLL from device %1x to device %1x", (int8_t)GetMyLogicalAddress(), m_iLogicalAddress);
+  AddLog(CEC_LOG_DEBUG, strLog);
+
+  cec_command command;
+  cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_NONE);
+  CLockObject lock(&m_mutex);
+
+  bReturn = m_processor->Transmit(command);
+  AddLog(CEC_LOG_DEBUG, bReturn ? ">> POLL sent" : ">> POLL not sent");
+  return bReturn;
+}
index 5971f58718a9fe929e78bddcfeffffb71c168aa2..278c0386c5619b165870d7515bb636a440849659 100644 (file)
@@ -58,6 +58,7 @@ namespace CEC
     virtual cec_version         GetCecVersion(bool bRefresh = true);
     virtual cec_menu_language & GetMenuLanguage(bool bRefresh = true);
     virtual cec_power_status    GetPowerStatus(bool bRefresh = true);
+    virtual bool                PollDevice(void);
 
     virtual bool PowerOn(void);
     virtual bool Standby(void);
index 8efffedc4165c47fa01c7d57a747a76cdad765ad..048182985923f58af7ce76c3764fe6603c02c06f 100644 (file)
@@ -230,6 +230,9 @@ void show_console_help(void)
   "pow {addr}                get the power status of the specified device." << endl <<
   "[pow 0]                   get the power status of the TV" << endl <<
   endl <<
+  "poll {addr}               poll the specified device." << endl <<
+  "[poll 0]                  sends a poll message to 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 <<
@@ -451,6 +454,22 @@ int main (int argc, char *argv[])
             cout << "invalid destination" << endl;
           }
         }
+        else if (command == "poll")
+        {
+          string strValue;
+          uint8_t iValue = 0;
+          if (GetWord(input, strValue) && HexStrToInt(strValue, iValue) && iValue <= 0xF)
+          {
+            if (parser->PollDevice((cec_logical_address) iValue))
+              cout << "POLL message sent" << endl;
+            else
+              cout << "POLL message not sent" << endl;
+          }
+          else
+          {
+            cout << "invalid destination" << endl;
+          }
+        }
         else if (command == "la")
         {
           string strvalue;