remove all pre-v2.0 compatibility checks
[deb_libcec.git] / src / lib / CECProcessor.cpp
index 34ffed58db84902d286a2532b78223f3b58af9c8..824744cc061d9e52bfd11c69099508d050b81575 100644 (file)
@@ -63,13 +63,17 @@ CCECProcessor::CCECProcessor(CLibCEC *libcec) :
     m_iStandardLineTimeout(3),
     m_iRetryLineTimeout(3),
     m_iLastTransmission(0),
-    m_bMonitor(true)
+    m_bMonitor(true),
+    m_addrAllocator(NULL),
+    m_bStallCommunication(false)
 {
   m_busDevices = new CCECDeviceMap(this);
 }
 
 CCECProcessor::~CCECProcessor(void)
 {
+  m_bStallCommunication = false;
+  DELETE_AND_NULL(m_addrAllocator);
   Close();
   DELETE_AND_NULL(m_busDevices);
 }
@@ -100,6 +104,8 @@ void CCECProcessor::Close(void)
   SetCECInitialised(false);
 
   // stop the processor
+  StopThread(-1);
+  m_inBuffer.Broadcast();
   StopThread();
 
   // close the connection
@@ -218,7 +224,7 @@ void *CCECProcessor::Process(void)
     if (m_inBuffer.Pop(command, CEC_PROCESSOR_SIGNAL_WAIT_TIME))
       ProcessCommand(command);
 
-    if (CECInitialised())
+    if (CECInitialised() && !IsStopped())
     {
       // check clients for keypress timeouts
       m_libcec->CheckKeypressTimeout();
@@ -410,6 +416,9 @@ bool CCECProcessor::Transmit(const cec_command &data, bool bIsReply)
     }
   }
 
+  // wait until we finished allocating a new LA if it got lost
+  while (m_bStallCommunication) Sleep(5);
+
   {
     CLockObject lock(m_mutex);
     m_iLastTransmission = GetTimeMs();
@@ -430,7 +439,9 @@ bool CCECProcessor::Transmit(const cec_command &data, bool bIsReply)
     iLineTimeout = m_iRetryLineTimeout;
   }
 
-  return adapterState == ADAPTER_MESSAGE_STATE_SENT_ACKED;
+  return bIsReply ?
+      adapterState == ADAPTER_MESSAGE_STATE_SENT_ACKED || adapterState == ADAPTER_MESSAGE_STATE_SENT || adapterState == ADAPTER_MESSAGE_STATE_WAITING_TO_BE_SENT :
+      adapterState == ADAPTER_MESSAGE_STATE_SENT_ACKED;
 }
 
 void CCECProcessor::TransmitAbort(cec_logical_address source, cec_logical_address destination, cec_opcode opcode, cec_abort_reason reason /* = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE */)
@@ -684,6 +695,9 @@ bool CCECProcessor::AllocateLogicalAddresses(CCECClient* client)
   // set the new ackmask
   SetLogicalAddresses(GetLogicalAddresses());
 
+  // resume outgoing communication
+  m_bStallCommunication = false;
+
   return true;
 }
 
@@ -694,7 +708,13 @@ bool CCECProcessor::RegisterClient(CCECClient *client)
 
   libcec_configuration &configuration = *client->GetConfiguration();
 
-  if (configuration.clientVersion >= CEC_CLIENT_VERSION_1_6_3 && configuration.bMonitorOnly == 1)
+  if (configuration.clientVersion < CEC_CLIENT_VERSION_2_0_0)
+  {
+    m_libcec->AddLog(CEC_LOG_ERROR, "failed to register a new CEC client: client version %s is no longer supported", ToString((cec_client_version)configuration.clientVersion));
+    return false;
+  }
+
+  if (configuration.bMonitorOnly == 1)
     return true;
 
   if (!CECInitialised())
@@ -841,7 +861,7 @@ bool CCECProcessor::UnregisterClient(CCECClient *client)
 
 void CCECProcessor::UnregisterClients(void)
 {
-  m_libcec->AddLog(CEC_LOG_NOTICE, "unregistering all CEC clients");
+  m_libcec->AddLog(CEC_LOG_DEBUG, "unregistering all CEC clients");
 
   vector<CCECClient *> clients = m_libcec->GetClients();
   for (vector<CCECClient *>::iterator client = clients.begin(); client != clients.end(); client++)
@@ -914,18 +934,42 @@ void CCECProcessor::SwitchMonitoring(bool bSwitchTo)
     UnregisterClients();
 }
 
-void CCECProcessor::HandleLogicalAddressLost(cec_logical_address oldAddress, cec_logical_address newAddress)
+void CCECProcessor::HandleLogicalAddressLost(cec_logical_address oldAddress)
 {
-  m_libcec->AddLog(CEC_LOG_NOTICE, "logical address %x was taken by another device, changed to %x", oldAddress, newAddress);
+  // stall outgoing messages until we know our new LA
+  m_bStallCommunication = true;
+
+  m_libcec->AddLog(CEC_LOG_NOTICE, "logical address %x was taken by another device, allocating a new address", oldAddress);
   CCECClient* client = GetClient(oldAddress);
+  if (!client)
+    client = GetPrimaryClient();
   if (client)
   {
-    if (newAddress == CECDEVICE_UNKNOWN)
-      UnregisterClient(client);
-    else
-    {
-      client->m_configuration.logicalAddresses.Unset(oldAddress);
-      client->m_configuration.logicalAddresses.Set(newAddress);
-    }
+    if (m_addrAllocator)
+      while (m_addrAllocator->IsRunning()) Sleep(5);
+    delete m_addrAllocator;
+
+    m_addrAllocator = new CCECAllocateLogicalAddress(this, client);
+    m_addrAllocator->CreateThread();
   }
 }
+
+uint16_t CCECProcessor::GetAdapterVendorId(void) const
+{
+  return m_communication ? m_communication->GetAdapterVendorId() : 0;
+}
+
+uint16_t CCECProcessor::GetAdapterProductId(void) const
+{
+  return m_communication ? m_communication->GetAdapterProductId() : 0;
+}
+
+CCECAllocateLogicalAddress::CCECAllocateLogicalAddress(CCECProcessor* processor, CCECClient* client) :
+    m_processor(processor),
+    m_client(client) { }
+
+void* CCECAllocateLogicalAddress::Process(void)
+{
+  m_processor->AllocateLogicalAddresses(m_client);
+  return NULL;
+}