rpi: handle vendor specific remote control presses. closes #42
[deb_libcec.git] / src / lib / adapter / RPi / RPiCECAdapterCommunication.cpp
index 5e1efd493f4a8117018816616870219974d5d3fe..9176647f9f02630e212fa5d7363f84a26798620d 100644 (file)
@@ -58,16 +58,42 @@ void rpi_cec_callback(void *callback_data, uint32_t p0, uint32_t p1, uint32_t p2
     static_cast<CRPiCECAdapterCommunication *>(callback_data)->OnDataReceived(p0, p1, p2, p3, p4);
 }
 
+CRPiCECAdapterFindNewLogicalAddress::CRPiCECAdapterFindNewLogicalAddress(CRPiCECAdapterCommunication* communication, const cec_logical_address address) :
+    m_communication(communication),
+    m_address(address) { }
+
+void *CRPiCECAdapterFindNewLogicalAddress::Process(void)
+{
+  cec_logical_address newAddress(CECDEVICE_UNKNOWN);
+  for (unsigned int iLA = CECDEVICE_RECORDINGDEVICE1; newAddress == CECDEVICE_UNKNOWN && iLA < CECDEVICE_BROADCAST; iLA++)
+  {
+    if (CCECTypeUtils::GetType((cec_logical_address)iLA) == CCECTypeUtils::GetType(m_address) &&
+        m_communication->SupportsSourceLogicalAddress((cec_logical_address)iLA) &&
+        m_communication->RegisterLogicalAddress((cec_logical_address)iLA))
+      newAddress = (cec_logical_address)iLA;
+  }
+
+  m_communication->m_callback->HandleLogicalAddressLost(m_address, newAddress);
+  return NULL;
+}
+
 CRPiCECAdapterCommunication::CRPiCECAdapterCommunication(IAdapterCommunicationCallback *callback) :
     IAdapterCommunication(callback),
     m_logicalAddress(CECDEVICE_UNKNOWN),
-    m_bLogicalAddressChanged(false)
+    m_bLogicalAddressChanged(false),
+    m_laLost(NULL)
 {
   m_queue = new CRPiCECAdapterMessageQueue(this);
 }
 
 CRPiCECAdapterCommunication::~CRPiCECAdapterCommunication(void)
 {
+  if (m_laLost)
+  {
+    m_laLost->StopThread();
+    delete m_laLost;
+    m_laLost = NULL;
+  }
   delete(m_queue);
   Close();
 }
@@ -142,10 +168,14 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
     }
     break;
   case VC_CEC_BUTTON_PRESSED:
+  case VC_CEC_REMOTE_PRESSED:
     {
       // translate into a cec_command
       cec_command command;
-      cec_command::Format(command, (cec_logical_address)CEC_CB_INITIATOR(p0), (cec_logical_address)CEC_CB_FOLLOWER(p0), CEC_OPCODE_USER_CONTROL_PRESSED);
+      cec_command::Format(command,
+                          (cec_logical_address)CEC_CB_INITIATOR(p0),
+                          (cec_logical_address)CEC_CB_FOLLOWER(p0),
+                          reason == VC_CEC_BUTTON_PRESSED ? CEC_OPCODE_USER_CONTROL_PRESSED : CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN);
       command.parameters.PushBack((uint8_t)CEC_CB_OPERAND1(p0));
 
       // send to libCEC
@@ -153,10 +183,14 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
     }
     break;
   case VC_CEC_BUTTON_RELEASE:
+  case VC_CEC_REMOTE_RELEASE:
     {
       // translate into a cec_command
       cec_command command;
-      cec_command::Format(command, (cec_logical_address)CEC_CB_INITIATOR(p0), (cec_logical_address)CEC_CB_FOLLOWER(p0), CEC_OPCODE_USER_CONTROL_RELEASE);
+      cec_command::Format(command,
+                          (cec_logical_address)CEC_CB_INITIATOR(p0),
+                          (cec_logical_address)CEC_CB_FOLLOWER(p0),
+                          reason == VC_CEC_BUTTON_PRESSED ? CEC_OPCODE_USER_CONTROL_RELEASE : CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP);
       command.parameters.PushBack((uint8_t)CEC_CB_OPERAND1(p0));
 
       // send to libCEC
@@ -180,9 +214,20 @@ void CRPiCECAdapterCommunication::OnDataReceived(uint32_t header, uint32_t p0, u
       m_logicalAddressCondition.Signal();
     }
     break;
+  case VC_CEC_LOGICAL_ADDR_LOST:
+    {
+      // the logical address was taken by another device
+      cec_logical_address previousAddress = m_logicalAddress;
+      m_logicalAddress = CECDEVICE_UNKNOWN;
+
+      if (m_laLost && !m_laLost->IsRunning())
+        delete m_laLost;
+      m_laLost = new CRPiCECAdapterFindNewLogicalAddress(this, previousAddress);
+      if (m_laLost)
+        m_laLost->CreateThread();
+    }
+    break;
   case VC_CEC_TOPOLOGY:
-  case VC_CEC_REMOTE_PRESSED:
-  case VC_CEC_REMOTE_RELEASE:
     break;
   default:
     LIB_CEC->AddLog(CEC_LOG_DEBUG, "ignoring unknown reason %x", reason);