bool CCECProcessor::PowerOnDevice(const cec_logical_address initiator, cec_logical_address address) { CCECBusDevice *device = m_busDevices->At(address); return device ? device->PowerOn(initiator) : false; }
void CCECProcessor::HandlePoll(cec_logical_address initiator, cec_logical_address destination) { CCECBusDevice *device = m_busDevices->At(destination); if (device) device->HandlePollFrom(initiator); }
bool CCECProcessor::Transmit(const cec_command &data, bool bIsReply) { cec_command transmitData(data); uint8_t iMaxTries(0); bool bRetry(true); uint8_t iTries(0); // get the current timeout setting uint8_t iLineTimeout(GetStandardLineTimeout()); // reset the state of this message to 'unknown' cec_adapter_message_state adapterState = ADAPTER_MESSAGE_STATE_UNKNOWN; if (data.initiator == CECDEVICE_UNKNOWN && data.destination == CECDEVICE_UNKNOWN) return false; CLockObject lock(m_mutex); if (!m_communication) return false; if (!m_communication->SupportsSourceLogicalAddress(transmitData.initiator)) { if (transmitData.initiator == CECDEVICE_UNREGISTERED && m_communication->SupportsSourceLogicalAddress(CECDEVICE_FREEUSE)) { m_libcec->AddLog(CEC_LOG_DEBUG, "initiator '%s' is not supported by the CEC adapter. using '%s' instead", ToString(transmitData.initiator), ToString(CECDEVICE_FREEUSE)); transmitData.initiator = CECDEVICE_FREEUSE; } else { m_libcec->AddLog(CEC_LOG_DEBUG, "initiator '%s' is not supported by the CEC adapter", ToString(transmitData.initiator)); return false; } } LogOutput(transmitData); // find the initiator device CCECBusDevice *initiator = m_busDevices->At(transmitData.initiator); if (!initiator) { m_libcec->AddLog(CEC_LOG_WARNING, "invalid initiator"); return false; } // find the destination device, if it's not the broadcast address if (transmitData.destination != CECDEVICE_BROADCAST) { // check if the device is marked as handled by libCEC CCECBusDevice *destination = m_busDevices->At(transmitData.destination); if (destination && destination->IsHandledByLibCEC()) { // and reject the command if it's trying to send data to a device that is handled by libCEC m_libcec->AddLog(CEC_LOG_WARNING, "not sending data to myself!"); return false; } } // wait until we finished allocating a new LA if it got lost lock.Unlock(); while (m_bStallCommunication) Sleep(5); lock.Lock(); m_iLastTransmission = GetTimeMs(); // set the number of tries iMaxTries = initiator->GetHandler()->GetTransmitRetries() + 1; initiator->MarkHandlerReady(); // and try to send the command while (bRetry && ++iTries < iMaxTries) { if (initiator->IsUnsupportedFeature(transmitData.opcode)) return false; adapterState = !IsStopped() && m_communication && m_communication->IsOpen() ? m_communication->Write(transmitData, bRetry, iLineTimeout, bIsReply) : ADAPTER_MESSAGE_STATE_ERROR; iLineTimeout = m_iRetryLineTimeout; } return bIsReply ? adapterState == ADAPTER_MESSAGE_STATE_SENT_ACKED || adapterState == ADAPTER_MESSAGE_STATE_SENT || adapterState == ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT : adapterState == ADAPTER_MESSAGE_STATE_SENT_ACKED; }
bool CCECProcessor::IsPresentDevice(cec_logical_address address) { CCECBusDevice *device = m_busDevices->At(address); return device && device->GetStatus() == CEC_DEVICE_STATUS_PRESENT; }
bool CCECProcessor::IsActiveSource(cec_logical_address iAddress) { CCECBusDevice *device = m_busDevices->At(iAddress); return device && device->IsActiveSource(); }
bool CCECProcessor::IsHandledByLibCEC(const cec_logical_address address) const { CCECBusDevice *device = GetDevice(address); return device && device->IsHandledByLibCEC(); }
bool CCECProcessor::RegisterClient(CECClientPtr client) { if (!client) return false; libcec_configuration &configuration = *client->GetConfiguration(); if (configuration.bMonitorOnly == 1) return true; if (!CECInitialised()) { m_libcec->AddLog(CEC_LOG_ERROR, "failed to register a new CEC client: CEC processor is not initialised"); return false; } // unregister the client first if it's already been marked as registered if (client->IsRegistered()) UnregisterClient(client); // ensure that controlled mode is enabled m_communication->SetControlledMode(true); m_bMonitor = false; // source logical address for requests cec_logical_address sourceAddress(CECDEVICE_UNREGISTERED); if (!m_communication->SupportsSourceLogicalAddress(CECDEVICE_UNREGISTERED)) { if (m_communication->SupportsSourceLogicalAddress(CECDEVICE_FREEUSE)) sourceAddress = CECDEVICE_FREEUSE; else { m_libcec->AddLog(CEC_LOG_ERROR, "failed to register a new CEC client: both unregistered and free use are not supported by the device"); return false; } } // ensure that we know the vendor id of the TV CCECBusDevice *tv = GetTV(); cec_vendor_id tvVendor(tv->GetVendorId(sourceAddress)); // wait until the handler is replaced, to avoid double registrations if (tvVendor != CEC_VENDOR_UNKNOWN && CCECCommandHandler::HasSpecificHandler(tvVendor)) { while (!tv->ReplaceHandler(false)) CEvent::Sleep(5); } // get the configuration from the client m_libcec->AddLog(CEC_LOG_NOTICE, "registering new CEC client - v%s", CCECTypeUtils::VersionToString(configuration.clientVersion).c_str()); // get the current ackmask, so we can restore it if polling fails cec_logical_addresses previousMask = GetLogicalAddresses(); // mark as uninitialised client->SetInitialised(false); // find logical addresses for this client if (!AllocateLogicalAddresses(client)) { m_libcec->AddLog(CEC_LOG_ERROR, "failed to register the new CEC client - cannot allocate the requested device types"); SetLogicalAddresses(previousMask); return false; } // get the settings from the rom if (configuration.bGetSettingsFromROM == 1) { libcec_configuration config; config.Clear(); m_communication->GetConfiguration(config); CLockObject lock(m_mutex); if (!config.deviceTypes.IsEmpty()) configuration.deviceTypes = config.deviceTypes; if (CLibCEC::IsValidPhysicalAddress(config.iPhysicalAddress)) configuration.iPhysicalAddress = config.iPhysicalAddress; snprintf(configuration.strDeviceName, 13, "%s", config.strDeviceName); } // set the firmware version and build date configuration.serverVersion = LIBCEC_VERSION_CURRENT; configuration.iFirmwareVersion = m_communication->GetFirmwareVersion(); configuration.iFirmwareBuildDate = m_communication->GetFirmwareBuildDate(); configuration.adapterType = m_communication->GetAdapterType(); // mark the client as registered client->SetRegistered(true); sourceAddress = client->GetPrimaryLogicalAddress(); // initialise the client bool bReturn = client->OnRegister(); // log the new registration std::string strLog; strLog = StringUtils::Format("%s: %s", bReturn ? "CEC client registered" : "failed to register the CEC client", client->GetConnectionInfo().c_str()); m_libcec->AddLog(bReturn ? CEC_LOG_NOTICE : CEC_LOG_ERROR, strLog.c_str()); // display a warning if the firmware can be upgraded if (bReturn && !IsRunningLatestFirmware()) { const char *strUpgradeMessage = "The firmware of this adapter can be upgraded. Please visit http://blog.pulse-eight.com/ for more information."; m_libcec->AddLog(CEC_LOG_WARNING, strUpgradeMessage); libcec_parameter param; param.paramData = (void*)strUpgradeMessage; param.paramType = CEC_PARAMETER_TYPE_STRING; client->Alert(CEC_ALERT_SERVICE_DEVICE, param); } // ensure that the command handler for the TV is initialised if (bReturn) { CCECCommandHandler *handler = GetTV()->GetHandler(); if (handler) handler->InitHandler(); GetTV()->MarkHandlerReady(); } // report our OSD name to the TV, since some TVs don't request it client->GetPrimaryDevice()->TransmitOSDName(CECDEVICE_TV, false); // request the power status of the TV tv->RequestPowerStatus(sourceAddress, true, true); return bReturn; }
bool CCECProcessor::HandleReceiveFailed(cec_logical_address initiator) { CCECBusDevice *device = m_busDevices->At(initiator); return !device || !device->HandleReceiveFailed(); }
bool CCECBusDevice::ReplaceHandler(bool bActivateSource /* = true */) { if (m_iLogicalAddress == CECDEVICE_BROADCAST) return false; bool bInitHandler(false); { CLockObject lock(m_mutex); CLockObject handlerLock(m_handlerMutex); if (m_iHandlerUseCount > 0) return false; MarkBusy(); if (m_vendor != m_handler->GetVendorId()) { if (CCECCommandHandler::HasSpecificHandler(m_vendor)) { LIB_CEC->AddLog(CEC_LOG_DEBUG, "replacing the command handler for device '%s' (%x)", GetLogicalAddressName(), GetLogicalAddress()); int32_t iTransmitTimeout = m_handler->m_iTransmitTimeout; int32_t iTransmitWait = m_handler->m_iTransmitWait; int8_t iTransmitRetries = m_handler->m_iTransmitRetries; int64_t iActiveSourcePending = m_handler->m_iActiveSourcePending; SAFE_DELETE(m_handler); switch (m_vendor) { case CEC_VENDOR_SAMSUNG: m_handler = new CANCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; case CEC_VENDOR_LG: m_handler = new CSLCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; case CEC_VENDOR_PANASONIC: m_handler = new CVLCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; case CEC_VENDOR_PHILIPS: m_handler = new CPHCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; case CEC_VENDOR_TOSHIBA: case CEC_VENDOR_TOSHIBA2: m_handler = new CRLCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; case CEC_VENDOR_ONKYO: m_handler = new CRHCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; case CEC_VENDOR_SHARP: case CEC_VENDOR_SHARP2: m_handler = new CAQCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; default: m_handler = new CCECCommandHandler(this, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending); break; } /** override the vendor ID set in the handler, as a single vendor may have multiple IDs */ m_handler->SetVendorId(m_vendor); bInitHandler = true; } } } if (bInitHandler) { CCECBusDevice *primary = GetProcessor()->GetPrimaryDevice(); if (primary->GetLogicalAddress() != CECDEVICE_UNREGISTERED) { m_handler->InitHandler(); if (bActivateSource && IsHandledByLibCEC() && IsActiveSource()) m_handler->ActivateSource(); } } MarkReady(); return true; }