FreeBSD Bugzilla – Attachment 158475 Details for
Bug 198817
[PATCH] Update i2c(8) to use the I2CRDRW ioctl
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
i2c_patch_3
patch_i2c_3.diff (text/plain), 9.63 KB, created by
Emmanuel Vadot
on 2015-07-07 07:31:18 UTC
(
hide
)
Description:
i2c_patch_3
Filename:
MIME Type:
Creator:
Emmanuel Vadot
Created:
2015-07-07 07:31:18 UTC
Size:
9.63 KB
patch
obsolete
>diff --git a/usr.sbin/i2c/i2c.8 b/usr.sbin/i2c/i2c.8 >index 27f7621..57748e4 100644 >--- a/usr.sbin/i2c/i2c.8 >+++ b/usr.sbin/i2c/i2c.8 >@@ -1,5 +1,6 @@ > .\" > .\" Copyright (C) 2008-2009 Semihalf, Michal Hajduk and Bartlomiej Sieka >+.\" Copyright (C) 2015 Emmanuel Vadot <manu@bidouilliste.com> > .\" All rights reserved. > .\" > .\" Redistribution and use in source and binary forms, with or without >@@ -25,7 +26,7 @@ > .\" > .\" $FreeBSD$ > .\" >-.Dd January 23, 2009 >+.Dd July 5, 2015 > .Dt I2C 8 > .Os > .Sh NAME >@@ -33,7 +34,7 @@ > .Nd test I2C bus and slave devices > .Sh SYNOPSIS > .Nm >-.Cm -a Ar address >+.Cm -a|-A Ar address > .Op Fl f Ar device > .Op Fl d Ar r|w > .Op Fl w Ar 0|8|16 >@@ -41,6 +42,7 @@ > .Op Fl c Ar count > .Op Fl m Ar ss|rs|no > .Op Fl b >+.Op Fl x > .Op Fl v > .Nm > .Cm -s >@@ -62,6 +64,8 @@ The options are as follows: > .Bl -tag -width ".Fl d Ar direction" > .It Fl a Ar address > 7-bit address on the I2C device to operate on (hex). >+.It Fl A Ar address >+8-bit address on the I2C device to operate on (hex). > .It Fl b > binary mode - when performing a read operation, the data read from the device > is output in binary format on stdout; when doing a write, the binary data to >@@ -87,6 +91,20 @@ offset within the device for data transfer (hex). > reset the controller. > .It Fl s > scan the bus for devices. >+It outputs a table of all addresses. The content of each cell can have those meanings: >+.Bl -bullet >+.It >+"--" No chip answered >+.It >+"UU" Chip is in use by a driver >+.It >+"XX" The address was skipped (see -n) >+.It >+An 7-bit address if a chip was found. >+.El >+.It Fl x >+Use the I2CRDRW ioctl instead of the I2CREAD/I2CWRITE ones. >+Some newer drivers only support this method. > .It Fl v > be verbose. > .It Fl w Ar 0|8|16 >diff --git a/usr.sbin/i2c/i2c.c b/usr.sbin/i2c/i2c.c >index 920dda2..9e3844f 100644 >--- a/usr.sbin/i2c/i2c.c >+++ b/usr.sbin/i2c/i2c.c >@@ -1,5 +1,6 @@ > /*- > * Copyright (C) 2008-2009 Semihalf, Michal Hajduk and Bartlomiej Sieka >+ * Copyright (C) 2015 Emmanuel Vadot <manu@bidouilliste.com> > * All rights reserved. > * > * Redistribution and use in source and binary forms, with or without >@@ -57,6 +58,7 @@ struct options { > int reset; > int mode; > char dir; >+ char rdrw; > uint32_t addr; > uint32_t off; > }; >@@ -71,7 +73,7 @@ usage(void) > { > > fprintf(stderr, "usage: %s -a addr [-f device] [-d [r|w]] [-o offset] " >- "[-w [0|8|16]] [-c count] [-m [ss|rs|no]] [-b] [-v]\n", >+ "[-w [0|8|16]] [-c count] [-m [ss|rs|no]] [-b] [-x] [-v]\n", > getprogname()); > fprintf(stderr, " %s -s [-f device] [-n skip_addr] -v\n", > getprogname()); >@@ -119,11 +121,13 @@ skip_get_tokens(char *skip_addr, int *sk_addr, int max_index) > } > > static int >-scan_bus(struct iiccmd cmd, char *dev, int skip, char *skip_addr) >+scan_bus(struct iiccmd cmd, char rdrw, char *dev, int skip, char *skip_addr) > { >+ struct iic_rdwr_data msg; > struct skip_range addr_range = { 0, 0 }; >- int *tokens, fd, error, i, index, j; >- int len = 0, do_skip = 0, no_range = 1; >+ int *tokens, fd, error, index, i; >+ int len = 0, no_range = 1, row, col, addr, result; >+ char buf = 0; > > fd = open(dev, O_RDWR); > if (fd == -1) { >@@ -156,51 +160,86 @@ scan_bus(struct iiccmd cmd, char *dev, int skip, char *skip_addr) > } > } > >- printf("Scanning I2C devices on %s: ", dev); >- for (i = 1; i < 127; i++) { >- >- if (skip && ( addr_range.start < addr_range.end)) { >- if (i >= addr_range.start && i <= addr_range.end) >- continue; >+ msg.nmsgs = 1; >+ if ((msg.msgs = calloc(1, sizeof(struct iic_msg))) == NULL) >+ errx(1, "%s", strerror(errno)); >+ msg.msgs->buf = &buf; >+ msg.msgs->len = 1; >+ msg.msgs->flags = IIC_M_RD; >+ >+ printf("Scanning I2C devices on %s:\n", dev); >+ printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); >+ for (row = 1; row < 8; row++) { >+ printf("%02X:", row * 16); >+ for (col = 0; col < 16; col++) { >+ addr = (row * 16 + col); >+ result = 0; >+ >+ if (skip && ( addr_range.start < addr_range.end)) { >+ if (addr >= addr_range.start && addr <= addr_range.end) { >+ printf(" XX"); >+ continue; >+ } > >- } else if (skip && no_range) >- for (j = 0; j < index; j++) { >- if (tokens[j] == i) { >- do_skip = 1; >- break; >+ } else if (skip && no_range) >+ for (i = 0; i < index; i++) { >+ if (tokens[i] == (row * 16) + col) { >+ printf(" XX"); >+ continue; >+ } > } >- } > >- if (do_skip) { >- do_skip = 0; >- continue; >+ if (rdrw) { >+ msg.msgs->slave = addr << 1; >+ if (ioctl(fd, I2CRDWR, &msg) < 0) >+ result = errno; >+ } else { >+ cmd.slave = addr << 1; >+ cmd.last = 1; >+ cmd.count = 0; >+ if (ioctl(fd, I2CRSTCARD, &cmd) < 0) >+ goto out; >+ >+ cmd.slave = addr << 1; >+ cmd.last = 1; >+ if (ioctl(fd, I2CSTART, &cmd) < 0) >+ result = errno; >+ cmd.slave = addr << 1; >+ cmd.last = 1; >+ ioctl(fd, I2CSTOP, &cmd); >+ } >+ switch (result) { >+ case 0: >+ printf(" %02X", addr); >+ break; >+ case EIO: >+ case ENXIO: >+ case ENOENT: >+ printf(" --"); >+ break; >+ case EBUSY: >+ printf(" UU"); >+ break; >+ default: >+ printf(" "); >+ break; >+ } > } >- >- cmd.slave = i << 1; >- cmd.last = 1; >- cmd.count = 0; >- error = ioctl(fd, I2CRSTCARD, &cmd); >- if (error) >- goto out; >- >- cmd.slave = i << 1; >- cmd.last = 1; >- error = ioctl(fd, I2CSTART, &cmd); >- if (!error) >- printf("%x ", i); >- cmd.slave = i << 1; >- cmd.last = 1; >- error = ioctl(fd, I2CSTOP, &cmd); >+ printf("\n"); > } > printf("\n"); > >- error = ioctl(fd, I2CRSTCARD, &cmd); >+ if (!rdrw) >+ error = ioctl(fd, I2CRSTCARD, &cmd); > out: > close(fd); > if (skip && no_range) > free(tokens); > >- if (error) { >+ if (rdrw) >+ free(msg.msgs); >+ >+ if (!rdrw && error) { > fprintf(stderr, "Error scanning I2C controller (%s): %s\n", > dev, strerror(errno)); > return (EX_NOINPUT); >@@ -465,6 +504,87 @@ err2: > return (1); > } > >+static int >+i2c_rdrw(char *dev, struct options i2c_opt, char *i2c_buf) >+{ >+ struct iic_rdwr_data msgs; >+ int fd, error, i; >+ char *err_msg, ch; >+ >+ if (i2c_opt.dir == 'w') { >+ if (i2c_opt.verbose && !i2c_opt.binary) >+ fprintf(stderr, "Enter %u bytes of data: ", i2c_opt.count); >+ >+ for (i = 0; i < i2c_opt.count; i++) { >+ ch = getchar(); >+ if (ch == EOF) { >+ free(i2c_buf); >+ err(1, "not enough data, exiting\n"); >+ } >+ i2c_buf[i] = ch; >+ } >+ } >+ >+ fd = open(dev, O_RDWR); >+ if (fd == -1) >+ err(1, "open failed"); >+ >+ msgs.nmsgs = 1; >+ if (i2c_opt.width) { >+ msgs.nmsgs = 2; >+ msgs.msgs = calloc(2, sizeof(struct iic_msg)); >+ msgs.msgs[0].slave = i2c_opt.addr; >+ msgs.msgs[0].len = i2c_opt.width / 8; >+ >+ if ((msgs.msgs[0].buf = calloc(msgs.msgs[0].len, sizeof(uint8_t))) == NULL) { >+ err_msg = "can't malloc\n"; >+ goto err; >+ } >+ if (msgs.msgs[0].len == 1) >+ msgs.msgs[0].buf[0] = i2c_opt.off & 0xff; >+ else if (msgs.msgs[0].len == 2) { >+ msgs.msgs[0].buf[0] = (i2c_opt.off >> 8) & 0xff; >+ msgs.msgs[0].buf[1] = i2c_opt.off & 0xff; >+ } >+ if (msgs.msgs[0].buf == NULL) { >+ err_msg = "error: offset malloc"; >+ goto err; >+ } >+ >+ msgs.msgs[0].flags = IIC_M_WR; >+ if (i2c_opt.mode == I2C_MODE_REPEATED_START || i2c_opt.mode == I2C_MODE_NONE) >+ msgs.msgs[0].flags |= IIC_M_NOSTOP; >+ } >+ >+ msgs.msgs[msgs.nmsgs - 1].slave = i2c_opt.addr; >+ msgs.msgs[msgs.nmsgs - 1].len = i2c_opt.count; >+ msgs.msgs[msgs.nmsgs - 1].buf = i2c_buf; >+ >+ if (i2c_opt.dir == 'r') >+ msgs.msgs[msgs.nmsgs - 1].flags = IIC_M_RD; >+ else >+ msgs.msgs[msgs.nmsgs - 1].flags = IIC_M_WR; >+ >+ if (i2c_opt.mode == I2C_MODE_NONE) >+ msgs.msgs[msgs.nmsgs - 1].flags |= IIC_M_NOSTART; >+ >+ error = ioctl(fd, I2CRDWR, &msgs); >+ if (error == -1) { >+ err_msg = "error sending i2c frame\n"; >+ goto err; >+ } >+ >+ close(fd); >+ return (0); >+ >+err: >+ if (err_msg) >+ fprintf(stderr, "%s", err_msg); >+ >+ close(fd); >+ return (1); >+} >+ > int > main(int argc, char** argv) > { >@@ -493,11 +613,15 @@ main(int argc, char** argv) > i2c_opt.skip = 0; /* scan all addresses */ > i2c_opt.reset = 0; /* no bus reset */ > i2c_opt.mode = I2C_MODE_NOTSET; >+ i2c_opt.rdrw = 0; /* Use read/write by default */ > >- while ((ch = getopt(argc, argv, "a:f:d:o:w:c:m:n:sbvrh")) != -1) { >+ while ((ch = getopt(argc, argv, "a:A:f:d:o:w:c:m:n:sbvrhx")) != -1) { > switch(ch) { > case 'a': >- i2c_opt.addr = (strtoul(optarg, 0, 16) << 1); >+ case 'A': >+ if (i2c_opt.addr_set) >+ usage(); >+ i2c_opt.addr = ch == 'a' ? (strtoul(optarg, 0, 16) << 1) : strtoul(optarg, 0, 16); > if (i2c_opt.addr == 0 && errno == EINVAL) > i2c_opt.addr_set = 0; > else >@@ -546,6 +670,9 @@ main(int argc, char** argv) > case 'r': > i2c_opt.reset = 1; > break; >+ case 'x': >+ i2c_opt.rdrw = 1; >+ break; > case 'h': > default: > usage(); >@@ -581,11 +708,11 @@ main(int argc, char** argv) > if (i2c_opt.verbose) > fprintf(stderr, "dev: %s, addr: 0x%x, r/w: %c, " > "offset: 0x%02x, width: %u, count: %u\n", dev, >- i2c_opt.addr >> 1, i2c_opt.dir, i2c_opt.off, >+ i2c_opt.addr, i2c_opt.dir, i2c_opt.off, > i2c_opt.width, i2c_opt.count); > > if (i2c_opt.scan) >- exit(scan_bus(cmd, dev, i2c_opt.skip, skip_addr)); >+ exit(scan_bus(cmd, i2c_opt.rdrw, dev, i2c_opt.skip, skip_addr)); > > if (i2c_opt.reset) > exit(reset_bus(cmd, dev)); >@@ -594,19 +721,18 @@ main(int argc, char** argv) > if (i2c_buf == NULL) > err(1, "data malloc"); > >- if (i2c_opt.dir == 'w') { >- error = i2c_write(dev, i2c_opt, i2c_buf); >- if (error) { >- free(i2c_buf); >- return (1); >+ if (i2c_opt.rdrw == 1) { >+ error = i2c_rdrw(dev, i2c_opt, i2c_buf); >+ } else { >+ if (i2c_opt.dir == 'w') { >+ error = i2c_write(dev, i2c_opt, i2c_buf); >+ } else if (i2c_opt.dir == 'r') { >+ error = i2c_read(dev, i2c_opt, i2c_buf); > } > } >- if (i2c_opt.dir == 'r') { >- error = i2c_read(dev, i2c_opt, i2c_buf); >- if (error) { >- free(i2c_buf); >- return (1); >- } >+ if (error) { >+ free(i2c_buf); >+ return (1); > } > > if (i2c_opt.verbose)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 198817
:
154684
|
158368
| 158475