Hi Corey, Cédric,

On Fri, 24 Jul 2026 08:30:58 -0500, Corey Minyard <[email protected]> wrote:
> I think what Cédric is saying here is that if you provided a generic
> QMP interface that allowed these sorts of operations and wrote an
> external program that used said interface to provide a fuse interface,
> that would be better.

I see your point about keeping the core emulator clean and minimizing
dependencies.

I am willing to pivot to this architectural direction. I can drop the CUSE
backend from this patch series and instead implement the `i2c-transfer`
QMP command, as Cédric originally suggested. I will handle the CUSE
part externally.

Before I send v6, are there any other concerns regarding the core FSM
logic, or would replacing CUSE with a QMP backend be sufficient?

Best regards,
Ilya


пт, 24 июл. 2026 г. в 16:31, Corey Minyard <[email protected]>:
>
> On Fri, Jul 24, 2026 at 11:19:17AM +0300, Ilya Chichkov wrote:
> > Hi Cédric,
> >
> > On Wed, 22 Jul 2026 19:42:03 +0200, Cédric Le Goater <[email protected]> 
> > wrote:
> > > I think a lighter QMP-based approach would serve the same purpose,
> > > maybe better, and fit in better in QEMU, without the dependency and
> > > maintenance cost:
> >
> > As Corey and I discussed earlier in the thread, QMP doesn't cover the 
> > primary
> > motivation for this patch: zero-code transparency for existing host 
> > software.
> >
> > An `i2c-transfer` QMP command would be a great addition for custom scripts,
> > but the main goal here is to allow native Linux user-space binaries
> > (like i2c-tools,
> > lm-sensors) running on the host to talk to QEMU's I2C slaves unmodified, 
> > simply
> > by opening /dev/i2c-N. Rewriting legacy test suites to speak QMP JSON over a
> > socket is often not feasible.
>
> I think what Cédric is saying here is that if you provided a generic
> QMP interface that allowed these sorts of operations and wrote an
> external program that used said interface to provide a fuse interface,
> that would be better.  It has a number of advantages:
>
> * You add an interface to QEMU that others can easily use to test
>   devices.
>
> * You are not tied to QEMU when you want to extend the functions of
>   the fuse interface.
>
> * It's one less dependency in QEMU.  QEMU has a *lot* of dependencies,
>   and the fewer the better.
>
> The only disadvantage I can think of is that it's one more piece of
> software if you are setting this up.
>
> This is not a big piece of software, I agree, but from experience I
> think you will be happier with this sort of design in the long run.
> It puts you more in control of what you are doing.
>
> And, of course, it makes the QEMU maintainers happier :-).
>
> -corey
>
> >
> > > The dependency cost seems high for the use case: libfuse3 + the cuse
> > > kernel module pulled into the system emulator build. It's also ~3K
> > > lines of new code, three QOM types, FUSE session management, etc.
> >
> > Regarding dependencies, `libfuse3` is actually not new to the project — it 
> > has
> > been a supported QEMU dependency for a long time (already used by the block
> > layer in `block/export/fuse.c`). Also, just to clarify the diff: the core
> > implementation is roughly ~2K lines. The remaining ~900 lines are dedicated
> > entirely to qtests and RST documentation.
> >
> > However, I agree about not polluting the core emulation build with
> > Linux-specific
> > headers and libfuse3. The maintenance cost must be minimized. To address 
> > this,
> > I've refactored the architecture for v6 to ensure strict isolation:
> >
> > - All Linux and FUSE-specific headers are removed from public QEMU headers.
> >   The internal state structure is now opaque and hidden inside
> > remote-i2c-cuse.c.
> > - The CUSE backend is isolated behind its own
> >   CONFIG_REMOTE_I2C_BACKEND_CUSE in Kconfig and meson.build, strictly
> >   depending on LINUX and fuse3.
> >
> > On macOS, Windows, or minimalistic builds without libfuse, QEMU will build
> > cleanly without pulling in this backend or any of its dependencies.
> >
> > Would making the CUSE transport a strictly optional, isolated Linux-only 
> > backend
> > alleviate your concerns regarding the hardware emulation core?
> >
> > Best regards,
> > Ilya
> >
> > ср, 22 июл. 2026 г. в 20:42, Cédric Le Goater <[email protected]>:
> > >
> > > On 7/22/26 14:57, Ilya Chichkov wrote:
> > > > Add a "remote-i2c-master" device that exposes a QEMU I2C bus to the
> > > > host system through a FUSE/CUSE character device. This lets external
> > > > host programs and standard i2c-tools interact with I2C slaves emulated
> > > > inside QEMU as if they were real devices attached to the host.
> > > >
> > > > The implementation is split into three layers:
> > > >
> > > >    - A non-blocking finite state machine that drives the QEMU I2C
> > > >      master. It is pumped by a QEMU Bottom Half and uses virtual timers
> > > >      to yield during long transfers and to model clock stretching for
> > > >      asynchronous slaves, so the main loop is never blocked. The FSM
> > > >      walks IDLE -> ADDR -> SEND/RECV -> WAIT_STRETCH -> END -> FINISHED
> > > >      and handles NACKs (ENXIO), lost arbitration (EBUSY, with optional
> > > >      back-off and retry), stretch timeouts, and manual abort/reset.
> > > >
> > > >    - An abstract RemoteI2CBackend QOM base class that decouples the
> > > >      internal I2C hardware state machine (the frontend) from any
> > > >      host-specific transport, exposing on_tx_complete and on_tx_error
> > > >      virtual callbacks.
> > > >
> > > >    - A concrete remote-i2c-backend-cuse backend implementing that
> > > >      transport over CUSE. It manages the FUSE session and integrates
> > > >      its file descriptors into QEMU's main AioContext event loop,
> > > >      translates Linux I2C_RDWR, I2C_SMBUS and I2C_SLAVE ioctls into
> > > >      generic byte streams for the FSM, and formats responses back into
> > > >      Linux I2C/SMBus structures for the FUSE driver. SMBus repeated
> > > >      start is supported for atomic write-then-read operations.
> > > >
> > > > Example usage:
> > > >
> > > >    -device remote-i2c-master,i2cbus=i2c-bus.0,devname=i2c-33
> > > >    -object remote-i2c-backend-cuse,id=b0,devname=i2c-33
> > > >
> > > > This creates /dev/i2c-33 on the host, usable with i2c-tools:
> > > >
> > > >    i2cdetect -y -l
> > > >    i2cget -y <bus_id> <addr> <reg>
> > > >
> > > > Acked-by: Markus Armbruster <[email protected]>
> > > > Signed-off-by: Ilya Chichkov <[email protected]>
> > > > ---
> > > > v2:
> > > >    - docs/system/devices/remote-i2c-master.rst: Documented concurrent
> > > >      bus access details and the 'raise-arbitrage-lost' property.
> > > > ---
> > > > v3:
> > > >    - qapi/qom.json: Fix RemoteI2CBackendCuseProperties formatting and
> > > >      expand member documentation (devname, fuse-opts, debug).
> > > >    - tests/qtest: Add remote-i2c-cuse-test covering capabilities,
> > > >      functional smoke test, synchronous sensor read/write.
> > > > ---
> > > > v4:
> > > >   - qapi: reference the rst doc via :doc:
> > > >   - qapi: fuse-opts is now ['str'] instead of a space-separated string
> > > >   - qapi: drop redundant 'debug' property (pass -d via fuse-opts)
> > > > ---
> > > > v5:
> > > >   - docs/system/device-emulation.rst: add remote-i2c-master.rst to
> > > >     the toctree under "Emulated Devices"
> > > >   - qapi/qom.json: move RemoteI2CBackendCuseProperties definition
> > > >     before RemoteObjectProperties as requested; change "for usage
> > > >     information" to "for detailed usage information"
> > > > ---
> > > > ---
> > > >   docs/system/device-emulation.rst          |    1 +
> > > >   docs/system/devices/remote-i2c-master.rst |  217 ++++
> > > >   hw/i2c/Kconfig                            |    5 +
> > > >   hw/i2c/meson.build                        |    6 +
> > > >   hw/i2c/remote-i2c-backend.c               |   30 +
> > > >   hw/i2c/remote-i2c-cuse.c                  | 1173 +++++++++++++++++++++
> > > >   hw/i2c/remote-i2c-fsm.c                   |  521 +++++++++
> > > >   hw/i2c/remote-i2c-master.c                |  145 +++
> > > >   hw/i2c/trace-events                       |   29 +
> > > >   include/hw/i2c/remote-i2c-backend.h       |   70 ++
> > > >   include/hw/i2c/remote-i2c-cuse.h          |   93 ++
> > > >   include/hw/i2c/remote-i2c-master.h        |   77 ++
> > > >   qapi/qom.json                             |   29 +
> > > >   tests/qtest/meson.build                   |    2 +
> > > >   tests/qtest/remote-i2c-cuse-test.c        |  326 ++++++
> > > >   15 files changed, 2724 insertions(+)
> > > >   create mode 100644 docs/system/devices/remote-i2c-master.rst
> > > >   create mode 100644 hw/i2c/remote-i2c-backend.c
> > > >   create mode 100644 hw/i2c/remote-i2c-cuse.c
> > > >   create mode 100644 hw/i2c/remote-i2c-fsm.c
> > > >   create mode 100644 hw/i2c/remote-i2c-master.c
> > > >   create mode 100644 include/hw/i2c/remote-i2c-backend.h
> > > >   create mode 100644 include/hw/i2c/remote-i2c-cuse.h
> > > >   create mode 100644 include/hw/i2c/remote-i2c-master.h
> > > >   create mode 100644 tests/qtest/remote-i2c-cuse-test.c
> > >
> > > If I understand this proposal correctly, it lets host-side i2c
> > > tools talk to emulated I2C devices. The example is i2cdetect/i2cget
> > > against a tmp105 on an Aspeed bus.
> > >
> > > QEMU already has mechanisms for this though. qtest can read/write I2C
> > > registers programmatically, QMP can query device state, and the guest
> > > OS itself sees the I2C bus natively.
> > >
> > > The dependency cost seems high for the use case: libfuse3 + the cuse
> > > kernel module pulled into the system emulator build. It's also ~3K
> > > lines of new code, three QOM types, FUSE session management, etc.
> > > The surface area for bugs is large. It's a heavy burden for what it
> > > gives.
> > >
> > > I think a lighter QMP-based approach would serve the same purpose,
> > > maybe better, and fit in better in QEMU, without the dependency and
> > > maintenance cost:
> > >
> > > - No host kernel dependency
> > > - Works remotely (QMP over socket)
> > > - Fits QEMU's existing management model
> > > - Much less code
> > > - Testable without root or kernel modules
> > >
> > > Have you considered extending QMP with an I2C transaction command
> > > instead? Something like:
> > >
> > >    { 'command': 'i2c-transfer',
> > >      'data': { 'bus': 'str',
> > >                'address': 'uint8',
> > >                'read': 'bool',
> > >                '*data': ['uint8'],
> > >                '*length': 'uint16' },
> > >      'returns': { '*data': ['uint8'] } }
> > >
> > >
> > > Thanks,
> > >
> > > C.
> > >

Reply via email to