xref: /openbmc/phosphor-power/tools/i2c/i2c_interface.hpp (revision 4c94bc7c840d2bfda6ac7acec811f80fdf3f3b7a)
1 #pragma once
2 
3 #include <cstdint>
4 #include <cstring>
5 #include <exception>
6 #include <iostream>
7 #include <memory>
8 #include <sstream>
9 #include <string>
10 #include <vector>
11 
12 namespace i2c
13 {
14 
15 class I2CException : public std::exception
16 {
17   public:
18     explicit I2CException(const std::string& info, const std::string& bus,
19                           uint8_t addr, int errorCode = 0) :
20         bus(bus),
21         addr(addr), errorCode(errorCode)
22     {
23         std::stringstream ss;
24         ss << "I2CException: " << info << ": bus " << bus << ", addr 0x"
25            << std::hex << static_cast<int>(addr);
26         if (errorCode != 0)
27         {
28             ss << std::dec << ", errno " << errorCode << ": "
29                << strerror(errorCode);
30         }
31         errStr = ss.str();
32     }
33     virtual ~I2CException() = default;
34 
35     const char* what() const noexcept override
36     {
37         return errStr.c_str();
38     }
39     std::string bus;
40     uint8_t addr;
41     int errorCode;
42     std::string errStr;
43 };
44 
45 class I2CInterface
46 {
47   public:
48     /** @brief Destructor
49      *
50      * Closes the I2C interface to the device if necessary.
51      */
52     virtual ~I2CInterface() = default;
53 
54     /** @brief Initial state when an I2CInterface object is created */
55     enum class InitialState
56     {
57         OPEN,
58         CLOSED
59     };
60 
61     /** @brief The block transaction mode */
62     enum class Mode
63     {
64         SMBUS,
65         I2C,
66     };
67 
68     /** @brief Open the I2C interface to the device
69      *
70      * Throws an I2CException if the interface is already open.  See isOpen().
71      *
72      * @throw I2CException on error
73      */
74     virtual void open() = 0;
75 
76     /** @brief Indicates whether the I2C interface to the device is open
77      *
78      * @return true if interface is open, false otherwise
79      */
80     virtual bool isOpen() const = 0;
81 
82     /** @brief Close the I2C interface to the device
83      *
84      * The interface can later be re-opened by calling open().
85      *
86      * Note that the destructor will automatically close the I2C interface if
87      * necessary.
88      *
89      * Throws an I2CException if the interface is not open.  See isOpen().
90      *
91      * @throw I2CException on error
92      */
93     virtual void close() = 0;
94 
95     /** @brief Read byte data from i2c
96      *
97      * @param[out] data - The data read from the i2c device
98      *
99      * @throw I2CException on error
100      */
101     virtual void read(uint8_t& data) = 0;
102 
103     /** @brief Read byte data from i2c
104      *
105      * @param[in] addr - The register address of the i2c device
106      * @param[out] data - The data read from the i2c device
107      *
108      * @throw I2CException on error
109      */
110     virtual void read(uint8_t addr, uint8_t& data) = 0;
111 
112     /** @brief Read word data from i2c
113      *
114      * @param[in] addr - The register address of the i2c device
115      * @param[out] data - The data read from the i2c device
116      *
117      * @throw I2CException on error
118      */
119     virtual void read(uint8_t addr, uint16_t& data) = 0;
120 
121     /** @brief Read block data from i2c
122      *
123      * @param[in] addr - The register address of the i2c device
124      * @param[in,out] size - The out parameter to indicate the size of data read
125      *                       from i2c device; when mode is I2C, it is also the
126      *                       input parameter to indicate how many bytes to read
127      * @param[out] data - The pointer to buffer to read from the i2c device,
128      *                    the buffer shall be big enough to hold the data
129      *                    returned by the device. SMBus allows at most 32
130      *                    bytes.
131      * @param[in] mode - The block read mode, either SMBus or I2C.
132      *                   Internally, it invokes functions from libi2c:
133      *                    * For SMBus: i2c_smbus_read_block_data()
134      *                    * For I2C: i2c_smbus_read_i2c_block_data()
135      *
136      * @throw I2CException on error
137      */
138     virtual void read(uint8_t addr, uint8_t& size, uint8_t* data,
139                       Mode mode = Mode::SMBUS) = 0;
140 
141     /** @brief Write byte data to i2c
142      *
143      * @param[in] data - The data to write to the i2c device
144      *
145      * @throw I2CException on error
146      */
147     virtual void write(uint8_t data) = 0;
148 
149     /** @brief Write byte data to i2c
150      *
151      * @param[in] addr - The register address of the i2c device
152      * @param[in] data - The data to write to the i2c device
153      *
154      * @throw I2CException on error
155      */
156     virtual void write(uint8_t addr, uint8_t data) = 0;
157 
158     /** @brief Write word data to i2c
159      *
160      * @param[in] addr - The register address of the i2c device
161      * @param[in] data - The data to write to the i2c device
162      *
163      * @throw I2CException on error
164      */
165     virtual void write(uint8_t addr, uint16_t data) = 0;
166 
167     /** @brief Write block data to i2c
168      *
169      * @param[in] addr - The register address of the i2c device
170      * @param[in] size - The size of data to write, SMBus allows at most 32
171      *                   bytes
172      * @param[in] data - The data to write to the i2c device
173      * @param[in] mode - The block write mode, either SMBus or I2C.
174      *                   Internally, it invokes functions from libi2c:
175      *                    * For SMBus: i2c_smbus_write_block_data()
176      *                    * For I2C: i2c_smbus_write_i2c_block_data()
177      *
178      * @throw I2CException on error
179      */
180     virtual void write(uint8_t addr, uint8_t size, const uint8_t* data,
181                        Mode mode = Mode::SMBUS) = 0;
182 };
183 
184 /** @brief Create an I2CInterface instance
185  *
186  * Automatically opens the I2CInterface if initialState is OPEN.
187  *
188  * @param[in] busId - The i2c bus ID
189  * @param[in] devAddr - The device address of the i2c
190  * @param[in] initialState - Initial state of the I2CInterface object
191  *
192  * @return The unique_ptr holding the I2CInterface
193  */
194 std::unique_ptr<I2CInterface> create(
195     uint8_t busId, uint8_t devAddr,
196     I2CInterface::InitialState initialState = I2CInterface::InitialState::OPEN);
197 
198 } // namespace i2c
199