X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=miscutils%2Fi2c_tools.c;h=fc392d9dc7c205c7e176e806d0002f381afcba22;hb=73af705628ddaedc4c6f7f78b9658d6c01310309;hp=292ff88ddb61a8e5614d9499b80609842c6b960a;hpb=d60752f8c9be5689a249ad518deb38061d4bc45e;p=oweals%2Fbusybox.git diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 292ff88dd..fc392d9dc 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -8,40 +8,40 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ - //config:config I2CGET -//config: bool "i2cget" +//config: bool "i2cget (5.6 kb)" //config: default y //config: select PLATFORM_LINUX //config: help -//config: Read from I2C/SMBus chip registers. +//config: Read from I2C/SMBus chip registers. //config: //config:config I2CSET -//config: bool "i2cset" +//config: bool "i2cset (6.9 kb)" //config: default y //config: select PLATFORM_LINUX //config: help -//config: Set I2C registers. +//config: Set I2C registers. //config: //config:config I2CDUMP -//config: bool "i2cdump" +//config: bool "i2cdump (7.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help -//config: Examine I2C registers. +//config: Examine I2C registers. //config: //config:config I2CDETECT -//config: bool "i2cdetect" +//config: bool "i2cdetect (7.2 kb)" //config: default y //config: select PLATFORM_LINUX //config: help -//config: Detect I2C chips. +//config: Detect I2C chips. //config: //applet:IF_I2CGET(APPLET(i2cget, BB_DIR_USR_SBIN, BB_SUID_DROP)) //applet:IF_I2CSET(APPLET(i2cset, BB_DIR_USR_SBIN, BB_SUID_DROP)) //applet:IF_I2CDUMP(APPLET(i2cdump, BB_DIR_USR_SBIN, BB_SUID_DROP)) //applet:IF_I2CDETECT(APPLET(i2cdetect, BB_DIR_USR_SBIN, BB_SUID_DROP)) +/* not NOEXEC: if hw operation stalls, use less memory in "hung" process */ //kbuild:lib-$(CONFIG_I2CGET) += i2c_tools.o //kbuild:lib-$(CONFIG_I2CSET) += i2c_tools.o @@ -62,7 +62,6 @@ #include "libbb.h" #include -#include #define I2CDUMP_NUM_REGS 256 @@ -70,6 +69,25 @@ #define I2CDETECT_MODE_QUICK 1 #define I2CDETECT_MODE_READ 2 +/* linux/i2c-dev.h from i2c-tools overwrites the one from linux uapi + * and defines symbols already defined by linux/i2c.h. + * Also, it defines a bunch of static inlines which we would rather NOT + * inline. What a mess. + * We need only these definitions from linux/i2c-dev.h: + */ +#define I2C_SLAVE 0x0703 +#define I2C_SLAVE_FORCE 0x0706 +#define I2C_FUNCS 0x0705 +#define I2C_PEC 0x0708 +#define I2C_SMBUS 0x0720 +struct i2c_smbus_ioctl_data { + __u8 read_write; + __u8 command; + __u32 size; + union i2c_smbus_data *data; +}; +/* end linux/i2c-dev.h */ + /* * This is needed for ioctl_or_perror_and_die() since it only accepts pointers. */ @@ -358,7 +376,7 @@ static void check_read_funcs(int fd, int mode, int data_addr, int pec) break; #endif /* ENABLE_I2CDUMP */ default: - bb_error_msg_and_die("Programmer goofed!"); + bb_error_msg_and_die("internal error"); } check_funcs_test_end(funcs, pec, err); } @@ -436,31 +454,30 @@ static void confirm_action(int bus_addr, int mode, int data_addr, int pec) #if ENABLE_I2CGET //usage:#define i2cget_trivial_usage -//usage: "[-f] [-y] BUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]" +//usage: "[-fy] BUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]" //usage:#define i2cget_full_usage "\n\n" -//usage: "Read from I2C/SMBus chip registers\n" -//usage: "\n I2CBUS i2c bus number" -//usage: "\n ADDRESS 0x03 - 0x77" +//usage: "Read from I2C/SMBus chip registers" +//usage: "\n" +//usage: "\n I2CBUS I2C bus number" +//usage: "\n ADDRESS 0x03-0x77" //usage: "\nMODE is:" -//usage: "\n b read byte data (default)" -//usage: "\n w read word data" -//usage: "\n c write byte/read byte" +//usage: "\n b Read byte data (default)" +//usage: "\n w Read word data" +//usage: "\n c Write byte/read byte" //usage: "\n Append p for SMBus PEC" //usage: "\n" -//usage: "\n -f force access" -//usage: "\n -y disable interactive mode" +//usage: "\n -f Force access" +//usage: "\n -y Disable interactive mode" int i2cget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int i2cget_main(int argc UNUSED_PARAM, char **argv) { const unsigned opt_f = (1 << 0), opt_y = (1 << 1); - const char *const optstr = "fy"; int bus_num, bus_addr, data_addr = -1, status; int mode = I2C_SMBUS_BYTE, pec = 0, fd; unsigned opts; - opt_complementary = "-2:?4"; /* from 2 to 4 args */ - opts = getopt32(argv, optstr); + opts = getopt32(argv, "^" "fy" "\0" "-2:?4"/*from 2 to 4 args*/); argv += optind; bus_num = i2c_bus_lookup(argv[0]); @@ -520,29 +537,29 @@ int i2cget_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_I2CSET //usage:#define i2cset_trivial_usage -//usage: "[-f] [-y] [-m MASK] BUS CHIP-ADDR DATA-ADDR [VALUE] ... [MODE]" +//usage: "[-fy] [-m MASK] BUS CHIP-ADDRESS DATA-ADDRESS [VALUE] ... [MODE]" //usage:#define i2cset_full_usage "\n\n" -//usage: "Set I2C registers\n" -//usage: "\n I2CBUS i2c bus number" -//usage: "\n ADDRESS 0x03 - 0x77" +//usage: "Set I2C registers" +//usage: "\n" +//usage: "\n I2CBUS I2C bus number" +//usage: "\n ADDRESS 0x03-0x77" //usage: "\nMODE is:" -//usage: "\n c byte, no value" -//usage: "\n b byte data (default)" -//usage: "\n w word data" +//usage: "\n c Byte, no value" +//usage: "\n b Byte data (default)" +//usage: "\n w Word data" //usage: "\n i I2C block data" //usage: "\n s SMBus block data" //usage: "\n Append p for SMBus PEC" //usage: "\n" -//usage: "\n -f force access" -//usage: "\n -y disable interactive mode" -//usage: "\n -r read back and compare the result" -//usage: "\n -m MASK mask specifying which bits to write" +//usage: "\n -f Force access" +//usage: "\n -y Disable interactive mode" +//usage: "\n -r Read back and compare the result" +//usage: "\n -m MASK Mask specifying which bits to write" int i2cset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int i2cset_main(int argc, char **argv) { const unsigned opt_f = (1 << 0), opt_y = (1 << 1), opt_m = (1 << 2), opt_r = (1 << 3); - const char *const optstr = "fym:r"; int bus_num, bus_addr, data_addr, mode = I2C_SMBUS_BYTE, pec = 0; int val, blen = 0, mask = 0, fd, status; @@ -550,8 +567,7 @@ int i2cset_main(int argc, char **argv) char *opt_m_arg = NULL; unsigned opts; - opt_complementary = "-3"; /* from 3 to ? args */ - opts = getopt32(argv, optstr, &opt_m_arg); + opts = getopt32(argv, "^" "fym:r" "\0" "-3"/*from 3 to ? args*/, &opt_m_arg); argv += optind; argc -= optind; @@ -723,16 +739,18 @@ static int read_block_data(int buf_fd, int mode, int *block) uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2CDUMP_NUM_REGS]; int res, blen = 0, tmp, i; - if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA) { - res = i2c_smbus_read_block_data(buf_fd, 0, cblock); - blen = res; + if (mode == I2C_SMBUS_BLOCK_DATA) { + blen = i2c_smbus_read_block_data(buf_fd, 0, cblock); + if (blen <= 0) + goto fail; } else { for (res = 0; res < I2CDUMP_NUM_REGS; res += tmp) { tmp = i2c_smbus_read_i2c_block_data( buf_fd, res, I2C_SMBUS_BLOCK_MAX, cblock + res); - if (tmp < 0) { - bb_error_msg_and_die("block read failed"); + if (tmp <= 0) { + blen = tmp; + goto fail; } } @@ -748,6 +766,9 @@ static int read_block_data(int buf_fd, int mode, int *block) } return blen; + + fail: + bb_error_msg_and_die("block read failed: %d", blen); } /* Dump all but word data. */ @@ -876,38 +897,41 @@ static void dump_word_data(int bus_fd, unsigned first, unsigned last) } //usage:#define i2cdump_trivial_usage -//usage: "[-f] [-r FIRST-LAST] [-y] BUS ADDR [MODE]" +//usage: "[-fy] [-r FIRST-LAST] BUS ADDR [MODE]" //usage:#define i2cdump_full_usage "\n\n" -//usage: "Examine I2C registers\n" -//usage: "\n I2CBUS i2c bus number" -//usage: "\n ADDRESS 0x03 - 0x77" +//usage: "Examine I2C registers" +//usage: "\n" +//usage: "\n I2CBUS I2C bus number" +//usage: "\n ADDRESS 0x03-0x77" //usage: "\nMODE is:" -//usage: "\n b byte (default)" -//usage: "\n w word" -//usage: "\n W word on even register addresses" +//usage: "\n b Byte (default)" +//usage: "\n w Word" +//usage: "\n W Word on even register addresses" //usage: "\n i I2C block" //usage: "\n s SMBus block" -//usage: "\n c consecutive byte" +//usage: "\n c Consecutive byte" //usage: "\n Append p for SMBus PEC" //usage: "\n" -//usage: "\n -f force access" -//usage: "\n -y disable interactive mode" -//usage: "\n -r limit the number of registers being accessed" +//usage: "\n -f Force access" +//usage: "\n -y Disable interactive mode" +//usage: "\n -r Limit the number of registers being accessed" int i2cdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int i2cdump_main(int argc UNUSED_PARAM, char **argv) { const unsigned opt_f = (1 << 0), opt_y = (1 << 1), opt_r = (1 << 2); - const char *const optstr = "fyr:"; int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0; unsigned first = 0x00, last = 0xff, opts; - int *block = (int *)bb_common_bufsiz1; + int block[I2CDUMP_NUM_REGS]; char *opt_r_str, *dash; - int fd, res, blen; + int fd, res; - opt_complementary = "-2:?3"; /* from 2 to 3 args */ - opts = getopt32(argv, optstr, &opt_r_str); + opts = getopt32(argv, "^" + "fyr:" + "\0" "-2:?3" /* from 2 to 3 args */, + &opt_r_str + ); argv += optind; bus_num = i2c_bus_lookup(argv[0]); @@ -971,7 +995,10 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv) /* All but word data. */ if (mode != I2C_SMBUS_WORD_DATA || even) { - blen = read_block_data(fd, mode, block); + int blen = 0; + + if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA) + blen = read_block_data(fd, mode, block); if (mode == I2C_SMBUS_BYTE) { res = i2c_smbus_write_byte(fd, first); @@ -1022,33 +1049,33 @@ static const struct i2c_func i2c_funcs_tab[] = { { .value = I2C_FUNC_I2C, .name = "I2C" }, { .value = I2C_FUNC_SMBUS_QUICK, - .name = "SMBus Quick Command" }, + .name = "SMBus quick command" }, { .value = I2C_FUNC_SMBUS_WRITE_BYTE, - .name = "SMBus Send Byte" }, + .name = "SMBus send byte" }, { .value = I2C_FUNC_SMBUS_READ_BYTE, - .name = "SMBus Receive Byte" }, + .name = "SMBus receive byte" }, { .value = I2C_FUNC_SMBUS_WRITE_BYTE_DATA, - .name = "SMBus Write Byte" }, + .name = "SMBus write byte" }, { .value = I2C_FUNC_SMBUS_READ_BYTE_DATA, - .name = "SMBus Read Byte" }, + .name = "SMBus read byte" }, { .value = I2C_FUNC_SMBUS_WRITE_WORD_DATA, - .name = "SMBus Write Word" }, + .name = "SMBus write word" }, { .value = I2C_FUNC_SMBUS_READ_WORD_DATA, - .name = "SMBus Read Word" }, + .name = "SMBus read word" }, { .value = I2C_FUNC_SMBUS_PROC_CALL, - .name = "SMBus Process Call" }, + .name = "SMBus process call" }, { .value = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA, - .name = "SMBus Block Write" }, + .name = "SMBus block write" }, { .value = I2C_FUNC_SMBUS_READ_BLOCK_DATA, - .name = "SMBus Block Read" }, + .name = "SMBus block read" }, { .value = I2C_FUNC_SMBUS_BLOCK_PROC_CALL, - .name = "SMBus Block Process Call" }, + .name = "SMBus block process call" }, { .value = I2C_FUNC_SMBUS_PEC, .name = "SMBus PEC" }, { .value = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK, - .name = "I2C Block Write" }, + .name = "I2C block write" }, { .value = I2C_FUNC_SMBUS_READ_I2C_BLOCK, - .name = "I2C Block Read" }, + .name = "I2C block read" }, { .value = 0, .name = NULL } }; @@ -1180,33 +1207,34 @@ static void will_skip(const char *cmd) } //usage:#define i2cdetect_trivial_usage -//usage: "[-F I2CBUS] [-l] [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]" +//usage: "-l | -F I2CBUS | [-ya] [-q|-r] I2CBUS [FIRST LAST]" //usage:#define i2cdetect_full_usage "\n\n" -//usage: "Detect I2C chips.\n" -//usage: "\n I2CBUS i2c bus number" -//usage: "\n FIRST and LAST limit the probing range" +//usage: "Detect I2C chips" //usage: "\n" -//usage: "\n -l output list of installed busses" -//usage: "\n -y disable interactive mode" -//usage: "\n -a force scanning of non-regular addresses" -//usage: "\n -q use smbus quick write commands for probing (default)" -//usage: "\n -r use smbus read byte commands for probing" -//usage: "\n -F display list of functionalities" +//usage: "\n -l List installed buses" +//usage: "\n -F BUS# List functionalities on this bus" +//usage: "\n -y Disable interactive mode" +//usage: "\n -a Force scanning of non-regular addresses" +//usage: "\n -q Use smbus quick write commands for probing (default)" +//usage: "\n -r Use smbus read byte commands for probing" +//usage: "\n FIRST and LAST limit probing range" int i2cdetect_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int i2cdetect_main(int argc UNUSED_PARAM, char **argv) { const unsigned opt_y = (1 << 0), opt_a = (1 << 1), opt_q = (1 << 2), opt_r = (1 << 3), opt_F = (1 << 4), opt_l = (1 << 5); - const char *const optstr = "yaqrFl"; - int fd, bus_num, i, j, mode = I2CDETECT_MODE_AUTO, status; + int fd, bus_num, i, j, mode = I2CDETECT_MODE_AUTO, status, cmd; unsigned first = 0x03, last = 0x77, opts; unsigned long funcs; - opt_complementary = "q--r:r--q:" /* mutually exclusive */ - "?3"; /* up to 3 args */ - opts = getopt32(argv, optstr); + opts = getopt32(argv, "^" + "yaqrFl" + "\0" + "q--r:r--q:"/*mutually exclusive*/ + "?3"/*up to 3 args*/ + ); argv += optind; if (opts & opt_l) @@ -1251,17 +1279,17 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) no_support("detection commands"); } else if (mode == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)) { - no_support("SMBus Quick Write command"); + no_support("SMBus quick write"); } else if (mode == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) { - no_support("SMBus Receive Byte command"); + no_support("SMBus receive byte"); } if (mode == I2CDETECT_MODE_AUTO) { if (!(funcs & I2C_FUNC_SMBUS_QUICK)) - will_skip("SMBus Quick Write"); + will_skip("SMBus quick write"); if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) - will_skip("SMBus Receive Byte"); + will_skip("SMBus receive byte"); } if (!(opts & opt_y)) @@ -1270,22 +1298,23 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) puts(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"); for (i = 0; i < 128; i += 16) { printf("%02x: ", i); - for(j = 0; j < 16; j++) { + for (j = 0; j < 16; j++) { fflush_all(); + cmd = mode; if (mode == I2CDETECT_MODE_AUTO) { if ((i+j >= 0x30 && i+j <= 0x37) || (i+j >= 0x50 && i+j <= 0x5F)) - mode = I2CDETECT_MODE_READ; + cmd = I2CDETECT_MODE_READ; else - mode = I2CDETECT_MODE_QUICK; + cmd = I2CDETECT_MODE_QUICK; } /* Skip unwanted addresses. */ if (i+j < first || i+j > last - || (mode == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) - || (mode == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK))) + || (cmd == I2CDETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) + || (cmd == I2CDETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK))) { printf(" "); continue; @@ -1302,7 +1331,7 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) "can't set address to 0x%02x", i + j); } - switch (mode) { + switch (cmd) { case I2CDETECT_MODE_READ: /* * This is known to lock SMBus on various