diff --git a/system/i2c/Makefile b/system/i2c/Makefile index 4bd63918f..f0c1ef6d0 100644 --- a/system/i2c/Makefile +++ b/system/i2c/Makefile @@ -37,7 +37,7 @@ include $(TOPDIR)/Make.defs # I2C tool CSRCS = i2c_bus.c i2c_common.c i2c_dev.c i2c_get.c i2c_set.c i2c_verf.c -CSRCS += i2c_devif.c +CSRCS += i2c_devif.c i2c_dump.c i2c_hexdump.c MAINSRC = i2c_main.c PROGNAME = i2c diff --git a/system/i2c/i2c_dump.c b/system/i2c/i2c_dump.c new file mode 100644 index 000000000..aa6461172 --- /dev/null +++ b/system/i2c/i2c_dump.c @@ -0,0 +1,230 @@ +/**************************************************************************** + * apps/system/i2c/i2c_dump.c + * + * Copyright (C) 2011, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2019 David S. Alessio. All rights reserved. + * Authors: Gregory Nutt + * David S. Alessio + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "i2ctool.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: i2ctool_dump + ****************************************************************************/ + +static int i2ctool_dump(FAR struct i2ctool_s *i2ctool, int fd, uint8_t regaddr, + FAR uint8_t *buf, int nbytes) +{ + struct i2c_msg_s msg[2]; + int ret; + + /* Set up data structures */ + + if (i2ctool->hasregindx) + { + msg[0].frequency = i2ctool->freq; + msg[0].addr = i2ctool->addr; + msg[0].flags = I2C_M_NOSTOP; + msg[0].buffer = ®addr; + msg[0].length = 1; + + msg[1].frequency = i2ctool->freq; + msg[1].addr = i2ctool->addr; + msg[1].flags = I2C_M_READ; + + msg[1].buffer = buf; + msg[1].length = nbytes; + + if (i2ctool->start) + { + ret = i2cdev_transfer(fd, &msg[0], 1); + if (ret== OK) + { + ret = i2cdev_transfer(fd, &msg[1], 1); + } + } + else + { + ret = i2cdev_transfer(fd, msg, 2); + } + } + else + { + /* no register index "-r" has been specified so + * we do a pure read (no write of index) + */ + + msg[0].frequency = i2ctool->freq; + msg[0].addr = i2ctool->addr; + msg[0].flags = I2C_M_READ; + + msg[0].buffer = buf; + msg[0].length = nbytes; + + ret = i2cdev_transfer(fd, msg, 1); + } + + return ret; +} + +/**************************************************************************** + * Name: i2ccmd_dump + ****************************************************************************/ + +int i2ccmd_dump(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv) +{ + FAR char *ptr; + FAR uint8_t *buf; + uint8_t regaddr; + int dumpcnt; + int nargs; + int argndx; + int ret; + int fd; + + /* Parse any command line arguments */ + + for (argndx = 1; argndx < argc; ) + { + /* Break out of the look when the last option has been parsed */ + + ptr = argv[argndx]; + if (*ptr != '-') + { + break; + } + + /* Otherwise, check for common options */ + + nargs = i2ctool_common_args(i2ctool, &argv[argndx]); + if (nargs < 0) + { + return ERROR; + } + + argndx += nargs; + } + + /* There may be one more thing on the command line: The repitition + * count. + */ + + dumpcnt = 1; + if (argndx < argc) + { + dumpcnt = atoi(argv[argndx]); + if (dumpcnt < 1 || dumpcnt > MAX_DUMP_CNT) + { + i2ctool_printf(i2ctool, g_i2cargrange, argv[0]); + return ERROR; + } + + argndx++; + } + + if (argndx != argc) + { + i2ctool_printf(i2ctool, g_i2ctoomanyargs, argv[0]); + return ERROR; + } + + /* Get a handle to the I2C bus */ + + fd = i2cdev_open(i2ctool->bus); + if (fd < 0) + { + i2ctool_printf(i2ctool, "Failed to get bus %d\n", i2ctool->bus); + return ERROR; + } + + regaddr = i2ctool->regaddr; + ret = OK; + + /* allocate read buffer */ + + if (NULL == (buf = calloc(1, MAX_DUMP_CNT))) + { + fprintf(stderr, g_i2ccmdfailed, "dump", errno); + goto errout_with_fildes; + } + + /* Read from the I2C bus */ + + ret = i2ctool_dump(i2ctool, fd, regaddr, buf, dumpcnt); + + /* Display the result */ + + if (ret == OK) + { + i2ctool_printf(i2ctool, "DUMP Bus: %d Addr: %02x Subaddr: ", + i2ctool->bus, i2ctool->addr); + + /* if the index register was set, print it */ + if (i2ctool->hasregindx) + { + i2ctool_printf(i2ctool, "%02x\n", regaddr); + } + else + { + i2ctool_printf(i2ctool, "--\n"); + } + + /* dump the data in hex and ASCII format */ + i2ctool_hexdump(OUTSTREAM(i2ctool), buf, dumpcnt); + } + else + { + i2ctool_printf(i2ctool, g_i2cxfrerror, argv[0], -ret); + } + +/* free read buffer */ +free(buf); + +errout_with_fildes: + (void)close(fd); + return ret; +} + diff --git a/system/i2c/i2c_hexdump.c b/system/i2c/i2c_hexdump.c new file mode 100644 index 000000000..c1be24817 --- /dev/null +++ b/system/i2c/i2c_hexdump.c @@ -0,0 +1,131 @@ + +/**************************************************************************** + * apps/system/i2c/i2c_hexdump.c + * + * Copyright (C) 2005, 2016-2019 David S. Alessio. All rights reserved. + * Author: David S. Alessio + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "i2ctool.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: hexdump_line + ****************************************************************************/ + +static int hexdump_line(FILE *ostream, void *addr, int len) +{ + int i; + uint8_t *p; + + if (len <= 0) + { + return 0; + } + + /* print at most 16 chars */ + if (len > 16) + { + len = 16; + } + + /* print hex */ + for (i = 0, p = addr; i < len; ++i, ++p) + { + if (i % 8 == 0) + { + fputc(' ', ostream); + } + + fprintf(ostream, "%02x ", *p); + } + + /* pad if necessary */ + if (i <= 8) + { + fputc(' ', ostream); + } + + while (i++ < 16) + { + fputs(" ", ostream); + } + + /* print ASCII */ + fputs(" |", ostream); + for (i = 0, p = addr; i < len; ++i, ++p) + { + fputc(isprint(*p) ? *p : '.', ostream); + } + + /* pad if necessary */ + while (i++ < 16) + { + fputc(' ', ostream); + } + + fputs("|\n", ostream); + + return len; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void i2ctool_hexdump(FILE *outstream, void *addr, int len) +{ + int nbytes; + uint8_t *p = addr; + + /* print one line at a time */ + while (len > 0) + { + /* print address */ + fprintf(outstream, "%08x ", p - (uint8_t *) addr); + + /* print one line of data */ + nbytes = hexdump_line(outstream, p, len); + len -= nbytes; + p += nbytes; + } +} diff --git a/system/i2c/i2c_main.c b/system/i2c/i2c_main.c index 8ee550f37..4e09f460c 100644 --- a/system/i2c/i2c_main.c +++ b/system/i2c/i2c_main.c @@ -71,6 +71,7 @@ static const struct cmdmap_s g_i2ccmds[] = { "bus", i2ccmd_bus, "List busses ", NULL }, { "dev", i2ccmd_dev, "List devices ", "[OPTIONS] " }, { "get", i2ccmd_get, "Read register ", "[OPTIONS] []" }, + { "dump", i2ccmd_dump, "Dump register ", "[OPTIONS] []" }, { "help", i2ccmd_help, "Show help ", NULL }, { "set", i2ccmd_set, "Write register", "[OPTIONS] []" }, { "verf", i2ccmd_verf, "Verify access ", "[OPTIONS] [] []" }, diff --git a/system/i2c/i2ctool.h b/system/i2c/i2ctool.h index 415a3f35f..a8873e95d 100644 --- a/system/i2c/i2ctool.h +++ b/system/i2c/i2ctool.h @@ -95,6 +95,10 @@ #define MAX_ARGUMENTS 12 +/* Maximum number of bytes to dump */ + +#define MAX_DUMP_CNT 256 + /* Maximum size of one command line */ #define MAX_LINELEN 80 @@ -181,12 +185,14 @@ extern const char g_i2cxfrerror[]; ssize_t i2ctool_write(FAR struct i2ctool_s *i2ctool, FAR const void *buffer, size_t nbytes); int i2ctool_printf(FAR struct i2ctool_s *i2ctool, const char *fmt, ...); void i2ctool_flush(FAR struct i2ctool_s *i2ctool); +void i2ctool_hexdump(FILE *outstream, void *addr, int len); /* Command handlers */ int i2ccmd_bus(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); int i2ccmd_dev(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); int i2ccmd_get(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); +int i2ccmd_dump(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); int i2ccmd_set(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv); int i2ccmd_verf(FAR struct i2ctool_s *i2ctool, int argc, FAR char **argv);