[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260131-i2c-adapter-v1-4-5a436e34cd1a@gmail.com>
Date: Sat, 31 Jan 2026 14:12:46 +0000
From: Igor Korotin via B4 Relay <devnull+igor.korotin.linux.gmail.com@...nel.org>
To: Danilo Krummrich <dakr@...nel.org>,
Daniel Almeida <daniel.almeida@...labora.com>,
Miguel Ojeda <ojeda@...nel.org>, Boqun Feng <boqun.feng@...il.com>,
Gary Guo <gary@...yguo.net>,
Björn Roy Baron <bjorn3_gh@...tonmail.com>,
Benno Lossin <lossin@...nel.org>, Andreas Hindborg <a.hindborg@...nel.org>,
Alice Ryhl <aliceryhl@...gle.com>, Trevor Gross <tmgross@...ch.edu>,
Wolfram Sang <wsa+renesas@...g-engineering.com>
Cc: linux-kernel@...r.kernel.org, rust-for-linux@...r.kernel.org,
linux-i2c@...r.kernel.org, markus.probst@...teo.de,
Igor Korotin <igor.korotin.linux@...il.com>
Subject: [PATCH 4/5] rust: i2c: add I2C wrappers
From: Igor Korotin <igor.korotin.linux@...il.com>
Add safe Rust wrappers for common I2C/SMbus operations on I2C clients.
These wrappers provide safe abstractions over low-level C API calls:
- SMbus byte operations: read/write byte and byte data
- SMbus word operations: read/write word data
- SMbus block operations: read/write I2C block data
- Master I2C operations: master receive and master send
All operations include proper error handling through the Result type.
Signed-off-by: Igor Korotin <igor.korotin.linux@...il.com>
---
rust/helpers/helpers.c | 1 +
rust/helpers/i2c.c | 15 ++++++++
rust/kernel/i2c/client.rs | 92 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 108 insertions(+)
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 79c72762ad9c..6f6b0ff8713a 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -29,6 +29,7 @@
#include "err.c"
#include "irq.c"
#include "fs.c"
+#include "i2c.c"
#include "io.c"
#include "jump_label.c"
#include "kunit.c"
diff --git a/rust/helpers/i2c.c b/rust/helpers/i2c.c
new file mode 100644
index 000000000000..05bbd26eaaf8
--- /dev/null
+++ b/rust/helpers/i2c.c
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/i2c.h>
+
+__rust_helper int rust_helper_i2c_master_recv(const struct i2c_client *client,
+ char *buf, int count)
+{
+ return i2c_master_recv(client, buf, count);
+}
+
+__rust_helper int rust_helper_i2c_master_send(const struct i2c_client *client,
+ const char *buf, int count)
+{
+ return i2c_master_send(client, buf, count);
+}
diff --git a/rust/kernel/i2c/client.rs b/rust/kernel/i2c/client.rs
index a597793ff038..76fa01cb0351 100644
--- a/rust/kernel/i2c/client.rs
+++ b/rust/kernel/i2c/client.rs
@@ -140,6 +140,98 @@ unsafe impl Send for I2cClient {}
// (i.e. `I2cClient<Normal>) are thread safe.
unsafe impl Sync for I2cClient {}
+impl I2cClient<device::Normal> {
+ /// The C `i2c_smbus_read_byte` function wrapper for SMbus "read byte" protocol
+ pub fn i2c_smbus_read_byte(&self) -> Result<u8> {
+ // SAFETY: self is a valid reference to a I2cClient<Normal>
+ let result = unsafe { bindings::i2c_smbus_read_byte(self.as_raw()) };
+ to_result(result)?;
+ Ok(result as u8)
+ }
+
+ /// The C `i2c_smbus_write_byte` function wrapper for SMbus "write byte" protocol
+ pub fn i2c_smbus_write_byte(&self, value: u8) -> Result {
+ // SAFETY: self is a valid reference to a I2cClient<Normal>
+ to_result(unsafe { bindings::i2c_smbus_write_byte(self.as_raw(), value) })
+ }
+
+ /// The C `i2c_smbus_read_byte_data` function wrapper for SMbus "read byte" protocol
+ pub fn i2c_smbus_read_byte_data(&self, command: u8) -> Result<u8> {
+ // SAFETY: self is a valid reference to a I2cClient<Normal>
+ let result = unsafe { bindings::i2c_smbus_read_byte_data(self.as_raw(), command) };
+ to_result(result)?;
+ Ok(result as u8)
+ }
+
+ /// The C `i2c_smbus_write_byte_data` function wrapper for SMbus "write byte" protocol
+ pub fn i2c_smbus_write_byte_data(&self, command: u8, value: u8) -> Result {
+ // SAFETY: self is a valid reference to a I2cClient<Normal>
+ to_result(unsafe { bindings::i2c_smbus_write_byte_data(self.as_raw(), command, value) })
+ }
+
+ /// The C `i2c_smbus_read_word_data` function wrapper for SMbus "read word" protocol
+ pub fn i2c_smbus_read_word_data(&self, command: u8) -> Result<u16> {
+ // SAFETY: self is a valid reference to a I2cClient<Normal>
+ let result = unsafe { bindings::i2c_smbus_read_word_data(self.as_raw(), command) };
+ to_result(result)?;
+ Ok(result as u16)
+ }
+
+ /// The C `i2c_smbus_write_word_data` function wrapper for SMbus "write word" protocol
+ pub fn i2c_smbus_write_word_data(&self, command: u8, value: u16) -> Result {
+ // SAFETY: self is a valid reference to a I2cClient<Normal>
+ to_result(unsafe { bindings::i2c_smbus_write_word_data(self.as_raw(), command, value) })
+ }
+
+ /// The C `i2c_smbus_read_i2c_block_data` function wrapper for SMbus "block read" protocol
+ pub fn i2c_smbus_read_i2c_block_data(&self, command: u8, values: &mut [u8]) -> Result<usize> {
+ // SAFETY: self is a valid reference to a I2cClient<Normal>
+ let result = unsafe {
+ bindings::i2c_smbus_read_i2c_block_data(
+ self.as_raw(),
+ command,
+ values.len() as u8,
+ values.as_mut_ptr(),
+ )
+ };
+ to_result(result)?;
+ Ok(result as usize)
+ }
+
+ /// The C `i2c_smbus_write_i2c_block_data` function wrapper for SMbus "block write" protocol
+ pub fn i2c_smbus_write_i2c_block_data(&self, command: u8, values: &[u8]) -> Result {
+ // SAFETY: self is a valid reference to a I2cClient<Normal>
+ to_result(unsafe {
+ bindings::i2c_smbus_write_i2c_block_data(
+ self.as_raw(),
+ command,
+ values.len() as u8,
+ values.as_ptr(),
+ )
+ })
+ }
+
+ /// The C `i2c_master_recv` function wrapper to issue a single I2C message in master
+ /// receive mode
+ pub fn i2c_master_recv(&self, buf: &mut [u8]) -> Result<usize> {
+ // SAFETY: self is a valid reference to a I2cClient<Normal>
+ let result =
+ unsafe { bindings::i2c_master_recv(self.as_raw(), buf.as_mut_ptr(), buf.len() as i32) };
+ to_result(result)?;
+ Ok(result as usize)
+ }
+
+ /// The C `i2c_master_send` function wrapper to issue a single I2C message in master
+ /// transmit mode
+ pub fn i2c_master_send(&self, buf: &[u8]) -> Result<usize> {
+ // SAFETY: self is a valid reference to a I2cClient<Normal>
+ let result =
+ unsafe { bindings::i2c_master_send(self.as_raw(), buf.as_ptr(), buf.len() as i32) };
+ to_result(result)?;
+ Ok(result as usize)
+ }
+}
+
/// The registration of an i2c client device.
///
/// This type represents the registration of a [`struct i2c_client`]. When an instance of this
--
2.43.0
Powered by blists - more mailing lists