Ilya Chichkov <[email protected]> writes:
> 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>
>
> Signed-off-by: Ilya Chichkov <[email protected]>
[...]
> diff --git a/qapi/qom.json b/qapi/qom.json
> index dd45ac1087..b515f1e4e7 100644
> --- a/qapi/qom.json
> +++ b/qapi/qom.json
> @@ -1258,6 +1258,7 @@
> 'tls-creds-psk',
> 'tls-creds-x509',
> 'tls-cipher-suites',
> + 'remote-i2c-backend-cuse',
> { 'name': 'x-remote-object', 'features': [ 'unstable' ] },
> { 'name': 'x-vfio-user-server', 'features': [ 'unstable' ] }
> ] }
> @@ -1334,6 +1335,7 @@
> 'tls-creds-psk': 'TlsCredsPskProperties',
> 'tls-creds-x509': 'TlsCredsX509Properties',
> 'tls-cipher-suites': 'TlsCredsProperties',
> + 'remote-i2c-backend-cuse': 'RemoteI2CBackendCuseProperties',
> 'x-remote-object': 'RemoteObjectProperties',
> 'x-vfio-user-server': 'VfioUserServerProperties'
> } }
> @@ -1377,3 +1379,19 @@
> ##
> { 'command': 'object-del', 'data': {'id': 'str'},
> 'allow-preconfig': true }
> +
> +##
> +# @RemoteI2CBackendCuseProperties:
> +#
> +# Properties for the CUSE remote I2C backend.
> +#
> +# @devname: The CUSE device name to create (e.g., 'i2c-33').
What's a "CUSE device name"? What exactly is created?
> +# @fuse-opts: Optional FUSE mount options.
Syntax?
> +# @debug: Whether to enable debug output.
To what exactly does @debug apply?
Blank line between member descriptions, please.
> +#
> +# Since: (your version)
Assuming this can't make 11.1:
# Since: 11.2
> +##
> +{ 'struct': 'RemoteI2CBackendCuseProperties',
> + 'data': { 'devname': 'str',
> + '*fuse-opts': 'str',
> + '*debug': 'bool' } }
Should all this be 'if': 'CONFIG_LINUX'?