Page MenuHomeFreeBSD

D5470.1775826987.diff
No OneTemporary

Size
9 KB
Referenced Files
None
Subscribers
None

D5470.1775826987.diff

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

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)

Event Timeline