1515#include <zephyr/drivers/video.h>
1616#include <zephyr/drivers/video-controls.h>
1717#include <zephyr/drivers/i2c.h>
18+ #include <zephyr/drivers/i2c_emul.h>
1819#include <zephyr/logging/log.h>
1920
2021LOG_MODULE_REGISTER (video_emul_imager , CONFIG_VIDEO_LOG_LEVEL );
2122
22- #define EMUL_IMAGER_REG_SENSOR_ID 0x0000
23+ #define EMUL_IMAGER_REG_SENSOR_ID 0x00
2324#define EMUL_IMAGER_SENSOR_ID 0x99
24- #define EMUL_IMAGER_REG_CTRL 0x0001
25- #define EMUL_IMAGER_REG_INIT1 0x0002
26- #define EMUL_IMAGER_REG_INIT2 0x0003
27- #define EMUL_IMAGER_REG_TIMING1 0x0004
28- #define EMUL_IMAGER_REG_TIMING2 0x0005
29- #define EMUL_IMAGER_REG_TIMING3 0x0006
30- #define EMUL_IMAGER_REG_CUSTOM 0x0007
31- #define EMUL_IMAGER_REG_FORMAT 0x000a
25+ #define EMUL_IMAGER_REG_CTRL 0x01
26+ #define EMUL_IMAGER_REG_INIT1 0x02
27+ #define EMUL_IMAGER_REG_INIT2 0x03
28+ #define EMUL_IMAGER_REG_TIMING1 0x04
29+ #define EMUL_IMAGER_REG_TIMING2 0x05
30+ #define EMUL_IMAGER_REG_TIMING3 0x06
31+ #define EMUL_IMAGER_REG_CUSTOM 0x07
32+ #define EMUL_IMAGER_REG_FORMAT 0x0a
3233#define EMUL_IMAGER_PATTERN_OFF 0x00
3334#define EMUL_IMAGER_PATTERN_BARS1 0x01
3435#define EMUL_IMAGER_PATTERN_BARS2 0x02
3536
3637/* Custom control that is just an I2C write for example and test purpose */
3738#define EMUL_IMAGER_CID_CUSTOM (VIDEO_CID_PRIVATE_BASE + 0x01)
3839
39- /* Emulated register bank */
40- uint8_t emul_imager_fake_regs [10 ];
41-
4240enum emul_imager_fmt_id {
4341 RGB565_320x240 ,
4442 YUYV_320x240 ,
@@ -152,21 +150,15 @@ static const struct video_format_cap fmts[] = {
152150/* Emulated I2C register interface, to replace with actual I2C calls for real hardware */
153151static int emul_imager_read_reg (const struct device * const dev , uint8_t reg_addr , uint8_t * value )
154152{
155- LOG_DBG ("Placeholder for I2C read from 0x%02x" , reg_addr );
156- switch (reg_addr ) {
157- case EMUL_IMAGER_REG_SENSOR_ID :
158- * value = EMUL_IMAGER_SENSOR_ID ;
159- break ;
160- default :
161- * value = emul_imager_fake_regs [reg_addr ];
162- }
163- return 0 ;
153+ const struct emul_imager_config * cfg = dev -> config ;
154+
155+ return i2c_write_read_dt (& cfg -> i2c , & reg_addr , 1 , value , 1 );
164156}
165157
166158/* Helper to read a full integer directly from a register */
167159static int emul_imager_read_int (const struct device * const dev , uint8_t reg_addr , int * value )
168160{
169- uint8_t val8 ;
161+ uint8_t val8 = 0 ;
170162 int ret ;
171163
172164 ret = emul_imager_read_reg (dev , reg_addr , & val8 );
@@ -177,9 +169,10 @@ static int emul_imager_read_int(const struct device *const dev, uint8_t reg_addr
177169/* Some sensors will need reg8 or reg16 variants. */
178170static int emul_imager_write_reg (const struct device * const dev , uint8_t reg_addr , uint8_t value )
179171{
180- LOG_DBG ("Placeholder for I2C write 0x%08x to 0x%02x" , value , reg_addr );
181- emul_imager_fake_regs [reg_addr ] = value ;
182- return 0 ;
172+ const struct emul_imager_config * cfg = dev -> config ;
173+ uint8_t buf_w [] = {reg_addr , value };
174+
175+ return i2c_write_dt (& cfg -> i2c , buf_w , 2 );
183176}
184177
185178static int emul_imager_write_multi (const struct device * const dev ,
@@ -383,12 +376,13 @@ static DEVICE_API(video, emul_imager_driver_api) = {
383376
384377int emul_imager_init (const struct device * dev )
385378{
379+ const struct emul_imager_config * cfg = dev -> config ;
386380 struct video_format fmt ;
387381 uint8_t sensor_id ;
388382 int ret ;
389383
390- if (/* !i2c_is_ready_dt(&cfg->i2c) */ false ) {
391- /* LOG_ERR("Bus %s is not ready", cfg->i2c.bus->name); */
384+ if (!i2c_is_ready_dt (& cfg -> i2c )) {
385+ LOG_ERR ("Bus %s is not ready" , cfg -> i2c .bus -> name );
392386 return - ENODEV ;
393387 }
394388
@@ -422,11 +416,58 @@ int emul_imager_init(const struct device *dev)
422416 static struct emul_imager_data emul_imager_data_##inst; \
423417 \
424418 static const struct emul_imager_config emul_imager_cfg_##inst = { \
425- .i2c = /* I2C_DT_SPEC_INST_GET(inst) */ { 0 }, \
419+ .i2c = I2C_DT_SPEC_INST_GET(inst), \
426420 }; \
427421 \
428422 DEVICE_DT_INST_DEFINE(inst, &emul_imager_init, NULL, &emul_imager_data_##inst, \
429423 &emul_imager_cfg_##inst, POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \
430424 &emul_imager_driver_api);
431425
432426DT_INST_FOREACH_STATUS_OKAY (EMUL_IMAGER_DEFINE )
427+
428+ /* Simulated I2C bus */
429+
430+ static int emul_imager_transfer_i2c (const struct emul * target , struct i2c_msg msgs [], int num_msgs ,
431+ int addr )
432+ {
433+ static uint8_t fake_regs [10 ] = {
434+ [EMUL_IMAGER_REG_SENSOR_ID ] = EMUL_IMAGER_SENSOR_ID ,
435+ };
436+
437+ if (num_msgs == 0 ) {
438+ CODE_UNREACHABLE ;
439+ } else if (num_msgs == 1 &&
440+ msgs [0 ].len == 2 && (msgs [0 ].flags & I2C_MSG_READ ) == 0 ) {
441+ /* Register write */
442+ fake_regs [msgs [0 ].buf [0 ]] = msgs [0 ].buf [1 ];
443+ } else if (num_msgs == 2 &&
444+ msgs [0 ].len == 1 && (msgs [0 ].flags & I2C_MSG_READ ) == 0 &&
445+ msgs [1 ].len == 1 && (msgs [1 ].flags & I2C_MSG_READ ) == 0 ) {
446+ /* Register write */
447+ fake_regs [msgs [0 ].buf [0 ]] = msgs [1 ].buf [0 ];
448+ } else if (num_msgs == 2 &&
449+ msgs [0 ].len == 1 && (msgs [0 ].flags & I2C_MSG_READ ) == 0 &&
450+ msgs [1 ].len == 1 && (msgs [1 ].flags & I2C_MSG_READ ) != 0 ) {
451+ /* Register read */
452+ msgs [1 ].buf [0 ] = fake_regs [msgs [0 ].buf [0 ]];
453+ } else {
454+ LOG_ERR ("Unsupported I2C operation of %u messages" , num_msgs );
455+ return - EIO ;
456+ }
457+
458+ return 0 ;
459+ }
460+
461+ static const struct i2c_emul_api emul_imager_i2c_api = {
462+ .transfer = emul_imager_transfer_i2c ,
463+ };
464+
465+ static int emul_imager_init_i2c (const struct emul * target , const struct device * dev )
466+ {
467+ return 0 ;
468+ }
469+
470+ #define EMUL_I2C_DEFINE (inst ) \
471+ EMUL_DT_INST_DEFINE(inst, &emul_imager_init_i2c, NULL, NULL, &emul_imager_i2c_api, NULL);
472+
473+ DT_INST_FOREACH_STATUS_OKAY (EMUL_I2C_DEFINE )
0 commit comments