Skip to contentSkip to conversation

i2c: new i2c-pseudo driver for userspace i2c adapters

PATCH New Matthew Blecker 1 participant 1 message Jan 5, 2024

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 i2c: new i2c-pseudo driver for userspace i2c adapters

The i2c-pseudo module provides /dev/i2c-pseudo for implementing I2C adapters in userspace.

I2C adapter functionality supported:
* I2C_FUNC_I2C
* I2C_FUNC_10BIT_ADDR
* I2C_FUNC_PROTOCOL_MANGLING
* I2C_FUNC_SMBUS_EMUL

The UAPI is based around ioctl commands. Each open /dev/i2c-pseudo fd has its own independent state and I2C adapter device. For further detail see the documentation and UAPI header:
* Documentation/i2c/i2c-pseudo.rst
* include/uapi/linux/i2c-pseudo.h
* Of note, the new UAPI structs use actual pointer types, not __u64, because they're built around the existing i2c_msg with its __u8 * buf.

In the ChromeOS ecosystem i2c-pseudo is used for controlling I2C on devices under test (DUTs). A userspace program speaks the varying and evolving I2C controller interfaces provided by many types of I2C capable debug hardware, typically controlled over USB, or sometimes serial UART. That userspace program now uses /dev/i2c-pseudo, when present, to provide Linux I2C adapters for each I2C bus under its control.

These debug hardware I2C controller interfaces are better suited to userspace than kernel implementations, however it is useful to have /dev/i2c-<N> as a standard interface. This allows any software written for i2c-dev to simply work as-is with these userspace I2C controllers, and avoids having an alternate API for software that must support the debug hardware.

Examples where i2c-dev backed by i2c-pseudo is used:
* Writing or reading the firmware of certain microcontrollers, where this is done over I2C.
* i2c-tools e.g. i2ctransfer(8) for convenient interactive probing and mutating of I2C targets on the DUTs.

This driver can also be used to mock the behavior of I2C targets, for regression testing Linux drivers and software that control I2C devices. While i2c-stub exists for that purpose now, it is limited by design. This can emulate most possible behavior from an I2C target and adapter driver, including changing responses and failures.

---

This patch proposes a new UAPI, and I recognize that is no small ask. Please let me know if you are open to userspace I2C adapters, even if this specific UAPI or its implementation may have issues.

---

Historical note:

In May 2020 I sent an earlier implementation of an I2C adapter UAPI which also used the i2c-pseudo driver name.

https://lore.kernel.org/r/[email protected]/

This patch is a completely new implementation with a new UAPI. This ioctl-based UAPI is more typical for Linux and results in a much simpler driver implementation. This is also more aligned with the i2c-dev UAPI.

I think this patch is best considered as a new clean slate proposal, it does not make sense as diff from that old one. Hence "v1" with a subtly changed title.

---

Other notes:

* This v1 patch does not provide compat_ioctl. The pointer types make it non-trivial. CrOS have no use case for 32-bit compat mode with this driver, and it's unclear to me that anyone else would in 2024+. If compat_ioctl is still mandatory to support, or anyone reading this would find it useful with this specific driver, please let me know and I'll update the patch with it.

* Most usage to date has been as an out-of-tree module on x86_64 ChromeOS developer systems, compiled and installed separately from the main kernel. The most common use is the MCU firmware flashing mentioned above, where 512 KiB firmware images are sent or read as fast as the underlying I2C bus and MCU storage allows. i2c-pseudo has been reliable and not a bottleneck for this.

* I have stress tested having a userspace controller run many threads attempting epoll_wait(), I2CP_IOCTL_XFER_REQ, or I2CP_IOCTL_XFER_REPLY in parallel with a shared pseudo adapter. Parallel I/O threads with I2C is pointless of course, but should be handled gracefully.

---
 .../ABI/testing/sysfs-devices-i2c-pseudo      |  11 +
 Documentation/i2c/i2c-pseudo.rst              | 225 +++++
 Documentation/i2c/index.rst                   |   1 +
 .../userspace-api/ioctl/ioctl-number.rst      |   2 +
 drivers/i2c/Kconfig                           |  11 +
 drivers/i2c/Makefile                          |   1 +
 drivers/i2c/i2c-pseudo.c                      | 864 ++++++++++++++++++
 include/uapi/linux/i2c-pseudo.h               | 259 ++++++
 samples/i2c-pseudo/.gitignore                 |   2 +
 samples/i2c-pseudo/Makefile                   |  12 +
 samples/i2c-pseudo/i2c-adapter-example.c      | 160 ++++
 11 files changed, 1548 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-devices-i2c-pseudo
 create mode 100644 Documentation/i2c/i2c-pseudo.rst
 create mode 100644 drivers/i2c/i2c-pseudo.c
 create mode 100644 include/uapi/linux/i2c-pseudo.h
 create mode 100644 samples/i2c-pseudo/.gitignore
 create mode 100644 samples/i2c-pseudo/Makefile
 create mode 100644 samples/i2c-pseudo/i2c-adapter-example.c
