cec: refactor CEC command handling. split up standard and non-standard CEC implementa...
authorLars Op den Kamp <lars@opdenkamp.eu>
Wed, 26 Oct 2011 22:59:40 +0000 (00:59 +0200)
committerLars Op den Kamp <lars@opdenkamp.eu>
Wed, 26 Oct 2011 22:59:40 +0000 (00:59 +0200)
15 files changed:
configure.ac
include/cecloader.h
src/lib/ANCommandHandler.cpp [new file with mode: 0644]
src/lib/ANCommandHandler.h [new file with mode: 0644]
src/lib/CECBusDevice.cpp [new file with mode: 0644]
src/lib/CECBusDevice.h [new file with mode: 0644]
src/lib/CECCommandHandler.cpp [new file with mode: 0644]
src/lib/CECCommandHandler.h [new file with mode: 0644]
src/lib/CECProcessor.cpp
src/lib/CECProcessor.h
src/lib/LibCEC.cpp
src/lib/LibCEC.h
src/lib/Makefile.am
src/lib/SLCommandHandler.cpp [new file with mode: 0644]
src/lib/SLCommandHandler.h [new file with mode: 0644]

index fd1eb01a2e6e807ea1611dd3694aa2769d4bd540..b350c827cd30ad64b6b2d8483de40d5301788a87 100644 (file)
@@ -1,4 +1,4 @@
-AC_INIT([libcec], 0:7:0)
+AC_INIT([libcec], 0:8:0)
 AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
 
 AC_PROG_CXX
