device_create(...) 参数'void * drvdata'



功能

struct device * device_create ( struct class * class,
                                struct device * parent,
                                dev_t devt,
                                void * drvdata,
                                const char * fmt,
                                ...);

[链接到文档]接受一个参数"void * drvdata"。它被描述为"要添加到设备中用于回调的数据"。这里的回调到底是什么意思?file-operation-functions吗?

SysFS是一个有用的例子:每当用户空间使用SysFS与驱动程序通信时(请参阅文档中的"读取/写入属性数据"),内核调用相应的回调。device_create过程中提供的void * drvdata指针可以通过调用dev_get_drvdata(dev)来获得。该指针可用于引用包含驱动程序状态的结构,例如:

#include <linux/module.h>   /* Needed by all modules */
#include <linux/kernel.h>   /* Needed for KERN_INFO */
#include <linux/init.h>     /* Needed for the macros */
#include <linux/device.h>
#include <linux/err.h>
MODULE_LICENSE("GPL");
static ssize_t show_period(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t set_period(struct device* dev,
                          struct device_attribute* attr,
                          const char* buf,
                          size_t count);
static DEVICE_ATTR(period, S_IWUSR | S_IRUSR, show_period, set_period);
static struct device *s_pDeviceObject;
static struct class *s_pDeviceClass;
static struct pwm_device_state
{
    int m_Period;
} s_DeviceState;
static int __init pwmdriver_init(void)
{
    int result;
    s_pDeviceClass = class_create(THIS_MODULE, "pwmdriver");
    BUG_ON(IS_ERR(s_pDeviceClass));
    s_pDeviceObject = device_create(s_pDeviceClass, NULL, 0, &s_DeviceState, "channel");
    result = device_create_file(s_pDeviceObject, &dev_attr_period);
    BUG_ON(result < 0);
    return result;
}
static ssize_t show_period(struct device *dev, struct device_attribute *attr, char *buf)
{
    struct pwm_device_state *pwm_device_data;
    pwm_device_data = dev_get_drvdata(dev);
    return scnprintf(buf, PAGE_SIZE, "%dn", pwm_device_data->m_Period);
}
static ssize_t set_period(struct device* dev,
                          struct device_attribute* attr,
                          const char* buf,
                          size_t count)
{
    long period_value = 0;
    struct pwm_device_state *pwm_device_data;
    if (kstrtol(buf, 10, &period_value) < 0)
        return -EINVAL;
    if (period_value < 10)  //Safety check
        return -EINVAL;
    pwm_device_data = dev_get_drvdata(dev);
    pwm_device_data->m_Period = period_value;
    return count;
}
static void __exit pwmdriver_exit(void)
{
    device_remove_file(s_pDeviceObject, &dev_attr_period);
    device_destroy(s_pDeviceClass, 0);
    class_destroy(s_pDeviceClass);
}
module_init(pwmdriver_init);
module_exit(pwmdriver_exit);

相关内容

最新更新