1 /*
2  * Logging of I2C messages
3  *
4  * Copyright 2020 Google LLC
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <stdio.h>
10 
11 #include <zephyr/drivers/i2c.h>
12 
13 #define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(i2c);
16 
17 #if defined(CONFIG_I2C_CALLBACK) && defined(CONFIG_POLL)
z_i2c_transfer_signal_cb(const struct device * dev,int result,void * data)18 void z_i2c_transfer_signal_cb(const struct device *dev,
19 	int result,
20 	void *data)
21 {
22 	struct k_poll_signal *sig = (struct k_poll_signal *)data;
23 
24 	k_poll_signal_raise(sig, result);
25 }
26 #endif
27 
28 #ifdef CONFIG_I2C_DUMP_MESSAGES_ALLOWLIST
29 #define DEF_BUS_WITH_ADDR(node, prop, idx) I2C_DT_SPEC_GET(DT_PHANDLE_BY_IDX(node, prop, idx)),
30 #define DEF_ALLOWLIST_DEV(node)            DT_FOREACH_PROP_ELEM(node, devices, DEF_BUS_WITH_ADDR)
31 
32 struct i2c_dt_spec messages_allowlist[] = {
33 	DT_FOREACH_STATUS_OKAY(zephyr_i2c_dump_allowlist, DEF_ALLOWLIST_DEV)};
34 
35 #undef DEF_ALLOWLIST_DEV
36 #undef DEF_BUS_WITH_ADDR
37 #endif
38 
i2c_dump_msgs_rw(const struct device * dev,const struct i2c_msg * msgs,uint8_t num_msgs,uint16_t addr,bool dump_read)39 void i2c_dump_msgs_rw(const struct device *dev, const struct i2c_msg *msgs, uint8_t num_msgs,
40 		      uint16_t addr, bool dump_read)
41 {
42 #ifdef CONFIG_I2C_DUMP_MESSAGES_ALLOWLIST
43 	bool found_dev = 0;
44 
45 	for (int a = 0; a < ARRAY_SIZE(messages_allowlist); a++) {
46 		struct i2c_dt_spec *allowed = &messages_allowlist[a];
47 
48 		if (dev != allowed->bus || addr != allowed->addr) {
49 			continue;
50 		} else {
51 			found_dev = 1;
52 			break;
53 		}
54 	}
55 
56 	if (!found_dev) {
57 		return;
58 	}
59 #endif
60 
61 	LOG_DBG("I2C msg: %s, addr=%x", dev->name, addr);
62 	for (unsigned int i = 0; i < num_msgs; i++) {
63 		const struct i2c_msg *msg = &msgs[i];
64 		const bool is_read = msg->flags & I2C_MSG_READ;
65 		const bool dump_data = dump_read || !is_read;
66 
67 		if (msg->len == 1 && dump_data) {
68 			LOG_DBG("   %c %2s %1s len=01: %02x", is_read ? 'R' : 'W',
69 				msg->flags & I2C_MSG_RESTART ? "Sr" : "",
70 				msg->flags & I2C_MSG_STOP ? "P" : "", msg->buf[0]);
71 		} else {
72 			LOG_DBG("   %c %2s %1s len=%02x: ", is_read ? 'R' : 'W',
73 				msg->flags & I2C_MSG_RESTART ? "Sr" : "",
74 				msg->flags & I2C_MSG_STOP ? "P" : "", msg->len);
75 			if (dump_data) {
76 				LOG_HEXDUMP_DBG(msg->buf, msg->len, "contents:");
77 			}
78 		}
79 	}
80 }
81