Skip to content

Commit

Permalink
added: GetStats() command
Browse files Browse the repository at this point in the history
returns tx/rx stats for devices that support this
  • Loading branch information
opdenkamp committed Mar 31, 2020
1 parent d9c415c commit cb3cc57
Show file tree
Hide file tree
Showing 17 changed files with 141 additions and 4 deletions.
2 changes: 2 additions & 0 deletions include/cec.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@ namespace CEC
* @return True if the command was sent, false otherwise
*/
virtual bool AudioEnable(bool enable) = 0;

virtual bool GetStats(struct cec_adapter_stats* stats) = 0;
};
};

Expand Down
9 changes: 9 additions & 0 deletions include/cectypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,15 @@ typedef struct libcec_parameter
void* paramData; /**< the value of this parameter */
} libcec_parameter;

struct cec_adapter_stats
{
unsigned int tx_ack;
unsigned int tx_nack;
unsigned int tx_error;
unsigned int rx_total;
unsigned int rx_error;
};

typedef struct libcec_configuration libcec_configuration;

typedef struct ICECCallbacks
Expand Down
27 changes: 26 additions & 1 deletion src/cec-client/cec-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,30 @@ bool ProcessCommandSCAN(ICECAdapter *parser, const std::string &command, std::st
return false;
}

bool ProcessCommandSTATS(ICECAdapter *parser, const std::string &command, std::string & UNUSED(arguments))
{
if (command == "stats")
{
cec_adapter_stats stats;
if (parser->GetStats(&stats))
{
std::string strLog;
strLog += StringUtils::Format("tx acked: %u\n", stats.tx_ack);
strLog += StringUtils::Format("tx nacked: %u\n", stats.tx_nack);
strLog += StringUtils::Format("tx error: %u\n", stats.tx_error);
strLog += StringUtils::Format("rx total: %u\n", stats.rx_total);
strLog += StringUtils::Format("rx error: %u\n", stats.rx_error);
PrintToStdOut(strLog.c_str());
}
else
{
PrintToStdOut("not supported\n");
}
return true;
}
return false;
}

bool ProcessConsoleCommand(ICECAdapter *parser, std::string &input)
{
if (!input.empty())
Expand Down Expand Up @@ -961,7 +985,8 @@ bool ProcessConsoleCommand(ICECAdapter *parser, std::string &input)
ProcessCommandSCAN(parser, command, input) ||
ProcessCommandSP(parser, command, input) ||
ProcessCommandSPL(parser, command, input) ||
ProcessCommandSELF(parser, command, input);
ProcessCommandSELF(parser, command, input) ||
ProcessCommandSTATS(parser, command, input);
}
}
return true;
Expand Down
8 changes: 8 additions & 0 deletions src/libcec/CECClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1704,3 +1704,11 @@ bool CCECClient::AudioEnable(bool enable)
audio->EnableAudio(device) :
false;
}

bool CCECClient::GetStats(struct cec_adapter_stats* stats)
{
return !!m_processor ?
m_processor->GetStats(stats) :
false;
}

1 change: 1 addition & 0 deletions src/libcec/CECClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ namespace CEC
virtual void RescanActiveDevices(void);
virtual bool IsLibCECActiveSource(void);
bool AudioEnable(bool enable);
bool GetStats(struct cec_adapter_stats* stats);

// configuration
virtual bool GetCurrentConfiguration(libcec_configuration &configuration);
Expand Down
7 changes: 7 additions & 0 deletions src/libcec/CECProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,13 @@ bool CCECProcessor::ActivateSource(uint16_t iStreamPath)
return bReturn;
}

bool CCECProcessor::GetStats(struct cec_adapter_stats* stats)
{
return !!m_communication ?
m_communication->GetStats(stats) :
false;
}

void CCECProcessor::SetActiveSource(bool bSetTo, bool bClientUnregistered)
{
if (m_communication)
Expand Down
1 change: 1 addition & 0 deletions src/libcec/CECProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ namespace CEC
bool SetDeckInfo(cec_deck_info info, bool bSendUpdate = true);
bool ActivateSource(uint16_t iStreamPath);
void SetActiveSource(bool bSetTo, bool bClientUnregistered);
bool GetStats(struct cec_adapter_stats* stats);
bool PollDevice(cec_logical_address iAddress);
void SetStandardLineTimeout(uint8_t iTimeout);
uint8_t GetStandardLineTimeout(void);
Expand Down
7 changes: 7 additions & 0 deletions src/libcec/LibCEC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,3 +624,10 @@ bool CLibCEC::AudioEnable(bool enable)
m_client->AudioEnable(enable) :
false;
}

