Merge branch 'master' of github.com:Pulse-Eight/libcec
[deb_libcec.git] / src / lib / adapter / USBCECAdapterCommunication.cpp
index c97d9955f8d7855f5aa3b7249f6adf032548be3e..8f3bb7f0bef62dde35165454f35b4c13061ee122 100644 (file)
@@ -133,7 +133,7 @@ bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = 10000 */
   return bReturn;
 }
 
-bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs /* = 10000 */, bool bSkipChecks /* = false */)
+bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs /* = 10000 */, bool bSkipChecks /* = false */, bool bStartListening /* = true */)
 {
   uint64_t iNow = GetTimeMs();
   uint64_t iTimeout = iNow + iTimeoutMs;
@@ -200,9 +200,11 @@ bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32
   if (!bSkipChecks && !CheckAdapter())
   {
     CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter failed to pass basic checks");
+    delete m_port;
+    m_port = NULL;
     return false;
   }
-  else
+  else if (bStartListening)
   {
     if (CreateThread())
     {
@@ -211,11 +213,19 @@ bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32
     }
     else
     {
+      delete m_port;
+      m_port = NULL;
       CLibCEC::AddLog(CEC_LOG_ERROR, "could not create a communication thread");
+      return false;
     }
   }
+  else
+  {
+    delete m_port;
+    m_port = NULL;
+  }
 
-  return false;
+  return true;
 }
 
 void CUSBCECAdapterCommunication::Close(void)
@@ -261,6 +271,7 @@ void *CUSBCECAdapterCommunication::Process(void)
   /* stop the message processor */
   m_messageProcessor->StopThread();
   delete m_messageProcessor;
+  m_messageProcessor = NULL;
 
   /* notify all threads that are waiting on messages to be sent */
   CCECAdapterMessage *msg(NULL);
@@ -279,6 +290,7 @@ void *CUSBCECAdapterCommunication::Process(void)
     m_port = NULL;
   }
 
+  m_rcvCondition.Broadcast();
   return NULL;
 }
 
@@ -300,6 +312,7 @@ cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &
   output->retryTimeout = iRetryLineTimeout;
   output->tries = 0;
 
+  if (data.destination < 15)
   {
     CLockObject lock(m_mutex);
     m_bWaitingForAck[data.destination] = true;
@@ -429,10 +442,13 @@ bool CUSBCECAdapterCommunication::ParseMessage(const CCECAdapterMessage &msg)
       if (m_currentframe.ack == 0x1)
       {
         m_lastDestination    = m_currentframe.destination;
-        if (!m_bWaitingForAck[m_currentframe.destination])
-          m_processor->HandlePoll(m_currentframe.initiator, m_currentframe.destination);
-        else
-          m_bWaitingForAck[m_currentframe.destination] = false;
+        if (m_currentframe.destination < 15)
+        {
+          if (!m_bWaitingForAck[m_currentframe.destination])
+            m_processor->HandlePoll(m_currentframe.initiator, m_currentframe.destination);
+          else
+            m_bWaitingForAck[m_currentframe.destination] = false;
+        }
       }
     }
     break;
@@ -532,6 +548,7 @@ bool CUSBCECAdapterCommunication::PersistConfiguration(libcec_configuration *con
 
 bool CUSBCECAdapterCommunication::GetConfiguration(libcec_configuration *configuration)
 {
+  configuration->iFirmwareVersion = m_iFirmwareVersion;
   if (m_iFirmwareVersion < 2)
     return false;
 
@@ -811,9 +828,9 @@ bool CUSBCECAdapterCommunication::WaitForAck(CCECAdapterMessage &message)
 
     if (msg.Message() == MSGCODE_FRAME_START && msg.IsACK())
     {
-      if (m_bWaitingForAck[msg.Initiator()])
+      if (msg.Initiator() < 15 && m_bWaitingForAck[msg.Initiator()])
         m_bWaitingForAck[msg.Initiator()] = false;
-      else
+      else if (msg.Initiator() < 15)
       {
         m_processor->HandlePoll(msg.Initiator(), msg.Destination());
         m_lastDestination = msg.Initiator();
@@ -1008,12 +1025,14 @@ bool CUSBCECAdapterCommunication::SendCommand(cec_adapter_messagecode msgCode, C
     Write(output);
 
   bool bWriteOk = output->state == (output->expectControllerAck ? ADAPTER_MESSAGE_STATE_SENT_ACKED : ADAPTER_MESSAGE_STATE_SENT);
+  cec_adapter_messagecode reply = output->reply;
+  delete output;
+
   if (!bWriteOk)
   {
     CLibCEC::AddLog(CEC_LOG_ERROR, "'%s' failed", CCECAdapterMessage::ToString(msgCode));
-    delete output;
 
-    if (!bIsRetry && output->reply == MSGCODE_COMMAND_REJECTED && msgCode != MSGCODE_SET_CONTROLLED)
+    if (!bIsRetry && reply == MSGCODE_COMMAND_REJECTED && msgCode != MSGCODE_SET_CONTROLLED)
     {
       CLibCEC::AddLog(CEC_LOG_DEBUG, "setting controlled mode and retrying");
       if (SetControlledMode(true))
@@ -1022,7 +1041,6 @@ bool CUSBCECAdapterCommunication::SendCommand(cec_adapter_messagecode msgCode, C
     return false;
   }
 
-  delete output;
   return true;
 }