libcec v0.5 (WIP)
authorLars Op den Kamp <lars@opdenkamp.eu>
Fri, 7 Oct 2011 21:05:40 +0000 (23:05 +0200)
committerLars Op den Kamp <lars@opdenkamp.eu>
Fri, 7 Oct 2011 21:05:40 +0000 (23:05 +0200)
  * bumped interface version to 5
  * don't pass std::string and std::vector accross the interface
  * fixed heap corruption crashes on windows
  * fixed some memory leaks
  * reset all structs to default values before doing with them

23 files changed:
ChangeLog
configure.ac
debian/changelog
include/CECExports.h
include/CECExportsC.h
include/CECExportsCpp.h
project/libcec.vcxproj
src/lib/AdapterCommunication.cpp
src/lib/AdapterCommunication.h
src/lib/AdapterDetection.cpp
src/lib/AdapterDetection.h
src/lib/CECProcessor.cpp
src/lib/CECProcessor.h
src/lib/LibCEC.cpp
src/lib/LibCEC.h
src/lib/LibCECC.cpp
src/lib/platform/linux/serialport.cpp
src/lib/platform/serialport.h
src/lib/platform/threads.cpp
src/lib/platform/threads.h
src/lib/platform/windows/serialport.cpp
src/lib/util/buffer.h
src/testclient/main.cpp

index c96e49ade06d505d3b2a52ff8254bc49cbcf4b78..2cdc3d1904a64839ca608f51977dd13044151b52 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+libcec (0.5-0) unstable; urgency=low
+
+  * bumped interface version to 5
+  * don't pass std::string and std::vector accross the interface
+  * fixed heap corruption crashes on windows
+  * fixed some memory leaks
+  * reset all structs to default values before doing with them
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com>  Thu, 07 Oct 2011 22:00:00 +0200
+
 libcec (0.4-3) unstable; urgency=low
 
   * fixed reconnect
index dffe00b64805765160ae9fb5262c1fa2db1e5ea7..2034c08dd0320fbb16fbdf6e274247b11484d1d9 100644 (file)
@@ -1,4 +1,4 @@
-AC_INIT([libcec], 0:4:0)
+AC_INIT([libcec], 0:5:0)
 AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
 
 AC_PROG_CXX
index c96e49ade06d505d3b2a52ff8254bc49cbcf4b78..2cdc3d1904a64839ca608f51977dd13044151b52 100644 (file)
@@ -1,3 +1,13 @@
+libcec (0.5-0) unstable; urgency=low
+
+  * bumped interface version to 5
+  * don't pass std::string and std::vector accross the interface
+  * fixed heap corruption crashes on windows
+  * fixed some memory leaks
+  * reset all structs to default values before doing with them
+
+ -- Pulse-Eight Packaging <packaging@pulse-eight.com>  Thu, 07 Oct 2011 22:00:00 +0200
+
 libcec (0.4-3) unstable; urgency=low
 
   * fixed reconnect
index 9a5c0952c6f8cc5c3fc94edf812160ad6bb3275d..d1a7414242d83f8c389056fa1d66ec245c5bcf18 100644 (file)
@@ -34,9 +34,8 @@
 #ifndef CECEXPORTS_H_
 #define CECEXPORTS_H_
 
-#include <string>
 #include <stdint.h>
