cec: increase the transmit timeout for LG devices
authorLars Op den Kamp <lars@opdenkamp.eu>
Sun, 4 Dec 2011 02:08:15 +0000 (03:08 +0100)
committerLars Op den Kamp <lars@opdenkamp.eu>
Sun, 4 Dec 2011 02:28:30 +0000 (03:28 +0100)
include/cectypes.h
src/lib/devices/CECBusDevice.cpp
src/lib/devices/CECBusDevice.h
src/lib/implementations/SLCommandHandler.cpp

index c13f3491367dfa223b0dc7ea34c681ed5986b0f2..e6cd0b4e942967783474a23cb2fcec4ffd62f399 100644 (file)
@@ -713,11 +713,12 @@ typedef struct cec_command
     return *this;
   }
 
-  static void Format(cec_command &command, cec_logical_address initiator, cec_logical_address destination, cec_opcode opcode)
+  static void Format(cec_command &command, cec_logical_address initiator, cec_logical_address destination, cec_opcode opcode, int32_t timeout = 1000)
   {
     command.Clear();
-    command.initiator    = initiator;
-    command.destination  = destination;
+    command.initiator        = initiator;
+    command.destination      = destination;
+    command.transmit_timeout = timeout;
     if (opcode != CEC_OPCODE_NONE)
     {
       command.opcode     = opcode;
@@ -749,7 +750,7 @@ typedef struct cec_command
     eom              = 0;
     opcode_set       = 0;
     opcode           = CEC_OPCODE_FEATURE_ABORT;
-    transmit_timeout = 1000;
+    transmit_timeout = 0;
     retries          = 4;
     parameters.Clear();
   };
index 5cfca5914c10bb890b07cf0a2a7f0cce80c69b1b..01be1d2254f1398486e1cc1ed00333c1a50be176 100644 (file)
@@ -55,7 +55,8 @@ CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogi
   m_iLastCommandSent(0),
   m_iLastActive(0),
   m_cecVersion(CEC_VERSION_UNKNOWN),
-  m_deviceStatus(CEC_DEVICE_STATUS_UNKNOWN)
+  m_deviceStatus(CEC_DEVICE_STATUS_UNKNOWN),
+  m_iTransmitTimeout(1000)
 {
   m_handler = new CCECCommandHandler(this);
 
@@ -104,7 +105,7 @@ bool CCECBusDevice::PowerOn(void)
   AddLog(CEC_LOG_DEBUG, strLog.c_str());
 
   cec_command command;
-  cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_IMAGE_VIEW_ON);
+  cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_IMAGE_VIEW_ON, m_iTransmitTimeout);
   if (m_processor->Transmit(command))
   {
     {
@@ -130,7 +131,7 @@ bool CCECBusDevice::Standby(void)
   AddLog(CEC_LOG_DEBUG, strLog.c_str());
 
   cec_command command;
-  cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_STANDBY);
+  cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_STANDBY, m_iTransmitTimeout);
 
   return m_processor->Transmit(command);
 }
@@ -156,7 +157,7 @@ bool CCECBusDevice::RequestCecVersion(void)
     strLog.Format("<< requesting CEC version of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
     cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_CEC_VERSION);
+    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_CEC_VERSION, m_iTransmitTimeout);
     CLockObject lock(&m_transmitMutex);
     if (m_processor->Transmit(command))
       bReturn = m_condition.Wait(&m_transmitMutex, 1000);
@@ -193,7 +194,7 @@ bool CCECBusDevice::RequestMenuLanguage(void)
     strLog.Format("<< requesting menu language of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
     cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_MENU_LANGUAGE);
+    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_MENU_LANGUAGE, m_iTransmitTimeout);
     CLockObject lock(&m_transmitMutex);
     if (m_processor->Transmit(command))
       bReturn = m_condition.Wait(&m_transmitMutex, 1000);
@@ -230,7 +231,7 @@ bool CCECBusDevice::RequestOSDName(void)
     strLog.Format("<< requesting OSD name of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
     cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_OSD_NAME);
+    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_OSD_NAME, m_iTransmitTimeout);
     CLockObject lock(&m_transmitMutex);
     if (m_processor->Transmit(command))
       bReturn = m_condition.Wait(&m_transmitMutex, 1000);
@@ -260,7 +261,7 @@ bool CCECBusDevice::RequestPhysicalAddress(void)
     strLog.Format("<< requesting physical address of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
     cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_PHYSICAL_ADDRESS);
+    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_PHYSICAL_ADDRESS, m_iTransmitTimeout);
     CLockObject lock(&m_transmitMutex);
     if (m_processor->Transmit(command))
       bReturn = m_condition.Wait(&m_transmitMutex, 1000);
@@ -287,7 +288,7 @@ bool CCECBusDevice::RequestPowerStatus(void)
     strLog.Format("<< requesting power status of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
     cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_POWER_STATUS);
+    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_POWER_STATUS, m_iTransmitTimeout);
     CLockObject lock(&m_transmitMutex);
     if (m_processor->Transmit(command))
       bReturn = m_condition.Wait(&m_transmitMutex, 1000);
