X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Flib%2Fadapter%2FAdapterCommunication.cpp;h=ff69a7f4a73f2aeb6a10cf43bb9a888e21190330;hb=ba65909d0a9c43a1bac71c6182c53f202285cec5;hp=44b24e1a7c28e9672f3926fd21aea683355c5f73;hpb=71c4a2f532f422c80337ff11de69d1fa6f3910bd;p=deb_libcec.git diff --git a/src/lib/adapter/AdapterCommunication.cpp b/src/lib/adapter/AdapterCommunication.cpp index 44b24e1..ff69a7f 100644 --- a/src/lib/adapter/AdapterCommunication.cpp +++ b/src/lib/adapter/AdapterCommunication.cpp @@ -33,8 +33,10 @@ #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; @@ -43,7 +45,8 @@ using namespace PLATFORM; CAdapterCommunication::CAdapterCommunication(CCECProcessor *processor) : m_port(NULL), m_processor(processor), - m_iLineTimeout(0) + m_iLineTimeout(0), + m_iFirmwareVersion(CEC_FW_VERSION_UNKNOWN) { m_port = new PLATFORM::CSerialPort; } @@ -68,13 +71,13 @@ bool CAdapterCommunication::Open(const char *strPort, uint16_t iBaudRate /* = 38 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; } @@ -92,24 +95,28 @@ bool CAdapterCommunication::Open(const char *strPort, uint16_t iBaudRate /* = 38 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; @@ -149,18 +156,25 @@ bool CAdapterCommunication::Write(CCECAdapterMessage *data) 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; @@ -195,7 +209,7 @@ bool CAdapterCommunication::Read(CCECAdapterMessage &msg, uint32_t iTimeout) 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; } @@ -221,9 +235,11 @@ bool CAdapterCommunication::Read(CCECAdapterMessage &msg, uint32_t iTimeout) 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) @@ -232,7 +248,7 @@ 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); @@ -242,7 +258,7 @@ bool CAdapterCommunication::StartBootloader(void) 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; @@ -254,7 +270,7 @@ bool CAdapterCommunication::PingAdapter(void) 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); @@ -263,12 +279,45 @@ bool CAdapterCommunication::PingAdapter(void) 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; } +uint16_t CAdapterCommunication::GetFirmwareVersion(void) +{ + uint16_t iReturn(m_iFirmwareVersion); + if (!IsRunning()) + return iReturn; + + if (iReturn == CEC_FW_VERSION_UNKNOWN) + { + CLibCEC::AddLog(CEC_LOG_DEBUG, "requesting the firmware version"); + CCECAdapterMessage *output = new CCECAdapterMessage; + + output->PushBack(MSGSTART); + output->PushEscaped(MSGCODE_FIRMWARE_VERSION); + output->PushBack(MSGEND); + output->isTransmission = false; + output->expectControllerAck = false; + + SendMessageToAdapter(output); + delete output; + + CCECAdapterMessage input; + if (!Read(input, CEC_DEFAULT_TRANSMIT_WAIT) || input.Message() != MSGCODE_FIRMWARE_VERSION || input.Size() != 3) + 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]); + iReturn = m_iFirmwareVersion; + } + } + + return iReturn; +} + bool CAdapterCommunication::SetLineTimeout(uint8_t iTimeout) { bool bReturn(m_iLineTimeout != iTimeout); @@ -284,7 +333,7 @@ bool CAdapterCommunication::SetLineTimeout(uint8_t iTimeout) 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; } @@ -296,7 +345,7 @@ bool CAdapterCommunication::SetAckMask(uint16_t iMask) 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; @@ -308,7 +357,7 @@ bool CAdapterCommunication::SetAckMask(uint16_t iMask) 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; @@ -319,20 +368,23 @@ bool CAdapterCommunication::IsOpen(void) 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; @@ -355,25 +407,25 @@ bool CAdapterCommunication::WaitForTransmitSucceeded(CCECAdapterMessage *message 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 @@ -403,12 +455,13 @@ bool CAdapterCommunication::ReadFromDevice(uint32_t iTimeout) if (!m_port) return false; + CLockObject lock(m_mutex); iBytesRead = m_port->Read(buff, sizeof(buff), iTimeout); if (iBytesRead < 0 || iBytesRead > 256) { 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) @@ -419,17 +472,18 @@ bool CAdapterCommunication::ReadFromDevice(uint32_t iTimeout) void CAdapterCommunication::SendMessageToAdapter(CCECAdapterMessage *msg) { + CLockObject adapterLock(m_mutex); CLockObject lock(msg->mutex); if (m_port->Write(msg->packet.data, msg->Size()) != (int32_t) msg->Size()) { 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();