index 7ae8b4984f9d9ae825dc1dfffecc97273e2d7e8c..242d4fe52d9fb0cbe12cbfeeca6fa8af828d7e7b 100644 (file)
@@ -84,9 +84,9 @@ CEC::ICECAdapter *LoadLibCec(const char *strName, CEC::cec_logical_address iLogi
     if (!g_libCEC)
     {
 #if defined(__APPLE__)
-      cout << "cannot find " << (strLib ? strLib : "libcec.dylib") << endl;
+      cout << "cannot find " << (strLib ? strLib : "libcec.dylib") << dlerror() << endl;
 #else
-      cout << "cannot find " << (strLib ? strLib : "libcec.so") << endl;
+      cout << "cannot find " << (strLib ? strLib : "libcec.so") << dlerror() << endl;
 #endif
       return NULL;
     }
diff --git a/src/lib/ANCommandHandler.cpp b/src/lib/ANCommandHandler.cpp
new file mode 100644 (file)
index 0000000..575c4c3
--- /dev/null
@@ -0,0 +1,108 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "ANCommandHandler.h"
+#include "CECBusDevice.h"
+#include "CECProcessor.h"
+#include "util/StdString.h"
+
+using namespace CEC;
+
+CANCommandHandler::CANCommandHandler(CCECBusDevice *busDevice) :
+    CCECCommandHandler(busDevice)
+{
+}
+
+bool CANCommandHandler::HandleVendorRemoteButtonDown(const cec_command &command)
+{
+  if (command.parameters.size > 0)
+  {
+    m_busDevice->GetProcessor()->AddKey();
+
+    uint8_t iButton = 0;
+    switch (command.parameters[0])
+    {
+    case CEC_AN_USER_CONTROL_CODE_RETURN:
+      iButton = CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL;
+      break;
+    default:
+      break;
+    }
+
+    if (iButton > 0 && iButton <= CEC_USER_CONTROL_CODE_MAX)
+    {
+      CStdString strLog;
+      strLog.Format("key pressed: %1x", iButton);
+      m_busDevice->AddLog(CEC_LOG_DEBUG, strLog);
+
+      m_busDevice->GetProcessor()->SetCurrentButton((cec_user_control_code) command.parameters[0]);
+    }
+  }
+
+  return true;
+}
+
+bool CANCommandHandler::HandleCommand(const cec_command &command)
+{
+  bool bHandled(true);
+  if (command.destination == m_busDevice->GetMyLogicalAddress())
+  {
+    switch(command.opcode)
+    {
+    case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
+      HandleVendorRemoteButtonDown(command);
+      break;
+    case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
+      HandleUserControlRelease(command);
+      break;
+    default:
+      bHandled = false;
+      break;
+    }
+  }
+  else if (command.destination == CECDEVICE_BROADCAST)
+  {
+    switch(command.opcode)
+    {
+    // TODO
+    default:
+      bHandled = false;
+      break;
+    }
+  }
+
+  if (!bHandled)
+    bHandled = CCECCommandHandler::HandleCommand(command);
+
+  return bHandled;
+}
diff --git a/src/lib/ANCommandHandler.h b/src/lib/ANCommandHandler.h
new file mode 100644 (file)
index 0000000..d1729aa
--- /dev/null
@@ -0,0 +1,49 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "CECCommandHandler.h"
+
+namespace CEC
+{
+  class CANCommandHandler : public CCECCommandHandler
+  {
+  public:
+    CANCommandHandler(CCECBusDevice *busDevice);
+    virtual ~CANCommandHandler(void) {};
+
+    virtual bool HandleCommand(const cec_command &command);
+
+  protected:
+    virtual bool HandleVendorRemoteButtonDown(const cec_command &command);
+  };
+};
diff --git a/src/lib/CECBusDevice.cpp b/src/lib/CECBusDevice.cpp
new file mode 100644 (file)
index 0000000..bcd73cf
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "CECBusDevice.h"
+#include "CECProcessor.h"
+#include "ANCommandHandler.h"
+#include "SLCommandHandler.h"
+
+using namespace CEC;
+
+CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogicalAddress, uint16_t iPhysicalAddress) :
+  m_iPhysicalAddress(iPhysicalAddress),
+  m_iLogicalAddress(iLogicalAddress),
+  m_processor(processor),
+  m_iVendorId(0),
+  m_iVendorClass(0)
+{
+  m_handler = new CCECCommandHandler(this);
+}
+
+CCECBusDevice::~CCECBusDevice(void)
+{
+  delete m_handler;
+}
+
+cec_logical_address CCECBusDevice::GetMyLogicalAddress(void) const
+{
+  return m_processor->GetLogicalAddress();
+}
+
+uint16_t CCECBusDevice::GetMyPhysicalAddress(void) const
+{
+  return m_processor->GetPhysicalAddress();
+}
+
+void CCECBusDevice::AddLog(cec_log_level level, const CStdString &strMessage)
+{
+  m_processor->AddLog(level, strMessage);
+}
+
+void CCECBusDevice::SetVendorId(uint16_t iVendorId, uint8_t iVendorClass /* = 0 */)
+{
+  delete m_handler;
+  m_iVendorId = iVendorId;
+  m_iVendorClass = iVendorClass;
+
+  switch (iVendorId)
+  {
+  case CEC_VENDOR_SAMSUNG:
+    m_handler = new CANCommandHandler(this);
+    break;
+  case CEC_VENDOR_LG:
+    m_handler = new CSLCommandHandler(this);
+    break;
+  default:
+    m_handler = new CCECCommandHandler(this);
+    break;
+  }
+
+  CStdString strLog;
+  strLog.Format("device %d: vendor = %s (%04x) class = %2x", m_iLogicalAddress, CECVendorIdToString(iVendorId), iVendorId, iVendorClass);
+  m_processor->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+}
+
+bool CCECBusDevice::HandleCommand(const cec_command &command)
+{
+  CLockObject lock(&m_mutex);
+  m_handler->HandleCommand(command);
+  return true;
+}
+
+const char *CCECBusDevice::CECVendorIdToString(const uint64_t iVendorId)
+{
+  switch (iVendorId)
+  {
+  case CEC_VENDOR_SAMSUNG:
+    return "Samsung";
+  case CEC_VENDOR_LG:
+      return "LG";
+  default:
+    return "Unknown";
+  }
+}
diff --git a/src/lib/CECBusDevice.h b/src/lib/CECBusDevice.h
new file mode 100644 (file)
index 0000000..b7ae7e9
--- /dev/null
@@ -0,0 +1,72 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "CECCommandHandler.h"
+#include "platform/threads.h"
+#include "util/StdString.h"
+
+namespace CEC
+{
+  class CCECProcessor;
+
+  class CCECBusDevice
+  {
+  public:
+    CCECBusDevice(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress = 0);
+    virtual ~CCECBusDevice(void);
+
+    virtual cec_logical_address GetLogicalAddress(void) const { return m_iLogicalAddress; }
+    virtual uint16_t GetPhysicalAddress(void) const { return m_iPhysicalAddress; }
+
+    virtual cec_logical_address GetMyLogicalAddress(void) const;
+    virtual uint16_t GetMyPhysicalAddress(void) const;
+
+    virtual void SetVendorId(uint16_t iVendorId, uint8_t iVendorClass = 0);
+    virtual bool HandleCommand(const cec_command &command);
+
+    virtual void AddLog(cec_log_level level, const CStdString &strMessage);
+    virtual CCECProcessor *GetProcessor() const { return m_processor; }
+    virtual CCECCommandHandler *GetHandler(void) const { return m_handler; };
+
+    static const char *CECVendorIdToString(const uint64_t iVendorId);
+
+  protected:
+    uint16_t            m_iPhysicalAddress;
+    cec_logical_address m_iLogicalAddress;
+    CCECProcessor      *m_processor;
+    CCECCommandHandler *m_handler;
+    uint64_t            m_iVendorId;
+    uint8_t             m_iVendorClass;
+    CMutex              m_mutex;
+  };
+};
diff --git a/src/lib/CECCommandHandler.cpp b/src/lib/CECCommandHandler.cpp
new file mode 100644 (file)
index 0000000..314313d
--- /dev/null
@@ -0,0 +1,250 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "CECCommandHandler.h"
+#include "CECBusDevice.h"
+#include "CECProcessor.h"
+
+using namespace CEC;
+
+CCECCommandHandler::CCECCommandHandler(CCECBusDevice *busDevice)
+{
+  m_busDevice = busDevice;
+}
+
+bool CCECCommandHandler::HandleCommand(const cec_command &command)
+{
+  bool bHandled(true);
+
+  if (command.destination == m_busDevice->GetMyLogicalAddress())
+  {
+    switch(command.opcode)
+    {
+    case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
+      HandleGivePhysicalAddress(command);
+      break;
+    case CEC_OPCODE_GIVE_OSD_NAME:
+      HandleGiveOSDName(command);
+      break;
+    case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
+      HandleGiveDeviceVendorId(command);
+      break;
+    case CEC_OPCODE_DEVICE_VENDOR_ID:
+      HandleDeviceVendorId(command);
+      break;
+    case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
+      HandleDeviceVendorCommandWithId(command);
+      break;
+    case CEC_OPCODE_GIVE_DECK_STATUS:
+      HandleGiveDeckStatus(command);
+      break;
+    case CEC_OPCODE_MENU_REQUEST:
+      HandleMenuRequest(command);
+      break;
+    case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
+      HandleGiveDevicePowerStatus(command);
+      break;
+    case CEC_OPCODE_GET_CEC_VERSION:
+      HandleGetCecVersion(command);
+      break;
+    case CEC_OPCODE_USER_CONTROL_PRESSED:
+      HandleUserControlPressed(command);
+      break;
+    case CEC_OPCODE_USER_CONTROL_RELEASE:
+      HandleUserControlRelease(command);
+      break;
+    default:
+      UnhandledCommand(command);
+      bHandled = false;
+      break;
+    }
+  }
+  else if (command.destination == CECDEVICE_BROADCAST)
+  {
+    CStdString strLog;
+    switch (command.opcode)
+    {
+    case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
+      HandleRequestActiveSource(command);
+      break;
+    case CEC_OPCODE_SET_STREAM_PATH:
+      HandleSetStreamPath(command);
+      break;
+    case CEC_OPCODE_ROUTING_CHANGE:
+      HandleRoutingChange(command);
+      break;
+    case CEC_OPCODE_DEVICE_VENDOR_ID:
+      HandleDeviceVendorId(command);
+      break;
+    case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
+      HandleDeviceVendorCommandWithId(command);
+     break;
+    default:
+      UnhandledCommand(command);
+      bHandled = false;
+      break;
+    }
+  }
+  else
+  {
+    CStdString strLog;
+    strLog.Format("ignoring frame: destination: %u != %u", command.destination, (uint8_t)m_busDevice->GetMyLogicalAddress());
+    m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+    bHandled = false;
+  }
+
+  return bHandled;
+}
+
+bool CCECCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command)
+{
+  m_busDevice->GetProcessor()->ParseVendorId(command.initiator, command.parameters);
+  return true;
+}
+
+bool CCECCommandHandler::HandleDeviceVendorId(const cec_command &command)
+{
+  m_busDevice->GetProcessor()->ParseVendorId(command.initiator, command.parameters);
+  return true;
+}
+
+bool CCECCommandHandler::HandleGetCecVersion(const cec_command &command)
+{
+  m_busDevice->GetProcessor()->ReportCECVersion(command.initiator);
+  return true;
+}
+
+bool CCECCommandHandler::HandleGiveDeckStatus(const cec_command &command)
+{
+  // need to support opcodes play and deck control before doing anything with this
+  m_busDevice->GetProcessor()->TransmitAbort(command.initiator, CEC_OPCODE_GIVE_DECK_STATUS);
+  return true;
+}
+
+bool CCECCommandHandler::HandleGiveDevicePowerStatus(const cec_command &command)
+{
+  m_busDevice->GetProcessor()->ReportPowerState(command.initiator);
+  return true;
+}
+
+bool CCECCommandHandler::HandleGiveDeviceVendorId(const cec_command &command)
+{
+  m_busDevice->GetProcessor()->ReportVendorID(command.initiator);
+  return true;
+}
+
+bool CCECCommandHandler::HandleGiveOSDName(const cec_command &command)
+{
+  m_busDevice->GetProcessor()->ReportOSDName(command.initiator);
+  return true;
+}
+
+bool CCECCommandHandler::HandleGivePhysicalAddress(const cec_command &command)
+{
+  m_busDevice->GetProcessor()->ReportPhysicalAddress();
+  return true;
+}
+
+bool CCECCommandHandler::HandleMenuRequest(const cec_command &command)
+{
+  if (command.parameters[0] == CEC_MENU_REQUEST_TYPE_QUERY)
+    m_busDevice->GetProcessor()->ReportMenuState(command.initiator);
+  return true;
+}
+
+bool CCECCommandHandler::HandleRequestActiveSource(const cec_command &command)
+{
+  CStdString strLog;
+  strLog.Format(">> %i requests active source", (uint8_t) command.initiator);
+  m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+  m_busDevice->GetProcessor()->BroadcastActiveSource();
+  return true;
+}
+
+bool CCECCommandHandler::HandleRoutingChange(const cec_command &command)
+{
+  if (command.parameters.size == 4)
+  {
+    uint16_t iOldAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
+    uint16_t iNewAddress = ((uint16_t)command.parameters[2] << 8) | ((uint16_t)command.parameters[3]);
+    CStdString strLog;
+    strLog.Format(">> %i changed physical address from %04x to %04x", command.initiator, iOldAddress, iNewAddress);
+    m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+
+    m_busDevice->GetProcessor()->AddCommand(command);
+  }
+  return true;
+}
+
+bool CCECCommandHandler::HandleSetStreamPath(const cec_command &command)
+{
+  if (command.parameters.size >= 2)
+  {
+    int streamaddr = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
+    CStdString strLog;
+    strLog.Format(">> %i requests stream path from physical address %04x", command.initiator, streamaddr);
+    m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+    if (streamaddr == m_busDevice->GetMyPhysicalAddress())
+      m_busDevice->GetProcessor()->BroadcastActiveSource();
+  }
+  return true;
+}
+
+bool CCECCommandHandler::HandleUserControlPressed(const cec_command &command)
+{
+  if (command.parameters.size > 0)
+  {
+    m_busDevice->GetProcessor()->AddKey();
+
+    if (command.parameters[0] <= CEC_USER_CONTROL_CODE_MAX)
+    {
+      CStdString strLog;
+      strLog.Format("key pressed: %1x", command.parameters[0]);
+      m_busDevice->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+
+      m_busDevice->GetProcessor()->SetCurrentButton((cec_user_control_code) command.parameters[0]);
+    }
+  }
+  return true;
+}
+
+bool CCECCommandHandler::HandleUserControlRelease(const cec_command &command)
+{
+  m_busDevice->GetProcessor()->AddKey();
+  return true;
+}
+
+void CCECCommandHandler::UnhandledCommand(const cec_command &command)
+{
+  m_busDevice->GetProcessor()->AddCommand(command);;
+}
diff --git a/src/lib/CECCommandHandler.h b/src/lib/CECCommandHandler.h
new file mode 100644 (file)
index 0000000..7129b40
--- /dev/null
@@ -0,0 +1,67 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include <cectypes.h>
+
+namespace CEC
+{
+  class CCECBusDevice;
+
+  class CCECCommandHandler
+  {
+  public:
+    CCECCommandHandler(CCECBusDevice *busDevice);
+    virtual ~CCECCommandHandler(void) {};
+
+    virtual bool HandleCommand(const cec_command &command);
+
+  protected:
+    bool HandleDeviceVendorCommandWithId(const cec_command &command);
+    bool HandleDeviceVendorId(const cec_command &command);
+    bool HandleGetCecVersion(const cec_command &command);
+    bool HandleGiveDeckStatus(const cec_command &command);
+    bool HandleGiveDevicePowerStatus(const cec_command &command);
+    bool HandleGiveDeviceVendorId(const cec_command &command);
+    bool HandleGiveOSDName(const cec_command &command);
+    bool HandleGivePhysicalAddress(const cec_command &command);
+    bool HandleMenuRequest(const cec_command &command);
+    bool HandleRequestActiveSource(const cec_command &command);
+    bool HandleRoutingChange(const cec_command &command);
+    bool HandleSetStreamPath(const cec_command &command);
+    bool HandleUserControlPressed(const cec_command &command);
+    bool HandleUserControlRelease(const cec_command &command);
+    void UnhandledCommand(const cec_command &command);
+
+    CCECBusDevice *m_busDevice;
+  };
+};
index e32489973bdedcb67bcf96357a324999895bca69..eae4c3cfa7b3b2e92eeae6d3623feaed19c43b39 100644 (file)
@@ -33,6 +33,7 @@
 #include "CECProcessor.h"
 
 #include "AdapterCommunication.h"
