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

Revision 2695, 6.2 KB (checked in by khali, 10 years ago)

Mass reindent/coding-style update.

  • 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 [-f] [-q|-r] I2CBUS [FIRST LAST]\n"
39                "  I2CBUS is an integer\n"
40                "  With -f, scans all addresses (NOT RECOMMENDED)\n"
41                "  With -q, uses only quick write commands for probing (NOT "
42                "RECOMMENDED)\n"
43                "  With -r, uses only read byte commands for probing (NOT "
44                "RECOMMENDED)\n"
45                "  If provided, FIRST and LAST limit the probing range.\n"
46                "  i2cdetect -l lists installed busses only\n");
47}
48
49int scan_i2c_bus(int file, const int mode, const int first, const int last)
50{
51        int i, j;
52        int res;
53
54        printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
55
56        for (i = 0; i < 128; i += 16) {
57                printf("%02x: ", i);
58                for(j = 0; j < 16; j++) {
59                        /* Skip unwanted addresses */
60                        if (i+j < first || i+j > last) {
61                                printf("   ");
62                                continue;
63                        }
64
65                        /* Set slave address */
66                        if (ioctl(file, I2C_SLAVE, i+j) < 0) {
67                                if (errno == EBUSY) {
68                                        printf("UU ");
69                                        continue;
70                                } else {
71                                        fprintf(stderr, "Error: Could not set "
72                                                "address to 0x%02x: %s\n", i+j,
73                                                strerror(errno));
74                                        return -1;
75                                }
76                        }
77
78                        /* Probe this address */
79                        switch (mode) {
80                        case MODE_QUICK:
81                                /* This is known to corrupt the Atmel AT24RF08
82                                   EEPROM */
83                                res = i2c_smbus_write_quick(file,
84                                      I2C_SMBUS_WRITE);
85                                break;
86                        case MODE_READ:
87                                /* This is known to lock SMBus on various
88                                   write-only chips (mainly clock chips) */
89                                res = i2c_smbus_read_byte(file);
90                                break;
91                        default:
92                                if ((i+j >= 0x30 && i+j <= 0x37)
93                                 || (i+j >= 0x50 && i+j <= 0x5F))
94                                        res = i2c_smbus_read_byte(file);
95                                else
96                                        res = i2c_smbus_write_quick(file,
97                                              I2C_SMBUS_WRITE);
98                        }
99
100                        if (res < 0)
101                                printf("XX ");
102                        else
103                                printf("%02x ", i+j);
104                }
105                printf("\n");
106        }
107
108        return 0;
109}
110
111int main(int argc, char *argv[])
112{
113        char *end;
114        int i = 1, i2cbus = -1, file, res;
115        char filename[20];
116        long funcs;
117        int mode = MODE_AUTO;
118        int first = 0x03, last = 0x77;
119
120        while(i2cbus == -1) {
121                if (i >= argc) {
122                        fprintf(stderr, "Error: No i2c-bus specified!\n");
123                        help();
124                        exit(1);
125                }
126
127                if(!strcasecmp(argv[i], "-v")) {
128                        fprintf(stderr, "i2cdetect version %s\n", LM_VERSION);
129                        exit(0);
130                }
131
132                if(!strcmp(argv[i], "-l")) {
133                        print_i2c_busses(1);
134                        exit(0);
135                }
136
137                if(!strcmp(argv[i], "-f")) {
138                        first = 0x00;
139                        last = 0x7F;
140                        i++;
141                } else
142                if(!strcmp(argv[i], "-q")) {
143                        if (mode != MODE_AUTO) {
144                                fprintf(stderr, "Error: Different modes "
145                                        "specified!\n");
146                                exit(1);
147                        }
148                        mode = MODE_QUICK;
149                        i++;
150                } else
151                if(!strcmp(argv[i], "-r")) {
152                        if (mode != MODE_AUTO) {
153                                fprintf(stderr, "Error: Different modes "
154                                        "specified!\n");
155                                exit(1);
156                        }
157                        mode = MODE_READ;
158                        i++;
159                } else {
160                        i2cbus = strtol(argv[i],&end,0);
161                        if (*end) {
162                                fprintf(stderr, "Error: I2CBUS argument not a "
163                                        "number!\n");
164                                help();
165                                exit(1);
166                        }
167                        if ((i2cbus < 0) || (i2cbus > 0xff)) {
168                                fprintf(stderr, "Error: I2CBUS argument out "
169                                        "of range (0-255)!\n");
170                                help();
171                                exit(1);
172                        }
173                        i++;
174                }
175        }
176
177        /* read address range if present */
178        if (i+2 == argc) {
179                int tmp;
180
181                tmp = strtol(argv[i], &end, 0);
182                if (*end) {
183                        fprintf(stderr, "Error: FIRST argment not a "
184                                "number!\n");
185                        help();
186                        exit(1);
187                }
188                if (tmp < first || tmp > last) {
189                        fprintf(stderr, "Error: FIRST argument out of range "
190                                "(0x%02x-0x%02x)!\n", first, last);
191                        help();
192                        exit(1);
193                }
194                first = tmp;
195
196                tmp = strtol(argv[i+1], &end, 0);
197                if (*end) {
198                        fprintf(stderr, "Error: LAST argment not a "
199                                "number!\n");
200                        help();
201                        exit(1);
202                }
203                if (tmp < first || tmp > last) {
204                        fprintf(stderr, "Error: LAST argument out of range "
205                                "(0x%02x-0x%02x)!\n", first, last);
206                        help();
207                        exit(1);
208                }
209                last = tmp;
210        } else if (i != argc) {
211                help();
212                exit(1);
213        }
214
215        file = open_i2c_dev(i2cbus, filename);
216        if (file < 0) {
217                exit(1);
218        }
219
220        if (ioctl(file,I2C_FUNCS,&funcs) < 0) {
221                fprintf(stderr, "Error: Could not get the adapter "
222                        "functionality matrix: %s\n", strerror(errno));
223                close(file);
224                exit(1);
225        }
226        if (mode != MODE_READ && !(funcs & I2C_FUNC_SMBUS_QUICK)) {
227                fprintf(stderr, "Error: Can't use SMBus Quick Write command "
228                        "on this bus (ISA bus?)\n");
229                close(file);
230                exit(1);
231        }
232        if (mode != MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
233                fprintf(stderr, "Error: Can't use SMBus Read Byte command "
234                        "on this bus (ISA bus?)\n");
235                close(file);
236                exit(1);
237        }
238
239        fprintf(stderr, "  WARNING! This program can confuse your I2C bus, "
240                "cause data loss and worse!\n");
241        fprintf(stderr, "  I will probe file %s%s.\n", filename,
242                mode==MODE_QUICK?" using quick write commands":
243                mode==MODE_READ?" using read byte commands":"");
244        fprintf(stderr, "  I will probe address range 0x%02x-0x%02x.\n",
245                first, last);
246        fprintf(stderr, "  You have five seconds to reconsider and press "
247                "CTRL-C!\n\n");
248        sleep(5);
249
250        res = scan_i2c_bus(file, mode, first, last);
251
252        close(file);
253
254        exit(res?1:0);
255}
Note: See TracBrowser for help on using the browser.