* http://www.pulse-eight.net/
*/
+#include "env.h"
#include "USBCECAdapterCommunication.h"
+
#include "USBCECAdapterCommands.h"
#include "USBCECAdapterMessageQueue.h"
-#include "../platform/sockets/serialport.h"
-#include "../platform/util/timeutils.h"
-#include "../platform/util/util.h"
-#include "../platform/util/edid.h"
-#include "../platform/adl/adl-edid.h"
-#include "../platform/nvidia/nv-edid.h"
-#include "../LibCEC.h"
-#include "../CECProcessor.h"
+#include "USBCECAdapterMessage.h"
+#include "lib/platform/sockets/serialport.h"
+#include "lib/platform/util/timeutils.h"
+#include "lib/platform/util/util.h"
+#include "lib/platform/util/edid.h"
+#include "lib/platform/adl/adl-edid.h"
+#include "lib/platform/nvidia/nv-edid.h"
+#include "lib/LibCEC.h"
+#include "lib/CECProcessor.h"
using namespace std;
using namespace CEC;
using namespace PLATFORM;
-#define CEC_ADAPTER_PING_TIMEOUT 15000
+#define CEC_ADAPTER_PING_TIMEOUT 15000
+#define CEC_ADAPTER_EEPROM_WRITE_INTERVAL 30000
+#define CEC_ADAPTER_EEPROM_WRITE_RETRY 5000
// firmware version 2
#define CEC_LATEST_ADAPTER_FW_VERSION 2
m_pingThread(NULL),
m_commands(NULL),
m_adapterMessageQueue(NULL),
- m_iAckMask(0xFFFF)
+ m_iLastEepromWrite(0),
+ m_iScheduleEepromWrite(0)
{
+ m_logicalAddresses.Clear();
for (unsigned int iPtr = CECDEVICE_TV; iPtr < CECDEVICE_BROADCAST; iPtr++)
m_bWaitingForAck[iPtr] = false;
m_port = new CSerialPort(strPort, iBaudRate);
}
// always start by setting the ackmask to 0, to clear previous values
- SetAckMask(0);
+ cec_logical_addresses addresses; addresses.Clear();
+ SetLogicalAddresses(addresses);
if (!CreateThread())
{
if (IsOpen() && m_port->GetErrorNumber() == 0)
{
LIB_CEC->AddLog(CEC_LOG_DEBUG, "%s - closing the connection", __FUNCTION__);
- SetAckMask(0);
+ cec_logical_addresses addresses; addresses.Clear();
+ SetLogicalAddresses(addresses);
if (m_commands->GetFirmwareVersion() >= 2)
SetControlledMode(false);
}
m_port->Close();
}
-cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout)
+cec_adapter_message_state CUSBCECAdapterCommunication::Write(const cec_command &data, bool &bRetry, uint8_t iLineTimeout, bool UNUSED(bIsReply))
{
cec_adapter_message_state retVal(ADAPTER_MESSAGE_STATE_UNKNOWN);
if (!IsRunning())
CCECAdapterMessage msg;
LIB_CEC->AddLog(CEC_LOG_DEBUG, "communication thread started");
+ bool bWriteEeprom(false);
while (!IsStopped())
{
/* read from the serial port */
break;
}
+ // check if we need to do another eeprom write
+ {
+ CLockObject lock(m_mutex);
+ uint64_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);
}
return !IsStopped() && m_port->IsOpen() && IsRunning();
}
-CStdString CUSBCECAdapterCommunication::GetError(void) const
+std::string CUSBCECAdapterCommunication::GetError(void) const
{
return m_port->GetError();
}
return false;
}
-bool CUSBCECAdapterCommunication::SetAckMask(uint16_t iMask)
+bool CUSBCECAdapterCommunication::SetLogicalAddresses(const cec_logical_addresses &addresses)
{
{
CLockObject lock(m_mutex);
- if (m_iAckMask == iMask)
+ if (m_logicalAddresses == addresses)
return true;
}
- if (IsOpen() && m_commands->SetAckMask(iMask))
+ if (IsOpen() && m_commands->SetAckMask(addresses.AckMask()))
{
CLockObject lock(m_mutex);
- m_iAckMask = iMask;
+ m_logicalAddresses = addresses;
return true;
}
return false;
}
-uint16_t CUSBCECAdapterCommunication::GetAckMask(void)
+cec_logical_addresses CUSBCECAdapterCommunication::GetLogicalAddresses(void)
{
+ cec_logical_addresses addresses;
CLockObject lock(m_mutex);
- return m_iAckMask;
+ addresses = m_logicalAddresses;
+ return addresses;
}
bool CUSBCECAdapterCommunication::PingAdapter(void)
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->GetConfiguration(configuration) : false;
}
-CStdString CUSBCECAdapterCommunication::GetPortName(void)
+std::string CUSBCECAdapterCommunication::GetPortName(void)
{
return m_port->GetName();
}