cec: wait for multiple responses, not just for one. don't try to read and write at...
[deb_libcec.git] / src / lib / implementations / CECCommandHandler.h
index a1b1f96fb90e2c16ff5c57f711d6af7703d8028a..2943ba39b3a17059491bc098a3414a3be18c8182 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "../../../include/cectypes.h"
 #include <vector>
+#include <map>
 #include "../platform/threads/mutex.h"
 #include "../platform/util/StdString.h"
 
@@ -41,6 +42,83 @@ namespace CEC
   class CCECProcessor;
   class CCECBusDevice;
 
+  class CResponse
+  {
+  public:
+    CResponse(cec_opcode opcode) :
+        m_opcode(opcode){}
+    ~CResponse(void)
+    {
+      Broadcast();
+    }
+
+    bool Wait(uint32_t iTimeout)
+    {
+      return m_event.Wait(iTimeout);
+    }
+
+    void Broadcast(void)
+    {
+      m_event.Broadcast();
+    }
+
+  private:
+    cec_opcode       m_opcode;
+    PLATFORM::CEvent m_event;
+  };
+
+  class CWaitForResponse
+  {
+  public:
+    CWaitForResponse(void) {}
+    ~CWaitForResponse(void)
+    {
+      PLATFORM::CLockObject lock(m_mutex);
+      for (std::map<cec_opcode, CResponse*>::iterator it = m_waitingFor.begin(); it != m_waitingFor.end(); it++)
+      {
+        it->second->Broadcast();
+        delete it->second;
+      }
+      m_waitingFor.clear();
+    }
+
+    bool Wait(cec_opcode opcode, uint32_t iTimeout = 2000)
+    {
+      CResponse *response = GetEvent(opcode);
+      return response ? response->Wait(iTimeout) : false;
+    }
+
+    void Received(cec_opcode opcode)
+    {
+      CResponse *response = GetEvent(opcode);
+      if (response)
+        response->Broadcast();
+    }
+
+  private:
+    CResponse *GetEvent(cec_opcode opcode)
+    {
+      CResponse *retVal(NULL);
+      {
+        PLATFORM::CLockObject lock(m_mutex);
+        std::map<cec_opcode, CResponse*>::iterator it = m_waitingFor.find(opcode);
+        if (it != m_waitingFor.end())
+        {
+          retVal = it->second;
+        }
+        else
+        {
+          retVal = new CResponse(opcode);
+          m_waitingFor[opcode] = retVal;
+        }
+        return retVal;
+      }
+    }
+
+    PLATFORM::CMutex                 m_mutex;
+    std::map<cec_opcode, CResponse*> m_waitingFor;
+  };
+
   class CCECCommandHandler
   {
   public:
@@ -136,12 +214,8 @@ namespace CEC
     int32_t                               m_iTransmitWait;
     int8_t                                m_iTransmitRetries;
     bool                                  m_bHandlerInited;
-    cec_opcode                            m_expectedResponse;
-    cec_opcode                            m_lastCommandSent;
     bool                                  m_bOPTSendDeckStatusUpdateOnActiveSource;
     cec_vendor_id                         m_vendorId;
-    PLATFORM::CMutex                      m_receiveMutex;
-    PLATFORM::CCondition<volatile bool &> m_condition;
-    volatile bool                         m_bRcvSignal;
+    CWaitForResponse                     *m_waitForResponse;
   };
 };