@@ -677,6 +677,66 @@ static int standby_resume_wakeup_deck_play(struct node *node, unsigned me, unsig
return standby_resume_wakeup_deck(node, me, la, interactive, CEC_OP_PLAY_MODE_PLAY_FWD);
}
+static int standby_record(struct node *node, unsigned me, unsigned la, bool interactive, bool active_source)
+{
+ struct cec_msg msg;
+ __u8 rec_status;
+ unsigned unresponsive_time = 0;
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_record_on_own(&msg);
+ msg.reply = CEC_MSG_RECORD_STATUS;
+ fail_on_test(!transmit_timeout(node, &msg, 10000));
+ if (timed_out_or_abort(&msg))
+ return OK_NOT_SUPPORTED;
+ cec_ops_record_status(&msg, &rec_status);
+ fail_on_test(rec_status != CEC_OP_RECORD_STATUS_CUR_SRC &&
+ rec_status != CEC_OP_RECORD_STATUS_ALREADY_RECORDING);
+
+ cec_msg_init(&msg, me, la);
+ if (active_source)
+ cec_msg_active_source(&msg, node->remote[la].phys_addr);
+ else
+ cec_msg_active_source(&msg, me);
+ fail_on_test(!transmit_timeout(node, &msg));
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_standby(&msg);
+ fail_on_test(!transmit_timeout(node, &msg));
+ /* Standby should not interrupt the recording. */
+ fail_on_test(!poll_stable_power_status(node, me, la, CEC_OP_POWER_STATUS_ON, unresponsive_time));
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_record_off(&msg, false);
+ fail_on_test(!transmit_timeout(node, &msg));
+
+ /* When the recording stops, recorder should standby unless it is the active source. */
+ if (active_source) {
+ fail_on_test(!poll_stable_power_status(node, me, la, CEC_OP_POWER_STATUS_ON, unresponsive_time));
+ } else {
+ fail_on_test(!poll_stable_power_status(node, me, la, CEC_OP_POWER_STATUS_STANDBY, unresponsive_time));
+ fail_on_test(interactive && !question("Is the device in standby?"));
+ node->remote[la].in_standby = true;
+
+ int ret = standby_resume_wakeup(node, me, la, interactive);
+ if (ret)
+ return ret;
+ node->remote[la].in_standby = false;
+ }
+
+ return OK;
+}
+
+static int standby_record_active_source(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ return standby_record(node, me, la, interactive, true);
+}
+
+static int standby_record_inactive_source(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ return standby_record(node, me, la, interactive, false);
+}
+
const vec_remote_subtests standby_resume_subtests{
{ "Standby", CEC_LOG_ADDR_MASK_ALL, standby_resume_standby },
{ "Repeated Standby message does not wake up", CEC_LOG_ADDR_MASK_ALL, standby_resume_standby_toggle },
@@ -697,4 +757,6 @@ const vec_remote_subtests standby_resume_subtests{
{ "Power State Transitions", CEC_LOG_ADDR_MASK_TV, power_state_transitions, false, true },
{ "Deck Eject Standby Resume", CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD, standby_resume_wakeup_deck_eject },
{ "Deck Play Standby Resume", CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD, standby_resume_wakeup_deck_play },
+ { "Record Standby Active Source", CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP, standby_record_active_source },
+ { "Record Standby Inactive Source", CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP, standby_record_inactive_source },
};
@@ -318,6 +318,7 @@ void state_init(struct node &node)
node.state.deck_state = CEC_OP_DECK_INFO_STOP;
node.state.deck_skip_start = 0;
node.state.one_touch_record_on = false;
+ node.state.record_received_standby = false;
tuner_dev_info_init(&node.state);
node.state.last_aud_rate_rx_ts = 0;
}
@@ -54,6 +54,7 @@ struct state {
__u8 deck_state;
__u64 deck_skip_start;
bool one_touch_record_on;
+ bool record_received_standby;
time_t toggle_power_status;
__u64 last_aud_rate_rx_ts;
};
@@ -230,5 +231,6 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
void reply_feature_abort(struct node *node, struct cec_msg *msg,
__u8 reason = CEC_OP_ABORT_UNRECOGNIZED_OP);
void testProcessing(struct node *node, bool wallclock);
+bool enter_standby(struct node *node);
#endif
@@ -146,6 +146,9 @@ void reply_feature_abort(struct node *node, struct cec_msg *msg, __u8 reason)
static bool exit_standby(struct node *node)
{
+ /* Cancel any standby request that was pending. */
+ node->state.record_received_standby = false;
+
if (node->state.power_status == CEC_OP_POWER_STATUS_STANDBY ||
node->state.power_status == CEC_OP_POWER_STATUS_TO_STANDBY) {
node->state.old_power_status = node->state.power_status;
@@ -157,14 +160,23 @@ static bool exit_standby(struct node *node)
return false;
}
-static bool enter_standby(struct node *node)
+bool enter_standby(struct node *node)
{
if (node->state.power_status == CEC_OP_POWER_STATUS_ON ||
node->state.power_status == CEC_OP_POWER_STATUS_TO_ON) {
+ /*
+ * Standby should not interrupt a recording in progress, but
+ * remember to go to standby once the recording is finished.
+ */
+ if (node->state.one_touch_record_on) {
+ node->state.record_received_standby = true;
+ return false;
+ }
node->state.old_power_status = node->state.power_status;
node->state.power_status = CEC_OP_POWER_STATUS_STANDBY;
node->state.power_status_changed_time = time(nullptr);
node->state.deck_skip_start = 0;
+ node->state.record_received_standby = false;
dev_info("Changing state to standby\n");
return true;
}
@@ -724,6 +724,15 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
cec_msg_record_status(&msg, CEC_OP_RECORD_STATUS_TERMINATED_OK);
transmit(node, &msg);
node->state.one_touch_record_on = false;
+ /*
+ * If standby was received during recording, enter standby when the
+ * recording is finished unless recording device is the active source.
+ */
+ if (node->state.record_received_standby) {
+ if (node->phys_addr != node->state.active_source_pa)
+ enter_standby(node);
+ node->state.record_received_standby = false;
+ }
return;
case CEC_MSG_RECORD_STATUS:
return;
Check that the recording device ignores a Standby message while it is recording. When the recording is finished, check that the recording device enters standby unless the recording device is the active source. Signed-off-by: Deborah Brouwer <deborahbrouwer3563@gmail.com> --- utils/cec-compliance/cec-test-power.cpp | 62 +++++++++++++++++++++++++ utils/cec-follower/cec-follower.cpp | 1 + utils/cec-follower/cec-follower.h | 2 + utils/cec-follower/cec-processing.cpp | 14 +++++- utils/cec-follower/cec-tuner.cpp | 9 ++++ 5 files changed, 87 insertions(+), 1 deletion(-)