From c409848208093a15758c91e3fab9fbe806a62e12 Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Fri, 11 Nov 2011 12:13:39 +0100 Subject: [PATCH] cec: added some more audio related opcode handling. added TransmitVendorId(), but only transmit the id if it's not set to 'unknown'. transmit an abort message when a vendor specific command was received --- include/cectypes.h | 27 +------ src/lib/CECProcessor.cpp | 3 +- src/lib/devices/CECAudioSystem.cpp | 41 ++++++++-- src/lib/devices/CECAudioSystem.h | 2 + src/lib/devices/CECBusDevice.cpp | 74 ++++++++++++------- src/lib/devices/CECBusDevice.h | 11 +-- src/lib/implementations/CECCommandHandler.cpp | 47 +++++++++++- src/lib/implementations/CECCommandHandler.h | 4 + 8 files changed, 145 insertions(+), 64 deletions(-) diff --git a/include/cectypes.h b/include/cectypes.h index 4e5413e..258452d 100644 --- a/include/cectypes.h +++ b/include/cectypes.h @@ -103,7 +103,8 @@ typedef enum cec_version CEC_VERSION_1_2 = 0x01, CEC_VERSION_1_2A = 0x02, CEC_VERSION_1_3 = 0x03, - CEC_VERSION_1_3A = 0x04 + CEC_VERSION_1_3A = 0x04, + CEC_VERSION_1_4 = 0x05 } cec_version; typedef enum cec_channel_identifier @@ -816,30 +817,6 @@ typedef enum cec_vendor_id CEC_VENDOR_UNKNOWN = 0 } cec_vendor_id; -typedef struct cec_vendor -{ -#ifdef __cplusplus - const char *AsString(void) const - { - switch (vendor) - { - case CEC_VENDOR_SAMSUNG: - return "Samsung"; - case CEC_VENDOR_LG: - return "LG"; - case CEC_VENDOR_PANASONIC: - return "Panasonic"; - case CEC_VENDOR_PIONEER: - return "Pioneer"; - default: - return "Unknown"; - } - } -#endif - - cec_vendor_id vendor; -} cec_vendor; - //default physical address 1.0.0.0, HDMI port 1 #define CEC_DEFAULT_PHYSICAL_ADDRESS 0x1000 #define MSGSTART 0xFF diff --git a/src/lib/CECProcessor.cpp b/src/lib/CECProcessor.cpp index d094be1..cf3ea3f 100644 --- a/src/lib/CECProcessor.cpp +++ b/src/lib/CECProcessor.cpp @@ -157,7 +157,8 @@ bool CCECProcessor::TryLogicalAddress(cec_logical_address address, unsigned int m_busDevices[address]->m_bActiveSource = true; } m_busDevices[address]->m_powerStatus = CEC_POWER_STATUS_STANDBY; - m_busDevices[address]->m_cecVersion = CEC_VERSION_1_3A; + m_busDevices[address]->m_cecVersion = CEC_VERSION_1_3A; + m_logicalAddresses.set(address); // TODO diff --git a/src/lib/devices/CECAudioSystem.cpp b/src/lib/devices/CECAudioSystem.cpp index f2c0fad..d6c6f70 100644 --- a/src/lib/devices/CECAudioSystem.cpp +++ b/src/lib/devices/CECAudioSystem.cpp @@ -32,6 +32,7 @@ #include "CECAudioSystem.h" #include "../CECProcessor.h" +#include "../implementations/CECCommandHandler.h" using namespace CEC; @@ -40,14 +41,44 @@ CCECAudioSystem::CCECAudioSystem(CCECProcessor *processor, cec_logical_address a m_systemAudioStatus(CEC_SYSTEM_AUDIO_STATUS_ON), m_audioStatus(CEC_AUDIO_MUTE_STATUS_MASK) { - m_type = CEC_DEVICE_TYPE_AUDIO_SYSTEM; + m_type = CEC_DEVICE_TYPE_AUDIO_SYSTEM; +} + +bool CCECAudioSystem::SetAudioStatus(const cec_audio_status status) +{ + if (m_audioStatus != status) + { + CStdString strLog; + strLog.Format(">> %s (%X): audio status changed from %s to %s", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(m_audioStatus), CCECCommandHandler::ToString(status)); + AddLog(CEC_LOG_DEBUG, strLog.c_str()); + + m_audioStatus = status; + return true; + } + + return false; +} + +bool CCECAudioSystem::SetSystemAudioMode(const cec_system_audio_status mode) +{ + if (m_systemAudioStatus != mode) + { + CStdString strLog; + strLog.Format(">> %s (%X): system audio mode changed from %s to %s", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(m_systemAudioStatus), CCECCommandHandler::ToString(mode)); + AddLog(CEC_LOG_DEBUG, strLog.c_str()); + + m_systemAudioStatus = mode; + return true; + } + + return false; } bool CCECAudioSystem::SetSystemAudioMode(const cec_command &command) { - m_systemAudioStatus = (command.parameters.size == 0) ? + SetSystemAudioMode((command.parameters.size == 0) ? CEC_SYSTEM_AUDIO_STATUS_OFF : - CEC_SYSTEM_AUDIO_STATUS_ON; + CEC_SYSTEM_AUDIO_STATUS_ON); return TransmitAudioStatus(command.initiator); } @@ -55,7 +86,7 @@ bool CCECAudioSystem::SetSystemAudioMode(const cec_command &command) bool CCECAudioSystem::TransmitAudioStatus(cec_logical_address dest) { CStdString strLog; - strLog.Format("<< %x -> %x: audio status '%2x'", m_iLogicalAddress, dest, m_audioStatus); + strLog.Format("<< %x -> %x: audio status '%2x'", m_iLogicalAddress, dest, CCECCommandHandler::ToString(m_audioStatus)); AddLog(CEC_LOG_NOTICE, strLog); cec_command command; @@ -68,7 +99,7 @@ bool CCECAudioSystem::TransmitAudioStatus(cec_logical_address dest) bool CCECAudioSystem::TransmitSystemAudioModeStatus(cec_logical_address dest) { CStdString strLog; - strLog.Format("<< %x -> %x: system audio mode '%2x'", m_iLogicalAddress, dest, m_systemAudioStatus); + strLog.Format("<< %x -> %x: system audio mode '%s'", m_iLogicalAddress, dest, CCECCommandHandler::ToString(m_systemAudioStatus)); AddLog(CEC_LOG_NOTICE, strLog); cec_command command; diff --git a/src/lib/devices/CECAudioSystem.h b/src/lib/devices/CECAudioSystem.h index 56b73a1..0a80dac 100644 --- a/src/lib/devices/CECAudioSystem.h +++ b/src/lib/devices/CECAudioSystem.h @@ -41,6 +41,8 @@ namespace CEC CCECAudioSystem(CCECProcessor *processor, cec_logical_address address, uint16_t iPhysicalAddress = 0); virtual ~CCECAudioSystem(void) {}; + virtual bool SetAudioStatus(const cec_audio_status status); + virtual bool SetSystemAudioMode(const cec_system_audio_status mode); virtual bool SetSystemAudioMode(const cec_command &command); virtual bool TransmitAudioStatus(cec_logical_address dest); virtual bool TransmitSystemAudioModeStatus(cec_logical_address dest); diff --git a/src/lib/devices/CECBusDevice.cpp b/src/lib/devices/CECBusDevice.cpp index dc6d4f8..3eeb295 100644 --- a/src/lib/devices/CECBusDevice.cpp +++ b/src/lib/devices/CECBusDevice.cpp @@ -40,15 +40,18 @@ using namespace CEC; +#define ToString(p) CCECCommandHandler::ToString(p) + CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogicalAddress, uint16_t iPhysicalAddress) : + m_type(CEC_DEVICE_TYPE_RESERVED), m_iPhysicalAddress(iPhysicalAddress), m_iStreamPath(0), m_iLogicalAddress(iLogicalAddress), m_powerStatus(CEC_POWER_STATUS_UNKNOWN), m_processor(processor), + m_vendor(CEC_VENDOR_UNKNOWN), m_bMenuActive(true), m_bActiveSource(false), - m_iVendorClass(CEC_VENDOR_UNKNOWN), m_iLastCommandSent(0), m_iLastActive(0), m_cecVersion(CEC_VERSION_UNKNOWN) @@ -60,9 +63,7 @@ CCECBusDevice::CCECBusDevice(CCECProcessor *processor, cec_logical_address iLogi m_menuLanguage.language[3] = 0; m_menuLanguage.device = iLogicalAddress; - m_vendor.vendor = CEC_VENDOR_UNKNOWN; - m_type = CEC_DEVICE_TYPE_RESERVED; - m_strDeviceName = CCECCommandHandler::ToString(m_iLogicalAddress); + m_strDeviceName = ToString(m_iLogicalAddress); } CCECBusDevice::~CCECBusDevice(void) @@ -89,7 +90,7 @@ void CCECBusDevice::PollVendorId(void) { CLockObject lock(&m_mutex); if (m_iLastActive > 0 && m_iLogicalAddress != CECDEVICE_BROADCAST && - m_vendor.vendor == CEC_VENDOR_UNKNOWN && + m_vendor == CEC_VENDOR_UNKNOWN && GetTimeMs() - m_iLastCommandSent > 5000 && !m_processor->IsMonitoring()) { @@ -162,7 +163,7 @@ cec_version CCECBusDevice::GetCecVersion(void) const char* CCECBusDevice::GetLogicalAddressName(void) const { - return CCECCommandHandler::ToString(m_iLogicalAddress); + return ToString(m_iLogicalAddress); } cec_menu_language &CCECBusDevice::GetMenuLanguage(void) @@ -215,9 +216,9 @@ cec_power_status CCECBusDevice::GetPowerStatus(void) return m_powerStatus; } -const cec_vendor &CCECBusDevice::GetVendor(void) +const cec_vendor_id CCECBusDevice::GetVendorId(void) { - if (m_vendor.vendor == CEC_VENDOR_UNKNOWN) + if (m_vendor == CEC_VENDOR_UNKNOWN) { if (!MyLogicalAddressContains(m_iLogicalAddress)) { @@ -236,6 +237,12 @@ const cec_vendor &CCECBusDevice::GetVendor(void) return m_vendor; } +const char *CCECBusDevice::GetVendorName(void) +{ + GetVendorId(); + return ToString(m_vendor); +} + bool CCECBusDevice::MyLogicalAddressContains(cec_logical_address address) const { return m_processor->HasLogicalAddress(address); @@ -250,7 +257,7 @@ void CCECBusDevice::SetCecVersion(const cec_version newVersion) m_cecVersion = newVersion; CStdString strLog; - strLog.Format("%s (%X): CEC version %s", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(newVersion)); + strLog.Format("%s (%X): CEC version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(newVersion)); AddLog(CEC_LOG_DEBUG, strLog); } @@ -297,16 +304,15 @@ void CCECBusDevice::SetPowerStatus(const cec_power_status powerStatus) if (m_powerStatus != powerStatus) { CStdString strLog; - strLog.Format(">> %s (%X): power status changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(m_powerStatus), CCECCommandHandler::ToString(powerStatus)); + strLog.Format(">> %s (%X): power status changed from '%s' to '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(m_powerStatus), ToString(powerStatus)); m_processor->AddLog(CEC_LOG_DEBUG, strLog); m_powerStatus = powerStatus; } } -void CCECBusDevice::SetVendorId(uint64_t iVendorId, uint8_t iVendorClass /* = 0 */) +void CCECBusDevice::SetVendorId(uint64_t iVendorId) { - m_vendor.vendor = (cec_vendor_id)iVendorId; - m_iVendorClass = iVendorClass; + m_vendor = (cec_vendor_id)iVendorId; switch (iVendorId) { @@ -341,7 +347,7 @@ void CCECBusDevice::SetVendorId(uint64_t iVendorId, uint8_t iVendorClass /* = 0 } CStdString strLog; - strLog.Format("%s (%X): vendor = %s (%06x) class = %2x", GetLogicalAddressName(), m_iLogicalAddress, GetVendorName(), GetVendorId(), GetVendorClass()); + strLog.Format("%s (%X): vendor = %s (%06x)", GetLogicalAddressName(), m_iLogicalAddress, GetVendorName(), GetVendorId()); m_processor->AddLog(CEC_LOG_DEBUG, strLog.c_str()); } //@} @@ -382,7 +388,7 @@ bool CCECBusDevice::TransmitActiveSource(void) bool CCECBusDevice::TransmitCECVersion(cec_logical_address dest) { CStdString strLog; - strLog.Format("<< %s (%X) -> %s (%X): cec version %s", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(dest), dest, CCECCommandHandler::ToString(m_cecVersion)); + strLog.Format("<< %s (%X) -> %s (%X): cec version %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_cecVersion)); AddLog(CEC_LOG_NOTICE, strLog); cec_command command; @@ -409,7 +415,7 @@ bool CCECBusDevice::TransmitInactiveView(void) bool CCECBusDevice::TransmitMenuState(cec_logical_address dest) { CStdString strLog; - strLog.Format("<< %s (%X) -> %s (%X): ", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(dest), dest); + strLog.Format("<< %s (%X) -> %s (%X): ", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest); if (m_bMenuActive) strLog.append("menu active"); else @@ -426,7 +432,7 @@ bool CCECBusDevice::TransmitMenuState(cec_logical_address dest) bool CCECBusDevice::TransmitOSDName(cec_logical_address dest) { CStdString strLog; - strLog.Format("<< %s (%X) -> %s (%X): OSD name '%s'", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(dest), dest, m_strDeviceName.c_str()); + strLog.Format("<< %s (%X) -> %s (%X): OSD name '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, m_strDeviceName.c_str()); AddLog(CEC_LOG_NOTICE, strLog.c_str()); cec_command command; @@ -440,7 +446,7 @@ bool CCECBusDevice::TransmitOSDName(cec_logical_address dest) bool CCECBusDevice::TransmitOSDString(cec_logical_address dest, cec_display_control duration, const char *strMessage) { CStdString strLog; - strLog.Format("<< %s (%X) -> %s (%X): display OSD message '%s'", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(dest), dest, strMessage); + strLog.Format("<< %s (%X) -> %s (%X): display OSD message '%s'", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, strMessage); AddLog(CEC_LOG_NOTICE, strLog.c_str()); cec_command command; @@ -479,7 +485,7 @@ bool CCECBusDevice::TransmitPoll(cec_logical_address dest) dest = m_iLogicalAddress; CStdString strLog; - strLog.Format("<< %s (%X) -> %s (%X): POLL", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(dest), dest); + strLog.Format("<< %s (%X) -> %s (%X): POLL", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest); AddLog(CEC_LOG_NOTICE, strLog.c_str()); cec_command command; @@ -494,7 +500,7 @@ bool CCECBusDevice::TransmitPoll(cec_logical_address dest) bool CCECBusDevice::TransmitPowerState(cec_logical_address dest) { CStdString strLog; - strLog.Format("<< %s (%X) -> %s (%X): %s", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(dest), dest, CCECCommandHandler::ToString(m_powerStatus)); + strLog.Format("<< %s (%X) -> %s (%X): %s", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_powerStatus)); AddLog(CEC_LOG_NOTICE, strLog.c_str()); cec_command command; @@ -506,11 +512,29 @@ bool CCECBusDevice::TransmitPowerState(cec_logical_address dest) bool CCECBusDevice::TransmitVendorID(cec_logical_address dest) { - CStdString strLog; - strLog.Format("<< %s (%X) -> %s (%X): vendor id feature abort", GetLogicalAddressName(), m_iLogicalAddress, CCECCommandHandler::ToString(dest), dest); - AddLog(CEC_LOG_NOTICE, strLog); + if (m_vendor == CEC_VENDOR_UNKNOWN) + { + CStdString strLog; + strLog.Format("<< %s (%X) -> %s (%X): vendor id feature abort", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest); + AddLog(CEC_LOG_NOTICE, strLog); - m_processor->TransmitAbort(dest, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); - return false; + m_processor->TransmitAbort(dest, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); + return false; + } + else + { + CStdString strLog; + strLog.Format("<< %s (%X) -> %s (%X): vendor id %s (%x)", GetLogicalAddressName(), m_iLogicalAddress, ToString(dest), dest, ToString(m_vendor), (uint64_t)m_vendor); + AddLog(CEC_LOG_NOTICE, strLog); + + cec_command command; + cec_command::format(command, m_iLogicalAddress, dest, CEC_OPCODE_GIVE_DEVICE_VENDOR_ID); + + command.parameters.push_back((uint8_t) (((uint64_t)m_vendor >> 16) & 0xFF)); + command.parameters.push_back((uint8_t) (((uint64_t)m_vendor >> 8) & 0xFF)); + command.parameters.push_back((uint8_t) ((uint64_t)m_vendor & 0xFF)); + + return m_processor->Transmit(command); + } } //@} diff --git a/src/lib/devices/CECBusDevice.h b/src/lib/devices/CECBusDevice.h index d07f4c8..cad6591 100644 --- a/src/lib/devices/CECBusDevice.h +++ b/src/lib/devices/CECBusDevice.h @@ -67,17 +67,15 @@ namespace CEC virtual cec_power_status GetPowerStatus(void); virtual CCECProcessor * GetProcessor(void) const { return m_processor; } virtual cec_device_type GetType(void) const { return m_type; } - virtual const cec_vendor & GetVendor(void); - virtual uint8_t GetVendorClass(void) const { return m_iVendorClass; } - virtual cec_vendor_id GetVendorId(void) { return GetVendor().vendor; }; - virtual const char * GetVendorName(void) { return GetVendor().AsString(); } + virtual const cec_vendor_id GetVendorId(void); + virtual const char * GetVendorName(void); virtual bool MyLogicalAddressContains(cec_logical_address address) const; virtual void SetPhysicalAddress(uint16_t iNewAddress); virtual void SetStreamPath(uint16_t iNewAddress, uint16_t iOldAddress = 0); virtual void SetCecVersion(const cec_version newVersion); virtual void SetMenuLanguage(const cec_menu_language &menuLanguage); - virtual void SetVendorId(uint64_t iVendorId, uint8_t iVendorClass = 0); + virtual void SetVendorId(uint64_t iVendorId); virtual void SetPowerStatus(const cec_power_status powerStatus); virtual bool TransmitActiveSource(void); @@ -101,10 +99,9 @@ namespace CEC cec_menu_language m_menuLanguage; CCECProcessor *m_processor; CCECCommandHandler *m_handler; - cec_vendor m_vendor; + cec_vendor_id m_vendor; bool m_bMenuActive; bool m_bActiveSource; - uint8_t m_iVendorClass; uint64_t m_iLastCommandSent; uint64_t m_iLastActive; cec_version m_cecVersion; diff --git a/src/lib/implementations/CECCommandHandler.cpp b/src/lib/implementations/CECCommandHandler.cpp index 7785ef6..1c0f8d9 100644 --- a/src/lib/implementations/CECCommandHandler.cpp +++ b/src/lib/implementations/CECCommandHandler.cpp @@ -212,6 +212,7 @@ bool CCECCommandHandler::HandleDeviceCecVersion(const cec_command &command) bool CCECCommandHandler::HandleDeviceVendorCommandWithId(const cec_command &command) { SetVendorId(command); + m_busDevice->GetProcessor()->TransmitAbort(command.initiator, command.opcode, CEC_ABORT_REASON_REFUSED); return true; } @@ -315,6 +316,7 @@ bool CCECCommandHandler::HandleRequestActiveSource(const cec_command &command) vector devices; for (int iDevicePtr = (int)GetMyDevices(devices)-1; iDevicePtr >=0; iDevicePtr--) devices[iDevicePtr]->TransmitActiveSource(); + return true; } @@ -463,6 +465,11 @@ CCECBusDevice *CCECCommandHandler::GetDeviceByPhysicalAddress(uint16_t iPhysical return m_busDevice->GetProcessor()->GetDeviceByPhysicalAddress(iPhysicalAddress); } +CCECBusDevice *CCECCommandHandler::GetDeviceByType(cec_device_type type) const +{ + return m_busDevice->GetProcessor()->GetDeviceByType(type); +} + void CCECCommandHandler::SetVendorId(const cec_command &command) { if (command.parameters.size < 3) @@ -477,7 +484,7 @@ void CCECCommandHandler::SetVendorId(const cec_command &command) CCECBusDevice *device = GetDevice((cec_logical_address) command.initiator); if (device) - device->SetVendorId(iVendorId, command.parameters.size > 3 ? command.parameters[3] : 0); + device->SetVendorId(iVendorId); } const char *CCECCommandHandler::ToString(const cec_version version) @@ -492,6 +499,8 @@ const char *CCECCommandHandler::ToString(const cec_version version) return "1.3"; case CEC_VERSION_1_3A: return "1.3a"; + case CEC_VERSION_1_4: + return "1.4"; default: return "unknown"; } @@ -743,3 +752,39 @@ const char *CCECCommandHandler::ToString(const cec_opcode opcode) return "UNKNOWN"; } } + +const char *CCECCommandHandler::ToString(const cec_system_audio_status mode) +{ + switch(mode) + { + case CEC_SYSTEM_AUDIO_STATUS_ON: + return "on"; + case CEC_SYSTEM_AUDIO_STATUS_OFF: + return "off"; + default: + return "unknown"; + } +} + +const char *CCECCommandHandler::ToString(const cec_audio_status status) +{ + // TODO this is a mask + return "TODO"; +} + +const char *CCECCommandHandler::ToString(const cec_vendor_id vendor) +{ + switch (vendor) + { + case CEC_VENDOR_SAMSUNG: + return "Samsung"; + case CEC_VENDOR_LG: + return "LG"; + case CEC_VENDOR_PANASONIC: + return "Panasonic"; + case CEC_VENDOR_PIONEER: + return "Pioneer"; + default: + return "Unknown"; + } +} diff --git a/src/lib/implementations/CECCommandHandler.h b/src/lib/implementations/CECCommandHandler.h index 16095f6..aed84fd 100644 --- a/src/lib/implementations/CECCommandHandler.h +++ b/src/lib/implementations/CECCommandHandler.h @@ -53,6 +53,9 @@ namespace CEC static const char *ToString(const cec_deck_info status); static const char* ToString(const cec_logical_address address); static const char* ToString(const cec_opcode opcode); + static const char *ToString(const cec_system_audio_status mode); + static const char *ToString(const cec_audio_status status); + static const char *ToString(const cec_vendor_id vendor); protected: virtual bool HandleActiveSource(const cec_command &command); @@ -83,6 +86,7 @@ namespace CEC virtual unsigned int GetMyDevices(std::vector &devices) const; virtual CCECBusDevice *GetDevice(cec_logical_address iLogicalAddress) const; virtual CCECBusDevice *GetDeviceByPhysicalAddress(uint16_t iPhysicalAddress) const; + virtual CCECBusDevice *GetDeviceByType(cec_device_type type) const; virtual void SetVendorId(const cec_command &command); CCECBusDevice *m_busDevice; -- 2.34.1