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