+#include "CECBusDevice.h"
 #include "LibCEC.h"
 #include "util/StdString.h"
 #include "platform/timeutils.h"
@@ -48,10 +49,8 @@ CCECProcessor::CCECProcessor(CLibCEC *controller, CAdapterCommunication *serComm
     m_controller(controller),
     m_bMonitor(false)
 {
-  for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
-    m_vendorIds[iPtr] = CEC_VENDOR_UNKNOWN;
-  for (uint8_t iPtr = 0; iPtr < 16; iPtr++)
-    m_vendorClasses[iPtr] = (uint8_t) 0;
+  for (unsigned int iPtr = 0; iPtr < 16; iPtr++)
+    m_busDevices[iPtr] = new CCECBusDevice(this, (cec_logical_address) iPtr, 0);
 }
 
 CCECProcessor::~CCECProcessor(void)
@@ -59,6 +58,7 @@ CCECProcessor::~CCECProcessor(void)
   StopThread();
   m_communication = NULL;
   m_controller = NULL;
+  delete[] m_busDevices;
 }
 
 bool CCECProcessor::Start(void)
@@ -533,246 +533,37 @@ void CCECProcessor::ParseVendorId(cec_logical_address device, const cec_datapack
                        ((uint64_t)data[1] << 2) +
                         (uint64_t)data[2];
 
-  m_vendorIds[(uint8_t)device]     = iVendorId;
-  m_vendorClasses[(uint8_t)device] = data.size >= 4 ? data[3] : 0;
-
-  CStdString strLog;
-  strLog.Format("device %d: vendor = %s (%04x) class = %2x", (uint8_t)device, CECVendorIdToString(m_vendorIds[(uint8_t)device]), iVendorId, m_vendorClasses[(uint8_t)device]);
-  m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
+  m_busDevices[(uint8_t)device]->SetVendorId(iVendorId, data.size >= 4 ? data[3] : 0);
 }
 
