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 <cstring>
7 #include <map>
8 #include <sstream>
9 #include <vector>
10
11 #include <sys/ioctl.h>
12 #include <unistd.h>
13
14 #include "cec-compliance.h"
15
16 enum Months { Jan = 1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec };
17
18 /* Tuner Control */
19
bcast_type2s(__u8 bcast_type)20 static const char *bcast_type2s(__u8 bcast_type)
21 {
22 switch (bcast_type) {
23 case CEC_OP_ANA_BCAST_TYPE_CABLE:
24 return "Cable";
25 case CEC_OP_ANA_BCAST_TYPE_SATELLITE:
26 return "Satellite";
27 case CEC_OP_ANA_BCAST_TYPE_TERRESTRIAL:
28 return "Terrestrial";
29 default:
30 return "Future use";
31 }
32 }
33
log_tuner_service(const struct cec_op_tuner_device_info & info,const char * prefix="")34 static int log_tuner_service(const struct cec_op_tuner_device_info &info,
35 const char *prefix = "")
36 {
37 printf("\t\t%s", prefix);
38
39 if (info.is_analog) {
40 double freq_mhz = (info.analog.ana_freq * 625) / 10000.0;
41
42 printf("Analog Channel %.2f MHz (%s, %s)\n", freq_mhz,
43 bcast_system2s(info.analog.bcast_system),
44 bcast_type2s(info.analog.ana_bcast_type));
45
46 switch (info.analog.bcast_system) {
47 case CEC_OP_BCAST_SYSTEM_PAL_BG:
48 case CEC_OP_BCAST_SYSTEM_SECAM_LQ:
49 case CEC_OP_BCAST_SYSTEM_PAL_M:
50 case CEC_OP_BCAST_SYSTEM_NTSC_M:
51 case CEC_OP_BCAST_SYSTEM_PAL_I:
52 case CEC_OP_BCAST_SYSTEM_SECAM_DK:
53 case CEC_OP_BCAST_SYSTEM_SECAM_BG:
54 case CEC_OP_BCAST_SYSTEM_SECAM_L:
55 case CEC_OP_BCAST_SYSTEM_PAL_DK:
56 break;
57 default:
58 return fail("invalid analog bcast_system %u", info.analog.bcast_system);
59 }
60 if (info.analog.ana_bcast_type > CEC_OP_ANA_BCAST_TYPE_TERRESTRIAL)
61 return fail("invalid analog bcast_type %u\n", info.analog.ana_bcast_type);
62 fail_on_test(!info.analog.ana_freq);
63 return 0;
64 }
65
66 __u8 system = info.digital.dig_bcast_system;
67
68 printf("%s Channel ", dig_bcast_system2s(system));
69 if (info.digital.service_id_method) {
70 __u16 major = info.digital.channel.major;
71 __u16 minor = info.digital.channel.minor;
72
73 switch (info.digital.channel.channel_number_fmt) {
74 case CEC_OP_CHANNEL_NUMBER_FMT_2_PART:
75 printf("%u.%u\n", major, minor);
76 break;
77 case CEC_OP_CHANNEL_NUMBER_FMT_1_PART:
78 printf("%u\n", minor);
79 break;
80 default:
81 printf("%u.%u\n", major, minor);
82 return fail("invalid service ID method\n");
83 }
84 return 0;
85 }
86
87
88 switch (system) {
89 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_GEN:
90 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
91 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_CS:
92 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T: {
93 __u16 tsid = info.digital.arib.transport_id;
94 __u16 sid = info.digital.arib.service_id;
95 __u16 onid = info.digital.arib.orig_network_id;
96
97 printf("TSID: %u, SID: %u, ONID: %u\n", tsid, sid, onid);
98 break;
99 }
100 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN:
101 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
102 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE:
103 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T: {
104 __u16 tsid = info.digital.atsc.transport_id;
105 __u16 pn = info.digital.atsc.program_number;
106
107 printf("TSID: %u, Program Number: %u\n", tsid, pn);
108 break;
109 }
110 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_GEN:
111 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S:
112 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
113 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_C:
114 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T: {
115 __u16 tsid = info.digital.dvb.transport_id;
116 __u16 sid = info.digital.dvb.service_id;
117 __u16 onid = info.digital.dvb.orig_network_id;
118
119 printf("TSID: %u, SID: %u, ONID: %u\n", tsid, sid, onid);
120 break;
121 }
122 default:
123 break;
124 }
125
126 switch (system) {
127 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_GEN:
128 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN:
129 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_GEN:
130 warn_once("generic digital broadcast systems should not be used");
131 break;
132 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
133 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_CS:
134 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T:
135 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE:
136 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
137 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T:
138 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_C:
139 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S:
140 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
141 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T:
142 break;
143 default:
144 return fail("invalid digital broadcast system %u", system);
145 }
146
147 if (info.digital.service_id_method > CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL)
148 return fail("invalid service ID method %u\n", info.digital.service_id_method);
149
150 return 0;
151 }
152
tuner_ctl_test(struct node * node,unsigned me,unsigned la,bool interactive)153 static int tuner_ctl_test(struct node *node, unsigned me, unsigned la, bool interactive)
154 {
155 struct cec_msg msg;
156 struct cec_op_tuner_device_info info = {};
157 std::vector<struct cec_op_tuner_device_info> info_vec;
158 bool has_tuner = (1 << la) & (CEC_LOG_ADDR_MASK_TV | CEC_LOG_ADDR_MASK_TUNER);
159 int ret;
160
161 cec_msg_init(&msg, me, la);
162 cec_msg_give_tuner_device_status(&msg, true, CEC_OP_STATUS_REQ_ONCE);
163 fail_on_test(!transmit_timeout(node, &msg));
164 fail_on_test(!has_tuner && !timed_out_or_abort(&msg));
165 if (!has_tuner)
166 return OK_NOT_SUPPORTED;
167 if (timed_out(&msg) || unrecognized_op(&msg))
168 return OK_NOT_SUPPORTED;
169 if (cec_msg_status_is_abort(&msg))
170 return OK_REFUSED;
171
172 printf("\t Start Channel Scan\n");
173 cec_ops_tuner_device_status(&msg, &info);
174 info_vec.push_back(info);
175 ret = log_tuner_service(info);
176 if (ret)
177 return ret;
178
179 while (true) {
180 cec_msg_init(&msg, me, la);
181 cec_msg_tuner_step_increment(&msg);
182 fail_on_test(!transmit(node, &msg));
183 fail_on_test(cec_msg_status_is_abort(&msg));
184 if (cec_msg_status_is_abort(&msg)) {
185 fail_on_test(abort_reason(&msg) == CEC_OP_ABORT_UNRECOGNIZED_OP);
186 if (abort_reason(&msg) == CEC_OP_ABORT_REFUSED) {
187 warn("Tuner step increment does not wrap.\n");
188 break;
189 }
190
191 warn("Tuner at end of service list did not receive feature abort refused.\n");
192 break;
193 }
194 cec_msg_init(&msg, me, la);
195 cec_msg_give_tuner_device_status(&msg, true, CEC_OP_STATUS_REQ_ONCE);
196 fail_on_test(!transmit_timeout(node, &msg));
197 fail_on_test(timed_out_or_abort(&msg));
198 memset(&info, 0, sizeof(info));
199 cec_ops_tuner_device_status(&msg, &info);
200 if (!memcmp(&info, &info_vec[0], sizeof(info)))
201 break;
202 ret = log_tuner_service(info);
203 if (ret)
204 return ret;
205 info_vec.push_back(info);
206 }
207 printf("\t Finished Channel Scan\n");
208
209 printf("\t Start Channel Test\n");
210 for (const auto &iter : info_vec) {
211 cec_msg_init(&msg, me, la);
212 log_tuner_service(iter, "Select ");
213 if (iter.is_analog)
214 cec_msg_select_analogue_service(&msg, iter.analog.ana_bcast_type,
215 iter.analog.ana_freq, iter.analog.bcast_system);
216 else
217 cec_msg_select_digital_service(&msg, &iter.digital);
218 fail_on_test(!transmit(node, &msg));
219 fail_on_test(cec_msg_status_is_abort(&msg));
220 cec_msg_init(&msg, me, la);
221 cec_msg_give_tuner_device_status(&msg, true, CEC_OP_STATUS_REQ_ONCE);
222 fail_on_test(!transmit_timeout(node, &msg));
223 fail_on_test(timed_out_or_abort(&msg));
224 memset(&info, 0, sizeof(info));
225 cec_ops_tuner_device_status(&msg, &info);
226 if (memcmp(&info, &iter, sizeof(info))) {
227 log_tuner_service(info);
228 log_tuner_service(iter);
229 }
230 fail_on_test(memcmp(&info, &iter, sizeof(info)));
231 }
232 printf("\t Finished Channel Test\n");
233
234 cec_msg_init(&msg, me, la);
235 cec_msg_select_analogue_service(&msg, 3, 16000, 9);
236 printf("\t\tSelect invalid analog channel\n");
237 fail_on_test(!transmit_timeout(node, &msg));
238 fail_on_test(!cec_msg_status_is_abort(&msg));
239 fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
240 cec_msg_init(&msg, me, la);
241 info.digital.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID;
242 info.digital.dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2;
243 info.digital.dvb.transport_id = 0;
244 info.digital.dvb.service_id = 0;
245 info.digital.dvb.orig_network_id = 0;
246 cec_msg_select_digital_service(&msg, &info.digital);
247 printf("\t\tSelect invalid digital channel\n");
248 fail_on_test(!transmit_timeout(node, &msg));
249 fail_on_test(!cec_msg_status_is_abort(&msg));
250 fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
251
252 return 0;
253 }
254
255 const vec_remote_subtests tuner_ctl_subtests{
256 { "Tuner Control", CEC_LOG_ADDR_MASK_TUNER | CEC_LOG_ADDR_MASK_TV, tuner_ctl_test },
257 };
258
259 /* One Touch Record */
260
one_touch_rec_on_send(struct node * node,unsigned me,unsigned la,const struct cec_op_record_src & rec_src,__u8 & rec_status)261 static int one_touch_rec_on_send(struct node *node, unsigned me, unsigned la,
262 const struct cec_op_record_src &rec_src, __u8 &rec_status)
263 {
264 struct cec_msg msg;
265
266 cec_msg_init(&msg, me, la);
267 cec_msg_record_off(&msg, false);
268 fail_on_test(!transmit_timeout(node, &msg));
269
270 cec_msg_init(&msg, me, la);
271 cec_msg_record_on(&msg, true, &rec_src);
272 /* Allow 10s for reply because the spec says it may take several seconds to accurately respond. */
273 fail_on_test(!transmit_timeout(node, &msg, 10000));
274 fail_on_test(timed_out_or_abort(&msg));
275 cec_ops_record_status(&msg, &rec_status);
276
277 return OK;
278 }
279
one_touch_rec_on_send_invalid(struct node * node,unsigned me,unsigned la,const struct cec_op_record_src & rec_src)280 static int one_touch_rec_on_send_invalid(struct node *node, unsigned me, unsigned la,
281 const struct cec_op_record_src &rec_src)
282 {
283 struct cec_msg msg;
284
285 cec_msg_init(&msg, me, la);
286 cec_msg_record_on(&msg, true, &rec_src);
287 fail_on_test(!transmit_timeout(node, &msg));
288 fail_on_test(!cec_msg_status_is_abort(&msg));
289 fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
290
291 return OK;
292 }
293
294 /*
295 * Returns true if the Record Status is an error indicating that the
296 * request to start recording has failed.
297 */
rec_status_is_a_valid_error_status(__u8 rec_status)298 static bool rec_status_is_a_valid_error_status(__u8 rec_status)
299 {
300 switch (rec_status) {
301 case CEC_OP_RECORD_STATUS_NO_DIG_SERVICE:
302 case CEC_OP_RECORD_STATUS_NO_ANA_SERVICE:
303 case CEC_OP_RECORD_STATUS_NO_SERVICE:
304 case CEC_OP_RECORD_STATUS_INVALID_EXT_PLUG:
305 case CEC_OP_RECORD_STATUS_INVALID_EXT_PHYS_ADDR:
306 case CEC_OP_RECORD_STATUS_UNSUP_CA:
307 case CEC_OP_RECORD_STATUS_NO_CA_ENTITLEMENTS:
308 case CEC_OP_RECORD_STATUS_CANT_COPY_SRC:
309 case CEC_OP_RECORD_STATUS_NO_MORE_COPIES:
310 case CEC_OP_RECORD_STATUS_NO_MEDIA:
311 case CEC_OP_RECORD_STATUS_PLAYING:
312 case CEC_OP_RECORD_STATUS_ALREADY_RECORDING:
313 case CEC_OP_RECORD_STATUS_MEDIA_PROT:
314 case CEC_OP_RECORD_STATUS_NO_SIGNAL:
315 case CEC_OP_RECORD_STATUS_MEDIA_PROBLEM:
316 case CEC_OP_RECORD_STATUS_NO_SPACE:
317 case CEC_OP_RECORD_STATUS_PARENTAL_LOCK:
318 case CEC_OP_RECORD_STATUS_OTHER:
319 return true;
320 default:
321 return false;
322 }
323 }
324
one_touch_rec_tv_screen(struct node * node,unsigned me,unsigned la,bool interactive)325 static int one_touch_rec_tv_screen(struct node *node, unsigned me, unsigned la, bool interactive)
326 {
327 struct cec_msg msg;
328
329 cec_msg_init(&msg, me, la);
330 cec_msg_record_tv_screen(&msg, true);
331 fail_on_test(!transmit_timeout(node, &msg));
332 fail_on_test_v2(node->remote[la].cec_version,
333 node->remote[la].has_rec_tv && unrecognized_op(&msg));
334 fail_on_test_v2(node->remote[la].cec_version,
335 !node->remote[la].has_rec_tv && !unrecognized_op(&msg));
336 if (unrecognized_op(&msg))
337 return OK_NOT_SUPPORTED;
338 if (refused(&msg))
339 return OK_REFUSED;
340 if (cec_msg_status_is_abort(&msg))
341 return OK_PRESUMED;
342 /* Follower should ignore this message if it is not sent by a recording device */
343 if (node->prim_devtype != CEC_OP_PRIM_DEVTYPE_RECORD) {
344 fail_on_test(!timed_out(&msg));
345 return OK;
346 }
347 fail_on_test(timed_out(&msg));
348
349 struct cec_op_record_src rec_src = {};
350
351 cec_ops_record_on(&msg, &rec_src);
352
353 fail_on_test(rec_src.type < CEC_OP_RECORD_SRC_OWN ||
354 rec_src.type > CEC_OP_RECORD_SRC_EXT_PHYS_ADDR);
355
356 if (rec_src.type == CEC_OP_RECORD_SRC_DIGITAL) {
357 switch (rec_src.digital.dig_bcast_system) {
358 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_GEN:
359 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_GEN:
360 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_GEN:
361 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS:
362 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_CS:
363 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_T:
364 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_CABLE:
365 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_SAT:
366 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T:
367 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_C:
368 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S:
369 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_S2:
370 case CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T:
371 break;
372 default:
373 return fail("Invalid digital service broadcast system operand.\n");
374 }
375
376 if (rec_src.digital.service_id_method == CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL)
377 fail_on_test(rec_src.digital.channel.channel_number_fmt < CEC_OP_CHANNEL_NUMBER_FMT_1_PART ||
378 rec_src.digital.channel.channel_number_fmt > CEC_OP_CHANNEL_NUMBER_FMT_2_PART);
379 }
380
381 if (rec_src.type == CEC_OP_RECORD_SRC_ANALOG) {
382 fail_on_test(rec_src.analog.ana_bcast_type > CEC_OP_ANA_BCAST_TYPE_TERRESTRIAL);
383 fail_on_test(rec_src.analog.bcast_system > CEC_OP_BCAST_SYSTEM_PAL_DK &&
384 rec_src.analog.bcast_system != CEC_OP_BCAST_SYSTEM_OTHER);
385 fail_on_test(rec_src.analog.ana_freq == 0 || rec_src.analog.ana_freq == 0xffff);
386 }
387
388 if (rec_src.type == CEC_OP_RECORD_SRC_EXT_PLUG)
389 fail_on_test(rec_src.ext_plug.plug == 0);
390
391 return OK;
392 }
393
one_touch_rec_on(struct node * node,unsigned me,unsigned la,bool interactive)394 static int one_touch_rec_on(struct node *node, unsigned me, unsigned la, bool interactive)
395 {
396 struct cec_msg msg;
397 struct cec_op_record_src rec_src = {};
398
399 rec_src.type = CEC_OP_RECORD_SRC_OWN;
400 cec_msg_init(&msg, me, la);
401 cec_msg_record_on(&msg, true, &rec_src);
402 /* Allow 10s for reply because the spec says it may take several seconds to accurately respond. */
403 fail_on_test(!transmit_timeout(node, &msg, 10000));
404 fail_on_test(timed_out(&msg));
405 if (unrecognized_op(&msg)) {
406 fail_on_test(node->remote[la].prim_type == CEC_OP_PRIM_DEVTYPE_RECORD);
407 return OK_NOT_SUPPORTED;
408 }
409 if (refused(&msg))
410 return OK_REFUSED;
411 if (cec_msg_status_is_abort(&msg))
412 return OK_PRESUMED;
413
414 __u8 rec_status;
415
416 cec_ops_record_status(&msg, &rec_status);
417 if (rec_status != CEC_OP_RECORD_STATUS_CUR_SRC)
418 fail_on_test(!rec_status_is_a_valid_error_status(rec_status));
419
420 /* In the following tests, these digital services are taken from the cec-follower tuner emulation. */
421 memset(&rec_src, 0, sizeof(rec_src));
422 rec_src.type = CEC_OP_RECORD_SRC_DIGITAL;
423 rec_src.digital.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID;
424 rec_src.digital.dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS;
425 rec_src.digital.arib.transport_id = 1032;
426 rec_src.digital.arib.service_id = 30203;
427 rec_src.digital.arib.orig_network_id = 1;
428 fail_on_test(one_touch_rec_on_send(node, me, la, rec_src, rec_status));
429 if (rec_status != CEC_OP_RECORD_STATUS_DIG_SERVICE)
430 fail_on_test(!rec_status_is_a_valid_error_status(rec_status));
431
432 memset(&rec_src, 0, sizeof(rec_src));
433 rec_src.type = CEC_OP_RECORD_SRC_DIGITAL;
434 rec_src.digital.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL;
435 rec_src.digital.dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ATSC_T;
436 rec_src.digital.channel.channel_number_fmt = CEC_OP_CHANNEL_NUMBER_FMT_2_PART;
437 rec_src.digital.channel.major = 4;
438 rec_src.digital.channel.minor = 1;
439 fail_on_test(one_touch_rec_on_send(node, me, la, rec_src, rec_status));
440 if (rec_status != CEC_OP_RECORD_STATUS_DIG_SERVICE)
441 fail_on_test(!rec_status_is_a_valid_error_status(rec_status));
442
443 memset(&rec_src, 0, sizeof(rec_src));
444 rec_src.type = CEC_OP_RECORD_SRC_DIGITAL;
445 rec_src.digital.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_DIG_ID;
446 rec_src.digital.dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_DVB_T;
447 rec_src.digital.dvb.transport_id = 1004;
448 rec_src.digital.dvb.service_id = 1040;
449 rec_src.digital.dvb.orig_network_id = 8945;
450 fail_on_test(one_touch_rec_on_send(node, me, la, rec_src, rec_status));
451 if (rec_status != CEC_OP_RECORD_STATUS_DIG_SERVICE)
452 fail_on_test(!rec_status_is_a_valid_error_status(rec_status));
453
454 /* In the following tests, these channels taken from the cec-follower tuner emulation. */
455 memset(&rec_src, 0, sizeof(rec_src));
456 rec_src.type = CEC_OP_RECORD_STATUS_ANA_SERVICE;
457 rec_src.analog.ana_bcast_type = CEC_OP_ANA_BCAST_TYPE_CABLE;
458 rec_src.analog.ana_freq = (471250 * 10) / 625;
459 rec_src.analog.bcast_system = CEC_OP_BCAST_SYSTEM_PAL_BG;
460 fail_on_test(one_touch_rec_on_send(node, me, la, rec_src, rec_status));
461 if (rec_status != CEC_OP_RECORD_STATUS_ANA_SERVICE)
462 fail_on_test(!rec_status_is_a_valid_error_status(rec_status));
463
464 memset(&rec_src, 0, sizeof(rec_src));
465 rec_src.type = CEC_OP_RECORD_STATUS_ANA_SERVICE;
466 rec_src.analog.ana_bcast_type = CEC_OP_ANA_BCAST_TYPE_SATELLITE;
467 rec_src.analog.ana_freq = (551250 * 10) / 625;
468 rec_src.analog.bcast_system = CEC_OP_BCAST_SYSTEM_SECAM_BG;
469 fail_on_test(one_touch_rec_on_send(node, me, la, rec_src, rec_status));
470 if (rec_status != CEC_OP_RECORD_STATUS_ANA_SERVICE)
471 fail_on_test(!rec_status_is_a_valid_error_status(rec_status));
472
473 memset(&rec_src, 0, sizeof(rec_src));
474 rec_src.type = CEC_OP_RECORD_STATUS_ANA_SERVICE;
475 rec_src.analog.ana_bcast_type = CEC_OP_ANA_BCAST_TYPE_TERRESTRIAL;
476 rec_src.analog.ana_freq = (185250 * 10) / 625;
477 rec_src.analog.bcast_system = CEC_OP_BCAST_SYSTEM_PAL_DK;
478 fail_on_test(one_touch_rec_on_send(node, me, la, rec_src, rec_status));
479 if (rec_status != CEC_OP_RECORD_STATUS_ANA_SERVICE)
480 fail_on_test(!rec_status_is_a_valid_error_status(rec_status));
481
482 memset(&rec_src, 0, sizeof(rec_src));
483 rec_src.type = CEC_OP_RECORD_SRC_EXT_PLUG;
484 rec_src.ext_plug.plug = 1;
485 fail_on_test(one_touch_rec_on_send(node, me, la, rec_src, rec_status));
486 if (rec_status != CEC_OP_RECORD_STATUS_EXT_INPUT)
487 fail_on_test(!rec_status_is_a_valid_error_status(rec_status));
488
489 memset(&rec_src, 0, sizeof(rec_src));
490 rec_src.type = CEC_OP_RECORD_SRC_EXT_PHYS_ADDR;
491 fail_on_test(one_touch_rec_on_send(node, me, la, rec_src, rec_status));
492 if (rec_status != CEC_OP_RECORD_STATUS_EXT_INPUT)
493 fail_on_test(!rec_status_is_a_valid_error_status(rec_status));
494
495 return OK;
496 }
497
one_touch_rec_on_invalid(struct node * node,unsigned me,unsigned la,bool interactive)498 static int one_touch_rec_on_invalid(struct node *node, unsigned me, unsigned la, bool interactive)
499 {
500 struct cec_msg msg;
501
502 cec_msg_init(&msg, me, la);
503 cec_msg_record_on_own(&msg);
504 msg.msg[2] = 0; /* Invalid source operand */
505 fail_on_test(!transmit_timeout(node, &msg));
506 if (unrecognized_op(&msg))
507 return OK_NOT_SUPPORTED;
508 fail_on_test(!cec_msg_status_is_abort(&msg));
509 fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
510
511 cec_msg_init(&msg, me, la);
512 cec_msg_record_on_own(&msg);
513 msg.msg[2] = 6; /* Invalid source operand */
514 fail_on_test(!transmit_timeout(node, &msg));
515 fail_on_test(!cec_msg_status_is_abort(&msg));
516 fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_INVALID_OP);
517
518 struct cec_op_record_src rec_src = {};
519
520 rec_src.type = CEC_OP_RECORD_SRC_DIGITAL;
521 rec_src.digital.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL;
522 rec_src.digital.dig_bcast_system = 0x7f; /* Invalid digital service broadcast system operand */
523 rec_src.digital.channel.channel_number_fmt = CEC_OP_CHANNEL_NUMBER_FMT_1_PART;
524 rec_src.digital.channel.major = 0;
525 rec_src.digital.channel.minor = 30203;
526 fail_on_test(one_touch_rec_on_send_invalid(node, me, la, rec_src));
527
528 rec_src.type = CEC_OP_RECORD_SRC_DIGITAL;
529 rec_src.digital.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL;
530 rec_src.digital.dig_bcast_system = CEC_OP_DIG_SERVICE_BCAST_SYSTEM_ARIB_BS;
531 rec_src.digital.channel.channel_number_fmt = 0; /* Invalid channel number format operand */
532 rec_src.digital.channel.major = 0;
533 rec_src.digital.channel.minor = 30609;
534 fail_on_test(one_touch_rec_on_send_invalid(node, me, la, rec_src));
535
536 memset(&rec_src, 0, sizeof(rec_src));
537 rec_src.type = CEC_OP_RECORD_SRC_ANALOG;
538 rec_src.analog.ana_bcast_type = 0xff; /* Invalid analog broadcast type */
539 rec_src.analog.ana_freq = (519250 * 10) / 625;
540 rec_src.analog.bcast_system = CEC_OP_BCAST_SYSTEM_PAL_BG;
541 fail_on_test(one_touch_rec_on_send_invalid(node, me, la, rec_src));
542
543 memset(&rec_src, 0, sizeof(rec_src));
544 rec_src.type = CEC_OP_RECORD_SRC_ANALOG;
545 rec_src.analog.ana_bcast_type = CEC_OP_ANA_BCAST_TYPE_SATELLITE;
546 rec_src.analog.ana_freq = (703250 * 10) / 625;
547 rec_src.analog.bcast_system = 0xff; /* Invalid analog broadcast system */
548 fail_on_test(one_touch_rec_on_send_invalid(node, me, la, rec_src));
549
550 memset(&rec_src, 0, sizeof(rec_src));
551 rec_src.type = CEC_OP_RECORD_SRC_ANALOG;
552 rec_src.analog.ana_bcast_type = CEC_OP_ANA_BCAST_TYPE_TERRESTRIAL;
553 rec_src.analog.ana_freq = 0; /* Invalid frequency */
554 rec_src.analog.bcast_system = CEC_OP_BCAST_SYSTEM_NTSC_M;
555 fail_on_test(one_touch_rec_on_send_invalid(node, me, la, rec_src));
556
557 memset(&rec_src, 0, sizeof(rec_src));
558 rec_src.type = CEC_OP_RECORD_SRC_ANALOG;
559 rec_src.analog.ana_bcast_type = CEC_OP_ANA_BCAST_TYPE_CABLE;
560 rec_src.analog.ana_freq = 0xffff; /* Invalid frequency */
561 rec_src.analog.bcast_system = CEC_OP_BCAST_SYSTEM_SECAM_L;
562 fail_on_test(one_touch_rec_on_send_invalid(node, me, la, rec_src));
563
564 memset(&rec_src, 0, sizeof(rec_src));
565 rec_src.type = CEC_OP_RECORD_SRC_EXT_PLUG;
566 rec_src.ext_plug.plug = 0; /* Invalid plug */
567 fail_on_test(one_touch_rec_on_send_invalid(node, me, la, rec_src));
568
569 return OK;
570 }
571
one_touch_rec_off(struct node * node,unsigned me,unsigned la,bool interactive)572 static int one_touch_rec_off(struct node *node, unsigned me, unsigned la, bool interactive)
573 {
574 struct cec_msg msg;
575
576 cec_msg_init(&msg, me, la);
577 cec_msg_record_off(&msg, true);
578 /* Allow 10s for reply because the spec says it may take several seconds to accurately respond. */
579 fail_on_test(!transmit_timeout(node, &msg, 10000));
580 if (unrecognized_op(&msg)) {
581 fail_on_test(node->remote[la].prim_type == CEC_OP_PRIM_DEVTYPE_RECORD);
582 return OK_NOT_SUPPORTED;
583 }
584 if (refused(&msg))
585 return OK_REFUSED;
586 if (cec_msg_status_is_abort(&msg))
587 return OK_PRESUMED;
588 if (timed_out(&msg))
589 return OK_PRESUMED;
590
591 __u8 rec_status;
592
593 cec_ops_record_status(&msg, &rec_status);
594
595 fail_on_test(rec_status != CEC_OP_RECORD_STATUS_TERMINATED_OK &&
596 rec_status != CEC_OP_RECORD_STATUS_ALREADY_TERM);
597
598 return OK;
599 }
600
601 const vec_remote_subtests one_touch_rec_subtests{
602 { "Record TV Screen", CEC_LOG_ADDR_MASK_TV, one_touch_rec_tv_screen },
603 {
604 "Record On",
605 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
606 one_touch_rec_on,
607 },
608 {
609 "Record On Invalid Operand",
610 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
611 one_touch_rec_on_invalid,
612 },
613 { "Record Off", CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP, one_touch_rec_off },
614
615 };
616
617 /* Timer Programming */
618
timer_status_is_valid(const struct cec_msg & msg)619 static int timer_status_is_valid(const struct cec_msg &msg)
620 {
621 __u8 timer_overlap_warning;
622 __u8 media_info;
623 __u8 prog_info;
624 __u8 prog_error;
625 __u8 duration_hr;
626 __u8 duration_min;
627
628 cec_ops_timer_status(&msg, &timer_overlap_warning, &media_info, &prog_info,
629 &prog_error, &duration_hr, &duration_min);
630 fail_on_test(media_info > CEC_OP_MEDIA_INFO_NO_MEDIA);
631 if (prog_info)
632 fail_on_test(prog_info < CEC_OP_PROG_INFO_ENOUGH_SPACE ||
633 prog_info > CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE);
634 else
635 fail_on_test(prog_error < CEC_OP_PROG_ERROR_NO_FREE_TIMER ||
636 (prog_error > CEC_OP_PROG_ERROR_CLOCK_FAILURE &&
637 prog_error != CEC_OP_PROG_ERROR_DUPLICATE));
638
639 return OK;
640 }
641
timer_cleared_status_is_valid(const struct cec_msg & msg)642 static int timer_cleared_status_is_valid(const struct cec_msg &msg)
643 {
644 __u8 timer_cleared_status;
645
646 cec_ops_timer_cleared_status(&msg, &timer_cleared_status);
647 fail_on_test(timer_cleared_status != CEC_OP_TIMER_CLR_STAT_RECORDING &&
648 timer_cleared_status != CEC_OP_TIMER_CLR_STAT_NO_MATCHING &&
649 timer_cleared_status != CEC_OP_TIMER_CLR_STAT_NO_INFO &&
650 timer_cleared_status != CEC_OP_TIMER_CLR_STAT_CLEARED);
651
652 return OK;
653 }
654
timer_has_error(const struct cec_msg & msg)655 static bool timer_has_error(const struct cec_msg &msg)
656 {
657 __u8 timer_overlap_warning;
658 __u8 media_info;
659 __u8 prog_info;
660 __u8 prog_error;
661 __u8 duration_hr;
662 __u8 duration_min;
663
664 cec_ops_timer_status(&msg, &timer_overlap_warning, &media_info, &prog_info,
665 &prog_error, &duration_hr, &duration_min);
666 if (prog_error)
667 return true;
668
669 return false;
670 }
671
send_timer_error(struct node * node,unsigned me,unsigned la,__u8 day,__u8 month,__u8 start_hr,__u8 start_min,__u8 dur_hr,__u8 dur_min,__u8 rec_seq)672 static int send_timer_error(struct node *node, unsigned me, unsigned la, __u8 day, __u8 month,
673 __u8 start_hr, __u8 start_min, __u8 dur_hr, __u8 dur_min, __u8 rec_seq)
674 {
675 struct cec_msg msg;
676 cec_msg_init(&msg, me, la);
677 cec_msg_set_analogue_timer(&msg, true, day, month, start_hr, start_min, dur_hr, dur_min,
678 rec_seq, CEC_OP_ANA_BCAST_TYPE_CABLE, 7668, // 479.25 MHz
679 node->remote[la].bcast_sys);
680 fail_on_test(!transmit_timeout(node, &msg, 10000));
681 fail_on_test(timed_out(&msg));
682 if (cec_msg_status_is_abort(&msg))
683 fail_on_test(abort_reason(&msg) != CEC_OP_ABORT_UNRECOGNIZED_OP);
684 else
685 fail_on_test(!timer_has_error(msg));
686
687 return OK;
688 }
689
timer_overlap_warning_is_set(const struct cec_msg & msg)690 static bool timer_overlap_warning_is_set(const struct cec_msg &msg)
691 {
692 __u8 timer_overlap_warning;
693 __u8 media_info;
694 __u8 prog_info;
695 __u8 prog_error;
696 __u8 duration_hr;
697 __u8 duration_min;
698
699 cec_ops_timer_status(&msg, &timer_overlap_warning, &media_info, &prog_info,
700 &prog_error, &duration_hr, &duration_min);
701
702 if (timer_overlap_warning)
703 return true;
704
705 return false;
706 }
707
send_timer_overlap(struct node * node,unsigned me,unsigned la,__u8 day,__u8 month,__u8 start_hr,__u8 start_min,__u8 dur_hr,__u8 dur_min,__u8 rec_seq)708 static int send_timer_overlap(struct node *node, unsigned me, unsigned la, __u8 day, __u8 month,
709 __u8 start_hr, __u8 start_min, __u8 dur_hr, __u8 dur_min, __u8 rec_seq)
710 {
711 struct cec_msg msg;
712
713 cec_msg_init(&msg, me, la);
714 cec_msg_set_analogue_timer(&msg, true, day, month, start_hr, start_min, dur_hr, dur_min,
715 rec_seq, CEC_OP_ANA_BCAST_TYPE_CABLE, 7668, // 479.25 MHz
716 node->remote[la].bcast_sys);
717 fail_on_test(!transmit_timeout(node, &msg, 10000));
718 fail_on_test(timed_out_or_abort(&msg));
719 fail_on_test(timer_has_error(msg));
720 fail_on_test(!timer_overlap_warning_is_set(msg));
721
722 return OK;
723 }
724
clear_timer(struct node * node,unsigned me,unsigned la,__u8 day,__u8 month,__u8 start_hr,__u8 start_min,__u8 dur_hr,__u8 dur_min,__u8 rec_seq)725 static int clear_timer(struct node *node, unsigned me, unsigned la, __u8 day, __u8 month,
726 __u8 start_hr, __u8 start_min, __u8 dur_hr, __u8 dur_min, __u8 rec_seq)
727 {
728 struct cec_msg msg;
729
730 cec_msg_init(&msg, me, la);
731 cec_msg_clear_analogue_timer(&msg, true, day, month, start_hr, start_min, dur_hr, dur_min,
732 rec_seq, CEC_OP_ANA_BCAST_TYPE_CABLE, 7668, // 479.25 MHz
733 node->remote[la].bcast_sys);
734 fail_on_test(!transmit_timeout(node, &msg, 10000));
735 fail_on_test(timed_out_or_abort(&msg));
736 fail_on_test(timer_has_error(msg));
737 fail_on_test(timer_cleared_status_is_valid(msg));
738
739 return OK;
740 }
741
timer_prog_set_analog_timer(struct node * node,unsigned me,unsigned la,bool interactive)742 static int timer_prog_set_analog_timer(struct node *node, unsigned me, unsigned la, bool interactive)
743 {
744 struct cec_msg msg;
745
746 cec_msg_init(&msg, me, la);
747 /* Set timer to start tomorrow, at current time, for 2 hr, 30 min. */
748 time_t tomorrow = node->current_time + (24 * 60 * 60);
749 struct tm *t = localtime(&tomorrow);
750 cec_msg_set_analogue_timer(&msg, true, t->tm_mday, t->tm_mon + 1, t->tm_hour, t->tm_min, 2, 30,
751 0x7f, CEC_OP_ANA_BCAST_TYPE_CABLE, 7668, // 479.25 MHz
752 node->remote[la].bcast_sys);
753 fail_on_test(!transmit_timeout(node, &msg, 10000));
754 fail_on_test(timed_out(&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 fail_on_test(timer_status_is_valid(msg));
762 node->remote[la].has_analogue_timer = true;
763
764 return OK;
765 }
766
timer_prog_set_digital_timer(struct node * node,unsigned me,unsigned la,bool interactive)767 static int timer_prog_set_digital_timer(struct node *node, unsigned me, unsigned la, bool interactive)
768 {
769 struct cec_msg msg;
770 struct cec_op_digital_service_id digital_service_id = {};
771
772 digital_service_id.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL;
773 digital_service_id.channel.channel_number_fmt = CEC_OP_CHANNEL_NUMBER_FMT_1_PART;
774 digital_service_id.channel.minor = 1;
775 digital_service_id.dig_bcast_system = node->remote[la].dig_bcast_sys;
776 cec_msg_init(&msg, me, la);
777 /* Set timer to start 2 days from now, at current time, for 4 hr, 30 min. */
778 time_t two_days_ahead = node->current_time + (2 * 24 * 60 * 60);
779 struct tm *t = localtime(&two_days_ahead);
780 cec_msg_set_digital_timer(&msg, true, t->tm_mday, t->tm_mon + 1, t->tm_hour,
781 t->tm_min, 4, 30, CEC_OP_REC_SEQ_ONCE_ONLY, &digital_service_id);
782 fail_on_test(!transmit_timeout(node, &msg, 10000));
783 fail_on_test(timed_out(&msg));
784 if (unrecognized_op(&msg))
785 return OK_NOT_SUPPORTED;
786 if (refused(&msg))
787 return OK_REFUSED;
788 if (cec_msg_status_is_abort(&msg))
789 return OK_PRESUMED;
790 fail_on_test(timer_status_is_valid(msg));
791
792 return 0;
793 }
794
timer_prog_set_ext_timer(struct node * node,unsigned me,unsigned la,bool interactive)795 static int timer_prog_set_ext_timer(struct node *node, unsigned me, unsigned la, bool interactive)
796 {
797 struct cec_msg msg;
798
799 cec_msg_init(&msg, me, la);
800 /* Set timer to start 3 days from now, at current time, for 6 hr, 30 min. */
801 time_t three_days_ahead = node->current_time + (3 * 24 * 60 * 60);
802 struct tm *t = localtime(&three_days_ahead);
803 cec_msg_set_ext_timer(&msg, true, t->tm_mday, t->tm_mon + 1, t->tm_hour, t->tm_min, 6, 30,
804 CEC_OP_REC_SEQ_ONCE_ONLY, CEC_OP_EXT_SRC_PHYS_ADDR, 0, node->phys_addr);
805 fail_on_test(!transmit_timeout(node, &msg, 10000));
806 fail_on_test(timed_out(&msg));
807 if (unrecognized_op(&msg))
808 return OK_NOT_SUPPORTED;
809 if (refused(&msg))
810 return OK_REFUSED;
811 if (cec_msg_status_is_abort(&msg))
812 return OK_PRESUMED;
813 fail_on_test(timer_status_is_valid(msg));
814
815 return 0;
816 }
817
timer_prog_clear_analog_timer(struct node * node,unsigned me,unsigned la,bool interactive)818 static int timer_prog_clear_analog_timer(struct node *node, unsigned me, unsigned la, bool interactive)
819 {
820 struct cec_msg msg;
821
822 cec_msg_init(&msg, me, la);
823 /* Clear timer set to start tomorrow, at current time, for 2 hr, 30 min. */
824 time_t tomorrow = node->current_time + (24 * 60 * 60);
825 struct tm *t = localtime(&tomorrow);
826 cec_msg_clear_analogue_timer(&msg, true, t->tm_mday, t->tm_mon + 1, t->tm_hour, t->tm_min, 2, 30,
827 0x7f, CEC_OP_ANA_BCAST_TYPE_CABLE,7668, // 479.25 MHz
828 node->remote[la].bcast_sys);
829 fail_on_test(!transmit_timeout(node, &msg, 10000));
830 fail_on_test(timed_out(&msg));
831 if (unrecognized_op(&msg))
832 return OK_NOT_SUPPORTED;
833 if (refused(&msg))
834 return OK_REFUSED;
835 if (cec_msg_status_is_abort(&msg))
836 return OK_PRESUMED;
837 fail_on_test(timer_cleared_status_is_valid(msg));
838
839 return 0;
840 }
841
timer_prog_clear_digital_timer(struct node * node,unsigned me,unsigned la,bool interactive)842 static int timer_prog_clear_digital_timer(struct node *node, unsigned me, unsigned la, bool interactive)
843 {
844 struct cec_msg msg;
845 struct cec_op_digital_service_id digital_service_id = {};
846
847 digital_service_id.service_id_method = CEC_OP_SERVICE_ID_METHOD_BY_CHANNEL;
848 digital_service_id.channel.channel_number_fmt = CEC_OP_CHANNEL_NUMBER_FMT_1_PART;
849 digital_service_id.channel.minor = 1;
850 digital_service_id.dig_bcast_system = node->remote[la].dig_bcast_sys;
851 cec_msg_init(&msg, me, la);
852 /* Clear timer set to start 2 days from now, at current time, for 4 hr, 30 min. */
853 time_t two_days_ahead = node->current_time + (2 * 24 * 60 * 60);
854 struct tm *t = localtime(&two_days_ahead);
855 cec_msg_clear_digital_timer(&msg, true, t->tm_mday, t->tm_mon + 1, t->tm_hour,
856 t->tm_min, 4, 30, CEC_OP_REC_SEQ_ONCE_ONLY, &digital_service_id);
857 fail_on_test(!transmit_timeout(node, &msg, 10000));
858 fail_on_test(timed_out(&msg));
859 if (unrecognized_op(&msg))
860 return OK_NOT_SUPPORTED;
861 if (refused(&msg))
862 return OK_REFUSED;
863 if (cec_msg_status_is_abort(&msg))
864 return OK_PRESUMED;
865 fail_on_test(timer_cleared_status_is_valid(msg));
866
867 return 0;
868 }
869
timer_prog_clear_ext_timer(struct node * node,unsigned me,unsigned la,bool interactive)870 static int timer_prog_clear_ext_timer(struct node *node, unsigned me, unsigned la, bool interactive)
871 {
872 struct cec_msg msg;
873
874 cec_msg_init(&msg, me, la);
875 /* Clear timer set to start 3 days from now, at current time, for 6 hr, 30 min. */
876 time_t three_days_ahead = node->current_time + (3 * 24 * 60 * 60);
877 struct tm *t = localtime(&three_days_ahead);
878 cec_msg_clear_ext_timer(&msg, true, t->tm_mday, t->tm_mon + 1, t->tm_hour, t->tm_min, 6, 30,
879 CEC_OP_REC_SEQ_ONCE_ONLY, CEC_OP_EXT_SRC_PHYS_ADDR, 0, node->phys_addr);
880 fail_on_test(!transmit_timeout(node, &msg, 10000));
881 fail_on_test(timed_out(&msg));
882 if (unrecognized_op(&msg))
883 return OK_NOT_SUPPORTED;
884 if (refused(&msg))
885 return OK_REFUSED;
886 if (cec_msg_status_is_abort(&msg))
887 return OK_PRESUMED;
888 fail_on_test(timer_cleared_status_is_valid(msg));
889
890 return 0;
891 }
892
timer_prog_set_prog_title(struct node * node,unsigned me,unsigned la,bool interactive)893 static int timer_prog_set_prog_title(struct node *node, unsigned me, unsigned la, bool interactive)
894 {
895 struct cec_msg msg;
896
897 cec_msg_init(&msg, me, la);
898 cec_msg_set_timer_program_title(&msg, "Super-Hans II");
899 fail_on_test(!transmit_timeout(node, &msg));
900 if (unrecognized_op(&msg))
901 return OK_NOT_SUPPORTED;
902 if (refused(&msg))
903 return OK_REFUSED;
904
905 return OK_PRESUMED;
906 }
907
timer_errors(struct node * node,unsigned me,unsigned la,bool interactive)908 static int timer_errors(struct node *node, unsigned me, unsigned la, bool interactive)
909 {
910 struct cec_msg msg;
911
912 if (!node->remote[la].has_analogue_timer)
913 return OK_NOT_SUPPORTED;
914
915 /* Day error: November 31, at 6:00 am, for 1 hr. */
916 fail_on_test(send_timer_error(node, me, la, 31, Nov, 6, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
917
918 /* Day error: December 32, at 6:00 am, for 1 hr. */
919 fail_on_test(send_timer_error(node, me, la, 32, Dec, 6, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
920
921 /* Day error: 0, in January, at 6:00 am, for 1 hr. Day range begins at 1. */
922 fail_on_test(send_timer_error(node, me, la, 0, Jan, 6, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
923
924 /* Month error: 0, on day 5, at 6:00 am, for 1 hr. CEC month range is 1-12. */
925 fail_on_test(send_timer_error(node, me, la, 5, 0, 6, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
926
927 /* Month error: 13, on day 5, at 6:00 am, for 1 hr. */
928 fail_on_test(send_timer_error(node, me, la, 5, 13, 6, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
929
930 /* Start hour error: 24 hr, on August 5, for 1 hr. Start hour range is 0-23. */
931 fail_on_test(send_timer_error(node, me, la, 5, Aug, 24, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
932
933 /* Start min error: 60 min, on August 5, for 1 hr. Start min range is 0-59. */
934 fail_on_test(send_timer_error(node, me, la, 5, Aug, 0, 60, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
935
936 /* Recording duration error: 0 hr, 0 min on August 5, at 6:00am. */
937 fail_on_test(send_timer_error(node, me, la, 5, Aug, 6, 0, 0, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
938
939 /* Duplicate timer error: start 2 hrs from now, for 1 hr. */
940 time_t two_hours_ahead = node->current_time + (2 * 60 * 60);
941 struct tm *t = localtime(&two_hours_ahead);
942 cec_msg_init(&msg, me, la);
943 cec_msg_set_analogue_timer(&msg, true, t->tm_mday, t->tm_mon + 1, t->tm_hour, t->tm_min, 1, 0,
944 CEC_OP_REC_SEQ_ONCE_ONLY,CEC_OP_ANA_BCAST_TYPE_CABLE,
945 7668, // 479.25 MHz
946 node->remote[la].bcast_sys);
947 fail_on_test(!transmit_timeout(node, &msg, 10000));
948 fail_on_test(timed_out_or_abort(&msg));
949 fail_on_test(timer_has_error(msg)); /* The first timer should be set. */
950 fail_on_test(send_timer_error(node, me, la, t->tm_mday, t->tm_mon + 1, t->tm_hour,
951 t->tm_min, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
952
953 /* Clear the timer that was set to test duplicate timers. */
954 fail_on_test(clear_timer(node, me, la, t->tm_mday, t->tm_mon + 1, t->tm_hour, t->tm_min, 1, 0,
955 CEC_OP_REC_SEQ_ONCE_ONLY));
956
957 /* Recording sequence error: 0xff, on August 5, at 6:00 am, for 1 hr. */
958 fail_on_test(send_timer_error(node, me, la, 5, Aug, 6, 0, 1, 0, 0xff));
959
960 /* Error in last day of February, at 6:00 am, for 1 hr. */
961 time_t current_time = node->current_time;
962 t = localtime(¤t_time);
963 if ((t->tm_mon + 1) > Feb)
964 t->tm_year++; /* The timer will be for next year. */
965 if (!(t->tm_year % 4) && ((t->tm_year % 100) || !(t->tm_year % 400)))
966 fail_on_test(send_timer_error(node, me, la, 30, Feb, 6, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
967 else
968 fail_on_test(send_timer_error(node, me, la, 29, Feb, 6, 0, 1, 0, CEC_OP_REC_SEQ_ONCE_ONLY));
969
970 return OK;
971 }
972
timer_overlap_warning(struct node * node,unsigned me,unsigned la,bool interactive)973 static int timer_overlap_warning(struct node *node, unsigned me, unsigned la, bool interactive)
974 {
975 struct cec_msg msg;
976
977 time_t tomorrow = node->current_time + (24 * 60 * 60);
978 struct tm *t = localtime(&tomorrow);
979
980 if (!node->remote[la].has_analogue_timer)
981 return OK_NOT_SUPPORTED;
982
983 /* No overlap: set timer for tomorrow at 8:00 am for 2 hr. */
984 cec_msg_init(&msg, me, la);
985 cec_msg_set_analogue_timer(&msg, true, t->tm_mday, t->tm_mon + 1, 8, 0, 2, 0,
986 CEC_OP_REC_SEQ_ONCE_ONLY, CEC_OP_ANA_BCAST_TYPE_CABLE,
987 7668, // 479.25 MHz
988 node->remote[la].bcast_sys);
989 fail_on_test(!transmit_timeout(node, &msg, 10000));
990 if (unrecognized_op(&msg))
991 return OK_NOT_SUPPORTED;
992 fail_on_test(timed_out_or_abort(&msg));
993 fail_on_test(timer_has_error(msg));
994 fail_on_test(timer_overlap_warning_is_set(msg));
995
996 /* No overlap, just adjacent: set timer for tomorrow at 10:00 am for 15 min. */
997 cec_msg_init(&msg, me, la);
998 cec_msg_set_analogue_timer(&msg, true, t->tm_mday, t->tm_mon + 1, 10, 0, 0, 15,
999 CEC_OP_REC_SEQ_ONCE_ONLY, CEC_OP_ANA_BCAST_TYPE_CABLE,
1000 7668, // 479.25 MHz
1001 node->remote[la].bcast_sys);
1002 fail_on_test(!transmit_timeout(node, &msg, 10000));
1003 fail_on_test(timed_out_or_abort(&msg));
1004 fail_on_test(timer_has_error(msg));
1005 fail_on_test(timer_overlap_warning_is_set(msg));
1006
1007 /* No overlap, just adjacent: set timer for tomorrow at 7:45 am for 15 min. */
1008 cec_msg_init(&msg, me, la);
1009 cec_msg_set_analogue_timer(&msg, true, t->tm_mday, t->tm_mon + 1, 7, 45, 0, 15,
1010 CEC_OP_REC_SEQ_ONCE_ONLY, CEC_OP_ANA_BCAST_TYPE_CABLE,
1011 7668, // 479.25 MHz
1012 node->remote[la].bcast_sys);
1013 fail_on_test(!transmit_timeout(node, &msg, 10000));
1014 fail_on_test(timed_out_or_abort(&msg));
1015 fail_on_test(timer_has_error(msg));
1016 fail_on_test(timer_overlap_warning_is_set(msg));
1017
1018 /* Overlap tail end: set timer for tomorrow at 9:00 am for 2 hr, repeats on Sun. */
1019 fail_on_test(send_timer_overlap(node, me, la, t->tm_mday, t->tm_mon + 1, 9, 0, 2, 0, 0x1));
1020
1021 /* Overlap front end: set timer for tomorrow at 7:00 am for 1 hr, 30 min. */
1022 fail_on_test(send_timer_overlap(node, me, la, t->tm_mday, t->tm_mon + 1, 7, 0, 1, 30, 0x1));
1023
1024 /* Overlap same start time: set timer for tomorrow at 8:00 am for 30 min. */
1025 fail_on_test(send_timer_overlap(node, me, la, t->tm_mday, t->tm_mon + 1, 8, 0, 0, 30, 0x1));
1026
1027 /* Overlap same end time: set timer for tomorrow at 9:30 am for 30 min. */
1028 fail_on_test(send_timer_overlap(node, me, la, t->tm_mday, t->tm_mon + 1, 9, 30, 0, 30, 0x1));
1029
1030 /* Overlap all timers: set timer for tomorrow at 6:00 am for 6 hr. */
1031 fail_on_test(send_timer_overlap(node, me, la, t->tm_mday, t->tm_mon + 1, 6, 0, 6, 0, 0x1));
1032
1033 /* Clear all the timers. */
1034 fail_on_test(clear_timer(node, me, la, t->tm_mday, t->tm_mon + 1, 8, 0, 2, 0,
1035 CEC_OP_REC_SEQ_ONCE_ONLY));
1036 fail_on_test(clear_timer(node, me, la, t->tm_mday, t->tm_mon + 1, 10, 0, 0, 15,
1037 CEC_OP_REC_SEQ_ONCE_ONLY));
1038 fail_on_test(clear_timer(node, me, la, t->tm_mday, t->tm_mon + 1, 7, 45, 0, 15,
1039 CEC_OP_REC_SEQ_ONCE_ONLY));
1040 fail_on_test(clear_timer(node, me, la, t->tm_mday, t->tm_mon + 1, 9, 0, 2, 0, 0x1));
1041 fail_on_test(clear_timer(node, me, la, t->tm_mday, t->tm_mon + 1, 7, 0, 1, 30, 0x1));
1042 fail_on_test(clear_timer(node, me, la, t->tm_mday, t->tm_mon + 1, 8, 0, 0, 30, 0x1));
1043 fail_on_test(clear_timer(node, me, la, t->tm_mday, t->tm_mon + 1, 9, 30, 0, 30, 0x1));
1044 fail_on_test(clear_timer(node, me, la, t->tm_mday, t->tm_mon + 1, 6, 0, 6, 0, 0x1));
1045
1046 return OK;
1047 }
1048
1049 const vec_remote_subtests timer_prog_subtests{
1050 {
1051 "Set Analogue Timer",
1052 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
1053 timer_prog_set_analog_timer,
1054 },
1055 {
1056 "Set Digital Timer",
1057 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
1058 timer_prog_set_digital_timer,
1059 },
1060 {
1061 "Set Timer Program Title",
1062 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
1063 timer_prog_set_prog_title,
1064 },
1065 {
1066 "Set External Timer",
1067 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
1068 timer_prog_set_ext_timer,
1069 },
1070 {
1071 "Clear Analogue Timer",
1072 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
1073 timer_prog_clear_analog_timer,
1074 },
1075 {
1076 "Clear Digital Timer",
1077 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
1078 timer_prog_clear_digital_timer,
1079 },
1080 {
1081 "Clear External Timer",
1082 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
1083 timer_prog_clear_ext_timer,
1084 },
1085 {
1086 "Set Timers with Errors",
1087 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
1088 timer_errors,
1089 },
1090 {
1091 "Set Overlapping Timers",
1092 CEC_LOG_ADDR_MASK_RECORD | CEC_LOG_ADDR_MASK_BACKUP,
1093 timer_overlap_warning,
1094 },
1095 };
1096