From 0b71487197ed7281dda06f53ecaf846f1fd7e942 Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Mon, 23 Apr 2012 11:34:33 +0200 Subject: [PATCH] cec: close the connection when a comm error was detected, and notify the client via an alert --- include/cectypes.h | 3 +- src/lib/CECProcessor.cpp | 12 +++-- src/lib/LibCEC.cpp | 9 ++-- .../adapter/USBCECAdapterCommunication.cpp | 44 +++++++++++-------- src/lib/platform/threads/threads.h | 2 +- src/testclient/main.cpp | 17 ++++--- 6 files changed, 54 insertions(+), 33 deletions(-) diff --git a/include/cectypes.h b/include/cectypes.h index d3e3bb1..ae8db71 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -1125,7 +1125,8 @@ typedef enum cec_server_version CEC_SERVER_VERSION_1_5_2 = 0x1502, CEC_SERVER_VERSION_1_5_3 = 0x1503, CEC_SERVER_VERSION_1_6_0 = 0x1600, - CEC_SERVER_VERSION_1_6_1 = 0x1601 + CEC_SERVER_VERSION_1_6_1 = 0x1601, + CEC_SERVER_VERSION_1_6_2 = 0x1602 } cec_server_version; typedef struct libcec_configuration diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index 708536f..4bdc882 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -210,7 +210,7 @@ bool CCECProcessor::OpenConnection(const char *strPort, uint16_t iBaudRate, uint bool CCECProcessor::IsInitialised(void) { - CLockObject lock(m_mutex); + CLockObject lock(m_threadMutex); return m_bInitialised; } @@ -1012,7 +1012,7 @@ uint16_t CCECProcessor::GetPhysicalAddress(void) const bool CCECProcessor::SetAckMask(uint16_t iMask) { - return m_communication->SetAckMask(iMask); + return m_communication ? m_communication->SetAckMask(iMask) : false; } bool CCECProcessor::TransmitKeypress(cec_logical_address iDestination, cec_user_control_code key, bool bWait /* = true */) @@ -1438,6 +1438,8 @@ const char *CCECProcessor::ToString(const cec_client_version version) return "1.6.0"; case CEC_CLIENT_VERSION_1_6_1: return "1.6.1"; + case CEC_CLIENT_VERSION_1_6_2: + return "1.6.2"; default: return "Unknown"; } @@ -1461,6 +1463,8 @@ const char *CCECProcessor::ToString(const cec_server_version version) return "1.6.0"; case CEC_SERVER_VERSION_1_6_1: return "1.6.1"; + case CEC_SERVER_VERSION_1_6_2: + return "1.6.2"; default: return "Unknown"; } @@ -1750,12 +1754,12 @@ bool CCECProcessor::GetCurrentConfiguration(libcec_configuration *configuration) bool CCECProcessor::CanPersistConfiguration(void) { - return m_communication->GetFirmwareVersion() >= 2; + return m_communication ? m_communication->GetFirmwareVersion() >= 2 : false; } bool CCECProcessor::PersistConfiguration(libcec_configuration *configuration) { - return m_communication->PersistConfiguration(configuration); + return m_communication ? m_communication->PersistConfiguration(configuration) : false; } void CCECProcessor::RescanActiveDevices(void) diff --git a/src/lib/LibCEC.cpp b/src/lib/LibCEC.cpp index 5dfa968..449231d 100644 --- a/src/lib/LibCEC.cpp +++ b/src/lib/LibCEC.cpp @@ -459,9 +459,12 @@ void CLibCEC::Alert(const libcec_alert type, const libcec_parameter ¶m) if (instance->m_callbacks && config.clientVersion >= CEC_CLIENT_VERSION_1_6_0 && - instance->m_callbacks->CBCecAlert != NULL && - instance->m_cec->IsInitialised()) + instance->m_cec->IsInitialised() && + instance->m_callbacks->CBCecAlert != NULL) instance->m_callbacks->CBCecAlert(instance->m_cbParam, type, param); + + if (type == CEC_ALERT_CONNECTION_LOST) + instance->Close(); } void CLibCEC::CheckKeypressTimeout(void) @@ -633,7 +636,7 @@ const char *CLibCEC::ToString(const cec_device_type type) bool CLibCEC::GetCurrentConfiguration(libcec_configuration *configuration) { - return m_cec->IsInitialised() && m_cec->GetCurrentConfiguration(configuration); + return m_cec->GetCurrentConfiguration(configuration); } bool CLibCEC::SetConfiguration(const libcec_configuration *configuration) diff --git a/src/lib/adapter/USBCECAdapterCommunication.cpp b/src/lib/adapter/USBCECAdapterCommunication.cpp index f5bdc2f..b53114c 100644 --- a/src/lib/adapter/USBCECAdapterCommunication.cpp +++ b/src/lib/adapter/USBCECAdapterCommunication.cpp @@ -152,9 +152,15 @@ bool CUSBCECAdapterCommunication::Open(uint32_t iTimeoutMs /* = 10000 */, bool b void CUSBCECAdapterCommunication::Close(void) { + /* stop the reader thread */ + StopThread(0); + + CLockObject lock(m_mutex); + /* set the ackmask to 0 before closing the connection */ - if (IsRunning()) + if (IsRunning() && m_port->IsOpen() && m_port->GetErrorNumber() == 0) { + CLibCEC::AddLog(CEC_LOG_DEBUG, "%s - closing the connection", __FUNCTION__); SetAckMask(0); if (m_commands->GetFirmwareVersion() >= 2) SetControlledMode(false); @@ -166,12 +172,12 @@ void CUSBCECAdapterCommunication::Close(void) delete m_pingThread; m_pingThread = NULL; - /* stop the reader thread */ - StopThread(0); - /* close and delete the com port connection */ if (m_port) m_port->Close(); + + libcec_parameter param; + CLibCEC::Alert(CEC_ALERT_CONNECTION_LOST, param); } cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout) @@ -187,7 +193,9 @@ cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command & /* send the message */ bRetry = (!m_adapterMessageQueue->Write(output) || output->NeedsRetry()) && output->transmit_timeout > 0; - if (bRetry) + if (output->state == ADAPTER_MESSAGE_STATE_ERROR) + Close(); + else if (bRetry) Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT); retVal = output->state; @@ -294,7 +302,7 @@ bool CUSBCECAdapterCommunication::WriteToDevice(CCECAdapterMessage *message) CLockObject adapterLock(m_mutex); if (!m_port->IsOpen()) { - CLibCEC::AddLog(CEC_LOG_DEBUG, "error writing command '%s' to the serial port: the connection is closed", CCECAdapterMessage::ToString(message->Message())); + CLibCEC::AddLog(CEC_LOG_DEBUG, "error writing command '%s' to serial port '%s': the connection is closed", CCECAdapterMessage::ToString(message->Message()), m_port->GetName().c_str()); message->state = ADAPTER_MESSAGE_STATE_ERROR; return false; } @@ -302,7 +310,7 @@ bool CUSBCECAdapterCommunication::WriteToDevice(CCECAdapterMessage *message) /* write the message */ if (m_port->Write(message->packet.data, message->Size()) != (ssize_t) message->Size()) { - CLibCEC::AddLog(CEC_LOG_DEBUG, "error writing command '%s' to the serial port: %s", CCECAdapterMessage::ToString(message->Message()), m_port->GetError().c_str()); + CLibCEC::AddLog(CEC_LOG_DEBUG, "error writing command '%s' to serial port '%s': %s", CCECAdapterMessage::ToString(message->Message()), m_port->GetName().c_str(), m_port->GetError().c_str()); message->state = ADAPTER_MESSAGE_STATE_ERROR; return false; } @@ -322,7 +330,7 @@ bool CUSBCECAdapterCommunication::ReadFromDevice(uint32_t iTimeout, size_t iSize /* read from the serial port */ { CLockObject lock(m_mutex); - if (!m_port) + if (!m_port || !m_port->IsOpen()) return false; iBytesRead = m_port->Read(buff, sizeof(uint8_t) * iSize, iTimeout); } @@ -330,7 +338,7 @@ bool CUSBCECAdapterCommunication::ReadFromDevice(uint32_t iTimeout, size_t iSize if (iBytesRead < 0 || iBytesRead > 256) { CLibCEC::AddLog(CEC_LOG_ERROR, "error reading from serial port: %s", m_port->GetError().c_str()); - StopThread(false); + Close(); return false; } else if (iBytesRead > 0) @@ -358,7 +366,8 @@ CCECAdapterMessage *CUSBCECAdapterCommunication::SendCommand(cec_adapter_message /* write the command */ if (!m_adapterMessageQueue->Write(output)) { - // timed out + if (output->state == ADAPTER_MESSAGE_STATE_ERROR) + Close(); return output; } else @@ -437,20 +446,17 @@ bool CUSBCECAdapterCommunication::IsInitialised(void) bool CUSBCECAdapterCommunication::StartBootloader(void) { - if (!IsRunning()) - return false; - - return m_commands->StartBootloader(); + return m_port->IsOpen() ? m_commands->StartBootloader() : false; } bool CUSBCECAdapterCommunication::SetAckMask(uint16_t iMask) { - return m_commands->SetAckMask(iMask); + return m_port->IsOpen() ? m_commands->SetAckMask(iMask) : false; } bool CUSBCECAdapterCommunication::PingAdapter(void) { - return m_commands->PingAdapter(); + return m_port->IsOpen() ? m_commands->PingAdapter() : false; } uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void) @@ -460,12 +466,12 @@ uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void) bool CUSBCECAdapterCommunication::PersistConfiguration(libcec_configuration *configuration) { - return m_commands->PersistConfiguration(configuration); + return m_port->IsOpen() ? m_commands->PersistConfiguration(configuration) : false; } bool CUSBCECAdapterCommunication::GetConfiguration(libcec_configuration *configuration) { - return m_commands->GetConfiguration(configuration); + return m_port->IsOpen() ? m_commands->GetConfiguration(configuration) : false; } CStdString CUSBCECAdapterCommunication::GetPortName(void) @@ -475,7 +481,7 @@ CStdString CUSBCECAdapterCommunication::GetPortName(void) bool CUSBCECAdapterCommunication::SetControlledMode(bool controlled) { - return m_commands->SetControlledMode(controlled); + return m_port->IsOpen() ? m_commands->SetControlledMode(controlled) : false; } void *CAdapterPingThread::Process(void) diff --git a/src/lib/platform/threads/threads.h b/src/lib/platform/threads/threads.h index 0cc07ee..31c2daf 100644 --- a/src/lib/platform/threads/threads.h +++ b/src/lib/platform/threads/threads.h @@ -143,13 +143,13 @@ namespace PLATFORM protected: void SetRunning(bool bSetTo); + CMutex m_threadMutex; private: bool m_bStop; bool m_bRunning; bool m_bStopped; CCondition m_threadCondition; - CMutex m_threadMutex; thread_t m_thread; }; }; diff --git a/src/testclient/main.cpp b/src/testclient/main.cpp index 1642ef1..04635ad 100644 --- a/src/testclient/main.cpp +++ b/src/testclient/main.cpp @@ -175,12 +175,18 @@ int CecCommand(void *UNUSED(cbParam), const cec_command &UNUSED(command)) return 0; } -void EnableCallbacks(ICECAdapter *adapter) +int CecAlert(void *UNUSED(cbParam), const libcec_alert type, const libcec_parameter &UNUSED(param)) { - g_callbacks.CBCecLogMessage = &CecLogMessage; - g_callbacks.CBCecKeyPress = &CecKeyPress; - g_callbacks.CBCecCommand = &CecCommand; - adapter->EnableCallbacks(NULL, &g_callbacks); + switch (type) + { + case CEC_ALERT_CONNECTION_LOST: + PrintToStdOut("Connection lost - exiting\n"); + g_bExit = true; + break; + default: + break; + } + return 0; } void ListDevices(ICECAdapter *parser) @@ -1070,6 +1076,7 @@ int main (int argc, char *argv[]) g_callbacks.CBCecLogMessage = &CecLogMessage; g_callbacks.CBCecKeyPress = &CecKeyPress; g_callbacks.CBCecCommand = &CecCommand; + g_callbacks.CBCecAlert = &CecAlert; g_config.callbacks = &g_callbacks; if (!ProcessCommandLineArguments(argc, argv)) -- 2.34.1