The branch main has been updated by phk:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=63c8d31e4f9bb4800be3247c9962d48257dedc94

commit 63c8d31e4f9bb4800be3247c9962d48257dedc94
Author:     Poul-Henning Kamp <p...@freebsd.org>
AuthorDate: 2021-05-13 10:55:37 +0000
Commit:     Poul-Henning Kamp <p...@freebsd.org>
CommitDate: 2021-05-13 11:58:35 +0000

    Rewrite and simplify the -n argument processing.
---
 usr.sbin/i2c/i2c.8 |  18 ++--
 usr.sbin/i2c/i2c.c | 246 ++++++++++++++++++++++-------------------------------
 2 files changed, 107 insertions(+), 157 deletions(-)

diff --git a/usr.sbin/i2c/i2c.8 b/usr.sbin/i2c/i2c.8
index 352b13157968..92cc62e983aa 100644
--- a/usr.sbin/i2c/i2c.8
+++ b/usr.sbin/i2c/i2c.8
@@ -96,10 +96,9 @@ mode creates control structures describing the transfer and 
submits them
 to the driver as a single complete transaction.
 This mode works on all types of I2C hardware.
 .It Fl n Ar skip_addr
-skip address - address(es) to be skipped during bus scan.
-There are two ways to specify addresses to ignore: by range 'a..b' or
-using selected addresses 'a:b:c'. This option is available only when "-s" is
-used.
+address(es) to be skipped during bus scan.
+One or more addresses ([0x]xx) or ranges of addresses
+([0x]xx-[0x]xx or [0x]xx..[0x]xx) separated by commas or colons.
 .It Fl o Ar offset
 offset within the device for data transfer (hex).
 The default is zero.
@@ -129,15 +128,10 @@ Scan the default bus (/dev/iic0) for devices:
 .Pp
 i2c -s
 .It
-Scan the default bus (/dev/iic0) for devices and skip addresses 0x56 and
-0x45.
+Scan the default bus (/dev/iic0) for devices and skip addresses 
+0x45 to 0x47 (inclusive) and 0x56.
 .Pp
-i2c -s -n 0x56:0x45
-.It
-Scan the default bus (/dev/iic0) for devices and skip address range
-0x34 to 0x56.
-.Pp
-i2c -s -n 0x34..0x56
+i2c -s -n 0x56,45-47
 .It
 Read 8 bytes of data from device at address 0x56 (e.g., an EEPROM):
 .Pp
diff --git a/usr.sbin/i2c/i2c.c b/usr.sbin/i2c/i2c.c
index 9bfa8c801a3e..753ddbf712d3 100644
--- a/usr.sbin/i2c/i2c.c
+++ b/usr.sbin/i2c/i2c.c
@@ -30,6 +30,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <assert.h>
+#include <ctype.h>
 #include <err.h>
 #include <errno.h>
 #include <sysexits.h>
