1 /*
2 * Copyright 2024 Google LLC
3 * SPDX-License-Identifier: Apache-2.0
4 */
5 #include "emulated_target.hpp"
6
7 #include <zephyr/devicetree.h>
8 #include <zephyr/drivers/i2c.h>
9 #include <zephyr/fff.h>
10 #include <zephyr/ztest.h>
11
12 namespace
13 {
14
15 /* Get the devicetree constants */
16 constexpr const struct device *controller = DEVICE_DT_GET(CONTROLLER_LABEL);
17
ZTEST(i2c_emul_forwarding,test_write_is_forwarded)18 ZTEST(i2c_emul_forwarding, test_write_is_forwarded)
19 {
20 // Try writing some values
21 for (uint8_t data = 0; data < 10; ++data) {
22 const unsigned int expected_call_count = 1 + data;
23
24 zassert_ok(i2c_write(controller, &data, sizeof(data),
25 emulated_target_config[0].address));
26
27 // Expected no reads to be made
28 zexpect_equal(0, target_read_requested_0_fake.call_count);
29 zexpect_equal(0, target_read_processed_0_fake.call_count);
30
31 // Expected N write requests to be made
32 zexpect_equal(expected_call_count, target_write_requested_0_fake.call_count,
33 "Expected to be called %d times, got %d", expected_call_count,
34 target_write_requested_0_fake.call_count);
35 zexpect_equal(expected_call_count, target_write_received_0_fake.call_count,
36 "Expected to be called %d times, got %d", expected_call_count,
37 target_write_received_0_fake.call_count);
38
39 // Check that the data written was correct
40 zexpect_equal(data, target_write_received_0_fake.arg1_val,
41 "Expected data value %u. got %u", data,
42 target_write_received_0_fake.arg1_val);
43
44 // Expect 1 stop call per write request
45 zexpect_equal(expected_call_count, target_stop_0_fake.call_count,
46 "Expected to be called %d times, got %d", expected_call_count,
47 target_stop_0_fake.call_count);
48 }
49 }
50
ZTEST(i2c_emul_forwarding,test_read_is_forwarded)51 ZTEST(i2c_emul_forwarding, test_read_is_forwarded)
52 {
53 // Try reading some values
54 for (uint8_t i = 0; i < 10; ++i) {
55 const uint8_t expected_data[2] = {
56 static_cast<uint8_t>(0x1 * i),
57 static_cast<uint8_t>(0x2 * i),
58 };
59 const unsigned int expected_call_count = 1 + i;
60 uint8_t data[2];
61
62 // Setup some lambdas to do the actual reads using 'expected_data'
63 target_read_requested_0_fake.custom_fake =
64 [expected_data](struct i2c_target_config *, uint8_t *out) -> int {
65 *out = expected_data[0];
66 return 0;
67 };
68 target_read_processed_0_fake.custom_fake =
69 [expected_data](struct i2c_target_config *, uint8_t *out) -> int {
70 *out = expected_data[1];
71 return 0;
72 };
73 zassert_ok(i2c_read(controller, data, sizeof(data),
74 emulated_target_config[0].address));
75
76 // Expect the read functions to be called N times
77 zexpect_equal(expected_call_count, target_read_requested_0_fake.call_count,
78 "Expected to be called %d times, got %d", expected_call_count,
79 target_read_requested_0_fake.call_count);
80 zexpect_equal(expected_call_count, target_read_processed_0_fake.call_count,
81 "Expected to be called %d times, got %d", expected_call_count,
82 target_read_processed_0_fake.call_count);
83
84 // Expect the data read to match
85 zexpect_equal(expected_data[0], data[0], "Expected 0x%02x, got 0x%02x",
86 expected_data[0], data[0]);
87 zexpect_equal(expected_data[1], data[1], "Expected 0x%02x, got 0x%02x",
88 expected_data[1], data[1]);
89
90 // Expect 0 write calls
91 zexpect_equal(0, target_write_requested_0_fake.call_count);
92 zexpect_equal(0, target_write_received_0_fake.call_count);
93
94 // Expect 1 stop call per read
95 zexpect_equal(expected_call_count, target_stop_0_fake.call_count,
96 "Expected to be called %d times, got %d", expected_call_count,
97 target_stop_0_fake.call_count);
98 }
99 }
100
ZTEST(i2c_emul_forwarding,test_recover_failed_write)101 ZTEST(i2c_emul_forwarding, test_recover_failed_write)
102 {
103 uint8_t write_data[2];
104
105 // Fail on the write request (should never call the write_received function)
106 target_write_requested_0_fake.return_val = -EINVAL;
107 zassert_equal(-EINVAL, i2c_write(controller, write_data, sizeof(write_data),
108 emulated_target_config[0].address));
109 zexpect_equal(1, target_write_requested_0_fake.call_count, "Was called %d times",
110 target_write_requested_0_fake.call_count);
111 zexpect_equal(0, target_write_received_0_fake.call_count, "Was called %d times",
112 target_write_requested_0_fake.call_count);
113
114 // Next instruction should succeed
115 target_write_requested_0_fake.return_val = 0;
116 zassert_ok(i2c_write(controller, write_data, sizeof(write_data),
117 emulated_target_config[0].address));
118 zexpect_equal(2, target_write_requested_0_fake.call_count, "Was called %d times",
119 target_write_requested_0_fake.call_count);
120 zexpect_equal(2, target_write_received_0_fake.call_count, "Was called %d times",
121 target_write_requested_0_fake.call_count);
122 }
123
ZTEST(i2c_emul_forwarding,test_recover_failed_read)124 ZTEST(i2c_emul_forwarding, test_recover_failed_read)
125 {
126 uint8_t read_data[2];
127
128 // Fail the read_requested (should never call the read_processed function)
129 target_read_requested_0_fake.return_val = -EINVAL;
130 zassert_equal(-EINVAL, i2c_read(controller, read_data, sizeof(read_data),
131 emulated_target_config[0].address));
132 zexpect_equal(1, target_read_requested_0_fake.call_count, "Was called %d times",
133 target_read_requested_0_fake.call_count);
134 zexpect_equal(0, target_read_processed_0_fake.call_count, "Was called %d times",
135 target_read_processed_0_fake.call_count);
136
137 // Next instruction should pass
138 target_read_requested_0_fake.return_val = 0;
139 zassert_ok(i2c_read(controller, read_data, sizeof(read_data),
140 emulated_target_config[0].address));
141 zexpect_equal(2, target_read_requested_0_fake.call_count, "Was called %d times",
142 target_read_requested_0_fake.call_count);
143 zexpect_equal(1, target_read_processed_0_fake.call_count, "Was called %d times",
144 target_read_processed_0_fake.call_count);
145 }
146
ZTEST(i2c_emul_forwarding,test_transfer_is_forwarded)147 ZTEST(i2c_emul_forwarding, test_transfer_is_forwarded)
148 {
149 uint8_t write_data[1] = {};
150 uint8_t read_data[2] = {};
151
152 struct i2c_msg msgs[] = {
153 {
154 .buf = write_data,
155 .len = sizeof(write_data),
156 .flags = I2C_MSG_WRITE,
157 },
158 {
159 .buf = read_data,
160 .len = sizeof(read_data),
161 .flags = I2C_MSG_READ | I2C_MSG_STOP,
162 },
163 };
164
165 int phase = 0;
166 target_write_requested_0_fake.custom_fake = [&phase](struct i2c_target_config *) -> int {
167 zassert_equal(0, phase, "Expected a call to write_requested before anything else");
168 phase++;
169 return 0;
170 };
171 target_write_received_0_fake.custom_fake = [&phase](struct i2c_target_config *,
172 uint8_t) -> int {
173 zassert_equal(1, phase, "Expected a call to write_received as the second step");
174 phase++;
175 return 0;
176 };
177 target_read_requested_0_fake.custom_fake = [&phase](struct i2c_target_config *,
178 uint8_t *) -> int {
179 zassert_equal(2, phase, "Expected a call to read_requested as the 3rd step");
180 phase++;
181 return 0;
182 };
183 target_read_processed_0_fake.custom_fake = [&phase](struct i2c_target_config *,
184 uint8_t *) -> int {
185 zassert_equal(3, phase, "Expected a call to read_processed as the 4th step");
186 phase++;
187 return 0;
188 };
189 target_stop_0_fake.custom_fake = [&phase](struct i2c_target_config *) -> int {
190 zassert_equal(4, phase, "Expected a call to stop as the 5th step");
191 phase++;
192 return 0;
193 };
194 zassert_ok(i2c_transfer(controller, msgs, ARRAY_SIZE(msgs),
195 emulated_target_config[0].address));
196 zexpect_equal(1, target_write_requested_0_fake.call_count,
197 "Expected target_write_requested to be called once, but got %d",
198 target_write_requested_0_fake.call_count);
199 zexpect_equal(1, target_write_received_0_fake.call_count,
200 "Expected target_write_received to be called once, but got %d",
201 target_write_received_0_fake.call_count);
202 zexpect_equal(1, target_read_requested_0_fake.call_count,
203 "Expected target_read_requested to be called once, but got %d",
204 target_read_requested_0_fake.call_count);
205 zexpect_equal(1, target_read_processed_0_fake.call_count,
206 "Expected target_read_processed to be called once, but got %d",
207 target_read_processed_0_fake.call_count);
208 zexpect_equal(1, target_stop_0_fake.call_count,
209 "Expected target_stop to be called once, but got %d",
210 target_stop_0_fake.call_count);
211 zexpect_equal(5, phase, "Expected a total of 5 phases, but got %d", phase);
212 }
213
ZTEST(i2c_emul_forwarding,test_forward_two_targets)214 ZTEST(i2c_emul_forwarding, test_forward_two_targets)
215 {
216 uint8_t read_data[2];
217
218 // Read the second forward and ensure that we only forwarded to the correct one
219 zassert_ok(i2c_read(controller, read_data, sizeof(read_data),
220 emulated_target_config[1].address));
221
222 // Check that we got the forward
223 zexpect_equal(1, target_read_requested_1_fake.call_count,
224 "Expected to be called 1 time, got %d",
225 target_read_requested_1_fake.call_count);
226 zexpect_equal(1, target_read_processed_1_fake.call_count,
227 "Expected to be called 1 time, got %d",
228 target_read_processed_1_fake.call_count);
229
230 // Check that we didn't forward to the first target
231 zexpect_equal(0, target_read_requested_0_fake.call_count,
232 "Expected to be called 0 times, got %d",
233 target_read_requested_0_fake.call_count);
234 zexpect_equal(0, target_read_processed_0_fake.call_count,
235 "Expected to be called 0 times, got %d",
236 target_read_processed_0_fake.call_count);
237 }
238
ZTEST(i2c_emul_forwarding,test_error_in_write_received)239 ZTEST(i2c_emul_forwarding, test_error_in_write_received)
240 {
241 uint8_t data;
242
243 target_write_received_0_fake.return_val = -EINTR;
244 zassert_equal(-EINTR, i2c_write(controller, &data, 1, emulated_target_config[0].address));
245 zexpect_equal(1, target_write_requested_0_fake.call_count);
246 zexpect_equal(1, target_write_received_0_fake.call_count);
247 zexpect_equal(0, target_stop_0_fake.call_count);
248 }
249
250 } // namespace
251