RPI updates with fixes
[deb_libcec.git] / src / lib / adapter / RPi / RPiCECAdapterMessageQueue.cpp
index df9a374dc4ad07b9746ebcd25a94dc7fff97c980..cb9fed01f8f9cc179b2b949cea72389f1167ae40 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
@@ -71,9 +71,12 @@ void CRPiCECAdapterMessageQueueEntry::Broadcast(void)
 
 bool CRPiCECAdapterMessageQueueEntry::MessageReceived(cec_opcode opcode, cec_logical_address initiator, cec_logical_address destination, uint32_t response)
 {
-  if ((!m_command.opcode_set || m_command.opcode == opcode) &&
-      m_command.initiator == initiator &&
-      m_command.destination == destination)
+  if ((m_command.opcode_set && m_command.opcode == opcode &&
+     m_command.initiator == initiator &&
+     m_command.destination == destination)
+     ||
+     (!m_command.opcode_set && 
+     m_command.destination == destination))
   {
     CLockObject lock(m_mutex);
     m_retval = response;
@@ -93,9 +96,6 @@ bool CRPiCECAdapterMessageQueueEntry::Wait(uint32_t iTimeout)
     CLockObject lock(m_mutex);
     bReturn = m_bSucceeded ? true : m_condition.Wait(m_mutex, m_bSucceeded, iTimeout);
     m_bWaiting = false;
-
-    if (bReturn)
-      bReturn = m_retval == VCHIQ_SUCCESS;
   }
   return bReturn;
 }
@@ -121,10 +121,15 @@ void CRPiCECAdapterMessageQueue::MessageReceived(cec_opcode opcode, cec_logical_
     bHandled = it->second->MessageReceived(opcode, initiator, destination, response);
 
   if (!bHandled)
-    LIB_CEC->AddLog(CEC_LOG_WARNING, "unhandled response received");
+    LIB_CEC->AddLog(CEC_LOG_WARNING, "unhandled response received: opcode=%x initiator=%x destination=%x response=%x", (int)opcode, (int)initiator, (int)destination, response);
 }
 
-bool CRPiCECAdapterMessageQueue::Write(const cec_command &command, bool bIsReply)
+uint32_t CRPiCECAdapterMessageQueueEntry::Result() const
+{
+  return m_retval;
+}
+
+cec_adapter_message_state CRPiCECAdapterMessageQueue::Write(const cec_command &command, bool &bRetry, uint32_t iLineTimeout, bool bIsReply, VC_CEC_ERROR_T &vcReply)
 {
   CRPiCECAdapterMessageQueueEntry *entry = new CRPiCECAdapterMessageQueueEntry(this, command);
   uint64_t iEntryId(0);
@@ -151,11 +156,13 @@ bool CRPiCECAdapterMessageQueue::Write(const cec_command &command, bool bIsReply
       message.payload[iPtr + 1] = command.parameters.At(iPtr);
   }
 
+#ifdef CEC_DEBUGGING
   CStdString strDump;
   strDump.Format("len = %d, payload = %X%X", message.length, (int)message.initiator, (int)message.follower);
   for (uint8_t iPtr = 0; iPtr < message.length - 1; iPtr++)
     strDump.AppendFormat(":%02X", message.payload[iPtr]);
   LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: %s", strDump.c_str());
+#endif
 
   int iReturn = vc_cec_send_message2(&message);
 #else
@@ -172,31 +179,52 @@ bool CRPiCECAdapterMessageQueue::Write(const cec_command &command, bool bIsReply
       payload[iPtr + 1] = command.parameters.At(iPtr);
   }
 
+#ifdef CEC_DEBUGGING
   CStdString strDump;
   strDump.Format("len = %d, payload = %X%X", iLength, (int)command.initiator, (int)command.destination);
   for (uint8_t iPtr = 0; iPtr < iLength; iPtr++)
     strDump.AppendFormat(":%02X", payload[iPtr]);
   LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: %s", strDump.c_str());
+#endif
 
-   int iReturn = vc_cec_send_message((uint32_t)command.destination, (uint8_t*)&payload, iLength, bIsReply);
+  int iReturn = vc_cec_send_message((uint32_t)command.destination, command.opcode_set ? (uint8_t*)&payload : NULL, iLength, bIsReply);
 #endif
 
+  bRetry = false;
   if (iReturn != VCHIQ_SUCCESS)
   {
     LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending command '%s' failed (%d)", command.opcode_set ? CCECTypeUtils::ToString(command.opcode) : "POLL", iReturn);
     delete (entry);
-    return false;
+    return ADAPTER_MESSAGE_STATE_ERROR;
   }
 
-  bool bReturn(true);
+  cec_adapter_message_state bReturn(ADAPTER_MESSAGE_STATE_ERROR);
   if (entry)
   {
-    if (!entry->Wait(CEC_DEFAULT_TRANSMIT_WAIT))
+    if (entry->Wait(iLineTimeout))
+    {
+      int status = entry->Result();
+
+      if (status == VC_CEC_ERROR_NO_ACK)
+        bReturn = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
+      else if (status == VC_CEC_SUCCESS)
+        bReturn = ADAPTER_MESSAGE_STATE_SENT_ACKED;
+      else
+        bReturn = ADAPTER_MESSAGE_STATE_SENT;
+    }
+    else
     {
-      LIB_CEC->AddLog(CEC_LOG_DEBUG, "command '%s' was not acked by the controller", command.opcode_set ? CCECTypeUtils::ToString(command.opcode) : "POLL");
-      bReturn = false;
+      if (command.opcode_set)
+      {
+        bRetry = true;
+        LIB_CEC->AddLog(CEC_LOG_DEBUG, "command '%s' timeout", command.opcode_set ? CCECTypeUtils::ToString(command.opcode) : "POLL");
+        sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT);
+      }
+      bReturn = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT;
     }
 
+    vcReply = (VC_CEC_ERROR_T)entry->Result();
+
     CLockObject lock(m_mutex);
     m_messages.erase(iEntryId);
     delete entry;