bool CAdapterCommunication::Write(CCECAdapterMessage *data)
{
- data->state = ADAPTER_MESSAGE_STATE_WAITING;
+ bool bReturn(false);
+
+ CLockObject lock(data->mutex);
+ data->state = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT;
m_outBuffer.Push(data);
- return true;
+ data->condition.Wait(data->mutex);
+
+ if (data->state != ADAPTER_MESSAGE_STATE_SENT)
+ {
+ m_processor->AddLog(CEC_LOG_ERROR, "command was not sent");
+ }
+ if (WaitForTransmitSucceeded(data))
+ {
+ if (data->isTransmission)
+ data->state = ADAPTER_MESSAGE_STATE_SENT_ACKED;
+ bReturn = true;
+ }
+ else
+ {
+ data->state = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
+ m_processor->AddLog(CEC_LOG_DEBUG, "did not receive ack");
+ }
+
+ return bReturn;
}
bool CAdapterCommunication::Read(CCECAdapterMessage &msg, uint32_t iTimeout)
}
if (bGotFullMessage)
- msg.state = ADAPTER_MESSAGE_STATE_RECEIVED;
+ msg.state = ADAPTER_MESSAGE_STATE_INCOMING;
return bGotFullMessage;
}
output->PushBack(MSGSTART);
output->PushEscaped(MSGCODE_START_BOOTLOADER);
output->PushBack(MSGEND);
+ output->isTransmission = false;
- CLockObject lock(output->mutex);
- if (Write(output))
- output->condition.Wait(output->mutex);
- bReturn = output->state == ADAPTER_MESSAGE_STATE_SENT;
+ if ((bReturn = Write(output)) == false)
+ m_processor->AddLog(CEC_LOG_ERROR, "could not start the bootloader");
delete output;
return bReturn;
output->PushBack(MSGSTART);
output->PushEscaped(MSGCODE_PING);
output->PushBack(MSGEND);
+ output->isTransmission = false;
- CLockObject lock(output->mutex);
- if (Write(output))
- output->condition.Wait(output->mutex);
- bReturn = output->state == ADAPTER_MESSAGE_STATE_SENT;
+ if ((bReturn = Write(output)) == false)
+ m_processor->AddLog(CEC_LOG_ERROR, "could not ping the adapter");
delete output;
return bReturn;
output->PushEscaped(MSGCODE_TRANSMIT_IDLETIME);
output->PushEscaped(iTimeout);
output->PushBack(MSGEND);
+ output->isTransmission = false;
if ((bReturn = Write(output)) == false)
m_processor->AddLog(CEC_LOG_ERROR, "could not set the idletime");
return bReturn;
}
+bool CAdapterCommunication::SetAckMask(uint16_t iMask)
+{
+ bool bReturn(false);
+ CStdString strLog;
+ strLog.Format("setting ackmask to %2x", iMask);
+ m_processor->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+
+ CCECAdapterMessage *output = new CCECAdapterMessage;
+
+ output->PushBack(MSGSTART);
+ output->PushEscaped(MSGCODE_SET_ACK_MASK);
+ output->PushEscaped(iMask >> 8);
+ output->PushEscaped((uint8_t)iMask);
+ output->PushBack(MSGEND);
+ output->isTransmission = false;
+
+ if ((bReturn = Write(output)) == false)
+ m_processor->AddLog(CEC_LOG_ERROR, "could not set the ackmask");
+ delete output;
+
+ return bReturn;
+}
+
bool CAdapterCommunication::IsOpen(void)
{
return !IsStopped() && m_port->IsOpen() && IsRunning();
}
+bool CAdapterCommunication::WaitForTransmitSucceeded(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;
+
+ if (!Read(msg, message->transmit_timeout > 0 ? (int32_t)(iTargetTime - iNow) : 1000))
+ {
+ 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();
+ m_processor->AddLog(CEC_LOG_DEBUG, msg.ToString());
+ }
+ else
+ {
+ switch(msg.Message())
+ {
+ case MSGCODE_COMMAND_ACCEPTED:
+ m_processor->AddLog(CEC_LOG_DEBUG, msg.ToString());
+ if (iPacketsLeft > 0)
+ iPacketsLeft--;
+ if (!message->isTransmission && iPacketsLeft == 0)
+ bTransmitSucceeded = true;
+ break;
+ case MSGCODE_TRANSMIT_SUCCEEDED:
+ m_processor->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;
+}
+
void CAdapterCommunication::AddData(uint8_t *data, uint8_t iLen)
{
CLockObject lock(m_mutex);