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