X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2FCECProcessor.cpp;h=38c9b76f8e52e3592802ea4d158a31eea5ea8601;hb=9f9c8c82288f9754d8d375c2e1dc0bf44292f290;hp=12cea4f8ecc80186bf141dfd40e49dbf510a9a80;hpb=2c7804018856ae3cbfc937b7c9b4cf9b00bc0e8d;p=deb_libcec.git diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index 12cea4f..38c9b76 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -1,7 +1,7 @@ /* * 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. @@ -32,7 +32,7 @@ #include "CECProcessor.h" -#include "adapter/AdapterMessage.h" +#include "adapter/USBCECAdapterCommunication.h" #include "devices/CECBusDevice.h" #include "devices/CECAudioSystem.h" #include "devices/CECPlaybackDevice.h" @@ -41,6 +41,7 @@ #include "devices/CECTV.h" #include "implementations/CECCommandHandler.h" #include "LibCEC.h" +#include "platform/util/timeutils.h" using namespace CEC; using namespace std; @@ -51,15 +52,14 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, cec m_bInitialised(false), m_iHDMIPort(CEC_DEFAULT_HDMI_PORT), m_iBaseDevice((cec_logical_address)CEC_DEFAULT_BASE_DEVICE), - m_lastInitiator(CECDEVICE_UNKNOWN), m_strDeviceName(strDeviceName), + m_communication(NULL), m_controller(controller), m_bMonitor(false), m_iStandardLineTimeout(3), m_iRetryLineTimeout(3), m_iLastTransmission(0) { - m_communication = new CAdapterCommunication(this); m_logicalAddresses.Clear(); m_logicalAddresses.Set(iLogicalAddress); m_types.clear(); @@ -74,13 +74,13 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, con m_iBaseDevice((cec_logical_address)CEC_DEFAULT_BASE_DEVICE), m_strDeviceName(strDeviceName), m_types(types), + m_communication(NULL), m_controller(controller), m_bMonitor(false), m_iStandardLineTimeout(3), m_iRetryLineTimeout(3), m_iLastTransmission(0) { - m_communication = new CAdapterCommunication(this); m_logicalAddresses.Clear(); for (int iPtr = 0; iPtr < 16; iPtr++) { @@ -132,12 +132,15 @@ bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint { bool bReturn(false); CLockObject lock(m_mutex); - if (!m_communication) + if (m_communication) { - CLibCEC::AddLog(CEC_LOG_ERROR, "no connection handler found"); - return bReturn; + CLibCEC::AddLog(CEC_LOG_WARNING, "existing connection handler found, deleting it"); + m_communication->Close(); + delete m_communication; } + m_communication = new CUSBCECAdapterCommunication(this, strPort, iBaudRate); + /* check for an already opened connection */ if (m_communication->IsOpen()) { @@ -145,47 +148,50 @@ bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint return bReturn; } + 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 */ - if ((bReturn = m_communication->Open(strPort, iBaudRate, iTimeoutMs)) == false) - CLibCEC::AddLog(CEC_LOG_ERROR, "could not open a connection"); + while (iNow < iTarget && (bConnected = m_communication->Open(iTimeoutMs)) == false) + { + CLibCEC::AddLog(CEC_LOG_ERROR, "could not open a connection (try %d)", ++iConnectTry); + Sleep(500); + iNow = GetTimeMs(); + } /* try to ping the adapter */ - int iPingTry(0); - bool bPingOk(false); - while (!bPingOk && iPingTry++ < CEC_PING_ADAPTER_TRIES) + while (bConnected && iNow < iTarget && (bPinged = m_communication->PingAdapter()) == false) { - if ((bPingOk = m_communication->PingAdapter()) == false) - { - CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to a ping (try %d of %d)", iPingTry, CEC_PING_ADAPTER_TRIES); - Sleep(500); - } + CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond correctly to a ping (try %d)", ++iPingTry); + Sleep(500); + iNow = GetTimeMs(); } - if (bPingOk) + /* 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) { - uint16_t iFirmwareVersion(CEC_FW_VERSION_UNKNOWN); - int iFwVersionTry(0); - bool bFwVersionOk(false); - while (!bFwVersionOk && iFwVersionTry++ < CEC_FW_VERSION_TRIES) - { - if ((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 of %d)", iFwVersionTry, CEC_FW_VERSION_TRIES); - Sleep(500); - } - } + CLibCEC::AddLog(CEC_LOG_ERROR, "the adapter did not respond with a correct firmware version (try %d)", ++iFwVersionTry); + Sleep(500); + iNow = GetTimeMs(); + } - if (iFirmwareVersion == CEC_FW_VERSION_UNKNOWN) - { - bReturn = false; - } - else + if (iFirmwareVersion >= 2) + { + /* try to set controlled mode */ + while (bConnected && iNow < iTarget && (bControlled = m_communication->SetControlledMode(true)) == false) { - bReturn = true; - CLibCEC::AddLog(CEC_LOG_NOTICE, "CEC Adapter firmware version: %d", iFirmwareVersion); + 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); + return bReturn; } @@ -331,7 +337,7 @@ bool CCECProcessor::ChangeDeviceType(cec_device_type from, cec_device_type to) if (previousDevice && newDevice) { newDevice->SetDeviceStatus(CEC_DEVICE_STATUS_HANDLED_BY_LIBCEC); - previousDevice->SetDeviceStatus(CEC_DEVICE_STATUS_UNKNOWN); + previousDevice->SetDeviceStatus(CEC_DEVICE_STATUS_NOT_PRESENT); newDevice->SetCecVersion(previousDevice->GetCecVersion(false)); previousDevice->SetCecVersion(CEC_VERSION_UNKNOWN); @@ -425,19 +431,13 @@ void *CCECProcessor::Process(void) { ReplaceHandlers(); command.Clear(); - msg.Clear(); { CLockObject lock(m_mutex); if (m_commandBuffer.Pop(command)) - { bParseFrame = true; - } - else if (m_communication->IsOpen() && m_communication->Read(msg, 50)) - { - if ((bParseFrame = (ParseMessage(msg) && !IsStopped())) == true) - command = m_currentframe; - } + else if (m_communication->IsOpen() && m_communication->Read(command, 50)) + bParseFrame = true; } if (bParseFrame) @@ -450,7 +450,11 @@ void *CCECProcessor::Process(void) } if (m_communication) + { m_communication->Close(); + delete m_communication; + m_communication = NULL; + } return NULL; } @@ -481,6 +485,12 @@ bool CCECProcessor::SetActiveSource(cec_device_type type /* = CEC_DEVICE_TYPE_RE { bReturn = m_busDevices[addr]->TransmitActiveSource(); + if (bReturn) + { + m_busDevices[addr]->SetMenuState(CEC_MENU_STATE_ACTIVATED); + m_busDevices[addr]->TransmitMenuState(CECDEVICE_TV); + } + if (bReturn && (m_busDevices[addr]->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || m_busDevices[addr]->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE) && m_busDevices[addr]->GetHandler()->SendDeckStatusUpdateOnActiveSource()) @@ -857,51 +867,23 @@ bool CCECProcessor::IsActiveSource(cec_logical_address iAddress) bool CCECProcessor::Transmit(const cec_command &data) { - bool bReturn(false); - LogOutput(data); - - CCECAdapterMessage *output = new CCECAdapterMessage(data); - - /* set the number of retries */ - if (data.opcode == CEC_OPCODE_NONE) - output->maxTries = 1; - else if (data.initiator != CECDEVICE_BROADCAST) - output->maxTries = m_busDevices[data.initiator]->GetHandler()->GetTransmitRetries() + 1; - - bReturn = Transmit(output); - - /* set to "not present" on failed ack */ - if (output->state == ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED && - output->Destination() != CECDEVICE_BROADCAST) - m_busDevices[output->Destination()]->SetDeviceStatus(CEC_DEVICE_STATUS_NOT_PRESENT); - - delete output; - return bReturn; -} - -bool CCECProcessor::Transmit(CCECAdapterMessage *output) -{ - bool bReturn(false); - CLockObject lock(m_mutex); + cec_adapter_message_state retVal(ADAPTER_MESSAGE_STATE_UNKNOWN); { - if (!m_communication) - return bReturn; - + CLockObject lock(m_mutex); + LogOutput(data); m_iLastTransmission = GetTimeMs(); - m_communication->SetLineTimeout(m_iStandardLineTimeout); - output->tries = 0; - - do - { - if (output->tries > 0) - m_communication->SetLineTimeout(m_iRetryLineTimeout); - bReturn = m_communication->Write(output); - }while (!bReturn && output->transmit_timeout > 0 && output->NeedsRetry() && ++output->tries < output->maxTries); + if (!m_communication) + return false; + uint8_t iMaxTries = m_busDevices[data.initiator]->GetHandler()->GetTransmitRetries() + 1; + retVal = m_communication->Write(data, iMaxTries, m_iLineTimeout, m_iRetryLineTimeout); } - m_communication->SetLineTimeout(m_iStandardLineTimeout); + /* set to "not present" on failed ack */ + if (retVal == ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED && + data.destination != CECDEVICE_BROADCAST) + m_busDevices[data.destination]->SetDeviceStatus(CEC_DEVICE_STATUS_NOT_PRESENT); - return bReturn; + return retVal == ADAPTER_MESSAGE_STATE_SENT_ACKED; } void CCECProcessor::TransmitAbort(cec_logical_address address, cec_opcode opcode, cec_abort_reason reason /* = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE */) @@ -917,57 +899,6 @@ void CCECProcessor::TransmitAbort(cec_logical_address address, cec_opcode opcode Transmit(command); } -bool CCECProcessor::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_busDevices[m_lastInitiator]->GetHandler()->HandlePoll(m_currentframe.initiator, m_currentframe.destination); - } - } - break; - case MSGCODE_RECEIVE_FAILED: - { - if (m_lastInitiator != CECDEVICE_UNKNOWN) - bIsError = m_busDevices[m_lastInitiator]->GetHandler()->HandleReceiveFailed(); - } - 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; -} - void CCECProcessor::ParseCommand(cec_command &command) { CStdString dataStr; @@ -1432,11 +1363,9 @@ bool CCECProcessor::PingAdapter(void) void CCECProcessor::HandlePoll(cec_logical_address initiator, cec_logical_address destination) { m_busDevices[initiator]->GetHandler()->HandlePoll(initiator, destination); - m_lastInitiator = initiator; } -bool CCECProcessor::HandleReceiveFailed(void) +bool CCECProcessor::HandleReceiveFailed(cec_logical_address initiator) { - return m_lastInitiator != CECDEVICE_UNKNOWN && - !m_busDevices[m_lastInitiator]->GetHandler()->HandleReceiveFailed(); + return !m_busDevices[initiator]->GetHandler()->HandleReceiveFailed(); }