blob: 28cedf6b538854c57f1cc54127fe27d3f68f4de0 [file] [log] [blame]
Lei YUab1327c2019-11-04 16:53:39 +08001#include "i2c.hpp"
2
Lei YU9af82a52019-11-06 14:51:22 +08003#include <fcntl.h>
Lei YU92e89eb2019-11-06 18:08:25 +08004#include <sys/ioctl.h>
Lei YU9af82a52019-11-06 14:51:22 +08005#include <sys/stat.h>
6#include <unistd.h>
7
Lei YU92e89eb2019-11-06 18:08:25 +08008#include <cassert>
Lei YU9af82a52019-11-06 14:51:22 +08009#include <cerrno>
Shawn McCarneya3ff7e72024-10-15 17:34:49 -050010#include <cstring>
11#include <format>
Lei YU9af82a52019-11-06 14:51:22 +080012
Brandon Wymand1bc4ce2019-12-13 14:20:34 -060013extern "C"
14{
Lei YU92e89eb2019-11-06 18:08:25 +080015#include <i2c/smbus.h>
16#include <linux/i2c-dev.h>
17#include <linux/i2c.h>
18}
19
Lei YUab1327c2019-11-04 16:53:39 +080020namespace i2c
21{
22
Shawn McCarneya3ff7e72024-10-15 17:34:49 -050023// Maximum number of data bytes in a block read/block write/block process call
24// in SMBus 3.0. The maximum was 32 data bytes in SMBus 2.0 and earlier.
25constexpr uint8_t I2C_SMBUS3_BLOCK_MAX = 255;
26
Shawn McCarney38ed88d2019-12-11 12:26:09 -060027unsigned long I2CDevice::getFuncs()
Lei YU92e89eb2019-11-06 18:08:25 +080028{
Shawn McCarney38ed88d2019-12-11 12:26:09 -060029 // If functionality has not been cached
30 if (cachedFuncs == NO_FUNCS)
Lei YU92e89eb2019-11-06 18:08:25 +080031 {
Shawn McCarney38ed88d2019-12-11 12:26:09 -060032 // Get functionality from adapter
Shawn McCarney770de582021-11-05 02:28:35 -050033 int ret = 0, retries = 0;
34 do
35 {
36 ret = ioctl(fd, I2C_FUNCS, &cachedFuncs);
37 } while ((ret < 0) && (++retries <= maxRetries));
38
39 if (ret < 0)
Shawn McCarney38ed88d2019-12-11 12:26:09 -060040 {
Shawn McCarneya3ff7e72024-10-15 17:34:49 -050041 cachedFuncs = NO_FUNCS;
Shawn McCarney38ed88d2019-12-11 12:26:09 -060042 throw I2CException("Failed to get funcs", busStr, devAddr, errno);
43 }
Lei YU92e89eb2019-11-06 18:08:25 +080044 }
45
Shawn McCarney38ed88d2019-12-11 12:26:09 -060046 return cachedFuncs;
47}
48
49void I2CDevice::checkReadFuncs(int type)
50{
51 unsigned long funcs = getFuncs();
Lei YU92e89eb2019-11-06 18:08:25 +080052 switch (type)
53 {
54 case I2C_SMBUS_BYTE:
55 if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE))
56 {
57 throw I2CException("Missing SMBUS_READ_BYTE", busStr, devAddr);
58 }
59 break;
60 case I2C_SMBUS_BYTE_DATA:
61 if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA))
62 {
63 throw I2CException("Missing SMBUS_READ_BYTE_DATA", busStr,
64 devAddr);
65 }
66 break;
Lei YU92e89eb2019-11-06 18:08:25 +080067 case I2C_SMBUS_WORD_DATA:
68 if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA))
69 {
70 throw I2CException("Missing SMBUS_READ_WORD_DATA", busStr,
71 devAddr);
72 }
73 break;
74 case I2C_SMBUS_BLOCK_DATA:
75 if (!(funcs & I2C_FUNC_SMBUS_READ_BLOCK_DATA))
76 {
77 throw I2CException("Missing SMBUS_READ_BLOCK_DATA", busStr,
78 devAddr);
79 }
80 break;
Lei YU1d103422019-11-29 14:00:02 +080081 case I2C_SMBUS_I2C_BLOCK_DATA:
82 if (!(funcs & I2C_FUNC_SMBUS_READ_I2C_BLOCK))
83 {
84 throw I2CException("Missing I2C_FUNC_SMBUS_READ_I2C_BLOCK",
85 busStr, devAddr);
86 }
87 break;
Lei YU92e89eb2019-11-06 18:08:25 +080088 default:
89 fprintf(stderr, "Unexpected read size type: %d\n", type);
90 assert(false);
91 break;
92 }
93}
94
Lei YU34fb8bd2019-11-07 14:24:20 +080095void I2CDevice::checkWriteFuncs(int type)
96{
Shawn McCarney38ed88d2019-12-11 12:26:09 -060097 unsigned long funcs = getFuncs();
Lei YU34fb8bd2019-11-07 14:24:20 +080098 switch (type)
99 {
100 case I2C_SMBUS_BYTE:
101 if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE))
102 {
103 throw I2CException("Missing SMBUS_WRITE_BYTE", busStr, devAddr);
104 }
105 break;
106 case I2C_SMBUS_BYTE_DATA:
107 if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
108 {
109 throw I2CException("Missing SMBUS_WRITE_BYTE_DATA", busStr,
110 devAddr);
111 }
112 break;
Lei YU34fb8bd2019-11-07 14:24:20 +0800113 case I2C_SMBUS_WORD_DATA:
114 if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA))
115 {
116 throw I2CException("Missing SMBUS_WRITE_WORD_DATA", busStr,
117 devAddr);
118 }
119 break;
120 case I2C_SMBUS_BLOCK_DATA:
121 if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
122 {
123 throw I2CException("Missing SMBUS_WRITE_BLOCK_DATA", busStr,
124 devAddr);
125 }
126 break;
Lei YU1d103422019-11-29 14:00:02 +0800127 case I2C_SMBUS_I2C_BLOCK_DATA:
128 if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK))
129 {
130 throw I2CException("Missing I2C_FUNC_SMBUS_WRITE_I2C_BLOCK",
131 busStr, devAddr);
132 }
133 break;
Shawn McCarneya3ff7e72024-10-15 17:34:49 -0500134 case I2C_SMBUS_PROC_CALL:
135 if (!(funcs & I2C_FUNC_SMBUS_PROC_CALL))
136 {
137 throw I2CException("Missing I2C_FUNC_SMBUS_PROC_CALL", busStr,
138 devAddr);
139 }
140 break;
141 case I2C_SMBUS_BLOCK_PROC_CALL:
142 if (!(funcs & I2C_FUNC_SMBUS_BLOCK_PROC_CALL))
143 {
144 throw I2CException("Missing I2C_FUNC_SMBUS_BLOCK_PROC_CALL",
145 busStr, devAddr);
146 }
147 break;
Lei YU34fb8bd2019-11-07 14:24:20 +0800148 default:
Shawn McCarney770de582021-11-05 02:28:35 -0500149 fprintf(stderr, "Unexpected write size type: %d\n", type);
Lei YU34fb8bd2019-11-07 14:24:20 +0800150 assert(false);
151 }
152}
153
Shawn McCarneya3ff7e72024-10-15 17:34:49 -0500154void I2CDevice::processCallSMBus(uint8_t addr, uint8_t writeSize,
155 const uint8_t* writeData, uint8_t& readSize,
156 uint8_t* readData)
157{
158 int ret = 0, retries = 0;
159 uint8_t buffer[I2C_SMBUS_BLOCK_MAX];
160 do
161 {
162 // Copy write data to buffer. Buffer is also used by SMBus function to
163 // store the data read from the device.
164 std::memcpy(buffer, writeData, writeSize);
165 ret = i2c_smbus_block_process_call(fd, addr, writeSize, buffer);
166 } while ((ret < 0) && (++retries <= maxRetries));
167
168 if (ret < 0)
169 {
170 throw I2CException("Failed to execute block process call", busStr,
171 devAddr, errno);
172 }
173
174 readSize = static_cast<uint8_t>(ret);
175 std::memcpy(readData, buffer, readSize);
176}
177
178void I2CDevice::processCallI2C(uint8_t addr, uint8_t writeSize,
179 const uint8_t* writeData, uint8_t& readSize,
180 uint8_t* readData)
181{
182 // Buffer for block write. Linux supports SMBus 3.0 max size for block
183 // write. Buffer will contain register address, byte count, and data bytes.
184 constexpr uint16_t writeBufferSize = I2C_SMBUS3_BLOCK_MAX + 2;
185 uint8_t writeBuffer[writeBufferSize];
186
187 // Buffer for block read. Linux supports smaller SMBus 2.0 max size for
188 // block read. After ioctl() buffer will contain byte count and data bytes.
189 constexpr uint16_t readBufferSize = I2C_SMBUS_BLOCK_MAX + 1;
190 uint8_t readBuffer[readBufferSize];
191
192 // i2c_msg and i2c_rdwr_ioctl_data structs required for ioctl()
193 constexpr unsigned int numMessages = 2;
194 struct i2c_msg messages[numMessages];
195 struct i2c_rdwr_ioctl_data readWriteData;
196 readWriteData.msgs = messages;
197 readWriteData.nmsgs = numMessages;
198
199 int ret = 0, retries = 0;
200 do
201 {
202 // Initialize write buffer with reg addr, byte count, and data bytes
203 writeBuffer[0] = addr;
204 writeBuffer[1] = writeSize;
205 std::memcpy(&(writeBuffer[2]), writeData, writeSize);
206
207 // Initialize first i2c_msg to perform block write
208 messages[0].addr = devAddr;
209 messages[0].flags = 0;
210 messages[0].len = writeSize + 2; // 2 == reg addr + byte count
211 messages[0].buf = writeBuffer;
212
213 // Initialize read buffer. Set first byte to number of "extra bytes"
214 // that will be read in addition to data bytes. Set to 1 since only
215 // extra byte is the byte count.
216 readBuffer[0] = 1;
217
218 // Initialize second i2c_msg to perform block read. Linux requires the
219 // len field to be set to the buffer size.
220 messages[1].addr = devAddr;
221 messages[1].flags = I2C_M_RD | I2C_M_RECV_LEN;
222 messages[1].len = readBufferSize;
223 messages[1].buf = readBuffer;
224
225 // Call ioctl() to send the I2C messages
226 ret = ioctl(fd, I2C_RDWR, &readWriteData);
227 } while ((ret != numMessages) && (++retries <= maxRetries));
228
229 if (ret < 0)
230 {
231 throw I2CException("Failed to execute I2C block process call", busStr,
232 devAddr, errno);
233 }
234 else if (ret != numMessages)
235 {
236 throw I2CException(
237 std::format(
238 "Failed to execute I2C block process call: {} messages sent",
239 ret),
240 busStr, devAddr);
241 }
242
243 // Read size is in first byte; copy remaining data bytes to readData param
244 readSize = readBuffer[0];
245 std::memcpy(readData, &(readBuffer[1]), readSize);
246}
247
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600248void I2CDevice::open()
249{
250 if (isOpen())
251 {
252 throw I2CException("Device already open", busStr, devAddr);
253 }
254
Shawn McCarney770de582021-11-05 02:28:35 -0500255 int retries = 0;
256 do
257 {
258 fd = ::open(busStr.c_str(), O_RDWR);
259 } while ((fd == -1) && (++retries <= maxRetries));
260
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600261 if (fd == -1)
262 {
263 throw I2CException("Failed to open", busStr, devAddr, errno);
264 }
265
Shawn McCarney770de582021-11-05 02:28:35 -0500266 retries = 0;
267 int ret = 0;
268 do
269 {
270 ret = ioctl(fd, I2C_SLAVE, devAddr);
271 } while ((ret < 0) && (++retries <= maxRetries));
272
273 if (ret < 0)
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600274 {
275 // Close device since setting slave address failed
276 closeWithoutException();
277
278 throw I2CException("Failed to set I2C_SLAVE", busStr, devAddr, errno);
279 }
280}
281
282void I2CDevice::close()
283{
284 checkIsOpen();
Shawn McCarney770de582021-11-05 02:28:35 -0500285
286 int ret = 0, retries = 0;
287 do
288 {
289 ret = ::close(fd);
290 } while ((ret == -1) && (++retries <= maxRetries));
291
292 if (ret == -1)
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600293 {
294 throw I2CException("Failed to close", busStr, devAddr, errno);
295 }
Shawn McCarney770de582021-11-05 02:28:35 -0500296
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600297 fd = INVALID_FD;
Shawn McCarney38ed88d2019-12-11 12:26:09 -0600298 cachedFuncs = NO_FUNCS;
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600299}
300
Lei YUab1327c2019-11-04 16:53:39 +0800301void I2CDevice::read(uint8_t& data)
302{
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600303 checkIsOpen();
Lei YU92e89eb2019-11-06 18:08:25 +0800304 checkReadFuncs(I2C_SMBUS_BYTE);
305
Shawn McCarney770de582021-11-05 02:28:35 -0500306 int ret = 0, retries = 0;
307 do
308 {
309 ret = i2c_smbus_read_byte(fd);
310 } while ((ret < 0) && (++retries <= maxRetries));
311
Lei YU92e89eb2019-11-06 18:08:25 +0800312 if (ret < 0)
313 {
314 throw I2CException("Failed to read byte", busStr, devAddr, errno);
315 }
Shawn McCarney770de582021-11-05 02:28:35 -0500316
Lei YU92e89eb2019-11-06 18:08:25 +0800317 data = static_cast<uint8_t>(ret);
Lei YUab1327c2019-11-04 16:53:39 +0800318}
319
320void I2CDevice::read(uint8_t addr, uint8_t& data)
321{
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600322 checkIsOpen();
Lei YU92e89eb2019-11-06 18:08:25 +0800323 checkReadFuncs(I2C_SMBUS_BYTE_DATA);
324
Shawn McCarney770de582021-11-05 02:28:35 -0500325 int ret = 0, retries = 0;
326 do
327 {
328 ret = i2c_smbus_read_byte_data(fd, addr);
329 } while ((ret < 0) && (++retries <= maxRetries));
330
Lei YU92e89eb2019-11-06 18:08:25 +0800331 if (ret < 0)
332 {
333 throw I2CException("Failed to read byte data", busStr, devAddr, errno);
334 }
Shawn McCarney770de582021-11-05 02:28:35 -0500335
Lei YU92e89eb2019-11-06 18:08:25 +0800336 data = static_cast<uint8_t>(ret);
Lei YUab1327c2019-11-04 16:53:39 +0800337}
338
339void I2CDevice::read(uint8_t addr, uint16_t& data)
340{
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600341 checkIsOpen();
Lei YU92e89eb2019-11-06 18:08:25 +0800342 checkReadFuncs(I2C_SMBUS_WORD_DATA);
Shawn McCarney770de582021-11-05 02:28:35 -0500343
344 int ret = 0, retries = 0;
345 do
346 {
347 ret = i2c_smbus_read_word_data(fd, addr);
348 } while ((ret < 0) && (++retries <= maxRetries));
349
Lei YU92e89eb2019-11-06 18:08:25 +0800350 if (ret < 0)
351 {
352 throw I2CException("Failed to read word data", busStr, devAddr, errno);
353 }
Shawn McCarney770de582021-11-05 02:28:35 -0500354
Lei YU92e89eb2019-11-06 18:08:25 +0800355 data = static_cast<uint16_t>(ret);
Lei YUab1327c2019-11-04 16:53:39 +0800356}
357
Lei YU1d103422019-11-29 14:00:02 +0800358void I2CDevice::read(uint8_t addr, uint8_t& size, uint8_t* data, Mode mode)
Lei YUab1327c2019-11-04 16:53:39 +0800359{
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600360 checkIsOpen();
Shawn McCarney770de582021-11-05 02:28:35 -0500361
362 int ret = -1, retries = 0;
Lei YU1d103422019-11-29 14:00:02 +0800363 switch (mode)
364 {
365 case Mode::SMBUS:
366 checkReadFuncs(I2C_SMBUS_BLOCK_DATA);
Shawn McCarney770de582021-11-05 02:28:35 -0500367 do
368 {
369 ret = i2c_smbus_read_block_data(fd, addr, data);
370 } while ((ret < 0) && (++retries <= maxRetries));
Lei YU1d103422019-11-29 14:00:02 +0800371 break;
372 case Mode::I2C:
373 checkReadFuncs(I2C_SMBUS_I2C_BLOCK_DATA);
Shawn McCarney770de582021-11-05 02:28:35 -0500374 do
375 {
376 ret = i2c_smbus_read_i2c_block_data(fd, addr, size, data);
377 } while ((ret < 0) && (++retries <= maxRetries));
Lei YU1d103422019-11-29 14:00:02 +0800378 if (ret != size)
379 {
380 throw I2CException("Failed to read i2c block data", busStr,
381 devAddr, errno);
382 }
383 break;
384 }
Shawn McCarney770de582021-11-05 02:28:35 -0500385
Lei YU92e89eb2019-11-06 18:08:25 +0800386 if (ret < 0)
387 {
388 throw I2CException("Failed to read block data", busStr, devAddr, errno);
389 }
Shawn McCarney770de582021-11-05 02:28:35 -0500390
Lei YU92e89eb2019-11-06 18:08:25 +0800391 size = static_cast<uint8_t>(ret);
Lei YUab1327c2019-11-04 16:53:39 +0800392}
393
394void I2CDevice::write(uint8_t data)
395{
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600396 checkIsOpen();
Lei YU34fb8bd2019-11-07 14:24:20 +0800397 checkWriteFuncs(I2C_SMBUS_BYTE);
398
Shawn McCarney770de582021-11-05 02:28:35 -0500399 int ret = 0, retries = 0;
400 do
401 {
402 ret = i2c_smbus_write_byte(fd, data);
403 } while ((ret < 0) && (++retries <= maxRetries));
404
405 if (ret < 0)
Lei YU34fb8bd2019-11-07 14:24:20 +0800406 {
407 throw I2CException("Failed to write byte", busStr, devAddr, errno);
408 }
Lei YUab1327c2019-11-04 16:53:39 +0800409}
410
411void I2CDevice::write(uint8_t addr, uint8_t data)
412{
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600413 checkIsOpen();
Lei YU34fb8bd2019-11-07 14:24:20 +0800414 checkWriteFuncs(I2C_SMBUS_BYTE_DATA);
415
Shawn McCarney770de582021-11-05 02:28:35 -0500416 int ret = 0, retries = 0;
417 do
418 {
419 ret = i2c_smbus_write_byte_data(fd, addr, data);
420 } while ((ret < 0) && (++retries <= maxRetries));
421
422 if (ret < 0)
Lei YU34fb8bd2019-11-07 14:24:20 +0800423 {
424 throw I2CException("Failed to write byte data", busStr, devAddr, errno);
425 }
Lei YUab1327c2019-11-04 16:53:39 +0800426}
427
428void I2CDevice::write(uint8_t addr, uint16_t data)
429{
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600430 checkIsOpen();
Lei YU34fb8bd2019-11-07 14:24:20 +0800431 checkWriteFuncs(I2C_SMBUS_WORD_DATA);
432
Shawn McCarney770de582021-11-05 02:28:35 -0500433 int ret = 0, retries = 0;
434 do
435 {
436 ret = i2c_smbus_write_word_data(fd, addr, data);
437 } while ((ret < 0) && (++retries <= maxRetries));
438
439 if (ret < 0)
Lei YU34fb8bd2019-11-07 14:24:20 +0800440 {
441 throw I2CException("Failed to write word data", busStr, devAddr, errno);
442 }
Lei YUab1327c2019-11-04 16:53:39 +0800443}
444
Lei YU1d103422019-11-29 14:00:02 +0800445void I2CDevice::write(uint8_t addr, uint8_t size, const uint8_t* data,
446 Mode mode)
Lei YUab1327c2019-11-04 16:53:39 +0800447{
Shawn McCarneyd45a9a62019-12-10 18:35:44 -0600448 checkIsOpen();
Shawn McCarney770de582021-11-05 02:28:35 -0500449
450 int ret = -1, retries = 0;
Lei YU1d103422019-11-29 14:00:02 +0800451 switch (mode)
452 {
453 case Mode::SMBUS:
454 checkWriteFuncs(I2C_SMBUS_BLOCK_DATA);
Shawn McCarney770de582021-11-05 02:28:35 -0500455 do
456 {
457 ret = i2c_smbus_write_block_data(fd, addr, size, data);
458 } while ((ret < 0) && (++retries <= maxRetries));
Lei YU1d103422019-11-29 14:00:02 +0800459 break;
460 case Mode::I2C:
461 checkWriteFuncs(I2C_SMBUS_I2C_BLOCK_DATA);
Shawn McCarney770de582021-11-05 02:28:35 -0500462 do
463 {
464 ret = i2c_smbus_write_i2c_block_data(fd, addr, size, data);
465 } while ((ret < 0) && (++retries <= maxRetries));
Lei YU1d103422019-11-29 14:00:02 +0800466 break;
467 }
Shawn McCarney770de582021-11-05 02:28:35 -0500468
Lei YU1d103422019-11-29 14:00:02 +0800469 if (ret < 0)
Lei YU34fb8bd2019-11-07 14:24:20 +0800470 {
471 throw I2CException("Failed to write block data", busStr, devAddr,
472 errno);
473 }
Lei YUab1327c2019-11-04 16:53:39 +0800474}
475
Shawn McCarneya3ff7e72024-10-15 17:34:49 -0500476void I2CDevice::processCall(uint8_t addr, uint16_t writeData,
477 uint16_t& readData)
478{
479 checkIsOpen();
480 checkWriteFuncs(I2C_SMBUS_PROC_CALL);
481
482 int ret = 0, retries = 0;
483 do
484 {
485 ret = i2c_smbus_process_call(fd, addr, writeData);
486 } while ((ret < 0) && (++retries <= maxRetries));
487
488 if (ret < 0)
489 {
490 throw I2CException("Failed to execute process call", busStr, devAddr,
491 errno);
492 }
493
494 readData = static_cast<uint16_t>(ret);
495}
496
497void I2CDevice::processCall(uint8_t addr, uint8_t writeSize,
498 const uint8_t* writeData, uint8_t& readSize,
499 uint8_t* readData)
500{
501 checkIsOpen();
502 unsigned long funcs = getFuncs();
503
504 if ((funcs & I2C_FUNC_SMBUS_BLOCK_PROC_CALL) &&
505 (writeSize <= I2C_SMBUS_BLOCK_MAX))
506 {
507 // Use standard SMBus function which supports smaller SMBus 2.0 maximum
508 processCallSMBus(addr, writeSize, writeData, readSize, readData);
509 }
510 else if (funcs & I2C_FUNC_I2C)
511 {
512 // Use lower level I2C ioctl which supports larger SMBus 3.0 maximum
513 processCallI2C(addr, writeSize, writeData, readSize, readData);
514 }
515 else
516 {
517 throw I2CException(
518 std::format(
519 "Block process call unsupported: writeSize={:d}, funcs={}",
520 writeSize, funcs),
521 busStr, devAddr);
522 }
523}
524
Patrick Williamsf5402192024-08-16 15:20:53 -0400525std::unique_ptr<I2CInterface> I2CDevice::create(
526 uint8_t busId, uint8_t devAddr, InitialState initialState, int maxRetries)
Lei YUab1327c2019-11-04 16:53:39 +0800527{
Shawn McCarney770de582021-11-05 02:28:35 -0500528 std::unique_ptr<I2CDevice> dev(
529 new I2CDevice(busId, devAddr, initialState, maxRetries));
Lei YUab1327c2019-11-04 16:53:39 +0800530 return dev;
531}
532
Patrick Williamsf5402192024-08-16 15:20:53 -0400533std::unique_ptr<I2CInterface>
534 create(uint8_t busId, uint8_t devAddr,
535 I2CInterface::InitialState initialState, int maxRetries)
Lei YUab1327c2019-11-04 16:53:39 +0800536{
Shawn McCarney770de582021-11-05 02:28:35 -0500537 return I2CDevice::create(busId, devAddr, initialState, maxRetries);
Lei YUab1327c2019-11-04 16:53:39 +0800538}
539
540} // namespace i2c