aboutsummaryrefslogtreecommitdiff
path: root/toys/other/i2ctools.c
diff options
context:
space:
mode:
Diffstat (limited to 'toys/other/i2ctools.c')
-rw-r--r--toys/other/i2ctools.c131
1 files changed, 65 insertions, 66 deletions
diff --git a/toys/other/i2ctools.c b/toys/other/i2ctools.c
index bce160df..ad296adf 100644
--- a/toys/other/i2ctools.c
+++ b/toys/other/i2ctools.c
@@ -10,11 +10,13 @@
* TODO: i2cdump non-byte modes, -r FIRST-LAST?
* TODO: i2cget non-byte modes? default to current read address?
* TODO: i2cset -r? -m MASK? c/s modes, p mode modifier?
+ * TODO: I2C_M_TEN bit addressing (-t, larger range in probe...)
-USE_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CGET(NEWTOY(i2cget, "<3>3fy", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_BIN))
+// note: confirm() needs "y" to be in same place for all commands
+USE_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CGET(NEWTOY(i2cget, "<2>3fy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_SBIN))
config I2CDETECT
bool "i2cdetect"
@@ -31,7 +33,7 @@ config I2CDETECT
-l List available buses
-q Probe with SMBus Quick Write (default)
-r Probe with SMBus Read Byte
- -y Answer "yes" to confirmation prompts (for script use)
+ -y Skip confirmation prompts (yes to all)
config I2CDUMP
bool "i2cdump"
@@ -42,18 +44,18 @@ config I2CDUMP
Dump i2c registers.
-f Force access to busy devices
- -y Answer "yes" to confirmation prompts (for script use)
+ -y Skip confirmation prompts (yes to all)
config I2CGET
bool "i2cget"
default y
help
- usage: i2cget [-fy] BUS CHIP ADDR
+ usage: i2cget [-fy] BUS CHIP [ADDR]
Read an i2c register.
-f Force access to busy devices
- -y Answer "yes" to confirmation prompts (for script use)
+ -y Skip confirmation prompts (yes to all)
config I2CSET
bool "i2cset"
@@ -64,10 +66,11 @@ config I2CSET
Write an i2c register. MODE is b for byte, w for 16-bit word, i for I2C block.
-f Force access to busy devices
- -y Answer "yes" to confirmation prompts (for script use)
+ -y Skip confirmation prompts (yes to all)
*/
#define FOR_i2cdetect
+#define FORCE_FLAGS
#define TT this.i2ctools
#include "toys.h"
@@ -86,13 +89,13 @@ printf_format static void confirm(const char *fmt, ...)
if (!yesno(1)) error_exit("Exiting");
}
-static int i2c_open(int bus, int slave, int chip)
+static int i2c_open(int bus, int slave, long chip)
{
int fd;
- snprintf(toybuf, sizeof(toybuf), "/dev/i2c-%d", bus);
+ sprintf(toybuf, "/dev/i2c-%d", bus);
fd = xopen(toybuf, O_RDONLY);
- if (slave) xioctl(fd, slave, (void *)(long)chip);
+ if (slave) xioctl(fd, slave, (void *)chip);
return fd;
}
@@ -103,10 +106,11 @@ static unsigned long i2c_get_funcs(int bus)
xioctl(fd, I2C_FUNCS, &result);
close(fd);
+
return result;
}
-static int i2c_read_byte(int fd, int addr, int *byte)
+static int i2c_read_byte(int fd, int addr, char *byte)
{
union i2c_smbus_data data;
struct i2c_smbus_ioctl_data ioctl_data = { .read_write = I2C_SMBUS_READ,
@@ -115,42 +119,31 @@ static int i2c_read_byte(int fd, int addr, int *byte)
memset(&data, 0, sizeof(data));
if (ioctl(fd, I2C_SMBUS, &ioctl_data)==-1) return -1;
*byte = data.byte;
+
return 0;
}
static int i2c_quick_write(int fd, int addr)
{
struct i2c_smbus_ioctl_data ioctl_data = { .read_write = I2C_SMBUS_QUICK,
- .size = 0, .command = addr };
+ .command = addr };
return ioctl(fd, I2C_SMBUS, &ioctl_data);
}
static void i2cdetect_dash_F(int bus)
{
- struct { int mask; const char *name; } funcs[] = {
- {I2C_FUNC_I2C, "I2C"},
- {I2C_FUNC_SMBUS_QUICK, "SMBus Quick Command"},
- {I2C_FUNC_SMBUS_WRITE_BYTE, "SMBus Send Byte"},
- {I2C_FUNC_SMBUS_READ_BYTE, "SMBus Receive Byte"},
- {I2C_FUNC_SMBUS_WRITE_BYTE_DATA, "SMBus Write Byte"},
- {I2C_FUNC_SMBUS_READ_BYTE_DATA, "SMBus Read Byte"},
- {I2C_FUNC_SMBUS_WRITE_WORD_DATA, "SMBus Write Word"},
- {I2C_FUNC_SMBUS_READ_WORD_DATA, "SMBus Read Word"},
- {I2C_FUNC_SMBUS_PROC_CALL, "SMBus Process Call"},
- {I2C_FUNC_SMBUS_WRITE_BLOCK_DATA, "SMBus Write Block"},
- {I2C_FUNC_SMBUS_READ_BLOCK_DATA, "SMBus Read Block"},
- {I2C_FUNC_SMBUS_BLOCK_PROC_CALL, "SMBus Block Process Call"},
- {I2C_FUNC_SMBUS_PEC, "SMBus PEC"},
- {I2C_FUNC_SMBUS_WRITE_I2C_BLOCK, "I2C Write Block"},
- {I2C_FUNC_SMBUS_READ_I2C_BLOCK, "I2C Read Block"},
- };
- unsigned long sup = i2c_get_funcs(bus);
- int i;
+ char *funcs[] = {
+ "I2C", "10 bit", 0, "SMBus PEC", 0, 0, "SMBus Block Process Call",
+ "SMBus Quick Command", "SMBus Receive Byte", "SMBus Send Byte",
+ "SMBus Read Byte", "SMBus Write Byte", "SMBus Read Word",
+ "SMBus Write Word", "SMBus Process Call", "SMBus Read Block",
+ "SMBus Write Block", "I2C Read Block", "I2C Write Block" };
+ unsigned sup = i2c_get_funcs(bus), i;
printf("Functionalities implemented by %s:\n", toybuf);
- for (i = 0; i < ARRAY_LEN(funcs); ++i)
- printf("%-32s %s\n", funcs[i].name, (sup & funcs[i].mask) ? "yes" : "no");
+ for (i = 0; i<ARRAY_LEN(funcs); i++)
+ if (funcs[i]) printf("%-32s %s\n", funcs[i], (sup&(1<<i)) ? "yes" : "no");
}
static int i2cdetect_dash_l(struct dirtree *node)
@@ -186,9 +179,10 @@ void i2cdetect_main(void)
dirtree_flagread("/sys/class/i2c-dev", DIRTREE_SHUTUP, i2cdetect_dash_l);
} else if (FLAG(F)) {
if (toys.optc != 1) error_exit("-F BUS");
- i2cdetect_dash_F(atolx_range(*toys.optargs, 0, INT_MAX));
+ i2cdetect_dash_F(atolx_range(*toys.optargs, 0, 0x3f));
} else {
- int bus, first = 0x03, last = 0x77, fd, row, addr, byte;
+ int bus, first = 0x03, last = 0x77, fd, row, addr;
+ char byte;
if (FLAG(a)) {
first = 0x00;
@@ -196,7 +190,7 @@ void i2cdetect_main(void)
}
if (toys.optc!=1 && toys.optc!=3) help_exit("Needs 1 or 3 arguments");
- bus = atolx_range(*toys.optargs, 0, INT_MAX);
+ bus = atolx_range(*toys.optargs, 0, 0x3f);
if (toys.optc==3) {
first = atolx_range(toys.optargs[1], 0, 0x7f);
last = atolx_range(toys.optargs[2], 0, 0x7f);
@@ -207,22 +201,24 @@ void i2cdetect_main(void)
fd = i2c_open(bus, 0, 0);
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n");
- for (row = 0; row <= 0x70; row += 16) {
+ for (row = 0; row < 0x80; row += 16) {
xprintf("%02x:", row & 0xf0);
for (addr = row; addr<row+16; ++addr) {
- if (addr<first || addr>last) printf(" ");
- else {
- if (ioctl(fd, I2C_SLAVE, addr) == -1) {
- if (errno == EBUSY) {
- xprintf(" UU");
- continue;
- }
- perror_exit("ioctl(I2C_SLAVE)");
+ if (addr<first || addr>last) {
+ printf(" ");
+
+ continue;
+ }
+ if (ioctl(fd, I2C_SLAVE, addr) == -1) {
+ if (errno == EBUSY) {
+ xprintf(" UU");
+ continue;
}
- if ((FLAG(r) ? i2c_read_byte(fd, addr, &byte)
- : i2c_quick_write(fd, addr)) == -1) xprintf(" --");
- else xprintf(" %02x", addr);
+ perror_exit("ioctl(I2C_SLAVE)");
}
+ if ((FLAG(r) ? i2c_read_byte(fd, addr, &byte)
+ : i2c_quick_write(fd, addr)) == -1) xprintf(" --");
+ else xprintf(" %02x", addr);
}
putchar('\n');
}
@@ -235,15 +231,15 @@ void i2cdetect_main(void)
void i2cdump_main(void)
{
- int bus = atolx_range(toys.optargs[0], 0, INT_MAX);
- int chip = atolx_range(toys.optargs[1], 0, 0x7f);
- int fd, row, addr, byte;
+ int fd, row, addr, bus = atolx_range(toys.optargs[0], 0, 0x3f),
+ chip = atolx_range(toys.optargs[1], 0, 0x7f);
+ char byte;
confirm("Dump chip 0x%02x on bus %d?", chip, bus);
fd = i2c_open(bus, FLAG(f) ? I2C_SLAVE_FORCE : I2C_SLAVE, chip);
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef\n");
- for (row = 0; row<=0xf0; row += 16) {
+ for (row = 0; row<0x100; row += 16) {
xprintf("%02x:", row & 0xf0);
for (addr = row; addr<row+16; ++addr) {
if (!i2c_read_byte(fd, addr, &byte)) printf(" %02x", byte);
@@ -251,7 +247,7 @@ void i2cdump_main(void)
printf(" XX");
byte = 'X';
}
- toybuf[addr-row] = isprint(byte) ? byte : (byte ? '?' : '.');
+ toybuf[addr-row] = isprint(byte) ? byte : byte ? '?' : '.';
}
printf(" %16.16s\n", toybuf);
}
@@ -263,15 +259,18 @@ void i2cdump_main(void)
void i2cget_main(void)
{
- int bus = atolx_range(toys.optargs[0], 0, INT_MAX);
- int chip = atolx_range(toys.optargs[1], 0, 0x7f);
- int addr = atolx_range(toys.optargs[2], 0, 0xff);
- int fd, byte;
+ int fd, bus = atolx_range(toys.optargs[0], 0, 0x3f),
+ chip = atolx_range(toys.optargs[1], 0, 0x7f),
+ addr = (toys.optc == 3) ? atolx_range(toys.optargs[2], 0, 0xff) : -1;
+ char byte;
confirm("Read register 0x%02x from chip 0x%02x on bus %d?", addr, chip, bus);
fd = i2c_open(bus, FLAG(f) ? I2C_SLAVE_FORCE : I2C_SLAVE, chip);
- if (i2c_read_byte(fd, addr, &byte)==-1) perror_exit("i2c_read_byte");
+ if (toys.optc == 3) {
+ if (i2c_read_byte(fd, addr, &byte)==-1) perror_exit("i2c_read_byte");
+ } else if (read(fd, &byte, 1) != 1) perror_exit("i2c_read");
+
printf("0x%02x\n", byte);
close(fd);
}
@@ -281,11 +280,10 @@ void i2cget_main(void)
void i2cset_main(void)
{
- int bus = atolx_range(toys.optargs[0], 0, INT_MAX);
- int chip = atolx_range(toys.optargs[1], 0, 0x7f);
- int addr = atolx_range(toys.optargs[2], 0, 0xff);
+ int fd, i, bus = atolx_range(toys.optargs[0], 0, 0x3f),
+ chip = atolx_range(toys.optargs[1], 0, 0x7f),
+ addr = atolx_range(toys.optargs[2], 0, 0xff);
char *mode = toys.optargs[toys.optc-1];
- int fd, i;
struct i2c_smbus_ioctl_data ioctl_data;
union i2c_smbus_data data;
@@ -300,13 +298,14 @@ void i2cset_main(void)
} else if (*mode=='i' && toys.optc>=5) {
if (toys.optc-4>I2C_SMBUS_BLOCK_MAX) error_exit("too much data");
ioctl_data.size = I2C_SMBUS_I2C_BLOCK_DATA;
- for (i = 0; i<toys.optc-4; ++i)
- data.block[i+1] = atolx_range(toys.optargs[3+i], 0, 0xff);
data.block[0] = toys.optc-4;
+ for (i = 0; i<toys.optc-4; i++)
+ data.block[i+1] = atolx_range(toys.optargs[3+i], 0, 0xff);
} else help_exit("syntax error");
confirm("Write register 0x%02x from chip 0x%02x on bus %d?", addr, chip, bus);
+ // We open the device read-only and the write command works?
fd = i2c_open(bus, FLAG(f) ? I2C_SLAVE_FORCE : I2C_SLAVE, chip);
ioctl_data.read_write = I2C_SMBUS_WRITE;
ioctl_data.command = addr;