From 825ddb962b0515e1efb06bb10a1cbb74cde803f8 Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Thu, 29 Sep 2011 21:53:47 +0200 Subject: [PATCH] cec: added CEC command that were received by the adapter in a buffer that can be read by a client with GetNextCommand()/cec_get_next_command(). added a 'help' command to the test client, that displays all available commands --- include/CECExports.h | 74 +++++++++++++++++++++++++++++++++++++++++ include/CECExportsC.h | 11 ++++++ include/CECExportsCpp.h | 5 +++ include/CECTypes.h | 66 ------------------------------------ src/lib/CECParser.cpp | 23 +++++++++++-- src/lib/CECParser.h | 5 ++- src/lib/CECParserC.cpp | 7 ++++ src/lib/util/buffer.h | 25 ++++++++------ src/testclient/main.cpp | 30 ++++++++++++++++- 9 files changed, 166 insertions(+), 80 deletions(-) diff --git a/include/CECExports.h b/include/CECExports.h index ad1eb96..0aef25c 100644 --- a/include/CECExports.h +++ b/include/CECExports.h @@ -167,6 +167,72 @@ namespace CEC { CECDEVICE_BROADCAST = 15 } cec_logical_address; + typedef enum cec_opcode + { + CEC_OPCODE_ACTIVE_SOURCE = 0x82, + CEC_OPCODE_IMAGE_VIEW_ON = 0x04, + CEC_OPCODE_TEXT_VIEW_ON = 0x0D, + CEC_OPCODE_INACTIVE_SOURCE = 0x9D, + CEC_OPCODE_REQUEST_ACTIVE_SOURCE = 0x85, + CEC_OPCODE_ROUTING_CHANGE = 0x80, + CEC_OPCODE_ROUTING_INFORMATION = 0x81, + CEC_OPCODE_SET_STREAM_PATH = 0x86, + CEC_OPCODE_STANDBY = 0x36, + CEC_OPCODE_RECORD_OFF = 0x0B, + CEC_OPCODE_RECORD_ON = 0x09, + CEC_OPCODE_RECORD_STATUS = 0x0A, + CEC_OPCODE_RECORD_TV_SCREEN = 0x0F, + CEC_OPCODE_CLEAR_ANALOGUE_TIMER = 0x33, + CEC_OPCODE_CLEAR_DIGITAL_TIMER = 0x99, + CEC_OPCODE_CLEAR_EXTERNAL_TIMER = 0xA1, + CEC_OPCODE_SET_ANALOGUE_TIMER = 0x34, + CEC_OPCODE_SET_DIGITAL_TIMER = 0x97, + CEC_OPCODE_SET_EXTERNAL_TIMER = 0xA2, + CEC_OPCODE_SET_TIMER_PROGRAM_TITLE = 0x67, + CEC_OPCODE_TIMER_CLEARED_STATUS = 0x43, + CEC_OPCODE_TIMER_STATUS = 0x35, + CEC_OPCODE_CEC_VERSION = 0x9E, + CEC_OPCODE_GET_CEC_VERSION = 0x9F, + CEC_OPCODE_GIVE_PHYSICAL_ADDRESS = 0x83, + CEC_OPCODE_GET_MENU_LANGUAGE = 0x91, + CEC_OPCODE_REPORT_PHYSICAL_ADDRESS = 0x84, + CEC_OPCODE_SET_MENU_LANGUAGE = 0x32, + CEC_OPCODE_DECK_CONTROL = 0x42, + CEC_OPCODE_DECK_STATUS = 0x1B, + CEC_OPCODE_GIVE_DECK_STATUS = 0x1A, + CEC_OPCODE_PLAY = 0x41, + CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS = 0x08, + CEC_OPCODE_SELECT_ANALOGUE_SERVICE = 0x92, + CEC_OPCODE_SELECT_DIGITAL_SERVICE = 0x93, + CEC_OPCODE_TUNER_DEVICE_STATUS = 0x07, + CEC_OPCODE_TUNER_STEP_DECREMENT = 0x06, + CEC_OPCODE_TUNER_STEP_INCREMENT = 0x05, + CEC_OPCODE_DEVICE_VENDOR_ID = 0x87, + CEC_OPCODE_GIVE_DEVICE_VENDOR_ID = 0x8C, + CEC_OPCODE_VENDOR_COMMAND = 0x89, + CEC_OPCODE_VENDOR_COMMAND_WITH_ID = 0xA0, + CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A, + CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP = 0x8B, + CEC_OPCODE_SET_OSD_STRING = 0x64, + CEC_OPCODE_GIVE_OSD_NAME = 0x46, + CEC_OPCODE_SET_OSD_NAME = 0x47, + CEC_OPCODE_MENU_REQUEST = 0x8D, + CEC_OPCODE_MENU_STATUS = 0x8E, + CEC_OPCODE_USER_CONTROL_PRESSED = 0x44, + CEC_OPCODE_USER_CONTROL_RELEASE = 0x45, + CEC_OPCODE_GIVE_DEVICE_POWER_STATUS = 0x8F, + CEC_OPCODE_REPORT_POWER_STATUS = 0x90, + CEC_OPCODE_FEATURE_ABORT = 0x00, + CEC_OPCODE_ABORT = 0xFF, + CEC_OPCODE_GIVE_AUDIO_STATUS = 0x71, + CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, + CEC_OPCODE_REPORT_AUDIO_STATUS = 0x7A, + CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72, + CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70, + CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E, + CEC_OPCODE_SET_AUDIO_RATE = 0x9A + } cec_opcode; + typedef enum cec_log_level { CEC_LOG_DEBUG = 0, @@ -193,6 +259,14 @@ namespace CEC { std::string comm; } cec_device; + typedef struct cec_command + { + cec_logical_address source; + cec_logical_address destination; + cec_opcode opcode; + cec_frame parameters; + } cec_command; + //default physical address 1.0.0.0 #define CEC_DEFAULT_PHYSICAL_ADDRESS 0x1000 diff --git a/include/CECExportsC.h b/include/CECExportsC.h index 6fa4dbe..5d278f4 100644 --- a/include/CECExportsC.h +++ b/include/CECExportsC.h @@ -145,6 +145,17 @@ extern DECLSPEC bool cec_get_next_keypress(CEC::cec_keypress *key); extern DECLSPEC bool cec_get_next_keypress(cec_keypress *key); #endif +/*! + * @brief Get the next CEC command that was received by the adapter. + * @param action The next command. + * @return True when a command was passed, false otherwise. + */ +#ifdef __cplusplus +extern DECLSPEC bool cec_get_next_command(CEC::cec_command *command); +#else +extern DECLSPEC bool cec_get_next_command(cec_command *command); +#endif + /*! * @brief Transmit a frame on the CEC line. * @param data The frame to send. diff --git a/include/CECExportsCpp.h b/include/CECExportsCpp.h index ec69a4b..fd4ea9f 100644 --- a/include/CECExportsCpp.h +++ b/include/CECExportsCpp.h @@ -91,6 +91,11 @@ namespace CEC */ virtual bool GetNextKeypress(cec_keypress *key) = 0; + /*! + * @see cec_get_next_command + */ + virtual bool GetNextCommand(cec_command *command) = 0; + /*! * @see cec_transmit */ diff --git a/include/CECTypes.h b/include/CECTypes.h index 5b8ef2b..3518d20 100644 --- a/include/CECTypes.h +++ b/include/CECTypes.h @@ -36,72 +36,6 @@ #include #include "CECExports.h" -typedef enum -{ - CEC_OPCODE_ACTIVE_SOURCE = 0x82, - CEC_OPCODE_IMAGE_VIEW_ON = 0x04, - CEC_OPCODE_TEXT_VIEW_ON = 0x0D, - CEC_OPCODE_INACTIVE_SOURCE = 0x9D, - CEC_OPCODE_REQUEST_ACTIVE_SOURCE = 0x85, - CEC_OPCODE_ROUTING_CHANGE = 0x80, - CEC_OPCODE_ROUTING_INFORMATION = 0x81, - CEC_OPCODE_SET_STREAM_PATH = 0x86, - CEC_OPCODE_STANDBY = 0x36, - CEC_OPCODE_RECORD_OFF = 0x0B, - CEC_OPCODE_RECORD_ON = 0x09, - CEC_OPCODE_RECORD_STATUS = 0x0A, - CEC_OPCODE_RECORD_TV_SCREEN = 0x0F, - CEC_OPCODE_CLEAR_ANALOGUE_TIMER = 0x33, - CEC_OPCODE_CLEAR_DIGITAL_TIMER = 0x99, - CEC_OPCODE_CLEAR_EXTERNAL_TIMER = 0xA1, - CEC_OPCODE_SET_ANALOGUE_TIMER = 0x34, - CEC_OPCODE_SET_DIGITAL_TIMER = 0x97, - CEC_OPCODE_SET_EXTERNAL_TIMER = 0xA2, - CEC_OPCODE_SET_TIMER_PROGRAM_TITLE = 0x67, - CEC_OPCODE_TIMER_CLEARED_STATUS = 0x43, - CEC_OPCODE_TIMER_STATUS = 0x35, - CEC_OPCODE_CEC_VERSION = 0x9E, - CEC_OPCODE_GET_CEC_VERSION = 0x9F, - CEC_OPCODE_GIVE_PHYSICAL_ADDRESS = 0x83, - CEC_OPCODE_GET_MENU_LANGUAGE = 0x91, - CEC_OPCODE_REPORT_PHYSICAL_ADDRESS = 0x84, - CEC_OPCODE_SET_MENU_LANGUAGE = 0x32, - CEC_OPCODE_DECK_CONTROL = 0x42, - CEC_OPCODE_DECK_STATUS = 0x1B, - CEC_OPCODE_GIVE_DECK_STATUS = 0x1A, - CEC_OPCODE_PLAY = 0x41, - CEC_OPCODE_GIVE_TUNER_DEVICE_STATUS = 0x08, - CEC_OPCODE_SELECT_ANALOGUE_SERVICE = 0x92, - CEC_OPCODE_SELECT_DIGITAL_SERVICE = 0x93, - CEC_OPCODE_TUNER_DEVICE_STATUS = 0x07, - CEC_OPCODE_TUNER_STEP_DECREMENT = 0x06, - CEC_OPCODE_TUNER_STEP_INCREMENT = 0x05, - CEC_OPCODE_DEVICE_VENDOR_ID = 0x87, - CEC_OPCODE_GIVE_DEVICE_VENDOR_ID = 0x8C, - CEC_OPCODE_VENDOR_COMMAND = 0x89, - CEC_OPCODE_VENDOR_COMMAND_WITH_ID = 0xA0, - CEC_OPCODE_VENDOR_REMOTE_BUTTON_DOWN = 0x8A, - CEC_OPCODE_VENDOR_REMOTE_BUTTON_UP = 0x8B, - CEC_OPCODE_SET_OSD_STRING = 0x64, - CEC_OPCODE_GIVE_OSD_NAME = 0x46, - CEC_OPCODE_SET_OSD_NAME = 0x47, - CEC_OPCODE_MENU_REQUEST = 0x8D, - CEC_OPCODE_MENU_STATUS = 0x8E, - CEC_OPCODE_USER_CONTROL_PRESSED = 0x44, - CEC_OPCODE_USER_CONTROL_RELEASE = 0x45, - CEC_OPCODE_GIVE_DEVICE_POWER_STATUS = 0x8F, - CEC_OPCODE_REPORT_POWER_STATUS = 0x90, - CEC_OPCODE_FEATURE_ABORT = 0x00, - CEC_OPCODE_ABORT = 0xFF, - CEC_OPCODE_GIVE_AUDIO_STATUS = 0x71, - CEC_OPCODE_GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D, - CEC_OPCODE_REPORT_AUDIO_STATUS = 0x7A, - CEC_OPCODE_SET_SYSTEM_AUDIO_MODE = 0x72, - CEC_OPCODE_SYSTEM_AUDIO_MODE_REQUEST = 0x70, - CEC_OPCODE_SYSTEM_AUDIO_MODE_STATUS = 0x7E, - CEC_OPCODE_SET_AUDIO_RATE = 0x9A -} ECecOpcode; - typedef enum { CEC_ABORT_REASON_UNRECOGNIZED_OPCODE = 0, diff --git a/src/lib/CECParser.cpp b/src/lib/CECParser.cpp index df2ce10..97fbcd3 100644 --- a/src/lib/CECParser.cpp +++ b/src/lib/CECParser.cpp @@ -255,9 +255,14 @@ bool CCECParser::GetNextKeypress(cec_keypress *key) { return m_keyBuffer.Pop(*key); } + +bool CCECParser::GetNextCommand(cec_command *command) +{ + return m_commandBuffer.Pop(*command); +} //@} -void CCECParser::TransmitAbort(cec_logical_address address, ECecOpcode opcode, ECecAbortReason reason /* = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE */) +void CCECParser::TransmitAbort(cec_logical_address address, cec_opcode opcode, ECecAbortReason reason /* = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE */) { AddLog(CEC_LOG_DEBUG, "transmitting abort message"); cec_frame frame; @@ -692,7 +697,7 @@ void CCECParser::ParseCurrentFrame(void) return; vector tx; - ECecOpcode opCode = (ECecOpcode) m_currentframe[1]; + cec_opcode opCode = (cec_opcode) m_currentframe[1]; if (destination == (uint16_t) m_iLogicalAddress) { switch(opCode) @@ -732,6 +737,9 @@ void CCECParser::ParseCurrentFrame(void) AddKey(); break; default: + cec_frame params = m_currentframe; + params.erase(params.begin(), params.begin() + 2); + AddCommand((cec_logical_address) initiator, (cec_logical_address) destination, opCode, ¶ms); break; } } @@ -851,6 +859,17 @@ void CCECParser::AddKey(void) } } +void CCECParser::AddCommand(cec_logical_address source, cec_logical_address destination, cec_opcode opcode, cec_frame *parameters) +{ + cec_command command; + command.source = source; + command.destination = destination; + command.opcode = opcode; + if (parameters) + command.parameters = *parameters; + m_commandBuffer.Push(command); +} + int CCECParser::GetMinVersion(void) { return CEC_MIN_VERSION; diff --git a/src/lib/CECParser.h b/src/lib/CECParser.h index f257fe1..1eca99c 100644 --- a/src/lib/CECParser.h +++ b/src/lib/CECParser.h @@ -62,6 +62,7 @@ namespace CEC virtual bool SetInactiveView(void); virtual bool GetNextLogMessage(cec_log_message *message); virtual bool GetNextKeypress(cec_keypress *key); + virtual bool GetNextCommand(cec_command *command); virtual bool Transmit(const cec_frame &data, bool bWaitForAck = true, int64_t iTimeout = (int64_t) 5000); virtual bool SetLogicalAddress(cec_logical_address iLogicalAddress); virtual bool SetAckMask(uint16_t iMask); @@ -73,7 +74,7 @@ namespace CEC bool Process(void); protected: virtual bool TransmitFormatted(const cec_frame &data, bool bWaitForAck = true, int64_t iTimeout = (int64_t) 2000); - virtual void TransmitAbort(cec_logical_address address, ECecOpcode opcode, ECecAbortReason reason = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE); + virtual void TransmitAbort(cec_logical_address address, cec_opcode opcode, ECecAbortReason reason = CEC_ABORT_REASON_UNRECOGNIZED_OPCODE); virtual void ReportCECVersion(cec_logical_address address = CECDEVICE_TV); virtual void ReportPowerState(cec_logical_address address = CECDEVICE_TV, bool bOn = true); virtual void ReportMenuState(cec_logical_address address = CECDEVICE_TV, bool bActive = true); @@ -85,6 +86,7 @@ namespace CEC private: void AddKey(void); + void AddCommand(cec_logical_address source, cec_logical_address destination, cec_opcode opcode, cec_frame *parameters); void AddLog(cec_log_level level, const std::string &strMessage); bool WaitForAck(int64_t iTimeout = (int64_t) 1000); bool ReadFromDevice(int iTimeout); @@ -110,6 +112,7 @@ namespace CEC CecBuffer m_frameBuffer; CecBuffer m_logBuffer; CecBuffer m_keyBuffer; + CecBuffer m_commandBuffer; std::string m_strDeviceName; pthread_t m_thread; CMutex m_mutex; diff --git a/src/lib/CECParserC.cpp b/src/lib/CECParserC.cpp index 4b6a1ef..a4841a0 100644 --- a/src/lib/CECParserC.cpp +++ b/src/lib/CECParserC.cpp @@ -124,6 +124,13 @@ bool cec_get_next_keypress(cec_keypress *key) return false; } +bool cec_get_next_command(cec_command *command) +{ + if (cec_parser) + return cec_parser->GetNextCommand(command); + return false; +} + bool cec_transmit(const CEC::cec_frame &data, bool bWaitForAck /* = true */, int64_t iTimeout /* = 2000 */) { if (cec_parser) diff --git a/src/lib/util/buffer.h b/src/lib/util/buffer.h index 299b019..4379f8d 100644 --- a/src/lib/util/buffer.h +++ b/src/lib/util/buffer.h @@ -38,29 +38,34 @@ template struct CecBuffer { public: - CecBuffer(void) {} + CecBuffer(int iMaxSize = 100) {} virtual ~CecBuffer(void) {} - void Push(_BType entry) + bool Push(_BType entry) { - CLockObject lock(&mutex); - buffer.push(entry); + CLockObject lock(&m_mutex); + if (m_buffer.size() == m_maxSize) + return false; + + m_buffer.push(entry); + return true; } bool Pop(_BType &entry) { bool bReturn(false); - CLockObject lock(&mutex); - if (buffer.size() > 0) + CLockObject lock(&m_mutex); + if (m_buffer.size() > 0) { - entry = buffer.front(); - buffer.pop(); + entry = m_buffer.front(); + m_buffer.pop(); bReturn = true; } return bReturn; } private: - std::queue<_BType> buffer; - CMutex mutex; + int m_maxSize; + std::queue<_BType> m_buffer; + CMutex m_mutex; }; diff --git a/src/testclient/main.cpp b/src/testclient/main.cpp index d119aef..15a333d 100644 --- a/src/testclient/main.cpp +++ b/src/testclient/main.cpp @@ -100,7 +100,31 @@ void show_help(const char* strExec) "parameters:" << endl << "\t-h --help Shows this help text" << endl << "\t-l --list-devices List all devices on this system" << endl << - "\t[COM PORT] The com port to connect to. If no COM port is given, the client tries to connect to the first device that is detected" << endl; + "\t[COM PORT] The com port to connect to. If no COM port is given, the client tries to connect to the first device that is detected" << endl << + endl << + "Type 'h' or 'help' and press enter after starting the client to display all available commands" << endl; +} + +void show_console_help(void) +{ + cout << endl << + "================================================================================" << endl << + "Available commands:" << endl << + endl << + "tx {bytes} transfer bytes over the CEC line." << endl << + "[tx 40 00 FF 11 22 33] sends bytes 0x40 0x00 0xFF 0x11 0x22 0x33" << endl << + endl << + "am {ackmack} change the ackmask of the CEC adapter." << endl << + "[am 10] ackmask 0x10 (logical address 4)" << endl << + endl << + "la {logical_address} change the logical address of the CEC adapter." << endl << + "[la 4] logical address 4" << endl << + endl << + "[ping] send a ping command to the CEC adapter." << endl << + "[bl] to let the adapter enter the bootloader, to upgrade the flash rom." << endl << + "[h] or [help] show this help." << endl << + "[q] or [quit] to quit the CEC test client and switch off all connected CEC devices." << endl << + "================================================================================" << endl; } int main (int argc, char *argv[]) @@ -224,6 +248,10 @@ int main (int argc, char *argv[]) { parser->StartBootloader(); } + else if (command == "h" || command == "help") + { + show_console_help(); + } else if (command == "q" || command == "quit") { bContinue = false; -- 2.34.1