blob: 79c312b50fa56699e5eed1c2775bca38f2e704cb [file] [log] [blame]
diff -ruN iotools-1.5~/i2c_rw.c iotools-1.5/i2c_rw.c
--- iotools-1.5~/i2c_rw.c 1969-12-31 16:00:00.000000000 -0800
+++ iotools-1.5/i2c_rw.c 2017-03-16 09:52:49.386028184 -0700
@@ -0,0 +1,166 @@
+/*
+ Copyright 2017 Google Inc.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include "commands.h"
+#include "linux-i2c-dev.h"
+
+#define I2C_MAX_LEN 32
+
+struct i2c_params {
+ uint8_t i2c_bus;
+ uint8_t address;
+ uint8_t read_len;
+ uint8_t write_len;
+ uint8_t read_data[I2C_MAX_LEN];
+ uint8_t write_data[I2C_MAX_LEN];
+};
+
+static int
+parse_uint8(const char *arg, uint8_t *ret)
+{
+ unsigned long ldata;
+ char *end;
+
+ ldata = strtoul(arg, &end, 0);
+ if (ldata == LONG_MAX || *end != '\0') {
+ return -1;
+ }
+ *ret = (uint8_t)ldata;
+ return 0;
+}
+
+static int
+i2c_params(int argc, const char *argv[], struct i2c_params *params)
+{
+ int len, arg = 1;
+
+ memset(params, 0, sizeof(struct i2c_params));
+
+ if (parse_uint8(argv[arg++], &params->i2c_bus)) {
+ fprintf(stderr, "invalid adapter value\n");
+ return -1;
+ }
+ if (parse_uint8(argv[arg++], &params->address)) {
+ fprintf(stderr, "invalid address value\n");
+ return -1;
+ }
+ if (parse_uint8(argv[arg++], &params->read_len)) {
+ fprintf(stderr, "invalid read length value\n");
+ return -1;
+ }
+ if (params->read_len > I2C_MAX_LEN) {
+ fprintf(stderr, "invalid read length value %d\n",
+ params->read_len);
+ return -1;
+ }
+
+ /* Data to write */
+ for (len = 0; arg < argc; arg++, len++) {
+ if (parse_uint8(argv[arg], &params->write_data[len])) {
+ fprintf(stderr, "error parsing write data %d", len);
+ return -1;
+ }
+ }
+ params->write_len = len;
+
+ return 0;
+}
+
+static int
+i2c_xfer(int argc, const char *argv[], const struct cmd_info *info)
+{
+ int i, ret = 0;
+ struct i2c_params params;
+ struct i2c_rdwr_ioctl_data data;
+ struct i2c_msg msg[2];
+ char devfile[15];
+ int fd;
+
+ if (i2c_params(argc, argv, &params) < 0)
+ return -1;
+
+ memset(msg, 0, sizeof(struct i2c_msg) * 2);
+ memset(&data, 0, sizeof(struct i2c_rdwr_ioctl_data));
+
+ if (params.write_len > 0) {
+ /* Write message */
+ msg[data.nmsgs].addr = params.address;
+ msg[data.nmsgs].flags = 0;
+ msg[data.nmsgs].len = params.write_len;
+ msg[data.nmsgs].buf = params.write_data;
+ data.nmsgs++;
+ }
+
+ if (params.read_len > 0) {
+ /* Read message */
+ msg[data.nmsgs].addr = params.address;
+ msg[data.nmsgs].flags = I2C_M_RD;
+ msg[data.nmsgs].len = params.read_len;
+ msg[data.nmsgs].buf = params.read_data;
+ data.nmsgs++;
+ }
+
+ data.msgs = msg;
+
+ /* Open slave device */
+ sprintf(devfile, "/dev/i2c-%d", params.i2c_bus);
+ fd = open(devfile, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "Couldn't open i2c device file: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ ret = ioctl(fd, I2C_RDWR, &data);
+ close(fd);
+
+ if (ret < 0 || ret != data.nmsgs) {
+ fprintf(stderr, "i2c transfer failed: %s\n",
+ strerror(errno));
+ ret = -1;
+ }
+
+ /* Print out the read data */
+ if (params.read_len > 0) {
+ for (i = 0; i < params.read_len; i++) {
+ printf("0x%02x ", params.read_data[i]);
+ }
+ printf("\n");
+ }
+
+ return ret;
+}
+
+MAKE_PREREQ_PARAMS_VAR_ARGS(i2c_xfer_params, 3, I2C_MAX_LEN + 3,
+ "<adapter> <address> <read_count> [write bytes...]", 0);
+
+static const struct cmd_info i2c_cmds[] = {
+ MAKE_CMD_WITH_PARAMS(i2c_xfer, &i2c_xfer, NULL, &i2c_xfer_params)
+};
+
+MAKE_CMD_GROUP(I2C, "commands to access I2C devices", i2c_cmds);
+REGISTER_CMD_GROUP(I2C);
diff -ruN iotools-1.5~/linux-i2c-dev.h iotools-1.5/linux-i2c-dev.h
--- iotools-1.5~/linux-i2c-dev.h 2013-04-23 10:01:37.000000000 -0700
+++ iotools-1.5/linux-i2c-dev.h 2017-03-16 09:33:43.519882173 -0700
@@ -38,17 +38,17 @@
*/
struct i2c_msg {
__u16 addr; /* slave address */
- unsigned short flags;
-#define I2C_M_TEN 0x10 /* we have a ten bit chip address */
-#define I2C_M_RD 0x01
-#define I2C_M_NOSTART 0x4000
-#define I2C_M_REV_DIR_ADDR 0x2000
-#define I2C_M_IGNORE_NAK 0x1000
-#define I2C_M_NO_RD_ACK 0x0800
- short len; /* msg length */
- char *buf; /* pointer to msg data */
- int err;
- short done;
+ __u16 flags;
+#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
+#define I2C_M_RD 0x0001 /* read data, from slave to master */
+#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_NOSTART */
+#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
+ __u16 len; /* msg length */
+ __u8 *buf; /* pointer to msg data */
};
/* To determine what functionality is present */
@@ -191,7 +191,7 @@
/* This is the structure as used in the I2C_RDWR ioctl call */
struct i2c_rdwr_ioctl_data {
struct i2c_msg *msgs; /* pointers to i2c_msgs */
- int nmsgs; /* number of i2c_msgs */
+ __u32 nmsgs; /* number of i2c_msgs */
};