1*0cbe4818SRobert Mustacchi /*
2*0cbe4818SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*0cbe4818SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*0cbe4818SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*0cbe4818SRobert Mustacchi * 1.0 of the CDDL.
6*0cbe4818SRobert Mustacchi *
7*0cbe4818SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*0cbe4818SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*0cbe4818SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*0cbe4818SRobert Mustacchi */
11*0cbe4818SRobert Mustacchi
12*0cbe4818SRobert Mustacchi /*
13*0cbe4818SRobert Mustacchi * Copyright 2025 Oxide Computer Company
14*0cbe4818SRobert Mustacchi */
15*0cbe4818SRobert Mustacchi
16*0cbe4818SRobert Mustacchi /*
17*0cbe4818SRobert Mustacchi * Verify that we fail when we're missing a field in a given request. This works
18*0cbe4818SRobert Mustacchi * from the empty device profile and targets smbussim1 where there will be no
19*0cbe4818SRobert Mustacchi * devices.
20*0cbe4818SRobert Mustacchi */
21*0cbe4818SRobert Mustacchi
22*0cbe4818SRobert Mustacchi #include <stdlib.h>
23*0cbe4818SRobert Mustacchi #include <err.h>
24*0cbe4818SRobert Mustacchi
25*0cbe4818SRobert Mustacchi #include "libi2c_test_util.h"
26*0cbe4818SRobert Mustacchi
27*0cbe4818SRobert Mustacchi static bool
test_add(i2c_hdl_t * hdl,i2c_dev_add_req_t * req,const char * desc)28*0cbe4818SRobert Mustacchi test_add(i2c_hdl_t *hdl, i2c_dev_add_req_t *req, const char *desc)
29*0cbe4818SRobert Mustacchi {
30*0cbe4818SRobert Mustacchi if (i2c_device_add_req_exec(req)) {
31*0cbe4818SRobert Mustacchi warnx("TEST FAILED: incomplete device add (%s) accidentally "
32*0cbe4818SRobert Mustacchi "succeeded", desc);
33*0cbe4818SRobert Mustacchi return (false);
34*0cbe4818SRobert Mustacchi } else if (i2c_err(hdl) != I2C_ERR_ADD_DEV_REQ_MISSING_FIELDS) {
35*0cbe4818SRobert Mustacchi warnx("TEST FAILED: incomplete device add (%s) failed with "
36*0cbe4818SRobert Mustacchi "%s (0x%x), expected I2C_ERR_ADD_DEV_REQ_MISSING_FIELDS "
37*0cbe4818SRobert Mustacchi "(0x%x)", desc, i2c_errtostr(hdl, i2c_err(hdl)),
38*0cbe4818SRobert Mustacchi i2c_err(hdl), I2C_ERR_ADD_DEV_REQ_MISSING_FIELDS);
39*0cbe4818SRobert Mustacchi return (false);
40*0cbe4818SRobert Mustacchi } else {
41*0cbe4818SRobert Mustacchi (void) printf("TEST PASSED: incomplete device add (%s) failed "
42*0cbe4818SRobert Mustacchi "with I2C_ERR_ADD_DEV_REQ_MISSING_FIELDS\n", desc);
43*0cbe4818SRobert Mustacchi return (true);
44*0cbe4818SRobert Mustacchi }
45*0cbe4818SRobert Mustacchi }
46*0cbe4818SRobert Mustacchi
47*0cbe4818SRobert Mustacchi /*
48*0cbe4818SRobert Mustacchi * Test that we error with missing fields. The compatible field is optional so
49*0cbe4818SRobert Mustacchi * this is basically just checking combinations of name and addr.
50*0cbe4818SRobert Mustacchi */
51*0cbe4818SRobert Mustacchi static bool
missing_adds(i2c_hdl_t * hdl,i2c_port_t * port)52*0cbe4818SRobert Mustacchi missing_adds(i2c_hdl_t *hdl, i2c_port_t *port)
53*0cbe4818SRobert Mustacchi {
54*0cbe4818SRobert Mustacchi bool ret = true;
55*0cbe4818SRobert Mustacchi i2c_dev_add_req_t *add;
56*0cbe4818SRobert Mustacchi
57*0cbe4818SRobert Mustacchi if (!i2c_device_add_req_init(port, &add)) {
58*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
59*0cbe4818SRobert Mustacchi "initialize device add requiest");
60*0cbe4818SRobert Mustacchi }
61*0cbe4818SRobert Mustacchi
62*0cbe4818SRobert Mustacchi if (!test_add(hdl, add, "all")) {
63*0cbe4818SRobert Mustacchi ret = false;
64*0cbe4818SRobert Mustacchi }
65*0cbe4818SRobert Mustacchi
66*0cbe4818SRobert Mustacchi const i2c_addr_t addr = { I2C_ADDR_7BIT, 0x23 };
67*0cbe4818SRobert Mustacchi if (!i2c_device_add_req_set_addr(add, &addr)) {
68*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to set "
69*0cbe4818SRobert Mustacchi "device add address");
70*0cbe4818SRobert Mustacchi }
71*0cbe4818SRobert Mustacchi
72*0cbe4818SRobert Mustacchi if (!test_add(hdl, add, "name")) {
73*0cbe4818SRobert Mustacchi ret = false;
74*0cbe4818SRobert Mustacchi }
75*0cbe4818SRobert Mustacchi i2c_device_add_req_fini(add);
76*0cbe4818SRobert Mustacchi
77*0cbe4818SRobert Mustacchi if (!i2c_device_add_req_init(port, &add)) {
78*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
79*0cbe4818SRobert Mustacchi "initialize device add requiest");
80*0cbe4818SRobert Mustacchi }
81*0cbe4818SRobert Mustacchi
82*0cbe4818SRobert Mustacchi if (!i2c_device_add_req_set_name(add, "foobar")) {
83*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to set "
84*0cbe4818SRobert Mustacchi "device add address");
85*0cbe4818SRobert Mustacchi }
86*0cbe4818SRobert Mustacchi
87*0cbe4818SRobert Mustacchi if (!test_add(hdl, add, "addr")) {
88*0cbe4818SRobert Mustacchi ret = false;
89*0cbe4818SRobert Mustacchi }
90*0cbe4818SRobert Mustacchi
91*0cbe4818SRobert Mustacchi i2c_device_add_req_fini(add);
92*0cbe4818SRobert Mustacchi
93*0cbe4818SRobert Mustacchi return (ret);
94*0cbe4818SRobert Mustacchi }
95*0cbe4818SRobert Mustacchi
96*0cbe4818SRobert Mustacchi static bool
test_i2c_io(i2c_hdl_t * hdl,i2c_io_req_t * req,const char * desc)97*0cbe4818SRobert Mustacchi test_i2c_io(i2c_hdl_t *hdl, i2c_io_req_t *req, const char *desc)
98*0cbe4818SRobert Mustacchi {
99*0cbe4818SRobert Mustacchi if (i2c_io_req_exec(req)) {
100*0cbe4818SRobert Mustacchi warnx("TEST FAILED: incomplete I2C I/O (%s) accidentally "
101*0cbe4818SRobert Mustacchi "succeeded", desc);
102*0cbe4818SRobert Mustacchi return (false);
103*0cbe4818SRobert Mustacchi } else if (i2c_err(hdl) != I2C_ERR_IO_REQ_MISSING_FIELDS) {
104*0cbe4818SRobert Mustacchi warnx("TEST FAILED: incomplete I2C I/O (%s) failed with "
105*0cbe4818SRobert Mustacchi "%s (0x%x), expected I2C_ERR_IO_REQ_MISSING_FIELDS (0x%x)",
106*0cbe4818SRobert Mustacchi desc, i2c_errtostr(hdl, i2c_err(hdl)), i2c_err(hdl),
107*0cbe4818SRobert Mustacchi I2C_ERR_IO_REQ_MISSING_FIELDS);
108*0cbe4818SRobert Mustacchi return (false);
109*0cbe4818SRobert Mustacchi } else {
110*0cbe4818SRobert Mustacchi (void) printf("TEST PASSED: incomplete I2C I/O (%s) failed "
111*0cbe4818SRobert Mustacchi "with I2C_ERR_IO_REQ_MISSING_FIELDS\n", desc);
112*0cbe4818SRobert Mustacchi return (true);
113*0cbe4818SRobert Mustacchi }
114*0cbe4818SRobert Mustacchi }
115*0cbe4818SRobert Mustacchi
116*0cbe4818SRobert Mustacchi static bool
missing_i2c_io(i2c_hdl_t * hdl,i2c_port_t * port)117*0cbe4818SRobert Mustacchi missing_i2c_io(i2c_hdl_t *hdl, i2c_port_t *port)
118*0cbe4818SRobert Mustacchi {
119*0cbe4818SRobert Mustacchi bool ret = true;
120*0cbe4818SRobert Mustacchi i2c_io_req_t *req;
121*0cbe4818SRobert Mustacchi
122*0cbe4818SRobert Mustacchi if (!i2c_io_req_init(port, &req)) {
123*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
124*0cbe4818SRobert Mustacchi "initialize I2C I/O request");
125*0cbe4818SRobert Mustacchi }
126*0cbe4818SRobert Mustacchi
127*0cbe4818SRobert Mustacchi if (!test_i2c_io(hdl, req, "all")) {
128*0cbe4818SRobert Mustacchi ret = false;
129*0cbe4818SRobert Mustacchi }
130*0cbe4818SRobert Mustacchi
131*0cbe4818SRobert Mustacchi uint8_t rbuf[4] = { 0 };
132*0cbe4818SRobert Mustacchi uint8_t wbuf[4] = { 0 };
133*0cbe4818SRobert Mustacchi if (!i2c_io_req_set_transmit_data(req, wbuf, sizeof (wbuf))) {
134*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
135*0cbe4818SRobert Mustacchi "set I2C transmit buffer");
136*0cbe4818SRobert Mustacchi }
137*0cbe4818SRobert Mustacchi
138*0cbe4818SRobert Mustacchi if (!i2c_io_req_set_receive_buf(req, rbuf, sizeof (rbuf))) {
139*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
140*0cbe4818SRobert Mustacchi "set I2C receive buffer");
141*0cbe4818SRobert Mustacchi }
142*0cbe4818SRobert Mustacchi
143*0cbe4818SRobert Mustacchi if (!test_i2c_io(hdl, req, "addr")) {
144*0cbe4818SRobert Mustacchi ret = false;
145*0cbe4818SRobert Mustacchi }
146*0cbe4818SRobert Mustacchi i2c_io_req_fini(req);
147*0cbe4818SRobert Mustacchi return (ret);
148*0cbe4818SRobert Mustacchi }
149*0cbe4818SRobert Mustacchi
150*0cbe4818SRobert Mustacchi static bool
test_smbus_io(i2c_hdl_t * hdl,smbus_io_req_t * req,const char * desc)151*0cbe4818SRobert Mustacchi test_smbus_io(i2c_hdl_t *hdl, smbus_io_req_t *req, const char *desc)
152*0cbe4818SRobert Mustacchi {
153*0cbe4818SRobert Mustacchi if (smbus_io_req_exec(req)) {
154*0cbe4818SRobert Mustacchi warnx("TEST FAILED: incomplete SMBus I/O (%s) accidentally "
155*0cbe4818SRobert Mustacchi "succeeded", desc);
156*0cbe4818SRobert Mustacchi return (false);
157*0cbe4818SRobert Mustacchi } else if (i2c_err(hdl) != I2C_ERR_IO_REQ_MISSING_FIELDS) {
158*0cbe4818SRobert Mustacchi warnx("TEST FAILED: incomplete SMBus I/O (%s) failed with "
159*0cbe4818SRobert Mustacchi "%s (0x%x), expected I2C_ERR_IO_REQ_MISSING_FIELDS (0x%x)",
160*0cbe4818SRobert Mustacchi desc, i2c_errtostr(hdl, i2c_err(hdl)), i2c_err(hdl),
161*0cbe4818SRobert Mustacchi I2C_ERR_IO_REQ_MISSING_FIELDS);
162*0cbe4818SRobert Mustacchi return (false);
163*0cbe4818SRobert Mustacchi } else {
164*0cbe4818SRobert Mustacchi (void) printf("TEST PASSED: incomplete SMBus I/O (%s) failed "
165*0cbe4818SRobert Mustacchi "with I2C_ERR_IO_REQ_MISSING_FIELDS\n", desc);
166*0cbe4818SRobert Mustacchi return (true);
167*0cbe4818SRobert Mustacchi }
168*0cbe4818SRobert Mustacchi }
169*0cbe4818SRobert Mustacchi
170*0cbe4818SRobert Mustacchi /*
171*0cbe4818SRobert Mustacchi * We only test a handful of the various SMBus operations here and hope that if
172*0cbe4818SRobert Mustacchi * it works for them it works for most.
173*0cbe4818SRobert Mustacchi */
174*0cbe4818SRobert Mustacchi static bool
missing_smbus_io(i2c_hdl_t * hdl,i2c_port_t * port)175*0cbe4818SRobert Mustacchi missing_smbus_io(i2c_hdl_t *hdl, i2c_port_t *port)
176*0cbe4818SRobert Mustacchi {
177*0cbe4818SRobert Mustacchi bool ret = true;
178*0cbe4818SRobert Mustacchi smbus_io_req_t *req;
179*0cbe4818SRobert Mustacchi
180*0cbe4818SRobert Mustacchi if (!smbus_io_req_init(port, &req)) {
181*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
182*0cbe4818SRobert Mustacchi "initialize SMBus I/O request");
183*0cbe4818SRobert Mustacchi }
184*0cbe4818SRobert Mustacchi
185*0cbe4818SRobert Mustacchi if (!test_smbus_io(hdl, req, "all")) {
186*0cbe4818SRobert Mustacchi ret = false;
187*0cbe4818SRobert Mustacchi }
188*0cbe4818SRobert Mustacchi smbus_io_req_fini(req);
189*0cbe4818SRobert Mustacchi
190*0cbe4818SRobert Mustacchi if (!smbus_io_req_init(port, &req)) {
191*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
192*0cbe4818SRobert Mustacchi "initialize SMBus I/O request");
193*0cbe4818SRobert Mustacchi }
194*0cbe4818SRobert Mustacchi
195*0cbe4818SRobert Mustacchi const i2c_addr_t addr = { I2C_ADDR_7BIT, 0x42 };
196*0cbe4818SRobert Mustacchi if (!smbus_io_req_set_addr(req, &addr)) {
197*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
198*0cbe4818SRobert Mustacchi "set SMBus request address");
199*0cbe4818SRobert Mustacchi }
200*0cbe4818SRobert Mustacchi
201*0cbe4818SRobert Mustacchi if (!test_smbus_io(hdl, req, "command")) {
202*0cbe4818SRobert Mustacchi ret = false;
203*0cbe4818SRobert Mustacchi }
204*0cbe4818SRobert Mustacchi smbus_io_req_fini(req);
205*0cbe4818SRobert Mustacchi
206*0cbe4818SRobert Mustacchi if (!smbus_io_req_init(port, &req)) {
207*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
208*0cbe4818SRobert Mustacchi "initialize SMBus I/O request");
209*0cbe4818SRobert Mustacchi }
210*0cbe4818SRobert Mustacchi
211*0cbe4818SRobert Mustacchi if (!smbus_io_req_set_write_u16(req, 0x23, 0x7777)) {
212*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
213*0cbe4818SRobert Mustacchi "set write u16 command");
214*0cbe4818SRobert Mustacchi }
215*0cbe4818SRobert Mustacchi
216*0cbe4818SRobert Mustacchi if (!test_smbus_io(hdl, req, "addr: u16")) {
217*0cbe4818SRobert Mustacchi ret = false;
218*0cbe4818SRobert Mustacchi }
219*0cbe4818SRobert Mustacchi smbus_io_req_fini(req);
220*0cbe4818SRobert Mustacchi
221*0cbe4818SRobert Mustacchi if (!smbus_io_req_init(port, &req)) {
222*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
223*0cbe4818SRobert Mustacchi "initialize SMBus I/O request");
224*0cbe4818SRobert Mustacchi }
225*0cbe4818SRobert Mustacchi
226*0cbe4818SRobert Mustacchi uint8_t buf[4];
227*0cbe4818SRobert Mustacchi if (!smbus_io_req_set_read_block_i2c(req, 0x23, buf, sizeof (buf))) {
228*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
229*0cbe4818SRobert Mustacchi "set read I2C block command");
230*0cbe4818SRobert Mustacchi }
231*0cbe4818SRobert Mustacchi
232*0cbe4818SRobert Mustacchi if (!test_smbus_io(hdl, req, "addr: read block i2c")) {
233*0cbe4818SRobert Mustacchi ret = false;
234*0cbe4818SRobert Mustacchi }
235*0cbe4818SRobert Mustacchi smbus_io_req_fini(req);
236*0cbe4818SRobert Mustacchi
237*0cbe4818SRobert Mustacchi
238*0cbe4818SRobert Mustacchi return (ret);
239*0cbe4818SRobert Mustacchi }
240*0cbe4818SRobert Mustacchi
241*0cbe4818SRobert Mustacchi int
main(void)242*0cbe4818SRobert Mustacchi main(void)
243*0cbe4818SRobert Mustacchi {
244*0cbe4818SRobert Mustacchi i2c_port_t *port;
245*0cbe4818SRobert Mustacchi int ret = EXIT_SUCCESS;
246*0cbe4818SRobert Mustacchi i2c_hdl_t *hdl = i2c_init();
247*0cbe4818SRobert Mustacchi if (hdl == NULL) {
248*0cbe4818SRobert Mustacchi err(EXIT_FAILURE, "INTERNAL TEST FAILURE: failed to create "
249*0cbe4818SRobert Mustacchi "libi2c handle");
250*0cbe4818SRobert Mustacchi }
251*0cbe4818SRobert Mustacchi
252*0cbe4818SRobert Mustacchi if (!i2c_port_init_by_path(hdl, "smbussim1/0", &port)) {
253*0cbe4818SRobert Mustacchi libi2c_test_fatal(hdl, "INTERNAL TEST FAILURE: failed to "
254*0cbe4818SRobert Mustacchi "initialize port smbussim1/0");
255*0cbe4818SRobert Mustacchi }
256*0cbe4818SRobert Mustacchi
257*0cbe4818SRobert Mustacchi if (!missing_adds(hdl, port)) {
258*0cbe4818SRobert Mustacchi ret = EXIT_FAILURE;
259*0cbe4818SRobert Mustacchi }
260*0cbe4818SRobert Mustacchi
261*0cbe4818SRobert Mustacchi if (!missing_i2c_io(hdl, port)) {
262*0cbe4818SRobert Mustacchi ret = EXIT_FAILURE;
263*0cbe4818SRobert Mustacchi }
264*0cbe4818SRobert Mustacchi
265*0cbe4818SRobert Mustacchi if (!missing_smbus_io(hdl, port)) {
266*0cbe4818SRobert Mustacchi ret = EXIT_FAILURE;
267*0cbe4818SRobert Mustacchi }
268*0cbe4818SRobert Mustacchi
269*0cbe4818SRobert Mustacchi if (ret == EXIT_SUCCESS) {
270*0cbe4818SRobert Mustacchi (void) printf("All tests passed successfully\n");
271*0cbe4818SRobert Mustacchi }
272*0cbe4818SRobert Mustacchi i2c_port_fini(port);
273*0cbe4818SRobert Mustacchi i2c_fini(hdl);
274*0cbe4818SRobert Mustacchi return (ret);
275*0cbe4818SRobert Mustacchi }
276