i2cdump: code rework
Split i2cdump_main() into shorter functions. Simplify the code a bit. Make block an array of ints so that we can store negative results of read functions (fixes a bug found by Denys Vlasenko). Signed-off-by: Bartosz Golaszewski <bartekgola@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
2204472497
commit
aeb11a9496
@ -816,6 +816,163 @@ int i2cset_main(int argc, char **argv)
|
|||||||
#endif /* ENABLE_I2CSET */
|
#endif /* ENABLE_I2CSET */
|
||||||
|
|
||||||
#if ENABLE_I2CDUMP
|
#if ENABLE_I2CDUMP
|
||||||
|
static int read_block_data(int buf_fd, int mode, int *block)
|
||||||
|
{
|
||||||
|
uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2C_MAX_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;
|
||||||
|
} else {
|
||||||
|
for (res = 0; res < I2C_MAX_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 (res >= I2C_MAX_REGS)
|
||||||
|
res = I2C_MAX_REGS;
|
||||||
|
|
||||||
|
for (i = 0; i < res; i++)
|
||||||
|
block[i] = cblock[i];
|
||||||
|
|
||||||
|
if (mode != I2C_SMBUS_BLOCK_DATA)
|
||||||
|
for (i = res; i < I2C_MAX_REGS; i++)
|
||||||
|
block[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return blen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dump all but word data. */
|
||||||
|
static void dump_data(int bus_fd, int mode, unsigned first,
|
||||||
|
unsigned last, int *block, int blen)
|
||||||
|
{
|
||||||
|
int i, j, res;
|
||||||
|
|
||||||
|
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"
|
||||||
|
" 0123456789abcdef\n");
|
||||||
|
|
||||||
|
for (i = 0; i < I2C_MAX_REGS; i += 0x10) {
|
||||||
|
if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen)
|
||||||
|
break;
|
||||||
|
if (i/16 < first/16)
|
||||||
|
continue;
|
||||||
|
if (i/16 > last/16)
|
||||||
|
break;
|
||||||
|
|
||||||
|
printf("%02x: ", i);
|
||||||
|
for (j = 0; j < 16; j++) {
|
||||||
|
fflush_all();
|
||||||
|
/* Skip unwanted registers */
|
||||||
|
if (i+j < first || i+j > last) {
|
||||||
|
printf(" ");
|
||||||
|
if (mode == I2C_SMBUS_WORD_DATA) {
|
||||||
|
printf(" ");
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case I2C_SMBUS_BYTE_DATA:
|
||||||
|
res = i2c_smbus_read_byte_data(bus_fd, i+j);
|
||||||
|
block[i+j] = res;
|
||||||
|
break;
|
||||||
|
case I2C_SMBUS_WORD_DATA:
|
||||||
|
res = i2c_smbus_read_word_data(bus_fd, i+j);
|
||||||
|
if (res < 0) {
|
||||||
|
block[i+j] = res;
|
||||||
|
block[i+j+1] = res;
|
||||||
|
} else {
|
||||||
|
block[i+j] = res & 0xff;
|
||||||
|
block[i+j+1] = res >> 8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case I2C_SMBUS_BYTE:
|
||||||
|
res = i2c_smbus_read_byte(bus_fd);
|
||||||
|
block[i+j] = res;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
res = block[i+j];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == I2C_SMBUS_BLOCK_DATA &&
|
||||||
|
i+j >= blen) {
|
||||||
|
printf(" ");
|
||||||
|
} else if (res < 0) {
|
||||||
|
printf("XX ");
|
||||||
|
if (mode == I2C_SMBUS_WORD_DATA)
|
||||||
|
printf("XX ");
|
||||||
|
} else {
|
||||||
|
printf("%02x ", block[i+j]);
|
||||||
|
if (mode == I2C_SMBUS_WORD_DATA)
|
||||||
|
printf("%02x ", block[i+j+1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == I2C_SMBUS_WORD_DATA)
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
printf(" ");
|
||||||
|
|
||||||
|
for (j = 0; j < 16; j++) {
|
||||||
|
if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen)
|
||||||
|
break;
|
||||||
|
/* Skip unwanted registers */
|
||||||
|
if (i+j < first || i+j > last) {
|
||||||
|
printf(" ");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = block[i+j];
|
||||||
|
if (res < 0) {
|
||||||
|
printf("X");
|
||||||
|
} else if (res == 0x00 || res == 0xff) {
|
||||||
|
printf(".");
|
||||||
|
} else if (res < 32 || res >= 127) {
|
||||||
|
printf("?");
|
||||||
|
} else {
|
||||||
|
printf("%c", res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_word_data(int bus_fd, unsigned first, unsigned last)
|
||||||
|
{
|
||||||
|
int i, j, rv;
|
||||||
|
|
||||||
|
/* Word data. */
|
||||||
|
printf(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f\n");
|
||||||
|
for (i = 0; i < 256; i += 8) {
|
||||||
|
if (i/8 < first/8)
|
||||||
|
continue;
|
||||||
|
if (i/8 > last/8)
|
||||||
|
break;
|
||||||
|
|
||||||
|
printf("%02x: ", i);
|
||||||
|
for (j = 0; j < 8; j++) {
|
||||||
|
/* Skip unwanted registers. */
|
||||||
|
if (i+j < first || i+j > last) {
|
||||||
|
printf(" ");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = i2c_smbus_read_word_data(bus_fd, i+j);
|
||||||
|
if (rv < 0)
|
||||||
|
printf("XXXX ");
|
||||||
|
else
|
||||||
|
printf("%04x ", rv & 0xffff);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//usage:#define i2cdump_trivial_usage
|
//usage:#define i2cdump_trivial_usage
|
||||||
//usage: "[-f] [-r FIRST-LAST] [-y] BUS ADDR [MODE]"
|
//usage: "[-f] [-r FIRST-LAST] [-y] BUS ADDR [MODE]"
|
||||||
//usage:#define i2cdump_full_usage "\n\n"
|
//usage:#define i2cdump_full_usage "\n\n"
|
||||||
@ -842,12 +999,10 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
const char *const optstr = "fyr:";
|
const char *const optstr = "fyr:";
|
||||||
|
|
||||||
int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0;
|
int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0;
|
||||||
unsigned first = 0x00, last = 0xff;
|
unsigned first = 0x00, last = 0xff, opts;
|
||||||
int fd, i, j, res, blen = 0, tmp;
|
int *block = (int *)bb_common_bufsiz1;
|
||||||
unsigned char cblock[I2C_SMBUS_BLOCK_MAX + I2C_MAX_REGS];
|
|
||||||
unsigned char block[I2C_SMBUS_BLOCK_MAX];
|
|
||||||
char *opt_r_str, *dash;
|
char *opt_r_str, *dash;
|
||||||
unsigned opts;
|
int fd, res, blen;
|
||||||
|
|
||||||
opt_complementary = "-2:?3"; /* from 2 to 3 args */
|
opt_complementary = "-2:?3"; /* from 2 to 3 args */
|
||||||
opts = getopt32(argv, optstr, &opt_r_str);
|
opts = getopt32(argv, optstr, &opt_r_str);
|
||||||
@ -858,7 +1013,7 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
|
|
||||||
if (argv[2]) {
|
if (argv[2]) {
|
||||||
switch (argv[2][0]) {
|
switch (argv[2][0]) {
|
||||||
case 'b': /* Already set */ break;
|
case 'b': /* Already set. */ break;
|
||||||
case 'c': mode = I2C_SMBUS_BYTE; break;
|
case 'c': mode = I2C_SMBUS_BYTE; break;
|
||||||
case 'w': mode = I2C_SMBUS_WORD_DATA; break;
|
case 'w': mode = I2C_SMBUS_WORD_DATA; break;
|
||||||
case 'W':
|
case 'W':
|
||||||
@ -887,7 +1042,7 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
bb_error_msg_and_die("invalid range");
|
bb_error_msg_and_die("invalid range");
|
||||||
last = xstrtou_range(++dash, 0, first, 0xff);
|
last = xstrtou_range(++dash, 0, first, 0xff);
|
||||||
|
|
||||||
/* Range is not available for every mode */
|
/* Range is not available for every mode. */
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case I2C_SMBUS_BYTE:
|
case I2C_SMBUS_BYTE:
|
||||||
case I2C_SMBUS_BYTE_DATA:
|
case I2C_SMBUS_BYTE_DATA:
|
||||||
@ -912,156 +1067,19 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
if (!(opts & opt_y))
|
if (!(opts & opt_y))
|
||||||
confirm_action(bus_addr, mode, -1 /* data_addr */, pec);
|
confirm_action(bus_addr, mode, -1 /* data_addr */, pec);
|
||||||
|
|
||||||
/* All but word data */
|
/* All but word data. */
|
||||||
if (mode != I2C_SMBUS_WORD_DATA || even) {
|
if (mode != I2C_SMBUS_WORD_DATA || even) {
|
||||||
/*
|
blen = read_block_data(fd, mode, block);
|
||||||
* FIXME This section has been ported from upstream i2cdump.
|
|
||||||
* It has been reworked a bit but is still pretty spaghetti
|
|
||||||
* and needs splitting into several functions.
|
|
||||||
*/
|
|
||||||
if (mode == I2C_SMBUS_BLOCK_DATA ||
|
|
||||||
mode == I2C_SMBUS_I2C_BLOCK_DATA) {
|
|
||||||
res = i2c_smbus_read_block_data(fd, 0, cblock);
|
|
||||||
blen = res;
|
|
||||||
} else {
|
|
||||||
for (res = 0; res < I2C_MAX_REGS; res += tmp) {
|
|
||||||
tmp = i2c_smbus_read_i2c_block_data(
|
|
||||||
fd, res, I2C_SMBUS_BLOCK_MAX,
|
|
||||||
cblock + res);
|
|
||||||
if (tmp < 0) {
|
|
||||||
bb_error_msg_and_die(
|
|
||||||
"block read failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res >= I2C_MAX_REGS)
|
|
||||||
res = I2C_MAX_REGS;
|
|
||||||
for (i = 0; i < res; i++)
|
|
||||||
block[i] = cblock[i];
|
|
||||||
if (mode != I2C_SMBUS_BLOCK_DATA)
|
|
||||||
for (i = res; i < I2C_MAX_REGS; i++)
|
|
||||||
cblock[i] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == I2C_SMBUS_BYTE) {
|
if (mode == I2C_SMBUS_BYTE) {
|
||||||
res = i2c_smbus_write_byte(fd, first);
|
res = i2c_smbus_write_byte(fd, first);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
bb_perror_msg_and_die(
|
bb_perror_msg_and_die("write start address");
|
||||||
"write start address failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f"
|
dump_data(fd, mode, first, last, block, blen);
|
||||||
" 0123456789abcdef\n");
|
|
||||||
|
|
||||||
for (i = 0; i < I2C_MAX_REGS; i += 0x10) {
|
|
||||||
if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen)
|
|
||||||
break;
|
|
||||||
if (i/16 < first/16)
|
|
||||||
continue;
|
|
||||||
if (i/16 > last/16)
|
|
||||||
break;
|
|
||||||
|
|
||||||
printf("%02x: ", i);
|
|
||||||
for (j = 0; j < 16; j++) {
|
|
||||||
fflush_all();
|
|
||||||
/* Skip unwanted registers */
|
|
||||||
if (i+j < first || i+j > last) {
|
|
||||||
printf(" ");
|
|
||||||
if (mode == I2C_SMBUS_WORD_DATA) {
|
|
||||||
printf(" ");
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case I2C_SMBUS_BYTE_DATA:
|
|
||||||
res = i2c_smbus_read_byte_data(fd, i+j);
|
|
||||||
block[i+j] = res;
|
|
||||||
break;
|
|
||||||
case I2C_SMBUS_WORD_DATA:
|
|
||||||
res = i2c_smbus_read_word_data(fd, i+j);
|
|
||||||
if (res < 0) {
|
|
||||||
block[i+j] = res;
|
|
||||||
block[i+j+1] = res;
|
|
||||||
} else {
|
|
||||||
block[i+j] = res & 0xff;
|
|
||||||
block[i+j+1] = res >> 8;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case I2C_SMBUS_BYTE:
|
|
||||||
res = i2c_smbus_read_byte(fd);
|
|
||||||
block[i+j] = res;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
res = block[i+j];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == I2C_SMBUS_BLOCK_DATA &&
|
|
||||||
i+j >= blen) {
|
|
||||||
printf(" ");
|
|
||||||
} else if (res < 0) {
|
|
||||||
printf("XX ");
|
|
||||||
if (mode == I2C_SMBUS_WORD_DATA)
|
|
||||||
printf("XX ");
|
|
||||||
} else {
|
|
||||||
printf("%02x ", block[i+j]);
|
|
||||||
if (mode == I2C_SMBUS_WORD_DATA)
|
|
||||||
printf("%02x ", block[i+j+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == I2C_SMBUS_WORD_DATA)
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
printf(" ");
|
|
||||||
|
|
||||||
for (j = 0; j < 16; j++) {
|
|
||||||
if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen)
|
|
||||||
break;
|
|
||||||
/* Skip unwanted registers */
|
|
||||||
if (i+j < first || i+j > last) {
|
|
||||||
printf(" ");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = block[i+j];
|
|
||||||
if (res < 0) {
|
|
||||||
//FIXME: impossible, block[] is uchar[]
|
|
||||||
printf("X");
|
|
||||||
} else if (res == 0x00 || res == 0xff) {
|
|
||||||
printf(".");
|
|
||||||
} else if (res < 32 || res >= 127) {
|
|
||||||
printf("?");
|
|
||||||
} else {
|
|
||||||
printf("%c", res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* Word data. */
|
dump_word_data(fd, first, last);
|
||||||
printf(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f\n");
|
|
||||||
for (i = 0; i < 256; i += 8) {
|
|
||||||
if (i/8 < first/8)
|
|
||||||
continue;
|
|
||||||
if (i/8 > last/8)
|
|
||||||
break;
|
|
||||||
|
|
||||||
printf("%02x: ", i);
|
|
||||||
for (j = 0; j < 8; j++) {
|
|
||||||
/* Skip unwanted registers. */
|
|
||||||
if (i+j < first || i+j > last) {
|
|
||||||
printf(" ");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = i2c_smbus_read_word_data(fd, i+j);
|
|
||||||
if (res < 0)
|
|
||||||
printf("XXXX ");
|
|
||||||
else
|
|
||||||
printf("%04x ", res & 0xffff);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user