blob: d86736d81979380546a53bf982830b173aac9718 [file]
// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0
//! Production IPC transport for `I2cClient`.
//!
//! The **only** IPC-coupled, kernel-tagged piece of the client path. It
//! implements `i2c_api::Transport` over a Pigweed channel; all wire
//! marshalling stays in the host-buildable `i2c_client`. Wiring:
//!
//! ```rust,ignore
//! use i2c_client::I2cClient;
//! use i2c_client_ipc::IpcTransport;
//! let mut bus = I2cClient::new(IpcTransport::new(handle::I2C_0));
//! ```
//!
//! Swapping this for `i2c_server::LoopbackTransport` (host) exercises the same
//! `I2cClient` code with no kernel — that is the point of the seam.
#![no_std]
use i2c_api::{Transport, TransportError};
use userspace::syscall;
use userspace::time::Instant;
/// Cross-process transport: one `channel_transact` per whole transaction.
pub struct IpcTransport {
handle: u32,
}
impl IpcTransport {
/// Bind to the IPC channel for one bus (handle from the app's generated
/// `handle` module — one channel per bus).
pub const fn new(handle: u32) -> Self {
Self { handle }
}
}
impl Transport for IpcTransport {
fn transact(&mut self, req: &[u8], resp: &mut [u8]) -> Result<usize, TransportError> {
syscall::channel_transact(self.handle, req, resp, Instant::MAX)
.map_err(|_| TransportError::Failed)
}
}