1 /*
2  * Copyright 2024 Google LLC
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "emulated_target.hpp"
6 #include <cstdint>
7 
8 #include <zephyr/devicetree.h>
9 #include <zephyr/drivers/i2c.h>
10 #include <zephyr/fff.h>
11 #include <zephyr/ztest.h>
12 
13 namespace
14 {
15 
16 #define GET_TARGET_DEVICE(node_id, prop, n) DEVICE_DT_GET(DT_PHANDLE_BY_IDX(node_id, prop, n)),
17 
18 /* Get the devicetree constants */
19 constexpr const struct device *controller = DEVICE_DT_GET(CONTROLLER_LABEL);
20 constexpr const struct device *targets[FORWARD_COUNT] = {
21 	DT_FOREACH_PROP_ELEM(CONTROLLER_LABEL, forwards, GET_TARGET_DEVICE)};
22 
ZTEST(i2c_emul_forwarding,test_write_is_forwarded)23 ZTEST(i2c_emul_forwarding, test_write_is_forwarded)
24 {
25 	uint8_t data[] = {0x00, 0x01, 0x02};
26 
27 	target_buf_write_received_0_fake.custom_fake = [&data](struct i2c_target_config *,
28 							       uint8_t *buf, uint32_t len) {
29 		zassert_equal(ARRAY_SIZE(data), len);
30 		zexpect_mem_equal(data, buf, len);
31 	};
32 
33 	zassert_ok(
34 		i2c_write(controller, data, ARRAY_SIZE(data), emulated_target_config[0].address));
35 
36 	// Expect 0 reads and 1 write/stop to be made
37 	zexpect_equal(0, target_buf_read_requested_0_fake.call_count);
38 	zexpect_equal(1, target_buf_write_received_0_fake.call_count);
39 	zexpect_equal(1, target_stop_0_fake.call_count);
40 }
41 
ZTEST(i2c_emul_forwarding,test_read_is_forwarded)42 ZTEST(i2c_emul_forwarding, test_read_is_forwarded)
43 {
44 	uint8_t expected[] = {0x01, 0x02, 0x03};
45 	uint8_t data[ARRAY_SIZE(expected)] = {};
46 
47 	/* Set the custom fake function to a lambda which captures the expected value as a reference.
48 	 * This means that when the function is executed, we can access 'expected' as though it were
49 	 * within the lambda's scope.
50 	 */
51 	target_buf_read_requested_0_fake.custom_fake = [&expected](struct i2c_target_config *,
52 								   uint8_t **ptr, uint32_t *len) {
53 		*ptr = expected;
54 		*len = ARRAY_SIZE(expected);
55 		return 0;
56 	};
57 
58 	zassert_ok(i2c_read(controller, data, ARRAY_SIZE(expected),
59 			    emulated_target_config[0].address));
60 
61 	// Expect 1 read/stop and 0 write to be made
62 	zexpect_equal(1, target_buf_read_requested_0_fake.call_count);
63 	zexpect_equal(0, target_buf_write_received_0_fake.call_count);
64 	zexpect_equal(1, target_stop_0_fake.call_count);
65 	zexpect_mem_equal(expected, data, ARRAY_SIZE(expected));
66 }
67 
ZTEST(i2c_emul_forwarding,test_failed_read_request)68 ZTEST(i2c_emul_forwarding, test_failed_read_request)
69 {
70 	uint8_t data;
71 	target_buf_read_requested_0_fake.return_val = -EINTR;
72 
73 	zassert_equal(-EINTR, i2c_read(controller, &data, 1, emulated_target_config[0].address));
74 	zexpect_equal(1, target_buf_read_requested_0_fake.call_count);
75 	zexpect_equal(0, target_buf_write_received_0_fake.call_count);
76 	zexpect_equal(0, target_stop_0_fake.call_count);
77 }
78 
ZTEST(i2c_emul_forwarding,test_read_request_overflow)79 ZTEST(i2c_emul_forwarding, test_read_request_overflow)
80 {
81 	uint8_t data;
82 
83 	/* Set the custom_fake to a local lambda with no capture values. */
84 	target_buf_read_requested_0_fake.custom_fake = [](struct i2c_target_config *, uint8_t **_,
85 							  uint32_t *len) {
86 		*len = UINT32_MAX;
87 		return 0;
88 	};
89 
90 	zassert_equal(-ENOMEM, i2c_read(controller, &data, 1, emulated_target_config[0].address));
91 	zexpect_equal(1, target_buf_read_requested_0_fake.call_count);
92 	zexpect_equal(0, target_buf_write_received_0_fake.call_count);
93 	zexpect_equal(0, target_stop_0_fake.call_count);
94 }
95 
ZTEST(i2c_emul_forwarding,test_transfer_is_forwarded)96 ZTEST(i2c_emul_forwarding, test_transfer_is_forwarded)
97 {
98 	uint8_t write_data[1] = {};
99 	uint8_t read_data[2] = {};
100 
101 	struct i2c_msg msgs[] = {
102 		{
103 			.buf = write_data,
104 			.len = sizeof(write_data),
105 			.flags = I2C_MSG_WRITE,
106 		},
107 		{
108 			.buf = read_data,
109 			.len = sizeof(read_data),
110 			.flags = I2C_MSG_READ | I2C_MSG_STOP,
111 		},
112 	};
113 
114 	int phase = 0;
115 	target_buf_write_received_0_fake.custom_fake = [&phase](struct i2c_target_config *,
116 								uint8_t *, uint32_t) {
117 		zassert_equal(0, phase,
118 			      "Expected a call to buf_write_received before anything else");
119 		phase++;
120 	};
121 	target_buf_read_requested_0_fake.custom_fake = [&phase](struct i2c_target_config *,
122 								uint8_t **ptr, uint32_t *len) {
123 		zassert_equal(1, phase, "Expected a call to buf_Read_requested as the second step");
124 		phase++;
125 
126 		// Write a random byte. It doesn't make a difference.
127 		*ptr = (uint8_t *)&phase;
128 		*len = 1;
129 		return 0;
130 	};
131 	target_stop_0_fake.custom_fake = [&phase](struct i2c_target_config *) -> int {
132 		zassert_equal(2, phase, "Expected a call to stop as the 3rd step");
133 		phase++;
134 		return 0;
135 	};
136 
137 	zassert_ok(i2c_transfer(controller, msgs, ARRAY_SIZE(msgs),
138 				emulated_target_config[0].address));
139 	zexpect_equal(1, target_buf_write_received_0_fake.call_count);
140 	zexpect_equal(1, target_buf_read_requested_0_fake.call_count);
141 	zexpect_equal(1, target_stop_0_fake.call_count);
142 	zexpect_equal(3, phase, "Expected a total of 3 phases, but got %d", phase);
143 }
144 
ZTEST(i2c_emul_forwarding,test_call_pio_forwarded_bus_when_buffering_enabled)145 ZTEST(i2c_emul_forwarding, test_call_pio_forwarded_bus_when_buffering_enabled)
146 {
147 	uint8_t data[2];
148 
149 	zassert_ok(i2c_read(controller, data, ARRAY_SIZE(data), emulated_target_config[1].address));
150 	zexpect_equal(1, target_read_requested_1_fake.call_count);
151 	zexpect_equal(1, target_read_processed_1_fake.call_count);
152 	zexpect_equal(1, target_stop_1_fake.call_count);
153 }
154 
155 } // namespace
156