Reference#

pw_i2c: Cross-platform I2C API with interactive debugging

Overview#

pw::i2c::Address#

class Address#

A helper class that represents I2C addresses.

#include "pw_i2c/address.h"

constexpr pw::i2c::Address kAddress1 = pw::i2c::Address::SevenBit<0x42>();
uint8_t raw_address_1 = kAddress1.GetSevenBit();

const pw::i2c::Address kAddress2(0x200);  // 10-bit
uint16_t raw_address_2 = kAddress2.GetTenBit();
// Note: kAddress2.GetSevenBit() would fail an assertion here.

Public Functions

explicit Address(uint16_t address)#

Creates a pw::i2c::Address instance.

constexpr pw::i2c::Address kAddress(0x200);

Parameters:

address[in] A 10-bit address as an unsigned integer. This method does a runtime assertion to ensure that address is 10 bits or less.

Returns:

A pw::i2c::Address instance.

uint8_t GetSevenBit() const#

Gets the 7-bit address that was provided when this instance was created.

This method does a runtime assertion to ensure that the address is 7 bits or less.

Returns:

A 7-bit address as an unsigned integer.

inline uint16_t GetTenBit() const#

Gets the 10-bit address that was provided when this instance was created.

Returns:

A 10-bit address as an unsigned integer.

Public Static Functions

template<uint16_t kAddress>
static inline constexpr Address TenBit()#

Creates a pw::i2c::Address instance for an address that’s 10 bits or less.

This constant expression does a compile-time assertion to ensure that the provided address is 10 bits or less.

constexpr pw::i2c::Address kAddress = pw::i2c::Address::TenBit(0x200);
Returns:

A pw::i2c::Address instance.

template<uint8_t kAddress>
static inline constexpr Address SevenBit()#

Creates a pw::i2c::Address instance for an address that’s 7 bits or less.

This constant expression does a compile-time assertion to ensure that the provided address is 7 bits or less.

constexpr pw::i2c::Address kAddress = pw::i2c::Address::SevenBit(0x42);
Returns:

A pw::i2c::Address instance.

pw::i2c::Initiator#

class Initiator#

The common, base driver interface for initiating thread-safe transactions with devices on an I2C bus. Other documentation may call this style of interface an I2C “master”, “central”, or “controller”.

pw::i2c::Initiator isn’t required to support 10-bit addressing. If only 7-bit addressing is supported, pw::i2c::Initiator fails a runtime assertion when given an address that is out of 7-bit address range.

The implementer of this pure virtual interface is responsible for ensuring thread safety and enabling functionality such as initialization, configuration, enabling and disabling, unsticking SDA, and detecting device address registration collisions.

Note

pw::i2c::Initiator uses internal synchronization, so it’s safe to initiate transactions from multiple threads. However, a combined write and read transaction may not be atomic when there are multiple initiators on the bus. Furthermore, devices may require specific sequences of transactions, and application logic must provide the synchronization to execute these sequences correctly.

Subclassed by pw::i2c::GmockInitiator, pw::i2c::LinuxInitiator, pw::i2c::MockInitiator

Public Functions

inline Status WriteReadFor(
Address device_address,
ConstByteSpan tx_buffer,
ByteSpan rx_buffer,
chrono::SystemClock::duration timeout,
)#

Writes bytes to an I2C device and then reads bytes from that same device as either one atomic I2C transaction or two independent I2C transactions.

If the I2C bus is a multi-initiator then the implementer of this class must ensure it’s a single-atomic transaction.

The signal on the bus for the atomic transaction should look like this:

START + I2C_ADDRESS + WRITE(0) + TX_BUFFER_BYTES +
START + I2C_ADDRESS + READ(1) + RX_BUFFER_BYTES + STOP

The signal on the bus for the two independent transactions should look like this:

