diff options
Diffstat (limited to 'toys/other/i2ctools.c')
-rw-r--r-- | toys/other/i2ctools.c | 131 |
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; |