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