[PATCH 1/1] i2c: add I2C ioctl decoding
Tobias Peter
git at tobyp.net
Tue Apr 6 16:47:01 UTC 2021
Add decoding of I2C (and SMBUS) ioctls. These have been part of the uapi
since v3.7 and existed since v.2.3.34 (partial) and v2.3.35 (all
ioctls).
Signed-off-by: Tobias Peter <git at tobyp.net>
---
bundled/linux/include/uapi/linux/i2c-dev.h | 59 +++++
bundled/linux/include/uapi/linux/i2c.h | 164 ++++++++++++++
maint/ioctls_gen.sh | 1 +
src/Makefile.am | 1 +
src/defs.h | 1 +
src/i2c_ioctl.c | 239 +++++++++++++++++++++
src/ioctl.c | 2 +
src/linux/32/ioctls_inc_align16.h | 9 +
src/linux/32/ioctls_inc_align32.h | 9 +
src/linux/32/ioctls_inc_align64.h | 9 +
src/linux/64/ioctls_inc.h | 9 +
src/xlat/i2c_funcs.in | 21 ++
src/xlat/i2c_msg_flags.in | 10 +
src/xlat/i2c_smbus_read_write.in | 3 +
src/xlat/i2c_smbus_size.in | 10 +
15 files changed, 547 insertions(+)
create mode 100644 bundled/linux/include/uapi/linux/i2c-dev.h
create mode 100644 bundled/linux/include/uapi/linux/i2c.h
create mode 100644 src/i2c_ioctl.c
create mode 100644 src/xlat/i2c_funcs.in
create mode 100644 src/xlat/i2c_msg_flags.in
create mode 100644 src/xlat/i2c_smbus_read_write.in
create mode 100644 src/xlat/i2c_smbus_size.in
diff --git a/bundled/linux/include/uapi/linux/i2c-dev.h b/bundled/linux/include/uapi/linux/i2c-dev.h
new file mode 100644
index 00000000..1f1f16ea
--- /dev/null
+++ b/bundled/linux/include/uapi/linux/i2c-dev.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * i2c-dev.h - I2C bus char device interface
+ *
+ * Copyright (C) 1995-97 Simon G. Vogl
+ * Copyright (C) 1998-99 Frodo Looijaard <frodol at dds.nl>
+ */
+
+#ifndef _UAPI_LINUX_I2C_DEV_H
+#define _UAPI_LINUX_I2C_DEV_H
+
+#include <linux/types.h>
+
+/* /dev/i2c-X ioctl commands. The ioctl's parameter is always an
+ * unsigned long, except for:
+ * - I2C_FUNCS, takes pointer to an unsigned long
+ * - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data
+ * - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data
+ */
+#define I2C_RETRIES 0x0701 /* number of times a device address should
+ be polled when not acknowledging */
+#define I2C_TIMEOUT 0x0702 /* set timeout in units of 10 ms */
+
+/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses
+ * are NOT supported! (due to code brokenness)
+ */
+#define I2C_SLAVE 0x0703 /* Use this slave address */
+#define I2C_SLAVE_FORCE 0x0706 /* Use this slave address, even if it
+ is already in use by a driver! */
+#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */
+
+#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */
+
+#define I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */
+
+#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */
+#define I2C_SMBUS 0x0720 /* SMBus transfer */
+
+
+/* This is the structure as used in the I2C_SMBUS ioctl call */
+struct i2c_smbus_ioctl_data {
+ __u8 read_write;
+ __u8 command;
+ __u32 size;
+ union i2c_smbus_data *data;
+};
+
+/* 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 */
+ __u32 nmsgs; /* number of i2c_msgs */
+};
+
+#define I2C_RDWR_IOCTL_MAX_MSGS 42
+/* Originally defined with a typo, keep it for compatibility */
+#define I2C_RDRW_IOCTL_MAX_MSGS I2C_RDWR_IOCTL_MAX_MSGS
+
+
+#endif /* _UAPI_LINUX_I2C_DEV_H */
diff --git a/bundled/linux/include/uapi/linux/i2c.h b/bundled/linux/include/uapi/linux/i2c.h
new file mode 100644
index 00000000..92326ebd
--- /dev/null
+++ b/bundled/linux/include/uapi/linux/i2c.h
@@ -0,0 +1,164 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * i2c.h - definitions for the I2C bus interface
+ *
+ * Copyright (C) 1995-2000 Simon G. Vogl
+ * With some changes from Kyösti Mälkki <kmalkki at cc.hut.fi> and
+ * Frodo Looijaard <frodol at dds.nl>
+ */
+
+#ifndef _UAPI_LINUX_I2C_H
+#define _UAPI_LINUX_I2C_H
+
+#include <linux/types.h>
+
+/**
+ * struct i2c_msg - an I2C transaction segment beginning with START
+ *
+ * @addr: Slave address, either 7 or 10 bits. When this is a 10 bit address,
+ * %I2C_M_TEN must be set in @flags and the adapter must support
+ * %I2C_FUNC_10BIT_ADDR.
+ *
+ * @flags:
+ * Supported by all adapters:
+ * %I2C_M_RD: read data (from slave to master). Guaranteed to be 0x0001!
+ *
+ * Optional:
+ * %I2C_M_DMA_SAFE: the buffer of this message is DMA safe. Makes only sense
+ * in kernelspace, because userspace buffers are copied anyway
+ *
+ * Only if I2C_FUNC_10BIT_ADDR is set:
+ * %I2C_M_TEN: this is a 10 bit chip address
+ *
+ * Only if I2C_FUNC_SMBUS_READ_BLOCK_DATA is set:
+ * %I2C_M_RECV_LEN: message length will be first received byte
+ *
+ * Only if I2C_FUNC_NOSTART is set:
+ * %I2C_M_NOSTART: skip repeated start sequence
+
+ * Only if I2C_FUNC_PROTOCOL_MANGLING is set:
+ * %I2C_M_NO_RD_ACK: in a read message, master ACK/NACK bit is skipped
+ * %I2C_M_IGNORE_NAK: treat NACK from client as ACK
+ * %I2C_M_REV_DIR_ADDR: toggles the Rd/Wr bit
+ * %I2C_M_STOP: force a STOP condition after the message
+ *
+ * @len: Number of data bytes in @buf being read from or written to the I2C
+ * slave address. For read transactions where %I2C_M_RECV_LEN is set, the
+ * caller guarantees that this buffer can hold up to %I2C_SMBUS_BLOCK_MAX
+ * bytes in addition to the initial length byte sent by the slave (plus,
+ * if used, the SMBus PEC); and this value will be incremented by the number
+ * of block data bytes received.
+ *
+ * @buf: The buffer into which data is read, or from which it's written.
+ *
+ * An i2c_msg is the low level representation of one segment of an I2C
+ * transaction. It is visible to drivers in the @i2c_transfer() procedure,
+ * to userspace from i2c-dev, and to I2C adapter drivers through the
+ * @i2c_adapter. at master_xfer() method.
+ *
+ * Except when I2C "protocol mangling" is used, all I2C adapters implement
+ * the standard rules for I2C transactions. Each transaction begins with a
+ * START. That is followed by the slave address, and a bit encoding read
+ * versus write. Then follow all the data bytes, possibly including a byte
+ * with SMBus PEC. The transfer terminates with a NAK, or when all those
+ * bytes have been transferred and ACKed. If this is the last message in a
+ * group, it is followed by a STOP. Otherwise it is followed by the next
+ * @i2c_msg transaction segment, beginning with a (repeated) START.
+ *
+ * Alternatively, when the adapter supports %I2C_FUNC_PROTOCOL_MANGLING then
+ * passing certain @flags may have changed those standard protocol behaviors.
+ * Those flags are only for use with broken/nonconforming slaves, and with
+ * adapters which are known to support the specific mangling options they need.
+ */
+struct i2c_msg {
+ __u16 addr;
+ __u16 flags;
+#define I2C_M_RD 0x0001 /* guaranteed to be 0x0001! */
+#define I2C_M_TEN 0x0010 /* use only if I2C_FUNC_10BIT_ADDR */
+#define I2C_M_DMA_SAFE 0x0200 /* use only in kernel space */
+#define I2C_M_RECV_LEN 0x0400 /* use only if I2C_FUNC_SMBUS_READ_BLOCK_DATA */
+#define I2C_M_NO_RD_ACK 0x0800 /* use only if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_IGNORE_NAK 0x1000 /* use only if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_REV_DIR_ADDR 0x2000 /* use only if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_NOSTART 0x4000 /* use only if I2C_FUNC_NOSTART */
+#define I2C_M_STOP 0x8000 /* use only if I2C_FUNC_PROTOCOL_MANGLING */
+ __u16 len;
+ __u8 *buf;
+};
+
+/* To determine what functionality is present */
+
+#define I2C_FUNC_I2C 0x00000001
+#define I2C_FUNC_10BIT_ADDR 0x00000002 /* required for I2C_M_TEN */
+#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* required for I2C_M_IGNORE_NAK etc. */
+#define I2C_FUNC_SMBUS_PEC 0x00000008
+#define I2C_FUNC_NOSTART 0x00000010 /* required for I2C_M_NOSTART */
+#define I2C_FUNC_SLAVE 0x00000020
+#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 or later */
+#define I2C_FUNC_SMBUS_QUICK 0x00010000
+#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
+#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
+#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000
+#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000
+#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000
+#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000
+#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000
+#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 /* required for I2C_M_RECV_LEN */
+#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000
+#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */
+#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
+#define I2C_FUNC_SMBUS_HOST_NOTIFY 0x10000000 /* SMBus 2.0 or later */
+
+#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
+ I2C_FUNC_SMBUS_WRITE_BYTE)
+#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
+#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
+ I2C_FUNC_SMBUS_WRITE_WORD_DATA)
+#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
+#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
+ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
+
+#define I2C_FUNC_SMBUS_EMUL (I2C_FUNC_SMBUS_QUICK | \
+ I2C_FUNC_SMBUS_BYTE | \
+ I2C_FUNC_SMBUS_BYTE_DATA | \
+ I2C_FUNC_SMBUS_WORD_DATA | \
+ I2C_FUNC_SMBUS_PROC_CALL | \
+ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
+ I2C_FUNC_SMBUS_I2C_BLOCK | \
+ I2C_FUNC_SMBUS_PEC)
+
+/* if I2C_M_RECV_LEN is also supported */
+#define I2C_FUNC_SMBUS_EMUL_ALL (I2C_FUNC_SMBUS_EMUL | \
+ I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL)
+
+/*
+ * Data for SMBus Messages
+ */
+#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
+union i2c_smbus_data {
+ __u8 byte;
+ __u16 word;
+ __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
+ /* and one more for user-space compatibility */
+};
+
+/* i2c_smbus_xfer read or write markers */
+#define I2C_SMBUS_READ 1
+#define I2C_SMBUS_WRITE 0
+
+/* SMBus transaction types (size parameter in the above functions)
+ Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
+#define I2C_SMBUS_QUICK 0
+#define I2C_SMBUS_BYTE 1
+#define I2C_SMBUS_BYTE_DATA 2
+#define I2C_SMBUS_WORD_DATA 3
+#define I2C_SMBUS_PROC_CALL 4
+#define I2C_SMBUS_BLOCK_DATA 5
+#define I2C_SMBUS_I2C_BLOCK_BROKEN 6
+#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
+#define I2C_SMBUS_I2C_BLOCK_DATA 8
+
+#endif /* _UAPI_LINUX_I2C_H */
diff --git a/maint/ioctls_gen.sh b/maint/ioctls_gen.sh
index fa1fd687..dba461fd 100755
--- a/maint/ioctls_gen.sh
+++ b/maint/ioctls_gen.sh
@@ -53,6 +53,7 @@ trap 'cleanup 1' HUP PIPE INT QUIT TERM
# Fetch ioctl commands defined in hex form.
{
"$mydir"/ioctls_hex.sh "$inc_dir" 03 linux/hdreg.h
+ "$mydir"/ioctls_hex.sh "$inc_dir" 07 linux/i2c-dev.h
"$mydir"/ioctls_hex.sh "$inc_dir" 22 scsi/sg.h
"$mydir"/ioctls_hex.sh "$inc_dir" 46 linux/fb.h
"$mydir"/ioctls_hex.sh "$inc_dir" 4B linux/kd.h
diff --git a/src/Makefile.am b/src/Makefile.am
index b5abd1c8..b2db6333 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -139,6 +139,7 @@ libstrace_a_SOURCES = \
hostname.c \
inotify.c \
inotify_ioctl.c \
+ i2c_ioctl.c \
io.c \
io_uring.c \
ioctl.c \
diff --git a/src/defs.h b/src/defs.h
index 08a29313..031af714 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -1250,6 +1250,7 @@ DECL_IOCTL(fs_0x94);
DECL_IOCTL(fs_f);
DECL_IOCTL(fs_x);
DECL_IOCTL(gpio);
+DECL_IOCTL(i2c);
DECL_IOCTL(inotify);
DECL_IOCTL(kvm);
DECL_IOCTL(nbd);
diff --git a/src/i2c_ioctl.c b/src/i2c_ioctl.c
new file mode 100644
index 00000000..e8cfa1d9
--- /dev/null
+++ b/src/i2c_ioctl.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2021 The strace developers.
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "defs.h"
+
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+#include "xlat/i2c_funcs.h"
+
+static int
+print_i2c_funcs(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ kernel_ulong_t funcs;
+
+ if (entering(tcp))
+ return 0;
+
+ tprint_arg_next();
+ if (umove_or_printaddr(tcp, arg, &funcs))
+ return RVAL_IOCTL_DECODED;
+
+ printflags(i2c_funcs, funcs, NULL);
+ return RVAL_IOCTL_DECODED;
+}
+
+#include "xlat/i2c_msg_flags.h"
+
+static void
+print_i2c_msg(struct tcb *const tcp, const struct i2c_msg *const sd)
+{
+ tprint_struct_begin();
+ PRINT_FIELD_X(*sd, addr);
+ tprint_struct_next();
+ PRINT_FIELD_FLAGS(*sd, flags, i2c_msg_flags, "I2C_M_???");
+ tprint_struct_next();
+ PRINT_FIELD_U(*sd, len);
+ tprint_struct_next();
+ tprints_field_name("buf");
+
+ __u8 * buf = xmalloc(sd->len);
+ if (!umoven_or_printaddr(tcp, (kernel_ulong_t)sd->buf, sd->len, buf)) {
+ print_quoted_string((const char *)buf, sd->len,
+ QUOTE_FORCE_HEX);
+ }
+ free(buf);
+ tprint_struct_end();
+}
+
+static int
+print_i2c_rdwr(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ struct i2c_rdwr_ioctl_data rwd;
+ struct i2c_msg msg;
+
+ if (entering(tcp))
+ tprint_arg_next();
+ else if (syserror(tcp))
+ return RVAL_IOCTL_DECODED;
+ else
+ tprint_value_changed();
+
+ if (umove_or_printaddr(tcp, arg, &rwd))
+ return RVAL_IOCTL_DECODED;
+
+ if (entering(tcp)) {
+ tprint_struct_begin();
+
+ PRINT_FIELD_D(rwd, nmsgs);
+ tprint_struct_next();
+
+ tprint_array_begin();
+ for (unsigned long i=0; i<rwd.nmsgs; ++i) {
+ if (i != 0) tprint_array_next();
+ if (!umove_or_printaddr(tcp,
+ (kernel_ulong_t)(rwd.msgs + i),
+ &msg)) {
+ print_i2c_msg(tcp, &msg);
+ }
+ }
+ tprint_array_end();
+
+ return 0;
+ }
+
+ /* exiting */
+ tprint_array_begin();
+ for (unsigned long i=0; i<rwd.nmsgs; ++i) {
+ if (i != 0) tprint_array_next();
+ if (!umove_or_printaddr(tcp, (kernel_ulong_t)(rwd.msgs + i),
+ &msg)) {
+ print_i2c_msg(tcp, &msg);
+ }
+ }
+ tprint_array_end();
+ tprint_struct_end();
+
+ return RVAL_IOCTL_DECODED;
+}
+
+#include "xlat/i2c_smbus_read_write.h"
+#include "xlat/i2c_smbus_size.h"
+
+#include <stdio.h>
+
+/* For QUICK actions and single-byte writes, the data field is ignored. */
+static int
+i2c_smbus_data_matters(const struct i2c_smbus_ioctl_data *const sd)
+{
+ return !(sd->size == I2C_SMBUS_QUICK ||
+ ((sd->size == I2C_SMBUS_BYTE) &&
+ (sd->read_write == I2C_SMBUS_WRITE)));
+}
+
+/* The kernel only changes data on procedure calls or reads. */
+static int
+i2c_smbus_data_mutation(const struct i2c_smbus_ioctl_data *const sd)
+{
+ return sd->size == I2C_SMBUS_PROC_CALL ||
+ sd->size == I2C_SMBUS_BLOCK_PROC_CALL ||
+ sd->read_write == I2C_SMBUS_READ;
+}
+
+static int
+print_i2c_smbus(struct tcb *const tcp, const kernel_ulong_t arg)
+{
+ struct i2c_smbus_ioctl_data sd;
+ union i2c_smbus_data d;
+
+ if (entering(tcp))
+ tprint_arg_next();
+ else if (syserror(tcp))
+ return RVAL_IOCTL_DECODED;
+
+ if (umove_or_printaddr(tcp, arg, &sd))
+ return RVAL_IOCTL_DECODED;
+
+ if (entering(tcp)) {
+ tprint_struct_begin();
+
+ PRINT_FIELD_XVAL(sd, read_write, i2c_smbus_read_write,
+ "I2C_SMBUS_???");
+ tprint_struct_next();
+
+ PRINT_FIELD_X(sd, command);
+ tprint_struct_next();
+
+ PRINT_FIELD_XVAL(sd, size, i2c_smbus_size, "I2C_SMBUS_???");
+ tprint_struct_next();
+
+ if (!i2c_smbus_data_matters(&sd)) {
+ /* in this case data is not used at all, only command */
+ tprints_field_name("data");
+ tprint_more_data_follows();
+ tprint_struct_end(); // struct i2c_smbus_ioctl_data
+ return RVAL_IOCTL_DECODED;
+ }
+
+ tprints_field_name("data");
+ if (umove_or_printaddr(tcp, (kernel_ulong_t)sd.data, &d))
+ return RVAL_IOCTL_DECODED;
+ tprint_struct_begin();
+ if (sd.size == I2C_SMBUS_BYTE_DATA ||
+ sd.size == I2C_SMBUS_BYTE)
+ PRINT_FIELD_X(d, byte);
+ else if (sd.size == I2C_SMBUS_WORD_DATA ||
+ sd.size == I2C_SMBUS_PROC_CALL)
+ PRINT_FIELD_X(d, word);
+ else
+ PRINT_FIELD_HEX_ARRAY(d, block);
+ tprint_struct_end();
+
+ return 0;
+ }
+
+ /* exiting */
+ if (i2c_smbus_data_mutation(&sd)) {
+ tprint_value_changed();
+ if (!umove_or_printaddr(tcp, (kernel_ulong_t)sd.data, &d)) {
+ tprint_struct_begin();
+ if (sd.size == I2C_SMBUS_BYTE_DATA ||
+ sd.size == I2C_SMBUS_BYTE)
+ PRINT_FIELD_X(d, byte);
+ else if (sd.size == I2C_SMBUS_WORD_DATA ||
+ sd.size == I2C_SMBUS_PROC_CALL)
+ PRINT_FIELD_X(d, word);
+ else
+ PRINT_FIELD_HEX_ARRAY(d, block);
+ tprint_struct_end();
+ }
+ }
+
+ tprint_struct_end(); // struct i2c_smbus_ioctl_data
+
+ return RVAL_IOCTL_DECODED;
+}
+
+int
+i2c_ioctl(struct tcb *const tcp, const unsigned int code,
+ const kernel_ulong_t arg)
+{
+ switch (code) {
+ /* numeric arguments; I2C_TIMEOUT is in units of 10ms */
+ case I2C_RETRIES:
+ case I2C_TIMEOUT:
+ tprint_arg_next();
+ PRINT_VAL_D((kernel_long_t)arg);
+ return RVAL_IOCTL_DECODED;
+
+ /* booleans (==0 as false, !=0 as true) */
+ case I2C_PEC:
+ case I2C_TENBIT:
+ tprint_arg_next();
+ PRINT_VAL_D((kernel_long_t)arg);
+ return RVAL_IOCTL_DECODED;
+
+ /* I2C Addresses */
+ case I2C_SLAVE:
+ case I2C_SLAVE_FORCE:
+ tprint_arg_next();
+ PRINT_VAL_X((kernel_long_t)arg);
+ return RVAL_IOCTL_DECODED;
+
+ /* Flags */
+ case I2C_FUNCS:
+ return print_i2c_funcs(tcp, arg);
+
+ /* Structures */
+ case I2C_RDWR:
+ return print_i2c_rdwr(tcp, arg);
+ case I2C_SMBUS:
+ return print_i2c_smbus(tcp, arg);
+ }
+ return RVAL_DECODED;
+}
diff --git a/src/ioctl.c b/src/ioctl.c
index 12029028..dad02bff 100644
--- a/src/ioctl.c
+++ b/src/ioctl.c
@@ -346,6 +346,8 @@ ioctl_decode(struct tcb *tcp)
switch (_IOC_TYPE(code)) {
case 0x03:
return hdio_ioctl(tcp, code, arg);
+ case 0x07:
+ return i2c_ioctl(tcp, code, arg);
case 0x12:
return block_ioctl(tcp, code, arg);
case '"': /* 0x22 */
diff --git a/src/linux/32/ioctls_inc_align16.h b/src/linux/32/ioctls_inc_align16.h
index 2d028bb1..c09572bb 100644
--- a/src/linux/32/ioctls_inc_align16.h
+++ b/src/linux/32/ioctls_inc_align16.h
@@ -1218,6 +1218,15 @@
{ "linux/hsi/hsi_char.h", "HSC_SET_PM", _IOC_NONE, 0x6b11, 0x00 },
{ "linux/hsi/hsi_char.h", "HSC_SET_RX", _IOC_WRITE, 0x6b13, 0x0c },
{ "linux/hsi/hsi_char.h", "HSC_SET_TX", _IOC_WRITE, 0x6b15, 0x10 },
+{ "linux/i2c-dev.h", "I2C_FUNCS", 0, 0x0705, 0 },
+{ "linux/i2c-dev.h", "I2C_PEC", 0, 0x0708, 0 },
+{ "linux/i2c-dev.h", "I2C_RDWR", 0, 0x0707, 0 },
+{ "linux/i2c-dev.h", "I2C_RETRIES", 0, 0x0701, 0 },
+{ "linux/i2c-dev.h", "I2C_SLAVE", 0, 0x0703, 0 },
+{ "linux/i2c-dev.h", "I2C_SLAVE_FORCE", 0, 0x0706, 0 },
+{ "linux/i2c-dev.h", "I2C_SMBUS", 0, 0x0720, 0 },
+{ "linux/i2c-dev.h", "I2C_TENBIT", 0, 0x0704, 0 },
+{ "linux/i2c-dev.h", "I2C_TIMEOUT", 0, 0x0702, 0 },
{ "linux/i2o-dev.h", "I2OEVTGET", _IOC_READ, 0x690b, 0x68 },
{ "linux/i2o-dev.h", "I2OEVTREG", _IOC_WRITE, 0x690a, 0x0c },
{ "linux/i2o-dev.h", "I2OGETIOPS", _IOC_READ, 0x6900, 0x20 },
diff --git a/src/linux/32/ioctls_inc_align32.h b/src/linux/32/ioctls_inc_align32.h
index a6e9e351..a6e06617 100644
--- a/src/linux/32/ioctls_inc_align32.h
+++ b/src/linux/32/ioctls_inc_align32.h
@@ -1218,6 +1218,15 @@
{ "linux/hsi/hsi_char.h", "HSC_SET_PM", _IOC_NONE, 0x6b11, 0x00 },
{ "linux/hsi/hsi_char.h", "HSC_SET_RX", _IOC_WRITE, 0x6b13, 0x0c },
{ "linux/hsi/hsi_char.h", "HSC_SET_TX", _IOC_WRITE, 0x6b15, 0x10 },
+{ "linux/i2c-dev.h", "I2C_FUNCS", 0, 0x0705, 0 },
+{ "linux/i2c-dev.h", "I2C_PEC", 0, 0x0708, 0 },
+{ "linux/i2c-dev.h", "I2C_RDWR", 0, 0x0707, 0 },
+{ "linux/i2c-dev.h", "I2C_RETRIES", 0, 0x0701, 0 },
+{ "linux/i2c-dev.h", "I2C_SLAVE", 0, 0x0703, 0 },
+{ "linux/i2c-dev.h", "I2C_SLAVE_FORCE", 0, 0x0706, 0 },
+{ "linux/i2c-dev.h", "I2C_SMBUS", 0, 0x0720, 0 },
+{ "linux/i2c-dev.h", "I2C_TENBIT", 0, 0x0704, 0 },
+{ "linux/i2c-dev.h", "I2C_TIMEOUT", 0, 0x0702, 0 },
{ "linux/i2o-dev.h", "I2OEVTGET", _IOC_READ, 0x690b, 0x68 },
{ "linux/i2o-dev.h", "I2OEVTREG", _IOC_WRITE, 0x690a, 0x0c },
{ "linux/i2o-dev.h", "I2OGETIOPS", _IOC_READ, 0x6900, 0x20 },
diff --git a/src/linux/32/ioctls_inc_align64.h b/src/linux/32/ioctls_inc_align64.h
index 485f2d14..eb656a43 100644
--- a/src/linux/32/ioctls_inc_align64.h
+++ b/src/linux/32/ioctls_inc_align64.h
@@ -1218,6 +1218,15 @@
{ "linux/hsi/hsi_char.h", "HSC_SET_PM", _IOC_NONE, 0x6b11, 0x00 },
{ "linux/hsi/hsi_char.h", "HSC_SET_RX", _IOC_WRITE, 0x6b13, 0x0c },
{ "linux/hsi/hsi_char.h", "HSC_SET_TX", _IOC_WRITE, 0x6b15, 0x10 },
+{ "linux/i2c-dev.h", "I2C_FUNCS", 0, 0x0705, 0 },
+{ "linux/i2c-dev.h", "I2C_PEC", 0, 0x0708, 0 },
+{ "linux/i2c-dev.h", "I2C_RDWR", 0, 0x0707, 0 },
+{ "linux/i2c-dev.h", "I2C_RETRIES", 0, 0x0701, 0 },
+{ "linux/i2c-dev.h", "I2C_SLAVE", 0, 0x0703, 0 },
+{ "linux/i2c-dev.h", "I2C_SLAVE_FORCE", 0, 0x0706, 0 },
+{ "linux/i2c-dev.h", "I2C_SMBUS", 0, 0x0720, 0 },
+{ "linux/i2c-dev.h", "I2C_TENBIT", 0, 0x0704, 0 },
+{ "linux/i2c-dev.h", "I2C_TIMEOUT", 0, 0x0702, 0 },
{ "linux/i2o-dev.h", "I2OEVTGET", _IOC_READ, 0x690b, 0x68 },
{ "linux/i2o-dev.h", "I2OEVTREG", _IOC_WRITE, 0x690a, 0x0c },
{ "linux/i2o-dev.h", "I2OGETIOPS", _IOC_READ, 0x6900, 0x20 },
diff --git a/src/linux/64/ioctls_inc.h b/src/linux/64/ioctls_inc.h
index 902903de..e7b195c2 100644
--- a/src/linux/64/ioctls_inc.h
+++ b/src/linux/64/ioctls_inc.h
@@ -1223,6 +1223,15 @@
{ "linux/hsi/hsi_char.h", "HSC_SET_PM", _IOC_NONE, 0x6b11, 0x00 },
{ "linux/hsi/hsi_char.h", "HSC_SET_RX", _IOC_WRITE, 0x6b13, 0x0c },
{ "linux/hsi/hsi_char.h", "HSC_SET_TX", _IOC_WRITE, 0x6b15, 0x10 },
+{ "linux/i2c-dev.h", "I2C_FUNCS", 0, 0x0705, 0 },
+{ "linux/i2c-dev.h", "I2C_PEC", 0, 0x0708, 0 },
+{ "linux/i2c-dev.h", "I2C_RDWR", 0, 0x0707, 0 },
+{ "linux/i2c-dev.h", "I2C_RETRIES", 0, 0x0701, 0 },
+{ "linux/i2c-dev.h", "I2C_SLAVE", 0, 0x0703, 0 },
+{ "linux/i2c-dev.h", "I2C_SLAVE_FORCE", 0, 0x0706, 0 },
+{ "linux/i2c-dev.h", "I2C_SMBUS", 0, 0x0720, 0 },
+{ "linux/i2c-dev.h", "I2C_TENBIT", 0, 0x0704, 0 },
+{ "linux/i2c-dev.h", "I2C_TIMEOUT", 0, 0x0702, 0 },
{ "linux/i2o-dev.h", "I2OEVTGET", _IOC_READ, 0x690b, 0x68 },
{ "linux/i2o-dev.h", "I2OEVTREG", _IOC_WRITE, 0x690a, 0x0c },
{ "linux/i2o-dev.h", "I2OGETIOPS", _IOC_READ, 0x6900, 0x20 },
diff --git a/src/xlat/i2c_funcs.in b/src/xlat/i2c_funcs.in
new file mode 100644
index 00000000..d3bb8d91
--- /dev/null
+++ b/src/xlat/i2c_funcs.in
@@ -0,0 +1,21 @@
+#unconditional
+I2C_FUNC_I2C
+I2C_FUNC_10BIT_ADDR
+I2C_FUNC_PROTOCOL_MANGLING
+I2C_FUNC_SMBUS_PEC
+I2C_FUNC_NOSTART
+I2C_FUNC_SLAVE
+I2C_FUNC_SMBUS_BLOCK_PROC_CALL
+I2C_FUNC_SMBUS_QUICK
+I2C_FUNC_SMBUS_READ_BYTE
+I2C_FUNC_SMBUS_WRITE_BYTE
+I2C_FUNC_SMBUS_READ_BYTE_DATA
+I2C_FUNC_SMBUS_WRITE_BYTE_DATA
+I2C_FUNC_SMBUS_READ_WORD_DATA
+I2C_FUNC_SMBUS_WRITE_WORD_DATA
+I2C_FUNC_SMBUS_PROC_CALL
+I2C_FUNC_SMBUS_READ_BLOCK_DATA
+I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
+I2C_FUNC_SMBUS_READ_I2C_BLOCK
+I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
+I2C_FUNC_SMBUS_HOST_NOTIFY
diff --git a/src/xlat/i2c_msg_flags.in b/src/xlat/i2c_msg_flags.in
new file mode 100644
index 00000000..8eb5e921
--- /dev/null
+++ b/src/xlat/i2c_msg_flags.in
@@ -0,0 +1,10 @@
+#unconditional
+I2C_M_RD
+I2C_M_TEN
+I2C_M_DMA_SAFE
+I2C_M_RECV_LEN
+I2C_M_NO_RD_ACK
+I2C_M_IGNORE_NAK
+I2C_M_REV_DIR_ADDR
+I2C_M_NOSTART
+I2C_M_STOP
diff --git a/src/xlat/i2c_smbus_read_write.in b/src/xlat/i2c_smbus_read_write.in
new file mode 100644
index 00000000..cab3ae3c
--- /dev/null
+++ b/src/xlat/i2c_smbus_read_write.in
@@ -0,0 +1,3 @@
+#unconditional
+I2C_SMBUS_READ
+I2C_SMBUS_WRITE
diff --git a/src/xlat/i2c_smbus_size.in b/src/xlat/i2c_smbus_size.in
new file mode 100644
index 00000000..ca176072
--- /dev/null
+++ b/src/xlat/i2c_smbus_size.in
@@ -0,0 +1,10 @@
+#unconditional
+I2C_SMBUS_QUICK
+I2C_SMBUS_BYTE
+I2C_SMBUS_BYTE_DATA
+I2C_SMBUS_WORD_DATA
+I2C_SMBUS_PROC_CALL
+I2C_SMBUS_BLOCK_DATA
+I2C_SMBUS_I2C_BLOCK_BROKEN
+I2C_SMBUS_BLOCK_PROC_CALL
+I2C_SMBUS_I2C_BLOCK_DATA
--
2.31.1
More information about the Strace-devel
mailing list