-bool CCECProcessor::HandleANCommand(cec_command &command)
+void CCECProcessor::ParseCommand(cec_command &command)
 {
-  bool bHandled(true);
-  if (command.destination == m_iLogicalAddress)
-  {
-    switch(command.opcode)
-    {
-    case CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN:
-      if (command.parameters.size > 0)
-      {
-        m_controller->AddKey();
-
-        uint8_t iButton = 0;
-        switch (command.parameters[0])
-        {
-        case CEC_AN_USER_CONTROL_CODE_RETURN:
-          iButton = CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL;
-          break;
-        default:
-          break;
-        }
-
-        if (iButton > 0 && iButton <= CEC_USER_CONTROL_CODE_MAX)
-        {
-          CStdString strLog;
-          strLog.Format("key pressed: %1x", iButton);
-          m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
-
-          m_controller->SetCurrentButton((cec_user_control_code) command.parameters[0]);
-        }
-      }
-      break;
-    case CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP:
-      m_controller->AddKey();
-      break;
-    default:
-      bHandled = false;
-      break;
-    }
-  }
-  else if (command.destination == CECDEVICE_BROADCAST)
-  {
-    switch(command.opcode)
-    {
-    // TODO
-    default:
-      bHandled = false;
-      break;
-    }
-  }
-
-  if (!bHandled)
-    bHandled = HandleCecCommand(command);
+  CStdString dataStr;
+  dataStr.Format(">> received frame: %1x%1x:%02x", command.initiator, command.destination, command.opcode);
+  for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
+    dataStr.AppendFormat(":%02x", (unsigned int)command.parameters[iPtr]);
+  m_controller->AddLog(CEC_LOG_DEBUG, dataStr.c_str());
 
-  return bHandled;
+  if (!m_bMonitor)
+    m_busDevices[(uint8_t)command.initiator]->HandleCommand(command);
 }
 