Documentation/ABI/testing/sysfs-devices-i2c-pseudo new file +11 -0
new file mode 100644
index 000000000000..9b6dfd066384
@@ -0,0 +1,11 @@
+What:	/sys/devices/virtual/i2c-pseudo/.../open_count
+Date:	November 2023
+Contact:	Matthew Blecker <[email protected]>
+Description:
+	The number of open file handles for the i2c-pseudo device.
+
+	This shows utilization of a resource whose limit is set by
+	i2c-pseudo module max_adapters parameter.
+
+	This may be greater than the number of extant pseudo adapters
+	because an adapter is only created after a specific ioctl call.
Documentation/i2c/i2c-pseudo.rst new file +225 -0

225 lines not on this page · raw message

Documentation/i2c/index.rst +1 -0
index 2b213d4ce89c..31800ef2c410 100644
@@ -58,6 +58,7 @@ Advanced topics
    :maxdepth: 1
 
    ten-bit-addresses
+   i2c-pseudo
 
 Legacy documentation
 ====================
Documentation/userspace-api/ioctl/ioctl-number.rst +2 -0
index 4ea5b837399a..c15e729a8b24 100644
@@ -88,6 +88,8 @@ Code  Seq#    Include File                                           Comments
                                                                      <http://infiniband.sourceforge.net/>
 0x20  all    drivers/cdrom/cm206.h
 0x22  all    scsi/sg.h
+0x2C  00-04  uapi/linux/i2c-pseudo.h                                 userspace I2C controllers
+0x2C  05-31  uapi/linux/i2c-pseudo.h                                 reserved for future use (e.g. SMBUS UAPI)
 0x3E  00-0F  linux/counter.h                                         <mailto:[email protected]>
 '!'   00-1F  uapi/linux/seccomp.h
 '#'   00-3F                                                          IEEE 1394 Subsystem
drivers/i2c/Kconfig +11 -0
index 9388823bb0bb..7ce7fd4baec0 100644
@@ -107,6 +107,17 @@ config I2C_SMBUS
 source "drivers/i2c/algos/Kconfig"
 source "drivers/i2c/busses/Kconfig"
 
+config I2C_PSEUDO
+	tristate "I2C userspace adapter interface"
+	help
+	  Say Y here to have an i2c-pseudo device file, usually found in
+	  the /dev directory on your system.  This makes it possible to
+	  have user-space programs implement an I2C adapter.
+	  Information on how to do this is contained in
+	  <file:Documentation/i2c/i2c-pseudo.rst>.
+
+	  This support is also available as a module, called i2c-pseudo.
+
 config I2C_STUB
 	tristate "I2C/SMBus Test Stub"
 	depends on m
drivers/i2c/Makefile +1 -0
index 3f71ce4711e3..799141f1e9fb 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
 obj-$(CONFIG_I2C_MUX)		+= i2c-mux.o
 obj-$(CONFIG_I2C_ATR)		+= i2c-atr.o
 obj-y				+= algos/ busses/ muxes/
+obj-$(CONFIG_I2C_PSEUDO)	+= i2c-pseudo.o
 obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o
 obj-$(CONFIG_I2C_SLAVE_EEPROM)	+= i2c-slave-eeprom.o
 obj-$(CONFIG_I2C_SLAVE_TESTUNIT)	+= i2c-slave-testunit.o
drivers/i2c/i2c-pseudo.c new file +864 -0

864 lines not on this page · raw message

include/uapi/linux/i2c-pseudo.h new file +259 -0

259 lines not on this page · raw message

samples/i2c-pseudo/.gitignore new file +2 -0
new file mode 100644
index 000000000000..34622ae2686a
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+/i2c-adapter-example
samples/i2c-pseudo/Makefile new file +12 -0
new file mode 100644
index 000000000000..2b80fb544655
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+userprogs-always-y += i2c-adapter-example
+
+userccflags += -I usr/include
+
+.PHONY: all clean
+
+all:
+	$(MAKE) -C ../.. samples/i2c-pseudo/
+
+clean:
+	$(MAKE) -C ../.. M=samples/i2c-pseudo/ clean
samples/i2c-pseudo/i2c-adapter-example.c new file +160 -0

160 lines not on this page · raw message

Signature · 1 line
2.43.0.472.g3155946c3a-goog