X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fadapter%2FUSBCECAdapterCommunication.cpp;h=e51a861f28579ebe6d5685c883032626e05add52;hb=be54289b785d3318dd644223cacb9f281f3e2d3d;hp=2d8597205214408c5f9f8ba72aa6255dc550c3c3;hpb=f9e01dac894ab26e63aaa38a8df5cba237195b76;p=deb_libcec.git diff --git a/src/lib/adapter/USBCECAdapterCommunication.cpp b/src/lib/adapter/USBCECAdapterCommunication.cpp index 2d85972..e51a861 100644 --- a/src/lib/adapter/USBCECAdapterCommunication.cpp +++ b/src/lib/adapter/USBCECAdapterCommunication.cpp @@ -40,6 +40,24 @@ using namespace std; using namespace CEC; using namespace PLATFORM; +void *CUSBCECAdapterProcessor::Process(void) +{ + cec_command command; + while (!IsStopped()) + { + if (m_inBuffer.Pop(command)) + m_callback->OnCommandReceived(command); + Sleep(5); + } + + return NULL; +} + +void CUSBCECAdapterProcessor::AddCommand(cec_command command) +{ + m_inBuffer.Push(command); +} + CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(CCECProcessor *processor, const char *strPort, uint16_t iBaudRate /* = 38400 */) : m_port(NULL), m_processor(processor), @@ -48,7 +66,9 @@ CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(CCECProcessor *processo m_iFirmwareVersion(CEC_FW_VERSION_UNKNOWN), m_lastInitiator(CECDEVICE_UNKNOWN), m_bNextIsEscaped(false), - m_bGotStart(false) + m_bGotStart(false), + m_messageProcessor(NULL), + m_bInitialised(false) { m_port = new PLATFORM::CSerialPort(strPort, iBaudRate); } @@ -70,20 +90,26 @@ bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = 10000 */ while (iNow < iTarget && (bPinged = PingAdapter()) == false) { CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to a ping (try %d)", ++iPingTry); - Sleep(500); + CEvent::Sleep(500); iNow = GetTimeMs(); } /* 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) + while (bPinged && iNow < iTarget && (m_iFirmwareVersion = GetFirmwareVersion()) == CEC_FW_VERSION_UNKNOWN && iFwVersionTry < 3) { - CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond with a correct firmware version (try %d)", ++iFwVersionTry); - Sleep(500); + CLibCEC::AddLog(CEC_LOG_WARNING, "the adapter did not respond with a correct firmware version (try %d)", ++iFwVersionTry); + CEvent::Sleep(500); iNow = GetTimeMs(); } + if (m_iFirmwareVersion == CEC_FW_VERSION_UNKNOWN) + { + CLibCEC::AddLog(CEC_LOG_DEBUG, "defaulting to firmware version 1"); + m_iFirmwareVersion = 1; + } + if (m_iFirmwareVersion >= 2) { /* try to set controlled mode */ @@ -92,7 +118,7 @@ bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = 10000 */ while (iNow < iTarget && (bControlled = SetControlledMode(true)) == false) { CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to setting controlled mode (try %d)", ++iControlledTry); - Sleep(500); + CEvent::Sleep(500); iNow = GetTimeMs(); } bReturn = bControlled; @@ -100,10 +126,15 @@ bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = 10000 */ else bReturn = true; + { + CLockObject lock(m_mutex); + m_bInitialised = bReturn; + } + return bReturn; } -bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs /* = 10000 */) +bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32_t iTimeoutMs /* = 10000 */, bool bSkipChecks /* = false */) { uint64_t iNow = GetTimeMs(); uint64_t iTimeout = iNow + iTimeoutMs; @@ -144,29 +175,35 @@ bool CUSBCECAdapterCommunication::Open(IAdapterCommunicationCallback *cb, uint32 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) + if (!bSkipChecks) { - CLibCEC::AddLog(CEC_LOG_DEBUG, "data received, clearing it"); - Sleep(250); + //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()) + if (!bSkipChecks && !CheckAdapter()) { - if (!CheckAdapter()) + CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter failed to pass basic checks"); + return false; + } + else + { + if (CreateThread()) { - StopThread(); - CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter failed to pass basic checks"); + CLibCEC::AddLog(CEC_LOG_DEBUG, "communication thread started"); + return true; } else { - CLibCEC::AddLog(CEC_LOG_DEBUG, "communication thread started"); - return true; + CLibCEC::AddLog(CEC_LOG_ERROR, "could not create a communication thread"); } } - CLibCEC::AddLog(CEC_LOG_ERROR, "could not create a communication thread"); return false; } @@ -178,19 +215,23 @@ void CUSBCECAdapterCommunication::Close(void) void *CUSBCECAdapterCommunication::Process(void) { + m_messageProcessor = new CUSBCECAdapterProcessor(m_callback); + m_messageProcessor->CreateThread(); + cec_command command; + command.Clear(); bool bCommandReceived(false); while (!IsStopped()) { { CLockObject lock(m_mutex); ReadFromDevice(50); - bCommandReceived = m_callback && Read(command, 0); + bCommandReceived = m_callback && Read(command, 0) && m_bInitialised; } /* push the next command to the callback method if there is one */ if (!IsStopped() && bCommandReceived) - m_callback->OnCommandReceived(command); + m_messageProcessor->AddCommand(command); if (!IsStopped()) { @@ -199,6 +240,10 @@ void *CUSBCECAdapterCommunication::Process(void) } } + /* stop the message processor */ + m_messageProcessor->StopThread(); + delete m_messageProcessor; + /* notify all threads that are waiting on messages to be sent */ CCECAdapterMessage *msg(NULL); while (m_outBuffer.Pop(msg)) @@ -293,7 +338,7 @@ bool CUSBCECAdapterCommunication::Read(CCECAdapterMessage &msg, uint32_t iTimeou if (iTimeout == 0 || !m_rcvCondition.Wait(m_mutex, m_bHasData, iTimeout)) return false; m_inBuffer.Pop(buf); - m_bHasData = m_inBuffer.Size() > 0; + m_bHasData = !m_inBuffer.IsEmpty(); } if (buf) @@ -337,11 +382,9 @@ bool CUSBCECAdapterCommunication::StartBootloader(void) bool CUSBCECAdapterCommunication::PingAdapter(void) { - bool bReturn(false); - if (!IsRunning()) - return bReturn; - + CLockObject lock(m_mutex); CLibCEC::AddLog(CEC_LOG_DEBUG, "sending ping"); + CCECAdapterMessage *output = new CCECAdapterMessage; output->PushBack(MSGSTART); @@ -349,11 +392,16 @@ bool CUSBCECAdapterCommunication::PingAdapter(void) output->PushBack(MSGEND); output->isTransmission = false; - if ((bReturn = Write(output)) == false) - CLibCEC::AddLog(CEC_LOG_ERROR, "could not ping the adapter"); + SendMessageToAdapter(output); + bool bWriteOk = output->state == ADAPTER_MESSAGE_STATE_SENT_ACKED; delete output; + if (!bWriteOk) + { + CLibCEC::AddLog(CEC_LOG_ERROR, "could not ping the adapter"); + return false; + } - return bReturn; + return true; } bool CUSBCECAdapterCommunication::ParseMessage(const CCECAdapterMessage &msg) @@ -364,6 +412,7 @@ bool CUSBCECAdapterCommunication::ParseMessage(const CCECAdapterMessage &msg) if (msg.IsEmpty()) return bEom; + CLockObject adapterLock(m_mutex); switch(msg.Message()) { case MSGCODE_FRAME_START: @@ -397,7 +446,6 @@ bool CUSBCECAdapterCommunication::ParseMessage(const CCECAdapterMessage &msg) m_currentframe.PushBack(msg[1]); m_currentframe.eom = msg.IsEOM(); } - bEom = msg.IsEOM(); } break; default: @@ -405,14 +453,12 @@ bool CUSBCECAdapterCommunication::ParseMessage(const CCECAdapterMessage &msg) } CLibCEC::AddLog(bIsError ? CEC_LOG_WARNING : CEC_LOG_DEBUG, msg.ToString()); - return bEom; + return msg.IsEOM(); } uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void) { uint16_t iReturn(m_iFirmwareVersion); - if (!IsRunning()) - return iReturn; if (iReturn == CEC_FW_VERSION_UNKNOWN) { @@ -513,7 +559,7 @@ bool CUSBCECAdapterCommunication::SetAckMaskInternal(uint16_t iMask, bool bWrite bool CUSBCECAdapterCommunication::SetControlledMode(bool controlled) { - bool bReturn(false); + CLockObject lock(m_mutex); CLibCEC::AddLog(CEC_LOG_DEBUG, "turning controlled mode %s", controlled ? "on" : "off"); CCECAdapterMessage *output = new CCECAdapterMessage; @@ -524,11 +570,16 @@ bool CUSBCECAdapterCommunication::SetControlledMode(bool controlled) output->PushBack(MSGEND); output->isTransmission = false; - if ((bReturn = Write(output)) == false) - CLibCEC::AddLog(CEC_LOG_ERROR, "could not set controlled mode"); + SendMessageToAdapter(output); + bool bWriteOk = output->state == ADAPTER_MESSAGE_STATE_SENT; delete output; + if (!bWriteOk) + { + CLibCEC::AddLog(CEC_LOG_ERROR, "could not set controlled mode"); + return false; + } - return bReturn; + return true; } bool CUSBCECAdapterCommunication::IsOpen(void) @@ -582,11 +633,11 @@ bool CUSBCECAdapterCommunication::WaitForAck(CCECAdapterMessage &message) switch(msg.Message()) { case MSGCODE_COMMAND_ACCEPTED: - CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString()); if (iPacketsLeft > 0) iPacketsLeft--; if (!message.isTransmission && iPacketsLeft == 0) bTransmitSucceeded = true; + CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - waiting for %d more", msg.ToString().c_str(), iPacketsLeft); break; case MSGCODE_TRANSMIT_SUCCEEDED: CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString()); @@ -636,7 +687,7 @@ void CUSBCECAdapterCommunication::AddData(uint8_t *data, size_t iLen) m_bGotStart = false; m_bNextIsEscaped = false; m_bHasData = true; - m_rcvCondition.Signal(); + m_rcvCondition.Broadcast(); } else if (m_bNextIsEscaped) {