• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * CEC API compliance test tool.
4  *
5  * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6  */
7 
8 #ifndef _CEC_COMPLIANCE_H_
9 #define _CEC_COMPLIANCE_H_
10 
11 #include <linux/cec-funcs.h>
12 #include "cec-htng-funcs.h"
13 
14 #include <cec-info.h>
15 
16 #include <vector>
17 
18 #define TAG_AUDIO_RATE_CONTROL		1
19 #define TAG_ARC_CONTROL 		(1 << 1)
20 #define TAG_CAP_DISCOVERY_CONTROL 	(1 << 2)
21 #define TAG_DECK_CONTROL 		(1 << 3)
22 #define TAG_DEVICE_MENU_CONTROL 	(1 << 4)
23 #define TAG_DEVICE_OSD_TRANSFER 	(1 << 5)
24 #define TAG_DYNAMIC_AUTO_LIPSYNC 	(1 << 6)
25 #define TAG_OSD_DISPLAY 		(1 << 7)
26 #define TAG_ONE_TOUCH_PLAY 		(1 << 8)
27 #define TAG_ONE_TOUCH_RECORD 		(1 << 9)
28 #define TAG_POWER_STATUS 		(1 << 10)
29 #define TAG_REMOTE_CONTROL_PASSTHROUGH	(1 << 11)
30 #define TAG_ROUTING_CONTROL 		(1 << 12)
31 #define TAG_SYSTEM_AUDIO_CONTROL 	(1 << 13)
32 #define TAG_SYSTEM_INFORMATION		(1 << 14)
33 #define TAG_TIMER_PROGRAMMING 		(1 << 15)
34 #define TAG_TUNER_CONTROL 		(1 << 16)
35 #define TAG_VENDOR_SPECIFIC_COMMANDS 	(1 << 17)
36 #define TAG_STANDBY_RESUME		(1 << 18)
37 
38 #define TAG_INTERACTIVE		(1 << 19)
39 #define TAG_CORE 0
40 #define TAG_ALL (~TAG_INTERACTIVE)
41 
42 #define NUM_TAGS 21
43 
44 struct short_audio_desc {
45 	/* Byte 1 */
46 	__u8 num_channels;
47 	__u8 format_code;
48 
49 	/* Byte 2 */
50 	__u8 sample_freq_mask;
51 
52 	/* Byte 3 */
53 	union {
54 		__u8 bit_depth_mask;    // LPCM
55 		__u8 max_bitrate;       // Format codes 2-8
56 		__u8 format_dependent;  // Format codes 9-13
57 		__u8 wma_profile;       // WMA Pro
58 		__u8 frame_length_mask; // Extension type codes 4-6, 8-10
59 	};
60 	__u8 mps;                       // Format codes 8-10
61 	__u8 extension_type_code;
62 };
63 
64 #define SAD_FMT_CODE_LPCM 		1
65 #define SAD_FMT_CODE_AC3		2
66 #define SAD_FMT_CODE_MPEG1		3
67 #define SAD_FMT_CODE_MP3 		4
68 #define SAD_FMT_CODE_MPEG2 		5
69 #define SAD_FMT_CODE_AAC_LC 		6
70 #define SAD_FMT_CODE_DTS 		7
71 #define SAD_FMT_CODE_ATRAC 		8
72 #define SAD_FMT_CODE_ONE_BIT_AUDIO	9
73 #define SAD_FMT_CODE_ENHANCED_AC3	10
74 #define SAD_FMT_CODE_DTS_HD 		11
75 #define SAD_FMT_CODE_MAT 		12
76 #define SAD_FMT_CODE_DST 		13
77 #define SAD_FMT_CODE_WMA_PRO 		14
78 #define SAD_FMT_CODE_EXTENDED 		15
79 
80 #define SAD_BIT_DEPTH_MASK_16 		1
81 #define SAD_BIT_DEPTH_MASK_20 		(1 << 1)
82 #define SAD_BIT_DEPTH_MASK_24 		(1 << 2)
83 
84 #define SAD_SAMPLE_FREQ_MASK_32 	1
85 #define SAD_SAMPLE_FREQ_MASK_44_1 	(1 << 1)
86 #define SAD_SAMPLE_FREQ_MASK_48 	(1 << 2)
87 #define SAD_SAMPLE_FREQ_MASK_88_2 	(1 << 3)
88 #define SAD_SAMPLE_FREQ_MASK_96 	(1 << 4)
89 #define SAD_SAMPLE_FREQ_MASK_176_4 	(1 << 5)
90 #define SAD_SAMPLE_FREQ_MASK_192 	(1 << 6)
91 
92 #define SAD_FRAME_LENGTH_MASK_960 	1
93 #define SAD_FRAME_LENGTH_MASK_1024	(1 << 1)
94 
95 #define SAD_EXT_TYPE_MPEG4_HE_AAC 		4
96 #define SAD_EXT_TYPE_MPEG4_HE_AACv2 		5
97 #define SAD_EXT_TYPE_MPEG4_AAC_LC 		6
98 #define SAD_EXT_TYPE_DRA 			7
99 #define SAD_EXT_TYPE_MPEG4_HE_AAC_SURROUND 	8
100 #define SAD_EXT_TYPE_MPEG4_AAC_LC_SURROUND	10
101 #define SAD_EXT_TYPE_MPEG_H_3D_AUDIO		11
102 #define SAD_EXT_TYPE_AC_4			12
103 #define SAD_EXT_TYPE_LPCM_3D_AUDIO		13
104 
105 extern bool show_info;
106 extern bool show_colors;
107 extern bool show_warnings;
108 extern bool exit_on_fail;
109 extern bool exit_on_warn;
110 extern unsigned warnings;
111 extern unsigned reply_threshold;
112 extern time_t long_timeout;
113 
114 struct remote {
115 	bool recognized_op[256];
116 	bool unrecognized_op[256];
117 	unsigned prim_type;
118 	__u16 phys_addr;
119 	char osd_name[15];
120 	char language[4];
121 	__u8 cec_version;
122 	__u8 rc_profile;
123 	__u8 dev_features;
124 	__u8 all_device_types;
125 	__u32 vendor_id;
126 	bool has_osd;
127 	bool has_power_status;
128 	bool has_image_view_on;
129 	bool has_text_view_on;
130 	bool in_standby;
131 	bool has_remote_control_passthrough;
132 	bool source_has_arc_rx;
133 	bool sink_has_arc_tx;
134 	bool arc_initiated;
135 	bool has_sys_audio_mode_req;
136 	bool has_set_sys_audio_mode;
137 	bool has_sad;
138 	__u8 supp_format_id;
139 	__u8 supp_format_code;
140 	__u8 volume;
141 	__u8 mute;
142 	bool has_aud_rate;
143 	bool has_deck_ctl;
144 	bool has_analogue_timer;
145 	__u8 bcast_sys;
146 	__u8 dig_bcast_sys;
147 	bool has_rec_tv;
148 	bool has_cdc;
149 };
150 
151 struct node {
152 	int fd;
153 	const char *device;
154 	bool has_cec20;
155 	unsigned caps;
156 	unsigned available_log_addrs;
157 	unsigned num_log_addrs;
158 	unsigned adap_la_mask;
159 	__u8 log_addr[CEC_MAX_LOG_ADDRS];
160 	unsigned remote_la_mask;
161 	struct remote remote[16];
162 	__u16 phys_addr;
163 	bool in_standby;
164 	__u8 prim_devtype;
165 	time_t current_time;
166 };
167 
168 struct remote_subtest {
169 	const char *name;
170 	const __u16 la_mask;
171 	int (*const test_fn)(struct node *node, unsigned me, unsigned la, bool interactive);
172 	bool in_standby;
173 	bool for_cec20;
174 };
175 
176 using vec_remote_subtests = std::vector<remote_subtest>;
177 
178 #ifndef __FILE_NAME__
179 #define __FILE_NAME__ __FILE__
180 #endif
181 
182 #define OK			0
183 #define FAIL			1
184 #define OK_PRESUMED		2
185 #define OK_NOT_SUPPORTED	3
186 #define OK_REFUSED		4
187 #define OK_UNEXPECTED		5
188 #define OK_EXPECTED_FAIL	6
189 #define NOTAPPLICABLE		7
190 #define FAIL_CRITICAL		8
191 #define DONT_CARE		255
192 
193 #define CEC_LOG_ADDR_MASK_ALL 0xffff
194 
195 #define COLOR_GREEN(s) "\033[32m" s "\033[0m"
196 #define COLOR_RED(s) "\033[1;31m" s "\033[0m"
197 #define COLOR_BOLD(s) "\033[1m" s "\033[0m"
198 
199 #define info(fmt, args...) 						\
200 	do {								\
201 		if (show_info)						\
202 			printf("\t\tinfo: " fmt, ##args);		\
203 	} while (0)
204 
205 #define announce(fmt, args...) 						\
206 	do {								\
207 		printf("\t\t>>> " fmt "\n", ##args);			\
208 	} while (0)
209 
210 #define interactive_info(block, fmt, args...)				\
211 	do {								\
212 		if (interactive) {					\
213 			printf("\t\t>>> " fmt "\n", ##args);		\
214 			if (block) {					\
215 				printf("\t\t>>> Press ENTER to proceed.\n"); \
216 				getchar();				\
217 			}						\
218 		}							\
219 	} while(0)
220 
221 #define warn(fmt, args...) 						\
222 ({									\
223 	warnings++;							\
224 	if (show_warnings)						\
225 		printf("\t\%s: %s(%d): " fmt,				\
226 		       show_colors ? COLOR_BOLD("warn") : "warn",	\
227 		       __FILE_NAME__, __LINE__, ##args);			\
228 	if (exit_on_warn)						\
229 		std::exit(EXIT_FAILURE);				\
230 	0;								\
231 })
232 
233 #define warn_once(fmt, args...)						\
234 	do {								\
235 		static bool show;					\
236 									\
237 		if (!show) {						\
238 			show = true;					\
239 			warn(fmt, ##args);				\
240 		}							\
241 	} while (0)
242 
243 #define warn_on_test(test) 						\
244 	do {								\
245 		if (test)						\
246 			warn("%s\n", #test);				\
247 	} while (0)
248 
249 #define warn_once_on_test(test) 					\
250 	do {								\
251 		if (test)						\
252 			warn_once("%s\n", #test);			\
253 	} while (0)
254 
255 #define fail(fmt, args...) 						\
256 ({ 									\
257 	printf("\t\t%s: %s(%d): " fmt, show_colors ?			\
258 	       COLOR_RED("fail") : "fail", __FILE_NAME__, __LINE__, ##args);	\
259 	if (exit_on_fail)						\
260 		std::exit(EXIT_FAILURE);				\
261 	FAIL;								\
262 })
263 
264 #define fail_once(fmt, args...)						\
265 	do {								\
266 		static bool show;					\
267 									\
268 		if (!show) {						\
269 			show = true;					\
270 			fail(fmt, ##args);				\
271 		}							\
272 	} while (0)
273 
274 #define fail_or_warn(node, fmt, args...)				\
275 ({									\
276  	if ((node)->in_standby)						\
277 		warn(fmt, ##args);					\
278 	else								\
279 		fail(fmt, ##args);					\
280 	(node)->in_standby ? 0 : FAIL;					\
281 })
282 
283 #define fail_on_test(test) 						\
284 	do {								\
285 		if (test)						\
286 			return fail("%s\n", #test);			\
287 	} while (0)
288 
289 #define fail_on_test_v2(version, test) fail_on_test(version >= CEC_OP_CEC_VERSION_2_0 && (test))
290 
291 #define fail_on_test_v2_warn(version, test)				\
292 	do {								\
293 		if (test) {						\
294 			if (version >= CEC_OP_CEC_VERSION_2_0)		\
295 				return fail("%s\n", #test);		\
296 			else						\
297 				warn("fails in CEC 2.0: %s\n", #test);	\
298 		}							\
299 	} while(0)
300 
get_yn()301 static inline char get_yn()
302 {
303 	char c;
304 
305 	while ((c = tolower(getchar())) != 'y' && c != 'n');
306 	getchar();
307 	return c;
308 }
309 
question(const char * prompt)310 static inline bool question(const char* prompt)
311 {
312 	printf("\t\t>>> %s (y/n) ", prompt);
313 	return get_yn() == 'y';
314 }
315 
316 int cec_named_ioctl(struct node *node, const char *name,
317 		    unsigned long int request, void *parm);
318 
319 #define doioctl(n, r, p) cec_named_ioctl(n, #r, r, p)
320 
321 const char *opcode2s(__u8 opcode);
322 std::string opcode2s(const struct cec_msg *msg);
323 
is_tv(unsigned la,unsigned prim_type)324 static inline bool is_tv(unsigned la, unsigned prim_type)
325 {
326 	return cec_has_tv(1 << la) ||
327 		(cec_has_specific(1 << la) && prim_type == CEC_OP_PRIM_DEVTYPE_TV);
328 }
329 
is_playback_or_rec(unsigned la)330 static inline bool is_playback_or_rec(unsigned la)
331 {
332 	return cec_has_playback(1 << la) || cec_has_record(1 << la);
333 }
334 
cec_msg_status_is_abort(const struct cec_msg * msg)335 static inline bool cec_msg_status_is_abort(const struct cec_msg *msg)
336 {
337 	return msg->rx_status & CEC_RX_STATUS_FEATURE_ABORT;
338 }
339 
abort_reason(const struct cec_msg * msg)340 static inline __u8 abort_reason(const struct cec_msg *msg)
341 {
342 	return msg->msg[3];
343 }
344 
unrecognized_op(const struct cec_msg * msg)345 static inline bool unrecognized_op(const struct cec_msg *msg)
346 {
347 	if (!cec_msg_status_is_abort(msg))
348 		return false;
349 	if (abort_reason(msg) == CEC_OP_ABORT_UNRECOGNIZED_OP)
350 		return true;
351 	if (abort_reason(msg) == CEC_OP_ABORT_UNDETERMINED) {
352 		warn("Opcode %x was undetermined and is treated as not supported.\n", msg->msg[2]);
353 		return true;
354 	}
355 	return false;
356 }
357 
refused(const struct cec_msg * msg)358 static inline bool refused(const struct cec_msg *msg)
359 {
360 	return cec_msg_status_is_abort(msg) && abort_reason(msg) == CEC_OP_ABORT_REFUSED;
361 }
362 
incorrect_mode(const struct cec_msg * msg)363 static inline bool incorrect_mode(const struct cec_msg *msg)
364 {
365 	return cec_msg_status_is_abort(msg) && abort_reason(msg) == CEC_OP_ABORT_INCORRECT_MODE;
366 }
367 
timed_out(const struct cec_msg * msg)368 static inline bool timed_out(const struct cec_msg *msg)
369 {
370 	return msg->rx_status & CEC_RX_STATUS_TIMEOUT;
371 }
372 
timed_out_or_abort(const struct cec_msg * msg)373 static inline bool timed_out_or_abort(const struct cec_msg *msg)
374 {
375 	return timed_out(msg) || cec_msg_status_is_abort(msg);
376 }
377 
response_time_ms(const struct cec_msg * msg)378 static inline unsigned response_time_ms(const struct cec_msg *msg)
379 {
380 	unsigned ms = (msg->rx_ts - msg->tx_ts) / 1000000;
381 
382 	// Compensate for the time it took (approx.) to receive the
383 	// message.
384 	if (ms >= msg->len * 24)
385 		return ms - msg->len * 24;
386 	return 0;
387 }
388 
389 bool transmit_timeout(struct node *node, struct cec_msg *msg,
390 		      unsigned timeout = 2000);
391 
transmit(struct node * node,struct cec_msg * msg)392 static inline bool transmit(struct node *node, struct cec_msg *msg)
393 {
394 	return transmit_timeout(node, msg, 0);
395 }
396 
mode_set_follower(struct node * node)397 static inline void mode_set_follower(struct node *node)
398 {
399 	__u32 mode = CEC_MODE_INITIATOR | CEC_MODE_FOLLOWER;
400 
401 	doioctl(node, CEC_S_MODE, &mode);
402 }
403 
mode_set_initiator(struct node * node)404 static inline void mode_set_initiator(struct node *node)
405 {
406 	__u32 mode = CEC_MODE_INITIATOR;
407 
408 	doioctl(node, CEC_S_MODE, &mode);
409 }
410 
get_ts_ms()411 static inline unsigned get_ts_ms()
412 {
413 	struct timespec timespec;
414 
415 	clock_gettime(CLOCK_MONOTONIC, &timespec);
416 	return timespec.tv_sec * 1000ull + timespec.tv_nsec / 1000000;
417 }
418 
419 const char *result_name(int res, bool show_colors);
420 const char *ok(int res);
421 const char *power_status2s(__u8 power_status);
422 const char *bcast_system2s(__u8 bcast_system);
423 const char *dig_bcast_system2s(__u8 bcast_system);
424 int check_0(const void *p, int len);
425 int util_receive(struct node *node, unsigned la, unsigned timeout,
426 		 struct cec_msg *msg, __u8 sent_msg,
427 		 __u8 reply1, __u8 reply2 = 0);
428 std::string safename(const char *name);
429 std::string current_ts();
430 
431 // CEC adapter tests
432 void testAdapter(struct node &node, struct cec_log_addrs &laddrs,
433 		 const char *device);
434 
435 // CEC fuzzing test
436 int testFuzzing(struct node &node, unsigned me, unsigned la);
437 
438 // CEC core tests
439 int testCore(struct node *node);
440 int core_unknown(struct node *node, unsigned me, unsigned la, bool interactive);
441 int core_abort(struct node *node, unsigned me, unsigned la, bool interactive);
442 int system_info_polling(struct node *node, unsigned me, unsigned la, bool interactive);
443 int system_info_phys_addr(struct node *node, unsigned me, unsigned la, bool interactive);
444 int system_info_version(struct node *node, unsigned me, unsigned la, bool interactive);
445 int system_info_get_menu_lang(struct node *node, unsigned me, unsigned la, bool interactive);
446 int system_info_give_features(struct node *node, unsigned me, unsigned la, bool interactive);
447 int vendor_specific_commands_id(struct node *node, unsigned me, unsigned la, bool interactive);
448 int device_osd_transfer_give(struct node *node, unsigned me, unsigned la, bool interactive);
449 
450 // CEC processing
451 int testProcessing(struct node *node, unsigned me);
452 
453 // CEC testing
454 void collectTests(void);
455 void listTests(void);
456 int setExpectedResult(char *optarg, bool no_warnings);
457 void testRemote(struct node *node, unsigned me, unsigned la, unsigned test_tags,
458 			     bool interactive, bool show_ts);
459 
460 // cec-test-tuner-record-timer.cpp
461 extern const vec_remote_subtests tuner_ctl_subtests;
462 extern const vec_remote_subtests one_touch_rec_subtests;
463 extern const vec_remote_subtests timer_prog_subtests;
464 
465 // cec-test-audio.cpp
466 extern const vec_remote_subtests sac_subtests;
467 extern const vec_remote_subtests dal_subtests;
468 extern const vec_remote_subtests arc_subtests;
469 extern const vec_remote_subtests audio_rate_ctl_subtests;
470 
471 // cec-test-power.cpp
472 bool util_interactive_ensure_power_state(struct node *node, unsigned me, unsigned la, bool interactive,
473 					 __u8 target_pwr);
474 int standby_resume_wakeup(struct node *node, unsigned me, unsigned la, bool interactive);
475 extern const vec_remote_subtests standby_subtests;
476 extern const vec_remote_subtests one_touch_play_subtests;
477 extern const vec_remote_subtests power_status_subtests;
478 extern const vec_remote_subtests standby_resume_subtests;
479 
480 #endif
481