blob: dd29e90f0f3fa3ed0b87111f57cdfedb9b200f1e [file]
// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0
//! In-process transport: client marshalling → [`dispatch`] → a real
//! `embedded_hal::i2c::I2c` bus, no kernel.
//!
//! First-class, not a test scaffold. It is:
//! - the host-test path — `I2cClient::new(LoopbackTransport::new(mock_bus))`
//! exercises the *same* encoders/decoders the IPC client uses; and
//! - the correct early-boot path before IPC exists (drive a real bus
//! in-process through the identical protocol code).
//!
//! Swapping `LoopbackTransport` for `i2c_client_ipc::IpcTransport` is a wiring
//! choice, never a code fork — that is the whole point of the seam.
use i2c_api::seam::{I2c, SevenBitAddress};
use i2c_api::{Transport, TransportError};
use crate::dispatch;
/// A [`Transport`] that runs [`dispatch`] against an owned in-process bus.
pub struct LoopbackTransport<B> {
bus: B,
}
impl<B> LoopbackTransport<B> {
pub const fn new(bus: B) -> Self {
Self { bus }
}
}
impl<B: I2c<SevenBitAddress>> Transport for LoopbackTransport<B> {
fn transact(&mut self, req: &[u8], resp: &mut [u8]) -> Result<usize, TransportError> {
// `dispatch` always produces a valid response frame (it encodes i2c
// errors *into* the payload), so the transport layer never fails.
Ok(dispatch(&mut self.bus, req, resp))
}
}