Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Raw traffic mode #640

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ project(libcec)
cmake_minimum_required(VERSION 3.12.0)

set(LIBCEC_VERSION_MAJOR 6)
set(LIBCEC_VERSION_MINOR 0)
set(LIBCEC_VERSION_PATCH 2)
set(LIBCEC_VERSION_MINOR 1)
set(LIBCEC_VERSION_PATCH 0)

# cec-client
add_subdirectory(src/cec-client)
Expand Down
11 changes: 10 additions & 1 deletion debian/cec-client.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH CEC-CLIENT "1" "January 2012" "User Commands"
.TH CEC-CLIENT "1" "October 2023" "User Commands"
.SH NAME
cec\-client \- CEC connection client utility
.SH DESCRIPTION
Expand Down Expand Up @@ -30,6 +30,15 @@ and log levels to a file.
\fB\-d\fR \fB\-\-log\-level\fR {level}
Sets the log level. See cectypes.h for values.
.TP
\fB\-m\fR \fB\-\-monitor\fR
Set monitor mode. The CEC tester does not allocate a logical address or send any messages.
.TP
\fB\-\-raw\fR
Set raw traffic mode. The command callback is called for all messages including polls. This also disables prioritization or special handling of certain devices.
.TP
\fB\-g\fR \fB\-\-gaps\fR
Add 1, 2 or 3 line gaps between log messages depending on their time interval. This can help group related messages.
.TP
\fB\-s\fR \fB\-\-single\-command\fR
Execute a single command and exit. Does not power
on devices on startup and power them off on exit.
Expand Down
7 changes: 7 additions & 0 deletions include/cec.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ namespace CEC
*/
virtual bool SwitchMonitoring(bool bEnable) = 0;

/*!
* @brief Enable or disable raw traffic mode. This is best used along with monitoring mode. It shows all traffic including polls and disables CEC packet prioritization.
* @param bEnable True to enable, false to disable.
* @return True when switched successfully, false otherwise.
*/
virtual bool SwitchRawTraffic(bool bEnable) = 0;