bool CLibCEC::GetStats(struct cec_adapter_stats* stats)
{
return !!m_client ?
m_client->GetStats(stats) :
false;
}
1 change: 1 addition & 0 deletions src/libcec/LibCEC.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ namespace CEC
cec_command CommandFromString(const char* strCommand);

bool AudioEnable(bool enable);
bool GetStats(struct cec_adapter_stats* stats);

CCECProcessor * m_cec;

Expand Down
1 change: 1 addition & 0 deletions src/libcec/adapter/AOCEC/AOCECAdapterCommunication.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ namespace CEC
uint16_t GetAdapterProductId(void) const { return 1; }
void HandleLogicalAddressLost(cec_logical_address oldAddress);
void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) {}
bool GetStats(struct cec_adapter_stats* UNUSED(stats)) { return false; }
///}

/** @name P8PLATFORM::CThread implementation */
Expand Down
2 changes: 2 additions & 0 deletions src/libcec/adapter/AdapterCommunication.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ namespace CEC
*/
virtual void SetActiveSource(bool bSetTo, bool bClientUnregistered) = 0;

virtual bool GetStats(struct cec_adapter_stats* stats) = 0;

IAdapterCommunicationCallback *m_callback;
};
};
1 change: 1 addition & 0 deletions src/libcec/adapter/Exynos/ExynosCECAdapterCommunication.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ namespace CEC
uint16_t GetAdapterProductId(void) const { return 1; }
void HandleLogicalAddressLost(cec_logical_address oldAddress);
void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) {}
bool GetStats(struct cec_adapter_stats* UNUSED(stats)) { return false; }
///}

