2003-11-17 03:04:09 +00:00
|
|
|
/*
|
2003-11-22 22:27:19 +00:00
|
|
|
i2cbusses: Print the installed i2c busses for both 2.4 and 2.6 kernels.
|
|
|
|
Part of user-space programs to access for I2C
|
|
|
|
devices.
|
2003-11-17 03:04:09 +00:00
|
|
|
Copyright (c) 1999-2003 Frodo Looijaard <frodol@dds.nl> and
|
|
|
|
Mark D. Studebaker <mdsxyz123@yahoo.com>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
2004-08-28 20:42:49 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
2003-11-17 03:04:09 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <dirent.h>
|
2004-08-28 20:42:49 +00:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include "i2cbusses.h"
|
2003-11-17 03:04:09 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
this just prints out the installed i2c busses in a consistent format, whether
|
|
|
|
on a 2.4 kernel using /proc or a 2.6 kernel using /sys.
|
2003-11-28 04:37:08 +00:00
|
|
|
If procfmt == 1, print out exactly /proc/bus/i2c format on stdout.
|
|
|
|
This allows this to be used in a program to emulate /proc/bus/i2c on a
|
|
|
|
sysfs system.
|
2003-11-17 03:04:09 +00:00
|
|
|
*/
|
2003-11-28 04:37:08 +00:00
|
|
|
void print_i2c_busses(int procfmt)
|
2003-11-17 03:04:09 +00:00
|
|
|
{
|
|
|
|
FILE *fptr;
|
|
|
|
char s[100];
|
2003-11-28 02:27:41 +00:00
|
|
|
struct dirent *de, *dde;
|
|
|
|
DIR *dir, *ddir;
|
2003-11-17 03:04:09 +00:00
|
|
|
FILE *f;
|
|
|
|
char *border;
|
|
|
|
char dev[NAME_MAX], fstype[NAME_MAX], sysfs[NAME_MAX], n[NAME_MAX];
|
|
|
|
int foundsysfs = 0;
|
|
|
|
int tmp;
|
|
|
|
int count=0;
|
|
|
|
|
|
|
|
|
|
|
|
/* look in /proc/bus/i2c */
|
|
|
|
if((fptr = fopen("/proc/bus/i2c", "r"))) {
|
|
|
|
while(fgets(s, 100, fptr)) {
|
2003-11-28 04:37:08 +00:00
|
|
|
if(count++ == 0 && !procfmt)
|
2003-11-22 22:27:19 +00:00
|
|
|
fprintf(stderr," Installed I2C busses:\n");
|
2003-11-28 04:37:08 +00:00
|
|
|
if(procfmt)
|
|
|
|
printf("%s", s);
|
|
|
|
else
|
|
|
|
fprintf(stderr, " %s", s);
|
2003-11-17 03:04:09 +00:00
|
|
|
}
|
|
|
|
fclose(fptr);
|
2003-11-22 22:27:19 +00:00
|
|
|
goto done;
|
2003-11-17 03:04:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* look in sysfs */
|
|
|
|
/* First figure out where sysfs was mounted */
|
2003-11-22 22:27:19 +00:00
|
|
|
if ((f = fopen("/proc/mounts", "r")) == NULL) {
|
|
|
|
goto done;
|
|
|
|
}
|
2003-11-17 03:04:09 +00:00
|
|
|
while (fgets(n, NAME_MAX, f)) {
|
|
|
|
sscanf(n, "%[^ ] %[^ ] %[^ ] %*s\n", dev, sysfs, fstype);
|
|
|
|
if (strcasecmp(fstype, "sysfs") == 0) {
|
|
|
|
foundsysfs++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(f);
|
2003-11-22 22:27:19 +00:00
|
|
|
if (! foundsysfs) {
|
|
|
|
goto done;
|
|
|
|
}
|
2003-11-27 23:53:10 +00:00
|
|
|
|
|
|
|
/* Bus numbers in i2c-adapter don't necessarily match those in
|
|
|
|
i2c-dev and what we really care about are the i2c-dev numbers.
|
|
|
|
Unfortunately the names are harder to get in i2c-dev */
|
|
|
|
strcat(sysfs, "/class/i2c-dev");
|
|
|
|
if(!(dir = opendir(sysfs)))
|
2003-11-22 22:27:19 +00:00
|
|
|
goto done;
|
2003-11-27 23:53:10 +00:00
|
|
|
/* go through the busses */
|
2003-11-17 03:04:09 +00:00
|
|
|
while ((de = readdir(dir)) != NULL) {
|
|
|
|
if (!strcmp(de->d_name, "."))
|
|
|
|
continue;
|
|
|
|
if (!strcmp(de->d_name, ".."))
|
|
|
|
continue;
|
|
|
|
|
2004-03-06 20:27:41 +00:00
|
|
|
/* this should work for kernels 2.6.5 or higher and */
|
|
|
|
/* is preferred because is unambiguous */
|
|
|
|
sprintf(n, "%s/%s/name", sysfs, de->d_name);
|
2003-11-27 23:53:10 +00:00
|
|
|
f = fopen(n, "r");
|
2004-03-06 20:27:41 +00:00
|
|
|
/* this seems to work for ISA */
|
|
|
|
if(f == NULL) {
|
|
|
|
sprintf(n, "%s/%s/device/name", sysfs, de->d_name);
|
|
|
|
f = fopen(n, "r");
|
|
|
|
}
|
|
|
|
/* non-ISA is much harder */
|
|
|
|
/* and this won't find the correct bus name if a driver
|
|
|
|
has more than one bus */
|
2003-11-27 23:53:10 +00:00
|
|
|
if(f == NULL) {
|
2003-11-28 02:27:41 +00:00
|
|
|
sprintf(n, "%s/%s/device", sysfs, de->d_name);
|
2003-11-27 23:53:10 +00:00
|
|
|
if(!(ddir = opendir(n)))
|
|
|
|
continue;
|
|
|
|
while ((dde = readdir(ddir)) != NULL) {
|
|
|
|
if (!strcmp(dde->d_name, "."))
|
|
|
|
continue;
|
|
|
|
if (!strcmp(dde->d_name, ".."))
|
|
|
|
continue;
|
2003-11-28 02:27:41 +00:00
|
|
|
if ((!strncmp(dde->d_name, "i2c-", 4))) {
|
|
|
|
sprintf(n, "%s/%s/device/%s/name",
|
2003-11-27 23:53:10 +00:00
|
|
|
sysfs, de->d_name, dde->d_name);
|
2003-11-28 02:27:41 +00:00
|
|
|
if((f = fopen(n, "r")))
|
|
|
|
goto found;
|
2003-11-27 23:53:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-11-17 03:04:09 +00:00
|
|
|
|
2003-11-27 23:53:10 +00:00
|
|
|
found:
|
|
|
|
if (f != NULL) {
|
2003-11-17 03:04:09 +00:00
|
|
|
char x[120];
|
2003-11-22 22:27:19 +00:00
|
|
|
|
2003-11-17 03:04:09 +00:00
|
|
|
fgets(x, 120, f);
|
|
|
|
fclose(f);
|
|
|
|
if((border = index(x, '\n')) != NULL)
|
|
|
|
*border = 0;
|
2003-11-28 04:37:08 +00:00
|
|
|
if(count++ == 0 && !procfmt)
|
2003-11-22 22:27:19 +00:00
|
|
|
fprintf(stderr," Installed I2C busses:\n");
|
|
|
|
/* match 2.4 /proc/bus/i2c format as closely as possible */
|
2003-11-28 04:37:08 +00:00
|
|
|
if(!strncmp(x, "ISA ", 4)) {
|
|
|
|
if(procfmt)
|
|
|
|
printf("%s\t%-10s\t%-32s\t%s\n", de->d_name,
|
|
|
|
"dummy", x, "ISA bus algorithm");
|
|
|
|
else
|
|
|
|
fprintf(stderr, " %s\t%-10s\t%-32s\t%s\n", de->d_name,
|
|
|
|
"dummy", x, "ISA bus algorithm");
|
|
|
|
} else if(!sscanf(de->d_name, "i2c-%d", &tmp)) {
|
|
|
|
if(procfmt)
|
|
|
|
printf("%s\t%-10s\t%-32s\t%s\n", de->d_name,
|
|
|
|
"dummy", x, "Dummy bus algorithm");
|
|
|
|
else
|
|
|
|
fprintf(stderr, " %s\t%-10s\t%-32s\t%s\n", de->d_name,
|
|
|
|
"dummy", x, "Dummy bus algorithm");
|
|
|
|
} else {
|
|
|
|
if(procfmt)
|
|
|
|
printf("%s\t%-10s\t%-32s\t%s\n", de->d_name,
|
|
|
|
"unknown", x, "Algorithm unavailable");
|
|
|
|
else
|
|
|
|
fprintf(stderr, " %s\t%-10s\t%-32s\t%s\n", de->d_name,
|
|
|
|
"unknown", x, "Algorithm unavailable");
|
|
|
|
}
|
2003-11-17 03:04:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
closedir(dir);
|
2003-11-22 22:27:19 +00:00
|
|
|
|
|
|
|
done:
|
2003-11-28 04:37:08 +00:00
|
|
|
if(count == 0 && !procfmt)
|
2003-11-27 23:53:10 +00:00
|
|
|
fprintf(stderr,"Error: No I2C busses found!\n"
|
|
|
|
"Be sure you have done 'modprobe i2c-dev'\n"
|
|
|
|
"and also modprobed your i2c bus drivers\n");
|
2003-11-17 03:04:09 +00:00
|
|
|
}
|
2004-08-28 20:42:49 +00:00
|
|
|
|
|
|
|
int open_i2c_dev(const int i2cbus, char *filename)
|
|
|
|
{
|
|
|
|
int file;
|
|
|
|
|
|
|
|
sprintf(filename, "/dev/i2c/%d", i2cbus);
|
|
|
|
file = open(filename, O_RDWR);
|
|
|
|
|
|
|
|
if (file < 0 && errno == ENOENT) {
|
|
|
|
sprintf(filename, "/dev/i2c-%d", i2cbus);
|
|
|
|
file = open(filename, O_RDWR);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (file < 0) {
|
|
|
|
if (errno == ENOENT) {
|
|
|
|
fprintf(stderr, "Error: Could not open file "
|
|
|
|
"`/dev/i2c-%d' or `/dev/i2c/%d': %s\n",
|
|
|
|
i2cbus, i2cbus, strerror(ENOENT));
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Error: Could not open file "
|
|
|
|
"`%s': %s\n", filename, strerror(errno));
|
|
|
|
if (errno == EACCES)
|
|
|
|
fprintf(stderr, "Run as root?\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|