1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
4  */
5 
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <inttypes.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <ctype.h>
15 #include <errno.h>
16 #include <sys/ioctl.h>
17 #include <config.h>
18 #include <cstdlib>
19 
20 #include "cec-compliance.h"
21 
22 
23 /* Dynamic Auto Lipsync */
24 
dal_request_current_latency(struct node * node,unsigned me,unsigned la,bool interactive)25 static int dal_request_current_latency(struct node *node, unsigned me, unsigned la, bool interactive)
26 {
27 	struct cec_msg msg = {};
28 
29 	cec_msg_init(&msg, me, la);
30 	cec_msg_request_current_latency(&msg, true, node->remote[la].phys_addr);
31 	fail_on_test(!transmit_timeout(node, &msg));
32 	fail_on_test_v2(node->remote[la].cec_version,
33 			timed_out(&msg) && is_tv(la, node->remote[la].prim_type));
34 	if (timed_out(&msg))
35 		return OK_NOT_SUPPORTED;
36 
37 	/* When the device supports Dynamic Auto Lipsync but does not implement
38 	   CEC 1.4b, or 2.0, a very strict subset of CEC can be supported. If we
39 	   get here and the version is < 1.4, we know that the device is not
40 	   complying to this specification. */
41 	if (node->remote[la].cec_version < CEC_OP_CEC_VERSION_1_4) {
42 		warn("CEC 2.0 specifies that devices with CEC version < 1.4 which implement\n");
43 		warn("Dynamic Auto Lipsync shall only implement a very strict subset of CEC.\n");
44 	}
45 
46 	uint16_t phys_addr;
47 	uint8_t video_latency, low_latency_mode, audio_out_compensated, audio_out_delay;
48 
49 	cec_ops_report_current_latency(&msg, &phys_addr, &video_latency, &low_latency_mode,
50 				       &audio_out_compensated, &audio_out_delay);
51 	fail_on_test(phys_addr != node->remote[la].phys_addr);
52 	info("Video latency: %d (%dms)\n", video_latency, (video_latency - 1) * 2);
53 	info("Low latency mode: %d\n", low_latency_mode);
54 	info("Audio output compensation: %d\n", audio_out_compensated);
55 	if (audio_out_compensated == CEC_OP_AUD_OUT_COMPENSATED_PARTIAL_DELAY) {
56 		info("Audio out delay: %d (%dms)\n", audio_out_delay, (audio_out_delay - 1) * 2);
57 		fail_on_test(audio_out_delay == 0 || audio_out_delay > 251);
58 		// Warn if the delay is more than 50 ms
59 		warn_on_test(audio_out_delay > (50 / 2) + 1);
60 	}
61 	fail_on_test(video_latency == 0 || video_latency > 251);
62 	// Warn if the delay is more than 50 ms and low latency mode is set
63 	if (video_latency > (50 / 2) + 1) {
64 		if (low_latency_mode)
65 			fail("Low latency mode is set, but video latency is > 50ms\n");
66 		else
67 			warn("Video latency is > 50ms\n");
68 	}
69 
70 	return 0;
71 }
72 
dal_req_current_latency_invalid(struct node * node,unsigned me,unsigned la,bool interactive)73 static int dal_req_current_latency_invalid(struct node *node, unsigned me, unsigned la, bool interactive)
74 {
75 	struct cec_msg msg = {};
76 
77 	/* Test that there is no reply when the physical address operand is not the
78 	   physical address of the remote device. */
79 	cec_msg_init(&msg, me, la);
80 	cec_msg_request_current_latency(&msg, true, CEC_PHYS_ADDR_INVALID);
81 	fail_on_test(!transmit_timeout(node, &msg));
82 	fail_on_test(!timed_out(&msg));
83 
84 	return 0;
85 }
86 
87 struct remote_subtest dal_subtests[] = {
88 	{ "Request Current Latency", CEC_LOG_ADDR_MASK_ALL, dal_request_current_latency },
89 	{ "Request Current Latency with invalid PA", CEC_LOG_ADDR_MASK_ALL, dal_req_current_latency_invalid },
90 };
91 
92 const unsigned dal_subtests_size = ARRAY_SIZE(dal_subtests);
93 
94 
95 /* Audio Return Channel Control */
96 
pa_common_mask(uint16_t pa1,uint16_t pa2)97 static uint16_t pa_common_mask(uint16_t pa1, uint16_t pa2)
98 {
99 	uint16_t mask = 0xf000;
100 
101 	for (int i = 0; i < 3; i++) {
102 		if ((pa1 & mask) != (pa2 & mask))
103 			break;
104 		mask = (mask >> 4) | 0xf000;
105 	}
106 	return mask << 4;
107 }
pa_are_adjacent(uint16_t pa1,uint16_t pa2)108 static bool pa_are_adjacent(uint16_t pa1, uint16_t pa2)
109 {
110 	const uint16_t mask = pa_common_mask(pa1, pa2);
111 	const uint16_t trail_mask = ((~mask) & 0xffff) >> 4;
112 
113 	if (pa1 == CEC_PHYS_ADDR_INVALID || pa2 == CEC_PHYS_ADDR_INVALID || pa1 == pa2)
114 		return false;
115 	if ((pa1 & trail_mask) || (pa2 & trail_mask))
116 		return false;
117 	return !((pa1 & ~mask) && (pa2 & ~mask));
118 }
119 
pa_is_upstream_from(uint16_t pa1,uint16_t pa2)120 static bool pa_is_upstream_from(uint16_t pa1, uint16_t pa2)
121 {
122 	const uint16_t mask = pa_common_mask(pa1, pa2);
123 
124 	if (pa1 == CEC_PHYS_ADDR_INVALID || pa2 == CEC_PHYS_ADDR_INVALID)
125 		return false;
126 	return !(pa1 & ~mask) && (pa2 & ~mask);
127 }
128 
arc_initiate_tx(struct node * node,unsigned me,unsigned la,bool interactive)129 static int arc_initiate_tx(struct node *node, unsigned me, unsigned la, bool interactive)
130 {
131 	/* Check if we are upstream from the device. If we are, then the device is
132 	   an HDMI source, which means that it is an ARC receiver, not a transmitter. */
133 	if (pa_is_upstream_from(node->phys_addr, node->remote[la].phys_addr))
134 		return NOTAPPLICABLE;
135 
136 	struct cec_msg msg = {};
137 
138 	/*
139 	 * Note that this is a special case: INITIATE_ARC can reply with two possible
140 	 * messages: CEC_MSG_REPORT_ARC_INITIATED or CEC_MSG_REPORT_ARC_TERMINATED.
141 	 * It's the only message that behaves like this.
142 	 */
143 	cec_msg_init(&msg, me, la);
144 	cec_msg_initiate_arc(&msg, true);
145 	fail_on_test(!transmit_timeout(node, &msg));
146 	if (timed_out(&msg)) {
147 		fail_on_test_v2(node->remote[la].cec_version, node->remote[la].sink_has_arc_tx);
148 		warn("Timed out waiting for Report ARC Initiated/Terminated.\n");
149 		return OK_PRESUMED;
150 	}
151 	if (unrecognized_op(&msg)) {
152 		fail_on_test_v2(node->remote[la].cec_version, node->remote[la].sink_has_arc_tx);
153 		return OK_NOT_SUPPORTED;
154 	}
155 	if (cec_msg_opcode(&msg) == CEC_MSG_REPORT_ARC_INITIATED) {
156 		fail_on_test(!pa_are_adjacent(node->phys_addr, node->remote[la].phys_addr));
157 		fail_on_test_v2(node->remote[la].cec_version, !node->remote[la].sink_has_arc_tx);
158 		node->remote[la].arc_initiated = true;
159 	}
160 	else if (cec_msg_opcode(&msg) == CEC_MSG_REPORT_ARC_TERMINATED)
161 		announce("Device supports ARC but is not ready to initiate.");
162 	else if (refused(&msg))
163 		return OK_REFUSED;
164 	else if (cec_msg_status_is_abort(&msg))
165 		return OK_PRESUMED;
166 
167 	return 0;
168 }
169 
arc_terminate_tx(struct node * node,unsigned me,unsigned la,bool interactive)170 static int arc_terminate_tx(struct node *node, unsigned me, unsigned la, bool interactive)
171 {
172 	/* Check if we are upstream from the device. If we are, then the device is
173 	   an HDMI source, which means that it is an ARC receiver, not a transmitter. */
174 	if (pa_is_upstream_from(node->phys_addr, node->remote[la].phys_addr))
175 		return NOTAPPLICABLE;
176 	if (!node->remote[la].arc_initiated)
177 		return NOTAPPLICABLE;
178 
179 	struct cec_msg msg = {};
180 
181 	cec_msg_init(&msg, me, la);
182 	cec_msg_terminate_arc(&msg, true);
183 	fail_on_test(!transmit_timeout(node, &msg));
184 	if (timed_out(&msg)) {
185 		warn("Timed out waiting for Report ARC Terminated.\n");
186 		return OK_PRESUMED;
187 	}
188 	fail_on_test(unrecognized_op(&msg));
189 	if (cec_msg_status_is_abort(&msg)) {
190 		warn("Received Feature Abort for Terminate ARC (but the message was recognized).\n");
191 		if (refused(&msg))
192 			return OK_REFUSED;
193 		return OK_PRESUMED;
194 	}
195 
196 	return 0;
197 }
198 
arc_initiate_rx(struct node * node,unsigned me,unsigned la,bool interactive)199 static int arc_initiate_rx(struct node *node, unsigned me, unsigned la, bool interactive)
200 {
201 	/* Check if the DUT is upstream from us. If it is, then it is an
202 	   HDMI sink, which means that it is an ARC transmitter, not receiver. */
203 	if (pa_is_upstream_from(node->remote[la].phys_addr, node->phys_addr))
204 		return NOTAPPLICABLE;
205 
206 	struct cec_msg msg = {};
207 
208 	cec_msg_init(&msg, me, la);
209 	cec_msg_request_arc_initiation(&msg, true);
210 
211 	bool unsupported = false;
212 
213 	fail_on_test(!transmit_timeout(node, &msg));
214 	if (timed_out(&msg) || unrecognized_op(&msg))
215 		unsupported = true;
216 	else if (cec_msg_status_is_abort(&msg)) {
217 		uint8_t abort_msg, reason;
218 
219 		cec_ops_feature_abort(&msg, &abort_msg, &reason);
220 		if (reason == CEC_OP_ABORT_INCORRECT_MODE) {
221 			announce("The device supports ARC but is not ready to initiate.");
222 			return 0;
223 		}
224 
225 		warn("Device responded Feature Abort with unexpected abort reason. Assuming no ARC support.\n");
226 		unsupported = true;
227 	}
228 
229 	if (unsupported) {
230 		fail_on_test_v2(node->remote[la].cec_version, node->remote[la].source_has_arc_rx);
231 		return OK_NOT_SUPPORTED;
232 	}
233 	fail_on_test(!pa_are_adjacent(node->phys_addr, node->remote[la].phys_addr));
234 	fail_on_test_v2(node->remote[la].cec_version, !node->remote[la].source_has_arc_rx);
235 
236 	cec_msg_init(&msg, me, la);
237 	cec_msg_report_arc_initiated(&msg);
238 	fail_on_test(!transmit_timeout(node, &msg));
239 	fail_on_test(unrecognized_op(&msg));
240 	node->remote[la].arc_initiated = true;
241 
242 	return 0;
243 }
244 
arc_terminate_rx(struct node * node,unsigned me,unsigned la,bool interactive)245 static int arc_terminate_rx(struct node *node, unsigned me, unsigned la, bool interactive)
246 {
247 	/* Check if the DUT is upstream from us. If it is, then it is an
248 	   HDMI sink, which means that it is an ARC transmitter, not receiver. */
249 	if (pa_is_upstream_from(node->remote[la].phys_addr, node->phys_addr))
250 		return NOTAPPLICABLE;
251 	if (!node->remote[la].arc_initiated)
252 		return NOTAPPLICABLE;
253 
254 	struct cec_msg msg = {};
255 
256 	cec_msg_init(&msg, me, la);
257 	cec_msg_request_arc_termination(&msg, true);
258 	fail_on_test(!transmit_timeout(node, &msg));
259 	if (timed_out(&msg)) {
260 		warn("Timed out waiting for Terminate ARC.\n");
261 		return OK_PRESUMED;
262 	}
263 	fail_on_test(unrecognized_op(&msg));
264 	if (cec_msg_status_is_abort(&msg)) {
265 		warn("Received Feature Abort for Request ARC Termination (but the message was recognized).\n");
266 		if (refused(&msg))
267 			return OK_REFUSED;
268 		return OK_PRESUMED;
269 	}
270 
271 	cec_msg_init(&msg, me, la);
272 	cec_msg_report_arc_terminated(&msg);
273 	fail_on_test(!transmit_timeout(node, &msg));
274 	fail_on_test(unrecognized_op(&msg));
275 
276 	return 0;
277 }
278 
279 struct remote_subtest arc_subtests[] = {
280 	{ "Initiate ARC (RX)", CEC_LOG_ADDR_MASK_ALL, arc_initiate_rx },
281 	{ "Terminate ARC (RX)", CEC_LOG_ADDR_MASK_ALL, arc_terminate_rx },
282 	{ "Initiate ARC (TX)", CEC_LOG_ADDR_MASK_ALL, arc_initiate_tx },
283 	{ "Terminate ARC (TX)", CEC_LOG_ADDR_MASK_ALL, arc_terminate_tx },
284 };
285 
286 const unsigned arc_subtests_size = ARRAY_SIZE(arc_subtests);
287 
288 
289 /* System Audio Control */
290 
291 /*
292  * The following scenarios are defined in section 13.15 of the CEC 1.4
293  * specification.
294  *
295  * These are not tested as they need three CEC devices.  An amplifier
296  * provides the audio for a source that is being displayed on a TV.
297  *
298  * 1.  Amplifier initiated <System Audio Mode Request> and active source
299  *     discovery with a <Request Active Source> broadcast plus the
300  *     <Active Source> response.
301  * 2.  Post discovery, subsequent amplifier <Set System Audio Mode> [On]
302  *     and System Audio Control feature confirmation with TV.
303  * 3.  Amplifier broadcasts <Set System Audio Mode> [On] to mute the TV and
304  *     unmute amplifier.
305  * 4.  Amplifier broadcasts <Set System Audio Mode> [Off] to unmute the TV
306  *     and mute the amplifier.
307  * 5.  When System Audio Mode is On, muting and unmuting an amplifier sends
308  *     a <Report Audio Status> message to the TV.
309  * 6.  When System Audio Mode is On, the amplifier sends a <Set System Audio
310  *     Mode> [Off] to unmute the TV before going into standby.
311  * 7.  When System Audio Mode is On, only the amplifier can control system
312  *     volume.
313  *
314  * These are not tested as they are hard-to-test corner cases.
315  *
316  * 1.  Optional features in subsection 13.15.4 of version 1.4.
317  *
318  * These are not tested as they deal with 1.3a or older versions and is not
319  * worth spending time on.
320  *
321  * 1.  <Request Audio Descriptor> message is from version 1.4 so older versions
322  *     report <Feature Abort>.
323  * 2.  <Report Audio Descriptor> message is from version 1.4 so older versions
324  *     report <Feature Abort>.
325  * 3.  System Audio Control is from version 1.3a so older versions report
326  *     <Feature Abort>.
327  */
328 
sac_request_sad_probe(struct node * node,unsigned me,unsigned la,bool interactive)329 static int sac_request_sad_probe(struct node *node, unsigned me, unsigned la, bool interactive)
330 {
331 	struct cec_msg msg = {};
332 	uint8_t audio_format_id = 0;
333 	uint8_t audio_format_code = 1;
334 
335 	cec_msg_init(&msg, me, la);
336 	cec_msg_request_short_audio_descriptor(&msg, true, 1, &audio_format_id, &audio_format_code);
337 	fail_on_test(!transmit_timeout(node, &msg));
338 	fail_on_test(timed_out(&msg));
339 	if (unrecognized_op(&msg))
340 		return OK_NOT_SUPPORTED;
341 	if (refused(&msg))
342 		return OK_REFUSED;
343 	if (cec_msg_status_is_abort(&msg))
344 		return OK_PRESUMED;
345 	node->remote[la].has_sad = true;
346 
347 	return 0;
348 }
349 
sac_request_sad_invalid(struct node * node,unsigned me,unsigned la,bool interactive)350 static int sac_request_sad_invalid(struct node *node, unsigned me, unsigned la, bool interactive)
351 {
352 	if (!node->remote[la].has_sad)
353 		return NOTAPPLICABLE;
354 
355 	struct cec_msg msg = {};
356 	uint8_t audio_format_id = CEC_OP_AUD_FMT_ID_CEA861;
357 	uint8_t audio_format_code = 63; // This is outside the range of CEA861-F
358 
359 	cec_msg_init(&msg, me, la);
360 	cec_msg_request_short_audio_descriptor(&msg, true, 1, &audio_format_id, &audio_format_code);
361 	fail_on_test(!transmit_timeout(node, &msg));
362 	fail_on_test(timed_out(&msg));
363 	fail_on_test(!cec_msg_status_is_abort(&msg));
364 	if (abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP) {
365 		warn("Expected Feature Abort [Invalid operand] in reply to Request Short\n");
366 		warn("Audio Descriptor with invalid audio format as operand.\n");
367 	}
368 
369 	return 0;
370 }
371 
sac_sad_format_check(struct node * node,unsigned me,unsigned la,bool interactive)372 static int sac_sad_format_check(struct node *node, unsigned me, unsigned la, bool interactive)
373 {
374 	if (!node->remote[la].has_sad)
375 		return NOTAPPLICABLE;
376 
377 	struct cec_msg msg = {};
378 	uint8_t audio_format_id;
379 	uint8_t audio_format_code;
380 
381 	for (unsigned int id = 0; id <= 1; id++) {
382 		audio_format_id = id;
383 		for (unsigned int fmt_code = 1; fmt_code <= 14; fmt_code++) {
384 			audio_format_code = fmt_code;
385 
386 			cec_msg_init(&msg, me, la);
387 			cec_msg_request_short_audio_descriptor(&msg, true, 1, &audio_format_id, &audio_format_code);
388 			fail_on_test(!transmit_timeout(node, &msg));
389 			fail_on_test(timed_out(&msg));
390 			fail_on_test(unrecognized_op(&msg) || refused(&msg));
391 
392 			if (cec_msg_status_is_abort(&msg) &&
393 			    abort_reason(&msg) == CEC_OP_ABORT_INVALID_OP)
394 				continue;
395 
396 			uint8_t num_descriptors;
397 			uint32_t descriptors[4] = {};
398 
399 			cec_ops_report_short_audio_descriptor(&msg, &num_descriptors, descriptors);
400 			fail_on_test(num_descriptors == 0);
401 			if (id == 1 && node->remote[la].cec_version < CEC_OP_CEC_VERSION_2_0)
402 				warn("The device has CEC version < 2.0 but reports audio format(s) introduced in CEC 2.0.\n");
403 
404 			for (int j = 0; j < num_descriptors; j++) {
405 				struct short_audio_desc sad;
406 
407 				sad_decode(&sad, descriptors[j]);
408 				if ((id == 0 && sad.format_code != fmt_code) ||
409 				    (id == 1 && sad.extension_type_code != fmt_code))
410 					return fail("Different audio format code reported than requested.\n");
411 				info("Supports format %s\n", short_audio_desc2s(sad).c_str());
412 
413 				/* We need to store the ID and Code for one of the audio formats found,
414 				   for use in later test(s) */
415 				node->remote[la].supp_format_id = audio_format_id;
416 				node->remote[la].supp_format_code = audio_format_code;
417 			}
418 		}
419 	}
420 
421 	return 0;
422 }
423 
sac_sad_req_multiple(struct node * node,unsigned me,unsigned la,bool interactive)424 static int sac_sad_req_multiple(struct node *node, unsigned me, unsigned la, bool interactive)
425 {
426 	if (!node->remote[la].has_sad || node->remote[la].supp_format_code == 0)
427 		return NOTAPPLICABLE;
428 
429 	/* Check that if we got a response to a Request Short Audio Descriptor
430 	   with a single format, we also get a response when the same audio format
431 	   occurs in a request together with other formats. */
432 	struct cec_msg msg = {};
433 	uint8_t audio_format_id[4] = { };
434 	uint8_t audio_format_code[4];
435 
436 	for (int i = 0; i < 4; i++) {
437 		if (node->remote[la].supp_format_code <= 12)
438 			audio_format_code[i] = node->remote[la].supp_format_code - 1 + i;
439 		else
440 			audio_format_code[i] = node->remote[la].supp_format_code - 1 - i;
441 	}
442 	cec_msg_init(&msg, me, la);
443 	cec_msg_request_short_audio_descriptor(&msg, true, 4, audio_format_id, audio_format_code);
444 	fail_on_test(!transmit_timeout(node, &msg));
445 	fail_on_test(timed_out(&msg));
446 	fail_on_test(cec_msg_status_is_abort(&msg));
447 
448 	return 0;
449 }
450 
sac_set_system_audio_mode_direct(struct node * node,unsigned me,unsigned la,bool interactive)451 static int sac_set_system_audio_mode_direct(struct node *node, unsigned me, unsigned la, bool interactive)
452 {
453 	struct cec_msg msg = {};
454 
455 	cec_msg_init(&msg, me, la);
456 	cec_msg_set_system_audio_mode(&msg, CEC_OP_SYS_AUD_STATUS_ON);
457 	fail_on_test(!transmit_timeout(node, &msg));
458 	fail_on_test_v2(node->remote[la].cec_version,
459 			unrecognized_op(&msg) && is_tv(la, node->remote[la].prim_type));
460 	if (unrecognized_op(&msg))
461 		return OK_NOT_SUPPORTED;
462 	if (refused(&msg))
463 		return OK_REFUSED;
464 	node->remote[la].has_set_sys_audio_mode = true;
465 
466 	return OK_PRESUMED;
467 }
468 
sac_set_system_audio_mode_broadcast_on(struct node * node,unsigned me,unsigned la,bool interactive)469 static int sac_set_system_audio_mode_broadcast_on(struct node *node, unsigned me, unsigned la, bool interactive)
470 {
471 	struct cec_msg msg = {};
472 
473 	cec_msg_init(&msg, me, CEC_LOG_ADDR_BROADCAST);
474 	cec_msg_set_system_audio_mode(&msg, CEC_OP_SYS_AUD_STATUS_ON);
475 	fail_on_test(!transmit_timeout(node, &msg));
476 
477 	return OK_PRESUMED;
478 }
479 
sac_system_audio_mode_status(struct node * node,unsigned me,unsigned la,bool interactive)480 static int sac_system_audio_mode_status(struct node *node, unsigned me, unsigned la, bool interactive)
481 {
482 	struct cec_msg msg = {};
483 
484 	/* The device shall not feature abort System Audio Status if it did not
485 	   feature abort Set System Audio Mode.
486 
487 	   The message is mandatory for TVs in CEC 2.0. */
488 	cec_msg_init(&msg, me, la);
489 	cec_msg_system_audio_mode_status(&msg, CEC_OP_SYS_AUD_STATUS_ON);
490 	fail_on_test(!transmit_timeout(node, &msg));
491 	fail_on_test_v2(node->remote[la].cec_version,
492 			is_tv(la, node->remote[la].prim_type) && unrecognized_op(&msg));
493 	if (unrecognized_op(&msg) && !node->remote[la].has_set_sys_audio_mode)
494 		return OK_NOT_SUPPORTED;
495 	fail_on_test(unrecognized_op(&msg));
496 	if (refused(&msg))
497 		return OK_REFUSED;
498 	if (cec_msg_status_is_abort(&msg))
499 		return OK_PRESUMED;
500 
501 	return 0;
502 }
503 
sac_set_system_audio_mode_broadcast_off(struct node * node,unsigned me,unsigned la,bool interactive)504 static int sac_set_system_audio_mode_broadcast_off(struct node *node, unsigned me, unsigned la, bool interactive)
505 {
506 	struct cec_msg msg = {};
507 
508 	cec_msg_init(&msg, me, CEC_LOG_ADDR_BROADCAST);
509 	cec_msg_set_system_audio_mode(&msg, CEC_OP_SYS_AUD_STATUS_OFF);
510 	fail_on_test(!transmit_timeout(node, &msg));
511 
512 	return OK_PRESUMED;
513 }
514 
sac_system_audio_mode_req_on(struct node * node,unsigned me,unsigned la,bool interactive)515 static int sac_system_audio_mode_req_on(struct node *node, unsigned me, unsigned la, bool interactive)
516 {
517 	struct cec_msg msg = {};
518 	uint8_t status;
519 
520 	/* Send a System Audio Mode Request to the audio system. This notifies the
521 	   audio system that our device has SAC capabilities, so it should enable
522 	   the feature right away by sending Set System Audio Mode with On as status.
523 
524 	   The message is mandatory for audio systems in CEC 2.0. */
525 	cec_msg_init(&msg, me, la);
526 	cec_msg_system_audio_mode_request(&msg, true, node->phys_addr);
527 	fail_on_test(!transmit_timeout(node, &msg));
528 	fail_on_test(timed_out(&msg));
529 	fail_on_test_v2(node->remote[la].cec_version,
530 			cec_has_audiosystem(1 << la) && unrecognized_op(&msg));
531 	if (unrecognized_op(&msg))
532 		return OK_NOT_SUPPORTED;
533 	if (refused(&msg))
534 		return OK_REFUSED;
535 	if (cec_msg_status_is_abort(&msg))
536 		return OK_PRESUMED;
537 	node->remote[la].has_sys_audio_mode_req = true;
538 	cec_ops_set_system_audio_mode(&msg, &status);
539 	fail_on_test(status != CEC_OP_SYS_AUD_STATUS_ON);
540 
541 	return 0;
542 }
543 
sac_give_system_audio_mode_status(struct node * node,unsigned me,unsigned la,bool interactive)544 static int sac_give_system_audio_mode_status(struct node *node, unsigned me, unsigned la, bool interactive)
545 {
546 	struct cec_msg msg = {};
547 	uint8_t system_audio_status;
548 
549 	/* The device shall not feature abort Give System Audio Mode Status if it did not
550 	   feature abort System Audio Mode Request.
551 
552 	   The message is mandatory for audio systems in CEC 2.0. */
553 	cec_msg_init(&msg, me, la);
554 	cec_msg_give_system_audio_mode_status(&msg, true);
555 	fail_on_test(!transmit_timeout(node, &msg));
556 	fail_on_test(timed_out(&msg));
557 	fail_on_test_v2(node->remote[la].cec_version,
558 			cec_has_audiosystem(1 << la) && unrecognized_op(&msg));
559 	if (unrecognized_op(&msg) && !node->remote[la].has_sys_audio_mode_req)
560 		return OK_NOT_SUPPORTED;
561 	fail_on_test(unrecognized_op(&msg));
562 	if (refused(&msg))
563 		return OK_REFUSED;
564 	if (cec_msg_status_is_abort(&msg))
565 		return OK_PRESUMED;
566 	cec_ops_system_audio_mode_status(&msg, &system_audio_status);
567 	fail_on_test(system_audio_status != CEC_OP_SYS_AUD_STATUS_ON);
568 
569 	return 0;
570 }
571 
sac_give_audio_status(struct node * node,unsigned me,unsigned la,bool interactive)572 static int sac_give_audio_status(struct node *node, unsigned me, unsigned la, bool interactive)
573 {
574 	struct cec_msg msg = {};
575 
576 	/* Give Audio Status is mandatory for audio systems in CEC 2.0, except
577 	   for systems that lack external controls for volume/mute status. */
578 	cec_msg_init(&msg, me, la);
579 	cec_msg_give_audio_status(&msg, true);
580 	fail_on_test(!transmit_timeout(node, &msg));
581 	fail_on_test(timed_out(&msg));
582 	fail_on_test_v2(node->remote[la].cec_version,
583 			cec_has_audiosystem(1 << la) && unrecognized_op(&msg));
584 	if (unrecognized_op(&msg))
585 		return OK_NOT_SUPPORTED;
586 	if (refused(&msg))
587 		return OK_REFUSED;
588 	if (cec_msg_status_is_abort(&msg))
589 		return OK_PRESUMED;
590 
591 	cec_ops_report_audio_status(&msg, &node->remote[la].mute, &node->remote[la].volume);
592 	fail_on_test(node->remote[la].volume > 100);
593 	info("Volume: %d %s\n", node->remote[la].volume, node->remote[la].mute ? "(muted)" : "");
594 
595 	return 0;
596 }
597 
sac_util_send_user_control_press(struct node * node,unsigned me,unsigned la,uint8_t ui_cmd)598 static int sac_util_send_user_control_press(struct node *node, unsigned me, unsigned la, uint8_t ui_cmd)
599 {
600 	struct cec_msg msg = {};
601 	struct cec_op_ui_command rc_press = {};
602 
603 	/* The device shall not feature abort
604 	     - User Control Pressed ["Volume Up"]
605 	     - User Control Pressed ["Volume Down"]
606 	     - User Control Pressed ["Mute"]
607 	   if it did not feature abort System Audio Mode Request.
608 
609 	   The messages are mandatory for audio systems and TVs in CEC 2.0,
610 	   and it is mandatory for audio systems to send Report Audio Status
611 	   back to the TV in CEC 2.0.
612 
613 	   It is recommended for devices to not send Report Audio Status back
614 	   more often than once every 500ms. We therefore sleep a second before
615 	   each User Control Pressed is sent. */
616 	bool got_response;
617 
618 	sleep(1);
619 	mode_set_follower(node);
620 	cec_msg_init(&msg, me, la);
621 	rc_press.ui_cmd = ui_cmd;
622 	cec_msg_user_control_pressed(&msg, &rc_press);
623 	fail_on_test(!transmit(node, &msg));
624 	cec_msg_init(&msg, me, la);
625 	cec_msg_user_control_released(&msg);
626 	fail_on_test(!transmit_timeout(node, &msg));
627 	got_response = util_receive(node, la, 1000, &msg,
628 				    CEC_MSG_USER_CONTROL_PRESSED, CEC_MSG_REPORT_AUDIO_STATUS) >= 0;
629 
630 	fail_on_test_v2(node->remote[la].cec_version, !got_response &&
631 			cec_has_audiosystem(1 << la));
632 	fail_on_test_v2(node->remote[la].cec_version, unrecognized_op(&msg) &&
633 			(is_tv(la, node->remote[la].prim_type) || cec_has_audiosystem(1 << la)));
634 	if (unrecognized_op(&msg) && !node->remote[la].has_sys_audio_mode_req)
635 		return OK_NOT_SUPPORTED;
636 	fail_on_test(unrecognized_op(&msg));
637 	if (refused(&msg))
638 		return OK_REFUSED;
639 	if (cec_msg_status_is_abort(&msg))
640 		return OK_PRESUMED;
641 	if (got_response) {
642 		cec_ops_report_audio_status(&msg, &node->remote[la].mute, &node->remote[la].volume);
643 		return 0;
644 	}
645 
646 	return OK_PRESUMED;
647 }
648 
sac_user_control_press_vol_up(struct node * node,unsigned me,unsigned la,bool interactive)649 static int sac_user_control_press_vol_up(struct node *node, unsigned me, unsigned la, bool interactive)
650 {
651 	uint8_t ret, old_volume = node->remote[la].volume;
652 
653 	if ((ret = sac_util_send_user_control_press(node, me, la, 0x41)))
654 		return ret;
655 	/* Check that if not already at the highest, the volume was increased. */
656 	fail_on_test_v2(node->remote[la].cec_version,
657 			la == CEC_LOG_ADDR_AUDIOSYSTEM &&
658 			old_volume < 100 && node->remote[la].volume <= old_volume);
659 
660 	return 0;
661 }
662 
sac_user_control_press_vol_down(struct node * node,unsigned me,unsigned la,bool interactive)663 static int sac_user_control_press_vol_down(struct node *node, unsigned me, unsigned la, bool interactive)
664 {
665 	uint8_t ret, old_volume = node->remote[la].volume;
666 
667 	if ((ret = sac_util_send_user_control_press(node, me, la, 0x42)))
668 		return ret;
669 	/* Check that if not already at the lowest, the volume was lowered. */
670 	fail_on_test_v2(node->remote[la].cec_version,
671 			la == CEC_LOG_ADDR_AUDIOSYSTEM &&
672 			old_volume > 0 && node->remote[la].volume >= old_volume);
673 
674 	return 0;
675 }
676 
sac_user_control_press_mute(struct node * node,unsigned me,unsigned la,bool interactive)677 static int sac_user_control_press_mute(struct node *node, unsigned me, unsigned la, bool interactive)
678 {
679 	uint8_t ret, old_mute = node->remote[la].mute;
680 
681 	if ((ret = sac_util_send_user_control_press(node, me, la, 0x43)))
682 		return ret;
683 	/* Check that mute has been toggled from what it was before. */
684 	fail_on_test_v2(node->remote[la].cec_version,
685 			la == CEC_LOG_ADDR_AUDIOSYSTEM &&
686 			node->remote[la].mute == old_mute);
687 
688 	return 0;
689 }
690 
sac_user_control_press_mute_function(struct node * node,unsigned me,unsigned la,bool interactive)691 static int sac_user_control_press_mute_function(struct node *node, unsigned me, unsigned la, bool interactive)
692 {
693 	uint8_t ret;
694 
695 	if ((ret = sac_util_send_user_control_press(node, me, la, 0x65)))
696 		return ret;
697 	fail_on_test_v2(node->remote[la].cec_version,
698 			la == CEC_LOG_ADDR_AUDIOSYSTEM &&
699 			node->remote[la].mute == CEC_OP_AUD_MUTE_STATUS_ON);
700 
701 	return 0;
702 }
703 
sac_user_control_press_restore_volume_function(struct node * node,unsigned me,unsigned la,bool interactive)704 static int sac_user_control_press_restore_volume_function(struct node *node, unsigned me, unsigned la, bool interactive)
705 {
706 	uint8_t ret;
707 
708 	if ((ret = sac_util_send_user_control_press(node, me, la, 0x66)))
709 		return ret;
710 	fail_on_test_v2(node->remote[la].cec_version,
711 			la == CEC_LOG_ADDR_AUDIOSYSTEM &&
712 			node->remote[la].mute == CEC_OP_AUD_MUTE_STATUS_OFF);
713 
714 	return 0;
715 }
716 
sac_user_control_release(struct node * node,unsigned me,unsigned la,bool interactive)717 static int sac_user_control_release(struct node *node, unsigned me, unsigned la, bool interactive)
718 {
719 	struct cec_msg msg = {};
720 
721 	/* The device shall not feature abort User Control Released if it did not
722 	   feature abort System Audio Mode Request
723 
724 	   The message is mandatory for audio systems and TVs in CEC 2.0. */
725 	cec_msg_init(&msg, me, la);
726 	cec_msg_user_control_released(&msg);
727 	fail_on_test(!transmit_timeout(node, &msg));
728 	fail_on_test_v2(node->remote[la].cec_version, unrecognized_op(&msg) &&
729 			(is_tv(la, node->remote[la].prim_type) || cec_has_audiosystem(1 << la)));
730 	if (unrecognized_op(&msg) && !node->remote[la].has_sys_audio_mode_req)
731 		return OK_NOT_SUPPORTED;
732 	fail_on_test(unrecognized_op(&msg));
733 	if (refused(&msg))
734 		return OK_REFUSED;
735 	if (cec_msg_status_is_abort(&msg))
736 		return OK_PRESUMED;
737 
738 	return OK_PRESUMED;
739 }
740 
sac_system_audio_mode_req_off(struct node * node,unsigned me,unsigned la,bool interactive)741 static int sac_system_audio_mode_req_off(struct node *node, unsigned me, unsigned la, bool interactive)
742 {
743 	if (!node->remote[la].has_sys_audio_mode_req)
744 		return NOTAPPLICABLE;
745 
746 	struct cec_msg msg = {};
747 	uint8_t status;
748 
749 	cec_msg_init(&msg, me, la);
750 	cec_msg_system_audio_mode_request(&msg, true, CEC_PHYS_ADDR_INVALID);
751 	fail_on_test(!transmit_timeout(node, &msg));
752 	fail_on_test(timed_out(&msg));
753 	fail_on_test_v2(node->remote[la].cec_version,
754 			cec_has_audiosystem(1 << la) && unrecognized_op(&msg));
755 	if (unrecognized_op(&msg))
756 		return OK_NOT_SUPPORTED;
757 	if (refused(&msg))
758 		return OK_REFUSED;
759 	if (cec_msg_status_is_abort(&msg))
760 		return OK_PRESUMED;
761 	cec_ops_set_system_audio_mode(&msg, &status);
762 	fail_on_test(status != CEC_OP_SYS_AUD_STATUS_OFF);
763 
764 	return 0;
765 }
766 
767 struct remote_subtest sac_subtests[] = {
768 	{ "Request Short Audio Descriptor",
769 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
770 	  sac_request_sad_probe },
771 	{ "Request Short Audio Descriptor, invalid",
772 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
773 	  sac_request_sad_invalid },
774 	{ "Report Short Audio Descriptor consistency",
775 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
776 	  sac_sad_format_check },
777 	{ "Report Short Audio Descriptor, multiple requests in one",
778 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
779 	  sac_sad_req_multiple },
780 	{ "Set System Audio Mode (directly addressed)",
781 	  CEC_LOG_ADDR_MASK_TV,
782 	  sac_set_system_audio_mode_direct },
783 	{ "Set System Audio Mode (broadcast on)",
784 	  CEC_LOG_ADDR_MASK_TV,
785 	  sac_set_system_audio_mode_broadcast_on },
786 	{ "System Audio Mode Status",
787 	  CEC_LOG_ADDR_MASK_TV,
788 	  sac_system_audio_mode_status },
789 	{ "System Audio Mode Request (on)",
790 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
791 	  sac_system_audio_mode_req_on },
792 	{ "Give System Audio Mode Status",
793 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
794 	  sac_give_system_audio_mode_status },
795 	{ "Give Audio Status",
796 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
797 	  sac_give_audio_status },
798 	{ "User Control Pressed (Volume Up)",
799 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
800 	  sac_user_control_press_vol_up },
801 	{ "User Control Pressed (Volume Down)",
802 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
803 	  sac_user_control_press_vol_down },
804 	{ "User Control Pressed (Mute)",
805 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
806 	  sac_user_control_press_mute },
807 	{ "User Control Pressed (Restore Volume Function)",
808 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
809 	  sac_user_control_press_restore_volume_function },
810 	{ "User Control Pressed (Mute Function)",
811 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
812 	  sac_user_control_press_mute_function },
813 	{ "User Control Released (Audio)",
814 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
815 	  sac_user_control_release },
816 	{ "Set System Audio Mode (broadcast off)",
817 	  CEC_LOG_ADDR_MASK_TV,
818 	  sac_set_system_audio_mode_broadcast_off },
819 	{ "System Audio Mode Request (off)",
820 	  CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
821 	  sac_system_audio_mode_req_off },
822 };
823 
824 const unsigned sac_subtests_size = ARRAY_SIZE(sac_subtests);
825 
826 
827 /* Audio Rate Control */
828 
829 /*
830   TODO: These are very rudimentary tests which should be expanded.
831  */
832 
audio_rate_ctl_set_audio_rate(struct node * node,unsigned me,unsigned la,bool interactive)833 static int audio_rate_ctl_set_audio_rate(struct node *node, unsigned me, unsigned la, bool interactive)
834 {
835 	struct cec_msg msg = {};
836 
837 	cec_msg_init(&msg, me, la);
838 	cec_msg_set_audio_rate(&msg, CEC_OP_AUD_RATE_WIDE_STD);
839 	fail_on_test(!transmit_timeout(node, &msg));
840 	/* CEC 2.0: Devices shall use the device feature bit to indicate support. */
841 	fail_on_test_v2(node->remote[la].cec_version,
842 			node->remote[la].has_aud_rate && unrecognized_op(&msg));
843 	fail_on_test_v2(node->remote[la].cec_version,
844 			!node->remote[la].has_aud_rate && !unrecognized_op(&msg));
845 	if (unrecognized_op(&msg))
846 		return OK_NOT_SUPPORTED;
847 	if (refused(&msg))
848 		return OK_REFUSED;
849 
850 	return OK_PRESUMED;
851 }
852 
853 struct remote_subtest audio_rate_ctl_subtests[] = {
854 	{ "Set Audio Rate",
855 	  CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_TUNER,
856 	  audio_rate_ctl_set_audio_rate },
857 };
858 
859 const unsigned audio_rate_ctl_subtests_size = ARRAY_SIZE(audio_rate_ctl_subtests);
860