X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fadapter%2FUSBCECAdapterCommunication.cpp;h=6c548b00ad2eab495083b57ed76295c290b1d71d;hb=5daed059e1d5bca3ddfa0787679ef4e7b349e382;hp=a74194369029665969f01de31ab8783b70b997d5;hpb=a75e3a5a63546d6f7e670bc2a7a1931887a5d2a0;p=deb_libcec.git diff --git a/src/lib/adapter/USBCECAdapterCommunication.cpp b/src/lib/adapter/USBCECAdapterCommunication.cpp index a741943..6c548b0 100644 --- a/src/lib/adapter/USBCECAdapterCommunication.cpp +++ b/src/lib/adapter/USBCECAdapterCommunication.cpp @@ -44,7 +44,12 @@ using namespace PLATFORM; #define CEC_ADAPTER_PING_TIMEOUT 15000 -CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(IAdapterCommunicationCallback *callback, const char *strPort, uint16_t iBaudRate /* = 38400 */) : +// firmware version 2 +#define CEC_LATEST_ADAPTER_FW_VERSION 2 +// firmware date Thu Apr 26 20:14:49 2012 +0000 +#define CEC_LATEST_ADAPTER_FW_DATE 0x4F99ACB9 + +CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(IAdapterCommunicationCallback *callback, const char *strPort, uint16_t iBaudRate /* = CEC_SERIAL_DEFAULT_BAUDRATE */) : IAdapterCommunication(callback), m_port(NULL), m_iLineTimeout(0), @@ -54,7 +59,7 @@ CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(IAdapterCommunicationCa m_commands(NULL), m_adapterMessageQueue(NULL) { - for (unsigned int iPtr = 0; iPtr < 15; iPtr++) + for (unsigned int iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++) m_bWaitingForAck[iPtr] = false; m_port = new CSerialPort(strPort, iBaudRate); } @@ -64,9 +69,10 @@ CUSBCECAdapterCommunication::~CUSBCECAdapterCommunication(void) Close(); delete m_commands; delete m_adapterMessageQueue; + delete m_port; } -bool CUSBCECAdapterCommunication::Open(uint32_t iTimeoutMs /* = 10000 */, bool bSkipChecks /* = false */, bool bStartListening /* = true */) +bool CUSBCECAdapterCommunication::Open(uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */, bool bSkipChecks /* = false */, bool bStartListening /* = true */) { bool bConnectionOpened(false); { @@ -91,7 +97,10 @@ bool CUSBCECAdapterCommunication::Open(uint32_t iTimeoutMs /* = 10000 */, bool b m_commands = new CUSBCECAdapterCommands(this); if (!m_adapterMessageQueue) + { m_adapterMessageQueue = new CCECAdapterMessageQueue(this); + m_adapterMessageQueue->CreateThread(); + } /* try to open the connection */ CStdString strError; @@ -145,58 +154,57 @@ bool CUSBCECAdapterCommunication::Open(uint32_t iTimeoutMs /* = 10000 */, bool b if (!bConnectionOpened || !bStartListening) StopThread(0); - if (!bConnectionOpened) - { - delete m_port; - m_port = NULL; - } return bConnectionOpened; } 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); } + m_adapterMessageQueue->Clear(); + /* stop and delete the ping thread */ if (m_pingThread) m_pingThread->StopThread(0); delete m_pingThread; m_pingThread = NULL; - /* stop the reader thread */ - StopThread(0); - /* close and delete the com port connection */ - delete m_port; - m_port = NULL; + 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, uint8_t iMaxTries, uint8_t iLineTimeout /* = 3 */, uint8_t iRetryLineTimeout /* = 3 */) +cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout) { cec_adapter_message_state retVal(ADAPTER_MESSAGE_STATE_UNKNOWN); if (!IsRunning()) return retVal; - CCECAdapterMessage *output = new CCECAdapterMessage(data, iMaxTries, iLineTimeout, iRetryLineTimeout); + CCECAdapterMessage *output = new CCECAdapterMessage(data, iLineTimeout); /* mark as waiting for an ack from the destination */ MarkAsWaiting(data.destination); /* send the message */ - bool bRetry(true); - while (bRetry && ++output->tries < output->maxTries) - { - bRetry = (!m_adapterMessageQueue->Write(output) || output->NeedsRetry()) && output->transmit_timeout > 0; - if (bRetry) - Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT); - } + bRetry = (!m_adapterMessageQueue->Write(output) || output->NeedsRetry()) && output->transmit_timeout > 0; + if (bRetry) + Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT); retVal = output->state; delete output; @@ -263,15 +271,16 @@ void CUSBCECAdapterCommunication::MarkAsWaiting(const cec_logical_address dest) } } -void CUSBCECAdapterCommunication::ClearInputBytes(uint32_t iTimeout /* = 1000 */) +void CUSBCECAdapterCommunication::ClearInputBytes(uint32_t iTimeout /* = CEC_CLEAR_INPUT_DEFAULT_WAIT */) { CTimeout timeout(iTimeout); uint8_t buff[1024]; ssize_t iBytesRead(0); - bool bGotMsgEnd(false); + bool bGotMsgEnd(true); while (timeout.TimeLeft() > 0 && ((iBytesRead = m_port->Read(buff, 1024, 5)) > 0 || !bGotMsgEnd)) { + bGotMsgEnd = false; /* if something was received, wait for MSGEND */ for (ssize_t iPtr = 0; iPtr < iBytesRead; iPtr++) bGotMsgEnd = buff[iPtr] == MSGEND; @@ -301,7 +310,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; } @@ -309,8 +318,9 @@ 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; + Close(); return false; } @@ -329,17 +339,21 @@ 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); + + if (m_port->GetErrorNumber()) + { + CLibCEC::AddLog(CEC_LOG_ERROR, "error reading from serial port: %s", m_port->GetError().c_str()); + m_port->Close(); + return false; + } } if (iBytesRead < 0 || iBytesRead > 256) - { - CLibCEC::AddLog(CEC_LOG_ERROR, "error reading from serial port: %s", m_port->GetError().c_str()); - StopThread(false); return false; - } else if (iBytesRead > 0) { /* add the data to the current frame */ @@ -365,12 +379,14 @@ 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 { - if (!bIsRetry && output->Reply() == MSGCODE_COMMAND_REJECTED && msgCode != MSGCODE_SET_CONTROLLED) + if (!bIsRetry && output->Reply() == MSGCODE_COMMAND_REJECTED && msgCode != MSGCODE_SET_CONTROLLED && + msgCode != MSGCODE_GET_BUILDDATE /* same messagecode value had a different meaning in older fw builds */) { /* if the controller reported that the command was rejected, and we didn't send the command to set controlled mode, then the controller probably switched to auto mode. set controlled @@ -385,7 +401,7 @@ CCECAdapterMessage *CUSBCECAdapterCommunication::SendCommand(cec_adapter_message return output; } -bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = 10000 */) +bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = CEC_DEFAULT_CONNECT_TIMEOUT */) { bool bReturn(false); CTimeout timeout(iTimeoutMs > 0 ? iTimeoutMs : CEC_DEFAULT_TRANSMIT_WAIT); @@ -415,6 +431,9 @@ bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = 10000 */ else bReturn = true; + /* try to read the build date */ + m_commands->RequestBuildDate(); + SetInitialised(bReturn); return bReturn; } @@ -444,20 +463,22 @@ bool CUSBCECAdapterCommunication::IsInitialised(void) bool CUSBCECAdapterCommunication::StartBootloader(void) { - if (!IsRunning()) - return false; - - return m_commands->StartBootloader(); + if (m_port->IsOpen() && m_commands->StartBootloader()) + { + Close(); + return true; + } + return 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) @@ -465,14 +486,25 @@ uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void) return m_commands->GetFirmwareVersion(); } +uint32_t CUSBCECAdapterCommunication::GetFirmwareBuildDate(void) +{ + return m_commands->RequestBuildDate(); +} + +bool CUSBCECAdapterCommunication::IsRunningLatestFirmware(void) +{ + return GetFirmwareVersion() >= CEC_LATEST_ADAPTER_FW_VERSION && + GetFirmwareBuildDate() >= CEC_LATEST_ADAPTER_FW_DATE; +} + 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) @@ -482,7 +514,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) @@ -501,8 +533,8 @@ void *CAdapterPingThread::Process(void) { if (!m_com->PingAdapter()) { - /* sleep 1 second and retry */ - Sleep(1000); + /* sleep and retry */ + Sleep(CEC_DEFAULT_TRANSMIT_RETRY_WAIT); ++iFailedCounter; } else