-bool CCECProcessor::HandleSLCommand(cec_command &command)
+void CCECProcessor::SetCurrentButton(cec_user_control_code iButtonCode)
 {
-  bool bHandled(true);
-  if (command.destination == m_iLogicalAddress)
-  {
-    switch(command.opcode)
-    {
-    // TODO
-    default:
-      bHandled = false;
-      break;
-    }
-  }
-  else if (command.destination == CECDEVICE_BROADCAST)
-  {
-    switch(command.opcode)
-    {
-    // TODO
-    default:
-      bHandled = false;
-      break;
-    }
-  }
-
-  if (!bHandled)
-    bHandled = HandleCecCommand(command);
-
-  return bHandled;
+  m_controller->SetCurrentButton(iButtonCode);
 }
 
-bool CCECProcessor::HandleCecCommand(cec_command &command)
+void CCECProcessor::AddCommand(const cec_command &command)
 {
-  bool bHandled(true);
-
-  if (command.destination == m_iLogicalAddress)
-  {
-    switch(command.opcode)
-    {
-    case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS:
-      ReportPhysicalAddress();
-      break;
-    case CEC_OPCODE_GIVE_OSD_NAME:
-      ReportOSDName(command.initiator);
-      break;
-    case CEC_OPCODE_GIVE_DEVICE_VENDOR_ID:
-      ReportVendorID(command.initiator);
-      break;
-    case CEC_OPCODE_DEVICE_VENDOR_ID:
-    case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
-      ParseVendorId(command.initiator, command.parameters);
-      break;
-    case CEC_OPCODE_GIVE_DECK_STATUS:
-      // need to support opcodes play and deck control before doing anything with this
-      TransmitAbort(command.initiator, CEC_OPCODE_GIVE_DECK_STATUS);
-      break;
-    case CEC_OPCODE_MENU_REQUEST:
-      if (command.parameters[0] == CEC_MENU_REQUEST_TYPE_QUERY)
-        ReportMenuState(command.initiator);
-      break;
-    case CEC_OPCODE_GIVE_DEVICE_POWER_STATUS:
-      ReportPowerState(command.initiator);
-      break;
-    case CEC_OPCODE_GET_CEC_VERSION:
-      ReportCECVersion(command.initiator);
-      break;
-    case CEC_OPCODE_USER_CONTROL_PRESSED:
-      if (command.parameters.size > 0)
-      {
-        m_controller->AddKey();
-
-        if (command.parameters[0] <= CEC_USER_CONTROL_CODE_MAX)
-        {
-          CStdString strLog;
-          strLog.Format("key pressed: %1x", command.parameters[0]);
-          m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
-
-          m_controller->SetCurrentButton((cec_user_control_code) command.parameters[0]);
-        }
-      }
-      break;
-    case CEC_OPCODE_USER_CONTROL_RELEASE:
-      m_controller->AddKey();
-      break;
-    default:
-      m_controller->AddCommand(command);
-      bHandled = false;
-      break;
-    }
-  }
-  else if (command.destination == CECDEVICE_BROADCAST)
-  {
-    CStdString strLog;
-    switch (command.opcode)
-    {
-    case CEC_OPCODE_REQUEST_ACTIVE_SOURCE:
-      strLog.Format(">> %i requests active source", (uint8_t) command.initiator);
-      m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
-      BroadcastActiveSource();
-      break;
-    case CEC_OPCODE_SET_STREAM_PATH:
-      if (command.parameters.size >= 2)
-      {
-        int streamaddr = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
-        strLog.Format(">> %i requests stream path from physical address %04x", command.initiator, streamaddr);
-        m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
-        if (streamaddr == m_iPhysicalAddress)
-          BroadcastActiveSource();
-      }
-      break;
-    case CEC_OPCODE_ROUTING_CHANGE:
-      if (command.parameters.size == 4)
-      {
-        uint16_t iOldAddress = ((uint16_t)command.parameters[0] << 8) | ((uint16_t)command.parameters[1]);
-        uint16_t iNewAddress = ((uint16_t)command.parameters[2] << 8) | ((uint16_t)command.parameters[3]);
-        strLog.Format(">> %i changed physical address from %04x to %04x", command.initiator, iOldAddress, iNewAddress);
-        m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
-
-        m_controller->AddCommand(command);
-      }
-      break;
-    case CEC_OPCODE_DEVICE_VENDOR_ID:
-    case CEC_OPCODE_VENDOR_COMMAND_WITH_ID:
-      ParseVendorId(command.initiator, command.parameters);
-     break;
-    default:
-      m_controller->AddCommand(command);
-      bHandled = false;
-      break;
-    }
-  }
-  else
-  {
-    CStdString strLog;
-    strLog.Format("ignoring frame: destination: %u != %u", command.destination, (uint8_t)m_iLogicalAddress);
-    m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
-    bHandled = false;
-  }
-
-  return bHandled;
+  m_controller->AddCommand(command);
 }
 
