1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
4 */
5
6 #include <ctime>
7 #include <string>
8
9 #include <sys/ioctl.h>
10
11 #include "cec-compliance.h"
12
testFuzzing(struct node & node,unsigned me,unsigned la)13 int testFuzzing(struct node &node, unsigned me, unsigned la)
14 {
15 printf("test fuzzing CEC local LA %d (%s) to remote LA %d (%s):\n\n",
16 me, cec_la2s(me), la, cec_la2s(la));
17
18 if (node.remote[la].in_standby) {
19 announce("The remote device is in standby. It should be powered on when fuzzing. Aborting.");
20 return 0;
21 }
22 if (!node.remote[la].has_power_status) {
23 announce("The device didn't support Give Device Power Status.");
24 announce("Assuming that the device is powered on.");
25 }
26
27 unsigned int cnt = 0;
28
29 for (;;) {
30 cec_msg msg;
31 __u8 cmd;
32 unsigned offset = 2;
33
34 cec_msg_init(&msg, me, la);
35 msg.msg[1] = cmd = random() & 0xff;
36 if (msg.msg[1] == CEC_MSG_STANDBY)
37 continue;
38 msg.len = (random() & 0xf) + 2;
39 if (msg.msg[1] == CEC_MSG_VENDOR_COMMAND_WITH_ID &&
40 node.remote[la].vendor_id != CEC_VENDOR_ID_NONE) {
41 msg.len += 3;
42 offset += 3;
43 msg.msg[2] = (node.remote[la].vendor_id & 0xff0000) >> 16;
44 msg.msg[3] = (node.remote[la].vendor_id & 0xff00) >> 8;
45 msg.msg[4] = node.remote[la].vendor_id & 0xff;
46 }
47 if (msg.len > CEC_MAX_MSG_SIZE)
48 continue;
49
50 const char *name = cec_opcode2s(msg.msg[1]);
51
52 printf("Send message %u:", cnt);
53 for (unsigned int i = 0; i < offset; i++)
54 printf(" %02x", msg.msg[i]);
55 for (unsigned int i = offset; i < msg.len; i++) {
56 msg.msg[i] = random() & 0xff;
57 printf(" %02x", msg.msg[i]);
58 }
59 if (name)
60 printf(" (%s)", name);
61 printf(": ");
62 msg.reply = CEC_MSG_FEATURE_ABORT;
63 fail_on_test(!transmit_timeout(&node, &msg, 1200));
64 printf("%s", timed_out(&msg) ? "Timed out" : "Feature Abort");
65
66 if (cec_msg_status_is_abort(&msg)) {
67 __u8 abort_msg, reason;
68
69 cec_ops_feature_abort(&msg, &abort_msg, &reason);
70 fail_on_test(abort_msg != cmd);
71 switch (reason) {
72 case CEC_OP_ABORT_UNRECOGNIZED_OP:
73 printf(" (Unrecognized Op)");
74 break;
75 case CEC_OP_ABORT_UNDETERMINED:
76 printf(" (Undetermined)");
77 break;
78 case CEC_OP_ABORT_INVALID_OP:
79 printf(" (Invalid Op)");
80 break;
81 case CEC_OP_ABORT_NO_SOURCE:
82 printf(" (No Source)");
83 break;
84 case CEC_OP_ABORT_REFUSED:
85 printf(" (Refused)");
86 break;
87 case CEC_OP_ABORT_INCORRECT_MODE:
88 printf(" (Incorrect Mode)");
89 break;
90 default:
91 printf(" (0x%02x)\n", reason);
92 fail("Invalid reason\n");
93 break;
94 }
95 }
96 printf("\n");
97 if (++cnt % 10)
98 continue;
99 if (la == CEC_LOG_ADDR_BROADCAST)
100 continue;
101 cec_msg_init(&msg, me, la);
102 cec_msg_get_cec_version(&msg, true);
103 printf("Query CEC Version: ");
104 fail_on_test(!transmit_timeout(&node, &msg) || timed_out_or_abort(&msg));
105 printf("OK\n");
106 }
107 }
108