cec: handle bus scan from LG TVs
[deb_libcec.git] / src / lib / AdapterCommunication.cpp
index 661478396a58a8ce09f7d5ac992a45ffd27f7e0f..32ceeafc02e5835be628af9a2d8e140056c838b0 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.IsEmpty() ? (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
@@ -212,8 +215,7 @@ CStdString CCECAdapterMessage::ToString(void) const
 bool CCECAdapterMessage::is_error(void) const
 {
   cec_adapter_messagecode code = message();
-  return (code == MSGCODE_TIMEOUT_ERROR ||
-    code == MSGCODE_HIGH_ERROR ||
+  return (code == MSGCODE_HIGH_ERROR ||
     code == MSGCODE_LOW_ERROR ||
     code == MSGCODE_RECEIVE_FAILED ||
     code == MSGCODE_COMMAND_REJECTED ||
@@ -224,15 +226,15 @@ bool CCECAdapterMessage::is_error(void) const
     code == MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE);
 }
 
-void CCECAdapterMessage::push_escaped(int16_t byte)
+void CCECAdapterMessage::push_escaped(uint8_t byte)
 {
-  if (byte >= MSGESC && byte != MSGSTART)
+  if (byte >= MSGESC)
   {
     push_back(MSGESC);
-    push_back((uint8_t) (byte - ESCOFFSET));
+    push_back(byte - ESCOFFSET);
   }
   else
-    push_back((uint8_t) byte);
+    push_back(byte);
 }
 
 CAdapterCommunication::CAdapterCommunication(CLibCEC *controller) :
@@ -279,7 +281,7 @@ bool CAdapterCommunication::Open(const char *strPort, uint16_t iBaudRate /* = 38
 
   //clear any input bytes
   uint8_t buff[1024];
-  m_port->Read(buff, sizeof(buff), 500);
+  while (m_port->Read(buff, sizeof(buff), 500) > 0) {}
 
   if (CreateThread())
   {
@@ -354,23 +356,26 @@ void CAdapterCommunication::WriteNextCommand(void)
 {
   CCECAdapterMessage *msg;
   if (m_outBuffer.Pop(msg))
+    SendMessageToAdapter(msg);
+}
+
+void CAdapterCommunication::SendMessageToAdapter(CCECAdapterMessage *msg)
+{
+  CLockObject lock(&msg->mutex);
+  if (m_port->Write(msg) != (int32_t) msg->size())
   {
-    CLockObject lock(&msg->mutex);
-    if (m_port->Write(msg) != (int32_t) msg->size())
-    {
-      CStdString strError;
-      strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
-      m_controller->AddLog(CEC_LOG_ERROR, strError);
-      msg->state = ADAPTER_MESSAGE_STATE_ERROR;
-    }
-    else
-    {
-      m_controller->AddLog(CEC_LOG_DEBUG, "command sent");
-      CCondition::Sleep((uint32_t) msg->size() * 24 /*data*/ + 5 /*start bit (4.5 ms)*/ + 10);
-      msg->state = ADAPTER_MESSAGE_STATE_SENT;
-    }
-    msg->condition.Signal();
+    CStdString strError;
+    strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
+    m_controller->AddLog(CEC_LOG_ERROR, strError);
+    msg->state = ADAPTER_MESSAGE_STATE_ERROR;
+  }
+  else
+  {
+    m_controller->AddLog(CEC_LOG_DEBUG, "command sent");
+    CCondition::Sleep((uint32_t) msg->size() * 24 /*data*/ + 5 /*start bit (4.5 ms)*/);
+    msg->state = ADAPTER_MESSAGE_STATE_SENT;
   }
+  msg->condition.Signal();
 }
 
 bool CAdapterCommunication::Write(CCECAdapterMessage *data)
@@ -408,7 +413,8 @@ bool CAdapterCommunication::Read(CCECAdapterMessage &msg, uint32_t iTimeout)
     }
     else if (buf == MSGSTART) //we found a msgstart before msgend, this is not right, remove
     {
-      m_controller->AddLog(CEC_LOG_ERROR, "received MSGSTART before MSGEND");
+      if (msg.size() > 0)
+        m_controller->AddLog(CEC_LOG_WARNING, "received MSGSTART before MSGEND, removing previous buffer contents");
       msg.clear();
       bGotStart = true;
     }
@@ -452,9 +458,8 @@ bool CAdapterCommunication::StartBootloader(void)
   output->push_escaped(MSGCODE_START_BOOTLOADER);
   output->push_back(MSGEND);
 
-  if ((bReturn = Write(output)) == false)
-    m_controller->AddLog(CEC_LOG_ERROR, "could not start the bootloader");
-
+  SendMessageToAdapter(output);
+  bReturn = output->state == ADAPTER_MESSAGE_STATE_SENT;
   delete output;
 
   return bReturn;
@@ -473,10 +478,8 @@ bool CAdapterCommunication::PingAdapter(void)
   output->push_escaped(MSGCODE_PING);
   output->push_back(MSGEND);
 
-  if ((bReturn = Write(output)) == false)
-    m_controller->AddLog(CEC_LOG_ERROR, "could not send ping command");
-
-  // TODO check for pong
+  SendMessageToAdapter(output);
+  bReturn = output->state == ADAPTER_MESSAGE_STATE_SENT;
   delete output;
 
   return bReturn;