From: Lars Op den Kamp Date: Tue, 6 Dec 2011 19:29:52 +0000 (+0100) Subject: cec: fix background polling and libcec exit X-Git-Tag: upstream/2.2.0~1^2~44^2~29 X-Git-Url: https://git.piment-noir.org/?p=deb_libcec.git;a=commitdiff_plain;h=5f3167157997a0d64fd8a44ad04babf43327eec8 cec: fix background polling and libcec exit --- diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index 7f4f366..84b9baf 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -57,7 +57,8 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, cec m_bMonitor(false), m_busScan(NULL), m_iStandardLineTimeout(3), - m_iRetryLineTimeout(3) + m_iRetryLineTimeout(3), + m_iLastTransmission(0) { m_communication = new CAdapterCommunication(this); m_logicalAddresses.Clear(); @@ -76,7 +77,8 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, con m_controller(controller), m_bMonitor(false), m_iStandardLineTimeout(3), - m_iRetryLineTimeout(3) + m_iRetryLineTimeout(3), + m_iLastTransmission(0) { m_communication = new CAdapterCommunication(this); m_logicalAddresses.Clear(); @@ -115,6 +117,9 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, const char *strDeviceName, con CCECProcessor::~CCECProcessor(void) { + m_bStarted = false; + StopThread(false); + if (m_busScan) { m_busScan->StopThread(); @@ -695,6 +700,7 @@ bool CCECProcessor::Transmit(CCECAdapterMessage *output) bool bReturn(false); CLockObject lock(&m_mutex); { + m_iLastTransmission = GetTimeMs(); m_communication->SetLineTimeout(m_iStandardLineTimeout); output->tries = 1; @@ -1292,37 +1298,42 @@ const char *CCECProcessor::ToString(const cec_vendor_id vendor) void *CCECBusScan::Process(void) { CCECBusDevice *device(NULL); - int iCount(50); + while (!IsStopped()) { - if (iCount == 0) + for (unsigned int iPtr = 0; iPtr <= 11 && !IsStopped(); iPtr++) { - for (unsigned int iPtr = 0; iPtr <= 11 && !IsStopped(); iPtr++) + device = m_processor->m_busDevices[iPtr]; + WaitUntilIdle(); + if (device && device->GetStatus(true) == CEC_DEVICE_STATUS_PRESENT) { - device = m_processor->m_busDevices[iPtr]; - if (device && device->GetStatus(true) == CEC_DEVICE_STATUS_PRESENT) - { - if (!IsStopped()) - { - device->GetVendorId(); - Sleep(5); - } - if (!IsStopped()) - { - device->GetPowerStatus(true); - Sleep(5); - } - } + WaitUntilIdle(); + if (!IsStopped()) + device->GetVendorId(); + + WaitUntilIdle(); + if (!IsStopped()) + device->GetPowerStatus(true); } } - - if (++iCount > 60) - iCount = 0; - Sleep(1000); } + return NULL; } +void CCECBusScan::WaitUntilIdle(void) +{ + if (IsStopped()) + return; + + int64_t iWaitTime = 3000 - (GetTimeMs() - m_processor->GetLastTransmission()); + while (iWaitTime > 0) + { + Sleep(iWaitTime); + iWaitTime = 3000 - (GetTimeMs() - m_processor->GetLastTransmission()); + } +} + bool CCECProcessor::StartBootloader(void) { return m_communication->StartBootloader(); diff --git a/src/lib/CECProcessor.h b/src/lib/CECProcessor.h index b725119..24dd5b1 100644 --- a/src/lib/CECProcessor.h +++ b/src/lib/CECProcessor.h @@ -72,6 +72,8 @@ namespace CEC virtual bool IsActiveDevice(cec_logical_address address); virtual bool IsActiveDeviceType(cec_device_type type); virtual uint16_t GetPhysicalAddress(void) const; + virtual uint64_t GetLastTransmission(void) const { return m_iLastTransmission; } + virtual bool IsStarted(void) const { return m_bStarted; } virtual bool SetActiveView(void); virtual bool SetActiveSource(cec_device_type type = CEC_DEVICE_TYPE_RESERVED); @@ -126,6 +128,7 @@ namespace CEC CCECBusDevice *m_busDevices[16]; CMutex m_transmitMutex; + uint64_t m_iLastTransmission; private: void ScanCECBus(void); @@ -170,6 +173,8 @@ namespace CEC virtual void *Process(void); private: + void WaitUntilIdle(void); + CCECProcessor *m_processor; }; }; diff --git a/src/lib/implementations/ANCommandHandler.cpp b/src/lib/implementations/ANCommandHandler.cpp index 3da959e..e9674ba 100644 --- a/src/lib/implementations/ANCommandHandler.cpp +++ b/src/lib/implementations/ANCommandHandler.cpp @@ -44,7 +44,7 @@ CANCommandHandler::CANCommandHandler(CCECBusDevice *busDevice) : bool CANCommandHandler::HandleVendorRemoteButtonDown(const cec_command &command) { - if (command.parameters.size > 0) + if (m_processor->IsStarted() && command.parameters.size > 0) { cec_keypress key; key.duration = CEC_BUTTON_TIMEOUT; diff --git a/src/lib/implementations/CECCommandHandler.cpp b/src/lib/implementations/CECCommandHandler.cpp index 9f8dc9d..2fe0308 100644 --- a/src/lib/implementations/CECCommandHandler.cpp +++ b/src/lib/implementations/CECCommandHandler.cpp @@ -210,7 +210,7 @@ bool CCECCommandHandler::HandleDeviceCecVersion(const cec_command &command) bool CCECCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) m_processor->TransmitAbort(command.initiator, command.opcode, CEC_ABORT_REASON_REFUSED); return true; @@ -223,7 +223,7 @@ bool CCECCommandHandler::HandleDeviceVendorId(const cec_command &command) bool CCECCommandHandler::HandleGetCecVersion(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) { CCECBusDevice *device = GetDevice(command.destination); if (device) @@ -235,7 +235,7 @@ bool CCECCommandHandler::HandleGetCecVersion(const cec_command &command) bool CCECCommandHandler::HandleGiveAudioStatus(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) { CCECBusDevice *device = GetDevice(command.destination); if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM) @@ -247,7 +247,7 @@ bool CCECCommandHandler::HandleGiveAudioStatus(const cec_command &command) bool CCECCommandHandler::HandleGiveDeckStatus(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) { CCECBusDevice *device = GetDevice(command.destination); if (device && (device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || device->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE)) @@ -259,7 +259,7 @@ bool CCECCommandHandler::HandleGiveDeckStatus(const cec_command &command) bool CCECCommandHandler::HandleGiveDevicePowerStatus(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) { CCECBusDevice *device = GetDevice(command.destination); if (device) @@ -271,7 +271,7 @@ bool CCECCommandHandler::HandleGiveDevicePowerStatus(const cec_command &command) bool CCECCommandHandler::HandleGiveDeviceVendorId(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) { CCECBusDevice *device = GetDevice(command.destination); if (device) @@ -283,7 +283,7 @@ bool CCECCommandHandler::HandleGiveDeviceVendorId(const cec_command &command) bool CCECCommandHandler::HandleGiveOSDName(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) { CCECBusDevice *device = GetDevice(command.destination); if (device) @@ -295,7 +295,7 @@ bool CCECCommandHandler::HandleGiveOSDName(const cec_command &command) bool CCECCommandHandler::HandleGivePhysicalAddress(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) { CCECBusDevice *device = GetDevice(command.destination); if (device) @@ -307,7 +307,7 @@ bool CCECCommandHandler::HandleGivePhysicalAddress(const cec_command &command) bool CCECCommandHandler::HandleGiveSystemAudioModeStatus(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) { CCECBusDevice *device = GetDevice(command.destination); if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM) @@ -325,7 +325,7 @@ bool CCECCommandHandler::HandleImageViewOn(const cec_command &command) bool CCECCommandHandler::HandleMenuRequest(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) { if (command.parameters[0] == CEC_MENU_REQUEST_TYPE_QUERY) { @@ -375,15 +375,19 @@ bool CCECCommandHandler::HandleReportPowerStatus(const cec_command &command) bool CCECCommandHandler::HandleRequestActiveSource(const cec_command &command) { - CStdString strLog; - strLog.Format(">> %i requests active source", (uint8_t) command.initiator); - m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str()); + if (m_processor->IsStarted()) + { + CStdString strLog; + strLog.Format(">> %i requests active source", (uint8_t) command.initiator); + m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str()); - vector devices; - for (int iDevicePtr = (int)GetMyDevices(devices)-1; iDevicePtr >=0; iDevicePtr--) - devices[iDevicePtr]->TransmitActiveSource(); + vector devices; + for (int iDevicePtr = (int)GetMyDevices(devices)-1; iDevicePtr >=0; iDevicePtr--) + devices[iDevicePtr]->TransmitActiveSource(); - return true; + return true; + } + return false; } bool CCECCommandHandler::HandleRoutingChange(const cec_command &command) @@ -453,7 +457,7 @@ bool CCECCommandHandler::HandleSetOSDName(const cec_command &command) bool CCECCommandHandler::HandleSetStreamPath(const cec_command &command) { - if (command.parameters.size >= 2) + if (m_processor->IsStarted() && command.parameters.size >= 2) { uint16_t iStreamAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]); CStdString strLog; @@ -475,7 +479,7 @@ bool CCECCommandHandler::HandleSetStreamPath(const cec_command &command) bool CCECCommandHandler::HandleSystemAudioModeRequest(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) { CCECBusDevice *device = GetDevice(command.destination); if (device && device->GetType() == CEC_DEVICE_TYPE_AUDIO_SYSTEM) @@ -547,7 +551,7 @@ bool CCECCommandHandler::HandleTextViewOn(const cec_command &command) bool CCECCommandHandler::HandleUserControlPressed(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination) && command.parameters.size > 0) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination) && command.parameters.size > 0) { m_processor->AddKey(); @@ -574,7 +578,7 @@ bool CCECCommandHandler::HandleUserControlPressed(const cec_command &command) bool CCECCommandHandler::HandleUserControlRelease(const cec_command &command) { - if (m_busDevice->MyLogicalAddressContains(command.destination)) + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination)) m_processor->AddKey(); return true; diff --git a/src/lib/implementations/SLCommandHandler.cpp b/src/lib/implementations/SLCommandHandler.cpp index 34f703a..7cf4399 100644 --- a/src/lib/implementations/SLCommandHandler.cpp +++ b/src/lib/implementations/SLCommandHandler.cpp @@ -51,7 +51,7 @@ CSLCommandHandler::CSLCommandHandler(CCECBusDevice *busDevice) : CCECCommandHandler(busDevice), m_bAwaitingReceiveFailed(false), m_bSLEnabled(false), - m_bSkipNextVendorId(false) + m_bVendorIdSent(false) { } @@ -60,44 +60,82 @@ bool CSLCommandHandler::HandleVendorCommand(const cec_command &command) if (command.parameters.size == 1 && command.parameters[0] == SL_COMMAND_UNKNOWN_01) { - /* enable SL */ - cec_command response; - cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND); - response.PushBack(SL_COMMAND_UNKNOWN_02); - response.PushBack(SL_COMMAND_UNKNOWN_03); - - Transmit(response); + HandleVendorCommand01(command); return true; } else if (command.parameters.size == 2 && command.parameters[0] == SL_COMMAND_CONNECT_REQUEST) { - /* enable SL */ - cec_command response; - cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND); - response.PushBack(SL_COMMAND_CONNECT_ACCEPT); - response.PushBack((uint8_t)m_busDevice->GetProcessor()->GetLogicalAddresses().primary); - Transmit(response); - - /* set deck status for the playback device */ - TransmitDeckStatus(command.initiator); + HandleVendorCommand04(command); return true; } else if (command.parameters.size == 1 && command.parameters[0] == SL_COMMAND_REQUEST_POWER_STATUS) { - if (command.destination != CECDEVICE_BROADCAST) - m_busDevice->GetProcessor()->m_busDevices[m_busDevice->GetProcessor()->GetLogicalAddresses().primary]->TransmitPowerState(command.initiator); + HandleVendorCommandA0(command); return true; } return false; } +bool CSLCommandHandler::HandleGiveDeckStatus(const cec_command &command) +{ + if (command.parameters.size == 1) + { + if (command.parameters[0] == CEC_STATUS_REQUEST_ONCE || + command.parameters[0] == CEC_STATUS_REQUEST_ON) + { + TransmitDeckStatus(command.initiator); + } + else + { + CCECCommandHandler::HandleGiveDeckStatus(command); + } + } + return true; +} + +void CSLCommandHandler::HandleVendorCommand01(const cec_command &command) +{ + cec_command response; + cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND); + response.PushBack(SL_COMMAND_UNKNOWN_02); + response.PushBack(SL_COMMAND_UNKNOWN_03); + + Transmit(response); + + /* transmit power status */ + if (command.destination != CECDEVICE_BROADCAST) + m_processor->m_busDevices[command.destination]->TransmitPowerState(command.initiator); +} + +void CSLCommandHandler::HandleVendorCommand04(const cec_command &command) +{ + cec_command response; + cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND); + response.PushBack(SL_COMMAND_CONNECT_ACCEPT); + response.PushBack((uint8_t)m_processor->GetLogicalAddresses().primary); + Transmit(response); + + TransmitDeckStatus(command.initiator); +} + +void CSLCommandHandler::HandleVendorCommandA0(const cec_command &command) +{ + if (command.destination != CECDEVICE_BROADCAST) + { + CCECBusDevice *device = m_processor->m_busDevices[m_processor->GetLogicalAddresses().primary]; + device->SetPowerStatus(CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON); + device->TransmitPowerState(command.initiator); + device->SetPowerStatus(CEC_POWER_STATUS_ON); + } +} + void CSLCommandHandler::TransmitDeckStatus(const cec_logical_address iDestination) { /* set deck status for the playback device */ - CCECBusDevice *primary = m_busDevice->GetProcessor()->m_busDevices[m_busDevice->GetProcessor()->GetLogicalAddresses().primary]; + CCECBusDevice *primary = m_processor->m_busDevices[m_processor->GetLogicalAddresses().primary]; if (primary->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE || primary->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE) { ((CCECPlaybackDevice *)primary)->SetDeckStatus(CEC_DECK_INFO_OTHER_STATUS_LG); @@ -130,7 +168,8 @@ bool CSLCommandHandler::HandleGiveDeviceVendorId(const cec_command &command) bool CSLCommandHandler::HandleCommand(const cec_command &command) { bool bHandled(false); - if (m_busDevice->MyLogicalAddressContains(command.destination) || + + if (m_processor->IsStarted() && m_busDevice->MyLogicalAddressContains(command.destination) || command.destination == CECDEVICE_BROADCAST) { switch(command.opcode) @@ -138,29 +177,12 @@ bool CSLCommandHandler::HandleCommand(const cec_command &command) case CEC_OPCODE_VENDOR_COMMAND: bHandled = HandleVendorCommand(command); break; - case CEC_OPCODE_GIVE_DECK_STATUS: - { - if (command.parameters.size == 1) - { - if (command.parameters[0] == CEC_STATUS_REQUEST_ONCE || - command.parameters[0] == CEC_STATUS_REQUEST_ON) - TransmitDeckStatus(command.initiator); - else - CCECCommandHandler::HandleCommand(command); - } - bHandled = true; - } - break; case CEC_OPCODE_FEATURE_ABORT: { - if (!m_bSkipNextVendorId) + if (!m_bVendorIdSent) { - m_bSkipNextVendorId = true; - TransmitLGVendorId(m_busDevice->GetProcessor()->GetLogicalAddresses().primary, CECDEVICE_BROADCAST); - } - else - { - m_bSkipNextVendorId = false; + m_bVendorIdSent = true; + TransmitLGVendorId(m_processor->GetLogicalAddresses().primary, CECDEVICE_BROADCAST); } m_bSLEnabled = false; } @@ -199,15 +221,15 @@ bool CSLCommandHandler::InitHandler(void) return true; m_bSLEnabled = true; - m_busDevice->GetProcessor()->SetStandardLineTimeout(3); - m_busDevice->GetProcessor()->SetRetryLineTimeout(3); + m_processor->SetStandardLineTimeout(3); + m_processor->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]; + CCECBusDevice *primary = m_processor->m_busDevices[m_processor->GetLogicalAddresses().primary]; if (m_busDevice->GetLogicalAddress() != primary->GetLogicalAddress()) primary->SetVendorId(CEC_VENDOR_LG, false); @@ -216,10 +238,6 @@ bool CSLCommandHandler::InitHandler(void) primary->TransmitVendorID(CECDEVICE_TV); primary->TransmitPhysicalAddress(); - cec_command command; - cec_command::Format(command, m_busDevice->GetProcessor()->GetLogicalAddresses().primary, CECDEVICE_TV, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); - Transmit(command); - /* LG TVs don't always reply to CEC version requests, so just set it to 1.3a */ m_busDevice->SetCecVersion(CEC_VERSION_1_3A); } @@ -232,12 +250,12 @@ bool CSLCommandHandler::InitHandler(void) if (m_busDevice->GetLogicalAddress() == CECDEVICE_TV) { - m_busDevice->GetProcessor()->SetActiveSource(m_busDevice->GetProcessor()->GetLogicalAddresses().primary); + m_processor->SetActiveSource(m_processor->GetLogicalAddresses().primary); /* LG TVs only route keypresses when the deck status is set to 0x20 */ - cec_logical_addresses addr = m_busDevice->GetProcessor()->GetLogicalAddresses(); + cec_logical_addresses addr = m_processor->GetLogicalAddresses(); for (uint8_t iPtr = 0; iPtr < 15; iPtr++) { - CCECBusDevice *device = m_busDevice->GetProcessor()->m_busDevices[iPtr]; + CCECBusDevice *device = m_processor->m_busDevices[iPtr]; if (addr[iPtr]) { @@ -254,13 +272,17 @@ bool CSLCommandHandler::InitHandler(void) return true; } - bool CSLCommandHandler::TransmitPowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination) { - cec_command command; - cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_VENDOR_COMMAND); - command.parameters.PushBack((uint8_t) (((uint16_t)SL_COMMAND_POWER_ON >> 8) & 0xFF)); - command.parameters.PushBack((uint8_t) ((uint16_t)SL_COMMAND_POWER_ON & 0xFF)); + if (iDestination != CECDEVICE_BROADCAST && + m_processor->m_busDevices[iDestination]->GetVendorId(false) == CEC_VENDOR_LG); + { + cec_command command; + cec_command::Format(command, iInitiator, iDestination, CEC_OPCODE_VENDOR_COMMAND); + command.parameters.PushBack((uint8_t) (((uint16_t)SL_COMMAND_POWER_ON >> 8) & 0xFF)); + command.parameters.PushBack((uint8_t) ((uint16_t)SL_COMMAND_POWER_ON & 0xFF)); + return Transmit(command); + } - return Transmit(command); + return CCECCommandHandler::TransmitPowerOn(iInitiator, iDestination); } diff --git a/src/lib/implementations/SLCommandHandler.h b/src/lib/implementations/SLCommandHandler.h index d020a14..b40c2ef 100644 --- a/src/lib/implementations/SLCommandHandler.h +++ b/src/lib/implementations/SLCommandHandler.h @@ -50,12 +50,17 @@ namespace CEC virtual bool TransmitPowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination); protected: + virtual void HandleVendorCommand01(const cec_command &command); + virtual void HandleVendorCommand04(const cec_command &command); + virtual void HandleVendorCommandA0(const cec_command &command); + virtual void TransmitDeckStatus(const cec_logical_address iDestination); virtual bool HandleGiveDeviceVendorId(const cec_command &command); virtual bool HandleVendorCommand(const cec_command &command); + virtual bool HandleGiveDeckStatus(const cec_command &command); bool m_bAwaitingReceiveFailed; bool m_bSLEnabled; - bool m_bSkipNextVendorId; + bool m_bVendorIdSent; }; };