/*
* This file is part of the libCEC(R) library.
*
- * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved.
* libCEC(R) is an original work, containing original code.
*
* libCEC(R) is a trademark of Pulse-Eight Limited.
#include "AdapterCommunication.h"
#include "AdapterMessage.h"
-#include "CECProcessor.h"
-#include "platform/serialport/serialport.h"
+#include "../CECProcessor.h"
+#include "../platform/sockets/serialport.h"
+#include "../platform/util/timeutils.h"
+#include "../LibCEC.h"
using namespace std;
using namespace CEC;
if (!m_port)
{
- m_processor->AddLog(CEC_LOG_ERROR, "port is NULL");
+ CLibCEC::AddLog(CEC_LOG_ERROR, "port is NULL");
return false;
}
if (IsOpen())
{
- m_processor->AddLog(CEC_LOG_ERROR, "port is already open");
+ CLibCEC::AddLog(CEC_LOG_ERROR, "port is already open");
return true;
}
if (!bConnected)
{
- m_processor->AddLog(CEC_LOG_ERROR, strError);
+ CLibCEC::AddLog(CEC_LOG_ERROR, strError);
return false;
}
- m_processor->AddLog(CEC_LOG_DEBUG, "connection opened");
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "connection opened, clearing any previous input and waiting for active transmissions to end before starting");
//clear any input bytes
- uint8_t buff[1];
- while (m_port->Read(buff, 1, 5) == 1) {}
+ uint8_t buff[1024];
+ while (m_port->Read(buff, 1024, 100) > 0)
+ {
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "data received, clearing it");
+ Sleep(250);
+ }
if (CreateThread())
{
- m_processor->AddLog(CEC_LOG_DEBUG, "communication thread started");
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "communication thread started");
return true;
}
else
{
- m_processor->AddLog(CEC_LOG_ERROR, "could not create a communication thread");
+ CLibCEC::AddLog(CEC_LOG_ERROR, "could not create a communication thread");
}
return false;
if (data->state != ADAPTER_MESSAGE_STATE_SENT)
{
- m_processor->AddLog(CEC_LOG_ERROR, "command was not sent");
+ CLibCEC::AddLog(CEC_LOG_ERROR, "command was not sent");
}
- if (data->expectControllerAck && WaitForTransmitSucceeded(data))
+ else if (data->expectControllerAck)
{
- if (data->isTransmission)
- data->state = ADAPTER_MESSAGE_STATE_SENT_ACKED;
- bReturn = true;
+ bReturn = WaitForAck(*data);
+ if (bReturn)
+ {
+ if (data->isTransmission)
+ data->state = ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ }
+ else
+ {
+ data->state = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "did not receive ack");
+ }
}
else
{
- data->state = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
- m_processor->AddLog(CEC_LOG_DEBUG, "did not receive ack");
+ bReturn = true;
}
return bReturn;
else if (buf == MSGSTART) //we found a msgstart before msgend, this is not right, remove
{
if (msg.Size() > 0)
- m_processor->AddLog(CEC_LOG_WARNING, "received MSGSTART before MSGEND, removing previous buffer contents");
+ CLibCEC::AddLog(CEC_LOG_WARNING, "received MSGSTART before MSGEND, removing previous buffer contents");
msg.Clear();
bGotStart = true;
}
return bGotFullMessage;
}
-std::string CAdapterCommunication::GetError(void) const
+CStdString CAdapterCommunication::GetError(void) const
{
- return m_port->GetError();
+ CStdString strError;
+ strError = m_port->GetError();
+ return strError;
}
bool CAdapterCommunication::StartBootloader(void)
if (!IsRunning())
return bReturn;
- m_processor->AddLog(CEC_LOG_DEBUG, "starting the bootloader");
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "starting the bootloader");
CCECAdapterMessage *output = new CCECAdapterMessage;
output->PushBack(MSGSTART);
output->expectControllerAck = false;
if ((bReturn = Write(output)) == false)
- m_processor->AddLog(CEC_LOG_ERROR, "could not start the bootloader");
+ CLibCEC::AddLog(CEC_LOG_ERROR, "could not start the bootloader");
delete output;
return bReturn;
if (!IsRunning())
return bReturn;
- m_processor->AddLog(CEC_LOG_DEBUG, "sending ping");
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "sending ping");
CCECAdapterMessage *output = new CCECAdapterMessage;
output->PushBack(MSGSTART);
output->isTransmission = false;
if ((bReturn = Write(output)) == false)
- m_processor->AddLog(CEC_LOG_ERROR, "could not ping the adapter");
+ CLibCEC::AddLog(CEC_LOG_ERROR, "could not ping the adapter");
delete output;
return bReturn;
if (iReturn == CEC_FW_VERSION_UNKNOWN)
{
- m_processor->AddLog(CEC_LOG_DEBUG, "requesting the firmware version");
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "requesting the firmware version");
CCECAdapterMessage *output = new CCECAdapterMessage;
output->PushBack(MSGSTART);
CCECAdapterMessage input;
if (!Read(input, CEC_DEFAULT_TRANSMIT_WAIT) || input.Message() != MSGCODE_FIRMWARE_VERSION || input.Size() != 3)
- m_processor->AddLog(CEC_LOG_ERROR, "no or invalid firmware version");
+ CLibCEC::AddLog(CEC_LOG_ERROR, "no or invalid firmware version (size = %d, message = %d)", input.Size(), input.Message());
else
{
m_iFirmwareVersion = (input[1] << 8 | input[2]);
output->isTransmission = false;
if ((bReturn = Write(output)) == false)
- m_processor->AddLog(CEC_LOG_ERROR, "could not set the idletime");
+ CLibCEC::AddLog(CEC_LOG_ERROR, "could not set the idletime");
delete output;
}
bool bReturn(false);
CStdString strLog;
strLog.Format("setting ackmask to %2x", iMask);
- m_processor->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+ CLibCEC::AddLog(CEC_LOG_DEBUG, strLog.c_str());
CCECAdapterMessage *output = new CCECAdapterMessage;
output->isTransmission = false;
if ((bReturn = Write(output)) == false)
- m_processor->AddLog(CEC_LOG_ERROR, "could not set the ackmask");
+ CLibCEC::AddLog(CEC_LOG_ERROR, "could not set the ackmask");
delete output;
return bReturn;
return !IsStopped() && m_port->IsOpen() && IsRunning();
}
-bool CAdapterCommunication::WaitForTransmitSucceeded(CCECAdapterMessage *message)
+bool CAdapterCommunication::WaitForAck(CCECAdapterMessage &message)
{
bool bError(false);
bool bTransmitSucceeded(false);
- uint8_t iPacketsLeft(message->Size() / 4);
+ uint8_t iPacketsLeft(message.Size() / 4);
int64_t iNow = GetTimeMs();
- int64_t iTargetTime = iNow + message->transmit_timeout;
+ int64_t iTargetTime = iNow + message.transmit_timeout;
- while (!bTransmitSucceeded && !bError && (message->transmit_timeout == 0 || iNow < iTargetTime))
+ while (!bTransmitSucceeded && !bError && (message.transmit_timeout == 0 || iNow < iTargetTime))
{
CCECAdapterMessage msg;
+ int32_t iWait = (int32_t)(iTargetTime - iNow);
+ if (iWait <= 5 || message.transmit_timeout <= 5)
+ iWait = CEC_DEFAULT_TRANSMIT_WAIT;
- if (!Read(msg, message->transmit_timeout > 0 ? (int32_t)(iTargetTime - iNow) : 1000))
+ if (!Read(msg, iWait))
{
iNow = GetTimeMs();
continue;
bError = msg.IsError();
if (bError)
{
- message->reply = msg.Message();
- m_processor->AddLog(CEC_LOG_DEBUG, msg.ToString());
+ message.reply = msg.Message();
+ CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
}
else
{
switch(msg.Message())
{
case MSGCODE_COMMAND_ACCEPTED:
- m_processor->AddLog(CEC_LOG_DEBUG, msg.ToString());
+ CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
if (iPacketsLeft > 0)
iPacketsLeft--;
- if (!message->isTransmission && iPacketsLeft == 0)
+ if (!message.isTransmission && iPacketsLeft == 0)
bTransmitSucceeded = true;
break;
case MSGCODE_TRANSMIT_SUCCEEDED:
- m_processor->AddLog(CEC_LOG_DEBUG, msg.ToString());
+ CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
bTransmitSucceeded = (iPacketsLeft == 0);
bError = !bTransmitSucceeded;
- message->reply = MSGCODE_TRANSMIT_SUCCEEDED;
+ message.reply = MSGCODE_TRANSMIT_SUCCEEDED;
break;
default:
// ignore other data while waiting
{
CStdString strError;
strError.Format("error reading from serial port: %s", m_port->GetError().c_str());
- m_processor->AddLog(CEC_LOG_ERROR, strError);
+ CLibCEC::AddLog(CEC_LOG_ERROR, strError);
return false;
}
else if (iBytesRead > 0)
{
CStdString strError;
strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
- m_processor->AddLog(CEC_LOG_ERROR, strError);
+ CLibCEC::AddLog(CEC_LOG_ERROR, strError);
msg->state = ADAPTER_MESSAGE_STATE_ERROR;
}
else
{
- m_processor->AddLog(CEC_LOG_DEBUG, "command sent");
+ CLibCEC::AddLog(CEC_LOG_DEBUG, "command sent");
msg->state = ADAPTER_MESSAGE_STATE_SENT;
}
msg->condition.Signal();