xref: /haiku/src/bin/i2c/i2c.cpp (revision 68d37cfb3a755a7270d772b505ee15c8b18aa5e0)
1 /*
2  * Copyright 2020, Jérôme Duval, jerome.duval@gmail.com.
3  * Distributed under the terms of the MIT license.
4  */
5 
6 
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <getopt.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <Drivers.h>
16 
17 #include <AutoDeleter.h>
18 
19 #include "i2c.h"
20 
21 
22 static struct option const kLongOptions[] = {
23 	{"help", no_argument, 0, 'h'},
24 	{NULL}
25 };
26 
27 
28 extern const char *__progname;
29 static const char *kProgramName = __progname;
30 
31 
32 void
33 usage(int returnValue)
34 {
35 	fprintf(stderr, "Usage: %s <path-to-i2c-bus-device>\n", kProgramName);
36 	exit(returnValue);
37 }
38 
39 
40 static int
41 scan_bus(const char *path)
42 {
43 	int err = EXIT_SUCCESS;
44 	int fd = open(path, O_RDONLY);
45 	if (fd < 0) {
46 		fprintf(stderr, "%s: Could not access path: %s\n", kProgramName,
47 			strerror(errno));
48 		return EXIT_FAILURE;
49 	}
50 
51 	setbuf(stdout, NULL);
52 	printf("Scanning I2C bus: %s\n", path);
53 	FileDescriptorCloser closer(fd);
54 
55 	printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
56 	for (int i = 0; i < 128; i+=16) {
57 		printf("%02x: ", i);
58 		for (int j = 0; j < 16; j++) {
59 			uint16 addr = i + j;
60 			uint8 cmd = 0;
61 			uint8 data = 0;
62 			i2c_ioctl_exec exec;
63 			exec.addr = addr;
64 			exec.op = I2C_OP_READ_STOP;
65 			exec.cmdBuffer = &cmd;
66 			exec.cmdLength = sizeof(cmd);
67 			exec.buffer = &data;
68 			exec.bufferLength = sizeof(data);
69 			if (ioctl(fd, I2CEXEC, &exec, sizeof(exec)) == 0)
70 				printf("%02x ", addr);
71 			else
72 				printf("-- ");
73 		}
74 		printf("\n");
75 	}
76 
77 	close(fd);
78 
79 	return err;
80 }
81 
82 
83 int
84 main(int argc, char** argv)
85 {
86 	int c;
87 	while ((c = getopt_long(argc, argv, "h", kLongOptions, NULL)) != -1) {
88 		switch (c) {
89 			case 0:
90 				break;
91 			case 'h':
92 				usage(0);
93 				break;
94 			default:
95 				usage(1);
96 				break;
97 		}
98 	}
99 
100 	if (argc - optind < 1)
101 		usage(1);
102 	const char* path = argv[optind++];
103 
104 	exit(scan_bus(path));
105 }
106