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