aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Fjeldtvedt <jaffe1@gmail.com>2016-08-09 15:06:38 +0200
committerHans Verkuil <hans.verkuil@cisco.com>2016-08-10 09:07:46 +0200
commitee14f940a2c8c087404a643badf5567e2eebf7c1 (patch)
treee5ddd8671f52ce4832b65231f9b6cce8425bc9e9
parent3d8a5930a029b5b57ec4c1ccda7e8a6bd11e379f (diff)
add test for Timer Programming feature
This adds basic tests for the messages in the Timer Programming feature. cec-follower is extended to recognize these messages and reply when receiving set- or clear timer requests. Comments are added with further suggestions. Signed-off-by: Johan Fjeldtvedt <jaffe1@gmail.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
-rw-r--r--utils/cec-compliance/cec-test.cpp217
-rw-r--r--utils/cec-follower/cec-processing.cpp39
2 files changed, 253 insertions, 3 deletions
diff --git a/utils/cec-compliance/cec-test.cpp b/utils/cec-compliance/cec-test.cpp
index 2ff6b6bd..a6058882 100644
--- a/utils/cec-compliance/cec-test.cpp
+++ b/utils/cec-compliance/cec-test.cpp
@@ -583,9 +583,10 @@ static int deck_ctl_give_status(struct node *node, unsigned me, unsigned la, boo
cec_msg_give_deck_status(&msg, true, CEC_OP_STATUS_REQ_ONCE);
fail_on_test(!transmit_timeout(node, &msg));
fail_on_test(timed_out(&msg));
- fail_on_test_v2(node->remote[la].cec_version, node->remote[la].has_deck_ctl &&
- cec_msg_status_is_abort(&msg));
- fail_on_test_v2(node->remote[la].cec_version, !node->remote[la].has_deck_ctl);
+ fail_on_test_v2(node->remote[la].cec_version,
+ node->remote[la].has_deck_ctl && cec_msg_status_is_abort(&msg));
+ fail_on_test_v2(node->remote[la].cec_version,
+ !node->remote[la].has_deck_ctl && !unrecognized_op(&msg));
if (unrecognized_op(&msg))
return NOTSUPPORTED;
@@ -897,6 +898,213 @@ static struct remote_subtest one_touch_rec_subtests[] = {
};
+/* Timer Programming */
+
+/*
+ TODO: These are very rudimentary tests which should be expanded.
+ */
+
+static int timer_prog_set_analog_timer(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ /* TODO: Check the timer status for possible errors, etc. */
+
+ struct cec_msg msg = {};
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_set_analogue_timer(&msg, true, 1, 1, 0, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY,
+ CEC_OP_ANA_BCAST_TYPE_CABLE,
+ 7668, // 479.25 MHz
+ node->remote[la].bcast_sys);
+ fail_on_test(!transmit_timeout(node, &msg, 10000));
+ if (timed_out(&msg)) {
+ warn("Timed out waiting for Timer Status. Assuming timer was set.\n");
+ return PRESUMED_OK;
+ }
+ if (unrecognized_op(&msg))
+ return NOTSUPPORTED;
+ if (cec_msg_status_is_abort(&msg))
+ return PRESUMED_OK;
+
+ return 0;
+}
+
+static int timer_prog_set_digital_timer(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ /* TODO: Check the timer status for possible errors, etc. */
+
+ struct cec_msg msg = {};
+ struct cec_op_digital_service_id digital_service_id = {};
+
+ digital_service_id.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL;
+ digital_service_id.channel.channel_number_fmt = CEC_OP_CHANNEL_NUMBER_FMT_1_PART;
+ digital_service_id.channel.minor = 1;
+ digital_service_id.dig_bcast_system = node->remote[la].dig_bcast_sys;
+ cec_msg_init(&msg, me, la);
+ cec_msg_set_digital_timer(&msg, true, 1, 1, 0, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY,
+ &digital_service_id);
+ fail_on_test(!transmit_timeout(node, &msg, 10000));
+ if (timed_out(&msg)) {
+ warn("Timed out waiting for Timer Status. Assuming timer was set.\n");
+ return PRESUMED_OK;
+ }
+ if (unrecognized_op(&msg))
+ return NOTSUPPORTED;
+ if (cec_msg_status_is_abort(&msg))
+ return PRESUMED_OK;
+
+ return 0;
+}
+
+static int timer_prog_set_ext_timer(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ /* TODO: Check the timer status. */
+
+ struct cec_msg msg = {};
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_set_ext_timer(&msg, true, 1, 1, 0, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY,
+ CEC_OP_EXT_SRC_PHYS_ADDR, 0, node->phys_addr);
+ fail_on_test(!transmit_timeout(node, &msg, 10000));
+ if (timed_out(&msg)) {
+ warn("Timed out waiting for Timer Status. Assuming timer was set.\n");
+ return PRESUMED_OK;
+ }
+ if (unrecognized_op(&msg))
+ return NOTSUPPORTED;
+ if (cec_msg_status_is_abort(&msg))
+ return PRESUMED_OK;
+
+ return 0;
+}
+
+static int timer_prog_clear_analog_timer(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ /* TODO: Check the timer cleared status. */
+
+ struct cec_msg msg = {};
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_clear_analogue_timer(&msg, true, 1, 1, 0, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY,
+ CEC_OP_ANA_BCAST_TYPE_CABLE,
+ 7668, // 479.25 MHz
+ node->remote[la].bcast_sys);
+ fail_on_test(!transmit_timeout(node, &msg, 10000));
+ if (timed_out(&msg)) {
+ warn("Timed out waiting for Timer Cleared Status. Assuming timer was cleared.\n");
+ return PRESUMED_OK;
+ }
+ if (unrecognized_op(&msg))
+ return NOTSUPPORTED;
+ if (cec_msg_status_is_abort(&msg))
+ return PRESUMED_OK;
+
+ return 0;
+}
+
+static int timer_prog_clear_digital_timer(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ /* TODO: Check the timer cleared status. */
+
+ struct cec_msg msg = {};
+ struct cec_op_digital_service_id digital_service_id = {};
+
+ digital_service_id.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL;
+ digital_service_id.channel.channel_number_fmt = CEC_OP_CHANNEL_NUMBER_FMT_1_PART;
+ digital_service_id.channel.minor = 1;
+ digital_service_id.dig_bcast_system = node->remote[la].dig_bcast_sys;
+ cec_msg_init(&msg, me, la);
+ cec_msg_clear_digital_timer(&msg, true, 1, 1, 0, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY,
+ &digital_service_id);
+ fail_on_test(!transmit_timeout(node, &msg, 10000));
+ if (timed_out(&msg)) {
+ warn("Timed out waiting for Timer Cleared Status. Assuming timer was cleared.\n");
+ return PRESUMED_OK;
+ }
+ if (unrecognized_op(&msg))
+ return NOTSUPPORTED;
+ if (cec_msg_status_is_abort(&msg))
+ return PRESUMED_OK;
+
+ return 0;
+}
+
+static int timer_prog_clear_ext_timer(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ /* TODO: Check the timer cleared status. */
+
+ struct cec_msg msg = {};
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_clear_ext_timer(&msg, true, 1, 1, 0, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY,
+ CEC_OP_EXT_SRC_PHYS_ADDR, 0, node->phys_addr);
+ fail_on_test(!transmit_timeout(node, &msg, 10000));
+ if (timed_out(&msg)) {
+ warn("Timed out waiting for Timer Cleared Status. Assuming timer was cleared.\n");
+ return PRESUMED_OK;
+ }
+ if (unrecognized_op(&msg))
+ return NOTSUPPORTED;
+ if (cec_msg_status_is_abort(&msg))
+ return PRESUMED_OK;
+
+ return 0;
+}
+
+static int timer_prog_set_prog_title(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ struct cec_msg msg = {};
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_set_timer_program_title(&msg, "Super-Hans II");
+ fail_on_test(!transmit_timeout(node, &msg));
+ if (unrecognized_op(&msg))
+ return NOTSUPPORTED;
+
+ return PRESUMED_OK;
+}
+
+static int timer_prog_timer_status(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ struct cec_msg msg = {};
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_timer_status(&msg, CEC_OP_TIMER_OVERLAP_WARNING_NO_OVERLAP,
+ CEC_OP_MEDIA_INFO_NO_MEDIA,
+ CEC_OP_PROG_INFO_ENOUGH_SPACE,
+ 0, 0, 0);
+ fail_on_test(!transmit_timeout(node, &msg));
+ if (unrecognized_op(&msg))
+ return NOTSUPPORTED;
+
+ return PRESUMED_OK;
+}
+
+static int timer_prog_timer_clear_status(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ struct cec_msg msg = {};
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_timer_cleared_status(&msg, CEC_OP_TIMER_CLR_STAT_CLEARED);
+ fail_on_test(!transmit_timeout(node, &msg));
+ if (unrecognized_op(&msg))
+ return NOTSUPPORTED;
+
+ return PRESUMED_OK;
+}
+
+static struct remote_subtest timer_prog_subtests[] = {
+ { "Set Analogue Timer", CEC_LOG_ADDR_MASK_RECORD, timer_prog_set_analog_timer },
+ { "Set Digital Timer", CEC_LOG_ADDR_MASK_RECORD, timer_prog_set_digital_timer },
+ { "Set Timer Program Title", CEC_LOG_ADDR_MASK_RECORD, timer_prog_set_prog_title },
+ { "Set External Timer", CEC_LOG_ADDR_MASK_RECORD, timer_prog_set_ext_timer },
+ { "Clear Analogue Timer", CEC_LOG_ADDR_MASK_RECORD, timer_prog_clear_analog_timer },
+ { "Clear Digital Timer", CEC_LOG_ADDR_MASK_RECORD, timer_prog_clear_digital_timer },
+ { "Clear External Timer", CEC_LOG_ADDR_MASK_RECORD, timer_prog_clear_ext_timer },
+ { "Timer Status", CEC_LOG_ADDR_MASK_RECORD, timer_prog_timer_status },
+ { "Timer Cleared Status", CEC_LOG_ADDR_MASK_RECORD, timer_prog_timer_clear_status },
+};
+
+
/* Post-test checks */
static int post_test_check_recognized(struct node *node, unsigned me, unsigned la, bool interactive)
@@ -954,6 +1162,9 @@ static struct remote_test tests[] = {
test_case("One Touch Record feature",
TAG_ONE_TOUCH_RECORD,
one_touch_rec_subtests),
+ test_case("Timer Progrmaming feature",
+ TAG_TIMER_PROGRAMMING,
+ timer_prog_subtests),
test_case_ext("Dynamic Auto Lipsync feature",
TAG_DYNAMIC_AUTO_LIPSYNC,
dal_subtests),
diff --git a/utils/cec-follower/cec-processing.cpp b/utils/cec-follower/cec-processing.cpp
index c5b9d837..5588e6bf 100644
--- a/utils/cec-follower/cec-processing.cpp
+++ b/utils/cec-follower/cec-processing.cpp
@@ -614,6 +614,45 @@ static void processMsg(struct node *node, struct cec_msg &msg, unsigned me)
return;
+ /*
+ Timer Programming
+
+ This is only a basic implementation.
+
+ TODO/Ideas:
+ - Act like an actual recording device; keep track of recording
+ schedule and act correctly when colliding timers are set.
+ - Emulate a finite storage space for recordings
+ */
+
+ case CEC_MSG_SET_ANALOGUE_TIMER:
+ case CEC_MSG_SET_DIGITAL_TIMER:
+ case CEC_MSG_SET_EXT_TIMER:
+ if (!cec_has_record(1 << me))
+ break;
+ cec_msg_set_reply_to(&msg, &msg);
+ cec_msg_timer_status(&msg, CEC_OP_TIMER_OVERLAP_WARNING_NO_OVERLAP,
+ CEC_OP_MEDIA_INFO_NO_MEDIA,
+ CEC_OP_PROG_INFO_ENOUGH_SPACE, 0, 0, 0);
+ transmit(node, &msg);
+ return;
+ case CEC_MSG_CLEAR_ANALOGUE_TIMER:
+ case CEC_MSG_CLEAR_DIGITAL_TIMER:
+ case CEC_MSG_CLEAR_EXT_TIMER:
+ if (!cec_has_record(1 << me))
+ break;
+ cec_msg_set_reply_to(&msg, &msg);
+ cec_msg_timer_cleared_status(&msg, CEC_OP_TIMER_CLR_STAT_CLEARED);
+ transmit(node, &msg);
+ return;
+ case CEC_MSG_SET_TIMER_PROGRAM_TITLE:
+ if (!cec_has_record(1 << me))
+ break;
+ return;
+ case CEC_MSG_TIMER_CLEARED_STATUS:
+ case CEC_MSG_TIMER_STATUS:
+ return;
+
/* Dynamic Auto Lipsync */
case CEC_MSG_REQUEST_CURRENT_LATENCY: {

Privacy Policy