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