我是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();
答案 0 :(得分:1)
我想我现在更了解设备驱动程序模型@Alexandre Belloni的评论并阅读这组演示幻灯片:http://free-electrons.com/doc/training/linux-kernel/linux-kernel-slides.pdf。相关幻灯片来自第221页至第236页。
有3种类型的设备驱动程序:
然而,有特定的"框架"作为字符设备驱动程序的子类存在,它实现了相同类型设备的驱动程序的公共部分。
例如,用于硬件监控的主板上的温度传感器将在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()
。要向用户空间公开,您需要使用/sys/class/hwmon/hwmon*
使用所需的公开读/写命令列表构建attributes
目录(例如:从通道1读取临时值,写入限制临时寄存器)。
构建内核时,请在make menuconfig
中选择您的设备,以便使用内核构建它。有了这个,一旦启动内核,设备将显示在/sys/class/hwmon/hwmon*
下,然后用户空间可以通过sysfs接口从设备open
和read
。
在这里查看一个很好的例子:http://lxr.free-electrons.com/source/drivers/hwmon/tmp421.c。或者hwmon目录中的任何设备。
这就是我的困惑所在。正如@Alexandre Belloni指出的那样,这些设备是在框架下注册的,因此不需要明确的字符设备驱动程序代码。对我来说情况并非如此,我不认为我正在做的设备(时钟PLL)有一个合适的框架。因此,我需要走一般路线并实施为角色设备。这也允许我作为模块加载/卸载,而不是在内核启动时自动加载。
请随时纠正我所犯的任何错误。我希望这对于其他任何对编写i2c-clients感到困惑的人都有帮助。