【发布时间】:2017-01-05 19:11:25
【问题描述】:
我是 Linux 设备驱动程序的菜鸟,所以请多多包涵。我正在尝试实现 i2c 驱动程序(客户端)。在我可以insmod、.probe 被调用的地方(因为设备树条目)并且在.probe 中我可以读/写设备。太好了。
但是,我需要能够启动从用户空间到驱动程序的读/写操作。为了做到这一点,i2c 驱动程序是否应该像任何其他 char 设备驱动程序一样设计?意味着有一个file_operations 结构,所以用户空间可以open、close、read、write 和ioctls?
我问是因为在我看到的所有 i2c 客户端示例中,没有人实现我提到的这些东西。我想知道他们是如何在没有设置 file_operations 结构的情况下从用户空间发起呼叫的。也许它是如此明显,没有人提到它,我不知道......我想知道是不是因为 i2c 被称为平台设备驱动程序它不需要这个?如果有人可以确认这将帮助我重新猜测自己。
如果你明白我在问什么,请忽略其余部分。如果您对我的问题感到困惑,这里是对我所问问题的更具体的解释:
我现在拥有的:
static int device_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct device_data *data;
/* Check the functionality of the i2c-adapter for smbus byte read/write */
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_BYTE_DATA))
{
printk(KERN_ALERT "%s %d: device required i2c functionality is not supported\n", __func__, __LINE__);
return -ENODEV;
}
/* Allocate memory to hold the device data
* Using devm_kzalloc so do not have to worry about kfree */
data = devm_kzalloc(dev, sizeof(struct device_data), GFP_KERNEL);
if (dev == NULL)
{
printk(KERN_ALERT "%s %d: no memory\n", __func__, __LINE__);
return -ENOMEM;
}
/* Record the pointer to current client */
data->device_i2c_client = client;
/* Set the client's data field to point to device-specific data struct */
i2c_set_clientdata(client, data);
/* Add the device-specific data struct to our collection of device client devices */
device_data_tbl[id->driver_data] = data;
/* Do a read, test the access */
device_read();
return 0;
}
static int device_remove(struct i2c_client *client)
{
return 0;
}
int device_read(uint8_t device_device_id,
uint16_t const dev_reg_addr,
uint8_t *const read_val)
{
/* some read access */
}
static struct i2c_device_id device_idtable[] = {
{ "si5342", 0 },
{ },
};
MODULE_DEVICE_TABLE(i2c, device_idtable);
static struct i2c_driver device_driver = {
.driver = {
.name = device_DRIVER_NAME,
.owner = THIS_MODULE
},
.id_table = device_idtable,
.probe = device_probe,
.remove = device_remove,
};
static int __init device_driver_init(void)
{
return i2c_add_driver(&device_driver);
}
module_init(device_driver_init);
static void __exit device_driver_exit(void)
{
return i2c_del_driver(&device_driver);
}
module_exit(device_driver_exit);
想知道是否需要添加以下元素
static struct file_operations oxdrv_fops =
{
.owner = THIS_MODULE,
.release = device_release,
.open = device_open,
.unlocked_ioctl = device_ioctl
};
/* Associated function definitions: device_open, device_ioctl, etc */
alloc_chrdev_region();
cdev_init();
【问题讨论】:
-
是的,很明显。驱动程序不需要这个,因为 I2C host 和 client 之间通过专门设计的 API 进行通信。只有一个驱动程序直接实现了与从属设备的用户空间通信,显然您不需要。
-
重复什么?我并不是要争论,但老实说,我不知道您要传达的解决方案。无论如何,这整个 Linux i2c 客户端编程似乎都是一个废话。文档描述部分,需要完整的解决方案。我会相信我的直觉,并将其实现为字符驱动程序,就像这里发布的答案一样:stackoverflow.com/questions/23979129/i2c-device-linux-driver。你会注意到这个人也回答了他们自己的问题,就像其他与 i2c 客户端相关的问题一样
-
好吧抱歉,我好像很懒。所以总结一下你是说:是的应该实现为用户空间的字符驱动程序 - > i2c-client驱动程序,并且可以从drivers/i2c/i2c-dev.c建模。我将 i2c 驱动程序作为 char 驱动程序的实现现在正在使用 ioctls 和 procfs。
-
驱动程序没有自己注册字符设备,因为框架正在为他们做这件事。为您的设备选择正确的框架并在那里注册您的驱动程序。
-
@0andriy,我知道你说过你不会回应,只是为了说清楚。 a) 用户空间中的 i2c-dev,这是我当前的实现,但它不是并发安全的。我必须共享进程互斥锁,这似乎不对。 b)是的,当然在内核中做所有事情,但是一些用户空间程序需要能够触发内核代码,对吗?!我要问的是我们如何公开该内核用户空间接口。字符设备使用 file_operations (open/close/read/write/ioctl)。我看到的 i2c 客户端示例使用 sysfs,我不确定这是否是唯一“正确”的方式。
标签: linux linux-device-driver i2c