/*!
* @brief Get the CEC version of the device with the given logical address
* @param iLogicalAddress The logical address of the device to get the CEC version for.
Expand Down
1 change: 1 addition & 0 deletions include/cecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ extern DECLSPEC int libcec_set_logical_address(libcec_connection_t connection, C
extern DECLSPEC int libcec_set_physical_address(libcec_connection_t connection, uint16_t iPhysicalAddress);
extern DECLSPEC int libcec_set_osd_string(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress, CEC_NAMESPACE cec_display_control duration, const char* strMessage);
extern DECLSPEC int libcec_switch_monitoring(libcec_connection_t connection, int bEnable);
extern DECLSPEC int libcec_switch_raw_traffic(libcec_connection_t connection, int bEnable);
extern DECLSPEC CEC_NAMESPACE cec_version libcec_get_device_cec_version(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
extern DECLSPEC int libcec_get_device_menu_language(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress, CEC_NAMESPACE cec_menu_language language);
extern DECLSPEC uint32_t libcec_get_device_vendor_id(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
Expand Down
2 changes: 2 additions & 0 deletions include/ceccloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ typedef struct {
int (CDECL *set_physical_address)(libcec_connection_t connection, uint16_t iPhysicalAddress);
int (CDECL *set_osd_string)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress, CEC_NAMESPACE cec_display_control duration, const char* strMessage);
int (CDECL *switch_monitoring)(libcec_connection_t connection, int bEnable);
int (CDECL *switch_raw_traffic)(libcec_connection_t connection, int bEnable);
CEC_NAMESPACE cec_version (CDECL *get_device_cec_version)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
int (CDECL *get_device_menu_language)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress, CEC_NAMESPACE cec_menu_language language);
uint64_t (CDECL *get_device_vendor_id)(libcec_connection_t connection, CEC_NAMESPACE cec_logical_address iLogicalAddress);
Expand Down Expand Up @@ -160,6 +161,7 @@ static int libcecc_resolve_all(void* lib, libcec_interface_t* iface)
_libcecc_resolve(lib, iface->set_physical_address, "libcec_set_physical_address", int(CDECL *)(libcec_connection_t, uint16_t));
_libcecc_resolve(lib, iface->set_osd_string, "libcec_set_osd_string", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, CEC_NAMESPACE cec_display_control, const char*));
_libcecc_resolve(lib, iface->switch_monitoring, "libcec_switch_monitoring", int(CDECL *)(libcec_connection_t, int));
_libcecc_resolve(lib, iface->switch_raw_traffic, "libcec_switch_raw_traffic", int(CDECL *)(libcec_connection_t, int));
_libcecc_resolve(lib, iface->get_device_cec_version, "libcec_get_device_cec_version", CEC_NAMESPACE cec_version(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
_libcecc_resolve(lib, iface->get_device_menu_language, "libcec_get_device_menu_language", int(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address, CEC_NAMESPACE cec_menu_language));
_libcecc_resolve(lib, iface->get_device_vendor_id, "libcec_get_device_vendor_id", uint64_t(CDECL *)(libcec_connection_t, CEC_NAMESPACE cec_logical_address));
Expand Down
12 changes: 11 additions & 1 deletion include/cectypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -741,8 +741,11 @@ typedef enum cec_logical_address
CECDEVICE_TUNER4 = 10,
CECDEVICE_PLAYBACKDEVICE3 = 11,
CECDEVICE_RESERVED1 = 12,
CECDEVICE_BACKUP1 = 12,
CECDEVICE_RESERVED2 = 13,
CECDEVICE_BACKUP2 = 13,
CECDEVICE_FREEUSE = 14,
CECDEVICE_SPECIFICUSE = 14,
CECDEVICE_UNREGISTERED = 15,
CECDEVICE_BROADCAST = 15
} cec_logical_address;
Expand Down Expand Up @@ -873,6 +876,7 @@ typedef enum cec_vendor_id
CEC_VENDOR_SHARP2 = 0x534850,
CEC_VENDOR_VIZIO = 0x6B746D,
CEC_VENDOR_BENQ = 0x8065E9,
CEC_VENDOR_ROKU = 0x8AC72E,
CEC_VENDOR_HARMAN_KARDON = 0x9C645E,
CEC_VENDOR_UNKNOWN = 0
} cec_vendor_id;
Expand Down Expand Up @@ -1055,6 +1059,7 @@ typedef struct cec_command
cec_logical_address destination; /**< the logical address of the destination of this message */
int8_t ack; /**< 1 when the ACK bit is set, 0 otherwise */
int8_t eom; /**< 1 when the EOM bit is set, 0 otherwise */
int8_t sent; /**< 1 if the command is sent, 0 if received */
cec_opcode opcode; /**< the opcode of this message */
cec_datapacket parameters; /**< the parameters attached to this message */
int8_t opcode_set; /**< 1 when an opcode is set, 0 otherwise (POLL message) */
Expand All @@ -1072,6 +1077,7 @@ typedef struct cec_command
destination = command.destination;
ack = command.ack;
eom = command.eom;
sent = command.sent;
opcode = command.opcode;
opcode_set = command.opcode_set;
transmit_timeout = command.transmit_timeout;
Expand Down Expand Up @@ -1133,6 +1139,7 @@ typedef struct cec_command
{
initiator = CECDEVICE_UNKNOWN;
destination = CECDEVICE_UNKNOWN;
sent = 0;
ack = 0;
eom = 0;
opcode_set = 0;
Expand Down Expand Up @@ -1500,7 +1507,8 @@ struct libcec_configuration
uint16_t iFirmwareVersion; /*!< (read-only) the firmware version of the adapter. added in 1.6.0 */
char strDeviceLanguage[3]; /*!< the menu language used by the client. 3 character ISO 639-2 country code. see http://http://www.loc.gov/standards/iso639-2/ added in 1.6.2 */
uint32_t iFirmwareBuildDate; /*!< (read-only) the build date of the firmware, in seconds since epoch. if not available, this value will be set to 0. added in 1.6.2 */
uint8_t bMonitorOnly; /*!< won't allocate a CCECClient when starting the connection when set (same as monitor mode). added in 1.6.3 */
uint8_t bMonitorOnly; /*!< won't allocate a CCECClient when starting the connection when set (same as monitor mode). added in 1.5.3 */
uint8_t bRawTraffic; /*!< include pings in commandReceived callback, report all error frames and no prioritization. Added in 1.6.1 */
cec_version cecVersion; /*!< CEC spec version to use by libCEC. defaults to v1.4. added in 1.8.0 */
cec_adapter_type adapterType; /*!< type of the CEC adapter that we're connected to. added in 1.8.2 */
cec_user_control_code comboKey; /*!< key code that initiates combo keys. defaults to CEC_USER_CONTROL_CODE_STOP. CEC_USER_CONTROL_CODE_UNKNOWN to disable. added in 2.0.5 */
Expand Down Expand Up @@ -1538,6 +1546,7 @@ struct libcec_configuration
!strncmp(strDeviceLanguage, other.strDeviceLanguage, 3) &&
iFirmwareBuildDate == other.iFirmwareBuildDate &&
bMonitorOnly == other.bMonitorOnly &&
bRawTraffic == other.bRawTraffic &&
cecVersion == other.cecVersion &&
adapterType == other.adapterType &&
iDoubleTapTimeoutMs == other.iDoubleTapTimeoutMs &&
Expand Down Expand Up @@ -1576,6 +1585,7 @@ struct libcec_configuration
memcpy(strDeviceLanguage, CEC_DEFAULT_DEVICE_LANGUAGE, 3);
iFirmwareBuildDate = CEC_FW_BUILD_UNKNOWN;
bMonitorOnly = 0;
bRawTraffic = 0;
cecVersion = (cec_version)CEC_DEFAULT_SETTING_CEC_VERSION;
adapterType = ADAPTERTYPE_UNKNOWN;
iDoubleTapTimeoutMs = CEC_DOUBLE_TAP_TIMEOUT_MS;
Expand Down
17 changes: 14 additions & 3 deletions src/EventGhost/egplugin_sources/PulseEight/cec_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ def __init__(self, com_port, adapter_name, hdmi_port, use_avr, poll_interval):
self.tuner4 = CECDevice(adapter, 'Tuner 4', cec.CECDEVICE_TUNER4)
self.audiosystem = CECDevice(adapter, 'AVR', cec.CECDEVICE_AUDIOSYSTEM)
self.freeuse = CECDevice(adapter, 'Free Use', cec.CECDEVICE_FREEUSE)
self.specificuse = CECDevice(adapter, 'Specific Use', cec.CECDEVICE_SPECIFICUSE)
self.unknown = CECDevice(adapter, 'Unknown', cec.CECDEVICE_UNKNOWN)
self.broadcast = CECDevice(
adapter,
Expand All @@ -366,11 +367,21 @@ def __init__(self, com_port, adapter_name, hdmi_port, use_avr, poll_interval):
'Reserved 1',
cec.CECDEVICE_RESERVED1
)
self.backup1 = CECDevice(
adapter,
'Backup 1',
cec.CECDEVICE_BACKUP1
)
self.reserved2 = CECDevice(
adapter,
'Reserved 2',
cec.CECDEVICE_RESERVED2
)
self.backup2 = CECDevice(
adapter,
'Backup 1',
cec.CECDEVICE_BACKUP2
)
self.recordingdevice1 = CECDevice(
adapter,
'Recording Device 1',
Expand Down Expand Up @@ -415,9 +426,9 @@ def __init__(self, com_port, adapter_name, hdmi_port, use_avr, poll_interval):
self.playbackdevice1,
self.playbackdevice2,
self.playbackdevice3,
self.reserved1,
self.reserved2,
self.freeuse,
self.backup1,
self.backup2,
self.specificuse,
self.broadcast,
self.unknown,
]
Expand Down
93 changes: 89 additions & 4 deletions src/cec-client/cec-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ int g_cecLogLevel(-1);
int g_cecDefaultLogLevel(CEC_LOG_ALL);
std::ofstream g_logOutput;
bool g_bShortLog(false);
bool g_logGaps(false);
uint64_t g_lastLogTime(0);
std::string g_strPort;
bool g_bSingleCommand(false);
volatile sig_atomic_t g_bExit(0);
Expand Down Expand Up @@ -91,7 +93,7 @@ class CReconnect : public P8PLATFORM::CThread
g_parser->Close();
if (!g_parser->Open(g_strPort.c_str()))
{
PrintToStdOut("Failed to reconnect\n");
PrintToStdOut("Failed to reconnect");
g_bExit = 1;
}
}
Expand Down Expand Up @@ -205,8 +207,18 @@ void CecLogMessage(void *UNUSED(cbParam), const cec_log_message* message)
break;
}

