Re: [PATCH v6 2/3] cec: add tests for Deck Play message

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Deb,

Some more (small) comments:

On 11/06/2021 01:58, Deborah Brouwer wrote:
> Send all Deck Play commands and check that the follower implements them.
> Test that the follower returns Feature Abort for invalid Play operands.
> 
> Signed-off-by: Deborah Brouwer <deborahbrouwer3563@xxxxxxxxx>
> ---
>  utils/cec-compliance/cec-test.cpp     | 100 +++++++++++++++++++++++---
>  utils/cec-follower/cec-processing.cpp |  70 +++++++++++++++++-
>  2 files changed, 156 insertions(+), 14 deletions(-)
> 
> diff --git a/utils/cec-compliance/cec-test.cpp b/utils/cec-compliance/cec-test.cpp
> index 83be6b73..f2ec4e90 100644
> --- a/utils/cec-compliance/cec-test.cpp
> +++ b/utils/cec-compliance/cec-test.cpp
> @@ -33,6 +33,20 @@ static int deck_status_get(struct node *node, unsigned me, unsigned la, __u8 &de
>  	return OK;
>  }
>  
> +static int test_play_mode(struct node *node, unsigned me, unsigned la, __u8 play_mode, __u8 expected)
> +{
> +	struct cec_msg msg = {};
> +	__u8 deck_status;
> +
> +	cec_msg_init(&msg, me, la);
> +	cec_msg_play(&msg, play_mode);
> +	fail_on_test(!transmit_timeout(node, &msg));
> +	fail_on_test(cec_msg_status_is_abort(&msg)); /* Assumes deck has media. */
> +	fail_on_test(deck_status_get(node, me, la, deck_status));
> +	fail_on_test(deck_status != expected);
> +
> +	return OK;
> +}
>  
>  /* System Information */
>  
> @@ -793,24 +807,79 @@ static int deck_ctl_deck_ctl_invalid(struct node *node, unsigned me, unsigned la
>  static int deck_ctl_play(struct node *node, unsigned me, unsigned la, bool interactive)
>  {
>  	struct cec_msg msg = {};
> +	__u8 deck_status;
>  
>  	cec_msg_init(&msg, me, la);
> -	cec_msg_play(&msg, CEC_OP_PLAY_MODE_PLAY_STILL);
> +	cec_msg_play(&msg, CEC_OP_PLAY_MODE_PLAY_FWD);
>  	fail_on_test(!transmit_timeout(node, &msg));
> -	if (is_playback_or_rec(la)) {
> -		fail_on_test_v2(node->remote[la].cec_version,
> -				node->remote[la].has_deck_ctl && unrecognized_op(&msg));
> -		fail_on_test_v2(node->remote[la].cec_version,
> -				!node->remote[la].has_deck_ctl && !unrecognized_op(&msg));
> -	}
> +	fail_on_test_v2(node->remote[la].cec_version,
> +	                node->remote[la].has_deck_ctl && unrecognized_op(&msg));
> +	fail_on_test_v2(node->remote[la].cec_version,
> +	                !node->remote[la].has_deck_ctl && !unrecognized_op(&msg));
>  	if (unrecognized_op(&msg))
>  		return OK_NOT_SUPPORTED;
>  	if (refused(&msg))
>  		return OK_REFUSED;
> -	if (cec_msg_status_is_abort(&msg))
> -		return OK_PRESUMED;
> +	fail_on_test(deck_status_get(node, me, la, deck_status));
> +	if (cec_msg_status_is_abort(&msg)) {
> +		if (incorrect_mode(&msg)) {
> +			if (deck_status == CEC_OP_DECK_INFO_NO_MEDIA)
> +				info("Play Still: no media.\n");
> +			else
> +				warn("Deck has media but returned Feature Abort with Incorrect Mode.");
> +			return OK;
> +		}
> +		return FAIL;

Do the same reordering as I suggested in the previous patch.

> +	}
> +	fail_on_test(deck_status != CEC_OP_DECK_INFO_PLAY);
>  
> -	return OK_PRESUMED;
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_STILL, CEC_OP_DECK_INFO_STILL));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_REV, CEC_OP_DECK_INFO_PLAY_REV));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MIN, CEC_OP_DECK_INFO_FAST_FWD));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_FAST_REV_MIN, CEC_OP_DECK_INFO_FAST_REV));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MED, CEC_OP_DECK_INFO_FAST_FWD));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_FAST_REV_MED, CEC_OP_DECK_INFO_FAST_REV));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MAX, CEC_OP_DECK_INFO_FAST_FWD));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_FAST_REV_MAX, CEC_OP_DECK_INFO_FAST_REV));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MIN, CEC_OP_DECK_INFO_SLOW));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MIN, CEC_OP_DECK_INFO_SLOW_REV));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MED, CEC_OP_DECK_INFO_SLOW));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MED, CEC_OP_DECK_INFO_SLOW_REV));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MAX, CEC_OP_DECK_INFO_SLOW));
> +	fail_on_test(test_play_mode(node, me, la, CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MAX, CEC_OP_DECK_INFO_SLOW_REV));
> +
> +	cec_msg_init(&msg, me, la);
> +	cec_msg_deck_control(&msg, CEC_OP_DECK_CTL_MODE_STOP);
> +	fail_on_test(!transmit_timeout(node, &msg));
> +
> +	return OK;
> +}
> +
> +static int deck_ctl_play_invalid(struct node *node, unsigned me, unsigned la, bool interactive)
> +{
> +	struct cec_msg msg = {};
> +
> +	cec_msg_init(&msg, me, la);
> +	cec_msg_play(&msg, 4); /* Invalid Operand */
> +	fail_on_test(!transmit_timeout(node, &msg));
> +	if (unrecognized_op(&msg))
> +		return OK_NOT_SUPPORTED;
> +	fail_on_test(!cec_msg_status_is_abort(&msg));
> +	fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
> +
> +	cec_msg_init(&msg, me, la);
> +	cec_msg_play(&msg, 8); /* Invalid Operand */

I think it would be more useful to test with 0 instead of 8.

I did consider testing for both, but I think that is a bit overkill.

> +	fail_on_test(!transmit_timeout(node, &msg));
> +	fail_on_test(!cec_msg_status_is_abort(&msg));
> +	fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
> +
> +	cec_msg_init(&msg, me, la);
> +	cec_msg_play(&msg, 0x26); /* Invalid Operand */
> +	fail_on_test(!transmit_timeout(node, &msg));
> +	fail_on_test(!cec_msg_status_is_abort(&msg));
> +	fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
> +
> +	return OK;
>  }
>  
>  static const vec_remote_subtests deck_ctl_subtests{
> @@ -825,7 +894,6 @@ static const vec_remote_subtests deck_ctl_subtests{
>  		deck_ctl_give_status_invalid,
>  	},
>  	{ "Deck Status", CEC_LOG_ADDR_MASK_ALL, deck_ctl_deck_status },
> -	{ "Play", CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD, deck_ctl_play },
>  	{
>  		"Deck Control",
>  		CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD,
> @@ -836,6 +904,16 @@ static const vec_remote_subtests deck_ctl_subtests{
>  		CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD,
>  		deck_ctl_deck_ctl_invalid,
>  	},
> +	{
> +		"Play",
> +		CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD,
> +		deck_ctl_play,
> +	},
> +	{
> +		"Play Invalid Operand",
> +		CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD,
> +		deck_ctl_play_invalid,
> +	},
>  };
>  
>  /* Tuner Control */
> diff --git a/utils/cec-follower/cec-processing.cpp b/utils/cec-follower/cec-processing.cpp
> index 4c7ba1d4..e58df85f 100644
> --- a/utils/cec-follower/cec-processing.cpp
> +++ b/utils/cec-follower/cec-processing.cpp
> @@ -553,14 +553,78 @@ static void processMsg(struct node *node, struct cec_msg &msg, unsigned me)
>  			return;
>  		}
>  	case CEC_MSG_PLAY:
> -		if (node->has_deck_ctl)
> +		if (!node->has_deck_ctl)
> +			break;
> +
> +		__u8 deck_state;
> +		__u8 play_mode;
> +
> +		cec_ops_play(&msg, &play_mode);
> +
> +		switch (play_mode) {
> +		case CEC_OP_PLAY_MODE_PLAY_FWD:
> +			/* Play Forward will close tray if open. */
> +			deck_state = CEC_OP_DECK_INFO_PLAY;
> +			break;
> +		case CEC_OP_PLAY_MODE_PLAY_REV:
> +			if (node->state.deck_state == CEC_OP_DECK_INFO_NO_MEDIA) {
> +				reply_feature_abort(node, &msg, CEC_OP_ABORT_INCORRECT_MODE);
> +				return;
> +			}
> +			deck_state = CEC_OP_DECK_INFO_PLAY_REV;
> +			break;
> +		case CEC_OP_PLAY_MODE_PLAY_STILL:
> +			/* Play Still will close tray if open. */
> +			deck_state = CEC_OP_DECK_INFO_STILL;
> +			break;
> +		case CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MIN:
> +		case CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MED:
> +		case CEC_OP_PLAY_MODE_PLAY_FAST_FWD_MAX:
> +			if (node->state.deck_state == CEC_OP_DECK_INFO_NO_MEDIA) {
> +				reply_feature_abort(node, &msg, CEC_OP_ABORT_INCORRECT_MODE);
> +				return;
> +			}
> +			deck_state = CEC_OP_DECK_INFO_FAST_FWD;
> +			break;
> +		case CEC_OP_PLAY_MODE_PLAY_FAST_REV_MIN:
> +		case CEC_OP_PLAY_MODE_PLAY_FAST_REV_MED:
> +		case CEC_OP_PLAY_MODE_PLAY_FAST_REV_MAX:
> +			if (node->state.deck_state == CEC_OP_DECK_INFO_NO_MEDIA) {
> +				reply_feature_abort(node, &msg, CEC_OP_ABORT_INCORRECT_MODE);
> +				return;
> +			}
> +			deck_state = CEC_OP_DECK_INFO_FAST_REV;
> +			break;
> +		case CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MIN:
> +		case CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MED:
> +		case CEC_OP_PLAY_MODE_PLAY_SLOW_FWD_MAX:
> +			if (node->state.deck_state == CEC_OP_DECK_INFO_NO_MEDIA) {
> +				reply_feature_abort(node, &msg, CEC_OP_ABORT_INCORRECT_MODE);
> +				return;
> +			}
> +			deck_state = CEC_OP_DECK_INFO_SLOW;
> +			break;
> +		case CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MIN:
> +		case CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MED:
> +		case CEC_OP_PLAY_MODE_PLAY_SLOW_REV_MAX:
> +			if (node->state.deck_state == CEC_OP_DECK_INFO_NO_MEDIA) {
> +				reply_feature_abort(node, &msg, CEC_OP_ABORT_INCORRECT_MODE);
> +				return;
> +			}
> +			deck_state = CEC_OP_DECK_INFO_SLOW_REV;
> +			break;
> +		default:
> +			cec_msg_reply_feature_abort(&msg, CEC_OP_ABORT_INVALID_OP);
> +			transmit(node, &msg);
>  			return;
> -		break;
> +		}

The NO_MEDIA checks are repeated several times in the switch above. I think that it
is better to do this here:

		if (play_mode != CEC_OP_PLAY_MODE_PLAY_FWD &&
		    play_mode != CEC_OP_PLAY_MODE_PLAY_STILL &&
		    node->state.deck_state == CEC_OP_DECK_INFO_NO_MEDIA) {
			reply_feature_abort(node, &msg, CEC_OP_ABORT_INCORRECT_MODE);
			return;
		}

> +		node->state.deck_skip_start = 0;
> +		update_deck_state(node, deck_state);
> +		return;
>  	case CEC_MSG_DECK_CONTROL:
>  		if (!node->has_deck_ctl)
>  			break;
>  
> -		__u8 deck_state;
>  		__u8 deck_control_mode;
>  
>  		cec_ops_deck_control(&msg, &deck_control_mode);
> 

Regards,

	Hans



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux