linux-device-driver - 虚拟 I2C 设备触发探测功能
问题描述
我正在为 CMOS 传感器编写驱动程序。该设备需要多个 I2C 设置,但我还通过带有 I2C 的 FPGA 控制它的 IO。具体来说,这个 FPGA 包含一个在启动流时需要控制的 IO。因为它是一个自定义设备,我正在尝试创建一个虚拟 i2c_client 结构。我在驱动程序中有以下(修改的)函数来启动流。
static int imx267_start_streaming(struct tegracam_device *tc_dev)
{
struct imx267 *priv = (struct imx267 *)tegracam_get_privdata(tc_dev);
int err;
struct i2c_client *fpgai2c;
struct i2c_adapter *adapterused;
s32 val;
u8 bytetowrite;
u8 regaddr_toread = 0xFF;
printk(KERN_INFO "%s\n", __FUNCTION__);
printk("[IMX267]: We can get the following information from the tc_dev struct, nr = %d, name = %s\n",tc_dev->client->adapter->nr,tc_dev->client->adapter->name);
adapterused = i2c_get_adapter(tc_dev->client->adapter->nr); //First we need to get a handle on the adapter beeing used by the currently starting sensor
fpgai2c = i2c_new_dummy(adapterused,0x48); //Create dummy I2C client to access FPGA I2C on same adapter as currently starting sensor
printk("[IMX267]: We can get the following information from the adapterused struct, nr = %d, name = %s\n",tc_dev->client->adapter->nr,tc_dev->client->adapter->name);
val = i2c_smbus_read_byte_data(fpgai2c,regaddr_toread); //Read register for read modify write
bytetowrite = (u8)val;
printk("[IMX267]: register 0x%x from FPGA reads 0x%x(%d). Casting it (s32) to u8 gives a value 0x%x(%d)\n",regaddr_toread,val,val,bytetowrite,bytetowrite);
bytetowrite |= 0x40;
printk("[IMX267]: after OR with 0x40 value is 0x%x(%d), name of client is now %s",bytetowrite,bytetowrite,fpgai2c->name);
val = i2c_smbus_write_byte_data(fpgai2c,regaddr_toread,bytetowrite);
printk("[IMX267]: FPGA I2C write gave following results 0x%x(%d)\n",val,val);
usleep_range(1000, 2000); // Falco: delay before stream start
if (test_mode) {
err = imx267_write_table(priv,
mode_table[IMX267_MODE_TEST_PATTERN]);
} else {
err = imx267_write_table(priv, mode_table[IMX267_MODE_START_STREAM]);
}
if (err) {
printk(KERN_ERR "%s in write table\n", __FUNCTION__);
return err;
}
i2c_unregister_device(fpgai2c); //Unregister temporary client to release FPGA control for now
return 0;
}
通过 I2C 使用 FPGA 控制 IO 的部分工作,我可以看到流开始。但是,查看 dmesg,我也看到它触发了传感器驱动程序的探测功能:
[ 62.884372] imx267_start_streaming
[ 62.884377] [IMX267]: We can get the following information from the tc_dev struct, nr = 30, name = i2c-2-mux (chan_id 0)
[ 62.885442] [IMX267]: We can get the following information from the adapterused struct, nr = 30, name = i2c-2-mux (chan_id 0)
[ 62.885788] [IMX267]: register 0xFF from FPGA reads 0x00(0). Casting it (s32) to u8 gives a value 0x00(0)
[ 62.885791] [IMX267]: after OR with 0xF0 value is 0xF0(240), name of client is now dummy
[ 62.886077] [IMX267]: FPGA I2C write gave following results 0x0(0)
[ 62.886605] imx267_probe: called
[ 62.886608] imx267_probe: module version: 0.04
[ 62.886614] imx267 32-001a: [IMX267]: probing v4l2 sensor at addr 0x1a with name 'imx267'.
[ 62.886655] imx267_parse_dt: called
[ 62.886657] imx267_parse_dt: OK of_match_device
[ 62.886660] imx267_parse_dt of_property_read_string (mclk) found: extperiph1
[ 62.886686] imx267 32-001a: reset-gpios not found 0
[ 62.888100] IMX267: Now writing table. Number of modes: 3, mode_prop_idx = 0, active_w/width = 4096, table = 12288
[ 62.891612] imx267 32-001a: tegra camera driver registration failed
整个 imx267_probe 和 _parse 不应该在那里,这已经在驱动程序的初始化时完成了。奇怪的是i2c_client的名字不一样,我创建的client名字是dummy但是imx267_probe函数使用的名字叫imx267(所以为什么会触发image driver的probe函数?)probe函数是定义为:
static int imx267_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct tegracam_device *tc_dev;
struct imx267 *priv;
int err;
printk("%s: called\n", __FUNCTION__);
printk("%s: module version: %s", __FUNCTION__, IMX267_MODULE_VERSION);
dev_info(&client->dev, "[IMX267]: probing v4l2 sensor at addr 0x%0x with name '%s'.\n",
client->addr,client->name);
...
我也尝试过创建一个虚拟 i2c_board_info 并使用 i2c_new_device,但它会导致触发传感器驱动程序的探测功能的相同效果。
我想我一定遗漏了一些需要更改 i2c 结构的信息,但我根本不知道该去哪里找。
使用的内核版本是 4.9.140
编辑:我还找到了函数 i2c_new_probed_device ,您可以为其传递自己的探测函数。这导致虚拟功能被触发,但仍然是传感器探测功能。
int dummy_probe(struct i2c_adapter *useless, unsigned short addr) //Needs to follow naming conventions
{
printk("IMX[267]: dummy_probe function triggered!\n");
return 1;
}
static int imx267_start_streaming(struct tegracam_device *tc_dev)
{
struct imx267 *priv = (struct imx267 *)tegracam_get_privdata(tc_dev);
int err;
static struct i2c_board_info dummy_board_info = {
I2C_BOARD_INFO("dummy", 0x48),
};
unsigned short addr_list[1] = { 0x48 };
struct i2c_client *fpgai2c;
struct i2c_adapter *adapterused;
s32 val;
u8 bytetowrite;
u8 regaddr_toread = 0xFF;
printk(KERN_INFO "%s\n", __FUNCTION__);
printk("[IMX267]: We can get the following information from the tc_dev struct, nr = %d, name = %s\n",tc_dev->client->adapter->nr,tc_dev->client->adapter->name);
adapterused = i2c_get_adapter(tc_dev->client->adapter->nr); //First we need to get a handle on the adapter beeing used by the currently starting sensor
//fpgai2c = i2c_new_dummy_device(adapterused,0x48); //Create dummy I2C client to access FPGA I2C on same adapter as currently starting sensor
fpgai2c = i2c_new_probed_device(adapterused,&dummy_board_info,addr_list,(*dummy_probe));
printk("[IMX267]: We can get the following information from the adapterused struct, nr = %d, name = %s\n",tc_dev->client->adapter->nr,tc_dev->client->adapter->name);
...
结果:
3
[ 76.276400] imx267_start_streaming
[ 76.276404] [IMX267]: We can get the following information from the tc_dev struct, nr = 30, name = i2c-2-mux (chan_id 0)
[ 76.276417] IMX[267]: dummy_probe function triggered!
[ 76.277201] [IMX267]: We can get the following information from the adapterused struct, nr = 30, name = i2c-2-mux (chan_id 0)
[ 76.277540] [IMX267]: register from FPGA reads . Casting it (s32) to u8 gives a value
[ 76.277543] [IMX267]: after OR with value is , name of client is now dummy
[ 76.277826] [IMX267]: FPGA I2C write gave following results 0x0(0)
[ 76.278820] imx267_probe: called
[ 76.278824] imx267_probe: module version: 0.04
[ 76.278829] imx267 32-001a: [IMX267]: probing v4l2 sensor at addr 0x1a with name 'imx267'.
[ 76.278868] imx267_parse_dt: called
[ 76.278870] imx267_parse_dt: OK of_match_device
[ 76.278873] imx267_parse_dt of_property_read_string (mclk) found: extperiph1
[ 76.278898] imx267 32-001a: reset-gpios not found 0
[ 76.279890] IMX267: Now writing table. Number of modes: 3, mode_prop_idx = 0, active_w/width = 4096, table = 12288
[ 76.283825] imx267 32-001a: tegra camera driver registration failed
解决方案
推荐阅读
- java - 将分数作为字符串输入并转换为 int
- google-cloud-storage - 使用 Python API 以最低权限从 Google Cloud Storage 读取数据
- css - 如何缩小 css 类之间重复的 css 属性代码?
- javascript - 在 next.js/next-auth.js 中使用凭据身份验证的正确方法
- python - 在Python中用一个字符替换字符串中的多个字符
- c - C 程序:memcpy 正在复制奇怪的数据
- java - 如何添加到 JFrame 3 JPanel:第一个 JPanel 占据框架的 90%,第二个在窄顶部,第三个是可以关闭的抽屉面板
- javascript - 如何使用 javascript 而不是 jquery 显示 div 部分 onclick 单选按钮:
- c# - 使用 .NET 通用主机的控制台应用程序过早退出
- c++ - 了解 Makefile 规则