/** @name P8PLATFORM::CThread implementation */
Expand Down
39 changes: 38 additions & 1 deletion src/libcec/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(IAdapterCommunicationCa
m_commands(NULL),
m_adapterMessageQueue(NULL)
{
memset(&m_stats, 0, sizeof(struct cec_adapter_stats));
m_logicalAddresses.Clear();
for (unsigned int iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
m_bWaitingForAck[iPtr] = false;
Expand Down Expand Up @@ -269,7 +270,6 @@ cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &

void *CUSBCECAdapterCommunication::Process(void)
{
CCECAdapterMessage msg;
LIB_CEC->AddLog(CEC_LOG_DEBUG, "communication thread started");

while (!IsStopped())
Expand Down Expand Up @@ -635,6 +635,13 @@ void CUSBCECAdapterCommunication::SetActiveSource(bool bSetTo, bool bClientUnreg
m_commands->SetActiveSource(bSetTo, bClientUnregistered);
}

bool CUSBCECAdapterCommunication::GetStats(struct cec_adapter_stats* stats)
{
CLockObject lock(m_statsMutex);
memcpy(stats, &m_stats, sizeof(struct cec_adapter_stats));
return true;
}

bool CUSBCECAdapterCommunication::IsRunningLatestFirmware(void)
{
return GetFirmwareBuildDate() >= CEC_LATEST_ADAPTER_FW_DATE &&
Expand Down Expand Up @@ -717,6 +724,36 @@ uint16_t CUSBCECAdapterCommunication::GetPhysicalAddress(void)
return iPA;
}

void CUSBCECAdapterCommunication::OnRxSuccess(void)
{
CLockObject lock(m_statsMutex);
++m_stats.rx_total;
}

void CUSBCECAdapterCommunication::OnRxError(void)
{
CLockObject lock(m_statsMutex);
++m_stats.rx_error;
}

void CUSBCECAdapterCommunication::OnTxAck(void)
{
CLockObject lock(m_statsMutex);
++m_stats.tx_ack;
}

void CUSBCECAdapterCommunication::OnTxNack(void)
{
CLockObject lock(m_statsMutex);
++m_stats.tx_nack;
}

void CUSBCECAdapterCommunication::OnTxError(void)
{
CLockObject lock(m_statsMutex);
++m_stats.tx_error;
}

void *CAdapterPingThread::Process(void)
{
while (!IsStopped())
Expand Down
9 changes: 9 additions & 0 deletions src/libcec/adapter/Pulse-Eight/USBCECAdapterCommunication.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,17 @@ namespace CEC
uint16_t GetAdapterVendorId(void) const;
uint16_t GetAdapterProductId(void) const;
void SetActiveSource(bool bSetTo, bool bClientUnregistered);
bool GetStats(struct cec_adapter_stats* stats);
///}

bool ProvidesExtendedResponse(void);

void OnRxSuccess(void);
void OnRxError(void);
void OnTxAck(void);
void OnTxNack(void);
void OnTxError(void);

void *Process(void);

private:
Expand Down Expand Up @@ -185,6 +192,8 @@ namespace CEC
CUSBCECAdapterCommands * m_commands; /**< commands that can be sent to the adapter */
CCECAdapterMessageQueue * m_adapterMessageQueue; /**< the incoming and outgoing message queue */
cec_logical_addresses m_logicalAddresses; /**< the logical address list that this instance is using */
struct cec_adapter_stats m_stats;
P8PLATFORM::CMutex m_statsMutex;
P8PLATFORM::CMutex m_waitingMutex;
};

Expand Down
28 changes: 26 additions & 2 deletions src/libcec/adapter/Pulse-Eight/USBCECAdapterMessageQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ bool CCECAdapterMessageQueueEntry::MessageReceivedTransmitSucceeded(const CCECAd
#endif
m_message->state = ADAPTER_MESSAGE_STATE_SENT_ACKED;
m_message->response = message.packet;
m_queue->m_com->OnTxAck();
}
else
{
Expand All @@ -261,13 +262,30 @@ bool CCECAdapterMessageQueueEntry::MessageReceivedResponse(const CCECAdapterMess
m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_DEBUG, "%s - received response - %s", ToString(), message.ToString().c_str());
#else
if (message.IsError())
{
m_queue->m_com->m_callback->GetLib()->AddLog(CEC_LOG_DEBUG, "%s - received response - %s", ToString(), message.ToString().c_str());
if (m_message->IsTransmission() && (message.Message() != MSGCODE_TRANSMIT_FAILED_ACK))
m_queue->m_com->OnTxError();
}
#endif
m_message->response = message.packet;
if (m_message->IsTransmission())
m_message->state = message.Message() == MSGCODE_TRANSMIT_SUCCEEDED ? ADAPTER_MESSAGE_STATE_SENT_ACKED : ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
{
if (message.Message() == MSGCODE_TRANSMIT_SUCCEEDED)
{
m_message->state = ADAPTER_MESSAGE_STATE_SENT_ACKED;
m_queue->m_com->OnTxAck();
}
else
{
m_message->state = ADAPTER_MESSAGE_STATE_SENT_NOT_ACKED;
m_queue->m_com->OnTxNack();
}
}
else
{
m_message->state = ADAPTER_MESSAGE_STATE_SENT_ACKED;
}
}

Signal();
Expand Down Expand Up @@ -365,7 +383,7 @@ void CCECAdapterMessageQueue::MessageReceived(const CCECAdapterMessage &msg)
bool bHandled(false);
CLockObject lock(m_mutex);
/* send the received message to each entry in the queue until it is handled */
for (std::map<uint64_t, CCECAdapterMessageQueueEntry *>::iterator it = m_messages.begin(); !bHandled && it != m_messages.end(); it++)
for (auto it = m_messages.begin(); !bHandled && it != m_messages.end(); ++it)
bHandled = it->second->MessageReceived(msg);

if (!bHandled)
Expand All @@ -376,15 +394,21 @@ void CCECAdapterMessageQueue::MessageReceived(const CCECAdapterMessage &msg)
m_com->m_callback->GetLib()->AddLog(bIsError ? CEC_LOG_WARNING : CEC_LOG_DEBUG, msg.ToString().c_str());
#else
if (bIsError)
{
m_com->OnRxError();
m_com->m_callback->GetLib()->AddLog(CEC_LOG_WARNING, msg.ToString().c_str());
}
#endif

/* push this message to the current frame */
if (!bIsError && msg.PushToCecCommand(m_currentCECFrame))
{
/* and push the current frame back over the callback method when a full command was received */
if (m_com->IsInitialised())
{
m_com->OnRxSuccess();
m_com->m_callback->OnCommandReceived(m_currentCECFrame);
}

/* clear the current frame */
m_currentCECFrame.Clear();
Expand Down
1 change: 1 addition & 0 deletions src/libcec/adapter/RPi/RPiCECAdapterCommunication.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ namespace CEC
uint16_t GetAdapterVendorId(void) const { return RPI_ADAPTER_VID; }
uint16_t GetAdapterProductId(void) const { return RPI_ADAPTER_PID; }
void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) {}
bool GetStats(struct cec_adapter_stats* UNUSED(stats)) { return false; }
///}

bool IsInitialised(void);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ namespace CEC
uint16_t GetAdapterProductId(void) const { return TDA995X_ADAPTER_PID; }
void HandleLogicalAddressLost(cec_logical_address oldAddress);
void SetActiveSource(bool UNUSED(bSetTo), bool UNUSED(bClientUnregistered)) {}
bool GetStats(struct cec_adapter_stats* UNUSED(stats)) { return false; }
///}

/** @name P8PLATFORM::CThread implementation */
Expand Down

3 comments on commit cb3cc57

@MilhouseVH
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any ideas? http://ix.io/2gfs

@MilhouseVH
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@opdenkamp
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that method didn't exist when PR380 was created. just needs one line added in it's header to make it compile:

bool GetStats(struct cec_adapter_stats* UNUSED(stats)) { return false; }

Please sign in to comment.