-void CCECProcessor::ParseCommand(cec_command &command)
+void CCECProcessor::AddKey(void)
 {
-  CStdString dataStr;
-  dataStr.Format(">> received frame: %1x%1x:%02x", command.initiator, command.destination, command.opcode);
-  for (uint8_t iPtr = 0; iPtr < command.parameters.size; iPtr++)
-    dataStr.AppendFormat(":%02x", (unsigned int)command.parameters[iPtr]);
-  m_controller->AddLog(CEC_LOG_DEBUG, dataStr.c_str());
-
-  if (!m_bMonitor)
-  {
-    switch(m_vendorIds[command.initiator])
-    {
-    case CEC_VENDOR_LG:
-      HandleSLCommand(command);
-      break;
-    case CEC_VENDOR_SAMSUNG:
-      HandleANCommand(command);
-      break;
-    default:
-      HandleCecCommand(command);
-      break;
-    }
-  }
+  m_controller->AddKey();
 }
 
-const char *CCECProcessor::CECVendorIdToString(const uint64_t iVendorId)
+void CCECProcessor::AddLog(cec_log_level level, const CStdString &strMessage)
 {
-  switch (iVendorId)
-  {
-  case CEC_VENDOR_SAMSUNG:
-    return "Samsung";
-  case CEC_VENDOR_LG:
-      return "LG";
-  default:
-    return "Unknown";
-  }
+  m_controller->AddLog(level, strMessage);
 }