-#include <vector>
+#include <string.h>
 
 #if !defined(DECLSPEC)
 #if defined(_WIN32) || defined(_WIN64)
 extern "C" {
 namespace CEC {
 #endif
-  #define CEC_MIN_VERSION      4
-  #define CEC_LIB_VERSION      4
+  #define CEC_MIN_VERSION      5
+  #define CEC_LIB_VERSION      5
   #define CEC_SETTLE_DOWN_TIME 1000
   #define CEC_BUTTON_TIMEOUT   500
 
-  typedef std::vector<uint8_t> cec_frame;
-
   typedef enum cec_user_control_code
   {
     CEC_USER_CONTROL_CODE_SELECT = 0x00,
@@ -244,7 +241,7 @@ namespace CEC {
 
   typedef struct cec_log_message
   {
-    std::string   message;
+    char          message[1024];
     cec_log_level level;
   } cec_log_message;
 
@@ -256,16 +253,49 @@ namespace CEC {
 
   typedef struct cec_adapter
   {
-    std::string path;
-    std::string comm;
+    char path[1024];
+    char comm[1024];
   } cec_adapter;
 
+  typedef struct cec_frame
+  {
+    uint8_t data[20];
+    uint8_t size;
+
+    void shift(uint8_t num)
+    {
+      for (uint8_t iPtr = 0; iPtr < num; iPtr++)
+        data[iPtr] = iPtr + num < size ? data[iPtr + num] : 0;
+      size -= num;
+    }
+
+    void push_back(uint8_t add)
+    {
+      if (size < 20)
+        data[size++] = add;
+    }
+
+    void clear(void)
+    {
+      memset(data, 0, sizeof(data));
+      size = 0;
+    }
+  } cec_frame;
+
   typedef struct cec_command
   {
     cec_logical_address source;
     cec_logical_address destination;
     cec_opcode          opcode;
     cec_frame           parameters;
+
+    void clear(void)
+    {
+      source      = CECDEVICE_UNKNOWN;
+      destination = CECDEVICE_UNKNOWN;
+      opcode      = CEC_OPCODE_FEATURE_ABORT;
+      parameters.clear();
+    };
   } cec_command;
 
   //default physical address 1.0.0.0
index 2a6b6146c9c94d25162d7d6c40396d3d0ca3499e..d1987cb18720233b064ef474976b88e74a6107cd 100644 (file)
@@ -62,7 +62,7 @@ extern DECLSPEC void cec_destroy(void);
  * @param iTimeout Connection timeout in ms.
  * @return True when connected, false otherwise.
  */
-extern DECLSPEC bool cec_open(const char *strPort, uint64_t iTimeout);
+extern DECLSPEC bool cec_open(const char *strPort, uint32_t iTimeout);
 
 /*!
  * @brief Close the connection to the CEC adapter.
@@ -76,9 +76,9 @@ extern DECLSPEC void cec_close(void);
  * @return The number of devices that were found, or -1 when an error occured.
  */
 #ifdef __cplusplus
-extern DECLSPEC int cec_find_adapters(std::vector<CEC::cec_adapter> &deviceList, const char *strDevicePath = NULL);
+extern DECLSPEC int8_t cec_find_adapters(CEC::cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL);
 #else
-extern DECLSPEC int cec_find_adapters(std::vector<cec_adapter> &deviceList, const char *strDevicePath = NULL);
+extern DECLSPEC int8_t cec_find_adapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL);
 #endif
 
 /*!
@@ -96,12 +96,12 @@ extern DECLSPEC bool cec_start_bootloader(void);
 /*!
  * @return Get the minimal version of libcec that this version of libcec can interface with.
  */
-extern DECLSPEC int cec_get_min_version(void);
+extern DECLSPEC int8_t cec_get_min_version(void);
 
 /*!
  * @return Get the version of libcec.
  */
-extern DECLSPEC int cec_get_lib_version(void);
+extern DECLSPEC int8_t cec_get_lib_version(void);
 
 /*!
  * @brief Power on the connected CEC capable devices.
index d5903515b4d9603c54927f336c15015b08fe0be8..34905735ea63a3931fde9925cc20bccf564b2f2c 100644 (file)
@@ -41,7 +41,7 @@ namespace CEC
     /*!
      * @see cec_open
      */
-    virtual bool Open(const char *strPort, uint64_t iTimeoutMs = 10000) = 0;
+    virtual bool Open(const char *strPort, uint32_t iTimeoutMs = 10000) = 0;
 
     /*!
      * @see cec_close
@@ -51,7 +51,7 @@ namespace CEC
     /*!
      * @see cec_find_adapters
      */
-    virtual int FindAdapters(std::vector<cec_adapter> &deviceList, const char *strDevicePath = NULL) = 0;
+    virtual int8_t FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL) = 0;
 
     /*!
      * @see cec_ping_adapters
@@ -67,12 +67,12 @@ namespace CEC
     /*!
      * @see cec_get_min_version
      */
-    virtual int GetMinVersion(void) = 0;
+    virtual int8_t GetMinVersion(void) = 0;
 
     /*!
      * @see cec_get_lib_version
      */
-    virtual int GetLibVersion(void) = 0;
+    virtual int8_t GetLibVersion(void) = 0;
 
     /*!
      * @see cec_get_next_log_message
@@ -124,6 +124,8 @@ namespace CEC
 
 extern DECLSPEC void * CECCreate(const char *strDeviceName, CEC::cec_logical_address iLogicalAddress = CEC::CECDEVICE_PLAYBACKDEVICE1, uint16_t iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS);
 
+extern DECLSPEC void CECDestroy(CEC::ICECAdapter *instance);
+
 #if !defined(DLL_EXPORT)
 #if defined(_WIN32) || defined(_WIN64)
 #include <windows.h>
@@ -158,7 +160,11 @@ inline CEC::ICECAdapter *LoadLibCec(const char *strName, CEC::cec_logical_addres
  */
 inline void UnloadLibCec(CEC::ICECAdapter *device)
 {
-  delete device;
+  typedef void (__cdecl*_DestroyLibCec)(void * device);
+  _DestroyLibCec DestroyLibCec;
+  DestroyLibCec = (_DestroyLibCec) (GetProcAddress(g_libCEC, "CECDestroy"));
+  if (DestroyLibCec)
+    DestroyLibCec(device);
 
   if (--g_iLibCECInstanceCount == 0)
   {
@@ -184,7 +190,7 @@ inline CEC::ICECAdapter *LoadLibCec(const char *strName, CEC::cec_logical_addres
 inline void UnloadLibCec(CEC::ICECAdapter *device)
 {
   device->Close();
-  delete device;
+  CECDestroy(device);
 };
 #endif
 
index 59ec3a3c1ace5c9b717c98c01d9848b8d0401e2e..30a88482c6c9ec79098c4dacd49b6435f19194bf 100644 (file)
@@ -81,7 +81,8 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ExtensionsToDeleteOnClean>*.cdf;*.cache;*.obj;*.ilk;*.resources;*.tlb;*.tli;*.tlh;*.tmp;*.rsp;*.pgc;*.pgd;*.meta;*.tlog;*.manifest;*.res;*.pch;*.exp;*.idb;*.rep;*.xdc;*.pdb;*_manifest.rc;*.bsc;*.sbr;*.xml;*.dll</ExtensionsToDeleteOnClean>
     <IncludePath>$(SolutionDir)..\include;$(IncludePath)</IncludePath>
-    <IgnoreImportLibrary>true</IgnoreImportLibrary>
+    <IgnoreImportLibrary>false</IgnoreImportLibrary>
+    <LinkIncremental>true</LinkIncremental>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <OutDir>$(SolutionDir)..\</OutDir>
       <OutputFile>$(SolutionDir)..\libcec.dll</OutputFile>
       <AdditionalDependencies>%(AdditionalDependencies);setupapi.lib;$(SolutionDir)..\src\lib\platform\pthread_win32\pthreadVC2d.lib</AdditionalDependencies>
       <IgnoreSpecificDefaultLibraries>libcmtd</IgnoreSpecificDefaultLibraries>
-      <Version>2</Version>
+      <Version>5</Version>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
index ae1a4e451c288fd4820cc3527efaf4084d67f20b..84ec74c118bc966eb6fdb8e88a4e41b80696200c 100644 (file)
@@ -60,11 +60,13 @@ CAdapterCommunication::~CAdapterCommunication(void)
     delete m_port;
     m_port = NULL;
   }
+
+  if (m_inbuf)
+    free(m_inbuf);
 }
 
-bool CAdapterCommunication::Open(const char *strPort, uint16_t iBaudRate /* = 38400 */, uint64_t iTimeoutMs /* = 10000 */)
+bool CAdapterCommunication::Open(const char *strPort, uint16_t iBaudRate /* = 38400 */, uint32_t iTimeoutMs /* = 10000 */)
 {
-  CLockObject lock(&m_commMutex);
   if (m_bStarted || !m_port)
     return false;
 
@@ -100,11 +102,13 @@ bool CAdapterCommunication::Open(const char *strPort, uint16_t iBaudRate /* = 38
 
 void CAdapterCommunication::Close(void)
 {
-  CLockObject lock(&m_commMutex);
-  if (m_port)
-    m_port->Close();
+  m_bStop = true;
+  m_rcvCondition.Broadcast();
 
   StopThread();
+
+  if (m_port)
+    m_port->Close();
 }
 
 void *CAdapterCommunication::Process(void)
@@ -113,95 +117,98 @@ void *CAdapterCommunication::Process(void)
 
   while (!m_bStop)
   {
-    CLockObject lock(&m_commMutex);
-    if (!ReadFromDevice(250))
+    if (!ReadFromDevice(1000))
     {
       m_bStarted = false;
       break;
     }
 
     if (!m_bStop)
-    {
-      lock.Leave();
       Sleep(50);
-    }
   }
 
   m_bStarted = false;
   return NULL;
 }
 
-bool CAdapterCommunication::ReadFromDevice(uint64_t iTimeout)
+bool CAdapterCommunication::ReadFromDevice(uint32_t iTimeout)
 {
-  uint8_t buff[1024];
-  if (!m_port)
-    return false;
+  int32_t iBytesRead;
 
-  int32_t iBytesRead = m_port->Read(buff, sizeof(buff), iTimeout);
-  if (iBytesRead < 0 || iBytesRead > 256)
   {
-    CStdString strError;
-    strError.Format("error reading from serial port: %s", m_port->GetError().c_str());
-    m_controller->AddLog(CEC_LOG_ERROR, strError);
-    return false;
+    CLockObject lock(&m_mutex);
+
+    uint8_t buff[1024];
+    if (!m_port)
+      return false;
+
+    iBytesRead = m_port->Read(buff, sizeof(buff), iTimeout);
+    if (iBytesRead < 0 || iBytesRead > 256)
+    {
+      CStdString strError;
+      strError.Format("error reading from serial port: %s", m_port->GetError().c_str());
+      m_controller->AddLog(CEC_LOG_ERROR, strError);
+      return false;
+    }
+    else if (iBytesRead > 0)
+      AddData(buff, (uint8_t) iBytesRead);
   }
-  else if (iBytesRead > 0)
-    AddData(buff, (uint8_t) iBytesRead);
+
+  if (iBytesRead > 0)
+    m_rcvCondition.Signal();
 
   return true;
 }
 
 void CAdapterCommunication::AddData(uint8_t *data, uint8_t iLen)
 {
-  CLockObject lock(&m_bufferMutex);
-  if (iLen + m_iInbufUsed > m_iInbufSize)
+  if (m_iInbufUsed + iLen > m_iInbufSize)
   {
-    m_iInbufSize = iLen + m_iInbufUsed;
+    m_iInbufSize = m_iInbufUsed + iLen;
     m_inbuf = (uint8_t*)realloc(m_inbuf, m_iInbufSize);
   }
 
   memcpy(m_inbuf + m_iInbufUsed, data, iLen);
   m_iInbufUsed += iLen;
-  lock.Leave();
-  m_condition.Signal();
 }
 
 bool CAdapterCommunication::Write(const cec_frame &data)
 {
-  CLockObject lock(&m_commMutex);
-
-  if (m_port->Write(data) != (int) data.size())
   {
-    CStdString strError;
-    strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
-    m_controller->AddLog(CEC_LOG_ERROR, strError);
-    return false;
-  }
+    CLockObject lock(&m_mutex);
+    if (m_port->Write(data) != (int32_t) data.size)
+    {
+      CStdString strError;
+      strError.Format("error writing to serial port: %s", m_port->GetError().c_str());
+      m_controller->AddLog(CEC_LOG_ERROR, strError);
+      return false;
+    }
 
-  m_controller->AddLog(CEC_LOG_DEBUG, "command sent");
+    m_controller->AddLog(CEC_LOG_DEBUG, "command sent");
 
-  Sleep((int) data.size() * 24 /*data*/ + 5 /*start bit (4.5 ms)*/ + 50 /* to be on the safe side */);
+    CCondition::Sleep((uint32_t) data.size * (uint32_t)24 /*data*/ + (uint32_t)5 /*start bit (4.5 ms)*/ + (uint32_t)50 /* to be on the safe side */);
+  }
 
   return true;
 }
 
-bool CAdapterCommunication::Read(cec_frame &msg, uint64_t iTimeout)
+bool CAdapterCommunication::Read(cec_frame &msg, uint32_t iTimeout)
 {
-  CLockObject lock(&m_bufferMutex);
+  CLockObject lock(&m_mutex);
 
   if (m_iInbufUsed < 1)
-    m_condition.Wait(&m_bufferMutex, iTimeout);
+    m_rcvCondition.Wait(&m_mutex, iTimeout);
 
-  if (m_iInbufUsed < 1)
+  if (m_iInbufUsed < 1 || m_bStop)
     return false;
 
   //search for first start of message
-  int startpos = -1;
-  for (int i = 0; i < m_iInbufUsed; i++)
+  int16_t startpos = -1;
+  for (int16_t iPtr = 0; iPtr < m_iInbufUsed; iPtr++)
   {
-    if (m_inbuf[i] == MSGSTART)
+    if (m_inbuf[iPtr] == MSGSTART)
     {
-      startpos = i;
+      startpos = iPtr;
       break;
     }
   }
@@ -221,17 +228,17 @@ bool CAdapterCommunication::Read(cec_frame &msg, uint64_t iTimeout)
 
   //look for end of message
   startpos = -1;
-  int endpos = -1;
-  for (int i = 1; i < m_iInbufUsed; i++)
+  int16_t endpos = -1;
+  for (int16_t iPtr = 1; iPtr < m_iInbufUsed; iPtr++)
   {
-    if (m_inbuf[i] == MSGEND)
+    if (m_inbuf[iPtr] == MSGEND)
     {
-      endpos = i;
+      endpos = iPtr;
       break;
     }
-    else if (m_inbuf[i] == MSGSTART)
+    else if (m_inbuf[iPtr] == MSGSTART)
     {
-      startpos = i;
+      startpos = iPtr;
       break;
     }
   }
@@ -248,20 +255,20 @@ bool CAdapterCommunication::Read(cec_frame &msg, uint64_t iTimeout)
   {
     msg.clear();
     bool isesc = false;
-    for (int i = 1; i < endpos; i++)
+    for (int16_t iPtr = 1; iPtr < endpos; iPtr++)
     {
       if (isesc)
       {
-        msg.push_back(m_inbuf[i] + (uint8_t)ESCOFFSET);
+        msg.push_back(m_inbuf[iPtr] + (uint8_t)ESCOFFSET);
         isesc = false;
       }
-      else if (m_inbuf[i] == MSGESC)
+      else if (m_inbuf[iPtr] == MSGESC)
       {
         isesc = true;
       }
       else
       {
-        msg.push_back(m_inbuf[i]);
+        msg.push_back(m_inbuf[iPtr]);
       }
     }
 
@@ -288,6 +295,8 @@ bool CAdapterCommunication::StartBootloader(void)
 
   m_controller->AddLog(CEC_LOG_DEBUG, "starting the bootloader");
   cec_frame output;
+  output.clear();
+
   output.push_back(MSGSTART);
   PushEscaped(output, MSGCODE_START_BOOTLOADER);
   output.push_back(MSGEND);
@@ -324,6 +333,7 @@ bool CAdapterCommunication::SetAckMask(uint16_t iMask)
   m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
 
   cec_frame output;
+  output.clear();
 
   output.push_back(MSGSTART);
   PushEscaped(output, MSGCODE_SET_ACK_MASK);
@@ -347,6 +357,8 @@ bool CAdapterCommunication::PingAdapter(void)
 
   m_controller->AddLog(CEC_LOG_DEBUG, "sending ping");
   cec_frame output;
+  output.clear();
+
   output.push_back(MSGSTART);
   PushEscaped(output, MSGCODE_PING);
   output.push_back(MSGEND);
index c95f729998d75d5505323125011397229599422b..8ce9c5b790d82dab14cdc13d01c0a585c67d9f8e 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "../../include/CECExports.h"
 #include "platform/threads.h"
+#include <string>
 
 namespace CEC
 {
@@ -45,8 +46,8 @@ namespace CEC
     CAdapterCommunication(CLibCEC *controller);
     virtual ~CAdapterCommunication();
 
-    bool Open(const char *strPort, uint16_t iBaudRate = 38400, uint64_t iTimeoutMs = 10000);
-    bool Read(cec_frame &msg, uint64_t iTimeout = 1000);
+    bool Open(const char *strPort, uint16_t iBaudRate = 38400, uint32_t iTimeoutMs = 10000);
+    bool Read(cec_frame &msg, uint32_t iTimeout = 1000);
     bool Write(const cec_frame &frame);
     bool PingAdapter(void);
     void Close(void);
@@ -60,17 +61,16 @@ namespace CEC
     static void PushEscaped(cec_frame &vec, uint8_t byte);
   private:
     void AddData(uint8_t *data, uint8_t iLen);
-    bool ReadFromDevice(uint64_t iTimeout);
+    bool ReadFromDevice(uint32_t iTimeout);
 
     CSerialPort *        m_port;
     CLibCEC *            m_controller;
     uint8_t*             m_inbuf;
-    int                  m_iInbufSize;
-    int                  m_iInbufUsed;
+    int16_t              m_iInbufSize;
+    int16_t              m_iInbufUsed;
     bool                 m_bStarted;
     bool                 m_bStop;
-    CMutex               m_commMutex;
-    CMutex               m_bufferMutex;
-    CCondition           m_condition;
+    CMutex               m_mutex;
+    CCondition           m_rcvCondition;
   };
 };
index e21d3dc20808a9b2d334b60da8588a0cf8507a9b..5d957a7a0150300bcd582a49616077e79f81e6b2 100644 (file)
@@ -100,9 +100,9 @@ bool FindComPort(CStdString &strLocation)
 }
 #endif
 
-int CAdapterDetection::FindAdapters(vector<cec_adapter> &deviceList, const char *strDevicePath /* = NULL */)
+uint8_t CAdapterDetection::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
 {
-  int iFound(0);
+  uint8_t iFound(0);
 
 #if !defined(__WINDOWS__)
   struct udev *udev;
@@ -111,7 +111,7 @@ int CAdapterDetection::FindAdapters(vector<cec_adapter> &deviceList, const char
 
   struct udev_enumerate *enumerate;
   struct udev_list_entry *devices, *dev_list_entry;
-  struct udev_device *dev;
+  struct udev_device *dev, *pdev;
   enumerate = udev_enumerate_new(udev);
   udev_enumerate_scan_devices(enumerate);
   devices = udev_enumerate_get_list_entry(enumerate);
@@ -124,32 +124,27 @@ int CAdapterDetection::FindAdapters(vector<cec_adapter> &deviceList, const char
     if (!dev)
       continue;
 
-    dev = udev_device_get_parent(udev_device_get_parent(dev));
-    if (!dev)
-      continue;
-    if (!udev_device_get_sysattr_value(dev,"idVendor") || !udev_device_get_sysattr_value(dev, "idProduct"))
+    pdev = udev_device_get_parent(udev_device_get_parent(dev));
+    if (!pdev || !udev_device_get_sysattr_value(pdev,"idVendor") || !udev_device_get_sysattr_value(pdev, "idProduct"))
     {
       udev_device_unref(dev);
       continue;
     }
 
     int iVendor, iProduct;
-    sscanf(udev_device_get_sysattr_value(dev, "idVendor"), "%x", &iVendor);
-    sscanf(udev_device_get_sysattr_value(dev, "idProduct"), "%x", &iProduct);
+    sscanf(udev_device_get_sysattr_value(pdev, "idVendor"), "%x", &iVendor);
+    sscanf(udev_device_get_sysattr_value(pdev, "idProduct"), "%x", &iProduct);
     if (iVendor == CEC_VID && iProduct == CEC_PID)
     {
-      CStdString strPath(udev_device_get_syspath(dev));
-      if (strDevicePath && strcmp(strPath.c_str(), strDevicePath))
-        continue;
-
-      CStdString strComm(strPath);
-      if (FindComPort(strComm))
+      CStdString strPath(udev_device_get_syspath(pdev));
+      if (!strDevicePath || !strcmp(strPath.c_str(), strDevicePath))
       {
-        cec_adapter foundDev;
-        foundDev.path = strPath;
-        foundDev.comm = strComm;
-        deviceList.push_back(foundDev);
-        ++iFound;
+        CStdString strComm(strPath);
+        if (FindComPort(strComm))
+        {
+          snprintf(deviceList[iFound  ].path, sizeof(deviceList[iFound].path), "%s", strPath.c_str());
+          snprintf(deviceList[iFound++].comm, sizeof(deviceList[iFound].path), "%s", strComm.c_str());
+        }
       }
     }
     udev_device_unref(dev);
@@ -174,7 +169,7 @@ int CAdapterDetection::FindAdapters(vector<cec_adapter> &deviceList, const char
   BOOL bResult = true;
   TCHAR *buffer = NULL;
   PSP_DEVICE_INTERFACE_DETAIL_DATA devicedetailData;
-  while(bResult)
+  while(bResult && iFound < iBufSize)
   {
     bResult = SetupDiEnumDeviceInfo(hDevHandle, iMemberIndex, &devInfoData);
 
@@ -217,8 +212,8 @@ int CAdapterDetection::FindAdapters(vector<cec_adapter> &deviceList, const char
     CStdString strVendorId;
     CStdString strProductId;
     CStdString strTmp(devicedetailData->DevicePath);
-    strVendorId = strTmp.substr(strTmp.Find("vid_") + 4, 4);
-    strProductId = strTmp.substr(strTmp.Find("pid_") + 4, 4);
+    strVendorId.assign(strTmp.substr(strTmp.Find("vid_") + 4, 4));
+    strProductId.assign(strTmp.substr(strTmp.Find("pid_") + 4, 4));
     if (strTmp.Find("&mi_") >= 0 && strTmp.Find("&mi_00") < 0)
       continue;
 
@@ -243,11 +238,8 @@ int CAdapterDetection::FindAdapters(vector<cec_adapter> &deviceList, const char
       if (_tcslen(strPortName) > 3 && _tcsnicmp(strPortName, _T("COM"), 3) == 0 &&
         _ttoi(&(strPortName[3])) > 0)
       {
-        cec_adapter foundDev;
-        foundDev.path = devicedetailData->DevicePath;
-        foundDev.comm = strPortName;
-        deviceList.push_back(foundDev);
-        ++iFound;
+        snprintf(deviceList[iFound  ].path, sizeof(deviceList[iFound].path), "%s", devicedetailData->DevicePath);
+        snprintf(deviceList[iFound++].comm, sizeof(deviceList[iFound].path), "%s", strPortName);
       }
     }
 
index d775bbc88984a50417d6e38b3e0a3f3deb1e467d..8af1834ba75efbb1b20579deca51785b6de7f87a 100644 (file)
@@ -38,6 +38,6 @@ namespace CEC
   class CAdapterDetection
   {
   public:
-    static int FindAdapters(std::vector<cec_adapter> &deviceList, const char *strDevicePath = NULL);
+    static uint8_t FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL); 
   };
 };
index 6750c87dba52a1a2c9dd8111755a51cb11c9bec4..74f03b379698d3965d48e6cdef662358d1b1d70f 100644 (file)
@@ -85,6 +85,8 @@ void *CCECProcessor::Process(void)
     {
       CLockObject lock(&m_mutex);
       cec_frame msg;
+      msg.clear();
+
       if (!m_bStop && m_communication->IsOpen() && m_communication->Read(msg, CEC_BUTTON_TIMEOUT))
         bParseFrame = ParseMessage(msg);
     }
@@ -111,6 +113,8 @@ bool CCECProcessor::PowerOnDevices(cec_logical_address address /* = CECDEVICE_TV
   strLog.Format("powering on devices with logical address %d", (int8_t)address);
   m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
   cec_frame frame;
+  frame.clear();
+
   frame.push_back(GetSourceDestination(address));
   frame.push_back((uint8_t) CEC_OPCODE_TEXT_VIEW_ON);
   return Transmit(frame);
@@ -125,6 +129,8 @@ bool CCECProcessor::StandbyDevices(cec_logical_address address /* = CECDEVICE_BR
   strLog.Format("putting all devices with logical address %d in standby mode", (int8_t)address);
   m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
   cec_frame frame;
+  frame.clear();
+
   frame.push_back(GetSourceDestination(address));
   frame.push_back((uint8_t) CEC_OPCODE_STANDBY);
   return Transmit(frame);
@@ -137,6 +143,8 @@ bool CCECProcessor::SetActiveView(void)
 
   m_controller->AddLog(CEC_LOG_DEBUG, "setting active view");
   cec_frame frame;
+  frame.clear();
+
   frame.push_back(GetSourceDestination(CECDEVICE_BROADCAST));
   frame.push_back((uint8_t) CEC_OPCODE_ACTIVE_SOURCE);
   frame.push_back((m_physicaladdress >> 8) & 0xFF);
@@ -151,6 +159,8 @@ bool CCECProcessor::SetInactiveView(void)
 
   m_controller->AddLog(CEC_LOG_DEBUG, "setting inactive view");
   cec_frame frame;
+  frame.clear();
+
   frame.push_back(GetSourceDestination(CECDEVICE_BROADCAST));
   frame.push_back((uint8_t) CEC_OPCODE_INACTIVE_SOURCE);
   frame.push_back((m_physicaladdress >> 8) & 0xFF);
@@ -161,40 +171,41 @@ bool CCECProcessor::SetInactiveView(void)
 bool CCECProcessor::Transmit(const cec_frame &data, bool bWaitForAck /* = true */)
 {
   CStdString txStr = "transmit ";
-  for (unsigned int i = 0; i < data.size(); i++)
-    txStr.AppendFormat(" %02x", data[i]);
+  for (unsigned int i = 0; i < data.size; i++)
+    txStr.AppendFormat(" %02x", data.data[i]);
   m_controller->AddLog(CEC_LOG_DEBUG, txStr.c_str());
 
-  if (data.empty())
+  if (data.size == 0)
   {
     m_controller->AddLog(CEC_LOG_WARNING, "transmit buffer is empty");
     return false;
   }
 
   cec_frame output;
+  output.clear();
 
   //set ack polarity to high when transmitting to the broadcast address
   //set ack polarity low when transmitting to any other address
   output.push_back(MSGSTART);
   CAdapterCommunication::PushEscaped(output, MSGCODE_TRANSMIT_ACK_POLARITY);
 
-  if ((data[0] & 0xF) == 0xF)
+  if ((data.data[0] & 0xF) == 0xF)
     CAdapterCommunication::PushEscaped(output, CEC_TRUE);
   else
     CAdapterCommunication::PushEscaped(output, CEC_FALSE);
 
   output.push_back(MSGEND);
 
-  for (unsigned int i = 0; i < data.size(); i++)
+  for (int8_t i = 0; i < data.size; i++)
   {
     output.push_back(MSGSTART);
 
-    if (i == data.size() - 1)
+    if (i == (int8_t)data.size - 1)
       CAdapterCommunication::PushEscaped(output, MSGCODE_TRANSMIT_EOM);
     else
       CAdapterCommunication::PushEscaped(output, MSGCODE_TRANSMIT);
 
-    CAdapterCommunication::PushEscaped(output, data[i]);
+    CAdapterCommunication::PushEscaped(output, data.data[i]);
 
     output.push_back(MSGEND);
   }
@@ -231,6 +242,8 @@ void CCECProcessor::TransmitAbort(cec_logical_address address, cec_opcode opcode
 {
   m_controller->AddLog(CEC_LOG_DEBUG, "transmitting abort message");
   cec_frame frame;
+  frame.clear();
+
   frame.push_back(GetSourceDestination(address));
   frame.push_back((uint8_t) CEC_OPCODE_FEATURE_ABORT);
   frame.push_back((uint8_t) opcode);
@@ -241,16 +254,20 @@ void CCECProcessor::TransmitAbort(cec_logical_address address, cec_opcode opcode
 void CCECProcessor::ReportCECVersion(cec_logical_address address /* = CECDEVICE_TV */)
 {
   cec_frame frame;
+  frame.clear();
+
   m_controller->AddLog(CEC_LOG_NOTICE, "reporting CEC version as 1.3a");
   frame.push_back(GetSourceDestination(address));
   frame.push_back((uint8_t) CEC_OPCODE_CEC_VERSION);
-  frame.push_back(CEC_VERSION_1_3A);
+  frame.push_back((uint8_t) CEC_VERSION_1_3A);
   Transmit(frame);
 }
 
 void CCECProcessor::ReportPowerState(cec_logical_address address /*= CECDEVICE_TV */, bool bOn /* = true */)
 {
   cec_frame frame;
+  frame.clear();
+
   if (bOn)
     m_controller->AddLog(CEC_LOG_NOTICE, "reporting \"On\" power status");
   else
@@ -265,6 +282,8 @@ void CCECProcessor::ReportPowerState(cec_logical_address address /*= CECDEVICE_T
 void CCECProcessor::ReportMenuState(cec_logical_address address /* = CECDEVICE_TV */, bool bActive /* = true */)
 {
   cec_frame frame;
+  frame.clear();
+
   if (bActive)
     m_controller->AddLog(CEC_LOG_NOTICE, "reporting menu state as active");
   else
@@ -285,6 +304,8 @@ void CCECProcessor::ReportVendorID(cec_logical_address address /* = CECDEVICE_TV
 void CCECProcessor::ReportOSDName(cec_logical_address address /* = CECDEVICE_TV */)
 {
   cec_frame frame;
+  frame.clear();
+
   const char *osdname = m_strDeviceName.c_str();
   CStdString strLog;
   strLog.Format("reporting OSD name as %s", osdname);
@@ -301,25 +322,29 @@ void CCECProcessor::ReportOSDName(cec_logical_address address /* = CECDEVICE_TV
 void CCECProcessor::ReportPhysicalAddress(void)
 {
   cec_frame frame;
+  frame.clear();
+
   CStdString strLog;
   strLog.Format("reporting physical address as %04x", m_physicaladdress);
   m_controller->AddLog(CEC_LOG_NOTICE, strLog.c_str());
   frame.push_back(GetSourceDestination(CECDEVICE_BROADCAST));
   frame.push_back((uint8_t) CEC_OPCODE_REPORT_PHYSICAL_ADDRESS);
-  frame.push_back((m_physicaladdress >> 8) & 0xFF);
-  frame.push_back(m_physicaladdress & 0xFF);
-  frame.push_back(CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
+  frame.push_back((uint8_t) ((m_physicaladdress >> 8) & 0xFF));
+  frame.push_back((uint8_t) (m_physicaladdress & 0xFF));
+  frame.push_back((uint8_t) CEC_DEVICE_TYPE_PLAYBACK_DEVICE);
   Transmit(frame);
 }
 
 void CCECProcessor::BroadcastActiveSource(void)
 {
   cec_frame frame;
+  frame.clear();
+
   m_controller->AddLog(CEC_LOG_NOTICE, "broadcasting active source");
   frame.push_back(GetSourceDestination(CECDEVICE_BROADCAST));
   frame.push_back((uint8_t) CEC_OPCODE_ACTIVE_SOURCE);
-  frame.push_back((m_physicaladdress >> 8) & 0xFF);
-  frame.push_back(m_physicaladdress & 0xFF);
+  frame.push_back((uint8_t) ((m_physicaladdress >> 8) & 0xFF));
+  frame.push_back((uint8_t) (m_physicaladdress & 0xFF));
   Transmit(frame);
 }
 
@@ -328,20 +353,22 @@ uint8_t CCECProcessor::GetSourceDestination(cec_logical_address destination /* =
   return ((uint8_t)m_iLogicalAddress << 4) + (uint8_t)destination;
 }
 
-bool CCECProcessor::WaitForAck(int iTimeout /* = 1000 */)
+bool CCECProcessor::WaitForAck(uint32_t iTimeout /* = 1000 */)
 {
   bool bGotAck(false);
   bool bError(false);
 
   int64_t iNow = GetTimeMs();
-  int64_t iTargetTime = iNow + (int64_t) iTimeout;
+  int64_t iTargetTime = iNow + (uint64_t) iTimeout;
 
-  while (!bGotAck && !bError && (iTimeout <= 0 || iNow < iTargetTime))
+  while (!bGotAck && !bError && (iTimeout == 0 || iNow < iTargetTime))
   {
     cec_frame msg;
+    msg.clear();
+
     while (!bGotAck && !bError && m_communication->Read(msg, iTimeout))
     {
-      uint8_t iCode = msg[0] & ~(MSGCODE_FRAME_EOM | MSGCODE_FRAME_ACK);
+      uint8_t iCode = msg.data[0] & ~(MSGCODE_FRAME_EOM | MSGCODE_FRAME_ACK);
 
       switch (iCode)
       {
@@ -379,7 +406,7 @@ bool CCECProcessor::WaitForAck(int iTimeout /* = 1000 */)
         break;
       default:
         m_frameBuffer.Push(msg);
-        bGotAck = (msg[0] & MSGCODE_FRAME_ACK) != 0;
+        bGotAck = (msg.data[0] & MSGCODE_FRAME_ACK) != 0;
         break;
       }
       iNow = GetTimeMs();
@@ -393,13 +420,13 @@ bool CCECProcessor::ParseMessage(cec_frame &msg)
 {
   bool bReturn(false);
 
-  if (msg.empty())
+  if (msg.size == 0)
     return bReturn;
 
   CStdString logStr;
-  uint8_t iCode = msg[0] & ~(MSGCODE_FRAME_EOM | MSGCODE_FRAME_ACK);
-  bool    bEom  = (msg[0] & MSGCODE_FRAME_EOM) != 0;
-  bool    bAck  = (msg[0] & MSGCODE_FRAME_ACK) != 0;
+  uint8_t iCode = msg.data[0] & ~(MSGCODE_FRAME_EOM | MSGCODE_FRAME_ACK);
+  bool    bEom  = (msg.data[0] & MSGCODE_FRAME_EOM) != 0;
+  bool    bAck  = (msg.data[0] & MSGCODE_FRAME_ACK) != 0;
 
   switch(iCode)
   {
@@ -417,8 +444,8 @@ bool CCECProcessor::ParseMessage(cec_frame &msg)
       else
         logStr = "MSGCODE_LOW_ERROR";
 
-      int iLine      = (msg.size() >= 3) ? (msg[1] << 8) | (msg[2]) : 0;
-      uint32_t iTime = (msg.size() >= 7) ? (msg[3] << 24) | (msg[4] << 16) | (msg[5] << 8) | (msg[6]) : 0;
+      int iLine      = (msg.size >= 3) ? (msg.data[1] << 8) | (msg.data[2]) : 0;
+      uint32_t iTime = (msg.size >= 7) ? (msg.data[3] << 24) | (msg.data[4] << 16) | (msg.data[5] << 8) | (msg.data[6]) : 0;
       logStr.AppendFormat(" line:%i", iLine);
       logStr.AppendFormat(" time:%u", iTime);
       m_controller->AddLog(CEC_LOG_WARNING, logStr.c_str());
@@ -428,13 +455,13 @@ bool CCECProcessor::ParseMessage(cec_frame &msg)
     {
       logStr = "MSGCODE_FRAME_START";
       m_currentframe.clear();
-      if (msg.size() >= 2)
+      if (msg.size >= 2)
       {
-        int iInitiator = msg[1] >> 4;
-        int iDestination = msg[1] & 0xF;
+        int iInitiator = msg.data[1] >> 4;
+        int iDestination = msg.data[1] & 0xF;
         logStr.AppendFormat(" initiator:%u destination:%u ack:%s %s", iInitiator, iDestination, bAck ? "high" : "low", bEom ? "eom" : "");
 
-        m_currentframe.push_back(msg[1]);
+        m_currentframe.push_back(msg.data[1]);
       }
       m_controller->AddLog(CEC_LOG_DEBUG, logStr.c_str());
     }
@@ -442,9 +469,9 @@ bool CCECProcessor::ParseMessage(cec_frame &msg)
   case MSGCODE_FRAME_DATA:
     {
       logStr = "MSGCODE_FRAME_DATA";
-      if (msg.size() >= 2)
+      if (msg.size >= 2)
       {
-        uint8_t iData = msg[1];
+        uint8_t iData = msg.data[1];
         logStr.AppendFormat(" %02x", iData);
         m_currentframe.push_back(iData);
       }
@@ -462,25 +489,24 @@ bool CCECProcessor::ParseMessage(cec_frame &msg)
 
 void CCECProcessor::ParseCurrentFrame(void)
 {
-  uint8_t initiator = m_currentframe[0] >> 4;
-  uint8_t destination = m_currentframe[0] & 0xF;
+  uint8_t initiator = m_currentframe.data[0] >> 4;
+  uint8_t destination = m_currentframe.data[0] & 0xF;
 
   CStdString dataStr;
   dataStr.Format("received frame: initiator: %u destination: %u", initiator, destination);
 
-  if (m_currentframe.size() > 1)
+  if (m_currentframe.size > 1)
   {
     dataStr += " data:";
-    for (unsigned int i = 1; i < m_currentframe.size(); i++)
-      dataStr.AppendFormat(" %02x", m_currentframe[i]);
+    for (unsigned int i = 1; i < m_currentframe.size; i++)
+      dataStr.AppendFormat(" %02x", m_currentframe.data[i]);
   }
   m_controller->AddLog(CEC_LOG_DEBUG, dataStr.c_str());
 
-  if (m_currentframe.size() <= 1)
+  if (m_currentframe.size <= 1)
     return;
 
-  vector<uint8_t> tx;
-  cec_opcode opCode = (cec_opcode) m_currentframe[1];
+  cec_opcode opCode = (cec_opcode) m_currentframe.data[1];
   if (destination == (uint16_t) m_iLogicalAddress)
   {
     switch(opCode)
@@ -505,12 +531,12 @@ void CCECProcessor::ParseCurrentFrame(void)
       ReportCECVersion((cec_logical_address)initiator);
       break;
     case CEC_OPCODE_USER_CONTROL_PRESSED:
-      if (m_currentframe.size() > 2)
+      if (m_currentframe.size > 2)
       {
         m_controller->AddKey();
 
-        if (m_currentframe[2] <= CEC_USER_CONTROL_CODE_MAX)
-          m_controller->SetCurrentButton((cec_user_control_code) m_currentframe[2]);
+        if (m_currentframe.data[2] <= CEC_USER_CONTROL_CODE_MAX)
+          m_controller->SetCurrentButton((cec_user_control_code) m_currentframe.data[2]);
       }
       break;
     case CEC_OPCODE_USER_CONTROL_RELEASE:
@@ -518,7 +544,7 @@ void CCECProcessor::ParseCurrentFrame(void)
       break;
     default:
       cec_frame params = m_currentframe;
-      params.erase(params.begin(), params.begin() + 2);
+      params.shift(2);
       m_controller->AddCommand((cec_logical_address) initiator, (cec_logical_address) destination, opCode, &params);
       break;
     }
@@ -531,9 +557,9 @@ void CCECProcessor::ParseCurrentFrame(void)
     }
     else if (opCode == CEC_OPCODE_SET_STREAM_PATH)
     {
-      if (m_currentframe.size() >= 4)
+      if (m_currentframe.size >= 4)
       {
-        int streamaddr = ((int)m_currentframe[2] << 8) | ((int)m_currentframe[3]);
+        int streamaddr = ((int)m_currentframe.data[2] << 8) | ((int)m_currentframe.data[3]);
         CStdString strLog;
         strLog.Format("%i requests stream path from physical address %04x", initiator, streamaddr);
         m_controller->AddLog(CEC_LOG_DEBUG, strLog.c_str());
@@ -544,7 +570,7 @@ void CCECProcessor::ParseCurrentFrame(void)
     else
     {
       cec_frame params = m_currentframe;
-      params.erase(params.begin(), params.begin() + 2);
+      params.shift(2);
       m_controller->AddCommand((cec_logical_address) initiator, (cec_logical_address) destination, opCode, &params);
     }
   }
index 90db3bc28038e57141dc129942f5b4e5b3a70975..5c8d8ab2651340e8a0a752027e44c2f221b61e60 100644 (file)
@@ -31,6 +31,7 @@
  *     http://www.pulse-eight.net/
  */
 
+#include <string>
 #include "../../include/CECExports.h"
 #include "../../include/CECTypes.h"
 #include "platform/threads.h"
@@ -71,7 +72,7 @@ namespace CEC
       virtual uint8_t GetSourceDestination(cec_logical_address destination = CECDEVICE_BROADCAST) const;
 
     private:
-      bool WaitForAck(int iTimeout = 1000);
+      bool WaitForAck(uint32_t iTimeout = 1000);
       bool ParseMessage(cec_frame &msg);
       void ParseCurrentFrame(void);
 
index abc800c19cc528af2ff0029f43b6787a9f9a5625..652d732087b62ca5bf85fe8413fe250a0ccbe1d3 100644 (file)
@@ -42,6 +42,7 @@ using namespace std;
 using namespace CEC;
 
 CLibCEC::CLibCEC(const char *strDeviceName, cec_logical_address iLogicalAddress /* = CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS */) :
+    m_bStarted(false),
     m_iCurrentButton(CEC_USER_CONTROL_CODE_UNKNOWN),
     m_buttontime(0)
 {
@@ -57,9 +58,13 @@ CLibCEC::~CLibCEC(void)
 
   delete m_comm;
   m_comm = NULL;
+
+  m_logBuffer.Clear();
+  m_keyBuffer.Clear();
+  m_commandBuffer.Clear();
 }
 
-bool CLibCEC::Open(const char *strPort, uint64_t iTimeoutMs /* = 10000 */)
+bool CLibCEC::Open(const char *strPort, uint32_t iTimeoutMs /* = 10000 */)
 {
   if (!m_comm)
   {
@@ -85,18 +90,20 @@ bool CLibCEC::Open(const char *strPort, uint64_t iTimeoutMs /* = 10000 */)
     return false;
   }
 
+  m_bStarted = true;
   return true;
 }
 
 void CLibCEC::Close(void)
 {
-  if (m_cec)
-    m_cec->StopThread();
   if (m_comm)
     m_comm->Close();
+  if (m_cec)
+    m_cec->StopThread();
+  m_bStarted = false;
 }
 
-int CLibCEC::FindAdapters(std::vector<cec_adapter> &deviceList, const char *strDevicePath /* = NULL */)
+int8_t CLibCEC::FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
 {
   CStdString strDebug;
   if (strDevicePath)
@@ -105,7 +112,7 @@ int CLibCEC::FindAdapters(std::vector<cec_adapter> &deviceList, const char *strD
     strDebug.Format("trying to autodetect all CEC adapters");
   AddLog(CEC_LOG_DEBUG, strDebug);
 
-  return CAdapterDetection::FindAdapters(deviceList, strDevicePath);
+  return CAdapterDetection::FindAdapters(deviceList, iBufSize, strDevicePath);
 }
 
 bool CLibCEC::PingAdapter(void)
@@ -118,19 +125,19 @@ bool CLibCEC::StartBootloader(void)
   return m_comm ? m_comm->StartBootloader() : false;
 }
 
-int CLibCEC::GetMinVersion(void)
+int8_t CLibCEC::GetMinVersion(void)
 {
   return CEC_MIN_VERSION;
 }
 
-int CLibCEC::GetLibVersion(void)
+int8_t CLibCEC::GetLibVersion(void)
 {
   return CEC_LIB_VERSION;
 }
 
 bool CLibCEC::GetNextLogMessage(cec_log_message *message)
 {
-  return m_logBuffer.Pop(*message);
+  return (m_logBuffer.Pop(*message));
 }
 
 bool CLibCEC::GetNextKeypress(cec_keypress *key)
@@ -175,17 +182,21 @@ bool CLibCEC::SetInactiveView(void)
 
 void CLibCEC::AddLog(cec_log_level level, const string &strMessage)
 {
-  cec_log_message message;
-  message.level = level;
-  message.message.assign(strMessage.c_str());
-  m_logBuffer.Push(message);
+  if (m_bStarted)
+  {
+    cec_log_message message;
+    message.level = level;
+    snprintf(message.message, sizeof(message.message), "%s", strMessage.c_str());
+    m_logBuffer.Push(message);
+  }
 }
 
 void CLibCEC::AddKey(void)
 {
-  if (m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN)
+  if (m_bStarted && m_iCurrentButton != CEC_USER_CONTROL_CODE_UNKNOWN)
   {
     cec_keypress key;
+
     key.duration = (unsigned int) (GetTimeMs() - m_buttontime);
     key.keycode = m_iCurrentButton;
     m_keyBuffer.Push(key);
@@ -196,7 +207,12 @@ void CLibCEC::AddKey(void)
 
 void CLibCEC::AddCommand(cec_logical_address source, cec_logical_address destination, cec_opcode opcode, cec_frame *parameters)
 {
+  if (!m_bStarted)
+    return;
+
   cec_command command;
+  command.clear();
+
   command.source       = source;
   command.destination  = destination;
   command.opcode       = opcode;
@@ -229,7 +245,14 @@ void CLibCEC::SetCurrentButton(cec_user_control_code iButtonCode)
   m_buttontime = GetTimeMs();
 }
 
-DECLSPEC void * CECCreate(const char *strDeviceName, CEC::cec_logical_address iLogicalAddress /*= CEC::CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS */)
+void * CECCreate(const char *strDeviceName, CEC::cec_logical_address iLogicalAddress /*= CEC::CECDEVICE_PLAYBACKDEVICE1 */, uint16_t iPhysicalAddress /* = CEC_DEFAULT_PHYSICAL_ADDRESS */)
 {
   return static_cast< void* > (new CLibCEC(strDeviceName, iLogicalAddress, iPhysicalAddress));
 }
+
+void CECDestroy(CEC::ICECAdapter *instance)
+{
+  CLibCEC *lib = static_cast< CLibCEC* > (instance);
+  if (lib)
+    delete lib;
+}
index 29110717536445c8c86de320908ae156b6f1453f..58c2262ede321ab4967e8660c82b872fd1525a01 100644 (file)
@@ -31,6 +31,7 @@
  *     http://www.pulse-eight.net/
  */
 
+#include <string>
 #include "../../include/CECExports.h"
 #include "../../include/CECTypes.h"
 #include "util/buffer.h"
@@ -50,14 +51,14 @@ namespace CEC
       CLibCEC(const char *strDeviceName, cec_logical_address iLogicalAddress = CECDEVICE_PLAYBACKDEVICE1, uint16_t iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS);
       virtual ~CLibCEC(void);
 
-      virtual bool Open(const char *strPort, uint64_t iTimeout = 10000);
+      virtual bool Open(const char *strPort, uint32_t iTimeout = 10000);
       virtual void Close(void);
-      virtual int  FindAdapters(std::vector<cec_adapter> &deviceList, const char *strDevicePath = NULL);
+      virtual int8_t FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL);
       virtual bool PingAdapter(void);
       virtual bool StartBootloader(void);
 
-      virtual int  GetMinVersion(void);
-      virtual int  GetLibVersion(void);
+      virtual int8_t GetMinVersion(void);
+      virtual int8_t GetLibVersion(void);
 
       virtual bool GetNextLogMessage(cec_log_message *message);
       virtual bool GetNextKeypress(cec_keypress *key);
@@ -79,6 +80,7 @@ namespace CEC
       virtual void SetCurrentButton(cec_user_control_code iButtonCode);
 
     protected:
+      bool                       m_bStarted;
       cec_user_control_code      m_iCurrentButton;
       int64_t                    m_buttontime;
       CCECProcessor             *m_cec;
index 60ada61b749fcc13c77f39ff1e292ecfbc19bfdf..4c7276a0fe5d8c28c4861ced3c1c6ad56f653b56 100644 (file)
@@ -50,11 +50,11 @@ bool cec_init(const char *strDeviceName, cec_logical_address iLogicalAddress /*
 void cec_destroy(void)
 {
   cec_close();
-  delete cec_parser;
+  CECDestroy(cec_parser);
   cec_parser = NULL;
 }
 
-bool cec_open(const char *strPort, uint64_t iTimeout)
+bool cec_open(const char *strPort, uint32_t iTimeout)
 {
   if (cec_parser)
     return cec_parser->Open(strPort, iTimeout);
@@ -67,10 +67,10 @@ void cec_close(void)
     cec_parser->Close();
 }
 
-int cec_find_adapters(vector<cec_adapter> &deviceList, const char *strDevicePath /* = NULL */)
+int8_t cec_find_adapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath /* = NULL */)
 {
   if (cec_parser)
-    return cec_parser->FindAdapters(deviceList, strDevicePath);
+    return cec_parser->FindAdapters(deviceList, iBufSize, strDevicePath);
   return -1;
 }
 
@@ -88,14 +88,14 @@ bool cec_start_bootloader(void)
   return false;
 }
 
-int cec_get_min_version(void)
+int8_t cec_get_min_version(void)
 {
   if (cec_parser)
     return cec_parser->GetMinVersion();
   return -1;
 }
 
-int cec_get_lib_version(void)
+int8_t cec_get_lib_version(void)
 {
   if (cec_parser)
     return cec_parser->GetLibVersion();
index e8fb8e5b411f52c34fbe82066b7800256bc89124..0bb4e2cf6c419ad0980fea55ecab2033664015f4 100644 (file)
@@ -35,7 +35,7 @@ CSerialPort::~CSerialPort()
   Close();
 }
 
-int32_t CSerialPort::Write(uint8_t* data, uint32_t len)
+int8_t CSerialPort::Write(const cec_frame &data)
 {
   fd_set port;
 
@@ -48,7 +48,7 @@ int32_t CSerialPort::Write(uint8_t* data, uint32_t len)
 
   int32_t byteswritten = 0;
 
-  while (byteswritten < (int32_t) len)
+  while (byteswritten < (int32_t) data.size)
   {
     FD_ZERO(&port);
     FD_SET(m_fd, &port);
@@ -59,7 +59,7 @@ int32_t CSerialPort::Write(uint8_t* data, uint32_t len)
       return -1;
     }
 
-    returnv = write(m_fd, data + byteswritten, len - byteswritten);
+    returnv = write(m_fd, data.data + byteswritten, data.size - byteswritten);
     if (returnv == -1)
     {
       m_error = strerror(errno);
@@ -73,8 +73,8 @@ int32_t CSerialPort::Write(uint8_t* data, uint32_t len)
 //  {
 //    printf("%s write:", m_name.c_str());
 //    for (int i = 0; i < byteswritten; i++)
-//      printf(" %02x", (unsigned int)data[i]);
-
+//      printf(" %02x", (unsigned int)data.data[i]);
+//
 //    printf("\n");
 //  }
 
index ea6cdea15ff31eb152e5e78268e494d78cbdbe2b..9cc2c9a1439b5530b5380e1d85312b7451c992bf 100644 (file)
@@ -19,8 +19,8 @@
  */
 
 #include "os-dependent.h"
+#include "../../../include/CECExports.h"
 #include <string>
-#include <vector>
 #include <stdint.h>
 #include "../platform/threads.h"
 
@@ -46,11 +46,7 @@ namespace CEC
       bool IsOpen();
       void Close();
 
-      int32_t  Write(std::vector<uint8_t> data)
-      {
-        return Write(&data[0], (uint32_t) data.size());
-      }
-      int32_t Write(uint8_t* data, uint32_t len);
+      int8_t Write(const cec_frame &data);
       int32_t Read(uint8_t* data, uint32_t len, uint64_t iTimeoutMs = 0);
 
       std::string GetError() { return m_error; }
index 08a4c3b8884c39e9ce775212e8d5665a78175316..46953169c98c5a4e485c87470f1bfcd48e88e235 100644 (file)
@@ -106,7 +106,7 @@ void CCondition::Signal(void)
   pthread_cond_signal(&m_cond);
 }
 
-bool CCondition::Wait(CMutex *mutex, int64_t iTimeout)
+bool CCondition::Wait(CMutex *mutex, uint32_t iTimeout)
 {
   bool bReturn(false);
   sched_yield();
@@ -114,19 +114,17 @@ bool CCondition::Wait(CMutex *mutex, int64_t iTimeout)
   {
     struct timespec abstime;
     struct timeval now;
-    if (gettimeofday(&now, NULL) == 0)
-    {
-      iTimeout       += now.tv_usec / 1000;
-      abstime.tv_sec  = now.tv_sec + (time_t)(iTimeout / 1000);
-      abstime.tv_nsec = (long)((iTimeout % (unsigned long)1000) * (unsigned long)1000000);
-      bReturn         = (pthread_cond_timedwait(&m_cond, &mutex->m_mutex, &abstime) == 0);
-    }
+    gettimeofday(&now, NULL);
+    iTimeout       += now.tv_usec / 1000;
+    abstime.tv_sec  = now.tv_sec + (time_t)(iTimeout / 1000);
+    abstime.tv_nsec = (int32_t)((iTimeout % (uint32_t)1000) * (uint32_t)1000000);
+    bReturn         = (pthread_cond_timedwait(&m_cond, &mutex->m_mutex, &abstime) == 0);
   }
 
   return bReturn;
 }
 
-void CCondition::Sleep(int64_t iTimeout)
+void CCondition::Sleep(uint32_t iTimeout)
 {
   CCondition w;
   CMutex m;
@@ -142,9 +140,7 @@ CThread::CThread(void) :
 
 CThread::~CThread(void)
 {
-  m_bStop = true;
-  m_threadCondition.Broadcast();
-  pthread_join(m_thread, NULL);
+  StopThread();
 }
 
 bool CThread::CreateThread(void)
@@ -179,14 +175,19 @@ bool CThread::StopThread(bool bWaitForExit /* = true */)
   m_bStop = true;
 
   m_threadCondition.Broadcast();
-  void *retVal;
-  if (bWaitForExit)
-    bReturn = (pthread_join(m_thread, &retVal) == 0);
+  if (m_bRunning)
+  {
+    void *retVal;
+    if (bWaitForExit)
+      bReturn = (pthread_join(m_thread, &retVal) == 0);
+
+    m_bRunning = false;
+  }
 
   return bReturn;
 }
 
-bool CThread::Sleep(uint64_t iTimeout)
+bool CThread::Sleep(uint32_t iTimeout)
 {
   CLockObject lock(&m_threadMutex);
   return m_bStop ? false :m_threadCondition.Wait(&m_threadMutex, iTimeout);
index 8b0729db4cf045dccbf3f1bf6777b5d33f6e0df2..9ba273c9970662cb0225fb8f5ba27f141b3e552a 100644 (file)
@@ -46,8 +46,8 @@ namespace CEC
 
     void Broadcast(void);
     void Signal(void);
-    bool Wait(CMutex *mutex, int64_t iTimeout);
-    static void Sleep(int64_t iTimeout);
+    bool Wait(CMutex *mutex, uint32_t iTimeout);
+    static void Sleep(uint32_t iTimeout);
 
   private:
     pthread_cond_t  m_cond;
@@ -90,7 +90,7 @@ namespace CEC
     virtual bool IsRunning(void) const { return m_bRunning; }
     virtual bool CreateThread(void);
     virtual bool StopThread(bool bWaitForExit = true);
-    virtual bool Sleep(uint64_t iTimeout);
+    virtual bool Sleep(uint32_t iTimeout);
 
     static void *ThreadHandler(CThread *thread);
     virtual void *Process(void) = 0;
index ce299cf0d443177ed9ff1bf289761eede2e082e2..443b426b2fd9c9e174e830b00e1ece7b5ade7961 100644 (file)
@@ -166,21 +166,21 @@ void CSerialPort::Close(void)
   }
 }
 
-int32_t CSerialPort::Write(uint8_t* data, uint32_t len)
+int8_t CSerialPort::Write(const cec_frame &data)
 {
   CLockObject lock(&m_mutex);
   DWORD iBytesWritten = 0;
   if (!m_bIsOpen)
     return -1;
 
-  if (!WriteFile(m_handle, data, len, &iBytesWritten, NULL))
+  if (!WriteFile(m_handle, data.data, data.size, &iBytesWritten, NULL))
   {
     m_error = "Error while writing to COM port";
     FormatWindowsError(GetLastError(), m_error);
     return -1;
   }
 
-  return iBytesWritten;
+  return (int8_t)iBytesWritten;
 }
 
 int32_t CSerialPort::Read(uint8_t* data, uint32_t len, uint64_t iTimeoutMs /* = 0 */)
index d49de62554ea7ea8305c1c810ce2809d8f2228eb..ded4001dac43586d92fac960938de629195f6b65 100644 (file)
@@ -44,7 +44,17 @@ namespace CEC
       {
         m_maxSize = iMaxSize;
       }
-      virtual ~CecBuffer(void) {}
+
+      virtual ~CecBuffer(void)
+      {
+        Clear();
+      }
+
+      void Clear(void)
+      {
+        while (!m_buffer.empty())
+          m_buffer.pop();
+      }
 
       int Size(void) const { return m_buffer.size(); }
 
@@ -62,7 +72,7 @@ namespace CEC
       {
         bool bReturn(false);
         CLockObject lock(&m_mutex);
-        if (m_buffer.size() > 0)
+        if (!m_buffer.empty())
         {
           entry = m_buffer.front();
           m_buffer.pop();
index 813e22b4cd193501dd0f7447d26041e1f690c7e7..bec5c4d1655dd597ba03b39ad396df66c6f408ba 100644 (file)
@@ -42,7 +42,7 @@
 using namespace CEC;
 using namespace std;
 
-#define CEC_TEST_CLIENT_VERSION 3
+#define CEC_TEST_CLIENT_VERSION 5
 
 
 inline bool HexStrToInt(const std::string& data, uint8_t& value)
@@ -105,16 +105,16 @@ void flush_log(ICECAdapter *cecParser)
     switch (message.level)
     {
     case CEC_LOG_ERROR:
-      cout << "ERROR:   " << message.message.c_str() << endl;
+      cout << "ERROR:   " << message.message << endl;
       break;
     case CEC_LOG_WARNING:
-      cout << "WARNING: " << message.message.c_str() << endl;
+      cout << "WARNING: " << message.message << endl;
       break;
     case CEC_LOG_NOTICE:
-      cout << "NOTICE:  " << message.message.c_str() << endl;
+      cout << "NOTICE:  " << message.message << endl;
       break;
     case CEC_LOG_DEBUG:
-      cout << "DEBUG:   " << message.message.c_str() << endl;
+      cout << "DEBUG:   " << message.message << endl;
       break;
     }
   }
@@ -122,24 +122,21 @@ void flush_log(ICECAdapter *cecParser)
 
 void list_devices(ICECAdapter *parser)
 {
-  cout << "Found devices: ";
-  vector<cec_adapter> devices;
-  int iDevicesFound = parser->FindAdapters(devices);
+  cec_adapter *devices = new cec_adapter[10];
+  uint8_t iDevicesFound = parser->FindAdapters(devices, 10, NULL);
   if (iDevicesFound <= 0)
   {
-#ifdef __WINDOWS__
-    cout << "Not supported yet, sorry!" << endl;
-#else
-    cout << "NONE" << endl;
-#endif
+    cout << "Found devices: NONE" << endl;
   }
   else
   {
-    cout << devices.size() << endl;
-    for (unsigned int iDevicePtr = 0; iDevicePtr < devices.size(); iDevicePtr++)
+    CStdString strLog;
+    strLog.Format("Found devices: %d", iDevicesFound);
+    cout << strLog.c_str() << endl;
+    for (unsigned int iDevicePtr = 0; iDevicePtr < iDevicesFound; iDevicePtr++)
     {
       CStdString strDevice;
-      strDevice.Format("device:        %d\npath:          %s\ncom port:      %s", iDevicePtr, devices[iDevicePtr].path.c_str(), devices[0].comm.c_str());
+      strDevice.Format("device:        %d\npath:          %s\ncom port:      %s", iDevicePtr + 1, devices[iDevicePtr].path, devices[iDevicePtr].comm);
       cout << endl << strDevice.c_str() << endl;
     }
   }
@@ -200,8 +197,8 @@ int main (int argc, char *argv[])
   if (argc < 2)
   {
     cout << "no serial port given. trying autodetect: ";
-    vector<cec_adapter> devices;
-    int iDevicesFound = parser->FindAdapters(devices);
+    cec_adapter devices[10];
+    uint8_t iDevicesFound = parser->FindAdapters(devices, 10, NULL);
     if (iDevicesFound <= 0)
     {
       cout << "FAILED" << endl;
@@ -266,7 +263,9 @@ int main (int argc, char *argv[])
         {
           string strvalue;
           uint8_t ivalue;
-          vector<uint8_t> bytes;
+          cec_frame bytes;
+          bytes.clear();
+
           while (GetWord(input, strvalue) && HexStrToInt(strvalue, ivalue))
           bytes.push_back(ivalue);
 
@@ -290,8 +289,15 @@ int main (int argc, char *argv[])
         }
         else if (command == "r")
         {
+          cout << "closing the connection" << endl;
           parser->Close();
+          flush_log(parser);
+
+          cout << "opening a new connection" << endl;
           parser->Open(strPort.c_str());
+          flush_log(parser);
+
+          cout << "setting active view" << endl;
           parser->SetActiveView();
         }
         else if (command == "h" || command == "help")