X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fadapter%2FUSBCECAdapterCommunication.cpp;fp=src%2Flib%2Fadapter%2FAdapterCommunication.cpp;h=0134751d31b2b05f8eb4f88f3320ff9b09fba686;hb=7bb4ed43f15a0fa2be17d2c3f580b181ac7430a7;hp=c0f9ea165a98ebb1823a3cd6248cebf0309c22d3;hpb=996665192725398172263999b88c63663d11db04;p=deb_libcec.git diff --git a/src/lib/adapter/AdapterCommunication.cpp b/src/lib/adapter/USBCECAdapterCommunication.cpp similarity index 62% rename from src/lib/adapter/AdapterCommunication.cpp rename to src/lib/adapter/USBCECAdapterCommunication.cpp index c0f9ea1..0134751 100644 --- a/src/lib/adapter/AdapterCommunication.cpp +++ b/src/lib/adapter/USBCECAdapterCommunication.cpp @@ -30,28 +30,29 @@ * http://www.pulse-eight.net/ */ -#include "AdapterCommunication.h" - -#include "AdapterMessage.h" -#include "../CECProcessor.h" +#include "USBCECAdapterCommunication.h" #include "../platform/sockets/serialport.h" #include "../platform/util/timeutils.h" #include "../LibCEC.h" +#include "../CECProcessor.h" using namespace std; using namespace CEC; using namespace PLATFORM; -CAdapterCommunication::CAdapterCommunication(CCECProcessor *processor, const char *strPort, uint16_t iBaudRate /* = 38400 */) : +CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(CCECProcessor *processor, const char *strPort, uint16_t iBaudRate /* = 38400 */) : m_port(NULL), m_processor(processor), m_iLineTimeout(0), - m_iFirmwareVersion(CEC_FW_VERSION_UNKNOWN) + m_iFirmwareVersion(CEC_FW_VERSION_UNKNOWN), + m_lastInitiator(CECDEVICE_UNKNOWN), + m_bNextIsEscaped(false), + m_bGotStart(false) { m_port = new PLATFORM::CSerialPort(strPort, iBaudRate); } -CAdapterCommunication::~CAdapterCommunication(void) +CUSBCECAdapterCommunication::~CUSBCECAdapterCommunication(void) { Close(); @@ -62,7 +63,7 @@ CAdapterCommunication::~CAdapterCommunication(void) } } -bool CAdapterCommunication::Open(uint32_t iTimeoutMs /* = 10000 */) +bool CUSBCECAdapterCommunication::Open(uint32_t iTimeoutMs /* = 10000 */) { uint64_t iNow = GetTimeMs(); uint64_t iTimeout = iNow + iTimeoutMs; @@ -122,14 +123,14 @@ bool CAdapterCommunication::Open(uint32_t iTimeoutMs /* = 10000 */) return false; } -void CAdapterCommunication::Close(void) +void CUSBCECAdapterCommunication::Close(void) { CLockObject lock(m_mutex); m_rcvCondition.Broadcast(); StopThread(); } -void *CAdapterCommunication::Process(void) +void *CUSBCECAdapterCommunication::Process(void) { while (!IsStopped()) { @@ -145,7 +146,36 @@ void *CAdapterCommunication::Process(void) return NULL; } -bool CAdapterCommunication::Write(CCECAdapterMessage *data) +cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &data, uint8_t iMaxTries, uint8_t iLineTimeout /* = 3 */, uint8_t iRetryLineTimeout /* = 3 */) +{ + cec_adapter_message_state retVal(ADAPTER_MESSAGE_STATE_UNKNOWN); + + CCECAdapterMessage *output = new CCECAdapterMessage(data); + + /* set the number of retries */ + if (data.opcode == CEC_OPCODE_NONE) //TODO + output->maxTries = 1; + else if (data.initiator != CECDEVICE_BROADCAST) + output->maxTries = iMaxTries; + + output->lineTimeout = iLineTimeout; + output->retryTimeout = iRetryLineTimeout; + output->tries = 0; + + bool bRetry(true); + while (bRetry && ++output->tries < output->maxTries) + { + bRetry = (!Write(output) || output->NeedsRetry()) && output->transmit_timeout > 0; + if (bRetry) + Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT); + } + retVal = output->state; + + delete output; + return retVal; +} + +bool CUSBCECAdapterCommunication::Write(CCECAdapterMessage *data) { bool bReturn(false); @@ -180,69 +210,53 @@ bool CAdapterCommunication::Write(CCECAdapterMessage *data) return bReturn; } -bool CAdapterCommunication::Read(CCECAdapterMessage &msg, uint32_t iTimeout) +bool CUSBCECAdapterCommunication::Read(cec_command &command, uint32_t iTimeout) { - CLockObject lock(m_mutex); - - msg.Clear(); - uint64_t iNow = GetTimeMs(); - uint64_t iTarget = iNow + iTimeout; - bool bGotFullMessage(false); - bool bNextIsEscaped(false); - bool bGotStart(false); - - while(!bGotFullMessage && iNow < iTarget) + CCECAdapterMessage msg; + if (Read(msg, iTimeout)) { - uint8_t buf = 0; - if (!m_inBuffer.Pop(buf)) + if (ParseMessage(msg)) { - if (!m_rcvCondition.Wait(m_mutex, (uint32_t) (iTarget - iNow))) - return false; + command = m_currentframe; + m_currentframe.Clear(); + return true; } + } + return false; +} - if (!bGotStart) - { - if (buf == MSGSTART) - bGotStart = true; - continue; - } - else if (buf == MSGSTART) //we found a msgstart before msgend, this is not right, remove - { - if (msg.Size() > 0) - CLibCEC::AddLog(CEC_LOG_WARNING, "received MSGSTART before MSGEND, removing previous buffer contents"); - msg.Clear(); - bGotStart = true; - } +bool CUSBCECAdapterCommunication::Read(CCECAdapterMessage &msg, uint32_t iTimeout) +{ + CLockObject lock(m_mutex); - if (buf == MSGEND) - { - bGotFullMessage = true; - } - else if (bNextIsEscaped) - { - msg.PushBack(buf + (uint8_t)ESCOFFSET); - bNextIsEscaped = false; - } - else if (buf == MSGESC) - bNextIsEscaped = true; - else - msg.PushBack(buf); - } + msg.Clear(); + CCECAdapterMessage *buf(NULL); - if (bGotFullMessage) - msg.state = ADAPTER_MESSAGE_STATE_INCOMING; + if (!m_inBuffer.Pop(buf)) + { + if (!m_rcvCondition.Wait(m_mutex, iTimeout)) + return false; + m_inBuffer.Pop(buf); + } - return bGotFullMessage; + if (buf) + { + msg.packet = buf->packet; + msg.state = msg.state = ADAPTER_MESSAGE_STATE_INCOMING; + delete buf; + return true; + } + return false; } -CStdString CAdapterCommunication::GetError(void) const +CStdString CUSBCECAdapterCommunication::GetError(void) const { CStdString strError; strError = m_port->GetError(); return strError; } -bool CAdapterCommunication::StartBootloader(void) +bool CUSBCECAdapterCommunication::StartBootloader(void) { bool bReturn(false); if (!IsRunning()) @@ -264,7 +278,7 @@ bool CAdapterCommunication::StartBootloader(void) return bReturn; } -bool CAdapterCommunication::PingAdapter(void) +bool CUSBCECAdapterCommunication::PingAdapter(void) { bool bReturn(false); if (!IsRunning()) @@ -285,7 +299,59 @@ bool CAdapterCommunication::PingAdapter(void) return bReturn; } -uint16_t CAdapterCommunication::GetFirmwareVersion(void) +bool CUSBCECAdapterCommunication::ParseMessage(const CCECAdapterMessage &msg) +{ + bool bEom(false); + bool bIsError(msg.IsError()); + + if (msg.IsEmpty()) + return bEom; + + switch(msg.Message()) + { + case MSGCODE_FRAME_START: + { + m_currentframe.Clear(); + if (msg.Size() >= 2) + { + m_currentframe.initiator = msg.Initiator(); + m_currentframe.destination = msg.Destination(); + m_currentframe.ack = msg.IsACK(); + m_currentframe.eom = msg.IsEOM(); + } + if (m_currentframe.ack == 0x1) + { + m_lastInitiator = m_currentframe.initiator; + m_processor->HandlePoll(m_currentframe.initiator, m_currentframe.destination); + } + } + break; + case MSGCODE_RECEIVE_FAILED: + { + m_currentframe.Clear(); + if (m_lastInitiator != CECDEVICE_UNKNOWN) + bIsError = m_processor->HandleReceiveFailed(m_lastInitiator); + } + break; + case MSGCODE_FRAME_DATA: + { + if (msg.Size() >= 2) + { + m_currentframe.PushBack(msg[1]); + m_currentframe.eom = msg.IsEOM(); + } + bEom = msg.IsEOM(); + } + break; + default: + break; + } + + CLibCEC::AddLog(bIsError ? CEC_LOG_WARNING : CEC_LOG_DEBUG, msg.ToString()); + return bEom; +} + +uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void) { uint16_t iReturn(m_iFirmwareVersion); if (!IsRunning()) @@ -318,29 +384,32 @@ uint16_t CAdapterCommunication::GetFirmwareVersion(void) return iReturn; } -bool CAdapterCommunication::SetLineTimeout(uint8_t iTimeout) +bool CUSBCECAdapterCommunication::SetLineTimeout(uint8_t iTimeout) { - bool bReturn(m_iLineTimeout != iTimeout); - - if (!bReturn) - { - CCECAdapterMessage *output = new CCECAdapterMessage; - - output->PushBack(MSGSTART); - output->PushEscaped(MSGCODE_TRANSMIT_IDLETIME); - output->PushEscaped(iTimeout); - output->PushBack(MSGEND); - output->isTransmission = false; - - if ((bReturn = Write(output)) == false) - CLibCEC::AddLog(CEC_LOG_ERROR, "could not set the idletime"); - delete output; - } - - return bReturn; + m_iLineTimeout = iTimeout; + return true; + //TODO +// bool bReturn(m_iLineTimeout != iTimeout); +// +// if (!bReturn) +// { +// CCECAdapterMessage *output = new CCECAdapterMessage; +// +// output->PushBack(MSGSTART); +// output->PushEscaped(MSGCODE_TRANSMIT_IDLETIME); +// output->PushEscaped(iTimeout); +// output->PushBack(MSGEND); +// output->isTransmission = false; +// +// if ((bReturn = Write(output)) == false) +// CLibCEC::AddLog(CEC_LOG_ERROR, "could not set the idletime"); +// delete output; +// } +// +// return bReturn; } -bool CAdapterCommunication::SetAckMask(uint16_t iMask) +bool CUSBCECAdapterCommunication::SetAckMask(uint16_t iMask) { bool bReturn(false); CStdString strLog; @@ -363,12 +432,12 @@ bool CAdapterCommunication::SetAckMask(uint16_t iMask) return bReturn; } -bool CAdapterCommunication::IsOpen(void) +bool CUSBCECAdapterCommunication::IsOpen(void) { return !IsStopped() && m_port->IsOpen() && IsRunning(); } -bool CAdapterCommunication::WaitForAck(CCECAdapterMessage &message) +bool CUSBCECAdapterCommunication::WaitForAck(CCECAdapterMessage &message) { bool bError(false); bool bTransmitSucceeded(false); @@ -393,12 +462,14 @@ bool CAdapterCommunication::WaitForAck(CCECAdapterMessage &message) if (msg.Message() == MSGCODE_FRAME_START && msg.IsACK()) { m_processor->HandlePoll(msg.Initiator(), msg.Destination()); + m_lastInitiator = msg.Initiator(); iNow = GetTimeMs(); continue; } if (msg.Message() == MSGCODE_RECEIVE_FAILED && - m_processor->HandleReceiveFailed()) + m_lastInitiator != CECDEVICE_UNKNOWN && + m_processor->HandleReceiveFailed(m_lastInitiator)) { iNow = GetTimeMs(); continue; @@ -439,16 +510,50 @@ bool CAdapterCommunication::WaitForAck(CCECAdapterMessage &message) return bTransmitSucceeded && !bError; } -void CAdapterCommunication::AddData(uint8_t *data, size_t iLen) +void CUSBCECAdapterCommunication::AddData(uint8_t *data, size_t iLen) { CLockObject lock(m_mutex); for (size_t iPtr = 0; iPtr < iLen; iPtr++) - m_inBuffer.Push(data[iPtr]); - - m_rcvCondition.Signal(); + { + if (!m_bGotStart) + { + if (data[iPtr] == MSGSTART) + m_bGotStart = true; + } + else if (data[iPtr] == MSGSTART) //we found a msgstart before msgend, this is not right, remove + { + if (m_currentAdapterMessage.Size() > 0) + CLibCEC::AddLog(CEC_LOG_WARNING, "received MSGSTART before MSGEND, removing previous buffer contents"); + m_currentAdapterMessage.Clear(); + m_bGotStart = true; + } + else if (data[iPtr] == MSGEND) + { + CCECAdapterMessage *newMessage = new CCECAdapterMessage; + newMessage->packet = m_currentAdapterMessage.packet; + m_inBuffer.Push(newMessage); + m_currentAdapterMessage.Clear(); + m_bGotStart = false; + m_bNextIsEscaped = false; + m_rcvCondition.Signal(); + } + else if (m_bNextIsEscaped) + { + m_currentAdapterMessage.PushBack(data[iPtr] + (uint8_t)ESCOFFSET); + m_bNextIsEscaped = false; + } + else if (data[iPtr] == MSGESC) + { + m_bNextIsEscaped = true; + } + else + { + m_currentAdapterMessage.PushBack(data[iPtr]); + } + } } -bool CAdapterCommunication::ReadFromDevice(uint32_t iTimeout) +bool CUSBCECAdapterCommunication::ReadFromDevice(uint32_t iTimeout) { ssize_t iBytesRead; uint8_t buff[256]; @@ -470,10 +575,15 @@ bool CAdapterCommunication::ReadFromDevice(uint32_t iTimeout) return iBytesRead > 0; } -void CAdapterCommunication::SendMessageToAdapter(CCECAdapterMessage *msg) +void CUSBCECAdapterCommunication::SendMessageToAdapter(CCECAdapterMessage *msg) { CLockObject adapterLock(m_mutex); CLockObject lock(msg->mutex); + if (msg->tries == 1) + SetLineTimeout(msg->lineTimeout); + else + SetLineTimeout(msg->retryTimeout); + if (m_port->Write(msg->packet.data, msg->Size()) != (ssize_t) msg->Size()) { CStdString strError; @@ -489,7 +599,7 @@ void CAdapterCommunication::SendMessageToAdapter(CCECAdapterMessage *msg) msg->condition.Signal(); } -void CAdapterCommunication::WriteNextCommand(void) +void CUSBCECAdapterCommunication::WriteNextCommand(void) { CCECAdapterMessage *msg(NULL); if (m_outBuffer.Pop(msg))