⛏️ index : haiku.git

/*
 * Copyright 2020, JΓ©rΓ΄me Duval, jerome.duval@gmail.com.
 * Distributed under the terms of the MIT license.
 */


#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <Drivers.h>

#include <AutoDeleter.h>

#include "i2c.h"


static struct option const kLongOptions[] = {
	{"help", no_argument, 0, 'h'},
	{NULL}
};


extern const char *__progname;
static const char *kProgramName = __progname;


void
usage(int returnValue)
{
	fprintf(stderr, "Usage: %s <path-to-i2c-bus-device>\n", kProgramName);
	exit(returnValue);
}


static int
scan_bus(const char *path)
{
	int err = EXIT_SUCCESS;
	FileDescriptorCloser fd(open(path, O_RDONLY));
	if (!fd.IsSet()) {
		fprintf(stderr, "%s: Could not access path: %s\n", kProgramName,
			strerror(errno));
		return EXIT_FAILURE;
	}

	setbuf(stdout, NULL);
	printf("Scanning I2C bus: %s\n", path);

	printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
	for (int i = 0; i < 128; i+=16) {
		printf("%02x: ", i);
		for (int j = 0; j < 16; j++) {
			uint16 addr = i + j;
			uint8 cmd = 0;
			uint8 data = 0;
			i2c_ioctl_exec exec;
			exec.addr = addr;
			exec.op = I2C_OP_READ_STOP;
			exec.cmdBuffer = &cmd;
			exec.cmdLength = sizeof(cmd);
			exec.buffer = &data;
			exec.bufferLength = sizeof(data);
			if (ioctl(fd.Get(), I2CEXEC, &exec, sizeof(exec)) == 0)
				printf("%02x ", addr);
			else
				printf("-- ");
		}
		printf("\n");
	}

	return err;
}


int
main(int argc, char** argv)
{
	int c;
	while ((c = getopt_long(argc, argv, "h", kLongOptions, NULL)) != -1) {
		switch (c) {
			case 0:
				break;
			case 'h':
				usage(0);
				break;
			default:
				usage(1);
				break;
		}
	}

	if (argc - optind < 1)
		usage(1);
	const char* path = argv[optind++];

	exit(scan_bus(path));
}