rpi: don't try to re-register a logical address when the logical address isn't regist...
[deb_libcec.git] / src / lib / adapter / RPi / RPiCECAdapterCommunication.cpp
index 5e1efd493f4a8117018816616870219974d5d3fe..8084b780a15bf8c62756f74d217662995aaad95e 100644 (file)
@@ -61,7 +61,9 @@ void rpi_cec_callback(void *callback_data, uint32_t p0, uint32_t p1, uint32_t p2
 CRPiCECAdapterCommunication::CRPiCECAdapterCommunication(IAdapterCommunicationCallback *callback) :
     IAdapterCommunication(callback),
     m_logicalAddress(CECDEVICE_UNKNOWN),
-    m_bLogicalAddressChanged(false)
+    m_bLogicalAddressChanged(false),
+    m_previousLogicalAddress(CECDEVICE_FREEUSE),
+    m_bLogicalAddressRegistered(false)
 {
   m_queue = new CRPiCECAdapterMessageQueue(this);
 }
@@ -109,7 +111,9 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
 {
   VC_CEC_NOTIFY_T reason = (VC_CEC_NOTIFY_T)CEC_CB_REASON(header);
 
+#ifdef CEC_DEBUGGING
   LIB_CEC->AddLog(CEC_LOG_DEBUG, "received data: header:%08X p0:%08X p1:%08X p2:%08X p3:%08X reason:%x", header, p0, p1, p2, p3, reason);
+#endif
 
   switch (reason)
   {
@@ -142,10 +146,14 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
     }
     break;
   case VC_CEC_BUTTON_PRESSED:
+  case VC_CEC_REMOTE_PRESSED:
     {
       // translate into a cec_command
       cec_command command;
-      cec_command::Format(command, (cec_logical_address)CEC_CB_INITIATOR(p0), (cec_logical_address)CEC_CB_FOLLOWER(p0), CEC_OPCODE_USER_CONTROL_PRESSED);
+      cec_command::Format(command,
+                          (cec_logical_address)CEC_CB_INITIATOR(p0),
+                          (cec_logical_address)CEC_CB_FOLLOWER(p0),
+                          reason == VC_CEC_BUTTON_PRESSED ? CEC_OPCODE_USER_CONTROL_PRESSED : CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN);
       command.parameters.PushBack((uint8_t)CEC_CB_OPERAND1(p0));
 
       // send to libCEC
@@ -153,10 +161,14 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
     }
     break;
   case VC_CEC_BUTTON_RELEASE:
+  case VC_CEC_REMOTE_RELEASE:
     {
       // translate into a cec_command
       cec_command command;
-      cec_command::Format(command, (cec_logical_address)CEC_CB_INITIATOR(p0), (cec_logical_address)CEC_CB_FOLLOWER(p0), CEC_OPCODE_USER_CONTROL_RELEASE);
+      cec_command::Format(command,
+                          (cec_logical_address)CEC_CB_INITIATOR(p0),
+                          (cec_logical_address)CEC_CB_FOLLOWER(p0),
+                          reason == VC_CEC_BUTTON_PRESSED ? CEC_OPCODE_USER_CONTROL_RELEASE : CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP);
       command.parameters.PushBack((uint8_t)CEC_CB_OPERAND1(p0));
 
       // send to libCEC
@@ -166,6 +178,7 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
   case VC_CEC_LOGICAL_ADDR:
     {
       CLockObject lock(m_mutex);
+      m_previousLogicalAddress = m_logicalAddress;
       if (CEC_CB_RC(header) == VCHIQ_SUCCESS)
       {
         m_bLogicalAddressChanged = true;
@@ -174,15 +187,29 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
       }
       else
       {
-        m_logicalAddress = CECDEVICE_BROADCAST;
+        m_logicalAddress = CECDEVICE_FREEUSE;
         LIB_CEC->AddLog(CEC_LOG_DEBUG, "failed to change the logical address, reset to %s (%x)", LIB_CEC->ToString(m_logicalAddress), m_logicalAddress);
       }
       m_logicalAddressCondition.Signal();
     }
     break;
+  case VC_CEC_LOGICAL_ADDR_LOST:
+    {
+      // the logical address was taken by another device
+      cec_logical_address previousAddress = m_logicalAddress == CECDEVICE_BROADCAST ? m_previousLogicalAddress : m_logicalAddress;
+      m_logicalAddress = CECDEVICE_UNKNOWN;
+
+      // notify libCEC that we lost our LA when the connection was initialised
+      bool bNotify(false);
+      {
+        CLockObject lock(m_mutex);
+        bNotify = m_bInitialised && m_bLogicalAddressRegistered;
+      }
+      if (bNotify)
+        m_callback->HandleLogicalAddressLost(previousAddress);
+    }
+    break;
   case VC_CEC_TOPOLOGY:
-  case VC_CEC_REMOTE_PRESSED:
-  case VC_CEC_REMOTE_RELEASE:
     break;
   default:
     LIB_CEC->AddLog(CEC_LOG_DEBUG, "ignoring unknown reason %x", reason);
@@ -358,7 +385,11 @@ bool CRPiCECAdapterCommunication::UnregisterLogicalAddress(void)
     return true;
 
   LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - releasing previous logical address", __FUNCTION__);
-  m_bLogicalAddressChanged = false;
+  {
+    CLockObject lock(m_mutex);
+    m_bLogicalAddressRegistered = false;
+    m_bLogicalAddressChanged    = false;
+  }
 
   vc_cec_release_logical_address();
 
@@ -390,7 +421,12 @@ bool CRPiCECAdapterCommunication::RegisterLogicalAddress(const cec_logical_addre
     return false;
   }
 
-  return m_logicalAddressCondition.Wait(m_mutex, m_bLogicalAddressChanged);
+  if (m_logicalAddressCondition.Wait(m_mutex, m_bLogicalAddressChanged))
+  {
+    m_bLogicalAddressRegistered = true;
+    return true;
+  }
+  return false;
 }
 
 cec_logical_addresses CRPiCECAdapterCommunication::GetLogicalAddresses(void)