index 4e9d1115c475aba934769702b5dc650ce63db0b1..c9028a8d823a7002d977258a68c7ec7820c579d9 100644 (file)
@@ -35,6 +35,7 @@
 #include <cectypes.h>
 #include "platform/threads.h"
 #include "util/buffer.h"
+#include "util/StdString.h"
 
 class CSerialPort;
 
@@ -42,6 +43,7 @@ namespace CEC
 {
   class CLibCEC;
   class CAdapterCommunication;
+  class CCECBusDevice;
 
   class CCECProcessor : public CThread
   {
@@ -62,9 +64,14 @@ namespace CEC
       virtual bool SetOSDString(cec_logical_address iLogicalAddress, cec_display_control duration, const char *strMessage);
       virtual bool SwitchMonitoring(bool bEnable);
 
-      static const char *CECVendorIdToString(const uint64_t iVendorId);
+      virtual cec_logical_address GetLogicalAddress(void) const { return m_iLogicalAddress; }
+      virtual uint16_t GetPhysicalAddress(void) const { return m_iPhysicalAddress; }
+
+      virtual void SetCurrentButton(cec_user_control_code iButtonCode);
+      virtual void AddCommand(const cec_command &command);
+      virtual void AddKey(void);
+      virtual void AddLog(cec_log_level level, const CStdString &strMessage);
 
-    protected:
       virtual bool TransmitFormatted(const cec_adapter_message &data, bool bWaitForAck = true);
       virtual void TransmitAbort(cec_logical_address address, cec_opcode opcode, ECecAbortReason reason = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE);
       virtual void ReportCECVersion(cec_logical_address address = CECDEVICE_TV);
@@ -74,16 +81,13 @@ namespace CEC
       virtual void ReportOSDName(cec_logical_address address = CECDEVICE_TV);
       virtual void ReportPhysicalAddress(void);
       virtual void BroadcastActiveSource(void);
-      virtual bool HandleANCommand(cec_command &command);
-      virtual bool HandleSLCommand(cec_command &command);
-      virtual bool HandleCecCommand(cec_command &command);
+      virtual void ParseVendorId(cec_logical_address device, const cec_datapacket &data);
 
     private:
       void LogOutput(const cec_command &data);
       bool WaitForAck(bool *bError, uint32_t iTimeout = 1000);
       void ParseMessage(cec_adapter_message &msg, bool *bError, bool *bTransmitSucceeded, bool *bEom, bool bProcessMessages = true);
       void ParseCommand(cec_command &command);
-      void ParseVendorId(cec_logical_address device, const cec_datapacket &data);
 
       cec_command                    m_currentframe;
       uint16_t                       m_iPhysicalAddress;
@@ -93,8 +97,7 @@ namespace CEC
       CMutex                         m_mutex;
       CAdapterCommunication         *m_communication;
       CLibCEC                       *m_controller;
-      uint64_t                       m_vendorIds[16];
-      uint8_t                        m_vendorClasses[16];
+      CCECBusDevice                 *m_busDevices[16];
       bool                           m_bMonitor;
   };
 };
