Ejemplo n.º 1
0
cec_adapter_message_state CRPiCECAdapterMessageQueue::Write(const cec_command &command, bool &bRetry, uint32_t iLineTimeout, bool bIsReply, VC_CEC_ERROR_T &vcReply)
{
  // handle POLL (msg like '11') in a special way - the way it was
  // originally designed by BCM, expected to happen and documented
  // in API docs (/opt/vc/includes)
  // due to often (more than 20% test cases - CEC bus with 8 devices)
  // irregularities on returned status, repeat until we get SAME
  // result twice in a row
  if (!command.opcode_set && command.destination == command.initiator)
  {
    int iReturnPrev = -1;
    int iReturn = 0;

    while((iReturn = vc_cec_poll_address((CEC_AllDevices_T)command.destination)) != iReturnPrev)
      iReturnPrev = iReturn;
    if (iReturn == 0)
      return ADAPTER_MESSAGE_STATE_SENT_ACKED;
    else if (iReturn > 0)
      return ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
    else
      return ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT;
  }

  CRPiCECAdapterMessageQueueEntry *entry = new CRPiCECAdapterMessageQueueEntry(this, command);
  uint64_t iEntryId(0);
  /* add to the wait for ack queue */
  {
    CLockObject lock(m_mutex);
    iEntryId = m_iNextMessage++;
    m_messages.insert(std::make_pair(iEntryId, entry));
  }

#if defined(RPI_USE_SEND_MESSAGE2)
  VC_CEC_MESSAGE_T message;
  message.initiator = (CEC_AllDevices_T)command.initiator;
  message.follower = (CEC_AllDevices_T)command.destination;
  message.length = 1;

  if (command.opcode_set)
  {
    message.length += 1;
    message.payload[0] = command.opcode;

    message.length += command.parameters.size;
    for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
      message.payload[iPtr + 1] = command.parameters.At(iPtr);
  }

#ifdef CEC_DEBUGGING
  std::string strDump;
  strDump = StringUtils::Format("len = %d, payload = %X%X", message.length, (int)message.initiator, (int)message.follower);
  for (uint8_t iPtr = 0; iPtr < message.length - 1; iPtr++)
    strDump += StringUtils::Format(":%02X", message.payload[iPtr]);
  LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: %s", strDump.c_str());
#endif

  int iReturn = vc_cec_send_message2(&message);
#else
  uint8_t payload[32];
  uint32_t iLength(0);

  if (command.opcode_set)
  {
    iLength += 1;
    payload[0] = command.opcode;

    iLength += command.parameters.size;
    for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
      payload[iPtr + 1] = command.parameters.At(iPtr);
  }

#ifdef CEC_DEBUGGING
  std:string strDump;
  strDump = StringUtils::Format("len = %d, payload = %X%X", iLength, (int)command.initiator, (int)command.destination);
  for (uint8_t iPtr = 0; iPtr < iLength; iPtr++)
    strDump += StringUtils::Format(":%02X", payload[iPtr]);
  LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: %s", strDump.c_str());
#endif

  int iReturn = vc_cec_send_message((uint32_t)command.destination, command.opcode_set ? (uint8_t*)&payload : NULL, iLength, bIsReply);
#endif

  bRetry = false;
  if (iReturn != VCHIQ_SUCCESS)
  {
    LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending command '%s' failed (%d)", CCECTypeUtils::ToString(command.opcode), iReturn);
    delete entry;
    m_messages.erase(iEntryId);
    return ADAPTER_MESSAGE_STATE_ERROR;
  }

  cec_adapter_message_state bReturn(ADAPTER_MESSAGE_STATE_ERROR);
  if (entry)
  {
    if (entry->Wait(iLineTimeout))
    {
      int status = entry->Result();

      if (status == VC_CEC_ERROR_NO_ACK)
        bReturn = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
      else if (status == VC_CEC_SUCCESS)
        bReturn = ADAPTER_MESSAGE_STATE_SENT_ACKED;
      else
        bReturn = ADAPTER_MESSAGE_STATE_SENT;
    }
    else
    {
      bRetry = true;
      LIB_CEC->AddLog(CEC_LOG_DEBUG, "command '%s' timeout", CCECTypeUtils::ToString(command.opcode));
      CEvent::Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT);
      bReturn = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT;
    }

    vcReply = (VC_CEC_ERROR_T)entry->Result();

    CLockObject lock(m_mutex);
    m_messages.erase(iEntryId);
    delete entry;
  }

  return bReturn;
}
cec_adapter_message_state CRPiCECAdapterMessageQueue::Write(const cec_command &command, bool &bRetry, uint32_t iLineTimeout, bool bIsReply, VC_CEC_ERROR_T &vcReply)
{
  CRPiCECAdapterMessageQueueEntry *entry = new CRPiCECAdapterMessageQueueEntry(this, command);
  uint64_t iEntryId(0);
  /* add to the wait for ack queue */
  {
    CLockObject lock(m_mutex);
    iEntryId = m_iNextMessage++;
    m_messages.insert(make_pair(iEntryId, entry));
  }

#if defined(RPI_USE_SEND_MESSAGE2)
  VC_CEC_MESSAGE_T message;
  message.initiator = (CEC_AllDevices_T)command.initiator;
  message.follower = (CEC_AllDevices_T)command.destination;
  message.length = 1;

  if (command.opcode_set)
  {
    message.length += 1;
    message.payload[0] = command.opcode;

    message.length += command.parameters.size;
    for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
      message.payload[iPtr + 1] = command.parameters.At(iPtr);
  }

#ifdef CEC_DEBUGGING
  CStdString strDump;
  strDump.Format("len = %d, payload = %X%X", message.length, (int)message.initiator, (int)message.follower);
  for (uint8_t iPtr = 0; iPtr < message.length - 1; iPtr++)
    strDump.AppendFormat(":%02X", message.payload[iPtr]);
  LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: %s", strDump.c_str());
#endif

  int iReturn = vc_cec_send_message2(&message);
#else
  uint8_t payload[32];
  uint32_t iLength(0);

  if (command.opcode_set)
  {
    iLength += 1;
    payload[0] = command.opcode;

    iLength += command.parameters.size;
    for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
      payload[iPtr + 1] = command.parameters.At(iPtr);
  }

#ifdef CEC_DEBUGGING
  CStdString strDump;
  strDump.Format("len = %d, payload = %X%X", iLength, (int)command.initiator, (int)command.destination);
  for (uint8_t iPtr = 0; iPtr < iLength; iPtr++)
    strDump.AppendFormat(":%02X", payload[iPtr]);
  LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: %s", strDump.c_str());
#endif

  int iReturn = vc_cec_send_message((uint32_t)command.destination, command.opcode_set ? (uint8_t*)&payload : NULL, iLength, bIsReply);
#endif

  bRetry = false;
  if (iReturn != VCHIQ_SUCCESS)
  {
    LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending command '%s' failed (%d)", command.opcode_set ? CCECTypeUtils::ToString(command.opcode) : "POLL", iReturn);
    delete (entry);
    return ADAPTER_MESSAGE_STATE_ERROR;
  }

  cec_adapter_message_state bReturn(ADAPTER_MESSAGE_STATE_ERROR);
  if (entry)
  {
    if (entry->Wait(iLineTimeout))
    {
      int status = entry->Result();

      if (status == VC_CEC_ERROR_NO_ACK)
        bReturn = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
      else if (status == VC_CEC_SUCCESS)
        bReturn = ADAPTER_MESSAGE_STATE_SENT_ACKED;
      else
        bReturn = ADAPTER_MESSAGE_STATE_SENT;
    }
    else
    {
      if (command.opcode_set)
      {
        bRetry = true;
        LIB_CEC->AddLog(CEC_LOG_DEBUG, "command '%s' timeout", command.opcode_set ? CCECTypeUtils::ToString(command.opcode) : "POLL");
        CEvent::Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT);
      }
      bReturn = ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT;
    }

    vcReply = (VC_CEC_ERROR_T)entry->Result();

    CLockObject lock(m_mutex);
    m_messages.erase(iEntryId);
    delete entry;
  }

  return bReturn;
}
Ejemplo n.º 3
0
bool CRPiCECAdapterMessageQueue::Write(const cec_command &command, bool bIsReply)
{
  CRPiCECAdapterMessageQueueEntry *entry = new CRPiCECAdapterMessageQueueEntry(this, command);
  uint64_t iEntryId(0);
  /* add to the wait for ack queue */
  {
    CLockObject lock(m_mutex);
    iEntryId = m_iNextMessage++;
    m_messages.insert(make_pair(iEntryId, entry));
  }

#if defined(RPI_USE_SEND_MESSAGE2)
  VC_CEC_MESSAGE_T message;
  message.initiator = (CEC_AllDevices_T)command.initiator;
  message.follower = (CEC_AllDevices_T)command.destination;
  message.length = 1;

  if (command.opcode_set)
  {
    message.length += 1;
    message.payload[0] = command.opcode;

    message.length += command.parameters.size;
    for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
      message.payload[iPtr + 1] = command.parameters.At(iPtr);
  }

  CStdString strDump;
  strDump.Format("len = %d, payload = %X%X", message.length, (int)message.initiator, (int)message.follower);
  for (uint8_t iPtr = 0; iPtr < message.length - 1; iPtr++)
    strDump.AppendFormat(":%02X", message.payload[iPtr]);
  LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: %s", strDump.c_str());

  int iReturn = vc_cec_send_message2(&message);
#else
  uint8_t payload[32];
  uint32_t iLength(0);

  if (command.opcode_set)
  {
    iLength += 1;
    payload[0] = command.opcode;

    iLength += command.parameters.size;
    for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
      payload[iPtr + 1] = command.parameters.At(iPtr);
  }

  CStdString strDump;
  strDump.Format("len = %d, payload = %X%X", iLength, (int)command.initiator, (int)command.destination);
  for (uint8_t iPtr = 0; iPtr < iLength; iPtr++)
    strDump.AppendFormat(":%02X", payload[iPtr]);
  LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending data: %s", strDump.c_str());

   int iReturn = vc_cec_send_message((uint32_t)command.destination, (uint8_t*)&payload, iLength, bIsReply);
#endif

  if (iReturn != VCHIQ_SUCCESS)
  {
    LIB_CEC->AddLog(CEC_LOG_DEBUG, "sending command '%s' failed (%d)", command.opcode_set ? CCECTypeUtils::ToString(command.opcode) : "POLL", iReturn);
    delete (entry);
    return false;
  }

  bool bReturn(true);
  if (entry)
  {
    if (!entry->Wait(CEC_DEFAULT_TRANSMIT_WAIT))
    {
      LIB_CEC->AddLog(CEC_LOG_DEBUG, "command '%s' was not acked by the controller", command.opcode_set ? CCECTypeUtils::ToString(command.opcode) : "POLL");
      bReturn = false;
    }

    CLockObject lock(m_mutex);
    m_messages.erase(iEntryId);
    delete entry;
  }

  return bReturn;
}