std::string strGap;
if (g_logGaps)
if (message->time - g_lastLogTime >= 1000)
strGap = "---\n---\n---\n";
else if (message->time - g_lastLogTime >= 100)
strGap = "--\n--\n";
else if (message->time - g_lastLogTime >= 10)
strGap = "-\n";
g_lastLogTime = message->time;

std::string strFullLog;
strFullLog = StringUtils::Format("%s[%16lld]\t%s", strLevel.c_str(), message->time, message->message);
strFullLog = StringUtils::Format("%s%s[%16lld]\t%s", strGap.c_str(), strLevel.c_str(), message->time, message->message);
PrintToStdOut(strFullLog.c_str());

if (g_logOutput.is_open())
Expand All @@ -223,8 +235,31 @@ void CecKeyPress(void *UNUSED(cbParam), const cec_keypress* UNUSED(key))
{
}

void CecCommand(void *UNUSED(cbParam), const cec_command* UNUSED(command))
void CecCommand(void *UNUSED(cbParam), const cec_command* command)
{
if (g_config.bRawTraffic)
{
std::string s;
if (command->sent)
s = StringUtils::Format("COMMAND: sent << %X%X",
command->initiator, command->destination);
else {
std::string src = "?", dst = "?";
if (command->initiator != CECDEVICE_UNKNOWN) {
src = StringUtils::Format("%X", command->initiator);
}
if (command->destination != CECDEVICE_UNKNOWN) {
dst = StringUtils::Format("%X", command->destination);
}
s = StringUtils::Format("COMMAND: received ack=%d eom=%d >> %s%s",
command->ack, command->eom, src.c_str(), dst.c_str());
}
if (command->opcode_set)
s += StringUtils::Format(":%02X", command->opcode);
for (int i = 0; i < command->parameters.size; ++i)
s += StringUtils::Format(":%02X", command->parameters.data[i]);
PrintToStdOut("%s", s.c_str());
}
}

