root/lm-sensors/trunk/prog/dump/i2cbusses.c @ 2675

Revision 2675, 5.6 KB (checked in by khali, 9 years ago)

Refactor i2c device opening.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    i2cbusses: Print the installed i2c busses for both 2.4 and 2.6 kernels.
3               Part of user-space programs to access for I2C
4               devices.
5    Copyright (c) 1999-2003  Frodo Looijaard <frodol@dds.nl> and
6                             Mark D. Studebaker <mdsxyz123@yahoo.com>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <string.h>
26#include <stdio.h>
27#include <limits.h>
28#include <dirent.h>
29#include <fcntl.h>
30#include <errno.h>
31#include "i2cbusses.h"
32
33/*
34   this just prints out the installed i2c busses in a consistent format, whether
35   on a 2.4 kernel using /proc or a 2.6 kernel using /sys.
36   If procfmt == 1, print out exactly /proc/bus/i2c format on stdout.
37   This allows this to be used in a program to emulate /proc/bus/i2c on a
38   sysfs system.
39*/
40void print_i2c_busses(int procfmt)
41{
42        FILE *fptr;
43        char s[100];
44        struct dirent *de, *dde;
45        DIR *dir, *ddir;
46        FILE *f;
47        char *border;
48        char dev[NAME_MAX], fstype[NAME_MAX], sysfs[NAME_MAX], n[NAME_MAX];
49        int foundsysfs = 0;
50        int tmp;
51        int count=0;
52
53
54        /* look in /proc/bus/i2c */
55        if((fptr = fopen("/proc/bus/i2c", "r"))) {
56                while(fgets(s, 100, fptr)) {
57                        if(count++ == 0 && !procfmt)
58                                fprintf(stderr,"  Installed I2C busses:\n");
59                        if(procfmt)
60                                printf("%s", s);       
61                        else
62                                fprintf(stderr, "    %s", s);   
63                }
64                fclose(fptr);
65                goto done;
66        }
67
68        /* look in sysfs */
69        /* First figure out where sysfs was mounted */
70        if ((f = fopen("/proc/mounts", "r")) == NULL) {
71                goto done;
72        }
73        while (fgets(n, NAME_MAX, f)) {
74                sscanf(n, "%[^ ] %[^ ] %[^ ] %*s\n", dev, sysfs, fstype);
75                if (strcasecmp(fstype, "sysfs") == 0) {
76                        foundsysfs++;
77                        break;
78                }
79        }
80        fclose(f);
81        if (! foundsysfs) {
82                goto done;
83        }
84
85        /* Bus numbers in i2c-adapter don't necessarily match those in
86           i2c-dev and what we really care about are the i2c-dev numbers.
87           Unfortunately the names are harder to get in i2c-dev */
88        strcat(sysfs, "/class/i2c-dev");
89        if(!(dir = opendir(sysfs)))
90                goto done;
91        /* go through the busses */
92        while ((de = readdir(dir)) != NULL) {
93                if (!strcmp(de->d_name, "."))
94                        continue;
95                if (!strcmp(de->d_name, ".."))
96                        continue;
97
98                /* this should work for kernels 2.6.5 or higher and */
99                /* is preferred because is unambiguous */
100                sprintf(n, "%s/%s/name", sysfs, de->d_name);
101                f = fopen(n, "r");
102                /* this seems to work for ISA */
103                if(f == NULL) {
104                        sprintf(n, "%s/%s/device/name", sysfs, de->d_name);
105                        f = fopen(n, "r");
106                }
107                /* non-ISA is much harder */
108                /* and this won't find the correct bus name if a driver
109                   has more than one bus */
110                if(f == NULL) {
111                        sprintf(n, "%s/%s/device", sysfs, de->d_name);
112                        if(!(ddir = opendir(n)))
113                                continue;               
114                        while ((dde = readdir(ddir)) != NULL) {
115                                if (!strcmp(dde->d_name, "."))
116                                        continue;
117                                if (!strcmp(dde->d_name, ".."))
118                                        continue;
119                                if ((!strncmp(dde->d_name, "i2c-", 4))) {
120                                        sprintf(n, "%s/%s/device/%s/name",
121                                                sysfs, de->d_name, dde->d_name);
122                                        if((f = fopen(n, "r")))
123                                                goto found;
124                                }
125                        }
126                }
127
128found:
129                if (f != NULL) {
130                        char    x[120];
131
132                        fgets(x, 120, f);
133                        fclose(f);
134                        if((border = index(x, '\n')) != NULL)
135                                *border = 0;
136                        if(count++ == 0 && !procfmt)
137                                fprintf(stderr,"  Installed I2C busses:\n");
138                        /* match 2.4 /proc/bus/i2c format as closely as possible */
139                        if(!strncmp(x, "ISA ", 4)) {
140                                if(procfmt)
141                                        printf("%s\t%-10s\t%-32s\t%s\n", de->d_name,
142                                                "dummy", x, "ISA bus algorithm");
143                                else
144                                        fprintf(stderr, "    %s\t%-10s\t%-32s\t%s\n", de->d_name,
145                                                "dummy", x, "ISA bus algorithm");
146                        } else if(!sscanf(de->d_name, "i2c-%d", &tmp)) {
147                                if(procfmt)
148                                        printf("%s\t%-10s\t%-32s\t%s\n", de->d_name,
149                                                "dummy", x, "Dummy bus algorithm");
150                                else
151                                        fprintf(stderr, "    %s\t%-10s\t%-32s\t%s\n", de->d_name,
152                                                "dummy", x, "Dummy bus algorithm");
153                        } else {
154                                if(procfmt)
155                                        printf("%s\t%-10s\t%-32s\t%s\n", de->d_name,
156                                                "unknown", x, "Algorithm unavailable");
157                                else
158                                        fprintf(stderr, "    %s\t%-10s\t%-32s\t%s\n", de->d_name,
159                                                "unknown", x, "Algorithm unavailable");
160                        }
161                }
162        }
163        closedir(dir);
164
165done:
166        if(count == 0 && !procfmt)
167                fprintf(stderr,"Error: No I2C busses found!\n"
168                               "Be sure you have done 'modprobe i2c-dev'\n"
169                               "and also modprobed your i2c bus drivers\n");
170}
171
172int open_i2c_dev(const int i2cbus, char *filename)
173{
174        int file;
175
176        sprintf(filename, "/dev/i2c/%d", i2cbus);
177        file = open(filename, O_RDWR);
178
179        if (file < 0 && errno == ENOENT) {
180                sprintf(filename, "/dev/i2c-%d", i2cbus);
181                file = open(filename, O_RDWR);
182        }
183
184        if (file < 0) {
185                if (errno == ENOENT) {
186                        fprintf(stderr, "Error: Could not open file "
187                                "`/dev/i2c-%d' or `/dev/i2c/%d': %s\n",
188                                i2cbus, i2cbus, strerror(ENOENT));
189                } else {
190                        fprintf(stderr, "Error: Could not open file "
191                                "`%s': %s\n", filename, strerror(errno));
192                        if (errno == EACCES)
193                                fprintf(stderr, "Run as root?\n");
194                }
195        }
196       
197        return file;
198}
Note: See TracBrowser for help on using the browser.