@@ -314,7 +315,7 @@ bool CCECBusDevice::RequestVendorId(void)
     strLog.Format("<< requesting vendor ID of '%s' (%X)", GetLogicalAddressName(), m_iLogicalAddress);
     AddLog(CEC_LOG_NOTICE, strLog);
     cec_command command;
-    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID);
+    cec_command::Format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID, m_iTransmitTimeout);
 
     CLockObject lock(&m_transmitMutex);
     if (m_processor->Transmit(command))
@@ -629,7 +630,7 @@ bool CCECBusDevice::TransmitActiveSource(void)
     AddLog(CEC_LOG_NOTICE, strLog);
 
     cec_command command;
-    cec_command::Format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE);
+    cec_command::Format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_ACTIVE_SOURCE, m_iTransmitTimeout);
     command.parameters.PushBack((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF));
     command.parameters.PushBack((uint8_t) (m_iPhysicalAddress & 0xFF));
 
@@ -654,7 +655,7 @@ bool CCECBusDevice::TransmitCECVersion(cec_logical_address dest)
   AddLog(CEC_LOG_NOTICE, strLog);
 
   cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_CEC_VERSION);
+  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_CEC_VERSION, m_iTransmitTimeout);
   command.parameters.PushBack((uint8_t)m_cecVersion);
 
   lock.Leave();
@@ -668,7 +669,7 @@ bool CCECBusDevice::TransmitInactiveSource(void)
   AddLog(CEC_LOG_NOTICE, strLog);
 
   cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, CECDEVICE_TV, CEC_OPCODE_INACTIVE_SOURCE);
+  cec_command::Format(command, m_iLogicalAddress, CECDEVICE_TV, CEC_OPCODE_INACTIVE_SOURCE, m_iTransmitTimeout);
   command.parameters.PushBack((m_iPhysicalAddress >> 8) & 0xFF);
   command.parameters.PushBack(m_iPhysicalAddress & 0xFF);
 
@@ -682,7 +683,7 @@ bool CCECBusDevice::TransmitMenuState(cec_logical_address dest)
   AddLog(CEC_LOG_NOTICE, strLog);
 
   cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_MENU_STATUS);
+  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_MENU_STATUS, m_iTransmitTimeout);
   command.parameters.PushBack((uint8_t)m_menuState);
 
   return m_processor->Transmit(command);
@@ -696,7 +697,7 @@ bool CCECBusDevice::TransmitOSDName(cec_logical_address dest)
   AddLog(CEC_LOG_NOTICE, strLog.c_str());
 
   cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_OSD_NAME);
+  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_OSD_NAME, m_iTransmitTimeout);
   for (unsigned int iPtr = 0; iPtr < m_strDeviceName.length(); iPtr++)
     command.parameters.PushBack(m_strDeviceName.at(iPtr));
 
@@ -712,7 +713,7 @@ bool CCECBusDevice::TransmitOSDString(cec_logical_address dest, cec_display_cont
   AddLog(CEC_LOG_NOTICE, strLog.c_str());
 
   cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_OSD_STRING);
+  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_SET_OSD_STRING, m_iTransmitTimeout);
   command.parameters.PushBack((uint8_t)duration);
 
   unsigned int iLen = strlen(strMessage);
@@ -733,7 +734,7 @@ bool CCECBusDevice::TransmitPhysicalAddress(void)
   AddLog(CEC_LOG_NOTICE, strLog.c_str());
 
   cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_REPORT_PHYSICAL_ADDRESS);
+  cec_command::Format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_REPORT_PHYSICAL_ADDRESS, m_iTransmitTimeout);
   command.parameters.PushBack((uint8_t) ((m_iPhysicalAddress >> 8) & 0xFF));
   command.parameters.PushBack((uint8_t) (m_iPhysicalAddress & 0xFF));
   command.parameters.PushBack((uint8_t) (m_type));
@@ -753,7 +754,7 @@ bool CCECBusDevice::TransmitPoll(cec_logical_address dest)
   AddLog(CEC_LOG_NOTICE, strLog.c_str());
 
   cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_NONE);
+  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_NONE, m_iTransmitTimeout);
   command.retries = 0;
 
   {
@@ -780,7 +781,7 @@ bool CCECBusDevice::TransmitPowerState(cec_logical_address dest)
   AddLog(CEC_LOG_NOTICE, strLog.c_str());
 
   cec_command command;
-  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_REPORT_POWER_STATUS);
+  cec_command::Format(command, m_iLogicalAddress, dest, CEC_OPCODE_REPORT_POWER_STATUS, m_iTransmitTimeout);
   command.parameters.PushBack((uint8_t) m_powerStatus);
 
   lock.Leave();
@@ -807,7 +808,7 @@ bool CCECBusDevice::TransmitVendorID(cec_logical_address dest)
     AddLog(CEC_LOG_NOTICE, strLog);
 
     cec_command command;
