mirror of
https://github.com/lm-sensors/lm-sensors.git
synced 2026-11-06 15:51:34 +00:00
Move i2cdetect, i2cdump, i2cset and i2cget to a separate package
(i2c-tools). git-svn-id: http://lm-sensors.org/svn/lm-sensors/branches/lm-sensors-3.0.0@4480 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
1 parent
9ab400fad3
commit
d7b4debbf6
14 files changed
+10
-1981
No files matched your search
+3
-14
@@ -22,28 +22,18 @@ MODULE_DIR := prog/detect
|
||||
PROGDETECTDIR := $(MODULE_DIR)
|
||||
|
||||
PROGDETECTMAN8DIR := $(MANDIR)/man8
|
||||
PROGDETECTMAN8FILES := $(MODULE_DIR)/i2cdetect.8 $(MODULE_DIR)/sensors-detect.8
|
||||
PROGDETECTMAN8FILES := $(MODULE_DIR)/sensors-detect.8
|
||||
|
||||
# Regrettably, even 'simply expanded variables' will not put their currently
|
||||
# defined value verbatim into the command-list of rules...
|
||||
PROGDETECTTARGETS := $(MODULE_DIR)/i2cdetect
|
||||
PROGDETECTSOURCES := $(MODULE_DIR)/i2cdetect.c
|
||||
PROGDETECTSBININSTALL := $(MODULE_DIR)/sensors-detect \
|
||||
$(MODULE_DIR)/i2cdetect
|
||||
|
||||
# Include all dependency files. We use '.rd' to indicate this will create
|
||||
# executables.
|
||||
INCLUDEFILES += $(PROGDETECTSOURCES:.c=.rd)
|
||||
PROGDETECTSBININSTALL := $(MODULE_DIR)/sensors-detect
|
||||
|
||||
REMOVEDETECTBIN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(SBINDIR)/%,$(PROGDETECTSBININSTALL))
|
||||
REMOVEDETECTMAN := $(patsubst $(MODULE_DIR)/%,$(DESTDIR)$(PROGDETECTMAN8DIR)/%,$(PROGDETECTMAN8FILES))
|
||||
|
||||
all-prog-detect: $(PROGDETECTTARGETS)
|
||||
all-prog-detect:
|
||||
user :: all-prog-detect
|
||||
|
||||
$(MODULE_DIR)/i2cdetect: $(MODULE_DIR)/i2cdetect.ro prog/dump/i2cbusses.ro
|
||||
$(CC) $(EXLDFLAGS) -o $@ $^
|
||||
|
||||
install-prog-detect: all-prog-detect
|
||||
$(MKDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(PROGDETECTMAN8DIR)
|
||||
$(INSTALL) -m 755 $(PROGDETECTSBININSTALL) $(DESTDIR)$(SBINDIR)
|
||||
@@ -55,5 +45,4 @@ user_uninstall::
|
||||
$(RM) $(REMOVEDETECTMAN)
|
||||
|
||||
clean-prog-detect:
|
||||
$(RM) $(PROGDETECTDIR)/*.rd $(PROGDETECTDIR)/*.ro $(PROGDETECTTARGETS)
|
||||
clean :: clean-prog-detect
|
||||
@@ -1,88 +0,0 @@
|
||||
.TH I2CDETECT 8 "October 2006"
|
||||
.SH NAME
|
||||
i2cdetect \- detect I2C chips
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B i2cdetect
|
||||
.RI [ -y ]
|
||||
.RI [ -a ]
|
||||
.RI [ -q | -r ]
|
||||
.I i2cbus
|
||||
.RI [ "first last" ]
|
||||
.br
|
||||
.B i2cdetect
|
||||
.I -F
|
||||
.I i2cbus
|
||||
.br
|
||||
.B i2cdetect
|
||||
.I -V
|
||||
.br
|
||||
.B i2cdetect
|
||||
.I -l
|
||||
|
||||
.SH DESCRIPTION
|
||||
i2cdetect is a userspace program to scan an I2C bus for devices. It
|
||||
outputs a table with the list of detected devices on the specified bus.
|
||||
\fIi2cbus\fR indicates the number of the I2C bus to be scanned, and
|
||||
should correspond to one of the busses listed by \fIi2cdetect -l\fR.
|
||||
The optional parameters \fIfirst\fR and \fIlast\fR restrict the scanning
|
||||
range (default: from 0x03 to 0x77).
|
||||
.PP
|
||||
i2cdetect can also be used to query the functionalities of an I2C bus
|
||||
(see option \fB-F\fP.)
|
||||
|
||||
.SH WARNING
|
||||
This program can confuse your I2C bus, cause data loss and worse!
|
||||
|
||||
.SH INTERPRETING THE OUTPUT
|
||||
Each cell in the output table will contain one of the following symbols:
|
||||
.IP \(bu "\w'\(bu'u+1n"
|
||||
"--". The address was probed but no chip answered.
|
||||
.IP \(bu
|
||||
"UU". Probing was skipped, because this address is currently in use by
|
||||
a driver. This strongly suggests that there is a chip at this address.
|
||||
.IP \(bu
|
||||
An address number in hexadecimal, e.g. "2d" or "4e". A chip
|
||||
was found at this address.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B "\-y"
|
||||
Disable interactive mode. By default, i2cdetect will wait for a confirmation
|
||||
from the user before messing with the I2C bus. When this flag is used, it
|
||||
will perform the operation directly. This is mainly meant to be used in
|
||||
scripts.
|
||||
.TP
|
||||
.B "\-a"
|
||||
Force scanning of non-regular addresses. Not recommended.
|
||||
.TP
|
||||
.B "\-q"
|
||||
Use SMBus "quick write" commands for probing (by default, the command
|
||||
used is the one believed to be the safest for each address).
|
||||
Not recommended. This is known to corrupt the Atmel AT24RF08 EEPROM
|
||||
found on many IBM Thinkpad laptops.
|
||||
.TP
|
||||
.B "\-r"
|
||||
Use SMBus "read byte" commands for probing (by default, the command
|
||||
used is the one believed to be the safest for each address).
|
||||
Not recommended. This is known to lock SMBus on various write-only
|
||||
chips (most notably clock chips at address 0x69).
|
||||
.TP
|
||||
.B "\-F"
|
||||
Display the list of functionalities implemented by the adapter and exit.
|
||||
.TP
|
||||
.B "\-V"
|
||||
Display the version and exit.
|
||||
.TP
|
||||
.B "\-l"
|
||||
Output a list of installed busses.
|
||||
|
||||
.SH SEE ALSO
|
||||
i2cdump(8), sensors-detect(8)
|
||||
|
||||
.SH AUTHOR
|
||||
Frodo Looijaard, Mark D. Studebaker, and the lm_sensors group
|
||||
http://www.lm-sensors.org/
|
||||
This manual page was written by Aurelien Jarno <aurel32@debian.org>, for
|
||||
the Debian GNU/Linux system. It was then reviewed by the lm_sensors team and
|
||||
is now part of the lm_sensors source distribution.
|
||||
@@ -1,347 +0,0 @@
|
||||
/*
|
||||
i2cdetect.c - a user-space program to scan for I2C devices
|
||||
Copyright (C) 1999-2004 Frodo Looijaard <frodol@dds.nl>,
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com> and
|
||||
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
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "../dump/i2cbusses.h"
|
||||
#include "i2c-dev.h"
|
||||
#include "version.h"
|
||||
|
||||
#define MODE_AUTO 0
|
||||
#define MODE_QUICK 1
|
||||
#define MODE_READ 2
|
||||
#define MODE_FUNC 3
|
||||
|
||||
void help(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Syntax: i2cdetect [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]\n"
|
||||
" i2cdetect -F I2CBUS\n"
|
||||
" i2cdetect -l\n"
|
||||
" i2cdetect -V\n"
|
||||
" I2CBUS is an integer\n"
|
||||
" With -a, probe all addresses (NOT RECOMMENDED)\n"
|
||||
" With -q, uses only quick write commands for probing (NOT "
|
||||
"RECOMMENDED)\n"
|
||||
" With -r, uses only read byte commands for probing (NOT "
|
||||
"RECOMMENDED)\n"
|
||||
" If provided, FIRST and LAST limit the probing range.\n"
|
||||
" With -l, lists installed busses only\n");
|
||||
print_i2c_busses(0);
|
||||
}
|
||||
|
||||
int scan_i2c_bus(int file, const int mode, const int first, const int last)
|
||||
{
|
||||
int i, j;
|
||||
int res;
|
||||
|
||||
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
|
||||
|
||||
for (i = 0; i < 128; i += 16) {
|
||||
printf("%02x: ", i);
|
||||
for(j = 0; j < 16; j++) {
|
||||
fflush(stdout);
|
||||
|
||||
/* Skip unwanted addresses */
|
||||
if (i+j < first || i+j > last) {
|
||||
printf(" ");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set slave address */
|
||||
if (ioctl(file, I2C_SLAVE, i+j) < 0) {
|
||||
if (errno == EBUSY) {
|
||||
printf("UU ");
|
||||
continue;
|
||||
} else {
|
||||
fprintf(stderr, "Error: Could not set "
|
||||
"address to 0x%02x: %s\n", i+j,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Probe this address */
|
||||
switch (mode) {
|
||||
case MODE_QUICK:
|
||||
/* This is known to corrupt the Atmel AT24RF08
|
||||
EEPROM */
|
||||
res = i2c_smbus_write_quick(file,
|
||||
I2C_SMBUS_WRITE);
|
||||
break;
|
||||
case MODE_READ:
|
||||
/* This is known to lock SMBus on various
|
||||
write-only chips (mainly clock chips) */
|
||||
res = i2c_smbus_read_byte(file);
|
||||
break;
|
||||
default:
|
||||
if ((i+j >= 0x30 && i+j <= 0x37)
|
||||
|| (i+j >= 0x50 && i+j <= 0x5F))
|
||||
res = i2c_smbus_read_byte(file);
|
||||
else
|
||||
res = i2c_smbus_write_quick(file,
|
||||
I2C_SMBUS_WRITE);
|
||||
}
|
||||
|
||||
if (res < 0)
|
||||
printf("-- ");
|
||||
else
|
||||
printf("%02x ", i+j);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct func
|
||||
{
|
||||
long value;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
static const struct func all_func[] = {
|
||||
{ .value = I2C_FUNC_I2C,
|
||||
.name = "I2C" },
|
||||
{ .value = I2C_FUNC_SMBUS_QUICK,
|
||||
.name = "SMBus Quick Command" },
|
||||
{ .value = I2C_FUNC_SMBUS_WRITE_BYTE,
|
||||
.name = "SMBus Send Byte" },
|
||||
{ .value = I2C_FUNC_SMBUS_READ_BYTE,
|
||||
.name = "SMBus Receive Byte" },
|
||||
{ .value = I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
|
||||
.name = "SMBus Write Byte" },
|
||||
{ .value = I2C_FUNC_SMBUS_READ_BYTE_DATA,
|
||||
.name = "SMBus Read Byte" },
|
||||
{ .value = I2C_FUNC_SMBUS_WRITE_WORD_DATA,
|
||||
.name = "SMBus Write Word" },
|
||||
{ .value = I2C_FUNC_SMBUS_READ_WORD_DATA,
|
||||
.name = "SMBus Read Word" },
|
||||
{ .value = I2C_FUNC_SMBUS_PROC_CALL,
|
||||
.name = "SMBus Process Call" },
|
||||
{ .value = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA,
|
||||
.name = "SMBus Block Write" },
|
||||
{ .value = I2C_FUNC_SMBUS_READ_BLOCK_DATA,
|
||||
.name = "SMBus Block Read" },
|
||||
{ .value = I2C_FUNC_SMBUS_BLOCK_PROC_CALL,
|
||||
.name = "SMBus Block Process Call" },
|
||||
{ .value = I2C_FUNC_SMBUS_HWPEC_CALC,
|
||||
.name = "SMBus PEC" },
|
||||
{ .value = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK,
|
||||
.name = "I2C Block Write" },
|
||||
{ .value = I2C_FUNC_SMBUS_READ_I2C_BLOCK,
|
||||
.name = "I2C Block Read" },
|
||||
{ }
|
||||
};
|
||||
|
||||
void print_functionality(unsigned long funcs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; all_func[i].value; i++) {
|
||||
printf("%-32s %s\n", all_func[i].name,
|
||||
(funcs & all_func[i].value) ? "yes" : "no");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *end;
|
||||
int i2cbus, file, res;
|
||||
char filename[20];
|
||||
unsigned long funcs;
|
||||
int mode = MODE_AUTO;
|
||||
int first = 0x03, last = 0x77;
|
||||
int flags = 0;
|
||||
int yes = 0, version = 0, list = 0;
|
||||
|
||||
/* handle (optional) flags first */
|
||||
while (1+flags < argc && argv[1+flags][0] == '-') {
|
||||
switch (argv[1+flags][1]) {
|
||||
case 'V': version = 1; break;
|
||||
case 'y': yes = 1; break;
|
||||
case 'l': list = 1; break;
|
||||
case 'F':
|
||||
if (mode != MODE_AUTO && mode != MODE_FUNC) {
|
||||
fprintf(stderr, "Error: Different modes "
|
||||
"specified!\n");
|
||||
exit(1);
|
||||
}
|
||||
mode = MODE_FUNC;
|
||||
break;
|
||||
case 'r':
|
||||
if (mode == MODE_QUICK) {
|
||||
fprintf(stderr, "Error: Different modes "
|
||||
"specified!\n");
|
||||
exit(1);
|
||||
}
|
||||
mode = MODE_READ;
|
||||
break;
|
||||
case 'q':
|
||||
if (mode == MODE_READ) {
|
||||
fprintf(stderr, "Error: Different modes "
|
||||
"specified!\n");
|
||||
exit(1);
|
||||
}
|
||||
mode = MODE_QUICK;
|
||||
break;
|
||||
case 'a':
|
||||
first = 0x00;
|
||||
last = 0x7F;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Warning: Unsupported flag "
|
||||
"\"-%c\"!\n", argv[1+flags][1]);
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
flags++;
|
||||
}
|
||||
|
||||
if (version) {
|
||||
fprintf(stderr, "i2cdetect version %s\n", LM_VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (list) {
|
||||
print_i2c_busses(1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (argc < flags + 2) {
|
||||
fprintf(stderr, "Error: No i2c-bus specified!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
i2cbus = strtol(argv[flags+1], &end, 0);
|
||||
if (*end) {
|
||||
fprintf(stderr, "Error: I2CBUS argument not a number!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
if ((i2cbus < 0) || (i2cbus > 0xff)) {
|
||||
fprintf(stderr, "Error: I2CBUS argument out of range "
|
||||
"(0-255)!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* read address range if present */
|
||||
if (argc == flags + 4 && mode != MODE_FUNC) {
|
||||
int tmp;
|
||||
|
||||
tmp = strtol(argv[flags+2], &end, 0);
|
||||
if (*end) {
|
||||
fprintf(stderr, "Error: FIRST argment not a "
|
||||
"number!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
if (tmp < first || tmp > last) {
|
||||
fprintf(stderr, "Error: FIRST argument out of range "
|
||||
"(0x%02x-0x%02x)!\n", first, last);
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
first = tmp;
|
||||
|
||||
tmp = strtol(argv[flags+3], &end, 0);
|
||||
if (*end) {
|
||||
fprintf(stderr, "Error: LAST argment not a "
|
||||
"number!\n");
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
if (tmp < first || tmp > last) {
|
||||
fprintf(stderr, "Error: LAST argument out of range "
|
||||
"(0x%02x-0x%02x)!\n", first, last);
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
last = tmp;
|
||||
} else if (argc != flags + 2) {
|
||||
help();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
file = open_i2c_dev(i2cbus, filename, 0);
|
||||
if (file < 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
|
||||
fprintf(stderr, "Error: Could not get the adapter "
|
||||
"functionality matrix: %s\n", strerror(errno));
|
||||
close(file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Special case, we only list the implemented functionalities */
|
||||
if (mode == MODE_FUNC) {
|
||||
close(file);
|
||||
printf("Functionalities implemented by %s:\n", filename);
|
||||
print_functionality(funcs);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (mode != MODE_READ && !(funcs & I2C_FUNC_SMBUS_QUICK)) {
|
||||
fprintf(stderr, "Error: Can't use SMBus Quick Write command "
|
||||
"on this bus (ISA bus?)\n");
|
||||
close(file);
|
||||
exit(1);
|
||||
}
|
||||
if (mode != MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) {
|
||||
fprintf(stderr, "Error: Can't use SMBus Read Byte command "
|
||||
"on this bus (ISA bus?)\n");
|
||||
close(file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!yes) {
|
||||
char s[2];
|
||||
|
||||
fprintf(stderr, "WARNING! This program can confuse your I2C "
|
||||
"bus, cause data loss and worse!\n");
|
||||
|
||||
fprintf(stderr, "I will probe file %s%s.\n", filename,
|
||||
mode==MODE_QUICK?" using quick write commands":
|
||||
mode==MODE_READ?" using read byte commands":"");
|
||||
fprintf(stderr, "I will probe address range 0x%02x-0x%02x.\n",
|
||||
first, last);
|
||||
|
||||
fprintf(stderr, "Continue? [Y/n] ");
|
||||
fflush(stderr);
|
||||
if (!fgets(s, 2, stdin)
|
||||
|| (s[0] != '\n' && s[0] != 'y' && s[0] != 'Y')) {
|
||||
fprintf(stderr, "Aborting on user request.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
res = scan_i2c_bus(file, mode, first, last);
|
||||
|
||||
close(file);
|
||||
|
||||
exit(res?1:0);
|
||||
}
|
||||
Reference in new issue
Block a user