|
|
@ -4,6 +4,7 @@ |
|
|
|
devices. |
|
|
|
Copyright (c) 1999-2003 Frodo Looijaard <frodol@dds.nl> and |
|
|
|
Mark D. Studebaker <mdsxyz123@yahoo.com> |
|
|
|
Copyright (C) 2008 Jean Delvare <khali@linux-fr.org> |
|
|
|
|
|
|
|
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); |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|