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

时间:2014-06-25 11:56:48

标签: linux-kernel linux-device-driver

功能

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

[link to documentation]接受论证" void * drvdata"。它被描述为"要添加到设备以进行回调的数据"。究竟是什么回调在这里?文件操作功能?

1 个答案:

答案 0 :(得分:0)

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

#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, "%d\n", 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);