+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 (!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
+ while (m_bStallCommunication) Sleep(5);
+
+ {
+ CLockObject lock(m_mutex);
+ 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;