@@ -55,7 +56,7 @@ struct options {
        int             count;
        int             verbose;
        int             binary;
-       char            *skip;
+       const char      *skip;
        int             mode;
        char            dir;
        uint32_t        addr;
@@ -64,11 +65,6 @@ struct options {
        size_t          off_len;
 };
 
-struct skip_range {
-       int     start;
-       int     end;
-};
-
 __dead2 static void
 usage(const char *msg)
 {
@@ -84,169 +80,126 @@ usage(const char *msg)
        exit(EX_USAGE);
 }
 
-static struct skip_range
-skip_get_range(char *skip_addr)
+static void
+parse_skip(const char *skip, char blacklist[128])
 {
-       struct skip_range addr_range;
-       char *token;
-
-       addr_range.start = 0;
-       addr_range.end = 0;
-
-       token = strsep(&skip_addr, "..");
-       if (token) {
-               addr_range.start = strtoul(token, 0, 16);
-               token = strsep(&skip_addr, "..");
-               if ((token != NULL) && !atoi(token)) {
-                       token = strsep(&skip_addr, "..");
-                       if (token)
-                               addr_range.end = strtoul(token, 0, 16);
+       const char *p;
+       unsigned x, y;
+
+       for (p = skip; *p != '\0';) {
+               if (*p == '0' && p[1] == 'x')
+                       p += 2;
+               if (!isxdigit(*p))
+                       usage("Bad -n argument, expected (first) hex-digit");
+               x = digittoint(*p++) << 4;
+               if (!isxdigit(*p))
+                       usage("Bad -n argument, expected (second) hex-digit");
+               x |= digittoint(*p++);
+               if (x == 0 || x > 0x7f)
+                       usage("Bad -n argument, (01..7f)");
+               if (*p == ':' || *p == ',' || *p == '\0') {
+                       blacklist[x] = 1;
+                       if (*p != '\0')
+                               p++;
+                       continue;
                }
+               if (*p == '-') {
+                       p++;
+               } else if (*p == '.' && p[1] == '.') {
+                       p += 2;
+               } else {
+                       usage("Bad -n argument, ([:|,|..|-])");
+               }
+               if (*p == '0' && p[1] == 'x')
+                       p += 2;
+               if (!isxdigit(*p))
+                       usage("Bad -n argument, expected (first) hex-digit");
+               y = digittoint(*p++) << 4;
+               if (!isxdigit(*p))
+                       usage("Bad -n argument, expected (second) hex-digit");
+               y |= digittoint(*p++);
+               if (y == 0 || y > 0x7f)
+                       usage("Bad -n argument, (01..7f)");
+               if (y < x)
+                       usage("Bad -n argument, (end < start)");
+               for (;x <= y; x++)
+                       blacklist[x] = 1;
+               if (*p == ':' || *p == ',')
+                       p++;
        }
-
-       return (addr_range);
-}
-
-/* Parse the string to get hex 7 bits addresses */
-static int
-skip_get_tokens(char *skip_addr, int *sk_addr, int max_index)
-{
-       char *token;
-       int i;
-
-       for (i = 0; i < max_index; i++) {
-               token = strsep(&skip_addr, ":");
-               if (token == NULL)
-                       break;
-               sk_addr[i] = strtoul(token, 0, 16);
-       }
-       return (i);
 }
 
 static int
-scan_bus(const char *dev, int fd, char *skip)
+scan_bus(const char *dev, int fd, const char *skip)
 {
        struct iiccmd cmd;
        struct iic_msg rdmsg;
        struct iic_rdwr_data rdwrdata;
-       struct skip_range addr_range = { 0, 0 };
-       int *tokens = NULL, error, i, idx = 0, j;
-       int len = 0, do_skip = 0, no_range = 1, num_found = 0, use_read_xfer = 
0;
+       int error;
+       unsigned u;
+       int num_found = 0, use_read_xfer;
        uint8_t rdbyte;
+       char blacklist[128];
 
-       if (skip != NULL) {
-               len = strlen(skip);
-               if (strstr(skip, "..") != NULL) {
-                       addr_range = skip_get_range(skip);
-                       no_range = 0;
-               } else {
-                       tokens = (int *)malloc((len / 2 + 1) * sizeof(int));
-                       if (tokens == NULL) {
-                               fprintf(stderr, "Error allocating tokens "
-                                   "buffer\n");
-                               error = -1;
-                               goto out;
-                       }
-                       idx = skip_get_tokens(skip, tokens,
-                           len / 2 + 1);
-               }
+       memset(blacklist, 0, sizeof blacklist);
 
-               if (!no_range && (addr_range.start > addr_range.end)) {
-                       fprintf(stderr, "Skip address out of range\n");
-                       error = -1;
-                       goto out;
-               }
-       }
+       if (skip != NULL)
+               parse_skip(skip, blacklist);
 
-       printf("Scanning I2C devices on %s: ", dev);
+       printf("Scanning I2C devices on %s:", dev);
 
-start_over:
-       if (use_read_xfer) {
-               fprintf(stderr,
-                   "Hardware may not support START/STOP scanning; "
-                   "trying less-reliable read method.\n");
-       }
-
-       for (i = 1; i < 127; i++) {
-
-               if (skip != NULL && ( addr_range.start < addr_range.end)) {
-                       if (i >= addr_range.start && i <= addr_range.end)
+       for (use_read_xfer = 0; use_read_xfer < 2; use_read_xfer++) {
+               for (u = 1; u < 127; u++) {
+                       if (blacklist[u])
                                continue;
 
-               } else if (skip != NULL && no_range) {
-                       assert (tokens != NULL);
-                       for (j = 0; j < idx; j++) {
-                               if (tokens[j] == i) {
-                                       do_skip = 1;
-                                       break;
-                               }
-                       }
-               }
-
-               if (do_skip) {
-                       do_skip = 0;
-                       continue;
-               }
-
-               cmd.slave = i << 1;
-               cmd.last = 1;
-               cmd.count = 0;
-               error = ioctl(fd, I2CRSTCARD, &cmd);
-               if (error) {
-                       fprintf(stderr, "Controller reset failed\n");
-                       goto out;
-               }
-               if (use_read_xfer) {
-                       rdmsg.buf = &rdbyte;
-                       rdmsg.len = 1;
-                       rdmsg.flags = IIC_M_RD;
-                       rdmsg.slave = i << 1;
-                       rdwrdata.msgs = &rdmsg;
-                       rdwrdata.nmsgs = 1;
-                       error = ioctl(fd, I2CRDWR, &rdwrdata);
-               } else {
-                       cmd.slave = i << 1;
+                       cmd.slave = u << 1;
                        cmd.last = 1;
-                       error = ioctl(fd, I2CSTART, &cmd);
-                       if (errno == ENODEV || errno == EOPNOTSUPP) {
-                               /* If START not supported try reading. */
-                               use_read_xfer = 1;
-                               goto start_over;
+                       cmd.count = 0;
+                       error = ioctl(fd, I2CRSTCARD, &cmd);
+                       if (error) {
+                               fprintf(stderr, "Controller reset failed\n");
+                               fprintf(stderr,
+                                   "Error scanning I2C controller (%s): %s\n",
+                                   dev, strerror(errno));
+                               return (EX_NOINPUT);
+                       }
+                       if (use_read_xfer) {
+                               rdmsg.buf = &rdbyte;
+                               rdmsg.len = 1;
+                               rdmsg.flags = IIC_M_RD;
+                               rdmsg.slave = u << 1;
+                               rdwrdata.msgs = &rdmsg;
+                               rdwrdata.nmsgs = 1;
+                               error = ioctl(fd, I2CRDWR, &rdwrdata);
+                       } else {
+                               cmd.slave = u << 1;
+                               cmd.last = 1;
+                               error = ioctl(fd, I2CSTART, &cmd);
+                               if (errno == ENODEV || errno == EOPNOTSUPP)
+                                       break; /* Try reads instead */
+                               (void)ioctl(fd, I2CSTOP);
+                       }
+                       if (error == 0) {
+                               ++num_found;
+                               printf(" %02x", u);
                        }
-                       (void)ioctl(fd, I2CSTOP);
-               }
-               if (error == 0) {
-                       ++num_found;
-                       printf("%02x ", i);
                }
+               if (num_found > 0)
+                       break;
+               fprintf(stderr,
+                   "Hardware may not support START/STOP scanning; "
+                   "trying less-reliable read method.\n");
        }
-
-       /*
-        * If we found nothing, maybe START is not supported and returns a
-        * generic error code such as EIO or ENXIO, so try again using reads.
-        */
-       if (num_found == 0) {
-               if (!use_read_xfer) {
-                       use_read_xfer = 1;
-                       goto start_over;
-               }
+       if (num_found == 0)
                printf("<none found>");
-       }
+
        printf("\n");
 
        error = ioctl(fd, I2CRSTCARD, &cmd);
-out:
-       if (skip != NULL  && no_range)
-               free(tokens);
-       else
-               assert(tokens == NULL);
-
-       if (error) {
-               fprintf(stderr, "Error scanning I2C controller (%s): %s\n",
-                   dev, strerror(errno));
-               return (EX_NOINPUT);
-       } else
-               return (EX_OK);
+       if (error)
+               fprintf(stderr, "Controller reset failed\n");
+       return (EX_OK);
 }
 
 static int
@@ -671,9 +624,12 @@ main(int argc, char** argv)
        while ((ch = getopt(argc, argv, optflags)) != -1) {
                switch(ch) {
                case 'a':
-                       i2c_opt.addr = (strtoul(optarg, 0, 16) << 1);
+                       i2c_opt.addr = strtoul(optarg, 0, 16);
                        if (i2c_opt.addr == 0 && errno == EINVAL)
                                usage("Bad -a argument (hex)");
+                       if (i2c_opt.addr == 0 || i2c_opt.addr > 0x7f)
+                               usage("Bad -a argument (01..7f)");
+                       i2c_opt.addr <<= 1;
                        break;
                case 'f':
                        dev = optarg;
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to