Split print_i2c_busses into a gathering part and a printing part.
---
tools/i2cbusses.c | 172 +++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 147 insertions(+), 25 deletions(-)
--- i2c-tools.orig/tools/i2cbusses.c 2008-04-12 13:31:43.000000000 +0200
+++ i2c-tools/tools/i2cbusses.c 2008-04-12 13:41:19.000000000 +0200
@@ -4,6 +4,7 @@
devices.
Copyright (c) 1999-2003 Frodo Looijaard <[EMAIL PROTECTED]> and
Mark D. Studebaker <[EMAIL PROTECTED]>
+ Copyright (C) 2008 Jean Delvare <[EMAIL PROTECTED]>
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
@@ -54,6 +55,13 @@ static struct adap_type adap_types[5] =
.algo = "N/A", },
};
+struct i2c_adap {
+ int nr;
+ char *name;
+ const char *funcs;
+ const char *algo;
+};
+
static enum adt i2c_get_funcs(int i2cbus)
{
unsigned long funcs;
@@ -80,14 +88,47 @@ static enum adt i2c_get_funcs(int i2cbus
return ret;
}
-/*
- 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.
- 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.
-*/
-void print_i2c_busses(int procfmt)
+/* Remove trailing spaces from a string
+ Return the new string length including the trailing NUL */
+static int rtrim(char *s)
+{
+ int i;
+
+ for (i = strlen(s) - 1; i >= 0 && (s[i] == ' ' || s[i] == '\n'); i--)
+ s[i] = '\0';
+ return i + 2;
+}
+
+static void free_adapters(struct i2c_adap *adapters)
+{
+ int i;
+
+ for (i = 0; adapters[i].name; i++)
+ free(adapters[i].name);
+ free(adapters);
+}
+
+/* We allocate space for the adapters in bunches. The last item is a
+ terminator, so here we start with room for 7 adapters, which should
+ be enough in most cases. If not, we allocate more later as needed. */
+#define BUNCH 8
+
+/* n must match the size of adapters at calling time */
+static struct i2c_adap *more_adapters(struct i2c_adap *adapters, int n)
+{
+ struct i2c_adap *new_adapters;
+
+ new_adapters = realloc(adapters, (n + BUNCH) * sizeof(struct i2c_adap));
+ if (!new_adapters) {
+ free_adapters(adapters);
+ return NULL;
+ }
+ memset(new_adapters + n, 0, BUNCH * sizeof(struct i2c_adap));
+
+ return new_adapters;
+}
+
+static struct i2c_adap *gather_i2c_busses(void)
{
FILE *fptr;
char s[100];
@@ -98,17 +139,51 @@ void print_i2c_busses(int procfmt)
char dev[NAME_MAX], fstype[NAME_MAX], sysfs[NAME_MAX], n[NAME_MAX];
int foundsysfs = 0;
int count=0;
+ struct i2c_adap *adapters;
+ adapters = calloc(BUNCH, sizeof(struct i2c_adap));
+ if (!adapters)
+ return NULL;
/* look in /proc/bus/i2c */
if((fptr = fopen("/proc/bus/i2c", "r"))) {
while(fgets(s, 100, fptr)) {
- if(count++ == 0 && !procfmt)
- fprintf(stderr," Installed I2C busses:\n");
- if(procfmt)
- printf("%s", s);
- else
- fprintf(stderr, " %s", s);
+ char *algo, *name, *type, *all;
+ int len_algo, len_name, len_type;
+ int i2cbus;
+
+ algo = strrchr(s, '\t');
+ *(algo++) = '\0';
+ len_algo = rtrim(algo);
+
+ name = strrchr(s, '\t');
+ *(name++) = '\0';
+ len_name = rtrim(name);
+
+ type = strrchr(s, '\t');
+ *(type++) = '\0';
+ len_type = rtrim(type);
+
+ sscanf(s, "i2c-%d", &i2cbus);
+
+ if ((count + 1) % BUNCH == 0) {
+ /* We need more space */
+ adapters = more_adapters(adapters, count + 1);
+ if (!adapters)
+ return NULL;
+ }
+
+ all = malloc(len_name + len_type + len_algo);
+ if (all == NULL) {
+ free_adapters(adapters);
+ return NULL;
+ }
+ adapters[count].nr = i2cbus;
+ adapters[count].name = strcpy(all, name);
+ adapters[count].funcs = strcpy(all + len_name, type);
+ adapters[count].algo = strcpy(all + len_name + len_type,
+ algo);
+ count++;
}
fclose(fptr);
goto done;
@@ -189,33 +264,80 @@ found:
}
if ((border = strchr(x, '\n')) != NULL)
*border = 0;
- if(count++ == 0 && !procfmt)
- fprintf(stderr," Installed I2C busses:\n");
- /* match 2.4 /proc/bus/i2c format as closely as
possible */
+ if (!sscanf(de->d_name, "i2c-%d", &i2cbus))
+ continue;
if(!strncmp(x, "ISA ", 4)) {
type = adt_isa;
- } else if(!sscanf(de->d_name, "i2c-%d", &i2cbus)) {
- type = adt_dummy;
} else {
/* Attempt to probe for adapter capabilities */
type = i2c_get_funcs(i2cbus);
}
- if (procfmt)
- printf("%s\t%-10s\t%-32s\t%s\n", de->d_name,
- adap_types[type].funcs, x,
adap_types[type].algo);
- else
- fprintf(stderr, " %s\t%-10s\t%s\n",
de->d_name,
- adap_types[type].funcs, x);
+ if ((count + 1) % BUNCH == 0) {
+ /* We need more space */
+ adapters = more_adapters(adapters, count + 1);
+ if (!adapters)
+ return NULL;
+ }
+
+ adapters[count].nr = i2cbus;
+ adapters[count].name = strdup(x);
+ if (adapters[count].name == NULL) {
+ free_adapters(adapters);
+ return NULL;
+ }
+ adapters[count].funcs = adap_types[type].funcs;
+ adapters[count].algo = adap_types[type].algo;
+ count++;
}
}
closedir(dir);
done:
+ return adapters;
+}
+
+/*
+ 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.
+ 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.
+*/
+void print_i2c_busses(int procfmt)
+{
+ struct i2c_adap *adapters;
+ int count;
+
+ adapters = gather_i2c_busses();
+ if (adapters == NULL) {
+ fprintf(stderr, "Error: Out of memory!\n");
+ return;
+ }
+
+ for (count = 0; adapters[count].name; count++) {
+ if (count == 0 && !procfmt)
+ fprintf(stderr," Installed I2C busses:\n");
+ if (procfmt)
+ /* match 2.4 /proc/bus/i2c format as closely as
possible */
+ printf("i2c-%d\t%-10s\t%-32s\t%s\n",
+ adapters[count].nr,
+ adapters[count].funcs,
+ adapters[count].name,
+ adapters[count].algo);
+ else
+ fprintf(stderr, " i2c-%d\t%-10s\t%s\n",
+ adapters[count].nr,
+ adapters[count].funcs,
+ adapters[count].name);
+ }
+
if(count == 0 && !procfmt)
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");
+
+ free_adapters(adapters);
}
/*
--
Jean Delvare
_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c