@@ -677,6 +677,67 @@ 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, __u8 opcode)
+{
+ struct cec_msg msg;
+ __u8 rec_status;
+
+ 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);
+ cec_msg_standby(&msg);
+ fail_on_test(!transmit_timeout(node, &msg));
+ /* Standby should not interrupt the recording. */
+ fail_on_test(!cec_msg_status_is_abort(&msg));
+
+ /* When the recording stops, the recorder should standby unless the recorder is the active source */
+ cec_msg_init(&msg, me, la);
+ if (opcode == CEC_MSG_ACTIVE_SOURCE)
+ cec_msg_active_source(&msg, node->remote[la].phys_addr);
+ else
+ cec_msg_active_source(&msg, node->remote[la].phys_addr + 1);
+ fail_on_test(!transmit_timeout(node, &msg));
+
+ cec_msg_init(&msg, me, la);
+ cec_msg_record_off(&msg, false);
+ fail_on_test(!transmit_timeout(node, &msg));
+
+ unsigned unresponsive_time = 0;
+
+ if (opcode == CEC_MSG_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, CEC_MSG_ACTIVE_SOURCE);
+}
+
+static int standby_record_inactive_source(struct node *node, unsigned me, unsigned la, bool interactive)
+{
+ return standby_record(node, me, la, interactive, CEC_MSG_INACTIVE_SOURCE);
+}
+
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 +758,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 },
};
@@ -317,6 +317,7 @@ void state_init(struct node &node)
node.state.deck_report_changes_to = 0;
node.state.deck_state = CEC_OP_DECK_INFO_STOP;
node.state.deck_skip_start = 0;
+ node.state.one_touch_record_standby = false;
node.state.one_touch_record_on = false;
tuner_dev_info_init(&node.state);
node.state.last_aud_rate_rx_ts = 0;
@@ -53,6 +53,7 @@ struct state {
__u8 deck_report_changes_to;
__u8 deck_state;
__u64 deck_skip_start;
+ bool one_touch_record_standby;
bool one_touch_record_on;
time_t toggle_power_status;
__u64 last_aud_rate_rx_ts;
@@ -229,5 +230,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
@@ -157,7 +157,7 @@ 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) {
@@ -320,6 +320,11 @@ static void processMsg(struct node *node, struct cec_msg &msg, unsigned me, __u8
/* Standby */
case CEC_MSG_STANDBY:
+ /* Standby should not interrupt a recording in progress. */
+ if (node->state.one_touch_record_on) {
+ node->state.one_touch_record_standby = true;
+ break;
+ }
enter_standby(node);
return;
@@ -708,6 +708,15 @@ void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, uns
cec_msg_set_reply_to(&msg, &msg);
cec_msg_record_status(&msg, CEC_OP_RECORD_STATUS_TERMINATED_OK);
transmit(node, &msg);
+ /*
+ * If standby was received during recording, enter standby when the recording is finished
+ * unless the recording device is the currently the active source.
+ */
+ if (node->state.one_touch_record_standby) {
+ if (node->phys_addr != node->state.active_source_pa)
+ enter_standby(node);
+ node->state.one_touch_record_standby = false;
+ }
node->state.one_touch_record_on = false;
return;
case CEC_MSG_RECORD_STATUS:
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 | 63 +++++++++++++++++++++++++ utils/cec-follower/cec-follower.cpp | 1 + utils/cec-follower/cec-follower.h | 2 + utils/cec-follower/cec-processing.cpp | 7 ++- utils/cec-follower/cec-tuner.cpp | 9 ++++ 5 files changed, 81 insertions(+), 1 deletion(-)