-    cec_command::Format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_DEVICE_VENDOR_ID);
+    cec_command::Format(command, m_iLogicalAddress, CECDEVICE_BROADCAST, CEC_OPCODE_DEVICE_VENDOR_ID, m_iTransmitTimeout);
 
     command.parameters.PushBack((uint8_t) (((uint64_t)m_vendor >> 16) & 0xFF));
     command.parameters.PushBack((uint8_t) (((uint64_t)m_vendor >> 8) & 0xFF));
@@ -822,7 +823,7 @@ bool CCECBusDevice::SendKeypress(cec_user_control_code key, bool bWait /* = fals
 {
   CLockObject lock(&m_transmitMutex);
   cec_command command;
-  cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_PRESSED);
+  cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_PRESSED, m_iTransmitTimeout);
   command.parameters.PushBack((uint8_t)key);
 
   if (bWait)
@@ -839,7 +840,7 @@ bool CCECBusDevice::SendKeyRelease(bool bWait /* = false */)
 {
   CLockObject lock(&m_transmitMutex);
   cec_command command;
-  cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_RELEASE);
+  cec_command::Format(command, m_processor->GetLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_USER_CONTROL_RELEASE, m_iTransmitTimeout);
 
   if (bWait)
   {
index 01b74c2de6b57fac04477f6f2e5569a4d01fdbd9..0097dd4f28eb49e0e45cf7472be1bcdffa37886a 100644 (file)
@@ -69,6 +69,7 @@ namespace CEC
     virtual cec_device_type       GetType(void) const { return m_type; }
     virtual cec_vendor_id         GetVendorId(void);
     virtual const char *          GetVendorName(void);
+    virtual int32_t               GetTransmitTimeout(void) const { return m_iTransmitTimeout; }
     virtual bool                  MyLogicalAddressContains(cec_logical_address address) const;
     virtual cec_bus_device_status GetStatus(bool bForcePoll = false);
 
@@ -92,6 +93,7 @@ namespace CEC
     virtual void SetMenuState(const cec_menu_state state);
     virtual void SetVendorId(uint64_t iVendorId);
     virtual void SetPowerStatus(const cec_power_status powerStatus);
+    virtual void SetTransmitTimeout(uint32_t iTimeout) { m_iTransmitTimeout = iTimeout; }
 
     virtual bool TransmitActiveSource(void);
     virtual bool TransmitCECVersion(cec_logical_address dest);
@@ -125,6 +127,7 @@ namespace CEC
     uint64_t              m_iLastActive;
     cec_version           m_cecVersion;
     cec_bus_device_status m_deviceStatus;
+    int32_t               m_iTransmitTimeout;
     CMutex                m_transmitMutex;
     CMutex                m_writeMutex;
     CMutex                m_mutex;
index d442eaf44a09fd6650832309044518baac45533f..2270d169161ca77a2993b717d456ef55d3203bcf 100644 (file)
@@ -50,7 +50,7 @@ bool CSLCommandHandler::HandleVendorCommand(const cec_command &command)
   {
     /* enable SL */
     cec_command response;
-    cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND);
+    cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND, m_busDevice->GetTransmitTimeout());
     response.PushBack(0x02);
     response.PushBack(0x05);
 
@@ -82,7 +82,7 @@ bool CSLCommandHandler::HandleVendorCommand(const cec_command &command)
 bool CSLCommandHandler::TransmitLGVendorId(const cec_logical_address iInitiator, const cec_logical_address iDestination)
 {
   cec_command response;
-  cec_command::Format(response, iInitiator, iDestination, CEC_OPCODE_VENDOR_COMMAND);
+  cec_command::Format(response, iInitiator, iDestination, CEC_OPCODE_VENDOR_COMMAND, m_busDevice->GetTransmitTimeout());
   response.parameters.PushBack((uint8_t) (((uint64_t)CEC_VENDOR_LG >> 16) & 0xFF));
   response.parameters.PushBack((uint8_t) (((uint64_t)CEC_VENDOR_LG >> 8) & 0xFF));
   response.parameters.PushBack((uint8_t) ((uint64_t)CEC_VENDOR_LG & 0xFF));
@@ -152,13 +152,19 @@ bool CSLCommandHandler::InitHandler(void)
   if (m_busDevice->GetLogicalAddress() != CECDEVICE_TV)
     return true;
 
+  /* LG TVs don't always reply to CEC version requests, so just set it to 1.3a */
+  m_busDevice->GetProcessor()->m_busDevices[CECDEVICE_TV]->SetCecVersion(CEC_VERSION_1_3A);
+
   /* LG TVs only route keypresses when the deck status is set to 0x20 */
   cec_logical_addresses addr = m_busDevice->GetProcessor()->GetLogicalAddresses();
   for (uint8_t iPtr = 0; iPtr < 15; iPtr++)
   {
+    CCECBusDevice *device = m_busDevice->GetProcessor()->m_busDevices[iPtr];
+
+    /* increase the transmit timeout because the tv is keeping the bus busy at times */
+    device->SetTransmitTimeout(3000);
     if (addr[iPtr])
     {
-      CCECBusDevice *device = m_busDevice->GetProcessor()->m_busDevices[iPtr];
       if (device && (device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE ||
                      device->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE))
       {