root/lm-sensors/trunk/prog/detect/i2cdetect.c @ 3077

Revision 3077, 6.6 KB (checked in by khali, 9 years ago)

Add a "quiet" parameter to open_i2c_dev() to prevent it from
displaying error messages.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2    i2cdetect.c - a user-space program to scan for I2C devices
3    Copyright (C) 1999-2004  Frodo Looijaard <frodol@dds.nl>,
4                             Mark D. Studebaker <mdsxyz123@yahoo.com> and
5                             Jean Delvare <khali@linux-fr.org>
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20*/
21
22#include <errno.h>
23#include <string.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include "../dump/i2cbusses.h"
28#include "i2c-dev.h"
29#include "version.h"
30
31#define MODE_AUTO       0
32#define MODE_QUICK      1
33#define MODE_READ       2
34
35void help(void)
36{
37        fprintf(stderr,
38                "Syntax: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]\n"
39                "        i2cdetect -l\n"
40                "        i2cdetect -V\n"
41                "  I2CBUS is an integer\n"
42                "  With -a, probe all addresses (NOT RECOMMENDED)\n"
43                "  With -q, uses only quick write commands for probing (NOT "
44                "RECOMMENDED)\n"
45                "  With -r, uses only read byte commands for probing (NOT "
46                "RECOMMENDED)\n"
47                "  If provided, FIRST and LAST limit the probing range.\n"
48                "  With -l, lists installed busses only\n");
49        print_i2c_busses(0);
50}
51
52int scan_i2c_bus(int file, const int mode, const int first, const int last)
53{
54        int i, j;
55        int res;
56
57        printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
58
59        for (i = 0; i < 128; i += 16) {
60                printf("%02x: ", i);
61                for(j = 0; j < 16; j++) {
62                        /* Skip unwanted addresses */
63                        if (i+j < first || i+j > last) {
64                                printf("   ");
65                                continue;
66                        }
67
68                        /* Set slave address */
69                        if (ioctl(file, I2C_SLAVE, i+j) < 0) {
70                                if (errno == EBUSY) {
71                                        printf("UU ");
72                                        continue;
73                                } else {
74                                        fprintf(stderr, "Error: Could not set "
75                                                "address to 0x%02x: %s\n", i+j,
76                                                strerror(errno));
77                                        return -1;
78                                }
79                        }
80
81                        /* Probe this address */
82                        switch (mode) {
83                        case MODE_QUICK:
84                                /* This is known to corrupt the Atmel AT24RF08
85                                   EEPROM */
86                                res = i2c_smbus_write_quick(file,
87                                      I2C_SMBUS_WRITE);
88                                break;
89                        case MODE_READ:
90                                /* This is known to lock SMBus on various
91                                   write-only chips (mainly clock chips) */
92                                res = i2c_smbus_read_byte(file);
93                                break;
94                        default:
95                                if ((i+j >= 0x30 && i+j <= 0x37)
96                                 || (i+j >= 0x50 && i+j <= 0x5F))
97                                        res = i2c_smbus_read_byte(file);
98                                else
99                                        res = i2c_smbus_write_quick(file,
100                                              I2C_SMBUS_WRITE);
101                        }
102
103                        if (res < 0)
104                                printf("XX ");
105                        else
106                                printf("%02x ", i+j);
107                }
108                printf("\n");
109        }
110
111        return 0;
112}
113
114int main(int argc, char *argv[])
115{
116        char *end;
117        int i2cbus, file, res;
118        char filename[20];
119        long funcs;
120        int mode = MODE_AUTO;
121        int first = 0x03, last = 0x77;
122        int flags = 0;
123        int yes = 0, version = 0, list = 0;
124
125        /* handle (optional) flags first */
126        while (1+flags < argc && argv[1+flags][0] == '-') {
127                switch (argv[1+flags][1]) {
128                case 'V': version = 1; break;
129                case 'y': yes = 1; break;
130                case 'l': list = 1; break;
131                case 'r':
132                        if (mode == MODE_QUICK) {
133                                fprintf(stderr, "Error: Different modes "
134                                        "specified!\n");
135                                exit(1);
136                        }
137                        mode = MODE_READ;
138                        break;
139                case 'q':
140                        if (mode == MODE_READ) {
141                                fprintf(stderr, "Error: Different modes "
142                                        "specified!\n");
143                                exit(1);
144                        }
145                        mode = MODE_QUICK;
146                        break;
147                case 'a':
148                        first = 0x00;
149                        last = 0x7F;
150                        break;
151                default:
152                        fprintf(stderr, "Warning: Unsupported flag "
153                                "\"-%c\"!\n", argv[1+flags][1]);
154                        help();
155                        exit(1);
156                }
157                flags++;
158        }
159
160        if (version) {
161                fprintf(stderr, "i2cdetect version %s\n", LM_VERSION);
162                exit(0);
163        }
164
165        if (list) {
166                print_i2c_busses(1);
167                exit(0);
168        }
169
170        if (argc < flags + 2) {
171                fprintf(stderr, "Error: No i2c-bus specified!\n");
172                help();
173                exit(1);
174        }
175        i2cbus = strtol(argv[flags+1], &end, 0);
176        if (*end) {
177                fprintf(stderr, "Error: I2CBUS argument not a number!\n");
178                help();
179                exit(1);
180        }
181        if ((i2cbus < 0) || (i2cbus > 0xff)) {
182                fprintf(stderr, "Error: I2CBUS argument out of range "
183                        "(0-255)!\n");
184                help();
185                exit(1);
186        }
187
188        /* read address range if present */
189        if (argc == flags + 4) {
190                int tmp;
191
192                tmp = strtol(argv[flags+2], &end, 0);
193                if (*end) {
194                        fprintf(stderr, "Error: FIRST argment not a "
195                                "number!\n");
196                        help();
197                        exit(1);
198                }
199                if (tmp < first || tmp > last) {
200                        fprintf(stderr, "Error: FIRST argument out of range "
201                                "(0x%02x-0x%02x)!\n", first, last);
202                        help();
203                        exit(1);
204                }
205                first = tmp;
206
207                tmp = strtol(argv[flags+3], &end, 0);
208                if (*end) {
209                        fprintf(stderr, "Error: LAST argment not a "
210                                "number!\n");
211                        help();
212                        exit(1);
213                }
214                if (tmp < first || tmp > last) {
215                        fprintf(stderr, "Error: LAST argument out of range "
216                                "(0x%02x-0x%02x)!\n", first, last);
217                        help();
218                        exit(1);
219                }
220                last = tmp;
221        } else if (argc != flags + 2) {
222                help();
223                exit(1);
224        }
225
226        file = open_i2c_dev(i2cbus, filename, 0);
227        if (file < 0) {
228                exit(1);
229        }
230
231        if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
232                fprintf(stderr, "Error: Could not get the adapter "
233                        "functionality matrix: %s\n", strerror(errno));
234                close(file);
235                exit(1);
236        }
237        if (mode != MODE_READ && !(funcs & I2C_FUNC_SMBUS_QUICK)) {
238                fprintf(stderr, "Error: Can't use SMBus Quick Write command "
239                        "on this bus (ISA bus?)\n");
240                close(file);
241                exit(1);
242        }
243        if (mode != MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
244                fprintf(stderr, "Error: Can't use SMBus Read Byte command "
245                        "on this bus (ISA bus?)\n");
246                close(file);
247                exit(1);
248        }
249
250        if (!yes) {
251                char s[2];
252
253                fprintf(stderr, "WARNING! This program can confuse your I2C "
254                        "bus, cause data loss and worse!\n");
255
256                fprintf(stderr, "I will probe file %s%s.\n", filename,
257                        mode==MODE_QUICK?" using quick write commands":
258                        mode==MODE_READ?" using read byte commands":"");
259                fprintf(stderr, "I will probe address range 0x%02x-0x%02x.\n",
260                        first, last);
261
262                fprintf(stderr, "Continue? [Y/n] ");
263                fflush(stderr);
264                fgets(s, 2, stdin);
265                if (s[0] != '\n' && s[0] != 'y' && s[0] != 'Y') {
266                        fprintf(stderr, "Aborting on user request.\n");
267                        exit(0);
268                }
269        }
270
271        res = scan_i2c_bus(file, mode, first, last);
272
273        close(file);
274
275        exit(res?1:0);
276}
Note: See TracBrowser for help on using the browser.