START + I2C_ADDRESS + WRITE(0) + TX_BUFFER_BYTES + STOP
START + I2C_ADDRESS + READ(1) + RX_BUFFER_BYTES + STOP
Parameters:
  • device_address[in] The address of the I2C device.

  • tx_buffer[in] The transmit buffer.

  • rx_buffer[out] The receive buffer.

  • timeout[in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction or transactions.

Pre:

The provided address must be supported by the initiator. I.e. don’t use a 10-bit address if the initiator only supports 7-bit addresses. This method fails a runtime assertion if this precondition isn’t met.

Returns:

Code

Description

OK

The transaction or transactions succeeded.

INVALID_ARGUMENT

The device address provided is bigger than 10 bits.

DEADLINE_EXCEEDED

Was unable to acquire exclusive initiator access and complete the I2C transaction in time.

UNAVAILABLE

A NACK condition occurred, meaning the addressed device didn’t respond or was unable to process the request.

FAILED_PRECONDITION

The interface isn’t initialized or enabled.

inline Status WriteReadFor(
Address device_address,
const void *tx_buffer,
size_t tx_size_bytes,
void *rx_buffer,
size_t rx_size_bytes,
chrono::SystemClock::duration timeout,
)#

A variation of pw::i2c::Initiator::WriteReadFor that accepts explicit sizes for the amount of bytes to write to the device and read from the device.

inline Status WriteFor(Address device_address, ConstByteSpan tx_buffer, chrono::SystemClock::duration timeout)#

Write bytes to the I2C device.

The signal on the bus should look like this:

START + I2C_ADDRESS + WRITE(0) + TX_BUFFER_BYTES + STOP
Parameters:
  • device_address[in] The address of the I2C device.

  • tx_buffer[in] The transmit buffer.

  • rx_buffer[out] The receive buffer.

  • timeout[in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.

Pre:

The provided address must be supported by the initiator. I.e. don’t use a 10-bit address if the initiator only supports 7-bit addresses. This method fails a runtime assertion if this precondition isn’t met.

Returns:

Code

Description

OK

The transaction succeeded.

INVALID_ARGUMENT

The device address provided is bigger than 10 bits.

DEADLINE_EXCEEDED

Was unable to acquire exclusive initiator access and complete the I2C transaction in time.

UNAVAILABLE

A NACK condition occurred, meaning the addressed device didn’t respond or was unable to process the request.

FAILED_PRECONDITION

The interface isn’t initialized or enabled.

inline Status WriteFor(
Address device_address,
const void *tx_buffer,
size_t tx_size_bytes,
chrono::SystemClock::duration timeout,
)#

A variation of pw::i2c::Initiator::WriteFor that accepts an explicit size for the amount of bytes to write to the device.

inline Status ReadFor(Address device_address, ByteSpan rx_buffer, chrono::SystemClock::duration timeout)#

Reads bytes from an I2C device.

The signal on the bus should look like this:

START + I2C_ADDRESS + READ(1) + RX_BUFFER_BYTES + STOP
Parameters:
  • device_address[in] The address of the I2C device.

  • rx_buffer[out] The receive buffer.

  • timeout[in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.

Pre:

The provided address must be supported by the initiator. I.e. don’t use a 10-bit address if the initiator only supports 7-bit addresses. This method fails a runtime assertion if this precondition isn’t met.

Returns:

Code

Description

OK

The transaction succeeded.

INVALID_ARGUMENT

The device address provided is bigger than 10 bits.

DEADLINE_EXCEEDED

Was unable to acquire exclusive initiator access and complete the I2C transaction in time.

UNAVAILABLE

A NACK condition occurred, meaning the addressed device didn’t respond or was unable to process the request.

FAILED_PRECONDITION

The interface isn’t initialized or enabled.

inline Status ReadFor(Address device_address, void *rx_buffer, size_t rx_size_bytes, chrono::SystemClock::duration timeout)#

A variation of pw::i2c::Initiator::ReadFor that accepts an explicit size for the amount of bytes to read from the device.

inline Status ProbeDeviceFor(Address device_address, chrono::SystemClock::duration timeout)#

Probes the device for an I2C ACK after only writing the address. This is done by attempting to read a single byte from the specified device.

Parameters:
  • device_address[in] The address of the I2C device.

  • timeout[in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.

Pre:

The provided address must be supported by the initiator. I.e. don’t use a 10-bit address if the initiator only supports 7-bit addresses. This method fails a runtime assertion if this precondition isn’t met.

Returns:

Code

Description

OK

The transaction succeeded.

INVALID_ARGUMENT

The device address provided is bigger than 10 bits.

DEADLINE_EXCEEDED

Was unable to acquire exclusive initiator access and complete the I2C transaction in time.

UNAVAILABLE

A NACK condition occurred, meaning the addressed device didn’t respond or was unable to process the request.

FAILED_PRECONDITION

The interface isn’t initialized or enabled.

pw::i2c::Device#

class Device#

The common interface for generic I2C devices. Reads and writes arbitrary chunks of data over an I2C bus to an I2C device. This class contains pw::i2c::Address and wraps the pw::i2c::Initiator API. Only works with devices that have a single device address.

pw::i2c::Device is intended to represent ownership of a specific responder. Individual transactions are atomic but there’s no synchronization for sequences of transactions. Therefore, shared access should be faciliated with higher-level application abstractions. To help enforce this, pw::i2c::Device instances are only movable and not copyable.

Subclassed by pw::i2c::RegisterDevice

Public Functions

inline constexpr Device(Initiator &initiator, Address device_address)#

Creates a pw::i2c::Device instance.

The address for the I2C device is set in this constructor and can’t be modified later.

Parameters:
  • initiator[in] A reference to a pw::i2c::Initiator instance.

  • device_address[in] The address of the I2C device.

Returns:

A pw::i2c::Device instance.

inline Status WriteReadFor(ConstByteSpan tx_buffer, ByteSpan rx_buffer, chrono::SystemClock::duration timeout)#

Wraps pw::i2c::Initiator::WriteReadFor.

inline Status WriteReadFor(
const void *tx_buffer,
size_t tx_size_bytes,
void *rx_buffer,
size_t rx_size_bytes,
chrono::SystemClock::duration timeout,
)#

Wraps the variation of pw::i2c::Initiator::WriteReadFor that accepts explicit sizes for the amount of bytes to write to the device and read from the device.

inline Status WriteFor(ConstByteSpan tx_buffer, chrono::SystemClock::duration timeout)#

Wraps pw::i2c::Initiator::WriteFor.

inline Status WriteFor(const void *tx_buffer, size_t tx_size_bytes, chrono::SystemClock::duration timeout)#

Wraps the variation of pw::i2c::Initiator::WriteFor that accepts an explicit size for the amount of bytes to write to the device.

inline Status ReadFor(ByteSpan rx_buffer, chrono::SystemClock::duration timeout)#

Wraps pw::i2c::Initiator::ReadFor.

inline Status ReadFor(void *rx_buffer, size_t rx_size_bytes, chrono::SystemClock::duration timeout)#

Wraps the variation of pw::i2c::Initiator::ReadFor that accepts an explicit size for the amount of bytes to read from the device.

inline Status ProbeFor(chrono::SystemClock::duration timeout)#

Wraps pw::i2c::Initiator::ProbeDeviceFor.

pw::i2c::RegisterDevice#

See Configure and read an I2C device’s registers for example usage of pw::i2c::RegisterDevice.

class RegisterDevice : public pw::i2c::Device#

The common interface for I2C register devices. Contains methods to help read and write the device’s registers.

Warning

This interface assumes that you know how to consult your device’s datasheet to determine correct address sizes, data sizes, endianness, etc.

Public Functions

inline constexpr RegisterDevice(
Initiator &initiator,
Address address,
endian register_address_order,
endian data_order,
RegisterAddressSize register_address_size,
)#

This constructor specifies the endianness of the register address and data separately. If your register address and data have the same endianness and you’d like to specify them both with a single argument, see the other pw::i2c::RegisterDevice constructor.

Parameters:
  • initiator[in] A pw::i2c::Initiator instance for the bus that the device is on.

  • address[in] The address of the I2C device.

  • register_address_order[in] The endianness of the register address.

  • data_order[in] The endianness of the data.

  • register_address_size[in] The size of the register address.

inline constexpr RegisterDevice(Initiator &initiator, Address address, endian order, RegisterAddressSize register_address_size)#

This constructor specifies the endianness of the register address and data with a single argument. If your register address and data have different endianness, use the other pw::i2c::RegisterDevice constructor.

Parameters:
  • initiator[in] A pw::i2c::Initiator instance for the bus that the device is on.

  • address[in] The address of the I2C device.

  • order[in] The endianness of both the register address and register data.

  • register_address_size[in] The size of the register address.

inline Status WriteRegisters(
uint32_t register_address,
ConstByteSpan register_data,
ByteSpan buffer,
chrono::SystemClock::duration timeout,
)#

Writes data to multiple contiguous registers starting at a specific register. This method is byte-addressable.

register_address and register_data use the endianness that was provided when this pw::i2c::RegisterDevice instance was constructed.

Parameters:
  • register_address[in] The register address to begin writing at.

  • register_data[in] The data to write. Endianness is taken into account if the data is 2 or 4 bytes.

  • buffer[in] A buffer for constructing the write data. The size of this buffer must be at least as large as the size of register_address plus the size of register_data.

  • timeout[in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.

Pre:

This method assumes that you’ve verified that your device supports bulk writes and that register_data is a correct size for your device.

Returns:

Code

Description

OK

The bulk write was successful.

DEADLINE_EXCEEDED

Unable to acquire exclusive bus access and complete the transaction in time.

FAILED_PRECONDITION

The interface is not initialized or enabled.

INTERNAL

An issue occurred while building register_data.

INVALID_ARGUMENT

register_address is larger than the 10-bit address space.

OUT_OF_RANGE

The size of buffer is less than the size of register_address plus the size of register_data.

UNAVAILABLE

The device took too long to respond to the NACK.

inline Status WriteRegisters8(
uint32_t register_address,
span<const uint8_t> register_data,
ByteSpan buffer,
chrono::SystemClock::duration timeout,
)#

Variant of pw::i2c::RegisterDevice::WriteRegisters() that requires register_data to be exactly 8 bits.

inline Status WriteRegisters16(
uint32_t register_address,
span<const uint16_t> register_data,
ByteSpan buffer,
chrono::SystemClock::duration timeout,
)#

Variant of pw::i2c::RegisterDevice::WriteRegisters() that requires register_data to be exactly 16 bits.

inline Status WriteRegisters32(
uint32_t register_address,
span<const uint32_t> register_data,
ByteSpan buffer,
chrono::SystemClock::duration timeout,
)#

Variant of pw::i2c::RegisterDevice::WriteRegisters() that requires register_data to be exactly 32 bits.

Status ReadRegisters(uint32_t register_address, ByteSpan return_data, chrono::SystemClock::duration timeout)#

Reads data from multiple contiguous registers starting from a specific offset or register. This method is byte-addressable.

register_address and return_data use the endianness that was provided when this pw::i2c::RegisterDevice instance was constructed.

Parameters:
  • register_address[in] The register address to begin reading at.

  • return_data[out] The area to read the data into. The amount of data that will be read is equal to the size of this span. Endianness is taken into account if this span is 2 or 4 bytes.

  • timeout[in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.

Pre:

This method assumes that you’ve verified that your device supports bulk reads and that return_data is a correct size for your device.

Returns:

Code

Description

OK

The bulk read was successful.

DEADLINE_EXCEEDED

Unable to acquire exclusive bus access and complete the transaction in time.

FAILED_PRECONDITION

The interface is not initialized or enabled.

INTERNAL

An issue occurred while building return_data.

INVALID_ARGUMENT

register_address is larger than the 10-bit address space.

UNAVAILABLE

The device took too long to respond to the NACK.

inline Status ReadRegisters8(uint32_t register_address, span<uint8_t> return_data, chrono::SystemClock::duration timeout)#

Variant of pw::i2c::RegisterDevice::ReadRegisters() that requires return_data to be exactly 8 bits.

inline Status ReadRegisters16(uint32_t register_address, span<uint16_t> return_data, chrono::SystemClock::duration timeout)#

Variant of pw::i2c::RegisterDevice::ReadRegisters() that requires return_data to be exactly 16 bits.

inline Status ReadRegisters32(uint32_t register_address, span<uint32_t> return_data, chrono::SystemClock::duration timeout)#

Variant of pw::i2c::RegisterDevice::ReadRegisters() that requires return_data to be exactly 32 bits.

inline Status WriteRegister(uint32_t register_address, std::byte register_data, chrono::SystemClock::duration timeout)#

Sends a register address to write to and then writes to that address.

register_address and register_data use the endianness that was provided when this pw::i2c::RegisterDevice instance was constructed.

Parameters:
  • register_address[in] The register address to write to.

  • register_data[in] The data that should be written at the address. The maximum allowed size is 4 bytes.

  • timeout[in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.

Pre:

This method assumes that you’ve verified that register_data is a correct size for your device.

Returns:

Code

Description

OK

The write was successful.

DEADLINE_EXCEEDED

Unable to acquire exclusive bus access and complete the transaction in time.

FAILED_PRECONDITION

The interface is not initialized or enabled.

INTERNAL

An issue occurred while writing the data.

INVALID_ARGUMENT

register_address is larger than the 10-bit address space.

UNAVAILABLE

The device took too long to respond to the NACK.

inline Status WriteRegister8(uint32_t register_address, uint8_t register_data, chrono::SystemClock::duration timeout)#

Variant of pw::i2c::RegisterDevice::WriteRegister() that writes exactly 8 bits.

inline Status WriteRegister16(uint32_t register_address, uint16_t register_data, chrono::SystemClock::duration timeout)#

Variant of pw::i2c::RegisterDevice::WriteRegister() that writes exactly 16 bits.

inline Status WriteRegister32(uint32_t register_address, uint32_t register_data, chrono::SystemClock::duration timeout)#

Variant of pw::i2c::RegisterDevice::WriteRegister() that writes exactly 32 bits.

inline Result<std::byte> ReadRegister(uint32_t register_address, chrono::SystemClock::duration timeout)#

Sends a register address to read from and then reads from that address.

register_address and the return data use the endianness that was provided when this pw::i2c::RegisterDevice instance was constructed.

Parameters:
  • register_address[in] The register address to read.

  • timeout[in] The maximum duration to block waiting for both exclusive bus access and the completion of the I2C transaction.

Pre:

This method assumes that you’ve verified that the return data size is a correct size for your device.

Returns:

Code

Description

OK

Returns the register data.

DEADLINE_EXCEEDED

Unable to acquire exclusive bus access and complete the transaction in time.

FAILED_PRECONDITION

The interface is not initialized or enabled.

INTERNAL

An issue occurred while building the return data.

INVALID_ARGUMENT

register_address is larger than the 10-bit address space.

UNAVAILABLE

The device took too long to respond to the NACK.

inline Result<uint8_t> ReadRegister8(uint32_t register_address, chrono::SystemClock::duration timeout)#

Variant of pw::i2c::RegisterDevice::ReadRegister() that returns exactly 8 bits.

inline Result<uint16_t> ReadRegister16(uint32_t register_address, chrono::SystemClock::duration timeout)#

Variant of pw::i2c::RegisterDevice::ReadRegister() that returns exactly 16 bits.

inline Result<uint32_t> ReadRegister32(uint32_t register_address, chrono::SystemClock::duration timeout)#

Variant of pw::i2c::RegisterDevice::ReadRegister() that returns exactly 32 bits.

pw::i2c::I2cService#

class I2cService : public pw_rpc::pwpb::I2c::Service<I2cService>#

RPC service for performing I2C transactions.

Public Types

using InitiatorSelector = pw::Function<Initiator*(size_t pos)>#

A callback that returns a pw::i2c::Initiator instance for the given bus index position or nullptr if the position is not valid for this I2C device.

Public Functions

inline explicit I2cService(InitiatorSelector &&initiator_selector)#

Creates an I2cService instance.

void I2cWrite(
const pwpb::I2cWriteRequest::Message &request,
pw::rpc::PwpbUnaryResponder<pwpb::I2cWriteResponse::Message> &responder,
)#

Writes a message to the specified I2C device register.

void I2cRead(
const pwpb::I2cReadRequest::Message &request,
pw::rpc::PwpbUnaryResponder<pwpb::I2cReadResponse::Message> &responder,
)#

Reads a message from the specified I2C device register.

pw::i2c::MockInitiator#

class MockInitiator : public pw::i2c::Initiator#

A generic mocked backend for pw::i2c::Initiator that’s specifically designed to make it easier to develop I2C device drivers. pw::i2c::MockInitiator compares actual I2C transactions against expected transactions. The expected transactions are represented as a list of pw::i2c::Transaction instances that are passed as arguments in the pw::i2c::MockInitiator constructor. Each consecutive call to pw::i2c::MockInitiator iterates to the next expected transaction. pw::i2c::MockInitiator::Finalize() indicates whether the actual transactions matched the expected transactions.

pw::i2c::MockInitiator is intended to be used within GoogleTest tests. See pw_unit_test .

#include <chrono>

#include "pw_bytes/array.h"
#include "pw_i2c/address.h"
#include "pw_i2c/initiator_mock.h"
#include "pw_result/result.h"
#include "pw_unit_test/framework.h"

using namespace std::chrono_literals;

namespace {

TEST(I2CTestSuite, I2CWriteTestCase) {
  constexpr pw::i2c::Address kAddress =
  pw::i2c::Address::SevenBit<0x01>(); constexpr auto kExpectedWrite =
  pw::bytes::Array<1, 2, 3>(); auto expected_transactions =
  pw::i2c::MakeExpectedTransactionArray(
    {pw::i2c::WriteTransaction(pw::OkStatus(), kAddress, kExpectedWrite,
    1ms)}
  );
  pw::i2c::MockInitiator initiator(expected_transactions);
  pw::ConstByteSpan kActualWrite = pw::bytes::Array<1, 2, 3>();
  pw::Status status = initiator.WriteFor(kAddress, kActualWrite, 1ms);
  EXPECT_EQ(initiator.Finalize(), pw::OkStatus());
}

}

Public Functions

inline Status Finalize() const#

Indicates whether the actual I2C transactions matched the expected transactions. Should be called at the end of the test.

Returns:

Code

Description

OK

The actual transactions matched the expected transactions.

OUT_OF_RANGE

The mocked set of transactions hasn’t been exhausted.

~MockInitiator() override#

Runs pw::i2c::MockInitiator::Finalize() regardless of whether it was already optionally finalized.

pw::i2c::Transaction#

class Transaction#

Base class for creating transaction instances. For read-only, write-only, or probe transactions, improve code readability by using one of the following helpers instead:

  • pw::i2c::ReadTransaction

  • pw::i2c::WriteTransaction

  • pw::i2c::ProbeTransaction

If you need to create a write-then-read transaction, you can use this class.

Public Functions

inline constexpr Transaction(
Status expected_return_value,
Address device_address,
ConstByteSpan write_buffer,
ConstByteSpan read_buffer,
std::optional<chrono::SystemClock::duration> timeout = std::nullopt,
)#

Constructor for creating write-only, read-only, or write-then-read transactions.

inline constexpr Transaction(
Status expected_return_value,
Address device_address,
std::optional<chrono::SystemClock::duration> timeout = std::nullopt,
)#

Alternative constructor for creating probe transactions.

inline ConstByteSpan read_buffer() const#

Gets the buffer that is virtually read.

inline ConstByteSpan write_buffer() const#

Gets the buffer that the I2C device should write to.

inline std::optional<chrono::SystemClock::duration> timeout() const#

Gets the minimum duration to wait for a blocking I2C transaction.

inline Address address() const#

Gets the I2C address that the I2C transaction is targeting.

inline Status return_value() const#

Gets the expected return value for the transaction.

pw::i2c::ReadTransaction#

constexpr Transaction pw::i2c::ReadTransaction(
Status expected_return_value,
Address device_address,
ConstByteSpan read_buffer,
std::optional<chrono::SystemClock::duration> timeout = std::nullopt,
)#

A helper that constructs a read-only I2C transaction. Used for testing read transactions with pw::i2c::MockInitiator.

pw::i2c::WriteTransaction#

constexpr Transaction pw::i2c::WriteTransaction(
Status expected_return_value,
Address device_address,
ConstByteSpan write_buffer,
std::optional<chrono::SystemClock::duration> timeout = std::nullopt,
)#

A helper that constructs a write-only I2C transaction. Used for testing write transactions with pw::i2c::MockInitiator.

pw::i2c::ProbeTransaction#

constexpr Transaction pw::i2c::ProbeTransaction(
Status expected_return_value,
Address device_address,
std::optional<chrono::SystemClock::duration> timeout = std::nullopt,
)#

A helper that constructs a one-byte read I2C transaction. Used for testing probe transactions with pw::i2c::MockInitiator.

pw::i2c::GmockInitiator#

class GmockInitiator : public pw::i2c::Initiator#

Provides the MOCK_METHOD implementation for gMock compatibility.