From efed01e1744208de67b6c54799a5c45e87d00406 Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Thu, 2 Feb 2012 20:20:10 +0100 Subject: [PATCH] cec: ping the adapter and request the firmware version in CUSBCECAdapterCommunication instead of CCECProcesssor. fixes failed libCEC inits on win32 --- src/lib/CECProcessor.cpp | 37 +--- .../adapter/USBCECAdapterCommunication.cpp | 159 +++++++++++++----- src/lib/adapter/USBCECAdapterCommunication.h | 1 + 3 files changed, 119 insertions(+), 78 deletions(-) diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index f1686d6..20b63bd 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -146,47 +146,18 @@ bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint uint64_t iNow = GetTimeMs(); uint64_t iTarget = iTimeoutMs > 0 ? iNow + iTimeoutMs : iNow + CEC_DEFAULT_TRANSMIT_WAIT; - unsigned iConnectTry(0), iPingTry(0), iFwVersionTry(0), iControlledTry(0); - bool bConnected(false), bPinged(false), bControlled(false); /* open a new connection */ - while (iNow < iTarget && (bConnected = m_communication->Open(this, iTimeoutMs)) == false) + unsigned iConnectTry(0); + while (iNow < iTarget && (bReturn = m_communication->Open(this, iTimeoutMs)) == false) { CLibCEC::AddLog(CEC_LOG_ERROR, "could not open a connection (try %d)", ++iConnectTry); Sleep(500); iNow = GetTimeMs(); } - /* try to ping the adapter */ - while (bConnected && iNow < iTarget && (bPinged = m_communication->PingAdapter()) == false) - { - CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to a ping (try %d)", ++iPingTry); - Sleep(500); - iNow = GetTimeMs(); - } - - /* try to read the firmware version */ - uint16_t iFirmwareVersion(CEC_FW_VERSION_UNKNOWN); - while (bPinged && iNow < iTarget && (iFirmwareVersion = m_communication->GetFirmwareVersion()) == CEC_FW_VERSION_UNKNOWN) - { - CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond with a correct firmware version (try %d)", ++iFwVersionTry); - Sleep(500); - iNow = GetTimeMs(); - } - - if (iFirmwareVersion >= 2) - { - /* try to set controlled mode */ - while (bConnected && iNow < iTarget && (bControlled = m_communication->SetControlledMode(true)) == false) - { - CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to setting controlled mode (try %d)", ++iControlledTry); - Sleep(500); - iNow = GetTimeMs(); - } - } - - if ((bReturn = iFirmwareVersion != CEC_FW_VERSION_UNKNOWN) == true) - CLibCEC::AddLog(CEC_LOG_NOTICE, "connected to the CEC adapter. firmware version = %d", iFirmwareVersion); + if (bReturn) + CLibCEC::AddLog(CEC_LOG_NOTICE, "connected to the CEC adapter. firmware version = %d", m_communication->GetFirmwareVersion()); return bReturn; } diff --git a/src/lib/adapter/USBCECAdapterCommunication.cpp b/src/lib/adapter/USBCECAdapterCommunication.cpp index a27765c..a97ded8 100644 --- a/src/lib/adapter/USBCECAdapterCommunication.cpp +++ b/src/lib/adapter/USBCECAdapterCommunication.cpp @@ -57,63 +57,115 @@ CUSBCECAdapterCommunication::~CUSBCECAdapterCommunication(void) Close(); } -bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs /* = 10000 */) +bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = 10000 */) { + bool bReturn(false); uint64_t iNow = GetTimeMs(); - uint64_t iTimeout = iNow + iTimeoutMs; - - CLockObject lock(m_mutex); + uint64_t iTarget = iTimeoutMs > 0 ? iNow + iTimeoutMs : iNow + CEC_DEFAULT_TRANSMIT_WAIT; - if (!m_port) + /* try to ping the adapter */ + bool bPinged(false); + unsigned iPingTry(0); + while (iNow < iTarget && (bPinged = PingAdapter()) == false) { - CLibCEC::AddLog(CEC_LOG_ERROR, "port is NULL"); - return false; + CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to a ping (try %d)", ++iPingTry); + Sleep(500); + iNow = GetTimeMs(); } - if (IsOpen()) + /* try to read the firmware version */ + m_iFirmwareVersion = CEC_FW_VERSION_UNKNOWN; + unsigned iFwVersionTry(0); + while (bPinged && iNow < iTarget && (m_iFirmwareVersion = GetFirmwareVersion()) == CEC_FW_VERSION_UNKNOWN) { - CLibCEC::AddLog(CEC_LOG_ERROR, "port is already open"); - return true; + CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond with a correct firmware version (try %d)", ++iFwVersionTry); + Sleep(500); + iNow = GetTimeMs(); } - m_callback = cb; - CStdString strError; - bool bConnected(false); - while (!bConnected && iNow < iTimeout) + if (m_iFirmwareVersion >= 2) { - if ((bConnected = m_port->Open(iTimeout)) == false) + /* try to set controlled mode */ + unsigned iControlledTry(0); + bool bControlled(false); + while (iNow < iTarget && (bControlled = SetControlledMode(true)) == false) { - strError.Format("error opening serial port '%s': %s", m_port->GetName().c_str(), m_port->GetError().c_str()); - Sleep(250); + CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to setting controlled mode (try %d)", ++iControlledTry); + Sleep(500); iNow = GetTimeMs(); } + bReturn = bControlled; } + else + bReturn = true; - if (!bConnected) - { - CLibCEC::AddLog(CEC_LOG_ERROR, strError); - return false; - } + return bReturn; +} - CLibCEC::AddLog(CEC_LOG_DEBUG, "connection opened, clearing any previous input and waiting for active transmissions to end before starting"); +bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs /* = 10000 */) +{ + uint64_t iNow = GetTimeMs(); + uint64_t iTimeout = iNow + iTimeoutMs; - //clear any input bytes - uint8_t buff[1024]; - while (m_port->Read(buff, 1024, 100) > 0) { - CLibCEC::AddLog(CEC_LOG_DEBUG, "data received, clearing it"); - Sleep(250); + CLockObject lock(m_mutex); + + if (!m_port) + { + CLibCEC::AddLog(CEC_LOG_ERROR, "port is NULL"); + return false; + } + + if (IsOpen()) + { + CLibCEC::AddLog(CEC_LOG_ERROR, "port is already open"); + return true; + } + + m_callback = cb; + CStdString strError; + bool bConnected(false); + while (!bConnected && iNow < iTimeout) + { + if ((bConnected = m_port->Open(iTimeout)) == false) + { + strError.Format("error opening serial port '%s': %s", m_port->GetName().c_str(), m_port->GetError().c_str()); + Sleep(250); + iNow = GetTimeMs(); + } + } + + if (!bConnected) + { + CLibCEC::AddLog(CEC_LOG_ERROR, strError); + return false; + } + + 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[1024]; + while (m_port->Read(buff, 1024, 100) > 0) + { + CLibCEC::AddLog(CEC_LOG_DEBUG, "data received, clearing it"); + Sleep(250); + } } if (CreateThread()) { - CLibCEC::AddLog(CEC_LOG_DEBUG, "communication thread started"); - return true; - } - else - { - CLibCEC::AddLog(CEC_LOG_ERROR, "could not create a communication thread"); + if (!CheckAdapter()) + { + StopThread(); + CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter failed to pass basic checks"); + } + else + { + CLibCEC::AddLog(CEC_LOG_DEBUG, "communication thread started"); + return true; + } } + CLibCEC::AddLog(CEC_LOG_ERROR, "could not create a communication thread"); return false; } @@ -128,16 +180,24 @@ void CUSBCECAdapterCommunication::Close(void) void *CUSBCECAdapterCommunication::Process(void) { cec_command command; + bool bCommandReceived(false); while (!IsStopped()) { - ReadFromDevice(50); + { + CLockObject lock(m_mutex); + ReadFromDevice(50); + bCommandReceived = m_callback && Read(command, 0); + } /* push the next command to the callback method if there is one */ - if (m_callback && Read(command, 0)) + if (!IsStopped() && bCommandReceived) m_callback->OnCommandReceived(command); - Sleep(5); - WriteNextCommand(); + if (!IsStopped()) + { + Sleep(5); + WriteNextCommand(); + } } CCECAdapterMessage *msg(NULL); @@ -187,7 +247,7 @@ bool CUSBCECAdapterCommunication::Write(CCECAdapterMessage *data) CLockObject lock(data->mutex); data->state = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT; m_outBuffer.Push(data); - data->condition.Wait(data->mutex); + data->condition.Wait(data->mutex, data->transmit_timeout); if ((data->expectControllerAck && data->state != ADAPTER_MESSAGE_STATE_SENT_ACKED) || (!data->expectControllerAck && data->state != ADAPTER_MESSAGE_STATE_SENT)) @@ -342,6 +402,7 @@ bool CUSBCECAdapterCommunication::ParseMessage(const CCECAdapterMessage &msg) uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void) { + CLockObject lock(m_mutex); uint16_t iReturn(m_iFirmwareVersion); if (!IsRunning()) return iReturn; @@ -357,24 +418,32 @@ uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void) output->isTransmission = false; output->expectControllerAck = false; - bool bWriteOk = Write(output); + SendMessageToAdapter(output); + bool bWriteOk = output->state == ADAPTER_MESSAGE_STATE_SENT; delete output; if (!bWriteOk) { CLibCEC::AddLog(CEC_LOG_ERROR, "could not request the firmware version"); + return iReturn; } - else + + Sleep(250); // TODO ReadFromDevice() isn't waiting for the timeout to pass on win32 + ReadFromDevice(CEC_DEFAULT_TRANSMIT_WAIT, 5 /* start + msgcode + 2 bytes for fw version + end */); + CCECAdapterMessage input; + if (Read(input, 0)) { - ReadFromDevice(CEC_DEFAULT_TRANSMIT_WAIT, 5 /* start + msgcode + 2 bytes for fw version + end */); - CCECAdapterMessage input; - if (!Read(input, 0) || 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()); + if (input.Message() != MSGCODE_FIRMWARE_VERSION || input.Size() != 3) + CLibCEC::AddLog(CEC_LOG_ERROR, "invalid firmware version (size = %d, message = %d)", input.Size(), input.Message()); else { m_iFirmwareVersion = (input[1] << 8 | input[2]); iReturn = m_iFirmwareVersion; } } + else + { + CLibCEC::AddLog(CEC_LOG_ERROR, "no firmware version received"); + } } return iReturn; diff --git a/src/lib/adapter/USBCECAdapterCommunication.h b/src/lib/adapter/USBCECAdapterCommunication.h index ee8593f..f4fab4b 100644 --- a/src/lib/adapter/USBCECAdapterCommunication.h +++ b/src/lib/adapter/USBCECAdapterCommunication.h @@ -69,6 +69,7 @@ namespace CEC void *Process(void); private: + bool CheckAdapter(uint32_t iTimeoutMs = 10000); bool Write(CCECAdapterMessage *data); bool Read(CCECAdapterMessage &msg, uint32_t iTimeout = 1000); bool ParseMessage(const CCECAdapterMessage &msg); -- 2.34.1