aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Fjeldtvedt <jaffe1@gmail.com>2016-07-22 11:43:08 +0200
committerHans Verkuil <hans.verkuil@cisco.com>2016-07-22 14:36:49 +0200
commit7838079e2084b4d30e72dab5ce32adc4a43f1137 (patch)
treefbf8510a6af71e7f0249d74d431133dbf1e06313
parent1e31eadf1fe4d0408224121b9decf37bafdb5591 (diff)
cec-compliance: keep track of recognized and unrecognized opcodes
Whenever we transmit something, we categorize the opcode as either recognized (we got back a reply if that was expected, or a feature abort with different reason than [Unrecognized opcode], or we got no reply when not expecting any). We also cateogrize opcodes based on manually received Feature Aborts. The [Abort Message] operand is used in this case. Signed-off-by: Johan Fjeldtvedt <jaffe1@gmail.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
-rw-r--r--utils/cec-compliance/cec-compliance.cpp55
-rw-r--r--utils/cec-compliance/cec-compliance.h6
-rw-r--r--utils/cec-compliance/cec-test.cpp26
3 files changed, 83 insertions, 4 deletions
diff --git a/utils/cec-compliance/cec-compliance.cpp b/utils/cec-compliance/cec-compliance.cpp
index 93cbc1ce..f6ddbd1a 100644
--- a/utils/cec-compliance/cec-compliance.cpp
+++ b/utils/cec-compliance/cec-compliance.cpp
@@ -609,13 +609,18 @@ void sad_decode(struct short_audio_desc *sad, __u32 descriptor)
}
}
-int cec_named_ioctl(int fd, const char *name,
+int cec_named_ioctl(struct node *node, const char *name,
unsigned long int request, void *parm)
{
int retval;
int e;
+ struct cec_msg *msg = (struct cec_msg *)parm;
+ __u8 opcode = 0;
- retval = ioctl(fd, request, parm);
+ if (request == CEC_TRANSMIT)
+ opcode = cec_msg_opcode(msg);
+
+ retval = ioctl(node->fd, request, parm);
e = retval == 0 ? 0 : errno;
if (options[OptTrace])
@@ -625,6 +630,52 @@ int cec_named_ioctl(int fd, const char *name,
if (retval < 0)
app_result = -1;
+ if (!retval) {
+ /* TODO: The logic here might need to be re-evaluated.
+
+ Currently a message is registered as recognized if
+ - We receive a reply that is not Feature Abort with
+ [Unrecognized Opcode]
+ - We did not receive a reply, but also did not
+ expect one (other than Feature Abort)
+ - We manually receive (CEC_RECEIVE) and get a Feature Abort
+ with reason different than [Unrecognized Opcode] */
+ if (request == CEC_TRANSMIT && msg->timeout > 0 &&
+ cec_msg_initiator(msg) != CEC_LOG_ADDR_UNREGISTERED &&
+ cec_msg_destination(msg) != CEC_LOG_ADDR_BROADCAST &&
+ (msg->tx_status & CEC_TX_STATUS_OK)) {
+ if (msg->rx_status & CEC_RX_STATUS_OK) {
+ __u8 la = cec_msg_initiator(msg);
+
+ if (cec_msg_status_is_abort(msg) &&
+ abort_reason(msg) == CEC_OP_ABORT_UNRECOGNIZED_OP)
+ node->remote[la].unrecognized_op[opcode] = true;
+ else
+ node->remote[la].recognized_op[opcode] = true;
+ }
+ else {
+ __u8 la = cec_msg_destination(msg);
+
+ if (msg->reply > 0)
+ node->remote[la].unrecognized_op[opcode] = true;
+ else
+ node->remote[la].recognized_op[opcode] = true;
+ }
+ }
+
+ if (request == CEC_RECEIVE &&
+ cec_msg_initiator(msg) != CEC_LOG_ADDR_UNREGISTERED &&
+ cec_msg_status_is_abort(msg)) {
+ __u8 la = cec_msg_initiator(msg);
+ __u8 abort_msg = msg->msg[2];
+
+ if (abort_reason(msg) == CEC_OP_ABORT_UNRECOGNIZED_OP)
+ node->remote[la].unrecognized_op[abort_msg] = true;
+ else
+ node->remote[la].recognized_op[abort_msg] = true;
+ }
+ }
+
return retval == -1 ? e : (retval ? -1 : 0);
}
diff --git a/utils/cec-compliance/cec-compliance.h b/utils/cec-compliance/cec-compliance.h
index 9762bb70..3cd67d00 100644
--- a/utils/cec-compliance/cec-compliance.h
+++ b/utils/cec-compliance/cec-compliance.h
@@ -123,6 +123,8 @@ extern bool show_warnings;
extern unsigned warnings;
struct remote {
+ bool recognized_op[256];
+ bool unrecognized_op[256];
unsigned prim_type;
__u16 phys_addr;
__u8 cec_version;
@@ -263,10 +265,10 @@ static inline bool question(const char* prompt)
return get_yn() == 'y';
}
-int cec_named_ioctl(int fd, const char *name,
+int cec_named_ioctl(struct node *node, const char *name,
unsigned long int request, void *parm);
-#define doioctl(n, r, p) cec_named_ioctl((n)->fd, #r, r, p)
+#define doioctl(n, r, p) cec_named_ioctl(n, #r, r, p)
#define cec_phys_addr_exp(pa) \
((pa) >> 12), ((pa) >> 8) & 0xf, ((pa) >> 4) & 0xf, (pa) & 0xf
diff --git a/utils/cec-compliance/cec-test.cpp b/utils/cec-compliance/cec-test.cpp
index ab354ee7..f6f2a285 100644
--- a/utils/cec-compliance/cec-test.cpp
+++ b/utils/cec-compliance/cec-test.cpp
@@ -516,6 +516,29 @@ static struct remote_subtest rc_passthrough_subtests[] = {
};
+/* Post-test checks */
+
+static int post_test_check_recognized(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ bool fail = false;
+
+ for (unsigned i = 0; i < 256; i++) {
+ if (node->remote[la].recognized_op[i] && node->remote[la].unrecognized_op[i]) {
+ info("Opcode %x has been both recognized by and has been replied\n", i);
+ info("Feature Abort [Unrecognized Opcode] to by the device.\n");
+ fail = true;
+ }
+ }
+ fail_on_test(fail);
+
+ return 0;
+}
+
+static struct remote_subtest post_test_subtests[] = {
+ { "Recognized/unrecognized message consistency", CEC_LOG_ADDR_MASK_ALL, post_test_check_recognized },
+};
+
+
static struct remote_test tests[] = {
test_case("Core",
TAG_CORE,
@@ -559,6 +582,9 @@ static struct remote_test tests[] = {
test_case_ext("Standby/Resume and Power Status",
TAG_POWER_STATUS | TAG_STANDBY_RESUME,
standby_resume_subtests),
+ test_case("Post-test checks",
+ TAG_CORE,
+ post_test_subtests),
};
static const unsigned num_tests = sizeof(tests) / sizeof(struct remote_test);

Privacy Policy