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 22static struct option const kLongOptions[] = { 23 {"help", no_argument, 0, 'h'}, 24 {NULL} 25}; 26 27 28extern const char *__progname; 29static const char *kProgramName = __progname; 30 31 32void 33usage(int returnValue) 34{ 35 fprintf(stderr, "Usage: %s <path-to-i2c-bus-device>\n", kProgramName); 36 exit(returnValue); 37} 38 39 40static int 41scan_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 80int 81main(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