Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144620356
D5470.1775826987.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D5470.1775826987.diff
View Options
Index: usr.sbin/i2c/i2c.8
===================================================================
--- usr.sbin/i2c/i2c.8
+++ usr.sbin/i2c/i2c.8
@@ -1,5 +1,6 @@
.\"
.\" Copyright (C) 2008-2009 Semihalf, Michal Hajduk and Bartlomiej Sieka
+.\" Copyright (C) 2015-2016 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 March 18, 2016
.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
@@ -61,7 +63,9 @@
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).
+7-bit hex address of the I2C device.
+.It Fl A Ar address
+8-bit hex address of the I2C device.
.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
@@ -86,7 +90,21 @@
.It Fl r
reset the controller.
.It Fl s
-scan the bus for devices.
+scan the bus for devices and print a table of all addresses.
+The content of each cell can have these 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
+A 7-bit address of a chip.
+.El
+.It Fl x
+Use the I2CRDRW ioctl instead of I2CREAD/I2CWRITE.
+Some newer drivers only support this method.
.It Fl v
be verbose.
.It Fl w Ar 0|8|16
Index: usr.sbin/i2c/i2c.c
===================================================================
--- usr.sbin/i2c/i2c.c
+++ 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 @@
int reset;
int mode;
char dir;
+ char rdrw;
uint32_t addr;
uint32_t off;
};
@@ -71,7 +73,7 @@
{
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 @@
}
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 @@
}
}
- 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);
@@ -516,6 +555,87 @@
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)
{
@@ -544,11 +664,15 @@
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
@@ -597,6 +721,9 @@
case 'r':
i2c_opt.reset = 1;
break;
+ case 'x':
+ i2c_opt.rdrw = 1;
+ break;
case 'h':
default:
usage();
@@ -632,11 +759,11 @@
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));
@@ -645,19 +772,18 @@
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)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 10, 1:16 PM (7 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28316063
Default Alt Text
D5470.1775826987.diff (9 KB)
Attached To
Mode
D5470: i2c(8) Support for I2CRDRW and change scan output
Attached
Detach File
Event Timeline
Log In to Comment