cec: added buttoncode for 'channels list' on samsung (0x96)
[deb_libcec.git] / src / lib / implementations / CECCommandHandler.cpp
index f742fc9922b98bedefecb36314471326b5e64eb8..0668ee793bd16e3e6c1b47c58b3f8b76df251302 100644 (file)
@@ -48,21 +48,22 @@ CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice) :
     m_iTransmitWait(CEC_DEFAULT_TRANSMIT_WAIT),
     m_iTransmitRetries(CEC_DEFAULT_TRANSMIT_RETRIES),
     m_bHandlerInited(false),
-    m_expectedResponse(CEC_OPCODE_NONE),
-    m_lastCommandSent(CEC_OPCODE_NONE),
     m_bOPTSendDeckStatusUpdateOnActiveSource(false),
     m_vendorId(CEC_VENDOR_UNKNOWN),
-    m_bRcvSignal(false)
+    m_waitForResponse(new CWaitForResponse)
 {
 }
 
 CCECCommandHandler::~CCECCommandHandler(void)
 {
-  m_condition.Broadcast();
+  delete m_waitForResponse;
 }
 
 bool CCECCommandHandler::HandleCommand(const cec_command &command)
 {
+  if (command.opcode_set == 0)
+    return HandlePoll(command);
+
   bool bHandled(true);
 
   CLibCEC::AddCommand(command);
@@ -189,16 +190,7 @@ bool CCECCommandHandler::HandleCommand(const cec_command &command)
   }
 
   if (bHandled)
-  {
-    CLockObject lock(m_receiveMutex);
-    if (m_expectedResponse == CEC_OPCODE_NONE ||
-        m_expectedResponse == command.opcode ||
-        (command.opcode == CEC_OPCODE_FEATURE_ABORT && command.parameters.size > 0 && command.parameters[0] == m_lastCommandSent))
-    {
-      m_bRcvSignal = true;
-      m_condition.Signal();
-    }
-  }
+    m_waitForResponse->Received((command.opcode == CEC_OPCODE_FEATURE_ABORT && command.parameters.size > 0) ? (cec_opcode)command.parameters[0] : command.opcode);
 
   return bHandled;
 }
@@ -253,7 +245,9 @@ bool CCECCommandHandler::HandleDeviceVendorId(const cec_command &command)
 
 bool CCECCommandHandler::HandleFeatureAbort(const cec_command &command)
 {
-  if (command.parameters.size == 2 && command.parameters[1] == CEC_ABORT_REASON_UNRECOGNIZED_OPCODE)
+  if (command.parameters.size == 2 &&
+        (command.parameters[1] == CEC_ABORT_REASON_UNRECOGNIZED_OPCODE ||
+         command.parameters[1] == CEC_ABORT_REASON_REFUSED))
     m_processor->m_busDevices[command.initiator]->SetUnsupportedFeature((cec_opcode)command.parameters[0]);
   return true;
 }
@@ -380,6 +374,12 @@ bool CCECCommandHandler::HandleMenuRequest(const cec_command &command)
   return false;
 }
 
+bool CCECCommandHandler::HandlePoll(const cec_command &command)
+{
+  m_busDevice->HandlePoll(command.initiator);
+  return true;
+}
+
 bool CCECCommandHandler::HandleReportAudioStatus(const cec_command &command)
 {
   if (command.parameters.size == 1)
@@ -591,37 +591,49 @@ bool CCECCommandHandler::HandleTextViewOn(const cec_command &command)
 
 bool CCECCommandHandler::HandleUserControlPressed(const cec_command &command)
 {
-  if (m_processor->IsRunning() && m_busDevice->MyLogicalAddressContains(command.destination) && command.parameters.size > 0)
+  if (m_processor->IsRunning() &&
+      m_busDevice->MyLogicalAddressContains(command.destination) &&
+      command.parameters.size > 0)
   {
     CLibCEC::AddKey();
-
     if (command.parameters[0] <= CEC_USER_CONTROL_CODE_MAX)
+      CLibCEC::SetCurrentButton((cec_user_control_code) command.parameters[0]);
+
+    if (command.parameters[0] == CEC_USER_CONTROL_CODE_POWER ||
+        command.parameters[0] == CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION)
     {
-      if (command.parameters[0] == CEC_USER_CONTROL_CODE_POWER ||
-          command.parameters[0] == CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION)
+      bool bPowerOn(true);
+      CCECBusDevice *device = GetDevice(command.destination);
+      if (!device)
+        return true;
+
+      // CEC_USER_CONTROL_CODE_POWER operates as a toggle
+      // assume CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION does not
+      if (command.parameters[0] == CEC_USER_CONTROL_CODE_POWER)
       {
-        CCECBusDevice *device = GetDevice(command.destination);
-        if (device)
-        {
-          device->SetPowerStatus(CEC_POWER_STATUS_ON);
-          if (device->MyLogicalAddressContains(device->GetLogicalAddress()))
-          {
-            device->SetActiveSource();
-            device->TransmitImageViewOn();
-            device->TransmitActiveSource();
-
-            if (device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE ||
-                device->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE)
-              ((CCECPlaybackDevice *)device)->TransmitDeckStatus(command.initiator);
-          }
-        }
+        cec_power_status status = device->GetPowerStatus();
+        bPowerOn = !(status == CEC_POWER_STATUS_ON || status == CEC_POWER_STATUS_IN_TRANSITION_STANDBY_TO_ON);
+      }
+
+      if (bPowerOn)
+      {
+        device->SetActiveSource();
+        device->TransmitImageViewOn();
+        device->TransmitActiveSource();
+
+        if (device->GetType() == CEC_DEVICE_TYPE_PLAYBACK_DEVICE ||
+            device->GetType() == CEC_DEVICE_TYPE_RECORDING_DEVICE)
+          ((CCECPlaybackDevice *)device)->TransmitDeckStatus(command.initiator);
       }
       else
       {
-        CLibCEC::SetCurrentButton((cec_user_control_code) command.parameters[0]);
+        device->SetInactiveSource();
+        device->TransmitInactiveSource();
+        device->SetMenuState(CEC_MENU_STATE_DEACTIVATED);
       }
-      return true;
     }
+
+    return true;
   }
   return false;
 }
@@ -962,19 +974,16 @@ bool CCECCommandHandler::Transmit(cec_command &command, bool bExpectResponse /*
 
   {
     uint8_t iTries(0), iMaxTries(command.opcode == CEC_OPCODE_NONE ? 1 : m_iTransmitRetries + 1);
-    CLockObject writeLock(m_processor->m_transmitMutex);
-    CLockObject receiveLock(m_receiveMutex);
     while (!bReturn && ++iTries <= iMaxTries)
     {
-      m_expectedResponse = expectedResponse;
-      m_lastCommandSent  = command.opcode;
-      m_bRcvSignal = false;
       if ((bReturn = m_processor->Transmit(command)) == true)
       {
         CLibCEC::AddLog(CEC_LOG_DEBUG, "command transmitted");
         if (bExpectResponse)
-          bReturn = m_condition.Wait(m_receiveMutex, m_bRcvSignal, m_iTransmitWait);
-        CLibCEC::AddLog(CEC_LOG_DEBUG, bReturn ? "expected response received" : "expected response not received");
+        {
+          bReturn = m_waitForResponse->Wait(expectedResponse);
+          CLibCEC::AddLog(CEC_LOG_DEBUG, bReturn ? "expected response received (%X: %s)" : "expected response not received (%X: %s)", (int)expectedResponse, m_processor->ToString(expectedResponse));
+        }
       }
     }
   }