*
* 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
*/
#include "libbb.h"
-#include "common_bufsiz.h"
#include <linux/i2c.h>
-#include <linux/i2c-dev.h>
#define I2CDUMP_NUM_REGS 256
#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.
*/
static void confirm_or_abort(void)
{
fprintf(stderr, "Continue? [y/N] ");
- fflush_all();
- if (!bb_ask_confirmation())
+ if (!bb_ask_y_confirmation())
bb_error_msg_and_die("aborting");
}
#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]);
#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;
+ int val, blen, mask, fd, status;
unsigned char block[I2C_SMBUS_BLOCK_MAX];
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", /* minimum 3 args */
+ &opt_m_arg
+ );
argv += optind;
argc -= optind;
+ argc--; /* now argv[argc] is last arg */
bus_num = i2c_bus_lookup(argv[0]);
bus_addr = i2c_parse_bus_addr(argv[1]);
if (!argv[4] && argv[3][0] != 'c') {
mode = I2C_SMBUS_BYTE_DATA; /* Implicit b */
} else {
- switch (argv[argc-1][0]) {
- case 'c': /* Already set */ break;
- case 'b': mode = I2C_SMBUS_BYTE_DATA; break;
- case 'w': mode = I2C_SMBUS_WORD_DATA; break;
- case 's': mode = I2C_SMBUS_BLOCK_DATA; break;
- case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA; break;
+ switch (argv[argc][0]) {
+ case 'c': /* Already set */
+ break;
+ case 'b': mode = I2C_SMBUS_BYTE_DATA;
+ break;
+ case 'w': mode = I2C_SMBUS_WORD_DATA;
+ break;
+ case 's': mode = I2C_SMBUS_BLOCK_DATA;
+ break;
+ case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA;
+ break;
default:
bb_error_msg("invalid mode");
bb_show_usage();
}
- pec = argv[argc-1][1] == 'p';
- if (mode == I2C_SMBUS_BLOCK_DATA ||
- mode == I2C_SMBUS_I2C_BLOCK_DATA) {
+ pec = (argv[argc][1] == 'p');
+ if (mode == I2C_SMBUS_BLOCK_DATA
+ || mode == I2C_SMBUS_I2C_BLOCK_DATA
+ ) {
if (pec && mode == I2C_SMBUS_I2C_BLOCK_DATA)
bb_error_msg_and_die(
"PEC not supported for I2C "
}
/* Prepare the value(s) to be written according to current mode. */
+ mask = 0;
+ blen = 0;
switch (mode) {
case I2C_SMBUS_BYTE_DATA:
val = xstrtou_range(argv[3], 0, 0, 0xff);
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_I2C_BLOCK_DATA:
- for (blen = 3; blen < (argc - 1); blen++)
- block[blen] = xstrtou_range(argv[blen], 0, 0, 0xff);
+ for (blen = 3; blen < argc; blen++)
+ block[blen - 3] = xstrtou_range(argv[blen], 0, 0, 0xff);
+ blen -= 3;
val = -1;
break;
default:
}
//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;
- 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]);
}
//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, 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)