samsung: respond to vendor command 0x23 sent by samsung. attempt to fix bugzid: 2164
[deb_libcec.git] / src / lib / implementations / ANCommandHandler.cpp
index 2a4dc0d064dece6f48aecbe5986e0bbe143ef383..115fa88709b261fd0f68351532fabe054a9cf33e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libCEC(R) library.
  *
- * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is Copyright (C) 2011-2013 Pulse-Eight Limited.  All rights reserved.
  * libCEC(R) is an original work, containing original code.
  *
  * libCEC(R) is a trademark of Pulse-Eight Limited.
  *     http://www.pulse-eight.net/
  */
 
+#include "env.h"
 #include "ANCommandHandler.h"
-#include "../devices/CECBusDevice.h"
-#include "../CECProcessor.h"
-#include "../LibCEC.h"
-#include "../CECClient.h"
+
+#include "lib/devices/CECBusDevice.h"
+#include "lib/CECProcessor.h"
+#include "lib/LibCEC.h"
+#include "lib/CECClient.h"
 
 using namespace CEC;
 
 #define LIB_CEC     m_busDevice->GetProcessor()->GetLib()
 #define ToString(p) LIB_CEC->ToString(p)
 
-CANCommandHandler::CANCommandHandler(CCECBusDevice *busDevice) :
-    CCECCommandHandler(busDevice)
+CANCommandHandler::CANCommandHandler(CCECBusDevice *busDevice,
+                                     int32_t iTransmitTimeout /* = CEC_DEFAULT_TRANSMIT_TIMEOUT */,
+                                     int32_t iTransmitWait /* = CEC_DEFAULT_TRANSMIT_WAIT */,
+                                     int8_t iTransmitRetries /* = CEC_DEFAULT_TRANSMIT_RETRIES */,
+                                     int64_t iActiveSourcePending /* = 0 */) :
+    CCECCommandHandler(busDevice, iTransmitTimeout, iTransmitWait, iTransmitRetries, iActiveSourcePending)
 {
   m_vendorId = CEC_VENDOR_SAMSUNG;
   m_bOPTSendDeckStatusUpdateOnActiveSource = false;
 }
 
-bool CANCommandHandler::HandleVendorRemoteButtonDown(const cec_command &command)
+int CANCommandHandler::HandleVendorRemoteButtonDown(const cec_command &command)
 {
-  if (m_processor->IsRunning() && command.parameters.size > 0)
-  {
-    CCECClient *client = m_processor->GetClient(command.destination);
+  if (command.parameters.size == 0)
+    return CEC_ABORT_REASON_INVALID_OPERAND;
 
-    cec_keypress key;
-    key.duration = CEC_BUTTON_TIMEOUT;
-    key.keycode = CEC_USER_CONTROL_CODE_UNKNOWN;
+  if (!m_processor->CECInitialised())
+    return CEC_ABORT_REASON_NOT_IN_CORRECT_MODE_TO_RESPOND;
 
-    switch (command.parameters[0])
-    {
-    case CEC_USER_CONTROL_CODE_AN_RETURN:
-      key.keycode = client && client->GetConfiguration()->clientVersion >= CEC_CLIENT_VERSION_1_5_0 ?
-        CEC_USER_CONTROL_CODE_AN_RETURN :
-        CEC_USER_CONTROL_CODE_EXIT;
-      break;
-    case CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST:
-      key.keycode = CEC_USER_CONTROL_CODE_AN_CHANNELS_LIST;
-      break;
-    default:
-      break;
-    }
+  CCECClient *client = m_processor->GetClient(command.destination);
+  if (!client)
+    return CEC_ABORT_REASON_NOT_IN_CORRECT_MODE_TO_RESPOND;
 
-    if (key.keycode != CEC_USER_CONTROL_CODE_UNKNOWN && client)
-      client->AddKey(key);
-  }
+  cec_keypress key;
+  key.duration = CEC_BUTTON_TIMEOUT;
+  key.keycode = (cec_user_control_code)command.parameters[0];
+
+  if (client)
+    client->AddKey(key);
 
-  return true;
+  return COMMAND_HANDLED;
 }
 
-bool CANCommandHandler::HandleCommand(const cec_command &command)
+int CANCommandHandler::HandleVendorRemoteButtonUp(const cec_command &command)
 {
-  bool bHandled(false);
-  if (m_processor->IsHandledByLibCEC(command.destination))
-  {
-    switch(command.opcode)
-    {
-    case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
-      bHandled = true;
-      HandleVendorRemoteButtonDown(command);
-      break;
-    case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
-      bHandled = true;
-      HandleUserControlRelease(command);
-      break;
-    default:
-      break;
-    }
-  }
-
-  if (!bHandled)
-    bHandled = CCECCommandHandler::HandleCommand(command);
-
-  return bHandled;
+  return HandleUserControlRelease(command);
 }
 
 bool CANCommandHandler::PowerOn(const cec_logical_address iInitiator, const cec_logical_address iDestination)
@@ -116,3 +92,32 @@ bool CANCommandHandler::PowerOn(const cec_logical_address iInitiator, const cec_
 
   return CCECCommandHandler::PowerOn(iInitiator, iDestination);
 }
+
+int CANCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command)
+{
+  if (!m_processor->IsHandledByLibCEC(command.destination))
+    return CEC_ABORT_REASON_INVALID_OPERAND;
+
+  // samsung's vendor id
+  if (command.parameters[0] == 0x00 && command.parameters[1] == 0x00 && command.parameters[2] == 0xf0)
+  {
+    // unknown vendor command sent to devices
+    if (command.parameters[3] == 0x23)
+    {
+      cec_command response;
+      cec_command::Format(response, command.destination, command.initiator, CEC_OPCODE_VENDOR_COMMAND_WITH_ID);
+
+      // samsung vendor id
+      response.parameters.PushBack(0x00); response.parameters.PushBack(0x00); response.parameters.PushBack(0xf0);
+
+      // XXX see bugzid 2164. reply sent back by audio systems, we might have to send something different
+      response.parameters.PushBack(0x24);
+      response.parameters.PushBack(0x00);
+      response.parameters.PushBack(0x80);
+
+      Transmit(response, false, true);
+      return COMMAND_HANDLED;
+    }
+  }
+  return CEC_ABORT_REASON_INVALID_OPERAND;
+}