device_create_file的使用

  • Post author:
  • Post category:其他


DEVICE_ATTR是一个宏,其定义在include/linux/device.h:

#define DEVICE_ATTR(_name, _mode, _show, _store) \
    struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)

__ATTR宏定义在include/linux/sysfs.h:

#define __ATTR(_name,_mode,_show,_store) { \
    .attr = {.name = __stringify(_name), .mode = _mode },   \
    .show   = _show,                                        \
    .store  = _store,                                       \
}

struct device_attribute结构定义在include/linux/device.h:

/* interface for exporting device attributes */
struct device_attribute {
    struct attribute    attr;
    ssize_t (*show)(struct device *dev, struct device_attribute *attr,
            char *buf);
    ssize_t (*store)(struct device *dev, struct device_attribute *attr,
             const char *buf, size_t count);
};

DEVICE_ATTR宏展开:

#define DEVICE_ATTR(_name, _mode, _show, _store) \
    struct device_attribute dev_attr_##_name = { \
        .attr = {.name = __stringify(_name), .mode = _mode },   \
        .show   = _show,                                        \
        .store  = _store,                                       \
    }

举例说明DEVICE_ATTR使用方法:


static DEVICE_ATTR(msm_gpio, 0664, msmgpio_show, msmgpio_store);

static ssize_t msmgpio_show(struct device *dev,
                   struct device_attribute *attr, char *buf)
{
    int temp[5];
    struct gpio_data *gpio_data_ptr = dev_get_drvdata(dev);

    temp[0] = gpio_get_value(gpio_data_ptr->gpio0);
    temp[1] = gpio_get_value(gpio_data_ptr->gpio2);
    temp[2] = gpio_get_value(gpio_data_ptr->gpio3);
    temp[3] = gpio_get_value(gpio_data_ptr->gpio10);
    temp[4] = gpio_get_value(gpio_data_ptr->gpio11);

    return snprintf(buf, 6, "%d%d%d%d%d", temp[0], temp[1],
                    temp[2], temp[3], temp[4]);
}

static ssize_t msmgpio_store(struct device *dev,
           struct device_attribute *attr, const char *buf, size_t size)
{
    struct gpio_data *gpio_data_ptr = dev_get_drvdata(dev);

    gpio_set_value(gpio_data_ptr->gpio0,  (buf[0] == '1') ? 1 : 0);
    gpio_set_value(gpio_data_ptr->gpio2,  (buf[1] == '1') ? 1 : 0);
    gpio_set_value(gpio_data_ptr->gpio3,  (buf[2] == '1') ? 1 : 0);
    gpio_set_value(gpio_data_ptr->gpio10, (buf[3] == '1') ? 1 : 0);
    gpio_set_value(gpio_data_ptr->gpio11, (buf[4] == '1') ? 1 : 0);

    return size;
}

static DEVICE_ATTR(msm_gpio, 0664, msmgpio_show, msmgpio_store);

之后在驱动的probe函数中即可调用device_create_file:

err = device_create_file(&dev->dev, &dev_attr_msm_gpio);
if (err) {
        dev_err(&dev->dev, "sys file creation failed\n");
        return -ENODEV;
}

device_create_file和device_remove_file定义在drivers/base/core.c中,声明在include/linux/device.h中,device_create_file返回0代表创建成功。

int device_create_file(struct device *dev, const struct device_attribute *attr)
{
    int error = 0;

    if (dev) {
        WARN(((attr->attr.mode & S_IWUGO) && !attr->store),
            "Attribute %s: write permission without 'store'\n",
            attr->attr.name);
        WARN(((attr->attr.mode & S_IRUGO) && !attr->show),
            "Attribute %s: read permission without 'show'\n",
            attr->attr.name);
        error = sysfs_create_file(&dev->kobj, &attr->attr);
    }

    return error;
}

void device_remove_file(struct device *dev,
            const struct device_attribute *attr)
{
    if (dev)
        sysfs_remove_file(&dev->kobj, &attr->attr);
}

在文件系统/sys/devices/soc.0/gpio_ctrl.72下面生成msm_gpio节点,用cat,echo操作硬件:

root@msm8909:/sys/devices/soc.0/gpio_ctrl.72 # ls -l msm_gpio

-rw-rw-r– root     root         4096 1970-01-01 00:02 msm_gpio

root@msm8909:/sys/devices/soc.0/gpio_ctrl.72 # cat msm_gpio

00000

root@msm8909:/sys/devices/soc.0/gpio_ctrl.72 # echo 11111 > msm_gpio



版权声明:本文为armfpga123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。