From owner-svn-src-all@freebsd.org Tue Sep 15 11:21:17 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id AED13A046AA; Tue, 15 Sep 2015 11:21:17 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9FA6F144D; Tue, 15 Sep 2015 11:21:17 +0000 (UTC) (envelope-from zbb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t8FBLHEG035647; Tue, 15 Sep 2015 11:21:17 GMT (envelope-from zbb@FreeBSD.org) Received: (from zbb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t8FBLH1w035646; Tue, 15 Sep 2015 11:21:17 GMT (envelope-from zbb@FreeBSD.org) Message-Id: <201509151121.t8FBLH1w035646@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: zbb set sender to zbb@FreeBSD.org using -f From: Zbigniew Bodek Date: Tue, 15 Sep 2015 11:21:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r287820 - head/usr.sbin/i2c X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 Sep 2015 11:21:17 -0000 Author: zbb Date: Tue Sep 15 11:21:16 2015 New Revision: 287820 URL: https://svnweb.freebsd.org/changeset/base/287820 Log: Perform I2C transmission in a single burst when mode is "none" or not set Some more automated I2C controllers cannot explicitly create START/STOP/etc. conditions on the bus. Instead, the correct condition is set automatically according to the pending transfer status. This particular behavior can cause trouble if some I2C slave requires sending address offset within the chip followed by the actual data or command. In that case we cannot assume that the driver will not STOP immediately after sending offset. To avoid that, do not split offset transfer from data transfer for default transmission modes and do exactly that if requested in command line (stop-start and repeated-start modes). This more generic approach should cover special cases like the one described. Reviewed by: imp Submitted by: Marcin Mazurek Obtained from: Semihalf Modified: head/usr.sbin/i2c/i2c.c Modified: head/usr.sbin/i2c/i2c.c ============================================================================== --- head/usr.sbin/i2c/i2c.c Tue Sep 15 10:57:16 2015 (r287819) +++ head/usr.sbin/i2c/i2c.c Tue Sep 15 11:21:16 2015 (r287820) @@ -280,9 +280,6 @@ i2c_write(char *dev, struct options i2c_ err(1, "open failed"); } - /* - * Write offset where the data will go - */ cmd.slave = i2c_opt.addr; error = ioctl(fd, I2CSTART, &cmd); if (error == -1) { @@ -297,20 +294,24 @@ i2c_write(char *dev, struct options i2c_ err_msg = "error: offset malloc"; goto err1; } + } - cmd.count = bufsize; - cmd.buf = buf; - error = ioctl(fd, I2CWRITE, &cmd); - free(buf); - if (error == -1) { - err_msg = "ioctl: error when write offset"; - goto err1; + switch(i2c_opt.mode) { + case I2C_MODE_STOP_START: + /* + * Write offset where the data will go + */ + if (i2c_opt.width) { + cmd.count = bufsize; + cmd.buf = buf; + error = ioctl(fd, I2CWRITE, &cmd); + free(buf); + if (error == -1) { + err_msg = "ioctl: error when write offset"; + goto err1; + } } - } - /* Mode - stop start */ - if (i2c_opt.mode == I2C_MODE_STOP_START) { - cmd.slave = i2c_opt.addr; error = ioctl(fd, I2CSTOP, &cmd); if (error == -1) { err_msg = "ioctl: error sending stop condition"; @@ -322,9 +323,35 @@ i2c_write(char *dev, struct options i2c_ err_msg = "ioctl: error sending start condition"; goto err1; } - } - /* Mode - repeated start */ - if (i2c_opt.mode == I2C_MODE_REPEATED_START) { + + /* + * Write the data + */ + cmd.count = i2c_opt.count; + cmd.buf = i2c_buf; + cmd.last = 0; + error = ioctl(fd, I2CWRITE, &cmd); + if (error == -1) { + err_msg = "ioctl: error when write"; + goto err1; + } + break; + + case I2C_MODE_REPEATED_START: + /* + * Write offset where the data will go + */ + if (i2c_opt.width) { + cmd.count = bufsize; + cmd.buf = buf; + error = ioctl(fd, I2CWRITE, &cmd); + free(buf); + if (error == -1) { + err_msg = "ioctl: error when write offset"; + goto err1; + } + } + cmd.slave = i2c_opt.addr; error = ioctl(fd, I2CRPTSTART, &cmd); if (error == -1) { @@ -332,18 +359,42 @@ i2c_write(char *dev, struct options i2c_ "condition"; goto err1; } - } - /* - * Write the data - */ - cmd.count = i2c_opt.count; - cmd.buf = i2c_buf; - cmd.last = 0; - error = ioctl(fd, I2CWRITE, &cmd); - if (error == -1) { - err_msg = "ioctl: error when write"; - goto err1; + /* + * Write the data + */ + cmd.count = i2c_opt.count; + cmd.buf = i2c_buf; + cmd.last = 0; + error = ioctl(fd, I2CWRITE, &cmd); + if (error == -1) { + err_msg = "ioctl: error when write"; + goto err1; + } + break; + + case I2C_MODE_NONE: /* fall through */ + default: + buf = realloc(buf, bufsize + i2c_opt.count); + if (buf == NULL) { + err_msg = "error: data malloc"; + goto err1; + } + + memcpy(buf + bufsize, i2c_buf, i2c_opt.count); + /* + * Write offset and data + */ + cmd.count = bufsize + i2c_opt.count; + cmd.buf = buf; + cmd.last = 0; + error = ioctl(fd, I2CWRITE, &cmd); + free(buf); + if (error == -1) { + err_msg = "ioctl: error when write"; + goto err1; + } + break; } cmd.slave = i2c_opt.addr; error = ioctl(fd, I2CSTOP, &cmd);