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 <ctime>
7 #include <sstream>
8 #include <string>
9
10 #include <sys/ioctl.h>
11 #include <unistd.h>
12
13 #include "cec-compliance.h"
14 #include "compiler.h"
15
audio_format_code2s(__u8 format_code)16 static std::string audio_format_code2s(__u8 format_code)
17 {
18 switch (format_code) {
19 case 0:
20 return "Reserved";
21 case SAD_FMT_CODE_LPCM:
22 return "L-PCM";
23 case SAD_FMT_CODE_AC3:
24 return "AC-3";
25 case SAD_FMT_CODE_MPEG1:
26 return "MPEG-1";
27 case SAD_FMT_CODE_MP3:
28 return "MP3";
29 case SAD_FMT_CODE_MPEG2:
30 return "MPEG2";
31 case SAD_FMT_CODE_AAC_LC:
32 return "AAC LC";
33 case SAD_FMT_CODE_DTS:
34 return "DTS";
35 case SAD_FMT_CODE_ATRAC:
36 return "ATRAC";
37 case SAD_FMT_CODE_ONE_BIT_AUDIO:
38 return "One Bit Audio";
39 case SAD_FMT_CODE_ENHANCED_AC3:
40 return "Enhanced AC-3";
41 case SAD_FMT_CODE_DTS_HD:
42 return "DTS-HD";
43 case SAD_FMT_CODE_MAT:
44 return "MAT";
45 case SAD_FMT_CODE_DST:
46 return "DST";
47 case SAD_FMT_CODE_WMA_PRO:
48 return "WMA Pro";
49 case SAD_FMT_CODE_EXTENDED:
50 return "Extended";
51 default:
52 return "Illegal";
53 }
54 }
55
extension_type_code2s(__u8 type_code)56 static std::string extension_type_code2s(__u8 type_code)
57 {
58 switch (type_code) {
59 case 0:
60 case 1:
61 case 2:
62 case 3:
63 return "Not in use";
64 case SAD_EXT_TYPE_MPEG4_HE_AAC:
65 return "MPEG-4 HE AAC";
66 case SAD_EXT_TYPE_MPEG4_HE_AACv2:
67 return "MPEG-4 HE AAC v2";
68 case SAD_EXT_TYPE_MPEG4_AAC_LC:
69 return "MPEG-4 AAC LC";
70 case SAD_EXT_TYPE_DRA:
71 return "DRA";
72 case SAD_EXT_TYPE_MPEG4_HE_AAC_SURROUND:
73 return "MPEG-4 HE AAC + MPEG Surround";
74 case SAD_EXT_TYPE_MPEG4_AAC_LC_SURROUND:
75 return "MPEG-4 AAC LC + MPEG Surround";
76 case SAD_EXT_TYPE_MPEG_H_3D_AUDIO:
77 return "MPEG-H 3D Audio";
78 case SAD_EXT_TYPE_AC_4:
79 return "AC-4";
80 case SAD_EXT_TYPE_LPCM_3D_AUDIO:
81 return "L-PCM 3D Audio";
82 default:
83 return "Reserved";
84 }
85 }
86
short_audio_desc2s(const struct short_audio_desc & sad)87 static std::string short_audio_desc2s(const struct short_audio_desc &sad)
88 {
89 std::stringstream oss;
90
91 if (sad.format_code != SAD_FMT_CODE_EXTENDED)
92 oss << audio_format_code2s(sad.format_code);
93 else
94 oss << extension_type_code2s(sad.extension_type_code);
95 oss << ", " << static_cast<int>(sad.num_channels) << " channels";
96
97 oss << ", sampling rates (kHz): ";
98 if (sad.sample_freq_mask & SAD_SAMPLE_FREQ_MASK_32)
99 oss << "32,";
100 if (sad.sample_freq_mask & SAD_SAMPLE_FREQ_MASK_44_1)
101 oss << "44.1,";
102 if (sad.sample_freq_mask & SAD_SAMPLE_FREQ_MASK_48)
103 oss << "48,";
104 if (sad.sample_freq_mask & SAD_SAMPLE_FREQ_MASK_88_2)
105 oss << "88.2,";
106 if (sad.sample_freq_mask & SAD_SAMPLE_FREQ_MASK_96)
107 oss << "96,";
108 if (sad.sample_freq_mask & SAD_SAMPLE_FREQ_MASK_176_4)
109 oss << "176.4,";
110 if (sad.sample_freq_mask & SAD_SAMPLE_FREQ_MASK_192)
111 oss << "192,";
112 if (sad.sample_freq_mask & (1 << 7))
113 oss << "Reserved,";
114 oss << "\b \b";
115
116 if (sad.format_code == SAD_FMT_CODE_LPCM ||
117 (sad.format_code == SAD_FMT_CODE_EXTENDED &&
118 sad.extension_type_code == SAD_EXT_TYPE_LPCM_3D_AUDIO)) {
119 oss << ", bit depth: ";
120 if (sad.bit_depth_mask & SAD_BIT_DEPTH_MASK_16)
121 oss << "16,";
122 if (sad.bit_depth_mask & SAD_BIT_DEPTH_MASK_20)
123 oss << "20,";
124 if (sad.bit_depth_mask & SAD_BIT_DEPTH_MASK_24)
125 oss << "24,";
126 oss << "\b \b";
127 } else if (sad.format_code >= 2 && sad.format_code <= 8)
128 oss << " max bitrate (kbit/s): " << 8 * sad.max_bitrate;
129
130 if (sad.format_code == SAD_FMT_CODE_EXTENDED) {
131 switch (sad.extension_type_code) {
132 case 4:
133 case 5:
134 case 6:
135 case 8:
136 case 10:
137 oss << ", frame length: ";
138 if (sad.frame_length_mask & SAD_FRAME_LENGTH_MASK_960)
139 oss << "960,";
140 if (sad.frame_length_mask & SAD_FRAME_LENGTH_MASK_1024)
141 oss << "1024,";
142 oss << "\b";
143 break;
144 }
145
146 if (sad.extension_type_code == 8 || sad.extension_type_code == 10)
147 oss << ", MPS";
148 }
149
150 return oss.str();
151 }
152
sad_decode(struct short_audio_desc * sad,__u32 descriptor)153 static void sad_decode(struct short_audio_desc *sad, __u32 descriptor)
154 {
155 __u8 b1 = (descriptor >> 16) & 0xff;
156 __u8 b2 = (descriptor >> 8) & 0xff;
157 __u8 b3 = descriptor & 0xff;
158
159 sad->num_channels = (b1 & 0x07) + 1;
160 sad->format_code = (b1 >> 3) & 0x0f;
161 sad->sample_freq_mask = b2;
162
163 switch (sad->format_code) {
164 case SAD_FMT_CODE_LPCM:
165 sad->bit_depth_mask = b3 & 0x07;
166 break;
167 case 2:
168 case 3:
169 case 4:
170 case 5:
171 case 6:
172 case 7:
173 case 8:
174 sad->max_bitrate = b3;
175 break;
176 case 9:
177 case 10:
178 case 11:
179 case 12:
180 case 13:
181 sad->format_dependent = b3;
182 break;
183 case SAD_FMT_CODE_WMA_PRO:
184 sad->wma_profile = b3 & 0x03;
185 break;
186 case SAD_FMT_CODE_EXTENDED:
187 sad->extension_type_code = (b3 >> 3) & 0x1f;
188
189 switch (sad->extension_type_code) {
190 case 4:
191 case 5:
192 case 6:
193 sad->frame_length_mask = (b3 >> 1) & 0x03;
194 break;
195 case 8:
196 case 10:
197 sad->frame_length_mask = (b3 >> 1) & 0x03;
198 sad->mps = b3 & 1;
199 break;
200 case SAD_EXT_TYPE_MPEG_H_3D_AUDIO:
201 case SAD_EXT_TYPE_AC_4:
202 sad->format_dependent = b3 & 0x07;
203 fallthrough;
204 case SAD_EXT_TYPE_LPCM_3D_AUDIO:
205 sad->bit_depth_mask = b3 & 0x07;
206 break;
207 }
208 break;
209 }
210 }
211
212 /* Dynamic Auto Lipsync */
213
dal_request_current_latency(struct node * node,unsigned me,unsigned la,bool interactive)214 static int dal_request_current_latency(struct node *node, unsigned me, unsigned la, bool interactive)
215 {
216 struct cec_msg msg;
217
218 cec_msg_init(&msg, me, la);
219 cec_msg_request_current_latency(&msg, true, node->remote[la].phys_addr);
220 fail_on_test(!transmit_timeout(node, &msg));
221 fail_on_test_v2(node->remote[la].cec_version,
222 timed_out(&msg) && is_tv(la, node->remote[la].prim_type));
223 if (timed_out(&msg))
224 return OK_NOT_SUPPORTED;
225
226 /* When the device supports Dynamic Auto Lipsync but does not implement
227 CEC 1.4b, or 2.0, a very strict subset of CEC can be supported. If we
228 get here and the version is < 1.4, we know that the device is not
229 complying to this specification. */
230 if (node->remote[la].cec_version < CEC_OP_CEC_VERSION_1_4) {
231 warn("CEC 2.0 specifies that devices with CEC version < 1.4 which implement\n");
232 warn("Dynamic Auto Lipsync shall only implement a very strict subset of CEC.\n");
233 }
234
235 __u16 phys_addr;
236 __u8 video_latency, low_latency_mode, audio_out_compensated, audio_out_delay;
237
238 cec_ops_report_current_latency(&msg, &phys_addr, &video_latency, &low_latency_mode,
239 &audio_out_compensated, &audio_out_delay);
240 // cec_ops_report_current_latency will hardcode audio_out_delay
241 // if it is unused, but for this test we want the real value, so
242 // get it from the actual message.
243 if (msg.len >= 7)
244 audio_out_delay = msg.msg[6];
245 else
246 audio_out_delay = 1;
247 fail_on_test(phys_addr != node->remote[la].phys_addr);
248 info("Video latency: %d (%dms)\n", video_latency, (video_latency - 1) * 2);
249 info("Low latency mode: %d\n", low_latency_mode);
250 info("Audio output compensation: %d\n", audio_out_compensated);
251 if (audio_out_compensated == CEC_OP_AUD_OUT_COMPENSATED_PARTIAL_DELAY) {
252 info("Audio out delay: %d (%dms)\n", audio_out_delay, (audio_out_delay - 1) * 2);
253 fail_on_test(audio_out_delay == 0 || audio_out_delay > 251);
254 // Warn if the delay is more than 50 ms
255 warn_on_test(audio_out_delay > (50 / 2) + 1);
256 } else {
257 // Although this value will be ignored, it shouldn't use
258 // reserved values.
259 if (audio_out_delay == 0 || audio_out_delay > 251)
260 warn("Audio out delay is set to a reserved value (%d), set it to 1 instead (recommended value when this field is unused).\n", audio_out_delay);
261 else if (audio_out_delay != 1)
262 warn("Audio out delay is %d (%dms), but value 1 is recommended when this field is unused.\n",
263 audio_out_delay, (audio_out_delay - 1) * 2);
264 }
265 fail_on_test(video_latency == 0 || video_latency > 251);
266 // Warn if the delay is more than 50 ms and low latency mode is set
267 if (video_latency > (50 / 2) + 1) {
268 if (low_latency_mode)
269 fail("Low latency mode is set, but video latency is > 50ms\n");
270 else
271 warn("Video latency is > 50ms\n");
272 }
273
274 return 0;
275 }
276
dal_req_current_latency_invalid(struct node * node,unsigned me,unsigned la,bool interactive)277 static int dal_req_current_latency_invalid(struct node *node, unsigned me, unsigned la, bool interactive)
278 {
279 struct cec_msg msg;
280
281 /* Test that there is no reply when the physical address operand is not the
282 physical address of the remote device. */
283 cec_msg_init(&msg, me, la);
284 cec_msg_request_current_latency(&msg, true, CEC_PHYS_ADDR_INVALID);
285 fail_on_test(!transmit_timeout(node, &msg));
286 fail_on_test(!timed_out(&msg));
287
288 return 0;
289 }
290
291 const vec_remote_subtests dal_subtests{
292 { "Request Current Latency", CEC_LOG_ADDR_MASK_ALL, dal_request_current_latency },
293 { "Request Current Latency with invalid PA", CEC_LOG_ADDR_MASK_ALL, dal_req_current_latency_invalid },
294 };
295
296 /* Audio Return Channel Control */
297
pa_common_mask(__u16 pa1,__u16 pa2)298 static __u16 pa_common_mask(__u16 pa1, __u16 pa2)
299 {
300 __u16 mask = 0xf000;
301
302 for (int i = 0; i < 3; i++) {
303 if ((pa1 & mask) != (pa2 & mask))
304 break;
305 mask = (mask >> 4) | 0xf000;
306 }
307 return mask << 4;
308 }
pa_are_adjacent(__u16 pa1,__u16 pa2)309 static bool pa_are_adjacent(__u16 pa1, __u16 pa2)
310 {
311 const __u16 mask = pa_common_mask(pa1, pa2);
312 const __u16 trail_mask = ((~mask) & 0xffff) >> 4;
313
314 if (pa1 == CEC_PHYS_ADDR_INVALID || pa2 == CEC_PHYS_ADDR_INVALID || pa1 == pa2)
315 return false;
316 if ((pa1 & trail_mask) || (pa2 & trail_mask))
317 return false;
318 return !((pa1 & ~mask) && (pa2 & ~mask));
319 }
320
pa_is_upstream_from(__u16 pa1,__u16 pa2)321 static bool pa_is_upstream_from(__u16 pa1, __u16 pa2)
322 {
323 const __u16 mask = pa_common_mask(pa1, pa2);
324
325 if (pa1 == CEC_PHYS_ADDR_INVALID || pa2 == CEC_PHYS_ADDR_INVALID)
326 return false;
327 return !(pa1 & ~mask) && (pa2 & ~mask);
328 }
329
arc_initiate_tx(struct node * node,unsigned me,unsigned la,bool interactive)330 static int arc_initiate_tx(struct node *node, unsigned me, unsigned la, bool interactive)
331 {
332 /* Check if we are upstream from the device. If we are, then the device is
333 an HDMI source, which means that it is an ARC receiver, not a transmitter. */
334 if (pa_is_upstream_from(node->phys_addr, node->remote[la].phys_addr))
335 return NOTAPPLICABLE;
336
337 struct cec_msg msg;
338
339 /*
340 * Note that this is a special case: INITIATE_ARC can reply with two possible
341 * messages: CEC_MSG_REPORT_ARC_INITIATED or CEC_MSG_REPORT_ARC_TERMINATED.
342 * It's the only message that behaves like this.
343 */
344 cec_msg_init(&msg, me, la);
345 cec_msg_initiate_arc(&msg, true);
346 fail_on_test(!transmit_timeout(node, &msg));
347 if (timed_out(&msg)) {
348 fail_on_test_v2(node->remote[la].cec_version, node->remote[la].sink_has_arc_tx);
349 warn("Timed out waiting for Report ARC Initiated/Terminated.\n");
350 return OK_PRESUMED;
351 }
352 if (unrecognized_op(&msg)) {
353 fail_on_test_v2(node->remote[la].cec_version, node->remote[la].sink_has_arc_tx);
354 return OK_NOT_SUPPORTED;
355 }
356 if (cec_msg_opcode(&msg) == CEC_MSG_REPORT_ARC_INITIATED) {
357 fail_on_test(!pa_are_adjacent(node->phys_addr, node->remote[la].phys_addr));
358 fail_on_test_v2(node->remote[la].cec_version, !node->remote[la].sink_has_arc_tx);
359 node->remote[la].arc_initiated = true;
360 }
361 else if (cec_msg_opcode(&msg) == CEC_MSG_REPORT_ARC_TERMINATED)
362 announce("Device supports ARC but is not ready to initiate.");
363 else if (refused(&msg))
364 return OK_REFUSED;
365 else if (cec_msg_status_is_abort(&msg))
366 return OK_PRESUMED;
367
368 return 0;
369 }
370
arc_terminate_tx(struct node * node,unsigned me,unsigned la,bool interactive)371 static int arc_terminate_tx(struct node *node, unsigned me, unsigned la, bool interactive)
372 {
373 /* Check if we are upstream from the device. If we are, then the device is
374 an HDMI source, which means that it is an ARC receiver, not a transmitter. */
375 if (pa_is_upstream_from(node->phys_addr, node->remote[la].phys_addr))
376 return NOTAPPLICABLE;
377 if (!node->remote[la].arc_initiated)
378 return NOTAPPLICABLE;
379
380 struct cec_msg msg;
381
382 cec_msg_init(&msg, me, la);
383 cec_msg_terminate_arc(&msg, true);
384 fail_on_test(!transmit_timeout(node, &msg));
385 if (timed_out(&msg)) {
386 warn("Timed out waiting for Report ARC Terminated.\n");
387 return OK_PRESUMED;
388 }
389 fail_on_test(unrecognized_op(&msg));
390 if (cec_msg_status_is_abort(&msg)) {
391 warn("Received Feature Abort for Terminate ARC (but the message was recognized).\n");
392 if (refused(&msg))
393 return OK_REFUSED;
394 return OK_PRESUMED;
395 }
396
397 return 0;
398 }
399
arc_initiate_rx(struct node * node,unsigned me,unsigned la,bool interactive)400 static int arc_initiate_rx(struct node *node, unsigned me, unsigned la, bool interactive)
401 {
402 /* Check if the DUT is upstream from us. If it is, then it is an
403 HDMI sink, which means that it is an ARC transmitter, not receiver. */
404 if (pa_is_upstream_from(node->remote[la].phys_addr, node->phys_addr))
405 return NOTAPPLICABLE;
406
407 struct cec_msg msg;
408
409 cec_msg_init(&msg, me, la);
410 cec_msg_request_arc_initiation(&msg, true);
411
412 bool unsupported = false;
413
414 fail_on_test(!transmit_timeout(node, &msg));
415 if (timed_out(&msg) || unrecognized_op(&msg))
416 unsupported = true;
417 else if (cec_msg_status_is_abort(&msg)) {
418 __u8 abort_msg, reason;
419
420 cec_ops_feature_abort(&msg, &abort_msg, &reason);
421 if (reason == CEC_OP_ABORT_INCORRECT_MODE) {
422 announce("The device supports ARC but is not ready to initiate.");
423 return 0;
424 }
425
426 warn("Device responded Feature Abort with unexpected abort reason. Assuming no ARC support.\n");
427 unsupported = true;
428 }
429
430 if (unsupported) {
431 fail_on_test_v2(node->remote[la].cec_version, node->remote[la].source_has_arc_rx);
432 return OK_NOT_SUPPORTED;
433 }
434 fail_on_test(!pa_are_adjacent(node->phys_addr, node->remote[la].phys_addr));
435 fail_on_test_v2(node->remote[la].cec_version, !node->remote[la].source_has_arc_rx);
436
437 cec_msg_init(&msg, me, la);
438 cec_msg_report_arc_initiated(&msg);
439 fail_on_test(!transmit_timeout(node, &msg));
440 fail_on_test(unrecognized_op(&msg));
441 node->remote[la].arc_initiated = true;
442
443 return 0;
444 }
445
arc_terminate_rx(struct node * node,unsigned me,unsigned la,bool interactive)446 static int arc_terminate_rx(struct node *node, unsigned me, unsigned la, bool interactive)
447 {
448 /* Check if the DUT is upstream from us. If it is, then it is an
449 HDMI sink, which means that it is an ARC transmitter, not receiver. */
450 if (pa_is_upstream_from(node->remote[la].phys_addr, node->phys_addr))
451 return NOTAPPLICABLE;
452 if (!node->remote[la].arc_initiated)
453 return NOTAPPLICABLE;
454
455 struct cec_msg msg;
456
457 cec_msg_init(&msg, me, la);
458 cec_msg_request_arc_termination(&msg, true);
459 fail_on_test(!transmit_timeout(node, &msg));
460 if (timed_out(&msg)) {
461 warn("Timed out waiting for Terminate ARC.\n");
462 return OK_PRESUMED;
463 }
464 fail_on_test(unrecognized_op(&msg));
465 if (cec_msg_status_is_abort(&msg)) {
466 warn("Received Feature Abort for Request ARC Termination (but the message was recognized).\n");
467 if (refused(&msg))
468 return OK_REFUSED;
469 return OK_PRESUMED;
470 }
471
472 cec_msg_init(&msg, me, la);
473 cec_msg_report_arc_terminated(&msg);
474 fail_on_test(!transmit_timeout(node, &msg));
475 fail_on_test(unrecognized_op(&msg));
476
477 return 0;
478 }
479
480 const vec_remote_subtests arc_subtests{
481 { "Initiate ARC (RX)", CEC_LOG_ADDR_MASK_ALL, arc_initiate_rx },
482 { "Terminate ARC (RX)", CEC_LOG_ADDR_MASK_ALL, arc_terminate_rx },
483 { "Initiate ARC (TX)", CEC_LOG_ADDR_MASK_ALL, arc_initiate_tx },
484 { "Terminate ARC (TX)", CEC_LOG_ADDR_MASK_ALL, arc_terminate_tx },
485 };
486
487 /* System Audio Control */
488
489 /*
490 * The following scenarios are defined in section 13.15 of the CEC 1.4
491 * specification.
492 *
493 * These are not tested as they need three CEC devices. An amplifier
494 * provides the audio for a source that is being displayed on a TV.
495 *
496 * 1. Amplifier initiated <System Audio Mode Request> and active source
497 * discovery with a <Request Active Source> broadcast plus the
498 * <Active Source> response.
499 * 2. Post discovery, subsequent amplifier <Set System Audio Mode> [On]
500 * and System Audio Control feature confirmation with TV.
501 * 3. Amplifier broadcasts <Set System Audio Mode> [On] to mute the TV and
502 * unmute amplifier.
503 * 4. Amplifier broadcasts <Set System Audio Mode> [Off] to unmute the TV
504 * and mute the amplifier.
505 * 5. When System Audio Mode is On, muting and unmuting an amplifier sends
506 * a <Report Audio Status> message to the TV.
507 * 6. When System Audio Mode is On, the amplifier sends a <Set System Audio
508 * Mode> [Off] to unmute the TV before going into standby.
509 * 7. When System Audio Mode is On, only the amplifier can control system
510 * volume.
511 *
512 * These are not tested as they are hard-to-test corner cases.
513 *
514 * 1. Optional features in subsection 13.15.4 of version 1.4.
515 *
516 * These are not tested as they deal with 1.3a or older versions and is not
517 * worth spending time on.
518 *
519 * 1. <Request Audio Descriptor> message is from version 1.4 so older versions
520 * report <Feature Abort>.
521 * 2. <Report Audio Descriptor> message is from version 1.4 so older versions
522 * report <Feature Abort>.
523 * 3. System Audio Control is from version 1.3a so older versions report
524 * <Feature Abort>.
525 */
526
sac_request_sad_probe(struct node * node,unsigned me,unsigned la,bool interactive)527 static int sac_request_sad_probe(struct node *node, unsigned me, unsigned la, bool interactive)
528 {
529 struct cec_msg msg;
530 __u8 audio_format_id = 0;
531 __u8 audio_format_code = 1;
532
533 cec_msg_init(&msg, me, la);
534 cec_msg_request_short_audio_descriptor(&msg, true, 1, &audio_format_id, &audio_format_code);
535 fail_on_test(!transmit_timeout(node, &msg));
536 fail_on_test(timed_out(&msg));
537 if (unrecognized_op(&msg))
538 return OK_NOT_SUPPORTED;
539 if (refused(&msg))
540 return OK_REFUSED;
541 if (cec_msg_status_is_abort(&msg))
542 return OK_PRESUMED;
543 node->remote[la].has_sad = true;
544
545 return 0;
546 }
547
sac_request_sad_invalid(struct node * node,unsigned me,unsigned la,bool interactive)548 static int sac_request_sad_invalid(struct node *node, unsigned me, unsigned la, bool interactive)
549 {
550 if (!node->remote[la].has_sad)
551 return NOTAPPLICABLE;
552
553 struct cec_msg msg;
554 __u8 audio_format_id = CEC_OP_AUD_FMT_ID_CEA861;
555 __u8 audio_format_code = 63; // This is outside the range of CEA861-F
556
557 cec_msg_init(&msg, me, la);
558 cec_msg_request_short_audio_descriptor(&msg, true, 1, &audio_format_id, &audio_format_code);
559 fail_on_test(!transmit_timeout(node, &msg));
560 fail_on_test(timed_out(&msg));
561 fail_on_test(!cec_msg_status_is_abort(&msg));
562 if (abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP) {
563 warn("Expected Feature Abort [Invalid operand] in reply to Request Short\n");
564 warn("Audio Descriptor with invalid audio format as operand.\n");
565 }
566
567 return 0;
568 }
569
sac_sad_format_check(struct node * node,unsigned me,unsigned la,bool interactive)570 static int sac_sad_format_check(struct node *node, unsigned me, unsigned la, bool interactive)
571 {
572 if (!node->remote[la].has_sad)
573 return NOTAPPLICABLE;
574
575 struct cec_msg msg;
576 __u8 audio_format_id;
577 __u8 audio_format_code;
578
579 for (unsigned int id = 0; id <= 1; id++) {
580 audio_format_id = id;
581 for (unsigned int fmt_code = 1; fmt_code <= 14; fmt_code++) {
582 audio_format_code = fmt_code;
583
584 cec_msg_init(&msg, me, la);
585 cec_msg_request_short_audio_descriptor(&msg, true, 1, &audio_format_id, &audio_format_code);
586 fail_on_test(!transmit_timeout(node, &msg));
587 fail_on_test(timed_out(&msg));
588 fail_on_test(unrecognized_op(&msg) || refused(&msg));
589
590 if (cec_msg_status_is_abort(&msg) &&
591 abort_reason(&msg) == CEC_OP_ABORT_INVALID_OP)
592 continue;
593
594 __u8 num_descriptors;
595 __u32 descriptors[4] = {};
596
597 cec_ops_report_short_audio_descriptor(&msg, &num_descriptors, descriptors);
598 fail_on_test(num_descriptors == 0);
599 if (id == 1 && node->remote[la].cec_version < CEC_OP_CEC_VERSION_2_0)
600 warn("The device has CEC version < 2.0 but reports audio format(s) introduced in CEC 2.0.\n");
601
602 for (int j = 0; j < num_descriptors; j++) {
603 struct short_audio_desc sad = {};
604
605 sad_decode(&sad, descriptors[j]);
606 if ((id == 0 && sad.format_code != fmt_code) ||
607 (id == 1 && sad.extension_type_code != fmt_code))
608 return fail("Different audio format code reported than requested.\n");
609 info("Supports format %s\n", short_audio_desc2s(sad).c_str());
610
611 /* We need to store the ID and Code for one of the audio formats found,
612 for use in later test(s) */
613 node->remote[la].supp_format_id = audio_format_id;
614 node->remote[la].supp_format_code = audio_format_code;
615 }
616 }
617 }
618
619 return 0;
620 }
621
sac_sad_req_multiple(struct node * node,unsigned me,unsigned la,bool interactive)622 static int sac_sad_req_multiple(struct node *node, unsigned me, unsigned la, bool interactive)
623 {
624 if (!node->remote[la].has_sad || node->remote[la].supp_format_code == 0)
625 return NOTAPPLICABLE;
626
627 /* Check that if we got a response to a Request Short Audio Descriptor
628 with a single format, we also get a response when the same audio format
629 occurs in a request together with other formats. */
630 struct cec_msg msg;
631 __u8 audio_format_id[4] = { };
632 __u8 audio_format_code[4];
633
634 for (int i = 0; i < 4; i++) {
635 if (node->remote[la].supp_format_code <= 12)
636 audio_format_code[i] = node->remote[la].supp_format_code - 1 + i;
637 else
638 audio_format_code[i] = node->remote[la].supp_format_code - 1 - i;
639 }
640 cec_msg_init(&msg, me, la);
641 cec_msg_request_short_audio_descriptor(&msg, true, 4, audio_format_id, audio_format_code);
642 fail_on_test(!transmit_timeout(node, &msg));
643 fail_on_test(timed_out(&msg));
644 fail_on_test(cec_msg_status_is_abort(&msg));
645
646 return 0;
647 }
648
sac_set_system_audio_mode_direct(struct node * node,unsigned me,unsigned la,bool interactive)649 static int sac_set_system_audio_mode_direct(struct node *node, unsigned me, unsigned la, bool interactive)
650 {
651 struct cec_msg msg;
652
653 cec_msg_init(&msg, me, la);
654 cec_msg_set_system_audio_mode(&msg, CEC_OP_SYS_AUD_STATUS_ON);
655 fail_on_test(!transmit_timeout(node, &msg));
656 fail_on_test_v2(node->remote[la].cec_version,
657 unrecognized_op(&msg) && is_tv(la, node->remote[la].prim_type));
658 if (unrecognized_op(&msg))
659 return OK_NOT_SUPPORTED;
660 if (refused(&msg))
661 return OK_REFUSED;
662 node->remote[la].has_set_sys_audio_mode = true;
663
664 return OK_PRESUMED;
665 }
666
sac_set_system_audio_mode_broadcast_on(struct node * node,unsigned me,unsigned la,bool interactive)667 static int sac_set_system_audio_mode_broadcast_on(struct node *node, unsigned me, unsigned la, bool interactive)
668 {
669 struct cec_msg msg;
670
671 cec_msg_init(&msg, me, CEC_LOG_ADDR_BROADCAST);
672 cec_msg_set_system_audio_mode(&msg, CEC_OP_SYS_AUD_STATUS_ON);
673 fail_on_test(!transmit_timeout(node, &msg));
674
675 return OK_PRESUMED;
676 }
677
sac_system_audio_mode_status(struct node * node,unsigned me,unsigned la,bool interactive)678 static int sac_system_audio_mode_status(struct node *node, unsigned me, unsigned la, bool interactive)
679 {
680 struct cec_msg msg;
681
682 /* The device shall not feature abort System Audio Status if it did not
683 feature abort Set System Audio Mode.
684
685 The message is mandatory for TVs in CEC 2.0. */
686 cec_msg_init(&msg, me, la);
687 cec_msg_system_audio_mode_status(&msg, CEC_OP_SYS_AUD_STATUS_ON);
688 fail_on_test(!transmit_timeout(node, &msg));
689 fail_on_test_v2(node->remote[la].cec_version,
690 is_tv(la, node->remote[la].prim_type) && unrecognized_op(&msg));
691 if (unrecognized_op(&msg) && !node->remote[la].has_set_sys_audio_mode)
692 return OK_NOT_SUPPORTED;
693 fail_on_test(unrecognized_op(&msg));
694 if (refused(&msg))
695 return OK_REFUSED;
696 if (cec_msg_status_is_abort(&msg))
697 return OK_PRESUMED;
698
699 return 0;
700 }
701
sac_set_system_audio_mode_broadcast_off(struct node * node,unsigned me,unsigned la,bool interactive)702 static int sac_set_system_audio_mode_broadcast_off(struct node *node, unsigned me, unsigned la, bool interactive)
703 {
704 struct cec_msg msg;
705
706 cec_msg_init(&msg, me, CEC_LOG_ADDR_BROADCAST);
707 cec_msg_set_system_audio_mode(&msg, CEC_OP_SYS_AUD_STATUS_OFF);
708 fail_on_test(!transmit_timeout(node, &msg));
709
710 return OK_PRESUMED;
711 }
712
sac_system_audio_mode_req_on(struct node * node,unsigned me,unsigned la,bool interactive)713 static int sac_system_audio_mode_req_on(struct node *node, unsigned me, unsigned la, bool interactive)
714 {
715 struct cec_msg msg;
716 __u8 status;
717
718 /* Send a System Audio Mode Request to the audio system. This notifies the
719 audio system that our device has SAC capabilities, so it should enable
720 the feature right away by sending Set System Audio Mode with On as status.
721
722 The message is mandatory for audio systems in CEC 2.0. */
723 cec_msg_init(&msg, me, la);
724 cec_msg_system_audio_mode_request(&msg, true, node->phys_addr);
725 fail_on_test(!transmit_timeout(node, &msg));
726 fail_on_test(timed_out(&msg));
727 fail_on_test_v2(node->remote[la].cec_version,
728 cec_has_audiosystem(1 << la) && unrecognized_op(&msg));
729 if (unrecognized_op(&msg))
730 return OK_NOT_SUPPORTED;
731 if (refused(&msg))
732 return OK_REFUSED;
733 if (cec_msg_status_is_abort(&msg))
734 return OK_PRESUMED;
735 node->remote[la].has_sys_audio_mode_req = true;
736 cec_ops_set_system_audio_mode(&msg, &status);
737 fail_on_test(status != CEC_OP_SYS_AUD_STATUS_ON);
738
739 return 0;
740 }
741
sac_give_system_audio_mode_status(struct node * node,unsigned me,unsigned la,bool interactive)742 static int sac_give_system_audio_mode_status(struct node *node, unsigned me, unsigned la, bool interactive)
743 {
744 struct cec_msg msg;
745 __u8 system_audio_status;
746
747 /* The device shall not feature abort Give System Audio Mode Status if it did not
748 feature abort System Audio Mode Request.
749
750 The message is mandatory for audio systems in CEC 2.0. */
751 cec_msg_init(&msg, me, la);
752 cec_msg_give_system_audio_mode_status(&msg, true);
753 fail_on_test(!transmit_timeout(node, &msg));
754 fail_on_test(timed_out(&msg));
755 fail_on_test_v2(node->remote[la].cec_version,
756 cec_has_audiosystem(1 << la) && unrecognized_op(&msg));
757 if (unrecognized_op(&msg) && !node->remote[la].has_sys_audio_mode_req)
758 return OK_NOT_SUPPORTED;
759 fail_on_test(unrecognized_op(&msg));
760 if (refused(&msg))
761 return OK_REFUSED;
762 if (cec_msg_status_is_abort(&msg))
763 return OK_PRESUMED;
764 cec_ops_system_audio_mode_status(&msg, &system_audio_status);
765 fail_on_test(system_audio_status != CEC_OP_SYS_AUD_STATUS_ON);
766
767 return 0;
768 }
769
sac_give_audio_status(struct node * node,unsigned me,unsigned la,bool interactive)770 static int sac_give_audio_status(struct node *node, unsigned me, unsigned la, bool interactive)
771 {
772 struct cec_msg msg;
773
774 /* Give Audio Status is mandatory for audio systems in CEC 2.0, except
775 for systems that lack external controls for volume/mute status. */
776 cec_msg_init(&msg, me, la);
777 cec_msg_give_audio_status(&msg, true);
778 fail_on_test(!transmit_timeout(node, &msg));
779 fail_on_test(timed_out(&msg));
780 fail_on_test_v2(node->remote[la].cec_version,
781 cec_has_audiosystem(1 << la) && unrecognized_op(&msg));
782 if (unrecognized_op(&msg))
783 return OK_NOT_SUPPORTED;
784 if (refused(&msg))
785 return OK_REFUSED;
786 if (cec_msg_status_is_abort(&msg))
787 return OK_PRESUMED;
788
789 cec_ops_report_audio_status(&msg, &node->remote[la].mute, &node->remote[la].volume);
790 fail_on_test(node->remote[la].volume > 100);
791 info("Volume: %d %s\n", node->remote[la].volume, node->remote[la].mute ? "(muted)" : "");
792
793 return 0;
794 }
795
sac_util_send_user_control_press(struct node * node,unsigned me,unsigned la,__u8 ui_cmd)796 static int sac_util_send_user_control_press(struct node *node, unsigned me, unsigned la, __u8 ui_cmd)
797 {
798 struct cec_msg msg;
799 struct cec_op_ui_command rc_press = {};
800
801 /* The device shall not feature abort
802 - User Control Pressed ["Volume Up"]
803 - User Control Pressed ["Volume Down"]
804 - User Control Pressed ["Mute"]
805 if it did not feature abort System Audio Mode Request.
806
807 The messages are mandatory for audio systems and TVs in CEC 2.0,
808 and it is mandatory for audio systems to send Report Audio Status
809 back to the TV in CEC 2.0.
810
811 It is recommended for devices to not send Report Audio Status back
812 more often than once every 500ms. We therefore sleep a second before
813 each User Control Pressed is sent. */
814 bool got_response;
815
816 sleep(1);
817 mode_set_follower(node);
818 cec_msg_init(&msg, me, la);
819 rc_press.ui_cmd = ui_cmd;
820 cec_msg_user_control_pressed(&msg, &rc_press);
821 fail_on_test(!transmit(node, &msg));
822 cec_msg_init(&msg, me, la);
823 cec_msg_user_control_released(&msg);
824 fail_on_test(!transmit_timeout(node, &msg));
825 got_response = util_receive(node, la, 1000, &msg,
826 CEC_MSG_USER_CONTROL_PRESSED, CEC_MSG_REPORT_AUDIO_STATUS) >= 0;
827
828 fail_on_test_v2(node->remote[la].cec_version, !got_response &&
829 cec_has_audiosystem(1 << la));
830 fail_on_test_v2(node->remote[la].cec_version, unrecognized_op(&msg) &&
831 (is_tv(la, node->remote[la].prim_type) || cec_has_audiosystem(1 << la)));
832 if (unrecognized_op(&msg) && !node->remote[la].has_sys_audio_mode_req)
833 return OK_NOT_SUPPORTED;
834 fail_on_test(unrecognized_op(&msg));
835 if (refused(&msg))
836 return OK_REFUSED;
837 if (cec_msg_status_is_abort(&msg))
838 return OK_PRESUMED;
839 if (got_response) {
840 cec_ops_report_audio_status(&msg, &node->remote[la].mute, &node->remote[la].volume);
841 return 0;
842 }
843
844 return OK_PRESUMED;
845 }
846
sac_user_control_press_vol_up(struct node * node,unsigned me,unsigned la,bool interactive)847 static int sac_user_control_press_vol_up(struct node *node, unsigned me, unsigned la, bool interactive)
848 {
849 __u8 ret, old_volume = node->remote[la].volume;
850
851 if ((ret = sac_util_send_user_control_press(node, me, la, 0x41)))
852 return ret;
853 /* Check that if not already at the highest, the volume was increased. */
854 fail_on_test_v2(node->remote[la].cec_version,
855 la == CEC_LOG_ADDR_AUDIOSYSTEM &&
856 old_volume < 100 && node->remote[la].volume <= old_volume);
857
858 return 0;
859 }
860
sac_user_control_press_vol_down(struct node * node,unsigned me,unsigned la,bool interactive)861 static int sac_user_control_press_vol_down(struct node *node, unsigned me, unsigned la, bool interactive)
862 {
863 __u8 ret, old_volume = node->remote[la].volume;
864
865 if ((ret = sac_util_send_user_control_press(node, me, la, 0x42)))
866 return ret;
867 /* Check that if not already at the lowest, the volume was lowered. */
868 fail_on_test_v2(node->remote[la].cec_version,
869 la == CEC_LOG_ADDR_AUDIOSYSTEM &&
870 old_volume > 0 && node->remote[la].volume >= old_volume);
871
872 return 0;
873 }
874
sac_user_control_press_mute(struct node * node,unsigned me,unsigned la,bool interactive)875 static int sac_user_control_press_mute(struct node *node, unsigned me, unsigned la, bool interactive)
876 {
877 __u8 ret, old_mute = node->remote[la].mute;
878
879 if ((ret = sac_util_send_user_control_press(node, me, la, 0x43)))
880 return ret;
881 /* Check that mute has been toggled from what it was before. */
882 fail_on_test_v2(node->remote[la].cec_version,
883 la == CEC_LOG_ADDR_AUDIOSYSTEM &&
884 node->remote[la].mute == old_mute);
885
886 return 0;
887 }
888
sac_user_control_press_mute_function(struct node * node,unsigned me,unsigned la,bool interactive)889 static int sac_user_control_press_mute_function(struct node *node, unsigned me, unsigned la, bool interactive)
890 {
891 __u8 ret;
892
893 if ((ret = sac_util_send_user_control_press(node, me, la, 0x65)))
894 return ret;
895 fail_on_test_v2(node->remote[la].cec_version,
896 la == CEC_LOG_ADDR_AUDIOSYSTEM &&
897 node->remote[la].mute == CEC_OP_AUD_MUTE_STATUS_ON);
898
899 return 0;
900 }
901
sac_user_control_press_restore_volume_function(struct node * node,unsigned me,unsigned la,bool interactive)902 static int sac_user_control_press_restore_volume_function(struct node *node, unsigned me, unsigned la, bool interactive)
903 {
904 __u8 ret;
905
906 if ((ret = sac_util_send_user_control_press(node, me, la, 0x66)))
907 return ret;
908 fail_on_test_v2(node->remote[la].cec_version,
909 la == CEC_LOG_ADDR_AUDIOSYSTEM &&
910 node->remote[la].mute == CEC_OP_AUD_MUTE_STATUS_OFF);
911
912 return 0;
913 }
914
sac_user_control_release(struct node * node,unsigned me,unsigned la,bool interactive)915 static int sac_user_control_release(struct node *node, unsigned me, unsigned la, bool interactive)
916 {
917 struct cec_msg msg;
918
919 /* The device shall not feature abort User Control Released if it did not
920 feature abort System Audio Mode Request
921
922 The message is mandatory for audio systems and TVs in CEC 2.0. */
923 cec_msg_init(&msg, me, la);
924 cec_msg_user_control_released(&msg);
925 fail_on_test(!transmit_timeout(node, &msg));
926 fail_on_test_v2(node->remote[la].cec_version, unrecognized_op(&msg) &&
927 (is_tv(la, node->remote[la].prim_type) || cec_has_audiosystem(1 << la)));
928 if (unrecognized_op(&msg) && !node->remote[la].has_sys_audio_mode_req)
929 return OK_NOT_SUPPORTED;
930 fail_on_test(unrecognized_op(&msg));
931 if (refused(&msg))
932 return OK_REFUSED;
933 if (cec_msg_status_is_abort(&msg))
934 return OK_PRESUMED;
935
936 return OK_PRESUMED;
937 }
938
sac_system_audio_mode_req_off(struct node * node,unsigned me,unsigned la,bool interactive)939 static int sac_system_audio_mode_req_off(struct node *node, unsigned me, unsigned la, bool interactive)
940 {
941 if (!node->remote[la].has_sys_audio_mode_req)
942 return NOTAPPLICABLE;
943
944 struct cec_msg msg;
945 __u8 status;
946
947 cec_msg_init(&msg, me, la);
948 cec_msg_system_audio_mode_request(&msg, true, CEC_PHYS_ADDR_INVALID);
949 fail_on_test(!transmit_timeout(node, &msg));
950 fail_on_test(timed_out(&msg));
951 fail_on_test_v2(node->remote[la].cec_version,
952 cec_has_audiosystem(1 << la) && unrecognized_op(&msg));
953 if (unrecognized_op(&msg))
954 return OK_NOT_SUPPORTED;
955 if (refused(&msg))
956 return OK_REFUSED;
957 if (cec_msg_status_is_abort(&msg))
958 return OK_PRESUMED;
959 cec_ops_set_system_audio_mode(&msg, &status);
960 fail_on_test(status != CEC_OP_SYS_AUD_STATUS_OFF);
961
962 return 0;
963 }
964
965 const vec_remote_subtests sac_subtests{
966 {
967 "Request Short Audio Descriptor",
968 CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
969 sac_request_sad_probe,
970 },
971 {
972 "Request Short Audio Descriptor, invalid",
973 CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
974 sac_request_sad_invalid,
975 },
976 {
977 "Report Short Audio Descriptor consistency",
978 CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
979 sac_sad_format_check,
980 },
981 {
982 "Report Short Audio Descriptor, multiple requests in one",
983 CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
984 sac_sad_req_multiple,
985 },
986 {
987 "Set System Audio Mode (directly addressed)",
988 CEC_LOG_ADDR_MASK_TV,
989 sac_set_system_audio_mode_direct,
990 },
991 {
992 "Set System Audio Mode (broadcast on)",
993 CEC_LOG_ADDR_MASK_TV,
994 sac_set_system_audio_mode_broadcast_on,
995 },
996 {
997 "System Audio Mode Status",
998 CEC_LOG_ADDR_MASK_TV,
999 sac_system_audio_mode_status,
1000 },
1001 {
1002 "System Audio Mode Request (on)",
1003 CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
1004 sac_system_audio_mode_req_on,
1005 },
1006 {
1007 "Give System Audio Mode Status",
1008 CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
1009 sac_give_system_audio_mode_status,
1010 },
1011 {
1012 "Give Audio Status",
1013 CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
1014 sac_give_audio_status,
1015 },
1016 {
1017 "User Control Pressed (Volume Up)",
1018 CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
1019 sac_user_control_press_vol_up,
1020 },
1021 {
1022 "User Control Pressed (Volume Down)",
1023 CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
1024 sac_user_control_press_vol_down,
1025 },
1026 {
1027 "User Control Pressed (Mute)",
1028 CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
1029 sac_user_control_press_mute,
1030 },
1031 {
1032 "User Control Pressed (Restore Volume Function)",
1033 CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
1034 sac_user_control_press_restore_volume_function,
1035 },
1036 {
1037 "User Control Pressed (Mute Function)",
1038 CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
1039 sac_user_control_press_mute_function,
1040 },
1041 {
1042 "User Control Released (Audio)",
1043 CEC_LOG_ADDR_MASK_AUDIOSYSTEM | CEC_LOG_ADDR_MASK_TV,
1044 sac_user_control_release,
1045 },
1046 {
1047 "Set System Audio Mode (broadcast off)",
1048 CEC_LOG_ADDR_MASK_TV,
1049 sac_set_system_audio_mode_broadcast_off,
1050 },
1051 {
1052 "System Audio Mode Request (off)",
1053 CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
1054 sac_system_audio_mode_req_off,
1055 },
1056 };
1057
1058 /* Audio Rate Control */
1059
audio_rate_ctl_set_audio_rate(struct node * node,unsigned me,unsigned la,bool interactive)1060 static int audio_rate_ctl_set_audio_rate(struct node *node, unsigned me, unsigned la, bool interactive)
1061 {
1062 struct cec_msg msg;
1063
1064 cec_msg_init(&msg, me, la);
1065 cec_msg_set_audio_rate(&msg, CEC_OP_AUD_RATE_WIDE_STD);
1066 fail_on_test(!transmit_timeout(node, &msg));
1067 /* CEC 2.0: Devices shall use the device feature bit to indicate support. */
1068 fail_on_test_v2(node->remote[la].cec_version,
1069 node->remote[la].has_aud_rate && unrecognized_op(&msg));
1070 fail_on_test_v2(node->remote[la].cec_version,
1071 !node->remote[la].has_aud_rate && !unrecognized_op(&msg));
1072 if (unrecognized_op(&msg))
1073 return OK_NOT_SUPPORTED;
1074 if (refused(&msg))
1075 return OK_REFUSED;
1076
1077 return OK_PRESUMED;
1078 }
1079
audio_rate_ctl_active_sensing(struct node * node,unsigned me,unsigned la,bool interactive)1080 static int audio_rate_ctl_active_sensing(struct node *node, unsigned me, unsigned la, bool interactive)
1081 {
1082 /*
1083 * The source shall go back to Rate Control Off if no Set Audio Rate message is
1084 * received for more than 2 seconds.
1085 */
1086 if (!node->remote[la].has_aud_rate)
1087 return NOTAPPLICABLE;
1088
1089 struct cec_msg msg;
1090
1091 cec_msg_init(&msg, me, la);
1092
1093 /*
1094 * Since this subtest runs immediately after Set Audio Rate, delaying the interval
1095 * between the two tests is sufficient to test that the Source turns off rate control.
1096 */
1097 sleep(3);
1098 cec_msg_set_audio_rate(&msg, CEC_OP_AUD_RATE_OFF);
1099 fail_on_test(!transmit_timeout(node, &msg));
1100 fail_on_test_v2(node->remote[la].cec_version, unrecognized_op(&msg));
1101 return OK_PRESUMED;
1102 }
1103
audio_rate_ctl_invalid(struct node * node,unsigned me,unsigned la,bool interactive)1104 static int audio_rate_ctl_invalid(struct node *node, unsigned me, unsigned la, bool interactive)
1105 {
1106 if (!node->remote[la].has_aud_rate)
1107 return NOTAPPLICABLE;
1108
1109 struct cec_msg msg;
1110
1111 cec_msg_init(&msg, me, la);
1112 cec_msg_set_audio_rate(&msg, 0xa); /* Invalid Audio Rate Control message operand */
1113 fail_on_test(!transmit_timeout(node, &msg));
1114 fail_on_test(timed_out(&msg));
1115 fail_on_test(!cec_msg_status_is_abort(&msg));
1116 if (abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP) {
1117 warn("Expected Feature Abort [Invalid operand]\n");
1118 return FAIL;
1119 }
1120 return OK;
1121 }
1122
1123 const vec_remote_subtests audio_rate_ctl_subtests{
1124 {
1125 "Set Audio Rate",
1126 CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD |
1127 CEC_LOG_ADDR_MASK_TUNER | CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
1128 audio_rate_ctl_set_audio_rate,
1129 },
1130 {
1131 "Audio Rate Active Sensing",
1132 CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD |
1133 CEC_LOG_ADDR_MASK_TUNER | CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
1134 audio_rate_ctl_active_sensing,
1135 },
1136 {
1137 "Audio Rate Invalid Operand",
1138 CEC_LOG_ADDR_MASK_PLAYBACK | CEC_LOG_ADDR_MASK_RECORD |
1139 CEC_LOG_ADDR_MASK_TUNER | CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
1140 audio_rate_ctl_invalid,
1141 },
1142 };
1143