From ae693aaa8545b853946bf490dd0444c5862bafb9 Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Tue, 6 Dec 2011 00:26:01 +0100 Subject: [PATCH] cec: some more cleanups. increase the number of retries for LG devices because they're spamming the bus --- include/cectypes.h | 10 ++- src/lib/AdapterCommunication.cpp | 4 +- src/lib/AdapterCommunication.h | 3 +- src/lib/CECProcessor.cpp | 3 +- src/lib/implementations/CECCommandHandler.cpp | 67 +++++++++++-------- src/lib/implementations/CECCommandHandler.h | 4 +- src/lib/implementations/SLCommandHandler.cpp | 8 ++- 7 files changed, 58 insertions(+), 41 deletions(-) diff --git a/include/cectypes.h b/include/cectypes.h index e6cd0b4..7bce7e2 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -65,6 +65,10 @@ namespace CEC { #define ESCOFFSET 3 #define CEC_BUTTON_TIMEOUT 500 +#define CEC_DEFAULT_TRANSMIT_TIMEOUT 1000 +#define CEC_DEFAULT_TRANSMIT_WAIT 2000 +#define CEC_DEFAULT_TRANSMIT_RETRIES 1 + #define CEC_MIN_LIB_VERSION 1 #define CEC_LIB_VERSION_MAJOR 1 #define CEC_LIB_VERSION_MINOR 2 @@ -713,7 +717,7 @@ typedef struct cec_command return *this; } - static void Format(cec_command &command, cec_logical_address initiator, cec_logical_address destination, cec_opcode opcode, int32_t timeout = 1000) + static void Format(cec_command &command, cec_logical_address initiator, cec_logical_address destination, cec_opcode opcode, int32_t timeout = CEC_DEFAULT_TRANSMIT_TIMEOUT) { command.Clear(); command.initiator = initiator; @@ -750,8 +754,8 @@ typedef struct cec_command eom = 0; opcode_set = 0; opcode = CEC_OPCODE_FEATURE_ABORT; - transmit_timeout = 0; - retries = 4; + transmit_timeout = CEC_DEFAULT_TRANSMIT_TIMEOUT; + retries = CEC_DEFAULT_TRANSMIT_RETRIES; parameters.Clear(); }; #endif diff --git a/src/lib/AdapterCommunication.cpp b/src/lib/AdapterCommunication.cpp index df803f5..5541bf5 100644 --- a/src/lib/AdapterCommunication.cpp +++ b/src/lib/AdapterCommunication.cpp @@ -227,9 +227,9 @@ bool CCECAdapterMessage::is_error(void) const code == MSGCODE_LOW_ERROR || code == MSGCODE_RECEIVE_FAILED || code == MSGCODE_COMMAND_REJECTED || - code == MSGCODE_TRANSMIT_LINE_TIMEOUT || + code == MSGCODE_TRANSMIT_LINE_TIMEOUT || code == MSGCODE_TRANSMIT_FAILED_LINE || - code == MSGCODE_TRANSMIT_FAILED_ACK || + code == MSGCODE_TRANSMIT_FAILED_ACK || code == MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA || code == MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE); } diff --git a/src/lib/AdapterCommunication.h b/src/lib/AdapterCommunication.h index 1e2e1c0..1b81526 100644 --- a/src/lib/AdapterCommunication.h +++ b/src/lib/AdapterCommunication.h @@ -62,7 +62,7 @@ namespace CEC uint8_t operator[](uint8_t pos) const { return packet[pos]; } uint8_t at(uint8_t pos) const { return packet[pos]; } uint8_t size(void) const { return packet.size; } - void clear(void) { state = ADAPTER_MESSAGE_STATE_UNKNOWN; transmit_timeout = 0; packet.Clear(); maxTries = 5; tries = 0; reply = MSGCODE_NOTHING; } + void clear(void) { state = ADAPTER_MESSAGE_STATE_UNKNOWN; transmit_timeout = 0; packet.Clear(); maxTries = CEC_DEFAULT_TRANSMIT_RETRIES + 1; tries = 0; reply = MSGCODE_NOTHING; } void shift(uint8_t iShiftBy) { packet.Shift(iShiftBy); } void push_back(uint8_t add) { packet.PushBack(add); } cec_adapter_messagecode message(void) const { return packet.size >= 1 ? (cec_adapter_messagecode) (packet.At(0) & ~(MSGCODE_FRAME_EOM | MSGCODE_FRAME_ACK)) : MSGCODE_NOTHING; } @@ -75,7 +75,6 @@ namespace CEC bool needs_retry(void) const { return reply == MSGCODE_NOTHING || reply == MSGCODE_RECEIVE_FAILED || reply == MSGCODE_TIMEOUT_ERROR || - reply == MSGCODE_TRANSMIT_FAILED_ACK || reply == MSGCODE_TRANSMIT_FAILED_LINE || reply == MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA || reply == MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE || diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index af45f9a..6aad7e9 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -691,6 +691,7 @@ bool CCECProcessor::Transmit(CCECAdapterMessage *output) CLockObject lock(&m_mutex); { m_communication->SetLineTimeout(m_iStandardLineTimeout); + output->tries = 1; do { @@ -717,7 +718,7 @@ bool CCECProcessor::Transmit(CCECAdapterMessage *output) } else bReturn = true; - }while (output->transmit_timeout > 0 && output->needs_retry() && ++output->tries <= output->maxTries); + }while (output->transmit_timeout > 0 && output->needs_retry() && ++output->tries < output->maxTries); } m_communication->SetLineTimeout(m_iStandardLineTimeout); diff --git a/src/lib/implementations/CECCommandHandler.cpp b/src/lib/implementations/CECCommandHandler.cpp index 47a0b0e..9742739 100644 --- a/src/lib/implementations/CECCommandHandler.cpp +++ b/src/lib/implementations/CECCommandHandler.cpp @@ -42,7 +42,9 @@ using namespace std; CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice) : m_busDevice(busDevice), m_processor(m_busDevice->GetProcessor()), - m_iTransmitTimeout(1000) + m_iTransmitTimeout(CEC_DEFAULT_TRANSMIT_TIMEOUT), + m_iTransmitWait(CEC_DEFAULT_TRANSMIT_WAIT), + m_iTransmitRetries(CEC_DEFAULT_TRANSMIT_RETRIES) { } @@ -673,7 +675,7 @@ bool CCECCommandHandler::HandleReceiveFailed(void) bool CCECCommandHandler::TransmitPowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_IMAGE_VIEW_ON, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_IMAGE_VIEW_ON); return Transmit(command); } @@ -681,7 +683,7 @@ bool CCECCommandHandler::TransmitPowerOn(const cec_logical_address iInitiator, c bool CCECCommandHandler::TransmitStandby(const cec_logical_address iInitiator, const cec_logical_address iDestination) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_STANDBY, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_STANDBY); return Transmit(command); } @@ -689,7 +691,7 @@ bool CCECCommandHandler::TransmitStandby(const cec_logical_address iInitiator, c bool CCECCommandHandler::TransmitRequestCecVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GET_CEC_VERSION, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GET_CEC_VERSION); return Transmit(command); } @@ -697,7 +699,7 @@ bool CCECCommandHandler::TransmitRequestCecVersion(const cec_logical_address iIn bool CCECCommandHandler::TransmitRequestMenuLanguage(const cec_logical_address iInitiator, const cec_logical_address iDestination) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GET_MENU_LANGUAGE, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GET_MENU_LANGUAGE); return Transmit(command); } @@ -705,7 +707,7 @@ bool CCECCommandHandler::TransmitRequestMenuLanguage(const cec_logical_address i bool CCECCommandHandler::TransmitRequestOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_OSD_NAME, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_OSD_NAME); return Transmit(command); } @@ -713,7 +715,7 @@ bool CCECCommandHandler::TransmitRequestOSDName(const cec_logical_address iIniti bool CCECCommandHandler::TransmitRequestPhysicalAddress(const cec_logical_address iInitiator, const cec_logical_address iDestination) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_PHYSICAL_ADDRESS, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_PHYSICAL_ADDRESS); return Transmit(command); } @@ -721,7 +723,7 @@ bool CCECCommandHandler::TransmitRequestPhysicalAddress(const cec_logical_addres bool CCECCommandHandler::TransmitRequestPowerStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_DEVICE_POWER_STATUS, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_DEVICE_POWER_STATUS); return Transmit(command); } @@ -729,7 +731,7 @@ bool CCECCommandHandler::TransmitRequestPowerStatus(const cec_logical_address iI bool CCECCommandHandler::TransmitRequestVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); return Transmit(command); } @@ -737,7 +739,7 @@ bool CCECCommandHandler::TransmitRequestVendorId(const cec_logical_address iInit bool CCECCommandHandler::TransmitActiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress) { cec_command command; - cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE); command.parameters.PushBack((uint8_t) ((iPhysicalAddress >> 8) & 0xFF)); command.parameters.PushBack((uint8_t) (iPhysicalAddress & 0xFF)); @@ -747,7 +749,7 @@ bool CCECCommandHandler::TransmitActiveSource(const cec_logical_address iInitiat bool CCECCommandHandler::TransmitCECVersion(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_version cecVersion) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_CEC_VERSION, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_CEC_VERSION); command.parameters.PushBack((uint8_t)cecVersion); return Transmit(command); @@ -756,7 +758,7 @@ bool CCECCommandHandler::TransmitCECVersion(const cec_logical_address iInitiator bool CCECCommandHandler::TransmitInactiveSource(const cec_logical_address iInitiator, uint16_t iPhysicalAddress) { cec_command command; - cec_command::Format(command, iInitiator, CECDEVICE_TV, CEC_OPCODE_INACTIVE_SOURCE, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, CECDEVICE_TV, CEC_OPCODE_INACTIVE_SOURCE); command.parameters.PushBack((iPhysicalAddress >> 8) & 0xFF); command.parameters.PushBack(iPhysicalAddress & 0xFF); @@ -766,7 +768,7 @@ bool CCECCommandHandler::TransmitInactiveSource(const cec_logical_address iIniti bool CCECCommandHandler::TransmitMenuState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_menu_state menuState) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_MENU_STATUS, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_MENU_STATUS); command.parameters.PushBack((uint8_t)menuState); return Transmit(command); @@ -775,7 +777,7 @@ bool CCECCommandHandler::TransmitMenuState(const cec_logical_address iInitiator, bool CCECCommandHandler::TransmitOSDName(const cec_logical_address iInitiator, const cec_logical_address iDestination, CStdString strDeviceName) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_OSD_NAME, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_OSD_NAME); for (unsigned int iPtr = 0; iPtr < strDeviceName.length(); iPtr++) command.parameters.PushBack(strDeviceName.at(iPtr)); @@ -785,7 +787,7 @@ bool CCECCommandHandler::TransmitOSDName(const cec_logical_address iInitiator, c bool CCECCommandHandler::TransmitOSDString(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_display_control duration, const char *strMessage) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_OSD_STRING, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_OSD_STRING); command.parameters.PushBack((uint8_t)duration); unsigned int iLen = strlen(strMessage); @@ -800,7 +802,7 @@ bool CCECCommandHandler::TransmitOSDString(const cec_logical_address iInitiator, bool CCECCommandHandler::TransmitPhysicalAddress(const cec_logical_address iInitiator, uint16_t iPhysicalAddress, cec_device_type type) { cec_command command; - cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_REPORT_PHYSICAL_ADDRESS, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_REPORT_PHYSICAL_ADDRESS); command.parameters.PushBack((uint8_t) ((iPhysicalAddress >> 8) & 0xFF)); command.parameters.PushBack((uint8_t) (iPhysicalAddress & 0xFF)); command.parameters.PushBack((uint8_t) (type)); @@ -811,16 +813,15 @@ bool CCECCommandHandler::TransmitPhysicalAddress(const cec_logical_address iInit bool CCECCommandHandler::TransmitPoll(const cec_logical_address iInitiator, const cec_logical_address iDestination) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_NONE, m_iTransmitTimeout); - command.retries = 0; + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_NONE); - return Transmit(command); + return Transmit(command, false); } bool CCECCommandHandler::TransmitPowerState(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_power_status state) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_REPORT_POWER_STATUS, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_REPORT_POWER_STATUS); command.parameters.PushBack((uint8_t) state); return Transmit(command); @@ -829,7 +830,7 @@ bool CCECCommandHandler::TransmitPowerState(const cec_logical_address iInitiator bool CCECCommandHandler::TransmitVendorID(const cec_logical_address iInitiator, uint64_t iVendorId) { cec_command command; - cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_DEVICE_VENDOR_ID, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, CECDEVICE_BROADCAST, CEC_OPCODE_DEVICE_VENDOR_ID); command.parameters.PushBack((uint8_t) (((uint64_t)iVendorId >> 16) & 0xFF)); command.parameters.PushBack((uint8_t) (((uint64_t)iVendorId >> 8) & 0xFF)); @@ -841,7 +842,7 @@ bool CCECCommandHandler::TransmitVendorID(const cec_logical_address iInitiator, bool CCECCommandHandler::TransmitAudioStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, uint8_t state) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_REPORT_AUDIO_STATUS, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_REPORT_AUDIO_STATUS); command.parameters.PushBack(state); return Transmit(command); @@ -850,7 +851,7 @@ bool CCECCommandHandler::TransmitAudioStatus(const cec_logical_address iInitiato bool CCECCommandHandler::TransmitSetSystemAudioMode(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_SYSTEM_AUDIO_MODE, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SET_SYSTEM_AUDIO_MODE); command.parameters.PushBack((uint8_t)state); return Transmit(command); @@ -859,7 +860,7 @@ bool CCECCommandHandler::TransmitSetSystemAudioMode(const cec_logical_address iI bool CCECCommandHandler::TransmitSystemAudioModeStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_system_audio_status state) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS); command.parameters.PushBack((uint8_t)state); return Transmit(command); @@ -868,7 +869,7 @@ bool CCECCommandHandler::TransmitSystemAudioModeStatus(const cec_logical_address bool CCECCommandHandler::TransmitDeckStatus(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_deck_info state) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_DECK_STATUS, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_DECK_STATUS); command.PushBack((uint8_t)state); return Transmit(command); @@ -877,7 +878,7 @@ bool CCECCommandHandler::TransmitDeckStatus(const cec_logical_address iInitiator bool CCECCommandHandler::TransmitKeypress(const cec_logical_address iInitiator, const cec_logical_address iDestination, cec_user_control_code key) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_USER_CONTROL_PRESSED, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_USER_CONTROL_PRESSED); command.parameters.PushBack((uint8_t)key); return Transmit(command); @@ -886,16 +887,24 @@ bool CCECCommandHandler::TransmitKeypress(const cec_logical_address iInitiator, bool CCECCommandHandler::TransmitKeyRelease(const cec_logical_address iInitiator, const cec_logical_address iDestination) { cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_USER_CONTROL_RELEASE, m_iTransmitTimeout); + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_USER_CONTROL_RELEASE); return Transmit(command); } -bool CCECCommandHandler::Transmit(cec_command &command) +bool CCECCommandHandler::Transmit(cec_command &command, bool bExpectResponse /* = true */) { + command.transmit_timeout = m_iTransmitTimeout; + if (command.retries == CEC_DEFAULT_TRANSMIT_RETRIES) + command.retries = m_iTransmitRetries; + CLockObject writeLock(&m_processor->m_transmitMutex); if (m_processor->Transmit(command)) - return m_condition.Wait(&m_processor->m_transmitMutex, m_iTransmitTimeout); + { + if (bExpectResponse) + return m_condition.Wait(&m_processor->m_transmitMutex, m_iTransmitWait); + return true; + } return false; } diff --git a/src/lib/implementations/CECCommandHandler.h b/src/lib/implementations/CECCommandHandler.h index 15ab552..60133c7 100644 --- a/src/lib/implementations/CECCommandHandler.h +++ b/src/lib/implementations/CECCommandHandler.h @@ -121,11 +121,13 @@ namespace CEC virtual bool SetVendorId(const cec_command &command); virtual void SetPhysicalAddress(cec_logical_address iAddress, uint16_t iNewAddress); - virtual bool Transmit(cec_command &command); + virtual bool Transmit(cec_command &command, bool bExpectResponse = true); CCECBusDevice *m_busDevice; CCECProcessor *m_processor; int32_t m_iTransmitTimeout; + int32_t m_iTransmitWait; + int8_t m_iTransmitRetries; CCondition m_condition; }; }; diff --git a/src/lib/implementations/SLCommandHandler.cpp b/src/lib/implementations/SLCommandHandler.cpp index bf3ee43..4a9d19e 100644 --- a/src/lib/implementations/SLCommandHandler.cpp +++ b/src/lib/implementations/SLCommandHandler.cpp @@ -201,6 +201,11 @@ bool CSLCommandHandler::InitHandler(void) m_busDevice->GetProcessor()->SetStandardLineTimeout(3); m_busDevice->GetProcessor()->SetRetryLineTimeout(3); + /* increase the number of retries because the tv is keeping the bus busy at times */ + m_iTransmitWait = 2000; + m_iTransmitRetries = 4; + m_iTransmitTimeout = 500; + CCECBusDevice *primary = m_busDevice->GetProcessor()->m_busDevices[m_busDevice->GetProcessor()->GetLogicalAddresses().primary]; if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress()) primary->SetVendorId(CEC_VENDOR_LG, false); @@ -224,9 +229,6 @@ bool CSLCommandHandler::InitHandler(void) snprintf(lang.language, 4, "eng"); m_busDevice->SetMenuLanguage(lang); - /* increase the transmit timeout because the tv is keeping the bus busy at times */ - m_iTransmitTimeout = 5000; - if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV) { /* LG TVs only route keypresses when the deck status is set to 0x20 */ -- 2.34.1