blob: 84e83868653f186ced898e3e4cc287de7afc9562 [file] [log] [blame]
Lei YUab1327c2019-11-04 16:53:39 +08001#pragma once
2
3#include "i2c_interface.hpp"
4
5namespace i2c
6{
7
8class I2CDevice : public I2CInterface
9{
10 private:
11 I2CDevice() = delete;
12
Lei YU9af82a52019-11-06 14:51:22 +080013 /** @brief Constructor
14 *
15 * Construct I2CDevice object from the bus id and device address
16 *
Shawn McCarneyd45a9a62019-12-10 18:35:44 -060017 * Automatically opens the I2CDevice if initialState is OPEN.
18 *
Lei YU9af82a52019-11-06 14:51:22 +080019 * @param[in] busId - The i2c bus ID
20 * @param[in] devAddr - The device address of the I2C device
Shawn McCarneyd45a9a62019-12-10 18:35:44 -060021 * @param[in] initialState - Initial state of the I2CDevice object
Lei YU9af82a52019-11-06 14:51:22 +080022 */
Shawn McCarneyd45a9a62019-12-10 18:35:44 -060023 explicit I2CDevice(uint8_t busId, uint8_t devAddr,
24 InitialState initialState = InitialState::OPEN) :
25 busId(busId),
Shawn McCarney38ed88d2019-12-11 12:26:09 -060026 devAddr(devAddr)
Lei YUab1327c2019-11-04 16:53:39 +080027 {
Lei YU9af82a52019-11-06 14:51:22 +080028 busStr = "/dev/i2c-" + std::to_string(busId);
Shawn McCarneyd45a9a62019-12-10 18:35:44 -060029 if (initialState == InitialState::OPEN)
30 {
31 open();
32 }
Lei YUab1327c2019-11-04 16:53:39 +080033 }
34
Shawn McCarneyd45a9a62019-12-10 18:35:44 -060035 /** @brief Invalid file descriptor */
36 static constexpr int INVALID_FD = -1;
Lei YU9af82a52019-11-06 14:51:22 +080037
Shawn McCarney38ed88d2019-12-11 12:26:09 -060038 /** @brief Empty adapter functionality value with no bit flags set */
39 static constexpr unsigned long NO_FUNCS = 0;
40
Lei YU9af82a52019-11-06 14:51:22 +080041 /** @brief The I2C bus ID */
42 uint8_t busId;
43
44 /** @brief The i2c device address in the bus */
45 uint8_t devAddr;
46
47 /** @brief The file descriptor of the opened i2c device */
Shawn McCarney38ed88d2019-12-11 12:26:09 -060048 int fd = INVALID_FD;
Lei YU9af82a52019-11-06 14:51:22 +080049
50 /** @brief The i2c bus path in /dev */
51 std::string busStr;
52
Shawn McCarney38ed88d2019-12-11 12:26:09 -060053 /** @brief Cached I2C adapter functionality value */
54 unsigned long cachedFuncs = NO_FUNCS;
55
Shawn McCarneyd45a9a62019-12-10 18:35:44 -060056 /** @brief Check that device interface is open
57 *
58 * @throw I2CException if device is not open
59 */
60 void checkIsOpen() const
61 {
62 if (!isOpen())
63 {
64 throw I2CException("Device not open", busStr, devAddr);
65 }
66 }
67
68 /** @brief Close device without throwing an exception if an error occurs */
69 void closeWithoutException() noexcept
70 {
71 try
72 {
73 close();
74 }
75 catch (...)
76 {
77 }
78 }
79
Shawn McCarney38ed88d2019-12-11 12:26:09 -060080 /** @brief Get I2C adapter functionality
81 *
82 * Caches the adapter functionality value since it shouldn't change after
83 * opening the device.
84 *
85 * @throw I2CException on error
86 * @return Adapter functionality value
87 */
88 unsigned long getFuncs();
89
Lei YU92e89eb2019-11-06 18:08:25 +080090 /** @brief Check i2c adapter read functionality
91 *
92 * Check if the i2c adapter has the functionality specified by the SMBus
93 * transaction type
94 *
95 * @param[in] type - The SMBus transaction type defined in linux/i2c.h
96 *
97 * @throw I2CException if the function is not supported
98 */
99 void checkReadFuncs(int type);
100
Lei YU34fb8bd2019-11-07 14:24:20 +0800101 /** @brief Check i2c adapter write functionality
102 *
103 * Check if the i2c adapter has the functionality specified by the SMBus
104 * transaction type
105 *
106 * @param[in] type - The SMBus transaction type defined in linux/i2c.h
107 *
108 * @throw I2CException if the function is not supported
109 */
110 void checkWriteFuncs(int type);
111
Lei YUab1327c2019-11-04 16:53:39 +0800112 public:
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600113 /** @copydoc I2CInterface::~I2CInterface() */
Lei YU9af82a52019-11-06 14:51:22 +0800114 ~I2CDevice()
115 {
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600116 if (isOpen())
117 {
118 // Note: destructors must not throw exceptions
119 closeWithoutException();
120 }
Lei YU9af82a52019-11-06 14:51:22 +0800121 }
Lei YUab1327c2019-11-04 16:53:39 +0800122
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600123 /** @copydoc I2CInterface::open() */
124 void open();
125
126 /** @copydoc I2CInterface::isOpen() */
127 bool isOpen() const
128 {
129 return (fd != INVALID_FD);
130 }
131
132 /** @copydoc I2CInterface::close() */
133 void close();
134
Lei YUab1327c2019-11-04 16:53:39 +0800135 /** @copydoc I2CInterface::read(uint8_t&) */
136 void read(uint8_t& data) override;
137
138 /** @copydoc I2CInterface::read(uint8_t,uint8_t&) */
139 void read(uint8_t addr, uint8_t& data) override;
140
141 /** @copydoc I2CInterface::read(uint8_t,uint16_t&) */
142 void read(uint8_t addr, uint16_t& data) override;
143
Lei YU1d103422019-11-29 14:00:02 +0800144 /** @copydoc I2CInterface::read(uint8_t,uint8_t&,uint8_t*,Mode) */
145 void read(uint8_t addr, uint8_t& size, uint8_t* data,
146 Mode mode = Mode::SMBUS) override;
Lei YUab1327c2019-11-04 16:53:39 +0800147
148 /** @copydoc I2CInterface::write(uint8_t) */
149 void write(uint8_t data) override;
150
151 /** @copydoc I2CInterface::write(uint8_t,uint8_t) */
152 void write(uint8_t addr, uint8_t data) override;
153
154 /** @copydoc I2CInterface::write(uint8_t,uint16_t) */
155 void write(uint8_t addr, uint16_t data) override;
156
Lei YU1d103422019-11-29 14:00:02 +0800157 /** @copydoc I2CInterface::write(uint8_t,uint8_t,const uint8_t*,Mode) */
158 void write(uint8_t addr, uint8_t size, const uint8_t* data,
159 Mode mode = Mode::SMBUS) override;
Lei YUab1327c2019-11-04 16:53:39 +0800160
161 /** @brief Create an I2CInterface instance
162 *
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600163 * Automatically opens the I2CInterface if initialState is OPEN.
164 *
Lei YUab1327c2019-11-04 16:53:39 +0800165 * @param[in] busId - The i2c bus ID
166 * @param[in] devAddr - The device address of the i2c
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600167 * @param[in] initialState - Initial state of the I2CInterface object
Lei YUab1327c2019-11-04 16:53:39 +0800168 *
169 * @return The unique_ptr holding the I2CInterface
170 */
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600171 static std::unique_ptr<I2CInterface>
172 create(uint8_t busId, uint8_t devAddr,
173 InitialState initialState = InitialState::OPEN);
Lei YUab1327c2019-11-04 16:53:39 +0800174};
175
176} // namespace i2c