From 25701fa60407a0fc0bc1dfcd4049fc01ad9e4fd1 Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Fri, 7 Oct 2011 23:05:40 +0200 Subject: [PATCH] libcec v0.5 (WIP) * 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 --- ChangeLog | 10 ++ configure.ac | 2 +- debian/changelog | 10 ++ include/CECExports.h | 48 ++++++++-- include/CECExportsC.h | 10 +- include/CECExportsCpp.h | 18 ++-- project/libcec.vcxproj | 5 +- src/lib/AdapterCommunication.cpp | 122 +++++++++++++----------- src/lib/AdapterCommunication.h | 16 ++-- src/lib/AdapterDetection.cpp | 48 ++++------ src/lib/AdapterDetection.h | 2 +- src/lib/CECProcessor.cpp | 116 +++++++++++++--------- src/lib/CECProcessor.h | 3 +- src/lib/LibCEC.cpp | 51 +++++++--- src/lib/LibCEC.h | 10 +- src/lib/LibCECC.cpp | 12 +-- src/lib/platform/linux/serialport.cpp | 10 +- src/lib/platform/serialport.h | 8 +- src/lib/platform/threads.cpp | 33 +++---- src/lib/platform/threads.h | 6 +- src/lib/platform/windows/serialport.cpp | 6 +- src/lib/util/buffer.h | 14 ++- src/testclient/main.cpp | 44 +++++---- 23 files changed, 365 insertions(+), 239 deletions(-) diff --git a/ChangeLog b/ChangeLog index c96e49a..2cdc3d1 100644 --- 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 Thu, 07 Oct 2011 22:00:00 +0200 + libcec (0.4-3) unstable; urgency=low * fixed reconnect diff --git a/configure.ac b/configure.ac index dffe00b..2034c08 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/debian/changelog b/debian/changelog index c96e49a..2cdc3d1 100644 --- a/debian/changelog +++ b/debian/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 Thu, 07 Oct 2011 22:00:00 +0200 + libcec (0.4-3) unstable; urgency=low * fixed reconnect diff --git a/include/CECExports.h b/include/CECExports.h index 9a5c095..d1a7414 100644 --- a/include/CECExports.h +++ b/include/CECExports.h @@ -34,9 +34,8 @@ #ifndef CECEXPORTS_H_ #define CECEXPORTS_H_ -#include #include -#include +#include #if !defined(DECLSPEC) #if defined(_WIN32) || defined(_WIN64) @@ -55,13 +54,11 @@ 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 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 diff --git a/include/CECExportsC.h b/include/CECExportsC.h index 2a6b614..d1987cb 100644 --- a/include/CECExportsC.h +++ b/include/CECExportsC.h @@ -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 &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 &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. diff --git a/include/CECExportsCpp.h b/include/CECExportsCpp.h index d590351..3490573 100644 --- a/include/CECExportsCpp.h +++ b/include/CECExportsCpp.h @@ -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 &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 @@ -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 diff --git a/project/libcec.vcxproj b/project/libcec.vcxproj index 59ec3a3..30a8848 100644 --- a/project/libcec.vcxproj +++ b/project/libcec.vcxproj @@ -81,7 +81,8 @@ *.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 $(SolutionDir)..\include;$(IncludePath) - true + false + true $(SolutionDir)..\ @@ -104,7 +105,7 @@ $(SolutionDir)..\libcec.dll %(AdditionalDependencies);setupapi.lib;$(SolutionDir)..\src\lib\platform\pthread_win32\pthreadVC2d.lib libcmtd - 2 + 5 diff --git a/src/lib/AdapterCommunication.cpp b/src/lib/AdapterCommunication.cpp index ae1a4e4..84ec74c 100644 --- a/src/lib/AdapterCommunication.cpp +++ b/src/lib/AdapterCommunication.cpp @@ -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); diff --git a/src/lib/AdapterCommunication.h b/src/lib/AdapterCommunication.h index c95f729..8ce9c5b 100644 --- a/src/lib/AdapterCommunication.h +++ b/src/lib/AdapterCommunication.h @@ -33,6 +33,7 @@ #include "../../include/CECExports.h" #include "platform/threads.h" +#include 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; }; }; diff --git a/src/lib/AdapterDetection.cpp b/src/lib/AdapterDetection.cpp index e21d3dc..5d957a7 100644 --- a/src/lib/AdapterDetection.cpp +++ b/src/lib/AdapterDetection.cpp @@ -100,9 +100,9 @@ bool FindComPort(CStdString &strLocation) } #endif -int CAdapterDetection::FindAdapters(vector &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 &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 &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 &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 &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 &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); } } diff --git a/src/lib/AdapterDetection.h b/src/lib/AdapterDetection.h index d775bbc..8af1834 100644 --- a/src/lib/AdapterDetection.h +++ b/src/lib/AdapterDetection.h @@ -38,6 +38,6 @@ namespace CEC class CAdapterDetection { public: - static int FindAdapters(std::vector &deviceList, const char *strDevicePath = NULL); + static uint8_t FindAdapters(cec_adapter *deviceList, uint8_t iBufSize, const char *strDevicePath = NULL); }; }; diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index 6750c87..74f03b3 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -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 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, ¶ms); 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, ¶ms); } } diff --git a/src/lib/CECProcessor.h b/src/lib/CECProcessor.h index 90db3bc..5c8d8ab 100644 --- a/src/lib/CECProcessor.h +++ b/src/lib/CECProcessor.h @@ -31,6 +31,7 @@ * http://www.pulse-eight.net/ */ +#include #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); diff --git a/src/lib/LibCEC.cpp b/src/lib/LibCEC.cpp index abc800c..652d732 100644 --- a/src/lib/LibCEC.cpp +++ b/src/lib/LibCEC.cpp @@ -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 &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 &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; +} diff --git a/src/lib/LibCEC.h b/src/lib/LibCEC.h index 2911071..58c2262 100644 --- a/src/lib/LibCEC.h +++ b/src/lib/LibCEC.h @@ -31,6 +31,7 @@ * http://www.pulse-eight.net/ */ +#include #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 &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; diff --git a/src/lib/LibCECC.cpp b/src/lib/LibCECC.cpp index 60ada61..4c7276a 100644 --- a/src/lib/LibCECC.cpp +++ b/src/lib/LibCECC.cpp @@ -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 &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(); diff --git a/src/lib/platform/linux/serialport.cpp b/src/lib/platform/linux/serialport.cpp index e8fb8e5..0bb4e2c 100644 --- a/src/lib/platform/linux/serialport.cpp +++ b/src/lib/platform/linux/serialport.cpp @@ -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"); // } diff --git a/src/lib/platform/serialport.h b/src/lib/platform/serialport.h index ea6cdea..9cc2c9a 100644 --- a/src/lib/platform/serialport.h +++ b/src/lib/platform/serialport.h @@ -19,8 +19,8 @@ */ #include "os-dependent.h" +#include "../../../include/CECExports.h" #include -#include #include #include "../platform/threads.h" @@ -46,11 +46,7 @@ namespace CEC bool IsOpen(); void Close(); - int32_t Write(std::vector 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; } diff --git a/src/lib/platform/threads.cpp b/src/lib/platform/threads.cpp index 08a4c3b..4695316 100644 --- a/src/lib/platform/threads.cpp +++ b/src/lib/platform/threads.cpp @@ -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); diff --git a/src/lib/platform/threads.h b/src/lib/platform/threads.h index 8b0729d..9ba273c 100644 --- a/src/lib/platform/threads.h +++ b/src/lib/platform/threads.h @@ -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; diff --git a/src/lib/platform/windows/serialport.cpp b/src/lib/platform/windows/serialport.cpp index ce299cf..443b426 100644 --- a/src/lib/platform/windows/serialport.cpp +++ b/src/lib/platform/windows/serialport.cpp @@ -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 */) diff --git a/src/lib/util/buffer.h b/src/lib/util/buffer.h index d49de62..ded4001 100644 --- a/src/lib/util/buffer.h +++ b/src/lib/util/buffer.h @@ -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(); diff --git a/src/testclient/main.cpp b/src/testclient/main.cpp index 813e22b..bec5c4d 100644 --- a/src/testclient/main.cpp +++ b/src/testclient/main.cpp @@ -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 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 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 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") -- 2.34.1