X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fadapter%2FPulse-Eight%2FUSBCECAdapterCommunication.cpp;h=ae4c8ac60ebdc210e7706af77d55fac74dcf0bd5;hb=8b0462ea5e37459446a493c124e4c2d7a9e6b108;hp=fb16fe998321a57f18c42a657b3e81905228e6ff;hpb=6a581708f22be7d31ab7aa7242067b35d3540913;p=deb_libcec.git diff --git a/src/lib/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp b/src/lib/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp index fb16fe9..ae4c8ac 100644 --- a/src/lib/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp +++ b/src/lib/adapter/Pulse-Eight/USBCECAdapterCommunication.cpp @@ -55,8 +55,10 @@ using namespace PLATFORM; // 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 +// firmware date Thu Aug 2 08:31:24 UTC 2012 +#define CEC_LATEST_ADAPTER_FW_DATE 0x501a4b0c + +#define CEC_FW_DATE_EXTENDED_RESPONSE 0x501a4b0c #define LIB_CEC m_callback->GetLib() @@ -67,10 +69,9 @@ CUSBCECAdapterCommunication::CUSBCECAdapterCommunication(IAdapterCommunicationCa m_lastPollDestination(CECDEVICE_UNKNOWN), m_bInitialised(false), m_pingThread(NULL), + m_eepromWriteThread(NULL), m_commands(NULL), - m_adapterMessageQueue(NULL), - m_iLastEepromWrite(0), - m_iScheduleEepromWrite(0) + m_adapterMessageQueue(NULL) { m_logicalAddresses.Clear(); for (unsigned int iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++) @@ -171,17 +172,27 @@ bool CUSBCECAdapterCommunication::Open(uint32_t iTimeoutMs /* = CEC_DEFAULT_CONN } else if (bStartListening) { - /* start a ping thread, that will ping the adapter every 15 seconds - if it doesn't receive any ping for 30 seconds, it'll switch to auto mode */ - m_pingThread = new CAdapterPingThread(this, CEC_ADAPTER_PING_TIMEOUT); - if (m_pingThread->CreateThread()) + /* start the eeprom write thread, that handles all eeprom writes async */ + m_eepromWriteThread = new CAdapterEepromWriteThread(this); + if (!m_eepromWriteThread->CreateThread()) { - bConnectionOpened = true; + bConnectionOpened = false; + LIB_CEC->AddLog(CEC_LOG_ERROR, "could not create the eeprom write thread"); } else { - bConnectionOpened = false; - LIB_CEC->AddLog(CEC_LOG_ERROR, "could not create a ping thread"); + /* start a ping thread, that will ping the adapter every 15 seconds + if it doesn't receive any ping for 30 seconds, it'll switch to auto mode */ + m_pingThread = new CAdapterPingThread(this, CEC_ADAPTER_PING_TIMEOUT); + if (m_pingThread->CreateThread()) + { + bConnectionOpened = true; + } + else + { + bConnectionOpened = false; + LIB_CEC->AddLog(CEC_LOG_ERROR, "could not create a ping thread"); + } } } @@ -210,6 +221,11 @@ void CUSBCECAdapterCommunication::Close(void) m_adapterMessageQueue->Clear(); + /* stop and delete the write thread */ + if (m_eepromWriteThread) + m_eepromWriteThread->Stop(); + DELETE_AND_NULL(m_eepromWriteThread); + /* stop and delete the ping thread */ DELETE_AND_NULL(m_pingThread); @@ -244,7 +260,6 @@ void *CUSBCECAdapterCommunication::Process(void) CCECAdapterMessage msg; LIB_CEC->AddLog(CEC_LOG_DEBUG, "communication thread started"); - bool bWriteEeprom(false); while (!IsStopped()) { /* read from the serial port */ @@ -257,31 +272,6 @@ void *CUSBCECAdapterCommunication::Process(void) break; } - // check if we need to do another eeprom write - { - CLockObject lock(m_mutex); - int64_t iNow = GetTimeMs(); - if (m_iScheduleEepromWrite > 0 && - m_iScheduleEepromWrite >= iNow) - { - m_iScheduleEepromWrite = 0; - m_iLastEepromWrite = iNow; - bWriteEeprom = true; - } - } - - if (bWriteEeprom) - { - LIB_CEC->AddLog(CEC_LOG_DEBUG, "updating the eeprom (scheduled)"); - bWriteEeprom = false; - if (!m_commands->WriteEEPROM()) - { - // failed, retry later - CLockObject lock(m_mutex); - m_iScheduleEepromWrite = GetTimeMs() + CEC_ADAPTER_EEPROM_WRITE_RETRY; - } - } - /* TODO sleep 5 ms so other threads can get a lock */ Sleep(5); } @@ -403,7 +393,11 @@ bool CUSBCECAdapterCommunication::ReadFromDevice(uint32_t iTimeout, size_t iSize if (!IsOpen()) return false; - iBytesRead = m_port->Read(buff, sizeof(uint8_t) * iSize, iTimeout); + do { + /* retry Read() if it was interrupted */ + iBytesRead = m_port->Read(buff, sizeof(uint8_t) * iSize, iTimeout); + } while(m_port->GetErrorNumber() == EINTR); + if (m_port->GetErrorNumber()) { @@ -492,8 +486,14 @@ bool CUSBCECAdapterCommunication::CheckAdapter(uint32_t iTimeoutMs /* = CEC_DEFA else bReturn = true; - /* try to read the build date */ - m_commands->RequestBuildDate(); + if (m_commands->GetFirmwareVersion() >= 2) + { + /* try to read the build date */ + m_commands->RequestBuildDate(); + + /* try to read the adapter type */ + m_commands->RequestAdapterType(); + } SetInitialised(bReturn); return bReturn; @@ -571,47 +571,46 @@ uint16_t CUSBCECAdapterCommunication::GetFirmwareVersion(void) uint32_t CUSBCECAdapterCommunication::GetFirmwareBuildDate(void) { - return IsOpen() ? m_commands->RequestBuildDate() : m_commands ? m_commands->GetPersistedBuildDate() : 0; + uint32_t iBuildDate(0); + if (m_commands) + iBuildDate = m_commands->GetPersistedBuildDate(); + if (iBuildDate == 0 && IsOpen()) + iBuildDate = m_commands->RequestBuildDate(); + + return iBuildDate; +} + +cec_adapter_type CUSBCECAdapterCommunication::GetAdapterType(void) +{ + cec_adapter_type type(ADAPTERTYPE_UNKNOWN); + if (m_commands) + type = (cec_adapter_type)m_commands->GetPersistedAdapterType(); + if (type == ADAPTERTYPE_UNKNOWN && IsOpen()) + type = (cec_adapter_type)m_commands->RequestAdapterType(); + + return type; +} + +bool CUSBCECAdapterCommunication::ProvidesExtendedResponse(void) +{ + uint32_t iBuildDate(0); + if (m_commands) + iBuildDate = m_commands->GetPersistedBuildDate(); + + return iBuildDate >= CEC_FW_DATE_EXTENDED_RESPONSE; } bool CUSBCECAdapterCommunication::IsRunningLatestFirmware(void) { - return GetFirmwareVersion() >= CEC_LATEST_ADAPTER_FW_VERSION && - GetFirmwareBuildDate() >= CEC_LATEST_ADAPTER_FW_DATE; + return GetFirmwareBuildDate() >= CEC_LATEST_ADAPTER_FW_DATE && + GetFirmwareVersion() >= CEC_LATEST_ADAPTER_FW_VERSION; } bool CUSBCECAdapterCommunication::PersistConfiguration(const libcec_configuration &configuration) { - if (IsOpen()) - { - // returns true when something changed - if (m_commands->PersistConfiguration(configuration)) - { - { - CLockObject lock(m_mutex); - uint64_t iNow = GetTimeMs(); - if (iNow - m_iLastEepromWrite < CEC_ADAPTER_EEPROM_WRITE_INTERVAL) - { - // if there was more than 1 write within the last 30 seconds, schedule another one - if (m_iScheduleEepromWrite == 0) - m_iScheduleEepromWrite = m_iLastEepromWrite + CEC_ADAPTER_EEPROM_WRITE_INTERVAL; - return true; - } - else - { - m_iLastEepromWrite = iNow; - } - } - - if (!m_commands->WriteEEPROM()) - { - // write failed, retry later - CLockObject lock(m_mutex); - m_iScheduleEepromWrite = GetTimeMs() + CEC_ADAPTER_EEPROM_WRITE_RETRY; - } - } - } - return IsOpen() ? m_commands->PersistConfiguration(configuration) : false; + return IsOpen() ? + m_commands->PersistConfiguration(configuration) && m_eepromWriteThread->Write() : + false; } bool CUSBCECAdapterCommunication::GetConfiguration(libcec_configuration &configuration) @@ -700,7 +699,62 @@ void *CAdapterPingThread::Process(void) } } - Sleep(500); + Sleep(5); + } + return NULL; +} + +void CAdapterEepromWriteThread::Stop(void) +{ + StopThread(-1); + { + CLockObject lock(m_mutex); + if (m_iScheduleEepromWrite > 0) + m_com->LIB_CEC->AddLog(CEC_LOG_WARNING, "write thread stopped while a write was queued"); + m_condition.Signal(); + } + StopThread(); +} + +void *CAdapterEepromWriteThread::Process(void) +{ + while (!IsStopped()) + { + CLockObject lock(m_mutex); + if ((m_iScheduleEepromWrite > 0 && m_iScheduleEepromWrite < GetTimeMs()) || + m_condition.Wait(m_mutex, m_bWrite, 100)) + { + m_bWrite = false; + if (m_com->m_commands->WriteEEPROM()) + { + m_iLastEepromWrite = GetTimeMs(); + m_iScheduleEepromWrite = 0; + } + else + { + m_iScheduleEepromWrite = GetTimeMs() + CEC_ADAPTER_EEPROM_WRITE_RETRY; + } + } } return NULL; } + +bool CAdapterEepromWriteThread::Write(void) +{ + CLockObject lock(m_mutex); + if (m_iScheduleEepromWrite == 0) + { + int64_t iNow = GetTimeMs(); + if (m_iLastEepromWrite + CEC_ADAPTER_EEPROM_WRITE_INTERVAL > iNow) + { + m_com->LIB_CEC->AddLog(CEC_LOG_DEBUG, "delaying eeprom write by %ld ms", m_iLastEepromWrite + CEC_ADAPTER_EEPROM_WRITE_INTERVAL - iNow); + m_iScheduleEepromWrite = m_iLastEepromWrite + CEC_ADAPTER_EEPROM_WRITE_INTERVAL; + } + else + { + m_bWrite = true; + m_condition.Signal(); + } + } + return true; +}