+bool CAdapterCommunication::WaitForAck(CCECAdapterMessage &message)
+{
+ bool bError(false);
+ bool bTransmitSucceeded(false);
+ uint8_t iPacketsLeft(message.Size() / 4);
+
+ int64_t iNow = GetTimeMs();
+ int64_t iTargetTime = iNow + message.transmit_timeout;
+
+ while (!bTransmitSucceeded && !bError && (message.transmit_timeout == 0 || iNow < iTargetTime))
+ {
+ CCECAdapterMessage msg;
+ int32_t iWait = (int32_t)(iTargetTime - iNow);
+ if (iWait <= 5 || message.transmit_timeout <= 5)
+ iWait = CEC_DEFAULT_TRANSMIT_WAIT;
+
+ if (!Read(msg, iWait))
+ {
+ iNow = GetTimeMs();
+ continue;
+ }
+
+ if (msg.Message() == MSGCODE_FRAME_START && msg.IsACK())
+ {
+ m_processor->HandlePoll(msg.Initiator(), msg.Destination());
+ iNow = GetTimeMs();
+ continue;
+ }
+
+ if (msg.Message() == MSGCODE_RECEIVE_FAILED &&
+ m_processor->HandleReceiveFailed())
+ {
+ iNow = GetTimeMs();
+ continue;
+ }
+
+ bError = msg.IsError();
+ if (bError)
+ {
+ message.reply = msg.Message();
+ CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
+ }
+ else
+ {
+ switch(msg.Message())
+ {
+ case MSGCODE_COMMAND_ACCEPTED:
+ CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
+ if (iPacketsLeft > 0)
+ iPacketsLeft--;
+ if (!message.isTransmission && iPacketsLeft == 0)
+ bTransmitSucceeded = true;
+ break;
+ case MSGCODE_TRANSMIT_SUCCEEDED:
+ CLibCEC::AddLog(CEC_LOG_DEBUG, msg.ToString());
+ bTransmitSucceeded = (iPacketsLeft == 0);
+ bError = !bTransmitSucceeded;
+ message.reply = MSGCODE_TRANSMIT_SUCCEEDED;
+ break;
+ default:
+ // ignore other data while waiting
+ break;
+ }
+
+ iNow = GetTimeMs();
+ }
+ }
+
+ return bTransmitSucceeded && !bError;
+}
+