aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2017-07-19 10:48:41 +0200
committerHans Verkuil <hans.verkuil@cisco.com>2017-07-19 10:54:50 +0200
commit452323b1c9d10964db096b83f16c11119290de7a (patch)
treec409cff5f9dbaa7ecdd0e62d2193e8383e89b337
parent319bd6e4e80b65d2cdf4ae5c1d7147691c722c29 (diff)
cec-ctl: add error injection supportcec-error-inj
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
-rw-r--r--utils/cec-ctl/cec-ctl.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/utils/cec-ctl/cec-ctl.cpp b/utils/cec-ctl/cec-ctl.cpp
index 2d341cff..effe9983 100644
--- a/utils/cec-ctl/cec-ctl.cpp
+++ b/utils/cec-ctl/cec-ctl.cpp
@@ -638,6 +638,7 @@ static void log_u8_array(const char *arg_name, unsigned num, const __u8 *vals)
enum Option {
OptClear = 'C',
OptSetDevice = 'd',
+ OptErrorInj = 'e',
OptFrom = 'f',
OptHelp = 'h',
OptMonitor = 'm',
@@ -707,6 +708,7 @@ struct node {
bool show_info;
typedef std::vector<cec_msg> msg_vec;
+typedef std::vector<cec_error_inj> error_inj_vec;
static const struct message *opt2message[OptLast - OptMessages];
@@ -735,6 +737,7 @@ static struct option long_options[] = {
{ "monitor-all", no_argument, 0, OptMonitorAll },
{ "monitor-pin", no_argument, 0, OptMonitorPin },
{ "monitor-time", required_argument, 0, OptMonitorTime },
+ { "error-inj", required_argument, 0, OptErrorInj },
{ "no-reply", no_argument, 0, OptNoReply },
{ "to", required_argument, 0, OptTo },
{ "from", required_argument, 0, OptFrom },
@@ -792,6 +795,11 @@ static void usage(void)
" -M, --monitor-all Monitor all CEC traffic\n"
" --monitor-pin Monitor low-level CEC pin\n"
" --monitor-time=<secs> Monitor for <secs> seconds (default is forever)\n"
+ " -e, --error-inj=action=<act>,which=<idx>,when=<when>\n"
+ " Inject error:\n"
+ " act = clear, nack-dir, nack-bcast, tx-inv-bit, rx-inv-bit\n"
+ " which = byte index for nack-dir & nack-bcast, bit index for tx/rx-inv-bit\n"
+ " when = once, always\n"
" -n, --no-reply Don't wait for a reply\n"
" -t, --to=<la> Send message to the given logical address\n"
" -f, --from=<la> Send message from the given logical address\n"
@@ -864,6 +872,8 @@ static std::string caps2s(unsigned caps)
s += "\t\tNeeds HPD\n";
if (caps & CEC_CAP_MONITOR_PIN)
s += "\t\tMonitor Pin\n";
+ if (caps & CEC_CAP_ERROR_INJ)
+ s += "\t\tError Injection\n";
return s;
}
@@ -1492,6 +1502,7 @@ int main(int argc, char **argv)
const char *device = "/dev/cec0"; /* -d device */
const message *opt;
msg_vec msgs;
+ error_inj_vec error_injections;
char short_options[26 * 2 * 2 + 1];
__u32 timeout = 1000;
__u32 monitor_time = 0;
@@ -1652,6 +1663,56 @@ int main(int argc, char **argv)
fprintf(stderr, "Unknown argument '%s'\n\n", argv[optind]);
usage();
return 1;
+ case OptErrorInj: {
+ static const char *arg_names[] = {
+ "action",
+ "which",
+ "when",
+ NULL
+ };
+ char *value, *subs = optarg;
+ struct cec_error_inj error_inj = {};
+ bool error = false;
+
+ while (*subs != '\0') {
+ switch (parse_subopt(&subs, arg_names, &value)) {
+ case 0:
+ if (!strcmp(value, "clear"))
+ error_inj.action = CEC_ERROR_INJ_CLEAR;
+ else if (!strcmp(value, "nack-dir"))
+ error_inj.action = CEC_ERROR_INJ_RX_NACK_DIR_BYTE;
+ else if (!strcmp(value, "nack-bcast"))
+ error_inj.action = CEC_ERROR_INJ_RX_NACK_BCAST_BYTE;
+ else if (!strcmp(value, "tx-inv-bit"))
+ error_inj.action = CEC_ERROR_INJ_TX_INV_BIT;
+ else if (!strcmp(value, "rx-inv-bit"))
+ error_inj.action = CEC_ERROR_INJ_RX_INV_BIT;
+ else
+ error = true;
+ break;
+ case 1:
+ error_inj.which = strtoul(value, NULL, 0);
+ break;
+ case 2:
+ if (!strcmp(value, "once"))
+ error_inj.when = CEC_ERROR_INJ_ONCE;
+ else if (!strcmp(value, "always"))
+ error_inj.when = CEC_ERROR_INJ_ALWAYS;
+ else
+ error = true;
+ break;
+ default:
+ exit(1);
+ }
+ }
+ if (error) {
+ fprintf(stderr, "Unknown argument '%s'\n\n", argv[optind]);
+ usage();
+ return 1;
+ }
+ error_injections.push_back(error_inj);
+ break;
+ }
case OptVendorCommand: {
static const char *arg_names[] = {
"payload",
@@ -2104,6 +2165,10 @@ int main(int argc, char **argv)
break;
}
}
+
+ for (error_inj_vec::iterator iter = error_injections.begin(); iter != error_injections.end(); ++iter)
+ doioctl(&node, CEC_ERROR_INJ, &(*iter));
+
if (node.num_log_addrs == 0) {
if (options[OptMonitor] || options[OptMonitorAll] || options[OptMonitorPin])
goto skip_la;

Privacy Policy