index 97427958f9df8d1f65cc0f565d6840ace93cf4fe..ecbc55abece3df8350a42574ec23f4350c9045c2 100644 (file)
@@ -229,7 +229,7 @@ void CLibCEC::AddKey(void)
   }
 }
 
-void CLibCEC::AddCommand(cec_command &command)
+void CLibCEC::AddCommand(const cec_command &command)
 {
   if (m_commandBuffer.Push(command))
   {
index 968d615f979717dcd794503bb8321181c9826f8e..d0147d8e4f2a762b60f4938d207116f4bdc88a10 100644 (file)
@@ -77,7 +77,7 @@ namespace CEC
 
       virtual void AddLog(cec_log_level level, const std::string &strMessage);
       virtual void AddKey(void);
-      virtual void AddCommand(cec_command &command);
+      virtual void AddCommand(const cec_command &command);
       virtual void CheckKeypressTimeout(void);
       virtual void SetCurrentButton(cec_user_control_code iButtonCode);
 
index e3354e17115f71d68559c6b72eb42a1f599762b7..c608a6701ac3801352bb6e8158b73e448f293f6b 100644 (file)
@@ -12,11 +12,19 @@ libcec_la_SOURCES = AdapterCommunication.cpp \
                     AdapterCommunication.h \
                     AdapterDetection.cpp \
                     AdapterDetection.h \
+                    ANCommandHandler.cpp \
+                    ANCommandHandler.h \
+                    CECBusDevice.cpp \
+                    CECBusDevice.h \
+                    CECCommandHandler.cpp \
+                    CECCommandHandler.h \
                     CECProcessor.cpp \
                     CECProcessor.h \
                     LibCEC.cpp \
                     LibCEC.h \
                     LibCECC.cpp \
+                    SLCommandHandler.cpp \
+                    SLCommandHandler.h \
                     util/StdString.h \
                     platform/timeutils.h \
                     platform/baudrate.h \
diff --git a/src/lib/SLCommandHandler.cpp b/src/lib/SLCommandHandler.cpp
new file mode 100644 (file)
index 0000000..7c216e9
--- /dev/null
@@ -0,0 +1,41 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "SLCommandHandler.h"
+
+using namespace CEC;
+
+CSLCommandHandler::CSLCommandHandler(CCECBusDevice *busDevice) :
+    CCECCommandHandler(busDevice)
+{
+}
diff --git a/src/lib/SLCommandHandler.h b/src/lib/SLCommandHandler.h
new file mode 100644 (file)
index 0000000..e5edac5
--- /dev/null
@@ -0,0 +1,44 @@
+#pragma once
+/*
+ * This file is part of the libCEC(R) library.
+ *
+ * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited.  All rights reserved.
+ * libCEC(R) is an original work, containing original code.
+ *
+ * libCEC(R) is a trademark of Pulse-Eight Limited.
+ *
+ * This program is dual-licensed; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * Alternatively, you can license this library under a commercial license,
+ * please contact Pulse-Eight Licensing for more information.
+ *
+ * For more information contact:
+ * Pulse-Eight Licensing       <license@pulse-eight.com>
+ *     http://www.pulse-eight.com/
+ *     http://www.pulse-eight.net/
+ */
+
+#include "CECCommandHandler.h"
+
+namespace CEC
+{
+  class CSLCommandHandler : public CCECCommandHandler
+  {
+  public:
+    CSLCommandHandler(CCECBusDevice *busDevice);
+    virtual ~CSLCommandHandler(void) {};
+  };
+};