1.. _module-pw_i2c_linux: 2 3============ 4pw_i2c_linux 5============ 6.. pigweed-module:: 7 :name: pw_i2c_linux 8 9``pw_i2c_linux`` implements the ``pw_i2c`` interface using the Linux userspace 10``i2c-dev`` driver. Transfers are executed using blocking ``ioctl`` calls. 11Write+read transactions are implemented atomically using a single system call, 12and a retry mechanism is used to support bus arbitration between multiple 13controllers. 14 15------------- 16API reference 17------------- 18.. doxygenclass:: pw::i2c::LinuxInitiator 19 :members: 20 21-------- 22Examples 23-------- 24A simple example illustrating the usage: 25 26.. code-block:: C++ 27 28 #include "pw_i2c/address.h" 29 #include "pw_i2c/device.h" 30 #include "pw_i2c_linux/initiator.h" 31 #include "pw_log/log.h" 32 #include "pw_result/result.h" 33 34 constexpr auto kBusPath = "/dev/i2c-0"; 35 constexpr auto kAddress = pw::i2c::Address::SevenBit<0x42>(); 36 37 pw::Result<int> result = pw::i2c::LinuxInitiator::OpenI2cBus(kBusPath); 38 if (!result.ok()) { 39 PW_LOG_ERROR("Failed to open I2C bus [%s]", kBusPath); 40 return result.status(); 41 } 42 pw::i2c::LinuxInitiator initiator(*result); 43 pw::i2c::Device device(initiator, address); 44 // Use device to talk to address. 45 46In real-world use cases, you may want to create an initiator singleton. This 47can be done by initializing a function-local static variable with a lambda: 48 49.. code-block:: C++ 50 51 #include <functional> 52 53 #include "pw_i2c/address.h" 54 #include "pw_i2c/device.h" 55 #include "pw_i2c/initiator.h" 56 #include "pw_i2c_linux/initiator.h" 57 #include "pw_log/log.h" 58 #include "pw_result/result.h" 59 #include "pw_status/status.h" 60 61 // Open the I2C bus and return an initiator singleton. 62 pw::i2c::Initiator* GetInitiator() { 63 static constexpr auto kBusPath = "/dev/i2c-0"; 64 static auto* initiator = std::invoke([]() -> pw::i2c::Initiator* { 65 pw::Result<int> result = pw::i2c::LinuxInitiator::OpenI2cBus(kBusPath); 66 if (!result.ok()) { 67 PW_LOG_ERROR("Failed to open I2C bus [%s]", kBusPath); 68 return nullptr; 69 } 70 return new pw::i2c::Initiator(*result); 71 }); 72 return initiator; 73 } 74 75 // Use the initiator from anywhere. 76 constexpr auto kAddress = pw::i2c::Address::SevenBit<0x42>(); 77 auto* initiator = GetInitiator(); 78 if (initiator == nullptr) { 79 PW_LOG_ERROR("I2C initiator unavailable"); 80 return pw::Status::Internal(); 81 } 82 pw::i2c::Device device(*initiator, address); 83 // Use device to talk to address. 84 85------- 86Caveats 87------- 88Only 7-bit addresses are supported right now, but it should be possible to add 89support for 10-bit addresses with minimal changes - as long as the Linux driver 90supports 10-bit addresses. 91