问题描述
我是Linux设备驱动程序的菜鸟,所以请多多包涵.我正在尝试实现i2c驱动程序(客户端).在这里我可以insmod
调用.probe
(由于设备树条目),并且在.probe中我可以读取/写入设备.很好.
I'm a noob to Linux device drivers so please bear with me. I'm trying to implement a i2c driver (client). It's at the point where I can insmod
, .probe
gets called (because of device-tree entries) and in the .probe I can read/write to the device. Great.
但是,我需要能够启动从用户空间到驱动程序的读取/写入.为此,i2c驱动程序的形状是否应与其他任何char设备驱动程序一样?意味着具有file_operations
结构,以便用户空间可以open
,close
,read
,write
和ioctls
?
However I need to be able to initiate read/writes from userspace to the driver. In order to do this, should an i2c driver be shaped like any other char device driver? Meaning having a file_operations
struct so userspace can open
, close
, read
, write
, and ioctls
?
我之所以问是因为在我所看到的所有i2c客户端示例中,没有人实现我提到的这些内容.我想知道他们如何在没有设置file_operations
结构的情况下从用户空间发起调用.也许很明显,没有人提到它,我不知道...我想知道是否是因为i2c被称为平台设备驱动程序,所以不需要它吗?如果有人可以确认,那将帮助我第二次猜测自己.
I'm asking because in all the i2c client examples I've seen, nobody has implemented these things I've mentioned. I'm wondering how the heck they initiated calls from userspace without the file_operations
struct set up. Maybe it was so obvious that nobody mentioned it, I don't know... I'm wondering if it's because i2c is referred to as a platform device driver it doesn't need this? If someone can confirm that would help me second guessing myself.
如果您了解我的要求,请忽略其余内容.如果您对我的问题感到困惑,这里是对我所问问题的更具体的解释:
If you understand what I'm asking please ignore the rest. If you are confused about my question here is a more concrete explanation of what I'm asking:
我现在拥有的是:
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();
推荐答案
我认为我现在可以通过@Alexandre Belloni的注释并阅读以下演示幻灯片来更好地了解设备驱动程序模型: http://free-electrons.com/doc/training/linux-kernel/linux-kernel- slides.pdf .相关幻灯片从第221页到第236页.
I think I understand the device driver model better now with @Alexandre Belloni's comment and reading this set of presentation slides: http://free-electrons.com/doc/training/linux-kernel/linux-kernel-slides.pdf. The relevant slides are from page 221 to 236.
共有3种类型的设备驱动程序:
There are 3 types of device drivers:
- 字符
- 网络
- 阻止
但是,有一些特定的框架"作为字符设备驱动程序的子类存在,它们为同一类型的设备实现了驱动程序的公共部分.
However, there are specific "frameworks" that exist as a subclass of character device drivers which implements the common parts of drivers for the same type of devices.
例如,将在hwmon框架下注册用于硬件监视的主板上的温度传感器( https://www.kernel.org/doc/Documentation/hwmon/hwmon-kernel-api.txt ).您可以实现i2c probe
,read
,write
功能,但无需使用file_operations struct
将其整形为字符设备,只需将其注册为hwmon设备:hwmon_device_register_with_groups()
.要暴露给用户空间,您需要使用attributes
并使用所需的暴露的读/写命令列表来构建/sys/class/hwmon/hwmon*
目录(例如:从通道1读取温度,写入极限温度寄存器).
For example a temperature sensor on the motherboard used for hardware monitoring would be registered under the hwmon framework (https://www.kernel.org/doc/Documentation/hwmon/hwmon-kernel-api.txt). You would implement the i2c probe
, read
, write
functionality but instead of shaping it into a character device with file_operations struct
, you just need to register it as a hwmon device: hwmon_device_register_with_groups()
. To expose to userspace you need to build up your /sys/class/hwmon/hwmon*
directory using attributes
with the list of exposed read/write commands you want (ex: read temp from channel 1, write to limit temp register).
构建内核时,请在make menuconfig
中选择设备,以使其与内核一起构建.这样,一旦启动内核,该设备将出现在/sys/class/hwmon/hwmon*
下,然后用户空间可以通过sysfs接口从该设备的open
和read
.在此处看到一个很好的示例: http://lxr.free-electrons. com/source/drivers/hwmon/tmp421.c .或hwmon目录中的任何设备.
When you build the kernel, select your device in make menuconfig
in order for it to be built with the kernel. With this, once you bootup the kernel, the device will appear under /sys/class/hwmon/hwmon*
, and userspace can then open
and read
from the device through the sysfs interface.See a good example here: http://lxr.free-electrons.com/source/drivers/hwmon/tmp421.c. Or any device in the hwmon directory.
这就是我的困惑所在.正如@Alexandre Belloni指出的那样,这些设备是在框架下注册的,因此不需要显式字符设备驱动程序代码.对我而言,情况并非如此,我认为没有适用于我正在运行的设备的合适框架(时钟PLL).因此,我将需要走一般路线并将其实现为字符设备.这也将允许我以模块的形式加载/卸载,而不是在内核启动过程中自动加载.
So that's where my confusion was. As @Alexandre Belloni pointed out, these devices are registered under a framework so the explicit character device driver code is not necessary. For me this is not the case, I don't think there is a suitable framework for the device I'm doing (clocking PLL). Thus I will need to go the general route and implement as a character device. This will also allow me to load/unload as a module rather than it automatically being loaded during kernel bootup.
请随时纠正我犯的任何错误.我希望这对其他对编写i2c客户端感到困惑的人有所帮助.
Please feel free to correct any mistakes I made. I hope this is helpful for anyone else confused about writing i2c-clients.
这篇关于是否需要像其他任何字符设备驱动程序一样实现i2c驱动程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!