void CecAlert(void *UNUSED(cbParam), const libcec_alert type, const libcec_parameter UNUSED(param))
Expand All @@ -234,7 +269,7 @@ void CecAlert(void *UNUSED(cbParam), const libcec_alert type, const libcec_param
case CEC_ALERT_CONNECTION_LOST:
if (!CReconnect::Get().IsRunning())
{
PrintToStdOut("Connection lost - trying to reconnect\n");
PrintToStdOut("Connection lost - trying to reconnect");
CReconnect::Get().CreateThread(false);
}
break;
Expand Down Expand Up @@ -306,10 +341,12 @@ void ShowHelpCommandLine(const char* strExec)
" -sf --short-log-file {file} Writes all libCEC log message without timestamps" << std::endl <<
" and log levels to a file." << std::endl <<
" -d --log-level {level} Sets the log level. See cectypes.h for values." << std::endl <<
" -g --gaps Write logs with line gaps depending on time interval." << std::endl <<
" -s --single-command Execute a single command and exit. Does not power" << std::endl <<
" on devices on startup and power them off on exit." << std::endl <<
" -o --osd-name {osd name} Use a custom osd name." << std::endl <<
" -m --monitor Start a monitor-only client." << std::endl <<
" --raw Show raw traffic, including polls." << std::endl <<
" -i --info Shows information about how libCEC was compiled." << std::endl <<
" [COM PORT] The com port to connect to. If no COM" << std::endl <<
" port is given, the client tries to connect to the" << std::endl <<
Expand Down Expand Up @@ -353,7 +390,9 @@ void ShowHelpConsole(void)
"[self] show the list of addresses controlled by libCEC" << std::endl <<
"[scan] scan the CEC bus and display device info" << std::endl <<
"[mon] {1|0} enable or disable CEC bus monitoring." << std::endl <<
"[raw] {1|0} show raw traffic including polls." << std::endl <<
"[log] {1 - 31} change the log level. see cectypes.h for values." << std::endl <<
"[gaps] {1|0} enable/disable gaps between logs depending on time interval." << std::endl <<
"[ping] send a ping command to the CEC adapter." << std::endl <<
"[bl] to let the adapter enter the bootloader, to upgrade" << std::endl <<
" the flash rom." << std::endl <<
Expand Down Expand Up @@ -666,6 +705,21 @@ bool ProcessCommandMON(ICECAdapter *parser, const std::string &command, std::str
return false;
}

bool ProcessCommandRAW(ICECAdapter *parser, const std::string &command, std::string &arguments)
{
if (command == "raw")
{
std::string strEnable;
if (GetWord(arguments, strEnable) && (strEnable == "0" || strEnable == "1"))
{
parser->SwitchRawTraffic(strEnable == "1");
return true;
}
}

return false;
}

bool ProcessCommandBL(ICECAdapter *parser, const std::string &command, std::string & UNUSED(arguments))
{
if (command == "bl")
Expand Down Expand Up @@ -875,6 +929,22 @@ bool ProcessCommandLOG(ICECAdapter * UNUSED(parser), const std::string &command,
return false;
}

bool ProcessCommandGAPS(ICECAdapter *parser, const std::string &command, std::string &arguments)
{
if (command == "gaps")
{
std::string strEnable;
if (GetWord(arguments, strEnable) && (strEnable == "0" || strEnable == "1"))
{
g_logGaps = strEnable == "1";
return true;
}
}

return false;
}


bool ProcessCommandSCAN(ICECAdapter *parser, const std::string &command, std::string & UNUSED(arguments))
{
if (command == "scan")
Expand Down Expand Up @@ -972,6 +1042,7 @@ bool ProcessConsoleCommand(ICECAdapter *parser, std::string &input)
ProcessCommandVOLDOWN(parser, command, input) ||
ProcessCommandMUTE(parser, command, input) ||
ProcessCommandMON(parser, command, input) ||
ProcessCommandRAW(parser, command, input) ||
ProcessCommandBL(parser, command, input) ||
ProcessCommandLANG(parser, command, input) ||
ProcessCommandVEN(parser, command, input) ||
Expand All @@ -984,6 +1055,7 @@ bool ProcessConsoleCommand(ICECAdapter *parser, std::string &input)
ProcessCommandR(parser, command, input) ||
ProcessCommandH(parser, command, input) ||
ProcessCommandLOG(parser, command, input) ||
ProcessCommandGAPS(parser, command, input) ||
ProcessCommandSCAN(parser, command, input) ||
ProcessCommandSP(parser, command, input) ||
ProcessCommandSPL(parser, command, input) ||
Expand Down Expand Up @@ -1046,6 +1118,12 @@ bool ProcessCommandLineArguments(int argc, char *argv[])
++iArgPtr;
}
}
else if (!strcmp(argv[iArgPtr], "-g") ||
!strcmp(argv[iArgPtr], "--gaps"))
{
g_logGaps = 1;
++iArgPtr;
}
else if (!strcmp(argv[iArgPtr], "-t") ||
!strcmp(argv[iArgPtr], "--type"))
{
Expand Down Expand Up @@ -1193,6 +1271,13 @@ bool ProcessCommandLineArguments(int argc, char *argv[])
g_config.bMonitorOnly = 1;
++iArgPtr;
}
else if (!strcmp(argv[iArgPtr], "--raw"))
{
std::cout << "Showing raw traffic including polls. use 'raw 0' to disable" << std::endl;
g_config.bRawTraffic = 1;
++iArgPtr;
}

#if defined(HAVE_CURSES_API)
else if (!strcmp(argv[iArgPtr], "-c"))
{
Expand Down
6 changes: 6 additions & 0 deletions src/cecc-client/cecc-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,12 @@ static int cec_process_command_line_arguments(int argc, char *argv[])
g_config.bMonitorOnly = 1;
++iArgPtr;
}
else if (!strcmp(argv[iArgPtr], "--raw"))
{
printf("Showing raw traffic including polls. use 'raw 0' to disable\n");
g_config.bRawTraffic = 1;
++iArgPtr;
}
else
{
strcpy(g_strPort, argv[iArgPtr++]);
Expand Down
Loading