diff mbox series

[i2c-tools,2/3] i2ctransfer: add option to print binary data

Message ID 20240807112159.14220-3-wsa+renesas@sang-engineering.com
State Accepted
Headers show
Series i2ctransfer: cleanups & add binary data option | expand

Commit Message

Wolfram Sang Aug. 7, 2024, 11:21 a.m. UTC
Useful to pipe data to other commands for further inspection. Or to just
print out ASCII responses.

Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
---
 tools/i2ctransfer.8 |  8 ++++++++
 tools/i2ctransfer.c | 31 ++++++++++++++++++++++---------
 2 files changed, 30 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/tools/i2ctransfer.8 b/tools/i2ctransfer.8
index 88d5eb3..4bdf436 100644
--- a/tools/i2ctransfer.8
+++ b/tools/i2ctransfer.8
@@ -5,6 +5,7 @@  i2ctransfer \- send user-defined I2C messages in one transfer
 .SH SYNOPSIS
 .B i2ctransfer
 .RB [ -a ]
+.RB [ -b ]
 .RB [ -f ]
 .RB [ -v ]
 .RB [ -y ]
@@ -43,6 +44,13 @@  This program helps you to create proper transfers for your needs.
 .B -a
 Allow using addresses between 0x00 - 0x07 and 0x78 - 0x7f. Not recommended.
 .TP
+.B -b
+Print data from read messages as binary data. Disables
+.I -v
+(verbose). Useful for piping into a pretty printing tool like
+.B hexdump
+or for redirecting into a file to be analyzed later.
+.TP
 .B -f
 Force access to the device even if it is already busy.
 By default,
diff --git a/tools/i2ctransfer.c b/tools/i2ctransfer.c
index 15e774b..a7bbbaa 100644
--- a/tools/i2ctransfer.c
+++ b/tools/i2ctransfer.c
@@ -38,12 +38,14 @@  enum parse_state {
 #define PRINT_READ_BUF	(1 << 1)
 #define PRINT_WRITE_BUF	(1 << 2)
 #define PRINT_HEADER	(1 << 3)
+#define PRINT_BINARY	(1 << 4)
 
 static void help(void)
 {
 	fprintf(stderr,
 		"Usage: i2ctransfer [OPTIONS] I2CBUS DESC [DATA] [DESC [DATA]]...\n"
 		"  OPTIONS: -a allow even reserved addresses\n"
+		"           -b print read data as binary, disables -v\n"
 		"           -f force access even if address is marked used\n"
 		"           -h this help text\n"
 		"           -v verbose mode\n"
@@ -106,12 +108,16 @@  static void print_msgs(struct i2c_msg *msgs, __u32 nmsgs, unsigned flags)
 		}
 
 		if (len && print_buf) {
-			if (flags & PRINT_HEADER)
-				fprintf(output, ", buf ");
-			for (j = 0; j < len - 1; j++)
-				fprintf(output, "0x%02x ", msgs[i].buf[j]);
-			/* Print final byte with newline */
-			fprintf(output, "0x%02x\n", msgs[i].buf[j]);
+			if (flags & PRINT_BINARY) {
+				fwrite(msgs[i].buf, 1, len, output);
+			} else {
+				if (flags & PRINT_HEADER)
+					fprintf(output, ", buf ");
+				for (j = 0; j < len - 1; j++)
+					fprintf(output, "0x%02x ", msgs[i].buf[j]);
+				/* Print final byte with newline */
+				fprintf(output, "0x%02x\n", msgs[i].buf[j]);
+			}
 		} else if (flags & PRINT_HEADER) {
 			fprintf(output, "\n");
 		}
@@ -138,7 +144,7 @@  int main(int argc, char *argv[])
 {
 	char filename[20];
 	int i2cbus, address = -1, file, opt, arg_idx, nmsgs = 0, nmsgs_sent, i;
-	int force = 0, yes = 0, version = 0, verbose = 0, all_addrs = 0;
+	int force = 0, yes = 0, version = 0, verbose = 0, all_addrs = 0, binary = 0;
 	struct i2c_msg msgs[I2C_RDRW_IOCTL_MAX_MSGS];
 	enum parse_state state = PARSE_GET_DESC;
 	unsigned buf_idx = 0;
@@ -147,9 +153,10 @@  int main(int argc, char *argv[])
 		msgs[i].buf = NULL;
 
 	/* handle (optional) flags first */
-	while ((opt = getopt(argc, argv, "afhvVy")) != -1) {
+	while ((opt = getopt(argc, argv, "abfhvVy")) != -1) {
 		switch (opt) {
 		case 'a': all_addrs = 1; break;
+		case 'b': binary = 1; break;
 		case 'f': force = 1; break;
 		case 'v': verbose = 1; break;
 		case 'V': version = 1; break;
@@ -326,6 +333,7 @@  int main(int argc, char *argv[])
 
 	if (yes || confirm(filename, msgs, nmsgs)) {
 		struct i2c_rdwr_ioctl_data rdwr;
+		unsigned print_flags = PRINT_READ_BUF;
 
 		rdwr.msgs = msgs;
 		rdwr.nmsgs = nmsgs;
@@ -337,7 +345,12 @@  int main(int argc, char *argv[])
 			fprintf(stderr, "Warning: only %d/%d messages were sent\n", nmsgs_sent, nmsgs);
 		}
 
-		print_msgs(msgs, nmsgs_sent, PRINT_READ_BUF | (verbose ? PRINT_HEADER | PRINT_WRITE_BUF : 0));
+		if (binary)
+			print_flags |= PRINT_BINARY;
+		else if (verbose)
+			print_flags |= PRINT_HEADER | PRINT_WRITE_BUF;
+
+		print_msgs(msgs, nmsgs_sent, print_flags);
 	}
 
 	close(file);