xref: /haiku/src/bin/i2c/i2c.cpp (revision 9e25244c5e9051f6cd333820d6332397361abd6c)
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 	FileDescriptorCloser fd(open(path, O_RDONLY));
45 	if (!fd.IsSet()) {
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 
54 	printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
55 	for (int i = 0; i < 128; i+=16) {
56 		printf("%02x: ", i);
57 		for (int j = 0; j < 16; j++) {
58 			uint16 addr = i + j;
59 			uint8 cmd = 0;
60 			uint8 data = 0;
61 			i2c_ioctl_exec exec;
62 			exec.addr = addr;
63 			exec.op = I2C_OP_READ_STOP;
64 			exec.cmdBuffer = &cmd;
65 			exec.cmdLength = sizeof(cmd);
66 			exec.buffer = &data;
67 			exec.bufferLength = sizeof(data);
68 			if (ioctl(fd.Get(), I2CEXEC, &exec, sizeof(exec)) == 0)
69 				printf("%02x ", addr);
70 			else
71 				printf("-- ");
72 		}
73 		printf("\n");
74 	}
75 
76 	return err;
77 }
78 
79 
80 int
81 main(int argc, char** argv)
82 {
83 	int c;
84 	while ((c = getopt_long(argc, argv, "h", kLongOptions, NULL)) != -1) {
85 		switch (c) {
86 			case 0:
87 				break;
88 			case 'h':
89 				usage(0);
90 				break;
91 			default:
92 				usage(1);
93 				break;
94 		}
95 	}
96 
97 	if (argc - optind < 1)
98 		usage(1);
99 	const char* path = argv[optind++];
100 
101 	exit(scan_bus(path));
102 }
103