1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2 /*
3 * CEC API follower test tool.
4 *
5 * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
6 */
7
8 #ifndef _CEC_FOLLOWER_H_
9 #define _CEC_FOLLOWER_H_
10
11 #include <stdarg.h>
12 #include <ctime>
13 #include <cerrno>
14 #include <string>
15 #include <linux/cec-funcs.h>
16 #include "cec-htng-funcs.h"
17
18 #ifdef ANDROID
19 #include <android-config.h>
20 #else
21 #include <config.h>
22 #endif
23
24 #include <cec-info.h>
25 #include <cec-log.h>
26
27 #define ARRAY_SIZE(a) \
28 (sizeof(a) / sizeof(*a))
29
30 extern bool show_info;
31 extern bool show_msgs;
32 extern bool show_state;
33 extern bool show_warnings;
34 extern unsigned warnings;
35
36 struct state {
37 uint16_t active_source_pa;
38 uint8_t old_power_status;
39 uint8_t power_status;
40 time_t power_status_changed_time;
41 char menu_language[4];
42 uint8_t video_latency;
43 uint8_t low_latency_mode;
44 uint8_t audio_out_compensated;
45 uint8_t audio_out_delay;
46 bool arc_active;
47 bool sac_active;
48 uint8_t volume;
49 bool mute;
50 unsigned rc_state;
51 uint8_t rc_ui_cmd;
52 uint64_t rc_press_rx_ts;
53 unsigned rc_press_hold_count;
54 unsigned rc_duration_sum;
55 struct cec_op_tuner_device_info tuner_dev_info;
56 unsigned int service_idx;
57 bool service_by_dig_id;
58 bool tuner_report_changes;
59 bool deck_report_changes;
60 };
61
62 struct node {
63 int fd;
64 const char *device;
65 unsigned caps;
66 unsigned available_log_addrs;
67 unsigned adap_la_mask;
68 unsigned remote_la_mask;
69 uint16_t remote_phys_addr[15];
70 struct state state;
71 uint16_t phys_addr;
72 uint8_t cec_version;
73 bool source_has_arc_rx;
74 bool sink_has_arc_tx;
75 bool has_aud_rate;
76 bool has_deck_ctl;
77 bool has_rec_tv;
78 bool has_osd_string;
79
80 bool ignore_la[16];
81 unsigned short ignore_opcode[256];
82 };
83
84 struct la_info {
85 uint64_t ts;
86 struct {
87 unsigned count;
88 uint64_t ts;
89 } feature_aborted[256];
90 uint16_t phys_addr;
91 };
92
93 extern struct la_info la_info[15];
94
95 struct short_audio_desc {
96 /* Byte 1 */
97 uint8_t num_channels;
98 uint8_t format_code;
99
100 /* Byte 2 */
101 uint8_t sample_freq_mask;
102
103 /* Byte 3 */
104 union {
105 uint8_t bit_depth_mask; // LPCM
106 uint8_t max_bitrate; // Format codes 2-8
107 uint8_t format_dependent; // Format codes 9-13
108 uint8_t wma_profile; // WMA Pro
109 uint8_t frame_length_mask; // Extension type codes 4-6, 8-10
110 };
111 uint8_t mps; // Format codes 8-10
112 uint8_t extension_type_code;
113 };
114
115 #define SAD_FMT_CODE_LPCM 1
116 #define SAD_FMT_CODE_AC3 2
117 #define SAD_FMT_CODE_MPEG1 3
118 #define SAD_FMT_CODE_MP3 4
119 #define SAD_FMT_CODE_MPEG2 5
120 #define SAD_FMT_CODE_AAC_LC 6
121 #define SAD_FMT_CODE_DTS 7
122 #define SAD_FMT_CODE_ATRAC 8
123 #define SAD_FMT_CODE_ONE_BIT_AUDIO 9
124 #define SAD_FMT_CODE_ENHANCED_AC3 10
125 #define SAD_FMT_CODE_DTS_HD 11
126 #define SAD_FMT_CODE_MAT 12
127 #define SAD_FMT_CODE_DST 13
128 #define SAD_FMT_CODE_WMA_PRO 14
129 #define SAD_FMT_CODE_EXTENDED 15
130
131 #define SAD_BIT_DEPTH_MASK_16 1
132 #define SAD_BIT_DEPTH_MASK_20 (1 << 1)
133 #define SAD_BIT_DEPTH_MASK_24 (1 << 2)
134
135 #define SAD_SAMPLE_FREQ_MASK_32 1
136 #define SAD_SAMPLE_FREQ_MASK_44_1 (1 << 1)
137 #define SAD_SAMPLE_FREQ_MASK_48 (1 << 2)
138 #define SAD_SAMPLE_FREQ_MASK_88_2 (1 << 3)
139 #define SAD_SAMPLE_FREQ_MASK_96 (1 << 4)
140 #define SAD_SAMPLE_FREQ_MASK_176_4 (1 << 5)
141 #define SAD_SAMPLE_FREQ_MASK_192 (1 << 6)
142
143 #define SAD_FRAME_LENGTH_MASK_960 1
144 #define SAD_FRAME_LENGTH_MASK_1024 (1 << 1)
145
146 #define SAD_EXT_TYPE_MPEG4_HE_AAC 4
147 #define SAD_EXT_TYPE_MPEG4_HE_AACv2 5
148 #define SAD_EXT_TYPE_MPEG4_AAC_LC 6
149 #define SAD_EXT_TYPE_DRA 7
150 #define SAD_EXT_TYPE_MPEG4_HE_AAC_SURROUND 8
151 #define SAD_EXT_TYPE_MPEG4_AAC_LC_SURROUND 10
152 #define SAD_EXT_TYPE_MPEG_H_3D_AUDIO 11
153 #define SAD_EXT_TYPE_AC_4 12
154 #define SAD_EXT_TYPE_LPCM_3D_AUDIO 13
155
156 #define info(fmt, args...) \
157 do { \
158 if (show_info) \
159 printf("\t\tinfo: " fmt, ##args); \
160 } while (0)
161
162 #define dev_info(fmt, args...) \
163 do { \
164 if (show_state) \
165 printf(">>> " fmt, ##args); \
166 } while(0)
167
168 #define warn(fmt, args...) \
169 do { \
170 warnings++; \
171 if (show_warnings) \
172 printf("\t\twarn: %s(%d): " fmt, __FILE__, __LINE__, ##args); \
173 } while (0)
174
175 #define warn_once(fmt, args...) \
176 do { \
177 static bool show; \
178 \
179 if (!show) { \
180 show = true; \
181 warnings++; \
182 if (show_warnings) \
183 printf("\t\twarn: %s(%d): " fmt, \
184 __FILE__, __LINE__, ##args); \
185 } \
186 } while (0)
187
188 int cec_named_ioctl(int fd, const char *name,
189 unsigned long int request, void *parm);
190
191 #define doioctl(n, r, p) cec_named_ioctl((n)->fd, #r, r, p)
192
193 #define transmit(n, m) (doioctl(n, CEC_TRANSMIT, m))
194
ts_to_ms(uint64_t ts)195 static inline unsigned ts_to_ms(uint64_t ts)
196 {
197 return ts / 1000000;
198 }
199
ts_to_s(uint64_t ts)200 static inline unsigned ts_to_s(uint64_t ts)
201 {
202 return ts / 1000000000;
203 }
204
get_ts()205 static inline uint64_t get_ts()
206 {
207 struct timespec timespec;
208
209 clock_gettime(CLOCK_MONOTONIC, ×pec);
210 return timespec.tv_sec * 1000000000ull + timespec.tv_nsec;
211 }
212
213 const char *la2s(unsigned la);
214 const char *la_type2s(unsigned type);
215 const char *prim_type2s(unsigned type);
216 const char *version2s(unsigned version);
217 std::string status2s(const struct cec_msg &msg);
218 std::string all_dev_types2s(unsigned types);
219 std::string rc_src_prof2s(unsigned prof);
220 std::string dev_feat2s(unsigned feat);
221 std::string audio_format_id_code2s(uint8_t audio_format_id, uint8_t audio_format_code);
222 std::string opcode2s(const struct cec_msg *msg);
223 void sad_encode(const struct short_audio_desc *sad, uint32_t *descriptor);
224
225 // cec-tuner.cpp
226 void tuner_dev_info_init(struct state *state);
227 void process_tuner_record_timer_msgs(struct node *node, struct cec_msg &msg, unsigned me);
228
229 // CEC processing
230 void reply_feature_abort(struct node *node, struct cec_msg *msg,
231 uint8_t reason = CEC_OP_ABORT_UNRECOGNIZED_OP);
232 void testProcessing(struct node *node, bool wallclock);
233
234 #endif
235