From: Lars Op den Kamp Date: Sun, 30 Oct 2011 11:31:27 +0000 (+0100) Subject: cec: add GetDeviceCecVersion()/cec_get_device_cec_version() to the interface. mostly... X-Git-Tag: upstream/2.2.0~1^2~172 X-Git-Url: https://git.piment-noir.org/?p=deb_libcec.git;a=commitdiff_plain;h=6a1c0009842a1857b863655813595292422a512b cec: add GetDeviceCecVersion()/cec_get_device_cec_version() to the interface. mostly as a test for two-way device communication --- diff --git a/include/cec.h b/include/cec.h index 69f1941..68652b1 100644 --- a/include/cec.h +++ b/include/cec.h @@ -139,6 +139,11 @@ namespace CEC * @see cec_switch_monitoring */ virtual bool SwitchMonitoring(bool bEnable) = 0; + + /*! + * @see cec_get_device_cec_version + */ + virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress) = 0; }; }; diff --git a/include/cecc.h b/include/cecc.h index c069b14..f897e13 100644 --- a/include/cecc.h +++ b/include/cecc.h @@ -202,8 +202,10 @@ extern DECLSPEC int cec_set_logical_address(cec_logical_address myAddress, cec_l extern DECLSPEC int cec_set_physical_address(uint16_t iPhysicalAddress = CEC_DEFAULT_PHYSICAL_ADDRESS); /*! - * @brief Display a message on the TV. - * @brief The message to display. + * @brief Display a message on the device with the given logical address. + * @param iLogicalAddres The device to display the message on. + * @param duration The duration of the message + * @param strMessage The message to display. * @return True when the command was sent, false otherwise. */ #ifdef __cplusplus @@ -212,8 +214,24 @@ extern DECLSPEC int cec_set_osd_string(CEC::cec_logical_address iLogicalAddress, extern DECLSPEC int cec_set_osd_string(cec_logical_address iLogicalAddress, cec_display_control duration, const char *strMessage); #endif +/*! + * @brief Enable or disable monitoring mode. + * @param bEnable True to enable, false to disable. + * @return True when switched successfully, false otherwise. + */ extern DECLSPEC int cec_switch_monitoring(int bEnable); +/*! + * @brief Get the CEC version of the device with the given logical address + * @param iLogicalAddress The device to get the CEC version for. + * @return The version or CEC_VERSION_UNKNOWN when the version couldn't be fetched. + */ +#ifdef __cplusplus +extern DECLSPEC CEC::cec_version cec_get_device_cec_version(CEC::cec_logical_address iLogicalAddress); +#else +extern DECLSPEC cec_version cec_get_device_cec_version(cec_logical_address iLogicalAddress); +#endif + #ifdef __cplusplus }; #endif diff --git a/include/cectypes.h b/include/cectypes.h index 7fa70c7..6bad769 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -97,13 +97,14 @@ typedef enum CEC_TRUE = 1 } ECecBoolean; -typedef enum -{ - CEC_VERSION_1_2 = 0x01, - CEC_VERSION_1_2A = 0x02, - CEC_VERSION_1_3 = 0x03, - CEC_VERSION_1_3A = 0x04 -} ECecVersion; +typedef enum cec_version +{ + CEC_VERSION_UNKNOWN = 0x00, + CEC_VERSION_1_2 = 0x01, + CEC_VERSION_1_2A = 0x02, + CEC_VERSION_1_3 = 0x03, + CEC_VERSION_1_3A = 0x04 +} cec_version; typedef enum { diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index 3fb3bc2..ce2432d 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -202,6 +202,11 @@ bool CCECProcessor::SwitchMonitoring(bool bEnable) return m_communication && m_communication->SetAckMask(0x1 << (uint8_t)m_iLogicalAddress); } +cec_version CCECProcessor::GetDeviceCecVersion(cec_logical_address iAddress) +{ + return m_busDevices[iAddress]->GetCecVersion(); +} + bool CCECProcessor::Transmit(const cec_command &data) { bool bReturn(false); diff --git a/src/lib/CECProcessor.h b/src/lib/CECProcessor.h index fc9a2fa..5362bfc 100644 --- a/src/lib/CECProcessor.h +++ b/src/lib/CECProcessor.h @@ -61,6 +61,7 @@ namespace CEC virtual bool SetLogicalAddress(cec_logical_address iLogicalAddress); virtual bool SetPhysicalAddress(uint16_t iPhysicalAddress); virtual bool SwitchMonitoring(bool bEnable); + virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress); virtual cec_logical_address GetLogicalAddress(void) const { return m_iLogicalAddress; } virtual uint16_t GetPhysicalAddress(void) const; diff --git a/src/lib/LibCEC.cpp b/src/lib/LibCEC.cpp index bf5de8a..eecde16 100644 --- a/src/lib/LibCEC.cpp +++ b/src/lib/LibCEC.cpp @@ -204,6 +204,13 @@ bool CLibCEC::SwitchMonitoring(bool bEnable) return m_cec ? m_cec->SwitchMonitoring(bEnable) : false; } +cec_version CLibCEC::GetDeviceCecVersion(cec_logical_address iAddress) +{ + if (m_cec && iAddress >= CECDEVICE_TV && iAddress < CECDEVICE_BROADCAST) + return m_cec->GetDeviceCecVersion(iAddress); + return CEC_VERSION_UNKNOWN; +} + void CLibCEC::AddLog(cec_log_level level, const string &strMessage) { if (m_cec) diff --git a/src/lib/LibCEC.h b/src/lib/LibCEC.h index 8873ff9..8d65a34 100644 --- a/src/lib/LibCEC.h +++ b/src/lib/LibCEC.h @@ -73,6 +73,7 @@ namespace CEC virtual bool SetInactiveView(void); virtual bool SetOSDString(cec_logical_address iLogicalAddress, cec_display_control duration, const char *strMessage); virtual bool SwitchMonitoring(bool bEnable); + virtual cec_version GetDeviceCecVersion(cec_logical_address iAddress); //@} virtual void AddLog(cec_log_level level, const std::string &strMessage); diff --git a/src/lib/LibCECC.cpp b/src/lib/LibCECC.cpp index 1f8416b..cdc2778 100644 --- a/src/lib/LibCECC.cpp +++ b/src/lib/LibCECC.cpp @@ -187,4 +187,11 @@ int cec_switch_monitoring(int bEnable) return -1; } +cec_version cec_get_device_cec_version(cec_logical_address iLogicalAddress) +{ + if (cec_parser) + return cec_parser->GetDeviceCecVersion(iLogicalAddress); + return CEC_VERSION_UNKNOWN; +} + //@} diff --git a/src/lib/devices/CECBusDevice.cpp b/src/lib/devices/CECBusDevice.cpp index 75862b7..5c73eb8 100644 --- a/src/lib/devices/CECBusDevice.cpp +++ b/src/lib/devices/CECBusDevice.cpp @@ -45,13 +45,15 @@ CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogi m_processor(processor), m_iVendorId(0), m_iVendorClass(CEC_VENDOR_UNKNOWN), - m_iLastActive(0) + m_iLastActive(0), + m_cecVersion(CEC_VERSION_UNKNOWN) { m_handler = new CCECCommandHandler(this); } CCECBusDevice::~CCECBusDevice(void) { + m_condition.Broadcast(); delete m_handler; } @@ -70,6 +72,33 @@ void CCECBusDevice::AddLog(cec_log_level level, const CStdString &strMessage) m_processor->AddLog(level, strMessage); } +void CCECBusDevice::SetCecVersion(cec_version newVersion) +{ + CStdString strLog; + m_cecVersion = newVersion; + + switch (newVersion) + { + case CEC_VERSION_1_2: + strLog.Format("device %d reports CEC version 1.2", m_iLogicalAddress); + break; + case CEC_VERSION_1_2A: + strLog.Format("device %d reports CEC version 1.2a", m_iLogicalAddress); + break; + case CEC_VERSION_1_3: + strLog.Format("device %d reports CEC version 1.3", m_iLogicalAddress); + break; + case CEC_VERSION_1_3A: + strLog.Format("device %d reports CEC version 1.3a", m_iLogicalAddress); + break; + default: + strLog.Format("device %d reports an unknown CEC version", m_iLogicalAddress); + m_cecVersion = CEC_VERSION_UNKNOWN; + break; + } + AddLog(CEC_LOG_DEBUG, strLog); +} + void CCECBusDevice::SetVendorId(const cec_datapacket &data) { if (data.size < 3) @@ -125,6 +154,7 @@ bool CCECBusDevice::HandleCommand(const cec_command &command) CLockObject lock(&m_mutex); m_iLastActive = GetTimeMs(); m_handler->HandleCommand(command); + m_condition.Signal(); return true; } @@ -313,6 +343,21 @@ bool CCECBusDevice::BroadcastActiveSource(void) return m_processor->Transmit(command); } +cec_version CCECBusDevice::GetCecVersion(void) +{ + if (m_cecVersion == CEC_VERSION_UNKNOWN) + { + AddLog(CEC_LOG_NOTICE, "<< requesting CEC version"); + cec_command command; + cec_command::format(command, GetMyLogicalAddress(), m_iLogicalAddress, CEC_OPCODE_GET_CEC_VERSION); + CLockObject lock(&m_mutex); + if (m_processor->Transmit(command)) + m_condition.Wait(&m_mutex, 1000); + } + + return m_cecVersion; +} + const char *CCECBusDevice::CECVendorIdToString(const uint64_t iVendorId) { switch (iVendorId) diff --git a/src/lib/devices/CECBusDevice.h b/src/lib/devices/CECBusDevice.h index 227f14d..4b6aa67 100644 --- a/src/lib/devices/CECBusDevice.h +++ b/src/lib/devices/CECBusDevice.h @@ -53,6 +53,7 @@ namespace CEC virtual cec_logical_address GetMyLogicalAddress(void) const; virtual uint16_t GetMyPhysicalAddress(void) const; + virtual void SetCecVersion(cec_version newVersion); virtual void SetVendorId(const cec_datapacket &data); virtual void SetVendorId(uint64_t iVendorId, uint8_t iVendorClass = 0); virtual const char *GetVendorName(void) const { return CECVendorIdToString(m_iVendorId); } @@ -67,6 +68,7 @@ namespace CEC virtual CCECProcessor *GetProcessor() const { return m_processor; } virtual CCECCommandHandler *GetHandler(void) const { return m_handler; }; + virtual cec_version GetCecVersion(void); virtual void PollVendorId(void); virtual bool PowerOn(void); virtual bool Standby(void); @@ -93,6 +95,8 @@ namespace CEC uint64_t m_iVendorId; uint8_t m_iVendorClass; uint64_t m_iLastActive; + cec_version m_cecVersion; CMutex m_mutex; + CCondition m_condition; }; }; diff --git a/src/lib/implementations/CECCommandHandler.cpp b/src/lib/implementations/CECCommandHandler.cpp index e1d34f6..790b631 100644 --- a/src/lib/implementations/CECCommandHandler.cpp +++ b/src/lib/implementations/CECCommandHandler.cpp @@ -49,6 +49,9 @@ bool CCECCommandHandler::HandleCommand(const cec_command &command) { switch(command.opcode) { + case CEC_OPCODE_CEC_VERSION: + HandleDeviceCecVersion(command); + break; case CEC_OPCODE_GIVE_PHYSICAL_ADDRESS: HandleGivePhysicalAddress(command); break; @@ -125,13 +128,25 @@ bool CCECCommandHandler::HandleCommand(const cec_command &command) return bHandled; } +bool CCECCommandHandler::HandleDeviceCecVersion(const cec_command &command) +{ + if (command.parameters.size == 1) + { + CCECBusDevice *device = GetDevice(command.initiator); + if (device) + device->SetCecVersion((cec_version) command.parameters[0]); + } + + return true; +} + bool CCECCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command) { CCECBusDevice *device = GetDevice(command.initiator); if (device) device->SetVendorId(command.parameters); - return false; + return true; } bool CCECCommandHandler::HandleDeviceVendorId(const cec_command &command) @@ -140,7 +155,7 @@ bool CCECCommandHandler::HandleDeviceVendorId(const cec_command &command) if (device) device->SetVendorId(command.parameters); - return false; + return true; } bool CCECCommandHandler::HandleGetCecVersion(const cec_command &command) diff --git a/src/lib/implementations/CECCommandHandler.h b/src/lib/implementations/CECCommandHandler.h index 0da4ded..aa5940c 100644 --- a/src/lib/implementations/CECCommandHandler.h +++ b/src/lib/implementations/CECCommandHandler.h @@ -47,6 +47,7 @@ namespace CEC virtual cec_vendor_id GetVendorId(void) { return CEC_VENDOR_UNKNOWN; }; protected: + bool HandleDeviceCecVersion(const cec_command &command); bool HandleDeviceVendorCommandWithId(const cec_command &command); bool HandleDeviceVendorId(const cec_command &command); bool HandleGetCecVersion(const cec_command &command); diff --git a/src/testclient/main.cpp b/src/testclient/main.cpp index 9cb32bf..b8482d7 100644 --- a/src/testclient/main.cpp +++ b/src/testclient/main.cpp @@ -218,6 +218,9 @@ void show_console_help(void) "osd {addr} {string} set OSD message on the specified device." << endl << "[osd 0 Test Message] displays 'Test Message' on the TV" << endl << endl << + "ver {addr} get the CEC version of the specified device." << endl << + "[ver 0] get the CEC version of the TV" << endl << + endl << "[mon] {1|0} enable or disable CEC bus monitoring." << endl << "[log] {1 - 31} change the log level. see cectypes.h for values." << endl << "[ping] send a ping command to the CEC adapter." << endl << @@ -489,6 +492,36 @@ int main (int argc, char *argv[]) { parser->StartBootloader(); } + else if (command == "ver") + { + CStdString strDev; + if (GetWord(input, strDev)) + { + int iDev = atoi(strDev); + if (iDev >= 0 && iDev < 15) + { + cec_version iVersion = parser->GetDeviceCecVersion((cec_logical_address) iDev); + switch (iVersion) + { + case CEC_VERSION_1_2: + cout << "CEC version 1.2" << endl; + break; + case CEC_VERSION_1_2A: + cout << "CEC version 1.2a" << endl; + break; + case CEC_VERSION_1_3: + cout << "CEC version 1.3" << endl; + break; + case CEC_VERSION_1_3A: + cout << "CEC version 1.3a" << endl; + break; + default: + cout << "unknown CEC version" << endl; + break; + } + } + } + } else if (command == "r") { cout << "closing the connection" << endl;